From 01e61f5eff19c480bf322a974674dffc7a84c6f9 Mon Sep 17 00:00:00 2001 From: Charlymd Date: Wed, 26 Aug 2020 09:06:42 +0200 Subject: [PATCH 1/3] ajout de la fonction de calcul du checksum --- teleinfo.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/teleinfo.py b/teleinfo.py index 87467a7..bb29f5b 100644 --- a/teleinfo.py +++ b/teleinfo.py @@ -73,6 +73,16 @@ def add_measures(measures, time_measure): client.write_points(points) +def calc_checksum(group): + # Calcul le caractere de controle d'une ligne de trame linky + # seule l'etiquette et la donnée de chaque ligne doivent etre envoyés en parametre group + data_unicode = 0 + for data in group: + data_unicode += ord(data) + sum_unicode = (data_unicode & 63) + 32 + sum = chr(sum_unicode) + return sum + def main(): with serial.Serial(port='/dev/ttyS0', baudrate=1200, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, From ebd786e3a3c99ded50265172c6dc00da02478c93 Mon Sep 17 00:00:00 2001 From: Charlymd Date: Fri, 28 Aug 2020 22:43:23 +0200 Subject: [PATCH 2/3] checksum en UTF-8 erreur sur caractere 0x32 --- teleinfo.py | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/teleinfo.py b/teleinfo.py index bb29f5b..ffc83ac 100644 --- a/teleinfo.py +++ b/teleinfo.py @@ -7,11 +7,12 @@ # # Exemple de trame: # { -# 'OPTARIF': 'HC..', # option tarifaire -# 'IMAX': '007', # intensité max -# 'HCHC': '040177099', # index heure creuse en Wh +# 'BASE': '123456789' # Index heure de base en Wh +# 'OPTARIF': 'HC..', # Option tarifaire HC/BASE +# 'IMAX': '007', # Intensité max +# 'HCHC': '040177099', # Index heure creuse en Wh # 'IINST': '005', # Intensité instantanée en A -# 'PAPP': '01289', # puissance Apparente, en VA +# 'PAPP': '01289', # Puissance Apparente, en VA # 'MOTDETAT': '000000', # Mot d'état du compteur # 'HHPHC': 'A', # Horaire Heures Pleines Heures Creuses # 'ISOUSC': '45', # Intensité souscrite en A @@ -29,7 +30,8 @@ from datetime import datetime from influxdb import InfluxDBClient # clés téléinfo -int_measure_keys = ['IMAX', 'HCHC', 'IINST', 'PAPP', 'ISOUSC', 'ADCO', 'HCHP'] +int_measure_keys = ['BASE','IMAX', 'HCHC', 'IINST', 'PAPP', 'ISOUSC', 'ADCO', 'HCHP'] +no_checksum = ['MOTDETAT'] # création du logguer logging.basicConfig(filename='/var/log/teleinfo/releve.log', level=logging.INFO, format='%(asctime)s %(message)s') @@ -61,6 +63,7 @@ def add_measures(measures, time_measure): point = { "measurement": measure, "tags": { + # identification de la sonde et du compteur "host": "raspberry", "region": "linky" }, @@ -102,6 +105,7 @@ def main(): while True: line_str = line.decode("utf-8") + logging.debug(line_str) ar = line_str.split(" ") try: key = ar[0] @@ -109,15 +113,29 @@ def main(): value = int(ar[1]) else: value = ar[1] - - checksum = ar[2] + + # verification de la somme de controle + keyandvalue = ar[0] + " " + ar[1] + checksum = str(ar[2]).rstrip() # suppression saut de ligne + checksum2 = calc_checksum(keyandvalue) + if (checksum2 == checksum or (key in no_checksum)) : + checksum_ok = True + else : + logging.info("Erreur de checksum pour le champ %s" % key) + logging.info("Checksum: %s" % checksum) + logging.info("Calc_checksum: %s" % checksum2) + logging.info("Valeur d'origine: %s" % ar) + checksum_ok = False + trame[key] = value + if b'\x03' in line: # si caractère de fin dans la ligne, on insère la trame dans influx del trame['ADCO'] # adresse du compteur : confidentiel! time_measure = time.time() # insertion dans influxdb - add_measures(trame, time_measure) + if (checksum_ok) : + add_measures(trame, time_measure) # ajout timestamp pour debugger trame["timestamp"] = int(time_measure) @@ -125,7 +143,8 @@ def main(): trame = dict() # on repart sur une nouvelle trame except Exception as e: - logging.error("Exception : %s" % e) + logging.error("Exception : %s" % e, exc_info=True) + logging.error("%s %s" % (key,value)) line = ser.readline() From fbf2010dcabb406d147aa84d6fbb50a9c0b7ca93 Mon Sep 17 00:00:00 2001 From: Charlymd Date: Sat, 29 Aug 2020 16:39:04 +0200 Subject: [PATCH 3/3] correction bug checksum sur caractere 0x32 (espace) --- teleinfo.py | 47 +++++++++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/teleinfo.py b/teleinfo.py index ffc83ac..fcd204a 100644 --- a/teleinfo.py +++ b/teleinfo.py @@ -76,15 +76,17 @@ def add_measures(measures, time_measure): client.write_points(points) -def calc_checksum(group): - # Calcul le caractere de controle d'une ligne de trame linky - # seule l'etiquette et la donnée de chaque ligne doivent etre envoyés en parametre group + +def verif_checksum(data,checksum): data_unicode = 0 - for data in group: - data_unicode += ord(data) + for caractere in data: + data_unicode += ord(caractere) sum_unicode = (data_unicode & 63) + 32 sum = chr(sum_unicode) - return sum + if (checksum == sum): + return True + else: + return False def main(): @@ -105,36 +107,29 @@ def main(): while True: line_str = line.decode("utf-8") - logging.debug(line_str) - ar = line_str.split(" ") + logging.debug(line) + ar = line_str.split(" ") # separation sur espace /!\ attention le caractere de controle 0x32 est un espace aussi + # preparation données pour verification checksum + data = ar[0] + " " + ar[1] + checksum = (line_str.replace('\x03\x02',''))[-3:-2] # supprimer les retours charriot et saut de ligne puis selectionne le caractere de controle en partant de la fin + verif_checksum(data,checksum) + + try: key = ar[0] - if key in int_measure_keys : + if key in int_measure_keys : # typer les valeurs numériques en "integer" value = int(ar[1]) else: - value = ar[1] - - # verification de la somme de controle - keyandvalue = ar[0] + " " + ar[1] - checksum = str(ar[2]).rstrip() # suppression saut de ligne - checksum2 = calc_checksum(keyandvalue) - if (checksum2 == checksum or (key in no_checksum)) : - checksum_ok = True - else : - logging.info("Erreur de checksum pour le champ %s" % key) - logging.info("Checksum: %s" % checksum) - logging.info("Calc_checksum: %s" % checksum2) - logging.info("Valeur d'origine: %s" % ar) - checksum_ok = False - - trame[key] = value + value = ar[1] # typer les autres valeurs en "string" + + trame[key] = value # creation du champ pour la trame en cours if b'\x03' in line: # si caractère de fin dans la ligne, on insère la trame dans influx del trame['ADCO'] # adresse du compteur : confidentiel! time_measure = time.time() # insertion dans influxdb - if (checksum_ok) : + if (verif_checksum) : add_measures(trame, time_measure) # ajout timestamp pour debugger