Enedis Gateway

personne avec un semblant de piste?

Bonjour,

Si j’importe le flow « node-red.deprecated.flow » qui est disponible sur la page github de @M4dm4rtig4n tout fonctionne bien car je peux faire l’import en faisant un copier/coller.
Après l’avoir configuré, j’obtiens les données d’Enedis.

Par contre si j’essaye d’importer la nouvelle version qui s’importe en utilisant le flow import.json et en suivant les instructions, j’obtiens les messages suivant:
15/04/2021 à 14:30:53 node: get list Flows
msg : string[16]
« JSON parse error »

15/04/2021 à 14:30:53 node: search ID of Flowsfunction : (error)
« TypeError: msg.payload.forEach is not a function »

J’utilise Home Assistant avec Node-Red et InfluxDB installé comme des modules complémentaires.

J’ai fait plusieurs tests différents et j’ai cherché ce que j’avais mal configuré mais je ne trouve pas. :thinking:

Est-ce que quelqu’un aurait déjà installé ce flow avec une configuration identique et pourrait me dire s’il faut configurer quelque chose que j’oublierai?

Merci et merci à @M4dm4rtig4n pour partager ses flows!

Bonjour,

Il suffit que je demande de l’aide pour que ça fonctionne!!!

Honnêtement je ne sais pas ce qui empêché l’import.
Je suis reparti de zéro et le flow a été importé.

Désolé pour le message précédent.

Merci

Bonjour,

Le flow fonctionne parfaitement!
J’ai une question un peu plus précise concernant le code du flow.

Il y a 2 valeurs qui sont stockées dans la base: value et value_detail.
value_detail est la valeur fournie par Enedis
value est une valeur calculée à partir de la valeur d’Enedis et dont le résultat est la moitié de la valeur d’Enedis.

value = parseInt(interval_reading[id].value*(mesure_interval/60))
value_detail = parseInt(interval_reading[id].value)

Comme mesure_interval est égale à 30 la valeur initiale est multiplié par 0,5

Est-ce quelqu’un saurait ce que représente cette valeur?
Sinon, @M4dm4rtig4n, peut-être que c’est une valeur que tu as calculé pour des besoins personnels?

Merci

Bonjour,

Je voulais remettre en place mon consentement, après qu’il ait disparu suite aux problèmes de chez Enedis d’il y a quelques semaines, mais j’arrive sur une erreur 404, quand je clique sur le bouton « faire la demande de consentement ». Est-ce un problème Enedis, et la seule chose à faire est d’attendre ?
J’ai testé avec Firefox, puis Edge.

Aussi, je voulais en profiter pour indiquer que « crypter » signifie que c’est irréversible. Or dans la phrase suivante, il est clairement mentionné que c’est réversible. :

Pour information, les 2 jetons (access_token & refresh_token) sont cryptés en base de données avec votre propre clef de décryptage.

En Français, il faut dire « chiffrer » et « déchiffrer ».
Cela vient d’une mauvaise traduction de « encrypt » et « decrypt » en Anglais.

Après avoir réussi à obtenir mon token (l’erreur 404 ayant été réparé), j’ai voulu mettre en place le flow node-red.
J’ai testé sur Node-Red and standalone et dans HA, lors de l’import du flow, en suivant l’installation décrite ici, j’ai cette erreur :

Unexpected token < in JSON at position 0

Comment puis-je corriger ceci ?

Hello !
Toujours le même soucis à l’import du flow. J’ai aussi ouvert un ticket sous Github.
Quelle solution puis-je apporter pour avancer sur ce sujet ?

Hello @Tank ,

As tu bien suivis step by step la procédure d’Install ?

Je viens de suivre à nouveau le tuto à partir de zéro (donc création d’un flux nomé « Enedis », import du fichier .json, completions des crédentials puis deploy et inject), et j’ai toujours la même erreur :

11/05/2021 à 07:50:45node: Import Github Flow to onprem
msg : string[40]
"Unexpected token < in JSON at position 0"

Pour information, j’utilise NodeRed 1.3.3, avec les palettes suivantes :

Bonsoir !

Je viens de tomber sur votre impression d’écran et je me dis je suis une vraie burne en node… Si vous aviez des tutos ou infos pour des gros noobs allergiques a la programmation (mais qui arrive a ce démerder style escargot de 10 T______@ii quand on leur explique longtemps… je penses que nous sommes nombreux mais restons silencieux…).

