303 lines
9.7 KiB
Markdown
303 lines
9.7 KiB
Markdown
# 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.
|