{
  "spec_version": 1,
  "slug": "franklinwh-agate",
  "manufacturer": "FranklinWH",
  "model": "aPower battery with aGate (SunSpec DER)",
  "category": "Home battery",
  "supplier_url": "https://www.franklinwh.com/",
  "default_configuration": {
    "protocol": "modbus_tcp",
    "port": 502,
    "unit_id": 1,
    "addressing": "zero_based",
    "byte_order": "BigEndian",
    "word_order": "HighFirst"
  },
  "coils": [],
  "discrete_inputs": [],
  "input_registers": [],
  "holding_registers": [
    {
      "address": 0,
      "count": 2,
      "name": "SunSpec identifier (\"SunS\")",
      "data_type": "UInt32",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "0x53756E53. The aGate serves its SunSpec model chain from PDU 0; the M1 header at 2 and the M701 header at 70 only line up when the marker is read here."
    },
    {
      "address": 2,
      "count": 1,
      "name": "SunSpec model ID (common)",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "1 = common model."
    },
    {
      "address": 3,
      "count": 1,
      "name": "SunSpec common model length",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "66 registers follow."
    },
    {
      "address": 4,
      "count": 16,
      "name": "Manufacturer",
      "data_type": "Ascii",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "\"FranklinWH\" on firmware V12R02B60D00 and later, \"FranklinWH Technologies Co., Ltd\" before."
    },
    {
      "address": 20,
      "count": 16,
      "name": "Model",
      "data_type": "Ascii",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "e.g. \"aGate X\"."
    },
    {
      "address": 36,
      "count": 8,
      "name": "Options",
      "data_type": "Ascii",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R"
    },
    {
      "address": 44,
      "count": 8,
      "name": "Firmware version",
      "data_type": "Ascii",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Model 1 Vr, e.g. \"V12R02B60D00\"."
    },
    {
      "address": 52,
      "count": 16,
      "name": "Serial number",
      "data_type": "Ascii",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R"
    },
    {
      "address": 68,
      "count": 1,
      "name": "Modbus device address (DA)",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "RW",
      "description": "1 on the reference unit; the aGate answers on unit ID 1 and 2 alike."
    },
    {
      "address": 70,
      "count": 1,
      "name": "SunSpec model ID (DER measurement AC)",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "701."
    },
    {
      "address": 71,
      "count": 1,
      "name": "SunSpec model 701 length",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "153 registers follow."
    },
    {
      "address": 74,
      "count": 1,
      "name": "Inverter operating state (InvSt)",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "0 = off, 1 = sleeping, 2 = starting, 3 = running, 4 = throttled, 5 = shutting down, 6 = fault, 7 = standby (the values SunSpec model 701 defines)."
    },
    {
      "address": 75,
      "count": 1,
      "name": "Connection state (ConnSt)",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "0 = disconnected, 1 = connected (the values SunSpec model 701 defines)."
    },
    {
      "address": 78,
      "count": 2,
      "name": "DER operating mode (DERMode)",
      "data_type": "UInt32",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Bitfield: bit 0 = grid following, bit 1 = grid forming, bit 2 = PV clipped."
    },
    {
      "address": 80,
      "count": 1,
      "name": "AC active power at the point of connection (W)",
      "data_type": "Int16",
      "units": "W",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "SunSpec M701 W: the power the aGate exchanges with the grid. Scale comes from W_SF (186); 0 on the reference unit, so the raw value is watts."
    },
    {
      "address": 86,
      "count": 1,
      "name": "AC line-to-neutral voltage (LNV)",
      "data_type": "UInt16",
      "units": "V",
      "scale_factor": 0.1,
      "offset": 0,
      "access": "R",
      "description": "Scale from V_SF (184), which reads -1 on the reference unit."
    },
    {
      "address": 87,
      "count": 2,
      "name": "AC frequency (Hz)",
      "data_type": "UInt32",
      "units": "Hz",
      "scale_factor": 0.001,
      "offset": 0,
      "access": "R",
      "description": "Scale from Hz_SF (185), which reads -3 on the reference unit."
    },
    {
      "address": 184,
      "count": 1,
      "name": "AC voltage scale factor (V_SF)",
      "data_type": "Int16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Multiply the raw voltage by 10^this. -1 on the reference unit."
    },
    {
      "address": 185,
      "count": 1,
      "name": "Frequency scale factor (Hz_SF)",
      "data_type": "Int16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Multiply the raw frequency by 10^this. -3 on the reference unit."
    },
    {
      "address": 186,
      "count": 1,
      "name": "AC active power scale factor (W_SF)",
      "data_type": "Int16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Multiply the raw power by 10^this. 0 on the reference unit."
    },
    {
      "address": 225,
      "count": 1,
      "name": "SunSpec model ID (DER capacity)",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "702."
    },
    {
      "address": 226,
      "count": 1,
      "name": "SunSpec model 702 length",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "50 registers follow."
    },
    {
      "address": 227,
      "count": 1,
      "name": "Maximum rated active power (WMaxRtg)",
      "data_type": "UInt16",
      "units": "W",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Reads 0 on the reference aGate; the charge and discharge ratings below carry the real figures."
    },
    {
      "address": 235,
      "count": 1,
      "name": "Maximum charge rate (WChaRteMaxRtg)",
      "data_type": "UInt16",
      "units": "W",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "5000 W with one aPower battery on the reference site. Scale from W_SF (270)."
    },
    {
      "address": 236,
      "count": 1,
      "name": "Maximum discharge rate (WDisChaRteMaxRtg)",
      "data_type": "UInt16",
      "units": "W",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "5000 W with one aPower battery on the reference site. Scale from W_SF (270)."
    },
    {
      "address": 270,
      "count": 1,
      "name": "Capacity active power scale factor (W_SF)",
      "data_type": "Int16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Multiply the raw capacity values by 10^this. 0 on the reference unit."
    },
    {
      "address": 1033,
      "count": 1,
      "name": "SunSpec model ID (DER storage capacity)",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "713."
    },
    {
      "address": 1034,
      "count": 1,
      "name": "SunSpec model 713 length",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "7 registers follow."
    },
    {
      "address": 1035,
      "count": 1,
      "name": "Storage energy rating (WHRtg)",
      "data_type": "UInt16",
      "units": "Wh",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "13600 Wh on the reference site. Scale from WH_SF (1040)."
    },
    {
      "address": 1036,
      "count": 1,
      "name": "Storage energy available (WHAvail)",
      "data_type": "UInt16",
      "units": "Wh",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "SunSpec defines it as WHRtg * SoC * SoH. Scale from WH_SF (1040)."
    },
    {
      "address": 1037,
      "count": 1,
      "name": "Battery state of charge (SoC)",
      "data_type": "UInt16",
      "units": "%",
      "scale_factor": 0.1,
      "offset": 0,
      "access": "R",
      "description": "Scale from Pct_SF (1041), which reads -1 on the reference unit."
    },
    {
      "address": 1038,
      "count": 1,
      "name": "Battery state of health (SoH)",
      "data_type": "UInt16",
      "units": "%",
      "scale_factor": 0.1,
      "offset": 0,
      "access": "R",
      "description": "Scale from Pct_SF (1041)."
    },
    {
      "address": 1039,
      "count": 1,
      "name": "Storage status (Sta)",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "SunSpec storage status, not a charge/discharge state: 0 = OK, 1 = warning, 2 = error."
    },
    {
      "address": 1040,
      "count": 1,
      "name": "Energy scale factor (WH_SF)",
      "data_type": "Int16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Multiply the raw energy values by 10^this. 0 on the reference unit."
    },
    {
      "address": 1041,
      "count": 1,
      "name": "Percentage scale factor (Pct_SF)",
      "data_type": "Int16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Multiply the raw percentage values by 10^this. -1 on the reference unit."
    },
    {
      "address": 1042,
      "count": 1,
      "name": "SunSpec model ID (DER measurement DC)",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "714."
    },
    {
      "address": 1043,
      "count": 1,
      "name": "SunSpec model 714 length",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "43 registers follow."
    },
    {
      "address": 1044,
      "count": 2,
      "name": "DC port alarms (PrtAlrms)",
      "data_type": "UInt32",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Bitfield of the SunSpec DC port alarm flags."
    },
    {
      "address": 1046,
      "count": 1,
      "name": "Number of DC ports (NPrt)",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R"
    },
    {
      "address": 1048,
      "count": 1,
      "name": "Battery DC power (DCW)",
      "data_type": "Int16",
      "units": "W",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Positive while discharging, negative while charging (-100 W was a charging battery on the reference site). Scale from DCW_SF (1059), 0 there."
    },
    {
      "address": 1059,
      "count": 1,
      "name": "DC power scale factor (DCW_SF)",
      "data_type": "Int16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Multiply the raw DC power by 10^this. 0 on the reference unit."
    },
    {
      "address": 1087,
      "count": 1,
      "name": "SunSpec model ID (DER control)",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "715."
    },
    {
      "address": 1088,
      "count": 1,
      "name": "SunSpec model 715 length",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "7 registers follow."
    },
    {
      "address": 1089,
      "count": 1,
      "name": "Local / remote control (LocRemCtl)",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "1 = local control on the reference unit; the aGate must be in remote control before a client can dispatch the battery through model 704."
    },
    {
      "address": 1096,
      "count": 1,
      "name": "SunSpec model ID (solar module)",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "502."
    },
    {
      "address": 1097,
      "count": 1,
      "name": "SunSpec model 502 length",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "28 registers follow."
    },
    {
      "address": 1100,
      "count": 1,
      "name": "PV DC power scale factor (W_SF)",
      "data_type": "Int16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Multiply the raw PV power values by 10^this. 0 on the reference unit."
    },
    {
      "address": 1101,
      "count": 1,
      "name": "PV energy scale factor (Wh_SF)",
      "data_type": "Int16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Multiply the raw PV energy by 10^this. 0 on the reference unit."
    },
    {
      "address": 1117,
      "count": 2,
      "name": "PV lifetime energy (OutWh)",
      "data_type": "UInt32",
      "units": "Wh",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Scale from Wh_SF (1101). Matches the vendor extension register 15510."
    },
    {
      "address": 1119,
      "count": 1,
      "name": "PV output power (OutPw)",
      "data_type": "Int16",
      "units": "W",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Total PV output the aGate reports. Scale from W_SF (1100)."
    },
    {
      "address": 15502,
      "count": 1,
      "name": "Total PV power (FranklinWH extension)",
      "data_type": "UInt16",
      "units": "W",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "FranklinWH extension register outside the SunSpec chain: all PV sources combined."
    },
    {
      "address": 15506,
      "count": 1,
      "name": "Home load, quantised (FranklinWH extension)",
      "data_type": "UInt16",
      "units": "W",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "FranklinWH extension register: house consumption in steps of about 100 W. Use 16000 for the fine value."
    },
    {
      "address": 15507,
      "count": 1,
      "name": "Operating mode (FranklinWH extension)",
      "data_type": "UInt16",
      "units": "",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "1 = emergency backup, 2 = self-consumption, 3 = time-of-use. Those three are measured; no other value has been observed. Writes are not documented and did not take effect on the reference firmware."
    },
    {
      "address": 15508,
      "count": 1,
      "name": "Self-consumption reserve (FranklinWH extension)",
      "data_type": "UInt16",
      "units": "%",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "SoC reserve used in self-consumption mode."
    },
    {
      "address": 15509,
      "count": 1,
      "name": "Time-of-use reserve (FranklinWH extension)",
      "data_type": "UInt16",
      "units": "%",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "SoC reserve used in time-of-use mode. Firmware V10R01B04D00 repeated 15508 here; V12R02B60D00 reports the TOU reserve."
    },
    {
      "address": 15510,
      "count": 2,
      "name": "PV lifetime energy (FranklinWH extension)",
      "data_type": "UInt32",
      "units": "Wh",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "FranklinWH extension copy of the solar module lifetime energy (M502 OutWh)."
    },
    {
      "address": 16000,
      "count": 1,
      "name": "Home load, high resolution (FranklinWH extension)",
      "data_type": "UInt16",
      "units": "W",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Undocumented FranklinWH register, measured: house consumption in about 1 W steps."
    },
    {
      "address": 16001,
      "count": 1,
      "name": "Reserve of the active mode (FranklinWH extension)",
      "data_type": "UInt16",
      "units": "%",
      "scale_factor": 1,
      "offset": 0,
      "access": "R",
      "description": "Undocumented FranklinWH register, measured on V12R02B60D00: 100 in emergency backup, 15508's value in self-consumption, 15509's in time-of-use."
    }
  ],
  "combined_registers": [],
  "notes": "FranklinWH aPower batteries are read through the aGate gateway's Modbus TCP server (port 502; the aGate ignores the unit identifier - every UID tried (1, 2, 3, 126, 247) returned the same 17 models - so the unit_id of 1 in this file is arbitrary (the community project's default is 2); DA = 1). FranklinWH publishes no register map, so this file follows the SunSpec 700-series (IEEE 1547) model definitions (github.com/sunspec/models, models 1, 502, 701, 702, 713, 714, 715) with the absolute PDU addresses and scale-factor values recorded in the community project david2069/franklinwh-modbus (docs v0.10.1, snapshot of firmware V12R02B60D00, 2026-10-20). Addresses are 0-based PDU addresses: SunS at 0-1, model headers at 2 (M1), 70 (M701), 225 (M702), 1033 (M713), 1042 (M714), 1087 (M715), 1096 (M502), each block starting two registers after its header; the guide's 4xxxx numbers are the same PDU + 40000, and the firmware also mirrors the chain at 40000. SunSpec scale factors are themselves registers (184 V_SF, 185 Hz_SF, 186 W_SF, 270 and 1100 W_SF, 1040 WH_SF, 1041 Pct_SF, 1059 DCW_SF); the fixed factors here are the values those registers held on the reference unit, so re-read them if numbers look wrong. Omitted on purpose: the 64-bit accumulators (M701 TotWhInj/TotWhAbs, M714 DCWhInj/DCWhAbs) because the app has no 64-bit integer type (extension 15510 carries the PV total in 32 bits); M714 DCA because the aGate leaves it at 0; and the model 704 dispatch registers (WSetEna at PDU 318, WSetMod 319, WSet 320) because the write path is only partly understood and the charge/discharge sign convention differs between the vendor's app and the hardware. FranklinWH extension registers 15500-16002 are vendor-specific and undocumented; their meanings were measured on real hardware, writes did not take effect, and they can change with firmware. Only one Modbus client can poll an aGate at a time."
}
