Toestand en gebeurtenissen
Sound Show stuurt de actuele showtoestand na authenticatie en bij wijzigingen. Bouw je controller op deze snapshots en vraag wijzigingen aan via de commandoreferentie.
Volledige toestand
Sectie “Volledige toestand”Een state-bericht vervangt je volledige lokale toestand. Het volgt automatisch na hello_ok, brede of projectwijzigingen en als antwoord op request_state. Dit verkorte voorbeeld toont hoofdvelden; echte projecten bevatten gevulde arrays en meer metadata.
{ "type": "state", "protocol_version": 2, "server_time_ms": 1712345678901, "state": { "project": { "name": "My show", "categories": [] }, "players": [], "playable_runtime": [], "playlists": { "current_index": 0, "playlists": [] }, "instructions": { "current_index": 0, "players": [] }, "timers": [], "logical_devices": [], "control": { "next_sound_volume": 70, "selected_category_id": null, "low_volume_active": false, "volume_level_presets": [], "active_volume_level_ids": [], "effective_volume_level_id": null }, "capabilities": { "audio_controls": [], "manual_grid_layout": false }, "audio_controls": { "revision": 1, "logical_devices": [], "players": [] }, "lights": { "revision": 1, "lights": [] } }}Ondersteun ontbrekende of null-projecten, lege arrays, optionele en onbekende toegevoegde velden. Dit beschrijft de huidige v2. Oudere Sound Show 2-versies kunnen minder velden, commando’s of functies hebben; controleer hello_ok.features en de mogelijkheden vóór optioneel gebruik.
Live domeinsnapshots
Sectie “Live domeinsnapshots”Na de volledige toestand vervangen de meeste updates één domein, een benoemd onderdeel. Een lege array heeft betekenis: players: [] wist de huidige spelers. Voeg array-items niet samen met de oude lijst.
Bericht-type |
Te vervangen lokaal veld | Verzending |
|---|---|---|
control_snapshot |
control |
Directe antwoorden op volumeniveaucommando’s; wijzigingen van alle bedieners met runtime_snapshots. |
players_snapshot |
players |
Spelerwijzigingen. |
instructions_snapshot |
instructions |
Met runtime_snapshots. |
playlists_snapshot |
playlists |
Met runtime_snapshots. |
playable_runtime_snapshot |
playable_runtime |
Met runtime_snapshots. |
logical_devices_snapshot |
logical_devices |
Uitgangswijzigingen. |
timers_snapshot |
timers |
Timerwijzigingen. |
audio_controls_snapshot |
audio_controls |
Effectwijzigingen; vergelijk revision. |
lights_snapshot |
lights |
Lichtwijzigingen; vergelijk revision. |
Elk domeinbericht bevat het gelijknamige gegevensveld en server_time_ms. Bijvoorbeeld:
{ "type": "players_snapshot", "players": [], "server_time_ms": 1712345678901}Audio- en lichtberichten hebben ook een domeinrevisie:
{ "type": "audio_controls_snapshot", "revision": 5, "audio_controls": { "revision": 5, "logical_devices": [], "players": [] }, "server_time_ms": 1712345678901}Negeer voor deze twee domeinen revisies die lager zijn dan de reeds toegepaste revisie. Vergelijk revisies niet tussen domeinen. Een volledige state zet de basis opnieuw; wis alle lokale toestand en revisies bij verbreken. Pas andere domeinen in ontvangstvolgorde toe.
Vraag runtime_snapshots aan in hello.features. Anders worden wijzigingen van bediening, instructies en lijsten als samengevoegde volledige toestanden verstuurd, behalve directe bedieningsantwoorden. Alleen gewijzigde elementactiviteit veroorzaakt dan geen volledige toestand.
Runtimewijzigingen worden per cyclus van 50 ms samengevoegd. Dat garandeert geen bericht elke 50 ms of log van elke tussenstap. Een volledige toestand kan wachtende domeinupdates vervangen. Het JavaScript-voorbeeld verwerkt alle huidige snapshottypen.
Het juiste doel kiezen
Sectie “Het juiste doel kiezen”| Om… | Gebruik… |
|---|---|
| Een projectknop te starten | project.categories[].playables[].id als playable_id. |
| Een categorie te selecteren | project.categories[].id als category_id. |
| Eén actieve instantie te stoppen, pauzeren, verplaatsen of regelen | players[].id als player_id. |
| Een uitgang te bedienen | logical_devices[].id als logical_device_id. |
| Een volumepreset te activeren | control.volume_level_presets[].id als level_id. |
| Een effect te regelen | Descriptor-id als control_id, plus een actueel speler- of logisch-apparaatdoel. |
| Een lichtniveau in te stellen | lights.lights[].id als project_light_id. |
| Een lijstitem af te spelen | Huidige lijst- en wachtrijposities vanaf nul. |
| Een instructie te selecteren | Huidige instructiespelerpositie vanaf nul en de path van het item. |
| Een timer te bedienen | De huidige positie vanaf nul als timer_index. |
Speler-ID’s horen bij actieve instanties en zijn geen permanente projectidentiteit. Eén element kan meerdere actieve spelers hebben. Zoek overeenkomende source_playable_id of state_playable_id in de huidige snapshot en kies de bedoelde instantie expliciet. Namen zijn voor weergave bruikbaar maar niet noodzakelijk uniek.
Project en elementen
Sectie “Project en elementen”project.categories[] bevat categorie-id, name, color, is_hidden, optioneel icon_url en playables. Een element bevat:
{ "id": "playable-id", "name": "Wind", "kind": "sound", "color": "#3b82f6", "tags": [], "is_searchable": true, "runtime_state_key": "playable-id", "target_category_id": null}Veelvoorkomende typen zijn sound, video, image, random, timer, playlist, action, webbrowser, category_link en instruction. Accepteer nieuwe of unsupported-typen. Optionele metadata omvat icon_url, sneltoetsen en ID’s van ingestelde klikacties.
playable_runtime bevat items met state_playable_id, play_count, is_locked en is_playing. Koppel de runtime_state_key van het element, of zijn id als dat veld ontbreekt, aan state_playable_id. Gekoppelde elementen kunnen activiteit en vergrendeling delen. Deze projectknopvergrendeling verschilt van de bedieningsvergrendeling van een actieve speler.
Categorieën kunnen optioneel grid_layout met enabled, columns, rows, pages, positions en revision bevatten. Controleer capabilities.manual_grid_layout voordat je dit volgt. Clients mogen deze metadata negeren en de gewone lijst tonen; er is geen commando voor bewerken van de indeling op afstand.
Spelers
Sectie “Spelers”{ "id": "runtime-player-id", "kind": "sound", "title": "Wind", "color": "#3b82f6", "panel_position": 0, "position_seconds": 12.3, "duration_seconds": 95, "start_time_seconds": 5, "stop_time_seconds": 90, "timeline_duration_seconds": 95, "volume_percent": 70, "muted": false, "is_playing": true, "is_locked": false, "loop_enabled": true, "output_logical_device_id": "main", "source_playable_id": "playable-id", "state_playable_id": "playable-id"}Toon volume_percent direct. Het aparte ruwe veld volume, indien aanwezig, is geen percentage om met 100 te vermenigvuldigen; de app kan een niet-lineaire volumeschaal gebruiken.
Tijdlijnvelden gebruiken seconden. start_time_seconds, stop_time_seconds en timeline_duration_seconds kunnen ontbreken of null zijn. Gebruik ze bij zoeken om het bijgesneden afspeelvenster aan de brontijdlijn te koppelen. Andere optionele velden zijn remaining_playback_seconds, markers en icon_url.
Uitgangen en gedeelde bediening
Sectie “Uitgangen en gedeelde bediening”logical_devices[] geeft id, label, display_label, color, output_role, available, selected en volume_percent. Gebruik display_label voor weergave en id voor commando’s.
control geeft het volgende startvolume, de geselecteerde categorie, volume_level_presets, active_volume_level_ids en effective_volume_level_id. Presets bevatten id, name, direction (both, up_only of down_only), target_volume_percent, fade_down_ms en fade_up_ms. low_volume_active ondersteunt oudere controllers. Lees actieve ID’s uit de snapshot; ook andere bedieners kunnen ze wijzigen.
Afspeellijsten, instructies en timers
Sectie “Afspeellijsten, instructies en timers”| Domein | Bruikbare velden |
|---|---|
playlists |
current_index en playlists[]. Elke lijst heeft id, title, autoplay, loop_enabled en queue. Wachtrijitems bevatten playable_id, title en optioneel icon_url. Runtimemetadata kan active_item_id, active_item_title en active_player_id bevatten. |
instructions |
current_index en players[]. Spelers hebben id, title, has_instruction, waiting_for_go, next_instruction_text en items. Items geven item_id, title, kind, depth, path, can_set_next, is_next_to_play en is_visibly_playing. |
timers |
Array met numerieke id, mode, is_running, is_locked, elapsed_ms, duration_ms, remaining_ms en is_over_time. Timertijden zijn in milliseconden. |
Kies voor een GO-voorbeeld bij voorkeur het diepste volgende item met een niet-lege path en een kind anders dan group; neem anders een willekeurig diepst volgend item. Gebruik voor selectie de echte path, niet een pad afgeleid uit titel of diepte.
Audiobediening en mogelijkheden
Sectie “Audiobediening en mogelijkheden”capabilities.audio_controls[] beschrijft beschikbare effectbediening. Elke descriptor levert:
| Veld | Betekenis |
|---|---|
id, label |
Protocol-ID en weergavenaam. |
scopes |
Ondersteunde doelen: logical_device en/of player. |
min, max, default_value |
Oorspronkelijke numerieke grenzen en herstelwaarde. |
suggested_step |
Voorgestelde stapgrootte. |
unit, scale |
Weergave-eenheid en schaal. log2 geeft stappen in octaven. |
display_multiplier |
Vermenigvuldig oorspronkelijke waarden voor weergave; deel invoer hierdoor vóór verzending. |
Een verhouding 0.5 met display_multiplier: 100 verschijnt bijvoorbeeld als 50%. Gebruik de aangeboden catalogus in plaats van vaste bereiken.
audio_controls bevat revision, logical_devices[] en players[]. Elk doel heeft kind, id, label, available, locked en een values-object met bedienings-ID’s en oorspronkelijke numerieke waarden. Lineaire bediening fade lineair; log2-bediening geometrisch.
Verlichting
Sectie “Verlichting”lights bevat revision en lights[]. Elke lamp heeft id, name, capability (momenteel level) en available. value_percent ontbreekt als de adapter niet beschikbaar is. Toon onbeschikbaarheid, niet nul.
Pictogrammen
Sectie “Pictogrammen”Snapshots kunnen een ondoorzichtige relatieve icon_url bevatten, bijvoorbeeld /asset/file?id=opaque-asset-id. Los die op ten opzichte van het HTTP-adres van de server en haal hem via HTTP op. Pictogrammen zijn geen WebSocket-berichten.
Gebruik de geleverde URL zonder ID’s te maken of bestandspaden te sturen. Cache pictogrammen tijdens de huidige serversessie; verwacht nieuwe ID’s na herstart. Projectwijzigingen kunnen bronnen onbeschikbaar maken: toon een alternatief bij mislukte afbeeldingsverzoeken. Lokale bestandspaden verschijnen niet in snapshots.
Fouten en limieten
Sectie “Fouten en limieten”Een geauthenticeerde verbinding kan ontvangen:
{ "type": "error", "code": "invalid_value", "command_id": "eq-change-1", "message": "Human-readable error description"}code en command_id zijn optioneel. Audio-/lichtfouten kunnen unknown_control, target_locked, target_not_found, invalid_value, target_unavailable of command_failed zijn. Oudere commandopaden geven soms alleen message. Gebruik leesbare tekst niet als stabiele foutcode. Een fout kan de verbinding openlaten; blijf snapshots verwerken.
| Limiet | Clientgedrag |
|---|---|
| Eerste bericht binnen 10 seconden | Stuur hello direct na openen. |
| 16 gelijktijdige WebSocket-verbindingen | Hergebruik verbindingen en sluit ongebruikte clients. Niet-geauthenticeerde sockets tellen mee. |
| 64 KiB per inkomend bericht/frame | Eén klein JSON-commando per bericht. |
| Burst van 60 commando’s, aangevuld met 20 per seconde per verbinding | Beperk schuifregelaars en combineer wachtende waarden. Ping en verversen gebruiken hetzelfde budget. |
| Vijf verkeerde wachtwoorden vanaf één adres binnen 60 seconden | Corrigeer het wachtwoord en wacht. Nieuwe WebSocket-upgrades worden 60 seconden geblokkeerd met HTTP 429 en Retry-After. |
Een door de snelheidslimiet geweigerd commando wordt niet uitgevoerd en geeft code: "rate_limited". Aanhoudende overschrijding kan de verbinding sluiten. Volg Retry-After als je client het HTTP-antwoord toont. Meldt een browser alleen een verbindingsfout na herhaalde authenticatiefouten, wacht dan minstens 60 seconden. Herhaal afspelen, schakelen of GO niet blind: dat kan een tweede actie veroorzaken.
Hartslag en opnieuw verbinden
Sectie “Hartslag en opnieuw verbinden”Als hello_ok.features de functie ping bevat, kan een geauthenticeerde client {"type":"ping"} sturen en {"type":"pong"} verwachten. De ingebouwde afstandsbediening pingt elke tien seconden en verbindt bij die controle opnieuw als er langer dan 25 seconden geen geldig bericht is ontvangen. Ongewijzigde domeinen kunnen verder stil blijven.
Voor een blijvend actieve controller:
- Schakel commando’s uit zodra de socket sluit of de hartslag faalt.
- Wis gecachete toestand, speler-ID’s en revisies.
- Verbind opnieuw met een begrensde wachttijd die bij herhaalde fouten toeneemt. Respecteer authenticatiefouten en snelheidslimieten.
- Stuur een nieuwe
hello, wacht op de volledigestateen bepaal doelen opnieuw. - Schakel bediening in op basis van die toestand. Herhaal na herverbinden geen wachtende start-, schakel- of GO-commando’s.
Verbindingsgebonden volumehoudacties worden losgelaten bij verbreken. Behandel opnieuw verbinden als een nieuwe sessie, ook als het serveradres gelijk blijft.
Externe origins toestaan wijzigen werkt direct en verbreekt bestaande verbindingen. Na uitschakelen kunnen browsers van andere origins niet opnieuw verbinden. Zie eigen browserafstandsbedieningen voor instellingen en browserbeperkingen.