Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 

194 Zeilen
6.4 KiB

  1. import paho.mqtt.client as mqtt
  2. import json
  3. import os
  4. import logging
  5. import signal
  6. import requests
  7. from datetime import datetime
  8. from influxdb import InfluxDBClient
  9. from dotenv import find_dotenv, load_dotenv
  10. load_dotenv(find_dotenv())
  11. SRC_MQTT_HOST = os.getenv("SRC_MQTT_HOST")
  12. SRC_MQTT_USER = os.getenv("SRC_MQTT_USER")
  13. SRC_MQTT_PASS = os.getenv("SRC_MQTT_PASS")
  14. DST_MQTT_HOST = os.getenv("DST_MQTT_HOST")
  15. DST_MQTT_USER = os.getenv("DST_MQTT_USER")
  16. DST_MQTT_PASS = os.getenv("DST_MQTT_PASS")
  17. DST_INFLUX_HOST = os.getenv("DST_INFLUX_HOST")
  18. DST_INFLUX_USER = os.getenv("DST_INFLUX_USER")
  19. DST_INFLUX_PASS = os.getenv("DST_INFLUX_PASS")
  20. DST_INFLUX_DB = os.getenv("DST_INFLUX_DB")
  21. HC_PING_URL = os.getenv("HC_PING_URL")
  22. VERSION = "v2.0"
  23. OT_TOPIC="owntracks/tobru/dragino"
  24. OT_TID="dragino"
  25. def on_connect_ttn(client, userdata, flags, rc):
  26. logging.info("connected to ttn %s - %s", SRC_MQTT_HOST, str(rc))
  27. client.subscribe("+/devices/+/up")
  28. def on_connect_ot(client, userdata, flags, rc):
  29. logging.info("connected to ot %s - %s", DST_MQTT_HOST, str(rc))
  30. def on_publish_ot(client, userdata, rc):
  31. logging.info("published data to ot")
  32. def on_log(client, userdata, level, buf):
  33. logging_level = mqtt.LOGGING_LEVEL[level]
  34. logging.log(logging_level, buf)
  35. #logging.info("got a log message level %s: %s", level, str(buf))
  36. if "PINGRESP" in str(buf):
  37. # report to https://healthchecks.io to tell that the connection is alive
  38. requests.get(HC_PING_URL)
  39. # The callback for when a PUBLISH message is received from the server.
  40. def on_message_ttn(client, userdata, msg):
  41. data = json.loads(msg.payload)
  42. logging.info("message from ttn received for %s - #%s", data["dev_id"], data["counter"])
  43. # retrieve info about gateway
  44. gtw_id = data["metadata"]["gateways"][0]["gtw_id"]
  45. try:
  46. gtw_info = requests.get("https://www.thethingsnetwork.org/gateway-data/gateway/"+gtw_id).json()
  47. logging.info("received via gw %s, %s, owned by %s",
  48. data["metadata"]["gateways"][0]["gtw_id"],
  49. gtw_info[gtw_id]["description"],
  50. gtw_info[gtw_id]["owner"],
  51. )
  52. except:
  53. logging.info("received via gw %s", gtw_id)
  54. # max is 4 volts, 3 volts is considered empty
  55. batpercent = round((data["payload_fields"]["BatV"] - 3) * 100)
  56. if data["payload_fields"]["ALARM_status"]:
  57. logging.info("Red button pushed!")
  58. logging.info("Motion detection: %s", data["payload_fields"]["MD"])
  59. logging.info("LED status for position: %s", data["payload_fields"]["LON"])
  60. logging.info("Firmware version: %s", data["payload_fields"]["FW"])
  61. got_fix = False
  62. if data["payload_fields"]["Latitude"] == 0:
  63. logging.info("no GPS data (Latitude) present")
  64. # set GPS data to 0 for InfluxDB
  65. data["payload_fields"]["Latitude"] = 0.0
  66. data["payload_fields"]["Longitude"] = 0.0
  67. else:
  68. logging.info("GPS data (Latitude) present: lat %s, lon %s",
  69. data["payload_fields"]["Latitude"],
  70. data["payload_fields"]["Longitude"]
  71. )
  72. got_fix = True
  73. # transform received data into OwnTracks format
  74. ot_data = json.dumps({
  75. "_type": "location",
  76. "lat": data["payload_fields"]["Latitude"],
  77. "lon": data["payload_fields"]["Longitude"],
  78. "batt": batpercent,
  79. "t": "p",
  80. "tid": OT_TID,
  81. "tst": int(datetime.timestamp(datetime.now())),
  82. "conn": "m",
  83. })
  84. # publish to owntracks
  85. logging.info("publishing data to owntracks via mqtt to topic %s", OT_TOPIC)
  86. client_ot.publish(OT_TOPIC, payload=ot_data, retain=True, qos=1)
  87. # write to influxdb
  88. logging.info("writing data to influxdb")
  89. influxdb.write_points(
  90. [{
  91. "measurement": "dragino",
  92. "tags": {
  93. "device": "lgt92",
  94. },
  95. "fields": {
  96. "bat": float(data["payload_fields"]["BatV"]),
  97. "pitch": float(data["payload_fields"]["Pitch"]),
  98. "roll": float(data["payload_fields"]["Roll"]),
  99. "lat": float(data["payload_fields"]["Latitude"]),
  100. "lon": float(data["payload_fields"]["Longitude"]),
  101. "alarm": int(data["payload_fields"]["ALARM_status"]),
  102. "counter": data["counter"],
  103. "airtime": data["metadata"]["airtime"],
  104. "rssi": data["metadata"]["gateways"][0]["rssi"],
  105. "fix": got_fix,
  106. }
  107. }]
  108. )
  109. logging.info("data processing done")
  110. def shutdown():
  111. logging.info("disconnecting from mqtt")
  112. client_ot.disconnect()
  113. client_ot.loop_stop()
  114. client_ttn.disconnect()
  115. client_ttn.loop_stop()
  116. def handleSIGTERM(signalNumber, frame):
  117. logging.info("got SIGTERM")
  118. shutdown()
  119. return
  120. if __name__ == '__main__':
  121. signal.signal(signal.SIGTERM, handleSIGTERM)
  122. logging.basicConfig(
  123. level=logging.INFO,
  124. format='%(asctime)s - %(message)s',
  125. datefmt='%Y-%m-%d %H:%M:%S %Z'
  126. )
  127. logging.info("Starting ioteer lgt92. "+VERSION)
  128. # Prepare InfluxDB
  129. influxdb = InfluxDBClient(
  130. host=DST_INFLUX_HOST,
  131. port=443,
  132. database=DST_INFLUX_DB,
  133. username=DST_INFLUX_USER,
  134. password=DST_INFLUX_PASS,
  135. ssl=True,
  136. verify_ssl=True,
  137. )
  138. # Prepare MQTT for The Things Network
  139. client_ttn = mqtt.Client()
  140. client_ttn.enable_logger()
  141. client_ttn.on_connect = on_connect_ttn
  142. client_ttn.on_message = on_message_ttn
  143. client_ttn.on_log = on_log
  144. client_ttn.username_pw_set(SRC_MQTT_USER,SRC_MQTT_PASS)
  145. client_ttn.tls_set()
  146. client_ttn.connect(SRC_MQTT_HOST, 8883, 60)
  147. # Prepare MQTT for OwnTracks
  148. ot_lwt = json.dumps({
  149. "_type": "lwt",
  150. "tst": int(datetime.timestamp(datetime.now())),
  151. })
  152. client_ot = mqtt.Client()
  153. client_ot.enable_logger()
  154. client_ot.on_connect = on_connect_ot
  155. client_ot.on_publish = on_publish_ot
  156. client_ot.on_log = on_log
  157. client_ot.username_pw_set(DST_MQTT_USER,DST_MQTT_PASS)
  158. client_ot.tls_set()
  159. client_ot.will_set(OT_TOPIC, payload=ot_lwt, qos=1, retain=True)
  160. client_ot.connect(DST_MQTT_HOST, 8883, 60)
  161. try:
  162. # Connect to MQTT and react to messages
  163. client_ot.loop_start()
  164. client_ttn.loop_forever()
  165. except KeyboardInterrupt:
  166. shutdown()
  167. logging.info("tschuess")