Skip to content

Commit dbad075

Browse files
authored
Merge pull request #3 from rene-d/develop
correction paramètre cfg_led_tinfo
2 parents af22b49 + bca4c93 commit dbad075

File tree

11 files changed

+191
-137
lines changed

11 files changed

+191
-137
lines changed

README.md

+71-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ WifInfo est un module de consignation de la téléinformation des compteurs éle
44

55
## Introduction
66

7-
Ce projet est la fusion de développements réalisés en vue du remplacement d'un [eco-devices](http://gce-electronics.com/fr/111-eco-devices) sur base de [ESP-01](https://fr.wikipedia.org/wiki/ESP8266) et de la une réécriture quasi complète - sauf la partie interface web - du projet homonyme de C-H. Hallard [LibTeleinfo](https://github.com/hallard/LibTeleinfo) avec des modifications notamment de [olileger](https://github.com/olileger/LibTeleinfo) et [Doume](https://github.com/Doume/LibTeleinfo).
7+
Ce projet est la fusion de développements réalisés en vue du remplacement d'un [eco-devices](http://gce-electronics.com/fr/111-eco-devices) sur base de [ESP-01](https://fr.wikipedia.org/wiki/ESP8266) et de la une réécriture quasi complète - sauf la partie interface web - du projet homonyme de [C-H. Hallard](http://hallard.me) [LibTeleinfo](https://github.com/hallard/LibTeleinfo) avec des modifications notamment de [olileger](https://github.com/olileger/LibTeleinfo) et [Doume](https://github.com/Doume/LibTeleinfo).
88

