A customer of ours has embedded products with sensors and actuators. Now they would like to connect this device to the cloud so they can remotely monitor and configure it. It should support:
- Periodic data updates (LwM2M read or notify? Depends on how we implement it)
- Alerts (e.g. data above threshold) (LwM2M notifies)
- Configuration updates (LwM2M writes)
- LwM2M Execute triggers
- Optionally Cloud-to-Device data requests (that gets the most recent reading)
They want us to provide them with a simple module to accomplish this.
Our company is already using LwM2M quite extensively. More specifically, we have devices running Zephyr RTOS that use the built-in LwM2M engine. This engine requires to know the layout of the OMA/IPSO objects (which resources, what are their properties, etc.). Also, we register data pointers to the resources, and register read callbacks so that a read from the cloud triggers an update of those data before responding. Lastly, we also register write callbacks for e.g. configuration settings, so that they can trigger the required actions.
The LwM2M object .c files use an Observer pattern to observe the sensors/status/data in the appropriate other software modules, and the write callbacks call "SetConfig" type of functions directly at the target modules. This has led to quite tight coupling.
Now I'm investigating how to best integrate this functionality in an easy-to-use and generic module
I think the first step is to get rid of the tight coupling I described above, and thus maybe move all the Observers to a single module that handles all communication between the LwM2M objects/engine and the rest of the system? (Mediator / Facade pattern?)
I made this analysis of what that module would need to support the wished functionalities:
- Periodic data updates -> An update interval must be set per resource. Alternatively, the LwM2M server could set observe attributes pmin, pmax to trigger periodic notifies and thus periodic reads, these reads would then trigger read callbacks that update the info before responding to the server.
- Data threshold alerts -> Alert trigger that trigger a notify to the server.
- Configuration updates -> Write callbacks that take appropriate action (e.g. configure interrupt threshold).
- LwM2M Execute triggers -> Execute callback that takes appropriate action (e.g. reboot device).
- Optionally Cloud-triggered data updates -> Read callbacks that update the info before responding to the server.
What I find difficult
- As you can see, functionality 2 and 5 are sort of opposite (push vs. pull), but functionality 1 can be implemented in 1 of 2 ways, either push or pull. This is part of what I find challenging, there seems no generic solution for all 3?
- If we would choose server-triggered periodic updates (via the observe attributes), I see two problems: If the customer requires that no periodic sensor-data is lost on network failure, this can't work. Also, I think all resources in an object with different settings would require separate observes?
- The other thing I find challenging is the module interface design.
From the above ideas, it would require aliases for each resource to abstract away the LwM2M internals object/resource structure, and the following data per alias:
- Update interval (if the device is the one with the update schedule)
- Alert trigger
- Read callback
- Write callback
- Execute callback
- If going with the idea from challenge 3: This is quite an extensive list, and if the embedded firmware changes at the LwM2M module boundary, or if the LwM2M cloud API changes, this would require our interference, as we would have to update the internal resource mapping.