Azure Sphere Guardian 100 - Review

Table of contents

RoadTest: Azure Sphere Guardian 100

Author: BigG

Creation date:

Evaluation Type: Development Boards & Tools

Did you receive all parts the manufacturer stated would be included in the package?: True

What other parts do you consider comparable to this product?: Electric Imp and Particle.io for integrated managed cloud services. OSD32MP15x System-in-Package seems to be a close match for chipset and features

What were the biggest problems encountered?: Understanding where this product rightfully fits within a brownfield application, as in what does it take to make it work securely - all you get is marketing material, which is not helpful from technical standpoint. Then I found there were a couple of errors within AVNET documentation that caused confusion, especially with the initial setup to claim my device and testing the device using the AVNET prescribed tests. The Ethernet DHCP server capability also did not function as I assumed it would.

Detailed Review:

 

 

 

 

 

1.0 Introduction

 

image

 

The AVNET Guardian-100 is a multi-core edge device based on the Avnet Azure Sphere MT3620 module, which uses the MT3620AN SoC (System on Chip). The device offers Ethernet and a secure dual-band Wi-Fi connection to the internet or for connecting to a private local area network. The device is powered by 5V DC power supply via a USB Type-B connection, which can also be used as a serial interface.

 

The AVNET Guardian-100 is positioned as an edge device, suitable for brownfield applications where you can retrofit and provide secure connectivity without exposing the existing unconnected network to the outside world. The product datasheet goes on to say that “Beyond retrofitting existing devices, Avnet Guardian can also be used in scenarios where current connectivity does not meet enterprise-level security requirements. Avnet Guardian is a good fit for any industry that operates using mission-critical, capital-intense equipment.”

 

So, dare I say it, but the AVNET Guardian-100 may well be suitable to bridging that “air gap” between the public Internet and a secure SCADA or Local Area Network or standalone device. Of course that claim can only be made for the hardware as bridging this gap securely still relies on human effort and competence to ensure that the software does not unwittingly open up a “front or back door”.

 

I was therefore curious to see whether the Guardian 100 was the best configuration for this purpose, as the only hardware interface provided to the user for an application is USB (serial) and Ethernet (TCP/UDP) connectivity.

 

Let's find out.

 

 

2.0 Hardware Review

 

Unboxing

 

The device is neatly packaged within a gloss white box which has the AVNET logo and the tag line “Reach Further” printed on the lid. There is a stick on label containing a “SER” number, a MAC address and a QR code, which when scanned provides a longer (presumed) serial number and the same MAC address. On the reverse side of the box there is some health warning (with URL link to www.P65Warnings.ca.gov) and FCC compliance labelling.

 

image

 

The box opens landscape and you are then presented with a quick start guide (leaflet), which happens to be in portrait. Underneath the leaflet we find the Guardian-100 Edge device, which is neatly slotted into a foam insert.

 

{gallery:autoplay=false} Guardian 100 packaging

image

image

image

 

Removing the foam insert, we find 2 x USB cables and 1 x Cat 5 Ethernet cable. One of the USB cables is a micro-USB to USB type-A (male-male) cable, which is used for debugging and sideloading firmware, and the other is a USB 2.0 type-A to type-B cable (male-male) cable, which is used for power and for connecting to external brownfield devices. The USB 2.0 type-A to USB type-B cable is a decent length (6ft / 1.8m), which is great to see.

 

image

 

Also included in the box are 2 x 3M VHB adhesive mounting pads and 4 x mounting feet with 3M adhesive and 2 x mounting screws (as shown below).

 

image

 

 

Teardown

 

The PCB (AES-MS-MT3620-GUARD_PCB-REV A) is housed within a flanged enclosure which has a click-fit screw mounted lid. On the lid we have 4 LED indicators, one for power (green) and three others (amber) for user control. The enclosure itself has a nice black matt finish.

 

image

 

Inside the enclosure the black PCB is mounted with 4 screws. As shown on the block diagram, this PCB includes a number of modules:

  • MT3620 Azure Sphere Device
  • FTDI FT4232HQ USB 2.0 to UART IC
  • MCP2200 USB to UART Converter
  • ENC28J60 SPI to Ethernet Converter

 

 

{gallery:autoplay=false} Inside Guardian 100 enclosure

image

image
image

 

