Traduction du registre de statuts STGE du Linky

Bonjour à tous, comme je n’avais plus de suivi de conso sur le site enedis depuis plus d’un mois le service support m’a indiqué que c’était normal car le CPL du compteur n’était pas connecté. Pour connaître ce statut il faut appuyer simultanément sur les boutons + et - du compteur pendant plus de 5 secondes. Je me suis dit que c’était un peu dommage de ne s’intéresser à cette connexion que lorsqu’on s’aperçoit qu’elle ne fonctionne pas et qu’il devait bien y avoir quelque part une info issue de la téléinfo qui pourrait être utilisée. En fouillant un peu j’ai trouvé le registre de statuts dans la doc enedis téléchargeable ici: https://www.enedis.fr/media/2035/download

Problème: comment traduire ce truc et existe t’il qq chose déjà existant qui le permette. Je n’en ai pas trouvé mais j’ai peut être mal cherché. Donc je me suis fait un fichier excel pour traduire ce message, il suffit de mettre le code relevé par la téléinfo dans la cellule B2 au format texte. Le fichier en question, enlever le « .txt » à la fin car les fichier xlsx ne sont pas acceptés:
traduction STGE linky.xlsx.txt (17,6 Ko)

J’ai un petit doute dans le sens des bits reconstitués lorsque l’état en a plusieurs car je n’ai jamais eu de code affiché qui permette de le lever. Si tel était le cas il suffit de les inverser dans les formules de la colonne M.

Ensuite je me suis dite que ce serait bien que cela soit affiché dans jeedom, j’ai donc crée un virtuel avec les 21 champs de statuts + 1 qui reprend le code STGE de la téléinfo + 1 qui indique le dernier changement d’état de ce code + 1 commande pour rafraîchir le script qui remplira ces champs. Ensuite j’ai écrit le script suivant en python (attention, je suis totalement autodidacte alors il y a certainement des choses à faire pour améliorer ça et je suis preneur de toute suggestion):

##!/usr/bin/python
# ##settings

# AUTEUR : Noyax37
 # #SITE : 
 # #VERSION : 1.0
 # #DATE : 2021-10-25

#DEFINITION DE LA SIGNIFICATION DES BITS
#VOIR DOC ENEDIS POUR SIGNIFICATION DE CHAQUE MESSAGE https://www.enedis.fr/media/2035/download
def switch_mot1(argument):
	switcher = {
		0: "Ferme",
		1: "Ouvert",
	}
	return switcher.get(argument, "Invalide")

def switch_mot2(argument):
	switcher = {
		0: "Ferme",
		1: "Ouvert sur surpuissance",
		2: "ouvert sur surtension",
		3: "Ouvert sur delestage",
		4: "Ouvert sur ordre CPL ou Euridis",
		5: "Ouvert sur surchauffe avec I > Imax",
		6: "Ouvert sur surchauffe avec I < Imax",
	}
	return switcher.get(argument, "Invalide")

def switch_mot3(argument):
	switcher = {
		0: "Ferme",
		1: "Ouvert",
	}
	return switcher.get(argument, "Invalide")

def switch_mot4(argument):
	switcher = {
		0: "Toujours a 0",
		1: "Anormal",
	}
	return switcher.get(argument, "Invalide")

def switch_mot5(argument):
	switcher = {
		0: "Pas de surtension",
		1: "Surtension",
	}
	return switcher.get(argument, "Invalide")

def switch_mot6(argument):
	switcher = {
		0: "Pas de depassement",
		1: "Depassement en cours",
	}
	return switcher.get(argument, "Invalide")

def switch_mot7(argument):
	switcher = {
		0: "Consommateur",
		1: "Producteur",
	}
	return switcher.get(argument, "Invalide")

def switch_mot8(argument):
	switcher = {
		0: "Positive",
		1: "Negative",
	}
	return switcher.get(argument, "Invalide")

