DeviceHub Pro

● VR headset management · v0.3.8

Fifteen minutes to curtain. You should not be putting on headsets one by one.

DeviceHub Pro is a Meta Quest headset management system built for free-roam VR shows. Batch connectivity, per-show OSC routing, a pre-flight check before the doors open, and every headset’s view on one screen while the show runs. When the work tours without you, the rights stay in your hands.

Book a Demo Read the Spec

01 The problem

On a live floor, there is no “we’ll fix it after”

Guests take headsets off. Apps drop to the home menu, Wi-Fi drops, batteries die where you cannot see them. The changeover is three minutes.

Scenario: 12 headsets, a 3-minute changeover

Checking one by one eats the changeover

Checking 12 headsets by hand takes about 10 minutes; the changeover is 3.

About 50 s a headset: on, check the scene, off. When the changeover ends you are holding number 4, with eight still unchecked.

Mid-show, nobody knows which one dropped

A guest hits Home, the app crashes, a battery hits zero. Until someone raises a hand, your desk shows nothing.

Two shows at once, one signal path

Two audiences, two cue sheets, one OSC port. The cue that advances show A advances show B with it.

Every new build starts the cycle over

A new APK lands and you sideload it one cable at a time: twelve headsets, twelve plug-ins, twelve pulls.

02 Show night

One show night, from T−15 to curtain down.

Twelve headsets, two shows at once: six in show group A, six in B. In order, this is what DeviceHub does at each point of the night.

  1. T−15:00

    Plug in once; it moves itself to Wi-Fi

    Plug a headset in by USB and DeviceHub moves it to Wi-Fi: adb tcpip 5555, read the wlan0 address, connect. Pull the cable and it is already in the list. From then on every headset is read every 3 s, up to 8 at once.

    One round of 12 headsets: 1.6 s, against 8.7 s one at a time (measured, noted in the code)

  2. T−10:00

    Group the headsets, verify the room

    Each headset gets a show group, sub-group and ID. Each group gets a Photon room name, password and region, and Verify room checks them with XRPR; a pass bumps the revision. Headsets pick up the new revision on their next pull and answer /show_assignment_ack.

    The room password stays in DeviceHub; headsets receive room name, region and revision. They pull every 3 s until they have a name and sub-group, then every 60 s.

  3. T−05:00

    One page says whether you can start

    Show status gives each group one card: room · region · verified revision, OSC in → out, headsets / acknowledged / online, and a ✓ or ⚠ per headset. The card reads Ready only once every headset assigned to the group has acknowledged.

    ⚠ means that headset has not acknowledged rev.3 yet

  4. T−01:00

    Launch all, from the Monitor page

    v0.3.8 moved the batch row to the Monitor page: Refresh list, Launch all, Close all. Launch all sends the command and does not wait for a reply; the status grid shows the result, square by square, over the next few reads.

    Green square: ShowApp is in the foreground. Red: it is not.

  5. T 00:00

    Curtain up: A’s cues reach A only

    Each show group listens on its own OSC port. A cue arriving on 9002 goes to group A’s six headsets only; one on 9003 goes to B. DeviceHub forwards first and writes the log line after the packet has left.

    A: in 9002 → out 9200 · B: in 9003 → out 9201

  6. T+12:00

    The headset wall: spot the odd one

    Press Start and every online headset goes up on one wall: scrcpy, 480 px tiles at 10 fps, up to 16. V-10 is stuck on a loading screen, yet its status square is still green. Click its tile for a live preview at 15 fps.

    View only: scrcpy sends no input and does not wake a sleeping headset

  7. T+18:00

    V-07 leaves ShowApp

    Two reads in a row find V-07 off ShowApp, and a notice appears in the corner. Group B has Auto-relaunch on, so DeviceHub relaunches it, then leaves that headset alone for 30 s.

    A guest who glances at the system menu for a single read: no notice, no relaunch

  8. T+45:00

    Curtain down: End show and lock

    End show and lock ends the authorization session and closes DeviceHub, taking the wall, previews and OSC listeners with it. The next launch has to pass XRPR verification again.

    Authorization is checked at launch; nothing locks mid-show

