Refactor physical values to {value, unit} objects in JSON output

All fields with a physical unit are now emitted as
{"value": <number>, "unit": "<unit>"} instead of encoding the unit
in the field name.  Field names are renamed accordingly (e.g.
chargePower_kW → chargePower).  Battery temperature field names are
also fixed to reflect the already-applied K→°C conversion.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-25 19:01:44 +02:00
co-authored by Claude Sonnet 4.6
parent 02e8d71569
commit dcd5910b3d
+28 -21
View File
@@ -40,17 +40,20 @@ Sample output record
{ {
"ts": "2026-05-25T10:05:00+00:00", "ts": "2026-05-25T10:05:00+00:00",
"charging": { "charging": {
"chargingStatus": { "chargingState": "readyForCharging", ... }, "chargingStatus": { "chargingState": "readyForCharging",
"batteryStatus": { "currentSOC_pct": 80, "cruisingRangeElectric_km": 295 }, "chargePower": {"value": 9.5, "unit": "kW"}, ... },
"chargingSettings": { "targetSOC_pct": 80, ... }, "batteryStatus": { "currentSOC": {"value": 80, "unit": "%"},
"cruisingRangeElectric": {"value": 295, "unit": "km"} },
"chargingSettings": { "targetSOC": {"value": 80, "unit": "%"}, ... },
"plugStatus": { "plugConnectionState": "disconnected", ... } "plugStatus": { "plugConnectionState": "disconnected", ... }
}, },
"measurements": { "measurements": {
"odometerStatus": { "odometer": 12345 }, "odometerStatus": { "odometer": {"value": 12345, "unit": "km"} },
"rangeStatus": { "electricRange": 295, "totalRange_km": 295 }, "rangeStatus": { "electricRange": {"value": 295, "unit": "km"},
"batteryStatus": { "temperatureBatteryMax_K": 295.15, "totalRange": {"value": 295, "unit": "km"} },
"temperatureBatteryMin_K": 293.15 }, "temperatureBatteryStatus": { "temperatureHvBatteryMax": {"value": 22.0, "unit": "degC"},
"temperatureOutsideStatus": { "temperatureOutside_C": 18.0 } "temperatureHvBatteryMin": {"value": 20.0, "unit": "degC"} },
"temperatureOutsideStatus": { "temperatureOutside": {"value": 18.0, "unit": "degC"} }
}, },
"readiness": { "readiness": {
"readinessStatus": { "readinessStatus": {
@@ -96,6 +99,10 @@ def _str(v) -> str:
return str(v.value) if hasattr(v, "value") else str(v) return str(v.value) if hasattr(v, "value") else str(v)
def _phys(value, unit: str) -> dict:
return {"value": value, "unit": unit}
# ── domain extractors ──────────────────────────────────────────────────────── # ── domain extractors ────────────────────────────────────────────────────────
# Each function returns a dict whose keys are the WeConnect status-object names # Each function returns a dict whose keys are the WeConnect status-object names
# and whose values are dicts of field-name → value — mirroring the API layout. # and whose values are dicts of field-name → value — mirroring the API layout.
@@ -113,8 +120,8 @@ def extract_charging(vehicle) -> dict | None:
cs = d["chargingStatus"] cs = d["chargingStatus"]
result["chargingStatus"] = { result["chargingStatus"] = {
"chargingState": _str(cs.chargingState), "chargingState": _str(cs.chargingState),
"chargePower_kW": cs.chargePower_kW.value, "chargePower": _phys(cs.chargePower_kW.value, "kW"),
"remainingChargingTimeToComplete_min": cs.remainingChargingTimeToComplete_min.value, "remainingChargingTimeToComplete": _phys(cs.remainingChargingTimeToComplete_min.value, "min"),
"chargeType": _str(cs.chargeType), "chargeType": _str(cs.chargeType),
} }
except Exception: except Exception:
@@ -123,8 +130,8 @@ def extract_charging(vehicle) -> dict | None:
try: try:
bs = d["batteryStatus"] bs = d["batteryStatus"]
result["batteryStatus"] = { result["batteryStatus"] = {
"currentSOC_pct": bs.currentSOC_pct.value, "currentSOC": _phys(bs.currentSOC_pct.value, "%"),
"cruisingRangeElectric_km": bs.cruisingRangeElectric_km.value, "cruisingRangeElectric": _phys(bs.cruisingRangeElectric_km.value, "km"),
} }
except Exception: except Exception:
log.debug("charging/batteryStatus unavailable", exc_info=True) log.debug("charging/batteryStatus unavailable", exc_info=True)
@@ -132,7 +139,7 @@ def extract_charging(vehicle) -> dict | None:
try: try:
cfg = d["chargingSettings"] cfg = d["chargingSettings"]
result["chargingSettings"] = { result["chargingSettings"] = {
"targetSOC_pct": cfg.targetSOC_pct.value, "targetSOC": _phys(cfg.targetSOC_pct.value, "%"),
"maxChargeCurrentAC": _str(cfg.maxChargeCurrentAC), "maxChargeCurrentAC": _str(cfg.maxChargeCurrentAC),
"autoUnlockPlugWhenCharged": _str(cfg.autoUnlockPlugWhenCharged), "autoUnlockPlugWhenCharged": _str(cfg.autoUnlockPlugWhenCharged),
} }
@@ -164,7 +171,7 @@ def extract_climatisation(vehicle) -> dict | None:
cl = d["climatisationStatus"] cl = d["climatisationStatus"]
result["climatisationStatus"] = { result["climatisationStatus"] = {
"climatisationState": _str(cl.climatisationState), "climatisationState": _str(cl.climatisationState),
"remainingClimatisationTime_min": cl.remainingClimatisationTime_min.value, "remainingClimatisationTime": _phys(cl.remainingClimatisationTime_min.value, "min"),
} }
except Exception: except Exception:
log.debug("climatisationStatus unavailable", exc_info=True) log.debug("climatisationStatus unavailable", exc_info=True)
@@ -172,7 +179,7 @@ def extract_climatisation(vehicle) -> dict | None:
try: try:
cs = d["climatisationSettings"] cs = d["climatisationSettings"]
result["climatisationSettings"] = { result["climatisationSettings"] = {
"targetTemperature_C": cs.targetTemperature_C.value, "targetTemperature": _phys(cs.targetTemperature_C.value, "degC"),
"unitInCar": _str(cs.unitInCar), "unitInCar": _str(cs.unitInCar),
} }
except Exception: except Exception:
@@ -200,15 +207,15 @@ def extract_measurements(vehicle) -> dict | None:
try: try:
od = d["odometerStatus"] od = d["odometerStatus"]
result["odometerStatus"] = {"odometer": od.odometer.value} result["odometerStatus"] = {"odometer": _phys(od.odometer.value, "km")}
except Exception: except Exception:
log.debug("odometerStatus unavailable", exc_info=True) log.debug("odometerStatus unavailable", exc_info=True)
try: try:
rs = d["rangeStatus"] rs = d["rangeStatus"]
result["rangeStatus"] = { result["rangeStatus"] = {
"electricRange": rs.electricRange.value, "electricRange": _phys(rs.electricRange.value, "km"),
"totalRange_km": rs.totalRange_km.value, "totalRange": _phys(rs.totalRange_km.value, "km"),
} }
except Exception: except Exception:
log.debug("rangeStatus unavailable", exc_info=True) log.debug("rangeStatus unavailable", exc_info=True)
@@ -217,8 +224,8 @@ def extract_measurements(vehicle) -> dict | None:
try: try:
bs = d["temperatureBatteryStatus"] bs = d["temperatureBatteryStatus"]
result["temperatureBatteryStatus"] = { result["temperatureBatteryStatus"] = {
"temperatureHvBatteryMax_K": float(bs.temperatureHvBatteryMax_K.value - 273.15), "temperatureHvBatteryMax": _phys(float(bs.temperatureHvBatteryMax_K.value - 273.15), "degC"),
"temperatureHvBatteryMin_K": float(bs.temperatureHvBatteryMin_K.value - 273.15), "temperatureHvBatteryMin": _phys(float(bs.temperatureHvBatteryMin_K.value - 273.15), "degC"),
} }
except Exception: except Exception:
log.debug("measurements/temperatureBatteryStatus (temperature) unavailable", exc_info=True) log.debug("measurements/temperatureBatteryStatus (temperature) unavailable", exc_info=True)
@@ -226,7 +233,7 @@ def extract_measurements(vehicle) -> dict | None:
try: try:
temp = d["temperatureOutsideStatus"] temp = d["temperatureOutsideStatus"]
result["temperatureOutsideStatus"] = { result["temperatureOutsideStatus"] = {
"temperatureOutside_C": temp.temperatureOutside_C.value, "temperatureOutside": _phys(temp.temperatureOutside_C.value, "degC"),
} }
except Exception: except Exception:
log.debug("temperatureOutsideStatus unavailable", exc_info=True) log.debug("temperatureOutsideStatus unavailable", exc_info=True)