Feature #501


Implement device node registration

Added by Hammel over 8 years ago. Updated almost 6 years ago.

Device Node
Target version:
Start date:
24 Feb 2016
Due date:
% Done:


Estimated time:
02 - High


This is the device node registering with the PiBox server.

  1. Device node must be configured for local network first (that's already implemented)
  2. At boot, the node sends a multicast message advertising its device type and version. It's IP address will be available from the multicast message (I think).
  3. The PiBox server picks up the multicast message and calls back to the Device Node using it's RESTful api.
    1. This requires an additional thread in piboxd to pick up the registrations on the multicast address.
  4. The device node configures itself appropriately and disables the multicast messages.

I need to define what it means to be "registered". Registration should also only occur when a user enables it on the server so we don't have random registration of rogue devices.

Related issues

Related to Monitor - Bug #623: Enable Pair Mode in imrest at runtime if button enabledClosedHammel07 May 2018

Actions #1

Updated by Hammel over 8 years ago

Here is a discussion on using multicast with the ESP8266.

There should be a function that handles sending multicast packets. It tests for a flag. If the flag is not set, send the packet. If it is then skip it. The flag is set by the response from the PiBox server.

The sendRegistration() function does this:

  Serial.println("Sending UDP multicast packet");
  // send a reply, to the IP address and port that sent us the packet we received
  Udp.beginPacketMulticast(ipMulti, portMulti, WiFi.localIP());
  Udp.print(ESP.getChipId(), HEX);

The UDP object is a WiFiUdp class, which is found here: Arduino/libraries/ESP8266WiFi/src/WiFiUdp.cpp
That class has no documentation so you'll have to read the code. There are two write() methods, one for a byte and one for a character string. So the registration protocol will either be a bit string or a character string or both.

It seems likely that the response will include a UUID for the device node but the registration won't need anything like that. It should probably send one or more bytes, with the bytes being bit fields for device type and version values. A third byte may be used for encryption info, perhaps.

There are good examples of using Multicast in C programs for both client and server on the web.

Actions #2

Updated by Hammel over 8 years ago

  • Status changed from New to In Progress
  • % Done changed from 0 to 10

I added a multicast server to piboxd along with a unit test. Seems to work fine. It will call back to the sender at the following URL (via libcurl): http://<IPADDR>/im/1/registration/1, which means "registration accepted".

There is additional code that needs to go in here to remember a registration and to forget a registration if contact is lost for more than X number of pings. Plus I need a "ping" thread to go with this.

But the basic server is implemented.

Actions #3

Updated by Hammel over 8 years ago

I just realized that device registration needs to survive a power cycle. Since PiBox is not depending on cloud-based data storage, this means a local-storage-based database has to be used. Both MySQL and sqlist are enabled in PiBox. This use-case doesn't need the power of MySQL. Even sqlite could be overkill.

A simpler solution would be to use an abstract block of name/value pairs. This could easily be done in JSON using the parson library. Data is added/removed/etc from the data block and the data block as a whole is saved to disk using a double-buffer mechanism (write to new file, save old file, move new file to old file, remove saved file) to avoid data corruption. We will never have that much information to store - even thousands of devices wouldn't be that much data and we expire old data when devices go away.

Parson is a single C file. I use it at work for a message passing library. The library wraps Parson and exposes an API that uses namespaces for name/value pairs. The same idea works here. A namespace is a device and it contains the name/value pair of data we maintain about those devices.

I can't reuse the code from work, but since I wrote it I can recreate it from scratch. It's extremely simple in our case since we drop all the message passing stuff. We just need a simplified wrapper around parson.

The bonus will be that piboxd will then have a JSON library embedded in it for other uses. And we can use the simplified data-block API I'll add for device nodes or call parson directly. Very cool.

Integration of parson for data stores is an MVP issue. It will not be implemented for proof-of-concept. In the PoC if we lose power devices have to re-register. Note that this might be something we'd want to do in MVP - reregister a device if it hasn't heard from the server in a while. But that's a power drain on the IoT device, to keep track of when it was last contacted. It wouldn't be able to run in low-power mode (unless low-power mode supports multicast).

UPDATE: duh. Parson makes perfect sense for in-memory storage too. There's no reason to write a link list library to handle new device registrations. Parson can handle that now. So I'll integrate parson now, for the IoT registration in the PoC. That will speed implementation. I'll abstract the data block later, for MVP.

Actions #4

Updated by Hammel over 8 years ago

  • % Done changed from 10 to 50

Device registration succeeded tonight. The node came up, sent a registration which the piboxd server received and the server responded by contacting the node. It wasn't a full success because there are still some bits of the two-way transaction that need cleaning up.

What's left to do:
I can't tell. I need to see it happen again but the WiFi won't connect to the local network again. This is a continuing problem that I will need to solve before I can go any further. I believe the solution will be to fix the layout of WiFi routers in my home.

Actions #5

Updated by Hammel over 8 years ago

  • Priority changed from Immediate to Normal
  • Target version changed from 0.1.0 - Proof of concept to 0.5.0
I got it to work again. Here's what's left to do.
  1. Implement persistance in the server
    1. write data to file on exit
    2. read data from file on startup
  2. Implement device validation of commands using Uuid
  3. Implement reset
    1. Server sends multicast to devices
    2. Devices send registration requests again

None of this has to be done for the proof of concept. But it's required for MVP.

Switching to MVP for further work and lowering priority.

Actions #6

Updated by Hammel over 8 years ago

Added aJSON library and code for using JSON-formatted registration of device features for damper device. This is necessary for PoC implementation but will probably be broken into libraries later for different devices.

Actions #7

Updated by Hammel almost 6 years ago

  • % Done changed from 50 to 80

Device node registration changed dramatically. First, piboxd is now simply a responder to multicast discovery messages. This is implemented and tested against both Jarvis and sensors and is working properly.

Second, real registration between sensors and the monitor is now routed through the imrest REST API. This is mostly tested. I still need to fake availability of the imgpio and have both piboxd and imrest query the same directory for existing registrations during testing.

Actions #8

Updated by Hammel almost 6 years ago

  • Priority changed from Normal to Immediate
  • Severity changed from 03 - Medium to 02 - High
Actions #9

Updated by Hammel almost 6 years ago

  • Status changed from In Progress to Closed
  • % Done changed from 80 to 100

Closing this issue. Device node registration has been tested as working. If I discover bugs or inadequacies later I'll open new issues.

All code committed and pushed.

Closing issue.


Also available in: Atom PDF