Files
rrcs-home-assistant/README.md
T
2026-08-12 15:31:50 +10:00

303 lines
9.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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:
1. **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.
2. **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.
3. **Answer or be dropped.** If KeepAlive is enabled in the RRCS route options,
RRCS sends `GetAlive` every 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 with `IsRegisteredForAllEvents` and
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:
```json
[
{"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** — `port` is 128 and `slot` selects the bay: 0–15 for bays
1–16, 16 for bay X, 17 for bay Y, 20 for bay B.
- **Panel GPIO** — `port` is the panel's port address and `slot` is 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.
```yaml
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:
```yaml
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
```yaml
- 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
```yaml
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:
```yaml
triggers:
- trigger: event
event_type: riedel_rrcs_notification
event_data:
method: PortInactive
```
### Call anything else
```yaml
- 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`, `SetGpOutput` and
`KillXp` only affect state that RRCS itself set. A logic source driven from a
panel key will not respond to "off", and `GetXpStatus` can still report true
after a `KillXp`.
- **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.** `ConfigurationChange` and friends are not
wrapped as services deliberately — they rewrite the Artist configuration and
are better done in Director. `call_method` will 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.
`GetState` and 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:
```yaml
logger:
logs:
custom_components.riedel_rrcs: debug
```
Config entry diagnostics include the coordinator state, the resolved GPIO
addresses and the raw GPIO list payloads.