Interface mock-up; all data is sample data.

03 Parallel shows

Same room. Two shows. No crossed signals.

Each show is a show group with its own OSC port pair. A cue sent to 9002 moves group A’s headsets and nothing else.

Pick a port to send a cue.

Switch off to see one shared port

Cue software sends to

DeviceHub listens on

DeviceHub Pro

Headsets receive on

  • A9200
  • B9201
  • C9202
  • D9203
  • No group9999

Waiting for a cue.

Simulation. Port numbers are the defaults on a fresh install.

Default ports
ChannelIn: DeviceHubOut: headsets
All-call9001Each headset’s own group port; 9999 for a headset with no group
A90029200
B90039201
C90049202
D90059203
A new group E90069204 · takes the next free pair
Forwarded
Every OSC address is forwarded except /request_info and /hub_discovery.
Forward first, log after
The log line is written after the packet leaves. There is no ADB call on the forward path.
Checked on save
Ports must be 1024–65535, and no two enabled groups may share one.

04 Pre-flight

“Should be fine” is not a status.

The Show status page gives every show group one card: the verified room revision, its OSC ports, and how many headsets have acknowledged their assignment. Each ✓ is sent back by the headset itself, not guessed at the desk.

Checked in order. The card names the first step that fails.

  1. Group enabledOtherwise: Disabled

  2. Room name, password and region set, and verified by XRPROtherwise: the step that is missing

  3. At least one headset assignedOtherwise: Room ready, but no headsets yet

  4. Every headset has acknowledgedOtherwise: Room ready, N not yet acknowledged

  5. Ready

A · Main show Ready
Room SHOW-A · Jp · Verified rev.3 OSC in 9002 → out 9200

8 headset(s) · 8 acknowledged · 8 online

Sub-group 1 1. V-01 ✓2. V-02 ✓3. V-03 ✓4. V-04 ✓
Sub-group 2 1. V-05 ✓2. V-06 ✓3. V-07 ✓4. V-08 ✓
Interface mock-up; all data is sample data.

See the not-ready states

Acknowledgements count for this run only
They live in memory. Saving settings, re-verifying the room, changing an assignment or restarting DeviceHub clears them. Every ✓ on the card was earned this run, and a ⚠ is the exact headset that has not answered. You know which one to walk to.
Two things it does not check
Ready does not test the ports and does not require headsets to be online right now. The online count is on the card for you to read.

05 Monitor

What the show sends, and what each guest sees.

The Monitor page puts Unity’s output on the left and every headset’s live picture on the right. The headset stuck on a loading screen, back in Home or gone black stands out on the wall; click its tile and its picture opens next to the Unity feed.

Try it: click any tile to preview it, press Capture all, or switch the Unity status line below.

Interface mock-up · sample data

Monitor 11 headset(s) · 11 online · 11 on the target app Volume now: 40%-70% across 11 headset(s)
Unity feed Receiving · 1920x1080 · 15 fps

Pick a source and press Connect feed; the Unity output appears here.

Headset wall 11/11 feeds

Unity feed: the status line tells three cases apart

NDI takes a feed from any machine on the network; Spout only from the same PC, and only in the Windows build. Low bandwidth is on by default, so NDI sends its proxy stream. Defaults are 15 fps and 960 px wide, changed only in config.json. The feed never connects by itself: press Connect feed.

Headset wall: find the one that differs

All 11 feeds are green and every headset is on the target app, yet V-07 is stuck on a loading screen. The status grid cannot show that. The picture can.

10 fps
per tile by default, 480 px wide
1.5 Mbps
configured bit rate per tile. 11 tiles add up to 16.5 Mbps of configured bit rate, not measured traffic.
0.7 cores Measured
of CPU with 11 headsets on the wall, i9-12900HK
16 tiles
on one wall, at most

