mqtt.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. import logging
  2. import threading
  3. import paho.mqtt.client as mqtt
  4. from frigate.config import FrigateConfig
  5. logger = logging.getLogger(__name__)
  6. def create_mqtt_client(config: FrigateConfig, camera_metrics):
  7. mqtt_config = config.mqtt
  8. def on_clips_command(client, userdata, message):
  9. payload = message.payload.decode()
  10. logger.debug(f"on_clips_toggle: {message.topic} {payload}")
  11. camera_name = message.topic.split("/")[-3]
  12. clips_settings = config.cameras[camera_name].clips
  13. if payload == "ON":
  14. if not clips_settings.enabled:
  15. logger.info(f"Turning on clips for {camera_name} via mqtt")
  16. clips_settings._enabled = True
  17. elif payload == "OFF":
  18. if clips_settings.enabled:
  19. logger.info(f"Turning off clips for {camera_name} via mqtt")
  20. clips_settings._enabled = False
  21. else:
  22. logger.warning(f"Received unsupported value at {message.topic}: {payload}")
  23. state_topic = f"{message.topic[:-4]}/state"
  24. client.publish(state_topic, payload, retain=True)
  25. def on_snapshots_command(client, userdata, message):
  26. payload = message.payload.decode()
  27. logger.debug(f"on_snapshots_toggle: {message.topic} {payload}")
  28. camera_name = message.topic.split("/")[-3]
  29. snapshots_settings = config.cameras[camera_name].snapshots
  30. if payload == "ON":
  31. if not snapshots_settings.enabled:
  32. logger.info(f"Turning on snapshots for {camera_name} via mqtt")
  33. snapshots_settings._enabled = True
  34. elif payload == "OFF":
  35. if snapshots_settings.enabled:
  36. logger.info(f"Turning off snapshots for {camera_name} via mqtt")
  37. snapshots_settings._enabled = False
  38. else:
  39. logger.warning(f"Received unsupported value at {message.topic}: {payload}")
  40. state_topic = f"{message.topic[:-4]}/state"
  41. client.publish(state_topic, payload, retain=True)
  42. def on_detect_command(client, userdata, message):
  43. payload = message.payload.decode()
  44. logger.debug(f"on_detect_toggle: {message.topic} {payload}")
  45. camera_name = message.topic.split("/")[-3]
  46. detect_settings = config.cameras[camera_name].detect
  47. if payload == "ON":
  48. if not camera_metrics[camera_name]["detection_enabled"].value:
  49. logger.info(f"Turning on detection for {camera_name} via mqtt")
  50. camera_metrics[camera_name]["detection_enabled"].value = True
  51. detect_settings._enabled = True
  52. elif payload == "OFF":
  53. if camera_metrics[camera_name]["detection_enabled"].value:
  54. logger.info(f"Turning off detection for {camera_name} via mqtt")
  55. camera_metrics[camera_name]["detection_enabled"].value = False
  56. detect_settings._enabled = False
  57. else:
  58. logger.warning(f"Received unsupported value at {message.topic}: {payload}")
  59. state_topic = f"{message.topic[:-4]}/state"
  60. client.publish(state_topic, payload, retain=True)
  61. def on_connect(client, userdata, flags, rc):
  62. threading.current_thread().name = "mqtt"
  63. if rc != 0:
  64. if rc == 3:
  65. logger.error("MQTT Server unavailable")
  66. elif rc == 4:
  67. logger.error("MQTT Bad username or password")
  68. elif rc == 5:
  69. logger.error("MQTT Not authorized")
  70. else:
  71. logger.error(
  72. "Unable to connect to MQTT: Connection refused. Error code: "
  73. + str(rc)
  74. )
  75. logger.info("MQTT connected")
  76. client.subscribe(f"{mqtt_config.topic_prefix}/#")
  77. client.publish(mqtt_config.topic_prefix + "/available", "online", retain=True)
  78. client = mqtt.Client(client_id=mqtt_config.client_id)
  79. client.on_connect = on_connect
  80. client.will_set(
  81. mqtt_config.topic_prefix + "/available", payload="offline", qos=1, retain=True
  82. )
  83. # register callbacks
  84. for name in config.cameras.keys():
  85. client.message_callback_add(
  86. f"{mqtt_config.topic_prefix}/{name}/clips/set", on_clips_command
  87. )
  88. client.message_callback_add(
  89. f"{mqtt_config.topic_prefix}/{name}/snapshots/set", on_snapshots_command
  90. )
  91. client.message_callback_add(
  92. f"{mqtt_config.topic_prefix}/{name}/detect/set", on_detect_command
  93. )
  94. if not mqtt_config.user is None:
  95. client.username_pw_set(mqtt_config.user, password=mqtt_config.password)
  96. try:
  97. client.connect(mqtt_config.host, mqtt_config.port, 60)
  98. except Exception as e:
  99. logger.error(f"Unable to connect to MQTT server: {e}")
  100. raise
  101. client.loop_start()
  102. for name in config.cameras.keys():
  103. client.publish(
  104. f"{mqtt_config.topic_prefix}/{name}/clips/state",
  105. "ON" if config.cameras[name].clips.enabled else "OFF",
  106. retain=True,
  107. )
  108. client.publish(
  109. f"{mqtt_config.topic_prefix}/{name}/snapshots/state",
  110. "ON" if config.cameras[name].snapshots.enabled else "OFF",
  111. retain=True,
  112. )
  113. client.publish(
  114. f"{mqtt_config.topic_prefix}/{name}/detect/state",
  115. "ON" if config.cameras[name].detect.enabled else "OFF",
  116. retain=True,
  117. )
  118. return client