|
@@ -15,57 +15,83 @@ import datetime
|
|
|
import paho.mqtt.client as mqtt
|
|
|
import json
|
|
|
import os
|
|
|
+import re
|
|
|
+import configparser
|
|
|
|
|
|
-version = 0.2
|
|
|
+version = 0.3
|
|
|
|
|
|
+
|
|
|
+os.chdir(sys.path[0])
|
|
|
+
|
|
|
+config = configparser.ConfigParser()
|
|
|
+config.read('cul2mqtt.ini')
|
|
|
+
|
|
|
+
|
|
|
verbose = False
|
|
|
debug = False
|
|
|
+quiet = True
|
|
|
+
|
|
|
+serialCULAvailable = False
|
|
|
+devdata = {}
|
|
|
+RXcodesToDevFunction_IT = {}
|
|
|
+RXcodesToDevFunction_RAW = {}
|
|
|
+InTopicsToDevIds = {}
|
|
|
|
|
|
-deviceConfigFile = "/home/pi/cul2mqtt_devices.yaml"
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-log_enable = True
|
|
|
-log_path = '/home/pi/logs/cul2mqtt'
|
|
|
+
|
|
|
+deviceConfigFile = config['main'].get('devices_config_yml')
|
|
|
|
|
|
-mqtt_server = "10.1.1.11"
|
|
|
-mqtt_port = 1883
|
|
|
-mqtt_user = "admin"
|
|
|
-mqtt_password = "2Bierum4"
|
|
|
+log_enable = config['main'].getboolean('log_enable')
|
|
|
+log_path = config['main'].get('log_path')
|
|
|
+if not os.path.exists(log_path):
|
|
|
+ os.makedirs(log_path)
|
|
|
|
|
|
-TX_interface_prefer = "MQTT"
|
|
|
+mqtt_server = config['mqtt'].get('server')
|
|
|
+mqtt_port = config['mqtt'].getint('port')
|
|
|
+mqtt_user = config['mqtt'].get('user')
|
|
|
+mqtt_password = config['mqtt'].get('password')
|
|
|
|
|
|
-repeat_received_commands = True
|
|
|
+TX_interface_prefer = config['main'].get('TX_interface_prefer')
|
|
|
+
|
|
|
+repeat_received_commands = False
|
|
|
|
|
|
if len(sys.argv) >= 2:
|
|
|
if sys.argv[1] == "-q":
|
|
|
verbose = False
|
|
|
+ debug = False
|
|
|
+ quiet = True
|
|
|
elif sys.argv[1] == "-v":
|
|
|
verbose = True
|
|
|
+ debug = False
|
|
|
+ quiet = False
|
|
|
+ elif sys.argv[1] == "-d":
|
|
|
+ verbose = True
|
|
|
+ debug = True
|
|
|
+ quiet = False
|
|
|
|
|
|
|
|
|
-receive_from_serial_cul = True
|
|
|
-send_on_serial_cul = True
|
|
|
-serialPort = '/dev/serial/by-id/usb-1a86_USB2.0-Serial-if00-port0'
|
|
|
-serialBaudrate = 38400
|
|
|
-serialTimeout = 1
|
|
|
-culInitCmd = 'X21\r\n'
|
|
|
-culInitTimeout = 3
|
|
|
-forceSerialCULConnected = False
|
|
|
-serialCULAvailable = False
|
|
|
+receive_from_serial_cul = config['cul'].getboolean('receive_from_serial_cul')
|
|
|
+send_on_serial_cul = config['cul'].getboolean('send_on_serial_cul')
|
|
|
+serialPort = config['cul'].get('serialPort')
|
|
|
+serialBaudrate = config['cul'].getint('serialBaudrate')
|
|
|
+serialTimeout = config['cul'].getint('serialTimeout')
|
|
|
|
|
|
-
|
|
|
-receive_from_mqtt_cul = True
|
|
|
-send_on_mqtt_cul = True
|
|
|
-mqtt_topic_cul_received = "T5/CUL/received"
|
|
|
-mqtt_topic_cul_send = "T5/CUL/send"
|
|
|
|
|
|
+
|
|
|
+culInitCmd = config['cul'].get('culInitCmd') + '\r\n'
|
|
|
+culSendsRSSI = config['cul'].getboolean('culSendsRSSI')
|
|
|
|
|
|
-filterSelfSentIncomingTimeout = 100
|
|
|
+serialCulInitTimeout = config['cul'].getint('serialCulInitTimeout')
|
|
|
+forceSerialCULConnected = config['cul'].getboolean('forceSerialCULConnected')
|
|
|
+
|
|
|
+
|
|
|
+receive_from_mqtt_cul = config['cul'].getboolean('receive_from_mqtt_cul')
|
|
|
+send_on_mqtt_cul = config['cul'].getboolean('send_on_mqtt_cul')
|
|
|
+mqtt_cul_topic_received = config['cul'].get('mqtt_cul_topic_received')
|
|
|
+mqtt_cul_topic_send = config['cul'].get('mqtt_cul_topic_send')
|
|
|
+
|
|
|
+filterSelfSentIncomingTimeout = config['main'].get('filterSelfSentIncomingTimeout')
|
|
|
|
|
|
-devdata = {}
|
|
|
-RXcodesToDevFunction = {}
|
|
|
-InTopicsToDevIds = {}
|
|
|
|
|
|
try:
|
|
|
from yaml import CLoader as Loader
|
|
@@ -98,7 +124,6 @@ def log_start():
|
|
|
|
|
|
try:
|
|
|
_log_current_date = strftime("%Y%m%d")
|
|
|
-
|
|
|
_logfilename = _log_current_date + ".log"
|
|
|
logfilehandle = open(log_path + '/' + _logfilename, 'a')
|
|
|
log_last_date = _log_current_date
|
|
@@ -123,7 +148,7 @@ def log_rotate():
|
|
|
|
|
|
def log_write(_msg):
|
|
|
global logfilehandle
|
|
|
- print(_msg)
|
|
|
+ if not quiet: print(_msg)
|
|
|
log_rotate()
|
|
|
if log_enable:
|
|
|
try:
|
|
@@ -162,14 +187,25 @@ try:
|
|
|
log_write("RX codes:")
|
|
|
for key, value in devdata[deviceid]["RX"].items():
|
|
|
if debug:
|
|
|
- log_write(key, "->", value)
|
|
|
- if value in RXcodesToDevFunction.keys():
|
|
|
- log_write("")
|
|
|
- log_write("")
|
|
|
- log_write("ERROR: RX-string '" + str(value) + "' is already defined for another device! Must be unique.")
|
|
|
- raise
|
|
|
+ log_write(str(key) + "->" + str(value))
|
|
|
+ if value.startswith("i"):
|
|
|
+
|
|
|
+ if value in RXcodesToDevFunction_IT.keys():
|
|
|
+ log_write("")
|
|
|
+ log_write("")
|
|
|
+ log_write("ERROR: RX-string '" + str(value) + "' is already defined for another device! Must be unique.")
|
|
|
+ raise
|
|
|
+ else:
|
|
|
+ RXcodesToDevFunction_IT[value] = deviceid, key
|
|
|
else:
|
|
|
- RXcodesToDevFunction[value] = deviceid, key
|
|
|
+
|
|
|
+ if value in RXcodesToDevFunction_RAW.keys():
|
|
|
+ log_write("")
|
|
|
+ log_write("")
|
|
|
+ log_write("ERROR: RX-string '" + str(value) + "' is already defined for another device! Must be unique.")
|
|
|
+ raise
|
|
|
+ else:
|
|
|
+ RXcodesToDevFunction_RAW[value] = deviceid, key
|
|
|
|
|
|
if "cmdTopic" in devdata[deviceid].keys():
|
|
|
if devdata[deviceid]["cmdTopic"] != "":
|
|
@@ -188,8 +224,12 @@ try:
|
|
|
log_write("")
|
|
|
log_write("")
|
|
|
log_write("")
|
|
|
- log_write("RXcodesToDevFunction:")
|
|
|
- log_write(RXcodesToDevFunction)
|
|
|
+ log_write("RXcodesToDevFunction_IT:")
|
|
|
+ log_write(RXcodesToDevFunction_IT)
|
|
|
+ log_write("")
|
|
|
+ log_write("")
|
|
|
+ log_write("RXcodesToDevFunction_RAW:")
|
|
|
+ log_write(RXcodesToDevFunction_RAW)
|
|
|
log_write("")
|
|
|
log_write("")
|
|
|
log_write("InTopicsToDevIds:")
|
|
@@ -200,6 +240,10 @@ try:
|
|
|
log_write(InTopicsToDevIds.keys())
|
|
|
log_write("")
|
|
|
log_write("")
|
|
|
+ log_write("devdata.keys():")
|
|
|
+ log_write(devdata.keys())
|
|
|
+ log_write("")
|
|
|
+ log_write("")
|
|
|
log_write("==== parsing config file complete ====")
|
|
|
log_write("")
|
|
|
log_write("")
|
|
@@ -212,36 +256,22 @@ except ConstructorError as err:
|
|
|
exit(1)
|
|
|
except:
|
|
|
log_write("ERROR opening configfile")
|
|
|
+ log_write("Unexpected error: " + str(sys.exc_info()[0]))
|
|
|
exit(1)
|
|
|
|
|
|
|
|
|
+lastReceivedMaxAge = config['main'].getint('lastReceivedMaxAge')
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-lastReceived = ["","","","","","","","","",""]
|
|
|
-lastReceivedTime = [0,0,0,0,0,0,0,0,0,0]
|
|
|
-lastReceivedIndex = 0
|
|
|
-lastReceivedMaxAge = 500
|
|
|
+lastReceivedTime = dict()
|
|
|
|
|
|
lastSentTime = {}
|
|
|
-lastSentMinInterval = 1500
|
|
|
+lastSentMinInterval = config['main'].getint('lastSentMinInterval')
|
|
|
|
|
|
lastSentCmd = ""
|
|
|
lastSentCmdTime = 0
|
|
|
lastSentDev = ""
|
|
|
lastSentDevCmd = ""
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
def touch(fname, times=None):
|
|
|
with open(fname, 'a'):
|
|
|
os.utime(fname, times)
|
|
@@ -250,8 +280,12 @@ def on_connect(client, userdata, flags, rc):
|
|
|
if verbose:
|
|
|
log_write("MQTT connected with result code " + str(rc))
|
|
|
if receive_from_mqtt_cul:
|
|
|
- if mqtt_topic_cul_received != "":
|
|
|
- client.subscribe(mqtt_topic_cul_received)
|
|
|
+ if mqtt_cul_topic_received != "":
|
|
|
+ client.subscribe(mqtt_cul_topic_received)
|
|
|
+
|
|
|
+ if mqtt_cul_topic_send != "":
|
|
|
+
|
|
|
+ mqttc.publish(mqtt_cul_topic_send, culInitCmd, qos=0, retain=False)
|
|
|
|
|
|
for in_topic in InTopicsToDevIds.keys():
|
|
|
if in_topic != "":
|
|
@@ -265,20 +299,13 @@ def on_disconnect(client, userdata, rc):
|
|
|
|
|
|
def on_message(client, userdata, msg):
|
|
|
|
|
|
-
|
|
|
payload = msg.payload.decode("utf-8")
|
|
|
|
|
|
if verbose:
|
|
|
log_write("MQTT received: " + msg.topic + " -> " + str(payload))
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
|
|
|
- if receive_from_mqtt_cul and msg.topic == mqtt_topic_cul_received:
|
|
|
+ if receive_from_mqtt_cul and msg.topic == mqtt_cul_topic_received:
|
|
|
payload = payload.rstrip()
|
|
|
if verbose:
|
|
|
log_write("")
|
|
@@ -288,33 +315,11 @@ def on_message(client, userdata, msg):
|
|
|
else:
|
|
|
for in_topic, dev in InTopicsToDevIds.items():
|
|
|
if msg.topic == in_topic:
|
|
|
-
|
|
|
- log_write("MQTT received - '" + msg.topic + "' = '" + payload + "' => DEV: " + dev)
|
|
|
-
|
|
|
+ if verbose: log_write("MQTT received - '" + msg.topic + "' = '" + payload + "' => DEV: " + dev)
|
|
|
|
|
|
if 'name' in devdata[dev].keys():
|
|
|
log_write('devName: ' + devdata[dev]['name'])
|
|
|
|
|
|
- if 'statTopic' in devdata[dev].keys():
|
|
|
- log_write('statTopic: ' + devdata[dev]['statTopic'])
|
|
|
- mqttc.publish(devdata[dev]['statTopic'], payload, qos=0, retain=False)
|
|
|
-
|
|
|
- if 'add_statTopics_on' in devdata[dev].keys():
|
|
|
- log_write("add_statTopics_on:")
|
|
|
- for res in devdata[dev]['add_statTopics_on']:
|
|
|
-
|
|
|
- if 'on_payload' in res and 'topic' in res and 'payload' in res:
|
|
|
- if payload == res['on_payload'] and payload != "" and res['topic'] != "" and res['payload'] != "":
|
|
|
- log_write(" on '" + payload + "': '" + res['payload'] + "' => '" + res['topic'] + "'")
|
|
|
- mqttc.publish(res[topic], res[payload], qos=0, retain=False)
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- TX_interface = TX_interface_prefer
|
|
|
-
|
|
|
global lastSentDev, lastSentDevCmd, lastSentCmdTime
|
|
|
now = int(round(time.time() * 1000))
|
|
|
if debug:
|
|
@@ -322,41 +327,41 @@ def on_message(client, userdata, msg):
|
|
|
if dev == lastSentDev and payload == lastSentDevCmd and (now - lastSentCmdTime) < 1000:
|
|
|
if verbose:
|
|
|
log_write("MQTT: ignored command as we just sent this.")
|
|
|
- pass
|
|
|
else:
|
|
|
cul_send(dev, payload)
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
+ if 'statTopic' in devdata[dev].keys():
|
|
|
+ if verbose: log_write('statTopic: ' + devdata[dev]['statTopic'])
|
|
|
+ mqttc.publish(devdata[dev]['statTopic'], payload, qos=0, retain=False)
|
|
|
+
|
|
|
+ if 'add_statTopics_on' in devdata[dev].keys():
|
|
|
+ if verbose: log_write("add_statTopics_on:")
|
|
|
+ for res in devdata[dev]['add_statTopics_on']:
|
|
|
+ if 'on_payload' in res and 'topic' in res and 'payload' in res:
|
|
|
+ if payload == res['on_payload'] and payload != "" and res['topic'] != "" and res['payload'] != "":
|
|
|
+ if verbose: log_write(" on '" + payload + "': '" + res['payload'] + "' => '" + res['topic'] + "'")
|
|
|
+ mqttc.publish(res[topic], res[payload], qos=0, retain=False)
|
|
|
|
|
|
|
|
|
def publish_device_statusupdate(device, cmd):
|
|
|
if device in devdata.keys():
|
|
|
if 'statTopic' in devdata[device].keys():
|
|
|
- statTopic = devdata[device]['statTopic']
|
|
|
- log_write("MQTT publish: '" + cmd + "' -> '" + statTopic + "'")
|
|
|
+ statTopic = devdata[device].get('statTopic')
|
|
|
+ if verbose: log_write("MQTT publish: '" + cmd + "' -> '" + statTopic + "'")
|
|
|
mqttc.publish(statTopic, cmd, qos=0, retain=False)
|
|
|
|
|
|
if 'add_statTopics_on' in devdata[device].keys():
|
|
|
- log_write(" MQTT publish add_statTopics_on:")
|
|
|
- for res in devdata[device]['add_statTopics_on']:
|
|
|
-
|
|
|
+ if verbose: log_write(" MQTT publish add_statTopics_on:")
|
|
|
+ for res in devdata[device].get('add_statTopics_on'):
|
|
|
if 'on_payload' in res and 'topic' in res and 'payload' in res:
|
|
|
if cmd == res['on_payload']:
|
|
|
- log_write(" on '" + res['on_payload'] + "' -> publish '" + res['payload'] + "' on topic '" + res['topic'] + "'")
|
|
|
+ if verbose: log_write(" on '" + res['on_payload'] + "' -> publish '" + res['payload'] + "' on topic '" + res['topic'] + "'")
|
|
|
mqttc.publish(res['topic'], res['payload'], qos=0, retain=False)
|
|
|
|
|
|
if 'add_statTopics' in devdata[device].keys():
|
|
|
- log_write(" MQTT publish on add_statTopics:")
|
|
|
+ if verbose: log_write(" MQTT publish on add_statTopics:")
|
|
|
for res in devdata[device]['add_statTopics']:
|
|
|
- log_write(" '" + cmd + "' -> '" + res + "'")
|
|
|
+ if verbose: log_write(" '" + cmd + "' -> '" + res + "'")
|
|
|
mqttc.publish(res, cmd, qos=0, retain=False)
|
|
|
|
|
|
|
|
@@ -364,17 +369,32 @@ def publish_device_statusupdate(device, cmd):
|
|
|
def parseRXCode(rx_code, source_cul):
|
|
|
receivedForDevice = None
|
|
|
receivedCmnd = None
|
|
|
- if rx_code in RXcodesToDevFunction:
|
|
|
- receivedForDevice = RXcodesToDevFunction[rx_code][0]
|
|
|
- receivedCmnd = RXcodesToDevFunction[rx_code][1]
|
|
|
-
|
|
|
-
|
|
|
- log_write("")
|
|
|
- log_write("CUL '" + source_cul + "' received '" + rx_code + "' => DEV: " + receivedForDevice + ", CMD: " + receivedCmnd)
|
|
|
- else:
|
|
|
- if rx_code.startswith("i"):
|
|
|
+ if rx_code.startswith("i"):
|
|
|
+
|
|
|
+ if debug: log_write("INTERTECHNO PROTOCOL")
|
|
|
+ if rx_code in RXcodesToDevFunction_IT:
|
|
|
+ receivedForDevice = RXcodesToDevFunction_IT[rx_code][0]
|
|
|
+ receivedCmnd = RXcodesToDevFunction_IT[rx_code][1]
|
|
|
+ if debug: log_write("DEV: " + receivedForDevice + ", CMD: " + receivedCmnd + ", RX: " + rx_code)
|
|
|
+ if verbose:
|
|
|
+ log_write("")
|
|
|
+ log_write("CUL '" + source_cul + "' received '" + rx_code + "' => DEV: " + receivedForDevice + ", CMD: " + receivedCmnd)
|
|
|
+ else:
|
|
|
receivedForDevice, receivedCmnd = decodeInterTechnoRX(rx_code)
|
|
|
- print(receivedForDevice, receivedCmnd)
|
|
|
+ if debug: log_write(receivedForDevice + ", " + receivedCmnd)
|
|
|
+ else:
|
|
|
+
|
|
|
+ if debug: log_write("OTHER/RAW PROTOCOL")
|
|
|
+ if rx_code in RXcodesToDevFunction_RAW:
|
|
|
+ receivedForDevice = RXcodesToDevFunction_RAW[rx_code][0]
|
|
|
+ receivedCmnd = RXcodesToDevFunction_RAW[rx_code][1]
|
|
|
+ if debug: log_write("DEV: " + receivedForDevice + ", CMD: " + receivedCmnd + ", RX: " + rx_code)
|
|
|
+ if verbose:
|
|
|
+ log_write("")
|
|
|
+ log_write("CUL '" + source_cul + "' received '" + rx_code + "' => DEV: " + receivedForDevice + ", CMD: " + receivedCmnd)
|
|
|
+
|
|
|
+ if debug:
|
|
|
+ log_write("DEV: " + receivedForDevice + ", CMD: " + receivedCmnd + ", RX: " + rx_code)
|
|
|
|
|
|
if receivedForDevice != None and receivedCmnd != None:
|
|
|
publish_device_statusupdate(receivedForDevice, receivedCmnd)
|
|
@@ -431,17 +451,15 @@ def decodeInterTechnoRX(rx_code):
|
|
|
|
|
|
if _housecode != None and _devaddr != None and _command != None:
|
|
|
_itname = "IT_" + _housecode + _devaddr
|
|
|
-
|
|
|
+ if debug: log_write("valid IT code: '" + _itname + "' => '" + _command + "'")
|
|
|
return _itname, _command
|
|
|
|
|
|
else:
|
|
|
+ if debug: log_write("unknown or invalid IT code '" + rx_code + "'")
|
|
|
return False
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
+ else:
|
|
|
+ if debug: log_write("unknown or invalid IT code '" + rx_code + "'")
|
|
|
|
|
|
def encodeInterTechnoRX(itname, cmd):
|
|
|
|
|
@@ -491,7 +509,7 @@ def encodeInterTechnoRX(itname, cmd):
|
|
|
if cmd == "ON": _command = "15"
|
|
|
elif cmd == "OFF": _command = "14"
|
|
|
|
|
|
-
|
|
|
+ if debug: print("IT housecode=", _housecode, "- devaddr=", _devaddr, "- command=", _command)
|
|
|
|
|
|
if _housecode != None and _devaddr != None and _command != None:
|
|
|
_rxcode = "i" + _housecode + _devaddr + _command
|
|
@@ -499,55 +517,86 @@ def encodeInterTechnoRX(itname, cmd):
|
|
|
return _rxcode
|
|
|
|
|
|
else:
|
|
|
+ if debug: log_write("unknown or invalid IT code '" + rx_code + "'")
|
|
|
return False
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
|
|
|
-
|
|
|
-
|
|
|
+ else:
|
|
|
+ if debug: log_write("unknown or invalid IT code '" + rx_code + "'")
|
|
|
|
|
|
def cul_received(payload, source_cul):
|
|
|
-
|
|
|
- global lastReceivedTime, lastReceivedIndex, lastReceivedMaxAge
|
|
|
-
|
|
|
-
|
|
|
- isSendReply = False
|
|
|
+ global lastReceivedTime, lastReceivedMaxAge
|
|
|
|
|
|
if payload[:2] == 'is':
|
|
|
- isSendReply = True
|
|
|
+ pass
|
|
|
|
|
|
elif payload[:1] == 'i':
|
|
|
- inCmd = payload[:-2]
|
|
|
+
|
|
|
+ if culSendsRSSI:
|
|
|
+ inCmd = payload[:-2]
|
|
|
+ else:
|
|
|
+ inCmd = payload
|
|
|
+
|
|
|
if verbose:
|
|
|
- log_write("inCmd: " + inCmd + ", CUL: " + source_cul)
|
|
|
-
|
|
|
+ log_write("inCmd: " + inCmd + ", receiving CUL: " + source_cul)
|
|
|
|
|
|
+
|
|
|
ignoreCommand = False
|
|
|
- lastReceivedLength = len(lastReceived)
|
|
|
- i = 0
|
|
|
- while i < lastReceivedLength:
|
|
|
-
|
|
|
- if lastReceived[i] == inCmd:
|
|
|
- lastTime = int(lastReceivedTime[i])
|
|
|
+ if inCmd in lastReceivedTime.keys():
|
|
|
+ lastTime = int(lastReceivedTime[inCmd])
|
|
|
+ now = int(round(time.time() * 1000))
|
|
|
+ tdelta = (now - lastTime)
|
|
|
+ if debug: log_write("TDELTA = " + str(tdelta))
|
|
|
+ if debug: log_write("lastTime = " + str(lastTime))
|
|
|
+
|
|
|
+ if tdelta < lastReceivedMaxAge:
|
|
|
+ if verbose: log_write("ignoring command from CUL '" + source_cul + "', CMD: '" + inCmd + "' - already received " + str(tdelta) + " ms ago")
|
|
|
+ ignoreCommand = True
|
|
|
+
|
|
|
+ if not ignoreCommand:
|
|
|
+ lastReceivedTime[inCmd] = int(round(time.time() * 1000))
|
|
|
+ parseRXCode(inCmd, source_cul)
|
|
|
+
|
|
|
+ elif payload[:1] == 'p':
|
|
|
+
|
|
|
+
|
|
|
+ splitPayload = payload.split(' ')
|
|
|
+ actualPayload = splitPayload[len(splitPayload)-1]
|
|
|
+ if debug: log_write("actualPayload: '" + actualPayload)
|
|
|
+
|
|
|
+ ignoreCommand = False
|
|
|
+
|
|
|
+
|
|
|
+ isITrepetation = False
|
|
|
+ if ('i'+actualPayload) in lastReceivedTime.keys():
|
|
|
+ isITrepetation = True
|
|
|
+ if debug: log_write("IS IT REPETATION")
|
|
|
+ lastTime = int(lastReceivedTime['i'+actualPayload])
|
|
|
+ now = int(round(time.time() * 1000))
|
|
|
+ tdelta = (now - lastTime)
|
|
|
+ if debug: log_write("TDELTA = " + str(tdelta))
|
|
|
+ if tdelta < lastReceivedMaxAge:
|
|
|
+ if verbose: log_write("ignoring command from CUL '" + source_cul + "', CMD: '" + 'i'+actualPayload + "' - already received " + str(tdelta) + " ms ago")
|
|
|
+ ignoreCommand = True
|
|
|
+
|
|
|
+
|
|
|
+ if not isITrepetation:
|
|
|
+ if actualPayload in lastReceivedTime.keys():
|
|
|
+ lastTime = int(lastReceivedTime[actualPayload])
|
|
|
now = int(round(time.time() * 1000))
|
|
|
tdelta = (now - lastTime)
|
|
|
-
|
|
|
+ if debug: log_write("TDELTA = " + str(tdelta))
|
|
|
if tdelta < lastReceivedMaxAge:
|
|
|
- log_write("ignoring command from CUL '" + source_cul + "', CMD: '" + inCmd + "' - already received " + str(tdelta) + " ms ago")
|
|
|
+ if verbose: log_write("ignoring command from CUL '" + source_cul + "', CMD: '" + actualPayload + "' - already received " + str(tdelta) + " ms ago")
|
|
|
ignoreCommand = True
|
|
|
-
|
|
|
- i += 1
|
|
|
|
|
|
if not ignoreCommand:
|
|
|
- lastReceived[lastReceivedIndex] = inCmd
|
|
|
- lastReceivedTime[lastReceivedIndex] = int(round(time.time() * 1000))
|
|
|
- if lastReceivedIndex >= (lastReceivedLength - 1):
|
|
|
- lastReceivedIndex = 0
|
|
|
+ if isITrepetation:
|
|
|
+
|
|
|
+ lastReceivedTime['i'+actualPayload] = int(round(time.time() * 1000))
|
|
|
+ parseRXCode('i'+actualPayload, source_cul)
|
|
|
else:
|
|
|
- lastReceivedIndex += 1
|
|
|
-
|
|
|
- parseRXCode(inCmd, source_cul)
|
|
|
+ lastReceivedTime[actualPayload] = int(round(time.time() * 1000))
|
|
|
+ parseRXCode(actualPayload, source_cul)
|
|
|
|
|
|
|
|
|
|
|
@@ -617,47 +666,41 @@ def cul_send(device, cmd):
|
|
|
global lastSentTime
|
|
|
culCmd = ""
|
|
|
culSendCmdsKeyName = device + ' ' + cmd
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- publish_device_statusupdate(device, cmd)
|
|
|
-
|
|
|
+ if debug: log_write("CUL send '" + cmd + "' to device '" + device + "'")
|
|
|
+
|
|
|
tx_code = False
|
|
|
|
|
|
if 'TX' in devdata[device]:
|
|
|
-
|
|
|
-
|
|
|
- if cmd in devdata[device]['TX']:
|
|
|
+ if debug: print("TX data available, cmd="+cmd)
|
|
|
+ if debug: print(devdata[device]['TX'])
|
|
|
+ if cmd in devdata[device]['TX'].keys():
|
|
|
tx_code = devdata[device]['TX'][cmd]
|
|
|
- log_write(" TX code for '" + cmd + "': " + tx_code)
|
|
|
-
|
|
|
+ if verbose: log_write(" TX code for '" + cmd + "': " + tx_code)
|
|
|
+
|
|
|
if not tx_code:
|
|
|
- print(" deviceID: ", device)
|
|
|
- if 'RX' in devdata[device]:
|
|
|
- print(" RX code configured, cmd=" + cmd)
|
|
|
- print(devdata[device]['RX'])
|
|
|
- if cmd in devdata[device]['RX']:
|
|
|
+ if verbose: log_write(" deviceID: " + device)
|
|
|
+ if 'RX' in devdata[device].keys():
|
|
|
+ if verbose:
|
|
|
+ log_write(" RX code configured, cmd=" + cmd)
|
|
|
+ log_write(devdata[device]['RX'])
|
|
|
+ if cmd in devdata[device]['RX'].keys():
|
|
|
rx_code = devdata[device]['RX'][cmd]
|
|
|
- print(" RX code for '" + cmd + "': " + rx_code)
|
|
|
+ if debug: log_write(" RX code for '" + cmd + "': " + rx_code)
|
|
|
tx_code = IT_RXtoTXCode(rx_code)
|
|
|
- log_write(" TX code for '" + cmd + "': " + tx_code)
|
|
|
+ if verbose: log_write(" TX code for '" + cmd + "': " + tx_code)
|
|
|
+ else:
|
|
|
+ log_write(" RX code for '" + cmd + "' NOT FOUND")
|
|
|
+
|
|
|
elif device.startswith("IT_"):
|
|
|
|
|
|
rx_code = encodeInterTechnoRX(device, cmd)
|
|
|
if rx_code:
|
|
|
- print(" RX code for '" + cmd + "': " + rx_code)
|
|
|
+ if debug: log_write(" RX code for '" + cmd + "': " + rx_code)
|
|
|
tx_code = IT_RXtoTXCode(rx_code)
|
|
|
- log_write(" TX code for '" + cmd + "': " + tx_code)
|
|
|
+ if verbose: log_write(" TX code for '" + cmd + "': " + tx_code)
|
|
|
|
|
|
if not tx_code:
|
|
|
- log_write(" no valid TX code for this device/command")
|
|
|
+ if verbose: log_write(" no valid TX code for this device/command")
|
|
|
else:
|
|
|
now = int(round(time.time() * 1000))
|
|
|
|
|
@@ -668,14 +711,14 @@ def cul_send(device, cmd):
|
|
|
lastTime = 0
|
|
|
|
|
|
lastTimeAge = now - lastTime
|
|
|
- log_write(' lastTime: ' + str(lastTimeAge) + 'ms ago')
|
|
|
+ if verbose: log_write(' lastTime: ' + str(lastTimeAge) + 'ms ago')
|
|
|
|
|
|
if lastTimeAge > lastSentMinInterval:
|
|
|
lastSentTime[culSendCmdsKeyName] = now
|
|
|
|
|
|
TX_interface = TX_interface_prefer
|
|
|
if 'TX_interface' in devdata[device].keys():
|
|
|
- log_write(" TX_interface: " + devdata[device]['TX_interface'])
|
|
|
+ if verbose: log_write(" TX_interface: " + devdata[device]['TX_interface'])
|
|
|
|
|
|
if TX_interface == "UART" and not serialCULAvailable:
|
|
|
TX_interface = "MQTT"
|
|
@@ -688,23 +731,24 @@ def cul_send(device, cmd):
|
|
|
|
|
|
if send_on_mqtt_cul and (TX_interface == "MQTT" or TX_interface == "both"):
|
|
|
log_write(" TX via MQTT: " + tx_code)
|
|
|
- mqttc.publish(mqtt_topic_cul_send, tx_code, qos=0, retain=False)
|
|
|
+ mqttc.publish(mqtt_cul_topic_send, tx_code, qos=0, retain=False)
|
|
|
|
|
|
if serialCULAvailable and send_on_serial_cul and (TX_interface == "UART" or TX_interface == "both"):
|
|
|
log_write(" TX via UART: " + tx_code)
|
|
|
culCmd = tx_code + '\r\n'
|
|
|
- ser.write(culCmd.encode('utf-8'))
|
|
|
+ ser.write(culCmd.encode('ascii'))
|
|
|
|
|
|
else:
|
|
|
log_write("WARNING: CUL send command repeated too quickly.")
|
|
|
|
|
|
+ publish_device_statusupdate(device, cmd)
|
|
|
|
|
|
|
|
|
|
|
|
if receive_from_serial_cul or send_on_serial_cul:
|
|
|
if not os.path.exists(serialPort):
|
|
|
log_write("ERROR opening connection to serial CUL... device '" + serialPort + "' does not exist.")
|
|
|
- if log_enable: writeLog("CUL2MQTT v"+version+" starting")
|
|
|
+ if log_enable: log_write("CUL2MQTT v"+str(version)+" starting")
|
|
|
|
|
|
if receive_from_mqtt_cul:
|
|
|
if forceSerialCULConnected:
|
|
@@ -721,16 +765,16 @@ if receive_from_serial_cul or send_on_serial_cul:
|
|
|
log_write("opening connection to serial CUL...")
|
|
|
serLine = ""
|
|
|
ser = serial.Serial(port=serialPort,baudrate=serialBaudrate,parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE,bytesize=serial.EIGHTBITS,timeout=serialTimeout)
|
|
|
- sleep(culInitTimeout)
|
|
|
- ser.write('V\r\n'.encode('utf-8'))
|
|
|
+ sleep(serialCulInitTimeout)
|
|
|
+ ser.write('V\r\n'.encode('ascii'))
|
|
|
serLine = ser.readline()
|
|
|
- serLine = serLine.decode('utf-8').rstrip('\r\n')
|
|
|
+ serLine = serLine.decode('ascii').rstrip('\r\n')
|
|
|
if serLine.startswith("V ") and serLine.find("culfw") != -1:
|
|
|
log_write("connected. CUL version: " + serLine)
|
|
|
serialCULAvailable = True
|
|
|
sleep(0.1)
|
|
|
log_write('Initializing CUL with command: ' + culInitCmd.rstrip('\r\n'))
|
|
|
- ser.write(culInitCmd.encode('utf-8'))
|
|
|
+ ser.write(culInitCmd.encode('ascii'))
|
|
|
sleep(0.5)
|
|
|
else:
|
|
|
log_write("WARNING: could not connect serial CUL")
|
|
@@ -746,8 +790,9 @@ mqttc.on_connect = on_connect
|
|
|
mqttc.on_disconnect = on_disconnect
|
|
|
mqttc.on_message = on_message
|
|
|
|
|
|
-if len(mqtt_user) > 0 and len(mqtt_password) > 0:
|
|
|
- mqttc.username_pw_set(mqtt_user, mqtt_password)
|
|
|
+if mqtt_user is not None and mqtt_password is not None:
|
|
|
+ if len(mqtt_user) > 0 and len(mqtt_password) > 0:
|
|
|
+ mqttc.username_pw_set(mqtt_user, mqtt_password)
|
|
|
|
|
|
mqttc.connect(mqtt_server, mqtt_port, 60)
|
|
|
mqttc.loop_start()
|
|
@@ -757,7 +802,7 @@ while True:
|
|
|
serLine = ser.readline()
|
|
|
if len(serLine) > 0:
|
|
|
now = int(round(time.time() * 1000))
|
|
|
- recvCmd = serLine.decode('utf-8')
|
|
|
+ recvCmd = serLine.decode('ascii')
|
|
|
recvCmd = recvCmd.rstrip('\r\n')
|
|
|
|
|
|
|