The wall always uses scrcpy and only runs after you press Start. A tile that drops shows the reason instead of freezing on its last frame.

Capture all: one click, one frame per headset

Asks every online headset for one frame, saves each as captures\date-time\name.jpg and lays the results out in one grid, failures first. Each frame is one eye, 16:9, 1280×720.

scrcpy is view-only: no control channel, it does not wake a sleeping headset, and the headset’s APK needs no update.

Measured · 11 × Quest 3 · Wi-Fi

Capture all, 11 headsets

scrcpy 1.8 s median, range 1.2–2.3 s
ADB screencap 9.9 s

Single preview Each tick below is one frame, across 6.5 seconds.

scrcpy 15 fps
ADB screencap 0.15 fps one frame per 6.5 s

06 Connectivity

Plug in USB once. Then pull the cable.

DeviceHub manages headsets over ADB. A headset plugged in by USB moves itself to Wi-Fi; a total dropout reconnects from IP history; a new IP address keeps its name, ID and show group.

USB in, Wi-Fi out

On by default. DeviceHub sends tcpip 5555 to the USB headset, waits 2 s, reads the wlan0 address and connects over Wi-Fi. A headset already on Wi-Fi is skipped.

  1. adb tcpip 5555
  2. wait 2 s
  3. read wlan0 IP
  4. adb connect …:5555

A total dropout reconnects from IP history

On the poll where the online count falls from one or more to zero, DeviceHub runs adb connect on every address in its IP history, most recent first. One fall to zero, one attempt; it also runs once at start-up. A single headset dropping does not trigger it.

New IP, same headset

Identity resolves serial → UUID → IP history. While the serial or UUID can be read, the address plays no part. A new DHCP lease keeps the name, the ID and the show group.

PC hosts are on the list too

A computer running QuestCenter is identified as HOST-<machine>#<1–8>: up to 8 instances per PC, on ports 7908–7915. It reports every 60 s and is marked offline after 90 s of silence. An IP change leaves its group alone.

After DeviceHub restarts, a host shows offline until its next report, up to about 60 s.

Illustrations; addresses and serials are sample data.

07 Fleet

Groups, sub-groups, numbers — the language you already use on the floor.

A headset belongs to exactly one show group at a time. The sub-group is its role in that show. The number is what you call out over comms.

HeadsetsPick a headset, choose its show group and sub-group in Device settings, then Save settings. Leave ID blank and it takes the lowest free number in that sub-group.

AA · Show AOSC 9002 → 9200

Sub-group 1

Sub-group 2

