summaryrefslogtreecommitdiff
path: root/addons/hw_drivers/interface.py
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
commit3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch)
treea44932296ef4a9b71d5f010906253d8c53727726 /addons/hw_drivers/interface.py
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/hw_drivers/interface.py')
-rw-r--r--addons/hw_drivers/interface.py70
1 files changed, 70 insertions, 0 deletions
diff --git a/addons/hw_drivers/interface.py b/addons/hw_drivers/interface.py
new file mode 100644
index 00000000..dbecbbf4
--- /dev/null
+++ b/addons/hw_drivers/interface.py
@@ -0,0 +1,70 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+import logging
+from threading import Thread
+import time
+
+from odoo.addons.hw_drivers.main import drivers, interfaces, iot_devices
+
+_logger = logging.getLogger(__name__)
+
+
+class InterfaceMetaClass(type):
+ def __new__(cls, clsname, bases, attrs):
+ new_interface = super(InterfaceMetaClass, cls).__new__(cls, clsname, bases, attrs)
+ interfaces[clsname] = new_interface
+ return new_interface
+
+
+class Interface(Thread, metaclass=InterfaceMetaClass):
+ _loop_delay = 3 # Delay (in seconds) between calls to get_devices or 0 if it should be called only once
+ _detected_devices = {}
+ connection_type = ''
+
+ def __init__(self):
+ super(Interface, self).__init__()
+ self.drivers = sorted([d for d in drivers if d.connection_type == self.connection_type], key=lambda d: d.priority, reverse=True)
+
+ def run(self):
+ while self.connection_type and self.drivers:
+ self.update_iot_devices(self.get_devices())
+ if not self._loop_delay:
+ break
+ time.sleep(self._loop_delay)
+
+ def update_iot_devices(self, devices={}):
+ added = devices.keys() - self._detected_devices
+ removed = self._detected_devices - devices.keys()
+ # keys() returns a dict_keys, and the values of that stay in sync with the
+ # original dictionary if it changes. This means that get_devices needs to return
+ # a newly created dictionary every time. If it doesn't do that and reuses the
+ # same dictionary, this logic won't detect any changes that are made. Could be
+ # avoided by converting the dict_keys into a regular dict. The current logic
+ # also can't detect if a device is replaced by a different one with the same
+ # key. Also, _detected_devices starts out as a class variable but gets turned
+ # into an instance variable here. It would be better if it was an instance
+ # variable from the start to avoid confusion.
+ self._detected_devices = devices.keys()
+
+ for identifier in removed:
+ if identifier in iot_devices:
+ iot_devices[identifier].disconnect()
+ _logger.info('Device %s is now disconnected', identifier)
+
+ for identifier in added:
+ for driver in self.drivers:
+ if driver.supported(devices[identifier]):
+ _logger.info('Device %s is now connected', identifier)
+ d = driver(identifier, devices[identifier])
+ d.daemon = True
+ iot_devices[identifier] = d
+ # Start the thread after creating the iot_devices entry so the
+ # thread can assume the iot_devices entry will exist while it's
+ # running, at least until the `disconnect` above gets triggered
+ # when `removed` is not empty.
+ d.start()
+ break
+
+ def get_devices(self):
+ raise NotImplementedError()