Summary
The X401 is a ControlByWeb 400 Series I/O controller exposing relays, digital inputs, analog inputs, registers, and 1-Wire sensors over TCP/IP. This spec covers HTTP GET (XML/JSON), Modbus/TCP, SNMP, and MQTT/Sparkplug B interfaces as documented for the 400 Series product family.
Transport
protocols:
- tcp # HTTP, Modbus/TCP, MQTT (all over TCP)
addressing:
port: 80 # default; port 502 for Modbus/TCP per source line 293; configurable under Advanced Network tab
# Modbus/TCP default port per source: 502
auth:
type: basic # Base64-encoded user:password in HTTP Authorization header when User account enabled (source line 25)
# When User account disabled (default), no password required (source line 11 "No Password")
Traits
- queryable # inferred from query command examples (state.xml/json reads, Modbus register/coil reads)
- routable # inferred from relay/output routing commands (relay1=0/1/2, Modbus Write Single Coil)
- powerable # inferred from pulse relay and on/off relay commands (inferred from relay control examples)
Actions
# HTTP GET control (Section 1.1)
- id: read_state_xml
label: Read state.xml
kind: query
command: "GET /state.xml HTTP/1.1\r\n\r\n"
params: []
- id: read_state_json
label: Read state.json
kind: query
command: "GET /state.json HTTP/1.1\r\n\r\n"
params: []
- id: read_custom_state_xml
label: Read customState.xml
kind: query
command: "GET /customState.xml HTTP/1.1\r\n\r\n"
params: []
- id: read_custom_state_json
label: Read customState.json
kind: query
command: "GET /customState.json HTTP/1.1\r\n\r\n"
params: []
- id: set_register_value
label: Set Register (HTTP)
kind: action
command: "GET /state.xml?register1={value} HTTP/1.1\r\n\r\n"
params:
- name: register_number
type: integer
description: 1-based register number per source example "register1"
- name: value
type: number
description: Numeric register value (example: register1=25 or register1=10.5)
- id: relay_off
label: Turn Relay Off
kind: action
command: "GET /state.xml?relay{relay}=0 HTTP/1.1\r\n\r\n"
params:
- name: relay
type: integer
description: 1-based relay number (e.g. 1, 2)
- id: relay_on
label: Turn Relay On
kind: action
command: "GET /state.xml?relay{relay}=1 HTTP/1.1\r\n\r\n"
params:
- name: relay
type: integer
description: 1-based relay number
- id: relay_pulse
label: Pulse Relay (default duration)
kind: action
command: "GET /state.xml?relay{relay}=2 HTTP/1.1\r\n\r\n"
params:
- name: relay
type: integer
description: 1-based relay number
- id: relay_pulse_custom_duration
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: 1-based relay number
- name: seconds
type: number
description: Pulse duration in seconds (example: 5, 15). MUST precede relay=2 (source line 100)
- id: set_on_time
label: Set onTime counter reset
kind: action
command: "GET /state.xml?onTime{counter}=0 HTTP/1.1\r\n\r\n"
params:
- name: counter
type: integer
description: 1-based counter number
- id: set_total_on_time
label: Set totalOnTime counter reset
kind: action
command: "GET /state.xml?totalOnTime{counter}=0 HTTP/1.1\r\n\r\n"
params:
- name: counter
type: integer
description: 1-based counter number
- id: set_counter_value
label: Set counter value
kind: action
command: "GET /state.json?count{counter}={value} HTTP/1.1\r\n\r\n"
params:
- name: counter
type: integer
description: 1-based counter number
- name: value
type: number
description: Counter value (example: 200)
- id: combined_commands
label: Multiple I/O commands in one request
kind: action
command: "GET /customState.xml?relay1=1&relay2=0 HTTP/1.1\r\n\r\n"
params: []
- id: erase_log_txt
label: Erase log.txt
kind: action
command: "GET /log.txt?erase=1 HTTP/1.1\r\n\r\n"
params: []
- id: erase_syslog_txt
label: Erase syslog.txt
kind: action
command: "GET /syslog.txt?erase=1 HTTP/1.1\r\n\r\n"
params: []
# Modbus/TCP (Section 2.1)
- id: modbus_read_coils
label: Modbus Read Coils (FC 01 / 0x01)
kind: query
command: "Modbus FC 0x01 - Read Coils (relays and digital I/O configured as outputs)"
params:
- name: start_address
type: integer
description: From Modbus map in setup pages
- name: coil_quantity
type: integer
description: From Modbus map in setup pages
- id: modbus_read_discrete_inputs
label: Modbus Read Discrete Inputs (FC 02 / 0x02)
kind: query
command: "Modbus FC 0x02 - Read Discrete Inputs (digital inputs and digital I/O configured as inputs)"
params:
- name: start_address
type: integer
description: From Modbus map in setup pages
- name: input_quantity
type: integer
description: From Modbus map in setup pages
- id: modbus_read_holding_registers
label: Modbus Read Holding Registers (FC 03 / 0x03)
kind: query
command: "Modbus FC 0x03 - Read Holding Registers (Vin, sensors, registers, counters, analog inputs)"
params:
- name: start_address
type: integer
description: From Modbus map in setup pages
- name: register_quantity
type: integer
description: From Modbus map in setup pages. Must be even (32-bit pairs). IEEE 754 floats.
- id: modbus_write_single_coil
label: Modbus Write Single Coil (FC 05 / 0x05)
kind: action
command: "Modbus FC 0x05 - Write Single Coil, value 0x00 (Off) or 0xFF (On)"
params:
- name: start_address
type: integer
description: From Modbus map in setup pages
- name: output_value
type: enum
values: ["0x00", "0xFF"]
description: 0x00=Off, 0xFF=On
- id: modbus_write_multiple_coils
label: Modbus Write Multiple Coils (FC 15 / 0x0F)
kind: action
command: "Modbus FC 0x0F - Write Multiple Coils, value range 0x0000 to 0xFFFF"
params:
- name: start_address
type: integer
description: From Modbus map in setup pages
- name: output_value
type: integer
description: Bit-mask 0x0000 to 0xFFFF; 1 bit per coil
- id: modbus_write_multiple_registers
label: Modbus Write Multiple Registers (FC 16 / 0x10)
kind: action
command: "Modbus FC 0x10 - Write Multiple Registers (IEEE 754 floats, register count must be even)"
params:
- name: start_address
type: integer
description: From Modbus map in setup pages
- name: register_quantity
type: integer
description: Must be even (32-bit pairs). Endianness per Advanced Network setup.
- id: modbus_pulse_relay
label: Modbus Pulse Relay (FC 16, addresses 512-513)
kind: action
command: "Modbus FC 0x10 - Write 32-bit float pulse duration (seconds) to register pair 512-513 (PLC address 40513-40514) for relay 1"
params:
- name: duration_seconds
type: number
description: 32-bit float pulse duration in seconds
# SNMP (Section 3)
- id: snmp_get_request
label: SNMP GetRequest
kind: query
command: "SNMP GetRequest - standard RFC1213 objects (_system.sysDescr, _system.sysObjectID, _system.sysUpTime, _system.sysName) and module-defined I/O"
params: []
- id: snmp_set_request
label: SNMP SetRequest
kind: action
command: "SNMP SetRequest - set configured I/O values"
params: []
- id: snmp_trap
label: SNMP Trap (unsolicited)
kind: event
command: "SNMP Trap - sent when relay changes state, sensor threshold reached, or vin out of range (configured via Conditional/Scheduled tasks)"
params: []
- id: snmp_notification
label: SNMP Notification (v2c/v3)
kind: event
command: "SNMP Notification - requires acknowledgment from SNMP manager; retries on no response"
params: []
# MQTT / Sparkplug B (Section 4)
- id: mqtt_publish
label: MQTT Publish
kind: action
command: "MQTT Publish - topic and payload tokens per source (e.g. ${relay1}, ${vin}, ${register1}, ${mac}, ${ver}, ${uptime}, ${dateTime})"
params:
- name: topic
type: string
description: MQTT topic; Sparkplug B topic structure defined by spec
- name: payload
type: string
description: JSON/XML payload using tokens from source Table 4.1.4
- id: mqtt_subscribe
label: MQTT Subscribe
kind: action
command: "MQTT Subscribe - receive I/O data published by other devices on configured broker"
params:
- name: topic
type: string
description: MQTT topic filter
# Remote Services (Section 5)
- id: remote_services_connection_open
label: Remote Services TCP connection (device-initiated)
kind: event
command: "Device opens TCP connection per Connection Interval; sends state.xml with user-defined Connection String; expects 3-char ACK within 10 seconds"
params: []
- id: cloud_dat_url_state
label: Cloud DAT URL - Read state
kind: query
command: "GET https://api.controlbyweb.cloud/{dat_url}/state.json HTTP/1.1\r\n\r\n"
params:
- name: dat_url
type: string
description: Generated ControlByWeb Cloud DAT URL token
Feedbacks
# Observable state read via state.xml/json (Section 1.1.2)
- id: relay_state
type: enum
values: [0, 1, 2] # 0=off, 1=on, 2=pulse
description: <relayX> tag in state.xml/json
- id: digital_input_state
type: enum
values: [0, 1]
description: <digitalInputX> / "digitalInputX" - 0=off, 1=on
- id: digital_io_state
type: enum
values: [0, 1]
description: <digitalIOX> / "digitalIOX" - configured direction
- id: on_time
type: number
description: <onTimeX> seconds since last on
- id: total_on_time
type: number
description: <totalOnTimeX> cumulative on seconds
- id: count
type: number
description: <countX> counter value
- id: frequency
type: number
description: <frequencyX> frequency value
- id: analog_input
type: number
description: <analogInputX> / "analogInputX" - analog input X value
- id: vin
type: number
description: <vin> / "vin" - scaled internal Vin measurement
- id: frequency_input_x420
type: number
description: <frequencyInput> / "frequencyInput" - X-420 specific
- id: register
type: number
description: <registerX> / "registerX" - register value (IEEE 754 float; example: register1=10.5)
- id: utc_time
type: integer
description: <utcTime> / "utcTime" - seconds since Jan 1 1970
- id: timezone_offset
type: integer
description: <timezoneOffset> - offset for local time
- id: serial_number
type: string
description: <serialNumber> - MAC-format device serial
- id: one_wire_sensor
type: string
description: <oneWireSensorX> / "oneWireSensorX" - "x.x" if not read; numeric value (optionally with "showUnits=1")
- id: latitude
type: string
description: "lat" - GPS latitude (if device supports GPS)
- id: longitude
type: string
description: "long" - GPS longitude (if device supports GPS)
- id: min_rec_refresh
type: integer
description: "minRecRefresh" - minimum recording refresh interval
# Modbus error responses (Section 2.1)
- id: modbus_error_code
type: integer
description: Returned function code = original code + 0x80 (e.g. 0x81, 0x82, 0x83, 0x85, 0x8F, 0x90)
- id: modbus_exception_code
type: integer
description: 0x01=function not supported, 0x02=incorrect address/quantity, 0x03=padding/byte count out of range
# Remote Services (Section 5)
- id: remote_services_ack
type: string
description: 3-character ACK expected from external server after each connection string (within 10s)
# SNMP (Section 3)
- id: sys_descr
type: string
description: _system.sysDescr - "X-4xx"
- id: sys_object_id
type: string
description: _system.sysObjectID - "X4xx"
- id: sys_up_time
type: integer
description: _system.sysUpTime - hundredths of seconds since last powered
- id: sys_name
type: string
description: _system.sysName - "X-4xx" (configurable)
Variables
# Settable parameters documented in source
- id: register
type: number
description: General-purpose register (e.g. register1) settable via state.xml?register1={value} or Modbus FC 16
Events
- id: state_xml_pushed
description: Device sends state.xml over Remote Services TCP connection when a logic event triggers "send state" action
- id: connection_string_sent
description: Device periodically sends Connection String per Connection Interval setting when Remote Services enabled
Macros
# UNRESOLVED: source does not describe multi-step macros. Remove section if not applicable.
Safety
confirmation_required_for: []
interlocks: []
# UNRESOLVED: source contains no safety warnings, interlock procedures, or power-on sequencing requirements.
Notes
- Source document is the generic ControlByWeb 400 Series protocol/integration manual; X401-specific I/O counts (relays, digital inputs, analog inputs) are not enumerated and must be verified against the per-device setup pages.
- Default HTTP port is 80; default Modbus/TCP port is 502. Both are configurable under the Advanced Network tab per source.
- When the User account is enabled on the device, HTTP requests must include
Authorization: Basic <base64(name:password)>header (source line 35). Default credentials shown in example arenone:webrelay(Base64:bm9uZTp3ZWJyZWxheQ==). - When the User account is enabled, Modbus/TCP communication is disabled (source line 295).
- HTTP GET commands for the same connection may be combined:
/state.json?relay1=1&relay2=0(source line 147). - For
pulseTimeparameter: must precede the correspondingrelayN=2command in the query string (source line 100). - Modbus idle TCP connection times out after 50 seconds (source line 314); only 2 concurrent Modbus TCP connections supported.
- IEEE 754 32-bit floats used for holding registers; endianness configurable in Advanced Network tab (source line 398).
- Uninstalled temperature/humidity sensors return
0xFFFFFFFF(NaN) in Modbus reads (source line 402). oneWireSensorXreturnsx.xwhen sensor cannot be read; passshowUnits=1query param to append unit (e.g.77.3 F).- SNMP community strings default to
webrelayfor both read and write (source line 500). - Remote Services connection: device expects 3-char ACK within 10 seconds; closes connection if no ACK (source line 574).
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/2025/05/400-series-users-manual.pdf
- https://controlbyweb.com/support/cbw-integration-manual/
- https://controlbyweb.com/support/
retrieved_at: 2026-06-30T14:45:14.095Z
last_checked_at: 2026-07-07T11:14:50.608Z
Verification Summary
verdict: verified
checked_at: 2026-07-07T11:14:50.608Z
matched_actions: 30
action_count: 30
confidence: medium
summary: "All 30 spec actions matched literally to source commands. Transport parameters (port 80, port 502, basic auth) verified. Full protocol coverage confirmed. (4 unresolved item(s) noted in Known Gaps.)"
Known Gaps
- "source describes the generic X-400 Series; X401-specific I/O counts (relay count, analog input count, digital input count) are not enumerated in the source and must be confirmed per-device."
- "source does not describe multi-step macros. Remove section if not applicable."
- "source contains no safety warnings, interlock procedures, or power-on sequencing requirements."
- "firmware version compatibility not stated in source."
From the AI4AV catalog (https://ai4av.net) · ODbL-1.0