The Azure Sphere Guardian 100 Hardware User Guide (page 9 of version 1.3) provides us with a great use example. So when looking at the block diagram there was nothing obvious that answered my million dollar question, which is  “Can this Guardian-100 device really ring fence a "brownfield" network or device when it's hooked into our standalone network or device and it is communicating with the Azure cloud and/or the Internet”.

 

image

 

To get my head around this question I had to come up with a way to formulate a system architecture using modules I had. So, on a conceptual rather than purely technical level, I came up with the following design:

 

image

 

Thus for the Guardian 100 to deliver what I thought would be necessary, it would be similar to having a CooCox EmbeddedPi module, but with a high performance or multi-core MCU that could be used as the interface to a brownfield network via an Ethernet (TCP/UDP) and USB/Serial connection. This brownfield network interface controller would then be able to collect data from, and possibly send commands to, this network. This controller would then take this data and dispatch it to an edge device, which in my model is a Raspberry Pi, using an ultrasecure and encrypted method to prevent any eavesdropping thereby protecting the integrity of the unconnected network. The Raspberry Pi would then operate as the Gateway Device with secure encrypted Internet connectivity to the Azure cloud.

 

Well, I soon discovered that the Guardian 100 does this far more elegantly. According to the Microsoft Azure documentation, the hardware architecture provides a fundamentally secured computing base for connected devices. An Azure Sphere crossover MCU consists of multiple cores on a single die, as shown in figure below:

 

image

 

As per the datasheet, the Avnet Azure Sphere Module based on MT3620AN SoC provides good processor speed and a decent amount of memory resource:

  • 1x 500MHz ARM Cortex A7, 4MB SRAM
  • 2x 200MHz ARM Cortex M4F cores, 192KB TCM, 64KB SRAM (per core)
  • On-chip QSPI flash memory (16 MB)

 

The Microsoft documentation goes on to say “Each core, and its associated subsystem, is in a different trust domain. The root of trust resides in the Pluton security subsystem. Each layer of the architecture assumes that the layer above it may be compromised. Within each layer, resource isolation and compartmentalisation provide added security.”

 

Then there are numerous ways to architect your firmware on the hardware. Firstly, there is the high-level application core and then there are two real-time cores. Then there are internal hardware firewalls. These are silicon countermeasures that provide “sandbox” protection to ensure that I/O peripherals are accessible only to the core to which they are mapped. The firewalls impose compartmentalisation, thus preventing a security threat that is localised in the high-level application core from affecting the real-time cores’ access to their peripherals.

 

I suppose the bad news is that you can still mess this up through a badly designed software application. It is up to you to utilise the security features embedded within the hardware, such as a security processor core, cryptographic engines, a hardware random number generator, public/private key generation, asymmetric and symmetric encryption, support for elliptic curve digital signature algorithm (ECDSA) verification for secured boot, and measured boot in silicon to support remote attestation with a cloud service, as well as various tampering counter-measures including an entropy detection unit.

 

So the MT3620 + the OS architecture looks really promising. It just means (obviously) that you have to know what you are doing.

 

Let's now dig a little deeper to understand whether this device has to be treated as a peripheral on the brownfield network or needs to act as a central or hub device, like a server.

 

But first let me report on the firmware development process for the Guardian 100.

 

3.0 Firmware Development Review

 

Getting Started

 

Believe it or not, but this road test report got interrupted by the COVID-19 pandemic and the lockdown. On a positive note, it is amazing how a couple of months can make such a difference.

 

I have an old 32-bit Windows 10 based computer and an old Windows 7 laptop, so when I received the Guardian 100, I had to download Microsoft Visual Studio community edition onto another newer Windows 10 laptop that I had borrowed. Unfortunately for me, this resource was then commandeered by the owner and others when lockdown started.

 

Fortunately, during this delay, I spotted that Visual Studio Code IDE could now be used for Azure Sphere devices (and a sigh of relief could be heard) and one could also use Linux OS. Neither of these options were presented in the AVNET documentation at the start of the road test as they were not available at the time.

 

So opportunity beckoned.

 

Well, after a few false starts with Linux OS distros, which I found were not suitable or compatible to my needs, I eventually got up and running on Linux Mint 19 (or Ubuntu 18.04). Once Linux was installed I was then able to install Microsoft Visual Studio Code (VSC) very easily, as VSC is available for install via the Linux app store: snapcraft.io.

 

