Distributed node functionality Feb 2016
Just to avoid any possible confusion: the case made in the previous article for “centralised node management” is not meant to imply that nodes need to operate in a centralised fashion!
This is where design and development are really distinct from the decisions on what remote nodes (wireless as well as wired) actually do. We may well want to design a home automation infrastructure where a light-switch node sends out a signal when pressed, only intended for another node in the same room, controlling a lamp attached to it.
JET uses MQTT as its central message exchange “switchboard” (or “bus”, rather), which is indeed a centralised design. A model of automation where all decisions are made centrally is probably also going to be the main (or at least initial) mode of operation for JET and its hub. But all such decisions can be made on a case-by-case basis: you could for example, decide to use the central system only as a “data collection centre”, with all home-automation decisions taking place in the periphery, by the actual nodes involved in (and affected by) a particular event.
This leads to a design whereby the central node doesn’t end up becoming a potential “single point of failure”, an important concept in reliability engineering. A system without central decision-taking authority is able to limit the effect of any failure, allowing the rest of the system to continue to function. So that a faulty light switch in the garage will not affect the heating control system (assuming that different nodes are involved in these two functions).
Warning: what follows is HIGHLY tentative - it’s just a (wild) thought experiment for now!
The “bigger” plan for JET is to create a range of different node types, each with a specific set of sensors and other hardware, and to manage each of these remote units from a central node attached to the hub. This includes the source code, its cross-compilation, and the upload process to get the resulting firmware “flashed” into the remote units (either over the air, or by wiring them up temporarily). This will allow managing versions and revisions, especially when tied to each remote µC’s built-in unique “hardware ID”.
But the story does not end there. The idea in JET is to separate the functionality (i.e. basic capabilities and hardware drivers) from the wiring (i.e. the way all the available functions are tied together). The basic capabilities will have to be hard-coded into the firmware as C/C++ code, but the wiring is going to be implemented as (soft) data, i.e. as a (possibly quite elaborate) data structure describing all the periodic events, sensor triggers, and actual “readings”, and how these should be routed - both inside each remote node and between these nodes (as messages).
For the existing (currently all-wireless) nodes here at JeeLabs - which all happen to be various generations of JeeNodes - very little will change: they’ll continue to broadcast their sensor readings as is, without any notion of where that data ends up or what is done with it.
For future nodes, the aim is to build a lot more flexibility into them, by adding support for rules and a certain amount of decision-making capability. All driven from “wiring diagrams” and customisable for each individual node. An example of this could be a set of rules to behave as follows: “report motion detection immediately, but also send a trigger to a specific lamp if it’s dark outside”. Then again, maybe this logic should not be the motion sensor’s role, but the lamp’s role, i.e. we could instead tell the lamp node to listen for motion and light level messages, and let it decide for itself whether its lamp should be turned on. We can explore both avenues.
The idea here is not to come up with a design right now, but to illustrate how configurable “smarts” could be encoded as rules, sent out (and managed) by the central node, but leading to autonomous behaviour in the remote nodes. This can really only work when this kind of behaviour is designed for the network as a whole, and not simply by throwing new nodes in and leaving the old ones alone. Clearly, all of this will need to evolve over time - as we gradually find out and evaluate what sort of behaviour we actually want for our home!
With changes limited to sending out new wiring diagrams, we can greatly reduce the risk of failure and serious disruption in the case of (occasional, but inevitable) mistakes. These wiring diagrams are likely to be quite small, compared to a full firmware upgrade, and since we’re not altering the firmware itself, we’ll also benefit in the extremely important area of security: it’ll be impossible to make nodes do things they were definitely not intended to do, if their firmware stays intact (assuming it properly validates all incoming wiring changes!).
A nice side-effect (for everyone who is not a deep-diving C/C++ programmer), is that firmware recompiles will not be required to change a node’s behaviour: that’ll be controlled by the wiring.
Another benefit with this data-driven approach: with the separation of code and data, different node architectures can be tried out, with different µC boards and different RF technologies. As long as all the nodes understand the same basic common data structure conventions, we’ll be able to mix / replace / upgrade as needed, and make them inter-operate as much as we like.