def switch_mot9(argument):
	switcher = {
		0: "Ventile sur index 1",
		1: "Ventile sur index 2",
		2: "Ventile sur index 3",
		3: "Ventile sur index 4",
		4: "Ventile sur index 5",
		5: "Ventile sur index 6",
		6: "Ventile sur index 7",
		7: "Ventile sur index 8",
		8: "Ventile sur index 9",
		9: "Ventile sur index 10",
	}
	return switcher.get(argument, "Invalide")

def switch_mot10(argument):
	switcher = {
		0: "Ventile sur index 1",
		1: "Ventile sur index 2",
		2: "Ventile sur index 3",
		3: "Ventile sur index 4",
	}
	return switcher.get(argument, "Invalide")

def switch_mot11(argument):
	switcher = {
		0: "Correct",
		1: "Degrade",
	}
	return switcher.get(argument, "Invalide")

def switch_mot12(argument):
	switcher = {
		0: "Historique",
		1: "Standard",
	}
	return switcher.get(argument, "Invalide")

def switch_mot13(argument):
	switcher = {
		0: "Non utilise",
		1: "Non utilise",
	}
	return switcher.get(argument, "Invalide")

def switch_mot14(argument):
	switcher = {
		0: "Desactivee",
		1: "Activee sans secu",
		2: "Invalide",
		3: "Activee avec secu",
	}
	return switcher.get(argument, "Invalide")

def switch_mot15(argument):
	switcher = {
		0: "New/unlock",
		1: "New/lock",
		2: "Registered",
		3: "Invalide",
	}
	return switcher.get(argument, "Invalide")

def switch_mot16(argument):
	switcher = {
		0: "Non synchro",
		1: "synchro",
	}
	return switcher.get(argument, "Invalide")

def switch_mot17(argument):
	switcher = {
		0: "Contrat non Tempo",
		1: "Bleu",
		2: "Blanc",
		3: "Rouge",
	}
	return switcher.get(argument, "Invalide")

def switch_mot19(argument):
	switcher = {
		0: "Pas de preavis",
		1: "Preavis PM1",
		2: "Preavis PM2",
		3: "Preavis PM3",
	}
	return switcher.get(argument, "Invalide")

# DECLARATION DES VARIABLES
apikey = "mettre ici votre cle API trouvee dans réglages/systeme/configuration puis aller dans API et prendre 'clé API'" #cle API pour lire les donnees d une id
ip_jeedom = "mettre ici votre ip jeedom"
apikey_jeedom = "mettre ici la clé API que vous trouverez au même endroit que apikey mais prendre 'clé API virtuel'" #cle API pour aller ecrire les donnees sur une id

# ID DES COMMANDES SOUS JEEDOM
idSTGE = 2382 #id ou trouver le code STGE du linky
idprem= 2390 #premiere id si toutes se suivent sinon mettre 0 et remplir pour chaque id donc tout interet a creer toutes les infos en meme temps
idinfo = []
if idprem == 0:
	idinfo = ["a completer si besoin"]
	idinfo += ["a completer si besoin"]
	idinfo += ["a completer si besoin"]
	idinfo += ["a completer si besoin"]
	idinfo += ["a completer si besoin"]
	idinfo += ["a completer si besoin"]
	idinfo += ["a completer si besoin"]
	idinfo += ["a completer si besoin"]
	idinfo += ["a completer si besoin"]
	idinfo += ["a completer si besoin"]
	idinfo += ["a completer si besoin"]
	idinfo += ["a completer si besoin"]
	idinfo += ["a completer si besoin"]
	idinfo += ["a completer si besoin"]
	idinfo += ["a completer si besoin"]
	idinfo += ["a completer si besoin"]
	idinfo += ["a completer si besoin"]
	idinfo += ["a completer si besoin"]
	idinfo += ["a completer si besoin"]
	idinfo += ["a completer si besoin"]
else:
	for i in range(20):
		idinfo += [str(idprem+i)]


# IMPORTATION DES LIBRAIRIES
import sys
import requests

