Open Goose66 opened 4 years ago
Here's is, e.g., what I use today:
# load nodes previously saved to the polyglot database
# Note: has to be done in two passes to ensure system (primary/parent) nodes exist
# before device nodes
# first pass for system nodes
for addr in self._nodes:
node = self._nodes[addr]
if node["node_def_id"] == "SYSTEM":
LOGGER.info("Adding previously saved node - addr: %s, name: %s, type: %s", addr, node["name"], node["node_def_id"])
self.addNode(System(self, node["primary"], addr, node["name"]))
# second pass for device nodes
for addr in self._nodes:
node = self._nodes[addr]
if node["node_def_id"] not in ("CONTROLLER", "SYSTEM"):
LOGGER.info("Adding previously saved node - addr: %s, name: %s, type: %s", addr, node["name"], node["node_def_id"])
# add device and temperature controller nodes
if node["node_def_id"] == "DEVICE":
self.addNode(Device(self, node["primary"], addr, node["name"]))
elif node["node_def_id"] == "DIMMING_LIGHT":
self.addNode(DimmingLight(self, node["primary"], addr, node["name"]))
elif node["node_def_id"] in DEVICE_COLOR_LIGHT_TYPES.values():
self.addNode(ColorLight(self, node["primary"], addr, node["name"]))
elif node["node_def_id"] in ("TEMP_CONTROL", "TEMP_CONTROL_C"):
self.addNode(TempControl(self, node["primary"], addr, node["name"]))
I agree.
would it be possible to do something cleaner with enumerate()? I'm thinking that we add an API function to the controller that returns enumerate on the _nodes list. So something like this in the interface:
def enumerateNodes():
return enumerate(self._nodes, 0)
Then the node server code can look like:
for n in enumerateNodes():
if node['node_def_id'] == 'whatever':
self.addNode()
if node['node_def_id'] == 'my_node_id':
self.addNode()
As part of the API definition for enumerateNodes() we could define what the returned object looks like. That way it could be independent of the self._nodes data from the database. The database differences between cloud and local could then be handled in enumerateNodes() and not the node server code.
Yes, agree and that was something I planned to work on, but with V3 coming I put it off.
Whether we have an enumerateNodes() function, or we just override __members__
of the controller.nodes property, we need to make sure it returns the nodes with primaries sorted first, so that they can be created before child nodes, and the two passes illustrated above won't be necessary.
Since loading previously discovered nodes from the database on nodeserver start() is a thing in at least two developer's multiple nodeservers, the controllers _nodes list (which is prepopulated by Polyglot with the node data from the database on start) should be made usable/visible to the nodeserver code, with a more intuitive interface. Not sure if there is a way to pre-populate controller.nodes from controller._nodes since the nodes may be of different classes, but a fairly robust method of repopulating controller.nodes from controller._nodes needs to be established.