Summary

The ControlByWeb XW-110 is a Wi-Fi networked I/O module with a built-in web server. This spec covers control and monitoring via HTTP GET requests against the device's XML/JSON state endpoints and via Modbus/TCP. The device exposes relays, digital inputs, analog inputs, 1-Wire sensors, registers, and counters through a uniform <tagX> naming scheme.

Transport

# Source documents two concrete command-bearing transports: HTTP GET (built-in web server)
# and Modbus/TCP (device acts as Modbus slave). Both ports are explicitly stated.
protocols:
  - http
  - tcp
addressing:
  port: 80       # default HTTP port; source: "If the TCP port has been changed (not port 80)"
  base_url: "http://{host}/state.xml"   # host = device IP (e.g. 192.168.1.2 in examples)
# Modbus/TCP connection port 502 (configurable under Advanced Network tab) - stated verbatim.
# auth notes:
auth:
  type: basic  # HTTP Basic (Base64 "user:password"). OPTIONAL - User account disabled by default.
  # When enabled, header:  Authorization: Basic <base64(user:password)>
  # Example from source: bm9uZTp3ZWJyZWxheQ== decodes to "none:webrelay".
  # Note: Modbus/TCP is DISABLED whenever the User account is enabled (Modbus has no auth mechanism).
# serial / RS-232C: NOT present in source - see UNRESOLVED notes above.

Traits

traits:
  - queryable   # inferred: state.xml/state.json query + Modbus read function codes present
  - levelable   # inferred: register/count/analog values settable via HTTP and Modbus write
# powerable: NOT supported - no power on/off command in source.
# routable: NOT supported - no input/output routing in source.

Actions

# =====================================================================
# HTTP / XML / JSON commands (web server, port 80)
# Literal request shape from source: GET /state.xml?<params> HTTP/1.1\r\n\r\n
# Parameters use the form <ioType><localNumber>=<value>. "X" in source = local I/O number.
# customState.xml/json use the CamelCase user-configured name instead of <ioType><num>.
# Multiple args may be combined: /state.xml?relay1=1&relay2=0
# =====================================================================

- id: relay_set
  label: Set Relay State
  kind: action
  command: "GET /state.xml?relay{relay}={state} HTTP/1.1\r\n\r\n"
  params:
    - name: relay
      type: integer
      description: Relay local I/O number (1, 2, 3, ...)
    - name: state
      type: enum
      values: ["0", "1", "2"]
      description: "0=OFF, 1=ON, 2=PULSE (preset duration from relay setup page)"

- id: relay_pulse_custom
  label: Pulse Relay Custom Duration
  kind: action
  command: "GET /state.json?pulseTime{relay}={seconds}&relay{relay}=2 HTTP/1.1\r\n\r\n"
  params:
    - name: relay
      type: integer
      description: Relay local I/O number
    - name: seconds
      type: number
      description: Pulse duration in seconds for this single pulse (does not change stored Pulse Duration)
  notes: "pulseTime argument MUST come before the relay=2 command (source)."

- id: set_on_time
  label: Set On Time
  kind: action
  command: "GET /state.xml?onTime{x}={value} HTTP/1.1\r\n\r\n"
  params:
    - name: x
      type: integer
      description: Input local I/O number
    - name: value
      type: number
      description: On-time value in seconds (0 resets)

- id: set_total_on_time
  label: Set Total On Time
  kind: action
  command: "GET /state.xml?totalOnTime{x}={value} HTTP/1.1\r\n\r\n"
  params:
    - name: x
      type: integer
      description: Input local I/O number
    - name: value
      type: number
      description: Total on-time value in seconds (0 resets)

- id: set_counter
  label: Set Counter
  kind: action
  command: "GET /state.json?count{x}={value} HTTP/1.1\r\n\r\n"
  params:
    - name: x
      type: integer
      description: Input local I/O number
    - name: value
      type: number
      description: Counter value to set (e.g. 200)

- id: set_register
  label: Set Register Value
  kind: action
  command: "GET /state.xml?register{x}={value} HTTP/1.1\r\n\r\n"
  params:
    - name: x
      type: integer
      description: Register local I/O number
    - name: value
      type: number
      description: Register value (e.g. 10.5, 25)

- id: query_state_xml
  label: Query Device State (XML)
  kind: query
  command: "GET /state.xml HTTP/1.1\r\n\r\n"
  params: []
  notes: Returns full I/O state as XML. Custom-name variant: /customState.xml

- id: query_state_json
  label: Query Device State (JSON)
  kind: query
  command: "GET /state.json HTTP/1.1\r\n\r\n"
  params: []
  notes: Returns full I/O state as JSON. Custom-name variant: /customState.json

- id: erase_data_log
  label: Erase Data Log
  kind: action
  command: "GET /log.txt?erase=1 HTTP/1.1\r\n\r\n"
  params: []
  notes: Erases log.txt. Requires user password if User account enabled.

