Skip to main content

Modbus Explorer

The Modbus Explorer lets you browse a Modbus device's registers, write to coils and holding registers, watch live values, trend them over time, read communication diagnostics, run network tools, and map data points to GEM zones for monitoring and control. It works for both Modbus/TCP (over IP) and Modbus/RTU (over a serial port).

Open Modbus Explorer

Licensing

Modbus is a premium integration. Adding a modbus device — and opening this page — requires the Modbus product in your license. Core drivers are always included, and existing devices keep running if a license later changes. See License.

Prerequisites

Create a Modbus device in System > Devices with the driver set to modbus. Fill in either:

  • IP Address (required) and TCP Port (default 502) for Modbus/TCP, or
  • Serial Port (e.g. /dev/ttyUSB0) and Baud Rate for Modbus/RTU.

Set Unit ID to the slave address you want to target. The Modbus spec reserves the 1–247 range, but real TCP gear often parks itself higher — Brainboxes ED-series and many gateways default to 255 (0xFF), and 0 is broadcast. If you don't know the unit ID or the register layout, the Network Tools and Register Browser tabs can scan for it (the scan covers 1–255).

If no Modbus device exists yet, the page shows "No Modbus device found" and points you back to System > Devices to create one.

Disabled device

A disabled device has no loaded driver, so register reads/writes, unit-ID scans, and zone polling all fail. If you select a disabled device the page shows a Disabled badge in the toolbar and a warning with an Enable & Reload button — one click flips enabled on and reloads the driver in place, without a trip to System > Devices.

Toolbar

A toolbar runs across the top of every tab:

FieldDescription
Modbus DeviceChoose which Modbus device to work with. With a single Modbus device it is selected automatically; with several you pick one before the tabs appear.

Once a device is selected, the toolbar shows its connection summary — TCP <ip>:<port> or RTU <serial port>, and the configured unit ID. A red Disabled badge appears here when the selected device is disabled (see the warning under Prerequisites).

Tabs

The page has seven tabs: Register Browser, Watch List, Trending, Diagnostics, Zone Mapping, Network Tools, and Settings. The sections below follow that order.


Register Browser Tab

This is the main read/write surface. Pick a register type, set the address range, and read live values — then write to writable points, add points to the Watch List, or send a point to the Zone Mapping tab.

Register Type

Four buttons select the address space. The active button is highlighted:

ButtonModbus designationWritableDefault start
Coils (0x)CoilYes1
Discrete Inputs (1x)Discrete inputNo (read-only)10001
Holding Registers (4x)Holding registerYes40001
Input Registers (3x)Input registerNo (read-only)30001

Selecting a type resets the start address to that space's default.

Read Controls

FieldDescription
Start AddressFirst register/coil address to read. Accepts standard 5-digit or 6-digit Kohler-extended form (the driver converts automatically).
CountHow many to read — up to 125 for registers, up to 2000 for coils/discrete inputs.
Unit IDSlave address to read from (1–255; TCP gear often sits at 255). Seeded from the selected device's configured Unit ID (falls back to 1 when none is set); override per-read for multi-unit buses.
Data TypeOnly shown for registers (not coils/discrete inputs): UINT16, INT16, UINT32, INT32, FLOAT32, FLOAT64, String, or Bits.
Byte OrderOnly shown for registers: Big Endian (AB CD), Little Endian (CD AB), Mid-Big (BA DC), or Mid-Little (DC BA).

Click Read to fetch the range. The results table shows Address, Hex and Raw words (registers only), and the decoded Value.

Writing Values

  • Coils render as an on/off switch — flip it to write the coil immediately.
  • Holding registers show their value as a clickable link (or use the edit icon). Type a new number and press Enter or click save to write it.
  • Discrete inputs and input registers are read-only — they display ON/OFF or a value with no edit control.

Per-Row Actions

Each row carries action icons on the right:

  • Watch (eye icon) — adds the point to the Watch List tab.
  • Map (link icon) — sends the point (with its type, address, data type, and byte order) to the Zone Mapping tab and switches to it.

Discovery

