Primary vehicle: HYMER Grand Canyon S 600 CrossOver (2025), Mercedes Sprinter 419 CDI SCU Firmware: 1.12.0.0 Validated: April 2026 via mitmproxy captures + live HA correlation Discovery scan: 2026-04-23 — 129 sensors, 129 mapped, 0 unmapped. Vehicle-verified at Munich. JSON architecture: v2.44.0+ — all sensor mappings, entity definitions, lights, and switches loaded from
base.json+{brand}.json.
This document maps every known (bus_id, sensor_id) slot to its sensor name,
unit, and value transform. The base map was built on the S600 but includes
additive mappings from other EHG vehicles:
- Bus 60 (Dometic compressor fridge) — contributed by @mvondemhagen on Eriba Car 602 (#54)
Slot assignments are identical on S600 and S700 Grand Canyon models — both use the same SCU component types and bus IDs (confirmed by @dan-simms1 in #37). Other EHG brands may differ — see the Multi-Brand Notes in the README.
Starting with v2.43.0, all sensor mappings and entity definitions are loaded
from JSON files in custom_components/hymer_connect/sensor_maps/. The hardcoded
Python SENSOR_MAP dict is empty — everything comes from JSON.
At startup the integration loads base.json (universal buses shared by all EHG
brands) + {brand}.json (brand-specific overlays, e.g. hymer.json for S600/S700).
Each sensor entry is a JSON object with decode fields (how the raw protobuf value is processed) and optional entity fields (how the HA entity is configured):
{
"_comment": "Description (ignored by loader)",
"sensors": {
"1,1": {
"name": "odometer",
"unit": "km",
"transform": "div1000",
"platform": "sensor",
"device_class": "distance",
"state_class": "total_increasing",
"icon": "mdi:counter"
},
"1,10": {
"name": "engine_running",
"platform": "binary_sensor",
"device_class": "running",
"icon": "mdi:engine"
},
"1,8": {
"name": "vin_text"
}
}
}Decode fields (how the raw value is processed):
| Field | Required | Description | Examples |
|---|---|---|---|
name |
Yes | Sensor name — becomes the HA entity key and translation key | "odometer", "bms_voltage" |
unit |
No | HA unit string | "V", "A", "°C", "%", "W", "km", "bar", "m", "min", "Ah", "h" |
transform |
No | Value transform | "div10", "div100", "div1000", "div3600" (seconds → hours) |
Entity fields (how the HA entity is configured — all optional):
| Field | Description | Examples |
|---|---|---|
platform |
"sensor" or "binary_sensor". If omitted, the entry is decode-only (value stored in coordinator data but no HA entity created). |
"sensor", "binary_sensor" |
device_class |
HA device class string | "temperature", "voltage", "current", "door", "running", "power", "lock" |
state_class |
HA state class | "measurement", "total_increasing" |
icon |
MDI icon | "mdi:thermometer", "mdi:battery" |
on_value |
Binary sensor only — the raw value that means "on" | "Open", "On", 1, true (default: true) |
enabled |
Set to false to disable the entity by default (user can enable in entity registry) |
false |
Fields starting with _ (e.g. _comment, _doc, _vehicles) are ignored by the loader.
Backward compat: The old v2.41/v2.42 array format
["name", "unit", "transform"]is still accepted for decode-only entries but does not support entity metadata.
| File | Entries | Buses | Loaded when | Purpose |
|---|---|---|---|---|
base.json |
63 | 1, 3, 30, 45 | Always (first) | Universal sensors shared by ALL EHG vehicles |
hymer.json |
88 | 8, 11–27, 34, 37, 43–44, 49, 58, 99, 121 | Brand = HYMER | S600/S700: lights, Voltronic solar, Thetford fridge, Truma, BOS BMS, Victron |
eriba.json |
33 | 18, 59, 60, 93 | Brand = Eriba | Eriba Car 602: Dometic fridge, shower light, Truma AC, furniture light |
buerstner.json |
— | — | Brand = Bürstner | Community-contributed (empty) |
dethleffs.json |
— | — | Brand = Dethleffs | Community-contributed (empty) |
lmc.json |
— | — | Brand = LMC | Community-contributed (empty) |
niesmann-bischoff.json |
— | — | Brand = Niesmann+Bischoff | Community-contributed (empty) |
sunlight.json |
— | — | Brand = Sunlight | Community-contributed (empty) |
carado.json |
— | — | Brand = Carado | Community-contributed (empty) |
laika.json |
— | — | Brand = Laika | Community-contributed (empty) |
freeontour.json |
— | — | Brand = FreeOnTour | Community-contributed (empty) |
1. base.json (universal sensors) ← 63 entries (buses 1, 3, 30, 45)
2. + {brand}.json (brand-specific) ← overrides base entries for same (bus, slot)
Later entries win — a brand file can override anything in base.
JSON "sensors" entry with "platform" field
↓
pia_decoder.load_sensor_map() stores in SENSOR_MAP (decode) + ENTITY_DEFS (entity metadata)
↓
sensor.py / binary_sensor.py call _build_dynamic_sensors() / _build_dynamic_binary_sensors()
↓
HA entity descriptions created from ENTITY_DEFS at setup time
↓
Entities appear in HA with correct device_class, icon, state_class, etc.
Entries without a platform field are decode-only — they appear in coordinator.data["signalr_sensors"] but don't create an HA entity. This is useful for raw slots that are consumed by computed sensors (e.g. lithium_soc is decode-only, consumed by the static battery_soc entity which reads from it).
⚠️ Ignition dependency: Bus 1 data comes from the Mercedes chassis CAN, which is only active when the ignition is in ACC or ON position. With ignition OFF, the SCU has no new CAN frames to relay — sensors on this bus (outside temp, fuel, odometer, doors, etc.) will show stale/cached values even if the 12V habitation main is on.Theory (2026-05-07, unverified): The SCU appears to cache the last-known CAN values and re-sends them on SignalR reconnect / subscription refresh. HA records this as a state change (
last-changedupdates), but the value itself may be days old. Example:outside_temperatureshowed 25.5 °C withlast-changed= 15 h ago, but actual weather in Munich at that time was far below 25 °C. The 25.5 °C was likely cached from a warm afternoon days earlier. Planned verification: Weekend camping trip — drive with ignition on, confirm live temperature, fuel consumption, and estimated range updates.
| Slot | Sensor Name | Unit | Transform | Notes |
|---|---|---|---|---|
| (1, 1) | odometer |
km | div1000 | Lifetime odometer |
| (1, 2) | fuel_level |
% | — | Diesel fuel level (confirmed: EHG app 73% = sensor 72.72) |
| (1, 3) | lock_status |
— | — | Vehicle locked/unlocked string |
| (1, 4) | handbrake |
— | — | Handbrake state |
| (1, 5) | distance_to_service |
km | div100 | km to next service interval (was: rpm) |
| (1, 6) | adblue_level |
% | — | AdBlue tank level |
| (1, 7) | engine_hours |
h | div3600 | Engine runtime |
| (1, 8) | vin_text |
— | — | VIN string |
| (1, 9) | outside_temperature |
°C | — | Mercedes outside temperature sensor (bumper-mounted). Confirmed 2026-04-20: read 13°C → 16°C tracking real ambient weather in Unterföhring. Same value as Mercedes cockpit "Außentemperatur" display. |
| (1, 10) | engine_running |
— | — | Engine on/off |
| (1, 11) | wiping_water_empty |
— | — | Washer fluid low warning (per S700 PR #44; was door_sliding — never updated on S600) |
| (1, 12) | door_driver |
— | — | Driver door (confirmed at vehicle 2026-04-20, re-confirmed 2026-04-23). MB API: doorstatusfrontleft |
| (1, 13) | door_passenger |
— | — | Passenger door (confirmed at vehicle 2026-04-20, re-confirmed 2026-04-23). MB API: doorstatusfrontright |
| (1, 14) | motor_oil_warning |
— | — | Shows "SNA" (Sensor Not Available) on S600. Per S700 PR #44: engine oil warning. Not a door — confirmed 2026-04-23. Sliding/rear doors only via MB API (doorstatusrearright, decklidstatus). |
| (1, 15) | ignition_state |
— | — | IGN_LOCK/OFF/ACC/ON/START |
| (1, 16) | seatbelt_warning |
— | — | Seatbelt warning |
| (1, 17) | coolant_warning |
— | — | Coolant low warning (was: turn_signal) |
| (1, 18) | parking_brake |
— | — | Parking brake engaged (was: headlamp — confirmed by "ON" while parked) |
| (1, 19) | standheizung_available |
— | — | Auxiliary heater fitted (was: parking_light) |
| (1, 20) | standheizung_state |
— | — | Auxiliary heater on/off (was: fog_front) |
| (1, 21) | cruise_control_can |
— | — | Cruise control active (was: fog_rear) |
| (1, 22) | downhill_assist |
— | — | Downhill assist active (was: high_beam) |
| (1, 23) | language |
— | — | Dashboard language code |
| Slot | Sensor Name | Unit | Transform | Notes |
|---|---|---|---|---|
| (3, 1) | main_switch |
— | — | 12V main switch state. Write: str "On"/"Off" |
| (3, 2) | power_source |
— | — | "Battery / solar operated", "Mains" etc. |
| (3, 3) | charger_active |
— | — | Shore charger active. Also water pump write target (bool) |
| (3, 4) | charge_phase |
— | — | Bulk/Absorption/Float/Idle |
| (3, 5) | battery_voltage |
V | — | Living battery voltage |
| (3, 6) | battery_current |
A | — | Living battery current (negative = discharging) |
| (3, 7) | chassis_battery_voltage |
V | — | Starter battery voltage |
| (3, 8) | fresh_water_level_ebl |
% | — | Fresh water level from EBL402 tank input (per S700 PR #44). Discovery: 0 with empty tank. |
| (3, 9) | grey_water_level_ebl |
% | — | Grey water level from EBL402 tank input (per S700 PR #44). Discovery: 0 with empty tank. |
| (3, 10) | battery_soc |
% | — | Battery state of charge. Discovery: 95% |
| (3, 11) | battery_type |
— | — | "AGM/Lithium" |
| (3, 12–18) | switch_12v_1..7 |
— | — | 12V switch channels |
| (3, 19) | solar_voltage_sentinel |
V | — | Always 3276.8 (sentinel). Real solar on bus 8 |
| (3, 20) | solar_connected |
— | — | Solar panel connected. Discovery: 1 (int, not bool) |
| (3, 21) | solar_charger_status |
— | — | MPPT charger status. Discovery: 1 (int) |
| (3, 22) | shoreline_connected |
— | — | Shore power connected. Discovery: False (bool) |
All 7 slots are solar charger data — same layout on both S600 (MPP260CI) and
S700 (MPP250Duo). Some code labels in pia_decoder.py still carry legacy names
from an earlier incorrect sensor map where bus 8 was wrongly labeled as grey
water / ventilation. Solar power is computed as voltage × current instead of
reading the raw slot (8, 7) directly.
| Slot | Sensor Name | Unit | Notes |
|---|---|---|---|
| (8, 1) | solar_active |
— | MPPT "charging active" flag. Computed from solar_current > 0. Legacy code label: gray_water_sensor |
| (8, 2) | solar_voltage |
V | Panel voltage — confirmed 19.9V live |
| (8, 3) | solar_current |
A | Charge current — confirmed 2.1A live |
| (8, 4) | solar_error |
— | MPPT error flag. Legacy code label: vent_1 |
| (8, 5) | solar_reduced_power |
— | MPPT reduced power flag. Legacy code label: vent_2 |
| (8, 6) | solar_aes_active |
— | MPPT AES mode flag. Legacy code label: vent_3 |
| (8, 7) | solar_power |
W | MPPT power output. Computed as V×I instead. Legacy code label: tire_pressure |
| Slot | Sensor Name | Unit | Notes |
|---|---|---|---|
| (11, 1) | light_living_ceiling |
— | On/off |
| (11, 2) | light_living_ceiling_brightness |
% | Brightness |
| Slot | Sensor Name | Unit | Notes |
|---|---|---|---|
| (12, 1) | light_living_ambient |
— | On/off |
| (12, 2) | light_living_ambient_brightness |
% | Brightness |
| (12, 3) | light_living_ambient_color_temp |
— | Color temperature |
| Slot | Sensor Name | Unit | Notes |
|---|---|---|---|
| (15, 1) | light_bedroom_ambient |
— | On/off |
| (15, 2) | light_bedroom_ambient_brightness |
% | Brightness |
| (15, 3) | light_bedroom_ambient_color_temp |
— | Color temperature |
| Slot | Sensor Name | Unit | Notes |
|---|---|---|---|
| (16, 1) | light_nightlight |
— | On/off |
| (16, 2) | light_nightlight_brightness |
% | Brightness |
| Slot | Sensor Name | Unit | Notes |
|---|---|---|---|
| (19, 1) | light_bathroom_ceiling |
— | On/off |
| (19, 2) | light_bathroom_ceiling_brightness |
% | Brightness |
| Slot | Sensor Name | Unit | Notes |
|---|---|---|---|
| (21, 1) | light_kitchen |
— | On/off |
| (21, 2) | light_kitchen_brightness |
% | Brightness |
| (21, 3) | light_kitchen_color_temp |
— | Color temperature |
Previously labelled as fresh water tank. Confirmed at vehicle 2026-04-23: both water tanks were empty but bus 22 showed 88%, matching LED bar brightness on bus 25. Bus 22 is the outside LED bar — same physical light as bus 25 (separate SCU component registration). Sensor entities disabled by default (bus 25 is the primary control channel).
| Slot | Sensor Name | Unit | Notes |
|---|---|---|---|
| (22, 1) | light_led_bar_2 |
— | On/off (duplicate of bus 25) |
| (22, 2) | light_led_bar_2_brightness |
% | Brightness (tracks bus 25 LED bar) |
Sending (24,1)=true toggles all living area lights (ceiling, ambient, kitchen, seating). NOT an individual outside light — verified 2026-04-22: toggling activates all Wohnen lights.
| Slot | Sensor Name | Unit | Notes |
|---|---|---|---|
| (24, 1) | light_wohnen_group |
— | On/off. Toggles all Wohnen lights |
| (24, 2) | light_wohnen_group_brightness |
% | Group brightness (sentinel: 10000 when off) |
| (24, 3) | light_wohnen_group_color_temp |
— | Group color temperature context |
Previously mislabelled as grey water. Mitmproxy capture confirmed the EHG app sends on/off + brightness commands to bus 25 when toggling the LED bar. Issue #46 resolved.
| Slot | Sensor Name | Unit | Notes |
|---|---|---|---|
| (25, 1) | light_led_bar |
— | On/off (bool) |
| (25, 2) | light_led_bar_brightness |
% | Brightness (0-100) |
Discovered by tools/discover_sensors.py. Same structure as Bus 24 (All Wohnen group). Sending (27,1)=true toggles all bedroom/bath lights. NOT the outside LED bar — verified by user: toggling (27,1) activates all private area lights.
| Slot | Sensor Name | Unit | Notes |
|---|---|---|---|
| (27, 1) | light_privat_group |
— | On/off (bool). Toggles all Privat lights |
| (27, 2) | light_privat_group_brightness |
% | Group brightness (sentinel: 10000 when off) |
| (27, 3) | light_privat_group_color_temp |
— | Group color temperature context |
Slot labels verified against EHG app Hermes bundle (APK 2.10.14, decompiled 2026-05-05). Previous mapping incorrectly labelled slots 3-7 as GPS data — they are actually LTE quality, SCU voltage, and Bluetooth device counts. GPS position comes only from slot 1; the actual GPS fix/altitude/satellites/ heading are delivered via the REST API, not PIA.
| Slot | EHG Name | Sensor Name | Unit | Datatype | Mode | Notes |
|---|---|---|---|---|---|---|
| (30, 1) | GpsLocation |
gps_coordinates |
— | string | r | Lat,Lng string |
| (30, 2) | ScuInternalTime |
scu_internal_time |
— | string | r | SCU internal clock (YYYY-MM-DD hh:mm Z) |
| (30, 3) | LteConnectionQuality |
lte_connection_quality |
— | string | r | LTE signal quality (e.g. "excellent"). Previously mislabelled as gps_signal_quality |
| (30, 4) | LteConnectionState |
lte_connection_state |
— | bool | r | LTE modem connected. Previously mislabelled as gps_fix |
| (30, 5) | ScuVoltage |
scu_voltage |
V | float | r | SCU supply voltage (e.g. 13.1V). Previously mislabelled as gps_altitude (13.1m) |
| (30, 6) | PairedBTDevices |
paired_bt_devices |
— | int | r | Number of paired Bluetooth devices. Previously mislabelled as gps_satellites |
| (30, 7) | ConnectedBTDevices |
connected_bt_devices |
— | int | r | Currently connected BT devices. Previously mislabelled as gps_heading |
| (30, 8) | BatteryCutoffSwitch |
battery_cutoff_switch |
— | bool | r | Battery disconnect/cutoff switch state |
| (30, 9) | UserActive |
user_active |
— | bool | rw | User activity flag. Previously mislabelled as lte_connected |
| (30, 10) | DPlus |
d_plus_signal |
— | bool | r | D+ alternator charge signal from chassis |
| (30, 11) | WakeUpChassis |
wake_up_chassis |
— | bool | w | Chassis wake-up trigger (write-only — may not produce readable data) |
| (30, 12) | BatterySwitchActive |
battery_switch_active |
— | bool | r | 12V battery switch active. True = 12V ON |
| (30, 13) | ShoreLineConnected |
shoreline_connected_scu |
— | bool | r | Shore power (deprecated in EHG app; primary source is bus 3 slot 22) |
| (30, 14) | VehicleMovement |
vehicle_movement |
— | bool | r | Vehicle in motion detection |
Slot labels verified against EHG app Hermes bundle (APK 2.10.14, decompiled 2026-05-05).
| Slot | EHG Name | Sensor Name | Notes |
|---|---|---|---|
| (34, 1) | FridgeOn |
fridge_power |
Power on/off (bool write). Discovery: False |
| (34, 2) | NightMode |
fridge_eco |
ECO/quiet mode (bool write). Discovery: False |
| (34, 3) | FridgeLevel |
fridge_cooling_step |
Cooling step 1–5 (uint write). Discovery: 2 |
| (34, 4) | FreezerLevel |
fridge_freezer_level |
Freezer level (deprecated in EHG app). Discovery: 0 (int) |
| (34, 5) | DoorOpen |
fridge_door |
Fridge door open/closed (bool, read-only). Binary sensor. Previously unmapped — fridge_door entity was incorrectly reading from bus 37 slot 2 (VehicleBrand). Fixed in v2.53.0. |
| (34, 6) | WarningErrorInformation |
fridge_warning |
Fridge warning/error code (int). Discovery: 0 |
| (34, 7) | DCVoltage |
fridge_dc_voltage |
Fridge DC supply voltage (int, mV). Discovery: 13000 |
Note: The EHG app metadata labels this bus as
VehicleInformationwith slotsVehicleTypeandVehicleBrand. However, on the S600, the PIA protobuf data on bus 37 carries fridge mode and status readback, not vehicle identification. The fridge select entity readsfridge_modefrom here and it works correctly. This discrepancy may be a SCU firmware routing difference vs the EHG app's component registry.
| Slot | EHG Name | Sensor Name | Notes |
|---|---|---|---|
| (37, 1) | VehicleType |
fridge_mode |
Fridge operating mode on S600 PIA. Discovery: Off (string) |
| (37, 2) | VehicleBrand |
fridge_status |
Fridge status on S600 PIA. Not the fridge door — door is on bus 34 slot 5. |
| Slot | Sensor Name | Unit | Notes |
|---|---|---|---|
| (43, 1) | light_seating_overhead |
— | On/off |
| (43, 2) | light_seating_overhead_brightness |
% | Brightness |
| Slot | Sensor Name | Unit | Notes |
|---|---|---|---|
| (44, 1) | light_bedroom_overhead |
— | On/off |
| (44, 2) | light_bedroom_overhead_brightness |
% | Brightness |
| Slot | Sensor Name | Notes |
|---|---|---|
| (45, 8) | scu_connected |
SCU connectivity flag. Discovery: True |
| (45, 9) | scu_sensor_9 |
Discovery: False (bool) |
| (45, 10) | scu_sensor_10 |
Discovery: False (bool) |
| (45, 11) | scu_firmware |
SCU firmware version string. Discovery: 1.12.0.0 |
| Slot | Sensor Name | Notes |
|---|---|---|
| (49, 8) | truma_connected |
Truma connectivity flag |
| (49, 10) | truma_status |
Truma status code |
| (49, 11) | truma_firmware |
Truma firmware version string |
EHG canonical name in parentheses where the local sensor key is a legacy misnomer kept for backwards-compatibility with existing dashboards/history.
| Slot | Sensor Name | Unit | Notes |
|---|---|---|---|
| (58, 4) | heater_fuel_type (EHG: heater_air_energy_source) |
— | Heater air energy source string (Gas/Electric/Mix). rw |
| (58, 5) | heater_fan_speed (EHG: water_heater_mode) |
— | Boiler mode (Off/ECO/HOT). The legacy heater_fan_speed name is misleading — this is the water-heater (boiler) mode, not the heater fan. The Truma fan power (Eco/High) is not exposed on the SCU bus and remains panel-only. rw |
| (58, 6) | heater_fuel_type_2 (EHG: heater_water_energy_source) |
— | Water heater energy source. rw |
| (58, 7) | heater_state (EHG: panel_busy) |
— | Panel-busy flag (bool). r |
| (58, 8) | heater_setpoint (EHG: target_air_temperature) |
°C | Target air temperature, float write, range -273…30. rw |
| (58, 9) | heater_electric_power (EHG: power_limit) |
W | Electric heating element power (0/900/1800). rw |
| (58, 10) | heater_combi_error (EHG: combi_error) |
— | Combi error flag (bool). r |
| (58, 11) | heater_operating_mode (EHG: heater_air_mode) |
— | Heater air mode string (OFF / Normal / Automatic). Read-only in practice — SCU silently rolls back writes. rw per metadata |
| (58, 12) | heater_response_error (EHG: response_error) |
— | Response error flag (bool). r |
| (58, 13) | heater_shoreline_connected (EHG: shoreline_connected) |
— | Shoreline connected flag (bool). r |
| (58, 14) | heater_diesel_safety (EHG: window_switch_closed) |
— | Diesel safety interlock flag (bool). True = safety OK / heater can run, False = interlock inactive. Not a physical window contact. r |
Vehicles: Eriba Car 602 (2025, VW Crafter). Not present on S600/S700 (which use Thetford on buses 34/37). Contributed by: @mvondemhagen (#54)
| Slot | Sensor Name | Unit | Transform | Notes |
|---|---|---|---|---|
| (60, 1) | dometic_fridge_mode |
— | — | User mode: "Silent Mode" / "Performance Cooling" / "Turbo Mode" (rw) |
| (60, 2) | dometic_fridge_level |
— | — | Cooling level 1–5 (rw) |
| (60, 8) | dometic_fridge_power |
— | — | Power on/off (rw, bool) |
| (60, 9) | dometic_fridge_power_source |
— | — | Power source: "DC12V power" (r) |
| (60, 10) | dometic_cibus_on |
— | — | CiBus communication active (r, bool) |
| (60, 11) | dometic_compressor_on |
— | — | Compressor running (r, bool) |
| (60, 12) | dometic_condenser_fan |
— | — | Condenser fan running (r, bool) |
| (60, 13) | dometic_fridge_type |
— | — | Compressor type: "Compressor" (r) |
| (60, 16) | dometic_fridge_warning |
— | — | Warning/error code 0–127 (r) |
| (60, 17) | dometic_fridge_ai_type |
— | — | AI type: "Refrigeration" (r) |
EHG app metadata defines 21 slots for bus 60 (
DometicCompressorFridge, kind:fridge). Slots 3–7, 14–15, 18–21 are unmapped (not yet observed in live data). Seedocs/ehg-app-metadata.mdfor the full slot definitions.
Bus 99 is the BOS LUX LiFePO4 BMS on both S600 and S700 — same slot layout. The old labels (AdBlue, engine torque, fuel range, gear) were incorrect; they were remnants of an earlier wrong sensor map. Corrected by @dan-simms1 in #37. Legacy code labels are noted below for historical reference only.
| Slot | Sensor Name | Unit | Notes |
|---|---|---|---|
| (99, 1) | bms_voltage |
V | BMS pack voltage. Legacy code label: adblue_temp |
| (99, 2) | bms_current |
A | BMS current, negative = discharging. Legacy code label: engine_torque |
| (99, 3) | bms_temperature |
°C | Pack cell temperature. Legacy code label: ambient_temp |
| (99, 4) | lithium_soc |
% | Battery SOC |
| (99, 5) | bms_time_remaining |
min | Estimated runtime. Legacy code label: fuel_range |
| (99, 6) | bms_state_of_health |
% | Battery SoH. Legacy code label: current_gear |
| (99, 7) | bms_capacity_remaining |
Ah | Remaining capacity. Legacy code label: total_fuel_used |
| (99, 8) | lithium_soc_2 |
% | Relative capacity |
| (99, 9) | bms_charge_detected |
— | Charge active flag. Legacy code label: cruise_control |
| (99, 10) | bms_device_failure |
— | BMS error flag. Legacy code label: dpf_status |
| Transform | Description |
|---|---|
div10 |
Divide raw value by 10 |
div100 |
Divide raw value by 100 |
div1000 |
Divide raw value by 1000 |
div3600 |
Convert seconds to hours |
invert100 |
100 - value (inverted percentage) |
The S600 reports current from three independent measurement points:
Solar Panel (19V)
│
▼
┌─────────────┐
│ Voltronic │ solar_current (bus 8) → raw panel output
│ MPPT 260CI │ e.g. 2.1 A @ 19.4V = 40.7W
└──────┬──────┘
│ MPPT converts to battery voltage
▼
┌─────────────┐
│ BOS LUX │ bms_current (bus 99) → net flow at battery
│ LiFePO4 BMS│ positive = charging, negative = discharging
│ 4×80Ah │ e.g. +1.54 A (net charge into cells)
└──────┬──────┘
│
▼
┌─────────────┐
│ CBE EBL402 │ battery_current (bus 3) → habitation load draw
│ Habitation │ negative = consuming power
│ Controller │ e.g. -0.37 A (SCU, fridge ECU, standby loads)
└─────────────┘
Key relationships:
- Solar current is measured at the panel side (higher voltage, lower current). After MPPT conversion the power stays the same but current increases at the lower battery voltage.
- BMS current is the net result: solar input minus habitation load. Positive means the battery is charging.
- Battery current (EBL) shows what the habitation system draws. This is always negative when loads are connected, even while solar is charging — it measures downstream of the battery, not the net flow.
A negative habitation current while BMS current is positive is normal — the solar more than compensates for the load.
These sensors are not read from a CAN bus slot. They are computed by the
coordinator from (1,1) odometer and (1,2) fuel_level plus the configured
diesel tank capacity (default: 93 L for Sprinter 419/519 CDI).
| Sensor | Unit | Description |
|---|---|---|
fuel_level_liters |
L | fuel_level_% × tank_capacity / 100 |
fuel_consumption |
L/100km | Trip-based: (fuel_used_L / distance_km) × 100 |
fuel_range_estimated |
km | fuel_liters / consumption_L100 × 100 |
Trip tracking logic:
- A reference point (odometer + fuel %) is stored on first reading
- Consumption is only computed after ≥ 5 km driven (noise filter)
- Refueling auto-detected when fuel level increases > 5% → trip resets
- Sanity bounds: only values between 2–60 L/100km are accepted
Tank capacity configuration: Settings → Integrations → HYMER Connect → Configure → "Diesel tank capacity" Range: 30–200 L. Common Sprinter values: 71 L (314/316 CDI), 93 L (419/519 CDI standard).
From EHG app metadata extraction (Dan, April 2026). SCU component 121 = VictronMultiplus. No data received on S600 — even with Victron physically switched ON and entities entities enabled. The Victron MultiPlus communicates via VE.Bus (RS-485), which is incompatible with the vehicle CAN bus. A Victron Cerbo GX cannot bridge this either — VE.Bus → VE.Can (250 kbps Victron-proprietary CAN) and VE.Bus → MQTT/Modbus are supported, but neither VE.Bus nor VE.Can can bridge to the vehicle CAN bus (different baud rates, protocols, and message structures).
The slot definitions exist in the EHG app metadata, suggesting EHG may have a proprietary SCU-to-Victron interface (dedicated serial/LIN connection) on certain vehicle configurations, or these are placeholder definitions that were never implemented. No data has been observed on this bus on the S600.
All entities disabled by default.
| Slot | Sensor Name | R/W | Type | Notes |
|---|---|---|---|---|
| (121, 1) | victron_inverter_on |
rw | bool | Inverter power on/off |
| (121, 2) | victron_inverter_state |
r | int | Inverter state code |
| (121, 3) | victron_inverter_l1_voltage |
r | V | Inverter L1 output voltage |
| (121, 4) | victron_inverter_l1_current |
r | A | Inverter L1 output current |
| (121, 5) | victron_inverter_l1_frequency |
r | Hz | Inverter L1 output frequency |
| (121, 6) | victron_inverter_l2_voltage |
r | V | Inverter L2 output voltage |
| (121, 7) | victron_inverter_l2_current |
r | A | Inverter L2 output current |
| (121, 8) | victron_inverter_l2_frequency |
r | Hz | Inverter L2 output frequency |
| (121, 9) | victron_charger_on |
rw | bool | Charger power on/off |
| (121, 10) | victron_charger_state |
r | — | Charger state |
| (121, 11) | victron_charge_voltage |
r | V | Charge output voltage |
| (121, 12) | victron_charge_current |
r | A | Charge output current |
| (121, 13) | victron_max_charge_current |
rw | A | Maximum charge current limit |
| (121, 14) | victron_input_current_limit |
rw | A | Shore power input current limit |
| (121, 15) | victron_input_voltage |
r | V | Shore power input voltage |
| (121, 16) | victron_input_current |
r | A | Shore power input current |
| (121, 17) | victron_input_frequency |
r | Hz | Shore power input frequency |
| (121, 18) | victron_device_failure |
r | — | Device failure status |
| (121, 19) | victron_firmware |
r | — | Firmware version string |