Summary
The ControlByWeb X-13S is an RS-485 thermocouple expansion peripheral that is carried by a host controller (X-400 Series / X-600M). The X-13S has no native IP stack of its own; all network control and monitoring happens through the host controller's built-in web server and protocol stack. This spec covers HTTP GET (XML/JSON), Modbus/TCP, SNMP (V1/V2c/V3), and MQTT (v3.1.1 / Sparkplug B) as documented in ControlByWeb's "Integrating with ControlByWeb Devices" manual.
Transport
# X-13S itself is RS-485 peripheral to host controller. Source documents the
# host's network interfaces (HTTP, Modbus/TCP, SNMP, MQTT). All four are
# carried over TCP/IP on the host.
protocols:
- http
- tcp # Modbus/TCP
- udp # SNMP typically UDP; source does not state transport, inferred from SNMP standard. See UNRESOLVED below.
addressing:
base_url: "http://{host-ip}" # host controller IP; X-13S has none of its own
port: 502 # Modbus/TCP (configurable under Advanced Network tab)
# UNRESOLVED: HTTP port not stated in source (only notes port required if "not port 80")
# UNRESOLVED: SNMP port not stated in source
# UNRESOLVED: MQTT broker port not stated in source
auth:
# Source documents an optional User account with HTTP Basic auth (Base64
# "name:password"). Modbus/TCP disabled when User account enabled.
type: basic_or_none # optional User account; "none" when account disabled (default)
notes: "When enabled, HTTP Authorization: Basic <base64(name:password)>. Default example credential in source: none:webrelay -> bm9uZTp3ZWJyZWxheQ==. Modbus disabled when User account enabled."
serial: {} # N/A - X-13S talks RS-485 ribbon to host, not user-facing serial. Omitted.
Traits
traits:
- queryable # inferred: state.xml/json reads + Modbus FC03 + SNMP Get return values
- levelable # inferred: registerX set + analog value writes via Modbus FC16
# No power on/off command in source (relays are I/O, not device power).
# No input/output routing commands in source.
Actions
# Coverage: all distinct commands documented in the integration manual.
# HTTP GET commands (state.xml / state.json / customState.xml / customState.json
# share parameter syntax; listed once each). Modbus function codes listed
# separately. SNMP PDUs listed separately.
# ----- HTTP GET: state reads -----
- id: http_get_state_xml
label: Read state.xml
kind: query
command: "GET /state.xml HTTP/1.1\r\n\r\n"
params: []
- id: http_get_state_json
label: Read state.json
kind: query
command: "GET /state.json HTTP/1.1\r\n\r\n"
params: []
- id: http_get_customstate_xml
label: Read customState.xml
kind: query
command: "GET /customState.xml HTTP/1.1\r\n\r\n"
params: []
- id: http_get_customstate_json
label: Read customState.json
kind: query
command: "GET /customState.json HTTP/1.1\r\n\r\n"
params: []
# ----- HTTP GET: relay control (parameterized over relay index X) -----
- id: http_relay_off
label: Set 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 local I/O number (1-based)
- id: http_relay_on
label: Set 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 local I/O number (1-based)
- id: http_relay_pulse_preset
label: Pulse Relay (preset duration)
kind: action
command: "GET /state.json?relay{X}=2 HTTP/1.1\r\n\r\n"
params:
- name: X
type: integer
description: Relay local I/O number (1-based)
- id: http_relay_pulse_custom
label: Pulse Relay (custom duration)
kind: action
command: "GET /state.json?pulseTime{X}={seconds}&relay{X}=2 HTTP/1.1\r\n\r\n"
params:
- name: X
type: integer
description: Relay local I/O number (1-based); pulseTime index must match relay index
- name: seconds
type: number
description: Pulse duration in seconds for this single pulse (does not persist)
notes: "pulseTime argument MUST come before relay{X}=2 in the query string."
# ----- HTTP GET: counter / timer resets (parameterized) -----
- id: http_set_ontime
label: Reset onTime
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 (1-based)
- name: value
type: number
description: New onTime value in seconds
- id: http_set_totalontime
label: Reset totalOnTime
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 (1-based)
- name: value
type: number
description: New totalOnTime value in seconds
- id: http_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 (1-based)
- name: value
type: number
description: New counter value
- id: http_set_register
label: Set Register
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 (1-based)
- name: value
type: number
description: New register value (e.g. 10.5)
# ----- HTTP GET: log files -----
- id: http_get_log_txt
label: Read data log (log.txt)
kind: query
command: "GET /log.txt HTTP/1.1\r\n\r\n"
params: []
- id: http_erase_log_txt
label: Erase data log
kind: action
command: "GET /log.txt?erase=1 HTTP/1.1\r\n\r\n"
params: []
- id: http_get_syslog_txt
label: Read system log (syslog.txt)
kind: query
command: "GET /syslog.txt HTTP/1.1\r\n\r\n"
params: []
notes: "Requires setup username and password."
- id: http_erase_syslog_txt
label: Erase system log
kind: action
command: "GET /syslog.txt?erase=1 HTTP/1.1\r\n\r\n"
params: []
# ----- Modbus/TCP function codes -----
- id: modbus_fc01_read_coils
label: Read Coils (FC 0x01)
kind: query
command: "MBAP header + 0x01 {startAddrHi} {startAddrLo} {qtyHi} {qtyLo}"
params:
- name: startAddr
type: integer
description: Starting coil address (refer to host Modbus map in Setup pages)
- name: qty
type: integer
description: Number of coils to read
notes: "Reads relays and digital I/O configured as outputs. Error FC 0x81; exception 0x02 = bad start/qty."
- id: modbus_fc02_read_discrete_inputs
label: Read Discrete Inputs (FC 0x02)
kind: query
command: "MBAP header + 0x02 {startAddrHi} {startAddrLo} {qtyHi} {qtyLo}"
params:
- name: startAddr
type: integer
description: Starting input address (refer to host Modbus map)
- name: qty
type: integer
description: Number of inputs to read
notes: "Reads digital inputs and digital I/O configured as inputs. Error FC 0x82; exception 0x02 = bad start/qty."
- id: modbus_fc03_read_holding_registers
label: Read Holding Registers (FC 0x03)
kind: query
command: "MBAP header + 0x03 {startAddrHi} {startAddrLo} {qtyHi} {qtyLo}"
params:
- name: startAddr
type: integer
description: Starting register address (refer to host Modbus map)
- name: qty
type: integer
description: Number of 16-bit registers to read; MUST be divisible by 2 (32-bit floats read in pairs)
notes: "Reads Vin, sensors, registers, counters, analog inputs. IEEE 754 float, endianness set in Advanced Network tab. NaN (0xFFFFFFFF) when sensor absent. Error FC 0x83."
- id: modbus_fc05_write_single_coil
label: Write Single Coil (FC 0x05)
kind: action
command: "MBAP header + 0x05 {addrHi} {addrLo} {valueHi} {valueLo}"
params:
- name: addr
type: integer
description: Coil address (refer to host Modbus map)
- name: value
type: enum
description: "0x0000 = OFF, 0xFF00 = ON"
notes: "Response mirrors 0x0000 or 0xFF00. Error FC 0x85; exceptions 0x01 not supported, 0x02 addr out of range, 0x03 padding."
- id: modbus_fc0f_write_multiple_coils
label: Write Multiple Coils (FC 0x0F)
kind: action
command: "MBAP header + 0x0F {startAddrHi} {startAddrLo} {qtyHi} {qtyLo} {byteCount} {digitalIOValueBytes}"
params:
- name: startAddr
type: integer
description: Starting coil address
- name: qty
type: integer
description: Number of coils to write
- name: byteCount
type: integer
description: qty divided by 8
- name: digitalIOValue
type: string
description: "Hex byte string 0x0000-0xFFFF; bit per output (e.g. 0xF0 = first 4 off, next 4 on)"
notes: "Error FC 0x8F; exceptions 0x01 not supported, 0x02 bad start/qty, 0x03 byte count out of range."
- id: modbus_fc10_write_multiple_registers
label: Write Multiple Registers (FC 0x10)
kind: action
command: "MBAP header + 0x10 {startAddrHi} {startAddrLo} {qtyHi} {qtyLo} {byteCount} {valueBytesIEEE754}"
params:
- name: startAddr
type: integer
description: Starting register address
- name: qty
type: integer
description: Number of 16-bit registers; MUST be divisible by 2
- name: value
type: number
description: IEEE 754 32-bit float value(s), endianness per Advanced Network tab
notes: "Sets writable analog I/O (registers, analog outputs, pulse duration). Ack responds with register quantity written. Error FC 0x90; exceptions 0x01 not supported, 0x02 addr/qty not even."
# ----- SNMP PDUs -----
- id: snmp_getrequest
label: SNMP GetRequest
kind: query
command: "SNMP GetRequest {oid}"
params:
- name: oid
type: string
description: Object identifier (RFC1213 standard OIDs or module MIB OIDs)
- id: snmp_getnextrequest
label: SNMP GetNextRequest
kind: query
command: "SNMP GetNextRequest {oid}"
params:
- name: oid
type: string
description: Object identifier
- id: snmp_getbulkrequest
label: SNMP GetBulkRequest
kind: query
command: "SNMP GetBulkRequest {oid}"
params:
- name: oid
type: string
description: Object identifier
- id: snmp_setrequest
label: SNMP SetRequest
kind: action
command: "SNMP SetRequest {oid} {value}"
params:
- name: oid
type: string
description: Object identifier
- name: value
type: string
description: Value to set
- id: snmp_trap
label: Send SNMP Trap
kind: event
command: "SNMP Trap (configured in Conditional / Scheduled tasks)"
params: []
notes: "Device-emitted; triggered on relay state change, sensor threshold, or supply voltage out of range."
- id: snmp_notification
label: Send SNMP Notification
kind: event
command: "SNMP Notification (V2c/V3; requires manager ack, retries on no response)"
params: []
# ----- MQTT operations -----
- id: mqtt_subscribe
label: MQTT Subscribe to Broker
kind: action
command: "MQTT SUBSCRIBE {topic}"
params:
- name: topic
type: string
description: Broker-defined topic
notes: "MQTT v3.1.1. Device subscribes per Broker tab config; receives I/O published by other devices."
- id: mqtt_publish
label: MQTT Publish to Broker
kind: action
command: "MQTT PUBLISH {topic} {payload}"
params:
- name: topic
type: string
description: Broker-defined topic
- name: payload
type: string
description: "Payload string; supports tokens like ${relay1}, ${register1}, ${vin}, ${ser}, etc. (see Variables)"
- id: sparkplugb_publish
label: Sparkplug B Publish
kind: action
command: "Sparkplug B PUBLISH {topic} {payload}"
params:
- name: topic
type: string
description: Sparkplug B-defined topic structure
- name: payload
type: string
description: Sparkplug B-formatted payload
notes: "Alternative to plain MQTT with defined topic naming and payload structure."
# ----- ControlByWeb Cloud DAT URL -----
- id: cloud_dat_read_state
label: Cloud DAT URL read state
kind: query
command: "GET https://api.controlbyweb.cloud/{datUrl}/state.json HTTP/1.1\r\n\r\n"
params:
- name: datUrl
type: string
description: Generated DAT URL token from ControlByWeb.Cloud API
- id: cloud_dat_control
label: Cloud DAT URL control
kind: action
command: "GET https://api.controlbyweb.cloud/{datUrl}/state.json?{params} HTTP/1.1\r\n\r\n"
params:
- name: datUrl
type: string
description: Generated DAT URL token
- name: params
type: string
description: "Same state.xml/json query params (e.g. relay1=1&relay2=1)"
notes: "Enables control without port forwarding. Does not facilitate peer-to-peer device comms."
Feedbacks
# State values returned in state.xml/state.json (X = local I/O number).
- id: digital_input_state
type: enum
values: [off, on]
source_tag: "digitalInputX / digitalIOX"
description: "0 = voltage not applied; 1 = voltage applied"
- id: relay_state
type: enum
values: [off, on]
source_tag: "relayX"
description: "0 = coil off; 1 = coil energized"
- id: analog_input_value
type: number
source_tag: "analogInputX"
- id: vin_value
type: number
source_tag: "vin"
description: "Scaled internal Vin measurement; always present"
- id: register_value
type: number
source_tag: "registerX"
- id: on_time
type: number
source_tag: "onTimeX"
description: "Seconds input has been ON since last ON transition"
- id: total_on_time
type: number
source_tag: "totalOnTimeX"
- id: count_value
type: number
source_tag: "countX"
- id: frequency_value
type: number
source_tag: "frequencyX"
- id: onewire_sensor_value
type: number
source_tag: "oneWireSensorX"
description: "x.x = sensor unreadable; otherwise current value (units optional via showUnits=1)"
- id: utc_time
type: number
source_tag: "utcTime"
description: "Seconds since 1970-01-01"
- id: timezone_offset
type: number
source_tag: "timezoneOffset"
- id: serial_number
type: string
source_tag: "serialNumber"
description: "Host controller serial (MAC format 00:00:00:00:00:00)"
# UNRESOLVED: X-13S-specific thermocouple tag name not enumerated in source - likely surfaces under oneWireSensorX or a dedicated thermocouple tag on the host. Confirm against host device state.xml.
Variables
# MQTT payload tokens documented in source (Section 4.1.4). These are
# substitution variables usable in MQTT publish payloads, not settable I/O.
- id: mqtt_token_mac
token: "${mac}"
description: "MAC Address"
- id: mqtt_token_firmware
token: "${ver}"
description: "Firmware Revision"
- id: mqtt_token_serial
token: "${ser}"
description: "Serial Number"
- id: mqtt_token_uptime
token: "${uptime}"
description: "Up Time"
- id: mqtt_token_ip
token: "${ip}"
description: "IP Address"
- id: mqtt_token_http_port
token: "${port}"
description: "HTTP Port"
- id: mqtt_token_https_port
token: "${httpsport}"
description: "HTTPS Port"
- id: mqtt_token_datetime
token: "${dateTime}"
description: "Epoch Time Stamp"
- id: mqtt_token_name
token: "${name}"
description: "Name (Control Page Header)"
- id: mqtt_token_model
token: "${model}"
description: "Model Number"
- id: mqtt_token_clientid
token: "${clientID}"
description: "ClientID"
- id: mqtt_token_digitalinput
token: "${digitalInputN}"
description: "Digital Input N (source lists 1-4)"
- id: mqtt_token_relay
token: "${relayN}"
description: "Relay N (source lists 1-4)"
- id: mqtt_token_vin
token: "${vin}"
description: "Vin"
- id: mqtt_token_register
token: "${registerN}"
description: "Register N (source lists register1)"
# SNMP RFC1213 standard objects (Section 3.1.1).
- id: snmp_sysDescr
oid: "system.sysDescr"
description: "Returns 'X-4xx'"
- id: snmp_sysObjectID
oid: "system.sysObjectID"
description: "Returns 'X4xx'"
- id: snmp_sysUpTime
oid: "system.sysUpTime"
description: "Hundredths of seconds since last power-on"
- id: snmp_sysName
oid: "system.sysName"
description: "Returns 'X-4xx*'"
# UNRESOLVED: module-specific SNMP OIDs not in source - must be obtained from generated MIB file (Setup → Advanced Network → Generate and Download MIB File).
Events
- id: snmp_trap_event
description: "SNMP trap sent on relay state change, sensor threshold reached, or supply voltage out of range. Configured as actions in Conditional and Scheduled tasks."
- id: remote_services_connection_string
description: "When Remote Services enabled (Advanced Network tab), device opens TCP V1 connection to external server at the configured Connection Interval and sends a connection string (static device info + user-defined string + state.xml). Expects 3-character ACK within 10 seconds or device closes connection. state.xml is also sent on logic-event 'send state' actions."
- id: mqtt_state_publish
description: "Device publishes I/O state to MQTT broker per Broker tab configuration."
Macros
# UNRESOLVED: no explicit multi-step sequences documented in source.
Safety
confirmation_required_for: []
interlocks:
- "Modbus/TCP communications disabled whenever User account is enabled (Modbus provides no password mechanism). Disable User account (default) and enable Modbus on Advanced Network tab to use Modbus."
- "Modbus/TCP connection times out and closes after 50 seconds of inactivity. Send periodic read request to keep alive."
- "Module limits Modbus/TCP to 2 simultaneous sockets; additional connections rejected."
- "Remote Services expects 3-character ACK within 10 seconds or device closes connection."
# UNRESOLVED: source contains no X-13S-specific interlock, power-sequencing, or thermocouple-handling safety procedures.
Notes
- The X-13S is an RS-485 thermocouple expansion peripheral with no native network interface. All commands in this spec target the host controller (X-400 Series or X-600M) that carries the X-13S channels; the X-13S surfaces as additional temperature sensor / one-wire slots on the host's I/O map.
- HTTP supports combining multiple arguments in one request:
/state.json?relay1=1&relay2=0. state.xml/jsonuses I/O type + local I/O number (relay1).customState.xml/jsonuses the CamelCase version of user-configured I/O names (myRegister1).- Modbus 32-bit sensor values read in 16-bit register pairs (qty must be divisible by 2). IEEE 754 float, endianness configurable in Advanced Network tab. Example: little-endian 0x800042A2 = 81.25.
- 0xFFFFFFFF (NaN) returned for absent temperature/humidity sensor.
- SNMP V1/V2c default read and write community strings:
webrelay(configurable). V3 uses USM (auth + privacy protocols, each with algorithm + password, plus shared security username). - SNMP supports V1, V2c, V3.
- MQTT version 3.1.1 supported; Sparkplug B is the alternative with structured topic naming and payload format.
- ControlByWeb Cloud DAT URLs enable HTTP control without port forwarding; do not facilitate peer-to-peer device comms. Version 2.0 of Remote Services reserved for ControlByWeb.Cloud.
Spec built. 36 actions (HTTP + Modbus FCs + SNMP PDUs + MQTT ops + Cloud DAT), feedbacks for every state tag, variables for MQTT tokens + SNMP standard OIDs, safety interlocks all from source text. X-13S is peripheral — spec notes all commands target host controller. Gaps marked UNRESOLVED.
## Provenance
```yaml
source_domains:
- controlbyweb.com
source_urls:
- https://controlbyweb.com/wp-content/uploads/2025/05/cbw-integration-and-protocols-manual.pdf
- https://www.controlbyweb.com/wp-content/uploads/2024/01/X-13S_manual_v1.1.pdf
- https://controlbyweb.com/support/cbw-integration-manual/
- https://controlbyweb.com/support/manuals/x-400-users-manual/
- https://controlbyweb.com/support/
retrieved_at: 2026-07-01T09:21:18.203Z
last_checked_at: 2026-07-07T11:11:01.174Z
```
## Verification Summary
```yaml
verdict: verified
checked_at: 2026-07-07T11:11:01.174Z
matched_actions: 33
action_count: 33
confidence: medium
summary: "All 33 spec actions matched literally to source commands; transport parameters verified; source coverage complete. (12 unresolved item(s) noted in Known Gaps.)"
```
## Known Gaps
```yaml
- "X-13S-specific tag names and Modbus addresses are not enumerated in this source. The source is a host-controller integration manual; the X-13S channels appear under the host's I/O map (e.g. oneWireSensor/temperature slots) and must be confirmed against the host device's Setup → Advanced Network → Modbus Address Table and the generated MIB file."
- "source does not state default TCP port for HTTP (mentions port 80 only as the \"unchanged\" case), SNMP port, or MQTT broker port."
- "HTTP port not stated in source (only notes port required if \"not port 80\")"
- "SNMP port not stated in source"
- "MQTT broker port not stated in source"
- "X-13S-specific thermocouple tag name not enumerated in source - likely surfaces under oneWireSensorX or a dedicated thermocouple tag on the host. Confirm against host device state.xml."
- "module-specific SNMP OIDs not in source - must be obtained from generated MIB file (Setup → Advanced Network → Generate and Download MIB File)."
- "no explicit multi-step sequences documented in source."
- "source contains no X-13S-specific interlock, power-sequencing, or thermocouple-handling safety procedures."
- "X-13S thermocouple channel count, mapping to host tag names, and Modbus addresses not in this source — obtain from host Setup pages → View Modbus Address Table and generated MIB file."
- "default HTTP/SNMP/MQTT port numbers not stated in source."
- "firmware version compatibility, voltage/current/power specs, and X-13S-specific wiring not in this integration manual."
```
---
From the AI4AV catalog (https://ai4av.net) · ODbL-1.0