Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bugfix meter value logic #934

Merged
merged 1 commit into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
nlindn marked this conversation as resolved.
Show resolved Hide resolved
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):
nlindn marked this conversation as resolved.
Show resolved Hide resolved
"""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