Files
Arduino/ESP8266_BATTERIE_INJECTION/ESP8266_BATTERIE_INJECTION.ino
2025-07-01 18:25:48 +02:00

1439 lines
38 KiB
C++

//#include <ArduinoJson.h>
#include "math.h"
#include <EEPROM.h>
//#include <Ticker.h>
#include <ArduinoJson.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <time.h>
#include <Ticker.h>
#include "common.h"
// FORCE BUFFER to 512 bytes / 64 default is too low
#define _SS_MAX_RX_BUFF 512
String devicename = "Victron Blue Solar";
#define PRINT_EVERY_SECONDS 10
// Time to sleep (in seconds):
const int sleepTimeS = 10;
// Your WiFi credentials.
// Set password to "" for open networks.
const char* ssid = "Livebox-37cc";
const char* pass = "8A6060920A8A86896F770F2C47";
const char* adminPassword = "setaou"; // Mot de passe pour la connexion
//#define PIN_TENSION A0
//#define PIN_HALL A0
//
//#define PIN_POWER 13 // D7
#define PIN_INJECTION 14 // D6
#define PIN_CHARGE 12 // D5
// #define PIN_BATTERIE 16 // D0
//#define PIN_DIMMER_OUTPUT 18 // D8
//#define PIN_DIMMER_ZEROCROSS 19 // 12 // D6 for boards with CHANGEBLE input pins
#ifdef ESP8266
#define PIN_SOFTWARE_SERIAL_RX D4 // GPIO2
#define PIN_SOFTWARE_SERIAL_TX D2 // GPIO4
#elif defined(ESP32)
//#define PZEM true
#define PIN_LED 2
#define SERIAL_BLUE_SOLAR true
#define SERIAL_XY6020L true
//#define SERIAL_XY6020L_2 true
#define PIN_SOFTWARE_SERIAL_RX 4
#define PIN_SOFTWARE_SERIAL_TX 5
#define PIN_SOFTWARE_SERIAL_RX2 25
#define PIN_SOFTWARE_SERIAL_TX2 26
#define PIN_SOFTWARE_SERIAL_TX3 32
#define PIN_SOFTWARE_SERIAL_RX3 33
#define PIN_REGULATION 21
// #define PIN_DALLAS 26 // D5
//#define PIN_HALL 33
#endif
//#define PIN_TENSION A0
//#define PIN_HALL A0
//#define PIN_DALLAS 14 // D5
//#define PIN_POWER 0 // D3
//#define PIN_INJECTION 3 // RX
//#define PIN_CHARGE 4 // D2
//#define PIN_BATTERIE 5 // D1
//#define PIN_DIMMER_OUTPUT D7 // D7
//#define PIN_DIMMER_ZEROCROSS D6 // D6 for boards with CHANGEBLE input pins
//#define PIN_REGULATION D8
// --------------
// XY6020L
// --------------
#include "xy.h"
// -------------------------------------------------------------
// TUYA : pour lire la consommation via Wifi et un micro service
// Ou utiliser PZEM
// -------------------------------------------------------------
#define TUYA true
#define MICRO_SERVICE_ADDRESS "http://192.168.1.3:5000/control"
//IPAddress gateway(192, 168, 1, 1);
//IPAddress subnet(255, 255, 0, 0);
//IPAddress DNS(192, 168, 1, 1);
bool led;
int pwm;
const char* host = "192.168.1.3";
const int port = 81;
const char* apiEndpoint = "/json.htm?type=command&param=getSunRiseSet";
unsigned long lastUpdateTime = 0;
const unsigned long updateInterval = 5 * 60 * 1000; // 5 minutes en millisecondes
String date = "";
String heure = "";
// 192.168.1.18 ==> Solarblue
#define HOSTNAME "ESP8266_SOLAR_BLUE"
// 192.168.1.11 ==> Batterie
// #define HOSTNAME "ESP8266_ECO_WORTHY"
int current_regulation = 0;// variable to hold speed value
const int pins[] = {
#ifdef PIN_POWER
PIN_POWER,
#endif
PIN_INJECTION,
PIN_CHARGE
#ifdef PIN_BATTERIE
, PIN_BATTERIE
#endif
}; // Exemple: D1, D2, D3
//////////////////////////////////////////
// DIMMER
/////////////////////////////////////////
#ifdef PIN_DIMMER_OUTPUT
#include "dimmer.h"
// Dimmer
#include <RBDdimmer.h>//
#define pas 5
dimmerLamp dimmer(PIN_DIMMER_OUTPUT, PIN_DIMMER_ZEROCROSS); //initialase port for dimmer for ESP8266, ESP32, Arduino due boards
//dimmerLamp dimmer(PIN_DIMMER_OUTPUT); //initialase port for dimmer for MEGA, Leonardo, UNO, Arduino M0, Arduino Zero
#endif
//////////////////////////////////////////
// HALL
//////////////////////////////////////////
#ifdef PIN_HALL
#include "hall.h"
#endif
//////////////////////////////////////////
// DALLAS
/////////////////////////////////////////
#ifdef PIN_DALLAS
float temperature = 0;
#include <OneWire.h>
#include <DallasTemperature.h>
#define onewirepin PIN_DALLAS // DATA pin of DS18B20 wired to pin DALLAS of Arduino
OneWire oneWire(onewirepin);
DallasTemperature sensors(&oneWire);
// find the DeviceAddress of your DS18B20 with the sketch DS18B20_address_reporter
// then replace the 8-byte ID below with the reported one
DeviceAddress Probe = { 0x28, 0xFF, 0x61, 0x1D, 0x76, 0x04, 0x00, 0x34 };
float printTemperature(DeviceAddress deviceAddress);
#endif
void blink();
//////////////////////////////////////////
// Victron Blue Solar
/////////////////////////////////////////
#include "config.h"
#ifdef SERIAL_BLUE_SOLAR
// #define rxPin PIN_SOFTWARE_SERIAL_RX // D7
// #define txPin PIN_SOFTWARE_SERIAL_TX // D8 // TX Not used
// Serial port configuration
//Baud rate:19200
//Data bits: 8
//Parity: None
//Stop bits: 1
//Flow control: None
#ifdef ESP8266
SoftwareSerial victronSerial(PIN_SOFTWARE_SERIAL_RX, PIN_SOFTWARE_SERIAL_TX);
#endif // via the USB serial provided by the NodeMCU.
// void initialize_arrays() {
// memset(recv_label, 0, sizeof(recv_label));
// memset(recv_value, 0, sizeof(recv_value));
// memset(value, 0, sizeof(value));
// }
#endif
//////////////////////////////////////////
// Ticker
//////////////////////////////////////////
#define MYTZ TZ_Europe_Paris
struct tm timeinfo;
// Variables for storing time
time_t currentTime;
time_t localTime;
unsigned long lastSyncMillis;
unsigned long analogReadInterval = 10000;
unsigned long lastTimeRead = millis();
#include "victron.h"
#include "html.h"
#include "regulation.h"
#include "tuya.h"
// ----------------
// PZEM for arduino
// -----------------
#ifdef PZEM
#include <PZEM004Tv30.h>
#ifdef ESP8266
#define PIN_PZEM_1 D5
#define PIN_PZEM_2 D6
PZEM004Tv30 pzem(PIN_PZEM_1, PIN_PZEM_2);
#elif defined(ESP32)
#define RXD2 16
#define TXD2 17
PZEM004Tv30 pzem(&Serial2);
#endif
double voltage;
double current;
double pf;
double power;
double energy;
double frequency;
#endif
void setup() {
// initialize digital pin LED_BUILTIN as an output.
Serial.begin(115200);
#ifdef PZEM
#ifdef ESP32
Serial2.begin(9600, SERIAL_8N1, RXD2, TXD2);
#endif
#endif
#ifdef PIN_TENSION
pinMode(PIN_TENSION, INPUT);
#endif
#ifdef PIN_HALL
pinMode(PIN_HALL, INPUT);
delay(200);
getHall();
#endif
#ifdef PIN_POWER
pinMode(PIN_POWER, OUTPUT);
#endif
#ifdef PIN_LED
pinMode(PIN_LED, OUTPUT);
#endif
pinMode(PIN_INJECTION, OUTPUT);
pinMode(PIN_CHARGE, OUTPUT);
#ifdef PIN_BATTERIE
pinMode(PIN_BATTERIE, OUTPUT);
#endif
#ifdef PIN_REGULATION
#ifdef ESP32
// ledcAttachPin(PIN_REGULATION, 0); // assign a led pins to a channel
// // Initialize channels
// // channels 0-15, resolution 1-16 bits, freq limits depend on resolution
// // ledcSetup(uint8_t channel, uint32_t freq, uint8_t resolution_bits);
// ledcSetup(0, 4000, 8); // 12 kHz PWM, 8-bit resolution
pinMode(PIN_REGULATION, OUTPUT);
#else
pinMode(PIN_REGULATION, OUTPUT); // set mtorPin as output
#endif
#endif
#ifdef SERIAL_BLUE_SOLAR
#ifdef ESP32
Serial1.begin(19200, SERIAL_8N1, PIN_SOFTWARE_SERIAL_RX, PIN_SOFTWARE_SERIAL_TX); // Rx = 4, Tx = 5 will work for ESP32, S2, S3 and C3
#else
// Serial port configuration
//Baud rate:19200
//Data bits: 8
//Parity: None
//Stop bits: 1
//Flow control: None
victronSerial.begin(19200); //, SWSERIAL_8N1);
#endif
#endif
char tmpBuf[30]; // text buffer for serial messages
#ifdef SERIAL_XY6020L
#ifdef ESP32
xy6020l xy(Serial2, 0x01, 50, XY6020_OPT_SKIP_SAME_HREG_VALUE | XY6020_OPT_NO_HREG_UPDATE);
Serial2.begin(115200, SERIAL_8N1, PIN_SOFTWARE_SERIAL_RX2, PIN_SOFTWARE_SERIAL_TX2); // Rx = 4, Tx = 5 will work for ESP32, S2, S3 and C3
Serial.println("HardwareSerial (Serial) initialisé");
// 12 V supply
Mem.Nr = MemIdx;
Mem.VSet = 0; // 10v
Mem.ISet = 500;
Mem.sLVP = 1000;
Mem.sOVP = 1300;
Mem.sOCP = 620;
Mem.sOPP = 1040;
Mem.sOHPh = 0;
Mem.sOHPm = 0;
Mem.sOAH = 0;
Mem.sOWH = 0;
Mem.sOTP = 61;
Mem.sINI = 0;
xy.SetMemory(Mem);
xy.PrintMemory(Mem);
// START DISABLE ALL
xy.setOutput(false);
xy.setCV(0);
xy.setCC(0);
sprintf( tmpBuf, "Modele 1 :%04X Version 1 :%04X\n", xy.getModel(), xy.getVersion() );
Serial.print(tmpBuf);
#endif
#endif
#ifdef SERIAL_XY6020L_2
#ifdef ESP32
// xy6020l xy2(Serial3, 0x01, 50, XY6020_OPT_SKIP_SAME_HREG_VALUE | XY6020_OPT_NO_HREG_UPDATE);
Serial3.begin(115200); //, SERIAL_8N1); //, PIN_SOFTWARE_SERIAL_RX2, PIN_SOFTWARE_SERIAL_TX2); // Rx = 4, Tx = 5 will work for ESP32, S2, S3 and C3
Serial.println("SoftwareSerial (Serial3) initialisé à 115200 baud.");
// 12 V supply
Mem2.Nr = MemIdx;
Mem2.VSet = 0; // 10v
Mem2.ISet = 500;
Mem2.sLVP = 1000;
Mem2.sOVP = 1300;
Mem2.sOCP = 619;
Mem2.sOPP = 1041;
Mem2.sOHPh = 0;
Mem2.sOHPm = 0;
Mem2.sOAH = 0;
Mem2.sOWH = 0;
Mem2.sOTP = 60;
Mem2.sINI = 0;
xy2.SetMemory(Mem2);
xy2.PrintMemory(Mem2);
// START DISABLE ALL
xy2.setOutput(false);
xy2.setCV(0);
xy2.setCC(0);
sprintf( tmpBuf, "Modele 2 :%04X Version 2 :%04X\n", xy.getModel(), xy.getVersion() );
Serial.print(tmpBuf);
#endif
#endif
delay(10);
handleStop();
// Connectez-vous au réseau WiFi
WiFi.begin(ssid, pass);
Serial.println("Connexion au WiFi en cours.");
while (WiFi.status() != WL_CONNECTED) {
digitalWrite(PIN_LED, LOW);
delay(500);
Serial.print(".");
digitalWrite(PIN_LED, HIGH);
delay(500);
}
Serial.println("");
Serial.println("Connecté au réseau WiFi");
Serial.println(WiFi.localIP());
// Définissez les gestionnaires pour les différentes URL
server.on("/", HTTP_GET, handleRoot);
server.on("/stop", HTTP_GET, handleStop);
server.on("/start", HTTP_GET, handleStart);
server.on("/injection", HTTP_GET, handleInjection);
server.on("/stopInjection", HTTP_GET, handleStopInjection);
server.on("/charge", HTTP_GET, handleCharge);
server.on("/stopCharge", HTTP_GET, handleStopCharge);
server.on("/coupe", HTTP_GET, handleCoupe);
server.on("/getData", HTTP_GET, handleData);
server.on("/getDebug", HTTP_GET, handleDebug);
server.on("/getVictron", HTTP_GET, handleVictron);
// Configuration des routes du serveur web
server.on("/settings", HTTP_GET, handleSettings);
server.on("/save", HTTP_POST, handleSave);
//server.on("/test", HTTP_GET, handleTestConnection);
server.on("/slider", HTTP_POST, handleUpdate);
#ifdef SERIAL_BLUE_SOLAR
// Initialisation de l'EEPROM
EEPROM.begin(EEPROM_SIZE); //sizeof(To_Store) + sizeof(config));
// Lire la valeur stockée dans l'EEPROM
EEPROM.get(TO_STORE_ADDRESS, to_store);
// Lire la configuration
readConfiguration();
// initialize_arrays();
for (int i = 0; i < maxSize; i++) {
if (to_store.tensions[i] > 30000 || to_store.tensions[i] < 10) {
to_store.tensions[i] = 26000;
}
// to_store.hour[i] = 0;
// to_store.min[i] = 0;
}
if (to_store.total_elements > maxSize) {
to_store.total_elements = 0;
}
#endif
configTime(0, 0, "pool.ntp.org", "time.nist.gov");
// Synchronize time
synchronizeTime();
// Store the current time and millis
time(&currentTime);
lastSyncMillis = millis();
// Dimmer
#ifdef PIN_DIMMER_OUTPUT
server.on("/minus", minus);
server.on("/plus", plus);
server.on("/exact", exact);
server.on("/zero", stopPWM);
#endif
#ifdef PIN_REGULATION
server.on("/minus_reg", minus_reg);
server.on("/plus_reg", plus_reg);
server.on("/exact_reg", exact_reg);
server.on("/zero_reg", stop_reg);
#endif
//initialize variables__________________
pwm = 0;
led = 0;
// Dimmer
Serial.println("Dimmer Program is starting...");
delay(1000);
#ifdef PIN_DIMMER_OUTPUT
dimmer.begin(NORMAL_MODE, ON); //dimmer initialisation: name.begin(MODE, STATE)
Serial.println("Set value");
dimmer.setState(ON_OFF_typedef::OFF);
dimmer.setPower(pwm); // setPower(0-100%);
#endif
// Démarrer le serveur
server.begin();
Serial.println("Serveur Web démarré");
#ifdef PIN_DALLAS
sensors.begin (); // Initialize the sensor and set resolution level
sensors.setResolution(Probe, 10);
delay(1000);
Serial.println();
Serial.print ("Number of Devices found on bus = ");
Serial.println (sensors.getDeviceCount());
Serial.print ("Getting temperatures... ");
Serial.println ();
#endif
#ifdef PZEM
Serial.println("-------PZEM-----------"); // Start Print Test to Line 2
pzem.resetEnergy();
delay(1000);
#endif
///////////////////////////////////
// UPDATE OTA
///////////////////////////////////
// Port defaults to 8266
ArduinoOTA.setPort(8266);
// Hostname defaults to esp8266-[ChipID]
#ifdef HOSTNAME
ArduinoOTA.setHostname(HOSTNAME);
#endif
// No authentication by default
// ArduinoOTA.setPassword("admin");
// Password can be set with it's md5 value as well
// MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
// ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");
ArduinoOTA.onStart([]() {
Serial.println("Start");
});
ArduinoOTA.onEnd([]() {
Serial.println("\nEnd");
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
else if (error == OTA_END_ERROR) Serial.println("End Failed");
});
ArduinoOTA.begin();
// timer.start();
slider_on = false;
}
void loop() {
// getJson();
ArduinoOTA.handle();
// Gérez les requêtes du serveur
server.handleClient();
//timer.update();
#ifdef SERIAL_BLUE_SOLAR
// Receive information on Serial from MPPT
recvWithEndMarker();
handleNewData();
printData();
#endif
#ifdef SERIAL_XY6020L
xy.task();
// if(xy.HRegUpdated()) {
// double vIn = xy.getInV();
// xy.setCV(500);
// }
#endif
#ifdef SERIAL_XY6020L_2
xy2.task();
// if(xy.HRegUpdated()) {
// double vIn = xy.getInV();
// xy.setCV(500);
// }
#endif
if (millis() - lastTimeRead >= analogReadInterval)//read ldr periodically
{
traitement();
lastTimeRead = millis();
}
if (millis() - lastUpdateTime >= updateInterval || lastUpdateTime == 0) {
// digitalWrite(PIN_LED, HIGH);
// delay(500);
unsigned long currentMillis = millis();
time_t elapsedTime = (currentMillis - lastSyncMillis) / 1000;
localTime = currentTime + elapsedTime;
// Convert to struct tm
struct tm* timeinfo = localtime(&localTime);
// Print the current time
if (timeinfo) {
Serial.printf("Current time: %02d:%02d:%02d\n", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
} else {
last_message = "Failed to obtain time";
Serial.println("Failed to obtain time");
}
#ifdef SERIAL_BLUE_SOLAR
addTension(timeinfo, String(value[3]).toInt());
cleanValues();
#endif
//#ifdef SERIAL_XY6020L
// printMem();
//#endif
//#ifdef SERIAL_XY6020L_2
// printMem();
//#endif
// Mettre à jour le temps de la dernière mise à jour
lastUpdateTime = millis();
#ifdef PIN_TENSION
getTension();
#endif
// digitalWrite(PIN_LED, LOW);
// delay(500);
}
// ///////////////////////////////////////////////////////////////
#ifdef SERIAL_XY6020L
#endif
// //////////////////////////////////////////////////////////////
}
void handleRoot() {
// IPAddress clientIP = server.client().remoteIP();
// Serial.println("Client IP: " + clientIP.toString());
//
// if (!isLocalIP(clientIP)) {
// // Vérifie si le mot de passe est correct
// if (server.hasArg("password")) {
// String passwordParam = server.arg("password");
// if (passwordParam == adminPassword) {
// server.send(200, "text/html", "<h1>Accès autorisé</h1>");
// } else {
// server.send(401, "text/html", "<h1>Mot de passe incorrect</h1>");
// }
// } else {
// server.send(401, "text/html", "<form action='/' method='get'>"
// "<label for='password'>Mot de passe:</label><br>"
// "<input type='password' id='password' name='password'><br>"
// "<input type='submit' value='Se connecter'>"
// "</form>");
// }
// return;
// }
// bool connectionStatus = testDomoticzConnection();
// String connectionIcon = connectionStatus
// ? "<i class='fas fa-check-circle' style='color: green;'></i>"
// : "<i class='fas fa-times-circle' style='color: red;'></i>";
#ifdef PIN_HALL
getHall();
#endif
#ifdef PIN_DALLAS
temperature = printTemperature(Probe);
#endif
#ifdef PIN_TENSION
getTension();
#endif
// recvWithEndMarker();
// handleNewData();
// Générer la page HTML avec CSS
String html = "<!DOCTYPE html><html><head>";
html += "<link rel='icon' type='image/svg+xml' href='data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj4KICAgIDxyZWN0IHgxPSIyMCIgeTE9IjMwIiB3aWR0aD0iNjAiIGhlaWdodD0iNDAiIHJ4PSI1IiByeT0iNSIgZmlsbD0iIzRBQ0Y1MCIgc3Ryb2tlPSIjMzMzIiBzdHJva2Utd2lkdGg9IjMiLz4KICAgIDxyZWN0IHgxPSI0NSIgeTE9IjIwIiB3aWR0aD0iMTAiIGhlaWdodD0iMTAiIGZpbGw9IiMzMzMiLz4KICAgIDxjaXJjbGUgY3g9IjUwIiBjeT0iNTAiIHI9IjEwIiBmaWxsPSIjRkZENzAwIiBzdHJva2U9IiMzMzMiIHN0cm9rZS13aWR0aD0iMiIvPgo8L3N2Zz4=' />";
html += "<meta charset='UTF-8'>";
html += "<meta name='viewport' content='width=device-width, initial-scale=1.0'>";
html += "<link type='text/css' rel='stylesheet' href='http://192.168.1.3:81/velux/style.css'>";
html += "<script src='http://192.168.1.3:81/velux/jquery.min.js'></script>";
html += "<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css'>";
html += "<script src='https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js'></script>";
html += "<script src='https://cdn.jsdelivr.net/npm/chart.js'></script>";
html += "<script src='http://192.168.1.3:81/velux/velux.js'></script>";
html += "<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css'>";
html += "<style>.connection-indicator {font-size: 1.5em;margin-left: 20px;}</style>";
html += to_include;
html += "</head><body onload='process()'>";
// html += "<h1>Controle des batteries</h1>";
// html += "<h2>" + String(WiFi.localIP().toString()) + "</h2>";
String buttons = "";
buttons += "<h3 class='list-title'>Actions</h3><ul class='buttons'>";
String pinState = "low"; //digitalRead(PIN_POWER) == LOW ? "low" : "high";
buttons += "<li class='button " + pinState + "' onclick=\"showNotification('Arret effectué');\"><form action='/stop' method='get'>";
buttons += "<input type='submit' value='Arret'>";
buttons += "</form></li>";
#ifdef PIN_POWER
pinState = digitalRead(PIN_POWER) == LOW ? "high" : "low";
buttons += "<li class='button " + pinState + "' onclick=\"showNotification('Démarrage effectué')\"><form action='/start' method='get'>";
buttons += "<input type='submit' value='Demarrer'>";
buttons += "</form></li>";
#endif
pinState = digitalRead(PIN_INJECTION) == LOW ? "high" : "low";
buttons += "<li class='button " + pinState + "' onclick=\"showNotification('Injection en cours')\"><form action='/injection' method='get'>";
// buttons += "<input type='hidden' id='time' name='time' value='" + String(to_store.max_time - to_store.theorique_position) + "'>";
buttons += "<input type='submit' value='Injecter'>";
buttons += "</form></li>";
pinState = digitalRead(PIN_CHARGE) == LOW ? "high" : "low";
buttons += "<li class='button " + pinState + "' onclick=\"showNotification('Chargement des batteries')\"><form action='/charge' method='get'>";
buttons += "<input type='submit' value='Charger'>";
buttons += "</form></li>";
#ifdef PIN_BATTERIE
pinState = digitalRead(PIN_BATTERIE) == LOW ? "high" : "low";
buttons += "<li class='button " + pinState + "' onclick=\"showNotification('Arret de la batterie')\"><form action='/coupe' method='get'>";
buttons += "<input type='submit' value='Coupe Batterie'>";
buttons += "</form></li>";
#endif
buttons += "</ul>";
#ifdef PIN_DIMMER_OUTPUT
buttons += "<h3 class='list-title'>Radiateur</h3><ul class='buttons'>";
buttons += "<li class='button' onclick='showNotification()'><form action='/plus?value=10' method='get'>";
buttons += "<input type='submit' value='Plus'>";
buttons += "</form></li>";
buttons += "<li class='button' onclick='showNotification()'><form action='/minus?value=10' method='get'>";
buttons += "<input type='submit' value='Minus'>";
buttons += "</form></li>";
buttons += "<li class='button' onclick='showNotification()'><form action='/zero' method='get'>";
buttons += "<input type='submit' value='Stop'>";
buttons += "</form></li>";
buttons += "</ul>";
#endif
// PIN_REGULATION
#ifdef PIN_REGULATION
buttons += "<h3 class='list-title'>Régulation</h3><ul class='buttons'>";
buttons += "<li class='button' onclick='showNotification()'><form action='/plus_reg?value=10' method='get'>";
buttons += "<input type='submit' value='Plus'>";
buttons += "</form></li>";
buttons += "<li class='button' onclick='showNotification()'><form action='/minus_reg?value=10' method='get'>";
buttons += "<input type='submit' value='Minus'>";
buttons += "</form></li>";
buttons += "<li class='button' onclick='showNotification()'><form action='/zero_reg' method='get'>";
buttons += "<input type='submit' value='Stop'>";
buttons += "</form></li>";
//buttons += "<li><div class='arcade-button'><div class='button-content'>" + String(current_regulation) + " %</div></div>";
buttons += "</ul>";
#endif
html += "<ul class='buttons data'>";
// #ifdef PIN_DIMMER_OUTPUT
// html += "<li><div class='arcade-button'><div class='button-content'>@@pwm@@ %</div></div>";
// #endif
String indicators = "<h3 class='list-title'>Indicateurs</h3>";
String to_add = indicator;
#ifdef TUYA
to_add.replace("@@VALUE@@", String(String(conso_apparente).toFloat(), 1) + " W");
to_add.replace("@@LABEL@@", "Conso apparente");
to_add.replace("@@KEY@@", "IND_CONSO");
indicators += to_add;
to_add = indicator;
to_add.replace("@@VALUE@@", String(String(production).toFloat(), 1) + " W");
to_add.replace("@@LABEL@@", "Production");
to_add.replace("@@KEY@@", "IND_PROD");
indicators += to_add;
#endif
#ifdef SERIAL_BLUE_SOLAR
to_add = indicator;
to_add.replace("@@VALUE@@", String(String(value[I]).toFloat() / 1000, 2) + " A");;
to_add.replace("@@LABEL@@", "Intensité Charge");
to_add.replace("@@KEY@@", "IND_I");
indicators += to_add;
to_add = indicator;
to_add.replace("@@VALUE@@", String(String(value[V]).toFloat() / 1000, 1) + " V");
to_add.replace("@@LABEL@@", "Tension Batterie");
to_add.replace("@@KEY@@", "IND_V");
indicators += to_add;
to_add = indicator;
to_add.replace("@@VALUE@@", String(String(value[PPV]).toFloat() / 1000, 2) + " A");
to_add.replace("@@LABEL@@", "Courant charge");
to_add.replace("@@KEY@@", "IND_PPV");
indicators += to_add;
to_add = indicator;
to_add.replace("@@VALUE@@", String(String(value[VPV]).toFloat() / 1000, 1) + " V");
to_add.replace("@@LABEL@@", "Tension charge");
to_add.replace("@@KEY@@", "IND_VPV");
indicators += to_add;
to_add = indicator;
to_add.replace("@@VALUE@@", String(String(value[IL]).toFloat() / 1000, 1) + " V");
to_add.replace("@@LABEL@@", "Intensité décharge");
to_add.replace("@@KEY@@", "IND_IL");
indicators += to_add;
// to_add = indicator;
// to_add.replace("@@VALUE@@", String(String(value[IL]).toFloat() / 1000,1) + " V");
// to_add.replace("@@LABEL@@", "Intensié décharge");
// to_add.replace("@@KEY@@", "IND_IL");
//
// indicators += to_add;
// html += "<li><div class='arcade-button'><div class='button-content'>" + String(value[I]) + " mA</div></div>";
// html += "<li><div class='arcade-button'><div class='button-content'>" + String(value[V]) + " mV</div></div>";
// html += "<li><div class='arcade-button'><div class='button-content'>" + String(value[PPV]) + " mA</div></div>";
// html += "<li><div class='arcade-button'><div class='button-content'>" + String(value[VPV]) + " mV</div></div>";
// html += "<li><div class='arcade-button'><div class='button-content'>" + String(Amps * Voltage) + " W</div></div>";
//#else
// html += "<li><div class='arcade-button'><div class='button-content'>" + String(Voltage / 55) + " mV</div></div>";
#endif
#ifdef PIN_REGULATION
to_add = indicator;
to_add.replace("@@VALUE@@", "%");
to_add.replace("@@LABEL@@", "Régulation");
to_add.replace("@@KEY@@", "IND_REGULATION");
indicators += to_add;
#endif
#ifdef PIN_DIMMER_OUTPUT
to_add = indicator;
to_add.replace("@@VALUE@@", "%");
to_add.replace("@@LABEL@@", "Radiateur");
to_add.replace("@@KEY@@", "IND_RADIATEUR");
indicators += to_add;
#endif
#ifdef PIN_DALLAS
to_add = indicator;
to_add.replace("@@VALUE@@", "°");
to_add.replace("@@LABEL@@", "Température");
to_add.replace("@@KEY@@", "IND_TEMPERATURE");
indicators += to_add;
//html += "<li><div class='arcade-button'><div class='button-content'>" + String(temperature) + " °C</div></div>";
#endif
html += "</ul>";
//String response_items = "";
html += webpage;
// response_items = "<div class='victron_data'><span><A id='response_items'></A></span></div>";
// html.replace("@@RESPONSE_ITEMS@@", response_items);
// html+= "<div class='victron_data'><span style='font-family: Arial, Helvetica, sans-serif;font-size: 20px;font-weight: bold;color: #a5a5a5;'><A id='response_items'></A></span></div>";
// if (error != "") {
// html += "<p>" + error + "</p>";
// }
// String page = "<h1>État des broches GPIO</h1>";
//
// // Pour chaque broche GPIO dans la liste
// for (int i = 0; i < sizeof(pins) / sizeof(pins[0]); i++) {
// // Lecture de l'état de la broche
// int pinState = digitalRead(pins[i]);
//
// // Ajout d'un bouton rouge ou vert en fonction de l'état de la broche
// if (pinState == LOW) {
// page += "<button style=\"background-color: green;\">Pin ";
// page += pins[i];
// page += " : LOW</button>";
// } else {
// page += "<button style=\"background-color: red;\">Pin ";
// page += pins[i];
// page += " : HIGH</button>";
// }
// page += "<br>";
// }
//
// html += page;
html.replace("@@pwm@@", String(pwm));
html.replace("@@INDICATORS@@", indicators);
html.replace("@@BUTTONS@@", buttons);
html.replace("@@CONNECTION_INDICATOR@@", ""); //connectionIcon);
html.replace("@@IP@@", String(WiFi.localIP().toString()));
html.replace("@@CC@@", String(cc));
html.replace("@@CC2@@", String(cc2));
struct tm* timeinfo = localtime(&localTime);
//html.replace("@@TIME@@", fprintf("%02d:%02d:%02d\n", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec));
html += "<div id='notification' class='notification'></div>";
delay(100);
html += end_script_to_add;
// String message = getParamFromGet("message");
// if (!message.equals("")) {
// html += "<script>showNotification('" + message + "');</script>";
// }
html += "</body></html>";
delay(100);
// Envoyer la page HTML au client
server.send(200, "text/html", html);
}
void handleStop() {
Serial.println("Arrêt");
digitalWrite(PIN_INJECTION, LOW);
cc2 = 0;
cc = 0;
setCC(xy, 0);
#ifdef SERIAL_XY6020L_2
setCC2(xy2, 0);
#endif
delay(200);
digitalWrite(PIN_CHARGE, LOW);
delay(200);
#ifdef PIN_POWER
digitalWrite(PIN_POWER, LOW);
delay(200);
#endif
#ifdef PIN_BATTERIE
digitalWrite(PIN_BATTERIE, LOW);
delay(200);
#endif
// Vous pouvez ajouter ici le code pour gérer l'arrêt comme vous le souhaitez
// Rediriger vers la page principale après le traitement
blink(); server.sendHeader("Location", "/?message='Arret effectué'");
server.send(302, "text/plain", "Redirection vers la page principale");
}
void handleStart() {
#ifdef PIN_DIMMER_OUTPUT
dimmer.setState(ON_OFF_typedef::ON);
#endif
Serial.println("Start");
#ifdef PIN_POWER
digitalWrite(PIN_POWER, HIGH);
delay(200);
#endif
#ifdef PIN_BATTERIE
digitalWrite(PIN_BATTERIE, HIGH);
delay(200);
#endif
// Vous pouvez ajouter ici le code pour gérer l'arrêt comme vous le souhaitez
// Rediriger vers la page principale après le traitement
blink(); server.sendHeader("Location", "/");
server.send(302, "text/plain", "Redirection vers la page principale");
}
void injection() {
#ifdef PIN_DIMMER_OUTPUT
dimmer.setState(ON_OFF_typedef::OFF);
#endif
#ifdef PIN_POWER
digitalWrite(PIN_POWER, HIGH);
delay(200);
#endif
#ifdef PIN_BATTERIE
digitalWrite(PIN_BATTERIE, HIGH);
delay(200);
#endif
digitalWrite(PIN_CHARGE, LOW);
delay(200);
Serial.println("injection");
digitalWrite(PIN_INJECTION, HIGH);
delay(200);
#ifdef PIN_BATTERIE
digitalWrite(PIN_BATTERIE, HIGH);
delay(200);
#endif
#ifdef PIN_REGULATION
setReg(0);
#endif
}
void handleInjection() {
injection();
// Rediriger vers la page principale après le traitement
blink(); server.sendHeader("Location", "/");
server.send(302, "text/plain", "Redirection vers la page principale");
}
void stopInjection()
{
#ifdef PIN_BATTERIE
digitalWrite(PIN_BATTERIE, LOW);
delay(200);
#endif
Serial.println("Stop injection");
digitalWrite(PIN_INJECTION, LOW);
delay(200);
}
void handleStopInjection() {
stopInjection();
// Rediriger vers la page principale après le traitement
blink(); server.sendHeader("Location", "/");
server.send(302, "text/plain", "Redirection vers la page principale");
}
void charge()
{
#ifdef PIN_DIMMER_OUTPUT
dimmer.setState(ON_OFF_typedef::ON);
#endif
Serial.println("charge");
#ifdef PIN_POWER
digitalWrite(PIN_POWER, HIGH);
delay(200);
#endif
#ifdef PIN_BATTERIE
digitalWrite(PIN_BATTERIE, LOW);
delay(200);
#endif
digitalWrite(PIN_INJECTION, LOW);
delay(200);
digitalWrite(PIN_CHARGE, HIGH);
delay(200);
}
void handleCharge() {
charge();
// Rediriger vers la page principale après le traitement
blink(); server.sendHeader("Location", "/");
server.send(302, "text/plain", "Redirection vers la page principale");
}
void stopCharge()
{
slider_on = false;
Serial.println("stop charge");
#ifdef PIN_BATTERIE
digitalWrite(PIN_BATTERIE, LOW);
delay(200);
#endif
digitalWrite(PIN_CHARGE, LOW);
delay(200);
#ifdef PIN_REGULATION
setReg(0);
#endif
#ifdef SERIAL_XY6020L
setCC(xy, 0);
#endif
}
void handleStopCharge() {
stopCharge();
// Rediriger vers la page principale après le traitement
blink(); server.sendHeader("Location", "/");
server.send(302, "text/plain", "Redirection vers la page principale");
}
void handleCoupe() {
Serial.println("coupe batterie");
#ifdef PIN_BATTERIE
digitalWrite(PIN_BATTERIE, LOW);
delay(200);
#endif
// Vous pouvez ajouter ici le code pour traiter la vitesse comme vous le souhaitez
// Rediriger vers la page principale après le traitement
blink(); server.sendHeader("Location", "/");
server.send(302, "text/plain", "Redirection vers la page principale");
}
// Méthode pour gérer la requête '/getData'
void handleData() {
blink();
#ifdef PIN_DALLAS
// Command all devices on bus to read temperature
// Serial.print("Temperature is: ");
temperature = printTemperature(Probe);
//Serial.println();
#endif
// Créer un objet JSON
DynamicJsonDocument doc(200);
// Remplir l'objet JSON avec les données PZEM
#ifdef PIN_POWER
doc["PIN_POWER"] = digitalRead(PIN_POWER);
#endif
doc["PIN_INJECTION"] = digitalRead(PIN_INJECTION);
doc["PIN_CHARGE"] = digitalRead(PIN_CHARGE);
#ifdef PIN_BATTERIE
doc["PIN_BATTERIE"] = digitalRead(PIN_BATTERIE);
#endif
// doc["AMPS"] = Amps;
// doc["VOLTAGE"] = Voltage;
#ifdef PIN_DALLAS
doc["TEMPERATURE"] = temperature;
#endif
#ifdef PIN_REGULATION
doc["REGULATION"] = current_regulation;
#endif
#ifdef PIN_DIMMER_OUTPUT
doc["RADIATEUR"] = pwm;
#endif
#ifdef SERIAL_BLUE_SOLAR
//doc["INJECT"] = value[IL] / 1000 * value[V] / 1000;
//doc["last_serial_string"] = last_serial_string;
for (int i = 0; i < num_keywords - 1; i++) {
String key = String(keywords[i]);
String val = String(value[i]);
doc[key] = val;
}
tension_batterie = String(value[3]).toInt() / 1000.0;
String tensions = "";
for (int i = 0; i < maxSize; i++) {
if (i == 0) {
tensions = String(to_store.tensions[i]);
}
else {
tensions += "," + String(to_store.tensions[i]);
}
}
doc["TENSIONS"] = tensions;
doc["VB"] = tension_batterie;
#endif
#ifdef SERIAL_XY6020L
printMem();
doc["XY_V"] = xy.getCV();
doc["XY_C"] = xy.getCC();
doc["CC"] = cc;
doc["XY_T"] = xy.getTemp();
doc["XY_ON"] = xy.getOutputOn();
doc["XY_AV"] = xy.getActV();
doc["XY_AC"] = xy.getActC();
doc["XY_AW"] = xy.getActP();
#endif
#ifdef SERIAL_XY6020L_2
printMem2();
doc["XY2_V"] = xy2.getCV();
doc["XY2_C"] = xy2.getCC();
doc["CC2"] = cc2;
doc["XY2_T"] = xy2.getTemp();
doc["XY2_ON"] = xy2.getOutputOn();
doc["XY2_AV"] = xy2.getActV();
doc["XY2_AC"] = xy2.getActC();
doc["XY2_AW"] = xy2.getActP();
#endif
#ifdef PZEM
pzemRead();
// Remplir l'objet JSON avec les données PZEM
doc["PZEM_VOLTAGE"] = voltage;
doc["PZEM_CURRENT"] = current;
doc["PZEM_PF"] = pf;
doc["PZEM_POWER"] = power;
doc["PZEM_ENERGY"] = energy;
doc["PZEM_FREQUENCY"] = frequency;
#endif
#ifdef PIN_HALL
getHall();
doc["HALL_VOLTAGE"] = VRMS;
doc["HALL_CURRENT"] = Amps;
doc["HALL_POWER"] = Amps * 230;
#endif
#ifdef TUYA
doc["CONSO"] = conso_apparente;
doc["PROD"] = production;
#endif
doc["Message"] = last_message;
// Convertir l'objet JSON en chaîne
String jsonData;
serializeJson(doc, jsonData);
// Envoyer la réponse JSON au client
server.send(200, "application/json", jsonData);
}
#ifdef PIN_TENSION
void getTension()
{
int pin_value = analogRead(PIN_TENSION);
Voltage = pin_value;
}
#endif
//#ifdef PIN_REGULATION
//void setReg(int speed_to_set)
//{
// current_regulation = speed_to_set;
// if (current_regulation > 100) current_regulation = 100;
// if (current_regulation <= 1) {
// current_regulation = 0;
// }
//
// Serial.println(current_regulation);
//
// analogWrite(PIN_REGULATION, current_regulation * 2.55);// send current_regulation value to motor
//
// blink(); server.sendHeader("Location", "/?message='Arret effectué'");
// server.send(302, "text/plain", "Redirection vers la page principale");
//
//}
//
//
//void exact_reg() {
// int value_to_set = getParamFromGet("value").toInt();
//
// current_regulation = value_to_set;
// if (current_regulation > 100) current_regulation = 100;
// if (current_regulation < 0) {
// current_regulation = 0;
// }
//
// setReg(current_regulation);
//
//}
//void plus_reg() {
// int value_to_set = getParamFromGet("value").toInt();
// if (value_to_set <= 0) {
// value_to_set = 5;
// }
// current_regulation += value_to_set;
// setReg(current_regulation);
//
//}
//
//void minus_reg() {
// int value_to_set = getParamFromGet("value").toInt();
// if (value_to_set <= 0) {
// value_to_set = 5;
// }
// current_regulation -= value_to_set;
// setReg(current_regulation);
//}
//
//void stop_reg() {
// current_regulation = 0;
// setReg(current_regulation);
//}
//#endif
#ifdef PIN_DALLAS
float printTemperature(DeviceAddress deviceAddress)
{
sensors.requestTemperatures();
float tempC = sensors.getTempC(deviceAddress);
// if (tempC == -127.00)
// {
// Serial.print ("Error getting temperature ");
// }
// else
// {
// Serial.print ("C: ");
// Serial.println (tempC);
// // Serial.print (" F: ");
// // Serial.print(DallasTemperature::toFahrenheit(tempC));
// }
return tempC;
}
#endif
void synchronizeTime() {
struct tm timeinfo;
int bcl = 0;
while (!getLocalTime(&timeinfo) && bcl < 5) {
Serial.println("Waiting for time synchronization...");
delay(1000);
bcl ++;
}
Serial.println("Time synchronized");
}
void blink()
{
digitalWrite(PIN_LED, HIGH);
delay(10);
digitalWrite(PIN_LED, LOW);
delay(10);
}
#ifdef PZEM
double pzemRead() {
voltage = pzem.voltage();
current = pzem.current();
pf = pzem.pf();
power = pzem.power();
energy = pzem.energy();
frequency = pzem.frequency();
if ( !isnan(voltage) ) {
Serial.print("Voltage: "); Serial.print(voltage); Serial.println("V");
//Serial.println(String(voltage,1) + " V ");
} else {
Serial.println("Error reading voltage");
}
if ( !isnan(current) ) {
Serial.print("Current: "); Serial.print(current); Serial.println("A");
// Serial.println(String(current,1) + "A ");
} else {
Serial.println("Error reading current");
}
if ( !isnan(pf) ) {
//Serial.print("PF: "); Serial.println(pf);
Serial.println(String(pf, 3) + "pf ");
if (pf != 0) {
Serial.println(String(power / pf, 0) + "Wa");
}
} else {
//Serial.println("Error reading power factor");
}
if ( !isnan(power) ) {
//Serial.print("Power: "); Serial.print(power); Serial.println("W");
if (pf > 0) {
Serial.println("+" + String(power, 1) + "W ");
}
else {
Serial.println("-" + String(power, 1) + "Wa");
}
} else {
//Serial.println("Error reading power");
}
if ( !isnan(energy) ) {
if (energy < 1000) {
Serial.println(String(energy * 1000, 0) + "Wh ");
}
else {
Serial.println(String(energy, 1) + "kWh ");
}
Serial.print("Energy: ");
Serial.print(energy, 3);
Serial.println("kWh");
} else {
Serial.println("Error reading energy");
}
if ( !isnan(frequency) ) {
Serial.print("Frequency: "); Serial.print(frequency, 1); Serial.println("Hz");
} else {
Serial.println("Error reading frequency");
}
return power;
}
#endif