Compare commits
7 Commits
68db78cd5e
...
ba96f09717
Author | SHA1 | Date | |
---|---|---|---|
ba96f09717 | |||
604de64deb | |||
46ac08ac9c | |||
6f41843cd5 | |||
43ff899cde | |||
f2ddf22a5a | |||
1180e340fb |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,6 @@
|
|||||||
#specific files
|
#specific files
|
||||||
secret.h
|
secret.h
|
||||||
|
build/
|
||||||
|
|
||||||
# ---> C++
|
# ---> C++
|
||||||
# Prerequisites
|
# Prerequisites
|
||||||
|
8
.theia/launch.json
Normal file
8
.theia/launch.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
BIN
docs/Enedis-NOI-CPT_54E.pdf
Normal file
BIN
docs/Enedis-NOI-CPT_54E.pdf
Normal file
Binary file not shown.
@ -1,22 +1,43 @@
|
|||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
#include "secret.h"
|
#include "secret.h"
|
||||||
#include "tic.h"
|
#include "tic.h"
|
||||||
|
#include "ota.h"
|
||||||
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
#include <WiFiClient.h>
|
#include <WiFiClient.h>
|
||||||
#include <ESP8266WebServer.h>
|
#include <ESP8266WebServer.h>
|
||||||
|
#include <ElegantOTA.h>
|
||||||
|
#include <PubSubClient.h>
|
||||||
|
|
||||||
// Activer le Wi-Fi
|
// Activer le Wi-Fi
|
||||||
#define WIFI_ENABLE
|
#define WIFI_ENABLE
|
||||||
|
|
||||||
// Initialiser le serveur web si le Wi-Fi est activé
|
// Initialiser le serveur web si le Wi-Fi est activé
|
||||||
#ifdef WIFI_ENABLE
|
|
||||||
ESP8266WebServer server(HTTP_PORT);
|
ESP8266WebServer server(HTTP_PORT);
|
||||||
#endif
|
WiFiClient espClient;
|
||||||
|
PubSubClient mqttclient(espClient);
|
||||||
|
|
||||||
// Durée de sommeil en microsecondes (par exemple, 5 secondes)
|
unsigned long previousMillis = 0;
|
||||||
const int sleepDuration = 5 * 1000000;
|
unsigned long previousForceMillis = 0;
|
||||||
|
const long interval = 1000;
|
||||||
|
|
||||||
|
void mqttConnect() {
|
||||||
|
// Loop until we're reconnected
|
||||||
|
while (!mqttclient.connected()) {
|
||||||
|
// Create a random client ID
|
||||||
|
String clientId = MQTT_CLIENTID;
|
||||||
|
clientId += String(random(0xffff), HEX);
|
||||||
|
// Attempt to connect
|
||||||
|
if (mqttclient.connect(clientId.c_str(), MQTT_USERNAME, MQTT_PASSWORD)) {
|
||||||
|
// Once connected, publish an announcement...
|
||||||
|
mqttclient.publish(MQTT_TOPIC, "MQTT TIC interface online");
|
||||||
|
} else {
|
||||||
|
delay(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Fonction pour configurer et connecter au réseau Wi-Fi
|
// Fonction pour configurer et connecter au réseau Wi-Fi
|
||||||
void setup_wifi() {
|
void setup_wifi() {
|
||||||
@ -24,10 +45,10 @@ void setup_wifi() {
|
|||||||
// Connexion au réseau Wi-Fi
|
// Connexion au réseau Wi-Fi
|
||||||
DebugPort.println();
|
DebugPort.println();
|
||||||
DebugPort.print("Connecting to ");
|
DebugPort.print("Connecting to ");
|
||||||
DebugPort.println(ssid);
|
DebugPort.println(STASSID);
|
||||||
|
|
||||||
WiFi.mode(WIFI_STA);
|
WiFi.mode(WIFI_STA);
|
||||||
WiFi.begin(ssid, passPhrase);
|
WiFi.begin(STASSID, STAPSK);
|
||||||
|
|
||||||
int c = 0;
|
int c = 0;
|
||||||
// Attendre la connexion Wi-Fi
|
// Attendre la connexion Wi-Fi
|
||||||
@ -114,12 +135,6 @@ void setup_serial() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fonction pour mettre l'ESP8266 en mode deep sleep
|
|
||||||
void goToDeepSleep() {
|
|
||||||
DebugPort.println("Going to deep sleep...");
|
|
||||||
ESP.deepSleep(sleepDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fonction d'initialisation principale
|
// Fonction d'initialisation principale
|
||||||
void setup() {
|
void setup() {
|
||||||
|
|
||||||
@ -130,20 +145,60 @@ void setup() {
|
|||||||
// Configurer les routes du serveur
|
// Configurer les routes du serveur
|
||||||
restServerRouting();
|
restServerRouting();
|
||||||
|
|
||||||
|
ElegantOTA.begin(&server);
|
||||||
|
// ElegantOTA callbacks
|
||||||
|
ElegantOTA.onStart(onOTAStart);
|
||||||
|
ElegantOTA.onProgress(onOTAProgress);
|
||||||
|
ElegantOTA.onEnd(onOTAEnd);
|
||||||
|
|
||||||
// Démarrer le serveur HTTP
|
// Démarrer le serveur HTTP
|
||||||
DebugPort.println("Start HTTP server");
|
DebugPort.println("Start HTTP server");
|
||||||
server.begin();
|
server.begin();
|
||||||
DebugPort.println("HTTP server started");
|
DebugPort.println("HTTP server started");
|
||||||
|
|
||||||
|
//Démarrer le serveur MQTT
|
||||||
|
mqttclient.setServer(MQTT_SERVER, MQTT_PORT);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Boucle principale
|
// Boucle principale
|
||||||
void loop() {
|
void loop() {
|
||||||
|
ElegantOTA.loop();
|
||||||
server.handleClient();
|
server.handleClient();
|
||||||
readTicPort();
|
readTicPort();
|
||||||
|
|
||||||
|
unsigned long currentMillis = millis();
|
||||||
|
|
||||||
|
if (currentMillis - previousMillis >= interval) {
|
||||||
|
// save the last time you blinked the LED
|
||||||
|
previousMillis = currentMillis;
|
||||||
|
|
||||||
|
//Interface MQTT
|
||||||
|
if (!mqttclient.connected()) {
|
||||||
|
mqttConnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
mqttPublish(&mqttclient);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentMillis - previousForceMillis >= (30*interval)) {
|
||||||
|
// save the last time you blinked the LED
|
||||||
|
previousForceMillis = currentMillis;
|
||||||
|
|
||||||
|
//Interface MQTT
|
||||||
|
if (!mqttclient.connected()) {
|
||||||
|
mqttConnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
mqttForcePublish(&mqttclient);
|
||||||
|
}
|
||||||
|
mqttclient.loop();
|
||||||
|
|
||||||
|
/*
|
||||||
// Si aucune requête n'est en cours, mettre l'ESP8266 en mode deep sleep
|
// Si aucune requête n'est en cours, mettre l'ESP8266 en mode deep sleep
|
||||||
if (server.client().available() == 0) {
|
if (server.client().available() == 0) {
|
||||||
goToDeepSleep();
|
goToDeepSleep();
|
||||||
}
|
}*/
|
||||||
}
|
}
|
32
ota.cpp
Normal file
32
ota.cpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#include "ota.h"
|
||||||
|
#include "serial.h"
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
unsigned long ota_progress_millis = 0;
|
||||||
|
|
||||||
|
void onOTAStart() {
|
||||||
|
// Log when OTA has started
|
||||||
|
DebugPort.println("OTA update started!");
|
||||||
|
// <Add your own code here>
|
||||||
|
}
|
||||||
|
|
||||||
|
void onOTAProgress(size_t current, size_t final) {
|
||||||
|
// Log every 1 second
|
||||||
|
if (millis() - ota_progress_millis > 1000) {
|
||||||
|
ota_progress_millis = millis();
|
||||||
|
DebugPort.printf("OTA Progress Current: %u bytes, Final: %u bytes\n", current, final);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onOTAEnd(bool success) {
|
||||||
|
// Log when OTA has finished
|
||||||
|
if (success) {
|
||||||
|
DebugPort.println("OTA update finished successfully!");
|
||||||
|
} else {
|
||||||
|
DebugPort.println("There was an error during OTA update!");
|
||||||
|
}
|
||||||
|
// <Add your own code here>
|
||||||
|
}
|
||||||
|
|
12
ota.h
Normal file
12
ota.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef OTA
|
||||||
|
#define OTA
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void onOTAStart();
|
||||||
|
void onOTAProgress(size_t current, size_t final);
|
||||||
|
void onOTAEnd(bool success);
|
||||||
|
|
||||||
|
#endif
|
@ -16,3 +16,11 @@
|
|||||||
|
|
||||||
const char *ssid = STASSID;
|
const char *ssid = STASSID;
|
||||||
const char *passPhrase = STAPSK;
|
const char *passPhrase = STAPSK;
|
||||||
|
|
||||||
|
// MQTT Broker settings
|
||||||
|
const char *mqtt_broker = "broker.emqx.io"; // EMQX broker endpoint
|
||||||
|
const char *mqtt_topic = "emqx/esp8266/led"; // MQTT topic
|
||||||
|
const char *mqtt_username = "emqx"; // MQTT username for authentication
|
||||||
|
const char *mqtt_password = "public"; // MQTT password for authentication
|
||||||
|
const int mqtt_port = 1883; // MQTT port (TCP)
|
||||||
|
const char *mqtt_clientId = "tic_client-"
|
344
tic.cpp
344
tic.cpp
@ -1,7 +1,9 @@
|
|||||||
#include "lwip/ip.h"
|
#include "lwip/ip.h"
|
||||||
#include "tic.h"
|
#include "tic.h"
|
||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
|
#include "secret.h"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#include <PubSubClient.h>
|
||||||
|
|
||||||
// #define DEBUG 1
|
// #define DEBUG 1
|
||||||
|
|
||||||
@ -9,19 +11,21 @@ struct GroupDetail TicValues[NB_ETIQUETTE] = {};
|
|||||||
|
|
||||||
// La lecture / ecriture des données tic s'effectue sur les variables data{1,2}.
|
// La lecture / ecriture des données tic s'effectue sur les variables data{1,2}.
|
||||||
// Pour éviter des pb, il y a un swap. ce qui permet d'avoir une variable en lecture seule, une en écriture seule.
|
// Pour éviter des pb, il y a un swap. ce qui permet d'avoir une variable en lecture seule, une en écriture seule.
|
||||||
String data1 = ""; // Variable pour stocker la trame complète
|
String data1 = ""; // Variable pour stocker la trame complète
|
||||||
String data2 = ""; // Variable pour stocker la trame complète
|
String data2 = ""; // Variable pour stocker la trame complète
|
||||||
|
|
||||||
int nActiveData = 1;
|
int nActiveData = 1;
|
||||||
boolean isReceiving = false; // Indicateur pour savoir si on est dans une trame
|
boolean isReceiving = false; // Indicateur pour savoir si on est dans une trame
|
||||||
RegistreStatus regStatus; // definition du registre status
|
RegistreStatus regStatus; // definition du registre status
|
||||||
RelaisStatus relaisStatus; // definition du relais status
|
RelaisStatus relaisStatus; // definition du relais status
|
||||||
Action actionJp1[11]; // actions définie pour jour +1
|
Action actionJp1[11]; // actions définie pour jour +1
|
||||||
int nbActions;
|
int nbActions;
|
||||||
|
|
||||||
static struct GroupDetail processGroup(String group)
|
static struct GroupDetail processGroup(String group) {
|
||||||
{
|
|
||||||
struct GroupDetail gd;
|
struct GroupDetail gd;
|
||||||
|
gd.globale = group;
|
||||||
|
unsigned char computedChecksum = calcCheckSum(group);
|
||||||
|
|
||||||
int indexgrp = group.indexOf(HT);
|
int indexgrp = group.indexOf(HT);
|
||||||
gd.name = group.substring(0, indexgrp);
|
gd.name = group.substring(0, indexgrp);
|
||||||
|
|
||||||
@ -31,30 +35,33 @@ static struct GroupDetail processGroup(String group)
|
|||||||
|
|
||||||
group = group.substring(indexgrp + 1);
|
group = group.substring(indexgrp + 1);
|
||||||
indexgrp = group.indexOf(HT);
|
indexgrp = group.indexOf(HT);
|
||||||
String key = group.substring(0, indexgrp);
|
String key = "";
|
||||||
|
if (indexgrp != -1) // some parameters may have hour recording.
|
||||||
group = group.substring(indexgrp + 1);
|
|
||||||
indexgrp = group.indexOf(HT);
|
|
||||||
if (indexgrp != -1) // some parameters may have hour recording.
|
|
||||||
{
|
{
|
||||||
gd.horodate = gd.value;
|
gd.horodate = gd.value;
|
||||||
gd.value = key;
|
gd.value = group.substring(0, indexgrp);
|
||||||
|
group = group.substring(indexgrp + 1);
|
||||||
}
|
}
|
||||||
|
//gd.checksum = group;
|
||||||
|
if (group[0]==computedChecksum) {
|
||||||
|
gd.checkok = true;
|
||||||
|
} else {
|
||||||
|
gd.checkok = false;
|
||||||
|
}
|
||||||
|
|
||||||
return gd;
|
return gd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void processStge(RegistreStatus *rs, String value)
|
static void processStge(RegistreStatus *rs, String value) {
|
||||||
{
|
|
||||||
char stge[9] = "";
|
char stge[9] = "";
|
||||||
// copy in the char array
|
// copy in the char array
|
||||||
strncpy(stge, value.c_str(), 8);
|
strncpy(stge, value.c_str(), 8);
|
||||||
stge[8] = '\0';
|
stge[8] = '\0';
|
||||||
unsigned long l = strtoul(stge, NULL, 16); // Convert hex pair to unsigned long
|
unsigned long l = strtoul(stge, NULL, 16); // Convert hex pair to unsigned long
|
||||||
rs->uli = l;
|
rs->uli = l;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void processRelais(RelaisStatus *rs, String value)
|
static void processRelais(RelaisStatus *rs, String value) {
|
||||||
{
|
|
||||||
char stge[4] = "";
|
char stge[4] = "";
|
||||||
// copy in the char array
|
// copy in the char array
|
||||||
strncpy(stge, value.c_str(), 3);
|
strncpy(stge, value.c_str(), 3);
|
||||||
@ -62,24 +69,19 @@ static void processRelais(RelaisStatus *rs, String value)
|
|||||||
rs->ui = strtoul(stge, NULL, 16);
|
rs->ui = strtoul(stge, NULL, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void processActionsCalendrier(String value)
|
static void processActionsCalendrier(String value) {
|
||||||
{
|
|
||||||
nbActions = 0;
|
nbActions = 0;
|
||||||
String s = value;
|
String s = value;
|
||||||
while (s.length() > 0)
|
while (s.length() > 0) {
|
||||||
{
|
|
||||||
int index = s.indexOf(SP);
|
int index = s.indexOf(SP);
|
||||||
if (index == -1) // No space found
|
if (index == -1) // No space found
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
char data[9] = "";
|
char data[9] = "";
|
||||||
data[8] = '\0';
|
data[8] = '\0';
|
||||||
strncpy(data, s.substring(0, index).c_str(), 8);
|
strncpy(data, s.substring(0, index).c_str(), 8);
|
||||||
if (strncmp(data, NONUTILE, 8) != 0)
|
if (strncmp(data, NONUTILE, 8) != 0) {
|
||||||
{
|
|
||||||
char stge[5] = "";
|
char stge[5] = "";
|
||||||
// copy ssss field
|
// copy ssss field
|
||||||
memcpy(stge, &data[4], 4);
|
memcpy(stge, &data[4], 4);
|
||||||
@ -102,19 +104,14 @@ static void processActionsCalendrier(String value)
|
|||||||
*
|
*
|
||||||
* @param data A reference to a String containing the data frame to be processed.
|
* @param data A reference to a String containing the data frame to be processed.
|
||||||
*/
|
*/
|
||||||
static void processTrame(String &data)
|
static void processTrame(String &data) {
|
||||||
{
|
while (data.length() > 0) {
|
||||||
while (data.length() > 0)
|
|
||||||
{
|
|
||||||
// Find the position of the next carriage return (CR) character
|
// Find the position of the next carriage return (CR) character
|
||||||
int index = data.indexOf(CR);
|
int index = data.indexOf(CR);
|
||||||
// If no CR is found, exit the loop
|
// If no CR is found, exit the loop
|
||||||
if (index == -1)
|
if (index == -1) {
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// Extract the group string between the start and the CR character
|
// Extract the group string between the start and the CR character
|
||||||
String group = data.substring(1, index);
|
String group = data.substring(1, index);
|
||||||
// Process the group to extract detailed information
|
// Process the group to extract detailed information
|
||||||
@ -122,26 +119,37 @@ static void processTrame(String &data)
|
|||||||
|
|
||||||
// Check if the extracted group name matches any user-selected etiquette
|
// Check if the extracted group name matches any user-selected etiquette
|
||||||
int t = 0;
|
int t = 0;
|
||||||
while ((SelectedEtiquette[t] != gd.name) && (t < NB_ETIQUETTE))
|
while ((SelectedEtiquette[t] != gd.name) && (t < NB_ETIQUETTE)) {
|
||||||
{
|
|
||||||
++t;
|
++t;
|
||||||
}
|
}
|
||||||
// If a match is found, update the corresponding TicValues entry
|
// If a match is found, update the corresponding TicValues entry if the group confirms the checksum
|
||||||
if (t < NB_ETIQUETTE)
|
if (t < NB_ETIQUETTE) {
|
||||||
{
|
//If there is a value update
|
||||||
TicValues[t] = gd;
|
if (TicValues[t].value.compareTo(gd.value) != 0 && gd.checkok){
|
||||||
// Depending on the group name, call the appropriate processing function
|
//There is some noise on instantaneous value, filter
|
||||||
if (gd.name == "STGE")
|
if (SelectedEtiquette[t] == "SINSTS" || SelectedEtiquette[t] == "SINSTS1" || SelectedEtiquette[t] == "SINSTS2" || SelectedEtiquette[t] == "SINSTS3") {
|
||||||
{
|
int oldval = TicValues[t].value.toInt();
|
||||||
processStge(®Status, gd.value);
|
int newcal = (gd.value.toInt() + oldval) / 2;
|
||||||
}
|
if (newcal < oldval * 0.92 || newcal > oldval * 1.02) {
|
||||||
else if (gd.name == "RELAIS")
|
gd.updated = true;
|
||||||
{
|
TicValues[t] = gd;
|
||||||
processRelais(&relaisStatus, gd.value);
|
} else {
|
||||||
}
|
TicValues[t].value = String(newcal);
|
||||||
else if (gd.name == "PJOURF+1")
|
}
|
||||||
{
|
} else {
|
||||||
processActionsCalendrier(gd.value);
|
gd.updated = true;
|
||||||
|
TicValues[t] = gd;
|
||||||
|
// Depending on the group name, call the appropriate processing function
|
||||||
|
if (gd.name == "STGE") {
|
||||||
|
processStge(®Status, gd.value);
|
||||||
|
} else if (gd.name == "RELAIS") {
|
||||||
|
processRelais(&relaisStatus, gd.value);
|
||||||
|
} else if (gd.name == "PJOURF+1") {
|
||||||
|
processActionsCalendrier(gd.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
TicValues[t].updated = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data = data.substring(index + 1);
|
data = data.substring(index + 1);
|
||||||
@ -149,33 +157,30 @@ static void processTrame(String &data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *actionJp1AsJson()
|
static char *actionJp1AsJson() {
|
||||||
{
|
|
||||||
const int bufferSize = 1000;
|
const int bufferSize = 1000;
|
||||||
static char jsonBuffer[bufferSize]; // Adjust size as needed
|
static char jsonBuffer[bufferSize]; // Adjust size as needed
|
||||||
snprintf(jsonBuffer, bufferSize, "\"PJOURF+1\": [");
|
snprintf(jsonBuffer, bufferSize, "\"PJOURF+1\": [");
|
||||||
|
|
||||||
for (int i = 0; i < nbActions; i++)
|
for (int i = 0; i < nbActions; i++) {
|
||||||
{
|
|
||||||
// Format each action
|
// Format each action
|
||||||
char actionJson[256]; // To store individual action JSON string
|
char actionJson[256]; // To store individual action JSON string
|
||||||
String relaisSec = "";
|
String relaisSec = "";
|
||||||
switch ((unsigned int)actionJp1[i].action.bits.relaisSec)
|
switch ((unsigned int)actionJp1[i].action.bits.relaisSec) {
|
||||||
{
|
case 0:
|
||||||
case 0:
|
relaisSec = "no change";
|
||||||
relaisSec = "no change";
|
break;
|
||||||
break;
|
case 1:
|
||||||
case 1:
|
relaisSec = "tempo";
|
||||||
relaisSec = "tempo";
|
break;
|
||||||
break;
|
case 2:
|
||||||
case 2:
|
relaisSec = "open";
|
||||||
relaisSec = "open";
|
break;
|
||||||
break;
|
case 3:
|
||||||
case 3:
|
relaisSec = "closed";
|
||||||
relaisSec = "closed";
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
relaisSec = "unknown";
|
||||||
relaisSec = "unknown";
|
|
||||||
}
|
}
|
||||||
snprintf(actionJson, sizeof(actionJson),
|
snprintf(actionJson, sizeof(actionJson),
|
||||||
" { \"startTime\": \"%c%c%c%c\", "
|
" { \"startTime\": \"%c%c%c%c\", "
|
||||||
@ -189,12 +194,9 @@ static char *actionJp1AsJson()
|
|||||||
actionJp1[i].action.bits.relais1, actionJp1[i].action.bits.index);
|
actionJp1[i].action.bits.relais1, actionJp1[i].action.bits.index);
|
||||||
|
|
||||||
// Append the current action's JSON to the overall JSON buffer
|
// Append the current action's JSON to the overall JSON buffer
|
||||||
if (i == (nbActions - 1))
|
if (i == (nbActions - 1)) { // Last item, no comma at the end
|
||||||
{ // Last item, no comma at the end
|
|
||||||
strncat(jsonBuffer, actionJson, bufferSize - strlen(jsonBuffer) - 1);
|
strncat(jsonBuffer, actionJson, bufferSize - strlen(jsonBuffer) - 1);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
strncat(jsonBuffer, actionJson, bufferSize - strlen(jsonBuffer) - 1);
|
strncat(jsonBuffer, actionJson, bufferSize - strlen(jsonBuffer) - 1);
|
||||||
strncat(jsonBuffer, ",", bufferSize - strlen(jsonBuffer) - 1);
|
strncat(jsonBuffer, ",", bufferSize - strlen(jsonBuffer) - 1);
|
||||||
}
|
}
|
||||||
@ -205,10 +207,9 @@ static char *actionJp1AsJson()
|
|||||||
return jsonBuffer;
|
return jsonBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *relaisStatusAsJson(RelaisStatusBits *status, String rawValue)
|
static char *relaisStatusAsJson(RelaisStatusBits *status, String rawValue) {
|
||||||
{
|
|
||||||
// Pre-allocate buffer large enough to hold the JSON string
|
// Pre-allocate buffer large enough to hold the JSON string
|
||||||
static char response[150]; // Adjust size as needed
|
static char response[150]; // Adjust size as needed
|
||||||
// Use snprintf to construct the JSON string efficiently
|
// Use snprintf to construct the JSON string efficiently
|
||||||
snprintf(response, sizeof(response),
|
snprintf(response, sizeof(response),
|
||||||
"\"RELAIS\": "
|
"\"RELAIS\": "
|
||||||
@ -235,10 +236,9 @@ static char *relaisStatusAsJson(RelaisStatusBits *status, String rawValue)
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *registreStatusAsJson(RegistreStatusBits *status, String rawValue)
|
static char *registreStatusAsJson(RegistreStatusBits *status, String rawValue) {
|
||||||
{
|
|
||||||
// Pre-allocate buffer large enough to hold the JSON string
|
// Pre-allocate buffer large enough to hold the JSON string
|
||||||
static char response[1000]; // Adjust size as needed
|
static char response[1000]; // Adjust size as needed
|
||||||
|
|
||||||
// Use snprintf to construct the JSON string efficiently
|
// Use snprintf to construct the JSON string efficiently
|
||||||
snprintf(response, sizeof(response),
|
snprintf(response, sizeof(response),
|
||||||
@ -286,28 +286,19 @@ static char *registreStatusAsJson(RegistreStatusBits *status, String rawValue)
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
String ticValuesAsJson()
|
String ticValuesAsJson() {
|
||||||
{
|
|
||||||
String response = "{";
|
String response = "{";
|
||||||
|
|
||||||
for (int i = 0; i < NB_ETIQUETTE; ++i)
|
for (int i = 0; i < NB_ETIQUETTE; ++i) {
|
||||||
{
|
|
||||||
|
|
||||||
if (SelectedEtiquette[i] == "STGE")
|
if (SelectedEtiquette[i] == "STGE") {
|
||||||
{
|
|
||||||
response += registreStatusAsJson(®Status.bits, TicValues[i].value);
|
response += registreStatusAsJson(®Status.bits, TicValues[i].value);
|
||||||
}
|
} else if (SelectedEtiquette[i] == "RELAIS") {
|
||||||
else if (SelectedEtiquette[i] == "RELAIS")
|
|
||||||
{
|
|
||||||
response += relaisStatusAsJson(&relaisStatus.bits, TicValues[i].value);
|
response += relaisStatusAsJson(&relaisStatus.bits, TicValues[i].value);
|
||||||
}
|
} else if (SelectedEtiquette[i] == "PJOURF+1") {
|
||||||
else if (SelectedEtiquette[i] == "PJOURF+1")
|
|
||||||
{
|
|
||||||
response += actionJp1AsJson();
|
response += actionJp1AsJson();
|
||||||
}
|
} else {
|
||||||
else
|
static char jres[150]; // Adjust size as needed
|
||||||
{
|
|
||||||
static char jres[150]; // Adjust size as needed
|
|
||||||
|
|
||||||
// Use snprintf to construct the JSON string efficiently
|
// Use snprintf to construct the JSON string efficiently
|
||||||
snprintf(jres, sizeof(jres),
|
snprintf(jres, sizeof(jres),
|
||||||
@ -317,8 +308,7 @@ String ticValuesAsJson()
|
|||||||
response += jres;
|
response += jres;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i < (NB_ETIQUETTE - 1))
|
if (i < (NB_ETIQUETTE - 1)) {
|
||||||
{
|
|
||||||
response += ',';
|
response += ',';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -326,20 +316,16 @@ String ticValuesAsJson()
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
String ticBasicValuesAsJson()
|
String ticBasicValuesAsJson() {
|
||||||
{
|
|
||||||
String response = "{";
|
String response = "{";
|
||||||
|
|
||||||
for (int i = 0; i < NB_ETIQUETTE; ++i)
|
for (int i = 0; i < NB_ETIQUETTE; ++i) {
|
||||||
{
|
|
||||||
|
|
||||||
if (SelectedEtiquette[i] == "LTARF" || SelectedEtiquette[i] == "EAST" || SelectedEtiquette[i] == "EASF01" || SelectedEtiquette[i] == "EASF02" || SelectedEtiquette[i] == "EASF03" || SelectedEtiquette[i] == "EASF04" || SelectedEtiquette[i] == "EASD01" || SelectedEtiquette[i] == "EASD02" || SelectedEtiquette[i] == "EASD03" || SelectedEtiquette[i] == "EASD04" || SelectedEtiquette[i] == "EAIT" || SelectedEtiquette[i] == "ERQ1" || SelectedEtiquette[i] == "ERQ2" || SelectedEtiquette[i] == "ERQ3" || SelectedEtiquette[i] == "ERQ4" || SelectedEtiquette[i] == "IRMS1" || SelectedEtiquette[i] == "IRMS2" || SelectedEtiquette[i] == "IRMS3" || SelectedEtiquette[i] == "URMS1" || SelectedEtiquette[i] == "URMS2" || SelectedEtiquette[i] == "URMS3" || SelectedEtiquette[i] == "SINSTS" || SelectedEtiquette[i] == "SINSTSI" || SelectedEtiquette[i] == "SINSTS1" || SelectedEtiquette[i] == "SINSTS2" || SelectedEtiquette[i] == "SINSTS3" || SelectedEtiquette[i] == "SINSTSI")
|
if (SelectedEtiquette[i] == "LTARF" || SelectedEtiquette[i] == "EAST" || SelectedEtiquette[i] == "EASF01" || SelectedEtiquette[i] == "EASF02" || SelectedEtiquette[i] == "EASF03" || SelectedEtiquette[i] == "EASF04" || SelectedEtiquette[i] == "EASD01" || SelectedEtiquette[i] == "EASD02" || SelectedEtiquette[i] == "EASD03" || SelectedEtiquette[i] == "EASD04" || SelectedEtiquette[i] == "EAIT" || SelectedEtiquette[i] == "ERQ1" || SelectedEtiquette[i] == "ERQ2" || SelectedEtiquette[i] == "ERQ3" || SelectedEtiquette[i] == "ERQ4" || SelectedEtiquette[i] == "IRMS1" || SelectedEtiquette[i] == "IRMS2" || SelectedEtiquette[i] == "IRMS3" || SelectedEtiquette[i] == "URMS1" || SelectedEtiquette[i] == "URMS2" || SelectedEtiquette[i] == "URMS3" || SelectedEtiquette[i] == "SINSTS" || SelectedEtiquette[i] == "SINSTSI" || SelectedEtiquette[i] == "SINSTS1" || SelectedEtiquette[i] == "SINSTS2" || SelectedEtiquette[i] == "SINSTS3" || SelectedEtiquette[i] == "SINSTSI") {
|
||||||
{
|
|
||||||
|
|
||||||
static char jres[150]; // Adjust size as needed
|
static char jres[150]; // Adjust size as needed
|
||||||
|
|
||||||
if (response != "{")
|
if (response != "{") {
|
||||||
{
|
|
||||||
response += ",";
|
response += ",";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -355,6 +341,27 @@ String ticBasicValuesAsJson()
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mqttPublish(PubSubClient *mqttclient) {
|
||||||
|
for (int i = 0; i < NB_ETIQUETTE; ++i) {
|
||||||
|
if (TicValues[i].updated) {
|
||||||
|
String topic = MQTT_TOPIC;
|
||||||
|
topic += "/",
|
||||||
|
topic += SelectedEtiquette[i];
|
||||||
|
mqttclient->publish(topic.c_str(), TicValues[i].value.c_str());
|
||||||
|
TicValues[i].updated = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mqttForcePublish(PubSubClient *mqttclient) {
|
||||||
|
for (int i = 0; i < NB_ETIQUETTE; ++i) {
|
||||||
|
String topic = MQTT_TOPIC;
|
||||||
|
topic += "/",
|
||||||
|
topic += SelectedEtiquette[i];
|
||||||
|
mqttclient->publish(topic.c_str(), TicValues[i].value.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads data from the TicPort and processes it according to specific control characters.
|
* Reads data from the TicPort and processes it according to specific control characters.
|
||||||
*
|
*
|
||||||
@ -369,76 +376,56 @@ String ticBasicValuesAsJson()
|
|||||||
*
|
*
|
||||||
* The built-in LED is used to indicate the state of data reception.
|
* The built-in LED is used to indicate the state of data reception.
|
||||||
*/
|
*/
|
||||||
void readTicPort()
|
void readTicPort() {
|
||||||
{
|
|
||||||
// Check TicPort availability
|
// Check TicPort availability
|
||||||
if (TicPort.available())
|
if (TicPort.available()) {
|
||||||
{
|
byte incomingByte = TicPort.read(); // Read a byte from the TicPort
|
||||||
byte incomingByte = TicPort.read(); // Read a byte from the TicPort
|
|
||||||
// Check if the incoming byte is the End Of Transmission (EOT) character
|
// Check if the incoming byte is the End Of Transmission (EOT) character
|
||||||
if (incomingByte == EOT)
|
if (incomingByte == EOT) {
|
||||||
{
|
|
||||||
// Force the end of transmission
|
// Force the end of transmission
|
||||||
// Reject everything
|
// Reject everything
|
||||||
isReceiving = false;
|
isReceiving = false;
|
||||||
digitalWrite(LED_BUILTIN, HIGH); // Turn the built-in LED to indicate the end of transmission
|
digitalWrite(LED_BUILTIN, HIGH); // Turn the built-in LED to indicate the end of transmission
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the system is currently receiving data
|
// Check if the system is currently receiving data
|
||||||
if (isReceiving)
|
if (isReceiving) {
|
||||||
{
|
|
||||||
// Check if the end of the frame is reached (ETX character)
|
// Check if the end of the frame is reached (ETX character)
|
||||||
if (incomingByte == ETX)
|
if (incomingByte == ETX) {
|
||||||
{
|
|
||||||
// Extract the useful part of the frame
|
// Extract the useful part of the frame
|
||||||
if (nActiveData == 1)
|
if (nActiveData == 1) {
|
||||||
{
|
processTrame(data1); // Process the data in data1
|
||||||
processTrame(data1); // Process the data in data1
|
} else {
|
||||||
}
|
processTrame(data2); // Process the data in data2
|
||||||
else
|
|
||||||
{
|
|
||||||
processTrame(data2); // Process the data in data2
|
|
||||||
}
|
}
|
||||||
// Indicate that the data reception is complete
|
// Indicate that the data reception is complete
|
||||||
isReceiving = false;
|
isReceiving = false;
|
||||||
digitalWrite(LED_BUILTIN, HIGH);
|
digitalWrite(LED_BUILTIN, HIGH);
|
||||||
// Debugging information: Print the extracted data
|
// Debugging information: Print the extracted data
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
for (int i = 0; i < NB_ETIQUETTE; ++i)
|
for (int i = 0; i < NB_ETIQUETTE; ++i) {
|
||||||
{
|
|
||||||
DebugPort.print(TicValues[i].name);
|
DebugPort.print(TicValues[i].name);
|
||||||
DebugPort.print(":");
|
DebugPort.print(":");
|
||||||
DebugPort.println(TicValues[i].value);
|
DebugPort.println(TicValues[i].value);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// Add the incoming byte to the current frame
|
// Add the incoming byte to the current frame
|
||||||
if (nActiveData == 1)
|
if (nActiveData == 1) {
|
||||||
{
|
data1 += (char)incomingByte; // Append the byte to data1
|
||||||
data1 += (char)incomingByte; // Append the byte to data1
|
} else {
|
||||||
}
|
data2 += (char)incomingByte; // Append the byte to data2
|
||||||
else
|
|
||||||
{
|
|
||||||
data2 += (char)incomingByte; // Append the byte to data2
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// Look for the start of the frame (STX character)
|
// Look for the start of the frame (STX character)
|
||||||
if (incomingByte == STX)
|
if (incomingByte == STX) {
|
||||||
{
|
|
||||||
isReceiving = true;
|
isReceiving = true;
|
||||||
digitalWrite(LED_BUILTIN, LOW);
|
digitalWrite(LED_BUILTIN, LOW);
|
||||||
if (nActiveData == 1)
|
if (nActiveData == 1) {
|
||||||
{
|
|
||||||
data2 = "";
|
data2 = "";
|
||||||
nActiveData = 2;
|
nActiveData = 2;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
data1 = "";
|
data1 = "";
|
||||||
nActiveData = 1;
|
nActiveData = 1;
|
||||||
}
|
}
|
||||||
@ -446,3 +433,46 @@ void readTicPort()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function to calculate the checksum
|
||||||
|
unsigned char calcCheckSum(const String &data) {
|
||||||
|
unsigned int sum = 0;
|
||||||
|
|
||||||
|
// Calculate the sum of ASCII values
|
||||||
|
for (size_t i = 0; i < data.length() - 1; ++i) {
|
||||||
|
sum += data[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Truncate the sum to 6 bits
|
||||||
|
sum &= 0x3F;
|
||||||
|
|
||||||
|
// Add 0x20 to get the final checksum
|
||||||
|
unsigned char checksum = sum + 0x20;
|
||||||
|
|
||||||
|
return checksum;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char calcCheckSum2(GroupDetail *data) {
|
||||||
|
char c;
|
||||||
|
uint sum = 2 * HT;
|
||||||
|
|
||||||
|
if (data->name.length() && data->value.length()) {
|
||||||
|
for (char &c : data->name) {
|
||||||
|
if (c >= 0x20 && c <= 0x7E) {
|
||||||
|
sum += c;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (char &c : data->value) {
|
||||||
|
if (c >= 0x20 && c <= 0x7E) {
|
||||||
|
sum += c;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (sum & 0x3f) + 0x20;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
8
tic.h
8
tic.h
@ -4,6 +4,7 @@
|
|||||||
#define TIC_DEF
|
#define TIC_DEF
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#include <PubSubClient.h>
|
||||||
|
|
||||||
#define TIC
|
#define TIC
|
||||||
|
|
||||||
@ -12,6 +13,7 @@
|
|||||||
#define HTTP_PORT 80 //port
|
#define HTTP_PORT 80 //port
|
||||||
|
|
||||||
// Définition des constantes pour les délimiteurs de trame TIC
|
// Définition des constantes pour les délimiteurs de trame TIC
|
||||||
|
//Uniquement le mode standard est supporté
|
||||||
//CF document ENEDIS
|
//CF document ENEDIS
|
||||||
#define STX 0x02 // Début de la trame : 0x02 (<STX>)
|
#define STX 0x02 // Début de la trame : 0x02 (<STX>)
|
||||||
#define ETX 0x03 // Fin de la trame : 0x03 (<ETX>) End Of Text
|
#define ETX 0x03 // Fin de la trame : 0x03 (<ETX>) End Of Text
|
||||||
@ -28,9 +30,12 @@
|
|||||||
|
|
||||||
// Structure pour stocker les détails d'un groupe TIC
|
// Structure pour stocker les détails d'un groupe TIC
|
||||||
struct GroupDetail {
|
struct GroupDetail {
|
||||||
|
String globale;
|
||||||
String name; // Nom de l'étiquette
|
String name; // Nom de l'étiquette
|
||||||
String value; // Valeur associée à l'étiquette
|
String value; // Valeur associée à l'étiquette
|
||||||
String horodate; // Horodatage de la valeur
|
String horodate; // Horodatage de la valeur
|
||||||
|
bool updated;
|
||||||
|
bool checkok; //status of checksum
|
||||||
};
|
};
|
||||||
|
|
||||||
// Structure pour les bits de statut du registre
|
// Structure pour les bits de statut du registre
|
||||||
@ -159,4 +164,7 @@ const static String kPointeMobile[4] = { "no", "PM1", "PM2", "PM3" };
|
|||||||
void readTicPort();
|
void readTicPort();
|
||||||
String ticValuesAsJson();
|
String ticValuesAsJson();
|
||||||
String ticBasicValuesAsJson();
|
String ticBasicValuesAsJson();
|
||||||
|
void mqttPublish(PubSubClient *mqttclient);
|
||||||
|
void mqttForcePublish(PubSubClient *mqttclient);
|
||||||
|
unsigned char calcCheckSum(const String &data);//(GroupDetail *data);
|
||||||
#endif
|
#endif
|
Loading…
Reference in New Issue
Block a user