# ON RECUPERE LES DONNEES STGE
stgehex = requests.get("http://"+ip_jeedom+"/core/api/jeeApi.php?apikey="+apikey+"&type=cmd&id="+ str(idSTGE)).text

stgebin = bin(int(stgehex, 16)) #on traduit le message hexa en binaire
stgebin = stgebin [2::] #on supprime le 0b au debut du message binaire
bits = [stgebin]
longueur = len(stgebin)
#on stocke tous les bits unitairement
for i in range(32):
	if i > longueur - 1: 
		bits += '0' #on complete avec des zeros jusqu a 32 bits
	else:
		bits += [stgebin[longueur -1 -i:longueur -i]]
#print ('bits 2 ', bits)


message = [switch_mot1(int(bits[1]))]
message += [switch_mot2(int(bits[4]+bits[3]+bits[2],2))]
message += [switch_mot3(int(bits[5]))]
message += [switch_mot4(int(bits[6]))]
message += [switch_mot5(int(bits[7]))]
message += [switch_mot6(int(bits[8]))]
message += [switch_mot7(int(bits[9]))]
message += [switch_mot8(int(bits[10]))]
message += [switch_mot9(int(bits[14]+bits[13]+bits[12]+bits[11],2))]
message += [switch_mot10(int(bits[16]+bits[15],2))]
message += [switch_mot11(int(bits[17]))]
message += [switch_mot12(int(bits[18]))]
message += [switch_mot13(int(bits[19]))]
message += [switch_mot14(int(bits[21]+bits[20],2))]
message += [switch_mot15(int(bits[23]+bits[22],2))]
message += [switch_mot16(int(bits[24]))]
message += [switch_mot17(int(bits[26]+bits[25],2))]
message += [switch_mot17(int(bits[28]+bits[27],2))]
message += [switch_mot19(int(bits[30]+bits[29],2))]
message += [switch_mot19(int(bits[32]+bits[31],2))]
#print ('message', message)
#print ('test bin ', int(bits[2]+bits[1],2))

for i in range(20):
	requests.get("http://"+ip_jeedom+"/core/api/jeeApi.php?apikey="+apikey_jeedom+"&type=virtual&id="+str(idinfo[i])+"&value="+str(message[i]))

#test
      

# FIN DU SCRIPT

Si vous voulez l’utiliser il vous reste à indiquer la clé API (ligne 161) + l’IP locale de votre Jeedom (ligne 162) + la clé API des virtuels (ligne 163) + le numéro de l’Id où le script devra trouver le code STGE (ligne 166) + le 1er Id des champs de status si vous les avez créés à la suite (ligne 167) car ils doivent se suivre sinon mettre la variable idprem à 0 et remplir à la main à partir de la ligne 170
J’ai les mêmes doutes que pour le fichier excel mais la solution est là aussi assez simple dans les lignes qui en ont plusieurs pour les lignes entre 215 et 234 (script V1.0).

Et enfin j’ai écrit un scénario qui rafraîchit le script à chaque changement du code STGE.

Voici le résultat:
image

Voilà, donc si cela peut servir à quelqu’un ne vous gênez pas :wink:

Donc pour conclure chez moi on constate que la synchro CPL n’est pas bonne, est ce le problème… Pas grave je vais recontacter Enedis mais cela m’a permis de progresser sur ce sujet.

++

2 « J'aime »

Hello,

Merci pour ton taf, je me demandais justement à quoi correspondait ce champ STGE

Par contre, j’ai moi aussi un statut CPL à non synchro comme toi, mais j’ai bien les valeurs qui remontent sur le site Enedis, donc pas sur que ce soit ton problème réel en tout cas

Salut @darghorn, merci pour cette info. J’ai comparé plusieurs log que j’ai pu trouver sur internet et en effet cela n’a pas l’air d’être lié à ça. J’ai changé de fournisseur lundi dernier et j’attends qq jours pour voir si ça fait pareil avec lui. Et ton statut CPL est à quelle valeur chez toi? Chez moi il est en ce moment à « New/lock ».

Idem, même valeur pour moi

