From ba34b20305424404678a439f09403b67cec7ad2f Mon Sep 17 00:00:00 2001 From: matth-x <63792403+matth-x@users.noreply.github.com> Date: Thu, 5 Aug 2021 11:37:08 +0200 Subject: [PATCH 01/19] add session energy to total import --- src/ocpp.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ocpp.cpp b/src/ocpp.cpp index fe6809f5..31b74d4a 100644 --- a/src/ocpp.cpp +++ b/src/ocpp.cpp @@ -87,7 +87,10 @@ void ArduinoOcppTask::loadEvseBehavior() { }); setEnergyActiveImportSampler([evse = evse] () { - return (float) evse->getTotalEnergy(); + float activeImport = 0.f; + activeImport += (float) evse->getTotalEnergy(); + activeImport += (float) evse->getSessionEnergy(); + return activeImport; }); setOnChargingRateLimitChange([&charging_limit = charging_limit, this] (float limit) { //limit = maximum charge rate in Watts From 5981b7df8085a35b52cc85914760609979b6ef42 Mon Sep 17 00:00:00 2001 From: matth-x <63792403+matth-x@users.noreply.github.com> Date: Thu, 5 Aug 2021 15:04:55 +0200 Subject: [PATCH 02/19] add connector plugged for Status Notification --- src/ocpp.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ocpp.cpp b/src/ocpp.cpp index 31b74d4a..8041ad5f 100644 --- a/src/ocpp.cpp +++ b/src/ocpp.cpp @@ -98,6 +98,10 @@ void ArduinoOcppTask::loadEvseBehavior() { this->updateEvseClaim(); }); + setConnectorPluggedSampler([evse = evse] () { + return (bool) evse->isConnected(); + }); + setEvRequestsEnergySampler([evse = evse] () { return (bool) evse->isCharging(); }); From a3978a219e589081dc574eec4d3890e9676ffc9d Mon Sep 17 00:00:00 2001 From: matth-x <63792403+matth-x@users.noreply.github.com> Date: Thu, 5 Aug 2021 17:37:14 +0200 Subject: [PATCH 03/19] integrate reset, unlock conn, err report --- src/ocpp.cpp | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ocpp.h | 4 ++++ 2 files changed, 67 insertions(+) diff --git a/src/ocpp.cpp b/src/ocpp.cpp index 8041ad5f..ee472816 100644 --- a/src/ocpp.cpp +++ b/src/ocpp.cpp @@ -14,6 +14,9 @@ #include "emonesp.h" //for DEFAULT_VOLTAGE +#include "net_manager.h" //shut down network connection before reset +#include "espal.h" + #define LCD_DISPLAY(X) if (lcd) lcd->display((X), 0, 1, 5 * 1000, LCD_CLEAR_LINE); @@ -110,6 +113,41 @@ void ArduinoOcppTask::loadEvseBehavior() { return evse->isActive(); }); + /* + * Report failures to central system. Note that the error codes are standardized + */ + + addConnectorErrorCodeSampler([evse = evse] () { + if (evse->getEvseState() == OPENEVSE_STATE_GFI_FAULT || + evse->getEvseState() == OPENEVSE_STATE_NO_EARTH_GROUND || + evse->getEvseState() == OPENEVSE_STATE_GFI_SELF_TEST_FAILED) { + return "GroundFailure"; + } + return (const char *) NULL; + }); + + addConnectorErrorCodeSampler([evse = evse] () { + if (evse->getEvseState() == OPENEVSE_STATE_OVER_TEMPERATURE) { + return "HighTemperature"; + } + return (const char *) NULL; + }); + + addConnectorErrorCodeSampler([evse = evse] () { + if (evse->getEvseState() == OPENEVSE_STATE_OVER_CURRENT) { + return "OverCurrentFailure"; + } + return (const char *) NULL; + }); + + addConnectorErrorCodeSampler([evse = evse] () { + if (evse->getEvseState() == OPENEVSE_STATE_STUCK_RELAY || + evse->getEvseState() == OPENEVSE_STATE_DIODE_CHECK_FAILED) { + return "InternalError"; + } + return (const char *) NULL; + }); + /* * CP behavior definition: How will plugging and unplugging the EV start or stop OCPP transactions */ @@ -177,6 +215,21 @@ void ArduinoOcppTask::loadEvseBehavior() { this->updateEvseClaim(); }); + setOnResetReceiveReq([this] (JsonObject payload) { + const char *type = payload["type"] | "Soft"; + if (!strcmp(type, "Hard")) { + resetHard = true; + } + + resetTime = millis(); + resetTriggered = true; + }); + + setOnUnlockConnector([] () { + //TODO Send unlock command to peripherals. If successful, return true, otherwise false + return false; + }); + updateEvseClaim(); } @@ -214,6 +267,16 @@ unsigned long ArduinoOcppTask::loop(MicroTasks::WakeReason reason) { onVehicleDisconnect(); } + if (resetTriggered) { + if (millis() - resetTime >= 10000UL) { //wait for 10 seconds after reset command to send the conf msg + if (resetHard) { + //TODO send reset command to all peripherals + } + net_wifi_disconnect(); + ESPAL.reset(); + } + } + return 0; } diff --git a/src/ocpp.h b/src/ocpp.h index 6ad5a180..70f0db85 100644 --- a/src/ocpp.h +++ b/src/ocpp.h @@ -33,6 +33,10 @@ class ArduinoOcppTask: public MicroTasks::Task { std::function onVehicleConnect = [] () {}; std::function onVehicleDisconnect = [] () {}; + bool resetTriggered = false; + bool resetHard = false; //default to soft reset + ulong resetTime; + void initializeArduinoOcpp(); bool arduinoOcppInitialized = false; void loadEvseBehavior(); From cdf919ad214f3364bbd7e1efaecfdd539a8333a2 Mon Sep 17 00:00:00 2001 From: matth-x <63792403+matth-x@users.noreply.github.com> Date: Fri, 6 Aug 2021 14:58:03 +0200 Subject: [PATCH 04/19] extend BootNotification credentials --- platformio.ini | 3 ++- src/ocpp.cpp | 11 ++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index 6effa8b2..2f3a9062 100644 --- a/platformio.ini +++ b/platformio.ini @@ -42,7 +42,8 @@ lib_deps = MicroTasks@0.0.2 ESP32 AnalogWrite@0.2 lorol/LittleFS_esp32@1.0.5 - matth-x/ArduinoOcpp@0.0.2 + #matth-x/ArduinoOcpp@0.0.2 + https://github.com/matth-x/ArduinoOcpp.git#develop lib_ignore = WebSockets ; ArduinoOcpp: don't compile built-in WS library extra_scripts = scripts/extra_script.py debug_flags = diff --git a/src/ocpp.cpp b/src/ocpp.cpp index ee472816..1e8b9b5c 100644 --- a/src/ocpp.cpp +++ b/src/ocpp.cpp @@ -63,7 +63,16 @@ void ArduinoOcppTask::initializeArduinoOcpp() { OCPP_initialize(ocppSocket, (float) DEFAULT_VOLTAGE, ArduinoOcpp::FilesystemOpt::Use, clockAdapter); - bootNotification("Advanced Series", "OpenEVSE", [lcd = lcd](JsonObject payload) { + DynamicJsonDocument *evseDetailsDoc = new DynamicJsonDocument(JSON_OBJECT_SIZE(6)); + JsonObject evseDetails = evseDetailsDoc->to(); + evseDetails["chargePointModel"] = "Advanced Series"; + //evseDetails["chargePointSerialNumber"] = "TODO"; + evseDetails["chargePointVendor"] = "OpenEVSE"; + evseDetails["firmwareVersion"] = evse->getFirmwareVersion(); + //evseDetails["meterSerialNumber"] = "TODO"; + //evseDetails["meterType"] = "TODO"; + + bootNotification(evseDetailsDoc, [lcd = lcd](JsonObject payload) { //ArduinoOcpp will delete evseDetailsDoc LCD_DISPLAY("OCPP connected!"); }); From 604b207cd98cf320cef39d01e1d0a784afffb858 Mon Sep 17 00:00:00 2001 From: matth-x <63792403+matth-x@users.noreply.github.com> Date: Thu, 12 Aug 2021 09:39:45 +0200 Subject: [PATCH 05/19] don't add superfluous slash --- src/ocpp.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ocpp.cpp b/src/ocpp.cpp index 1e8b9b5c..6c10eb16 100644 --- a/src/ocpp.cpp +++ b/src/ocpp.cpp @@ -361,11 +361,11 @@ String ArduinoOcppTask::getCentralSystemUrl() { if (url.isEmpty()) { return url; //return empty String } - if (!url.endsWith("/")) { - url += '/'; - } String chargeBoxId = ocpp_chargeBoxId; chargeBoxId.trim(); + if (!url.endsWith("/") && !chargeBoxId.isEmpty()) { + url += '/'; + } url += chargeBoxId; if (MongooseOcppSocketClient::isValidUrl(url.c_str())) { From ee9abe7eaa50f94d38aa5538dc4c70ffd2b27cea Mon Sep 17 00:00:00 2001 From: matth-x <63792403+matth-x@users.noreply.github.com> Date: Thu, 12 Aug 2021 12:11:53 +0200 Subject: [PATCH 06/19] minor corrections --- src/ocpp.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/ocpp.cpp b/src/ocpp.cpp index 6c10eb16..80d0a7d8 100644 --- a/src/ocpp.cpp +++ b/src/ocpp.cpp @@ -123,13 +123,13 @@ void ArduinoOcppTask::loadEvseBehavior() { }); /* - * Report failures to central system. Note that the error codes are standardized + * Report failures to central system. Note that the error codes are standardized in OCPP */ addConnectorErrorCodeSampler([evse = evse] () { if (evse->getEvseState() == OPENEVSE_STATE_GFI_FAULT || evse->getEvseState() == OPENEVSE_STATE_NO_EARTH_GROUND || - evse->getEvseState() == OPENEVSE_STATE_GFI_SELF_TEST_FAILED) { + evse->getEvseState() == OPENEVSE_STATE_DIODE_CHECK_FAILED) { return "GroundFailure"; } return (const char *) NULL; @@ -151,7 +151,7 @@ void ArduinoOcppTask::loadEvseBehavior() { addConnectorErrorCodeSampler([evse = evse] () { if (evse->getEvseState() == OPENEVSE_STATE_STUCK_RELAY || - evse->getEvseState() == OPENEVSE_STATE_DIODE_CHECK_FAILED) { + evse->getEvseState() == OPENEVSE_STATE_GFI_SELF_TEST_FAILED) { return "InternalError"; } return (const char *) NULL; @@ -232,6 +232,8 @@ void ArduinoOcppTask::loadEvseBehavior() { resetTime = millis(); resetTriggered = true; + + LCD_DISPLAY("Reboot EVSE"); }); setOnUnlockConnector([] () { From d6dadc5ff120c72ad6622eba55be92dbd573ee6c Mon Sep 17 00:00:00 2001 From: matth-x <63792403+matth-x@users.noreply.github.com> Date: Thu, 7 Oct 2021 16:45:49 +0200 Subject: [PATCH 07/19] block when ChangeAvailability to inoperative --- src/ocpp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ocpp.cpp b/src/ocpp.cpp index 80d0a7d8..bf29a304 100644 --- a/src/ocpp.cpp +++ b/src/ocpp.cpp @@ -162,7 +162,7 @@ void ArduinoOcppTask::loadEvseBehavior() { */ onVehicleConnect = [this] () { - if (getTransactionId() < 0) { + if (getTransactionId() < 0 && isAvailable()) { if (!ocpp_idTag.isEmpty()) { authorize(ocpp_idTag, [this] (JsonObject payload) { if (idTagIsAccepted(payload)) { From 7d9a71c744f6603a6b868044a0bf5fac6d8f8a31 Mon Sep 17 00:00:00 2001 From: matth-x <63792403+matth-x@users.noreply.github.com> Date: Thu, 7 Oct 2021 17:49:44 +0200 Subject: [PATCH 08/19] FW update progress on LCD --- src/ocpp.cpp | 33 +++++++++++++++++++++++++++++++++ src/ocpp.h | 2 ++ 2 files changed, 35 insertions(+) diff --git a/src/ocpp.cpp b/src/ocpp.cpp index bf29a304..27ccbb48 100644 --- a/src/ocpp.cpp +++ b/src/ocpp.cpp @@ -9,6 +9,7 @@ #include // Facade for ArduinoOcpp #include // define behavior for incoming req messages +#include #include @@ -63,6 +64,38 @@ void ArduinoOcppTask::initializeArduinoOcpp() { OCPP_initialize(ocppSocket, (float) DEFAULT_VOLTAGE, ArduinoOcpp::FilesystemOpt::Use, clockAdapter); + ArduinoOcpp::FirmwareService *fwService = ArduinoOcpp::getFirmwareService(); + if (fwService) { + + } + + //TODO HTTPUpdate has added the onProgress cb to its own class definition in Jun '21. Replace when available (https://github.com/espressif/arduino-esp32/commit/db4e7667afe0e169c5f00567f4b59ab8e0fc1532) + Update.onProgress([lcd = lcd, &updateUserNotified = updateUserNotified](size_t index, size_t total) { + if (!updateUserNotified && index > 0) { + updateUserNotified = true; + + DEBUG_PORT.printf("Update via OCPP start\n"); + + lcd->display(F("Updating WiFi"), 0, 0, 10 * 1000, LCD_CLEAR_LINE | LCD_DISPLAY_NOW); + lcd->display(F(""), 0, 1, 10 * 1000, LCD_CLEAR_LINE | LCD_DISPLAY_NOW); + } + + if (index < total) { + unsigned int percent = 0; + if (total / 100U != 0) { + percent = index / (total / 100U); + } else { + percent = 99; + } + DBUGVAR(percent); + String text = String(percent) + F("%"); + if (lcd) lcd->display(text, 0, 1, 10 * 1000, LCD_DISPLAY_NOW); + DEBUG_PORT.printf("Update: %d%%\n", percent); + } else { + lcd->display(F("Complete"), 0, 1, 10 * 1000, LCD_CLEAR_LINE | LCD_DISPLAY_NOW); + } + }); + DynamicJsonDocument *evseDetailsDoc = new DynamicJsonDocument(JSON_OBJECT_SIZE(6)); JsonObject evseDetails = evseDetailsDoc->to(); evseDetails["chargePointModel"] = "Advanced Series"; diff --git a/src/ocpp.h b/src/ocpp.h index 70f0db85..4e5f31d4 100644 --- a/src/ocpp.h +++ b/src/ocpp.h @@ -37,6 +37,8 @@ class ArduinoOcppTask: public MicroTasks::Task { bool resetHard = false; //default to soft reset ulong resetTime; + bool updateUserNotified = false; + void initializeArduinoOcpp(); bool arduinoOcppInitialized = false; void loadEvseBehavior(); From 5db64cc5e3dee5664534a7658b5b429177df0e1e Mon Sep 17 00:00:00 2001 From: matth-x <63792403+matth-x@users.noreply.github.com> Date: Thu, 21 Oct 2021 09:53:43 +0200 Subject: [PATCH 09/19] diagnostics reporting --- src/ocpp.cpp | 106 +++++++++++++++++++++++++++++++++++++++------------ src/ocpp.h | 4 ++ 2 files changed, 86 insertions(+), 24 deletions(-) diff --git a/src/ocpp.cpp b/src/ocpp.cpp index 27ccbb48..31ccbc7a 100644 --- a/src/ocpp.cpp +++ b/src/ocpp.cpp @@ -9,7 +9,9 @@ #include // Facade for ArduinoOcpp #include // define behavior for incoming req messages + #include +#include //for HTTP update #include @@ -66,35 +68,91 @@ void ArduinoOcppTask::initializeArduinoOcpp() { ArduinoOcpp::FirmwareService *fwService = ArduinoOcpp::getFirmwareService(); if (fwService) { - - } + fwService->setOnInstall([lcd = lcd, &updateUserNotified = updateUserNotified, &updateUrl = updateUrl](String location) { - //TODO HTTPUpdate has added the onProgress cb to its own class definition in Jun '21. Replace when available (https://github.com/espressif/arduino-esp32/commit/db4e7667afe0e169c5f00567f4b59ab8e0fc1532) - Update.onProgress([lcd = lcd, &updateUserNotified = updateUserNotified](size_t index, size_t total) { - if (!updateUserNotified && index > 0) { - updateUserNotified = true; + updateUrl = location; - DEBUG_PORT.printf("Update via OCPP start\n"); +#if 0 //TODO finish when HTTP FW download will be available in the OpenEVSE core - lcd->display(F("Updating WiFi"), 0, 0, 10 * 1000, LCD_CLEAR_LINE | LCD_DISPLAY_NOW); - lcd->display(F(""), 0, 1, 10 * 1000, LCD_CLEAR_LINE | LCD_DISPLAY_NOW); - } - - if (index < total) { - unsigned int percent = 0; - if (total / 100U != 0) { - percent = index / (total / 100U); + //TODO HTTPUpdate has added the onProgress cb to its own class definition in Jun '21. Replace when available (https://github.com/espressif/arduino-esp32/commit/db4e7667afe0e169c5f00567f4b59ab8e0fc1532) + Update.onProgress([lcd = lcd, &updateUserNotified = updateUserNotified](size_t index, size_t total) { + if (!updateUserNotified && index > 0) { + updateUserNotified = true; + + DEBUG_PORT.printf("Update via OCPP start\n"); + + lcd->display(F("Updating WiFi"), 0, 0, 10 * 1000, LCD_CLEAR_LINE | LCD_DISPLAY_NOW); + lcd->display(F(""), 0, 1, 10 * 1000, LCD_CLEAR_LINE | LCD_DISPLAY_NOW); + } + + if (index < total) { + unsigned int percent = 0; + if (total / 100U != 0) { + percent = index / (total / 100U); + } else { + percent = 99; + } + DBUGVAR(percent); + String text = String(percent) + F("%"); + if (lcd) lcd->display(text, 0, 1, 10 * 1000, LCD_DISPLAY_NOW); + DEBUG_PORT.printf("Update: %d%%\n", percent); + } else { + lcd->display(F("Complete"), 0, 1, 10 * 1000, LCD_CLEAR_LINE | LCD_DISPLAY_NOW); + } + }); + +// MongooseHttpClient client = MongooseHttpClient(); +// +// client.get(updateUrl.c_str(), [](MongooseHttpClientResponse *response) { +// //if (response->contentLength() < +// //Update.begin +// }); + +#endif + DEBUG_PORT.println(F("[ocpp] FW download not implemented yet! Ignore request")); + + return true; + }); + } + + ArduinoOcpp::DiagnosticsService *diagService = ArduinoOcpp::getDiagnosticsService(); + if (diagService) { + diagService->setOnUploadStatusSampler([this] () { + if (diagFailure) { + return ArduinoOcpp::UploadStatus::UploadFailed; + } else if (diagSuccess) { + return ArduinoOcpp::UploadStatus::Uploaded; } else { - percent = 99; + return ArduinoOcpp::UploadStatus::NotUploaded; } - DBUGVAR(percent); - String text = String(percent) + F("%"); - if (lcd) lcd->display(text, 0, 1, 10 * 1000, LCD_DISPLAY_NOW); - DEBUG_PORT.printf("Update: %d%%\n", percent); - } else { - lcd->display(F("Complete"), 0, 1, 10 * 1000, LCD_CLEAR_LINE | LCD_DISPLAY_NOW); - } - }); + }); + + diagService->setOnUpload([this] (String &location, ArduinoOcpp::OcppTimestamp &startTime, ArduinoOcpp::OcppTimestamp &stopTime) { + + //reset reported state + diagSuccess = false; + diagFailure = false; + + //check if input URL is valid (maybe add Same-origin policy?) + unsigned int port_i = 0; + struct mg_str scheme, query, fragment; + if (mg_parse_uri(mg_mk_str(location.c_str()), &scheme, NULL, NULL, &port_i, NULL, &query, &fragment)) { + DEBUG_PORT.print(F("[ocpp] Diagnostics upload, invalid URL: ")); + DEBUG_PORT.print(location); + diagFailure = true; + return false; + } + + //create file to upload + + + + diagClient.post("abc", "def", "ghj"); + + + return true; + }); + } DynamicJsonDocument *evseDetailsDoc = new DynamicJsonDocument(JSON_OBJECT_SIZE(6)); JsonObject evseDetails = evseDetailsDoc->to(); diff --git a/src/ocpp.h b/src/ocpp.h index 4e5f31d4..ae7bfbd7 100644 --- a/src/ocpp.h +++ b/src/ocpp.h @@ -38,6 +38,10 @@ class ArduinoOcppTask: public MicroTasks::Task { ulong resetTime; bool updateUserNotified = false; + String updateUrl = String('\0'); + + MongooseHttpClient diagClient = MongooseHttpClient(); + bool diagSuccess, diagFailure = false; void initializeArduinoOcpp(); bool arduinoOcppInitialized = false; From 64dba1127730305406f4556031e713a47aecd173 Mon Sep 17 00:00:00 2001 From: matth-x <63792403+matth-x@users.noreply.github.com> Date: Thu, 21 Oct 2021 10:11:18 +0200 Subject: [PATCH 10/19] match coding style --- src/ocpp.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ocpp.cpp b/src/ocpp.cpp index e086d659..666c290c 100644 --- a/src/ocpp.cpp +++ b/src/ocpp.cpp @@ -68,14 +68,14 @@ void ArduinoOcppTask::initializeArduinoOcpp() { ArduinoOcpp::FirmwareService *fwService = ArduinoOcpp::getFirmwareService(); if (fwService) { - fwService->setOnInstall([lcd = lcd, &updateUserNotified = updateUserNotified, &updateUrl = updateUrl](String location) { + fwService->setOnInstall([this](String location) { updateUrl = location; #if 0 //TODO finish when HTTP FW download will be available in the OpenEVSE core //TODO HTTPUpdate has added the onProgress cb to its own class definition in Jun '21. Replace when available (https://github.com/espressif/arduino-esp32/commit/db4e7667afe0e169c5f00567f4b59ab8e0fc1532) - Update.onProgress([lcd = lcd, &updateUserNotified = updateUserNotified](size_t index, size_t total) { + Update.onProgress([this](size_t index, size_t total) { if (!updateUserNotified && index > 0) { updateUserNotified = true; @@ -217,7 +217,7 @@ void ArduinoOcppTask::loadEvseBehavior() { * Report failures to central system. Note that the error codes are standardized in OCPP */ - addConnectorErrorCodeSampler([evse = evse] () { + addConnectorErrorCodeSampler([this] () { if (evse->getEvseState() == OPENEVSE_STATE_GFI_FAULT || evse->getEvseState() == OPENEVSE_STATE_NO_EARTH_GROUND || evse->getEvseState() == OPENEVSE_STATE_DIODE_CHECK_FAILED) { @@ -226,21 +226,21 @@ void ArduinoOcppTask::loadEvseBehavior() { return (const char *) NULL; }); - addConnectorErrorCodeSampler([evse = evse] () { + addConnectorErrorCodeSampler([this] () { if (evse->getEvseState() == OPENEVSE_STATE_OVER_TEMPERATURE) { return "HighTemperature"; } return (const char *) NULL; }); - addConnectorErrorCodeSampler([evse = evse] () { + addConnectorErrorCodeSampler([this] () { if (evse->getEvseState() == OPENEVSE_STATE_OVER_CURRENT) { return "OverCurrentFailure"; } return (const char *) NULL; }); - addConnectorErrorCodeSampler([evse = evse] () { + addConnectorErrorCodeSampler([this] () { if (evse->getEvseState() == OPENEVSE_STATE_STUCK_RELAY || evse->getEvseState() == OPENEVSE_STATE_GFI_SELF_TEST_FAILED) { return "InternalError"; From 84206016f744628d0efe18a639d6dfe262511dfd Mon Sep 17 00:00:00 2001 From: matth-x <63792403+matth-x@users.noreply.github.com> Date: Thu, 21 Oct 2021 10:40:07 +0200 Subject: [PATCH 11/19] fix include --- src/ocpp.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ocpp.h b/src/ocpp.h index ae7bfbd7..0ba2c6ef 100644 --- a/src/ocpp.h +++ b/src/ocpp.h @@ -12,6 +12,7 @@ #include "lcd.h" #include "MongooseOcppSocketClient.h" +#include class ArduinoOcppTask: public MicroTasks::Task { private: From 88647bb71191f5b7b0b2b10fa0646bf6280354ae Mon Sep 17 00:00:00 2001 From: matth-x <63792403+matth-x@users.noreply.github.com> Date: Thu, 21 Oct 2021 10:42:28 +0200 Subject: [PATCH 12/19] forward original log entry --- src/event_log.cpp | 4 ++-- src/event_log.h | 2 +- src/web_server_events.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/event_log.cpp b/src/event_log.cpp index 1566d71d..c19d9466 100644 --- a/src/event_log.cpp +++ b/src/event_log.cpp @@ -136,7 +136,7 @@ void EventLog::log(EventType type, EvseState managerState, uint8_t evseState, ui } } -void EventLog::enumerate(uint32_t index, std::function callback) +void EventLog::enumerate(uint32_t index, std::function callback) { String filename = filenameFromIndex(index); File eventFile = LittleFS.open(filename); @@ -169,7 +169,7 @@ void EventLog::enumerate(uint32_t index, std::function callback); + void enumerate(uint32_t index, std::function callback); }; diff --git a/src/web_server_events.cpp b/src/web_server_events.cpp index de8861ea..f9a320a6 100644 --- a/src/web_server_events.cpp +++ b/src/web_server_events.cpp @@ -43,7 +43,7 @@ void handleEventLogs(MongooseHttpServerRequest *request) response->print("["); - eventLog.enumerate(block, [&count, response](String time, EventType type, EvseState managerState, uint8_t evseState, uint32_t evseFlags, uint32_t pilot, double energy, uint32_t elapsed, double temperature, double temperatureMax, uint8_t divertMode) + eventLog.enumerate(block, [&count, response](String time, EventType type, const String &logEntry, EvseState managerState, uint8_t evseState, uint32_t evseFlags, uint32_t pilot, double energy, uint32_t elapsed, double temperature, double temperatureMax, uint8_t divertMode) { StaticJsonDocument<1024> event; From 5c63ae5a6c6c19c557d35fe1492d237f0149df39 Mon Sep 17 00:00:00 2001 From: matth-x <63792403+matth-x@users.noreply.github.com> Date: Thu, 21 Oct 2021 17:44:38 +0200 Subject: [PATCH 13/19] log upload integration --- src/main.cpp | 2 +- src/ocpp.cpp | 99 +++++++++++++++++++++++++++++++++++++++++++++++----- src/ocpp.h | 3 +- 3 files changed, 93 insertions(+), 11 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 359a580c..02f1b547 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -134,7 +134,7 @@ void setup() input_setup(); - ocpp.begin(evse, lcd); + ocpp.begin(evse, lcd, eventLog); lcd.display(F("OpenEVSE WiFI"), 0, 0, 0, LCD_CLEAR_LINE); lcd.display(currentfirmware, 0, 1, 5 * 1000, LCD_CLEAR_LINE); diff --git a/src/ocpp.cpp b/src/ocpp.cpp index 666c290c..28cd0f83 100644 --- a/src/ocpp.cpp +++ b/src/ocpp.cpp @@ -34,10 +34,11 @@ ArduinoOcppTask::~ArduinoOcppTask() { instance = NULL; } -void ArduinoOcppTask::begin(EvseManager &evse, LcdTask &lcd) { +void ArduinoOcppTask::begin(EvseManager &evse, LcdTask &lcd, EventLog &eventLog) { this->evse = &evse; this->lcd = &lcd; + this->eventLog = &eventLog; initializeArduinoOcpp(); loadEvseBehavior(); @@ -79,7 +80,7 @@ void ArduinoOcppTask::initializeArduinoOcpp() { if (!updateUserNotified && index > 0) { updateUserNotified = true; - DEBUG_PORT.printf("Update via OCPP start\n"); + DBUG("Update via OCPP start\n"); lcd->display(F("Updating WiFi"), 0, 0, 10 * 1000, LCD_CLEAR_LINE | LCD_DISPLAY_NOW); lcd->display(F(""), 0, 1, 10 * 1000, LCD_CLEAR_LINE | LCD_DISPLAY_NOW); @@ -95,7 +96,7 @@ void ArduinoOcppTask::initializeArduinoOcpp() { DBUGVAR(percent); String text = String(percent) + F("%"); if (lcd) lcd->display(text, 0, 1, 10 * 1000, LCD_DISPLAY_NOW); - DEBUG_PORT.printf("Update: %d%%\n", percent); + DBUGF("Update: %d%%\n", percent); } else { lcd->display(F("Complete"), 0, 1, 10 * 1000, LCD_CLEAR_LINE | LCD_DISPLAY_NOW); } @@ -109,7 +110,7 @@ void ArduinoOcppTask::initializeArduinoOcpp() { // }); #endif - DEBUG_PORT.println(F("[ocpp] FW download not implemented yet! Ignore request")); + DBUGLN(F("[ocpp] FW download not implemented yet! Ignore request")); return true; }); @@ -137,18 +138,98 @@ void ArduinoOcppTask::initializeArduinoOcpp() { unsigned int port_i = 0; struct mg_str scheme, query, fragment; if (mg_parse_uri(mg_mk_str(location.c_str()), &scheme, NULL, NULL, &port_i, NULL, &query, &fragment)) { - DEBUG_PORT.print(F("[ocpp] Diagnostics upload, invalid URL: ")); - DEBUG_PORT.print(location); + DBUG(F("[ocpp] Diagnostics upload, invalid URL: ")); + DBUGLN(location); + diagFailure = true; + return false; + } + + if (eventLog == NULL) { diagFailure = true; return false; } //create file to upload - + #define BOUNDARY_STRING "-----------------------------WebKitFormBoundary7MA4YWxkTrZu0gW025636501" + const char *bodyPrefix PROGMEM = BOUNDARY_STRING "\r\n" + "Content-Disposition: form-data; name=\"file\"; filename=\"diagnostics.log\"\r\n" + "Content-Type: application/octet-stream\r\n\r\n"; + const char *bodySuffix PROGMEM = "\r\n\r\n" BOUNDARY_STRING "--\r\n"; + const char *overflowMsg PROGMEM = "{\"diagnosticsMsg\":\"requested search period exceeds maximum diagnostics upload size\"}"; + + const size_t MAX_BODY_SIZE = 10000; //limit length of message + String body = String('\0'); + body.reserve(MAX_BODY_SIZE); + body += bodyPrefix; + body += "["; + const size_t SUFFIX_RESERVED_AREA = MAX_BODY_SIZE - strlen(bodySuffix) - strlen(overflowMsg) - 2; + + bool firstEntry = true; + bool overflow = false; + for (uint32_t i = 0; i <= (eventLog->getMaxIndex() - eventLog->getMinIndex()) && !overflow; i++) { + uint32_t index = eventLog->getMinIndex() + i; + + eventLog->enumerate(index, [this, startTime, stopTime, &body, SUFFIX_RESERVED_AREA, &firstEntry, &overflow] (String time, EventType type, const String &logEntry, EvseState managerState, uint8_t evseState, uint32_t evseFlags, uint32_t pilot, double energy, uint32_t elapsed, double temperature, double temperatureMax, uint8_t divertMode) { + if (overflow) return; + ArduinoOcpp::OcppTimestamp timestamp = ArduinoOcpp::OcppTimestamp(); + if (!timestamp.setTime(time.c_str())) { + DBUG(F("[ocpp] Diagnostics upload, cannot parse timestamp format: ")); + DBUGLN(time); + return; + } + if (timestamp < startTime || timestamp > stopTime) { + return; + } - diagClient.post("abc", "def", "ghj"); - + if (body.length() + logEntry.length() + 10 < SUFFIX_RESERVED_AREA) { + if (firstEntry) + firstEntry = false; + else + body += ","; + + body += logEntry; + body += "\n"; + } else { + overflow = true; + return; + } + }); + + } + + if (overflow) { + if (!firstEntry) + body += ",\r\n"; + body += overflowMsg; + } + + body += "]"; + + body += bodySuffix; + + DBUG(F("[ocpp] POST diagnostics file to ")); + DBUGLN(location); + + MongooseHttpClientRequest *request = + diagClient.beginRequest(location.c_str()); + request->setMethod(HTTP_POST); + request->addHeader("Content-Type", "multipart/form-data; boundary=" BOUNDARY_STRING); + request->setContent(body.c_str()); + request->onResponse([this] (MongooseHttpClientResponse *response) { + if (response->respCode() == 200) { + diagSuccess = true; + } else { + diagFailure = true; + } + }); + request->onClose([this] (MongooseHttpClientResponse *response) { + if (!diagSuccess) { + //triggered onClose before onResponse + diagFailure = true; + } + }); + diagClient.send(request); return true; }); diff --git a/src/ocpp.h b/src/ocpp.h index 0ba2c6ef..f39608b0 100644 --- a/src/ocpp.h +++ b/src/ocpp.h @@ -19,6 +19,7 @@ class ArduinoOcppTask: public MicroTasks::Task { MongooseOcppSocketClient *ocppSocket = NULL; EvseManager *evse; LcdTask *lcd; + EventLog *eventLog; /* * OCPP state @@ -68,7 +69,7 @@ class ArduinoOcppTask: public MicroTasks::Task { ArduinoOcppTask(); ~ArduinoOcppTask(); - void begin(EvseManager &evse, LcdTask &lcd); + void begin(EvseManager &evse, LcdTask &lcd, EventLog &eventLog); void updateEvseClaim(); From 71ddf3b20bed1f1ecb43c73c47ecee747201f7e1 Mon Sep 17 00:00:00 2001 From: matth-x <63792403+matth-x@users.noreply.github.com> Date: Tue, 26 Oct 2021 16:40:39 +0200 Subject: [PATCH 14/19] code structure --- src/ocpp.cpp | 300 +++++++++++++++++++++++---------------------------- src/ocpp.h | 6 +- 2 files changed, 136 insertions(+), 170 deletions(-) diff --git a/src/ocpp.cpp b/src/ocpp.cpp index 28cd0f83..64f5ac55 100644 --- a/src/ocpp.cpp +++ b/src/ocpp.cpp @@ -67,173 +67,8 @@ void ArduinoOcppTask::initializeArduinoOcpp() { OCPP_initialize(ocppSocket, (float) VOLTAGE_DEFAULT, ArduinoOcpp::FilesystemOpt::Use, clockAdapter); - ArduinoOcpp::FirmwareService *fwService = ArduinoOcpp::getFirmwareService(); - if (fwService) { - fwService->setOnInstall([this](String location) { - - updateUrl = location; - -#if 0 //TODO finish when HTTP FW download will be available in the OpenEVSE core - - //TODO HTTPUpdate has added the onProgress cb to its own class definition in Jun '21. Replace when available (https://github.com/espressif/arduino-esp32/commit/db4e7667afe0e169c5f00567f4b59ab8e0fc1532) - Update.onProgress([this](size_t index, size_t total) { - if (!updateUserNotified && index > 0) { - updateUserNotified = true; - - DBUG("Update via OCPP start\n"); - - lcd->display(F("Updating WiFi"), 0, 0, 10 * 1000, LCD_CLEAR_LINE | LCD_DISPLAY_NOW); - lcd->display(F(""), 0, 1, 10 * 1000, LCD_CLEAR_LINE | LCD_DISPLAY_NOW); - } - - if (index < total) { - unsigned int percent = 0; - if (total / 100U != 0) { - percent = index / (total / 100U); - } else { - percent = 99; - } - DBUGVAR(percent); - String text = String(percent) + F("%"); - if (lcd) lcd->display(text, 0, 1, 10 * 1000, LCD_DISPLAY_NOW); - DBUGF("Update: %d%%\n", percent); - } else { - lcd->display(F("Complete"), 0, 1, 10 * 1000, LCD_CLEAR_LINE | LCD_DISPLAY_NOW); - } - }); - -// MongooseHttpClient client = MongooseHttpClient(); -// -// client.get(updateUrl.c_str(), [](MongooseHttpClientResponse *response) { -// //if (response->contentLength() < -// //Update.begin -// }); - -#endif - DBUGLN(F("[ocpp] FW download not implemented yet! Ignore request")); - - return true; - }); - } - - ArduinoOcpp::DiagnosticsService *diagService = ArduinoOcpp::getDiagnosticsService(); - if (diagService) { - diagService->setOnUploadStatusSampler([this] () { - if (diagFailure) { - return ArduinoOcpp::UploadStatus::UploadFailed; - } else if (diagSuccess) { - return ArduinoOcpp::UploadStatus::Uploaded; - } else { - return ArduinoOcpp::UploadStatus::NotUploaded; - } - }); - - diagService->setOnUpload([this] (String &location, ArduinoOcpp::OcppTimestamp &startTime, ArduinoOcpp::OcppTimestamp &stopTime) { - - //reset reported state - diagSuccess = false; - diagFailure = false; - - //check if input URL is valid (maybe add Same-origin policy?) - unsigned int port_i = 0; - struct mg_str scheme, query, fragment; - if (mg_parse_uri(mg_mk_str(location.c_str()), &scheme, NULL, NULL, &port_i, NULL, &query, &fragment)) { - DBUG(F("[ocpp] Diagnostics upload, invalid URL: ")); - DBUGLN(location); - diagFailure = true; - return false; - } - - if (eventLog == NULL) { - diagFailure = true; - return false; - } - - //create file to upload - #define BOUNDARY_STRING "-----------------------------WebKitFormBoundary7MA4YWxkTrZu0gW025636501" - const char *bodyPrefix PROGMEM = BOUNDARY_STRING "\r\n" - "Content-Disposition: form-data; name=\"file\"; filename=\"diagnostics.log\"\r\n" - "Content-Type: application/octet-stream\r\n\r\n"; - const char *bodySuffix PROGMEM = "\r\n\r\n" BOUNDARY_STRING "--\r\n"; - const char *overflowMsg PROGMEM = "{\"diagnosticsMsg\":\"requested search period exceeds maximum diagnostics upload size\"}"; - - const size_t MAX_BODY_SIZE = 10000; //limit length of message - String body = String('\0'); - body.reserve(MAX_BODY_SIZE); - body += bodyPrefix; - body += "["; - const size_t SUFFIX_RESERVED_AREA = MAX_BODY_SIZE - strlen(bodySuffix) - strlen(overflowMsg) - 2; - - bool firstEntry = true; - bool overflow = false; - for (uint32_t i = 0; i <= (eventLog->getMaxIndex() - eventLog->getMinIndex()) && !overflow; i++) { - uint32_t index = eventLog->getMinIndex() + i; - - eventLog->enumerate(index, [this, startTime, stopTime, &body, SUFFIX_RESERVED_AREA, &firstEntry, &overflow] (String time, EventType type, const String &logEntry, EvseState managerState, uint8_t evseState, uint32_t evseFlags, uint32_t pilot, double energy, uint32_t elapsed, double temperature, double temperatureMax, uint8_t divertMode) { - if (overflow) return; - ArduinoOcpp::OcppTimestamp timestamp = ArduinoOcpp::OcppTimestamp(); - if (!timestamp.setTime(time.c_str())) { - DBUG(F("[ocpp] Diagnostics upload, cannot parse timestamp format: ")); - DBUGLN(time); - return; - } - - if (timestamp < startTime || timestamp > stopTime) { - return; - } - - if (body.length() + logEntry.length() + 10 < SUFFIX_RESERVED_AREA) { - if (firstEntry) - firstEntry = false; - else - body += ","; - - body += logEntry; - body += "\n"; - } else { - overflow = true; - return; - } - }); - - } - - if (overflow) { - if (!firstEntry) - body += ",\r\n"; - body += overflowMsg; - } - - body += "]"; - - body += bodySuffix; - - DBUG(F("[ocpp] POST diagnostics file to ")); - DBUGLN(location); - - MongooseHttpClientRequest *request = - diagClient.beginRequest(location.c_str()); - request->setMethod(HTTP_POST); - request->addHeader("Content-Type", "multipart/form-data; boundary=" BOUNDARY_STRING); - request->setContent(body.c_str()); - request->onResponse([this] (MongooseHttpClientResponse *response) { - if (response->respCode() == 200) { - diagSuccess = true; - } else { - diagFailure = true; - } - }); - request->onClose([this] (MongooseHttpClientResponse *response) { - if (!diagSuccess) { - //triggered onClose before onResponse - diagFailure = true; - } - }); - diagClient.send(request); - - return true; - }); - } + initializeDiagnosticsService(); + initializeFwService(); DynamicJsonDocument *evseDetailsDoc = new DynamicJsonDocument(JSON_OBJECT_SIZE(6)); JsonObject evseDetails = evseDetailsDoc->to(); @@ -571,6 +406,137 @@ void ArduinoOcppTask::reconfigure() { loadEvseBehavior(); } +void ArduinoOcppTask::initializeDiagnosticsService() { + ArduinoOcpp::DiagnosticsService *diagService = ArduinoOcpp::getDiagnosticsService(); + if (diagService) { + diagService->setOnUploadStatusSampler([this] () { + if (diagFailure) { + return ArduinoOcpp::UploadStatus::UploadFailed; + } else if (diagSuccess) { + return ArduinoOcpp::UploadStatus::Uploaded; + } else { + return ArduinoOcpp::UploadStatus::NotUploaded; + } + }); + + diagService->setOnUpload([this] (String &location, ArduinoOcpp::OcppTimestamp &startTime, ArduinoOcpp::OcppTimestamp &stopTime) { + + //reset reported state + diagSuccess = false; + diagFailure = false; + + //check if input URL is valid + unsigned int port_i = 0; + struct mg_str scheme, query, fragment; + if (mg_parse_uri(mg_mk_str(location.c_str()), &scheme, NULL, NULL, &port_i, NULL, &query, &fragment)) { + DBUG(F("[ocpp] Diagnostics upload, invalid URL: ")); + DBUGLN(location); + diagFailure = true; + return false; + } + + if (eventLog == NULL) { + diagFailure = true; + return false; + } + + //create file to upload + #define BOUNDARY_STRING "-----------------------------WebKitFormBoundary7MA4YWxkTrZu0gW025636501" + const char *bodyPrefix PROGMEM = BOUNDARY_STRING "\r\n" + "Content-Disposition: form-data; name=\"file\"; filename=\"diagnostics.log\"\r\n" + "Content-Type: application/octet-stream\r\n\r\n"; + const char *bodySuffix PROGMEM = "\r\n\r\n" BOUNDARY_STRING "--\r\n"; + const char *overflowMsg PROGMEM = "{\"diagnosticsMsg\":\"requested search period exceeds maximum diagnostics upload size\"}"; + + const size_t MAX_BODY_SIZE = 10000; //limit length of message + String body = String('\0'); + body.reserve(MAX_BODY_SIZE); + body += bodyPrefix; + body += "["; + const size_t SUFFIX_RESERVED_AREA = MAX_BODY_SIZE - strlen(bodySuffix) - strlen(overflowMsg) - 2; + + bool firstEntry = true; + bool overflow = false; + for (uint32_t i = 0; i <= (eventLog->getMaxIndex() - eventLog->getMinIndex()) && !overflow; i++) { + uint32_t index = eventLog->getMinIndex() + i; + + eventLog->enumerate(index, [this, startTime, stopTime, &body, SUFFIX_RESERVED_AREA, &firstEntry, &overflow] (String time, EventType type, const String &logEntry, EvseState managerState, uint8_t evseState, uint32_t evseFlags, uint32_t pilot, double energy, uint32_t elapsed, double temperature, double temperatureMax, uint8_t divertMode) { + if (overflow) return; + ArduinoOcpp::OcppTimestamp timestamp = ArduinoOcpp::OcppTimestamp(); + if (!timestamp.setTime(time.c_str())) { + DBUG(F("[ocpp] Diagnostics upload, cannot parse timestamp format: ")); + DBUGLN(time); + return; + } + + if (timestamp < startTime || timestamp > stopTime) { + return; + } + + if (body.length() + logEntry.length() + 10 < SUFFIX_RESERVED_AREA) { + if (firstEntry) + firstEntry = false; + else + body += ","; + + body += logEntry; + body += "\n"; + } else { + overflow = true; + return; + } + }); + } + + if (overflow) { + if (!firstEntry) + body += ",\r\n"; + body += overflowMsg; + } + + body += "]"; + + body += bodySuffix; + + DBUG(F("[ocpp] POST diagnostics file to ")); + DBUGLN(location); + + MongooseHttpClientRequest *request = + diagClient.beginRequest(location.c_str()); + request->setMethod(HTTP_POST); + request->addHeader("Content-Type", "multipart/form-data; boundary=" BOUNDARY_STRING); + request->setContent(body.c_str()); + request->onResponse([this] (MongooseHttpClientResponse *response) { + if (response->respCode() == 200) { + diagSuccess = true; + } else { + diagFailure = true; + } + }); + request->onClose([this] (MongooseHttpClientResponse *response) { + if (!diagSuccess) { + //triggered onClose before onResponse + diagFailure = true; + } + }); + diagClient.send(request); + + return true; + }); + } +} + +void ArduinoOcppTask::initializeFwService() { + //TODO finish when HTTP FW download will be available in the OpenEVSE core + //ArduinoOcpp::FirmwareService *fwService = ArduinoOcpp::getFirmwareService(); + //if (fwService) { + // fwService->setOnInstall([this](String location) { + // ... + // return true; + // }); + //} +} + bool ArduinoOcppTask::operationIsAccepted(JsonObject payload) { const char *status = payload["status"] | "Invalid"; return !strcmp(status, "Accepted"); diff --git a/src/ocpp.h b/src/ocpp.h index f39608b0..b2913bb0 100644 --- a/src/ocpp.h +++ b/src/ocpp.h @@ -39,11 +39,11 @@ class ArduinoOcppTask: public MicroTasks::Task { bool resetHard = false; //default to soft reset ulong resetTime; - bool updateUserNotified = false; - String updateUrl = String('\0'); - MongooseHttpClient diagClient = MongooseHttpClient(); bool diagSuccess, diagFailure = false; + void initializeDiagnosticsService(); + + void initializeFwService(); void initializeArduinoOcpp(); bool arduinoOcppInitialized = false; From aa4e87539d62b707d9fd5949e6175b4460c8b264 Mon Sep 17 00:00:00 2001 From: matth-x <63792403+matth-x@users.noreply.github.com> Date: Tue, 26 Oct 2021 16:41:17 +0200 Subject: [PATCH 15/19] pio registry updated --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index 5fb1d1e6..74fc06a3 100644 --- a/platformio.ini +++ b/platformio.ini @@ -42,8 +42,7 @@ lib_deps = jeremypoulter/MicroTasks@0.0.2 erropix/ESP32 AnalogWrite@0.2 lorol/LittleFS_esp32@1.0.5 - #matth-x/ArduinoOcpp@0.0.2 - https://github.com/matth-x/ArduinoOcpp.git#develop + matth-x/ArduinoOcpp@0.0.3 lib_ignore = WebSockets ; ArduinoOcpp: don't compile built-in WS library extra_scripts = scripts/extra_script.py debug_flags = @@ -80,6 +79,7 @@ build_flags = -D MG_ENABLE_SNTP=1 -D CS_PLATFORM=CS_P_ESP32 -D AO_CUSTOM_WS ; ArduinoOcpp: don't use built-in WS library + -D AO_CUSTOM_DIAGNOSTICS ; ArduinoOcpp: don't do internal logging #-D ENABLE_DEBUG #-D ENABLE_DEBUG_MONGOOSE_HTTP_CLIENT -D RAPI_MAX_COMMANDS=20 From f711f314b31d9740a65015b50067deacf8bf3e6c Mon Sep 17 00:00:00 2001 From: matth-x <63792403+matth-x@users.noreply.github.com> Date: Thu, 4 Nov 2021 15:55:14 +0100 Subject: [PATCH 16/19] integrate reset call update --- src/ocpp.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/ocpp.cpp b/src/ocpp.cpp index 64f5ac55..cc652383 100644 --- a/src/ocpp.cpp +++ b/src/ocpp.cpp @@ -17,9 +17,6 @@ #include "emonesp.h" //for VOLTAGE_DEFAULT -#include "net_manager.h" //shut down network connection before reset -#include "espal.h" - #define LCD_DISPLAY(X) if (lcd) lcd->display((X), 0, 1, 5 * 1000, LCD_CLEAR_LINE); @@ -287,11 +284,13 @@ unsigned long ArduinoOcppTask::loop(MicroTasks::WakeReason reason) { if (resetTriggered) { if (millis() - resetTime >= 10000UL) { //wait for 10 seconds after reset command to send the conf msg + resetTriggered = false; //execute only once + if (resetHard) { //TODO send reset command to all peripherals } - net_wifi_disconnect(); - ESPAL.reset(); + + restart_system(); } } From 34cd8edeb76b6f396955ca4d51ed2abe00c19d71 Mon Sep 17 00:00:00 2001 From: matth-x <63792403+matth-x@users.noreply.github.com> Date: Thu, 4 Nov 2021 15:56:17 +0100 Subject: [PATCH 17/19] integrate ArduinoMongoose update --- src/ocpp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ocpp.cpp b/src/ocpp.cpp index cc652383..9d770477 100644 --- a/src/ocpp.cpp +++ b/src/ocpp.cpp @@ -512,7 +512,7 @@ void ArduinoOcppTask::initializeDiagnosticsService() { diagFailure = true; } }); - request->onClose([this] (MongooseHttpClientResponse *response) { + request->onClose([this] () { if (!diagSuccess) { //triggered onClose before onResponse diagFailure = true; From 02bf21b9ec61a22d21e53234f18cbbedfa9d27a6 Mon Sep 17 00:00:00 2001 From: matth-x <63792403+matth-x@users.noreply.github.com> Date: Thu, 4 Nov 2021 15:57:05 +0100 Subject: [PATCH 18/19] integrate new HTTP FW update function --- src/ocpp.cpp | 50 +++++++++++++++++++++++++++++++++++++++----------- src/ocpp.h | 1 + 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/ocpp.cpp b/src/ocpp.cpp index 9d770477..16d6a7b9 100644 --- a/src/ocpp.cpp +++ b/src/ocpp.cpp @@ -10,8 +10,7 @@ #include // Facade for ArduinoOcpp #include // define behavior for incoming req messages -#include -#include //for HTTP update +#include "http_update.h" #include @@ -70,11 +69,12 @@ void ArduinoOcppTask::initializeArduinoOcpp() { DynamicJsonDocument *evseDetailsDoc = new DynamicJsonDocument(JSON_OBJECT_SIZE(6)); JsonObject evseDetails = evseDetailsDoc->to(); evseDetails["chargePointModel"] = "Advanced Series"; - //evseDetails["chargePointSerialNumber"] = "TODO"; + //evseDetails["chargePointSerialNumber"] = "TODO"; //see https://github.com/OpenEVSE/ESP32_WiFi_V4.x/issues/218 evseDetails["chargePointVendor"] = "OpenEVSE"; evseDetails["firmwareVersion"] = evse->getFirmwareVersion(); //evseDetails["meterSerialNumber"] = "TODO"; //evseDetails["meterType"] = "TODO"; + //see https://github.com/OpenEVSE/ESP32_WiFi_V4.x/issues/219 bootNotification(evseDetailsDoc, [this](JsonObject payload) { //ArduinoOcpp will delete evseDetailsDoc LCD_DISPLAY("OCPP connected!"); @@ -242,6 +242,7 @@ void ArduinoOcppTask::loadEvseBehavior() { setOnUnlockConnector([] () { //TODO Send unlock command to peripherals. If successful, return true, otherwise false + //see https://github.com/OpenEVSE/ESP32_WiFi_V4.x/issues/230 return false; }); @@ -526,14 +527,41 @@ void ArduinoOcppTask::initializeDiagnosticsService() { } void ArduinoOcppTask::initializeFwService() { - //TODO finish when HTTP FW download will be available in the OpenEVSE core - //ArduinoOcpp::FirmwareService *fwService = ArduinoOcpp::getFirmwareService(); - //if (fwService) { - // fwService->setOnInstall([this](String location) { - // ... - // return true; - // }); - //} + ArduinoOcpp::FirmwareService *fwService = ArduinoOcpp::getFirmwareService(); + if (fwService) { + fwService->setBuildNumber(evse->getFirmwareVersion()); + + fwService->setInstallationStatusSampler([this] () { + if (updateFailure) { + return ArduinoOcpp::InstallationStatus::InstallationFailed; + } else if (updateSuccess) { + return ArduinoOcpp::InstallationStatus::Installed; + } else { + return ArduinoOcpp::InstallationStatus::NotInstalled; + } + }); + + fwService->setOnInstall([this](String &location) { + + DBUGLN(F("[ocpp] Starting installation routine")); + + //reset reported state + updateFailure = false; + updateSuccess = false; + + return http_update_from_url(location, [] (size_t complete, size_t total) { }, + [this] (int status_code) { + //onSuccess + updateSuccess = true; + + resetTime = millis(); + resetTriggered = true; + }, [this] (int error_code) { + //onFailure + updateFailure = true; + }); + }); + } } bool ArduinoOcppTask::operationIsAccepted(JsonObject payload) { diff --git a/src/ocpp.h b/src/ocpp.h index b2913bb0..54b61f0f 100644 --- a/src/ocpp.h +++ b/src/ocpp.h @@ -43,6 +43,7 @@ class ArduinoOcppTask: public MicroTasks::Task { bool diagSuccess, diagFailure = false; void initializeDiagnosticsService(); + bool updateSuccess, updateFailure = false; void initializeFwService(); void initializeArduinoOcpp(); From e76d75d0aa470b1907276e1a3e1a36166d53b738 Mon Sep 17 00:00:00 2001 From: matth-x <63792403+matth-x@users.noreply.github.com> Date: Thu, 4 Nov 2021 18:20:14 +0100 Subject: [PATCH 19/19] update ArduinoOcpp PIO ver, add note --- platformio.ini | 2 +- src/ocpp.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 8ddc3375..dc91cd10 100644 --- a/platformio.ini +++ b/platformio.ini @@ -42,7 +42,7 @@ lib_deps = jeremypoulter/MicroTasks@0.0.2 erropix/ESP32 AnalogWrite@0.2 lorol/LittleFS_esp32@1.0.5 - matth-x/ArduinoOcpp@0.0.3 + matth-x/ArduinoOcpp@0.0.4 lib_ignore = WebSockets ; ArduinoOcpp: don't compile built-in WS library extra_scripts = scripts/extra_script.py debug_flags = diff --git a/src/ocpp.cpp b/src/ocpp.cpp index 16d6a7b9..d8b84293 100644 --- a/src/ocpp.cpp +++ b/src/ocpp.cpp @@ -289,6 +289,7 @@ unsigned long ArduinoOcppTask::loop(MicroTasks::WakeReason reason) { if (resetHard) { //TODO send reset command to all peripherals + //see https://github.com/OpenEVSE/ESP32_WiFi_V4.x/issues/228 } restart_system();