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 blockend = false; double tension_batterie; double intensite_decharge = 0; int outVal = 0; bool new_data = false; long temps = 0; String last_serial_string = ""; // //// =================================================================== //struct DataPair { // char key[10]; // char value[20]; //}; //DataPair data[num_keywords]; // Tableau pour stocker les paires //int currentIndex = 0; // // //void storeDataPair(String line) { // int delimiterIndex = line.indexOf('\t'); // Trouver la position de la tabulation // if (delimiterIndex > 0 && currentIndex < num_keywords) { // // Extraire la clé et la valeur de la ligne // String key = line.substring(0, delimiterIndex); // String value = line.substring(delimiterIndex + 1); // // // Stocker la clé et la valeur dans le tableau // key.toCharArray(data[currentIndex].key, sizeof(data[currentIndex].key)); // value.toCharArray(data[currentIndex].value, sizeof(data[currentIndex].value)); // currentIndex++; // } //} // //void processReceivedData(String data) { // currentIndex = 0; // Réinitialiser l'index pour les nouvelles données // int start = 0; // while (start < data.length()) { // int end = data.indexOf('\n', start); // if (end == -1) { // break; // } // String line = data.substring(start, end); // storeDataPair(line); // start = end + 1; // } //} // // //bool receivingData = false; // Indicateur pour savoir si nous sommes en train de recevoir des données //String receivedData = ""; //// =============================================================================== void addTension( struct tm* timeinfo, int value) { if(value > 30000) { return; } // Si le tableau est plein, décaler toutes les valeurs vers la gauche if (to_store.total_elements >= maxSize) { for (int i = 1; i < maxSize; i++) { to_store.hour[i - 1] = to_store.hour[i]; to_store.min[i - 1] = to_store.min[i]; to_store.tensions[i - 1] = to_store.tensions[i]; } to_store.hour[maxSize - 1] = timeinfo->tm_hour; to_store.min[maxSize - 1] = timeinfo->tm_min; to_store.tensions[maxSize - 1] = value; // Ajouter la nouvelle valeur à la fin } else { // Ajouter la nouvelle valeur à la fin //hour.toCharArray(to_store.hour[to_store.total_elements], sizeof(to_store.hour)); to_store.hour[to_store.total_elements] = timeinfo->tm_hour; to_store.min[to_store.total_elements] = timeinfo->tm_min; to_store.tensions[to_store.total_elements] = value; to_store.total_elements++; } to_store.total_elements %= maxSize; EEPROM.put(TO_STORE_ADDRESS, to_store); EEPROM.commit(); } // 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; // new_data = false; #ifdef ESP8266 while (victronSerial.available() > 0 && new_data == false) { rc = victronSerial.read(); #else while (Serial1.available() > 0 && new_data == false) { rc = Serial1.read(); #endif last_serial_string += rc; 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; } last_serial_string = String(receivedChars); 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 cleanValues() { // new_data = false; // strcpy("RESET", recv_value[CHECKSUM]); // for (int i = 0; i < num_keywords; i++){ // strcpy("", recv_value[i]); // } } void printValues() { for (int i = 0; i < num_keywords; i++){ Serial.print(keywords[i]); Serial.print("="); Serial.print(value[i]); Serial.print("|"); } Serial.println(""); } 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; } } // Méthode pour gérer la requête '/getData' void handleVictron() { blink(); #ifdef PIN_HALL getHall(); #endif #ifdef PIN_DALLAS // Command all devices on bus to read temperature // Serial.print("Temperature is: "); temperature = printTemperature(Probe); //Serial.println(); #endif #ifdef SERIAL_XY6020L printMem(); #endif #ifdef SERIAL_XY6020L_2 printMem2(); #endif String JSON = F("["); for (int i = 0; i < num_keywords; i++){ // String key = data[i].key; //String(keywords[i]); // String val = data[i].value; //String(value[i]); String key = String(keywords[i]); String val = String(value[i]); String label = ""; String key_label = ""; // if (key.equals("CS")) { // label = "Etat"; // val = operationStates[val.toInt()].label; // } for (int i = 0; i < mpptDataSize; i++) { if (key.equals(mpptData[i].code)) { key_label= key + " " + mpptData[i].label; } } if (key.equals("OR")) { for (int i = 0; i < offReasonsSize; i++) { if (val.equals(offReasons[i].code)) { label = offReasons[i].label; } } } if (key.equals("CS")) { for (int i = 0; i < operationStatesSize; i++) { if (val.equals(operationStates[i].code)) { label = operationStates[i].label; } } } if (key.equals("MPPT")) { for (int i = 0; i < mpptStatesSize; i++) { if (val.equals(mpptStates[i].code)) { label = mpptStates[i].label; } } } if (key.equals("ERR")) { for (int i = 0; i < errorCodesSize; i++) { if (val.equals(errorCodes[i].code)) { label = errorCodes[i].label; } } } if (key.equals("IL")) { intensite_decharge = val.toFloat() / 1000; } if (key.equals("V")) { tension_batterie = val.toFloat() / 1000; } if (key.equals("Checksum")) { String tensions = ""; String labels = ""; for (int i = 0; i < maxSize; i++) { if (i == 0) { tensions = String(to_store.tensions[i]); labels = String(to_store.hour[i]) + ":" + String(to_store.min[i]); } else { tensions += "," + String(to_store.tensions[i]); labels += "," + String((to_store.hour[i] < 10 ? "0" : "") + String(to_store.hour[i])) + ":" + String((to_store.min[i] < 10 ? "0" : "") + String(to_store.min[i])) ; } } JSON += "{\"id\":\"output-power\", \"value\":\"" + String(tension_batterie * intensite_decharge,1) + "\"},"; #ifdef TUYA JSON += "{\"id\":\"CONSO\", \"value\":\"" + String(String(conso_apparente).toFloat(),1) + "\"},"; JSON += "{\"id\":\"PROD\", \"value\":\"" + String(String(production).toFloat(),1) + "\"},"; #endif #ifdef PIN_DALLAS JSON += "{\"id\":\"TEMPERATURE\", \"value\":\"" + String(temperature,1) + "\"},"; #endif #ifdef PIN_REGULATION JSON += "{\"id\":\"REGULATION\", \"value\":\"" + String(current_regulation) + "\"},"; #endif #ifdef PIN_DIMMER_OUTPUT JSON += "{\"id\":\"RADIATEUR\", \"value\":\"" + String(pwm) + "\"},"; #endif #ifdef PIN_HALL getHall(); JSON += "{\"id\":\"HALL_V\", \"value\":\"" + String(VRMS) + "\"},"; JSON += "{\"id\":\"HALL_I\", \"value\":\"" + String(Amps) + "\"},"; JSON += "{\"id\":\"HALL_W\", \"value\":\"" + String(Amps * 230) + "\"},"; #endif #ifdef SERIAL_XY6020L if(xy.HRegUpdated()) { xy.ReadAllHRegs(); } JSON += "{\"id\":\"CHRG\", \"value\":\"" + String(digitalRead(PIN_CHARGE)) + "\"},"; JSON += "{\"id\":\"XY_ON\", \"value\":\"" + String(xy.getOutputOn()) + "\"},"; JSON += "{\"id\":\"XY_inV\", \"value\":\"" + String(xy.getInV()) + "\"},"; JSON += "{\"id\":\"XY_V\", \"value\":\"" + String(xy.getCV()) + "\"},"; JSON += "{\"id\":\"XY_C\", \"value\":\"" + String(xy.getCC()) + "\"},"; JSON += "{\"id\":\"XY_T\", \"value\":\"" + String(xy.getTemp()) + "\"},"; JSON += "{\"id\":\"XY_AV\", \"value\":\"" + String(xy.getActV()) + "\"},"; JSON += "{\"id\":\"XY_AC\", \"value\":\"" + String(xy.getActC()) + "\"},"; JSON += "{\"id\":\"XY_AW\", \"value\":\"" + String(xy.getActP()) + "\"},"; JSON += "{\"id\":\"XY_CHG\", \"value\":\"" + String(xy.getCharge()) + "\"},"; JSON += "{\"id\":\"XY_NRJ\", \"value\":\"" + String(xy.getEnergy()) + "\"},"; #endif #ifdef SERIAL_XY6020L_2 if(xy2.HRegUpdated()) { xy2.ReadAllHRegs(); } JSON += "{\"id\":\"INJC\", \"value\":\"" + String(digitalRead(PIN_INJECTION)) + "\"},"; JSON += "{\"id\":\"XY2_ON\", \"value\":\"" + String(xy2.getOutputOn()) + "\"},"; JSON += "{\"id\":\"XY2_inV\", \"value\":\"" + String(xy2.getInV()) + "\"},"; JSON += "{\"id\":\"XY2_V\", \"value\":\"" + String(xy2.getCV()) + "\"},"; JSON += "{\"id\":\"XY2_C\", \"value\":\"" + String(xy2.getCC()) + "\"},"; JSON += "{\"id\":\"XY2_T\", \"value\":\"" + String(xy2.getTemp()) + "\"},"; JSON += "{\"id\":\"XY2_AV\", \"value\":\"" + String(xy2.getActV()) + "\"},"; JSON += "{\"id\":\"XY2_AC\", \"value\":\"" + String(xy2.getActC()) + "\"},"; JSON += "{\"id\":\"XY2_AW\", \"value\":\"" + String(xy2.getActP()) + "\"},"; JSON += "{\"id\":\"XY2_CHG\", \"value\":\"" + String(xy2.getCharge()) + "\"},"; JSON += "{\"id\":\"XY2_NRJ\", \"value\":\"" + String(xy2.getEnergy()) + "\"},"; #endif JSON += "{\"id\":\"MESSAGE\", \"value\":\"" + last_message + "\"},"; JSON += "{\"id\":\"tensions\", \"value\":\"" + tensions + "\",\"labels\":\"" + labels + "\"},"; // #ifndef SERIAL_BLUE_SOLAR // JSON += "{\"id\":\"" + key + "\",\"key_label\":\"" + key_label + "\",\"label\":\"" + label + "\", \"value\":\"" + val + "\"},"; // #endif } else { // if (i == ERR) { // // } // // #ifdef SERIAL_BLUE_SOLAR JSON += "{\"id\":\"" + key + "\",\"key_label\":\"" + key_label + "\",\"label\":\"" + label + "\", \"value\":\"" + val + "\"},"; // #endif } } //to_store.tensions //JSON += "{\"id\":\"last_serial_string\", \"value\":\"" + last_serial_string + "\"},"; JSON += "{\"id\":\"end\", \"value\":\"end\"}"; JSON += "]"; blink(); 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 handleDebug() { // Envoyer la réponse au client server.send(200, "text/plain", last_serial_string); }