ioteer/lgt92.py

223 lines
7.1 KiB
Python
Raw Normal View History

2020-04-30 18:23:23 +00:00
import paho.mqtt.client as mqtt
import json
import os
import logging
2020-05-02 12:43:30 +00:00
import signal
2020-05-09 12:21:18 +00:00
import requests
2020-04-30 18:23:23 +00:00
from datetime import datetime
from influxdb import InfluxDBClient
from dotenv import find_dotenv, load_dotenv
load_dotenv(find_dotenv())
SRC_MQTT_HOST = os.getenv("SRC_MQTT_HOST")
SRC_MQTT_USER = os.getenv("SRC_MQTT_USER")
SRC_MQTT_PASS = os.getenv("SRC_MQTT_PASS")
DST_MQTT_HOST = os.getenv("DST_MQTT_HOST")
DST_MQTT_USER = os.getenv("DST_MQTT_USER")
DST_MQTT_PASS = os.getenv("DST_MQTT_PASS")
DST_INFLUX_HOST = os.getenv("DST_INFLUX_HOST")
DST_INFLUX_USER = os.getenv("DST_INFLUX_USER")
DST_INFLUX_PASS = os.getenv("DST_INFLUX_PASS")
DST_INFLUX_DB = os.getenv("DST_INFLUX_DB")
2020-05-09 12:21:18 +00:00
HC_PING_URL = os.getenv("HC_PING_URL")
2020-06-06 13:31:11 +00:00
VERSION = "v2.0"
2020-04-30 18:23:23 +00:00
2021-10-18 05:47:23 +00:00
OT_TOPIC = "owntracks/tobru/dragino"
OT_TID = "dragino"
2020-04-30 18:23:23 +00:00
def on_connect_ttn(client, userdata, flags, rc):
logging.info("connected to ttn %s - %s", SRC_MQTT_HOST, str(rc))
2021-10-16 12:55:00 +00:00
client.subscribe("v3/+/devices/+/up")
2020-04-30 18:23:23 +00:00
2021-10-18 05:47:23 +00:00
2020-04-30 18:23:23 +00:00
def on_connect_ot(client, userdata, flags, rc):
logging.info("connected to ot %s - %s", DST_MQTT_HOST, str(rc))
2021-10-18 05:47:23 +00:00
2020-04-30 18:23:23 +00:00
def on_publish_ot(client, userdata, rc):
2020-05-01 18:05:50 +00:00
logging.info("published data to ot")
2021-10-18 05:47:23 +00:00
2020-05-01 18:05:50 +00:00
def on_log(client, userdata, level, buf):
logging_level = mqtt.LOGGING_LEVEL[level]
logging.log(logging_level, buf)
2021-10-18 05:47:23 +00:00
# logging.info("got a log message level %s: %s", level, str(buf))
2020-05-09 12:21:18 +00:00
if "PINGRESP" in str(buf):
# report to https://healthchecks.io to tell that the connection is alive
requests.get(HC_PING_URL)
2020-04-30 18:23:23 +00:00
2021-10-18 05:47:23 +00:00
2020-04-30 18:23:23 +00:00
# The callback for when a PUBLISH message is received from the server.
def on_message_ttn(client, userdata, msg):
data = json.loads(msg.payload)
2021-10-18 05:47:23 +00:00
logging.info(
"message from ttn received for %s", data["end_device_ids"]["device_id"]
)
2020-05-10 19:52:01 +00:00
# retrieve info about gateway
2021-10-18 06:00:44 +00:00
gtw_id = data["uplink_message"]["rx_metadata"][0]["gateway_ids"]["gateway_id"]
2020-05-17 16:08:46 +00:00
try:
2021-10-18 05:47:23 +00:00
gtw_info = requests.get(
"https://www.thethingsnetwork.org/gateway-data/gateway/" + gtw_id
).json()
logging.info(
"received via gw %s, %s, owned by %s",
2020-05-17 16:08:46 +00:00
data["metadata"]["gateways"][0]["gtw_id"],
gtw_info[gtw_id]["description"],
gtw_info[gtw_id]["owner"],
)
except:
logging.info("received via gw %s", gtw_id)
2020-05-01 18:05:50 +00:00
2020-05-09 12:05:19 +00:00
# max is 4 volts, 3 volts is considered empty
2021-10-18 05:47:23 +00:00
batpercent = round((data["uplink_message"]["decoded_payload"]["BatV"] - 3) * 100)
2020-04-30 18:23:23 +00:00
2021-10-18 05:47:23 +00:00
if data["uplink_message"]["decoded_payload"]["ALARM_status"]:
2020-06-06 14:04:59 +00:00
logging.info("Red button pushed!")
2021-10-18 05:47:23 +00:00
logging.info(
"Motion detection: %s", data["uplink_message"]["decoded_payload"]["MD"]
)
logging.info(
"LED status for position: %s", data["uplink_message"]["decoded_payload"]["LON"]
)
logging.info(
"Firmware version: %s", data["uplink_message"]["decoded_payload"]["FW"]
)
2020-05-09 12:21:18 +00:00
2020-05-17 16:08:46 +00:00
got_fix = False
2021-10-18 05:47:23 +00:00
if data["uplink_message"]["decoded_payload"]["Latitude"] == 0:
2020-06-06 13:50:49 +00:00
logging.info("no GPS data (Latitude) present")
# set GPS data to 0 for InfluxDB
2021-10-18 05:47:23 +00:00
data["uplink_message"]["decoded_payload"]["Latitude"] = 0.0
data["uplink_message"]["decoded_payload"]["Longitude"] = 0.0
2020-06-06 13:50:49 +00:00
else:
2021-10-18 05:47:23 +00:00
logging.info(
"GPS data (Latitude) present: lat %s, lon %s",
data["uplink_message"]["decoded_payload"]["Latitude"],
data["uplink_message"]["decoded_payload"]["Longitude"],
2020-06-06 14:04:59 +00:00
)
2020-05-17 16:08:46 +00:00
got_fix = True
2020-04-30 18:23:23 +00:00
# transform received data into OwnTracks format
2021-10-18 05:47:23 +00:00
ot_data = json.dumps(
{
"_type": "location",
"lat": data["uplink_message"]["decoded_payload"]["Latitude"],
"lon": data["uplink_message"]["decoded_payload"]["Longitude"],
"batt": batpercent,
"t": "p",
"tid": OT_TID,
"tst": int(datetime.timestamp(datetime.now())),
"conn": "m",
}
)
2020-04-30 18:23:23 +00:00
# publish to owntracks
2020-06-06 14:04:59 +00:00
logging.info("publishing data to owntracks via mqtt to topic %s", OT_TOPIC)
2020-05-10 19:52:01 +00:00
client_ot.publish(OT_TOPIC, payload=ot_data, retain=True, qos=1)
2020-05-09 12:05:19 +00:00
# write to influxdb
logging.info("writing data to influxdb")
influxdb.write_points(
2021-10-18 05:47:23 +00:00
[
{
"measurement": "dragino",
"tags": {
"device": "lgt92",
},
"fields": {
"bat": float(data["uplink_message"]["decoded_payload"]["BatV"]),
"pitch": float(data["uplink_message"]["decoded_payload"]["Pitch"]),
"roll": float(data["uplink_message"]["decoded_payload"]["Roll"]),
"lat": float(data["uplink_message"]["decoded_payload"]["Latitude"]),
"lon": float(
data["uplink_message"]["decoded_payload"]["Longitude"]
),
2021-10-18 06:15:20 +00:00
# "alarm": int(
# data["uplink_message"]["decoded_payload"]["ALARM_status"]
# ),
2021-10-18 05:47:23 +00:00
"counter": data["counter"],
"airtime": data["metadata"]["airtime"],
"rssi": data["metadata"]["gateways"][0]["rssi"],
"fix": got_fix,
},
2020-05-09 12:05:19 +00:00
}
2021-10-18 05:47:23 +00:00
]
2020-05-09 12:05:19 +00:00
)
2020-04-30 18:23:23 +00:00
logging.info("data processing done")
2021-10-18 05:47:23 +00:00
2020-05-02 12:43:30 +00:00
def shutdown():
logging.info("disconnecting from mqtt")
2020-04-30 18:23:23 +00:00
client_ot.disconnect()
client_ot.loop_stop()
client_ttn.disconnect()
client_ttn.loop_stop()
2020-05-02 12:43:30 +00:00
2021-10-18 05:47:23 +00:00
2020-05-02 12:43:30 +00:00
def handleSIGTERM(signalNumber, frame):
logging.info("got SIGTERM")
shutdown()
return
2021-10-18 05:47:23 +00:00
if __name__ == "__main__":
2020-05-02 12:43:30 +00:00
signal.signal(signal.SIGTERM, handleSIGTERM)
logging.basicConfig(
level=logging.INFO,
2021-10-18 05:47:23 +00:00
format="%(asctime)s - %(message)s",
datefmt="%Y-%m-%d %H:%M:%S %Z",
2020-05-02 12:43:30 +00:00
)
2021-10-18 05:47:23 +00:00
logging.info("Starting ioteer lgt92. " + VERSION)
2020-05-09 12:21:18 +00:00
2020-05-02 12:43:30 +00:00
# Prepare InfluxDB
influxdb = InfluxDBClient(
2021-10-18 05:47:23 +00:00
host=DST_INFLUX_HOST,
port=443,
database=DST_INFLUX_DB,
username=DST_INFLUX_USER,
password=DST_INFLUX_PASS,
ssl=True,
verify_ssl=True,
2020-05-02 12:43:30 +00:00
)
2020-05-10 19:52:01 +00:00
# Prepare MQTT for The Things Network
2020-05-02 12:43:30 +00:00
client_ttn = mqtt.Client()
client_ttn.enable_logger()
client_ttn.on_connect = on_connect_ttn
client_ttn.on_message = on_message_ttn
client_ttn.on_log = on_log
2021-10-18 05:47:23 +00:00
client_ttn.username_pw_set(SRC_MQTT_USER, SRC_MQTT_PASS)
2020-05-02 12:43:30 +00:00
client_ttn.tls_set()
client_ttn.connect(SRC_MQTT_HOST, 8883, 60)
2020-05-10 19:52:01 +00:00
# Prepare MQTT for OwnTracks
2021-10-18 05:47:23 +00:00
ot_lwt = json.dumps(
{
"_type": "lwt",
"tst": int(datetime.timestamp(datetime.now())),
}
)
2020-05-02 12:43:30 +00:00
client_ot = mqtt.Client()
client_ot.enable_logger()
client_ot.on_connect = on_connect_ot
client_ot.on_publish = on_publish_ot
client_ot.on_log = on_log
2021-10-18 05:47:23 +00:00
client_ot.username_pw_set(DST_MQTT_USER, DST_MQTT_PASS)
2020-05-02 12:43:30 +00:00
client_ot.tls_set()
2020-05-10 19:52:01 +00:00
client_ot.will_set(OT_TOPIC, payload=ot_lwt, qos=1, retain=True)
2020-05-02 12:43:30 +00:00
client_ot.connect(DST_MQTT_HOST, 8883, 60)
try:
# Connect to MQTT and react to messages
client_ot.loop_start()
client_ttn.loop_forever()
except KeyboardInterrupt:
shutdown()
2020-05-31 19:55:32 +00:00
logging.info("tschuess")