- id: erase_syslog
  label: Erase System Log
  kind: action
  command: "GET /syslog.txt?erase=1 HTTP/1.1\r\n\r\n"
  params: []
  notes: Erases syslog.txt. Requires setup username/password.

# =====================================================================
# Modbus/TCP commands (slave, port 502)
# Device is a Modbus slave. Addresses come from the per-device Modbus map
# (Setup pages > Advanced Network > View Modbus Address Table). 32-bit values
# use IEEE-754 float across 16-bit register pairs (must read/write in pairs of 2).
# Endianness (little/big) configurable in Advanced Network tab.
# =====================================================================

- id: modbus_read_coils
  label: Modbus Read Coils
  kind: query
  command: "FC 0x01"
  params:
    - name: start_address
      type: integer
      description: Starting address (refer to device Modbus map)
    - name: quantity
      type: integer
      description: Number of coils to read
  notes: "Reads relays and digital I/O configured as outputs. 1=ON, 0=OFF. Error FC=0x81."

- id: modbus_read_discrete_inputs
  label: Modbus Read Discrete Inputs
  kind: query
  command: "FC 0x02"
  params:
    - name: start_address
      type: integer
      description: Starting address (refer to device Modbus map)
    - name: quantity
      type: integer
      description: Number of inputs to read
  notes: "Reads digital inputs and digital I/O configured as inputs. Error FC=0x82."

- id: modbus_read_holding_registers
  label: Modbus Read Holding Registers
  kind: query
  command: "FC 0x03"
  params:
    - name: start_address
      type: integer
      description: Starting address (refer to device Modbus map)
    - name: quantity
      type: integer
      description: Register count to read (must be divisible by 2)
  notes: "Reads Vin, sensors, registers, counters, analog inputs. 32-bit floats in pairs. NaN (0xFFFFFFFF) if sensor absent. Error FC=0x83."

- id: modbus_write_single_coil
  label: Modbus Write Single Coil
  kind: action
  command: "FC 0x05"
  params:
    - name: start_address
      type: integer
      description: Coil address (refer to device Modbus map)
    - name: output_value
      type: enum
      values: ["0x00", "0xFF"]
      description: "0x00=OFF, 0xFF=ON"
  notes: "Writes a single relay/digital output. Error FC=0x85 (0x01 unsupported, 0x02 out of range, 0x03 padding)."

- id: modbus_write_multiple_coils
  label: Modbus Write Multiple Coils
  kind: action
  command: "FC 0x0F"
  params:
    - name: start_address
      type: integer
      description: Starting coil address (2 bytes)
    - name: quantity
      type: integer
      description: Number of outputs (1 byte)
    - name: values
      type: integer
      description: "Bitmask 0x0000-0xFFFF (1=ON)"
  notes: "Writes multiple digital outputs/relays. Byte count = quantity/8. Error FC=0x8F (0x01 unsupported, 0x02 bad addr/qty, 0x03 byte count out of range)."

- id: modbus_write_multiple_registers
  label: Modbus Write Multiple Registers
  kind: action
  command: "FC 0x10"
  params:
    - name: start_address
      type: integer
      description: Starting register address (refer to device Modbus map)
    - name: quantity
      type: integer
      description: Register count to write (must be divisible by 2)
    - name: values
      type: number
      description: IEEE-754 32-bit float values (endianness per Modbus setup)
  notes: "Sets registers/analog outputs. ACK echoes register quantity written. Error FC=0x90 (0x01 unsupported, 0x02 addr qty not even)."

Feedbacks

# Observable state returned by state.xml/state.json and by Modbus read functions.
# "X" = local I/O number. All are queryable via query_state_xml / query_state_json.

- id: digital_input_state
  type: enum
  values: ["0", "1"]
  tag: digitalInputX
  description: "0=off (no voltage), 1=on (voltage applied)"

- id: relay_state
  type: enum
  values: ["0", "1"]
  tag: relayX
  description: "0=off (coil off), 1=on (coil energized)"

- id: digital_io_state
  type: enum
  values: ["0", "1"]
  tag: digitalIOX
  description: Digital I/O line state

- id: analog_input_value
  type: number
  tag: analogInputX
  description: Analog input X reading

- id: one_wire_sensor_value
  type: number
  tag: oneWireSensorX
  description: "1-Wire sensor reading; 'x.x' indicates sensor could not be read"

- id: vin
  type: number
  tag: vin
  description: Scaled internal Vin measurement (always present)

- id: register_value
  type: number
  tag: registerX
  description: Value of register X

- id: counter_value
  type: number
  tag: countX
  description: Count value associated with input X

- id: frequency_value
  type: number
  tag: frequencyX
  description: Frequency associated with input X

- id: on_time
  type: number
  tag: onTimeX
  description: Seconds the input has been on since last turning on

