Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OCPP 2.0.1 integrate BasicAuthPassword #13

Merged
merged 3 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
## Unreleased

### Added
- Mongoose v7.13 support ([#11](https://github.com/matth-x/MicroOcppMongoose/pull/11)
- Mongoose v7.13 support ([#11](https://github.com/matth-x/MicroOcppMongoose/pull/11))
- OCPP 2.0.1 BasicAuthPassword integration ([#13](https://github.com/matth-x/MicroOcppMongoose/pull/13))

### Fixed
- AuthorizationKey hex conversion ([#12](https://github.com/matth-x/MicroOcppMongoose/pull/12))
Expand Down
103 changes: 75 additions & 28 deletions src/MicroOcppMongooseClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
#include <MicroOcpp/Core/Configuration.h>
#include <MicroOcpp/Debug.h>

#if MO_ENABLE_V201
#include <MicroOcpp/Model/Variables/VariableContainer.h>
#endif

#define DEBUG_MSG_INTERVAL 5000UL
#define WS_UNRESPONSIVE_THRESHOLD_MS 15000UL

Expand Down Expand Up @@ -68,16 +72,32 @@ MOcppMongooseClient::MOcppMongooseClient(struct mg_mgr *mgr,
MO_DBG_WARN("auth_key_factory too long - will be cropped");
auth_key_factory_len = MO_AUTHKEY_LEN_MAX;
}
char auth_key_hex [2 * MO_AUTHKEY_LEN_MAX + 1];
auth_key_hex[0] = '\0';
if (auth_key_factory) {
for (size_t i = 0; i < auth_key_factory_len; i++) {
snprintf(auth_key_hex + 2 * i, 3, "%02X", auth_key_factory[i]);

#if MO_ENABLE_V201
if (protocolVersion.major == 2) {
websocketSettings = makeVariableContainerVolatile(MO_WSCONN_FN_V201, true);
auto variable = websocketSettings->createVariable(Variable::InternalDataType::String, Variable::AttributeType::Actual);
variable->setComponentId("SecurityCtrlr");
variable->setName("BasicAuthPassword");
char basicAuthPassword [MO_AUTHKEY_LEN_MAX + 1];
snprintf(basicAuthPassword, sizeof(basicAuthPassword), "%.*s", (int)auth_key_factory_len, auth_key_factory ? (const char*)auth_key_factory : "");
variable->setString(basicAuthPassword);
websocketSettings->add(std::move(variable));
basicAuthPasswordString = websocketSettings->getVariable("SecurityCtrlr", "BasicAuthPassword");
} else
#endif
{
char auth_key_hex [2 * MO_AUTHKEY_LEN_MAX + 1];
auth_key_hex[0] = '\0';
if (auth_key_factory) {
for (size_t i = 0; i < auth_key_factory_len; i++) {
snprintf(auth_key_hex + 2 * i, 3, "%02X", auth_key_factory[i]);
}
}
setting_auth_key_hex_str = declareConfiguration<const char*>(
"AuthorizationKey", auth_key_hex, MO_WSCONN_FN, readonly, true);
registerConfigurationValidator("AuthorizationKey", validateAuthorizationKeyHex);
}
setting_auth_key_hex_str = declareConfiguration<const char*>(
"AuthorizationKey", auth_key_hex, MO_WSCONN_FN, readonly, true);
registerConfigurationValidator("AuthorizationKey", validateAuthorizationKeyHex);

ws_ping_interval_int = declareConfiguration<int>(
"WebSocketPingInterval", 5, MO_WSCONN_FN);
Expand Down Expand Up @@ -378,15 +398,26 @@ void MOcppMongooseClient::setAuthKey(const unsigned char *auth_key, size_t len)
return;
}

char auth_key_hex [2 * MO_AUTHKEY_LEN_MAX + 1];
auth_key_hex[0] = '\0';
for (size_t i = 0; i < len; i++) {
snprintf(auth_key_hex + 2 * i, 3, "%02X", auth_key[i]);
}

if (setting_auth_key_hex_str) {
setting_auth_key_hex_str->setString(auth_key_hex);
configuration_save();
#if MO_ENABLE_V201
if (protocolVersion.major == 2) {
char basicAuthPassword [MO_AUTHKEY_LEN_MAX + 1];
snprintf(basicAuthPassword, sizeof(basicAuthPassword), "%.*s", (int)len, auth_key ? (const char*)auth_key : "");
if (basicAuthPasswordString) {
basicAuthPasswordString->setString(basicAuthPassword);
}
} else
#endif
{
char auth_key_hex [2 * MO_AUTHKEY_LEN_MAX + 1];
auth_key_hex[0] = '\0';
for (size_t i = 0; i < len; i++) {
snprintf(auth_key_hex + 2 * i, 3, "%02X", auth_key[i]);
}
if (setting_auth_key_hex_str) {
setting_auth_key_hex_str->setString(auth_key_hex);
configuration_save();
}
}
}

Expand All @@ -409,19 +440,29 @@ void MOcppMongooseClient::reloadConfigs() {
cb_id = setting_cb_id_str->getString();
}

if (setting_auth_key_hex_str) {
auto auth_key_hex = setting_auth_key_hex_str->getString();

#if MO_MG_VERSION_614
cs_from_hex((char*)auth_key, auth_key_hex, strlen(auth_key_hex));
#elif MO_MG_USE_VERSION <= MO_MG_V713
mg_unhex(auth_key_hex, strlen(auth_key_hex), auth_key);
#else
mg_str_to_num(mg_str(auth_key_hex), 16, auth_key, MO_AUTHKEY_LEN_MAX);
#endif
#if MO_ENABLE_V201
if (protocolVersion.major == 2) {
if (basicAuthPasswordString) {
snprintf((char*)auth_key, sizeof(auth_key), "%s", basicAuthPasswordString->getString());
auth_key_len = strlen((char*)auth_key);
}
} else
#endif
{
if (setting_auth_key_hex_str) {
auto auth_key_hex = setting_auth_key_hex_str->getString();

#if MO_MG_VERSION_614
cs_from_hex((char*)auth_key, auth_key_hex, strlen(auth_key_hex));
#elif MO_MG_USE_VERSION <= MO_MG_V713
mg_unhex(auth_key_hex, strlen(auth_key_hex), auth_key);
#else
mg_str_to_num(mg_str(auth_key_hex), 16, auth_key, MO_AUTHKEY_LEN_MAX);
#endif

auth_key_len = strlen(setting_auth_key_hex_str->getString()) / 2;
auth_key[auth_key_len] = '\0'; //need null-termination as long as deprecated `const char *getAuthKey()` exists
auth_key_len = strlen(setting_auth_key_hex_str->getString()) / 2;
auth_key[auth_key_len] = '\0'; //need null-termination as long as deprecated `const char *getAuthKey()` exists
}
}

/*
Expand Down Expand Up @@ -480,6 +521,12 @@ unsigned long MOcppMongooseClient::getLastConnected() {
return last_connection_established;
}

#if MO_ENABLE_V201
std::shared_ptr<VariableContainer> MOcppMongooseClient::getVariableContainer() {
return websocketSettings;
}
#endif

#if MO_MG_USE_VERSION == MO_MG_V614

void ws_cb(struct mg_connection *nc, int ev, void *ev_data, void *user_data) {
Expand Down
22 changes: 21 additions & 1 deletion src/MicroOcppMongooseClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,33 @@

#ifndef MO_WSCONN_FN
#define MO_WSCONN_FN (MO_FILENAME_PREFIX "ws-conn.jsn")
#define MO_WSCONN_FN_V201 (MO_FILENAME_PREFIX "ws-conn-v201.jsn")
#endif

#if MO_ENABLE_V201
#define MO_AUTHKEY_LEN_MAX 40 //BasicAuthPassword length
#else
#define MO_AUTHKEY_LEN_MAX 20 //AuthKey in Bytes. Hex value has double length
#endif

namespace MicroOcpp {

class FilesystemAdapter;
class Configuration;

#if MO_ENABLE_V201
class Variable;
class VariableContainer;
#endif

class MOcppMongooseClient : public MicroOcpp::Connection {
private:
struct mg_mgr *mgr {nullptr};
struct mg_connection *websocket {nullptr};
std::string backend_url;
std::string cb_id;
std::string url; //url = backend_url + '/' + cb_id
unsigned char auth_key [MO_AUTHKEY_LEN_MAX + 1]; //AuthKey in bytes encoding ("FF01" = {0xFF, 0x01})
unsigned char auth_key [MO_AUTHKEY_LEN_MAX + 1]; //OCPP 2.0.1: BasicAuthPassword. OCPP 1.6: AuthKey in bytes encoding ("FF01" = {0xFF, 0x01}). Both versions append a terminating '\0'
size_t auth_key_len;
const char *ca_cert; //zero-copy. The host system must ensure that this pointer remains valid during the lifetime of this class
std::shared_ptr<Configuration> setting_backend_url_str;
Expand All @@ -47,6 +57,10 @@ class MOcppMongooseClient : public MicroOcpp::Connection {
std::shared_ptr<Configuration> stale_timeout_int; //inactivity period after which the connection will be closed
std::shared_ptr<Configuration> ws_ping_interval_int; //heartbeat intervall in s. 0 sets hb off
unsigned long last_hb {0};
#if MO_ENABLE_V201
std::shared_ptr<VariableContainer> websocketSettings;
Variable *basicAuthPasswordString = nullptr;
#endif
bool connection_established {false};
unsigned long last_connection_established {-1UL / 2UL};
bool connection_closing {false};
Expand Down Expand Up @@ -115,6 +129,12 @@ class MOcppMongooseClient : public MicroOcpp::Connection {
void updateRcvTimer();
unsigned long getLastRecv(); //get time of last successful receive in millis
unsigned long getLastConnected(); //get time of last connection establish

#if MO_ENABLE_V201
//WS client creates and manages its own Variables. This getter function is a temporary solution, in future
//the WS client will be initialized with a Context reference for registering the Variables directly
std::shared_ptr<VariableContainer> getVariableContainer();
#endif
};

}
Expand Down