Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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:

Expand Down Expand Up @@ -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'
Expand Down
8 changes: 7 additions & 1 deletion README_mosquitto.md
Original file line number Diff line number Diff line change
@@ -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é
Expand All @@ -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:

Expand Down Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions mqtt_linky.service
Original file line number Diff line number Diff line change
@@ -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

Expand Down
2 changes: 1 addition & 1 deletion mqtt_linky_listen.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
76 changes: 52 additions & 24 deletions mqtt_linky_read_publish.py
Original file line number Diff line number Diff line change
Expand Up @@ -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={}
"""
Expand All @@ -31,42 +31,70 @@
"""
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)

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)
38 changes: 31 additions & 7 deletions mymqtt.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,44 @@

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():
"""
contains basic MQTT resources
"""
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)
self.log = logging.getLogger(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)

Expand All @@ -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):
Expand Down Expand Up @@ -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
"""
Expand Down
26 changes: 18 additions & 8 deletions teleinfo.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,42 @@
#!/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
if response != "":
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:
Expand All @@ -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)
Expand All @@ -47,6 +56,7 @@
sys.argv.remove(item)
if len(sys.argv) == 1:
break;

except KeyboardInterrupt:
ser.close()

Expand Down