Zoom Rooms
Controls a Zoom Room through ZR-CSAPI, the control system interface Zoom Rooms serves on TCP port 2244. Joins and leaves meetings, mutes the room microphone and camera, sets speaker volume, and tracks call status so the rest of GEM can react to whether the room is in a meeting.
This is the local control path. It talks directly to the room computer on the LAN — no cloud account, no OAuth, no Zoom Marketplace app.
ZR-CSAPI is served by the Zoom Rooms for Windows / macOS application. Appliance-mode rooms — Neat, Poly, Logitech, DTEN, and the Android-based bars — do not serve it and cannot be driven by this driver. Check what the room actually runs before quoting it.
Prerequisites
- A Zoom Room running on a Windows or Mac computer.
- The Zoom Rooms Control System API enabled on that room with a passcode set (Zoom Rooms Settings → Meetings → Zoom Rooms Control System API). It is off by default.
- TCP 2244 reachable from the GEM controller. The room computer's own firewall usually blocks it — that rule is separate from enabling the API, and forgetting it is the single most common commissioning failure.
- A static IP or DHCP reservation on the room computer.
Setup
- Enable the API on the room. In the Zoom Rooms application on the room computer, open Settings → Meetings and turn on the Zoom Rooms Control System API. Set a passcode and note it down.
- Open the firewall. Allow inbound TCP 2244 on the room computer for your controller's subnet.
- Verify by hand. From a workstation,
telnet <room-ip> 2244. The room answers with a banner and a login prompt; type the passcode and press Enter. A successful login is acknowledged, after whichzStatus Call Statusreturns the room's state. - Add the device. In
/admin/devicescreate a device with driver zoom_rooms:ip— the room computer's addressport— leave at 2244password— the control system passcode (stored encrypted)
- Confirm. Run
get_call_status. The device'scall_statusattribute should populate withNOT_IN_MEETINGorIN_MEETINGwithin a second or two, androom_namefills in from the room's own system info.
Attribute reference
Device
| Attribute | Required | Default | Description |
|---|---|---|---|
ip | yes | — | Room computer IP — not the scheduling display or the controller tablet |
password | yes | — | Control system passcode. Stored encrypted. |
port | no | 2244 | ZR-CSAPI port |
poll_interval | no | 30000 | Backstop call-status re-read interval, in ms |
default_duration | no | 30 | Minutes passed to start_meeting when the command carries no duration |
call_status | read-only | — | NOT_IN_MEETING / CONNECTING_MEETING / IN_MEETING |
mute_state | read-only | — | Room microphone, on / off |
camera_state | read-only | — | on when the room is sending video |
volume | read-only | — | Room speaker volume, 0-100 |
room_name | read-only | — | Room name as configured in Zoom |
Zones
This driver does not use zones — one GEM device per room, and state lands on the device.
Commands
| Command | Args | Notes |
|---|---|---|
join_meeting | meeting_number, password | Meeting number is stripped to digits; password optional |
start_meeting | duration | Starts the room's personal meeting for N minutes |
leave_meeting | — | The room leaves; the meeting continues for everyone else |
end_meeting | — | Ends the meeting for all participants |
mute_on / mute_off / mute_toggle | — | Room microphone. Toggle resolves from the cached state. |
mute_all / unmute_all | — | Every participant in the meeting, not just the room |
camera_on / camera_off | — | Camera mute |
volume | volume | 0-100 |
volume_up / volume_down | step | Default step 5, from the cached volume |
get_call_status | — | Re-read call status |
get_system_info | — | Room name, platform, version |
get_bookings / update_bookings | — | Read, or force a refresh of, the room's calendar bookings |
send_command | text | Send a literal ZR-CSAPI line |
dial_phone | number | Not implemented — see below |
send_command is the escape hatch. ZR-CSAPI exposes far more than this driver wraps (layout control, participant management, sharing), and any documented zCommand / zConfiguration / zStatus line can be sent through it from a macro without a driver change.
What this unlocks
The useful part of this driver is usually not the meeting control — the room's own tablet does that better — it is call_status as an automation input. A room that reports IN_MEETING can drive the rest of the building:
- Set an in-use indicator outside the door.
- Lower shades and drop the lights to a preset when a meeting starts, restore them when it ends.
- Hold back HVAC setbacks and cleaning-crew scenes while the room is occupied.
- Route the room's DSP to conferencing gain structure on entry and back to program audio on exit.
Build these as attribute triggers on the device's call_status.
Session behavior
The driver opens one long-lived socket, sends the passcode when the room prompts for it, then switches the session to JSON replies. State changes the room pushes are applied as they arrive; the poll loop is a backstop, not the primary path.
Most builds allow one control system session at a time. If a third-party controller is already connected, GEM may take the slot from it or be refused — decide which system owns the room before commissioning both.
Known limitations
dial_phoneis not implemented. It appears in the command list so it is discoverable, but the Zoom Phone outbound dial verb was not verifiable against the ZR-CSAPI reference, so it returnsnot yet implementedrather than a guessed wire format. Zoom Phone dialing can be driven throughsend_commandonce you have confirmed the verb for your build.- Sharing, layout and participant management are not wrapped. Use
send_command. - No appliance-mode support. Covered above.
- Not validated against a live room. The command surface follows Zoom's published control system interface, but this driver has not yet been run against physical hardware. Commission with
get_call_statusand one mute command before wiring it into automation.
Troubleshooting
| Symptom | Check |
|---|---|
| Connection refused on 2244 | The control system API is disabled, or the room computer's firewall is blocking the port. These are two separate things — confirm both. |
| Connects, then every command is ignored | The passcode was rejected. The device log records the login attempt; re-read the passcode from the room settings screen. |
| Status stops updating after a while | Another control system took the session slot. Reload the device and disconnect the other controller. |
volume_up returns "no cached volume" | The driver has not read the volume yet. Run get_system_info, or wait for the session to re-establish. |
| Nothing works on a Neat / Poly / DTEN room | Appliance-mode rooms serve no ZR-CSAPI. There is no local control path on that hardware. |
| Meeting joins but with no audio | Unrelated to this driver — check the room's own audio device selection in Zoom Rooms settings. |