Slightly modified version of my question to my fibaro group pasted here:
I've been thinking about fundamental design questions and I have one about event handling and initialisation:
Current design- keep it local
So far I have written my flows such that I drop each device that I am using in the flow on the canvas as a unique node.
On initialisation and on event I am using the messages from each device to update my local variables with values and to trigger parts of the flows - the bits I like to call the engines. These event messages also flow through my caching nodes to update uibuilder which in turn is updating the front end UI.
The benefits:
its simpler to visualise what's happening when coming back to a flow for maintenance / debugging / enhancements
there is no need to handle messages from the home-centre (controller node) as the messages within a flow relate to that flow
The costs:
more maintenance if I change device names; should one day become minimal when my system settles down
more maintenance / regression testing due to breaking changes in my home automation controller, for example, if the inbound data structure changes
less efficient than a centralised event handler - read below for more comments
Alternate design - Centralised event handler
An alternative approach would be to build an event handler:
such that on initialisation I store the entire devices API scrape (that happens anyway, given how the fibaro devices contrib has been written) + additional values that I need into global variables
on event I would update the global variables and trigger flows
The event handler may be more complex in that:
I am disassociating the device values from the flows, so for example, it may make debugging more complex
I would have probably setup a function to query fibaro for any values that are not included in the devices scrape; which I would to do in the current design anyway (but on a device-by-device basis), but again, it may become complex to maintain / debug
I would most likely direct messages to flows from the event handler - an overhead to maintain centrally and could add complexity to the code set, to maintenance and to debugging
However on the positive side:
the event handler may be easier to maintain when creating new flows, as everything feeds off a single set of data
It may be easier to maintain as the current method could become complex when devices are found on multiple flows, for example, when asking the question, which device is writing its state to the global variable that stores device states*
*However I could mitigate this, by storing duplicate states in each flow or by maintaining my own record of which flow is my NR golden source.
it should be more efficient in the long run
It feels to me conceptually that the event handler is the smarter / better / proper coders way to do things, and depending on the actual design it should be more efficient, but I can't drop this nagging feeling that it will just complicate things for what may end up being a minor efficiency gain or maybe even a noticeable efficiency gain in terms of CPU, but no real gain in terms of the end user experience. Bearing in mind that so far, I don't see NR being inefficient in any real way when used with uibuilder.
Any thoughts to share?
You may be able to tell that, in the balance, I'm leaning to sticking with the current setup, but I'm torn with the idea of should I be writing it in a more efficient (albeit, more complex) centralised module
You position is similar to mine with the Drayton Wiser heating system.
Indeed. It is almost certain that you will eventually change or, even more likely, add another controller.
Once you have everything into 1 or a few global variables in Node-RED, it makes little difference how you update them. Indeed, you are likely to end up with multiple update points.
It is very unlikely that you will end up with a single approach anyway, you will still need the specific data for your controller. For example, I will maintain separate objects for both the Wiser data and the raw input data from my RFXtrx433e because in the first case, I don't know what I'll need from that data and I have to grab it anyway. In the 2nd case, you sometimes need to see the original raw data to work out what is going on.
You will also end up with mapping tables between raw ID's and more useful structures such as human-readable room names for example.
Having the central, common data structure however, gives you a lot of flexibility.
One thing is always true - that you don't know what you need in the future.
Event handlers are indeed a good way to work - however, not everything supports that - such as the Wiser - having the central data means that you have data under your control which you will find useful for your own processing and UI's.
You will see from other threads that I'm building a module that takes a regular polling of the wiser controller (the only option) and creates an event driven interface from it.
I do something similar with the data from the RFXtrx433e - ensuring that the incoming data is enriched and standardised. This makes downstream processing a lot simpler.
Aha, so you're a night owl as well... I have an "issue" that when I get design ideas in my head I can't sleep.
Since embarking on thinking about how to design my entire NR system I haven't been able to focus on much else... fortunately it's not my morning with the kids tomorrow, and coffee is my friend!
Tomorrow I'm sure I'll move onto something else, like the best way (read: the best way my simple, non-programmer, brain can come up with) to design an automated lighting controller e.g.
a) centralised motion, lux and humidity triggers
b) lighting engine
b1) should the current state of a light be changed i.e. is there a current manual override
b2) turn lights on if they need to be turned on e.g motion triggered, light level has dropped, humidity is high i.e. shower is on, so turn on shower alcove lights and maybe (depending on the outside temp, turn the mirror heat pad on)
b3) dim lights when they need to be dimmed
b4) turn lights off when they need to be turned off
Sounds very easy when you put it that way.
I wrote my Fibaro lighting controller as 6 different scenes, with each one doing a specific task. I had seen every other implementation write an all-in-one scene for a zone/room. but given the number of zones I have, i didn't want to maintain duplicate code in what would become around 20 zones.
This is actually one of the reasons I love NR. It makes complete sense to me to write stuff the way it is designed. I can lift and shift my Fibaro LUA design directly into NR, where in theory I may have one node per a) through to b4) above, or I may group them in some way... I haven't got that far yet in my thinking yet.
After thinking about it a little longer, I'm tending to agree with your comment.
Create global variables, rather than the *flow variables I have created thus far, and update them from "NR golden source" flows.
*It's funny as I tended to create flow variables lately, as when built my first couple of dashboards I didn't know about context and flow variables and I didn't know the syntax to write to an array of objects, so I ruined my globals by having too much noise in it.. it will all be cleaned up in the coming months though!
I think it will also help my simple brain to see the actual device nodes in each flown when I come to look at them at a later date, and I also think I can easily determine where I am updating values from as I will have a single heating flow and a single lighting flow that will contain most of the key devices I need.
Sorry for the late reply. Thank you very much for the offer. What would be more useful to me and a wider audience I think would be a little help with this simple piece of js. https://discourse.nodered.org/t/found-this-really-cool-simple-time-picker/36601
The fact that I cannot figure it out tells you the level of my competence in this area.
Best regards,
oz