The Discover button walks all four address spaces from address 0 and reports which addresses are actually mapped on the device. It is useful for sparsely-documented gear where the manual doesn't list a full register map.

  • Read-only — never writes to the device.
  • Walks one register at a time, then expands to 16-at-a-time chunked reads once it finds a contiguous block of 4 or more.
  • Bails out per address space after a run of consecutive gaps (default 32) — most small devices map a low band of addresses and nothing above.
  • Scan to sets the upper address bound (default 256). Raise it if you suspect mapped addresses higher up.
  • Bails out on transport errors (timeout, port closed, network unreachable) so a dead bus doesn't burn the whole probe budget.
  • Auto unit-ID fallback — if discovery finds nothing and every address space saw a transport error (the device never answered on the entered unit ID), the Discover button automatically hunts for a responding unit ID — the reserved 248–255 range first (TCP gateways default to 255), then 1–247 — and re-runs discovery against the unit that answers. The Unit ID field updates to that unit, and — if the device has no Unit ID configured — the discovered unit is saved to the device and the driver reloaded so future polling uses it automatically. If a Unit ID is already configured but the device answers on a different one, GEM leaves your value alone and shows an informational notice rather than overwriting a deliberate choice (change it manually in System > Devices if the discovered unit is the one you want). If instead the device answers every ID identically, you get a TCP-gateway "ignores unit_id — any id works" notice; if nothing answers on any ID, a warning tells you to check IP / port / wiring.

Results are grouped by space and show each contiguous block's Modicon and internal address range, count, and a few sample values. Each block carries a Load → button that drops the range into the read controls above and reads it immediately.


Watch List Tab

The Watch List polls a chosen set of points on a fixed interval so you can watch them change in real time. Add points from the Register Browser tab (the eye icon).

ControlDescription
Start Polling / StopBegins/ends repeated reads of all watched points. A green dot shows when polling is active.
RatePoll interval: 1s, 2s, 5s (default), 10s, or 30s.
Read AllReads every watched point once, immediately.
ClearRemoves all watched points and stops polling.

The table lists Label, Type, Address, Unit, Value, Delta (change since the previous poll), editable Scale and Offset columns, and the last-Updated time. Scale and offset are applied per row (value × scale + offset) so you can read engineering units directly. The close icon removes a single row.

note

The Watch List is a live diagnostic view — its points and scale/offset are not saved to the device. To persist a point for ongoing monitoring or control, map it to a zone on the Zone Mapping tab.


The Trending tab charts watched points over time. Select one or more items from the Watch List sidebar (checkboxes), then start collecting.

ControlDescription
Start / Stop TrendingBegins/ends sampling the selected points into the chart.
RateSample interval: 1s, 2s (default), 5s, or 10s.
TypeChart style: Line or Area.
MaxPoints kept per series before the oldest roll off: 100, 200 (default), or 500.
CSVDownloads the collected series as a timestamped CSV.
ClearDiscards the chart and statistics.

A statistics strip under the chart shows live min / max / avg / current for each trended series. Scale and offset set on the Watch List carry into the chart and CSV.


Diagnostics Tab

Surfaces the Modbus driver's runtime counters and a recent communication log. Use it to narrow down whether a problem is on the wire, in the device, or in GEM's value handling.

ControlDescription
LoadFetches the current counters and log.
Auto-RefreshReloads every 5 seconds until toggled off.
ClearResets the counters and log.

Summary Cards

  • Total Reads / Total Writes — operation counters since boot or last clear.
  • Read Errors / Write Errors — failed operations (turn red when non-zero).
  • Error Rate — errors as a percentage of all operations (amber above 5%, red above 20%).
  • Timeouts — operations that timed out (a subset of errors).
  • Conn Drops — how many times the underlying TCP/serial connection has closed.
  • Client Recycles — how many times the driver has torn down and rebuilt the Modbus client (the watchdog escalates here — see below).
  • Last Success — time since the most recent successful read/write.
  • Uptime — time since the counters were last reset.

A red Last Client Error panel appears below the cards when the underlying transport has emitted a connection-level error (distinct from a Modbus exception, which means the device answered).

Communication Log

The last 200 operations. Each row shows time, command, function code, address, unit, the value sent on the wire (so you can confirm exactly what was written), duration, status (OK/ERR), and any error. A Class:2-style error in the error column means the device returned a Modbus exception — an application-layer response, not a broken socket.

Watchdog Tuning

Two device attributes (edit them in System > Devices) tune when the driver recycles a wedged client. Both gates must trip together, so one unreachable unit on a multi-unit bus does not drop the connection for everyone else:

AttributeUI labelDefaultEffect
op_failure_thresholdWatchdog Failure Threshold5Consecutive operation failures before a recycle is considered. Raise it on long RS-485 segments where a few consecutive timeouts is normal.
op_staleness_msWatchdog Staleness (ms)120000How long without a successful operation before the threshold can trip a recycle. Lower it in latency-sensitive deployments to catch a wedged socket faster.

