Centralina Web per inverter ABB Aurora (WIM): notifiche e debug – 4
Io uso la comunicazione tramite Serial
per interfacciare il nostro dispositivo con l’inverter quindi per il “debug” andremo ad utilizzare l’UART secondario presente sul WeMos D1 mini, potete trovare informazioni dettagliate nel mio articolo “WeMos D1 mini (esp8266): eseguire un debug sulla seriale secondaria“.
Puoi trovere il WeMos D1 mini su WeMos D1 mini - NodeMCU V2 V2.1 V3 - esp01 - esp01 programmer
Quindi nella scheda aggiungo un pin, puoi utilizzare il modulo CH340G standard per interfacciarlo,
Puoi trovere l'USB to TTL su USB to TTL CH340G - USB to TTL FT232RL
e devi controllare che il debug sia abilitato nel codice.
// Uncomment to enable printing out nice debug messages.
#define AURORA_SERVER_DEBUG
// Define where debug output will be printed.
#define DEBUG_PRINTER Serial1
// Setup debug printing macros.
#ifdef AURORA_SERVER_DEBUG
#define DEBUG_PRINT(...) { DEBUG_PRINTER.print(__VA_ARGS__); }
#define DEBUG_PRINTLN(...) { DEBUG_PRINTER.println(__VA_ARGS__); }
#else
#define DEBUG_PRINT(...) {}
#define DEBUG_PRINTLN(...) {}
#endif
Con questo sistema puoi recuperare anche l’ip tornato dal DHCP, (puoi anche usare uno sniffer di rete). Se vuoi espongo anche i pin i2c, quindi potresti collegare anche uno schermo dove mostrare IP o altre informazioni.
Notifiche
Per il sistema di notifica utilizzo la mia libreria creata per inviare email, è semplice configurabile e veloce da usare.
Per la libreria puoi fare riferimento al mio articolo “Inviare email con allegati“, dove spiego meglio l’utilizzo della libreria.
Memorizzerò il parametro in un file di configurazione all’interno dello SPIFFS (spero che questo file cambi pochissime volte), ma prima devi configurare il tuo server SMTP.
Poi andrò a gestire tutti e 4 i tipi di allarme che vengono generati dall’Inverter.
Puoi configurare per ogni attore attori un diverso set di notifiche e ricorda che probabilmente non hai collegato tutti i canali, quindi fai attenzione a disabilitare la configurazione per il canale inutilizzato.
Puoi specificare le impostazioni per ogni e-mail e puoi scegliere di inviare e-mail ogni volta che viene apportata una modifica o solo quando qualcosa va storto.
Puoi farlo per ogni unità monitorata:
- Allarme : quando viene restituito un allarme
- Stato : quando lo stato della rete viene modificato
- Canali : quando si verifica una modifica su un canale specificato.
Qui un pezzo di file di configurazione.
"emailNotification": {
"isNotificationEnabled": true,
"subject": "Notifica inverter",
"messageProblem": "Un problema è stato rilevato sull'inverter:",
"messageNoProblem": "E' stato ripristinato lo stato del tuo inverter:",
"emailList": [
{
"email": "renzo.mischianti@gmail.com",
"name": "Renzo Mischianti",
"alarm": "on_problem",
"ch1": "on_problem",
"ch2": "none",
"state": "on_problem"
}
]
},
Ecco la parte di codice per gestire l’invio dell’email di avviso in base alla configurazione salvata:
DEBUG_PRINT(F("MEM "));
DEBUG_PRINTLN(ESP.getFreeHeap());
if (lds.needNotify){
DEBUG_PRINT(F("Open config file..."));
fs::File configFile = SPIFFS.open(F("/mc/config.txt"), "r");
if (configFile) {
DEBUG_PRINTLN(F("done."));
DynamicJsonDocument doc(CONFIG_FILE_HEAP);
DeserializationError error = deserializeJson(doc, configFile);
if (error) {
// if the file didn't open, print an error:
DEBUG_PRINT(F("Error parsing JSON "));
DEBUG_PRINTLN(error.c_str());
}
// close the file:
configFile.close();
DEBUG_PRINT(F("MEM "));
DEBUG_PRINTLN(ESP.getFreeHeap());
JsonObject rootObj = doc.as<JsonObject>();
DEBUG_PRINT(F("After read config check serverSMTP and emailNotification "));
DEBUG_PRINTLN(rootObj.containsKey(F("serverSMTP")) && rootObj.containsKey(F("emailNotification")));
if (rootObj.containsKey(F("serverSMTP")) && rootObj.containsKey(F("emailNotification"))){
// JsonObject serverConfig = rootObj["server"];
JsonObject serverSMTP = rootObj[F("serverSMTP")];
JsonObject emailNotification = rootObj[F("emailNotification")];
bool isNotificationEnabled = (emailNotification.containsKey(F("isNotificationEnabled")))?emailNotification[F("isNotificationEnabled")]:false;
DEBUG_PRINT(F("isNotificationEnabled "));
DEBUG_PRINTLN(isNotificationEnabled);
if (isNotificationEnabled){
const char* serverSMTPAddr = serverSMTP[F("server")];
emailSend.setSMTPServer(serverSMTPAddr);
uint16_t portSMTP = serverSMTP[F("port")];
emailSend.setSMTPPort(portSMTP);
const char* loginSMTP = serverSMTP[F("login")];
emailSend.setEMailLogin(loginSMTP);
const char* passwordSMTP = serverSMTP[F("password")];
emailSend.setEMailPassword(passwordSMTP);
const char* fromSMTP = serverSMTP[F("from")];
emailSend.setEMailFrom(fromSMTP);
DEBUG_PRINT(F("server "));
DEBUG_PRINTLN(serverSMTPAddr);
DEBUG_PRINT(F("port "));
DEBUG_PRINTLN(portSMTP);
DEBUG_PRINT(F("login "));
DEBUG_PRINTLN(loginSMTP);
DEBUG_PRINT(F("password "));
DEBUG_PRINTLN(passwordSMTP);
DEBUG_PRINT(F("from "));
DEBUG_PRINTLN(fromSMTP);
EMailSender::EMailMessage message;
const String sub = emailNotification[F("subject")];
message.subject = sub;
JsonArray emailList = emailNotification[F("emailList")];
DEBUG_PRINT(F("Email list "));
for (uint8_t i=0; i<emailList.size(); i++){
JsonObject emailElem = emailList[i];
// byte asp = lastData[F("asp")];
// byte c1sp = lastData[F("c1sp")];
// byte c2sp = lastData[F("c2sp")];
// byte isp = lastData[F("isp")];
const String alarm = emailElem[F("alarm")];
const String ch1 = emailElem[F("ch1")];
const String ch2 = emailElem[F("ch2")];
const String state = emailElem[F("state")];
DEBUG_PRINT(F("State value "));
DEBUG_PRINTLN(state);
DEBUG_PRINT(F("State value on_problem comparison "));
DEBUG_PRINTLN(state==F("on_problem"));
DEBUG_PRINT(F("Alarm value "));
DEBUG_PRINTLN(alarm);
DEBUG_PRINT(F("Alarm all comparison "));
DEBUG_PRINTLN(alarm==F("all"));
bool allNotification = (
(alarm==F("all") && lds.asp != dataState.alarmState)
||
(ch1==F("all") && lds.c1sp != dataState.channel1State)
||
(ch2==F("all") && lds.c2sp != dataState.channel2State)
||
(state==F("all") && lds.isp != dataState.inverterState)
);
bool onProblem = (
(alarm==F("on_problem") && dataState.alarmState > 0)
||
(ch1==F("on_problem") && dataState.channel1State != 2)
||
(ch2==F("on_problem") && dataState.channel1State != 2)
||
(state==F("on_problem") && (dataState.inverterState != 2 && dataState.inverterState != 1))
);
DEBUG_PRINT(F("Check allNotification "));
DEBUG_PRINTLN(allNotification);
DEBUG_PRINT(F("Check onProblem "));
DEBUG_PRINTLN(onProblem);
DEBUG_PRINT(F("MEM "));
DEBUG_PRINTLN(ESP.getFreeHeap());
if (
allNotification
||
onProblem
){
const String mp = emailNotification[F("messageProblem")];
const String mnp = emailNotification[F("messageNoProblem")];
message.message = ((lds.inverterProblem)?mp:mnp)+
F("<br>Alarm: ")+dataState.getAlarmState()+
F("<br>CH1: ")+dataState.getDcDcChannel1State() +
F("<br>CH2: ")+dataState.getDcDcChannel2State()+
F("<br>Stato: ")+dataState.getInverterState();
EMailSender::Response resp = emailSend.send(emailElem[F("email")], message);
DEBUG_PRINTLN(F("Sending status: "));
const String em = emailElem[F("email")];
DEBUG_PRINTLN(em);
DEBUG_PRINTLN(resp.status);
DEBUG_PRINTLN(resp.code);
DEBUG_PRINTLN(resp.desc);
}
}
}
}
}else{
DEBUG_PRINTLN(F("fail."));
}
}
Quindi il codice legge la configurazione, itera per tutte le email inserite controlla i parametri e se deve essere inviato un particolare avviso.
Thanks
- ABB Aurora Web Inverter Monitor (WIM): project introduction
- ABB Aurora Web Inverter Monitor (WIM): wiring Arduino to RS-485
- ABB Aurora Web Inverter Monitor (WIM): storage devices
- ABB Aurora Web Inverter Monitor (WIM): debug and notification
- ABB Aurora Web Inverter Monitor (WIM): set time and UPS
- ABB Aurora Web Inverter Monitor (WIM): WIFI configuration and REST Server
- ABB Aurora Web Inverter Monitor (WIM): WebSocket and Web Server
- ABB Aurora Web Inverter Monitor (WIM): Wiring and PCB soldering
- ABB Aurora Web Inverter Monitor (WIM): upload the sketch and front end
- ABB Aurora web inverter Monitor (WIM): 3D printed case to complete project
- ABB Aurora web inverter monitor (WIM): repair E013 error
GitHub repository with all code BE and FE transpiled