{
  "spec_version": 1,
  "slug": "heidelberg-energy-control",
  "manufacturer": "Heidelberg (Amperfied)",
  "model": "Energy Control / Wallbox Energy Control",
  "category": "EV charger",
  "supplier_url": "https://www.amperfied.de/",
  "default_configuration": {
    "protocol": "modbus_tcp",
    "port": 502,
    "unit_id": 1,
    "addressing": "zero_based",
    "byte_order": "BigEndian",
    "word_order": "HighFirst",
    "native_interface": "rs485",
    "serial": {
      "parity": "Even",
      "baud_rate": 19200,
      "data_bits": 8,
      "stop_bits": 1
    }
  },
  "coils": [],
  "discrete_inputs": [],
  "input_registers": [
    {
      "address": 4,
      "count": 1,
      "name": "Modbus register layout version",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "0x100 = V1.0.0. Check this before trusting the layout."
    },
    {
      "address": 5,
      "count": 1,
      "name": "Charging state",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "2 = A1, 3 = A2, 4 = B1, 5 = B2, 6 = C1, 7 = C2 (reduced), 8 = derating, 9 = E, 10 = F, 11 = error. The table gives the range as 1-11 but names the states from value 2 upwards."
    },
    {
      "address": 6,
      "count": 1,
      "name": "Current L1",
      "data_type": "UInt16",
      "units": "A",
      "scale_factor": 0.1,
      "offset": 0,
      "access": "R"
    },
    {
      "address": 7,
      "count": 1,
      "name": "Current L2",
      "data_type": "UInt16",
      "units": "A",
      "scale_factor": 0.1,
      "offset": 0,
      "access": "R"
    },
    {
      "address": 8,
      "count": 1,
      "name": "Current L3",
      "data_type": "UInt16",
      "units": "A",
      "scale_factor": 0.1,
      "offset": 0,
      "access": "R"
    },
    {
      "address": 9,
      "count": 1,
      "name": "PCB temperature",
      "data_type": "Int16",
      "units": "°C",
      "scale_factor": 0.1,
      "offset": 0,
      "access": "R",
      "description": "Raw 325 = +32.5 °C, raw -145 = -14.5 °C."
    },
    {
      "address": 10,
      "count": 1,
      "name": "Voltage L1-N",
      "data_type": "UInt16",
      "units": "V",
      "scale_factor": 1,
      "offset": 0,
      "access": "R"
    },
    {
      "address": 11,
      "count": 1,
      "name": "Voltage L2-N",
      "data_type": "UInt16",
      "units": "V",
      "scale_factor": 1,
      "offset": 0,
      "access": "R"
    },
    {
      "address": 12,
      "count": 1,
      "name": "Voltage L3-N",
      "data_type": "UInt16",
      "units": "V",
      "scale_factor": 1,
      "offset": 0,
      "access": "R"
    },
    {
      "address": 13,
      "count": 1,
      "name": "External lock state",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "0 = locked, 1 = unlocked."
    },
    {
      "address": 14,
      "count": 1,
      "name": "Power (L1+L2+L3)",
      "data_type": "UInt16",
      "units": "VA",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Apparent power in VA, 1000 corresponds to 1 kVA."
    },
    {
      "address": 17,
      "count": 2,
      "name": "Energy since installation",
      "data_type": "UInt32",
      "units": "kVAh",
      "scale_factor": 0.001,
      "offset": 0,
      "access": "R",
      "description": "Lifetime counter in VAh (apparent energy), high word at 17, low word at 18; the register table's own label for row 17 still reads \"since PowerOn\", row 18 says \"since Installation\". evcc divides the raw value by 1000 and treats it as kWh."
    }
  ],
  "holding_registers": [
    {
      "address": 257,
      "count": 1,
      "name": "Modbus master watchdog timeout",
      "data_type": "UInt16",
      "units": "ms",
      "scale_factor": 1,
      "offset": 0,
      "access": "RW",
      "description": "Communication timeout in ms, e.g. 10000 = 10 s, 0 = off; factory default 15000. Readable and writable."
    },
    {
      "address": 258,
      "count": 1,
      "name": "Standby function control",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "RW",
      "description": "Power saving when no car is plugged in: 0 = enable standby, 4 = disable standby."
    },
    {
      "address": 259,
      "count": 1,
      "name": "Remote lock",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "RW",
      "description": "0 = locked, 1 = unlocked; only effective while the external lock is unlocked. Writing 0 forces the charging state to F, which is how evcc wakes the box up."
    },
    {
      "address": 261,
      "count": 1,
      "name": "Maximal current command",
      "data_type": "UInt16",
      "units": "A",
      "scale_factor": 0.1,
      "offset": 0,
      "access": "RW",
      "description": "Charging current limit, 0.0 A or 6.0 to 16.0 A (raw 60 to 160, 100 = 10 A). From firmware 1.0.8 this is the only holding register that falls back to its default after power on or standby."
    },
    {
      "address": 262,
      "count": 1,
      "name": "FailSafe current configuration",
      "data_type": "UInt16",
      "units": "A",
      "scale_factor": 0.1,
      "offset": 0,
      "access": "RW",
      "description": "Current limit applied when the Modbus communication is lost, 0.1 A per step (60 = 6 A)."
    }
  ],
  "combined_registers": [],
  "notes": "Source: Amperfied/Heidelberg, \"Table Modbus Register - Wallbox Energy Control\", status 22 February 2022 (EC_ModBus_register_table_20210222_LW.pdf, vendor-hosted at amperfied.de), for the register rows, scales and the 0.1 A/0.1 °C/0.1 kWh style raw units; the German vendor document \"ModBus-Anbindung\" (heidelberg-energy-control-modbus.pdf) for the interface itself: RS-485 two-wire half duplex, Modbus RTU, 19200 Bd, 8 data bits, 1 stop bit, even parity, unicast only, function codes 03, 04, 06 and 16. The unit is reached through a Modbus RTU-to-TCP gateway, so the serial block in this file is the factory setting the gateway has to use; the slave address is set with DIP switch S4 and evcc uses 1. Both register tables are read/write tables on holding registers and read-only tables on input registers, which is the split used here. Left out: the two \"Energy since PowerOn\" rows 15/16, because the table's own labels for 15-18 overlap (row 17 is headed \"since PowerOn\" while row 18 says \"since Installation\"), so only the 17/18 pair that evcc reads as lifetime energy is listed; and the manufacturer-reserved blocks (100-819) that the table marks as reserved or internal. The vendor warns that the internal meter values in this table should not be used for billing."
}