Value Coercion

Writes coerce stringified arguments at the driver boundary — for example, 'false' from a saved macro is normalized to false before it reaches the device. A garbage value (e.g. 'maybe' for a coil) returns an explicit error and does not send the write, so a typo can never silently energize a relay.


Zone Mapping Tab

This tab links a register to a zone attribute so GEM polls and controls it as part of that zone. The Map (link) icon in the Register Browser brings the selected register here automatically and shows it as a badge at the top.

The form reads top to bottom: pick the Subsystem and Zone the register belongs to, choose what it Maps to, then confirm the decode settings.

Mapping Fields

FieldDescription
① SubsystemThe subsystem that owns the target zone. Filters the Zone picker.
② ZoneThe target zone for this mapping. Use + New Zone (enabled once a subsystem is chosen) to create one inline without leaving the page — see Creating a zone inline.
③ Maps toWhat the register represents on the zone. A single grouped dropdown (Climate / Lighting / Shade / Power / Generic) lists the named functions — Setpoint, Temperature, Level / Brightness, Position, On / Off State, Power, etc. The Direction toggle next to it sets Read or Write; read-only functions (Temperature, Power, Energy, Voltage, Current) lock the toggle to Read. For anything outside the list, type a name in the custom field — it's normalized to lowercase-with-underscores. The grey preview shows the exact attribute that will be written (e.g. → modbus_setpoint_read).
Data TypeUINT16, INT16, UINT32, INT32, FLOAT32, FLOAT64, Bits, or String. Adopted automatically from the register you linked over from the browser.
Byte OrderBig Endian, Little Endian, Mid-Big, or Mid-Little. Also adopted from the linked register.
ScaleMultiplier applied to the decoded value. Defaults to 1.
OffsetAdded after scaling. Defaults to 0.
Poll Interval (ms)Optional per-mapping override of the device-wide poll rate. Leave blank to inherit.

The former Point Type field (a category-tab row plus a dropdown of read X / write X entries) is replaced by Maps to + the Direction toggle. The attribute names written are unchanged, so existing mappings are unaffected.

Creating a zone inline

If the zone doesn't exist yet, click + New Zone under the Zone picker (it activates once a subsystem is selected). Enter a name (lowercase letters, numbers, underscores) and an optional display label, then Create Zone. The new zone is created in the chosen subsystem, assigned to this Modbus device so polling picks it up immediately, and auto-selected in the picker.

Zone not assigned to this device