Ok merci. Là je ne vois pas ce qui peut bloquer… Ou alors c’est au niveau du concentrateur qu’il n’y a plus de liaison

Bonjour,

Je suis très intéressé par le sujet que je viens de découvrir (je restais en mode historique à cause de l’absence de décodage de ce mot).
Votre script semble devoir tourner en parallèle du script teleinfo.py. Est-ce qu’il ne serait pas possible de l’intégrer directement dans ce script ?
Par ailleurs, le script teleinfo.py avait deux problèmes, à savoir, l’absence de vérification de checksum des messages en mode standard, et la non compatibilité avec python3.
Le développer du plugin semble avoir cessé toute activité.

Bonjour @Jean-Baptiste, c’est peut-être possible d’intégrer cette traduction dans le plug in mais je préférerai que ce soit le développeur qui s’en occupe. Pas certain que je sois capable de le faire étant 100% autodidacte et plus bidouilleur que développeur

Je crois que le développeur ne supporte plus le projet.
J’ai ouvert une issue sur github en septembre pour la compatibilité avec python 3 et debian Bullseye, pas de retour. J’ai donc dû modifier le fichier teleinfo.py afin que ça fonctionne. Je ne suis absolument pas un développeur.
L’issue concernant l’absence de vérification de checksum en mode standard est ouverte depuis bien longtemps aussi.
Je pense que c’est le moyen le plus simple afin d’intégrer les registres d’états. Si moi je suis à peu près capable de comprendre ce script, je pense que tu as largement le niveau.

bonsoir, compliqué d’intégrer comme ça. Il faut tout reprendre de la création des champs à … Je peux par contre tenter de modifier des imperfection du code d’origine car là il s’agit juste de reprendre le code

pourtant apparemment il y a bien une vérif du checksum en mode standard. Par contre elle ne fonctionne peut être pas…

ah ok, en mode standard tout est prévu mais lors de la réception il n’y a pas d’appel à la vérification. Faudrait tester ça déjà.

Bonjour,
Merci d’avoir regardé.
Je te transmets le fichier qui tourne sur mon Bullseye.
Je crois comprendre que le calcul du checksum est fait à partir de la ligne 160, pour le calcul de « _is_valid »*.
Par contre, je ne vois pas l’appel vers ce calcul dans le cas du mode standard (à partir de la ligne 70), contrairement au mode historique - appelé ligne 147.

J’ai bien compris ?

teleinfo.txt (18,3 Ko)

oui c’est exactement cela

j’ai un peu avancé sur le sujet. Apparemment le checksum en mode standard fonctionne lorsqu’il n’y a pas d’horodatage sauf pour le champs PJOURF+1 qui est le « Profil du prochain jour calendrier fournisseur » d’après la doc Enedis.

Rectif, la vérif du checksum fonctionne pour tous les champs sauf donc pour PJOURF+1. Je regarde si je trouve pourquoi sinon s’il n’y a que lui qui ne fonctionne pas je vais m’en passer :wink:

donc cela fonctionne sauf pour le champs que j’ai déjà évoqué. Perso je ne vois pas trop quoi faire de cette info que comptes tu en faire?

voici ton fichier modifié. Dis moi si cela te convient. Les données dont le checksum est incorrect ne sont plus enregistrées.
teleinfo.txt (18,5 Ko)

Merci beaucoup.
Ça fonctionne toujours en mode historique. Je viens de demander le passage vers le mode standard.

Reste :confused: à implémenter le décodages des trames avec l’étiquette STGE (dans la section « Read a frame » - du type elif cle == ’ STGE ’ ?)

le décodage en soit ne me pose pas de pb mais c’est l’utilisation que l’on en fait après et surtout son affichage. Là on touche à la structure du plugin, la gestion des frames, … un tas de choses que je ne sais pas faire…

Je viens de comprendre pourquoi le checksum ne fonctionnait pas pour PJOURF+1 et j’ai apporté la modif à ton fichier.
teleinfo.txt (18,4 Ko)