- id: total_on_time
  type: number
  tag: totalOnTimeX
  description: Total seconds the input has been on

- id: utc_time
  type: integer
  tag: utcTime
  description: Current UTC time in seconds since 1970-01-01

- id: serial_number
  type: string
  tag: serialNumber
  description: Device serial (MAC-style, e.g. 00:0C:C8:00:00:00)

Variables

# Settable parameters that are not discrete actions. All set via set_register /
# modbus_write_multiple_registers above; listed here as the tunable state surface.

- id: register
  type: number
  writable: true
  description: Internal register value (settable via HTTP registerX or Modbus FC 0x10)

- id: counter
  type: number
  writable: true
  description: Counter value (settable via HTTP countX)

- id: pulse_duration
  type: number
  writable: false
  description: Per-relay pulse duration configured on relay setup page (read-only via API; one-shot override via pulseTimeX arg)

Events

# UNRESOLVED: source describes Remote Services sending the device's state.xml on logic events and
# SNMP traps/notifications on relay state changes / sensor thresholds, but these are outbound
# notifications FROM the device to a configured server/manager, not documented unsolicited event
# payloads on the HTTP/Modbus control channel. No event schema enumerated.

Macros

# No multi-step command sequences described in source.
# UNRESOLVED: none documented.

Safety

confirmation_required_for: []
interlocks: []
# UNRESOLVED: source contains no safety warnings, interlock procedures, or power-on sequencing
# requirements. Never inferred.

Notes

  • Protocol mismatch warning: The scraper family was labeled "serial" / "RS-232C", but this source document contains zero serial content. The XW-110 is a networked (Wi-Fi) module. All documented control is over HTTP (port 80) and Modbus/TCP (port 502). RS-232C should be considered N/A unless a separate serial appendix exists.
  • Source generality: The source ("Integrating with ControlByWeb Devices") is a generic ControlByWeb integration manual. Examples reference the X-400 / X-600M / X-420 series. It is asserted to apply to "each of the ControlByWeb modules," so the command structure is treated as applicable to the XW-110, but the XW-110's exact I/O count is not stated here.
  • Default auth: HTTP Basic auth is optional; the User account is disabled by default (hence no password by default). Enabling the User account simultaneously disables Modbus/TCP because Modbus has no auth mechanism.
  • Default port: HTTP port 80 is the default (source: "If the TCP port has been changed (not port 80)"). Alternate port shown in examples: 8000.
  • Modbus map is per-device: Coil/discrete/register addresses are not fixed in the source; they must be read from the device's Setup pages (Advanced Network > View Modbus Address Table), since added/removed I/O changes the map.
  • Modbus limits: 2 TCP sockets max; idle connections close after 50 s; register reads/writes must be even counts (32-bit floats in 16-bit pairs); endianness configurable.
  • Additional transports documented but not action-enumerated here: SNMP (v1/v2c/v3; default community webrelay; Get/Set/Trap/Notification), MQTT 3.1.1 + Sparkplug B (publish/subscribe via broker), Remote Services (device-initiated TCP V1 connection, expects 3-char "ACK", sends state.xml), ControlByWeb Cloud / DAT URLs (e.g. https://api.controlbyweb.cloud/{dat}/state.json?relay1=1). These are present in the source and available for a future spec expansion.

Provenance

source_domains:
  - controlbyweb.com
source_urls:
  - https://controlbyweb.com/wp-content/uploads/2025/05/cbw-integration-and-protocols-manual.pdf
  - https://controlbyweb.com/support/cbw-integration-manual/
  - https://controlbyweb.com/wp-content/uploads/2024/02/xw-110-users-manual.pdf
retrieved_at: 2026-06-30T22:27:49.988Z
last_checked_at: 2026-07-07T12:53:01.130Z

Verification Summary

verdict: verified
checked_at: 2026-07-07T12:53:01.130Z
matched_actions: 16
action_count: 16
confidence: medium
summary: "All 16 spec actions matched verbatim against source HTTP GET and Modbus/TCP commands; transport fully verified. (11 unresolved item(s) noted in Known Gaps.)"

Known Gaps

- "The source document (\"Integrating with ControlByWeb Devices\") is a generic"
- "Input metadata declared the known protocol as RS-232C, but this source contains"
- "SNMP, MQTT/Sparkplug B, Remote Services, and Cloud (DAT URL) are also documented"
- "source describes Remote Services sending the device's state.xml on logic events and"
- "none documented."
- "source contains no safety warnings, interlock procedures, or power-on sequencing"
- "firmware version compatibility not stated in source."
- "XW-110 specific I/O inventory (relay/input/sensor counts) not stated in source."
- "serial / RS-232C transport not present in source (likely N/A for this model)."
- "voltage/current/power specifications not stated in source."
- "exact default credentials (if any) beyond example \"none:webrelay\" not stated as default."

From the AI4AV catalog (https://ai4av.net) · ODbL-1.0