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.

shelly.py 6.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. from devices.base import base
  5. from devices.base import warning
  6. import logging
  7. import task
  8. class shelly(base):
  9. """ Communication (MQTT)
  10. shelly
  11. +- relay
  12. | +- 0 ["on" / "off"] <- status
  13. | | +- command ["on"/ "off"] <- command
  14. | | +- energy [numeric] <- status
  15. | +- 1 ["on" / "off"] <- status
  16. | +- command ["on"/ "off"] <- command
  17. | +- energy [numeric] <- status
  18. +- input
  19. | +- 0 [0 / 1] <- status
  20. | +- 1 [0 / 1] <- status
  21. +- input_event
  22. | +- 0 <- status
  23. | +- 1 <- status
  24. +- logpush
  25. | +- 0 [0 / 1] <- status
  26. | +- 1 [0 / 1] <- status
  27. +- temperature [numeric] °C <- status
  28. +- temperature_f [numeric] F <- status
  29. +- overtemperature [0 / 1] <- status
  30. +- id <- status
  31. +- model <- status
  32. +- mac <- status
  33. +- ip <- status
  34. +- new_fw <- status
  35. +- fw_ver <- status
  36. """
  37. KEY_OUTPUT_0 = "relay/0"
  38. KEY_OUTPUT_1 = "relay/1"
  39. KEY_INPUT_0 = "input/0"
  40. KEY_INPUT_1 = "input/1"
  41. KEY_LONGPUSH_0 = "longpush/0"
  42. KEY_LONGPUSH_1 = "longpush/1"
  43. KEY_TEMPERATURE = "temperature"
  44. KEY_OVERTEMPERATURE = "overtemperature"
  45. KEY_ID = "id"
  46. KEY_MODEL = "model"
  47. KEY_MAC = "mac"
  48. KEY_IP = "ip"
  49. KEY_NEW_FIRMWARE = "new_fw"
  50. KEY_FIRMWARE_VERSION = "fw_ver"
  51. #
  52. TX_TOPIC = "command"
  53. TX_TYPE = base.TX_VALUE
  54. TX_FILTER_DATA_KEYS = [KEY_OUTPUT_0, KEY_OUTPUT_1]
  55. #
  56. RX_KEYS = [KEY_OUTPUT_0, KEY_OUTPUT_1, KEY_INPUT_0, KEY_INPUT_1, KEY_LONGPUSH_0, KEY_LONGPUSH_1, KEY_OVERTEMPERATURE, KEY_TEMPERATURE,
  57. KEY_ID, KEY_MODEL, KEY_MAC, KEY_IP, KEY_NEW_FIRMWARE, KEY_FIRMWARE_VERSION]
  58. RX_IGNORE_TOPICS = [KEY_OUTPUT_0 + '/' + "energy", KEY_OUTPUT_1 + '/' + "energy", 'input_event/0', 'input_event/1']
  59. RX_IGNORE_KEYS = ['temperature_f']
  60. RX_FILTER_DATA_KEYS = [KEY_INPUT_0, KEY_INPUT_1, KEY_LONGPUSH_0, KEY_LONGPUSH_1, KEY_OUTPUT_0, KEY_OUTPUT_1, KEY_OVERTEMPERATURE]
  61. def __init__(self, mqtt_client, topic):
  62. super().__init__(mqtt_client, topic)
  63. #
  64. self.output_key_delayed = None
  65. self.delayed_flash_task = task.delayed(0.3, self.flash_task)
  66. self.delayed_off_task = task.delayed(0.3, self.off_task)
  67. #
  68. self.add_callback(self.KEY_OVERTEMPERATURE, True, self.__warning__, True)
  69. #
  70. self.all_off_requested = False
  71. def flash_task(self, *args):
  72. if self.flash_active:
  73. self.send_command(self.output_key_delayed, not self.get(self.output_key_delayed))
  74. self.output_key_delayed = None
  75. if self.all_off_requested:
  76. self.delayed_off_task.run()
  77. def off_task(self, *args):
  78. self.all_off()
  79. @property
  80. def flash_active(self):
  81. return self.output_key_delayed is not None
  82. #
  83. # WARNING CALL
  84. #
  85. def __warning__(self, client, key, data):
  86. w = warning(self.topic, warning.TYPE_OVERTEMPERATURE, "Temperature to high (%.1f°C)", self.get(self.KEY_TEMPERATURE) or math.nan)
  87. self.logger.warning(w)
  88. self.set(self.KEY_WARNING, w)
  89. #
  90. # RX
  91. #
  92. @property
  93. def output_0(self):
  94. """rv: [True, False]"""
  95. return self.get(self.KEY_OUTPUT_0)
  96. @property
  97. def output_1(self):
  98. """rv: [True, False]"""
  99. return self.get(self.KEY_OUTPUT_1)
  100. @property
  101. def input_0(self):
  102. """rv: [True, False]"""
  103. return self.get(self.KEY_INPUT_0)
  104. @property
  105. def input_1(self):
  106. """rv: [True, False]"""
  107. return self.get(self.KEY_INPUT_1)
  108. @property
  109. def longpush_0(self):
  110. """rv: [True, False]"""
  111. return self.get(self.KEY_LONGPUSH_0)
  112. @property
  113. def longpush_1(self):
  114. """rv: [True, False]"""
  115. return self.get(self.KEY_LONGPUSH_1)
  116. @property
  117. def temperature(self):
  118. """rv: numeric value"""
  119. return self.get(self.KEY_TEMPERATURE)
  120. #
  121. # TX
  122. #
  123. def set_output_0(self, state):
  124. """state: [True, False]"""
  125. self.send_command(self.KEY_OUTPUT_0, state)
  126. def set_output_0_mcb(self, device, key, data):
  127. self.logger.log(logging.INFO if data != self.output_0 else logging.DEBUG, "Changing output 0 to %s", str(data))
  128. self.set_output_0(data)
  129. def toggle_output_0_mcb(self, device, key, data):
  130. self.logger.info("Toggeling output 0")
  131. self.set_output_0(not self.output_0)
  132. def set_output_1(self, state):
  133. """state: [True, False]"""
  134. self.send_command(self.KEY_OUTPUT_1, state)
  135. def set_output_1_mcb(self, device, key, data):
  136. self.logger.log(logging.INFO if data != self.output_1 else logging.DEBUG, "Changing output 1 to %s", str(data))
  137. self.set_output_1(data)
  138. def toggle_output_1_mcb(self, device, key, data):
  139. self.logger.info("Toggeling output 1")
  140. self.set_output_1(not self.output_1)
  141. def flash_0_mcb(self, device, key, data):
  142. self.output_key_delayed = self.KEY_OUTPUT_0
  143. self.toggle_output_0_mcb(device, key, data)
  144. self.delayed_flash_task.run()
  145. def flash_1_mcb(self, device, key, data):
  146. self.output_key_delayed = self.KEY_OUTPUT_1
  147. self.toggle_output_1_mcb(device, key, data)
  148. self.delayed_flash_task.run()
  149. def all_off(self):
  150. if self.flash_active:
  151. self.all_off_requested = True
  152. else:
  153. if self.output_0:
  154. self.set_output_0(False)
  155. if self.output_1:
  156. self.set_output_1(False)