Summary
The ControlByWeb X-408 is an Ethernet-based relay/IO control module in the X-400 Series. It exposes a built-in web server that responds to HTTP GET requests, a Modbus/TCP slave on port 502, SNMP v1/v2c/v3, MQTT 3.1.1 (with Sparkplug B), and an optional ControlByWeb Cloud HTTP API. This spec covers the HTTP GET control interface as documented in the source; Modbus, SNMP, MQTT, and Cloud variants are noted but each requires a separate control surface.
Transport
protocols:
- http
- tcp
addressing:
port: 80
auth:
type: basic # Base64 encoded "name:password" when user account enabled; no auth by default
Notes on transport:
- The default TCP port is 80. The source documents port 8000 as an example of a user-changed port (
http://192.168.1.2:8000/log.txt), so 80 is the stated default. - For Modbus/TCP, the module listens on port 502 (configurable under Advanced Network tab). This is the Modbus/TCP IANA-registered port and is stated in the source. Modbus is disabled whenever the user account is enabled.
- For SNMP, the device supports v1, v2c, and v3. Default community strings are
webrelayfor both read and write (v1/v2c only). - For MQTT, the device supports version 3.1.1 with optional Sparkplug B.
Traits
# powerable inferred from relay on/off command examples
# routable inferred from relay1/relay2... selectable outputs
# queryable inferred from state.xml/json read endpoints
Actions
# HTTP GET endpoints (default port 80; user account may be enabled)
# NOTE: The source documents these against an X-400 Series example. The X-408
# is an 8-relay variant; the I/O number is configured in the device setup
# (Local I/O Number). Replace X with the assigned number 1-8.
#
# All GET requests terminate with \r\n\r\n as stated in the source.
- 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 Custom State (XML)
kind: query
command: "GET /customState.xml HTTP/1.1\r\n\r\n"
params: []
- id: read_custom_state_json
label: Read Custom State (JSON)
kind: query
command: "GET /customState.json HTTP/1.1\r\n\r\n"
params: []
- id: relay_off
label: Turn Relay Off
kind: action
command: "GET /state.xml?relay{X}=0 HTTP/1.1\r\n\r\n"
params:
- name: X
type: integer
description: Relay number (assigned local I/O number, typically 1-8 for X-408)
- id: relay_on
label: Turn Relay On
kind: action
command: "GET /state.xml?relay{X}=1 HTTP/1.1\r\n\r\n"
params:
- name: X
type: integer
description: Relay number (assigned local I/O number, typically 1-8 for X-408)
- id: relay_pulse
label: Pulse Relay (default duration)
kind: action
command: "GET /state.xml?relay{X}=2 HTTP/1.1\r\n\r\n"
params:
- name: X
type: integer
description: Relay number (assigned local I/O number, typically 1-8 for X-408)
# Uses the Pulse Duration configured in the relay setup page (1.5s shown in source example).
- id: relay_pulse_duration
label: Pulse Relay (specified duration)
kind: action
command: "GET /state.xml?pulseTime{X}={seconds}&relay{X}=2 HTTP/1.1\r\n\r\n"
params:
- name: X
type: integer
description: Relay number (assigned local I/O number)
- name: seconds
type: integer
description: Pulse duration in seconds (pulseTime argument MUST precede relay command per source)
- id: set_on_time
label: Set On Time Counter
kind: action
command: "GET /state.xml?onTime{X}={seconds} HTTP/1.1\r\n\r\n"
params:
- name: X
type: integer
description: I/O number
- name: seconds
type: integer
description: On-time value in seconds (0 to reset, or any positive value)
- id: set_total_on_time
label: Set Total On Time Counter
kind: action
command: "GET /state.xml?totalOnTime{X}={seconds} HTTP/1.1\r\n\r\n"
params:
- name: X
type: integer
description: I/O number
- name: seconds
type: integer
description: Total on-time value in seconds (0 to reset)
- id: set_counter
label: Set Counter Value
kind: action
command: "GET /state.xml?count{X}={value} HTTP/1.1\r\n\r\n"
params:
- name: X
type: integer
description: I/O number
- name: value
type: integer
description: Counter value to set
- 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 number
- name: value
type: number
description: Register value (numeric; e.g. 10.5)
- id: set_custom_register
label: Set Custom-Named Register
kind: action
command: "GET /customState.xml?{camelName}{X}={value} HTTP/1.1\r\n\r\n"
params:
- name: camelName
type: string
description: User-configured camelCase name for the I/O (e.g. myRegister)
- name: X
type: integer
description: I/O number
- name: value
type: number
description: Register value
- id: multiple_commands
label: Send Multiple Commands in One Request
kind: action
command: "GET /state.xml?{param1}={val1}&{param2}={val2} HTTP/1.1\r\n\r\n"
params:
- name: param1
type: string
description: First I/O parameter (e.g. relay1, register1, count1)
- name: val1
type: string
description: Value for first parameter
- name: param2
type: string
description: Second I/O parameter
- name: val2
type: string
description: Value for second parameter
- id: read_log_txt
label: Read Data Log File
kind: query
command: "GET /log.txt 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: read_syslog_txt
label: Read System Log File
kind: query
command: "GET /syslog.txt HTTP/1.1\r\n\r\n"
params: []
# Requires setup username and password per source.
- id: erase_syslog_txt
label: Erase System Log File
kind: action
command: "GET /syslog.txt?erase=1 HTTP/1.1\r\n\r\n"
params: []
# Requires setup username and password per source.
Feedbacks
- id: relay_state
type: enum
values: [0, 1]
description: relayX element in state.xml/json; 0=off (coil off), 1=on (coil energized)
- id: digital_input_state
type: enum
values: [0, 1]
description: digitalInputX element; 0=off (no voltage), 1=on (voltage applied)
- id: digital_io_state
type: enum
values: [0, 1]
description: digitalIOX element; 0=off, 1=on
- id: on_time
type: number
description: onTimeX - time in seconds the input was on since last coming on
- id: total_on_time
type: number
description: totalOnTimeX - total time in seconds the input has been on
- id: count
type: number
description: countX - count value associated with input X
- id: frequency
type: number
description: frequencyX - frequency associated with input X
- id: analog_input
type: number
description: analogInputX - value of analog input X
- id: vin
type: number
description: Scaled internal Vin measurement (always present in state.xml/json)
- id: register
type: number
description: registerX - value of the register X
- id: one_wire_sensor
type: string
description: oneWireSensorX; "x.x" = sensor not readable, "77.3" = current value, "77.3 F" = value with units (showUnits=1)
- id: utc_time
type: integer
description: utcTime - UTC seconds since January 1, 1970
- id: timezone_offset
type: integer
description: timezoneOffset - offset to apply to utcTime for local time
- id: serial_number
type: string
description: serialNumber - MAC/serial of the X-400 Series device
- id: min_rec_refresh
type: integer
description: minRecRefresh - present in state.json
Variables
# Registers are settable numeric parameters retained by the device.
- id: register
type: number
description: General-purpose register value, set via state.xml?registerX= or customState.xml?{name}X=
Events
# Unsolicited device-pushed notifications:
- id: snmp_trap
description: SNMP Trap sent when a relay changes state, when a sensor value threshold is reached, or when supply voltage goes out of range. Configured as actions in Conditional and Scheduled tasks. Sent only for v1/v2c with community strings; v2c/v3 use Notifications which require acknowledgement.
- id: remote_services_state_push
description: When Remote Services is enabled, the device opens a TCP V1 connection to an external server and sends the connection string (static info + user-defined string) followed by state.xml at the configured Connection Interval. A 3-character "ACK" is expected within 10 seconds or the device closes the connection.
- id: ack_response
description: 3-character "ACK" expected from the external server in response to each connection string push.
Macros
# UNRESOLVED: source does not document a named macro/sequence system on the X-408 itself;
# multiple-command batch GETs (see actions.multiple_commands) can be used to combine
# relay and register changes into a single request.
Safety
confirmation_required_for: []
interlocks: []
# UNRESOLVED: source does not contain explicit safety warnings, interlock procedures,
# or power-on sequencing requirements for the X-408.
Notes
- The X-408 is an 8-relay member of the X-400 Series. The source refines all examples against the series generically; per-channel numbering on the X-408 itself is set by the Local I/O Number assigned in device setup.
- HTTP requests are terminated with
\r\n\r\nper the source. - When the User account is enabled on the device, requests must include an
Authorization: Basicheader whose value is the Base64 encoding ofusername:password(e.g.none:webrelay→bm9uZTp3ZWJyZWxheQ==). - For Modbus/TCP, the device is a slave on port 502 (configurable). Modbus is disabled when the User account is enabled. The Modbus address map is dynamic per installed I/O and must be retrieved from the device's setup pages (Advanced Network tab → View Modbus Address Table). Up to two TCP sockets may be open concurrently; further connection requests are rejected. Idle connection timeout: 50 seconds.
- Pulse Duration for
relayX=2is configured per-relay in the relay setup page; thepulseTimeX=argument overrides it for a single command only and is not persisted. ThepulseTimeXargument MUST precede therelayX=2argument in the query string. - Modbus/TCP function codes supported: 01 (Read Coils), 02 (Read Discrete Inputs), 03 (Read Holding Registers), 05 (Write Single Coil), 15/0x0F (Write Multiple Coils), 16/0x10 (Write Multiple Registers). 32-bit floating-point values use IEEE 754; endianness (little/big) is configured in the Advanced Network tab.
- SNMP: v1, v2c, v3. Default community strings are
webrelay/webrelay(read/write). v3 uses the User-Based Security Model with separate auth and privacy protocols. - MQTT: version 3.1.1; Sparkplug B is supported as an alternative. The source documents payload tokens for common system variables and I/O (e.g.
${relay1},${vin},${mac},${ver}). - ControlByWeb Cloud: HTTP GET to
https://api.controlbyweb.cloud/{DAT URL}/state.json[?...]works the same as direct state.json access. Version 2.0 of Remote Services is reserved for ControlByWeb.Cloud and not for other use.
Provenance
source_domains:
- controlbyweb.com
- controlbyweb.cloud
source_urls:
- https://controlbyweb.com/wp-content/uploads/2025/05/cbw-integration-and-protocols-manual.pdf
- https://controlbyweb.cloud
retrieved_at: 2026-06-30T15:29:33.075Z
last_checked_at: 2026-07-07T12:27:14.800Z
Verification Summary
verdict: verified
checked_at: 2026-07-07T12:27:14.800Z
matched_actions: 18
action_count: 18
confidence: medium
summary: "All 18 HTTP GET endpoint commands verified with exact literal matches in source; transport parameters (port 80, basic auth, HTTP/TCP) confirmed. (4 unresolved item(s) noted in Known Gaps.)"
Known Gaps
- "per-relay pulse duration default (1.5s example given) and pulseTime parameter maximum not stated; firmware version compatibility not stated"
- "source does not document a named macro/sequence system on the X-408 itself;"
- "source does not contain explicit safety warnings, interlock procedures,"
- "per-channel X numbering on the X-408 is configured in setup (Local I/O Number) and not enumerated in the source; firmware version compatibility not stated; default pulse duration source-example value 1.5s but underlying default not stated."
From the AI4AV catalog (https://ai4av.net) · ODbL-1.0