9.7 KiB
Riedel RRCS for Home Assistant
A custom integration that talks to Riedel Router Control Software (RRCS), the third-party gateway to an Artist intercom system. Built against the RRCS 8.9.1.Rev1 interface specification.
It gives you logic sources and GPIOs as real Home Assistant entities, alarms and panel events on the event bus, and services for crosspoints, keys, labels and gains.
Integration, not add-on. Home Assistant add-ons are Supervisor-only Docker containers and cannot create entities. This is a custom integration, so it works the same on HAOS, Home Assistant Container and Core.
What you get
Entities
| Platform | Entity | Source |
|---|---|---|
switch |
One per logic source | GetAllLogicSources_v2 / SetLogicSourceState |
switch |
One per GP output | GetGpOutputState / SetGpOutput |
binary_sensor |
One per GP input | GetGpInputState |
binary_sensor |
Artist connection | IsConnectedToArtist |
sensor |
Gateway state (Working / Standby) | GetState |
sensor |
Active crosspoints | GetAllActiveXpsCount |
sensor |
RRCS version, logic source count | diagnostic, disabled by default |
event |
Alarm | ring, node, client and port alarms (ch. 9.7) |
event |
Send string | SendString / SendStringOff |
event |
Panel spy | panel spy events, disabled by default |
Services
set_xp, kill_xp, set_xp_volume, set_gp_output, set_logic_source,
press_key, set_key_label, clear_key_label, set_port_alias,
set_input_gain, set_output_gain, and call_method as an escape hatch to any
RRCS method that has no dedicated service.
Events
Every inbound notification is fired on the bus as riedel_rrcs_notification
with entry_id, method and params.
Installation
HACS
Add this repository as a custom repository of type Integration, install it, restart Home Assistant, then add Riedel RRCS from Settings → Devices & Services → Add Integration.
Manual
Copy custom_components/riedel_rrcs/ into your Home Assistant config/custom_components/
directory and restart.
Configuration
Everything is done in the UI. The initial dialog asks for:
| Field | Notes |
|---|---|
| Host | The machine running RRCS |
| Port | 8193 by default |
| RPC path | / unless the gateway is behind a reverse proxy |
| Request timeout | Seconds |
| Transaction key prefix | A single character. Avoid R, which RRCS reserves for its own requests |
The connection is tested with GetVersion before the entry is created.
Options
| Option | Default | Notes |
|---|---|---|
| Polling interval | 30 s | Raise it if push notifications are working |
| Receive push notifications | on | See below |
| Callback port | HA's HTTP port | Override if HA serves HTTPS |
| Discover GPIOs automatically | on | Requires RRCS 8.8 or later |
| Poll GPIO states | on | Turn off to reduce gateway load once push is confirmed |
| Manual GPIO list | empty | JSON, see below |
Push notifications
With notifications enabled, the integration calls RegisterForAllEvents and
serves an endpoint at /api/riedel_rrcs/<random-token>. RRCS then reverses the
roles and posts XML-RPC method calls at Home Assistant, so logic source, GPIO,
crosspoint and alarm changes arrive immediately rather than at the next poll.
Three things to know:
- The endpoint is unauthenticated. RRCS has no way to present a bearer token, so the path carries a random secret instead. It is only reachable from whatever can already reach your Home Assistant HTTP port.
- RRCS derives the destination host from the source address of the registration request. The gateway has to be able to reach Home Assistant back on that same IP, on the callback port, over plain HTTP. If Home Assistant serves HTTPS you must set a plain-HTTP callback port in the options; a warning is logged if this looks wrong.
- Answer or be dropped. If KeepAlive is enabled in the RRCS route options,
RRCS sends
GetAliveevery three seconds of inactivity and tears the channel down if it goes unanswered. This integration answers it. It also re-checks the registration on every poll withIsRegisteredForAllEventsand re-registers if RRCS has forgotten us, which it does after a restart.
GPIOs
Automatic discovery
GetAllGpIns and GetAllGpOuts arrived in RRCS 8.8, but the specification
documents them by name only — the return struct is literally ... on page 40.
Discovery here is a tolerant walk over whatever comes back, mapping the three
TGPIOAddress variants from chapter 6.7 onto the Net/Node/Port/Slot/Index
addressing that Set/GetGpOutput actually wants.
That means the Bay-to-Slot mapping in particular is an educated guess. If the
discovered entities look wrong, download the diagnostics for the config entry:
the raw GetAllGpIns / GetAllGpOuts payloads are included verbatim.
Manual list
Anything you define manually wins over discovery. The options flow takes a JSON array:
[
{"name": "Studio A tally", "direction": "in", "node": 2, "port": 128, "slot": 0, "index": 3},
{"name": "Red light", "direction": "out", "node": 2, "port": 128, "slot": 0, "index": 5},
{"name": "Panel GPI", "direction": "in", "node": 4, "port": 9, "index": 0}
]
node and index are required. Defaults are net 1, port 128, slot 0 and
direction in.
Addressing follows chapter 6.9:
- GPIO client card —
portis 128 andslotselects the bay: 0–15 for bays 1–16, 16 for bay X, 17 for bay Y, 20 for bay B. - Panel GPIO —
portis the panel's port address andslotis ignored. - Port address for Artist 32/64/128 is
((slot - 1) * 8) + port - 1, so port 5 in slot 2 is address 12.
Examples
Toggle a logic source from a physical button
This replaces toggle_v5.vbs — the logic source is just a switch now.
automation:
- alias: Toggle busy from desk button
triggers:
- trigger: state
entity_id: binary_sensor.desk_button
to: "on"
actions:
- action: switch.toggle
target:
entity_id: switch.rrcs_ben_busy
Press a panel key, primary trigger
The XML-RPC equivalent of ras_pi_RRCS_BusyLight.py, press and release:
script:
ben_busy_pulse:
sequence:
- action: riedel_rrcs.press_key
data:
node: 64
port: 46
page: 2
expansion_panel: 0
key_number: 1
is_virt_key: true
trigger: 1
press: true
- delay: "00:00:00.25"
- action: riedel_rrcs.press_key
data:
node: 64
port: 46
page: 2
expansion_panel: 0
key_number: 1
is_virt_key: true
trigger: 1
press: false
Route audio on an event
- action: riedel_rrcs.set_xp
data:
source_node: 2
source_port: 12
dest_node: 3
dest_port: 4
priority: "2"
Set destructive: true to drop any existing route to the destination first.
Passing net, node and port all as 0 clears every route for a source or
destination.
React to a ring alarm
automation:
- alias: Notify on upstream failure
triggers:
- trigger: state
entity_id: event.rrcs_alarm
conditions:
- condition: template
value_template: >-
{{ trigger.to_state.attributes.event_type in
['UpstreamFailed', 'DownstreamFailed', 'NodeControllerFailed'] }}
actions:
- action: notify.ntfy
data:
message: >-
RRCS {{ trigger.to_state.attributes.event_type }}:
{{ trigger.to_state.attributes.params }}
Or catch everything on the bus:
triggers:
- trigger: event
event_type: riedel_rrcs_notification
event_data:
method: PortInactive
Call anything else
- action: riedel_rrcs.call_method
data:
method: GetAllPorts
response_variable: ports
- action: notify.persistent_notification
data:
message: "{{ ports.result[1] | count }} ports"
call_method prepends a transaction key for you unless you turn that off. The
decoded response comes back under result.
Notes and limitations
- RRCS only undoes its own work.
SetLogicSourceState,SetGpOutputandKillXponly affect state that RRCS itself set. A logic source driven from a panel key will not respond to "off", andGetXpStatuscan still report true after aKillXp. - One request at a time. Requests are serialised behind a lock. RRCS is a single Windows service in front of a live ring, and chapter 12's timing figures (10 ms for queries, 50 ms for state changes, seconds for configuration changes) all assume an otherwise idle gateway. Don't set the polling interval aggressively low on a large system.
- No configuration changes.
ConfigurationChangeand friends are not wrapped as services deliberately — they rewrite the Artist configuration and are better done in Director.call_methodwill still let you if you mean it. - Standby gateways. In a redundant pair, a standby gateway answers only the
redundancy command set, so most entities will be unavailable against one.
GetStateand the connection sensor still work. - Crosspoint volume does not work for destinations on an Artist 1024.
- Encoding: some gateways declare UTF-8 but emit single-byte port labels. The parser strips the declaration and decodes leniently rather than dropping the whole response.
Troubleshooting
Turn on debug logging to see every RPC in both directions:
logger:
logs:
custom_components.riedel_rrcs: debug
Config entry diagnostics include the coordinator state, the resolved GPIO addresses and the raw GPIO list payloads.