Skip to content
Open
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: 3 additions & 0 deletions src/app_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ String ocpp_server;
String ocpp_chargeBoxId;
String ocpp_authkey;
String ocpp_idtag;
String ocpp_certificate_id;

// Time
String time_zone;
Expand Down Expand Up @@ -195,6 +196,7 @@ ConfigOpt *opts[] =
new ConfigOptDefinition<String>(ocpp_chargeBoxId, "", "ocpp_chargeBoxId", "cid"),
new ConfigOptDefinition<String>(ocpp_authkey, "", "ocpp_authkey", "oky"),
new ConfigOptDefinition<String>(ocpp_idtag, "DefaultIdTag", "ocpp_idtag", "idt"),
new ConfigOptDefinition<String>(ocpp_certificate_id, "", "ocpp_certificate_id", "oci"),

// Ohm Connect Settings
new ConfigOptDefinition<String>(ohm, "", "ohm", "o"),
Expand Down Expand Up @@ -252,6 +254,7 @@ ConfigOpt *opts[] =
new ConfigOptVirtualMaskedBool(flagsOpt, flagsChanged, CONFIG_SERVICE_OCPP, CONFIG_SERVICE_OCPP, "ocpp_enabled", "ope"),
new ConfigOptVirtualMaskedBool(flagsOpt, flagsChanged, CONFIG_OCPP_AUTO_AUTH, CONFIG_OCPP_AUTO_AUTH, "ocpp_auth_auto", "oaa"),
new ConfigOptVirtualMaskedBool(flagsOpt, flagsChanged, CONFIG_OCPP_OFFLINE_AUTH, CONFIG_OCPP_OFFLINE_AUTH, "ocpp_auth_offline", "ooa"),
new ConfigOptVirtualMaskedBool(flagsOpt, flagsChanged, CONFIG_OCPP_ALLOW_ANY_CERT, 0, "ocpp_reject_unauthorized", "oru"),
new ConfigOptVirtualMaskedBool(flagsOpt, flagsChanged, CONFIG_OCPP_ACCESS_SUSPEND, CONFIG_OCPP_ACCESS_SUSPEND, "ocpp_suspend_evse", "ops"),
new ConfigOptVirtualMaskedBool(flagsOpt, flagsChanged, CONFIG_OCPP_ACCESS_ENERGIZE, CONFIG_OCPP_ACCESS_ENERGIZE, "ocpp_energize_plug", "opn"),
new ConfigOptVirtualMaskedBool(flagsOpt, flagsChanged, CONFIG_RFID, CONFIG_RFID, "rfid_enabled", "rf"),
Expand Down
6 changes: 6 additions & 0 deletions src/app_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ extern String ocpp_server;
extern String ocpp_chargeBoxId;
extern String ocpp_authkey;
extern String ocpp_idtag;
extern String ocpp_certificate_id;

// RFID storage
extern String rfid_storage;
Expand Down Expand Up @@ -129,6 +130,7 @@ extern uint32_t flags;
#define CONFIG_THREEPHASE (1 << 24)
#define CONFIG_WIZARD (1 << 25)
#define CONFIG_DEFAULT_STATE (1 << 26)
#define CONFIG_OCPP_ALLOW_ANY_CERT (1 << 27)

#define INITIAL_CONFIG_VERSION 1

Expand Down Expand Up @@ -180,6 +182,10 @@ inline bool config_ocpp_offline_authorization() {
return CONFIG_OCPP_OFFLINE_AUTH == (flags & CONFIG_OCPP_OFFLINE_AUTH);
}

inline bool config_ocpp_reject_unauthorized() {
return 0 == (flags & CONFIG_OCPP_ALLOW_ANY_CERT);
}

inline bool config_divert_enabled() {
return CONFIG_SERVICE_DIVERT == (flags & CONFIG_SERVICE_DIVERT);
}
Expand Down
86 changes: 81 additions & 5 deletions src/ocpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include <MicroOcpp/Model/Diagnostics/DiagnosticsService.h>
#include <MicroOcpp/Model/FirmwareManagement/FirmwareService.h>
#include <MongooseCore.h>
#include <cstdlib>
#include <cstring>

#include "app_config.h"
#include "http_update.h"
Expand Down Expand Up @@ -131,6 +133,64 @@ void OcppTask::notifyConfigChanged() {
}
}

