How to affordably deploy network attached devices in the real world

devices

If you have a network attached widget you want to put out into the world you will soon discover that deploying it is not as simple as you might think. You will discover that every business has a different standard or setup of how to setup the network. If individual deployment/installation requires a skilled technician to install and debug, this will severely limit your market penetration.

First lets back up and talk about what we are trying to accomplish.

It would be nice if the world looked like this:

IE both the NetBurner and the computer try to talk each other. If the NetBurner were really out on the Internet the picture be much different.

The reality is much more likely to be this:

With both the computer and the NetBurner behind a NAT router, without changing the configuration of the NAT router on one end or the other, you will not be able to communicate at all. The solution people seem to be converging toward is to have both sides of the conversation talk to some computer in the cloud.

This computer either stores and forwards data, or passes messages. The development of this software to run on this “Cloud” device is not really what this discussion is about. I’m going to assume that all of that is setup and it all works. What I’m going to discuss here is how to deploy a new node into the world. IE add a new customer, store, business etc.

Before you deploy:

If the place you’re deploying a new node has an IT group you probably need to talk to them before you deploy the new node. If it does not then you can probably assume its setup with a NAT router supporting DHCP.
If not you need ask the IT group:

  1. Does the system support DHCP?
  2. Do I need to do anything special to get outbound web access ?
  3. Do you need to setup special permission for my device.

It’s quite common in large organization to have to get specific per device permission to make an outbound connection.

Once the device is installed.

Once the device is installed it would be really nice if you could just plug it in and everything would work. In the real world this seems to happen about 50% of the time. So for the other 50% of the time we need to understand what happens.

Steps for the device to come online in the process:

  1. Device is connected to Ethernet cable and gets Ethernet link
    Failure here is indicated by no link light….
  2. Device either has a static pre-assigned IP or gets DHCP IP
    Failure here is no assigned address and no DHCP server. This failure needs to be handled in your code and indicated to the installer by some flashing light or serial port message etc…
  3. Device has a gateway address for talking to the world
    Some times the DHCP server or the preconfigured IP address don’t include a gateway address, or the gateway address is not compatible with the programmed or delivered net mask. Again the only way to detect this is programmatically, and you need some way to notify the user…
  4. Device can ping the gateway
    IE can we actually route to the gateway… we may have one programmed, or one set by DHCP , but it does not mean you can actually reach it. Again needs to be detected and have an external indicator.
  5. Device has a DNS address to resolve DNS
    This is the identical situation to the Gateway.. IE may not be configured, may not be right.
  6. Device can resolve the DNS address of the location we are connecting to.
    So your connecting to www.myservice.com…. You need to resolve this name to an IP address. This may fail, ie someone configured the software wrong/ and or the corporate DNS you are connected to won’t give you that address. Again this needs to be detected and indcated to the user…
  7. Device can actually connect to the outside server.

So what does this look like for the users perspective?

I have recently helped deploy a system based on the PK70. This device contacts a central server for messages and then plays them over a 2 way radio.

We used the PK70 lights to indicate state and here is the cheat sheet given to the installer.

Left LED Right LED Status
Blink Red Blink Red No Ethernet Link
Blink Red Off No DHCP or Configured IP
Off Blink Red No Gateway address or cant ping
Steady Red Steady Red No DNS address
Steady Red Off Cant Resolve Server Name
Steady Green Off Contacted Server, it had no messages
Blink Green Green Message Received, Radio is busy
Off Blink Green Radio is busy no message to send
Steady Green Steady Red We are talking on the radio.

So how to you accomplish this in code?

//While loop indicating errors by LED state and serial port message
//We sit in this while loop until we are able to connect…
while (1)
{
 while (ip==0) //While we don't have an IP for server   
  {
    while (!EtherLink())
    {
        iprintf("No Ethernet Linkrn"); 
        LedState=LED_NO_ETHERNET; 
        OSTimeDly(TICKS_PER_SECOND);
    };
    while (EthernetIP==0)
    {
        iprintf("No Ethernet Addressrn"); 
        LedState=LED_NO_ADDRESS; 
        OSTimeDly(TICKS_PER_SECOND);
    };

    while (EthernetIpGate==0)
    {
        iprintf("No Ethernet Gateway Addressrn"); 
        LedState=LED_NO_GATEWAY; 
        OSTimeDly(TICKS_PER_SECOND);
    };

    while ((EthernetIpGate&EthernetIpMask) !=(EthernetIpMask&EthernetIP ))
    {
        iprintf("Gateway Address Wrong Subnetrn"); 
        LedState=LED_GATEWAY_WRONG; 
        OSTimeDly(TICKS_PER_SECOND);
    };

    while (EthernetDNS==0)
    {
        iprintf("No Ethernet DNS Addressrn"); 
        LedState=LED_NO_DNS_ADDR; 
        OSTimeDly(TICKS_PER_SECOND);
    };


    if (GetHostByName(pAddress,&ip,0,SLEEP_INTERVAL.tval())==DNS_OK)
    {
        iprintf("IP Address ="); ShowIP(ip);
        siprintf(tRequest,"GET /%s?%s HTTP/1.1rnHost:%srnrn",
                 pUrl,
                 DEVICENAME.string(),
                 pAddress
                 );

        iprintf("Request =[%s]rn",tRequest);
    } else
    {
        LedState=LED_NO_DNS_RESOLVE;
        iprintf("Failed to get DNS addressrn");
    }
}//While loop waiting for the world to setup

    //To get here we talked to DNS and got an ip address   

    DWORD LastStartTime=TimeTick;
    DWORD LastConTime=0;
    DWORD LastReadDoneTime=0;

    int fd=connect(ip,0,OUTBOUND_PORT.wval(),SLEEP_INTERVAL.tval());
    if (fd<0)
    {
        LedState=LED_NO_SERVER_CONNECT;
        ip=0;//We failed start DNS over...
    } else
    {
        LastConTime=TimeTick;
        writestring(fd,tRequest);//Send the server a reauest...
        int nread=0;
        while (1)
        {
            int rv=ReadWithTimeout(fd,
                              tResponse+nread,
                              RESPONSE_SIZE-nread,
                              REQUEST_TIMEOUT.tval()
                              );
            if (bLog)   
   iprintf("Read at %ldrn",TimeTick-LastStartTime);
            if (rv>0)
            {
                nread+=rv;
                if (nread>=(RESPONSE_SIZE-1)) break;
                tResponse[nread]=0;
            } else
                break;
        };
        LastReadDoneTime=TimeTick;
        if (nread)
        {//Process the request we received 
        }
        close(fd);

        DWORD tl=LastStartTime+SLEEP_INTERVAL.tval();
        DWORD now=TimeTick;
        if ((now < tl) && ((tl-now)<0xFFFF)) OSTimeDly((WORD)(tl-now));
    }

Please comment if you have any questions!

Share this post

Subscribe to our Newsletter

Get monthly updates from our Learn Blog with the latest in IoT and Embedded technology news, trends, tutorial and best practices. Or just opt in for product change notifications.

Leave a Reply
Click to access the login or register cheese