So, this is how I got started with Linux OS and Visual Studio Code.

 

 

Installation of Azure Sphere SDK on Linux

 

Document reference for this section: https://docs.microsoft.com/en-in/azure-sphere/install/install-sdk-linux?pivots=vs-code-linux

 

The Microsoft documentation now gives you a chance to choose you development environment as this tailors the content to suit your needs. You are given either the chance to install the SDK for Visual Studio Code, or you can simply install for use with the Command Line Interface (CLI).

image

 

The installation process notes that your computer must be running Ubuntu 20.04 LTS or 18.04 LTS.

 

The page does provide nicely detailed and easy to read instructions, although some parts could do with further tips for the novice Linux user.

 

For example, STEP 3 (under the section “Install the Azure Sphere SDK”) instructs the user to “Run the install script. It asks questions and then installs the SDK”. What it fails to do is tell the user that there are other Linux command options that could also be used to allow for logging installation progress to a file and for more verbose output to be provided in the terminal.

 

Steps 4, 5 and 6 refer to checking the SDK tarball fingerprint.

 

You are then presented with a link to the License Agreement (a text file) which you need to agree to.

 

You are then told that some device operations require root permissions, or permissions granted by a udev rule. This is a subtle difference to what the webpage instructions tell us: “After installation, the azsphere command is on the PATH and the new udev rules for your device are at /etc/udev/rules.d/.”

image

 

The rest of the detail provided under section “Install the Azure Sphere SDK” is very transparent. For example, it explains what and where files are installed. I like that.

 

The next section in the Microsoft quickstart guide for the SDK Install is “Set up a device connection”. Having followed through similar instructions given on the Windows 10 laptop in a previous install, I recalled that this step had caught me out.

 

The omission in the Microsoft documentation, is that it fails to tell the new user that they actually need to physically connect the device to your computer using the USB cable and that they need to connect with the USB connector on the PCB (type A micro) and not the type B connector. Other than that using the prescribed script files is very straight forward.

 

The final SDK installation step for Linux is setting up your VSC development environment. Even for a Linux VSC “newbie” I found this process to be painless thanks to the excellent Microsoft documentation.

 

 

Claiming the device and setting up WiFi

 

The Microsoft documentation and section 7 of the AVNET Hardware Guide (Installation Instructions) both cover this important step of creating a tenant and then claiming your device. It’s worth noting that the AVNET hardware guide is purely focused on Windows 10. There is no Linux guidance at this stage (version 1.4).

 

If you are using Windows then refer to the AVNET Hardware Guide as this covers the WiFi setup tool for Windows. Unfortunately, this tool is not available for Linux.

 

This begs the question as to why this tool is included on the Guardian 100 device by default, if it cannot be used on Linux computers. Seems a waste of valuable flash resource on the Guardian 100.

 

The AVNET hardware document has far too many pages about this windows wifi setup tool, in my opinion, and really it should be placed in an appendix.

 

Once again, I found the Microsoft documentation to be superb and nicely balanced.

 

With setup out the way it was time to see what tests can be done with the Guardian 100 and then review what examples or tutorials were available to learn from.

 

 

Initial tests using the Guardian 100

 

The AVNET Hardware Guide contains two tests that can be carried out without any firmware development involved. Unfortunately, I could only get one of those tests to work.

 

The first test available is the Wi-Fi Data Rate Test, which uses an external utility called “iPerf3”.

 

The Windows only instructions for this test can be found in section 14 of the AVNET Hardware Guide.

 

The test also works on Linux, although I struggled to get it to work initially purely because I forgot to set up the port in my firewall.

 

To start this test you need to download a pre-compiled, “production-signed” application. Even though the hardware guide is only a couple of months old the download references and links are wrong. A rather poor show in my opinion by AVNET.

 

Then there is no transparency as to what is contained in the compile Azure Sphere test program, so you have to take your chances with this one.

 

In order to get the compiled test program, you have to do a search on the Element14 website to find it. The image file is contained in a zip file. There is no readme or licensing document attached. I was quite taken aback by this lack of quality control and assurance for firmware earmarked for a device marketed for its robust security. It is exactly this type of shoddiness, which, in my opinion, creates security holes in the first place.

 

What makes a small difference is that “production-signed” firmware means that the software was created using the Azure Sphere SDK and thus will be verified when installing.

 

