Summary

Spec for the Somfy URTSI II Series, an RS-232-to-RS485 bridge that exposes Somfy Digital Network (SDN) bus control of Somfy motorized window-covering products (Ø30 DC, Ø50 AC/DC, Glydea, RS485 RTS transmitter families). Source document is the SDN Protocol Integration Guide describing the half-duplex RS-485 bus protocol, message structure, and the SET_/CTRL_/GET_/POST_ command catalogue.

Transport

protocols:
  - serial
serial:
  baud_rate: 4800
  data_bits: 8
  parity: odd
  stop_bits: 1
  flow_control: none
  # UNRESOLVED: physical layer is RS-485 per source (half-duplex bus), not RS-232C
auth:
  type: none  # inferred: no auth procedure in source

Traits

- powerable       # inferred: motor stop/move controls imply power-managed devices
- routable        # inferred: position-move and intermediate-position commands present
- queryable       # inferred: GET_NODE_ADDR, GET_MOTOR_POSITION, GET_MOTOR_STATUS present
- levelable       # inferred: SET_MOTOR_ROLLING_SPEED (UP/DOWN/Slow rpm) present
- lockable        # inferred: SET_NETWORK_LOCK present

Actions

# NOTE: SDN is a binary protocol over RS-485. Each frame has:
#   Byte 1      = MSG
#   Byte 2      = ACK/LEN (ACK bit + frame length)
#   Byte 3      = NODE TYPE (source high-nibble always 0h for master; dest NodeType low-nibble)
#   Bytes 4-6   = SOURCE@ (LSB-first 3-byte NodeID)
#   Bytes 7-9   = DEST@   (LSB-first 3-byte NodeID; FFFFFFh = broadcast; 000000h = group)
#   Bytes 10-n  = DATA (per-message)
#   Byte n      = CHECKSUM = (Byte1 + … + Byte n-2) of the un-inverted payload
# All data bytes must be bitwise-inverted before going on the wire (§4.2).
# The `command:` field below shows the MSG byte + DATA template per source.

- id: get_node_addr
  label: Get Device NodeID
  kind: query
  command: "MSG=40h, DATA=<none>"
  params: []

- id: set_group_addr
  label: Set Group Address
  kind: action
  command: "MSG=51h, DATA=<GroupIndex[8bit 0-15], GroupID[24bit]>"
  params:
    - name: GroupIndex
      type: integer
      description: Entry in the device group table (0 to 15)
    - name: GroupID
      type: integer
      description: 24-bit group address (NodeID of the group controller)

- id: get_group_addr
  label: Get Group Address
  kind: query
  command: "MSG=41h, DATA=<GroupIndex[8bit 0-15]>"
  params:
    - name: GroupIndex
      type: integer
      description: Entry in the group table to read (0 to 15)

- id: set_node_label
  label: Set Node Text Label
  kind: action
  command: "MSG=55h, DATA=<Label[16-char string, pad with spaces]>"
  params:
    - name: Label
      type: string
      description: Up to 16 ASCII characters, space-padded to length 16

- id: get_node_label
  label: Get Node Text Label
  kind: query
  command: "MSG=45h, DATA=<none>"

- id: get_node_app_version
  label: Get Firmware Version
  kind: query
  command: "MSG=74h, DATA=<none>"

- id: set_local_ui
  label: Set Local HMI (Lock/Enable)
  kind: action
  command: "MSG=17h, DATA=<Function[8bit 0-1], UI_Index[8bit 0-5], Priority[8bit 0-FFh]>"
  params:
    - name: Function
      type: integer
      description: "0h=Enable/Unlock, 1h=Disable/Lock"
    - name: UI_Index
      type: integer
      description: "0h=All, 1h=DCT input, 2h=Local stimuli, 3h=Local Radio (e.g. Bluetooth), 4h=Touch Motion, 5h=LEDs"
    - name: Priority
      type: integer
      description: 0-FFh; greater number = higher priority. Must be ≥ current lock priority or NACK(LOW_PRIORITY).

- id: get_local_ui
  label: Get Local HMI Status
  kind: query
  command: "MSG=27h, DATA=<UI_Index[8bit 1-UI_MAX]>"
  params:
    - name: UI_Index
      type: integer
      description: "1-UI_MAX (per SET_LOCAL_UI table)"

- id: set_motor_ip
  label: Set Intermediate Position
  kind: action
  command: "MSG=15h, DATA=<Function[8bit 0-4], IP_Index[8bit 1-16], Value[16bit]>"
  params:
    - name: Function
      type: integer
      description: "0h=Delete IP (Value ignored), 1h=Set IP at current position (Value ignored), 3h=Set IP at Value% position, 4h=Divide full range into Value equal IPs (IP_Index ignored)"
    - name: IP_Index
      type: integer
      description: 1 to 16 (ignored when Function=4h)
    - name: Value
      type: integer
      description: Position in % (Function=3h) or IP count (Function=4h); 16-bit

- id: get_motor_ip
  label: Get Intermediate Position
  kind: query
  command: "MSG=25h, DATA=<IP_Index[8bit 1-16]>"
  params:
    - name: IP_Index
      type: integer
      description: 1 to 16