Je sais c’est pas le sujet dans ce cas précis mais voilà j’ai regardé pas mal de truc depuis que je me suis mise sur home assistant et il y a des personnes comme vous très pédagogues.

Merci

Tu as trouvé ? (Je rencontre le même problème)

Malheureusement non.
J’ai mis de côté pour le moment.

Hello tout le monde.
tout d’abord bravo pour l’appli !

j’ai récup mes infos, mais le curl me donne

{« tag »:« enedis_return_ko »,« error_code »:« no_data_found »,« description »:« no measure found for this usage point »,« alert_user »:true,« enedis_return »:true,« support »:« liendiscord »}

l’historisation est bien activé

une idée ?
merci

Merci pour le développement de cette passerelle et pour tout ce partage, étant début sur HA ça m’a vraiment aider pour mettre en place mon suivi de conso.

Je ne sais pas si c’est volontaire, mais avec le flow impossible de récupérer les données de la veille, au mieux on ne peux récupérer que les conso de J-2.
Donc j’ai remplacé le script du node « Split date week per week » par:

msg.payload = [];

var since = msg.since;
var to = msg.to || 0;
var pass = (since - to) / 7;	

var dtStart = new Date();
dtStart.setDate(dtStart.getDate() - since);

var dtEnd = new Date();
dtEnd.setDate(dtEnd.getDate() - to);
			
for (var i=1; i < pass + 1; i++) {
	
	var end = new Date(dtStart);
	end.setDate(end.getDate() + 7);	
	
	end = end < dtEnd ? end : dtEnd;

	msg.payload.push({
		start: dtStart.toISOString().split('T')[0],
		end: end.toISOString().split('T')[0],
		id: i
	});    
	
	dtStart = end;
}
return msg;

Ce script conserve toutes les autres possibilités de récupération du flow d’origine.

Avec mon fournisseur d’énergie (Engie) j’ai des HP/HC à la con : 1H24-6H54 / 11H54-14H24
Comme le flow d’origine se fie juste à l’heure de la relève (toutes les 30min), je me retrouvais avec la conso de 1h30 complètement en HC alors qu’il y a 24min en HP et 6 en HC; forcément, inversement sur le créneau de 7h.
Donc j’ai remplacé le script du node « Fields » par:

var unit                = msg.payload.meter_reading.reading_type.unit;
var measurement_kind    = msg.payload.meter_reading.reading_type.measurement_kind
var aggregate           = msg.payload.meter_reading.reading_type.aggregate;
var interval_reading    = msg.payload.meter_reading.interval_reading;
var reading_start       = msg.payload.meter_reading.start;
var subscribed_power    = msg.subscribed_power;
var usage_point_id      = msg.usage_point_id;
var hc                  = msg.hc;

msg.payload = [];

