|
@@ -10,58 +10,58 @@ import serial
|
|
|
import sys
|
|
|
import time
|
|
|
from time import sleep
|
|
|
+from time import localtime, strftime
|
|
|
import datetime
|
|
|
import paho.mqtt.client as mqtt
|
|
|
+import json
|
|
|
import os
|
|
|
|
|
|
-version = 0.1
|
|
|
+version = 0.2
|
|
|
|
|
|
-verbose = True
|
|
|
+verbose = False
|
|
|
debug = False
|
|
|
|
|
|
deviceConfigFile = "/home/pi/cul2mqtt_devices.yaml"
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+log_enable = True
|
|
|
+log_path = '/home/pi/logs/cul2mqtt'
|
|
|
|
|
|
-mqtt_server = "mqtt.lan"
|
|
|
+mqtt_server = "10.1.1.11"
|
|
|
mqtt_port = 1883
|
|
|
-mqtt_user = ""
|
|
|
-mqtt_password = ""
|
|
|
+mqtt_user = "admin"
|
|
|
+mqtt_password = "2Bierum4"
|
|
|
|
|
|
-TX_interface_prefer = "UART"
|
|
|
+TX_interface_prefer = "MQTT"
|
|
|
|
|
|
-repeat_received_commands = False
|
|
|
+repeat_received_commands = True
|
|
|
|
|
|
if len(sys.argv) >= 2:
|
|
|
if sys.argv[1] == "-q":
|
|
|
verbose = False
|
|
|
elif sys.argv[1] == "-v":
|
|
|
verbose = True
|
|
|
- elif sys.argv[1] == "-d":
|
|
|
- debug = True
|
|
|
- verbose = True
|
|
|
|
|
|
|
|
|
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 = True
|
|
|
+serialTimeout = 1
|
|
|
+culInitCmd = 'X21\r\n'
|
|
|
+culInitTimeout = 3
|
|
|
+forceSerialCULConnected = False
|
|
|
+serialCULAvailable = False
|
|
|
|
|
|
|
|
|
-receive_from_mqtt_cul = False
|
|
|
-send_on_mqtt_cul = False
|
|
|
-mqtt_topic_cul_received = "MQTT-CUL/received"
|
|
|
-mqtt_topic_cul_send = "MQTT-CUL/send"
|
|
|
-
|
|
|
-filterSelfSentIncomingTimeout = 500
|
|
|
+receive_from_mqtt_cul = True
|
|
|
+send_on_mqtt_cul = True
|
|
|
+mqtt_topic_cul_received = "T5/CUL/received"
|
|
|
+mqtt_topic_cul_send = "T5/CUL/send"
|
|
|
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-serialCULAvailable = False
|
|
|
+filterSelfSentIncomingTimeout = 100
|
|
|
|
|
|
devdata = {}
|
|
|
RXcodesToDevFunction = {}
|
|
@@ -85,38 +85,88 @@ def no_duplicates_constructor(loader, node, deep=False):
|
|
|
|
|
|
yaml.add_constructor(yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, no_duplicates_constructor)
|
|
|
|
|
|
-print("CUL2MQTT v" + str(version))
|
|
|
-print("=====================================")
|
|
|
+
|
|
|
+log_last_date = None
|
|
|
+logfilehandle = False
|
|
|
+
|
|
|
+
|
|
|
+def log_start():
|
|
|
+ global logfilehandle, log_last_date
|
|
|
+ if log_enable:
|
|
|
+ if not os.path.exists(log_path):
|
|
|
+ os.makedirs(log_path)
|
|
|
+
|
|
|
+ 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
|
|
|
+ except:
|
|
|
+ pass
|
|
|
+
|
|
|
+
|
|
|
+def log_rotate():
|
|
|
+ global logfilehandle, log_last_date
|
|
|
+ if log_enable:
|
|
|
+ _log_current_date = strftime("%Y%m%d")
|
|
|
+
|
|
|
+ if log_last_date != _log_current_date:
|
|
|
+ try:
|
|
|
+ logfilehandle.close()
|
|
|
+ _logfilename = _log_current_date + ".log"
|
|
|
+ logfilehandle = open(log_path + '/' + _logfilename, 'a')
|
|
|
+ log_last_date = _log_current_date
|
|
|
+ except:
|
|
|
+ pass
|
|
|
+
|
|
|
+
|
|
|
+def log_write(_msg):
|
|
|
+ global logfilehandle
|
|
|
+ print(_msg)
|
|
|
+ log_rotate()
|
|
|
+ if log_enable:
|
|
|
+ try:
|
|
|
+ logfilehandle.write("[" + str(datetime.datetime.now()) + "] " + _msg + "\n")
|
|
|
+ logfilehandle.flush()
|
|
|
+ except:
|
|
|
+
|
|
|
+ pass
|
|
|
+
|
|
|
+log_start()
|
|
|
+
|
|
|
+log_write("CUL2MQTT v" + str(version))
|
|
|
+log_write("=====================================")
|
|
|
|
|
|
try:
|
|
|
with open(deviceConfigFile) as devfile:
|
|
|
devdata = yaml.load(devfile, Loader=yaml.FullLoader)
|
|
|
if debug:
|
|
|
- print()
|
|
|
- print()
|
|
|
- print("==== parsing config file ====")
|
|
|
- print()
|
|
|
- print(devdata)
|
|
|
- print()
|
|
|
+ log_write("")
|
|
|
+ log_write("")
|
|
|
+ log_write("==== parsing config file ====")
|
|
|
+ log_write("")
|
|
|
+ log_write(devdata)
|
|
|
+ log_write("")
|
|
|
|
|
|
for deviceid in devdata:
|
|
|
if debug:
|
|
|
- print()
|
|
|
- print()
|
|
|
- print("Device: " + deviceid)
|
|
|
- print(devdata[deviceid])
|
|
|
+ log_write("")
|
|
|
+ log_write("")
|
|
|
+ log_write("Device: " + deviceid)
|
|
|
+ log_write(devdata[deviceid])
|
|
|
|
|
|
if "RX" in devdata[deviceid].keys():
|
|
|
if devdata[deviceid]["RX"] != "":
|
|
|
if debug:
|
|
|
- print("RX codes:")
|
|
|
+ log_write("RX codes:")
|
|
|
for key, value in devdata[deviceid]["RX"].items():
|
|
|
if debug:
|
|
|
- print(key, "->", value)
|
|
|
+ log_write(key, "->", value)
|
|
|
if value in RXcodesToDevFunction.keys():
|
|
|
- print()
|
|
|
- print()
|
|
|
- print("ERROR: RX-string '" + str(value) + "' is already defined for another device! Must be unique.")
|
|
|
+ log_write("")
|
|
|
+ log_write("")
|
|
|
+ log_write("ERROR: RX-string '" + str(value) + "' is already defined for another device! Must be unique.")
|
|
|
raise
|
|
|
else:
|
|
|
RXcodesToDevFunction[value] = deviceid, key
|
|
@@ -125,43 +175,43 @@ try:
|
|
|
if devdata[deviceid]["cmdTopic"] != "":
|
|
|
cmdTopic = devdata[deviceid]["cmdTopic"]
|
|
|
if debug:
|
|
|
- print("cmdTopic: " + cmdTopic)
|
|
|
+ log_write("cmdTopic: " + cmdTopic)
|
|
|
if cmdTopic in InTopicsToDevIds.keys():
|
|
|
- print()
|
|
|
- print()
|
|
|
- print("ERROR: cmdTopic '" + str(cmdTopic) + "' is already defined for another device! Must be unique.")
|
|
|
+ log_write("")
|
|
|
+ log_write("")
|
|
|
+ log_write("ERROR: cmdTopic '" + str(cmdTopic) + "' is already defined for another device! Must be unique.")
|
|
|
raise
|
|
|
else:
|
|
|
InTopicsToDevIds[cmdTopic] = deviceid
|
|
|
|
|
|
if debug:
|
|
|
- print()
|
|
|
- print()
|
|
|
- print()
|
|
|
- print("RXcodesToDevFunction:")
|
|
|
- print(RXcodesToDevFunction)
|
|
|
- print()
|
|
|
- print()
|
|
|
- print("InTopicsToDevIds:")
|
|
|
- print(InTopicsToDevIds)
|
|
|
- print()
|
|
|
- print()
|
|
|
- print("InTopicsToDevIds.keys():")
|
|
|
- print(InTopicsToDevIds.keys())
|
|
|
- print()
|
|
|
- print()
|
|
|
- print("==== parsing config file complete ====")
|
|
|
- print()
|
|
|
- print()
|
|
|
- print()
|
|
|
- print()
|
|
|
+ log_write("")
|
|
|
+ log_write("")
|
|
|
+ log_write("")
|
|
|
+ log_write("RXcodesToDevFunction:")
|
|
|
+ log_write(RXcodesToDevFunction)
|
|
|
+ log_write("")
|
|
|
+ log_write("")
|
|
|
+ log_write("InTopicsToDevIds:")
|
|
|
+ log_write(InTopicsToDevIds)
|
|
|
+ log_write("")
|
|
|
+ log_write("")
|
|
|
+ log_write("InTopicsToDevIds.keys():")
|
|
|
+ log_write(InTopicsToDevIds.keys())
|
|
|
+ log_write("")
|
|
|
+ log_write("")
|
|
|
+ log_write("==== parsing config file complete ====")
|
|
|
+ log_write("")
|
|
|
+ log_write("")
|
|
|
+ log_write("")
|
|
|
+ log_write("")
|
|
|
|
|
|
except ConstructorError as err:
|
|
|
- print("ERROR on parsing configfile:")
|
|
|
- print(err)
|
|
|
+ log_write("ERROR on parsing configfile:")
|
|
|
+ log_write(err)
|
|
|
exit(1)
|
|
|
except:
|
|
|
- print("ERROR opening configfile")
|
|
|
+ log_write("ERROR opening configfile")
|
|
|
exit(1)
|
|
|
|
|
|
|
|
@@ -198,7 +248,7 @@ def touch(fname, times=None):
|
|
|
|
|
|
def on_connect(client, userdata, flags, rc):
|
|
|
if verbose:
|
|
|
- print("MQTT connected with result code " + str(rc))
|
|
|
+ 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)
|
|
@@ -206,21 +256,22 @@ def on_connect(client, userdata, flags, rc):
|
|
|
for in_topic in InTopicsToDevIds.keys():
|
|
|
if in_topic != "":
|
|
|
client.subscribe(in_topic)
|
|
|
- print("MQTT subscribed: " + in_topic)
|
|
|
+ if verbose:
|
|
|
+ log_write("MQTT subscribed: " + in_topic)
|
|
|
|
|
|
def on_disconnect(client, userdata, rc):
|
|
|
if rc != 0:
|
|
|
- print("Unexpected MQTT disconnection. Will auto-reconnect")
|
|
|
+ log_write("Unexpected MQTT disconnection. Will auto-reconnect")
|
|
|
|
|
|
def on_message(client, userdata, msg):
|
|
|
|
|
|
|
|
|
payload = msg.payload.decode("utf-8")
|
|
|
- print(msg.topic + ": " + str(payload))
|
|
|
-
|
|
|
|
|
|
+ if verbose:
|
|
|
+ log_write("MQTT received: " + msg.topic + " -> " + str(payload))
|
|
|
|
|
|
-
|
|
|
+
|
|
|
|
|
|
|
|
|
|
|
@@ -229,31 +280,33 @@ def on_message(client, userdata, msg):
|
|
|
|
|
|
if receive_from_mqtt_cul and msg.topic == mqtt_topic_cul_received:
|
|
|
payload = payload.rstrip()
|
|
|
- print("MQTT-CUL RX: '" + payload + "'")
|
|
|
- cul_received(payload)
|
|
|
+ if verbose:
|
|
|
+ log_write("")
|
|
|
+ log_write("MQTT-CUL RX: '" + payload + "'")
|
|
|
+ cul_received(payload, "MQTT")
|
|
|
|
|
|
else:
|
|
|
for in_topic, dev in InTopicsToDevIds.items():
|
|
|
if msg.topic == in_topic:
|
|
|
- print()
|
|
|
- print("MQTT command received - Topic: '" + msg.topic + "', Payload: '" + payload + " -> Device: '" + dev + "'")
|
|
|
+
|
|
|
+ log_write("MQTT received - '" + msg.topic + "' = '" + payload + "' => DEV: " + dev)
|
|
|
|
|
|
|
|
|
if 'name' in devdata[dev].keys():
|
|
|
- print('Device Name: ' + devdata[dev]['name'])
|
|
|
+ log_write('devName: ' + devdata[dev]['name'])
|
|
|
|
|
|
if 'statTopic' in devdata[dev].keys():
|
|
|
- print('statTopic: ' + devdata[dev]['statTopic'])
|
|
|
-
|
|
|
+ log_write('statTopic: ' + devdata[dev]['statTopic'])
|
|
|
+ mqttc.publish(devdata[dev]['statTopic'], payload, qos=0, retain=False)
|
|
|
|
|
|
if 'add_statTopics_on' in devdata[dev].keys():
|
|
|
- print("add_statTopics_on:")
|
|
|
+ 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'] != "":
|
|
|
- print(" on '" + payload + "' -> publish '" + res['payload'] + "' on topic '" + res['topic'] + "'")
|
|
|
-
|
|
|
+ log_write(" on '" + payload + "': '" + res['payload'] + "' => '" + res['topic'] + "'")
|
|
|
+ mqttc.publish(res[topic], res[payload], qos=0, retain=False)
|
|
|
|
|
|
|
|
|
|
|
@@ -264,9 +317,11 @@ def on_message(client, userdata, msg):
|
|
|
|
|
|
global lastSentDev, lastSentDevCmd, lastSentCmdTime
|
|
|
now = int(round(time.time() * 1000))
|
|
|
- print("dev="+dev+", lastSentDevCmd="+lastSentDevCmd)
|
|
|
+ if debug:
|
|
|
+ log_write("dev="+dev+", lastSentDevCmd="+lastSentDevCmd)
|
|
|
if dev == lastSentDev and payload == lastSentDevCmd and (now - lastSentCmdTime) < 1000:
|
|
|
- print("MQTT: ignored command as we just sent this.")
|
|
|
+ if verbose:
|
|
|
+ log_write("MQTT: ignored command as we just sent this.")
|
|
|
pass
|
|
|
else:
|
|
|
cul_send(dev, payload)
|
|
@@ -283,35 +338,176 @@ def on_message(client, userdata, msg):
|
|
|
|
|
|
|
|
|
def publish_device_statusupdate(device, cmd):
|
|
|
- if 'statTopic' in devdata[device].keys():
|
|
|
- statTopic = devdata[device]['statTopic']
|
|
|
- print("MQTT publish statTopic: " + statTopic + " -> " + cmd)
|
|
|
- mqttc.publish(statTopic, cmd, qos=0, retain=False)
|
|
|
-
|
|
|
- if 'add_statTopics_on' in devdata[device].keys():
|
|
|
- print(" MQTT publish add_statTopics_on:")
|
|
|
- for res in devdata[device]['add_statTopics_on']:
|
|
|
-
|
|
|
- if 'on_payload' in res and 'topic' in res and 'payload' in res:
|
|
|
- if cmd == res['on_payload']:
|
|
|
- print(" 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():
|
|
|
- print(" MQTT publish on add_statTopics:")
|
|
|
- for res in devdata[device]['add_statTopics']:
|
|
|
- print(" '" + cmd + "' -> '" + res + "'")
|
|
|
- mqttc.publish(res, cmd, qos=0, retain=False)
|
|
|
+ if device in devdata.keys():
|
|
|
+ if 'statTopic' in devdata[device].keys():
|
|
|
+ statTopic = devdata[device]['statTopic']
|
|
|
+ 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 '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'] + "'")
|
|
|
+ mqttc.publish(res['topic'], res['payload'], qos=0, retain=False)
|
|
|
+
|
|
|
+ if 'add_statTopics' in devdata[device].keys():
|
|
|
+ log_write(" MQTT publish on add_statTopics:")
|
|
|
+ for res in devdata[device]['add_statTopics']:
|
|
|
+ log_write(" '" + cmd + "' -> '" + res + "'")
|
|
|
+ mqttc.publish(res, cmd, qos=0, retain=False)
|
|
|
|
|
|
-def parseRXCode(rx_code):
|
|
|
+
|
|
|
+
|
|
|
+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]
|
|
|
- print("receivedForDevice = " + receivedForDevice + ", receivedCmnd = " + receivedCmnd)
|
|
|
+
|
|
|
+
|
|
|
+ log_write("")
|
|
|
+ log_write("CUL '" + source_cul + "' received '" + rx_code + "' => DEV: " + receivedForDevice + ", CMD: " + receivedCmnd)
|
|
|
+ else:
|
|
|
+ if rx_code.startswith("i"):
|
|
|
+ receivedForDevice, receivedCmnd = decodeInterTechnoRX(rx_code)
|
|
|
+ print(receivedForDevice, receivedCmnd)
|
|
|
+
|
|
|
+ if receivedForDevice != None and receivedCmnd != None:
|
|
|
publish_device_statusupdate(receivedForDevice, receivedCmnd)
|
|
|
+
|
|
|
+def decodeInterTechnoRX(rx_code):
|
|
|
+
|
|
|
+ _housecode = None
|
|
|
+ _devaddr = None
|
|
|
+ _command = None
|
|
|
+ _itname = None
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
|
|
|
-def cul_received(payload):
|
|
|
+ if rx_code[0:1] == "i":
|
|
|
+ if rx_code[1:3] == "00": _housecode = "A"
|
|
|
+ elif rx_code[1:3] == "40": _housecode = "B"
|
|
|
+ elif rx_code[1:3] == "10": _housecode = "C"
|
|
|
+ elif rx_code[1:3] == "50": _housecode = "D"
|
|
|
+ elif rx_code[1:3] == "04": _housecode = "E"
|
|
|
+ elif rx_code[1:3] == "44": _housecode = "F"
|
|
|
+ elif rx_code[1:3] == "14": _housecode = "G"
|
|
|
+ elif rx_code[1:3] == "54": _housecode = "H"
|
|
|
+ elif rx_code[1:3] == "01": _housecode = "I"
|
|
|
+ elif rx_code[1:3] == "41": _housecode = "J"
|
|
|
+ elif rx_code[1:3] == "11": _housecode = "K"
|
|
|
+ elif rx_code[1:3] == "51": _housecode = "L"
|
|
|
+ elif rx_code[1:3] == "05": _housecode = "M"
|
|
|
+ elif rx_code[1:3] == "45": _housecode = "N"
|
|
|
+ elif rx_code[1:3] == "15": _housecode = "O"
|
|
|
+ elif rx_code[1:3] == "55": _housecode = "P"
|
|
|
+
|
|
|
+ if rx_code[3:5] == "00": _devaddr = "1"
|
|
|
+ elif rx_code[3:5] == "40": _devaddr = "2"
|
|
|
+ elif rx_code[3:5] == "10": _devaddr = "3"
|
|
|
+ elif rx_code[3:5] == "50": _devaddr = "4"
|
|
|
+ elif rx_code[3:5] == "04": _devaddr = "5"
|
|
|
+ elif rx_code[3:5] == "44": _devaddr = "6"
|
|
|
+ elif rx_code[3:5] == "14": _devaddr = "7"
|
|
|
+ elif rx_code[3:5] == "54": _devaddr = "8"
|
|
|
+ elif rx_code[3:5] == "01": _devaddr = "9"
|
|
|
+ elif rx_code[3:5] == "41": _devaddr = "10"
|
|
|
+ elif rx_code[3:5] == "11": _devaddr = "11"
|
|
|
+ elif rx_code[3:5] == "51": _devaddr = "12"
|
|
|
+ elif rx_code[3:5] == "05": _devaddr = "13"
|
|
|
+ elif rx_code[3:5] == "45": _devaddr = "14"
|
|
|
+ elif rx_code[3:5] == "15": _devaddr = "15"
|
|
|
+ elif rx_code[3:5] == "55": _devaddr = "16"
|
|
|
+
|
|
|
+ if rx_code[5:7] == "15": _command = "ON"
|
|
|
+ elif rx_code[5:7] == "14": _command = "OFF"
|
|
|
+
|
|
|
+ if _housecode != None and _devaddr != None and _command != None:
|
|
|
+ _itname = "IT_" + _housecode + _devaddr
|
|
|
+
|
|
|
+ return _itname, _command
|
|
|
+
|
|
|
+ else:
|
|
|
+ return False
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+def encodeInterTechnoRX(itname, cmd):
|
|
|
+
|
|
|
+ _housecode = None
|
|
|
+ _devaddr = None
|
|
|
+ _command = None
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if itname[0:3] == "IT_":
|
|
|
+ if itname[3:4] == "A": _housecode = "00"
|
|
|
+ elif itname[3:4] == "B": _housecode = "40"
|
|
|
+ elif itname[3:4] == "C": _housecode = "10"
|
|
|
+ elif itname[3:4] == "D": _housecode = "50"
|
|
|
+ elif itname[3:4] == "E": _housecode = "04"
|
|
|
+ elif itname[3:4] == "F": _housecode = "44"
|
|
|
+ elif itname[3:4] == "G": _housecode = "14"
|
|
|
+ elif itname[3:4] == "H": _housecode = "54"
|
|
|
+ elif itname[3:4] == "I": _housecode = "01"
|
|
|
+ elif itname[3:4] == "J": _housecode = "41"
|
|
|
+ elif itname[3:4] == "K": _housecode = "11"
|
|
|
+ elif itname[3:4] == "L": _housecode = "51"
|
|
|
+ elif itname[3:4] == "M": _housecode = "05"
|
|
|
+ elif itname[3:4] == "N": _housecode = "45"
|
|
|
+ elif itname[3:4] == "O": _housecode = "15"
|
|
|
+ elif itname[3:4] == "P": _housecode = "55"
|
|
|
+
|
|
|
+ if itname[4:] == "1": _devaddr = "00"
|
|
|
+ elif itname[4:] == "2": _devaddr = "40"
|
|
|
+ elif itname[4:] == "3": _devaddr = "10"
|
|
|
+ elif itname[4:] == "4": _devaddr = "50"
|
|
|
+ elif itname[4:] == "5": _devaddr = "04"
|
|
|
+ elif itname[4:] == "6": _devaddr = "44"
|
|
|
+ elif itname[4:] == "7": _devaddr = "14"
|
|
|
+ elif itname[4:] == "8": _devaddr = "54"
|
|
|
+ elif itname[4:] == "9": _devaddr = "01"
|
|
|
+ elif itname[4:] == "10": _devaddr = "41"
|
|
|
+ elif itname[4:] == "11": _devaddr = "11"
|
|
|
+ elif itname[4:] == "12": _devaddr = "51"
|
|
|
+ elif itname[4:] == "13": _devaddr = "05"
|
|
|
+ elif itname[4:] == "14": _devaddr = "45"
|
|
|
+ elif itname[4:] == "15": _devaddr = "15"
|
|
|
+ elif itname[4:] == "16": _devaddr = "55"
|
|
|
+
|
|
|
+ if cmd == "ON": _command = "15"
|
|
|
+ elif cmd == "OFF": _command = "14"
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if _housecode != None and _devaddr != None and _command != None:
|
|
|
+ _rxcode = "i" + _housecode + _devaddr + _command
|
|
|
+
|
|
|
+ return _rxcode
|
|
|
+
|
|
|
+ else:
|
|
|
+ return False
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+def cul_received(payload, source_cul):
|
|
|
|
|
|
global lastReceivedTime, lastReceivedIndex, lastReceivedMaxAge
|
|
|
|
|
@@ -323,7 +519,8 @@ def cul_received(payload):
|
|
|
|
|
|
elif payload[:1] == 'i':
|
|
|
inCmd = payload[:-2]
|
|
|
- print("inCmd: " + inCmd)
|
|
|
+ if verbose:
|
|
|
+ log_write("inCmd: " + inCmd + ", CUL: " + source_cul)
|
|
|
|
|
|
|
|
|
ignoreCommand = False
|
|
@@ -337,7 +534,7 @@ def cul_received(payload):
|
|
|
tdelta = (now - lastTime)
|
|
|
|
|
|
if tdelta < lastReceivedMaxAge:
|
|
|
- print("ignoring received command '" + inCmd + "' - already received " + str(tdelta) + " ms ago")
|
|
|
+ log_write("ignoring command from CUL '" + source_cul + "', CMD: '" + inCmd + "' - already received " + str(tdelta) + " ms ago")
|
|
|
ignoreCommand = True
|
|
|
|
|
|
i += 1
|
|
@@ -350,7 +547,7 @@ def cul_received(payload):
|
|
|
else:
|
|
|
lastReceivedIndex += 1
|
|
|
|
|
|
- parseRXCode(inCmd)
|
|
|
+ parseRXCode(inCmd, source_cul)
|
|
|
|
|
|
|
|
|
|
|
@@ -412,7 +609,7 @@ def IT_RXtoTXCode(itReceiveCode):
|
|
|
statusstr += " -> TX: "
|
|
|
statusstr += itTransmitTristate
|
|
|
|
|
|
- print(statusstr)
|
|
|
+ log_write(statusstr)
|
|
|
|
|
|
return(itTransmitTristate)
|
|
|
|
|
@@ -439,19 +636,28 @@ def cul_send(device, cmd):
|
|
|
|
|
|
if cmd in devdata[device]['TX']:
|
|
|
tx_code = devdata[device]['TX'][cmd]
|
|
|
- print(" TX code for '" + cmd + "': " + tx_code)
|
|
|
+ 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']:
|
|
|
rx_code = devdata[device]['RX'][cmd]
|
|
|
-
|
|
|
+ print(" RX code for '" + cmd + "': " + rx_code)
|
|
|
+ tx_code = IT_RXtoTXCode(rx_code)
|
|
|
+ log_write(" TX code for '" + cmd + "': " + tx_code)
|
|
|
+ elif device.startswith("IT_"):
|
|
|
+
|
|
|
+ rx_code = encodeInterTechnoRX(device, cmd)
|
|
|
+ if rx_code:
|
|
|
+ print(" RX code for '" + cmd + "': " + rx_code)
|
|
|
tx_code = IT_RXtoTXCode(rx_code)
|
|
|
- print(" TX code for '" + cmd + "': " + tx_code)
|
|
|
+ log_write(" TX code for '" + cmd + "': " + tx_code)
|
|
|
+
|
|
|
if not tx_code:
|
|
|
- print(" no valid TX code for this device/command")
|
|
|
+ log_write(" no valid TX code for this device/command")
|
|
|
else:
|
|
|
now = int(round(time.time() * 1000))
|
|
|
|
|
@@ -462,14 +668,14 @@ def cul_send(device, cmd):
|
|
|
lastTime = 0
|
|
|
|
|
|
lastTimeAge = now - lastTime
|
|
|
- print(' lastTime: ' + str(lastTimeAge) + 'ms ago')
|
|
|
+ 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():
|
|
|
- print(" TX_interface: " + devdata[device]['TX_interface'])
|
|
|
+ log_write(" TX_interface: " + devdata[device]['TX_interface'])
|
|
|
|
|
|
if TX_interface == "UART" and not serialCULAvailable:
|
|
|
TX_interface = "MQTT"
|
|
@@ -481,34 +687,38 @@ def cul_send(device, cmd):
|
|
|
lastSentDevCmd = cmd
|
|
|
|
|
|
if send_on_mqtt_cul and (TX_interface == "MQTT" or TX_interface == "both"):
|
|
|
- print(" TX via MQTT: " + tx_code)
|
|
|
+ log_write(" TX via MQTT: " + tx_code)
|
|
|
mqttc.publish(mqtt_topic_cul_send, tx_code, qos=0, retain=False)
|
|
|
|
|
|
if serialCULAvailable and send_on_serial_cul and (TX_interface == "UART" or TX_interface == "both"):
|
|
|
- print(" TX via UART: " + tx_code)
|
|
|
+ log_write(" TX via UART: " + tx_code)
|
|
|
culCmd = tx_code + '\r\n'
|
|
|
ser.write(culCmd.encode('utf-8'))
|
|
|
|
|
|
else:
|
|
|
- print("WARNING: CUL send command repeated too quickly.")
|
|
|
+ log_write("WARNING: CUL send command repeated too quickly.")
|
|
|
|
|
|
|
|
|
+
|
|
|
+
|
|
|
if receive_from_serial_cul or send_on_serial_cul:
|
|
|
if not os.path.exists(serialPort):
|
|
|
- print("ERROR opening connection to serial CUL... device '" + serialPort + "' does not exist.")
|
|
|
+ log_write("ERROR opening connection to serial CUL... device '" + serialPort + "' does not exist.")
|
|
|
+ if log_enable: writeLog("CUL2MQTT v"+version+" starting")
|
|
|
+
|
|
|
if receive_from_mqtt_cul:
|
|
|
if forceSerialCULConnected:
|
|
|
exit(2)
|
|
|
else:
|
|
|
- print("resuming in MQTT-CUL only mode...")
|
|
|
+ log_write("resuming in MQTT-CUL only mode...")
|
|
|
TX_interface_prefer = "MQTT"
|
|
|
receive_from_serial_cul = False
|
|
|
send_on_serial_cul = False
|
|
|
serialCULAvailable = False
|
|
|
- print()
|
|
|
- print()
|
|
|
+ log_write("")
|
|
|
+ log_write("")
|
|
|
else:
|
|
|
- print("opening connection to 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)
|
|
@@ -516,14 +726,14 @@ if receive_from_serial_cul or send_on_serial_cul:
|
|
|
serLine = ser.readline()
|
|
|
serLine = serLine.decode('utf-8').rstrip('\r\n')
|
|
|
if serLine.startswith("V ") and serLine.find("culfw") != -1:
|
|
|
- print("connected. CUL version: " + serLine)
|
|
|
+ log_write("connected. CUL version: " + serLine)
|
|
|
serialCULAvailable = True
|
|
|
sleep(0.1)
|
|
|
- print('Initializing CUL with command: ' + culInitCmd.rstrip('\r\n'))
|
|
|
+ log_write('Initializing CUL with command: ' + culInitCmd.rstrip('\r\n'))
|
|
|
ser.write(culInitCmd.encode('utf-8'))
|
|
|
sleep(0.5)
|
|
|
else:
|
|
|
- print("WARNING: could not connect serial CUL")
|
|
|
+ log_write("WARNING: could not connect serial CUL")
|
|
|
receive_from_serial_cul = False
|
|
|
send_on_serial_cul = False
|
|
|
serialCULAvailable = False
|
|
@@ -556,9 +766,10 @@ while True:
|
|
|
if recvCmd == lastSentCmd and (now - lastSentCmdTime) < filterSelfSentIncomingTimeout:
|
|
|
pass
|
|
|
else:
|
|
|
- print()
|
|
|
- print("Serial-CUL RX: '" + recvCmd + "'")
|
|
|
- cul_received(recvCmd)
|
|
|
+ if verbose:
|
|
|
+ log_write("")
|
|
|
+ log_write("Serial-CUL RX: '" + recvCmd + "'")
|
|
|
+ cul_received(recvCmd, "UART")
|
|
|
|
|
|
sleep(0.05)
|
|
|
|