|
@@ -1,8 +1,14 @@
|
|
|
-
|
|
|
+
|
|
|
|
|
|
|
|
|
+
|
|
|
import serial
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
import time
|
|
|
+from time import localtime, strftime
|
|
|
+
|
|
|
import os
|
|
|
import paho.mqtt.client as mqtt
|
|
|
|
|
@@ -12,8 +18,10 @@ import paho.mqtt.client as mqtt
|
|
|
|
|
|
mqtt_server = "mqtt.lan"
|
|
|
mqtt_port = 1883
|
|
|
-mqtt_user = "sagi"
|
|
|
-mqtt_password = "dirsichernet!"
|
|
|
+mqtt_user = "script"
|
|
|
+mqtt_password = "rlAzqusqfbAy"
|
|
|
+
|
|
|
+sensordata_maxage = 300
|
|
|
|
|
|
verbosemode = False
|
|
|
|
|
@@ -22,12 +30,13 @@ def touch(fname, times=None):
|
|
|
os.utime(fname, times)
|
|
|
|
|
|
def on_connect(client, userdata, flags, rc):
|
|
|
- print("MQTT connected with result code " + str(rc))
|
|
|
+ if verbosemode:
|
|
|
+ print("MQTT connected with result code " + str(rc))
|
|
|
|
|
|
|
|
|
def on_disconnect(client, userdata, rc):
|
|
|
if rc != 0:
|
|
|
- print "Unexpected MQTT disconnection. Will auto-reconnect"
|
|
|
+ print("Unexpected MQTT disconnection. Will auto-reconnect")
|
|
|
|
|
|
|
|
|
|
|
@@ -40,8 +49,16 @@ mqtt_topic_prefix = "LaCrosse"
|
|
|
override_updateinterval_on_change = False
|
|
|
atemp_sensor_idx = 94
|
|
|
|
|
|
+checkLastUpdateInterval = 60
|
|
|
+checkLastUpdateInterval_lastRun = 0
|
|
|
+
|
|
|
sensors = {}
|
|
|
sensors_idx = {}
|
|
|
+sensors_lastTemp = {}
|
|
|
+sensors_lastHum = {}
|
|
|
+sensors_lastUpdate = {}
|
|
|
+sensors_unavailable = {}
|
|
|
+
|
|
|
with open("/home/pi/jeelink_sensors.csv", "r") as sensorscsv:
|
|
|
for line in sensorscsv:
|
|
|
if line.find('ID,DomoticzIdx,Name') == -1:
|
|
@@ -56,6 +73,10 @@ with open("/home/pi/jeelink_sensors.csv", "r") as sensorscsv:
|
|
|
|
|
|
sensors[str(sensorId)] = str(sensorName)
|
|
|
sensors_idx[str(sensorId)] = str(domoticzIdx)
|
|
|
+ sensors_lastUpdate[str(sensorId)] = 0
|
|
|
+ sensors_unavailable[str(sensorId)] = 1
|
|
|
+ if verbosemode:
|
|
|
+ print("Sensor " + sensorId + " = '" + sensorName + "'")
|
|
|
|
|
|
|
|
|
mqttc = mqtt.Client()
|
|
@@ -80,12 +101,11 @@ ser = serial.Serial(port='/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AL01MYTF-if
|
|
|
|
|
|
|
|
|
if verbosemode:
|
|
|
- print sensors
|
|
|
- print sensors_idx
|
|
|
+ print(sensors)
|
|
|
+ print(sensors_idx)
|
|
|
+
|
|
|
|
|
|
-sensors_lastTemp = {}
|
|
|
-sensors_lastHum = {}
|
|
|
-sensors_lastUpdate = {}
|
|
|
+checkLastUpdateInterval_lastRun = time.time()
|
|
|
|
|
|
try:
|
|
|
while True:
|
|
@@ -95,17 +115,16 @@ try:
|
|
|
ser.flushInput()
|
|
|
|
|
|
|
|
|
- serLine = ser.readline()
|
|
|
+ serLine = ser.readline().strip()
|
|
|
+ serLine = serLine.decode('ascii')
|
|
|
|
|
|
if(serLine):
|
|
|
-
|
|
|
- serLine = serLine.strip('\r')
|
|
|
- serLine = serLine.strip('\n')
|
|
|
-
|
|
|
if verbosemode:
|
|
|
- print serLine
|
|
|
-
|
|
|
+ print(serLine)
|
|
|
if serLine.find('OK 9') != -1:
|
|
|
+ if verbosemode:
|
|
|
+ print("is LaCrosse sensor")
|
|
|
+
|
|
|
|
|
|
|
|
|
|
|
@@ -119,32 +138,20 @@ try:
|
|
|
|
|
|
|
|
|
|
|
|
- bytes = serLine.split(' ')
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- addr = int(bytes[2])
|
|
|
- addrhex = "{0:x}".format(int(bytes[2]))
|
|
|
+ serLineParts = serLine.split(' ')
|
|
|
|
|
|
- currentsensor_name = sensors.get(str(addr), None)
|
|
|
-
|
|
|
- if currentsensor_name is None:
|
|
|
- fname = '/home/pi/logs/jeelink_unknown_sensor_' + str(addr)
|
|
|
- try:
|
|
|
- touch(fname)
|
|
|
- except:
|
|
|
-
|
|
|
- pass
|
|
|
- if verbosemode:
|
|
|
- print "unknown sensor ID " + str(addr)
|
|
|
- temp = (int(bytes[4])*256 + int(bytes[5]) - 1000)/10.0
|
|
|
- print "Temp: " + str(temp)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ addr = int(serLineParts[2])
|
|
|
+ addrhex = "{0:x}".format(int(serLineParts[2]))
|
|
|
+
|
|
|
|
|
|
lastUpdate = sensors_lastUpdate.get(str(addr), None)
|
|
|
lastTemp = sensors_lastTemp.get(str(addr), None)
|
|
|
lastHum = sensors_lastHum.get(str(addr), None)
|
|
|
currentsensor_idx = sensors_idx.get(str(addr),None)
|
|
|
+ currentsensor_name = sensors.get(str(addr), None)
|
|
|
|
|
|
senddata = False
|
|
|
if currentsensor_idx is not None:
|
|
@@ -157,34 +164,60 @@ try:
|
|
|
timediff = int(time.time()) - lastUpdate
|
|
|
if timediff >= minUpdateInterval:
|
|
|
senddata = True
|
|
|
-
|
|
|
+ elif sensors_unavailable[str(addr)] == 1:
|
|
|
+ senddata = True
|
|
|
else:
|
|
|
senddata = True
|
|
|
|
|
|
- if senddata:
|
|
|
- if int(bytes[3]) >= 128:
|
|
|
- batt_new = 1
|
|
|
- type = int(bytes[3]) - 128
|
|
|
- else:
|
|
|
- batt_new = 0
|
|
|
- type = int(bytes[3])
|
|
|
-
|
|
|
- temp = (int(bytes[4])*256 + int(bytes[5]) - 1000)/10.0
|
|
|
-
|
|
|
- if int(bytes[6]) >= 128:
|
|
|
- batt_low = 1
|
|
|
- hum = int(bytes[6]) - 128
|
|
|
- else:
|
|
|
- batt_low = 0
|
|
|
- hum = int(bytes[6])
|
|
|
- if hum > 100:
|
|
|
- hum = 100
|
|
|
-
|
|
|
- if batt_low == 0:
|
|
|
- batterystate = "ok"
|
|
|
+ sensors_unavailable[str(addr)] = 0
|
|
|
+
|
|
|
+
|
|
|
+ if int(serLineParts[3]) >= 128:
|
|
|
+ batt_new = 1
|
|
|
+ type = int(serLineParts[3]) - 128
|
|
|
+ else:
|
|
|
+ batt_new = 0
|
|
|
+ type = int(serLineParts[3])
|
|
|
+
|
|
|
+ temp = (int(serLineParts[4])*256 + int(serLineParts[5]) - 1000)/10.0
|
|
|
+
|
|
|
+ if int(serLineParts[6]) >= 128:
|
|
|
+ batt_low = 1
|
|
|
+ hum = int(serLineParts[6]) - 128
|
|
|
+ else:
|
|
|
+ batt_low = 0
|
|
|
+ hum = int(serLineParts[6])
|
|
|
+ if hum > 100:
|
|
|
+ hum = 100
|
|
|
+
|
|
|
+ if batt_low == 0:
|
|
|
+ batterystate = "ok"
|
|
|
+ else:
|
|
|
+ batterystate = "low"
|
|
|
+
|
|
|
+
|
|
|
+ if currentsensor_name is None:
|
|
|
+ if batt_new == 1:
|
|
|
+ fname = '/home/pi/logs/jeelink_unknown_new_sensor_' + str(addr)
|
|
|
else:
|
|
|
- batterystate = "low"
|
|
|
-
|
|
|
+ fname = '/home/pi/logs/jeelink_unknown_sensor_' + str(addr)
|
|
|
+
|
|
|
+ if not os.path.isfile(fname):
|
|
|
+ try:
|
|
|
+ touch(fname)
|
|
|
+ except:
|
|
|
+
|
|
|
+ pass
|
|
|
+ temp = (int(serLineParts[4])*256 + int(serLineParts[5]) - 1000)/10.0
|
|
|
+ if verbosemode:
|
|
|
+ print("unknown sensor ID " + str(addr))
|
|
|
+ print("Temp: " + str(temp))
|
|
|
+ mqttc.publish(mqtt_topic_prefix+"/UnknownSensor/"+str(addr)+"/temperature", str(temp), qos=2, retain=False)
|
|
|
+ mqttc.publish(mqtt_topic_prefix+"/UnknownSensor/"+str(addr)+"/humidity", str(hum), qos=2, retain=False)
|
|
|
+ mqttc.publish(mqtt_topic_prefix+"/UnknownSensor/"+str(addr)+"/battNew", str(batt_new), qos=2, retain=False)
|
|
|
+
|
|
|
+
|
|
|
+ if senddata:
|
|
|
sensors_lastUpdate[str(addr)] = int(time.time())
|
|
|
sensors_lastTemp[str(addr)] = str(temp)
|
|
|
sensors_lastHum[str(addr)] = str(hum)
|
|
@@ -195,24 +228,38 @@ try:
|
|
|
|
|
|
domoticz_json = "{\"idx\":" + str(currentsensor_idx) + ",\"nvalue\":0,\"svalue\":\"" + str(temp) + ";" + str(hum) + ";1\"}"
|
|
|
if verbosemode:
|
|
|
- print domoticz_json
|
|
|
+ print(domoticz_json)
|
|
|
mqttc.publish("domoticz/in", domoticz_json, qos=2, retain=False)
|
|
|
|
|
|
- mqttc.publish(mqtt_topic_prefix+"/"+str(currentsensor_name)+"/temperature", str(temp), qos=2, retain=True)
|
|
|
- mqttc.publish(mqtt_topic_prefix+"/"+str(currentsensor_name)+"/humidity", str(hum), qos=2, retain=True)
|
|
|
- mqttc.publish(mqtt_topic_prefix+"/"+str(currentsensor_name)+"/battery", str(batterystate), qos=2, retain=True)
|
|
|
+ mqttc.publish(mqtt_topic_prefix+"/"+str(currentsensor_name)+"/temperature", str(temp), qos=2, retain=False)
|
|
|
+ mqttc.publish(mqtt_topic_prefix+"/"+str(currentsensor_name)+"/humidity", str(hum), qos=2, retain=False)
|
|
|
+ mqttc.publish(mqtt_topic_prefix+"/"+str(currentsensor_name)+"/battery", str(batterystate), qos=2, retain=False)
|
|
|
+ mqttc.publish(mqtt_topic_prefix+"/"+str(currentsensor_name)+"/lastUpdate", strftime("%Y-%m-%d %H:%M:%S", localtime()), qos=2, retain=False)
|
|
|
+ mqttc.publish(mqtt_topic_prefix+"/"+str(currentsensor_name)+"/availability", "available", qos=2, retain=False)
|
|
|
|
|
|
lacrosse_json = "{\"temperature\":" + str(temp) + ", \"humidity\":" + str(hum) + ", \"battery\":\"" + str(batterystate) + "\"}"
|
|
|
- mqttc.publish(mqtt_topic_prefix+"/"+str(currentsensor_name)+"/json", lacrosse_json, qos=2, retain=True)
|
|
|
+ mqttc.publish(mqtt_topic_prefix+"/"+str(currentsensor_name)+"/json", lacrosse_json, qos=2, retain=False)
|
|
|
|
|
|
if verbosemode:
|
|
|
- print "addr: " + str(addr) + " = 0x" + str(addrhex) + " batt_new: " + str(batt_new) + " type: " + str(type) + " batt_low: " + str(batt_low) + " temp: " + str(temp) + " hum: " + str(hum) + " Name: " + str(currentsensor_name)
|
|
|
+ print("addr: " + str(addr) + " = 0x" + str(addrhex) + " batt_new: " + str(batt_new) + " type: " + str(type) + " batt_low: " + str(batt_low) + " temp: " + str(temp) + " hum: " + str(hum) + " Name: " + str(currentsensor_name))
|
|
|
+ print("\n")
|
|
|
|
|
|
try:
|
|
|
touch("/tmp/jeelink2mqtt_running")
|
|
|
except:
|
|
|
|
|
|
pass
|
|
|
+
|
|
|
+
|
|
|
+ if (time.time() - checkLastUpdateInterval_lastRun) > checkLastUpdateInterval:
|
|
|
+ checkLastUpdateInterval_lastRun = time.time()
|
|
|
+
|
|
|
+ for key in sensors_lastUpdate:
|
|
|
+
|
|
|
+ if (time.time() - sensors_lastUpdate[key]) > sensordata_maxage:
|
|
|
+ print(sensors[key], ' outd ->')
|
|
|
+ sensors_unavailable[key] = 1
|
|
|
+ mqttc.publish(mqtt_topic_prefix+"/"+str(sensors[key])+"/availability", "unavailable", qos=2, retain=False)
|
|
|
|
|
|
-except KeyboardInterrupt, e:
|
|
|
+except KeyboardInterrupt:
|
|
|
print('\n')
|