diff --git a/examples/ESP/main.cpp b/examples/ESP/main.cpp index 198d39a6..b9f46a7b 100644 --- a/examples/ESP/main.cpp +++ b/examples/ESP/main.cpp @@ -18,16 +18,14 @@ ESP8266WiFiMulti WiFiMulti; #define STASSID "YOUR_WIFI_SSID" #define STAPSK "YOUR_WIFI_PW" -#define OCPP_HOST "echo.websocket.events" -#define OCPP_PORT 80 -#define OCPP_URL "ws://echo.websocket.events/" +#define OCPP_BACKEND_URL "ws://echo.websocket.events" +#define OCPP_CHARGE_BOX_ID "" // // Settings which worked for my SteVe instance: // -//#define OCPP_HOST "my.instance.com" -//#define OCPP_PORT 80 -//#define OCPP_URL "ws://my.instance.com/steve/websocket/CentralSystemService/esp-charger" +//#define OCPP_BACKEND_URL "ws://192.168.178.100:8180/steve/websocket/CentralSystemService" +//#define OCPP_CHARGE_BOX_ID "esp-charger" void setup() { @@ -60,7 +58,7 @@ void setup() { /* * Initialize the OCPP library */ - mocpp_initialize(OCPP_HOST, OCPP_PORT, OCPP_URL, "My Charging Station", "My company name"); + mocpp_initialize(OCPP_BACKEND_URL, OCPP_CHARGE_BOX_ID, "My Charging Station", "My company name"); /* * Integrate OCPP functionality. You can leave out the following part if your EVSE doesn't need it. diff --git a/src/MicroOcpp.cpp b/src/MicroOcpp.cpp index cc9f9085..262ffb43 100644 --- a/src/MicroOcpp.cpp +++ b/src/MicroOcpp.cpp @@ -56,24 +56,90 @@ using namespace MicroOcpp::Facade; using namespace MicroOcpp::Ocpp16; #ifndef MO_CUSTOM_WS -void mocpp_initialize(const char *CS_hostname, uint16_t CS_port, const char *CS_url, const char *chargePointModel, const char *chargePointVendor, FilesystemOpt fsOpt, const char *login, const char *password, const char *CA_cert, bool autoRecover) { +void mocpp_initialize(const char *backendUrl, const char *chargeBoxId, const char *chargePointModel, const char *chargePointVendor, FilesystemOpt fsOpt, const char *password, const char *CA_cert, bool autoRecover) { if (context) { MO_DBG_WARN("already initialized. To reinit, call mocpp_deinitialize() before"); return; } + if (!backendUrl || !chargePointModel || !chargePointVendor) { + MO_DBG_ERR("invalid args"); + return; + } + + if (!chargeBoxId) { + chargeBoxId = ""; + } + + /* + * parse backendUrl so that it suits the links2004/arduinoWebSockets interface + */ + std::string url = backendUrl; + + //tolower protocol specifier + for (auto c = url.begin(); *c != ':' && c != url.end(); c++) { + *c = tolower(*c); + } + + bool isTLS = true; + if (!strncmp(url.c_str(),"wss://",strlen("wss://"))) { + isTLS = true; + } else if (!strncmp(url.c_str(),"ws://",strlen("ws://"))) { + isTLS = false; + } else { + MO_DBG_ERR("only ws:// and wss:// supported"); + return; + } + + //parse host, port + std::string host_port_path = url.substr(url.find_first_of("://") + strlen("://")); + std::string host_port = host_port_path.substr(0, host_port_path.find_first_of('/')); + std::string host = host_port.substr(0, host_port.find_first_of(':')); + if (host.empty()) { + MO_DBG_ERR("could not parse host: %s", url.c_str()); + return; + } + uint16_t port = 0; + std::string port_str = host_port.substr(host.length()); + if (port_str.empty()) { + port = isTLS ? 443U : 80U; + } else { + //skip leading ':' + port_str = port_str.substr(1); + for (auto c = port_str.begin(); c != port_str.end(); c++) { + if (*c < '0' || *c > '9') { + MO_DBG_ERR("could not parse port: %s", url.c_str()); + return; + } + auto p = port * 10U + (*c - '0'); + if (p < port) { + MO_DBG_ERR("could not parse port (overflow): %s", url.c_str()); + return; + } + port = p; + } + } + + if (url.back() != '/') { + url += '/'; + } + + url += chargeBoxId; + + MO_DBG_INFO("connecting to %s -- (host: %s, port: %u)", url.c_str(), host.c_str(), port); + if (!webSocket) webSocket = new WebSocketsClient(); - if (!strncmp(CS_url,"wss",3) || !strncmp(CS_url,"https",5)) + if (isTLS) { // server address, port, URL and TLS certificate - webSocket->beginSslWithCA(CS_hostname, CS_port, CS_url, CA_cert, "ocpp1.6"); + webSocket->beginSslWithCA(host.c_str(), port, url.c_str(), CA_cert, "ocpp1.6"); } else { // server address, port, URL - webSocket->begin(CS_hostname, CS_port, CS_url, "ocpp1.6"); + webSocket->begin(host.c_str(), port, url.c_str(), "ocpp1.6"); } // try ever 5000 again if connection has failed @@ -86,8 +152,8 @@ void mocpp_initialize(const char *CS_hostname, uint16_t CS_port, const char *CS_ webSocket->enableHeartbeat(15000, 3000, 2); //comment this one out to for specific OCPP servers // add authentication data (optional) - if (login && password && strlen(login) + strlen(password) >= 2) { - webSocket->setAuthorization(login, password); + if (password && strlen(password) + strlen(chargeBoxId) >= 4) { + webSocket->setAuthorization(chargeBoxId, password); } delete connection; diff --git a/src/MicroOcpp.h b/src/MicroOcpp.h index 44e6939a..7d7685e2 100644 --- a/src/MicroOcpp.h +++ b/src/MicroOcpp.h @@ -36,19 +36,16 @@ using MicroOcpp::OnReceiveErrorListener; * https://github.com/matth-x/MicroOcpp/issues/36#issuecomment-989716573 for recommendations on * how to track down the issue with the connection. * - * This is a convenience function only available for Arduino. For a full initialization with TLS, - * please refer to https://github.com/matth-x/MicroOcpp/tree/master/examples/ESP-TLS + * This is a convenience function only available for Arduino. */ void mocpp_initialize( - const char *CS_hostname, //e.g. "example.com" - uint16_t CS_port, //e.g. 80 - const char *CS_url, //e.g. "ws://example.com/steve/websocket/CentralSystemService/charger001" + const char *backendUrl, //e.g. "wss://example.com:8443/steve/websocket/CentralSystemService" + const char *chargeBoxId, //e.g. "charger001" const char *chargePointModel = "Demo Charger", //model name of this charger const char *chargePointVendor = "My Company Ltd.", //brand name MicroOcpp::FilesystemOpt fsOpt = MicroOcpp::FilesystemOpt::Use_Mount_FormatOnFail, //If this library should format the flash if necessary. Find further options in ConfigurationOptions.h - const char *login = "", //login present in the websocket message header - const char *password = "", //password present in the websocket message header - const char *CA_cert = NULL, //TLS certificate + const char *password = nullptr, //password present in the websocket message header + const char *CA_cert = nullptr, //TLS certificate bool autoRecover = false); //automatically sanitize the local data store when the lib detects recurring crashes. Not recommended during development #endif