diff --git a/ESPController/include/defines.h b/ESPController/include/defines.h index 861d657..4ef491f 100644 --- a/ESPController/include/defines.h +++ b/ESPController/include/defines.h @@ -20,7 +20,7 @@ #define SERIAL_RS485 Serial1 // Total number of cells a single controler can handle (memory limitation) -#define maximum_controller_cell_modules 128 +#define maximum_controller_cell_modules 192 typedef union { @@ -254,6 +254,10 @@ struct diybms_eeprom_settings uint8_t canbus_equipment_addr; // battery index on the same canbus for PYLONFORCE, 0 - 15, default 0 char homeassist_apikey[24+1]; + + // State of health variables + uint32_t soh_total_milliamphour_out; + uint32_t soh_total_milliamphour_in; }; typedef union diff --git a/ESPController/include/settings.h b/ESPController/include/settings.h index f75c964..429236b 100644 --- a/ESPController/include/settings.h +++ b/ESPController/include/settings.h @@ -14,7 +14,7 @@ bool getSetting(nvs_handle_t handle, const char *key, float *out_value); bool getSetting(nvs_handle_t handle, const char *key, uint8_t *out_value); bool getSetting(nvs_handle_t handle, const char *key, int8_t *out_value); bool getSetting(nvs_handle_t handle, const char *key, uint16_t *out_value); -// bool getSetting(nvs_handle_t handle, const char *key, uint32_t *out_value); +bool getSetting(nvs_handle_t handle, const char *key, uint32_t *out_value); bool getSetting(nvs_handle_t handle, const char *key, int32_t *out_value); bool getSetting(nvs_handle_t handle, const char *key, int16_t *out_value); bool getSetting(nvs_handle_t handle, const char *key, bool *out_value); @@ -22,7 +22,7 @@ bool getSetting(nvs_handle_t handle, const char *key, bool *out_value); bool getSettingBlob(nvs_handle_t handle, const char *key, void *out_value, size_t size); void InitializeNVS(); -void SaveConfiguration(diybms_eeprom_settings *settings); +void SaveConfiguration(const diybms_eeprom_settings *settings); void LoadConfiguration(diybms_eeprom_settings *settings); void ValidateConfiguration(diybms_eeprom_settings *settings); void DefaultConfiguration(diybms_eeprom_settings *settings); @@ -37,6 +37,8 @@ void writeSetting(nvs_handle_t handle, const char *key, bool value); void writeSetting(nvs_handle_t handle, const char *key, uint8_t value); void writeSetting(nvs_handle_t handle, const char *key, uint16_t value); void writeSetting(nvs_handle_t handle, const char *key, int16_t value); +void writeSetting(nvs_handle_t handle, const char *key, int32_t value); +void writeSetting(nvs_handle_t handle, const char *key, uint32_t value); void writeSetting(nvs_handle_t handle, const char *key, int8_t value); void writeSetting(nvs_handle_t handle, const char *key, const char *value); void writeSettingBlob(nvs_handle_t handle, const char *key, const void *value, size_t length); diff --git a/ESPController/include/webserver.h b/ESPController/include/webserver.h index 3c4830d..494a45f 100644 --- a/ESPController/include/webserver.h +++ b/ESPController/include/webserver.h @@ -27,8 +27,8 @@ int printBoolean(char *buffer, size_t bufferLen, const char *fieldName, boolean void generateUUID(); void StartServer(); -void resetModuleMinMaxVoltage(uint8_t module); -void clearModuleValues(uint8_t module); +void resetModuleMinMaxVoltage(uint8_t m); +void clearModuleValues(uint8_t m); httpd_handle_t start_webserver(void); void stop_webserver(httpd_handle_t server); @@ -47,6 +47,6 @@ extern RelayState previousRelayState[RELAY_TOTAL]; extern currentmonitoring_struct currentMonitor; extern void suspendTasksDuringFirmwareUpdate(); extern void resumeTasksAfterFirmwareUpdateFailure(); -extern void SaveConfiguration(diybms_eeprom_settings *settings); +extern void SaveConfiguration(const diybms_eeprom_settings *settings); extern esp_err_t content_handler_coredumpdownloadfile(httpd_req_t *req); #endif \ No newline at end of file diff --git a/ESPController/include/webserver_helper_funcs.h b/ESPController/include/webserver_helper_funcs.h index 610c6a8..1428c19 100644 --- a/ESPController/include/webserver_helper_funcs.h +++ b/ESPController/include/webserver_helper_funcs.h @@ -30,6 +30,8 @@ bool validateXSSWithPOST(httpd_req_t *req, const char *postbuffer, bool urlEncod void setCookieValue(); void setCookie(httpd_req_t *req); +void randomCharacters(char* value, int length); + // These are borrowed from the new ESP IDF framework, will need to be removed if framework is upgraded esp_err_t httpd_req_get_cookie_val(httpd_req_t *req, const char *cookie_name, char *val, size_t *val_size); esp_err_t httpd_cookie_key_value(const char *cookie_str, const char *key, char *val, size_t *val_size); diff --git a/ESPController/src/main.cpp b/ESPController/src/main.cpp index b7959d4..6426a43 100644 --- a/ESPController/src/main.cpp +++ b/ESPController/src/main.cpp @@ -1584,14 +1584,14 @@ void ShutdownAllNetworkServices() } /// @brief Count of events of RSSI low -uint16_t wifi_count_rssi_low=0; -uint16_t wifi_count_sta_start=0; +uint16_t wifi_count_rssi_low = 0; +uint16_t wifi_count_sta_start = 0; /// @brief Count of events for WIFI connect -uint16_t wifi_count_sta_connected=0; +uint16_t wifi_count_sta_connected = 0; /// @brief Count of events for WIFI disconnect -uint16_t wifi_count_sta_disconnected=0; -uint16_t wifi_count_sta_lost_ip=0; -uint16_t wifi_count_sta_got_ip=0; +uint16_t wifi_count_sta_disconnected = 0; +uint16_t wifi_count_sta_lost_ip = 0; +uint16_t wifi_count_sta_got_ip = 0; /// @brief WIFI Event Handler /// @param @@ -2767,7 +2767,7 @@ void send_ext_canbus_message(const uint32_t identifier, const uint8_t *buffer, c // Delay a little whilst sending packets to give ESP32 some breathing room and not flood the CANBUS // vTaskDelay(pdMS_TO_TICKS(100)); } - else if (mysettings.canbusprotocol == CanBusProtocolEmulation::CANBUS_PYLONFORCEH2 ) + else if (mysettings.canbusprotocol == CanBusProtocolEmulation::CANBUS_PYLONFORCEH2) { pylonforce_handle_tx(); } @@ -2823,10 +2823,10 @@ void send_ext_canbus_message(const uint32_t identifier, const uint8_t *buffer, c canbus_messages_received++; ESP_LOGD(TAG, "CANBUS received message ID: %0x, DLC: %d, flags: %0x", message.identifier, message.data_length_code, message.flags); - if (!(message.flags & TWAI_MSG_FLAG_RTR)) // we do not answer to Remote-Transmission-Requests + if (!(message.flags & TWAI_MSG_FLAG_RTR)) // we do not answer to Remote-Transmission-Requests { -// ESP_LOG_BUFFER_HEXDUMP(TAG, message.data, message.data_length_code, ESP_LOG_DEBUG); - if (mysettings.canbusprotocol == CanBusProtocolEmulation::CANBUS_PYLONFORCEH2 ) + // ESP_LOG_BUFFER_HEXDUMP(TAG, message.data, message.data_length_code, ESP_LOG_DEBUG); + if (mysettings.canbusprotocol == CanBusProtocolEmulation::CANBUS_PYLONFORCEH2) { pylonforce_handle_rx(&message); } @@ -3195,6 +3195,7 @@ void send_ext_canbus_message(const uint32_t identifier, const uint8_t *buffer, c // Screen off tftsleep(); } + } } @@ -3233,6 +3234,12 @@ void send_ext_canbus_message(const uint32_t identifier, const uint8_t *buffer, c // Has day rolled over? if (year_day != timeinfo.tm_yday) { + + mysettings.soh_total_milliamphour_out += currentMonitor.modbus.daily_milliamphour_out; + mysettings.soh_total_milliamphour_in += currentMonitor.modbus.daily_milliamphour_in; + + SaveConfiguration(&mysettings); + // Reset the current monitor at midnight (ish) CurrentMonitorResetDailyAmpHourCounters(); @@ -3833,11 +3840,12 @@ ESP32 Chip model = %u, Rev %u, Cores=%u, Features=%u)", LoadConfiguration(&mysettings); ValidateConfiguration(&mysettings); + if (strlen(mysettings.homeassist_apikey) == 0) { // Generate new key memset(&mysettings.homeassist_apikey, 0, sizeof(mysettings.homeassist_apikey)); - randomCharacters(mysettings.homeassist_apikey, sizeof(mysettings.homeassist_apikey) - 1); + randomCharacters(mysettings.homeassist_apikey, sizeof(mysettings.homeassist_apikey) - 1); saveConfiguration(); } ESP_LOGI(TAG, "homeassist_apikey=%s", mysettings.homeassist_apikey); diff --git a/ESPController/src/settings.cpp b/ESPController/src/settings.cpp index 993a08c..72c9b3b 100644 --- a/ESPController/src/settings.cpp +++ b/ESPController/src/settings.cpp @@ -91,6 +91,9 @@ static const char floatvoltagetimer_JSONKEY[] = "floatvoltagetimer"; static const char stateofchargeresumevalue_JSONKEY[] = "stateofchargeresumevalue"; static const char homeassist_apikey_JSONKEY[] = "homeassistapikey"; +static const char soh_total_milliamphour_out_JSONKEY[] = "soh_mah_out"; +static const char soh_total_milliamphour_in_JSONKEY[] = "soh_mah_in"; + /* NVS KEYS THESE STRINGS ARE USED TO HOLD THE PARAMETER IN NVS FLASH, MAXIMUM LENGTH OF 16 CHARACTERS */ @@ -122,7 +125,7 @@ static const char rs485stopbits_NVSKEY[] = "485stopbits"; static const char canbusprotocol_NVSKEY[] = "canbusprotocol"; static const char canbusinverter_NVSKEY[] = "canbusinverter"; static const char canbusbaud_NVSKEY[] = "canbusbaud"; -static const char canbus_equipment_addr_NVSKEY[]="canbusequip"; +static const char canbus_equipment_addr_NVSKEY[] = "canbusequip"; static const char nominalbatcap_NVSKEY[] = "nominalbatcap"; static const char chargevolt_NVSKEY[] = "cha_volt"; static const char chargecurrent_NVSKEY[] = "cha_current"; @@ -183,6 +186,10 @@ static const char floatvoltagetimer_NVSKEY[] = "floatVtimer"; static const char stateofchargeresumevalue_NVSKEY[] = "socresume"; static const char homeassist_apikey_NVSKEY[] = "haapikey"; +static const char soh_total_milliamphour_out_NVSKEY[] = "soh_mah_out"; +static const char soh_total_milliamphour_in_NVSKEY[] = "soh_mah_in"; + + #define MACRO_NVSWRITE(VARNAME) writeSetting(nvs_handle, VARNAME##_NVSKEY, settings->VARNAME); #define MACRO_NVSWRITE_UINT8(VARNAME) writeSetting(nvs_handle, VARNAME##_NVSKEY, (uint8_t)settings->VARNAME); #define MACRO_NVSWRITESTRING(VARNAME) writeSetting(nvs_handle, VARNAME##_NVSKEY, &settings->VARNAME[0]); @@ -201,7 +208,6 @@ bool ValidateGetSetting(esp_err_t err, const char *key) case ESP_OK: ESP_LOGD(TAG, "Read key (%s)", key); return true; - break; case ESP_ERR_NVS_NOT_FOUND: ESP_LOGW(TAG, "Key not initialized (%s)", key); break; @@ -310,6 +316,11 @@ void writeSetting(nvs_handle_t handle, const char *key, int16_t value) ESP_LOGD(TAG, "Writing (%s)=%i", key, value); ESP_ERROR_CHECK(nvs_set_i16(handle, key, value)); } +void writeSetting(nvs_handle_t handle, const char *key, uint32_t value) +{ + ESP_LOGD(TAG, "Writing (%s)=%i", key, value); + ESP_ERROR_CHECK(nvs_set_u32(handle, key, value)); +} void writeSetting(nvs_handle_t handle, const char *key, int32_t value) { ESP_LOGD(TAG, "Writing (%s)=%i", key, value); @@ -331,7 +342,7 @@ void writeSettingBlob(nvs_handle_t handle, const char *key, const void *value, s ESP_ERROR_CHECK(nvs_set_blob(handle, key, value, length)); } -void SaveConfiguration(diybms_eeprom_settings *settings) +void SaveConfiguration(const diybms_eeprom_settings *settings) { const char *partname = "diybms-ctrl"; ESP_LOGI(TAG, "Write config"); @@ -442,6 +453,9 @@ void SaveConfiguration(diybms_eeprom_settings *settings) MACRO_NVSWRITESTRING(homeassist_apikey); + MACRO_NVSWRITE(soh_total_milliamphour_out) + MACRO_NVSWRITE(soh_total_milliamphour_in) + ESP_ERROR_CHECK(nvs_commit(nvs_handle)); nvs_close(nvs_handle); } @@ -571,6 +585,9 @@ void LoadConfiguration(diybms_eeprom_settings *settings) MACRO_NVSREADSTRING(homeassist_apikey); + MACRO_NVSREAD(soh_total_milliamphour_out); + MACRO_NVSREAD(soh_total_milliamphour_in); + nvs_close(nvs_handle); } @@ -605,7 +622,7 @@ void DefaultConfiguration(diybms_eeprom_settings *_myset) _myset->canbusinverter = CanBusInverter::INVERTER_GENERIC; _myset->canbus_equipment_addr = 0; - _myset->canbusbaud=500; + _myset->canbusbaud = 500; _myset->nominalbatcap = 280; // Scale 1 _myset->chargevolt = 565; // Scale 0.1 _myset->chargecurrent = 650; // Scale 0.1 @@ -753,6 +770,10 @@ void DefaultConfiguration(diybms_eeprom_settings *_myset) _myset->floatvoltagetimer = 6 * 60; // Once battery SoC drops below this value, resume normal charging operation _myset->stateofchargeresumevalue = 96; + + // State of health + _myset->soh_total_milliamphour_out = 0; + _myset->soh_total_milliamphour_in = 0; } /// @brief Save WIFI settings into FLASH NVS @@ -1015,7 +1036,7 @@ void GenerateSettingsJSONDocument(DynamicJsonDocument *doc, diybms_eeprom_settin root[rs485stopbits_JSONKEY] = settings->rs485stopbits; root[language_JSONKEY] = settings->language; - root[homeassist_apikey_JSONKEY]=settings->homeassist_apikey; + root[homeassist_apikey_JSONKEY] = settings->homeassist_apikey; JsonObject mqtt = root.createNestedObject("mqtt"); mqtt[mqtt_enabled_JSONKEY] = settings->mqtt_enabled; @@ -1074,7 +1095,7 @@ void GenerateSettingsJSONDocument(DynamicJsonDocument *doc, diybms_eeprom_settin root[canbusprotocol_JSONKEY] = (uint8_t)settings->canbusprotocol; root[canbusinverter_JSONKEY] = (uint8_t)settings->canbusinverter; root[canbusbaud_JSONKEY] = settings->canbusbaud; - root[canbus_equipment_addr_JSONKEY]=settings->canbus_equipment_addr; + root[canbus_equipment_addr_JSONKEY] = settings->canbus_equipment_addr; root[nominalbatcap_JSONKEY] = settings->nominalbatcap; root[chargevolt_JSONKEY] = settings->chargevolt; @@ -1113,6 +1134,9 @@ void GenerateSettingsJSONDocument(DynamicJsonDocument *doc, diybms_eeprom_settin } // wifi["password"] = DIYBMSSoftAP::Config().wifi_passphrase; + + root[soh_total_milliamphour_out_JSONKEY] = settings->soh_total_milliamphour_out; + root[soh_total_milliamphour_in_JSONKEY] = settings->soh_total_milliamphour_in; } void JSONToSettings(DynamicJsonDocument &doc, diybms_eeprom_settings *settings) @@ -1177,7 +1201,7 @@ void JSONToSettings(DynamicJsonDocument &doc, diybms_eeprom_settings *settings) settings->canbusprotocol = (CanBusProtocolEmulation)root[canbusprotocol_JSONKEY]; settings->canbusinverter = (CanBusInverter)root[canbusinverter_JSONKEY]; settings->canbusbaud = root[canbusbaud_JSONKEY]; - settings->canbus_equipment_addr=root[canbus_equipment_addr_JSONKEY]; + settings->canbus_equipment_addr = root[canbus_equipment_addr_JSONKEY]; settings->nominalbatcap = root[nominalbatcap_JSONKEY]; settings->chargevolt = root[chargevolt_JSONKEY]; settings->chargecurrent = root[chargecurrent_JSONKEY]; @@ -1201,10 +1225,13 @@ void JSONToSettings(DynamicJsonDocument &doc, diybms_eeprom_settings *settings) settings->current_value1 = root[current_value1_JSONKEY]; settings->current_value2 = root[current_value2_JSONKEY]; - settings->absorptiontimer=root[absorptiontimer_JSONKEY]; - settings->floatvoltage=root[floatvoltage_JSONKEY]; - settings->floatvoltagetimer=root[floatvoltagetimer_JSONKEY]; - settings->stateofchargeresumevalue=root[stateofchargeresumevalue_JSONKEY]; + settings->absorptiontimer = root[absorptiontimer_JSONKEY]; + settings->floatvoltage = root[floatvoltage_JSONKEY]; + settings->floatvoltagetimer = root[floatvoltagetimer_JSONKEY]; + settings->stateofchargeresumevalue = root[stateofchargeresumevalue_JSONKEY]; + + settings->soh_total_milliamphour_out = root[soh_total_milliamphour_out_JSONKEY]; + settings->soh_total_milliamphour_in = root[soh_total_milliamphour_in_JSONKEY]; strncpy(settings->homeassist_apikey, root[homeassist_apikey_JSONKEY].as().c_str(), sizeof(settings->homeassist_apikey)); @@ -1212,7 +1239,7 @@ void JSONToSettings(DynamicJsonDocument &doc, diybms_eeprom_settings *settings) if (!mqtt.isNull()) { settings->mqtt_enabled = mqtt[mqtt_enabled_JSONKEY]; - settings->mqtt_basic_cell_reporting=mqtt[mqtt_basic_cell_reporting_JSONKEY]; + settings->mqtt_basic_cell_reporting = mqtt[mqtt_basic_cell_reporting_JSONKEY]; strncpy(settings->mqtt_uri, mqtt[mqtt_uri_JSONKEY].as().c_str(), sizeof(settings->mqtt_uri)); strncpy(settings->mqtt_topic, mqtt[mqtt_topic_JSONKEY].as().c_str(), sizeof(settings->mqtt_topic)); strncpy(settings->mqtt_username, mqtt[mqtt_username_JSONKEY].as().c_str(), sizeof(settings->mqtt_username));