diff --git a/README.md b/README.md index 0ec2ace..190cc18 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,8 @@ Test en ligne de commande : python teleinfo_ram.py IRMS1 IRMS2 IRMS3 URMS1 URMS A partir de Jeedom : Requete SCRIPT : /var/www/html/plugins/script/core/ressources/teleinfo_ram.py "IRMS1 IRMS2 IRMS3 URMS1 URMS2 URMS3" -## cat_file.php -Utilisé pour lire les fichiers créées par teleinfo_ram.py par Jeedom +## cat_file.php (obsolete: plus de Jeedom) +Utilisé pour lire les fichiers créés par teleinfo_ram.py par Jeedom A partir de Jeedom : 1 Requete SCRIPT par item : /var/www/html/plugins/script/core/ressources/cat_file.php "/var/tmp_ram/IRMS1" @@ -41,7 +41,7 @@ sudo systemctl list-unit-files --type=service | grep mosquitto sudo systemctl status mosquitto.service ``` -modification du service mosquitto pour sauver les logs dans /tmp/mosquitto.log +#### modification du service mosquitto pour sauver les logs dans /tmp/mosquitto.log fichier /etc/mosquitto/mosquitto.conf: @@ -133,6 +133,13 @@ On démarre un client sur tous les topics 'linky' /usr/bin/python3 /home/pi/TeleinfoLinky/mqtt_linky_listen.py ``` +Ce script envoye ses logs vers /home/pi/TeleinfoLinky/mqtt.log, donc on peut le suivre avec: + +```bash +tail -f /home/pi/TeleinfoLinky/mqtt.log +``` + + #### Surveillance des soucis du service `mqtt_linky` Afin d'essayer de comprendre pourquoi le service est parfois arrêté, on lance un client qui surveille le message de 'will' diff --git a/README_mosquitto.md b/README_mosquitto.md index 26e45ab..fb92cb4 100644 --- a/README_mosquitto.md +++ b/README_mosquitto.md @@ -1,5 +1,8 @@ # Installation d'un broker mosquitto en local sur la Pi +* (https://mosquitto.org/man/mosquitto-8.html) +* (https://mosquitto.org/man/mosquitto-conf-5.html) + sudo apt-get install mosquitto > Le broker mosquitto est directement installé et lancé @@ -13,7 +16,7 @@ sudo systemctl status mosquitto.service # Modification du service mosquitto pour sauver les logs dans /tmp/mosquitto.log -> /tmp/mosquitto.log, comme tous les fichiers de log, sera effacèe à chaque reboot de la Pi +> /tmp/mosquitto.log, comme tous les fichiers de log, sera effacé à chaque reboot de la Pi ## Fichier /etc/mosquitto/mosquitto.conf: @@ -42,6 +45,9 @@ sudo systemctl daemon-reload sudo systemctl restart mosquitto.service ``` +* --port: by default the mosquitto broker will listen on port 1883 + + ## Verification du service mosquitto > vérif: diff --git a/mqtt_linky.service b/mqtt_linky.service index 20ed094..cdf2765 100644 --- a/mqtt_linky.service +++ b/mqtt_linky.service @@ -1,5 +1,6 @@ [Unit] Description=Mosquitto client reading UART for Linky and publishing selected items to a local MQTT broker +Requires mosquitto.service After=network.target AssertPathExists=/sys/class/net/eth0 diff --git a/mqtt_linky_listen.py b/mqtt_linky_listen.py index 1246cee..ed10ad4 100644 --- a/mqtt_linky_listen.py +++ b/mqtt_linky_listen.py @@ -14,7 +14,7 @@ from mymqtt import myMqtt from paho.mqtt import client as mqtt_client -broker="PiCuisine" +broker="127.0.0.1" mqttc = myMqtt("linky_listen") mqttc.connect_to(broker) diff --git a/mqtt_linky_read_publish.py b/mqtt_linky_read_publish.py index f1cd316..7756b4b 100644 --- a/mqtt_linky_read_publish.py +++ b/mqtt_linky_read_publish.py @@ -13,13 +13,13 @@ import logging from mymqtt import myMqtt -from paho.mqtt import client as mqtt_client client_id="linky2mqtt" linky_args = ["URMS1", "IRMS1", "URMS2", "IRMS2", "URMS3", "IRMS3"] -broker="127.0.0.1" +#broker="localhost.local" +broker="PiCuisine" port = 1883 -mqttc = myMqtt(client_id) +mqttc = myMqtt(client_id, username="python", password="mymqtt") ymdhms = mqttc.yyyymmddhhmmss() item_values={} """ @@ -31,9 +31,22 @@ """ baudrate=9600 +debug = False +trace = False ser = serial.Serial('/dev/ttyAMA0', baudrate, bytesize=7, timeout=1) ser.isOpen() +item = "trace" +if item in sys.argv: + trace = True + sys.argv.remove(item) + +item = "debug" +if item in sys.argv: + debug = True + trace = True + sys.argv.remove(item) + mqttc.connect_to(broker, port, keepalive=30, publisher=True) mqttc.log.info(f"time/{client_id}/start/loop") mqttc.publish(topic=f"time/{client_id}/start/loop", msg=ymdhms) @@ -41,32 +54,47 @@ for item in linky_args: item_values[item]="" -try: - while True: - response = ser.readline() +while True: + try: + response = ser.readline().decode("utf-8") if response != "": items = response.split() + items = items[:-1] # print "# The line is not empty, let's go on..." splitLen = len(items) if splitLen >= 2: # There are at least 3 items in the line, as expected, let's go on... # The name is the first item # The value is the one-before-last item (in most cases). - item = items[0].decode('utf-8') - value = items[splitLen-2] - if str(item) in linky_args: - if value.isdigit(): - # Remove leading zeros from numerical values - value_int = int(value) - value = str(value_int) - if value != item_values[item]: - item_values[item] = value - mqttc.publish(topic=f"linky/{item}", msg=str(value), retain=False) -except serial.serialutil.SerialException as e: - print(f"\nserial.serialutil.SerialException {e}\n") - mqttc.log.error(f"serial.serialutil.SerialException {e}") - mqttc.publish(topic=f"linky/exception", msg=str(e), retain=True) - time.sleep(30) - exit() -except KeyboardInterrupt: - ser.close() + item = items[0] + value = items[splitLen-1] + if item in linky_args: + # Remove leading zeros from numerical values + value_int = int(value) + value = str(value_int) + if trace: print(f"linky/item/{item:8} {str(value)}", end='\c') + if value != item_values[item]: + item_values[item] = value + res = mqttc.publish(topic=f"linky/item/{item}", msg=str(value), retain=False) + if trace: print(f"linky/item/{item:8} {str(value)}") + else: + if debug: print(" unchanged " + item + " " + str(value)) + except serial.serialutil.SerialException as e: + if "device " in str(e): + if debug: print("passing over " + str(e) +" exception") + pass + else: + if debug: print(f"serial.serialutil.SerialException {e}") + #mqttc.log.error(f"serial.serialutil.SerialException {e}") + #mqttc.publish(topic=f"linky/exception", msg=str(e), retain=True) + #time.sleep(1) + #ser = serial.Serial('/dev/ttyAMA0', baudrate, bytesize=7, timeout=1) + #ser.isOpen() + pass + #ser.close() + #exit() + except ValueError: + pass + except KeyboardInterrupt: + ser.close() + sys.exit(0) diff --git a/mymqtt.py b/mymqtt.py index a34f207..7e70978 100644 --- a/mymqtt.py +++ b/mymqtt.py @@ -10,8 +10,8 @@ log_file = "mqtt.log" -print(f"logging to {log_file}. follow execution using 'tail -f {log_file}'") -logging.basicConfig(filename=log_file, level=logging.DEBUG) +print(f"logging to {log_file}. follow execution using 'tail -f {log_file}' or 'mosquitto_sub --port 1883 --debug --username home --pw assistant --topic linky/item/#'") +logging.basicConfig(filename=log_file, level=logging.INFO) class myMqtt(): """ @@ -19,9 +19,12 @@ class myMqtt(): """ client_id = "" broker = "" + # keep port set to 1883 if using username/password. 8883 forces use of TLS port = 1883 - def __init__(self, client_id): + def __init__(self, client_id, username="python", password="mymqtt"): + self.username = username + self.password = password self.client_id = client_id self.client = mqtt_client.Client(client_id) # print(self.client) @@ -29,11 +32,22 @@ def __init__(self, client_id): #self.log.basic(filename=f"{log_client_id}.txt", encoding='utf-8', level=logging.DEBUG) self.client.enable_logger(self.log) self.log.info(f"init complete") + self.client.username_pw_set(self.username, self.password) def on_connect(self, mqtt_client_id, userdata, flags, rc): ymdhms = self.yyyymmddhhmmss() if rc == 0: self.log.info(f"{ymdhms}: {self.client_id} Connected to MQTT Broker {self.broker}") + elif rc == 1: + self.log.info(f"{ymdhms}: {self.client_id} Connection refused incorrect protocol version {self.broker}") + elif rc == 2: + self.log.info(f"{ymdhms}: {self.client_id} Connection refused invalid client identifier {self.broker}") + elif rc == 3: + self.log.info(f"{ymdhms}: {self.client_id} Connection refused server unavailable {self.broker}") + elif rc == 4: + self.log.info(f"{ymdhms}: {self.client_id} Connection refused bad username or password {self.broker}") + elif rc == 5: + self.log.info(f"{ymdhms}: {self.client_id} Connection refused not authorised {self.broker}") else: self.log.info(f"{ymdhms}: {self.client_id} Failed to connect to MQTT Broker {self.broker}, return code %d\n", rc) @@ -51,15 +65,25 @@ def connect_to(self, broker, port=1883, keepalive=60, publisher=False): ymdhms = self.yyyymmddhhmmss() self.port = port try: - self.client.connect(broker, port, keepalive) + res = self.client.connect(broker, port, keepalive) except Exception as e: - logging.error(f"{e}") + msg = f"******** connect Exception Calling mymqtt.py/connect_to({broker}, {port}, keepalive={keepalive}, publisher=True) {e}" + print(msg) + logging.error(msg) + pass if publisher: """ With paho.mqtt, publishers need to call loop_start() to send regular PINGs """ self.client.loop_start() - self.publish(topic=f"time/{self.client_id}/start", msg=ymdhms) + try: + self.publish(topic=f"time/{self.client_id}/start", msg=ymdhms) + except Exception as e: + msg = f"******** Exception Calling mymqtt.py/connect_to({broker}, {port}, keepalive={keepalive}, publisher=True) {e}" + print(msg) + logging.error(msg) + #pass + self.client.will_set(topic="will/msg", payload=f"{self.client_id}: This is my last will, I'm disconnected without asking for it. I started at {ymdhms}") def disconnect(self): @@ -93,7 +117,7 @@ def publish(self, topic, msg, qos=1, retain=True): if status == 0: self.log.info(f"{self.client_id} > {topic}: {msg}") else: - self.log.info(f"Failed to send message to topic {topic}: result {str(result)}") + self.log.info(f"Failed to publish {topic}: {msg} result {str(result)}, reconnecting") """ In case of publishing errors, reconnect """ diff --git a/teleinfo.py b/teleinfo.py index e0fb2b4..c4f2092 100644 --- a/teleinfo.py +++ b/teleinfo.py @@ -1,22 +1,30 @@ -#!/usr/bin/python +#!/usr/bin/python3 import serial import time import sys -baudrate=9600 +baudrate = 9600 + ser = serial.Serial('/dev/ttyAMA0', baudrate, bytesize=7, timeout=1) ser.isOpen() + count=0 looping = 1 results_table="" +debug = False + +item = "debug" +if item in sys.argv: + debug = True + sys.argv.remove(item) try: -# print "...demarrage du mode standard a "+str(baudrate)+"... " + print("...demarrage du mode standard a "+str(baudrate)+"... ") while looping: - response = ser.readline() + response = ser.readline().decode("utf-8", errors='ignore') localtime = time.asctime( time.localtime(time.time()) ) - # print "count "+str(count) + if debug: print("count " + str(count) + " | ", end='') count = count + 1 if count >= 100: looping = 0 @@ -24,10 +32,11 @@ count = count - 1 # The line is not empty, let's go on... items = response.split() + items = items[:-1] splitLen = len(items) if splitLen >= 2: # There are 3 items in the line, as expected, let's go on... - print str(splitLen)+" items : "+response + if debug: print(str(splitLen) + " items : " + str(items)) item = items[0] value = items[splitLen-2] if item in sys.argv or "all" in sys.argv: @@ -36,8 +45,8 @@ value_int = int(value) value = str(value_int) if not "all" in sys.argv: - print " "+item+" "+value - filename = "/home/pi/teleinfo/"+item + print(" " + item + " " + value) + filename = "/home/pi/teleinfo/" + str(item) file_object = open(filename, 'w') result = localtime + " " + item + " " + value file_object.write(result) @@ -47,6 +56,7 @@ sys.argv.remove(item) if len(sys.argv) == 1: break; + except KeyboardInterrupt: ser.close()