{
  "spec_version": 1,
  "slug": "keba-kecontact-p30",
  "manufacturer": "KEBA",
  "model": "KeContact P30 (c-series / x-series)",
  "category": "EV charger",
  "supplier_url": "https://www.keba.com/en/emobility/products/ac-charging-stations/p30/kecontact-p30-overview",
  "default_configuration": {
    "protocol": "modbus_tcp",
    "port": 502,
    "unit_id": 255,
    "addressing": "zero_based",
    "byte_order": "BigEndian",
    "word_order": "HighFirst"
  },
  "coils": [],
  "discrete_inputs": [],
  "input_registers": [],
  "holding_registers": [
    {
      "address": 1000,
      "count": 2,
      "name": "Charging state",
      "data_type": "UInt32",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "0 = start-up, 1 = not ready for charging, 2 = ready and waiting for the vehicle, 3 = charging, 4 = error, 5 = interrupted because of overtemperature or suspended mode."
    },
    {
      "address": 1004,
      "count": 2,
      "name": "Cable state",
      "data_type": "UInt32",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "0 = no cable, 1 = cable connected to the station only, 3 = connected and locked at the station, 5 = connected to station and vehicle, 7 = connected to station and vehicle and locked (charging)."
    },
    {
      "address": 1006,
      "count": 2,
      "name": "Error code",
      "data_type": "UInt32",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "0 = no error, other values are error codes: convert to hex, the leading group is the error group."
    },
    {
      "address": 1008,
      "count": 2,
      "name": "Charging current L1",
      "data_type": "UInt32",
      "units": "A",
      "scale_factor": 0.001,
      "offset": 0,
      "access": "R"
    },
    {
      "address": 1010,
      "count": 2,
      "name": "Charging current L2",
      "data_type": "UInt32",
      "units": "A",
      "scale_factor": 0.001,
      "offset": 0,
      "access": "R"
    },
    {
      "address": 1012,
      "count": 2,
      "name": "Charging current L3",
      "data_type": "UInt32",
      "units": "A",
      "scale_factor": 0.001,
      "offset": 0,
      "access": "R"
    },
    {
      "address": 1014,
      "count": 2,
      "name": "Serial number",
      "data_type": "UInt32",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R"
    },
    {
      "address": 1016,
      "count": 2,
      "name": "Product type and features",
      "data_type": "UInt32",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Packed type code: product, cable/socket, supported current (1 = 13 A, 2 = 16 A, 3 = 20 A, 4 = 32 A), device series (1 = c-series, 0 = x-series), energy meter class, RFID support."
    },
    {
      "address": 1018,
      "count": 2,
      "name": "Firmware version",
      "data_type": "UInt32",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Convert to hex, e.g. 0x30A0D00 = firmware 3.10.14. In P30 Modbus TCP version 1.11 this register is at 1013."
    },
    {
      "address": 1020,
      "count": 2,
      "name": "Active power",
      "data_type": "UInt32",
      "units": "W",
      "scale_factor": 0.001,
      "offset": 0,
      "access": "R"
    },
    {
      "address": 1036,
      "count": 2,
      "name": "Total energy",
      "data_type": "UInt32",
      "units": "Wh",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Persistent device lifetime energy meter."
    },
    {
      "address": 1040,
      "count": 2,
      "name": "Voltage L1",
      "data_type": "UInt32",
      "units": "V",
      "scale_factor": 1,
      "offset": 0,
      "access": "R"
    },
    {
      "address": 1042,
      "count": 2,
      "name": "Voltage L2",
      "data_type": "UInt32",
      "units": "V",
      "scale_factor": 1,
      "offset": 0,
      "access": "R"
    },
    {
      "address": 1044,
      "count": 2,
      "name": "Voltage L3",
      "data_type": "UInt32",
      "units": "V",
      "scale_factor": 1,
      "offset": 0,
      "access": "R"
    },
    {
      "address": 1046,
      "count": 2,
      "name": "Power factor",
      "data_type": "UInt32",
      "units": "%",
      "scale_factor": 0.1,
      "offset": 0,
      "access": "R",
      "description": "cos phi in 0.1 %: raw 928 = 92.8 %."
    },
    {
      "address": 1100,
      "count": 2,
      "name": "Max charging current",
      "data_type": "UInt32",
      "units": "A",
      "scale_factor": 0.001,
      "offset": 0,
      "access": "R",
      "description": "Maximum charging current currently configured on the station."
    },
    {
      "address": 1110,
      "count": 2,
      "name": "Max supported current",
      "data_type": "UInt32",
      "units": "A",
      "scale_factor": 0.001,
      "offset": 0,
      "access": "R",
      "description": "Minimum of DIP switch setting, cable coding and temperature monitoring. Socket variants report 6 A while no cable is plugged in."
    },
    {
      "address": 1500,
      "count": 2,
      "name": "RFID card",
      "data_type": "UInt32",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "First four bytes of the UID of the RFID card that authorised the session, as a decimal number; convert to hex for the UID."
    },
    {
      "address": 1502,
      "count": 2,
      "name": "Charged energy",
      "data_type": "UInt32",
      "units": "Wh",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Energy transferred in the current charging session."
    },
    {
      "address": 1550,
      "count": 2,
      "name": "Phase switching source",
      "data_type": "UInt32",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Communication channel currently allowed to switch contact x2."
    },
    {
      "address": 1552,
      "count": 2,
      "name": "Phase switching state",
      "data_type": "UInt32",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "1 = one phase, 3 = three phases."
    },
    {
      "address": 1600,
      "count": 2,
      "name": "Failsafe current setting",
      "data_type": "UInt32",
      "units": "A",
      "scale_factor": 0.001,
      "offset": 0,
      "access": "R",
      "description": "Failsafe current set by the last failsafe command (may differ from the persisted setting)."
    },
    {
      "address": 1602,
      "count": 2,
      "name": "Failsafe timeout setting",
      "data_type": "UInt32",
      "units": "s",
      "scale_factor": 1,
      "offset": 0,
      "access": "R"
    },
    {
      "address": 5004,
      "count": 1,
      "name": "Set charging current",
      "data_type": "UInt16",
      "units": "A",
      "scale_factor": 0.001,
      "offset": 0,
      "access": "W",
      "description": "Charging current setpoint, 6000-63000 mA; valid until the station reboots."
    },
    {
      "address": 5010,
      "count": 1,
      "name": "Set energy",
      "data_type": "UInt16",
      "units": "Wh",
      "scale_factor": 10,
      "offset": 0,
      "access": "W",
      "description": "Energy to transfer in the current or next session, in units of 10 Wh; the session ends when the value is reached."
    },
    {
      "address": 5012,
      "count": 1,
      "name": "Unlock plug",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "W",
      "description": "Write 0 to unlock the plug; only possible while the station is in suspended state."
    },
    {
      "address": 5014,
      "count": 1,
      "name": "Enable / disable charging station",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "W",
      "description": "0 = disable charging station, 1 = enable charging station. An active session is stopped."
    },
    {
      "address": 5016,
      "count": 1,
      "name": "Failsafe current",
      "data_type": "UInt16",
      "units": "A",
      "scale_factor": 0.001,
      "offset": 0,
      "access": "W",
      "description": "0 deactivates charging on communication loss, 6000-32000 sets the failsafe current in mA."
    },
    {
      "address": 5018,
      "count": 1,
      "name": "Failsafe timeout",
      "data_type": "UInt16",
      "units": "s",
      "scale_factor": 1,
      "offset": 0,
      "access": "W",
      "description": "Activates the failsafe: 0 deactivates it (charging continues at the highest possible value), 10-600 sets the timeout in seconds."
    },
    {
      "address": 5020,
      "count": 1,
      "name": "Failsafe persist",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "W",
      "description": "Write 1 to persist the current failsafe settings to the PDC."
    },
    {
      "address": 5050,
      "count": 1,
      "name": "Set phase switch toggle",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "W",
      "description": "Communication channel allowed to switch contact x2: 0 = none, 1 = OCPP, 2 = REST API, 3 = Modbus, 4 = UDP."
    },
    {
      "address": 5052,
      "count": 1,
      "name": "Trigger phase switch",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "W",
      "description": "0 = one phase (default state), 1 = three phases."
    }
  ],
  "combined_registers": [],
  "notes": "Source: KEBA, \"KeContact P30 Charging Station - Modbus TCP Programmers Guide\", V1.04 (2022). The station is the Modbus TCP server on port 502 with unit ID 255, and only the holding-register area is used, with function codes 03 (read) and 06 (write). All readable values are UINT32 and therefore occupy two registers; the guide states that a single register cannot be read on its own, so the maximum read length per request is two words -- read each two-register value as one request. Register numbering starts at 0; some third-party tools need +1. The guide's failsafe section shows index 5016 three times (for 5016, 5018 and 5020); the register names and the description order imply 5016 = failsafe current, 5018 = failsafe timeout, 5020 = failsafe persist, which is also what the evcc KEBA implementation writes. Phase switching additionally needs the KeContact S10 phase switch and register 5050 set to 3."
}
