///////////////////// // Domoticz Classe ///////////////////// #include #include #include #include #include #include #include void handleRoot(void); int getValueFromParam(); void setPwm(int pwm); const char* ssid = "Livebox-37cc"; const char* pass = "8A6060920A8A86896F770F2C47"; IPAddress gateway(192, 168, 1, 1); IPAddress subnet(255, 255, 0, 0); IPAddress DNS(192, 168, 1, 1); // DIMMER ESP8266WebServer server(80); void ICACHE_RAM_ATTR handleInterrupt(); //// Dimmer //#include // // //#define LEDn 15 //#define outputPin D5 // D5 //#define zerocross D6 // D6 for boards with CHANGEBLE input pins //#define pas 5 // //dimmerLamp dimmer(outputPin, zerocross); //initialase port for dimmer for ESP8266, ESP32, Arduino due boards ////dimmerLamp dimmer(outputPin); //initialase port for dimmer for MEGA, Leonardo, UNO, Arduino M0, Arduino Zero // // ########################################## // VICTRON String devicename = "Victron Blue Solar"; #include "config.h" #define PRINT_EVERY_SECONDS 5 #define rxPin D4 //D7 #define txPin 1 // D8 // TX Not used SoftwareSerial victronSerial(rxPin, txPin); // via the USB serial provided by the NodeMCU. char receivedChars[buffsize]; // an array to store the received data char tempChars[buffsize]; // an array to manipulate the received data char recv_label[num_keywords][label_bytes] = {0}; // {0} tells the compiler to initalize it with 0. char recv_value[num_keywords][value_bytes] = {0}; // That does not mean it is filled with 0's char value[num_keywords][value_bytes] = {0}; // The array that holds the verified data static byte blockindex = 0; bool new_data = false; bool blockend = false; int outVal = 0; String webpage = R"=( Victron Control
@@pwmCount@@
)="; bool led; int pwm; int pwmCount; // //void ledON(){ // led=1; // digitalWrite(LEDn, led); // handleRoot(); // //} // //void ledOFF(){ // led=0; // digitalWrite(LEDn, led); // handleRoot(); //} // ////pwm functions - if pwm is set to 1/-1 it will in-/decrease pwmCounter in loop() //void exact(){ // int value_to_set = getValueFromParam(); // // pwm=value_to_set; // pwmCount = pwm; // if (pwmCount>100) pwmCount = 100; // if (pwmCount < 0) { // pwmCount = 0; // } // // Serial.println(pwmCount); // //dimmer.setPower(pwmCount); // setPwm(pwmCount); // // handleRoot(); //} //void plus(){ // int value_to_set = getValueFromParam(); // if (value_to_set <= 0) { // value_to_set = 5; // } // pwm+=value_to_set; // setPwm(pwm); // handleRoot(); //} // //void minus(){ // int value_to_set = getValueFromParam(); // if (value_to_set <= 0) { // value_to_set = 5; // } // pwm+=-value_to_set; // // setPwm(pwm); // handleRoot(); //} // //void stopPWM(){ // pwm=0; //-pwmCount; // setPwm(pwm); // handleRoot(); //} // //void setPwm(int pwm) //{ // pwmCount = pwm; // if (pwmCount>100) pwmCount = 100; // if (pwmCount <= 1) { // pwmCount = 0; // } // // Serial.println(pwmCount); // // if (pwmCount <= 0) { // dimmer.setState(ON_OFF_typedef::OFF); // } // else { // dimmer.setState(ON_OFF_typedef::ON); // } // dimmer.setPower(pwmCount); //} //---------------------------------------------------------------------------------- void handleRoot(void){ String page = webpage; page.replace("@@pwmCount@@", String(pwmCount)); //Serial.println(page); server.send(200, "text/html", page); } //int getValueFromParam() //{ // String message = "Number of args received:"; // // message += server.args(); // // for (int i = 0; i < server.args(); i++) { // message = message + ("Arg nº" + String(i) + " –> "); // message = message + (server.argName(i) + ": "); // message = message + (server.arg(i) + "\n"); // if (server.argName(i) == "value") { // return String(server.arg(i)).toInt(); // } // } // Serial.println(message); // return pas; //} void initWifi() { WiFi.mode(WIFI_AP); WiFi.begin(ssid, pass); //Connect to local Wifi Serial.println(); Serial.print("Connecting to WiFi"); while (WiFi.status() != WL_CONNECTED) { Serial.print("."); delay(500); } Serial.println("WiFi Connected!"); Serial.print("Connexion au reseau "); Serial.println(WiFi.localIP()); } void initWifiStatic( IPAddress ip, IPAddress gateway, IPAddress subnet, IPAddress DNS) { WiFi.config(ip, gateway, subnet, DNS); delay(100); WiFi.mode(WIFI_STA); WiFi.begin(ssid, pass); Serial.print("Connecting"); while (WiFi.status() != WL_CONNECTED) { Serial.print("."); delay(200); } while (WiFi.waitForConnectResult() != WL_CONNECTED) { Serial.println(); Serial.println("Fail connecting"); delay(5000); ESP.restart(); } Serial.print(" static OK "); Serial.print("Module IP: "); Serial.println(WiFi.localIP()); } String generateKey() { // WiFi.mode(WIFI_AP); // Do a little work to get a unique-ish name. Append the // last two bytes of the MAC (HEX'd) to "Thing-": uint8_t mac[WL_MAC_ADDR_LENGTH]; WiFi.softAPmacAddress(mac); String macID = String(mac[WL_MAC_ADDR_LENGTH - 2], HEX) + String(mac[WL_MAC_ADDR_LENGTH - 1], HEX); macID.toUpperCase(); String AP_NameString = "ESP8266 Thing " + macID; char AP_NameChar[AP_NameString.length() + 1]; memset(AP_NameChar, 0, AP_NameString.length() + 1); for (int i = 0; i < AP_NameString.length(); i++) { AP_NameChar[i] = AP_NameString.charAt(i); } // WiFi.softAP(AP_NameChar, WiFiAPPSK); Serial.println("macID=" + macID); return macID; } IPAddress getIP(String macId) { IPAddress ip; //(192, 168, 1, 222); String fst = macId.substring(0, 2); String sec = macId.substring(2); char fstc[fst.length() + 1]; fst.toCharArray(fstc, fst.length() + 1); char secc[sec.length() + 1]; sec.toCharArray(secc, fst.length() + 1); return IPAddress(192, 168, strtol(fstc, 0, 16), strtol(secc, 0, 16)); } // Méthode pour gérer la requête '/getData' void handleData() { String JSON = F("["); for (int i = 0; i < num_keywords; i++){ JSON += "{\"id\":\"" + String(keywords[i]) + "\", \"value\":\"" + String(value[i]) + "\"},"; } JSON += "{\"id\":\"end\", \"value\":\"end\"}"; JSON += "]"; server.send(200, "application/json", JSON); // // Créer un objet JSON // DynamicJsonDocument doc(200); // // for (int i = 0; i < num_keywords; i++){ // doc[String(keywords[i])] = String(value[i]); // } // // // Convertir l'objet jsonData en chaîne // String jsonData; // serializeJson(doc, jsonData); // // // Envoyer la réponse JSON au client // server.send(200, "application/json", jsonData); } void setup() { Serial.begin(115200); victronSerial.begin(19200); //delay(200); // String macId = generateKey(); // IPAddress ip = getIP(macId); // // // Conversion d'objet en pointeur // initWifiStatic(ip, gateway, subnet, DNS); // Connectez-vous au réseau WiFi WiFi.begin(ssid, pass); Serial.println("Connexion au WiFi en cours."); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.print("."); } Serial.println(""); Serial.println("Connecté au réseau WiFi"); Serial.println(WiFi.localIP()); //Server________________________________ server.begin(); server.on("/", handleRoot); // server.onNotFound([](AsyncWebServerRequest *request){ // if (request->method() == HTTP_OPTIONS){ // request->send(204); // } // else { // request->send(404); // } // }); // server.on("/LEDon", ledON); // server.on("/LEDoff", ledOFF); server.on("/getData", HTTP_GET, handleData); // server.on("/minus", minus); // server.on("/plus", plus); // server.on("/exact", exact); // server.on("/stop", stopPWM); //initialize variables__________________ pwm = 0; pwmCount= 0; led = 0; Serial.print("Module IP: "); Serial.println(WiFi.softAPIP()); // // Dimmer // Serial.println("Dimmer Program is starting..."); // delay(1000); // dimmer.begin(NORMAL_MODE, ON); //dimmer initialisation: name.begin(MODE, STATE) // Serial.println("Set value"); // dimmer.setState(ON_OFF_typedef::OFF); // dimmer.setPower(pwmCount); // setPower(0-100%); // send temperature every 30s // flipper.attach(30, flip); // Port defaults to 8266 ArduinoOTA.setPort(8266); // Hostname defaults to esp8266-[ChipID] // ArduinoOTA.setHostname("myesp8266"); // 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([]() { String type; if (ArduinoOTA.getCommand() == U_FLASH) { type = "sketch"; } else { // U_FS type = "filesystem"; } // NOTE: if updating FS this would be the place to unmount FS using FS.end() Serial.println("Start updating " + type); }); 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(); Serial.println("Ready"); Serial.print("IP address: "); Serial.println(WiFi.localIP()); } long temps = 0; // Serial Handling // --- // This block handles the serial reception of the data in a // non blocking way. It checks the Serial line for characters and // parses them in fields. If a block of data is send, which always ends // with "Checksum" field, the whole block is checked and if deemed correct // copied to the 'value' array. void recvWithEndMarker() { static byte ndx = 0; char endMarker = '\n'; char rc; while (victronSerial.available() > 0 && new_data == false) { rc = victronSerial.read(); if (rc != endMarker) { receivedChars[ndx] = rc; ndx++; if (ndx >= buffsize) { ndx = buffsize - 1; } } else { receivedChars[ndx] = '\0'; // terminate the string ndx = 0; new_data = true; } yield(); } } void parseData() { char * strtokIndx; // this is used by strtok() as an index strtokIndx = strtok(tempChars,"\t"); // get the first part - the label // The last field of a block is always the Checksum if (strcmp(strtokIndx, "Checksum") == 0) { blockend = true; } strcpy(recv_label[blockindex], strtokIndx); // copy it to label // Now get the value strtokIndx = strtok(NULL, "\r"); // This continues where the previous call left off until '/r'. if (strtokIndx != NULL) { // We need to check here if we don't receive NULL. strcpy(recv_value[blockindex], strtokIndx); } blockindex++; if (blockend) { // We got a whole block into the received data. // Check if the data received is not corrupted. // Sum off all received bytes should be 0; byte checksum = 0; for (int x = 0; x < blockindex; x++) { // Loop over the labels and value gotten and add them. // Using a byte so the the % 256 is integrated. char *v = recv_value[x]; char *l = recv_label[x]; while (*v) { checksum += *v; v++; } while (*l) { checksum+= *l; l++; } // Because we strip the new line(10), the carriage return(13) and // the horizontal tab(9) we add them here again. checksum += 32; } // Checksum should be 0, so if !0 we have correct data. if (!checksum) { // Since we are getting blocks that are part of a // keyword chain, but are not certain where it starts // we look for the corresponding label. This loop has a trick // that will start searching for the next label at the start of the last // hit, which should optimize it. int start = 0; for (int i = 0; i < blockindex; i++) { for (int j = start; (j - start) < num_keywords; j++) { if (strcmp(recv_label[i], keywords[j % num_keywords]) == 0) { // found the label, copy it to the value array strcpy(value[j], recv_value[i]); start = (j + 1) % num_keywords; // start searching the next one at this hit +1 break; } } } } // Reset the block index, and make sure we clear blockend. blockindex = 0; blockend = false; } } void printValues() { for (int i = 0; i < num_keywords; i++){ Serial.print(keywords[i]); Serial.print(","); Serial.println(value[i]); } } void printData() { static unsigned long prev_millis; if (millis() - prev_millis > PRINT_EVERY_SECONDS * 1000) { printValues(); prev_millis = millis(); } } void handleNewData() { // We have gotten a field of data if (new_data == true) { //Copy it to the temp array because parseData will alter it. strcpy(tempChars, receivedChars); parseData(); new_data = false; } } void loop() { server.handleClient(); ArduinoOTA.handle(); // Receive information on Serial from MPPT recvWithEndMarker(); handleNewData(); // Just print the values every second, // Add your own code here to use the data. // Make sure to not used delay(X)s of bigger than 50ms, // so make use of the same principle used in printData() // or use some sort of Alarm/Timer Library printData(); }