99
* Meilleure séparation des fonctions dans des fichiers sources différents
1010
* Homogénéisation du nommage, nettoyage du code source
@@ -19,12 +19,68 @@ Ce projet est la fusion de développements réalisés en vue du remplacement d'u
1919
* Exemple de stack [InfluxDB](https://www.influxdata.com) + [Grafana](https://grafana.com) pour la visualisation des données (avec sonde Python et client SSE)
2020
* Utilisation de [PlatformIO](https://platformio.org) comme environnement de développement
2121

22-
## Documentation
22+
La mise à jour OTA et les notifications jeedom/emoncms ne sont pas testées.
23+
24+
## Références
2325

2426
Documentation ERDF sur la [téléinformation client](https://www.enedis.fr/sites/default/files/Enedis-NOI-CPT_02E.pdf) pour les compteurs électroniques et pour les compteurs [Linky](https://www.enedis.fr/sites/default/files/Enedis-NOI-CPT_54E.pdf).
2527

2628
Module [PiTInfo](https://hallard.me/pitinfov12/) et explications pourquoi le montage avec uniquement optocoupleur et résistances ne suffit pas avec un esp8266.
2729

30+
## Interface web
31+
32+
### Affichage des jauges PAPP et IINST (en temps réel)
33+
34+
![teleinfo](docs/gauges.png)
35+
36+
### Affichage de données de téléinformation
37+
38+
![teleinfo](docs/teleinfo.png)
39+
40+
### Configuration des requêtes HTTP
41+
42+
Les requêtes HTTP sont de type GET.
43+
44+
Il y a 4 déclenchements possibles:
45+
* périodique
46+
* lors d'un changement de période tarifaire (exemple passage de HP à HC)
47+
* lors de dépassement d'un seuil haut ou retour à un seuil bas (en VA, test avec la valeur PAPP)
48+
* présence de l'étiquette ADPS (Avertissement de Dépassement de Puissance Souscrite)
49+
50+
L'URI est constituée avec les étiquettes de téléinformation (`ADCO`, `HCHC`, `HCHP`, `PTEC`, `PAPP`, `IINST`, etc.) ainsi que des étiquettes internes:
51+
* date : date au format ISO8601 (ex: 2020-02-02T12:12:00+0100)
52+
* timestamp : temps en secondes (Unix epoch)
53+
* chipid : l'identifiant de l'esp8266 sous forme hexadécimale (0x0011AA)
54+
* type : type de déclenchement (`MAJ`: périodique, `PTEC`: changement tarif, `HAUT`: seuil haut, `BAS`: retour seuil bas, `ADPS`: dépassement, `NORM`: fin dépassement)
55+
56+
La syntaxe pour utiliser les étiquettes est au choix:
57+
* `$NOM`
58+
* `~NOM~`
59+
60+
Exemple: `/update.php?ptec=$PTEC&conso=~HCHC~+~HCHP~&id=$chipid``/update.php?ptec=HP&conso=4000+3000&id=0x0011AA`
61+
62+
### Données JSON
63+
64+
* http://wifinfo/json : téléinformation sous forme de dictionnaire JSON
65+
* http://wifinfo/tinfo.json : téléinformation sous forme de tableau JSON, utilisé par l'onglet Téléinformation de l'interface
66+
* http://wifinfo/system.json : état du système, utilisé par l'onglet Système de l'interface
67+
* http://wifinfo/config.json : état du système, utilisé par l'onglet Configuration de l'interface
68+
* http://wifinfo/wifiscan.json : liste des réseaux Wi-Fi, utilisé par l'onglet Configuration de l'interface
69+
* http://wifinfo/spiffs.json : liste des fichiers, utilisé par l'onglet Fichiers de l'interface
70+
71+
### Autres requêtes
72+
73+
* http://wifinfo/reset : permet de redémarrer le module
74+
* http://wifinfo/version : retourne la version (tag git) du système de fichiers
75+
76+
### Client SSE
77+
78+
Le événements SSE sont accessibles via deux URL: http://wifinfo/tic ou http://wifinfo/sse/tinfo.json, avec une limitiation à deux clients simultatnés.
79+
80+
La donnée est la trame de téléinformation au format JSON, comme http://wifinfo/json.
81+
82+
Elle est envoyée à chaque réception de trame depuis le compteur.
83+
2884
## Compilation
2985

3086
Le projet est prévu pour PlatformIO sous macOS ou Linux, en conjonction avec [Visual Studio Code](https://code.visualstudio.com) et son extension [PlatformIO](https://marketplace.visualstudio.com/items?itemName=platformio.platformio-ide).
@@ -33,6 +89,16 @@ L'IDE d'Arduino peut également être utilisé.
3389

3490
La page HTML est compressée avec [html-minifier](https://github.com/kangax/html-minifier) et gzip.
3591

92+
93+
### Options de compilation
94+
95+
* `DEBUG` : active la sortie sur le port série TX et vitesse 115200. Non utilisable avec un compteur, il faut utiliser le client de test pour injecter des trames.
96+
* `ENABLE_CLI` : active les commandes par port série (`TAB` ou `ESC`)
97+
* `DISABLE_LED` : désactive l'utilisation de LED pour les cartes qui n'en ont pas
98+
* `ENABLE_OTA` : rajoute le code pour les mises à jour OTA **(non testé)**
99+
100+
Nota: Sans l'option `DEBUG`, le port série est réglé à 1200 7E1 en RX uniquement. Il y a suffisamment d'outils de mise au point pour ne pas à devoir tester avec un compteur ou un autre microcontrôleur qui simule la téléinformation.
101+
36102
### PlatformtIO
37103

38104
Avec PlatformIO (soit ligne de commandes, soit extension Visual Studio Code):
@@ -44,7 +110,7 @@ platformio run -t upload
44110

45111
### IDE Arduino
46112

47-
Cf. les nombreux tutos pour l'utilisation d'esp8266-arduino et l'upload de SPIFFS.
113+
Cf. les nombreux tutos pour l'utilisation d'esp8266-arduino et l'upload de SPIFFS. Il sera aussi nécessaire de rajouter la librairie SimpleCLI.
48114

49115
Le répertoire `data` est préparé à l'aide du script suivant (nécessite python3, gzip, html-minifier) :
50116

@@ -92,7 +158,7 @@ docker build -t tic .
92158
docker run --rm -ti -v $(pwd):/tic:ro -v $(pwd)/coverage:/coverage tic /tic/runtest.sh
93159
```
94160

95-
La couverture est disponible dans `./coverage/index.html`
161+
La couverture est disponible dans `./coverage/index.html`.
96162

97163
## Développement web
98164

@@ -141,7 +207,7 @@ Le dashboard sera alors accessible à cette adresse: [http://localhost:3000/](ht
141207

142208
Le montage final utilise un ESP-01S avec le module [PiTInfo](http://hallard.me/pitinfov12-light/) - à acheter sur [tindie](https://www.tindie.com/products/Hallard/pitinfo/). L'alimentation est assurée par un module USB.
143209

144-
![teleinfo](docs/teleinfo.jpg)
210+
![teleinfo](docs/montage.jpg)
145211

146212
## Technologies utilisées
147213

dashboard/wifinfo_sse/influx.py

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env python3
22
# rene-d 2020
33

4-
# dashboard:
4+
# à utiliser avec un dashboard comme celui-ci:
55
# https://www.kozodo.com/blog/techno/article.php?id=32
66

77
"""
@@ -17,7 +17,7 @@
1717
import click
1818

1919

20-
# Tarifs EDF réglementés fin 2019
20+
# Tarifs réglementés EDF fin 2019
2121

2222
# TVA à 5.5%
2323
ABO = 17.16 # Heures Creuses - 06kVA
@@ -89,14 +89,13 @@ def main(frequency, wifinfo_addr, influxdb_addr):
8989
"tags": {"host": data["ADCO"]},
9090
"time": data["timestamp"],
9191
"fields": {
92-
"COSTHC": data["HCHC"] / 1000 * tarif_hc_ttc,
93-
"COSTHP": data["HCHP"] / 1000 * tarif_hp_ttc,
92+
"COSTHC": round(data["HCHC"] / 1000 * tarif_hc_ttc, 4),
93+
"COSTHP": round(data["HCHP"] / 1000 * tarif_hp_ttc, 4),
9494
"HCHC": data["HCHC"],
9595
"HCHP": data["HCHP"],
9696
"PAPP": data["PAPP"],
9797
"IINST": data["IINST"],
98-
"IMAX": data["IMAX"],
99-
"PTEC": data["PTEC"][:2],
98+
"PTEC": data["PTEC"],
10099
},
101100
}
102101
]

docs/gauges.png

45.5 KB
Loading

docs/teleinfo.jpg docs/montage.jpg

File renamed without changes.

docs/teleinfo.png

39.6 KB
Loading

src/config.cpp

+50-50
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,9 @@ void config_reset()
8787
strcpy_P(config.jeedom.adco, CFG_JDOM_DEFAULT_ADCO);
8888

8989
// HTTP Request
90-
strcpy_P(config.httpReq.host, CFG_HTTPREQ_DEFAULT_HOST);
91-
config.httpReq.port = CFG_HTTPREQ_DEFAULT_PORT;
92-
strcpy_P(config.httpReq.url, CFG_HTTPREQ_DEFAULT_URL);
90+
strcpy_P(config.httpreq.host, CFG_HTTPREQ_DEFAULT_HOST);
91+
config.httpreq.port = CFG_HTTPREQ_DEFAULT_PORT;
92+
strcpy_P(config.httpreq.url, CFG_HTTPREQ_DEFAULT_URL);
9393

9494
// save back
9595
config_save();
@@ -204,7 +204,7 @@ void config_show()
204204
Serial.println(config.ota_port);
205205

206206
Serial.print(F("Config :"));
207-
if (config.config & CONFIG_LED_TINFO)
207+
if (config.options & OPTION_LED_TINFO)
208208
Serial.print(F(" LED_TINFO"));
209209
Serial.println();
210210

@@ -238,25 +238,25 @@ void config_show()
238238

239239
Serial.println(F("===== HTTP request"));
240240
Serial.print(F("host : "));
241-
Serial.println(config.httpReq.host);
241+
Serial.println(config.httpreq.host);
242242
Serial.print(F("port : "));
243-
Serial.println(config.httpReq.port);
243+
Serial.println(config.httpreq.port);
244244
Serial.print(F("url : "));
245-
Serial.println(config.httpReq.url);
245+
Serial.println(config.httpreq.url);
246246
Serial.print(F("freq : "));
247-
Serial.println(config.httpReq.freq);
247+
Serial.println(config.httpreq.freq);
248248
Serial.print(F("notifs :"));
249-
if (config.httpReq.trigger_ptec)
249+
if (config.httpreq.trigger_ptec)
250250
Serial.print(F(" PTEC"));
251-
if (config.httpReq.trigger_adps)
251+
if (config.httpreq.trigger_adps)
252252
Serial.print(F(" ADPS"));
253-
if (config.httpReq.trigger_seuils)
253+
if (config.httpreq.trigger_seuils)
254254
Serial.print(F(" seuils"));
255255
Serial.println();
256256
Serial.print(F("seuil bas : "));
257-
Serial.println(config.httpReq.seuil_bas);
257+
Serial.println(config.httpreq.seuil_bas);
258258
Serial.print(F("seuil haut: "));
259-
Serial.println(config.httpReq.seuil_haut);
259+
Serial.println(config.httpreq.seuil_haut);
260260

261261
Serial.flush();
262262
}
@@ -274,7 +274,7 @@ void config_get_json(String &r)
274274
js.append(CFG_FORM_OTA_AUTH, config.ota_auth);
275275
js.append(CFG_FORM_OTA_PORT, config.ota_port);
276276

277-
js.append(FPSTR("cfg_led_info"), (config.config & CONFIG_LED_TINFO) ? 1 : 0);
277+
js.append(CFG_LED_TINFO, (config.options & OPTION_LED_TINFO) ? 1 : 0);
278278

279279
js.append(CFG_FORM_EMON_HOST, config.emoncms.host);
280280
js.append(CFG_FORM_EMON_PORT, config.emoncms.port);
@@ -290,16 +290,16 @@ void config_get_json(String &r)
290290
js.append(CFG_FORM_JDOM_ADCO, config.jeedom.adco);
291291
js.append(CFG_FORM_JDOM_FREQ, config.jeedom.freq);
292292

293-
js.append(CFG_FORM_HTTPREQ_HOST, config.httpReq.host);
294-
js.append(CFG_FORM_HTTPREQ_PORT, config.httpReq.port);
295-
js.append(CFG_FORM_HTTPREQ_URL, config.httpReq.url);
296-
js.append(CFG_FORM_HTTPREQ_FREQ, config.httpReq.freq);
293+
js.append(CFG_FORM_HTTPREQ_HOST, config.httpreq.host);
294+
js.append(CFG_FORM_HTTPREQ_PORT, config.httpreq.port);
295+
js.append(CFG_FORM_HTTPREQ_URL, config.httpreq.url);
296+
js.append(CFG_FORM_HTTPREQ_FREQ, config.httpreq.freq);
297297

298-
js.append(CFG_FORM_HTTPREQ_TRIGGER_PTEC, config.httpReq.trigger_ptec);
299-
js.append(CFG_FORM_HTTPREQ_TRIGGER_ADPS, config.httpReq.trigger_adps);
300-
js.append(CFG_FORM_HTTPREQ_TRIGGER_SEUILS, config.httpReq.trigger_seuils);
301-
js.append(CFG_FORM_HTTPREQ_SEUIL_BAS, config.httpReq.seuil_bas);
302-
js.append(CFG_FORM_HTTPREQ_SEUIL_HAUT, config.httpReq.seuil_haut, true);
298+
js.append(CFG_FORM_HTTPREQ_TRIGGER_PTEC, config.httpreq.trigger_ptec);
299+
js.append(CFG_FORM_HTTPREQ_TRIGGER_ADPS, config.httpreq.trigger_adps);
300+
js.append(CFG_FORM_HTTPREQ_TRIGGER_SEUILS, config.httpreq.trigger_seuils);
301+
js.append(CFG_FORM_HTTPREQ_SEUIL_BAS, config.httpreq.seuil_bas);
302+
js.append(CFG_FORM_HTTPREQ_SEUIL_HAUT, config.httpreq.seuil_haut, true);
303303
}
304304

305305
static int validate_int(const String &value, int a, int b, int d)
@@ -325,45 +325,45 @@ void config_handle_form(ESP8266WebServer &server)
325325
Serial.println(F("===== Posted configuration"));
326326
#endif
327327

328-
// WifInfo
328+
// Wi-Fi et avancé
329329
strncpy(config.ssid, server.arg(CFG_FORM_SSID).c_str(), CFG_SSID_LENGTH);
330-
strncpy(config.psk, server.arg("psk").c_str(), CFG_SSID_LENGTH);
331-
strncpy(config.host, server.arg("host").c_str(), CFG_HOSTNAME_LENGTH);
332-
strncpy(config.ap_psk, server.arg("ap_psk").c_str(), CFG_SSID_LENGTH);
333-
strncpy(config.ota_auth, server.arg("ota_auth").c_str(), CFG_SSID_LENGTH);
334-
config.ota_port = validate_int(server.arg("ota_port"), 0, 65535, DEFAULT_OTA_PORT);
330+
strncpy(config.psk, server.arg(CFG_FORM_PSK).c_str(), CFG_SSID_LENGTH);
331+
strncpy(config.host, server.arg(CFG_FORM_HOST).c_str(), CFG_HOSTNAME_LENGTH);
332+
strncpy(config.ap_psk, server.arg(CFG_FORM_AP_PSK).c_str(), CFG_SSID_LENGTH);
333+
strncpy(config.ota_auth, server.arg(CFG_FORM_OTA_AUTH).c_str(), CFG_SSID_LENGTH);
334+
config.ota_port = validate_int(server.arg(CFG_FORM_OTA_PORT), 0, 65535, DEFAULT_OTA_PORT);
335335

336-
config.config = 0;
337-
if (server.hasArg("cfg_led_tinfo"))
338-
config.config |= CONFIG_LED_TINFO;
336+
config.options = 0;
337+
if (server.hasArg(CFG_LED_TINFO))
338+
config.options |= OPTION_LED_TINFO;
339339

340340
// Emoncms
341-
strncpy(config.emoncms.host, server.arg("emon_host").c_str(), CFG_EMON_HOST_LENGTH);
342-
strncpy(config.emoncms.url, server.arg("emon_url").c_str(), CFG_EMON_URL_LENGTH);
343-
strncpy(config.emoncms.apikey, server.arg("emon_apikey").c_str(), CFG_EMON_APIKEY_LENGTH);
344-
config.emoncms.node = validate_int(server.arg("emon_node"), 0, 255, 0);
345-
config.emoncms.port = validate_int(server.arg("emon_port"), 0, 65535, CFG_EMON_DEFAULT_PORT);
346-
config.emoncms.freq = validate_int(server.arg("emon_freq"), 0, 86400, 0);
341+
strncpy(config.emoncms.host, server.arg(CFG_FORM_EMON_HOST).c_str(), CFG_EMON_HOST_LENGTH);
342+
config.emoncms.port = validate_int(server.arg(CFG_FORM_EMON_PORT), 0, 65535, CFG_EMON_DEFAULT_PORT);
343+
strncpy(config.emoncms.url, server.arg(CFG_FORM_EMON_URL).c_str(), CFG_EMON_URL_LENGTH);
344+
strncpy(config.emoncms.apikey, server.arg(CFG_FORM_EMON_KEY).c_str(), CFG_EMON_KEY_LENGTH);
345+
config.emoncms.node = validate_int(server.arg(CFG_FORM_EMON_NODE), 0, 255, 0);
346+
config.emoncms.freq = validate_int(server.arg(CFG_FORM_EMON_FREQ), 0, 86400, 0);
347347

348348
// jeedom
349349
strncpy(config.jeedom.host, server.arg(CFG_FORM_JDOM_HOST).c_str(), CFG_JDOM_HOST_LENGTH);
350+
config.jeedom.port = validate_int(server.arg(CFG_FORM_JDOM_PORT), 0, 65535, CFG_JDOM_DEFAULT_PORT);
350351
strncpy(config.jeedom.url, server.arg(CFG_FORM_JDOM_URL).c_str(), CFG_JDOM_URL_LENGTH);
351-
strncpy(config.jeedom.apikey, server.arg(CFG_FORM_JDOM_KEY).c_str(), CFG_JDOM_APIKEY_LENGTH);
352+
strncpy(config.jeedom.apikey, server.arg(CFG_FORM_JDOM_KEY).c_str(), CFG_JDOM_KEY_LENGTH);
352353
strncpy(config.jeedom.adco, server.arg(CFG_FORM_JDOM_ADCO).c_str(), CFG_JDOM_ADCO_LENGTH);
353-
config.jeedom.port = validate_int(server.arg(CFG_FORM_JDOM_PORT), 0, 65535, CFG_JDOM_DEFAULT_PORT);
354354
config.jeedom.freq = validate_int(server.arg(CFG_FORM_JDOM_FREQ), 0, 86400, 0);
355355

356356
// HTTP Request
357-
strncpy(config.httpReq.host, server.arg(CFG_FORM_HTTPREQ_HOST).c_str(), CFG_HTTPREQ_HOST_LENGTH);
358-
strncpy(config.httpReq.url, server.arg(CFG_FORM_HTTPREQ_URL).c_str(), CFG_HTTPREQ_URL_LENGTH);
359-
config.httpReq.port = validate_int(server.arg(CFG_FORM_HTTPREQ_PORT), 0, 65535, CFG_HTTPREQ_DEFAULT_PORT);
360-
config.httpReq.freq = validate_int(server.arg(CFG_FORM_HTTPREQ_FREQ), 0, 86400, 0);
361-
362-
config.httpReq.trigger_ptec = server.hasArg(CFG_FORM_HTTPREQ_TRIGGER_PTEC);
363-
config.httpReq.trigger_adps = server.hasArg(CFG_FORM_HTTPREQ_TRIGGER_ADPS);
364-
config.httpReq.trigger_seuils = server.hasArg(CFG_FORM_HTTPREQ_TRIGGER_SEUILS);
365-
config.httpReq.seuil_bas = validate_int(server.arg(CFG_FORM_HTTPREQ_SEUIL_BAS), 0, 20000, 0);
366-
config.httpReq.seuil_haut = validate_int(server.arg(CFG_FORM_HTTPREQ_SEUIL_HAUT), 0, 20000, 0);
357+
strncpy(config.httpreq.host, server.arg(CFG_FORM_HTTPREQ_HOST).c_str(), CFG_HTTPREQ_HOST_LENGTH);
358+
config.httpreq.port = validate_int(server.arg(CFG_FORM_HTTPREQ_PORT), 0, 65535, CFG_HTTPREQ_DEFAULT_PORT);
359+
strncpy(config.httpreq.url, server.arg(CFG_FORM_HTTPREQ_URL).c_str(), CFG_HTTPREQ_URL_LENGTH);
360+
config.httpreq.freq = validate_int(server.arg(CFG_FORM_HTTPREQ_FREQ), 0, 86400, 0);
361+
362+
config.httpreq.trigger_adps = server.hasArg(CFG_FORM_HTTPREQ_TRIGGER_ADPS);
363+
config.httpreq.trigger_ptec = server.hasArg(CFG_FORM_HTTPREQ_TRIGGER_PTEC);
364+
config.httpreq.trigger_seuils = server.hasArg(CFG_FORM_HTTPREQ_TRIGGER_SEUILS);
365+
config.httpreq.seuil_bas = validate_int(server.arg(CFG_FORM_HTTPREQ_SEUIL_BAS), 0, 20000, 0);
366+
config.httpreq.seuil_haut = validate_int(server.arg(CFG_FORM_HTTPREQ_SEUIL_HAUT), 0, 20000, 0);
367367

368368
if (config_save())
369369
{

0 commit comments

Comments
 (0)