OcppTask::TlsConfig OcppTask::resolveTlsConfig() {
TlsConfig cfg{nullptr, config_ocpp_reject_unauthorized()};

if (!cfg.rejectUnauthorized) {
return cfg;
}

const char *selected = nullptr;

if (ocpp_certificate_id.length() > 0) {
char *end = nullptr;
uint64_t cert_id = strtoull(ocpp_certificate_id.c_str(), &end, 16);
if (end != ocpp_certificate_id.c_str() && *end == '\0') {
const char *cert = certs.getCertificate(cert_id);
if (cert && cert[0] != '\0') {
selected = cert;
} else {
DBUGF("[ocpp] certificate %s not found, falling back to default root CA", ocpp_certificate_id.c_str());
}
} else {
DBUGF("[ocpp] certificate id %s is invalid, falling back to default root CA", ocpp_certificate_id.c_str());
}
}

if (!selected) {
selected = certs.getRootCa();
}

cfg.caCert = selected;
return cfg;
}

bool OcppTask::applySecurityConfig() {
if (!connection) {
return false;
}

TlsConfig desired = resolveTlsConfig();

bool caChanged = false;
if (desired.caCert == nullptr || appliedCaCert == nullptr) {
caChanged = desired.caCert != appliedCaCert;
} else {
caChanged = std::strcmp(desired.caCert, appliedCaCert) != 0;
}

bool changed = !tlsConfigApplied || desired.rejectUnauthorized != appliedRejectUnauthorized || caChanged;

if (changed) {
connection->setCaCert(desired.caCert);
appliedRejectUnauthorized = desired.rejectUnauthorized;
appliedCaCert = desired.caCert;
tlsConfigApplied = true;
}

return changed;
}

void OcppTask::reconfigure() {

if (config_ocpp_enabled()) {
Expand All @@ -141,11 +201,17 @@ void OcppTask::reconfigure() {
initializeMicroOcpp();
}

if (!ocpp_server.equals(connection->getBackendUrl()) ||
if (connection) {
bool credentialsChanged = !ocpp_server.equals(connection->getBackendUrl()) ||
!ocpp_chargeBoxId.equals(connection->getChargeBoxId()) ||
!ocpp_authkey.equals(connection->getAuthKey())) {
//OpenEVSE WS URL configs have been updated - these must be applied manually
connection->reloadConfigs();
!ocpp_authkey.equals(connection->getAuthKey());

bool tlsChanged = applySecurityConfig();

if (credentialsChanged || tlsChanged) {
//OpenEVSE WS URL configs have been updated - these must be applied manually
connection->reloadConfigs();
}
}
} else {
//OCPP disabled via OpenEVSE config
Expand Down Expand Up @@ -240,7 +306,14 @@ void OcppTask::initializeMicroOcpp() {
MicroOcpp::declareConfiguration<bool>(
MO_CONFIG_EXT_PREFIX "SilentOfflineTransactions", true); //disable transaction journaling when being offline for a long time (can lead to data loss)

connection = new MicroOcpp::MOcppMongooseClient(Mongoose.getMgr(), nullptr, nullptr, nullptr, nullptr, filesystem);
TlsConfig tlsConfig = resolveTlsConfig();
const char *initialCa = tlsConfig.caCert;

connection = new MicroOcpp::MOcppMongooseClient(Mongoose.getMgr(), nullptr, nullptr, nullptr, initialCa, filesystem);

appliedRejectUnauthorized = tlsConfig.rejectUnauthorized;
appliedCaCert = tlsConfig.caCert;
tlsConfigApplied = true;

/*
* Initialize the OCPP library and provide it with the charger credentials
Expand All @@ -264,6 +337,9 @@ void OcppTask::deinitializeMicroOcpp() {
mocpp_deinitialize();
delete connection;
connection = nullptr;
tlsConfigApplied = false;
appliedCaCert = nullptr;
appliedRejectUnauthorized = false;
}

void OcppTask::setup() {
Expand Down
9 changes: 9 additions & 0 deletions src/ocpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,19 @@ class OcppTask: public MicroTasks::Task {
void initializeMicroOcpp();
void deinitializeMicroOcpp();
void loadEvseBehavior();
bool applySecurityConfig();
struct TlsConfig {
const char *caCert;
bool rejectUnauthorized;
};
TlsConfig resolveTlsConfig();

static OcppTask *instance;

bool synchronizationLock = false;
bool tlsConfigApplied = false;
const char *appliedCaCert = nullptr;
bool appliedRejectUnauthorized = false;
protected:

//hook method of MicroTask::Task
Expand Down