Smarthome Functionen
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. from base import mqtt_base
  5. from base import videv_base
  6. import json
  7. import time
  8. BATTERY_WARN_LEVEL = 10
  9. def is_json(data):
  10. try:
  11. json.loads(data)
  12. except json.decoder.JSONDecodeError:
  13. return False
  14. else:
  15. return True
  16. class base(mqtt_base):
  17. TX_TOPIC = "set"
  18. TX_VALUE = 0
  19. TX_DICT = 1
  20. TX_TYPE = -1
  21. TX_FILTER_DATA_KEYS = []
  22. #
  23. RX_KEYS = []
  24. RX_IGNORE_TOPICS = []
  25. RX_IGNORE_KEYS = []
  26. RX_FILTER_DATA_KEYS = []
  27. #
  28. KEY_WARNING = '__WARNING__'
  29. def __init__(self, mqtt_client, topic):
  30. super().__init__(mqtt_client, topic, default_values=dict.fromkeys(self.RX_KEYS + [self.KEY_WARNING]))
  31. # data storage
  32. # initialisations
  33. mqtt_client.add_callback(topic=self.topic, callback=self.receive_callback)
  34. mqtt_client.add_callback(topic=self.topic+"/#", callback=self.receive_callback)
  35. def set(self, key, data, block_callback=[]):
  36. if key in self.RX_IGNORE_KEYS:
  37. pass # ignore these keys
  38. elif key in self.RX_KEYS or key == self.KEY_WARNING:
  39. return super().set(key, data, block_callback)
  40. else:
  41. self.logger.warning("Unexpected key %s", key)
  42. def receive_callback(self, client, userdata, message):
  43. if message.topic != self.topic + '/' + videv_base.KEY_INFO:
  44. content_key = message.topic[len(self.topic) + 1:]
  45. if content_key not in self.RX_IGNORE_TOPICS and (not message.topic.endswith(self.TX_TOPIC) or len(self.TX_TOPIC) == 0):
  46. self.logger.debug("Unpacking content_key \"%s\" from message.", content_key)
  47. if is_json(message.payload):
  48. data = json.loads(message.payload)
  49. if type(data) is dict:
  50. for key in data:
  51. self.set(key, self.__device_to_instance_filter__(key, data[key]))
  52. else:
  53. self.set(content_key, self.__device_to_instance_filter__(content_key, data))
  54. # String
  55. else:
  56. self.set(content_key, self.__device_to_instance_filter__(content_key, message.payload.decode('utf-8')))
  57. else:
  58. self.logger.debug("Ignoring topic %s", content_key)
  59. def __device_to_instance_filter__(self, key, data):
  60. if key in self.RX_FILTER_DATA_KEYS:
  61. if data in [1, 'on', 'ON']:
  62. return True
  63. elif data in [0, 'off', 'OFF']:
  64. return False
  65. return data
  66. def __instance_to_device_filter__(self, key, data):
  67. if key in self.TX_FILTER_DATA_KEYS:
  68. if data is True:
  69. return "on"
  70. elif data is False:
  71. return "off"
  72. return data
  73. def send_command(self, key, data):
  74. data = self.__instance_to_device_filter__(key, data)
  75. if self.TX_TOPIC is not None:
  76. if self.TX_TYPE < 0:
  77. self.logger.error("Unknown tx type. Set TX_TYPE of class to a known value")
  78. else:
  79. self.logger.debug("Sending data for %s - %s", key, str(data))
  80. if self.TX_TYPE == self.TX_DICT:
  81. try:
  82. self.mqtt_client.send('/'.join([self.topic, self.TX_TOPIC]), json.dumps({key: data}))
  83. except TypeError:
  84. print(self.topic)
  85. print(key.__dict__)
  86. print(key)
  87. print(data)
  88. raise TypeError
  89. else:
  90. if type(data) not in [str, bytes]:
  91. data = json.dumps(data)
  92. self.mqtt_client.send('/'.join([self.topic, key, self.TX_TOPIC] if len(self.TX_TOPIC) > 0 else [self.topic, key]), data)
  93. else:
  94. self.logger.error("Unknown tx toptic. Set TX_TOPIC of class to a known value")
  95. class warning(dict):
  96. TYPE_BATTERY_LOW = 1
  97. TYPE_OVERTEMPERATURE = 2
  98. #
  99. KEY_ID = 'id'
  100. KEY_TYPE = 'type'
  101. KEY_TEXT = 'text'
  102. KEY_TM = 'tm'
  103. def __init__(self, identification, type, text, args):
  104. super().__init__({
  105. self.KEY_ID: identification,
  106. self.KEY_TYPE: type,
  107. self.KEY_TEXT: text % args,
  108. self.KEY_TM: time.localtime(),
  109. })
  110. def __str__(self):
  111. return time.asctime(self.get(self.KEY_TM)) + ": " + self[self.KEY_TEXT] + " - " + self[self.KEY_ID]