- CitrineOS core extracted (CSMS OCPP 2.0.1) - OpenOCPP extracted (firmware OCPP 1.6J/2.0.1) - ShapeShifter library installed (pip install -e) - ShapeShifter specification extracted - EVerest extracted TODO updated with progress
207 lines
7.5 KiB
C++
207 lines
7.5 KiB
C++
// SPDX-License-Identifier: Apache-2.0
|
|
// Copyright chargebyte GmbH and Contributors to EVerest
|
|
|
|
#include "Evse.hpp"
|
|
|
|
namespace methods {
|
|
|
|
RPCDataTypes::EVSEGetInfoResObj Evse::get_info(const int32_t evse_index) {
|
|
RPCDataTypes::EVSEGetInfoResObj res{};
|
|
|
|
const auto* evse = m_dataobj.get_evse_store(evse_index);
|
|
if (!evse) {
|
|
res.error = RPCDataTypes::ResponseErrorEnum::ErrorInvalidEVSEIndex;
|
|
return res;
|
|
}
|
|
|
|
const auto data = evse->evseinfo.get_data();
|
|
if (not data.has_value()) {
|
|
res.error = RPCDataTypes::ResponseErrorEnum::ErrorNoDataAvailable;
|
|
return res;
|
|
}
|
|
|
|
res.info = data.value();
|
|
res.error = RPCDataTypes::ResponseErrorEnum::NoError;
|
|
return res;
|
|
}
|
|
|
|
RPCDataTypes::EVSEGetStatusResObj Evse::get_status(const int32_t evse_index) {
|
|
RPCDataTypes::EVSEGetStatusResObj res{};
|
|
|
|
const auto* evse = m_dataobj.get_evse_store(evse_index);
|
|
if (!evse) {
|
|
res.error = RPCDataTypes::ResponseErrorEnum::ErrorInvalidEVSEIndex;
|
|
return res;
|
|
}
|
|
|
|
const auto data = evse->evsestatus.get_data();
|
|
if (not data.has_value()) {
|
|
res.error = RPCDataTypes::ResponseErrorEnum::ErrorNoDataAvailable;
|
|
return res;
|
|
}
|
|
|
|
res.status = data.value();
|
|
res.error = RPCDataTypes::ResponseErrorEnum::NoError;
|
|
return res;
|
|
}
|
|
|
|
RPCDataTypes::EVSEGetHardwareCapabilitiesResObj Evse::get_hardware_capabilities(const int32_t evse_index) {
|
|
RPCDataTypes::EVSEGetHardwareCapabilitiesResObj res{};
|
|
|
|
const auto* evse = m_dataobj.get_evse_store(evse_index);
|
|
if (!evse) {
|
|
res.error = RPCDataTypes::ResponseErrorEnum::ErrorInvalidEVSEIndex;
|
|
return res;
|
|
}
|
|
|
|
const auto data = evse->hardwarecapabilities.get_data();
|
|
if (not data.has_value()) {
|
|
res.error = RPCDataTypes::ResponseErrorEnum::ErrorNoDataAvailable;
|
|
return res;
|
|
}
|
|
|
|
res.hardware_capabilities = data.value();
|
|
return res;
|
|
}
|
|
|
|
RPCDataTypes::ErrorResObj Evse::set_charging_allowed(const int32_t evse_index, bool charging_allowed) {
|
|
RPCDataTypes::ErrorResObj res{};
|
|
|
|
const auto* evse = m_dataobj.get_evse_store(evse_index);
|
|
if (!evse) {
|
|
res.error = RPCDataTypes::ResponseErrorEnum::ErrorInvalidEVSEIndex;
|
|
return res;
|
|
}
|
|
return m_request_handler_ptr->set_charging_allowed(evse_index, charging_allowed);
|
|
}
|
|
|
|
RPCDataTypes::EVSEGetMeterDataResObj Evse::get_meter_data(const int32_t evse_index) {
|
|
RPCDataTypes::EVSEGetMeterDataResObj res{};
|
|
|
|
const auto* evse = m_dataobj.get_evse_store(evse_index);
|
|
if (!evse) {
|
|
res.error = RPCDataTypes::ResponseErrorEnum::ErrorInvalidEVSEIndex;
|
|
return res;
|
|
}
|
|
|
|
const auto data = evse->meterdata.get_data();
|
|
if (not data.has_value()) {
|
|
res.error = RPCDataTypes::ResponseErrorEnum::ErrorNoDataAvailable;
|
|
return res;
|
|
}
|
|
res.meter_data = data.value();
|
|
return res;
|
|
}
|
|
|
|
RPCDataTypes::ErrorResObj Evse::set_ac_charging(const int32_t evse_index, bool charging_allowed, float max_current,
|
|
std::optional<int> phase_count) {
|
|
RPCDataTypes::ErrorResObj res{};
|
|
|
|
const auto* evse = m_dataobj.get_evse_store(evse_index);
|
|
if (!evse) {
|
|
res.error = RPCDataTypes::ResponseErrorEnum::ErrorInvalidEVSEIndex;
|
|
return res;
|
|
}
|
|
return m_request_handler_ptr->set_ac_charging(evse_index, charging_allowed, max_current, phase_count);
|
|
}
|
|
|
|
RPCDataTypes::ErrorResObj Evse::set_ac_charging_current(const int32_t evse_index, float max_current) {
|
|
RPCDataTypes::ErrorResObj res{};
|
|
|
|
const auto* evse = m_dataobj.get_evse_store(evse_index);
|
|
if (!evse) {
|
|
res.error = RPCDataTypes::ResponseErrorEnum::ErrorInvalidEVSEIndex;
|
|
return res;
|
|
}
|
|
return m_request_handler_ptr->set_ac_charging_current(evse_index, max_current);
|
|
}
|
|
|
|
RPCDataTypes::ErrorResObj Evse::set_ac_charging_phase_count(const int32_t evse_index, int phase_count) {
|
|
RPCDataTypes::ErrorResObj res{};
|
|
|
|
const auto* evse = m_dataobj.get_evse_store(evse_index);
|
|
if (!evse) {
|
|
res.error = RPCDataTypes::ResponseErrorEnum::ErrorInvalidEVSEIndex;
|
|
return res;
|
|
}
|
|
|
|
// Check if the requested phase count is equal to the current active phase count
|
|
// If so, we can return a success response without making any changes. Phase switching is not
|
|
// necessary in this case.
|
|
auto evse_status = evse->evsestatus.get_data();
|
|
if (evse_status.has_value() && evse_status.value().ac_charge_status.has_value()) {
|
|
if (evse_status.value().ac_charge_status.value().evse_active_phase_count == phase_count) {
|
|
res.error = RPCDataTypes::ResponseErrorEnum::NoError;
|
|
return res;
|
|
}
|
|
}
|
|
|
|
// If phase switching must be performed and the hardware capabilities do not allow it
|
|
// we return an error response.
|
|
auto hardwarecapabilities = evse->hardwarecapabilities.get_data();
|
|
if (hardwarecapabilities.has_value() && hardwarecapabilities.value().phase_switch_during_charging == false) {
|
|
res.error = RPCDataTypes::ResponseErrorEnum::ErrorOperationNotSupported;
|
|
return res;
|
|
}
|
|
|
|
// Check if the requested phase count is within the allowed range
|
|
if ((hardwarecapabilities.has_value() && phase_count < hardwarecapabilities.value().min_phase_count_export) ||
|
|
phase_count > hardwarecapabilities.value().max_phase_count_export) {
|
|
res.error = RPCDataTypes::ResponseErrorEnum::ErrorOutOfRange;
|
|
return res;
|
|
}
|
|
|
|
// Check if phases are 1 or 3, otherwise return an error
|
|
if (phase_count != 1 && phase_count != 3) {
|
|
res.error = RPCDataTypes::ResponseErrorEnum::ErrorInvalidParameter;
|
|
return res;
|
|
}
|
|
|
|
return m_request_handler_ptr->set_ac_charging_phase_count(evse_index, phase_count);
|
|
}
|
|
|
|
RPCDataTypes::ErrorResObj Evse::set_dc_charging(const int32_t evse_index, bool charging_allowed, float max_power) {
|
|
RPCDataTypes::ErrorResObj res{};
|
|
|
|
const auto* evse = m_dataobj.get_evse_store(evse_index);
|
|
if (!evse) {
|
|
res.error = RPCDataTypes::ResponseErrorEnum::ErrorInvalidEVSEIndex;
|
|
return res;
|
|
}
|
|
return m_request_handler_ptr->set_dc_charging(evse_index, charging_allowed, max_power);
|
|
}
|
|
|
|
RPCDataTypes::ErrorResObj Evse::set_dc_charging_power(const int32_t evse_index, float max_power) {
|
|
RPCDataTypes::ErrorResObj res{};
|
|
|
|
const auto* evse = m_dataobj.get_evse_store(evse_index);
|
|
if (!evse) {
|
|
res.error = RPCDataTypes::ResponseErrorEnum::ErrorInvalidEVSEIndex;
|
|
return res;
|
|
}
|
|
return m_request_handler_ptr->set_dc_charging_power(evse_index, max_power);
|
|
}
|
|
|
|
RPCDataTypes::ErrorResObj Evse::enable_connector(const int32_t evse_index, int connector_index, bool enable,
|
|
int priority) {
|
|
RPCDataTypes::ErrorResObj res{};
|
|
|
|
const auto* evse = m_dataobj.get_evse_store(evse_index);
|
|
if (!evse) {
|
|
res.error = RPCDataTypes::ResponseErrorEnum::ErrorInvalidEVSEIndex;
|
|
return res;
|
|
}
|
|
// Iterate through the connectors to find the one with the given ID
|
|
const auto connectors = evse->evseinfo.get_available_connectors();
|
|
auto it = std::find_if(connectors.begin(), connectors.end(),
|
|
[connector_index](const auto& connector) { return connector.index == connector_index; });
|
|
// If not found, return an error
|
|
if (it == connectors.end()) {
|
|
res.error = RPCDataTypes::ResponseErrorEnum::ErrorInvalidConnectorIndex;
|
|
return res;
|
|
}
|
|
return m_request_handler_ptr->enable_connector(evse_index, connector_index, enable, priority);
|
|
}
|
|
|
|
} // namespace methods
|