Summary
The ControlByWeb X-410 is an Ethernet-attached industrial I/O module exposing relays, digital inputs, analog inputs, 1-Wire sensors, Vin, counters and internal registers. This spec covers the HTTP GET (XML/JSON) control surface, Modbus/TCP slave interface, SNMP, MQTT/Sparkplug B, and HTTP endpoint conventions described in the vendor Integration & Communication Protocols Manual.
Transport
protocols:
- tcp
- http
addressing:
base_url: http://{device_ip}
port: 80 # source states default; configurable (example "port 8000" given)
auth:
type: none # inferred: no auth procedure required when User account is disabled (default)
HTTP requests are GET against /state.xml, /state.json, /customState.xml, /customState.json, /log.txt, /syslog.txt. When the User account is enabled, requests must include Authorization: Basic <base64(user:pass)>.
Modbus/TCP slave listens on port 502 (configurable under Advanced Network tab). Two simultaneous Modbus TCP sockets; 50 second idle timeout.
SNMP v1/v2c/v3 over UDP/161 (default; not explicitly stated).
MQTT v3.1.1; broker address configured by user.
Traits
- queryable # inferred: state.xml/state.json expose read endpoints
- routable # inferred: input numbering and I/O assignments route which fields appear in state.xml/json
Actions
# HTTP GET endpoints (XML/JSON). All requests are GET against /state.xml or
# /state.json (or /customState.xml / /customState.json with renamed tags).
# Multiple query parameters can be combined with '&' in a single URL.
- id: get_state
label: Read full device state (XML)
kind: query
command: "GET /state.xml HTTP/1.1"
params: []
- id: get_state_json
label: Read full device state (JSON)
kind: query
command: "GET /state.json HTTP/1.1"
params: []
- id: get_custom_state
label: Read custom-named state (XML)
kind: query
command: "GET /customState.xml HTTP/1.1"
params: []
- id: get_custom_state_json
label: Read custom-named state (JSON)
kind: query
command: "GET /customState.json HTTP/1.1"
params: []
# Relay control (relay X where X = Local I/O Number assigned to the relay)
- id: relay_off
label: Turn Relay X OFF
kind: action
command: "GET /state.xml?relay{X}=0 HTTP/1.1"
params:
- name: X
type: integer
description: Local I/O number assigned to the relay
- id: relay_on
label: Turn Relay X ON
kind: action
command: "GET /state.xml?relay{X}=1 HTTP/1.1"
params:
- name: X
type: integer
description: Local I/O number assigned to the relay
- id: relay_pulse
label: Pulse Relay X (preset duration)
kind: action
command: "GET /state.xml?relay{X}=2 HTTP/1.1"
params:
- name: X
type: integer
description: Local I/O number assigned to the relay
- id: relay_pulse_time
label: Pulse Relay X for N seconds (override preset)
kind: action
command: "GET /state.json?pulseTime{X}={seconds}&relay{X}=2 HTTP/1.1"
params:
- name: X
type: integer
description: Local I/O number assigned to the relay
- name: seconds
type: number
description: Pulse duration in seconds (pulseTime must precede relay=X=2 in URL)
- id: relay_pulse_if_off
label: Pulse Relay X only if currently Off (firmware v3.13.7.8+)
kind: action
command: "GET /state.json?relay{X}=3 HTTP/1.1"
params:
- name: X
type: integer
description: Local I/O number assigned to the relay
- id: relay_toggle_off_when_pulsing
label: Let pulse finish then turn Relay X Off (firmware v3.13.7.8+)
kind: action
command: "GET /state.json?relay{X}=7 HTTP/1.1"
params:
- name: X
type: integer
description: Local I/O number assigned to the relay
# Counters / on-time setters
- id: set_on_time
label: Set onTimeX value
kind: action
command: "GET /state.xml?onTime{X}={value} HTTP/1.1"
params:
- name: X
type: integer
description: Digital input number
- name: value
type: number
description: Seconds value to set (e.g. 0, 5)
- id: set_total_on_time
label: Set totalOnTimeX value
kind: action
command: "GET /state.xml?totalOnTime{X}={value} HTTP/1.1"
params:
- name: X
type: integer
description: Digital input number
- name: value
type: number
description: Seconds value to set (e.g. 0, 5)
- id: set_counter
label: Set countX value
kind: action
command: "GET /state.json?count{X}={value} HTTP/1.1"
params:
- name: X
type: integer
description: Digital input number
- name: value
type: number
description: Counter value (e.g. 200)
# Register control
- id: set_register
label: Set registerX value
kind: action
command: "GET /state.xml?register{X}={value} HTTP/1.1"
params:
- name: X
type: integer
description: Register number
- name: value
type: number
description: Register value (e.g. 10.5, 25)
# Log file endpoints
- id: read_log
label: Read data log file
kind: query
command: "GET /log.txt HTTP/1.1"
params: []
- id: erase_log
label: Erase data log file
kind: action
command: "GET /log.txt?erase=1 HTTP/1.1"
params: []
- id: read_syslog
label: Read system log file
kind: query
command: "GET /syslog.txt HTTP/1.1"
params: []
- id: erase_syslog
label: Erase system log file
kind: action
command: "GET /syslog.txt?erase=1 HTTP/1.1"
params: []
# Modbus/TCP function codes (slave on port 502)
- id: modbus_read_coils
label: Read Coils (Function 01)
kind: query
command: "Modbus FC 0x01"
params:
- name: start_address
type: integer
description: Per Modbus map in setup pages
- name: quantity
type: integer
description: Number of coils to read
- id: modbus_read_discrete_inputs
label: Read Discrete Inputs (Function 02)
kind: query
command: "Modbus FC 0x02"
params:
- name: start_address
type: integer
description: Per Modbus map in setup pages
- name: quantity
type: integer
description: Number of discrete inputs to read
- id: modbus_read_holding_registers
label: Read Holding Registers (Function 03)
kind: query
command: "Modbus FC 0x03"
params:
- name: start_address
type: integer
description: 32-bit sensor/analog values require pairs (must read Nx2 registers)
- name: quantity
type: integer
description: Number of registers to read (must be divisible by 2)
- id: modbus_write_single_coil
label: Write Single Coil (Function 05)
kind: action
command: "Modbus FC 0x05"
params:
- name: start_address
type: integer
description: Per Modbus map in setup pages
- name: value
type: enum
values: [0x00, 0xFF]
description: 0x00 = Off, 0xFF = On
- id: modbus_write_multiple_coils
label: Write Multiple Coils (Function 15)
kind: action
command: "Modbus FC 0x0F"
params:
- name: start_address
type: integer
description: First coil address
- name: quantity
type: integer
description: Number of coils
- name: byte_count
type: integer
description: Output quantity divided by 8
- name: value
type: hex
description: 0x0000 to 0xFFFF bitfield (e.g. 0xFFFF = up to 16 outputs ON)
- id: modbus_write_multiple_registers
label: Write Multiple Registers (Function 16)
kind: action
command: "Modbus FC 0x10"
params:
- name: start_address
type: integer
description: Per Modbus map; pulse commands use addresses 512-513
- name: quantity
type: integer
description: Number of registers (divisible by 2)
- name: value
type: number
description: IEEE 754 32-bit float, little- or big-endian per Advanced Network setting
Feedbacks
# Tags returned in state.xml / state.json / customState.* (only present
# when the I/O type has a Local I/O Number assigned).
- id: digital_input
type: enum
values: [0, 1]
description: "0 = off (no voltage), 1 = on (voltage applied). Tag <digitalInputX>."
- id: relay_state
type: enum
values: [0, 1]
description: "0 = coil off, 1 = coil energized. Tag <relayX>."
- id: digital_io
type: enum
values: [0, 1]
description: "Configured-as-input digital I/O state. Tag <digitalIOX>."
- id: on_time
type: number
description: Seconds the input has been on since last coming on. Tag <onTimeX>.
- id: total_on_time
type: number
description: Total seconds the input has been on. Tag <totalOnTimeX>.
- id: count
type: number
description: Counter value associated with input X. Tag <countX>.
- id: frequency
type: number
description: Frequency associated with input X (or X-420 frequency input). Tag <frequencyX> / <frequencyInput>.
- id: analog_input
type: number
description: Value of analog input X. Tag <analogInputX>.
- id: vin
type: number
description: Scaled internal Vin measurement. Always present in state.xml/json. Tag <vin>.
- id: register
type: number
description: Internal register X value. Tag <registerX>.
- id: one_wire_sensor
type: number
description: "x.x = read error; 77.3 = reading; 77.3 F = reading with units (showUnits=1). Tag <oneWireSensorX>."
- id: utc_time
type: integer
description: UTC seconds since 1970-01-01. Tag <utcTime>.
- id: timezone_offset
type: integer
description: Seconds offset to apply to utcTime for local time. Tag <timezoneOffset>.
- id: serial_number
type: string
description: Device MAC address (used as serial). Format 00:00:00:00:00:00. Tag <serialNumber>.
- id: lat
type: number
description: GPS latitude (where supported). Tag "lat" in state.json.
- id: long
type: number
description: GPS longitude (where supported). Tag "long" in state.json.
- id: min_rec_refresh
type: integer
description: Minimum recommended refresh interval (state.json).
# Modbus error responses
- id: modbus_error_function_code
type: integer
description: "Original function code + 0x80. E.g. 0x81 = error during FC 0x01."
- id: modbus_exception_code
type: integer
description: "0x01 function/feature not supported, 0x02 incorrect address/quantity, 0x03 padding/out-of-range."
Variables
# Settable parameters surfaced via state.xml/json GET arguments.
- id: register_value
type: number
description: Internal register X - float writable via registerX={value}.
- id: on_time_value
type: number
description: onTimeX - seconds writable.
- id: total_on_time_value
type: number
description: totalOnTimeX - seconds writable.
- id: count_value
type: number
description: countX - counter writable.
- id: pulse_time_override
type: number
description: pulseTimeX - seconds, single-pulse override (must precede relayX=2 in URL).
Events
# Unsolicited notifications the device can emit.
- id: snmp_trap
description: "Trap PDU when relay state changes, sensor threshold met, or Vin out of range. Configured under Conditional/Scheduled tasks."
protocol: snmp
- id: snmp_notification
description: "Notification (v2c/v3) - acknowledged variant of trap; retries on missing response."
protocol: snmp
- id: mqtt_publish
description: "Publish to broker on I/O state change or update. Token expansion (e.g. ${relay1}, ${vin}, ${dateTime}) supported in payloads."
protocol: mqtt
Macros
# UNRESOLVED: source does not describe any device-side multi-step sequences
# beyond combining query parameters in a single URL (relay1=1&relay2=0).
Safety
confirmation_required_for: []
interlocks: []
# UNRESOLVED: source contains no safety warnings or interlock procedures.
# Operational note from source: Modbus is disabled when the User account is enabled,
# because Modbus/TCP has no built-in password protection.
Notes
- HTTP GET is the canonical control surface; XML and JSON variants expose identical state with different tag naming.
/customState.xml|jsonreuses the same URL scheme with user-configured CamelCase tag names. - Multiple control parameters can be combined into one URL:
/state.json?relay1=1&relay2=0. - Modbus/TCP slave holds two simultaneous connections; idle timeout 50 s. Default port 502. Addressing map is generated by the device based on configured I/O — refer to the device's "View Modbus Address Table" for actual addresses.
- For relay pulse with non-preset duration,
pulseTimeX={seconds}MUST precederelayX=2in the query string. - Special pulse commands (
relayX=3,relayX=7) require firmware v3.13.7.8 or later. - HTTP default port is 80 but is configurable; examples in source use
:8000. - When the User account is enabled, HTTP requests must include
Authorization: Basic <base64(user:password)>(default usernone, passwordwebrelay, base64bm9uZTp3ZWJyZWxheQ==). - MQTT v3.1.1; Sparkplug B supported as alternative payload format.
- SNMP supports v1, v2c, v3; community strings default to
webrelay(read and write). - Source does not enumerate which physical I/O channels the X-410 actually exposes (relays, digital I/O, analog inputs, 1-Wire sensors). I/O presence is determined by Local I/O Number assignment; consult the device setup or generated MIB/Modbus Address Table at runtime.
<!-- UNRESOLVED: device-side voltage/current/fault behavior not stated; firmware version not stated (one command branch requires v3.13.7.8+); default TCP port not stated as a configurable value beyond the example ":8000". -->
## Provenance
```yaml
source_domains:
- controlbyweb.com
source_urls:
- https://controlbyweb.com/support/cbw-integration-manual/
- https://controlbyweb.com/support/manuals/x-400-users-manual/
retrieved_at: 2026-06-30T15:10:13.320Z
last_checked_at: 2026-07-07T12:28:09.493Z
Verification Summary
verdict: verified
checked_at: 2026-07-07T12:28:09.493Z
matched_actions: 24
action_count: 24
confidence: medium
summary: "All 24 spec actions matched to source commands. HTTP GET endpoints, relay control variants, log/syslog access, and Modbus function codes verified. Transport YAML (tcp/http, port 80, auth none) confirmed in source. (4 unresolved item(s) noted in Known Gaps.)"
Known Gaps
- "source does not enumerate which relays/digital I/O/analog channels the X-410 physically exposes; addresses must be obtained from the device's generated Modbus Address Table at runtime."
- "source does not describe any device-side multi-step sequences"
- "source contains no safety warnings or interlock procedures."
- "device-side voltage/current/fault behavior not stated; firmware version not stated (one command branch requires v3.13.7.8+); default TCP port not stated as a configurable value beyond the example \":8000\"."
From the AI4AV catalog (https://ai4av.net) · ODbL-1.0