- id: set_motor_rolling_speed
  label: Set Motor Rolling Speed
  kind: action
  command: "MSG=13h, DATA=<UP_Speed[8bit], DOWN_Speed[8bit], Slow_Speed[8bit]>"
  params:
    - name: UP_Speed
      type: integer
      description: Speed during UP movement (rpm); range per device technical datasheet
    - name: DOWN_Speed
      type: integer
      description: Speed during DOWN movement (rpm); range per device technical datasheet
    - name: Slow_Speed
      type: integer
      description: Speed for adjustment movements (rpm); range per device technical datasheet

- id: get_motor_rolling_speed
  label: Get Motor Rolling Speed
  kind: query
  command: "MSG=23h, DATA=<none>"

- id: set_network_lock
  label: Set Network Lock
  kind: action
  command: "MSG=16h, DATA=<Function[8bit 0-4], Priority[8bit 0-FFh]>"
  params:
    - name: Function
      type: integer
      description: "0h=Unlock, 1h=Lock at current position, 3h=Save lock across power-cycle (Priority ignored), 4h=Do not save lock across power-cycle (Priority ignored)"
    - name: Priority
      type: integer
      description: 0-FFh; greater = higher priority. Ignored when Function=3h or 4h.

- id: get_network_lock
  label: Get Network Lock State
  kind: query
  command: "MSG=26h, DATA=<none>"

- id: ctrl_moveto
  label: Move to Position
  kind: action
  command: "MSG=03h, DATA=<Function[8bit], Position[16bit], Reserved[8bit]>"
  params:
    - name: Function
      type: integer
      description: "0h=Move to DOWN limit (Position ignored), 1h=Move to UP limit (Position ignored), 2h=Move to Intermediate Position (Position=IP index 0-15), 4h=Move to Position in % (Position=0-100)"
    - name: Position
      type: integer
      description: IP index (Function=2h) or % (Function=4h); 16-bit; ignored when Function=0h or 1h
    - name: Reserved
      type: integer
      description: 8-bit reserved; set 00h or FFh

- id: ctrl_stop
  label: Stop Motor
  kind: action
  command: "MSG=02h, DATA=<Reserved[8bit]>"
  params:
    - name: Reserved
      type: integer
      description: 8-bit reserved; set 00h

- id: get_motor_position
  label: Get Motor Position
  kind: query
  command: "MSG=0Ch, DATA=<none>"

- id: get_motor_status
  label: Get Motor Status
  kind: query
  command: "MSG=0Eh, DATA=<none>"

Feedbacks

- id: post_node_addr
  type: object
  description: "MSG=60h, no DATA. Reply to GET_NODE_ADDR; address carried in frame header (SOURCE@)."

- id: post_group_addr
  type: object
  description: "MSG=61h, DATA=<GroupIndex[8bit], GroupID[24bit]> - reply to GET_GROUP_ADDR."

- id: post_node_app_version
  type: object
  description: "MSG=75h, DATA=<App_Reference[24bit], App_IndexLetter[8bit ASCII 41h-5Ah], App_IndexNumber[8bit], Reserved[8bit]> - firmware Part Number + major letter + revision."

- id: post_node_label
  type: object
  description: "MSG=65h, DATA=<Label[16-char string]> - reply to GET_NODE_LABEL."

- id: post_local_ui
  type: object
  description: "MSG=37h, DATA=<UI_Index[8bit], Status[8bit 0-1], Source_Addr[24bit], Priority[8bit]>. Status 0h=Enabled, 1h=Disabled."

- id: post_motor_ip
  type: object
  description: "MSG=35h, DATA=<IP_Index[8bit 1-16], Reserved[16bit], IP_position_percentage[8bit 0-100, FFh=not set]> - reply to GET_MOTOR_IP."

- id: post_motor_rolling_speed
  type: object
  description: "MSG=33h, DATA=<UP_Speed[8bit], DOWN_Speed[8bit], Slow_Speed[8bit]> - reply to GET_MOTOR_ROLLING_SPEED."

- id: post_network_lock
  type: object
  description: "MSG=36h, DATA=<Status[8bit 0-1], Source_Addr[24bit], Priority[8bit], Saved[8bit 0-1]>. Status 0h=Unlocked, 1h=Locked. Saved 0h=not restored on power-cycle, 1h=restored."

- id: post_motor_position
  type: object
  description: "MSG=0Dh, DATA=<Position_pulse[16bit], Position_percentage[8bit 0-100], Reserved[8bit], IP[8bit 1-IP_MAX, FFh=not on any IP]>."

- id: post_motor_status
  type: object
  description: "MSG=0Fh, DATA=<Status[8bit], Direction[8bit], Source[8bit], Cause[8bit]>."
  values:
    Status:
      - "00h=Stopped"
      - "01h=Running"
      - "02h=Blocked (thermal, obstacle)"
      - "03h=Locked (NETWORK_LOCK)"
    Direction:
      - "00h=Going DOWN (or last direction if stopped)"
      - "01h=Going UP"
      - "FFh=Unknown"
    Source:
      - "00h=Internal (limit/IP reached, over-current, obstacle, thermal)"
      - "01h=Network message (SDN bus)"
      - "02h=Local UI (DCT, local stimulus, local wireless)"
    Cause:
      - "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 (CTRL_MOVE > 2 min)"
      - "FFh=Reset / Power Up"

