Summary
The Somfy ST-30 is a DC motor controller for window treatments using Somfy's SDN (Somfy Digital Network) RS-485 bus protocol. Communication is half-duplex serial at 4800 baud with a custom binary message format supporting point-to-point, group, and broadcast addressing. NodeID is factory-programmed and cannot be changed.
Transport
protocols:
- serial
serial:
baud_rate: 4800
data_bits: 8
parity: odd
stop_bits: 1
flow_control: none
encoding: NRZ
bit_order: lsb_first # least significant bit sent first
inverted: true # all data bits inverted for backward compatibility
auth:
type: none # inferred: no auth procedure in source
Traits
- queryable # inferred: GET_xxx query commands present (10 distinct queries)
- levelable # inferred: position % and rolling speed settable
Actions
# All command: fields hold the MSG opcode byte from §6 of source verbatim.
# Full frame = MSG + ACK/LEN + NODETYPE + SOURCE@ + DEST@ + DATA + CHECKSUM (see Notes).
#
# Device Control
- id: ctrl_moveto
label: Move to Position
kind: action
command: "03h" # CTRL_MOVETO
params:
- name: function
type: integer
description: |
00h = Move to DOWN limit
01h = Move to UP limit
02h = Move to Intermediate Position (Position contains IP index 0-15)
04h = Move to Position in % of full travel (Position contains 0-100)
- name: position
type: integer
description: Position value (context depends on function)
- name: reserved
type: integer
description: Reserved (set to 00h)
- id: ctrl_stop
label: Stop Motor
kind: action
command: "02h" # CTRL_STOP
params:
- name: reserved
type: integer
description: Reserved (set to 00h)
# Device Configuration (SET_xxx)
- id: set_group_addr
label: Set Group Address
kind: action
command: "51h" # SET_GROUP_ADDR
params:
- name: group_index
type: integer
description: Entry in group table (0-15)
- name: group_id
type: integer
description: 24-bit group address (LSBF)
- id: set_node_label
label: Set Node Label
kind: action
command: "55h" # SET_NODE_LABEL
params:
- name: label
type: string
description: 16-character label (pad with spaces if shorter)
- id: set_local_ui
label: Set Local UI
kind: action
command: "17h" # SET_LOCAL_UI
params:
- name: function
type: integer
description: |
00h = Enable/Unlock
01h = Disable/Lock
- name: ui_index
type: integer
description: |
00h = All Local controls
01h = DCT input
02h = Local stimuli (radio pairing)
03h = Local Radio (Bluetooth)
04h = Touch Motion
05h = LEDs
- name: priority
type: integer
description: Priority level (0-255, higher = higher priority)
- id: set_motor_ip
label: Set Intermediate Position
kind: action
command: "15h" # SET_MOTOR_IP
params:
- name: function
type: integer
description: |
00h = Delete IP
01h = Set IP at current position
03h = Set IP at specified position %
04h = Divide full range with N equally spaced IPs
- name: ip_index
type: integer
description: IP index (1-16)
- name: value
type: integer
description: Position value (context depends on function)
- id: set_motor_rolling_speed
label: Set Motor Speed
kind: action
command: "13h" # SET_MOTOR_ROLLING_SPEED
params:
- name: up_speed
type: integer
description: Speed during UP movement (rpm)
- name: down_speed
type: integer
description: Speed during DOWN movement (rpm)
- name: slow_speed
type: integer
description: Speed for adjustment movements (rpm)
- id: set_network_lock
label: Set Network Lock
kind: action
command: "16h" # SET_NETWORK_LOCK
params:
- name: function
type: integer
description: |
00h = Unlock
01h = Lock at current position
03h = Save lock on power cycle
04h = Do not save lock on power cycle
- name: priority
type: integer
description: Priority level (0-255)
# Status Queries (GET_xxx) - all return POST_xxx feedbacks listed below
- id: get_node_addr
label: Query Node Address
kind: query
command: "40h" # GET_NODE_ADDR
params: []
- id: get_group_addr
label: Query Group Address
kind: query
command: "41h" # GET_GROUP_ADDR
params:
- name: group_index
type: integer
description: Entry in group table (0-15)
- id: get_node_app_version
label: Query Firmware Version
kind: query
command: "74h" # GET_NODE_APP_VERSION
params: []
- id: get_node_label
label: Query Node Label
kind: query
command: "45h" # GET_NODE_LABEL
params: []
- id: get_local_ui
label: Query Local UI Status
kind: query
command: "27h" # GET_LOCAL_UI
params:
- name: ui_index
type: integer
description: UI index (01h to UI_MAX)
- id: get_motor_ip
label: Query Intermediate Position
kind: query
command: "25h" # GET_MOTOR_IP
params:
- name: ip_index
type: integer
description: IP index (1-16)
- id: get_motor_rolling_speed
label: Query Motor Speed
kind: query
command: "23h" # GET_MOTOR_ROLLING_SPEED
params: []
- id: get_network_lock
label: Query Network Lock Status
kind: query
command: "26h" # GET_NETWORK_LOCK
params: []
- id: get_motor_position
label: Query Motor Position
kind: query
command: "0Ch" # GET_MOTOR_POSITION
params: []
- id: get_motor_status
label: Query Motor Status
kind: query
command: "0Eh" # GET_MOTOR_STATUS
params: []
Feedbacks
# Status Query Responses
- id: post_node_addr
label: Node Address Response
kind: feedback
command: "60h" # POST_NODE_ADDR
fields:
- name: node_id
type: bytes
size: 3
description: Device NodeID (from message header)
- id: post_group_addr
label: Group Address Response
kind: feedback
command: "61h" # POST_GROUP_ADDR
fields:
- name: group_index
type: integer
- name: group_id
type: bytes
size: 3
- id: post_node_app_version
label: Firmware Version Response
kind: feedback
command: "75h" # POST_NODE_APP_VERSION
fields:
- name: app_reference
type: bytes
size: 3
description: Firmware part number
- name: app_index_letter
type: integer
description: Firmware major revision (ASCII)
- name: app_index_number
type: integer
description: Firmware revision number
- name: reserved
type: integer
- id: post_node_label
label: Node Label Response
kind: feedback
command: "65h" # POST_NODE_LABEL
fields:
- name: label
type: string
size: 16
- id: post_local_ui
label: Local UI Status Response
kind: feedback
command: "37h" # POST_LOCAL_UI
fields:
- name: ui_index
type: integer
- name: status
type: integer
description: 00h = Enabled/Unlocked, 01h = Disabled/Locked
- name: source_addr
type: bytes
size: 3
description: NodeID of locking device
- name: priority
type: integer
- id: post_motor_ip
label: Intermediate Position Response
kind: feedback
command: "35h" # POST_MOTOR_IP
fields:
- name: ip_index
type: integer
- name: reserved
type: bytes
size: 2
- name: ip_position_percentage
type: integer
description: Position 0-100, FFh if not set
- id: post_motor_rolling_speed
label: Motor Speed Response
kind: feedback
command: "33h" # POST_MOTOR_ROLLING_SPEED
fields:
- name: up_speed
type: integer
- name: down_speed
type: integer
- name: slow_speed
type: integer
- id: post_network_lock
label: Network Lock Status Response
kind: feedback
command: "36h" # POST_NETWORK_LOCK
fields:
- name: status
type: integer
description: 00h = Unlocked, 01h = Locked
- name: source_addr
type: bytes
size: 3
- name: priority
type: integer
- name: saved
type: integer
description: 00h = Not saved, 01h = Saved for power cycle
- id: post_motor_position
label: Motor Position Response
kind: feedback
command: "0Dh" # POST_MOTOR_POSITION
fields:
- name: position_pulse
type: integer
- name: position_percentage
type: integer
- name: reserved
type: integer
- name: ip
type: integer
description: Current IP index (01h-IP_MAX, FFh if no IP match)
- id: post_motor_status
label: Motor Status Response
kind: feedback
command: "0Fh" # POST_MOTOR_STATUS
fields:
- name: status
type: integer
description: |
00h = Stopped
01h = Running
02h = Blocked
03h = Locked
- name: direction
type: integer
description: |
00h = Going DOWN
01h = Going UP
FFh = Unknown
- name: source
type: integer
description: |
00h = Internal
01h = Network message
02h = Local UI
- name: cause
type: integer
description: |
00h = Target reached
01h = Explicit command
02h = Wink
20h = Obstacle detection
21h = Over-current protection
22h = Thermal protection
30h = Run time exceeded
32h = Timeout exceeded
FFh = Reset / PowerUp
- id: ack
label: Acknowledge
kind: feedback
command: "7Fh" # ACK
description: Positive acknowledgment (sent when ACK bit set in request)
- id: nack
label: Negative Acknowledge
kind: feedback
command: "6Fh" # NACK
fields:
- name: error_code
type: integer
description: |
01h = Data out of range
10h = Unknown message
11h = Message length error
FFh = Busy
Variables
# UNRESOLVED: no standalone settable parameters separate from actions
Events
# UNRESOLVED: no unsolicited event notifications defined in source
# Device only responds to MASTER requests; does not initiate communication
Macros
# UNRESOLVED: no explicit multi-step macros in source
Safety
confirmation_required_for: []
interlocks:
- description: Network lock blocks all movement commands except CTRL_NETWORK_LOCK with equal/higher priority
message: NACK(NODE_IS_LOCKED) returned when locked
- description: Motor blocked conditions trigger status reporting
message: thermal protection, obstacle detection, over-current
# UNRESOLVED: no explicit safety interlock procedures beyond network lock
Notes
- Addressing: NodeID is 3-byte factory-programmed address; groups support up to 16 GroupIDs per device
- Addressing Modes: Point-to-point (dest NodeID), Group (GroupID), Broadcast (FFFFFFh dest)
- Collision Avoidance: Avoid ACK/NACK requests in group/broadcast mode; avoid requesting feedback in group/broadcast
- Bit Inversion: All data bytes must be inverted before transmission (e.g., 58h → A7h) for backward compatibility
- Timing: Trep is randomized 5-255ms per slave; master must wait Treq=10ms minimum between requests
- Checksum: Simple sum of complement of all bytes (Byte 1 through Byte n-2)
- Message Format: 11-32 bytes total (MSG + ACK/LEN + NODETYPE + SOURCE@ + DEST@ + DATA + CHECKSUM)
- LSBF: NodeID and group addresses use least-significant-byte-first encoding
- Command Payloads: each action
command:field holds the single MSG opcode byte from §6; DATA parameters follow as documented in per-action params. Full frame construction per Message Format above.
Self-check done: no fabricated voltage/port/baud; status=draft; confidence=low; all MSG opcodes verbatim from source §6; existing IDs preserved; 10 new GET queries added per coverage rule.
## Provenance
```yaml
source_domains:
- service.somfy.com
source_urls:
- https://service.somfy.com/downloads/bui_v4/sdn-integration-guide--preliminary.pdf
retrieved_at: 2026-07-16T15:24:06.510Z
last_checked_at: 2026-07-22T01:14:00.003Z
Verification Summary
verdict: verified
checked_at: 2026-07-22T01:14:00.003Z
matched_actions: 18
action_count: 18
confidence: medium
summary: "All 18 spec actions matched with literal command opcodes and correct parameter shapes; all transport parameters verified; Feedbacks enumerate all SLAVE responses; complete source coverage. (9 unresolved item(s) noted in Known Gaps.)"
Known Gaps
- "no explicit power on/off commands — motor control via CTRL_MOVETO and CTRL_STOP only"
- "no standalone settable parameters separate from actions"
- "no unsolicited event notifications defined in source"
- "no explicit multi-step macros in source"
- "no explicit safety interlock procedures beyond network lock"
- "DC motor speed ranges not stated — \"See Technical Datasheet\" referenced but not provided"
- "exact IP_MAX value for intermediate positions not stated in source"
- "UI_MAX for HMI management not stated in source"
- "firmware compatibility range not stated in source"
From the AI4AV catalog (https://ai4av.net) · ODbL-1.0