script Python pour téléinfo standard

Forum dédié aux problématiques concernant les scripts pour DomoticZ.
Entourez votre code et les logs avec les balises nommées code grâce au bouton <\>.
Répondre
knasson
Messages : 120
Enregistré le : 26 mars 2021, 08:59

script Python pour téléinfo standard

Message par knasson »

bonsoir,
j'essaie d'adapter un script python ecrit pour Jeedom dans Domoticz, dont voici le code
le script tourne bien il récupère les valeurs mais rien ne rentre dans la base domoticz...Une idée? (J 'ai un doute sur le paramétrage de l'url de push vers domoticz)

Code : Tout sélectionner

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# __author__ = "Jordan Martin"
# __licence__ = "Apache License 2.0"

import serial
import logging
import subprocess
import requests
logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s')
# Port serial
stty_port = '/dev/ttyUSB0'
# URL de push vers Jeedom --->Domoticz
base_url = 'http://192.168.1.38:8080/json.htm?type=command&param=udevice&idx=9&nvalue=0&svalue=value{}'
# Clé à récupéré et id de l'info dans Jeedom
measure_keys = ['EAIT','SINSTI']
def main():
    logging.info('Starting...')
    # Reconfigure le port serial pour eviter
    # l'erreur: termios.error: (22, 'Invalid argument')
    logging.info('Reconfigure stty %s' % stty_port)
    subprocess.call(['stty', '-F',  stty_port, 'iexten'])
    with serial.Serial(port=stty_port, baudrate=9600, parity=serial.PARITY_EVEN, stopbits=serial.STOPBITS_ONE,
                       bytesize=serial.SEVENBITS, timeout=1) as ser:
        logging.info('Reading on %s' % stty_port)
        while True:
            line = ser.readline()
            arr = line.decode('ascii').split('\t')
            if len(arr) != 3:
                continue
            send_measure(arr)
def send_measure(arr):
    key = arr[0]
    if key not in measure_keys:
        return False
    if not verify_checksum(arr):
        logging.warn('checksum failure for %s' % key)
        return False
    value = int(arr[1])
#    cmd_id = measure_keys.get(key)
    url = base_url.format(value)
    logging.info('%s => %s' % (key, value))
    x = requests.get(url);
    print (x.status_code)
    return True
def verify_checksum(arr):
    tag = arr[0]
    data = arr[1]
    checksum = arr[2].replace('\r\n', '')
    checked_data = [ord(c) for c in (tag + '\t' + data + '\t')]
    computed_sum = (sum(checked_data) & 0x3F) + 0x20
    return checksum == chr(computed_sum)
if __name__ == '__main__':
    main()           

denis_brasseur
Messages : 778
Enregistré le : 24 déc. 2018, 17:05
Localisation : (26)

Re: script Python pour téléinfo standard

Message par denis_brasseur »

Bonjour knasson.

Que donne ceci, à partir de la ligne 43 ?

Code : Tout sélectionner

    # url = base_url.format(value)
    logging.info('%s => %s' % (key, value))
    # x = requests.get(url);
    # à remplacer par
    x = requests.get("http://192.168.1.38:8080/json.htm?type=command&param=udevice&idx=9&nvalue=0&svalue="+value)
Pi3 + DD PiDrive + RFXtrx433 + AEON Labs ZW090
Modules fil pilote ZMNHJD1
Détecteurs fumées Smart Smoke Sensor HS1SA-Z+
Capteurs thermo/hygro Bresser
Chauffe Eau Atlantic LINEO
OWL Micro+ CM180
D2L LINKY
FGR-223 "Roller Shutter 3"

knasson
Messages : 120
Enregistré le : 26 mars 2021, 08:59

Re: script Python pour téléinfo standard

Message par knasson »

Merci Denis pour ton aide
voici la reponse:

Code : Tout sélectionner

