Add EVerest DC charger and extend the RpcApi regarding DC charging

This commit is contained in:
Simon Stürz 2026-06-01 16:13:30 +02:00
parent 2dbab9be5d
commit cd61b5e8bb
7 changed files with 512 additions and 16 deletions

View File

@ -408,13 +408,17 @@ void IntegrationPluginEverest::setupThing(ThingSetupInfo *info)
if (available) {
thing->setStateValue(everestConnectionApiVersionStateTypeId, connection->client()->apiVersion());
// Sync things with availabe EvseInfos
// Sync things with availabe EvseInfos from this connection
QList<int> indexList;
ThingDescriptors descriptors;
qCDebug(dcEverest()) << "The client is now available, synching things...";
// First check if we have a thing for each index, if not, create the thing for it
foreach (const EverestJsonRpcClient::EVSEInfo &evseInfo, connection->client()->evseInfos()) {
// FIXME: somehow we need to now if this evse is AC or DC in order to spawn the right child thingclass.
// Collect all EVSE index in onder to check later if we have a thing for a dissapeard index.
indexList.append(evseInfo.index);
// Check if we already have a child device for this index
bool alreadyAdded = false;
@ -427,19 +431,42 @@ void IntegrationPluginEverest::setupThing(ThingSetupInfo *info)
}
if (!alreadyAdded) {
qCDebug(dcEverest()) << "-> Adding new discovered AC charger on" << connection->client()->serverUrl();
ThingDescriptor descriptor(everestChargerAcThingClassId, evseInfo.id, evseInfo.description, thing->id());
descriptor.setParams(ParamList() << Param(everestChargerAcThingIndexParamTypeId, evseInfo.index));
descriptors.append(descriptor);
if (evseInfo.supportedEnergyTransferModes.contains(EverestJsonRpcClient::EnergyTransferModeDC)
|| evseInfo.supportedEnergyTransferModes.contains(EverestJsonRpcClient::EnergyTransferModeDC_ACDP)
|| evseInfo.supportedEnergyTransferModes.contains(EverestJsonRpcClient::EnergyTransferModeDC_ACDP_BPT)
|| evseInfo.supportedEnergyTransferModes.contains(EverestJsonRpcClient::EnergyTransferModeDC_BPT)
|| evseInfo.supportedEnergyTransferModes.contains(EverestJsonRpcClient::EnergyTransferModeDC_combo_core)
|| evseInfo.supportedEnergyTransferModes.contains(EverestJsonRpcClient::EnergyTransferModeDC_core)
|| evseInfo.supportedEnergyTransferModes.contains(EverestJsonRpcClient::EnergyTransferModeDC_extended)
|| evseInfo.supportedEnergyTransferModes.contains(EverestJsonRpcClient::EnergyTransferModeDC_unique)) {
qCDebug(dcEverest()) << "-> Adding new discovered DC charger on" << connection->client()->serverUrl();
ThingDescriptor descriptor(everestChargerDcThingClassId, evseInfo.id, evseInfo.description, thing->id());
descriptor.setParams(ParamList() << Param(everestChargerDcThingIndexParamTypeId, evseInfo.index));
descriptors.append(descriptor);
} else {
// If not a DC charger, default to AC
qCDebug(dcEverest()) << "-> Adding new discovered AC charger on" << connection->client()->serverUrl();
ThingDescriptor descriptor(everestChargerAcThingClassId, evseInfo.id, evseInfo.description, thing->id());
descriptor.setParams(ParamList() << Param(everestChargerAcThingIndexParamTypeId, evseInfo.index));
descriptors.append(descriptor);
}
}
}
// TODO: evaluate if any thing dissapeared
// Check if we have things for an index which does not exist for this connection any more
QList<ThingId> thingIdsToRemove;
foreach (Thing *childThing, myThings().filterByParentId(thing->id())) {
int thingIndex = childThing->paramValue("index").toInt();
if (!indexList.contains(thingIndex)) {
qCDebug(dcEverest()) << "Removing thing" << childThing->name() << "because the index" << thingIndex << "does not exist any more on this connection.";
emit autoThingDisappeared(childThing->id());
}
}
if (!descriptors.isEmpty()) {
emit autoThingsAppeared(descriptors);
}
}
});
@ -447,7 +474,7 @@ void IntegrationPluginEverest::setupThing(ThingSetupInfo *info)
connection->start();
return;
} else if (thing->thingClassId() == everestChargerAcThingClassId) {
} else if (thing->thingClassId() == everestChargerAcThingClassId || thing->thingClassId() == everestChargerDcThingClassId) {
Thing *parentThing = myThings().findById(thing->parentId());
EverestConnection *connection = m_everstConnections.value(parentThing);
@ -601,12 +628,82 @@ void IntegrationPluginEverest::executeAction(ThingActionInfo *info)
info->finish(Thing::ThingErrorHardwareFailure);
return;
}
info->thing()->setStateValue(everestChargerAcDesiredPhaseCountStateTypeId, phaseCount);
info->finish(Thing::ThingErrorNoError);
});
}
return;
} else if (info->thing()->thingClassId() == everestChargerDcThingClassId) {
Thing *thing = info->thing();
Thing *parentThing = myThings().findById(thing->parentId());
EverestConnection *connection = m_everstConnections.value(parentThing);
if (!connection) {
info->finish(Thing::ThingErrorHardwareNotAvailable);
return;
}
if (!thing->stateValue(everestChargerDcConnectedStateTypeId).toBool()) {
info->finish(Thing::ThingErrorHardwareNotAvailable);
return;
}
EverestEvse *evse = connection->getEvse(thing);
if (!evse) {
info->finish(Thing::ThingErrorHardwareNotAvailable);
return;
}
if (info->action().actionTypeId() == everestChargerDcPowerActionTypeId) {
bool power = info->action().paramValue(everestChargerDcPowerActionPowerParamTypeId).toBool();
qCDebug(dcEverest()) << "Execute power action" << power;
EverestJsonRpcReply *reply = evse->setChargingAllowed(power) ;
connect(reply, &EverestJsonRpcReply::finished, reply, &EverestJsonRpcReply::deleteLater);
connect(reply, &EverestJsonRpcReply::finished, this, [info, reply, power](){
if (reply->error()) {
qCWarning(dcEverest()) << "Execute action reply finished with error" << reply->error();
info->finish(Thing::ThingErrorHardwareFailure);
return;
}
QVariantMap result = reply->response().value("result").toMap();
EverestJsonRpcClient::ResponseError error = EverestJsonRpcClient::parseResponseError(result.value("error").toString());
if (error) {
qCWarning(dcEverest()) << "Execute action reply finished with an error" << reply->method() << error;
info->finish(Thing::ThingErrorHardwareFailure);
return;
}
qCDebug(dcEverest()) << "Execute power action finished successfully" << reply->method() << error;
info->thing()->setStateValue(everestChargerDcPowerStateTypeId, power);
info->finish(Thing::ThingErrorNoError);
});
} else if (info->action().actionTypeId() == everestChargerDcChargingPowerActionTypeId) {
double chargingPower = info->action().paramValue(everestChargerDcChargingPowerActionChargingPowerParamTypeId).toDouble();
qCDebug(dcEverest()) << "Execute action set max charging power" << chargingPower << "[W]";
EverestJsonRpcReply *reply = evse->setDCChargingPower(chargingPower) ;
connect(reply, &EverestJsonRpcReply::finished, reply, &EverestJsonRpcReply::deleteLater);
connect(reply, &EverestJsonRpcReply::finished, this, [info, reply, chargingPower](){
if (reply->error()) {
qCWarning(dcEverest()) << "Execute action reply finished with error" << reply->error();
info->finish(Thing::ThingErrorHardwareFailure);
return;
}
QVariantMap result = reply->response().value("result").toMap();
EverestJsonRpcClient::ResponseError error = EverestJsonRpcClient::parseResponseError(result.value("error").toString());
if (error) {
qCWarning(dcEverest()) << "Execute action reply finished with an error" << reply->method() << error;
info->finish(Thing::ThingErrorHardwareFailure);
return;
}
qCDebug(dcEverest()) << "Execute power set chargingn power finished successfully" << reply->method() << error;
info->thing()->setStateValue(everestChargerDcChargingPowerStateTypeId, chargingPower);
info->finish(Thing::ThingErrorNoError);
});
}
return;
}
@ -634,7 +731,7 @@ void IntegrationPluginEverest::thingRemoved(Thing *thing)
}
} else if (thing->thingClassId() == everestConnectionThingClassId) {
m_everstConnections.take(thing)->deleteLater();
} else if (thing->thingClassId() == everestChargerAcThingClassId) {
} else if (thing->thingClassId() == everestChargerAcThingClassId || thing->thingClassId() == everestChargerDcThingClassId) {
Thing *parentThing = myThings().findById(thing->parentId());
EverestConnection *connection = m_everstConnections.value(parentThing);
if (!connection)
@ -643,5 +740,3 @@ void IntegrationPluginEverest::thingRemoved(Thing *thing)
connection->removeThing(thing);
}
}

