adapté
This commit is contained in:
parent
2dc277e8a4
commit
419d29f5be
121
teleinfo.py
Normal file → Executable file
121
teleinfo.py
Normal file → Executable file
|
@ -4,23 +4,6 @@
|
|||
# __licence__ = "Apache License 2.0"
|
||||
|
||||
# Python 3, prérequis : pip install pySerial influxdb
|
||||
#
|
||||
# Exemple de trame:
|
||||
# {
|
||||
# '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
|
||||
# 'MOTDETAT': '000000', # Mot d'état du compteur
|
||||
# 'HHPHC': 'A', # Horaire Heures Pleines Heures Creuses
|
||||
# 'ISOUSC': '45', # Intensité souscrite en A
|
||||
# 'ADCO': '000000000000', # Adresse du compteur
|
||||
# 'HCHP': '035972694', # index heure pleine en Wh
|
||||
# 'PTEC': 'HP..' # Période tarifaire en cours
|
||||
# }
|
||||
|
||||
|
||||
import logging
|
||||
import time
|
||||
|
@ -30,16 +13,48 @@ import requests
|
|||
import serial
|
||||
from influxdb import InfluxDBClient
|
||||
|
||||
# Nombre de secondes entre deux transmission des mesures
|
||||
DELAY_MESURE = 10
|
||||
|
||||
# clés à utiliser - les autres ne seront pas transmises
|
||||
USED_MESURE_KEYS = [
|
||||
'LTARF',
|
||||
'EAST',
|
||||
'EASF01',
|
||||
'EASF02',
|
||||
'IRMS1',
|
||||
'URMS1',
|
||||
'SINSTS',
|
||||
'SMAXSN',
|
||||
'CCASN',
|
||||
'UMOY1',
|
||||
'MSG1',
|
||||
'NTARF',
|
||||
]
|
||||
|
||||
# clés téléinfo
|
||||
INT_MESURE_KEYS = ['BASE', 'IMAX', 'HCHC', 'IINST', 'PAPP', 'ISOUSC', 'ADCO', 'HCHP']
|
||||
INT_MESURE_KEYS = [
|
||||
'EAST',
|
||||
'EASF',
|
||||
'EASD',
|
||||
'EAIT',
|
||||
'ERQ',
|
||||
'IRMS',
|
||||
'URMS',
|
||||
'PREF',
|
||||
'PCOUP',
|
||||
'SINST',
|
||||
'SMAX',
|
||||
'CCA',
|
||||
'UMOY',
|
||||
]
|
||||
|
||||
# création du logguer
|
||||
logging.basicConfig(filename='/var/log/teleinfo/releve.log', level=logging.INFO, format='%(asctime)s %(message)s')
|
||||
logging.basicConfig(filename='/tmp/teleinfo-releve.log', level=logging.INFO, format='%(asctime)s %(message)s')
|
||||
logging.info("Teleinfo starting..")
|
||||
|
||||
# connexion a la base de données InfluxDB
|
||||
client = InfluxDBClient('localhost', 8086)
|
||||
client = InfluxDBClient('192.168.0.10', 8086)
|
||||
DB_NAME = "teleinfo"
|
||||
connected = False
|
||||
while not connected:
|
||||
|
@ -58,9 +73,9 @@ while not connected:
|
|||
connected = True
|
||||
|
||||
|
||||
def add_measures(measures, time_measure):
|
||||
def add_measures(measures):
|
||||
points = []
|
||||
for measure, value in measures.items():
|
||||
for measure, values in measures.items():
|
||||
point = {
|
||||
"measurement": measure,
|
||||
"tags": {
|
||||
|
@ -69,12 +84,9 @@ def add_measures(measures, time_measure):
|
|||
"region": "linky"
|
||||
},
|
||||
"time": datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ"),
|
||||
"fields": {
|
||||
"value": value
|
||||
}
|
||||
"fields": values
|
||||
}
|
||||
points.append(point)
|
||||
|
||||
client.write_points(points)
|
||||
|
||||
|
||||
|
@ -85,13 +97,13 @@ def verif_checksum(data, checksum):
|
|||
sum_unicode = (data_unicode & 63) + 32
|
||||
return (checksum == chr(sum_unicode))
|
||||
|
||||
def checksum(line:str) -> str:
|
||||
return chr((sum(list(line)) & 0x3F) + 0x20)
|
||||
|
||||
def main():
|
||||
with serial.Serial(port='/dev/ttyS0', baudrate=1200, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE,
|
||||
bytesize=serial.SEVENBITS, timeout=1) as ser:
|
||||
|
||||
logging.info("Teleinfo is reading on /dev/ttyS0..")
|
||||
with serial.Serial(port='/dev/ttyAMA0', baudrate=9600, parity=serial.PARITY_EVEN, bytesize=serial.SEVENBITS, timeout=1) as ser:
|
||||
|
||||
logging.info("Teleinfo is reading on /dev/ttyAMA0..")
|
||||
trame = dict()
|
||||
|
||||
# boucle pour partir sur un début de trame
|
||||
|
@ -99,41 +111,50 @@ def main():
|
|||
while b'\x02' not in line: # recherche du caractère de début de trame
|
||||
line = ser.readline()
|
||||
|
||||
# lecture de la première ligne de la première trame
|
||||
line = ser.readline()
|
||||
|
||||
delaycounter = DELAY_MESURE
|
||||
while True:
|
||||
line_str = line.decode("utf-8")
|
||||
while delaycounter < DELAY_MESURE:
|
||||
ser.read_until(b'\x03')
|
||||
delaycounter+=1
|
||||
line = ser.readline()
|
||||
logging.debug(line)
|
||||
|
||||
try:
|
||||
# separation sur espace /!\ attention le caractere de controle 0x32 est un espace aussi
|
||||
[key, val, *_] = line_str.split(" ")
|
||||
|
||||
# supprimer les retours charriot et saut de ligne puis selectionne le caractere
|
||||
# de controle en partant de la fin
|
||||
checksum = (line_str.replace('\x03\x02', ''))[-3:-2]
|
||||
|
||||
if verif_checksum(f"{key} {val}", checksum):
|
||||
# creation du champ pour la trame en cours avec cast des valeurs de mesure en "integer"
|
||||
trame[key] = int(val) if key in INT_MESURE_KEYS else val
|
||||
|
||||
dataset = line.replace(b'\x03\x02', b'').rstrip(b'\r\n')
|
||||
checksumchar = checksum(dataset[:-1])
|
||||
if checksumchar == chr(dataset[-1]):
|
||||
spline = dataset.split(b'\t')
|
||||
logging.debug(spline)
|
||||
etiquette = spline[0].decode('ascii')
|
||||
if etiquette in USED_MESURE_KEYS:
|
||||
value = spline[1].decode('ascii')
|
||||
timestamp = None
|
||||
if len(spline) == 4 and spline[2] != b'' : # Horodaté
|
||||
value = spline[2].decode('ascii')
|
||||
timestamp = spline[1].decode('ascii')
|
||||
for radix in INT_MESURE_KEYS:
|
||||
if etiquette.startswith(radix):
|
||||
value = int(value)
|
||||
trame[etiquette] = {
|
||||
"value": value,
|
||||
"timestamp": timestamp,
|
||||
}
|
||||
else:
|
||||
logging.debug('Checksum error, aborting frame')
|
||||
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)
|
||||
add_measures(trame)
|
||||
|
||||
# ajout timestamp pour debugger
|
||||
trame["timestamp"] = int(time_measure)
|
||||
logging.debug(trame)
|
||||
|
||||
trame = dict() # on repart sur une nouvelle trame
|
||||
delaycounter=0
|
||||
except Exception as e:
|
||||
logging.error("Exception : %s" % e, exc_info=True)
|
||||
logging.error("%s %s" % (key, val))
|
||||
line = ser.readline()
|
||||
logging.error("%s" % (line))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
Loading…
Reference in a new issue