A zone is only polled by a Modbus device when the zone — or its subsystem — is assigned to that device. If you select a zone that isn't, an amber notice appears above the decode settings warning that this device won't poll it. Click Bind to <device> to assign the zone to the current device (a lightweight rebind that doesn't reconnect the device), or map it anyway if you intend to bind it later. Zones created with + New Zone are bound automatically.

Test Read

Click Test Read before saving to issue a one-shot read against the selected register using the chosen data type and byte order. The result panel shows:

  • Raw — the raw register words returned by the device.
  • Decoded — the value after data-type / byte-order interpretation (the label echoes the chosen data type and byte order).
  • Scaled — the value after scale and offset (shown only when scale ≠ 1 or offset ≠ 0).

Selecting a different register clears the result. Test reads never modify any attributes.

Map Point

Click Map Point to persist the mapping. The point's address is written to the zone as an attribute whose name is the chosen function plus direction (e.g. modbus_temperature_read) and whose value is the address with a type prefix:

PrefixRegister type
c_Coil
i_Discrete input
hr_Holding register
ir_Input register

So mapping holding register 40001 as a temperature read stores modbus_temperature_read = hr_40001 on the zone.

Any non-default decode settings are written as companion attributes named after the point's base (the attribute name with modbus_ and the trailing _read/_write stripped): modbus_<base>_data_type, modbus_<base>_byte_order, modbus_<base>_scale, modbus_<base>_offset, and modbus_<base>_poll_interval. They are only written when you change them from the default — e.g. mapping a Temperature read with FLOAT32 and a scale of 0.1 also writes modbus_temperature_data_type and modbus_temperature_scale.

Existing Mappings

Below the form, an Existing Mappings table lists every Modbus point already mapped across the system: Zone, Point (the function, human-readable), Address (the stored prefixed address), and Quality. Companion config rows (_data_type, _byte_order, _scale, _offset, _poll_interval) are not listed — only the point mappings themselves. The delete button removes the mapping by deleting the zone attribute.


Network Tools Tab

This tab consolidates network discovery, raw protocol access, and register-map import/export.

Unit ID Scanner

Finds Modbus slaves on the bus by sending a test read to a range of unit IDs.

FieldDefaultDescription
Start1First unit ID to scan.
End255Last unit ID to scan. The range allows 1–255: the spec reserves 1–247, but Brainboxes ED-series and many TCP gateways default to 255 (0xFF), so stopping at 247 would silently hide them. If a TCP device seems dead on ID 1, scan the top of the range — try Start 248, End 255 for a sub-second check.
Timeout250 msHow long to wait for each unit to respond. 250 ms is ample on a LAN (real replies land in ~1 ms); each non-responding ID costs one full timeout, so a 1–255 sweep takes a while. Raise it for slow or tunneled links.
Test Reg40001The register read on each unit to detect a response. Set it to an address the device actually maps.

Click Scan. The results table lists each responding Unit ID, its Status, and the Test Value read from the test register. Status is one of:

  • online — the unit returned data from the test register.
  • present — the unit replied with a Modbus exception rather than data. The device is there at that unit ID; the test register just isn't mapped on it (common on coil-only relay boards). The row shows exception <code> in place of a value. A present unit counts as a found device.
Device ignores unit_id

Many TCP-only Modbus devices (Brainboxes ED-series, Wago I/O, etc.) have no upstream RS-485 bus to route to, so they answer every unit ID with the same payload (or the same exception). When the scan sees 5 consecutive identical responses it aborts early and shows a single warning row — unit IDs are effectively meaningless on that device, so pick any.

Device Identification (FC43)

Sends FC 43 (Read Device Identification) to a chosen unit ID and returns the vendor name, product code, revision, and any extended object IDs the device exposes. If the device doesn't support FC 43, a notice is shown.

Raw FC Inspector

Sends a raw Modbus function code and shows the parsed response alongside a hex view. Useful for vendor-specific gear and function codes the higher-level browser doesn't wrap.

Function CodeInputs
1 — Read Coilsaddress, length
2 — Read Discrete Inputsaddress, length
3 — Read Holding Registersaddress, length
4 — Read Input Registersaddress, length
5 — Write Single Coiladdress, ON/OFF
6 — Write Single Registeraddress, integer
15 — Write Multiple Coilsaddress, comma-separated booleans
16 — Write Multiple Registersaddress, comma-separated integers
17 — Report Server ID
22 — Mask Write Registeraddress, AND mask, OR mask
43 — Read Device Identificationread code (1–4), object ID
65–72, 100–110 — User-Definedraw hex byte string (e.g. AA BB CC DD)

The dropdown lists FCs 1–6, 15–17, 22, and 43 (fully parsed), plus representative user-defined codes (65 and 100); any code in 65–72 or 100–110 may be entered and is returned as raw bytes. The response panel shows the raw bytes (hex) followed by the parsed body; errors render in a red panel.

warning

Function codes outside this set (e.g. FC 7, 8, 11) are not supported by the underlying library and return an explanatory error rather than hanging the connection.

Register Map Templates

Saves a JSON array of register definitions on the device. The map drives the Register Browser's column hints, default data types, and address labels.

ActionDescription
SaveValidates the textarea JSON and stores it on the device.
LoadReads the saved register map back from the device.
Export JSONDownloads the textarea as modbus_register_map_<device>.json.
Export CSVDownloads the textarea as a CSV using the standard column order.
Import CSVParses a CSV file (header row required) and replaces the textarea with equivalent JSON. Click Save afterwards to persist.

CSV columns (header names, lowercase): address, name, description, data_type, byte_order, scale, offset, writable.

The address column is required. writable accepts 1/true/yes/y (any case). scale, offset, and address are coerced to numbers when parseable. Empty cells are dropped from the row.


Settings Tab

A read-only summary of the selected device's connection, drawn from its device record:

FieldNotes
ID / Name / DriverDevice identity.
ConnectionTCP <ip>:<port> or RTU <serial port>.
Unit IDSlave address (default 1).
Baud RateSerial connections only (default 9600).
TimeoutPer-request timeout in ms (default 10000).
Polling RateHow often mapped zones are read, in ms (default 30000).

To change any of these, edit the device in System > Devices. An Addressing Format note confirms the driver accepts both standard 5-digit (40001–49999) and extended 6-digit Kohler (400001–409999) addresses and auto-detects which you used.


  • Devices — creating and configuring the Modbus device
  • Zones — zone configuration
  • License — enabling the Modbus product