root@raspberrypi:/home/kan/domoticz/scripts/python/linky-teleinfo# python3 teleinfo.py
2021-04-24 07:21:21,413 Starting...
2021-04-24 07:21:21,413 Reconfigure stty /dev/ttyUSB0
2021-04-24 07:21:21,435 Reading on /dev/ttyUSB0
2021-04-24 07:21:22,513 EAIT => 4255624
Traceback (most recent call last):
  File "teleinfo.py", line 76, in <module>
    main()
  File "teleinfo.py", line 44, in main
    send_measure(arr)
  File "teleinfo.py", line 61, in send_measure
    x=requests.get("http://192.168.1.38:8080/json.htm?type=command&param=udevice&idx=9&nvalue=0&svalue="+value
TypeError: can only concatenate str (not "int") to str
apparemment il n'aime la concatenation avec un entier! j'ai remplacé "value" par str (value) là je n'ai plus d'erreur mais toujours pas d'entrée dans domoticz.db

Keros
Messages : 4113
Enregistré le : 23 juil. 2019, 20:57

Re: script Python pour téléinfo standard

Message par Keros »

Est-ce que tu as essayé la ligne d'envoi sans paramètres (avec seulement du texte) ? Ca permettrait de déboguer et savoir si le problème est dans la fonction d'envoi ou si c'est le calcul de l'URL qui n'ai pas bon.

knasson
Messages : 120
Enregistré le : 26 mars 2021, 08:59

Re: script Python pour téléinfo standard

Message par knasson »

regardes dans le debug que j'ai tout parait normal...

Code : Tout sélectionner

root@raspberrypi:/home/kan/domoticz/scripts/python/linky-teleinfo# python3 teleinfo.py
2021-04-24 09:19:29,148 Starting...
2021-04-24 09:19:29,148 Reconfigure stty /dev/ttyUSB0
2021-04-24 09:19:29,171 Reading on /dev/ttyUSB0
2021-04-24 09:19:29,539 SINSTI => 325
{
        "status" : "OK",
        "title" : "Update Device"
}

2021-04-24 09:19:30,955 EAIT => 4255898
{
        "status" : "OK",
        "title" : "Update Device"
}

teleinfo.py:54: DeprecationWarning: The 'warn' function is deprecated, use 'warning' instead
  logging.warn('checksum failure for %s' % key)
2021-04-24 09:19:31,418 checksum failure for SINSTI
2021-04-24 09:19:32,824 EAIT => 4255899
{
        "status" : "OK",
        "title" : "Update Device"
}

2021-04-24 09:19:34,687 checksum failure for EAIT
2021-04-24 09:19:35,148 SINSTI => 323
{
        "status" : "OK",
        "title" : "Update Device"
}

knasson
Messages : 120
Enregistré le : 26 mars 2021, 08:59

Re: script Python pour téléinfo standard

Message par knasson »

J'ai compris d'où vient le problème....
la commande JSON de ce compteur attend 2 valeurs...or je n'en envoie qu'une...si je simule l'envoie d'une seconde valeur
(0)en ecrivant:

Code : Tout sélectionner

 x=requests.get("http://192.168.1.38:8080/json.htm?type=command&param=udevice&idx=9&nvalue=0&svalue="+str(value)+";0")
ca marche..je retrouve bien les valeurs dans la base (quand c'est l'heure voir iciviewtopic.php?p=95245#p95245)

knasson
Messages : 120
Enregistré le : 26 mars 2021, 08:59

Re: script Python pour téléinfo standard

Message par knasson »

bonsoir,

pour ceux qui sont intéressés voici le le script python pour la "teleinfo standard" dont le plugin n'existe pas encore dans domoticz, utilisable sur raspberrypi 4 et interface ch2i usb. Le tout est raccordé a un Linky de producteur solaire (en revente totale=pas d'autoconsommation).
l'avantage de ce script par rapport a celui de js-martin dont il est question par ailleurs dans ce forum, est qu'il garanti l'intégrité de la valeur du compteur. Plus de passages a zéro intempestifs qui causaient du bazard dans les données.

Code : Tout sélectionner

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# __author__ = "Jordan Martin"
# __licence__ = "Apache License 2.0"

import serial
import logging
import subprocess
import requests


logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s')

# Port serial
stty_port = '/dev/ttyUSB0'

# URL de push vers Jeedom
#base_url = 'https://<JEEDOM_HOST>/core/api/jeeApi.php?plugin=virtual&apikey=<API_KEY>&type=virtual&id={}&value={}'

 # Clé à récupérer et id de l'info dans Jeedom (pas necessaire dans domoticz)
measure_keys = ['EAIT','SINSTI']
measures=[0,0]
def main():
    logging.info('Starting...')
    # Reconfigure le port serial pour eviter
    # l'erreur: termios.error: (22, 'Invalid argument')
    logging.info('Reconfigure stty %s' % stty_port)
    subprocess.call(['stty', '-F',  stty_port, 'iexten'])
    with serial.Serial(port=stty_port, baudrate=9600, parity=serial.PARITY_EVEN, stopbits=serial.STOPBITS_ONE,
                       bytesize=serial.SEVENBITS, timeout=1) as ser:
        logging.info('Reading on %s' % stty_port)

        while True:
            line = ser.readline()
            arr = line.decode('ascii').split('\t')
            if len(arr) != 3:
                continue

            send_measure(arr)

def send_measure(arr):

    key = arr[0]

    if key not in measure_keys:
            return False

    if not verify_checksum(arr):
#       logging.warn('checksum failure for %s' % key)
        return False
    value = int(arr[1])
    if 'EAIT' in key:
        EAIT = value
        measures[0]=EAIT
    if 'SINSTI' in key:
        SINSTI = value
        measures[1]=SINSTI
#    print ("measures=", measures)

#        on envoie dans la base que lorsque la paire EAIT et SINSTI est non nulle.
    if measures[0] != 0 and measures[1] != 0:
        x=requests.get("http://192.168.1.38:8080/json.htm?type=command&param=udevice&idx=8&nvalue=0&svalue="+str(measures[1])+";"+str(measures[0]))
#       print (x.status_code)
    return True


def verify_checksum(arr):
    tag = arr[0]
     data = arr[1]
    checksum = arr[2].replace('\r\n', '')
    checked_data = [ord(c) for c in (tag + '\t' + data + '\t')]
    computed_sum = (sum(checked_data) & 0x3F) + 0x20
    return checksum == chr(computed_sum)

if __name__ == '__main__':
    main()  
    
et le service correspondant a placer dans systemd/system

Code : Tout sélectionner

[Unit]
Description=Téléinfo standard Linky
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/python3 /home/kan/domoticz/scripts/linky-teleinfo/teleinfo-std.pyw
Restart=on-failure
TimeoutStopSec=1
User=root

[Install]
WantedBy=multi-user.target


Sebastiii
Messages : 2
Enregistré le : 14 oct. 2021, 17:37

Re: script Python pour téléinfo standard

Message par Sebastiii »

Salut knasson,

Merci pour ce script, j'essaye de démêler tout ça, car en ce moment, j'ai un compteur (ancien Sagem) qui fonctionne avec le plugin Teleinfo (TIC) à 1200bauds.

On me propose la MAJ vers le compteur Linky donc j'hésite un peu pour la bascule.
Je suis en CACSI, et je capture les informations de production et conso via ma passerelle, mais effectivement, j'aimerais bien avoir des mesures précise du surplus (si le linky est en mode standard si j'ai bien compris).

Si je le change, je vais être en mode historique, mais dans le cas, on le mode standard peut être appliqué pour l'autoconsommation, avoir de bonnes valeurs peut être pas mal :)

Du coup, ton script python, donnera les memes info que teleinfo mais avec l'injection en plus ?
Sinon Domoticz est installé en docker sur mon NAS synology ;)

Répondre