Skip to content

Commit

Permalink
bugfix meter value logic
Browse files Browse the repository at this point in the history
  • Loading branch information
nlindn committed Oct 10, 2023
1 parent 6616437 commit fc03367
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 16 deletions.
41 changes: 26 additions & 15 deletions custom_components/ocpp/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1126,29 +1126,40 @@ def on_meter_values(self, connector_id: int, meter_value: dict, **kwargs):
measurand = DEFAULT_MEASURAND
unit = DEFAULT_ENERGY_UNIT

if measurand == DEFAULT_MEASURAND and unit is None:
unit = DEFAULT_ENERGY_UNIT

if self._metrics[csess.meter_start.value].value == 0:
# Charger reports Energy.Active.Import.Register directly as Session energy for transactions.
self._charger_reports_session_energy = True

if phase is None:
if unit == DEFAULT_POWER_UNIT:
self._metrics[measurand].value = float(value) / 1000
self._metrics[measurand].unit = HA_POWER_UNIT
elif unit == DEFAULT_ENERGY_UNIT or "Energy" in str(measurand):
if self._metrics[csess.meter_start.value].value == 0:
# Charger reports Energy.Active.Import.Register directly as Session energy for transactions
self._charger_reports_session_energy = True
if (
transaction_matches
and self._charger_reports_session_energy
and measurand == DEFAULT_MEASURAND
and connector_id
):
self._metrics[csess.session_energy.value].value = (
float(value) / 1000
elif (
measurand == DEFAULT_MEASURAND
and self._charger_reports_session_energy
):
if transaction_matches:
if unit == DEFAULT_ENERGY_UNIT:
value = float(value) / 1000
unit = HA_ENERGY_UNIT
self._metrics[csess.session_energy.value].value = float(
value
)
self._metrics[csess.session_energy.value].unit = unit
self._metrics[csess.session_energy.value].extra_attr[
cstat.id_tag.name
] = self._metrics[cstat.id_tag.value].value
elif (
transaction_matches or self._charger_reports_session_energy
):
else:
if unit == DEFAULT_ENERGY_UNIT:
value = float(value) / 1000
unit = HA_ENERGY_UNIT
self._metrics[measurand].value = float(value)
self._metrics[measurand].unit = unit
elif unit == DEFAULT_ENERGY_UNIT:
if transaction_matches:
self._metrics[measurand].value = float(value) / 1000
self._metrics[measurand].unit = HA_ENERGY_UNIT
else:
Expand Down
56 changes: 55 additions & 1 deletion tests/test_charge_point.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,6 @@ async def test_services(hass, socket_enabled):
cp.send_meter_err_phases(),
cp.send_meter_line_voltage(),
cp.send_meter_periodic_data(),
cp.send_main_meter_clock_data(),
# add delay to allow meter data to be processed
cp.send_stop_transaction(2),
),
Expand Down Expand Up @@ -370,6 +369,9 @@ async def test_services(hass, socket_enabled):
pass
await ws.close()
assert int(cs.get_metric("test_cpid", "Frequency")) == int(50)
assert float(cs.get_metric("test_cpid", "Energy.Active.Import.Register")) == float(
1101.452
)

await asyncio.sleep(1)

Expand Down Expand Up @@ -410,6 +412,33 @@ async def test_services(hass, socket_enabled):

await asyncio.sleep(1)

# test ocpp messages sent from charger that don't support errata 3.9 with meter values with kWh as energy unit
async with websockets.connect(
"ws://127.0.0.1:9000/CP_1_non_er_3.9",
subprotocols=["ocpp1.6"],
) as ws:
# use a different id for debugging
cp = ChargePoint("CP_1_non_errata_3.9", ws)
try:
await asyncio.wait_for(
asyncio.gather(
cp.start(),
cp.send_start_transaction(0),
cp.send_meter_energy_kwh(),
cp.send_meter_clock_data(),
# add delay to allow meter data to be processed
cp.send_stop_transaction(2),
),
timeout=5,
)
except asyncio.TimeoutError:
pass
await ws.close()

assert int(cs.get_metric("test_cpid", "Energy.Active.Import.Register")) == int(1101)
assert int(cs.get_metric("test_cpid", "Energy.Session")) == int(11)
assert cs.get_unit("test_cpid", "Energy.Active.Import.Register") == "kWh"

# test ocpp rejection messages sent from charger to cms
cs.charge_points["test_cpid"].received_boot_notification = False
cs.charge_points["test_cpid"].post_connect_success = False
Expand Down Expand Up @@ -971,6 +1000,31 @@ async def send_meter_err_phases(self):
resp = await self.call(request)
assert resp is not None

async def send_meter_energy_kwh(self):
"""Send periodic energy meter value with kWh unit."""
while self.active_transactionId == 0:
await asyncio.sleep(1)
request = call.MeterValuesPayload(
connector_id=1,
transaction_id=self.active_transactionId,
meter_value=[
{
"timestamp": "2021-06-21T16:15:09Z",
"sampledValue": [
{
"unit": "kWh",
"value": "11",
"context": "Sample.Periodic",
"format": "Raw",
"measurand": "Energy.Active.Import.Register",
},
],
}
],
)
resp = await self.call(request)
assert resp is not None

async def send_main_meter_clock_data(self):
"""Send periodic main meter value. Main meter values dont have transaction_id."""
while self.active_transactionId == 0:
Expand Down

0 comments on commit fc03367

Please sign in to comment.