driver.py 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. # -*- coding: utf-8 -*-
  2. # Part of Odoo. See LICENSE file for full copyright and licensing details.
  3. from threading import Thread, Event
  4. from odoo.addons.hw_drivers.main import drivers, iot_devices
  5. from odoo.tools.lru import LRU
  6. class DriverMetaClass(type):
  7. def __new__(cls, clsname, bases, attrs):
  8. newclass = super(DriverMetaClass, cls).__new__(cls, clsname, bases, attrs)
  9. if hasattr(newclass, 'priority'):
  10. newclass.priority += 1
  11. else:
  12. newclass.priority = 0
  13. drivers.append(newclass)
  14. return newclass
  15. class Driver(Thread, metaclass=DriverMetaClass):
  16. """
  17. Hook to register the driver into the drivers list
  18. """
  19. connection_type = ''
  20. def __init__(self, identifier, device):
  21. super(Driver, self).__init__()
  22. self.dev = device
  23. self.device_identifier = identifier
  24. self.device_name = ''
  25. self.device_connection = ''
  26. self.device_type = ''
  27. self.device_manufacturer = ''
  28. self.data = {'value': ''}
  29. self._actions = {}
  30. self._stopped = Event()
  31. # Least Recently Used (LRU) Cache that will store the idempotent keys already seen.
  32. self._iot_idempotent_ids_cache = LRU(500)
  33. @classmethod
  34. def supported(cls, device):
  35. """
  36. On specific driver override this method to check if device is supported or not
  37. return True or False
  38. """
  39. return False
  40. def action(self, data):
  41. """Helper function that calls a specific action method on the device.
  42. :param data: the `_actions` key mapped to the action method we want to call
  43. :type data: string
  44. """
  45. self._actions[data.get('action', '')](data)
  46. def disconnect(self):
  47. self._stopped.set()
  48. del iot_devices[self.device_identifier]
  49. def _check_idempotency(self, iot_idempotent_id, session_id):
  50. """
  51. Some IoT requests for the same action might be received several times.
  52. To avoid duplicating the resulting actions, we check if the action was "recently" executed.
  53. If this is the case, we will simply ignore the action
  54. :return: the `session_id` of the same `iot_idempotent_id` if any. False otherwise,
  55. which means that it is the first time that the IoT box received the request with this ID
  56. """
  57. cache = self._iot_idempotent_ids_cache
  58. if iot_idempotent_id in cache:
  59. return cache[iot_idempotent_id]
  60. cache[iot_idempotent_id] = session_id
  61. return False