QSC Q-SYS Core
GEM controls QSC Q-SYS Core processors via the QRC (Q-SYS Remote Control) JSON-RPC 2.0 protocol on TCP port 1710. One GEM device row represents one Core; each named control exposed by the deployed Q-SYS design becomes a GEM zone.
Prerequisites
- A Q-SYS Core (Core 8 Flex / 110f / 510i / NV-32-H / etc.) running a design in Run mode (not Emulate). The QRC port only listens while a design is running.
- External Control Access enabled in the design. In Q-SYS Designer:
File → Design Properties → External Control Access. Choose the lowest access level that meets the project's security requirement —External Control Access: All Controlsis simplest. - Each control you want to drive must have a Code Name. Right-click a control in Designer → Properties → set Code Name. The Code Name is what GEM puts on the zone as
zone.address. - TCP port 1710 reachable from the GEM controller (no firewall block between the controller and the Core).
Setup
- In Q-SYS Designer, decide which controls GEM should drive (volume, mic mute, source select, scene-recall buttons, page triggers, etc.) and give each a stable Code Name. Push the design to the Core (Run mode).
- In GEM admin → Devices → Add Device, pick driver
qsys_core. Enter the Core IP. Leave the TCP port at the default 1710. - If the design's External Control Access uses PIN-only auth, enter the PIN in the
passwordfield and leaveusernameblank. For user/password auth, fill both. For "All Controls" / no-auth, leave both blank. - Save and enable the device. The driver will:
- Open the JSON-RPC socket on port 1710.
- Send
Logonif credentials are present. - Issue
StatusGetand surfacedesign_name,platform, andcore_stateas device attributes. - Start a 30 s
NoOpkeepalive so the Core does not idle-close the socket.
- Run the
get_controlscommand with a comma-separated list of Code Names to verify each one resolves. Then create one zone per Code Name;zone.addressis the Code Name verbatim (e.g.lobby_volume,conf_mic_mute). For component controls useComponentName.ControlName.
Attribute reference
Device
| Attribute | Required | Description |
|---|---|---|
ip | yes | LAN IP or hostname of the Core. |
port | no | QRC port. Defaults to 1710 — only change for a TCP proxy in front of the Core. |
username | no | Q-SYS user. Only used when External Control Access is User/Password. |
password | no | Password (User/Password mode) or PIN (PIN-only mode). Encrypted at rest. |
status_interval | no | Status poll cadence, ms. Default 30 000. |
keepalive_interval | no | NoOp keepalive cadence, ms. Default 30 000 (under the Core's 60 s idle timeout). |
request_timeout | no | Per-request JSON-RPC timeout, ms. Default 5 000. |
Zone
| Attribute | Required | Description |
|---|---|---|
address | yes | The Q-SYS Code Name. Case sensitive. For component controls use ComponentName.ControlName. |
level_scale | no | Which Control.Set field set_level writes to. position (default) maps GEM's 0..100 onto Q-SYS Position 0..1, which works for any control type. value writes the raw value directly — use when the underlying control's units are known. |
Zone address format
A Q-SYS Code Name as it appears in Q-SYS Designer. Two shapes:
- Top-level named controls:
lobby_volume,conf_mic_mute,scene_outdoor. - Component controls:
Gain1.gain,Mixer.mute_1,Page.station_1.
Case matters. Designer's "copy code name" gives you the exact string.
Command reference
| Command | Args | Effect |
|---|---|---|
on | address | Control.Set with Position: 1.0. Boolean on / max gain. |
off | address | Control.Set with Position: 0.0. Boolean off / mute / min gain. |
set_level | address, level (0..100) | Writes Position: level/100 (default) or Value: level when zone's level_scale: value. |
set_value | address, value | Writes a raw numeric Value — bypasses Position scaling. Use for exact dB / integer writes. |
set_string | address, value | Writes a string Value — for combo-box / string controls. |
mute_on / mute_off | address | Writes boolean Value: true / false. |
mute_toggle | address | Resolved client-side from the cached control state. |
trigger | address | Pulse: writes Position: 1.0, then Position: 0.0 200 ms later — for momentary buttons / page triggers. |
get_controls | controls (csv) | Control.Get of multiple Code Names in one request. |
get_status | – | StatusGet: DesignName, Platform, State, IsRedundant, DesignCode. |
raw_command | method, params (JSON) | Send any QRC method (e.g. ChangeGroup.AddControl, Mixer.SetCrossPointGain). |
What's not yet supported
- ChangeGroup-based push status. The driver currently polls every zone via
Control.Getonstatus_interval. For designs with hundreds of controls this is wasteful; a future revision should let zones opt into aChangeGroup.AddControl+ChangeGroup.AutoPollflow. As a stop-gap, useraw_commandto set up your own change group and process notifications via the device log. - Phone / dialer control surfaces (
PA.SoftphoneDialand friends). The protocol supports them; the driver does not yet expose convenience verbs. - Mixer / matrix component setters (
Mixer.SetCrossPointGain,Mixer.SetInputMute, etc.). Reachable viaraw_commandbut not wrapped. - Snapshot recall via
Snapshot.Load. Reachable viaraw_command. - Logon for SSH/HTTPS encrypted control (Q-SYS Reflect tier). The driver speaks the plain TCP QRC port; if a design restricts QRC to the encrypted variant only, the connection will not open.
Troubleshooting
- "control not found" from
get_controlsor no status updates. The Code Name on the zone must match Designer exactly, including case. In Designer, click the control → Properties → copy the Code Name string. logon failedor socket closes shortly after connect. External Control Access level is higher than the supplied credentials cover. Open Design Properties → External Control Access in Designer and either lower the access level or supply matchingusername/password.- Status polling lags or commands time out. Q-SYS Cores throttle per-connection QRC traffic. Raise
status_interval, reduce the number of polled zones, or migrate frequently-changing controls to aChangeGroupviaraw_command. socket not readyon every command. The Core is not in Run mode, or the design's External Control Access is set toNone. Open the Core's diagnostic page — under Network the QRC port should reportListening.- Commands change the GEM-side level but nothing happens at the Core. Some controls are read-only in the design. In Designer, confirm the control's
Properties → Permissionsincludes Set.