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:

  1. Periodic data updates (LwM2M read or notify? Depends on how we implement it)
  2. Alerts (e.g. data above threshold) (LwM2M notifies)
  3. Configuration updates (LwM2M writes)
  4. LwM2M Execute triggers
  5. 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:

  1. 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.
  2. Data threshold alerts -> Alert trigger that trigger a notify to the server.
  3. Configuration updates -> Write callbacks that take appropriate action (e.g. configure interrupt threshold).
  4. LwM2M Execute triggers -> Execute callback that takes appropriate action (e.g. reboot device).
  5. Optionally Cloud-triggered data updates -> Read callbacks that update the info before responding to the server.

What I find difficult

  1. 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?
  2. 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?
  3. 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
  4. 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.

I'm very curious for your opinions, remarks and ideas on this! I would very much appreciate your advice.

  • I see a lot of technical non-functional requirements here. Have you thought about the functional requirements and how these non-functional requirements can best serve the functional requirements (i.e. your use cases)? If you can answer that, I think you'll find out what "best" means for your project and how you can effectively achieve it. Commented Jan 15, 2021 at 14:43
  • For example, you mentioned tight coupling, and how you would eliminate it as the first step. Loose coupling implies a need for your software to be modular enough where it can endure a significant number of changes and updates over time. Is this an actual need, or merely an impulse to satisfy "industry best-practices?" Commented Jan 15, 2021 at 14:52
  • Thank you for your response @RobertHarvey! I think the 5 features it should support are the only functional requirements (where nr. 5 is optional). As for non-functional: it should be modular because our company hopes to help more customers with this module in the future. How far to take this is difficult. If we would move the direct links to a single "mediator" that we ourselves would have to set up anyways, perhaps the resource aliasing and the associated parameters are not needed.
    – Kodiak
    Commented Jan 15, 2021 at 15:17
  • 1
    Yagni? Commented Jan 15, 2021 at 15:31
  • 1
    Well, I'm not there, and I don't know all of your context. Design, like everything else in software development, is an exercise in tradeoffs. The decisions you make should be based on cost/benefit analysis of your specific situation. Commented Jan 16, 2021 at 19:54


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.