Skip to content

Commit 7d6d3cb

Browse files
committed
feature(OCPP): Subscribing to powermeter public key and call set_powermeter_public_key at the ChargePoint when it is recieved
Added e2e test case for powermeter public key Signed-off-by: Piet Gömpel <pietgoempel@gmail.com>
1 parent 041410c commit 7d6d3cb

5 files changed

Lines changed: 157 additions & 20 deletions

File tree

modules/EVSE/OCPP/OCPP.cpp

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -190,12 +190,10 @@ void OCPP::process_session_event(int32_t evse_id, const types::evse_manager::Ses
190190
if (session_event.event == types::evse_manager::SessionEventEnum::Enabled) {
191191
this->charge_point->on_enabled(evse_id);
192192
} else if (session_event.event == types::evse_manager::SessionEventEnum::Disabled) {
193-
EVLOG_debug << "EVSE#" << evse_id << ": "
194-
<< "Received Disabled";
193+
EVLOG_debug << "EVSE#" << evse_id << ": " << "Received Disabled";
195194
this->charge_point->on_disabled(evse_id);
196195
} else if (session_event.event == types::evse_manager::SessionEventEnum::TransactionStarted) {
197-
EVLOG_info << "EVSE#" << evse_id << ": "
198-
<< "Received TransactionStarted";
196+
EVLOG_info << "EVSE#" << evse_id << ": " << "Received TransactionStarted";
199197
const auto transaction_started = session_event.transaction_started.value();
200198

201199
const auto timestamp = ocpp_conversions::to_ocpp_datetime_or_now(session_event.timestamp);
@@ -216,26 +214,21 @@ void OCPP::process_session_event(int32_t evse_id, const types::evse_manager::Ses
216214
this->charge_point->on_transaction_started(ocpp_connector_id, session_event.uuid, id_token, energy_Wh_import,
217215
reservation_id_opt, timestamp, signed_meter_data);
218216
} else if (session_event.event == types::evse_manager::SessionEventEnum::ChargingPausedEV) {
219-
EVLOG_debug << "Connector#" << ocpp_connector_id << ": "
220-
<< "Received ChargingPausedEV";
217+
EVLOG_debug << "Connector#" << ocpp_connector_id << ": " << "Received ChargingPausedEV";
221218
this->charge_point->on_suspend_charging_ev(ocpp_connector_id);
222219
} else if (session_event.event == types::evse_manager::SessionEventEnum::ChargingPausedEVSE or
223220
session_event.event == types::evse_manager::SessionEventEnum::WaitingForEnergy) {
224-
EVLOG_debug << "Connector#" << ocpp_connector_id << ": "
225-
<< "Received ChargingPausedEVSE";
221+
EVLOG_debug << "Connector#" << ocpp_connector_id << ": " << "Received ChargingPausedEVSE";
226222
this->charge_point->on_suspend_charging_evse(ocpp_connector_id);
227223
} else if (session_event.event == types::evse_manager::SessionEventEnum::SwitchingPhases) {
228-
EVLOG_debug << "Connector#" << ocpp_connector_id << ": "
229-
<< "Received SwitchingPhases";
224+
EVLOG_debug << "Connector#" << ocpp_connector_id << ": " << "Received SwitchingPhases";
230225
this->charge_point->on_suspend_charging_evse(ocpp_connector_id, SWITCHING_PHASES_REASON);
231226
} else if (session_event.event == types::evse_manager::SessionEventEnum::ChargingStarted ||
232227
session_event.event == types::evse_manager::SessionEventEnum::ChargingResumed) {
233-
EVLOG_debug << "Connector#" << ocpp_connector_id << ": "
234-
<< "Received ChargingResumed";
228+
EVLOG_debug << "Connector#" << ocpp_connector_id << ": " << "Received ChargingResumed";
235229
this->charge_point->on_resume_charging(ocpp_connector_id);
236230
} else if (session_event.event == types::evse_manager::SessionEventEnum::TransactionFinished) {
237-
EVLOG_debug << "Connector#" << ocpp_connector_id << ": "
238-
<< "Received TransactionFinished";
231+
EVLOG_debug << "Connector#" << ocpp_connector_id << ": " << "Received TransactionFinished";
239232

240233
const auto transaction_finished = session_event.transaction_finished.value();
241234
const auto timestamp = ocpp_conversions::to_ocpp_datetime_or_now(session_event.timestamp);
@@ -262,16 +255,14 @@ void OCPP::process_session_event(int32_t evse_id, const types::evse_manager::Ses
262255
energy_Wh_import, id_tag_opt, signed_meter_data);
263256
// always triggered by libocpp
264257
} else if (session_event.event == types::evse_manager::SessionEventEnum::SessionStarted) {
265-
EVLOG_info << "Connector#" << ocpp_connector_id << ": "
266-
<< "Received SessionStarted";
258+
EVLOG_info << "Connector#" << ocpp_connector_id << ": " << "Received SessionStarted";
267259
// ev side disconnect
268260
auto session_started = session_event.session_started.value();
269261
this->charge_point->on_session_started(ocpp_connector_id, session_event.uuid,
270262
conversions::to_ocpp_session_started_reason(session_started.reason),
271263
session_started.logging_path);
272264
} else if (session_event.event == types::evse_manager::SessionEventEnum::SessionFinished) {
273-
EVLOG_debug << "Connector#" << ocpp_connector_id << ": "
274-
<< "Received SessionFinished";
265+
EVLOG_debug << "Connector#" << ocpp_connector_id << ": " << "Received SessionFinished";
275266
// ev side disconnect
276267
this->evse_soc_map[evse_id].reset();
277268
this->charge_point->on_session_stopped(ocpp_connector_id, session_event.uuid);
@@ -338,6 +329,18 @@ void OCPP::init_evse_subscriptions() {
338329

339330
this->process_session_event(evse_id, session_event);
340331
});
332+
333+
evse->subscribe_powermeter_public_key_ocmf([this, evse_id](std::string public_key_ocmf) {
334+
if (!this->started) {
335+
this->event_queue.emplace(evse_id, PowermeterPublicKey{public_key_ocmf});
336+
return;
337+
}
338+
339+
if (!this->charge_point->set_powermeter_public_key(evse_id, public_key_ocmf)) {
340+
EVLOG_error << "Failed to set powermeter public key for evse_id: " << evse_id;
341+
}
342+
});
343+
341344
evse_id++;
342345
}
343346

@@ -1077,6 +1080,9 @@ void OCPP::ready() {
10771080
[&](const types::system::FirmwareUpdateStatus& fw) {
10781081
charge_point->on_firmware_update_status_notification(
10791082
fw.request_id, conversions::to_ocpp_firmware_status_notification(fw.firmware_update_status));
1083+
},
1084+
[&](const PowermeterPublicKey public_key) {
1085+
this->charge_point->set_powermeter_public_key(queued_event.evse_id, public_key.value);
10801086
}},
10811087
queued_event.data);
10821088
}