for (var i=0; i < interval_reading.length; i++) {

	var measure = interval_reading[i];
	var date = measure.date;
	var date_timestamp = new Date(date);
	const offset = date_timestamp.getTimezoneOffset()
	
	// Récupération de l'intervalle de mesure
	var interval = measure.interval_length.match(/\d+/)[0];
	// Calcul de la date de départ de l'interval de mesure
	var dtStart = new Date(date_timestamp - interval * 60000);
	
	var intervalStart= { type: 'HP', hc: undefined };
	var intervalEnd	 = { type: 'HP', hc: undefined };
	
	// Boucle de vérification du type de la date/heure du début et de la date/heure de fin de l'interval
	for (var j=0; j < hc.length; j++) {
		
		// Vérification du début de l'interval
		let hcStart = new Date(dtStart)
		hcStart.setHours(parseInt(hc[j].start.split('H')[0]));
		hcStart.setMinutes(parseInt(hc[j].start.split('H')[1]));					
							
		let hcEnd = new Date(dtStart);
		hcEnd.setHours(parseInt(hc[j].end.split('H')[0]));
		hcEnd.setMinutes(parseInt(hc[j].end.split('H')[1]));					
		
		intervalStart = dtStart > hcStart && dtStart < hcEnd ? { type: 'HC', hc: hc[j] } : intervalStart;
		
		// Vérification de la fin de l'interval
		hcStart = new Date(date_timestamp)
		hcStart.setHours(parseInt(hc[j].start.split('H')[0]));
		hcStart.setMinutes(parseInt(hc[j].start.split('H')[1]));					
							
		hcEnd = new Date(date_timestamp);
		hcEnd.setHours(parseInt(hc[j].end.split('H')[0]));
		hcEnd.setMinutes(parseInt(hc[j].end.split('H')[1]));					
		
		intervalEnd = date_timestamp > hcStart && date_timestamp < hcEnd ? { type: 'HC', hc: hc[j] } : intervalEnd;
	}
	
	var tags = {
		month: date.split(' ')[0].split('-')[1],
		year: date.split(' ')[0].split('-')[0],
		measure_type: measure.measure_type,
		// interval_length: interval_reading[id].interval_length,
		usage_point_id: usage_point_id
	};
	var fields = {
		subscribed_power: parseInt(subscribed_power),
		year: date.split(' ')[0].split('-')[0],
		month: date.split(' ')[0].split('-')[1],
	};
	
	// Si le créneau de début et de fin de sont du même type
	if (intervalStart.type == intervalEnd.type) {
	
		tags.type = intervalStart.type;		

		let time_human = new Date(date_timestamp.getTime() - (offset*60*1000));
		
		fields.value 		 = parseInt(measure.value*interval/60);
		fields.value_detail    = parseInt(measure.value);
		fields.time 		= date_timestamp*1000000;
		//fields.time_human = (time_human.toISOString().split('T')[0] + ' ' + time_human.toISOString().split('T')[1]).replace('Z', '');
		
		msg.payload.push([fields, tags]);					
	}
	else {			
	
		// Calcul du temps (en secondes) passé en HC
		var diff = 0;
		if (intervalStart.type == 'HC') {
			let hcEnd = new Date(dtStart)
			hcEnd.setHours(parseInt(intervalStart.hc.end.split('H')[0]));
			hcEnd.setMinutes(parseInt(intervalStart.hc.end.split('H')[1]));					
		
			diff = hcEnd - dtStart;
			dtStart.setTime(dtStart.getTime() + diff);
		}
		else {
			let hcStart = new Date(date_timestamp);
			hcStart.setHours(parseInt(intervalEnd.hc.start.split('H')[0]));
			hcStart.setMinutes(parseInt(intervalEnd.hc.start.split('H')[1]));					
		
			diff = date_timestamp - hcStart;
			dtStart.setTime(date_timestamp.getTime() - diff);
		}
		diff = Math.floor(diff / 1000);
		
		// Calcul des valeurs de consommation HC/HP
		var consoHC = Math.round(measure.value * diff / (interval * 60));
		var consoHP = measure.value - consoHC;
		
		// Intégration de la consommation du début de l'interval
		var tagsStart = Object.assign({}, tags);
		tagsStart.type = intervalStart.type;
		var value = tagsStart.type == 'HP' ? consoHP : consoHC;	

		let time_human = new Date(dtStart.getTime() - (offset*60*1000));
		
		var fieldsStart 		    = Object.assign({}, fields);
		fieldsStart.value 	    = Math.round(value*(interval - diff / 60)/60);
		fieldsStart.value_detail= parseInt(value);
		fieldsStart.time 	    = dtStart*1000000;
		//fieldsStart.time_human 	= (time_human.toISOString().split('T')[0] + ' ' + time_human.toISOString().split('T')[1]).replace('Z', '');
		
		msg.payload.push([fieldsStart, tagsStart]);	
		
		// Intégration de la consommation de la fin de l'interval
		var tagsEnd = Object.assign({}, tags);
		tagsEnd.type = intervalEnd.type;
		value = tagsEnd.type == 'HP' ? consoHP : consoHC;	

		time_human = new Date(date_timestamp.getTime() - (offset*60*1000));
		
		var fieldsEnd 			= Object.assign({}, fields);					
		fieldsEnd.value 		= Math.round(value*(interval - diff / 60)/60);
		fieldsEnd.value_detail 	= parseInt(value);
		fieldsEnd.time 		= date_timestamp*1000000;
		//fieldsEnd.time_human	= (time_human.toISOString().split('T')[0] + ' ' + time_human.toISOString().split('T')[1]).replace('Z', '');
		
		msg.payload.push([fieldsEnd, tagsEnd]);	
	}			
}