Sub-group 3

    Sub-group 4

      BB · Show BOSC 9003 → 9201

      Sub-group 1

      Sub-group 2

        Sub-group 3

          Sub-group 4

            Unassigned

            Device settings

            Serial: DEMO0000A005

            Interface mock-up with sample data. The app has no drag and drop: assignment happens in each headset’s Edit dialog.

            01

            Show group

            One running show: one Photon room, one OSC in/out port pair, and the headsets in it. A–D by default; you can add more.

            02

            Sub-group

            A role grouping inside a show. Each show group starts with 4; name and colour are set when you add one, and unused ones can be deleted.

            03

            ID

            The headset’s number within its sub-group, unique there. A newly assigned headset takes the lowest free number: with 1, 2 and 4 taken, the next one is 3.

            PC

            PC hosts can join a show group

            Since v0.3.4 a PC host can join a show group and receive that group’s show OSC. Volume, APK install, capture and the headset wall apply to headsets only.

            08 Fleet ops

            Tick the headsets, press once, and it installs them one by one.

            The Install page lists online Android headsets only; PC hosts are left off. Everything starts ticked, and an unticked headset is left alone.

            One at a time, a result for each

            DeviceHub runs adb install -r on each ticked headset in turn, not in parallel, allowing up to 120 s per headset. The log shows success, or the failure and its reason, for each one, then the totals.

            A headset that appears when the list updates is ticked only if everything was ticked before. Once you have unticked anything, a newcomer never adds itself to the targets.

            On a signature conflict, the old version goes first

            If the new APK is signed differently from the copy on the headset, DeviceHub runs adb uninstall on the old one and installs again, without asking first. Uninstalling wipes that app’s data on that headset.

            D:/Builds/show-build-1.4.2.apk
            7 of 7 selected
            • A · 1192.168.10.101:5555
            • A · 1192.168.10.102:5555
            • A · 1192.168.10.103:5555
            • A · 1192.168.10.104:5555
            • A · 2192.168.10.105:5555
            • A · 2192.168.10.106:5555
            • Unassigned192.168.10.107:5555

            Install complete — 6 succeeded, 1 failed

            [20:14:02] ===== Install started =====
            [20:14:02] APK: show-build-1.4.2.apk
            [20:14:02] Selected: 7 / 7
            [20:14:02] 
            [20:14:02] [1/7] Installing to V-01...
            [20:14:09] ✓ V-01 installed
            [20:14:09] [2/7] Installing to V-02...
            [20:14:16] ✓ V-02 installed
            [20:14:16] [3/7] Installing to V-03...
            [20:14:19] → Signature mismatch; removing old com.example.showapp (this clears that app's local data)...
            [20:14:21] → Old com.example.showapp removed, reinstalling...
            [20:14:28] ✓ V-03 installed
            [20:14:28] [4/7] Installing to V-04...
            [20:14:35] ✓ V-04 installed
            [20:14:35] [5/7] Installing to V-05...
            [20:14:42] ✓ V-05 installed
            [20:14:42] [6/7] Installing to V-06...
            [20:14:45] × V-06 install failed: Failure [INSTALL_FAILED_INSUFFICIENT_STORAGE]
            [20:14:45] [7/7] Installing to V-07...
            [20:14:52] ✓ V-07 installed
            [20:14:52] 
            [20:14:52] ===== Install complete =====
            [20:14:52] 6 succeeded | 1 failed

            Interface mock-up; all data is sample data. Untick a few, then press Start install.

            Launch all, Close all

            One click sends the launch or close command to every known device. It neither waits for nor confirms the result; the status grid shows it on the next reads. Since v0.3.8 the same row is on the Monitor page too.

            3 s between reads

            Each round reads online state, battery, volume, foreground app, app version, IP, serial and model, up to 8 headsets at once. Read time adds to the 3 s interval, so how fast a round reads decides how current the status grid is.

            One by one8.7 s
            In parallel (up to 8)1.6 s

            seconds per round, 12 headsets+ 3 s interval

            measured, per a code comment

            09 Auto-relaunch

            It will not relaunch because a guest glanced at a menu.

            When a headset leaves the show app, DeviceHub can pull it back. The hard part is deciding whether it really left: the Quest system menu or the Guardian boundary warning can hold the foreground for a few seconds while the piece runs on behind it, and sometimes ADB cannot read the foreground at all. Treat any of that as a departure and a guest gets pulled out of the work for nothing.

            One column per read: 3 s apart, plus read time

            The system menu on read 3, back on ShowApp by read 4. Never two in a row, so nothing happens.

            Simulation: scenarios and screens are samples; the decision rules follow devicehub_relaunch.py.

            01

            A failed read is not evidence

            When ADB cannot read the foreground app, that is a failed measurement, not a departure. The count neither rises nor resets. A headset going offline resets it: leaving the network is not leaving the piece.

            02

            Two reads in a row

            By default it takes 2 reads in a row off the show app. Reads are 3 s apart by default, so that is about 6 s plus read time. A blip that comes back inside that window triggers nothing; if your venue needs more slack, raise the count.

            03

            Then a 30 s cooldown

            After a relaunch each headset waits 30 s, so a second launch never lands on one that has not taken effect yet.

            Being told and acting are separate

            With auto-relaunch off, a departure still raises a notice in the bottom-right corner for 6 s, and coming back raises another. You can go by the notices alone and walk over yourself.

            Off by default, per show group

            Each show group has its own Auto-relaunch switch in Settings, off by default: on for this show, off for the one next door. The two thresholds are set in config.json only, under monitoring_settings:

            "monitoring_settings": {
              "relaunch_required_misses": 2,
              "relaunch_cooldown_seconds": 30
            }

            Software that relaunches on its own is easy. Software that knows when to leave a headset alone is not.

            10 Rights

            Your work. You decide who can open it, and until when.

            Once a show goes to a curator or an operator abroad, nobody controls how many times it runs, or whether it keeps running after the contract ends. XRPR is our project and licensing platform. DeviceHub verifies with it at every launch, and you are the one who issues the licence and takes it back.

            XRPR reads three ways, one per layer. The operator enters one room name and password, and the three layers run in order behind it.

            1. XR Passphrase RouterPassphrase routing

              Path: DeviceHubPro / SHOW-A

            2. XR Permission RelayPermission relay

              In date · project matches · pass

              Valid until 2027-06-30

            3. XR Private RoomPrivate room

              Room open · SHOW-A · Jp

            Verified. DeviceHub starts ADB, OSC and discovery, and each verified show group sends its room name, region and revision to its headsets.

            Simulation; all data is sample data.

            XR Passphrase Router Passphrase routing

            The Router reads the passphrase as coordinates and finds the one path it points to, among every project and room.

            In DeviceHubThe DH room name and password entered at launch, and each show group’s Photon room name and password, sent with Verify room.

            XR Permission Relay Permission relay

            The Relay is the gate. It checks with the database that the passphrase is in date, which project it belongs to, and whether it has been revoked. A request that fails stops here.

            In DeviceHubThis is your switch. Revoke or change the dates in XRPR, and their next launch is stopped here. A licence that belongs to another project is refused.

            XR Private Room Private room

            Past the gate, the connection lands in a private room driven by Photon. Signals from outside stay outside.

            In DeviceHubEach show group has its own room. The password stays in DeviceHub; headsets receive only the room name, region and revision, and a room name and region are all they need to join.

            The operator enters it once. Three layers run in order, and the switch on the middle one is yours.

            One booking, start to finish

            You open a licence in XRPR for the booking, set its dates to the run, and hand it over with DeviceHub. The operating team launches each day, enters it, and runs the show. When the run ends, the licence expires on its own. If the contract ends early, you revoke it, and their next launch will not open.

            1. Open a licence in XRPR
            2. Hand it over with DeviceHub
            3. Every launch in the run is verified
            4. The run ends; the licence expires

            Ended early: revoke it, and the next launch will not open

            What you hold

            Licences carry dates
            Each licence has a start and an end date that match the contract. After the end date it no longer verifies. Nobody has to remember to switch it off.
            Revoke at any time
            Early termination, a breach, a work withdrawn: revoke it in XRPR and their next launch fails. You do not need anything back from them.
            Nothing starts before the gate
            Until verification passes, ADB, OSC and discovery do not start, and headsets get no show room. There is no offline unlock.
            Lock it at the end of the day
            End show and lock closes DeviceHub. The next session has to verify again.

            What they get

            Never locked out mid-show
            Verification happens once, at launch. An expiry, a revocation or a dropped network during the show does not stop the show that is running.
            The end date is on screen
            After login the sidebar shows the valid-until date. It turns amber inside 7 days, and red inside 1 day or once expired.
            The room password stays in DeviceHub
            The Photon room password is kept only in DeviceHub. Headsets receive the room name, region and revision.
            A strict connection
            HTTPS only, redirects refused, a 10 s timeout. Remember room name and password only pre-fills the fields: it is a plain-text file in your user folder, not encrypted, and every launch still verifies.

            Two sides of one mechanism: you can withdraw the rights at any moment, and they will never be locked out in front of an audience.

            11 The interface

            Seven screens. None of them decorative.

            The v0.3.8 layout, redrawn in HTML. Click the sidebar to switch pages. All data is sample data.

            Mock-up · sample data

            Replace cover
            Link statusSort by nameSort by batterySort by appRefresh
            V-0184%60%
            V-0277%60%
            V-0318%70%
            V-0452%60%
            V-0541%--%
            V-0666%40%
            V-0792%60%
            V-08--%--%
            Refresh listLaunch allClose all
            LinkIDNameBatteryVolumeIP addressSerialRunning appApp versionActions
            1V-0184%60%192.168.10.101DEMO0000A001ShowApp1.4.2LaunchClose
            2V-0277%60%192.168.10.102DEMO0000A002ShowApp1.4.2LaunchClose
            1V-0318%70%192.168.10.103DEMO0000A003ShowApp1.4.2LaunchClose
            2V-0666%40%192.168.10.106DEMO0000A006Meta Home1.4.2LaunchClose
            2V-08—Unknown192.168.10.108DEMO0000A008——LaunchClose
            Monitor8 headset(s) · 7 online · 6 on the target appCapture all
            V-0184%60%
            V-0277%60%
            V-0318%70%
            V-0452%60%
            V-0541%--%
            V-0666%40%
            Refresh listLaunch allClose allVolume now: 40%-70% across 6 headset(s)

            Unity feedNDIReceiving · 1920x1080 · 15 fps

            Headset wallStop7/7 feeds

            Show statusRefresh

            A A · Main showReady

            Room SHOW-A · Jp · Verified rev.3

            OSC in 9002 → out 9200

            4 headset(s) · 4 acknowledged · 4 online

            Sub-group 11. V-01 ✓2. V-02 ✓

            Sub-group 21. V-03 ✓2. V-04 ✓

            B B · Second showRoom ready, 2 not yet acknowledged

            Room SHOW-B · Jp · Verified rev.1

            OSC in 9003 → out 9201

            4 headset(s) · 2 acknowledged · 3 online

            Sub-group 11. V-05 ✓2. V-06 ✓

            Sub-group 21. V-07 ⚠2. V-08 ⚠

            Choose APK fileshow-build-1.4.2.apkStart install
            Select all6 of 7 selectedRefresh devices

            Install complete — 5 succeeded, 1 failed

            [20:14:02] ===== Install started =====
            [20:14:02] APK: show-build-1.4.2.apk
            [20:14:02] Selected: 6 / 7
            [20:14:02] 
            [20:14:02] [1/6] Installing to V-01...
            [20:14:09] ✓ V-01 installed
            [20:14:09] [2/6] Installing to V-02...
            [20:14:16] ✓ V-02 installed
            [20:14:16] [3/6] Installing to V-03...
            [20:14:23] ✓ V-03 installed
            [20:14:23] [4/6] Installing to V-05...
            [20:14:30] ✓ V-05 installed
            [20:14:30] [5/6] Installing to V-06...
            [20:14:33] × V-06 install failed: INSTALL_FAILED_INSUFFICIENT_STORAGE
            [20:14:33] [6/6] Installing to V-07...
            [20:14:40] ✓ V-07 installed
            [20:14:40] 
            [20:14:40] ===== Install complete =====
            [20:14:40] 5 succeeded | 1 failed
            Search...Clear
            [20:11:40] Discovery server started, listening on port 9065
            [20:11:40] OSC listener started: All port 9001
            [20:11:40] OSC listener started: Group A port 9002
            [20:11:40] OSC listener started: Group B port 9003
            [20:11:43] [Device] V-01 (192.168.10.101:5555) online | group: 1 | app: ShowApp | battery: 84%
            [20:11:43] [Device] V-02 (192.168.10.102:5555) online | group: 1 | app: ShowApp | battery: 77%
            [20:12:03] OSC bypass[Group A]: received /scene/change (2) -> forwarded to 4 device(s)
            [20:12:31] [Assignment] V-07 acknowledged its assignment
            [20:13:55] V-06 left ShowApp for Meta Home
            [20:15:30] Headset wall started with 7 headset(s)
            Save all settings

            Application settings

            Package name:com.example.showapp

            Display name:ShowApp

            Interface language:English

            Connection settings

            ADB path:C:\platform-tools\adb.exe

            Refresh interval (s):3

            Anchor path:Anchors/Main

            Capture source:scrcpy stream (fastest, recommended)

            OSC settings

            Send port:9999

            Receive port:9001

            Enable OSC bypass

            Show groups

            AA · Main showEnableAuto-relaunchOSC in: 9002 Out: 92002 sub-group(s) · 4 headset(s) · 4/4 acknowledged

            Room name:SHOW-ARoom password:••••••Region:JpVerify roomVerified — ready to push

            BB · Second showEnableAuto-relaunchOSC in: 9003 Out: 92012 sub-group(s) · 4 headset(s) · 2/4 acknowledged

            Room name:SHOW-BRoom password:••••••Region:JpVerify roomVerified — ready to push

            1. Start The show cover; double-click it to change the picture. The last thing you see before you go up is tonight’s show, not a wall of numbers.
            2. Headsets One card per headset on top: online, battery, volume, on the target app or not. One row per headset below adds ID, IP, serial, app version and Launch / Close buttons.
            3. Monitor Unity’s output and every headset’s picture side by side on one page, with Launch all and Close all right there. The working version is in section 05.
            4. Show status One card per show group: room, region, verification revision, OSC ports, acknowledgements. A card says Ready only when the room is verified and every headset has acknowledged its settings.
            5. Install Tick the headsets to install to; they install one after another, one result line each. On a signature mismatch the old version is removed first, which wipes that app’s data on the headset.
            6. Log Live log with keyword filtering. app.log rotates every 5 MB and keeps 5 files; Clear empties the screen, not the file.
            7. Settings Target app, interface language, ADB path, poll interval (3 s by default), anchor path, capture source and OSC ports. Each show group’s room, its Auto-relaunch switch and Verify room live here too.

            12 Specs

            Spec sheet

            01Devices & platform

            Headsets
            Meta Quest family
            Operating system
            Windows 10 / 11 (primary); a macOS build for development, not field-validated
            Interface
            Traditional Chinese / English; a switch takes effect after a restart
            Scale per instance
            50+ headsets measured by the production team

            02Network & ports

            Headset link
            ADB over USB / Wi-Fi (TCP 5555)
            Control protocol
            OSC over UDP
            All-call
            In 9001
            Per-group ports
            From 9002 in / 9200 out, one pair per group
            Discovery
            UDP 9065 broadcast every 3 s; replies to 7908 (PC hosts 7908–7915)

            03Show control

            Show groups
            A–D by default, expandable
            Auto-relaunch
            Off by default, per show group; 2 consecutive reads, 30 s cooldown; thresholds in config.json

            04Monitoring

            Status reads
            3 s apart, up to 8 headsets in parallel
            Capture
            scrcpy, 1280×720, one eye at 16:9
            Capture all
            11 headsets, median 1.8 s measured
            Headset wall
            Up to 16 tiles, 480 px wide, 10 fps
            Unity feed
            NDI / Spout, 15 fps, 960 px wide; Spout on Windows only

            05Licensing

            Licence
            XRPR, verified online once per launch
            Expiry & revocation
            Expiry date shown, amber within 7 days; a revocation takes effect at the next launch

            06Build

            Portable config
            A writable config.json beside the .exe makes that folder the data folder; login and room passwords stay in the user folder
            Logging
            5 MB × 5 rotating files
            Version
            v0.3.8

            ● Book a demo

            Keep the unknowns outside the next show.

            Tell us your floor size and your run of show, and we will demo it against your actual setup. If you are planning to license a work to a curator or an operating partner abroad, we can walk through the licensing and handover flow as well.

            Read the spec first

            The spec sheet lists the ports, read interval, capture and licensing figures. For the full document on the licensing model and Photon room delivery, say so in the form.

            See the spec sheet

            Used only to reply to this enquiry. Never added to a marketing list.