Smarthome Functionen
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  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 videv_base
  12. from function.rooms import room, room_collection
  13. import time
  14. try:
  15. from config import APP_NAME as ROOT_LOGGER_NAME
  16. except ImportError:
  17. ROOT_LOGGER_NAME = 'root'
  18. class videv_switching(videv_base):
  19. KEY_STATE = 'state'
  20. def __init__(self, mqtt_client, topic, sw_device, sw_key):
  21. super().__init__(mqtt_client, topic)
  22. self.add_routing(self.KEY_STATE, sw_device, sw_key)
  23. #
  24. self.__tx_capabilities__()
  25. class videv_switching_timer(videv_base):
  26. KEY_STATE = 'state'
  27. KEY_TIMER = 'timer'
  28. def __init__(self, mqtt_client, topic, sw_device, sw_key, tm_device, tm_key):
  29. super().__init__(mqtt_client, topic)
  30. self.add_routing(self.KEY_STATE, sw_device, sw_key)
  31. self.add_display(self.KEY_TIMER, tm_device, tm_key)
  32. #
  33. self.__tx_capabilities__()
  34. class videv_switching_motion(videv_base):
  35. KEY_STATE = 'state'
  36. #
  37. KEY_TIMER = 'timer'
  38. KEY_MOTION_SENSOR = 'motion_%d'
  39. def __init__(self, mqtt_client, topic, sw_device, sw_key, motion_function):
  40. self.motion_sensors = motion_function.motion_sensors
  41. #
  42. super().__init__(mqtt_client, topic)
  43. self.add_routing(self.KEY_STATE, sw_device, sw_key)
  44. self.add_display(self.KEY_TIMER, motion_function, motion_function.KEY_TIMER)
  45. # motion sensor state
  46. for index, motion_sensor in enumerate(self.motion_sensors):
  47. self.add_display(self.KEY_MOTION_SENSOR % index, motion_sensor, motion_sensor.KEY_OCCUPANCY)
  48. #
  49. self.__tx_capabilities__()
  50. class videv_switch_brightness(videv_base):
  51. KEY_STATE = 'state'
  52. KEY_BRIGHTNESS = 'brightness'
  53. def __init__(self, mqtt_client, topic, sw_device, sw_key, br_device, br_key):
  54. super().__init__(mqtt_client, topic)
  55. self.add_routing(self.KEY_STATE, sw_device, sw_key)
  56. self.add_routing(self.KEY_BRIGHTNESS, br_device, br_key)
  57. #
  58. self.__tx_capabilities__()
  59. class videv_switch_brightness_color_temp(videv_base):
  60. KEY_STATE = 'state'
  61. KEY_BRIGHTNESS = 'brightness'
  62. KEY_COLOR_TEMP = 'color_temp'
  63. def __init__(self, mqtt_client, topic, sw_device, sw_key, br_device, br_key, ct_device, ct_key):
  64. super().__init__(mqtt_client, topic)
  65. self.add_routing(self.KEY_STATE, sw_device, sw_key)
  66. self.add_routing(self.KEY_BRIGHTNESS, br_device, br_key)
  67. self.add_routing(self.KEY_COLOR_TEMP, ct_device, ct_key)
  68. #
  69. self.__tx_capabilities__()
  70. class videv_heating(videv_base):
  71. KEY_USER_TEMPERATURE_SETPOINT = 'user_temperature_setpoint'
  72. KEY_VALVE_TEMPERATURE_SETPOINT = 'valve_temperature_setpoint'
  73. KEY_AWAY_MODE = 'away_mode'
  74. KEY_SUMMER_MODE = 'summer_mode'
  75. KEY_START_BOOST = 'start_boost'
  76. KEY_SET_DEFAULT_TEMPERATURE = 'set_default_temperature'
  77. KEY_BOOST_TIMER = 'boost_timer'
  78. #
  79. KEY_TEMPERATURE = 'temperature'
  80. def __init__(self, mqtt_client, topic, heating_function):
  81. super().__init__(mqtt_client, topic)
  82. #
  83. self.add_routing(self.KEY_USER_TEMPERATURE_SETPOINT, heating_function, heating_function.KEY_USER_TEMPERATURE_SETPOINT)
  84. self.add_routing(self.KEY_AWAY_MODE, heating_function, heating_function.KEY_AWAY_MODE)
  85. self.add_routing(self.KEY_SUMMER_MODE, heating_function, heating_function.KEY_SUMMER_MODE)
  86. #
  87. self.add_control(self.KEY_START_BOOST, heating_function, heating_function.KEY_START_BOOST, False)
  88. self.add_control(self.KEY_SET_DEFAULT_TEMPERATURE, heating_function, heating_function.KEY_SET_DEFAULT_TEMPERATURE, False)
  89. #
  90. self.add_display(self.KEY_VALVE_TEMPERATURE_SETPOINT, heating_function, heating_function.KEY_TEMPERATURE_SETPOINT)
  91. self.add_display(self.KEY_BOOST_TIMER, heating_function, heating_function.KEY_BOOST_TIMER)
  92. self.add_display(self.KEY_TEMPERATURE, heating_function, heating_function.KEY_TEMPERATURE_CURRENT, False)
  93. #
  94. self.__tx_capabilities__()
  95. class videv_multistate(videv_base):
  96. KEY_STATE = 'state_%d'
  97. def __init__(self, mqtt_client, topic, key_for_device, device, num_states, default_values=None):
  98. super().__init__(mqtt_client, topic)
  99. self.num_states = num_states
  100. # send default values
  101. for i in range(0, num_states):
  102. self.__tx__(self.KEY_STATE % i, False)
  103. #
  104. device.add_callback(key_for_device, None, self.__index_rx__, True)
  105. #
  106. self.__tx_capabilities__()
  107. def __index_rx__(self, device, key, data):
  108. for i in range(0, self.num_states):
  109. self.__tx__(self.KEY_STATE % i, i == data)
  110. #
  111. self.__tx_capabilities__()
  112. class videv_audio_player(videv_base):
  113. KEY_ACTIVE_PLAYER = 'player_%d'
  114. KEY_TITLE = 'title'
  115. NO_TITLE = '---'
  116. def __init__(self, mqtt_client, topic, *args):
  117. super().__init__(mqtt_client, topic)
  118. for i, device in enumerate(args):
  119. self.add_display(self.KEY_ACTIVE_PLAYER % i, device, device.KEY_STATE)
  120. #
  121. for audio_device in args:
  122. audio_device.add_callback(audio_device.KEY_TITLE, None, self.__title_rx__, True)
  123. #
  124. self.__tx_capabilities__()
  125. def __title_rx__(self, device, key, data):
  126. self.__tx__(self.KEY_TITLE, data or self.NO_TITLE)
  127. @property
  128. def capabilities(self):
  129. super().capabilities
  130. self.__capabilities__[self.KEY_TITLE] = {'display': True}
  131. return self.__capabilities__
  132. class videv_warnings(videv_base):
  133. MAX_WARNINGS = 10
  134. KEY_WARNING = 'html_short'
  135. def __init__(self, mqtt_client, topic, default_values=None):
  136. super().__init__(mqtt_client, topic, default_values)
  137. self.__warnings__ = []
  138. def warningcollector(self, client, key, data):
  139. self.__warnings__.append(data)
  140. self.__warnings__ = self.__warnings__[-self.MAX_WARNINGS:]
  141. txt = "<br><br>".join([time.asctime(w[w.KEY_TM]) + "<br>" + w[w.KEY_TEXT] + "<br>" + w[w.KEY_ID] for w in self.__warnings__])
  142. self.__tx__(self.KEY_WARNING, txt)
  143. class all_off(videv_base):
  144. ALLOWED_CLASSES = (room, room_collection, )
  145. def __init__(self, mqtt_client, topic, room_collection):
  146. super().__init__(mqtt_client, topic)
  147. self.__room_collection__ = room_collection
  148. # init __inst_dict__
  149. self.__inst_dict__ = {}
  150. self.__add_instances__("all", self.__room_collection__)
  151. # register mqtt callbacks for all my keys
  152. for key in self.__inst_dict__:
  153. mqtt_client.add_callback(topic + "/" + key, self.all_off)
  154. #
  155. self.__tx_capabilities__()
  156. def __check_inst_capabilities__(self, name, inst):
  157. # fits to specified classes
  158. if isinstance(inst, self.ALLOWED_CLASSES):
  159. try:
  160. # all_off method is callable
  161. return callable(inst.all_off)
  162. except AttributeError:
  163. # all_off method does not exist
  164. return False
  165. return False
  166. def __add_instances__(self, name, inst, level=0):
  167. if self.__check_inst_capabilities__(name, inst):
  168. # add given instance to my __inst_dict__
  169. self.__inst_dict__[name] = inst
  170. # iterate over all attribute names of instance
  171. for sub_name in dir(inst):
  172. # attribute name is not private
  173. if not sub_name.startswith("__"):
  174. sub = getattr(inst, sub_name)
  175. # recurse with this object
  176. if level == 0:
  177. self.__add_instances__(sub_name, sub, level=level+1)
  178. else:
  179. self.__add_instances__(name + "/" + sub_name, sub, level=level+1)
  180. def all_off(self, client, userdata, message):
  181. key = message.topic[len(self.topic) + 1:]
  182. self.__inst_dict__[key].all_off()
  183. self.__tx_capabilities__()
  184. @property
  185. def capabilities(self):
  186. if self.__capabilities__ is None:
  187. self.__capabilities__ = {}
  188. self.__capabilities__['__type__'] = self.__class__.__name__
  189. for key in self.__inst_dict__:
  190. self.__capabilities__[key] = {}
  191. self.__capabilities__[key]['control'] = True
  192. return self.__capabilities__