msg.measurement = "consumption_load_curve";

return msg;

Quand je suis sur un horaire à cheval HP/HC ce script permet de calculer (proportionnellement au temps passé), la part HP et la part HC.
Ok, c’est du proportionnel donc ça reste une approximation mais ça se rapproche plus de la réalité, sur les données du mois dernier j’ai un décalage de ~0.30€ par rapport au relevé de conso réel indiqué sur le site d’Engie et Grafana.

Si quelqu’un à une réponse à la question de @jpcasta ça m’intéresse aussi de comprendre.
Sur le site d’Enedis c’est bien la valeur du « value_detail » qui est indiqué mais sur le site d’Engie c’est la valeur du « value » (on va pas se plaindre, il vaut mieux payer la plus petite des valeurs ! :money_mouth_face:)

Hello,

Pour information je suis en train de dev un connecteur enedisgateway2mqtt :
https://forum.hacf.fr/t/enedisgateway2mqtt/6679

Par la suite je pense push de la data également dans un influxdb :slight_smile:

Bonjour,

je cherche à mettre en place la visu de ma conso electrique via enedis gateway.
j’ai fais la demande de consentement mais je ne trouve nulle part le token.
Comment faites-vous pour le recupérer?

Bonjour
Il y a actuellement un bug chez Enedis qui empêche de recevoir le token
Ils sont au courant
Il faut attendre
Philippe

D’accord.
Merci pour l’info

Hello,

Je recherche des beta tester pour ma nouvelle passerelle donc faite vous plaisir sur :
https://www.myelectricaldata.fr/

EnedisGateway2MQTT pointe encore sur l’ancienne passerelle, donc n’utilisez que les commandes curl disponible en retour des consentements.

Vous pouvez également lister tt les commandes curl via la Doc : MyElectricalData
Où même directement depuis le swagger : MyElectricalData

Autre grosse nouveauté sur cette version, j’ai mit en place du cache qui va vous apporter 2 gros avantages :

  • Si les API Enedis sont HS, et que j’ai la donnée en cache je peut vous la renvoyer sans soucis.
  • Temps de réponse beaucoup plus rapide.

Le fonctionnement est assez simple Il suffit d’ajouter « /cache » à la fin de l’url de l’endpoint et ca active le cache.

Exemple sans cache:

curl -s -X GET "https://www.myelectricaldata.fr/contracts/MON_PDL" -H "Authorization: MON_TOKEN"

Exemple avec cache:

curl -s -X GET "https://www.myelectricaldata.fr/contracts/MON_PDL/cache" -H "Authorization: MON_TOKEN"

Il est également possible de purger le cache via des endpoint dédié. Tout est expliquer dans le swagger :
https://www.myelectricaldata.fr/swagger

Si la donnée n’est pas en cache, je transfert la demande directement à Enedis (avec un temp de réponse assez long en général)
Si la demande à déjà était faites dans les 30j, je charge renvoie directement la donnée en cache (beaucoup plus rapide)

PS : Les consentements sur cette passerelle n’entre pas en conflit avec ceux d’EnedisGateway.tech.

Merci d’avance :slight_smile:

Hello,
Je ne me suis pas encore penché sur home assistant, donc tout ça me semble assez abscons pour l’instant, mais avant de m’ y plonger, je voudrais être sur de comprendre de la fonction de votre passerelle.
Si j’ai bien compris, elle sert donc a récupérer les infos fournis par enedis, les mêmes que l’on peut consulter sur l’appli « enedis et moi », pour les intégrer dans home assistant.
Si c’est bien ça, il n’y a pas par exemple de suivi de consommation plus précise que les infos par demi heure?
Peut-on récupérer ces infos pour interagir avec d’autre appareils dans « home assistant » ? par exemple allumer une lumière quand on dépasse un certain seuil de consommation.
J’ai le tarif « tempo » d’EDF, les jours bleus, blancs, et rouges, sont ils utilisés par la passerelle? Peut-on également intégrer des interactions dans home assistant en fonction de la couleur du jour, éteindre certains appareils, etc…?

Merci, et désolé pour mes questions si elles sont hors sujet, ou on déjà été répondues?