image

 

The second test available is in section 15 of the AVNET Hardware Guide. It is an Equipment Interface Test, which according to the documentation is aimed at configuring and testing the Guardian’s Wi-Fi, Ethernet and USB-Serial equipment interfaces and the status LEDs.

 

Unfortunately the documentation has errors and the compiled code has to be searched for as before (this time the image file name only partially the name given in the document, as it's missing the ".imagepackage"). Once again, the zip file cotains no attached documentation or licensing.

 

When trying to “sideload deploy” the precompiled code, it failed on my device. As such, this test was not carried out.

 

image

 

Thankfully, I discovered that the Microsoft tutorials and available examples (sample code) could be used to test the Ethernet, WiFi, Serial and LED interfaces.

 

 

Review of Microsoft Azure Sphere tutorials

 

The document reference to these tutorials is: https://docs.microsoft.com/en-in/azure-sphere/install/qs-overview

 

The Microsoft Azure Sphere documentation website provides you with three getting started tutorials, namely:

  • Build a high-level application
  • Create a cloud deployment
  • Build a real-time capable application

 

Where applicable, the webpages lets you configure the content according to your development environment.

image

 

The first two examples are very straightforward. But don’t ignore them.

 

The first tutorial introduces you to one of the most used commands you will use when developing your project, even though the documentation does not explicitly tell you what the command is… which is how to connect the device to your computer when you have the debug micro USB cable attached:

 

sudo /opt/azurespheresdk/Tools/azsphere_connect.sh

 

The gem gleaned from the first tutorial documentation is where all the Azure Sphere examples are stored: https://github.com/Azure/azure-sphere-samples

 

I referred to all these examples regularly.

 

This tutorial also introduces you to another important concept, which is the target hardware definition file. All Microsoft tutorials and examples are based on the MT3620 reference board design. It is a rather important learning step to get to grips with the information provided on this webpage and then to understand how this differs from the Azure Sphere Guardian 100.

 

I really struggled with the 3rd tutorial purely because I did not fully understand the differences and had skipped through knowing these details.

 

The pinout diagram and the table shown below is taken from Appendix A of the AVNET Hardware Guide. However, the last column (Pre-Assigned Guardian 100 Function) is actually not defined anywhere I could find and is probably just linked to some preinstalled demo firmware.

 

 

{gallery:autoplay=false} Guardian100 Pinout Table

image

image

image

 

 

The Azure Sphere Hardware files treat the Guardian 100 as an “avnet_aesms_mt3620” type hardware. So it is best to ignore that last column and work it out for yourself by referring to avnet_aesms_mt3620 json file and using the AVNET table column (MT3620 Net Name) for cross reference.

 

Then, one thing I spotted is that the web tutorial skips out how to start and stop the app. To find out how to do that using the terminal you need to look at the example’s ReadMe file (if ever someone wants a template on how to do a good “readme” then please look at any of these examples). So, read these “readme’s” for once as they are really useful,

 

It’s worth noting that this tutorial example actually runs, as is, on the Guardian 100, as SAMPLE_LED uses the same pin reference to GPIO 8, which happens to control the Red LED on the Guardian 100.

 

Still, it is worth understanding the detail to familiarise yourself with the code structure. Here is one such test example to show how easy it actually is.

 

Expanding Tutorial 1 using Guardian 100 LED’s

 

First things first, we need to change the hardware references.

image

 

That will throw up an error in main.c:

image

 

Simple, we don’t need that "sample_hardware.h" header file so just delete or comment out. Then we just replace it with the correct hardware header file.

image

 

We are now left with one more error in main.c: “SAMPLE_LED” is undefined.

image

 

No problem. Except, we cannot just change that name in main.c to something that the Guardian 100 hardware will understand as “SAMPLE_LED” is also referenced here in the "app_manifest.json" file:

image

 

So, we need to make the change in the two files.

 

For the Guardian 100, we can use “AVNET_AESMS_PIN11_GPIO8” as the pin reference.

 

We are now ready to try out the code if we want, but this is a little boring. Let’s add in the other “user defined” LED’s available on the Guardian 100 using the same code LED blink logic.

 

Here’s a short video demonstrating the result.

 

 

 

Tutorial 2: cloud deployment

 

This tutorial is useful to complete purely to understand the deployment methodology used and how products are defined.

 

When trying out this tutorial no problems were uncovered and everything worked as described.

 

 

Tutorial 3: Build a real-time capable application

image

 

This tutorial takes a bit of thinking through to get working on the Guardian 100 device as the “Set up hardware to display output” section is targeted at another board. So this instruction given in the tutorial “Connect RX on the USB-to-serial adapter to IOM4-0 TX on your dev kit. On MT3620 RDB hardware, IOM4-0 TX is Header 3, pin 6.” is pretty meaningless in our context.

 

Anyhow, after a bit of hassle, I figured out which pin on Guardian 100 can be used with this code to monitor the output. In our case, it is the test pin “IO0” or “IO0_GPIO86/IO0_TXD” as the MT3620 Net Name.

With that discovery out the way, all you do is follow the rest of the tutorial instructions to be able to see the “tick” and the “tock” streaming in real time through the IO0 serial output.

 

With the three tutorials out the way it was time to get familiar with developing an application of my own to test out the two key Guardian 100 interfaces, namely the Ethernet connection and the UART connection using the USB Type-B port.

 

 

 

4.0     Developing a Guardian 100 Ethernet Test Application

 

As mentioned before, there is plenty of documentation support to guide you with Azure Sphere application development on the dedicated Microsoft Azure Sphere website.

 

For Ethernet connection, I used this document reference: https://docs.microsoft.com/en-in/azure-sphere/network/connect-ethernet

 

For sample code, I used the “Private Network Services” example as my basis for testing: https://github.com/Azure/azure-sphere-samples/tree/master/Samples/PrivateNetworkServices

 

According to the code repository readme file, the example code does the following: “It configures the Azure Sphere device to run a DHCP server and an SNTP server, and implements a basic TCP server. The steps below show how to verify this functionality by connecting your computer to this private network.”

 

So it seemed a good place to start from.

 

 

When a picture is worth a 1000 clues

image

There is little to go on as nothing is documented, but based on the outcome of my tests, which I will reveal, the words “Ethernet (device-specific interface)” is particularly insightful when it comes to understanding how the Ethernet DHCP server function works on the Guardian 100 device. So, either the picture explains the behaviour witnessed or it’s a bug or a shortcoming (as it’s default behaviour) with the software that needs evaluating (it has been raised on the Microsoft forum).

As you know, in general, most computers and many connected devices are configured to acquire local area network settings automatically using a Dynamic Host Configuration Protocol (DHCP) server. If no DHCP server is found, then it is common practice for computer or device OS to assign an IP address in the 169.254.x.x range,  which is referred to as a link-local IP address (click here for reference, which is found on ni.com)

 

It is also a common assumption that the number of hosts connected to a (255.255.255.0 or 24) subnet in a DHCP service is typically up to 254 or from the starting address, e.g. 192.168.1.5 up to 192.168.1.254.

 

As such, I did not pay much attention to that diagram (Guardian Use Case example) and created the following topology for testing out my Guardian 100.

image

 

But it did not work as I thought it would.

 

So, when I connected the Arduino Ethernet board to the Guardian 100 DHCP server, it received an IP address that matched the starting address in the code. When I then connected the PC it would timeout and not receive an IP address. With the Beaglebone Black, it display an IP address in the 169.254.x.x range,  which is a similar result.

image

 

It was time to look at the code.

 

/// <summary>
///     Configure and start DHCP server on the specified network interface.
/// </summary>
/// <param name="interfaceName">
///     The name of the network interface on which to start the DHCP server.
/// </param>
/// <returns>
///     ExitCode_Success on success; otherwise another ExitCode value which indicates
///     the specific failure.
/// </returns>

static ExitCode ConfigureAndStartDhcpSever(const char *interfaceName)
{
    Networking_DhcpServerConfig dhcpServerConfig;
    Networking_DhcpServerConfig_Init(&dhcpServerConfig);

    struct in_addr dhcpStartIpAddress;
    inet_aton("192.168.100.11", &dhcpStartIpAddress);

    Networking_DhcpServerConfig_SetLease(&dhcpServerConfig, dhcpStartIpAddress, 1, subnetMask, gatewayIpAddress, 1);
    Networking_DhcpServerConfig_SetNtpServerAddresses(&dhcpServerConfig, &localServerIpAddress, 1);

    int result = Networking_DhcpServer_Start(interfaceName, &dhcpServerConfig);
    Networking_DhcpServerConfig_Destroy(&dhcpServerConfig);
    if (result != 0) {
        Log_Debug("ERROR: Networking_DhcpServer_Start: %d (%s)\n", errno, strerror(errno));
        return ExitCode_StartDhcpServer_StartDhcp;
    }
    Log_Debug("INFO: DHCP server has started on network interface: %s.\n", interfaceName);
    return ExitCode_Success;
}

 

Within the code there is a function called ConfigureAndStartDhcpSever and within this function there is a networking API function called Networking_DhcpServerConfig_SetLease. The parameter of interest is called ipAddressCount, which, according to the documentation, is the number of IP addresses the server can lease.

 

However, when I tried to change this value to something greater than 1, it returned an error.

 

So currently, the functionality of the networking API for the Avnet Sphere device is to allow a single client connection client only.

 

With that discovery out the way it was time to test the rest of the PrivateNetworkingService sample code. The sample code, allows for TCP communication on port 11,000 and it provides an SNTP server function, where the Azure Sphere uses WiFi to connect to the Internet.

 

Here is a video demo of this sample code being used with the Guardian-100 device.

 

 

The client device, shown in the video, was simply an Arduino Mega 2560 with a WZ5100 Ethernet Shield. When it requests the time using a standard Arduino UDP NTP library, instead of specifying the actual NTP time server (e.g. pool.ntp.org) the local host server address is specified and the Azure Sphere does the rest, securely, thus separating the private network from a public network.

 

This to me is nice clean demonstration of the principles behind the Azure Sphere device and would give me some confidence to attach the Azure Sphere to a brownfield site operating on a private network and develop a securely connected application to provide remote insights and possibly control into the brownfield site.

 

 

5.0     Conclusion

 

There is saying "don't use a sledgehammer to crack a nut", implying, within an engineering context, that we should be careful not to over-engineer and apply disproportionate effort to deliver a solution if a simple design would justly do the job. However, in a connected context, we could add that we should "use a sledgehammer to protect a nut" if that nut is valuable to your business. I believe that the Azure Sphere could well be that sledgehammer.

 

In my opinion it offers the right functionality to rightly be called a secure edge device suitable for a brownfield site.

Anonymous
  • Here is the Arduino Ethernet Code

     

    /*
      DHCP-based IP with Telnet client to prescribed server
    
      This sketch uses the DHCP extensions to the Ethernet library
      to get an IP address via DHCP and print the address obtained.
      using an Arduino Wiznet Ethernet shield.
    
      created 12 April 2011
      modified 9 Apr 2012
      by Tom Igoe
      modified 02 Sept 2015
      by Arturo Guadalupi
    
     */
    
     /* March 2020: Code modified by BigG (Gerrikoio) for Element14 Azure Sphere Guiardian 100 Roadest */
    
    #include <SPI.h>
    #include <Ethernet.h>
    #include <NTPClient.h>
    #include <EthernetUdp.h>
    
    const uint32_t AUTODISCONNECT = 90000;      // Set to zero to disable auto disconnect
    const uint32_t TIMEINTERVAL = 10000;
    uint32_t t_check = 0;
    uint32_t t_time = 0;
    
    bool FirstTime = true;
    bool TCPServerConnected = false;
    
    // Enter a MAC address for your controller below (Arduino Ethernet MAC Address).
    //byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x3A, 0xF1 };
    
    byte mac[] = { 0xDE, 0xAD, 0xBE, 0x0A, 0x0B, 0x02 };
    
    // Enter the IP address of the server you're connecting to:
    IPAddress server(192, 168, 100, 10);
    
    // Initialize the Ethernet client library with the IP address and port of the server
    // that you want to connect to (AzureSphere example uses port 11000):
    EthernetClient client;
    
    EthernetUDP ntpUDP;
    // You can specify the time server pool and the offset (in seconds, can be
    // changed later with setTimeOffset() ). Additionaly you can specify the
    // update interval (in milliseconds, can be changed using setUpdateInterval() ).
    NTPClient timeClient(ntpUDP, "192.168.100.10", 3600);
    
    
    void setup() {
      randomSeed(analogRead(A0)*analogRead(A0));
      // Use Ethernet.init(pin) to configure the CS pin
      Ethernet.init(10);
    
      // Open serial communications and wait for port to open:
      Serial.begin(57600);
      while (!Serial) {
        ; // wait for serial port to connect. Needed for native USB port only
      }
      delay(2000);
    
      // start the Ethernet connection:
      Serial.println(F("Initializing Ethernet with DHCP:"));
      if (Ethernet.begin(mac) == 0) {
        Serial.println(F("- Failed to configure Ethernet using DHCP"));
        // no point in carrying on, so do nothing forevermore:
        if (Ethernet.linkStatus() == LinkOFF) {
          Serial.println(F("-- Ethernet cable is not connected."));
        }
        while (true) {
          delay(10);
        }
      }
      
      
      // print your local IP address:
      Serial.print(F("DHCP IP address received: "));
      Serial.println(Ethernet.localIP());
    
      // give the Ethernet shield a second to initialize:
      delay(500);
      Serial.println(("Connecting to server..."));
    
      // try and get a connection, report back via serial:
      for (uint8_t x = 0; x <3; x++) {
        if (client.connect(server, 11000) == 1) {
          Serial.println(F("- connected to Guardian 100...sending intro"));
          if (AUTODISCONNECT) t_check = millis();             // For auto disconnect
          
          sendTCPdata();
          
          timeClient.begin();
          t_time = millis();
          
          TCPServerConnected = true;
          break;
          
        } else {
          // if you didn't get a connection to the server:
          Serial.println(F("- connection failed"));
          delay(1000);
        }
      }
        
    }
    
    void loop() {
      
      if ((millis() - t_time) > TIMEINTERVAL) {
        if (FirstTime) {
          Serial.println(F("Received time update from AzureSphere SNTP server"));
          FirstTime = false;
        }
        timeClient.update();
        Serial.println(timeClient.getFormattedTime());
        t_time = millis();
      }
      
      // if there are incoming bytes available
      // from the server, read them and print them:
      if (client.available()) {
        char c = client.read();
        Serial.print(c);
      }
    
      // as long as there are bytes in the serial queue,
      // read them and send them out the socket if it's open:
      while (Serial.available() > 0) {
        char inChar = Serial.read();
        if (client.connected()) {
          client.print(inChar);
        }
      }
    
      // if the server's disconnected, stop the client:
      if (!client.connected()) {
        Serial.println();
        Serial.println(F("...client not connected. Disconnecting."));
        client.stop();
        // do nothing:
        while (true) {
          delay(1);
        }
      }
      else {
        switch (Ethernet.maintain()) {
          case 1:   //renewed fail        
            Serial.println(F("Error: renewed fail"));
            break;
      
          case 2: //renewed success
            Serial.println("Renewed success");
            Serial.print("My IP address: ");
            Serial.println(Ethernet.localIP());
            break;
      
          case 3: //rebind fail
            Serial.println("Error: rebind fail");
            break;
      
          case 4: //rebind success
            Serial.println("Rebind success");
            Serial.print("My IP address: ");
            Serial.println(Ethernet.localIP());
            break;
      
          default:
            //nothing happened
            break;
        }
        if (!TCPServerConnected) {
          sendTCPdata();
          timeClient.begin();
          t_time = millis();
          TCPServerConnected = true;
        }
      }
    
      if (AUTODISCONNECT && (millis() - t_check) > AUTODISCONNECT) {
        Serial.println(F("...auto disconnecting."));
        client.stop();
      }
    
    }
    
    void sendTCPdata() {
      client.println("E14 Roadtest");
      Serial.print(F("-- server: "));
      //wait
      while (!client.available()){;;}
      
      // if there are incoming bytes available
      // from the server, read them and print them:
      while (client.available()) {
        char c = client.read();
        Serial.print(c);
      }
    
      // Send to Server the Ethernet Hardware
      if (Ethernet.hardwareStatus() == EthernetW5100) {
        Serial.println(F("- sending: W5100 NTPclient"));
        client.println("I'm a W5100");
      }
      else if (Ethernet.hardwareStatus() == EthernetW5200) {
        Serial.println(F("- sending: W5200 client"));
        client.println("I'm a W5200");
      }
      else if (Ethernet.hardwareStatus() == EthernetW5500) {
        Serial.println(F("- sending: W5500 NTPclient"));
        client.println("I'm a W5500");
      }
    }

  • I would like to get the sample code for arduino or raspberrypi which is a client to Azure gaurdian server