- id: ack
  type: object
  description: "MSG=7Fh, no DATA. Sent only when ACK bit set in the request; confirms settings saved or control execution started."

- id: nack
  type: object
  description: "MSG=6Fh, DATA=<ErrorCode[8bit 01h-FFh]>. Sent when ACK requested but message cannot be processed."
  values:
    ErrorCode:
      - "01h=Data out of range"
      - "10h=Unknown message"
      - "11h=Message length error"
      - "FFh=Busy - cannot process message"

Variables

# Discrete enumerated by the SET_xxx actions above.
# - id: intermediate_position
#   description: Motor intermediate position (1-16) with associated percentage 0-100.
#   set_by: set_motor_ip
#   read_by: get_motor_ip
# - id: rolling_speed
#   description: UP / DOWN / Slow rpm triplet for DC motors.
#   set_by: set_motor_rolling_speed
#   read_by: get_motor_rolling_speed
# - id: network_lock_priority
#   description: 0-FFh priority level gating network control.
#   set_by: set_network_lock
#   read_by: get_network_lock
# - id: hmi_lock_state
#   description: Per-UI_Index enable/disable + priority + source address.
#   set_by: set_local_ui
#   read_by: get_local_ui

Safety

confirmation_required_for:
  - ctrl_moveto  # implied: motor movement; "EXECUTION is started" but not finished per ACK semantics
interlocks:
  - SET_LOCAL_UI may be re-set/removed only by another SET_LOCAL_UI with ≥ current lock priority, else NACK(LOW_PRIORITY).
  - SET_NETWORK_LOCK prevents all CTRL_XXX, SET_MOTOR_LIMITS, SET_TILT_LIMITS from other than ≥ priority sources (NACK NODE_IS_LOCKED).
  - When SET_NETWORK_LOCK Function=3h (Save) used, the lock is restored at next power-on.
# UNRESOLVED: no explicit user-facing safety warnings about entanglement, pinch hazards, or
# human-load interlocks in the source. Motor-level thermal/obstacle/over-current protection is
# reported via POST_MOTOR_STATUS Cause bytes 20h/21h/22h but is firmware-internal, not protocol-gated.

Notes

  • Bus = RS-485, not RS-232C. Source §3–§4 explicitly describe a half-duplex RS-485 bus with 4800/8O1, NRZ, LSB-first, with all data bits bitwise-inverted before transmission (§4.2). The URTSI II host-facing connector is RS-232C, but the SDN commands documented here are the bus-side frames. The bridge translation itself is not described in this source.
  • Timings (§4.3): Master must wait ≥10 ms (Treq) after bus activity before transmitting; slave reply latency Trep = 5–255 ms (partially randomized); bus free timeout Tfree = 3 ms; max inter-character gap Tc ≤ 1 ms.
  • Addressing (§3.4, §5.4): DEST@ = FFFFFFh → broadcast; DEST@ = 000000h → group (uses each device's 16-entry group table); any other NodeID → point-to-point. SOURCE@ / DEST@ are LSB-first.
  • Acknowledgements (§3.6): Recommended for production use. NACK or timeout should trigger retry. No ACK on status requests (POST_xxx is the feedback).
  • Collisions (§3.7): Avoid requesting feedback or ACK in group/broadcast modes to lower collision risk.
  • NACK error code 6Fh carries a single ErrorCode byte in DATA[0] (see Feedbacks). Implemented across all products per source.
  • CTRL_STOP (§6.4.2): No speed ramp-down — motor is stopped immediately.
  • POST_MOTOR_POSITION returns position even while the motor is moving.

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:18.589Z
last_checked_at: 2026-06-02T22:14:53.690Z

Verification Summary

verdict: verified
checked_at: 2026-06-02T22:14:53.690Z
matched_actions: 18
action_count: 18
confidence: medium
summary: "All 18 spec actions traced to source (dip-safe re-verify). (6 unresolved item(s) noted in Known Gaps.)"

Known Gaps

- "Host-side RS-232 framing on the URTSI II is not documented in the refined source; this spec covers the bus-side SDN protocol."
- "physical layer is RS-485 per source (half-duplex bus), not RS-232C"
- "All data bits must be inverted (bitwise NOT) before transmission; least-significant-bit-first ordering; NRZ character coding. Documented in source §4.2."
- "no explicit user-facing safety warnings about entanglement, pinch hazards, or"
- "per-device UP/DOWN/Slow rpm ranges are not in the source — referenced to a device technical datasheet."
- "SET_MOTOR_LIMITS and SET_TILT_LIMITS are referenced in §6.3.4 remarks but not defined in the refined excerpt."

From the AI4AV catalog (https://ai4av.net) · ODbL-1.0