#!/usr/bin/python3 -u # import serial from time import sleep import os import sys import paho.mqtt.client as mqtt import json from datetime import datetime # --- CONFIGURATION --- import config # --- END CONFIGURATION --- # --- GLOBAL VARS --- noReceiveCount = 0 # increase everytime the serial readline times out (1s timeout) #getStatusCount = 0 # used as heartbeat, get status every 30s verbose = False debug = False quiet = True lastState_P2 = None lastState_P3 = None lastState_P4 = None lastState_P5 = None # --- END GLOBAL VARS --- if len(sys.argv) >= 2: if sys.argv[1] == "-q": verbose = False debug = False quiet = True #print("VERBOSE=ON") elif sys.argv[1] == "-v": verbose = True debug = False quiet = False #print("VERBOSE=ON") elif sys.argv[1] == "-d": verbose = True quiet = False debug = True #print("DEBUG=ON") def on_connect(client, userdata, flags, rc): if not quiet: print("MQTT connected with result code " + str(rc)) #client.subscribe(mqtt_topic_cmd) #def on_message(client, userdata, msg): # if msg.topic == mqtt_topic_cmd: # payload = msg.payload.decode('ascii') # if payload == "status" or payload == "get conf" or payload == "clear" or payload == "open door" or payload.startswith("set prof ") or payload.startswith("set conf "): # if verbose: # print("serCmd: " + payload) # serCmd = payload + '\n' # ser.write(serCmd.encode('ascii')) # elif verbose: # print("unknown command:", payload) def touch(fname, times=None): with open(fname, 'a'): os.utime(fname, times) mqttc = mqtt.Client() mqttc.on_connect = on_connect #mqttc.on_disconnect = on_disconnect #mqttc.on_message = on_message mqttc.username_pw_set(config.mqtt_user, config.mqtt_password) mqttc.connect(config.mqtt_server, config.mqtt_port, 60) mqttc.loop_start() ser = serial.Serial(port=config.serialPort, baudrate = config.serialBaud, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout=config.serialTimeout) try: while True: ##ser.flushInput() ## attention truncates incoming strings if there is little time between them #read buffer until cr/lf serLine = ser.readline().strip() # catch exception on invalid char coming in: UnicodeDecodeError: 'ascii' codec can't decode byte 0xf4 in position 6: ordinal not in range(128) try: serLine = serLine.decode('ascii') except: serLine = "" # if there came something in... if(serLine): noReceiveCount = 0 # touch status file if configured try: config.statusFile except: if debug: print("statusFile not defined") else: if config.statusFile is not None and config.statusFile != "": try: touch(config.statusFile) except: if debug: print("ERROR - could not touch statusFile '" + str(config.statusFile) + "'") else: if debug: print("statusFile not configured") if verbose: print ('RX: ' + repr(serLine)) #Echo the serial buffer bytes up to the CRLF back to screen mqttc.publish(config.mqtt_base_topic + "/RX", str(serLine), qos=0, retain=False) # digital input P2 if serLine.startswith('P2='): newState = None if serLine == "P2=L": newState = "OFF" elif serLine == "P2=H": newState = "ON" if newState is not None and (lastState_P2 != newState or not config.P2_MQTT_SendOnlyIfValueChanged): lastState_P2 = newState mqttc.publish(config.P2_MQTT_Topic, newState, qos=0, retain=config.P2_MQTT_SendRetained) if config.P2_MQTT_SendLastUpdate: mqttc.publish(config.P2_MQTT_Topic + "_lastUpdate", datetime.now().isoformat(), qos=0, retain=config.P2_MQTT_SendRetained) # digital input P3 if serLine.startswith('P3='): newState = None if serLine == "P3=L": newState = "OFF" elif serLine == "P3=H": newState = "ON" if newState is not None and (lastState_P3 != newState or not config.P3_MQTT_SendOnlyIfValueChanged): lastState_P3 = newState mqttc.publish(config.P3_MQTT_Topic, newState, qos=0, retain=config.P3_MQTT_SendRetained) if config.P3_MQTT_SendLastUpdate: mqttc.publish(config.P3_MQTT_Topic + "_lastUpdate", datetime.now().isoformat(), qos=0, retain=config.P3_MQTT_SendRetained) # digital input P4 if serLine.startswith('P4='): newState = None if serLine == "P4=L": newState = "OFF" elif serLine == "P4=H": newState = "ON" if newState is not None and (lastState_P4 != newState or not config.P4_MQTT_SendOnlyIfValueChanged): lastState_P4 = newState mqttc.publish(config.P4_MQTT_Topic, newState, qos=0, retain=config.P4_MQTT_SendRetained) if config.P4_MQTT_SendLastUpdate: mqttc.publish(config.P4_MQTT_Topic + "_lastUpdate", datetime.now().isoformat(), qos=0, retain=config.P4_MQTT_SendRetained) # digital input P5 if serLine.startswith('P5='): newState = None if serLine == "P5=L": newState = "OFF" elif serLine == "P5=H": newState = "ON" if newState is not None and (lastState_P5 != newState or not config.P5_MQTT_SendOnlyIfValueChanged): lastState_P5 = newState mqttc.publish(config.P5_MQTT_Topic, newState, qos=0, retain=config.P5_MQTT_SendRetained) if config.P5_MQTT_SendLastUpdate: mqttc.publish(config.P5_MQTT_Topic + "_lastUpdate", datetime.now().isoformat(), qos=0, retain=config.P5_MQTT_SendRetained) # DHT TH sensor # {"T":26.60,"H":36} if serLine.startswith('{"T":'): th = json.loads(serLine) t = round(float(th["T"]), 1) h = int(th["H"]) if t >= -20 and t <= 50: mqttc.publish(config.DHT22_MQTT_Topic_Temp, str(t), qos=0, retain=config.DHT22_MQTT_SendRetained) if h >= 0 and h <= 100: mqttc.publish(config.DHT22_MQTT_Topic_Hum, str(h), qos=0, retain=config.DHT22_MQTT_SendRetained) if config.DHT22_MQTT_SendLastUpdate: mqttc.publish(config.DHT22_MQTT_Topic_Temp + "_lastUpdate", datetime.now().isoformat(), qos=0, retain=config.DHT22_MQTT_SendRetained) # nothing came in this time... else: noReceiveCount += 1 if debug: print("noReceiveCount=" + str(noReceiveCount)) # quit script if nothing has been received for some time - will be restarted by systemd if noReceiveCount >= config.quitOnNoReceiveTimeout: quit() except KeyboardInterrupt: print('\n')