Smarthome Functionen
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

videv.py 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. """
  5. Virtual Device(s)
  6. Targets:
  7. * MQTT-Interface to control joined devices as one virtual device.
  8. * Primary signal routing
  9. * No functionality should be implemented here
  10. """
  11. from base import mqtt_base
  12. import devices
  13. import json
  14. import logging
  15. BASETOPIC = "videv"
  16. try:
  17. from config import APP_NAME as ROOT_LOGGER_NAME
  18. except ImportError:
  19. ROOT_LOGGER_NAME = 'root'
  20. class base(mqtt_base):
  21. DEFAULT_VALUES = {}
  22. def __init__(self, mqtt_client, topic, *args):
  23. super().__init__(mqtt_client, topic)
  24. self.__device_list__ = {}
  25. for videv_key, device in [reduced[:2] for reduced in args]:
  26. self.__device_list__[videv_key] = device
  27. # send initial state
  28. for key in self.keys():
  29. self.__tx__(key, self[key])
  30. # add receive topics
  31. mqtt_client.add_callback(self.topic + "/#", self.__rx__)
  32. def __tx__(self, key, data):
  33. if type(data) not in (str, ):
  34. data = json.dumps(data)
  35. if key in self.keys():
  36. self.mqtt_client.send(self.topic + '/' + key, data)
  37. else:
  38. self.logger.warning("Ignoring send request for key %s (not available for this class)", key)
  39. def __rx__(self, client, userdata, message):
  40. key = message.topic.split('/')[-1]
  41. if key in self.keys():
  42. try:
  43. data = json.loads(message.payload)
  44. except json.decoder.JSONDecodeError:
  45. data = message.payload
  46. if data != self[key]:
  47. self.__rx_functionality__(key, data)
  48. self.set(key, data)
  49. else:
  50. self.logger.info("Ignoring rx message with topic %s", message.topic)
  51. def __rx_functionality__(self, key, data):
  52. raise NotImplemented("Method __rx_functionality__ needs to be implemented in child class")
  53. def __device_data__(self, device, key, data):
  54. raise NotImplemented("Method __device_data__ needs to be implemented in child class")
  55. class base_routing(base):
  56. def __init__(self, mqtt_client, topic, *args):
  57. super().__init__(mqtt_client, topic, *args)
  58. #
  59. self.__device_key__ = {}
  60. index = 0
  61. for videv_key, device, device_key in args:
  62. if self.__device_list__[videv_key] != device:
  63. raise ReferenceError("Parent class generated a deviating device list")
  64. self.__device_key__[videv_key] = device_key
  65. index += 1
  66. # add callbacks
  67. for key in self.__device_list__:
  68. self.__device_list__[key].add_callback(self.__device_key__[key], None, self.__device_data__, True)
  69. def __rx_functionality__(self, key, data):
  70. try:
  71. self.__device_list__[key].set(self.__device_key__[key], data)
  72. except KeyError:
  73. self.logger.warning("RX passthrough not possible for key %s", key)
  74. def __device_data__(self, device, key, data):
  75. l1 = [k for k, v in self.__device_list__.items() if v == device]
  76. l2 = [k for k, v in self.__device_key__.items() if v == key]
  77. try:
  78. videv_key = [k for k in l1 if k in l2][0]
  79. except IndexError:
  80. self.logger.warning("videv_key not available for %s::%s", device.__class__.__name__, device.topic)
  81. else:
  82. self.set(videv_key, data)
  83. self.__tx__(videv_key, data)
  84. class videv_switching(base_routing):
  85. KEY_STATE = 'state'
  86. #
  87. DEFAULT_VALUES = {
  88. KEY_STATE: False,
  89. }
  90. def __init__(self, mqtt_client, topic, sw_device, sw_key):
  91. #
  92. super().__init__(mqtt_client, topic, (self.KEY_STATE, sw_device, sw_key))
  93. class videv_switch_brightness(base_routing):
  94. KEY_STATE = 'state'
  95. KEY_BRIGHTNESS = 'brightness'
  96. #
  97. DEFAULT_VALUES = {
  98. KEY_STATE: False,
  99. KEY_BRIGHTNESS: 0
  100. }
  101. def __init__(self, mqtt_client, topic, sw_device, sw_key, br_device, br_key):
  102. #
  103. super().__init__(mqtt_client, topic, (self.KEY_STATE, sw_device, sw_key), (self.KEY_BRIGHTNESS, br_device, br_key))
  104. class videv_switch_brightness_color_temp(base_routing):
  105. KEY_STATE = 'state'
  106. KEY_BRIGHTNESS = 'brightness'
  107. KEY_COLOR_TEMP = 'color_temp'
  108. #
  109. DEFAULT_VALUES = {
  110. KEY_STATE: False,
  111. KEY_BRIGHTNESS: 0,
  112. KEY_COLOR_TEMP: 0,
  113. }
  114. def __init__(self, mqtt_client, topic, sw_device, sw_key, br_device, br_key, ct_device, ct_key):
  115. #
  116. super().__init__(
  117. mqtt_client, topic,
  118. (self.KEY_STATE, sw_device, sw_key),
  119. (self.KEY_BRIGHTNESS, br_device, br_key),
  120. (self.KEY_COLOR_TEMP, ct_device, ct_key)
  121. )