Skip to main content

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 Controls is 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​

  1. 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).
  2. In GEM admin → Devices → Add Device, pick driver qsys_core. Enter the Core IP. Leave the TCP port at the default 1710.
  3. If the design's External Control Access uses PIN-only auth, enter the PIN in the password field and leave username blank. For user/password auth, fill both. For "All Controls" / no-auth, leave both blank.
  4. Save and enable the device. The driver will:
    • Open the JSON-RPC socket on port 1710.
    • Send Logon if credentials are present.
    • Issue StatusGet and surface design_name, platform, and core_state as device attributes.
    • Start a 30 s NoOp keepalive so the Core does not idle-close the socket.
  5. Run the get_controls command with a comma-separated list of Code Names to verify each one resolves. Then create one zone per Code Name; zone.address is the Code Name verbatim (e.g. lobby_volume, conf_mic_mute). For component controls use ComponentName.ControlName.

Attribute reference​

Device​

AttributeRequiredDescription
ipyesLAN IP or hostname of the Core.
portnoQRC port. Defaults to 1710 — only change for a TCP proxy in front of the Core.
usernamenoQ-SYS user. Only used when External Control Access is User/Password.
passwordnoPassword (User/Password mode) or PIN (PIN-only mode). Encrypted at rest.
status_intervalnoStatus poll cadence, ms. Default 30 000; values below 5 000 are raised to 5 000. After 3 consecutive failed polls the driver skips 1, 2, 4, 8 then 16 ticks between attempts, and returns to every tick on the first good reply.
keepalive_intervalnoNoOp keepalive cadence, ms. Default 30 000 (under the Core's 60 s idle timeout); values below 5 000 are raised to 5 000.
request_timeoutnoPer-request JSON-RPC timeout, ms. Default 5 000.

Zone​

AttributeRequiredDescription
addressyesThe Q-SYS Code Name. Case sensitive. For component controls use ComponentName.ControlName.
level_scalenoWhich 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. With value, the polled level is also read back as the raw numeric Value (e.g. -12.5 dB) rather than scaled from Position; a control whose Value isn't a number still reads back from Position.

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​

CommandArgsEffect
onaddressControl.Set with Position: 1.0. Boolean on / max gain.
offaddressControl.Set with Position: 0.0. Boolean off / mute / min gain.
set_leveladdress, levelWrites Position: level/100 for a 0..100 level (default), or Value: level when the zone's level_scale is value — then the level is the control's own units and may be negative.
set_valueaddress, valueWrites a raw numeric Value — bypasses Position scaling. Use for exact dB / integer writes. A blank value is refused (value required); 0 is sent.
set_stringaddress, valueWrites a string Value — for combo-box / string controls.
mute_on / mute_offaddressWrites boolean Value: true / false.
mute_toggleaddressResolved client-side from the cached control state. The cached Value decides — a numeric 1 (how Control.Get reports a mute) reads as muted, 0 as unmuted; Position is used only when there is no Value.
triggeraddressPulse: writes Position: 1.0, then Position: 0.0 200 ms later — for momentary buttons / page triggers. If the Core refuses the press, the release is not sent and the press error is returned.
get_controlscontrols (csv)Control.Get of multiple Code Names in one request.
get_status–StatusGet: DesignName, Platform, State, IsRedundant, DesignCode.
raw_commandmethod, 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.Get on status_interval. For designs with hundreds of controls this is wasteful; a future revision should let zones opt into a ChangeGroup.AddControl + ChangeGroup.AutoPoll flow. As a stop-gap, use raw_command to set up your own change group and process notifications via the device log.
  • Phone / dialer control surfaces (PA.SoftphoneDial and friends). The protocol supports them; the driver does not yet expose convenience verbs.
  • Mixer / matrix component setters (Mixer.SetCrossPointGain, Mixer.SetInputMute, etc.). Reachable via raw_command but not wrapped.
  • Snapshot recall via Snapshot.Load. Reachable via raw_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_controls or 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 failed or 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 matching username / password.
  • Status polling lags or commands time out. A run of failed polls logs qsys core status polling backing off once and slows the poll until the Core answers again. Failed attribute writes are logged as qsys core: attribute write failed. Q-SYS Cores throttle per-connection QRC traffic. Raise status_interval, reduce the number of polled zones, or migrate frequently-changing controls to a ChangeGroup via raw_command.
  • socket not ready on every command. The Core is not in Run mode, or the design's External Control Access is set to None. Open the Core's diagnostic page — under Network the QRC port should report Listening.
  • qsys core keepalive failed in the device log. The 30 s NoOp went out but the Core did not answer it within request_timeout. GEM's socket is still open, so this is a Core that has stopped servicing QRC rather than a dropped connection — a design stopped or being redeployed, a Core rebooting, or a half-open socket left behind by a network break. Commands will time out for as long as it persists, and the message repeats once per keepalive until the Core answers or the socket closes and the driver reconnects.
  • 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 → Permissions includes Set.