View File

@ -181,7 +181,7 @@
"setupMethod": "JustAdd",
"createMethods": [ "Discovery", "User" ],
"interfaces": [ "gateway", "networkdevice" ],
"providedInterfaces": [ "evchargerac" ],
"providedInterfaces": [ "evchargerac", "evchargerdc" ],
"discoveryParamTypes": [
{
"id": "cd1cfca6-22f7-4d31-a95f-f642e0e1470f",
@ -480,7 +480,266 @@
"eventTypes": [
]
},
{
"name": "everestChargerDc",
"displayName": "EVerest charger DC",
"id": "b31e14dd-43e0-4278-b517-d50afd6806ec",
"createMethods": ["auto"],
"interfaces": [ "evchargerdc", "connectable"],
"paramTypes": [
{
"id": "4a3e03ed-44ea-4a32-9f7f-b4e6b1647921",
"name": "index",
"displayName": "Index",
"type": "uint",
"defaultValue": 0
}
],
"settingsTypes": [],
"stateTypes": [
{
"id": "e02d8186-a678-4e5a-aea7-460109617a02",
"name": "connected",
"displayName": "Connected",
"type": "bool",
"defaultValue": true
},
{
"id": "c7b313bf-d12d-434f-b754-d0ada7209fe5",
"name": "power",
"displayName": "Charging enabled",
"displayNameAction": "Enable/disable charging",
"type": "bool",
"defaultValue": true,
"writable": true
},
{
"id": "4dc2b506-990b-4e84-8a4b-444aba489ac2",
"name": "currentPower",
"displayName": "Current measured power",
"type": "double",
"unit": "Watt",
"defaultValue": 0
},
{
"id": "4c1415c2-bb2e-412a-9861-12ad8daa9051",
"name": "chargingPower",
"displayName": "Charging power",
"displayNameAction": "Set charging power",
"type": "double",
"unit": "Watt",
"defaultValue": 0,
"writable": true
},
{
"id": "aa130c3c-56a5-4a23-8802-7bee78dee6d2",
"name": "chargingCapabilities",
"displayName": "Charging capabilities",
"type": "QString",
"possibleValues": ["charging", "discharging", "bidirectional"],
"defaultValue": "charging"
},
{
"id": "2e17f569-807e-4906-8748-0bd094cfd5d2",
"name": "chargingState",
"displayName": "Charging state",
"type": "QString",
"possibleValues": ["idle", "charging", "discharging"],
"defaultValue": "idle"
},
{
"id": "bd8fa91f-0bf6-474c-b6bb-3d68d466d379",
"name": "charging",
"displayName": "Charging",
"type": "bool",
"defaultValue": false
},
{
"id": "7cb1984a-c172-4f25-94f8-487dcd7881ab",
"name": "state",
"displayName": "State",
"type": "QString",
"defaultValue": "",
"cached": false
},
{
"id": "a4597881-958b-4b5b-87aa-941820fef84d",
"name": "sessionEnergy",
"displayName": "Session energy",
"type": "double",
"unit": "KiloWattHour",
"defaultValue": 0,
"suggestLogging": true
},
{
"id": "7dedd1a2-6c99-4c85-8511-319f45b4fc56",
"name": "minChargingPower",
"displayName": "Minimal charging power",
"type": "double",
"unit": "Watt",
"defaultValue": 100
},
{
"id": "e1f1936e-e038-4820-bb7c-46404859ae42",
"name": "maxChargingPower",
"displayName": "Maximal charging power",
"type": "double",
"unit": "Watt",
"defaultValue": 50000
},
{
"id": "60ce60bd-0a6b-4f76-b51b-c6d342b2a277",
"name": "minDischargingPower",
"displayName": "Minimal discharging power",
"type": "double",
"unit": "Watt",
"defaultValue": -100
},
{
"id": "5bd483e4-aae6-4e53-b208-d7caa5b7fbc6",
"name": "maxDischargingPower",
"displayName": "Maximal discharging power",
"type": "double",
"unit": "Watt",
"defaultValue": -50000
},
{
"id": "020e30ce-e3db-41ad-8066-a819ac1d4bd5",
"name": "pluggedIn",
"displayName": "Car is plugged in",
"type": "bool",
"defaultValue": true,
"cached": false
},
{
"id": "bdb910aa-63c0-4af4-8f21-f9e2de601928",
"name": "currentPowerPhaseA",
"displayName": "Current power phase A",
"displayNameEvent": "Current power phase A changed",
"type": "double",
"unit": "Watt",
"defaultValue": 0.00,
"cached": false
},
{
"id": "e1e5142f-e8a3-4fac-9ebd-ec467a1cdac5",
"name": "currentPowerPhaseB",
"displayName": "Current power phase B",
"displayNameEvent": "Current power phase B changed",
"type": "double",
"unit": "Watt",
"defaultValue": 0.00,
"cached": false
},
{
"id": "d0ca61a1-057c-4fd2-bf91-0ba9c4fcff9e",
"name": "currentPowerPhaseC",
"displayName": "Current power phase C",
"displayNameEvent": "Current power phase C changed",
"type": "double",
"unit": "Watt",
"defaultValue": 0.00,
"cached": false
},
{
"id": "4d49dbb6-6ca7-4ecd-949f-d2d5b3ebee04",
"name": "currentPhaseA",
"displayName": "Phase A current",
"displayNameEvent": "Phase A current changed",
"type": "double",
"unit": "Ampere",
"defaultValue": 0.00,
"cached": false
},
{
"id": "41febbb0-5265-4aa9-aa91-1ed9dbd5e35a",
"name": "currentPhaseB",
"displayName": "Phase B current",
"displayNameEvent": "Phase B current changed",
"type": "double",
"unit": "Ampere",
"defaultValue": 0.00,
"cached": false
},
{
"id": "c7d1832b-b0a7-4cbe-b7f7-ee91732f5a45",
"name": "currentPhaseC",
"displayName": "Phase C current",
"displayNameEvent": "Phase C current changed",
"type": "double",
"unit": "Ampere",
"defaultValue": 0.00,
"cached": false
},
{
"id": "3a2aced4-e9aa-4e5a-b96b-68978f5d5c3b",
"name": "voltagePhaseA",
"displayName": "Phase A voltage",
"displayNameEvent": "Phase A volatage changed",
"type": "double",
"unit": "Volt",
"defaultValue": 0.00,
"cached": false
},
{
"id": "97273965-dc8f-4be9-a6c5-1eeb5bebc3ad",
"name": "voltagePhaseB",
"displayName": "Phase B voltage",
"displayNameEvent": "Phase B voltage changed",
"type": "double",
"unit": "Volt",
"defaultValue": 0.00,
"cached": false
},
{
"id": "2a62c222-ad9c-42bc-807a-d4e345d46a76",
"name": "voltagePhaseC",
"displayName": "Phase C voltage",
"displayNameEvent": "Phase C voltage changed",
"type": "double",
"unit": "Volt",
"defaultValue": 0.00,
"cached": false
},
{
"id": "9bfc98a0-92f7-4b46-b390-72d8da721778",
"name": "totalEnergyConsumed",
"displayName": "Total consumed energy",
"type": "double",
"unit": "KiloWattHour",
"defaultValue": 0
},
{
"id": "782e6a0c-62e5-4b36-947c-c66ee1fa1737",
"name": "totalEnergyProduced",
"displayName": "Total returned energy",
"type": "double",
"unit": "KiloWattHour",
"defaultValue": 0
},
{
"id": "d526c751-51e0-4c69-a88e-ae33db38b182",
"name": "temperature",
"displayName": "Temperature",
"type": "double",
"unit": "DegreeCelsius",
"defaultValue": 0.0,
"cached": false
},
{
"id": "dda0fdfd-a21d-46ee-85b0-8e9e469af3d3",
"name": "fanSpeed",
"displayName": "Fan speed",
"type": "double",
"unit": "Rpm",
"defaultValue": 0,
"cached": false
}
],
"actionTypes": [ ]
}
]
}
]

