Summary
Spec for the Somfy RS485 RTS Transmitter (NodeType 05h) on the Somfy Digital Network (SDN) bus. Covers the asynchronous serial/RS-485 frame format, message identifiers (GET/SET/CTRL/POST/ACK/NACK), and the device-management, configuration, control, and status messages documented in the SDN Protocol Integration Guide.
Transport
protocols:
- serial
serial:
baud_rate: 4800
data_bits: 8
parity: odd
stop_bits: 1
flow_control: none # UNRESOLVED: no flow control stated; default none
physical_layer: RS485 # UNRESOLVED: not a transport spec field; documented in source
bit_order: LSB_first # UNRESOLVED: documented in source §4.2
data_inversion: true # UNRESOLVED: documented in source §4.2 (NOT applied before TX)
auth:
type: none # inferred: no auth procedure in source
# Frame layout (source §5), 11-32 bytes total, all values transmitted
# LSB-first and bit-inverted (source §4.2 - actual bus byte = NOT(frame_byte)):
# MSG | ACK/LEN | NODE_TYPE | SOURCE@ (3 bytes) | DEST@ (3 bytes) | DATA (0-21 bytes) | CHK
# CHK = sum of frame bytes 1..n-2 (source §5.6)
#
# Bus timing (source §4.3):
# Tc max 1ms between consecutive chars
# Tfree 3ms bus free timeout
# Trep 5-255ms slave reply delay (partially randomized)
# Treq min 10ms master quiet before next request
Traits
- queryable # inferred: multiple GET_xxx commands
- routable # inferred: group + broadcast + NodeType filtering in §3.4
- levelable # inferred: SET_MOTOR_ROLLING_SPEED present
Actions
# Command field format: "<MSG> <ACK/LEN> <NODE_TYPE> <SRC@:3> <DST@:3> <DATA...> <CHK>"
# Each placeholder <...> is replaced by the implementer; CHK = sum(MSG..last DATA byte)
# Addressing modes (source §3.4): point-to-point (SRC=NodeID, DST=NodeID),
# group (SRC=GroupID, DST=000000h), broadcast (SRC=NodeID, DST=FFFFFFh).
# When ACK bit (B7 of byte 2) = 1, slave responds with ACK(7Fh) or NACK(6Fh).
# ===== Device Management =====
- id: get_node_addr
label: Get Node Address
kind: query
command: "40 <ACK/LEN=0|80h> <NODE_TYPE=05h> <SRC@> <DST@=000000h|broadcast> <CHK>"
params: []
- id: post_node_addr
label: Node Address Report (slave → master)
kind: feedback
command: "60 <LEN=0> <NODE_TYPE=05h> <SRC@=responding_NodeID> <DST@> <CHK>"
params: []
- id: set_group_addr
label: Set Group Address
kind: action
command: "51 <ACK/LEN=84h> <NODE_TYPE=05h> <SRC@> <DST@=target_NodeID> {group_index} {group_id_3bytes} <CHK>"
params:
- name: group_index
type: integer
description: Group table slot 0..15
- name: group_id
type: bytes
description: 24-bit group address (3 bytes, LSBF)
- id: get_group_addr
label: Get Group Address
kind: query
command: "41 <ACK/LEN=81h> <NODE_TYPE=05h> <SRC@> <DST@=target_NodeID> {group_index} <CHK>"
params:
- name: group_index
type: integer
description: Group table slot 0..15
- id: post_group_addr
label: Group Address Report (slave → master)
kind: feedback
command: "61 <LEN=84h> <NODE_TYPE=05h> <SRC@=responding_NodeID> <DST@> {group_index} {group_id_3bytes} <CHK>"
params: []
- id: ack
label: Acknowledge
kind: feedback
command: "7F <LEN=0> <NODE_TYPE=05h> <SRC@=responding_NodeID> <DST@=requester> <CHK>"
params: []
- id: nack
label: Negative Acknowledge / Error
kind: feedback
command: "6F <LEN=81h> <NODE_TYPE=05h> <SRC@=responding_NodeID> <DST@=requester> {error_code} <CHK>"
params:
- name: error_code
type: enum
description: "01h=data out of range, 10h=unknown message, 11h=length error, FFh=busy"
# ===== Device Information =====
- id: get_node_app_version
label: Get Firmware Version
kind: query
command: "74 <ACK/LEN=0|80h> <NODE_TYPE=05h> <SRC@> <DST@=target_NodeID> <CHK>"
params: []
- id: post_node_app_version
label: Firmware Version Report (slave → master)
kind: feedback
command: "75 <LEN=86h> <NODE_TYPE=05h> <SRC@=responding_NodeID> <DST@> {app_ref_3bytes} {app_index_letter} {app_index_number} {reserved} <CHK>"
params: []
- id: set_node_label
label: Set Node Text Label
kind: action
command: "55 <ACK/LEN=90h> <NODE_TYPE=05h> <SRC@> <DST@=target_NodeID> {label_16_bytes} <CHK>"
params:
- name: label
type: string
description: 16 ASCII characters, pad with 20h
- id: get_node_label
label: Get Node Text Label
kind: query
command: "45 <ACK/LEN=0|80h> <NODE_TYPE=05h> <SRC@> <DST@=target_NodeID> <CHK>"
params: []
- id: post_node_label
label: Node Text Label Report (slave → master)
kind: feedback
command: "65 <LEN=90h> <NODE_TYPE=05h> <SRC@=responding_NodeID> <DST@> {label_16_bytes} <CHK>"
params: []
# ===== Device Configuration =====
- id: set_local_ui
label: Set Local UI (lock/enable)
kind: action
command: "17 <ACK/LEN=83h> <NODE_TYPE=05h> <SRC@> <DST@=target_NodeID> {function} {ui_index} {priority} <CHK>"
params:
- name: function
type: enum
description: "00h=enable/unlock, 01h=disable/lock"
- name: ui_index
type: enum
description: "00h=all, 01h=DCT input, 02h=local stimuli, 03h=local radio, 04h=touch motion, 05h=LEDs"
- name: priority
type: integer
description: 0..255; higher = higher priority
- id: get_local_ui
label: Get Local UI Status
kind: query
command: "27 <ACK/LEN=81h> <NODE_TYPE=05h> <SRC@> <DST@=target_NodeID> {ui_index} <CHK>"
params:
- name: ui_index
type: integer
description: 1..UI_MAX
- id: post_local_ui
label: Local UI Status Report (slave → master)
kind: feedback
command: "37 <LEN=85h> <NODE_TYPE=05h> <SRC@=responding_NodeID> <DST@> {ui_index} {status} {source_addr_3bytes} {priority} <CHK>"
params: []
- id: set_motor_ip
label: Set Intermediate Position
kind: action
command: "15 <ACK/LEN=84h> <NODE_TYPE=05h> <SRC@> <DST@=target_NodeID> {function} {ip_index} {value_lo} {value_hi} <CHK>"
params:
- name: function
type: enum
description: "00h=delete IP, 01h=set at current, 03h=set at % (Value=0..100), 04h=divide range into N IPs"
- name: ip_index
type: integer
description: 1..16
- name: value
type: integer
description: 16-bit; interpretation depends on function
- id: get_motor_ip
label: Get Intermediate Position
kind: query
command: "25 <ACK/LEN=81h> <NODE_TYPE=05h> <SRC@> <DST@=target_NodeID> {ip_index} <CHK>"
params:
- name: ip_index
type: integer
description: 1..16
- id: post_motor_ip
label: Intermediate Position Report (slave → master)
kind: feedback
command: "35 <LEN=84h> <NODE_TYPE=05h> <SRC@=responding_NodeID> <DST@> {ip_index} {reserved_lo} {reserved_hi} {ip_position_percentage} <CHK>"
params: []
- id: set_motor_rolling_speed
label: Set Motor Rolling Speed (DC motors only)
kind: action
command: "13 <ACK/LEN=83h> <NODE_TYPE=05h> <SRC@> <DST@=target_NodeID> {up_speed} {down_speed} {slow_speed} <CHK>"
params:
- name: up_speed
type: integer
description: rpm; range per device technical datasheet
- name: down_speed
type: integer
description: rpm; range per device technical datasheet
- name: slow_speed
type: integer
description: rpm; range per device technical datasheet
- id: get_motor_rolling_speed
label: Get Motor Rolling Speed
kind: query
command: "23 <ACK/LEN=0|80h> <NODE_TYPE=05h> <SRC@> <DST@=target_NodeID> <CHK>"
params: []
- id: post_motor_rolling_speed
label: Motor Rolling Speed Report (slave → master)
kind: feedback
command: "33 <LEN=83h> <NODE_TYPE=05h> <SRC@=responding_NodeID> <DST@> {up_speed} {down_speed} {slow_speed} <CHK>"
params: []
- id: set_network_lock
label: Set Network Lock
kind: action
command: "16 <ACK/LEN=82h> <NODE_TYPE=05h> <SRC@> <DST@=target_NodeID> {function} {priority} <CHK>"
params:
- name: function
type: enum
description: "00h=unlock, 01h=lock, 03h=save lock on power cycle, 04h=do not save lock on power cycle"
- name: priority
type: integer
description: 0..255; required for functions 00h/01h, ignored for 03h/04h
- id: get_network_lock
label: Get Network Lock Status
kind: query
command: "26 <ACK/LEN=0|80h> <NODE_TYPE=05h> <SRC@> <DST@=target_NodeID> <CHK>"
params: []
- id: post_network_lock
label: Network Lock Status Report (slave → master)
kind: feedback
command: "36 <LEN=86h> <NODE_TYPE=05h> <SRC@=responding_NodeID> <DST@> {status} {source_addr_3bytes} {priority} {saved} <CHK>"
params: []
# ===== Device Control =====
- id: ctrl_moveto
label: Move to Position
kind: action
command: "03 <ACK/LEN=84h> <NODE_TYPE=05h> <SRC@> <DST@=target_NodeID> {function} {position_lo} {position_hi} {reserved=00h} <CHK>"
params:
- name: function
type: enum
description: "00h=down limit, 01h=up limit, 02h=IP index (Position=0..15), 04h=position % (Position=0..100)"
- name: position
type: integer
description: 16-bit; meaning depends on function
- id: ctrl_stop
label: Stop
kind: action
command: "02 <ACK/LEN=81h> <NODE_TYPE=05h> <SRC@> <DST@=target_NodeID> {reserved=00h} <CHK>"
params: []
# UNRESOLVED: no power ramp-down - motor stops immediately (source §6.4.2)
# ===== Device Status =====
- id: get_motor_position
label: Get Motor Position
kind: query
command: "0C <ACK/LEN=0|80h> <NODE_TYPE=05h> <SRC@> <DST@=target_NodeID> <CHK>"
params: []
- id: post_motor_position
label: Motor Position Report (slave → master)
kind: feedback
command: "0D <LEN=85h> <NODE_TYPE=05h> <SRC@=responding_NodeID> <DST@> {position_pulse_lo} {position_pulse_hi} {position_percentage} {reserved} {ip} <CHK>"
params: []
- id: get_motor_status
label: Get Motor Status
kind: query
command: "0E <ACK/LEN=0|80h> <NODE_TYPE=05h> <SRC@> <DST@=target_NodeID> <CHK>"
params: []
- id: post_motor_status
label: Motor Status Report (slave → master)
kind: feedback
command: "0F <LEN=84h> <NODE_TYPE=05h> <SRC@=responding_NodeID> <DST@> {status} {direction} {source} {cause} <CHK>"
params:
- name: status
type: enum
description: "00h=stopped, 01h=running, 02h=blocked, 03h=locked"
- name: direction
type: enum
description: "00h=going down, 01h=going up, FFh=unknown"
- name: source
type: enum
description: "00h=internal, 01h=network message, 02h=local UI"
- name: cause
type: enum
description: "00h=target reached, 01h=explicit cmd, 02h=wink, 20h=obstacle, 21h=over-current, 22h=thermal, 30h=run time exceeded, 32h=timeout (CTRL_MOVE > 2min), FFh=reset/power up"
Feedbacks
- id: node_address
type: bytes
description: 3-byte NodeID returned in POST_NODE_ADDR (60h)
- id: group_address
type: bytes
description: 3-byte GroupID returned in POST_GROUP_ADDR (61h)
- id: firmware_version
type: object
description: POST_NODE_APP_VERSION (75h) - 24-bit App_Reference, ASCII major letter, minor number, reserved
- id: node_label
type: string
description: 16-byte ASCII label returned in POST_NODE_LABEL (65h)
- id: local_ui_status
type: object
description: POST_LOCAL_UI (37h) - UI_Index, Status (00h=enabled/01h=disabled), Source_Addr, Priority
- id: motor_ip
type: object
description: POST_MOTOR_IP (35h) - IP_index, position percentage (FFh=not set)
- id: motor_rolling_speed
type: object
description: POST_MOTOR_ROLLING_SPEED (33h) - UP, DOWN, Slow speeds
- id: network_lock_status
type: object
description: POST_NETWORK_LOCK (36h) - Status, Source_Addr, Priority, Saved flag
- id: motor_position
type: object
description: POST_MOTOR_POSITION (0Dh) - pulse count, percentage, IP index (FFh=no match)
- id: motor_status
type: object
description: POST_MOTOR_STATUS (0Fh) - Status/Direction/Source/Cause
- id: ack_nack
type: enum
description: ACK(7Fh) success or NACK(6Fh) error code (01h/10h/11h/FFh)
Variables
- id: group_table
description: Up to 16 GroupID entries per device (GroupIndex 0..15)
- id: node_label
description: 16-char ASCII label per device
- id: local_ui_locks
description: Per UI_Index (00h..05h) enable/lock state with priority 0..255
- id: motor_intermediate_positions
description: Up to 16 IP slots (IP_Index 1..16), position 0..100%
- id: motor_rolling_speed
description: UP/DOWN/Slow speed triplet (DC motors only)
- id: network_lock
description: Lock state + priority + power-cycle persist flag
Safety
confirmation_required_for:
- ctrl_moveto # physical movement; could pinch/crush
- set_motor_ip # modifies limit positions
interlocks:
- "When NETWORK_LOCK=locked, all CTRL_xxx and limit-modifying SET messages are rejected (NACK NODE_IS_LOCKED) unless sender priority ≥ lock priority"
- "Lock may be re-set or removed only by message with equal or higher priority (source §6.3.4)"
# UNRESOLVED: source does not document thermal-protection thresholds, obstacle-detection sensitivity, or run-time/timeout limits - do not infer.
Notes
- Source protocol is RS-485 (not RS-232C as hinted in input); physical-layer detail recorded as
serial.physical_layerin Transport. - All bytes on the wire are bit-inverted (LSB-first) before transmission: actual_bus_byte = NOT(frame_byte) (source §4.2).
- No synchronization byte; message boundary detected by bus inactivity (≥ Tfree = 3 ms).
- Acknowledged control messages should be retried on NACK or ACK timeout ≥ Treq (10 ms) (source §3.6).
- In group/broadcast modes the source recommends NOT requesting ACK or feedback to avoid collision risk (source §3.7).
- Each device's 3-byte NodeID is factory-programmed and not changeable; recycle period 3–5 years (source §3.2.1).
- POST messages are slave-originated responses to GET requests and are also enumerated above for completeness so an implementer can recognize unsolicited-looking frames.
- Firmware major letter is ASCII 41h..5Ah (A..Z); minor number is separate byte (source §6.2.1).
Provenance
source_domains:
- service.somfy.com
source_urls:
- https://service.somfy.com/downloads/bui_v4/sdn-integration-guide--preliminary.pdf
retrieved_at: 2026-04-29T08:47:09.501Z
last_checked_at: 2026-06-02T05:46:17.108Z
Verification Summary
verdict: verified
checked_at: 2026-06-02T05:46:17.108Z
matched_actions: 30
action_count: 30
confidence: medium
summary: "All 30 spec actions matched literally to source commands with correct hex codes; transport parameters verified verbatim; source command catalogue fully represented. (8 unresolved item(s) noted in Known Gaps.)"
Known Gaps
- "source describes the protocol/family, not a specific SKU. No part number stated."
- "no flow control stated; default none"
- "not a transport spec field; documented in source"
- "documented in source §4.2"
- "documented in source §4.2 (NOT applied before TX)"
- "no power ramp-down - motor stops immediately (source §6.4.2)"
- "source does not document thermal-protection thresholds, obstacle-detection sensitivity, or run-time/timeout limits - do not infer."
- "no specific SKU / part number, electrical limits, default-firmware behavior post-reset, or obstacle/thermal thresholds stated in source."
From the AI4AV catalog (https://ai4av.net) · ODbL-1.0