Repository: cgarwood/python-openzwave-mqtt

Issue:
Pass "parent" objects to children
Making issues for some items on the todo list in case anyone else wants to jump in with some code.
---

If we have an OZWValue object, we need an easy way to get to the OZWNode and OZWInstance objects that the value belongs to. Right now its easy to go from Instance > Node > Value, but not the other way around.

Discussion:

Patch:
diff --git a/openzwavemqtt/base.py b/openzwavemqtt/base.py
index bc529ea..a524c2b 100644
--- a/openzwavemqtt/base.py
+++ b/openzwavemqtt/base.py
@@ -1,5 +1,5 @@
 from abc import ABC
-from typing import Callable, Deque
+from typing import Callable, Deque, Optional
 
 from .const import EVENT_PLACEHOLDER, EMPTY, LOGGER
 from .options import OZWOptions
@@ -7,9 +7,13 @@ from .options import OZWOptions
 
 class ItemCollection:
     def __init__(
-        self, options: OZWOptions, item_class: Callable[[OZWOptions, str], "ZwaveBase"]
+        self,
+        options: OZWOptions,
+        parent: "ZWaveBase",
+        item_class: Callable[[OZWOptions, str], "ZwaveBase"],
     ):
         self.options = options
+        self.parent = parent
         self.item_class = item_class
         self.collection = {}
 
@@ -30,7 +34,9 @@ class ItemCollection:
             return
 
         elif item is None:
-            item = self.collection[item_id] = self.item_class(self.options, item_id)
+            item = self.collection[item_id] = self.item_class(
+                self.options, self.parent, item_id
+            )
             added = True
 
         if len(topic) == 0 and message is EMPTY:
@@ -67,8 +73,11 @@ class ZWaveBase(ABC):
     EVENT_CHANGED = EVENT_PLACEHOLDER
     EVENT_REMOVED = EVENT_PLACEHOLDER
 
-    def __init__(self, options: OZWOptions, item_id: str):
+    def __init__(
+        self, options: OZWOptions, parent: Optional["ZWaveBase"], item_id: str
+    ):
         self.options = options
+        self.parent = parent
         self.id = item_id
         self.collections = self.create_collections()
         self.data = EMPTY
diff --git a/openzwavemqtt/manager.py b/openzwavemqtt/manager.py
index d3bfe23..f94f3ed 100644
--- a/openzwavemqtt/manager.py
+++ b/openzwavemqtt/manager.py
@@ -12,11 +12,11 @@ class OZWManager(ZWaveBase):
     EVENT_CHANGED = None
 
     def __init__(self, options: OZWOptions):
-        super().__init__(options, None)
+        super().__init__(options, None, None)
 
     def create_collections(self):
         """Create collections that the manager supports."""
-        return {"instance": ItemCollection(self.options, OZWInstance)}
+        return {"instance": ItemCollection(self.options, self, OZWInstance)}
 
     def receive_message(self, topic: str, message: dict):
         """Receive an MQTT message."""
diff --git a/openzwavemqtt/models/instance.py b/openzwavemqtt/models/instance.py
index e05045c..1ba983f 100644
--- a/openzwavemqtt/models/instance.py
+++ b/openzwavemqtt/models/instance.py
@@ -45,7 +45,7 @@ class OZWInstance(ZWaveBase):
     def create_collections(self):
         """Create collections that Node supports."""
         return {
-            "node": ItemCollection(self.options, OZWNode),
-            "statistics": OZWInstanceStatistics(self.options, None),
-            "status": OZWInstanceStatus(self.options, None),
+            "node": ItemCollection(self.options, self, OZWNode),
+            "statistics": OZWInstanceStatistics(self.options, self, None),
+            "status": OZWInstanceStatus(self.options, self, None),
         }
diff --git a/openzwavemqtt/models/node.py b/openzwavemqtt/models/node.py
index 2d32d89..7270b47 100644
--- a/openzwavemqtt/models/node.py
+++ b/openzwavemqtt/models/node.py
@@ -14,6 +14,6 @@ class OZWNode(ZWaveBase):
     def create_collections(self):
         """Create collections that Node supports."""
         return {
-            "value": ItemCollection(self.options, OZWValue),
-            "statistics": OZWNodeStatistics(self.options, OZWNodeStatistics),
+            "value": ItemCollection(self.options, self, OZWValue),
+            "statistics": OZWNodeStatistics(self.options, self, OZWNodeStatistics),
         }


Test patch:
diff --git a/test/models/test_node.py b/test/models/test_node_statistics.py
similarity index 97%
rename from test/models/test_node.py
rename to test/models/test_node_statistics.py
index 4dbdd2c..ac6a27c 100644
--- a/test/models/test_node.py
+++ b/test/models/test_node_statistics.py
@@ -41,3 +41,4 @@ def test_statistics(mgr):
     assert statistics.average_response_rtt == 47
     assert statistics.average_request_rtt == 31
     assert statistics.send_count == 10
+    assert statistics.parent.id == "2"
diff --git a/test/models/test_value.py b/test/models/test_value.py
index 92fc5c4..2d06403 100644
--- a/test/models/test_value.py
+++ b/test/models/test_value.py
@@ -14,6 +14,7 @@ def test_value_events(mgr):
     assert len(events) == 1
     assert events[0].id == "3"
     assert events[0].value == "yo"
+    assert events[0].parent.id == "2"
 
     # Listen for value changed
     mgr.options.listen(EVENT_VALUE_CHANGED, events.append)