View File

@ -106,6 +106,9 @@ void EverestConnection::setMonitor(NetworkDeviceMonitor *monitor)
if (m_monitor) {
connect(m_monitor, &NetworkDeviceMonitor::reachableChanged, this, &EverestConnection::onMonitorReachableChanged);
}
if (m_monitor->reachable())
onMonitorReachableChanged(true);
}
void EverestConnection::start()

View File

@ -96,13 +96,17 @@ EverestJsonRpcReply *EverestEvse::setACChargingPhaseCount(int phaseCount)
return m_client->evseSetACChargingPhaseCount(m_index, phaseCount);
}
EverestJsonRpcReply *EverestEvse::setDCChargingPower(double chargingPower)
{
return m_client->evseSetDCChargingPower(m_index, chargingPower);
}
void EverestEvse::initialize()
{
qCDebug(dcEverest()) << "Evse: Starting to initialize the data for" << m_thing->name();
// Fetch all initial data for this device, once done we get notifications on data changes
EverestJsonRpcReply *reply = m_client->evseGetInfo(m_index);
connect(reply, &EverestJsonRpcReply::finished, reply, &EverestJsonRpcReply::deleteLater);
connect(reply, &EverestJsonRpcReply::finished, this, [this, reply](){
@ -166,6 +170,7 @@ void EverestEvse::initialize()
// Store data, thy will be processed once all replies arrived
m_evseStatus = EverestJsonRpcClient::parseEvseStatus(result.value("status").toMap());
EverestJsonRpcReply *reply = m_client->evseGetMeterData(m_index);
connect(reply, &EverestJsonRpcReply::finished, reply, &EverestJsonRpcReply::deleteLater);
connect(reply, &EverestJsonRpcReply::finished, this, [this, reply](){
@ -219,6 +224,25 @@ void EverestEvse::processEvseStatus()
if (m_evseStatus.acChargeParameters.maxCurrent > 0)
m_thing->setStateValue(everestChargerAcMaxChargingCurrentStateTypeId, m_evseStatus.acChargeParameters.maxCurrent);
} else if (m_thing->thingClassId() == everestChargerDcThingClassId) {
m_thing->setStateValue(everestChargerDcPowerStateTypeId, m_evseStatus.chargingAllowed);
m_thing->setStateValue(everestChargerDcSessionEnergyStateTypeId, m_evseStatus.chargedEnergyWh / 1000.0);
m_thing->setStateValue(everestChargerDcStateStateTypeId, m_evseStatus.evseStateString);
m_thing->setStateValue(everestChargerDcChargingStateTypeId, m_evseStatus.evseState == EverestJsonRpcClient::EvseStateCharging);
m_thing->setStateValue(everestChargerDcPluggedInStateTypeId, m_evseStatus.evseState != EverestJsonRpcClient::EvseStateUnplugged);
if (m_evseStatus.evseState == EverestJsonRpcClient::EvseStateCharging) {
if (m_thing->stateValue(everestChargerDcCurrentPowerStateTypeId).toDouble() > 0) {
m_thing->setStateValue(everestChargerDcChargingStateStateTypeId, "charging");
} else {
m_thing->setStateValue(everestChargerDcChargingStateStateTypeId, "discharging");
}
} else {
m_thing->setStateValue(everestChargerDcChargingStateStateTypeId, "idle");
}
}
}
@ -258,5 +282,23 @@ void EverestEvse::processMeterData()
m_thing->setStateValue(everestChargerAcVoltagePhaseCStateTypeId, m_meterData.voltageL3);
m_thing->setStateValue(everestChargerAcTotalEnergyConsumedStateTypeId, m_meterData.energyImportedTotal / 1000.0);
} else if (m_thing->thingClassId() == everestChargerDcThingClassId) {
m_thing->setStateValue(everestChargerDcCurrentPowerStateTypeId, m_meterData.powerTotal);
m_thing->setStateValue(everestChargerDcCurrentPowerPhaseAStateTypeId, m_meterData.powerL1);
m_thing->setStateValue(everestChargerDcCurrentPowerPhaseBStateTypeId, m_meterData.powerL2);
m_thing->setStateValue(everestChargerDcCurrentPowerPhaseCStateTypeId, m_meterData.powerL3);
m_thing->setStateValue(everestChargerDcCurrentPhaseAStateTypeId, m_meterData.currentL1);
m_thing->setStateValue(everestChargerDcCurrentPhaseBStateTypeId, m_meterData.currentL2);
m_thing->setStateValue(everestChargerDcCurrentPhaseCStateTypeId, m_meterData.currentL3);
m_thing->setStateValue(everestChargerDcVoltagePhaseAStateTypeId, m_meterData.voltageL1);
m_thing->setStateValue(everestChargerDcVoltagePhaseBStateTypeId, m_meterData.voltageL2);
m_thing->setStateValue(everestChargerDcVoltagePhaseCStateTypeId, m_meterData.voltageL3);
m_thing->setStateValue(everestChargerDcTotalEnergyConsumedStateTypeId, m_meterData.energyImportedTotal / 1000.0);
m_thing->setStateValue(everestChargerDcTotalEnergyProducedStateTypeId, m_meterData.energyExportedTotal/ 1000.0);
}
}

View File

@ -40,6 +40,7 @@ public:
EverestJsonRpcReply *setChargingAllowed(bool allowed);
EverestJsonRpcReply *setACChargingCurrent(double current);
EverestJsonRpcReply *setACChargingPhaseCount(int phaseCount);
EverestJsonRpcReply *setDCChargingPower(double chargingPower);
private:
EverestJsonRpcClient *m_client = nullptr;

View File

@ -239,6 +239,24 @@ EverestJsonRpcReply *EverestJsonRpcClient::evseSetACChargingPhaseCount(int evseI
return reply;
}
EverestJsonRpcReply *EverestJsonRpcClient::evseSetDCChargingPower(int evseIndex, double chargingPower)
{
QVariantMap params;
params.insert("evse_index", evseIndex);
params.insert("max_power", chargingPower);
EverestJsonRpcReply *reply = createReply("EVSE.SetDCChargingPower", params);
qCDebug(dcEverest()) << "Calling" << reply->method() << params;
sendRequest(reply);
return reply;
}
EverestJsonRpcClient::EnergyTransferMode EverestJsonRpcClient::parseEnergyTransferMode(const QString &energyTransferModeString)
{
QMetaEnum metaEnum = QMetaEnum::fromType<EnergyTransferMode>();
return static_cast<EnergyTransferMode>(metaEnum.keyToValue(QString("EnergyTransferMode").append(energyTransferModeString).toUtf8()));
}
EverestJsonRpcClient::ResponseError EverestJsonRpcClient::parseResponseError(const QString &responseErrorString)
{
QMetaEnum metaEnum = QMetaEnum::fromType<ResponseError>();
@ -272,6 +290,9 @@ EverestJsonRpcClient::EVSEInfo EverestJsonRpcClient::parseEvseInfo(const QVarian
foreach (const QVariant &connectorInfoVariant, evseInfoMap.value("available_connectors").toList()) {
evseInfo.availableConnectors.append(parseConnectorInfo(connectorInfoVariant.toMap()));
}
foreach (const QVariant &energyTransferModeVariant, evseInfoMap.value("supported_energy_transfer_modes").toList()) {
evseInfo.supportedEnergyTransferModes.append(parseEnergyTransferMode(energyTransferModeVariant.toString()));
}
return evseInfo;
}
@ -310,6 +331,10 @@ EverestJsonRpcClient::EVSEStatus EverestJsonRpcClient::parseEvseStatus(const QVa
if (evseStatusMap.contains("ac_charge_param"))
evseStatus.acChargeParameters = EverestJsonRpcClient::parseACChargeParameters(evseStatusMap.value("ac_charge_param").toMap());
// optional
if (evseStatusMap.contains("display_parameters"))
evseStatus.displayParameters = EverestJsonRpcClient::parseDisplayParameters(evseStatusMap.value("display_parameters").toMap());
return evseStatus;
}
@ -403,6 +428,39 @@ EverestJsonRpcClient::MeterData EverestJsonRpcClient::parseMeterData(const QVari
return meterData;
}
EverestJsonRpcClient::DisplayParameters EverestJsonRpcClient::parseDisplayParameters(const QVariantMap &displayParametersMap)
{
// As of now (EVerest 2026.02.0) the display paraters are not completely defined yet and marked as incomplete.
// Treat all properties as optional until the object is specified upstream.
DisplayParameters displayParameters;
if (displayParametersMap.contains("start_soc")) {
displayParameters.startSoc = displayParametersMap.value("start_soc").toInt() ;
} else if (displayParametersMap.contains("present_soc")) {
displayParameters.presentSoc = displayParametersMap.value("present_soc").toInt();
} else if (displayParametersMap.contains("minimum_soc")) {
displayParameters.minimumSoc = displayParametersMap.value("minimum_soc").toInt();
} else if (displayParametersMap.contains("target_soc")) {
displayParameters.targetSoc = displayParametersMap.value("target_soc").toInt();
} else if (displayParametersMap.contains("maximum_soc")) {
displayParameters.maximumSoc = displayParametersMap.value("maximum_soc").toInt();
} else if (displayParametersMap.contains("remaining_time_to_minimum_soc")) {
displayParameters.remainingTimeToMinimumSoc = displayParametersMap.value("remaining_time_to_minimum_soc").toInt();
} else if (displayParametersMap.contains("remaining_time_to_target_soc")) {
displayParameters.remainingTimeToTargetSoc = displayParametersMap.value("remaining_time_to_target_soc").toInt();
} else if (displayParametersMap.contains("remaining_time_to_maximum_soc")) {
displayParameters.remainingTimeToMaximumSoc = displayParametersMap.value("remaining_time_to_maximum_soc").toInt();
} else if (displayParametersMap.contains("charging_complete")) {
displayParameters.chargingComplete = displayParametersMap.value("charging_complete").toBool();
} else if (displayParametersMap.contains("battery_energy_capacity")) {
displayParameters.batteryEnergyCapacity = displayParametersMap.value("battery_energy_capacity").toDouble();
} else if (displayParametersMap.contains("inlet_hot")) {
displayParameters.inletHot = displayParametersMap.value("inlet_hot").toBool();
}
return displayParameters;
}
void EverestJsonRpcClient::connectToServer(const QUrl &serverUrl)
{
m_interface->connectServer(serverUrl);

View File

@ -102,6 +102,26 @@ public:
};
Q_ENUM(EvseState)
enum EnergyTransferMode {
EnergyTransferModeUnknown,
EnergyTransferModeAC_single_phase_core,
EnergyTransferModeAC_two_phase,
EnergyTransferModeAC_three_phase_core,
EnergyTransferModeDC_core,
EnergyTransferModeDC_extended,
EnergyTransferModeDC_combo_core,
EnergyTransferModeDC_unique,
EnergyTransferModeDC,
EnergyTransferModeAC_BPT,
EnergyTransferModeAC_BPT_DER,
EnergyTransferModeAC_DER,
EnergyTransferModeDC_BPT,
EnergyTransferModeDC_ACDP,
EnergyTransferModeDC_ACDP_BPT,
EnergyTransferModeWPT
};
Q_ENUM(EnergyTransferMode)
// API Objects
typedef struct ChargerInfo {
@ -123,6 +143,7 @@ public:
QString description; // optional
bool bidirectionalCharging = false;
QList<ConnectorInfo> availableConnectors;
QList<EnergyTransferMode> supportedEnergyTransferModes;
} EVSEInfo;
typedef struct ACChargeStatus {
@ -139,6 +160,20 @@ public:
// double nominalFrequency = 0; // Hz
} ACChargeParameters;
typedef struct DisplayParameters {
int startSoc = -1;
int presentSoc = -1;
int minimumSoc = -1;
int targetSoc = -1;
int maximumSoc = -1;
int remainingTimeToMinimumSoc = -1;
int remainingTimeToTargetSoc = -1;
int remainingTimeToMaximumSoc = -1;
bool chargingComplete = false;
double batteryEnergyCapacity = -1;
bool inletHot = false;
} DisplayParameters;
typedef struct EVSEStatus {
double chargedEnergyWh = 0;
double dischargedEnergyWh = 0;
@ -153,10 +188,10 @@ public:
ACChargeStatus acChargeStatus; // optional
ACChargeParameters acChargeParameters; // optional
DisplayParameters displayParameters; // optional
// TODO:
// o: "dc_charge_param": "$DCChargeParametersObj",
// o: "dc_charge_status": "$DCChargeLoopObj",
// o: display_parameters: "$DisplayParametersObj",
} EVSEStatus;
@ -223,6 +258,7 @@ public:
EverestJsonRpcReply *evseSetChargingAllowed(int evseIndex, bool allowed);
EverestJsonRpcReply *evseSetACChargingCurrent(int evseIndex, double current);
EverestJsonRpcReply *evseSetACChargingPhaseCount(int evseIndex, int phaseCount);
EverestJsonRpcReply *evseSetDCChargingPower(int evseIndex, double chargingPower);
// API parser methods
@ -231,6 +267,7 @@ public:
static ConnectorType parseConnectorType(const QString &connectorTypeString);
static ChargeProtocol parseChargeProtocol(const QString &chargeProtocolString);
static EvseState parseEvseState(const QString &evseStateString);
static EnergyTransferMode parseEnergyTransferMode(const QString &energyTransferModeString);
// Objects
static EVSEInfo parseEvseInfo(const QVariantMap &evseInfoMap);
@ -240,6 +277,7 @@ public:
static ACChargeParameters parseACChargeParameters(const QVariantMap &acChargeParametersMap);
static HardwareCapabilities parseHardwareCapabilities(const QVariantMap &hardwareCapabilitiesMap);
static MeterData parseMeterData(const QVariantMap &meterDataMap);
static DisplayParameters parseDisplayParameters(const QVariantMap &displayParametersMap);
public slots:
void connectToServer(const QUrl &serverUrl);