modules/EVSE/OCPP/OCPP.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,12 @@
4848

4949
struct ErrorRaised : public Everest::error::Error {};
5050
struct ErrorCleared : public Everest::error::Error {};
51+
struct PowermeterPublicKey {
52+
std::string value;
53+
};
5154

5255
using EventData = std::variant<types::evse_manager::SessionEvent, ErrorRaised, ErrorCleared, types::system::LogStatus,
53-
types::system::FirmwareUpdateStatus>;
56+
types::system::FirmwareUpdateStatus, PowermeterPublicKey>;
5457

5558
struct Event {
5659
EventData data;

modules/Simulation/YetiSimulator/powermeter/powermeterImpl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ void powermeterImpl::init() {
1010
}
1111

1212
void powermeterImpl::ready() {
13+
this->publish_public_key_ocmf("TESTPUBLICKEY" + std::to_string(this->mod->config.connector_id));
1314
}
1415

1516
types::powermeter::TransactionStartResponse

tests/ocpp_tests/test_sets/everest-aux/config/everest-config-two-connectors.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ active_modules:
4444
yeti_driver_2:
4545
module: YetiSimulator
4646
config_module:
47-
connector_id: 1
47+
connector_id: 2
4848
car_simulator_1:
4949
module: EvManager
5050
config_module:
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import pytest
2+
3+
from everest.testing.core_utils.controller.test_controller_interface import (
4+
TestController,
5+
)
6+
from everest.testing.ocpp_utils.charge_point_utils import (
7+
wait_for_and_validate,
8+
TestUtility,
9+
)
10+
from everest.testing.ocpp_utils.central_system import ChargePoint16
11+
from everest.testing.ocpp_utils.fixtures import test_utility, charge_point_v16
12+
from everest_test_utils import get_everest_config_path_str
13+
14+
from ocpp.v16 import call_result
15+
16+
17+
@pytest.mark.asyncio
18+
@pytest.mark.everest_core_config(
19+
get_everest_config_path_str("everest-config-two-connectors.yaml")
20+
)
21+
async def test_meter_public_key(
22+
charge_point_v16: ChargePoint16, test_utility: TestUtility
23+
):
24+
await charge_point_v16.get_configuration_req(key=["MeterPublicKey[1]"])
25+
assert await wait_for_and_validate(
26+
test_utility,
27+
charge_point_v16,
28+
"GetConfiguration",
29+
call_result.GetConfiguration(
30+
[{"key": "MeterPublicKey[1]", "readonly": True, "value": "TESTPUBLICKEY1"}]
31+
),
32+
)
33+
34+
await charge_point_v16.get_configuration_req(key=["MeterPublicKey[2]"])
35+
assert await wait_for_and_validate(
36+
test_utility,
37+
charge_point_v16,
38+
"GetConfiguration",
39+
call_result.GetConfiguration(
40+
[{"key": "MeterPublicKey[2]", "readonly": True, "value": "TESTPUBLICKEY2"}]
41+
),
42+
)
43+
44+
await charge_point_v16.get_configuration_req(key=["MeterPublicKey[3]"])
45+
46+
assert await wait_for_and_validate(
47+
test_utility,
48+
charge_point_v16,
49+
"GetConfiguration",
50+
{"unknownKey": ["MeterPublicKey[3]"]}
51+
)
52+
53+
test_utility.messages.clear()
54+
55+
response : call_result.GetConfiguration = await charge_point_v16.get_configuration_req()
56+
57+
assert any(
58+
entry['key'] == "MeterPublicKey[1]" and entry['value'] == "TESTPUBLICKEY1"
59+
for entry in response.configuration_key)
60+
61+
assert any(
62+
entry['key'] == "MeterPublicKey[2]" and entry['value'] == "TESTPUBLICKEY2"
63+
for entry in response.configuration_key)
64+
65+
await charge_point_v16.get_configuration_req(key=["MeterPublicKey[]"])
66+
67+
assert await wait_for_and_validate(
68+
test_utility,
69+
charge_point_v16,
70+
"GetConfiguration",
71+
{"unknownKey": ["MeterPublicKey[]"]}
72+
)
73+
74+
await charge_point_v16.get_configuration_req(key=["MeterPublicKey[MeterPublicKey[1]]"])
75+
76+
assert await wait_for_and_validate(
77+
test_utility,
78+
charge_point_v16,
79+
"GetConfiguration",
80+
{"unknownKey": ["MeterPublicKey[MeterPublicKey[1]]"]}
81+
)
82+
83+
await charge_point_v16.get_configuration_req(key=["MeterPublicKey[1X"])
84+
85+
assert await wait_for_and_validate(
86+
test_utility,
87+
charge_point_v16,
88+
"GetConfiguration",
89+
{"unknownKey": ["MeterPublicKey[1X"]}
90+
)
91+
92+
await charge_point_v16.get_configuration_req(key=["MeterPublicKey[1X]"])
93+
94+
assert await wait_for_and_validate(
95+
test_utility,
96+
charge_point_v16,
97+
"GetConfiguration",
98+
{"unknownKey": ["MeterPublicKey[1X]"]}
99+
)
100+
101+
await charge_point_v16.get_configuration_req(key=["MeterPublicKey[banana]"])
102+
103+
assert await wait_for_and_validate(
104+
test_utility,
105+
charge_point_v16,
106+
"GetConfiguration",
107+
{"unknownKey": ["MeterPublicKey[banana]"]}
108+
)
109+
110+
await charge_point_v16.get_configuration_req(key=["MeterPublicKey[0]"])
111+
112+
assert await wait_for_and_validate(
113+
test_utility,
114+
charge_point_v16,
115+
"GetConfiguration",
116+
{"unknownKey": ["MeterPublicKey[0]"]}
117+
)
118+
119+
await charge_point_v16.change_configuration_req(
120+
key="MeterPublicKey[1]", value="TEST"
121+
)
122+
assert await wait_for_and_validate(
123+
test_utility,
124+
charge_point_v16,
125+
"ChangeConfiguration",
126+
{"status": "Rejected"}
127+
)

0 commit comments

Comments
 (0)