Initial commit — KC868-A2 contrôleur solaire ESP32
Fonctionnalités : - Lecture RS485 Modbus Epever Tracer 4210N (115200 bps, FC03/FC04/FC16) - Moteur de règles JSON (LittleFS) — commande automatique des relais - Interface web mobile-first (dashboard, règles, config, historique, EPEVER, debug) - WiFi AP+STA simultanés avec reconnexion automatique et portail captif - mDNS configurable (pv.local par défaut) - Configuration registres EPEVER depuis l'UI (18 registres holding) - Historique basse/haute résolution avec graphes canvas - VPN WireGuard optionnel (désactivé par défaut, config via UI) - OTA firmware + filesystem via ElegantOTA - Deep sleep / économie d'énergie Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
|
||||
This directory is intended for project header files.
|
||||
|
||||
A header file is a file containing C declarations and macro definitions
|
||||
to be shared between several project source files. You request the use of a
|
||||
header file in your project source file (C, C++, etc) located in `src` folder
|
||||
by including it, with the C preprocessing directive `#include'.
|
||||
|
||||
```src/main.c
|
||||
|
||||
#include "header.h"
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Including a header file produces the same results as copying the header file
|
||||
into each source file that needs it. Such copying would be time-consuming
|
||||
and error-prone. With a header file, the related declarations appear
|
||||
in only one place. If they need to be changed, they can be changed in one
|
||||
place, and programs that include the header file will automatically use the
|
||||
new version when next recompiled. The header file eliminates the labor of
|
||||
finding and changing all the copies as well as the risk that a failure to
|
||||
find one copy will result in inconsistencies within a program.
|
||||
|
||||
In C, the convention is to give header files names that end with `.h'.
|
||||
|
||||
Read more about using header files in official GCC documentation:
|
||||
|
||||
* Include Syntax
|
||||
* Include Operation
|
||||
* Once-Only Headers
|
||||
* Computed Includes
|
||||
|
||||
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
||||
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
void initBoutons();
|
||||
void gererBoutons();
|
||||
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
#include <IPAddress.h>
|
||||
|
||||
// --- WiFi point d'accès ---
|
||||
#define WIFI_SSID "kc868-a2"
|
||||
#define WIFI_PASSWORD "soleil12" // mot de passe WiFi AP
|
||||
#define WIFI_IP IPAddress(192, 168, 4, 1)
|
||||
#define WIFI_GATEWAY IPAddress(192, 168, 4, 1)
|
||||
#define WIFI_SUBNET IPAddress(255, 255, 255, 0)
|
||||
|
||||
// --- GPIO ---
|
||||
#define PIN_RELAY1 15
|
||||
#define PIN_RELAY2 2 // pin de strapping boot — doit être HIGH au démarrage
|
||||
#define PIN_RS485_TX 32
|
||||
#define PIN_RS485_RX 35 // input only
|
||||
#define PIN_DI1 36 // input only
|
||||
#define PIN_DI2 39 // input only
|
||||
|
||||
// --- OTA ---
|
||||
#define OTA_USER "admin"
|
||||
#define OTA_PASSWORD "solar123"
|
||||
|
||||
// --- Modbus ---
|
||||
#define MODBUS_ADRESSE 1 // adresse esclave Epever
|
||||
#define MODBUS_BAUDRATE 115200 // baudrate principal de l'Epever
|
||||
#define TIMEOUT_MODBUS 3000 // timeout réponse (ms) — doit être > délai interne lib (1s)
|
||||
#define MODBUS_DEBUG_BOOT 1 // sonde RS485 détaillée au démarrage
|
||||
#define MODBUS_DEBUG_RX_MAX 64 // octets max affichés en cas d'erreur
|
||||
|
||||
// --- Intervalles (ms) ---
|
||||
#define INTERVALLE_MODBUS 5000
|
||||
#define INTERVALLE_REGLES 1000
|
||||
#define DEBOUNCE_BOUTON 50
|
||||
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
|
||||
void debugLogLine(const char *message);
|
||||
void debugLogf(const char *format, ...);
|
||||
void getDebugLogJson(String &out);
|
||||
void clearDebugLog();
|
||||
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <Arduino.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
struct EpeverRegDef {
|
||||
uint16_t reg;
|
||||
const char *key;
|
||||
float scale; // raw→float : 0.01 pour les tensions, 1.0 pour les entiers
|
||||
float valMin;
|
||||
float valMax;
|
||||
bool writable;
|
||||
const char *unit;
|
||||
const char *label;
|
||||
const char *aide;
|
||||
};
|
||||
|
||||
extern const EpeverRegDef EPEVER_REGS[];
|
||||
extern const uint8_t EPEVER_REGS_COUNT;
|
||||
|
||||
// Blocs de registres consécutifs
|
||||
#define EPEVER_BLOC1_REG 0x9000u
|
||||
#define EPEVER_BLOC1_QTY 14u
|
||||
#define EPEVER_BLOC2_REG 0x906Bu
|
||||
#define EPEVER_BLOC2_QTY 4u
|
||||
|
||||
void initConfigEpever();
|
||||
bool lireConfigEpever();
|
||||
bool ecrireConfigEpever(JsonObject obj, String &erreur);
|
||||
bool sauvegarderConfigJson();
|
||||
bool restaurerConfigJson(String &erreur);
|
||||
void getConfigJson(String &out);
|
||||
void getConfigSauvegardeJson(String &out);
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
|
||||
void initHistorique();
|
||||
void gererHistorique();
|
||||
void getHistoriqueJson(String &out); // lores : 30h, point toutes les 5 min
|
||||
void getHistoriqueHiresJson(String &out); // hires : 4h, point toutes les 1 min
|
||||
void getHistoriqueCsv(String &out); // export CSV lores pour téléchargement
|
||||
void getHistoriqueStatusJson(String &out); // debug compteurs internes
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
void initModbus();
|
||||
void gererModbus();
|
||||
void setIntervallesModbus(uint32_t jour_ms, uint32_t nuit_ms);
|
||||
void getIntervallesModbus(uint32_t &jour_ms, uint32_t &nuit_ms);
|
||||
bool reglerHorlogeEpever(uint16_t annee, uint8_t mois, uint8_t jour,
|
||||
uint8_t heure, uint8_t minute, uint8_t seconde);
|
||||
|
||||
// Accès Modbus partagé (pour epever_config.cpp)
|
||||
bool isModbusBusy();
|
||||
bool modbusAcquire();
|
||||
void modbusRelease();
|
||||
bool modbusLireHolding(uint16_t reg, uint16_t qty, uint16_t *dest, uint16_t timeoutMs);
|
||||
bool modbusEcrireHolding(uint16_t reg, uint16_t qty, const uint16_t *vals, uint16_t timeoutMs);
|
||||
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
void demarrerOTA();
|
||||
void gererOTA();
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
void initRegles();
|
||||
void gererRegles();
|
||||
|
||||
void reglesToJson(JsonArray arr);
|
||||
bool ajouterRegle(JsonObject obj);
|
||||
bool supprimerRegle(int id);
|
||||
bool toggleRegle(int id);
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
|
||||
// Appelé au tout début de setup() — entre en deep sleep si réveil timer + nuit
|
||||
void verifierEtDormirSiNuit();
|
||||
|
||||
// Appelé après montage de LittleFS
|
||||
void chargerConfigSleep();
|
||||
|
||||
// Restaure les relais depuis la mémoire RTC après un réveil
|
||||
void restaurerRelais();
|
||||
|
||||
// Appelé dans loop()
|
||||
void gererSleep();
|
||||
|
||||
// API REST
|
||||
void getSleepConfigJson(String &out);
|
||||
bool setSleepConfig(bool actif, uint32_t intervalle, float seuil);
|
||||
@@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
struct SystemState {
|
||||
// --- PV ---
|
||||
float pv = 0.0f; // Tension PV (V)
|
||||
float pvCurrent = 0.0f; // Courant PV (A)
|
||||
|
||||
// --- Batterie ---
|
||||
float battery = 0.0f; // Tension (V)
|
||||
float batTemperature = 0.0f; // Température (°C)
|
||||
uint8_t batSOC = 0; // Charge restante (%)
|
||||
uint8_t batStatut = 0; // 0=arrêt 1=float 2=boost 3=égalisation
|
||||
bool batSousVoltage = false;
|
||||
bool batSurVoltage = false;
|
||||
|
||||
// --- Sortie de charge (load) ---
|
||||
float loadVoltage = 0.0f; // Tension (V)
|
||||
float loadCurrent = 0.0f; // Courant (A)
|
||||
float loadPower = 0.0f; // Puissance (W)
|
||||
|
||||
// --- Énergie (kWh, calculées par l'Epever) ---
|
||||
float energieGenJour = 0.0f; // Générée aujourd'hui
|
||||
float energieGenTotal = 0.0f; // Générée total
|
||||
float energieConJour = 0.0f; // Consommée aujourd'hui
|
||||
float energieConTotal = 0.0f; // Consommée total
|
||||
|
||||
// --- Ensoleillement ---
|
||||
bool sun = false; // true = jour
|
||||
bool sunHistoryValid = false;
|
||||
uint8_t sunHistoryCount = 0;
|
||||
uint8_t sunHistoryHead = 0;
|
||||
bool sunHistoryState[5] = {};
|
||||
char sunHistoryTime[5][20] = {};
|
||||
|
||||
// --- Horloge interne Epever ---
|
||||
bool epeverClockOk = false;
|
||||
uint8_t epeverSecond = 0;
|
||||
uint8_t epeverMinute = 0;
|
||||
uint8_t epeverHour = 0;
|
||||
uint8_t epeverDay = 0;
|
||||
uint8_t epeverMonth = 0;
|
||||
uint16_t epeverYear = 0;
|
||||
bool espClockOk = false;
|
||||
|
||||
// --- Relais ---
|
||||
bool relay1 = false;
|
||||
bool relay2 = false;
|
||||
|
||||
// --- Boutons DI ---
|
||||
bool di1 = false;
|
||||
bool di2 = false;
|
||||
|
||||
// --- Mode ---
|
||||
bool autoMode = true; // true = automatique, false = manuel
|
||||
|
||||
// --- Santé RS485 ---
|
||||
bool rs485_ok = false;
|
||||
unsigned long last_update = 0;
|
||||
};
|
||||
|
||||
extern SystemState state;
|
||||
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include <ESPAsyncWebServer.h>
|
||||
|
||||
extern AsyncWebServer server;
|
||||
|
||||
void demarrerWebserveur();
|
||||
void restaurerRelaisNVS();
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
|
||||
void demarrerWifi();
|
||||
void gererWifi(); // boucle principale (DNS + reconnexion STA)
|
||||
void connecterWifiSTA(const char *ssid, const char *pass); // sauvegarde NVS + connexion
|
||||
void deconnecterWifiSTA(); // efface NVS + déconnecte STA
|
||||
void getWifiStatusJson(String &out); // statut AP + STA en JSON
|
||||
void scannerReseauxJson(String &out); // scan synchrone → JSON
|
||||
String getMdnsHostname(); // hostname mDNS courant
|
||||
bool setMdnsHostname(const char *nom); // change hostname + sauvegarde NVS
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
|
||||
void initWireGuard();
|
||||
void gererWireGuard();
|
||||
void getWireGuardJson(String &out);
|
||||
bool setWireGuardConfig(bool enabled, const char* privKey, const char* pubKey,
|
||||
const char* psk, const char* endpoint, uint16_t port,
|
||||
const char* localIP, uint16_t keepalive);
|
||||
Reference in New Issue
Block a user