{
  "spec_version": 1,
  "slug": "enapter-dry41-hydrogen-dryer",
  "manufacturer": "Enapter",
  "model": "Dryer 4.1 (DRY 4.1)",
  "category": "Hydrogen dryer",
  "supplier_url": "https://devices.enapter.com/electrolyser/dry41/dry41_firmware/4.0.0/modbus_tcp_communication_interface.html",
  "default_configuration": {
    "protocol": "modbus_tcp",
    "port": 502,
    "unit_id": 1,
    "addressing": "zero_based",
    "byte_order": "BigEndian",
    "word_order": "HighFirst"
  },
  "coils": [],
  "discrete_inputs": [],
  "input_registers": [
    {
      "address": 2,
      "count": 1,
      "name": "Device version, upper",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Firmware version major."
    },
    {
      "address": 3,
      "count": 1,
      "name": "Device version, patch",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Firmware version patch."
    },
    {
      "address": 4,
      "count": 2,
      "name": "Device version, build",
      "data_type": "UInt32",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Firmware build ID."
    },
    {
      "address": 1000,
      "count": 1,
      "name": "State",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Current dryer state."
    },
    {
      "address": 1001,
      "count": 1,
      "name": "Saved state",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Saved dryer state."
    },
    {
      "address": 1002,
      "count": 1,
      "name": "State flags",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "State flags as a bit field."
    },
    {
      "address": 1003,
      "count": 2,
      "name": "Drying start",
      "data_type": "UInt32",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Drying cycle start time."
    },
    {
      "address": 1005,
      "count": 2,
      "name": "Drying saved",
      "data_type": "UInt32",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Saved drying time."
    },
    {
      "address": 1007,
      "count": 2,
      "name": "Drying passed",
      "data_type": "UInt32",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Time passed in the current drying cycle."
    },
    {
      "address": 1009,
      "count": 2,
      "name": "Drying interval",
      "data_type": "UInt32",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Drying cycle interval."
    },
    {
      "address": 1011,
      "count": 1,
      "name": "Error",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Error flags as a bit field."
    },
    {
      "address": 1012,
      "count": 1,
      "name": "Warning",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Warning flags as a bit field."
    },
    {
      "address": 1013,
      "count": 1,
      "name": "Error, extra",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Extended error flags as a bit field."
    },
    {
      "address": 1014,
      "count": 1,
      "name": "Warning, extra",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Extended warning flags as a bit field."
    },
    {
      "address": 1015,
      "count": 2,
      "name": "Current heap size",
      "data_type": "UInt32",
      "units": "B",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Current heap memory size in bytes."
    },
    {
      "address": 1017,
      "count": 2,
      "name": "Minimum heap size",
      "data_type": "UInt32",
      "units": "B",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Minimum heap memory size in bytes."
    },
    {
      "address": 1055,
      "count": 1,
      "name": "Digital inputs",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Digital inputs as a bit field."
    },
    {
      "address": 1056,
      "count": 1,
      "name": "Digital outputs",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Digital outputs as a bit field."
    },
    {
      "address": 1057,
      "count": 1,
      "name": "Fan F100 speed",
      "data_type": "UInt16",
      "units": "rpm",
      "scale_factor": 1,
      "offset": 0,
      "access": "R"
    },
    {
      "address": 1058,
      "count": 1,
      "name": "Fan F101 speed",
      "data_type": "UInt16",
      "units": "rpm",
      "scale_factor": 1,
      "offset": 0,
      "access": "R"
    },
    {
      "address": 1059,
      "count": 1,
      "name": "Fan F102 speed",
      "data_type": "UInt16",
      "units": "rpm",
      "scale_factor": 1,
      "offset": 0,
      "access": "R"
    },
    {
      "address": 1060,
      "count": 2,
      "name": "Temperature TT00",
      "data_type": "Float32",
      "units": "°C",
      "scale_factor": 1,
      "offset": 0,
      "access": "R"
    },
    {
      "address": 1062,
      "count": 2,
      "name": "Temperature TT01",
      "data_type": "Float32",
      "units": "°C",
      "scale_factor": 1,
      "offset": 0,
      "access": "R"
    },
    {
      "address": 1064,
      "count": 2,
      "name": "Input pressure PT00",
      "data_type": "Float32",
      "units": "bar",
      "scale_factor": 1,
      "offset": 0,
      "access": "R"
    },
    {
      "address": 1066,
      "count": 2,
      "name": "Output pressure PT01",
      "data_type": "Float32",
      "units": "bar",
      "scale_factor": 1,
      "offset": 0,
      "access": "R"
    }
  ],
  "holding_registers": [
    {
      "address": 1000,
      "count": 1,
      "name": "Start command",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "RW",
      "description": "Start dryer operation (boolean: 1 = start)."
    },
    {
      "address": 1001,
      "count": 1,
      "name": "Stop command",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "RW",
      "description": "Stop dryer operation (boolean: 1 = stop)."
    },
    {
      "address": 1002,
      "count": 1,
      "name": "Save data command",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "RW",
      "description": "Save the current data to persistent storage."
    },
    {
      "address": 1003,
      "count": 1,
      "name": "Reboot command",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "RW",
      "description": "Reboot the dryer system."
    },
    {
      "address": 1004,
      "count": 1,
      "name": "Locate device on command",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "RW",
      "description": "Enable locate mode (LEDs blinking)."
    },
    {
      "address": 1005,
      "count": 1,
      "name": "Locate device off command",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "RW",
      "description": "Disable locate mode."
    },
    {
      "address": 1006,
      "count": 1,
      "name": "Reboot UCM command",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "RW",
      "description": "Reboot the UCM module."
    },
    {
      "address": 4000,
      "count": 1,
      "name": "Configuration begin",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "RW",
      "description": "Start a configuration transaction."
    },
    {
      "address": 4001,
      "count": 1,
      "name": "Configuration commit",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "RW",
      "description": "Commit the configuration changes."
    },
    {
      "address": 4002,
      "count": 1,
      "name": "Configuration result",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "RW",
      "description": "0 = idle, 1 = success, 2 = failed."
    },
    {
      "address": 4003,
      "count": 2,
      "name": "Ethernet IP address",
      "data_type": "UInt32",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "RW",
      "description": "Ethernet IPv4 address; 0.0.0.0 (or 0) enables DHCP."
    },
    {
      "address": 4005,
      "count": 2,
      "name": "Ethernet IP netmask",
      "data_type": "UInt32",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "RW"
    },
    {
      "address": 4007,
      "count": 2,
      "name": "Ethernet IP gateway",
      "data_type": "UInt32",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "RW"
    },
    {
      "address": 4009,
      "count": 2,
      "name": "Pressure output minimum threshold",
      "data_type": "Float32",
      "units": "bar",
      "scale_factor": 1,
      "offset": 0,
      "access": "RW",
      "description": "Minimum output pressure threshold."
    },
    {
      "address": 4011,
      "count": 2,
      "name": "Pressure output maximum threshold",
      "data_type": "Float32",
      "units": "bar",
      "scale_factor": 1,
      "offset": 0,
      "access": "RW",
      "description": "Maximum output pressure threshold."
    }
  ],
  "combined_registers": [],
  "notes": "Register map of the Enapter Dryer 4.1 as published for firmware 4.0.0; Enapter versions this document per firmware release. The vendor states port 502 and, for the slave address, only that 'any Modbus address can be set, does not affect communication', so unit 1 is a placeholder, not a documented factory value. Addresses are the document's own register numbers. Unlike the EL 2.1 and EL 4.1 pages, this page carries no 'Modbus Data Model' paragraph defining its numbers as protocol addresses, but it uses the same Enapter numbering (holding register 0, input registers from 2), so the numbers are used unchanged as zero-based wire addresses; check one read against a known value before trusting the offset. Data is big-endian, high word first, and boolean fields are 16-bit registers where 0 is false. Configuration registers are written as a transaction: open with 4000, write, commit with 4001, then read the result at 4002. Left out because the format has no 64-bit type: holding 0 (system time), input 1019, 1023, 1027, 1031, 1035, 1039, 1043, 1047 and 1051 (state save count, reboot count, lifetime and the six start/stop timestamps). Source: Enapter device handbook, 'DRY 4.1 FW 4.0.0 Modbus TCP Communication Interface'."
}
