Summary
The ControlByWeb X22S is a network-connected industrial I/O module (relay, digital, analog) from the X-400 Series family. This spec covers control and monitoring via HTTP GET requests against the on-board web server, Modbus/TCP, SNMP, and MQTT/Sparkplug B. The supplied source document is a generic X-400 Series integration guide; X22S-specific behavior (e.g. relay count, I/O mix) is not separately confirmed in the source.
Transport
protocols:
- http
- tcp # inferred: Modbus/TCP and HTTP both ride TCP; port stated below for Modbus
addressing:
port: 502 # Modbus/TCP port per source (Section 2.1)
base_url: "http://<device-ip>/" # inferred: source shows http://192.168.1.2/state.xml patterns; path segments follow
auth:
type: basic # inferred: source describes HTTP Basic auth via Base64-encoded "name:password" when User account enabled; otherwise no auth
Note: HTTP port is configurable on the device; source uses port 80 default and shows :8000 as an example of a changed port. Default TCP port for HTTP not explicitly fixed in source — base_url shown above uses port 80 by omission.
Traits
# - queryable (inferred: state.xml/json read commands present)
# - powerable (inferred: relay on/off commands present, per relay trait)
# - routable # not applicable - this is a relay/digital I/O module, no source/video routing
Actions
# HTTP GET-based control of X-400 Series I/O. Apply to X22S pending device-specific confirmation.
# Each `command` is the literal request line from the source. Variable parts are shown as {placeholders}.
# Server response is the state.xml/json document (see Feedbacks).
- id: get_state_xml
label: Read state (XML)
kind: query
command: "GET /state.xml HTTP/1.1\r\n\r\n"
params: []
- id: get_state_json
label: Read state (JSON)
kind: query
command: "GET /state.json HTTP/1.1\r\n\r\n"
params: []
- id: get_custom_state_xml
label: Read custom state (XML)
kind: query
command: "GET /customState.xml HTTP/1.1\r\n\r\n"
params: []
- id: get_custom_state_json
label: Read custom state (JSON)
kind: query
command: "GET /customState.json HTTP/1.1\r\n\r\n"
params: []
# Relay control - X22S relay count is not stated in source; parameterize relay number.
- id: relay_off
label: Turn Relay Off
kind: action
command: "GET /state.xml?relay{n}=0 HTTP/1.1\r\n\r\n"
params:
- name: n
type: integer
description: Relay number (1-based)
- id: relay_on
label: Turn Relay On
kind: action
command: "GET /state.xml?relay{n}=1 HTTP/1.1\r\n\r\n"
params:
- name: n
type: integer
description: Relay number (1-based)
- id: relay_pulse_default
label: Pulse Relay (default duration)
kind: action
command: "GET /state.json?relay{n}=2 HTTP/1.1\r\n\r\n"
params:
- name: n
type: integer
description: Relay number (1-based)
- id: relay_pulse_5s
label: Pulse Relay 1 for 5 seconds
kind: action
command: "GET /state.json?pulseTime{n}=5&relay{n}=2 HTTP/1.1\r\n\r\n"
params:
- name: n
type: integer
description: Relay number (1-based)
- id: relay_pulse_15s
label: Pulse Relay 1 for 15 seconds
kind: action
command: "GET /state.json?pulseTime{n}=15&relay{n}=2 HTTP/1.1\r\n\r\n"
params:
- name: n
type: integer
description: Relay number (1-based)
- id: set_on_time
label: Set onTime (seconds)
kind: action
command: "GET /state.xml?onTime{n}={seconds} HTTP/1.1\r\n\r\n"
params:
- name: n
type: integer
description: Input/relay number (1-based)
- name: seconds
type: number
description: On-time in seconds (e.g. 0 to reset, 5)
- id: set_total_on_time
label: Set totalOnTime (seconds)
kind: action
command: "GET /state.xml?totalOnTime{n}={seconds} HTTP/1.1\r\n\r\n"
params:
- name: n
type: integer
description: Input/relay number (1-based)
- name: seconds
type: number
description: Total on-time in seconds
- id: set_counter
label: Set counter value
kind: action
command: "GET /state.json?count{n}={value} HTTP/1.1\r\n\r\n"
params:
- name: n
type: integer
description: Input number (1-based)
- name: value
type: number
description: Counter value (e.g. 200)
- id: set_register
label: Set register value
kind: action
command: "GET /state.xml?register{n}={value} HTTP/1.1\r\n\r\n"
params:
- name: n
type: integer
description: Register number (1-based)
- name: value
type: number
description: Numeric register value (supports decimals, e.g. 10.5)
- id: multi_command_state
label: Multiple commands via state.xml/json
kind: action
command: "GET /state.json?relay1=1&relay2=0 HTTP/1.1\r\n\r\n"
params: []
- id: erase_log_txt
label: Erase data log file
kind: action
command: "GET /log.txt?erase=1 HTTP/1.1\r\n\r\n"
params: []
- id: erase_syslog
label: Erase system log file
kind: action
command: "GET /syslog.txt?erase=1 HTTP/1.1\r\n\r\n"
params: []
# Modbus/TCP function codes (Section 2.1.1). MBAP header is implied; payload = function code + data.
- id: modbus_read_coils
label: Modbus Read Coils (FC 01)
kind: query
command: "0x01 {startAddr} {quantity}"
params:
- name: startAddr
type: integer
description: Starting coil address (from device Modbus map)
- name: quantity
type: integer
description: Number of coils to read
- id: modbus_read_discrete_inputs
label: Modbus Read Discrete Inputs (FC 02)
kind: query
command: "0x02 {startAddr} {quantity}"
params:
- name: startAddr
type: integer
description: Starting discrete input address
- name: quantity
type: integer
description: Number of inputs to read
- id: modbus_read_holding_registers
label: Modbus Read Holding Registers (FC 03)
kind: query
command: "0x03 {startAddr} {quantity}"
params:
- name: startAddr
type: integer
description: Starting register address (must be even for 32-bit values)
- name: quantity
type: integer
description: Number of registers to read (must be divisible by 2)
- id: modbus_write_single_coil
label: Modbus Write Single Coil (FC 05)
kind: action
command: "0x05 {startAddr} {0x00|0xFF}"
params:
- name: startAddr
type: integer
description: Coil address
- name: value
type: enum
values: [0x00, 0xFF]
description: 0x00 = Off, 0xFF = On
- id: modbus_write_multiple_coils
label: Modbus Write Multiple Coils (FC 15)
kind: action
command: "0x0F {startAddr} {quantity} {byteCount} {valueBytes}"
params:
- name: startAddr
type: integer
description: Starting coil address
- name: quantity
type: integer
description: Number of outputs to write
- name: byteCount
type: integer
description: Quantity / 8
- name: valueBytes
type: string
description: Bit-packed output value (0x0000-0xFFFF)
- id: modbus_write_multiple_registers
label: Modbus Write Multiple Registers (FC 16)
kind: action
command: "0x10 {startAddr} {quantity} {byteCount} {registers}"
params:
- name: startAddr
type: integer
description: Starting register address (must be even)
- name: quantity
type: integer
description: Number of registers to write (must be even)
- name: registers
type: string
description: IEEE 754 32-bit float values, little- or big-endian per device config
# MQTT publish payloads (Section 4.1.4). Token strings are placeholders the device substitutes.
# UNRESOLVED: exact MQTT topic and publish command format not specified in source - only token list.
Feedbacks
# state.xml/json document fields as enumerated in the source.
- id: digital_input
type: integer
description: "0 = off, 1 = on. Element name pattern: digitalInputX (1-based)."
values: [0, 1]
- id: relay_state
type: integer
description: "0 = off (coil off), 1 = on (coil energized). Element name pattern: relayX."
values: [0, 1]
- id: digital_io
type: integer
description: "0 = off, 1 = on. Element name pattern: digitalIOX."
values: [0, 1]
- id: on_time
type: number
description: "Time in seconds the input was on since last coming on. Pattern: onTimeX."
- id: total_on_time
type: number
description: "Total time in seconds the input has been on. Pattern: totalOnTimeX."
- id: count
type: number
description: "Count value associated with input X. Pattern: countX."
- id: frequency
type: number
description: "Frequency associated with input X. Pattern: frequencyX."
- id: analog_input
type: number
description: "Value of analog input X. Pattern: analogInputX."
- id: vin
type: number
description: "Scaled internal Vin measurement. Element name: vin."
- id: frequency_input
type: number
description: "Value of the X-420 frequency input. Element name: frequencyInput."
- id: register
type: number
description: "Value of register X. Pattern: registerX."
- id: utc_time
type: integer
description: "Current UTC time, seconds since 1970-01-01. Element name: utcTime."
- id: one_wire_sensor
type: string
description: "1-Wire sensor value. 'x.x' = read failure. '77.3' = current value. '77.3 F' = value with units (showUnits=1). Pattern: oneWireSensorX."
- id: timezone_offset
type: integer
description: "Offset to add to utcTime for local time. Element name: timezoneOffset."
- id: serial_number
type: string
description: "Device serial number (MAC format, e.g. 00:0C:C8:00:00:00). Element name: serialNumber."
Variables
# Settable parameters covered by Actions above. Listed here for variable tracking.
- name: register{n}
type: number
description: "Writable register value, IEEE 754 float. Set via state.xml?register{n}={value} or Modbus FC 16."
- name: onTime{n}
type: number
description: "Per-input on-time counter (seconds). Set via state.xml?onTime{n}={seconds}."
- name: totalOnTime{n}
type: number
description: "Per-input total on-time (seconds). Set via state.xml?totalOnTime{n}={seconds}."
- name: count{n}
type: number
description: "Per-input counter value. Set via state.json?count{n}={value}."
- name: pulseTime{n}
type: number
description: "Per-pulse override duration (seconds). Must precede relay{n}=2 in same request."
Events
# UNRESOLVED: source describes SNMP traps generically (Section 3.1.3) but does not enumerate event IDs.
# MQTT publishes (Section 4.1.4) include a token list but not a definitive topic/payload schema for events.
Macros
# UNRESOLVED: source does not define multi-step sequences.
Safety
confirmation_required_for: []
interlocks: []
# UNRESOLVED: source contains no safety warnings, interlock procedures, or power-on sequencing requirements.
Notes
- Source document is the X-400 Series "Integrating with ControlByWeb Devices" guide, not an X22S-specific manual. The X22S is part of the X-400 Series family per ControlByWeb product naming, but X22S-specific I/O counts, channel counts, and any X22S-only behavior are not in this source.
- The Known protocol was given as RS-232C, but the supplied source documents only IP-based protocols (HTTP, Modbus/TCP, SNMP, MQTT/Sparkplug B). No RS-232 commands, baud rate, data bits, parity, stop bits, or framing are present. RS-232 fields are left UNRESOLVED.
- Modbus/TCP uses port 502 (Section 2.1). Connection times out after 50 seconds of idle; send a periodic read to keep open. Up to two concurrent Modbus/TCP sockets supported.
- Modbus function codes supported: 01 (Read Coils), 02 (Read Discrete Inputs), 03 (Read Holding Registers), 05 (Write Single Coil), 15 (Write Multiple Coils), 16 (Write Multiple Registers). 32-bit sensor values must be read/written in pairs (even register counts). 32-bit float values follow IEEE 754, little- or big-endian per device configuration.
- Modbus/TCP is disabled whenever the User account is enabled on the device (no Modbus password mechanism).
- Modbus error responses: function code + 0x80 (e.g. FC 01 → 0x81), with exception codes 0x01 (not supported) or 0x02 (bad start address/quantity).
- HTTP auth: by default no password. If User account is enabled, requests must include
Authorization: Basic <base64(user:pass)>header. - HTTP port is configurable; default is 80. Log file access may require setup username/password.
- MQTT supports version 3.1.1 with Sparkplug B. Sparkplug B is an alternative protocol on top of MQTT with defined topic structure.
- SNMP versions 1, 2c, and 3 supported. Default community strings are
webrelay(both read and write) for v1/v2c. v3 uses USM with separate auth and privacy algorithms and passwords. - Remote Services (Section 5): device can initiate outbound TCP connection to an external server. Server must send a 3-character "ACK" within 10 seconds or the device closes the connection. Version 2.0 of Remote Services is reserved for ControlByWeb.Cloud.
- ControlByWeb.Cloud (Section 6): DAT URLs allow HTTP GET integration without port forwarding. Example:
https://api.controlbyweb.cloud/{datUrl}/state.json?relay1=1&relay2=1.
Provenance
source_domains:
- controlbyweb.com
source_urls:
- https://controlbyweb.com/wp-content/uploads/2025/05/cbw-integration-and-protocols-manual.pdf
- https://controlbyweb.com/wp-content/uploads/2024/01/X-22s_manual_v2.0.pdf
- https://controlbyweb.com/support/cbw-integration-manual/
- https://controlbyweb.com/support/communication-protocols/communicating-with-standalone-products/
retrieved_at: 2026-06-30T15:31:33.922Z
last_checked_at: 2026-07-07T11:12:34.012Z
Verification Summary
verdict: verified
checked_at: 2026-07-07T11:12:34.012Z
matched_actions: 22
action_count: 22
confidence: medium
summary: "All 22 spec actions verified against source; HTTP GET commands, Modbus function codes, and transport parameters (port 502, HTTP auth basic) all confirmed. (6 unresolved item(s) noted in Known Gaps.)"
Known Gaps
- "source document is the X-400 Series integration manual; X22S-specific I/O counts, port defaults, and any RS-232 payload details are not explicitly stated. Known protocol was given as RS-232C, but the source documents only IP-based protocols (HTTP, Modbus/TCP, SNMP, MQTT); no RS-232 commands, baud rate, or framing appear."
- "exact MQTT topic and publish command format not specified in source - only token list."
- "source describes SNMP traps generically (Section 3.1.3) but does not enumerate event IDs."
- "source does not define multi-step sequences."
- "source contains no safety warnings, interlock procedures, or power-on sequencing requirements."
- "X22S-specific channel/relay counts; RS-232C commands, baud, framing; firmware version compatibility; any X22S-only command set or quirks."
From the AI4AV catalog (https://ai4av.net) · ODbL-1.0