551 lines
14 KiB
C
Executable File
551 lines
14 KiB
C
Executable File
#include "esp_log.h"
|
|
|
|
#include "ocpp.h"
|
|
#include "evse_api.h"
|
|
#include "evse_error.h"
|
|
#include "evse_state.h"
|
|
|
|
#include "esp_wifi.h"
|
|
#include "nvs.h"
|
|
|
|
/* MicroOcpp includes */
|
|
#include <mongoose.h>
|
|
#include <MicroOcpp_c.h> //C-facade of MicroOcpp
|
|
#include <MicroOcppMongooseClient_c.h> //WebSocket integration for ESP-IDF
|
|
|
|
#define NVS_NAMESPACE "ocpp"
|
|
|
|
#define NVS_OCPP_AUTHORIZATION "authorization"
|
|
#define NVS_OCPP_ENABLED "enabled"
|
|
#define NVS_OCPP_SERVER "ocpp_server"
|
|
#define NVS_OCPP_RFID "ocpp_rfid"
|
|
|
|
#define AP_SSID "PLX-%02x%02x%02x"
|
|
|
|
static nvs_handle nvs;
|
|
|
|
static const char *TAG = "ocpp";
|
|
|
|
static bool enabled = true;
|
|
|
|
static bool authorization = false;
|
|
|
|
// static bool connector_plugged = false;
|
|
|
|
// static bool is_charging = false;
|
|
|
|
static TaskHandle_t ocpp_task = NULL;
|
|
|
|
static struct mg_mgr mgr; // Event manager
|
|
|
|
static void ocpp_task_func(void *param)
|
|
{
|
|
|
|
while (true)
|
|
{
|
|
// if (enabled)
|
|
{
|
|
mg_mgr_poll(&mgr, 10);
|
|
ocpp_loop();
|
|
|
|
if (evse_is_enabled() != ocpp_isOperative())
|
|
{
|
|
printf("ocpp_isOperative()");
|
|
evse_set_enabled(ocpp_isOperative());
|
|
}
|
|
}
|
|
vTaskDelay(pdMS_TO_TICKS(500));
|
|
}
|
|
}
|
|
|
|
bool ocpp_get_enabled(void)
|
|
{
|
|
uint8_t value = false;
|
|
nvs_get_u8(nvs, NVS_OCPP_ENABLED, &value);
|
|
ESP_LOGI(TAG, "Ocpp get enabled %d", value);
|
|
return value;
|
|
}
|
|
|
|
bool ocpp_get_authorization(void)
|
|
{
|
|
uint8_t value = false;
|
|
nvs_get_u8(nvs, NVS_OCPP_AUTHORIZATION, &value);
|
|
ESP_LOGI(TAG, "Ocpp get authorization %d", value);
|
|
return value;
|
|
}
|
|
|
|
void ocpp_get_server(char *value)
|
|
{
|
|
size_t len = 64;
|
|
value[0] = '\0';
|
|
nvs_get_str(nvs, NVS_OCPP_SERVER, value, &len);
|
|
|
|
ESP_LOGI(TAG, "Ocpp get server %s", value);
|
|
}
|
|
|
|
void ocpp_get_rfid(char *value)
|
|
{
|
|
size_t len = 64;
|
|
value[0] = '\0';
|
|
nvs_get_str(nvs, NVS_OCPP_RFID, value, &len);
|
|
|
|
ESP_LOGI(TAG, "Ocpp get rfid %s", value);
|
|
}
|
|
|
|
void ocpp_set_authorization(bool value)
|
|
{
|
|
ESP_LOGI(TAG, "Ocpp set authorization %d", value);
|
|
nvs_set_u8(nvs, NVS_OCPP_ENABLED, value);
|
|
nvs_commit(nvs);
|
|
authorization = value;
|
|
}
|
|
|
|
void ocpp_set_enabled(bool value)
|
|
{
|
|
ESP_LOGI(TAG, "Ocpp set enabled %d", value);
|
|
nvs_set_u8(nvs, NVS_OCPP_ENABLED, value);
|
|
nvs_commit(nvs);
|
|
enabled = value;
|
|
}
|
|
|
|
void ocpp_set_server(char *value)
|
|
{
|
|
ESP_LOGI(TAG, "Ocpp set server %s", value);
|
|
|
|
nvs_set_str(nvs, NVS_OCPP_SERVER, value);
|
|
|
|
nvs_commit(nvs);
|
|
}
|
|
|
|
void ocpp_set_rfid(char *value)
|
|
{
|
|
ESP_LOGI(TAG, "Ocpp set rfid %s", value);
|
|
|
|
nvs_set_str(nvs, NVS_OCPP_RFID, value);
|
|
|
|
nvs_commit(nvs);
|
|
}
|
|
|
|
bool setConnectorPluggedInput()
|
|
{
|
|
// ESP_LOGI(TAG, "setConnectorPluggedInput");
|
|
return evse_is_connector_plugged(evse_get_state());
|
|
// return true;
|
|
}
|
|
|
|
bool setEvReadyInput()
|
|
{
|
|
// ESP_LOGI(TAG, "EvReadyInput");
|
|
return evse_state_is_charging(evse_get_state());
|
|
// return is_charging;
|
|
}
|
|
|
|
bool setEvseReadyInput()
|
|
{
|
|
// ESP_LOGI(TAG, "EvseReadyInput");
|
|
return evse_is_enabled();
|
|
// return false;
|
|
}
|
|
|
|
float setPowerMeterInput()
|
|
{
|
|
ESP_LOGI(TAG, "PowerMeterInput");
|
|
//MeterData data = meter_getData();
|
|
//return data.wattA + data.wattB + data.wattC;
|
|
return 0.0f;
|
|
}
|
|
|
|
float setEnergyMeterInput()
|
|
{
|
|
ESP_LOGI(TAG, "EnergyMeterInput");
|
|
|
|
// Exemplo com valor fixo (pode ser substituído depois)
|
|
return 3600.0f;
|
|
}
|
|
|
|
int setEnergyInput()
|
|
{
|
|
ESP_LOGI(TAG, "EnergyInput");
|
|
|
|
// Exemplo com valor fixo
|
|
return 3600;
|
|
}
|
|
|
|
float setCurrentInput()
|
|
{
|
|
ESP_LOGI(TAG, "CurrentInput");
|
|
|
|
/*
|
|
if (!meter_is_running()) {
|
|
ESP_LOGW(TAG, "Meter not running, returning fallback.");
|
|
return 0.0f;
|
|
}
|
|
|
|
MeterData data = meter_getData();
|
|
return data.irmsA;
|
|
*/
|
|
return 0;
|
|
}
|
|
|
|
float setVoltageInput()
|
|
{
|
|
ESP_LOGI(TAG, "VoltageInput");
|
|
|
|
/*
|
|
if (!meter_is_running()) {
|
|
ESP_LOGW(TAG, "Meter not running, returning fallback.");
|
|
return 0.0f;
|
|
}
|
|
|
|
MeterData data = meter_getData();
|
|
return data.vrmsA;
|
|
*/
|
|
return 0.0f;
|
|
}
|
|
|
|
float setTemperatureInput()
|
|
{
|
|
ESP_LOGI(TAG, "TemperatureInput");
|
|
return 16.5f;
|
|
}
|
|
|
|
float setPowerInput()
|
|
{
|
|
ESP_LOGI(TAG, "PowerInput");
|
|
// return (float)orno_modbus_get_meter_state().activepower;
|
|
//return meter_getData().wattA + meter_getData().wattB + meter_getData().wattC;
|
|
return 0;
|
|
}
|
|
|
|
void setSmartChargingCurrentOutput(float limit)
|
|
{
|
|
ESP_LOGI(TAG, "SmartChargingCurrentOutput: %.0f\n", limit);
|
|
};
|
|
|
|
void setSmartChargingPowerOutput(float limit)
|
|
{
|
|
ESP_LOGI(TAG, "SmartChargingPowerOutput: %.0f\n", limit);
|
|
};
|
|
|
|
void setSmartChargingOutput(float power, float current, int nphases)
|
|
{
|
|
ESP_LOGI(TAG, " SmartChargingOutput: %.0f %.0f \n", power, current);
|
|
};
|
|
|
|
void setGetConfiguration(const char *payload, size_t len)
|
|
{
|
|
ESP_LOGI(TAG, " setGetConfiguration: %s %d \n", payload, len);
|
|
}
|
|
|
|
void setStartTransaction(const char *payload, size_t len)
|
|
{
|
|
ESP_LOGI(TAG, " setStartTransaction: %s %d \n", payload, len);
|
|
}
|
|
|
|
void setChangeConfiguration(const char *payload, size_t len)
|
|
{
|
|
ESP_LOGI(TAG, " setChangeConfiguration: %s %d \n", payload, len);
|
|
}
|
|
|
|
void OnResetExecute(bool state)
|
|
{
|
|
ESP_LOGI(TAG, "#### OnResetExecute");
|
|
esp_restart();
|
|
}
|
|
|
|
bool setOccupiedInput()
|
|
{
|
|
ESP_LOGI(TAG, "setOccupiedInput");
|
|
return false;
|
|
}
|
|
|
|
bool setStartTxReadyInput()
|
|
{
|
|
ESP_LOGI(TAG, "!!!!!! StartTxReadyInput");
|
|
return false;
|
|
}
|
|
|
|
bool setStopTxReadyInput()
|
|
{
|
|
ESP_LOGI(TAG, "===== StopTxReadyInput");
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
enum OptionalBool setOnUnlockConnectorInOut()
|
|
{
|
|
ESP_LOGI(TAG, "***** OnUnlockConnectorInOut");
|
|
return OptionalTrue;
|
|
}*/
|
|
|
|
bool setOnResetNotify(bool value)
|
|
{
|
|
ESP_LOGI(TAG, "!!!!!! setOnResetNotify %d", value);
|
|
return true;
|
|
}
|
|
|
|
void notificationOutput(OCPP_Transaction *transaction, enum OCPP_TxNotification txNotification)
|
|
{
|
|
ESP_LOGI(TAG, "Set notificationOutput ----> %d", txNotification);
|
|
|
|
switch (txNotification)
|
|
{
|
|
// Authorization events
|
|
case Authorized:
|
|
ESP_LOGI(TAG, "<----------- Authorized ---------->");
|
|
evse_authorize();
|
|
// is_charging = true;
|
|
break; // success
|
|
case AuthorizationRejected:
|
|
ESP_LOGI(TAG, "AuthorizationRejected ---->");
|
|
break; // IdTag not authorized
|
|
case AuthorizationTimeout:
|
|
ESP_LOGI(TAG, "AuthorizationTimeout ---->");
|
|
break; // authorization failed - offline
|
|
case ReservationConflict:
|
|
ESP_LOGI(TAG, "ReservationConflict ---->");
|
|
break; // connector reserved for other IdTag
|
|
case ConnectionTimeout:
|
|
ESP_LOGI(TAG, "ConnectionTimeout ---->");
|
|
break; // user took to long to plug vehicle after the authorization
|
|
case DeAuthorized:
|
|
ESP_LOGI(TAG, "DeAuthorized ---->");
|
|
evse_set_authorized(false);
|
|
evse_set_limit_reached(2);
|
|
// ocpp_set_charging(false);
|
|
break; // server rejected StartTx
|
|
case RemoteStart:
|
|
ESP_LOGI(TAG, "RemoteStart ---->");
|
|
break; // authorized via RemoteStartTransaction
|
|
case RemoteStop:
|
|
ESP_LOGI(TAG, "RemoteStop ---->");
|
|
break; // stopped via RemoteStopTransaction
|
|
|
|
// Tx lifecycle events
|
|
case StartTx:
|
|
ESP_LOGI(TAG, "StartTx ---->");
|
|
break;
|
|
case StopTx:
|
|
// is_charging = false;
|
|
ESP_LOGI(TAG, "StopTx ---->");
|
|
evse_set_authorized(false);
|
|
evse_set_limit_reached(2);
|
|
break;
|
|
};
|
|
}
|
|
|
|
const char *addErrorCodeInput()
|
|
{
|
|
// ESP_LOGI(TAG, "AddErrorCodeInput");
|
|
|
|
char *ptr = NULL;
|
|
|
|
uint32_t error = 0; // evse_get_error();
|
|
|
|
// ESP_LOGI(TAG, "AddErrorCodeInput %" PRIu32 "", error);
|
|
|
|
if (error & EVSE_ERR_PILOT_FAULT_BIT)
|
|
{
|
|
ptr = "InternalError";
|
|
}
|
|
else if (error & EVSE_ERR_DIODE_SHORT_BIT)
|
|
{
|
|
ptr = "InternalError";
|
|
}
|
|
else if (error & EVSE_ERR_LOCK_FAULT_BIT)
|
|
{
|
|
ptr = "ConnectorLockFailure";
|
|
}
|
|
else if (error & EVSE_ERR_UNLOCK_FAULT_BIT)
|
|
{
|
|
ptr = "ConnectorLockFailure";
|
|
}
|
|
else if (error & EVSE_ERR_RCM_TRIGGERED_BIT)
|
|
{
|
|
ptr = "OtherError";
|
|
}
|
|
else if (error & EVSE_ERR_RCM_SELFTEST_FAULT_BIT)
|
|
{
|
|
ptr = "OtherError";
|
|
}
|
|
else if (error & EVSE_ERR_TEMPERATURE_HIGH_BIT)
|
|
{
|
|
ptr = "HighTemperature";
|
|
}
|
|
else if (error & EVSE_ERR_TEMPERATURE_FAULT_BIT)
|
|
{
|
|
ptr = "OtherError";
|
|
}
|
|
|
|
return ptr;
|
|
}
|
|
|
|
void ocpp_begin_transaction(char *value)
|
|
{
|
|
ocpp_beginTransaction(value);
|
|
}
|
|
|
|
void ocpp_end_transaction(char *value)
|
|
{
|
|
ocpp_endTransaction(value, "Local");
|
|
}
|
|
|
|
void ocpp_begin_transaction_authorized(char *value)
|
|
{
|
|
ocpp_beginTransaction_authorized(value, NULL);
|
|
}
|
|
|
|
void ocpp_end_transaction_authorized(char *value)
|
|
{
|
|
ocpp_endTransaction_authorized(value, "Local");
|
|
}
|
|
|
|
bool ocpp_is_TransactionActive()
|
|
{
|
|
return ocpp_isTransactionActive();
|
|
}
|
|
|
|
void ocpp_start()
|
|
{
|
|
ESP_LOGI(TAG, "Starting ocpp");
|
|
|
|
ESP_ERROR_CHECK(nvs_open(NVS_NAMESPACE, NVS_READWRITE, &nvs));
|
|
|
|
// enabled = ocpp_get_enabled();
|
|
authorization = ocpp_get_authorization();
|
|
|
|
char serverstr[64];
|
|
ocpp_get_server(serverstr);
|
|
char rfidstr[64];
|
|
ocpp_get_rfid(rfidstr);
|
|
|
|
/* Initialize Mongoose (necessary for MicroOcpp)*/
|
|
// struct mg_mgr mgr; // Event manager
|
|
mg_mgr_init(&mgr); // Initialise event manager
|
|
mg_log_set(MG_LL_ERROR); // Set log level
|
|
|
|
/* Initialize MicroOcpp */
|
|
struct OCPP_FilesystemOpt fsopt = {.use = true, .mount = true, .formatFsOnFail = true};
|
|
|
|
char chargeid[12];
|
|
uint8_t mac[6];
|
|
esp_wifi_get_mac(ESP_IF_WIFI_AP, mac);
|
|
sprintf((char *)chargeid, AP_SSID, mac[3], mac[4], mac[5]);
|
|
|
|
char *urlid = (char *)malloc(62 * sizeof(char));
|
|
sprintf(urlid, "%s", strupr(chargeid));
|
|
|
|
//"ws://192.168.1.164:3000",
|
|
|
|
// ws://192.168.1.115:8010/OCPP16/5c866e81a2d9593de43efdb4/6750f0235b1b277aa16caf19
|
|
|
|
OCPP_Connection *osock = ocpp_makeConnection(&mgr,
|
|
"ws://192.168.2.217:8010/OCPP16/5c866e81a2d9593de43efdb4/6750f0235b1b277aa16caf19/",
|
|
"Plx_00AA1",
|
|
"",
|
|
"", fsopt);
|
|
|
|
ocpp_initialize(osock, "EPower M1", "Plixin", fsopt, false);
|
|
|
|
// ocpp_authorize()
|
|
|
|
// ocpp_authorize(rfidstr,NULL,NULL,NULL,NULL,NULL);
|
|
|
|
// ocpp_authorize("2D3CF08E", NULL, NULL, NULL, NULL, NULL);
|
|
|
|
// 2D3CF08E
|
|
|
|
/*
|
|
* Load OCPP configs. Default values will be overwritten by OpenEVSE configs. Mark configs
|
|
* to require reboot if changed via OCPP server
|
|
|
|
freevendActive = ArduinoOcpp::declareConfiguration<bool>("AO_FreeVendActive", true, CONFIGURATION_FN, true, true, true, true);
|
|
freevendIdTag = ArduinoOcpp::declareConfiguration<const char*>("AO_FreeVendIdTag", "DefaultIdTag", CONFIGURATION_FN, true, true, true, true);
|
|
*/
|
|
// allowOfflineTxForUnknownId = ArduinoOcpp::declareConfiguration<bool>("AllowOfflineTxForUnknownId", true, CONFIGURATION_FN, true, true, true, true);
|
|
// silentOfflineTx = ArduinoOcpp::declareConfiguration<bool>("AO_SilentOfflineTransactions", true, CONFIGURATION_FN, true, true, true, true);
|
|
|
|
/*
|
|
//when the OCPP server updates the configs, the following callback will apply them to the OpenEVSE configs
|
|
setOnReceiveRequest("ChangeConfiguration", [this] (JsonObject) {
|
|
|
|
config_set("ocpp_auth_auto", (uint32_t) (*freevendActive ? 1 : 0));
|
|
config_set("ocpp_idtag", String((const char*) *freevendIdTag));
|
|
config_set("ocpp_auth_offline", (uint32_t) (*allowOfflineTxForUnknownId ? 1 : 0));
|
|
config_commit();
|
|
});
|
|
*/
|
|
|
|
// ocpp_set_authorization
|
|
|
|
// ocpp_setEnergyMeterInput(&setEnergyInput);
|
|
|
|
// ocpp_setPowerMeterInput(&setPowerMeterInput);
|
|
|
|
ocpp_setEvReadyInput(&setEvReadyInput);
|
|
|
|
ocpp_setEvseReadyInput(&setEvseReadyInput);
|
|
|
|
ocpp_setSmartChargingCurrentOutput(&setSmartChargingCurrentOutput);
|
|
|
|
ocpp_setSmartChargingPowerOutput(&setSmartChargingPowerOutput);
|
|
|
|
ocpp_setSmartChargingOutput(&setSmartChargingOutput);
|
|
|
|
ocpp_setConnectorPluggedInput(&setConnectorPluggedInput);
|
|
|
|
ocpp_setOnResetExecute(&OnResetExecute);
|
|
|
|
ocpp_setTxNotificationOutput(¬ificationOutput);
|
|
|
|
// ocpp_setStartTxReadyInput(&setStartTxReadyInput);
|
|
|
|
ocpp_setStopTxReadyInput(&setStopTxReadyInput);
|
|
|
|
// ocpp_setOnUnlockConnectorInOut(&setOnUnlockConnectorInOut);
|
|
|
|
// ocpp_setOccupiedInput(&setOccupiedInput);
|
|
|
|
ocpp_addMeterValueInputFloat(&setCurrentInput, "Current.Import", "A", NULL, NULL);
|
|
ocpp_addMeterValueInputFloat(&setCurrentInput, "Current.Offered", "A", NULL, NULL);
|
|
ocpp_addMeterValueInputFloat(&setVoltageInput, "Voltage", "V", NULL, NULL);
|
|
ocpp_addMeterValueInputFloat(&setTemperatureInput, "Temperature", "Celsius", NULL, NULL);
|
|
|
|
ocpp_addMeterValueInputFloat(&setPowerMeterInput, "Power.Active.Import", "W", NULL, NULL);
|
|
ocpp_addMeterValueInputFloat(&setEnergyMeterInput, "Energy.Active.Import.Register", "W", NULL, NULL);
|
|
|
|
ocpp_addErrorCodeInput(&addErrorCodeInput);
|
|
|
|
ocpp_setOnResetNotify(&setOnResetNotify);
|
|
|
|
// ocpp_setOnResetExecute(void (*onResetExecute)(bool));
|
|
|
|
// ocpp_setOnReceiveRequest(const char *operationType, OnMessage onRequest);
|
|
|
|
// ocpp_setOnSendConf(const char *operationType, OnMessage onConfirmation);
|
|
|
|
// when the OCPP server updates the configs, the following callback will apply them to the OpenEVSE configs
|
|
// ocpp_setOnReceiveRequest("ChangeConfiguration", &setChangeConfiguration);
|
|
|
|
// ocpp_setOnReceiveRequest("GetConfiguration", &setGetConfiguration);
|
|
|
|
// ocpp_setOnReceiveRequest("StartTransaction", &setStartTransaction);
|
|
|
|
xTaskCreate(ocpp_task_func, "ocpp_task", 5 * 1024, NULL, 5, &ocpp_task);
|
|
}
|
|
|
|
void ocpp_stop(void)
|
|
{
|
|
ESP_LOGI(TAG, "Stopping");
|
|
|
|
if (ocpp_task)
|
|
{
|
|
vTaskDelete(ocpp_task);
|
|
ocpp_task = NULL;
|
|
}
|
|
|
|
/* Deallocate ressources */
|
|
ocpp_deinitialize();
|
|
// ocpp_deinitConnection(osock);
|
|
mg_mgr_free(&mgr);
|
|
} |