Feature #501

Implement device node registration

Added by Hammel over 1 year ago. Updated over 1 year ago.

Status:In ProgressStart date:24 Feb 2016
Priority:NormalDue date:
Assignee:Hammel% Done:

50%

Category:Device Node
Target version:002 - MVP
Severity:03 - Medium

Description

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.

Associated revisions

Revision ae454ae0
Added by Hammel over 1 year ago

RM #501: Implemented multicast server for accepting device node registration requests. Added unit test to verify inbound message handling.

Revision b44178c4
Added by Hammel over 1 year ago

RM #501: Add missing "$" to PIBOX_PORT when referenced in nc calls.

Revision a9a6e926
Added by Hammel over 1 year ago

RM #501: Implemented multicast server to handle IoT device registration.

Revision 3511de4c
Added by Hammel over 1 year ago

RM #501: Implement device registration via multicast messages and a RESTful interface.

Revision e70bf729
Added by Hammel over 1 year ago

RM #501: Add aJSON library support so the ESP8266 can send JSON messages to the server in support of registration.

Revision 703e413e
Added by Hammel over 1 year ago

RM #501: Implemented basic JSON-formatted registration for damper device.

History

#1 Updated by Hammel over 1 year 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.write(byte1);
  Udp.write(byte2);
  Udp.print(ESP.getChipId(), HEX);
  Udp.print(":");
  Udp.print(WiFi.localIP());
  Udp.endPacket();

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.

#2 Updated by Hammel over 1 year 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.

#3 Updated by Hammel over 1 year 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.

#4 Updated by Hammel over 1 year 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.

#5 Updated by Hammel over 1 year ago

  • Priority changed from Immediate to Normal
  • Target version changed from 001 - Proof of concept to 002 - MVP
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.

#6 Updated by Hammel over 1 year 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.

Also available in: Atom PDF