Official IAMMETER documentation
IAMMETER devices support Modbus/TCP. This simulator provides the shared legacy registers and the read-only SunSpec 203 map described below. Consult the official guides for real-device model compatibility.
Goal and tools
Read phase A with a Modbus client or the Python standard-library example below. No Python packages are required.
Use a hostname and TCP port, not an HTTPS URL or a model path. The configured endpoint is shown below.
Modbus endpoint
simulator.iammeter.com:502Connection settings
- Connect to the endpoint above. Read 10 registers starting at address 0.
- Decode voltage, current, signed active power and energy using the table below.
- Repeat after several seconds: energy grows while the corresponding power direction is active. Reads do not drive the simulation clock.
| Setting | Value |
|---|---|
| Host | simulator.iammeter.com |
| TCP port | 502 |
| Function code | 03 or 04 |
| Unit ID | Any value, echoed unchanged |
| Start address | 0 |
| Register count | 10 |
Decode phase A
| Address | Type | Conversion |
|---|---|---|
| 0 | uint16 | ÷100 V |
| 1 | uint16 | ÷100 A |
| 2–3 | int32 | W |
| 4–5 | uint32 | ÷800 kWh (import) |
| 6–7 | uint32 | ÷800 kWh (export) |
| 8 | int16 | ÷1000 PF |
Python 3 example
import socket, struct
HOST, PORT = "simulator.iammeter.com", 502
def receive_exact(sock, size):
data = bytearray()
while len(data) < size:
chunk = sock.recv(size - len(data))
if not chunk:
raise ConnectionError("Connection closed")
data.extend(chunk)
return bytes(data)
# Transaction=1, protocol=0, length=6, Unit ID=1; FC03, address=0, count=10.
request = struct.pack(">HHHBBHH", 1, 0, 6, 1, 3, 0, 10)
with socket.create_connection((HOST, PORT), timeout=5) as sock:
sock.sendall(request)
transaction, protocol, length, unit = struct.unpack(">HHHB", receive_exact(sock, 7))
if transaction != 1 or protocol != 0 or unit != 1 or not 2 <= length <= 254:
raise ValueError("Invalid Modbus header")
pdu = receive_exact(sock, length - 1)
if pdu[:2] != bytes([3, 20]) or len(pdu) != 22:
raise ValueError("Unexpected response: " + pdu.hex())
raw = pdu[2:]
print("Voltage V:", struct.unpack_from(">H", raw, 0)[0] / 100)
print("Current A:", struct.unpack_from(">H", raw, 2)[0] / 100)
print("Active W:", struct.unpack_from(">i", raw, 4)[0])
print("Import kWh:", struct.unpack_from(">I", raw, 8)[0] / 800)
print("Export kWh:", struct.unpack_from(">I", raw, 12)[0] / 800)
print("PF:", struct.unpack_from(">H", raw, 16)[0] / 1000)Expected results
The default Inverter and grid source returns A generation, B signed grid power and zero-valued C. B and C start at addresses 10 and 20. All 32-bit values use the high word first, with big-endian bytes.
All models use the shared three-phase register map: active energy ÷800 kWh and reactive energy ÷1000 kvarh. Do not apply the physical single-phase ÷3200 scaling.
Browser source selection and Reactive/NEM settings do not change this shared service. It supports reads only.
SunSpec 203: read-only three-phase meter
SunSpec uses the same TCP endpoint as the legacy registers. Use function 03 and zero-based protocol addresses. The simulator always identifies as WEM3050T, model 203, regardless of the selected web model or Unit ID.
Read the 107-register meter block at 40070 every poll. Decode values as integer × 10^SF, reading each value and its signed scale factor in the same response. Energy is in Wh; power factor is a percentage. Scales can change as values grow.
The shared endpoint exposes model 203 only. Firmware mappings 201 (WEM3080) and 202 (WEM2067) are not selected through browser pages or Unit IDs. Float models 211–214 are not provided. This implementation is not SunSpec-certified.
| Start address | Register count | Contents |
|---|---|---|
| 40000 | 2 | SunS: 0x5375, 0x6E53 |
| 40002 | 68 | Common model 1, length 66: IAMMETER / WEM3050T / simulator-1.0 / 1AD9B537 |
| 40070 | 107 | Integer meter model 203, length 105 |
| 40177 | 2 | End model 0xFFFF, length 0 |
Troubleshooting
Connection timeout: check the displayed port, firewall and TCP reachability. A working HTTPS page does not prove the Modbus port is reachable.
Unexpected values: check zero-based addressing, signed power, word order and scaling. Do not send Modbus RTU frames to this TCP endpoint.