Guarda come viene costruito
Film / Crea un’app kiosk con l’SDK
3:07

Claude Code scrive un kiosk check-in lobby contro window.screenrig: waitUntilActive(), ready(), kv.get() e emitConfirmed(). Il tocco di un visitatore raggiunge l’agente, che risponde sul muro di benvenuto. Capitoli e trascrizione →
Il runtime è già nell’app
app pack e app upload prendono una directory statica già costruita con una radice index.html. Il pacchettizzatore inietta _screenrig/runtime.js e aggiunge il suo tag script a quel documento. L’applicazione in esecuzione riceve window.screenrig senza passaggi di build e senza dipendenze npm: non c’è nulla da installare, importare o configurare.
Ogni versione immutabile dell’applicazione viene eseguita su una propria origine isolata sotto apps.screenrig.ai. L’id dell’applicazione sopravvive alla versione, quindi i dati chiave/valore scritti da una versione restano disponibili anche per la successiva.
La superficie window.screenrig
Tre proprietà in sola lettura, dieci metodi, un namespace kv di altri cinque e un namespace device per il display, la presenza, i tasti fisici, il sensore di luce, lo stato della rete e il feedback aptico. Leggi prima readyState e controlla capabilities prima di chiamare un metodo che una data attivazione potrebbe non avere.
Ogni metodo risponde a una domanda diversa, quindi inizia da ciò che vuoi fare:
| Per fare questo | Chiamata |
|---|---|
| Attendere che il Player attivi questa pagina | screenrig.waitUntilActive() |
| Indica che l’applicazione è attiva e sullo schermo | screenrig.ready() |
| Termina il turno di questa applicazione su una pagina di avanzamento applicazione | screenrig.nextPage() |
| Comunicare al Player che questa pagina non ha nulla da mostrare in questo momento | screenrig.skip(reason) |
| Comunica all’agente che qualcosa è successo | screenrig.emit(code) |
| Il backend ha registrato quell’evento | screenrig.emitConfirmed(code) |
| Lascia una diagnostica per il Player e il runtime da raccogliere | screenrig.log(...) |
| Leggi lo stato live dell’applicazione | screenrig.kv.get(), screenrig.kv.list() |
| Scrivi stato applicazione live | screenrig.kv.set(), screenrig.kv.delete() |
| Aggiorna al momento del cambiamento dello stato dell’applicazione live | screenrig.kv.onChange() |
| Reagire a un cambiamento di dimensione o capacità | screenrig.onResize(), screenrig.onCapabilities() |
| Attenuare, oscurare o riattivare il display | screenrig.device.display.set() |
| Sapere che qualcuno si è avvicinato allo schermo | screenrig.device.onPresence() |
| Prendere il controllo dei tasti volume fisici | screenrig.device.onKey() |
| Sapere il livello di luce ambientale | screenrig.device.onLight() |
| Sapere che il dispositivo è andato online o offline | screenrig.device.onNetwork() |
| Riprodurre un impulso aptico | screenrig.device.vibrate() |
| Rimuovere i listener quando l’applicazione ha finito con il runtime | screenrig.destroy() |
screenrig.readyState#
Se il runtime iniettato è collegato. Ogni documento inizia inert e diventa active quando arrivano handshake e contesto del Player; una pagina non ancora su schermo resta inert. Aspetta active con screenrig.waitUntilActive(); non considerare inert al caricamento come “fuori screenRIG”. Su failed, o quando window.screenrig manca, mostra il tuo contenuto e salta la superficie sottostante, così la stessa build funziona anche fuori screenRIG. Mentre inert, ready(), log(), emit(), emitConfirmed(), nextPage(), skip() e kv leggono e scrivono lanciando o rifiutando con codice inert; kv.onChange può essere registrato in qualsiasi momento.
screenrig.context#
Dove viene eseguito questo documento.
| Campo | Tipo | Note |
|---|---|---|
application_id | string | L’ID app_ da app upload. Il key/value store gli appartiene. |
release_id | string | La release immutabile che serve questa origine. |
primitive_id | string | Il primitivo che questo documento riempie nella pagina corrente. |
viewport | { width, height } | La superficie in cui il Player esegue il rendering. |
primitive | { width, height } | Il rettangolo che questo documento occupa all’interno di quella viewport. |
capabilities | object | Gli stessi booleani di screenrig.capabilities. |
screen_id | stringa, opzionale | Presente quando il runtime sa quale schermo sta riproducendo. |
context è descrizione, non materiale di richiesta. Nulla in esso è destinato a essere firmato, inoltrato o inviato a screenRIG; i metodi seguenti portano ciò che il runtime richiede.
I parametri di avvio non fanno parte di context: una playlist può dare a un'applicazione params (vedi Token dello schermo negli indirizzi iframe e nei parametri dell'applicazione), e il Player aggiunge ciascuno all'indirizzo della pagina come parametro di query dopo ticket. Leggili da location.search, ad esempio new URLSearchParams(location.search).get("kiosk"). Sono suggerimenti, non credenziali, e chiunque possa aprire la pagina può inviare qualsiasi valore, quindi trattali come input non attendibile; context.screen_id resta il modo per sapere quale schermo sta riproducendo. I Player Qt, Android, Apple e Windows caricano un'applicazione dal pacchetto locale, che non ha un indirizzo di avvio, e non le passano parametri.
screenrig.capabilities#
Dieci booleani che indicano quali metodi gated faranno qualcosa per questa attivazione. Le chiavi sono puntate, quindi leggile con la notazione a parentesi quadre.
| Segnala | Cancelli |
|---|---|
page.advance | screenrig.nextPage() |
page.skip | screenrig.skip() |
kv.read | screenrig.kv.get(), screenrig.kv.list() e screenrig.kv.onChange() |
kv.write | screenrig.kv.set() e screenrig.kv.delete() |
device.display | screenrig.device.display.get(), .set() e screenrig.device.onDisplay() |
device.presence | screenrig.device.onPresence() |
device.keys | screenrig.device.onKey() |
device.light | screenrig.device.onLight() |
device.network | screenrig.device.onNetwork() |
device.haptics | screenrig.device.vibrate() |
if (window.screenrig.capabilities["kv.write"]) {
saveButton.hidden = false;
}Iscriviti con onCapabilities invece di leggere i flag una volta all’avvio.
screenrig.waitUntilActive(timeoutMs)#
Chiamalo per primo, prima di qualsiasi altro metodo, e rendi la tua UI mentre attende. Si risolve quando il Player ha attivato questa pagina, o subito se il runtime è già active, e non dichiara l’applicazione resa. Rifiuta con activation_timeout dopo timeoutMs (default 10000, massimo 300000); una pagina in attesa può semplicemente attendere di nuovo. Avvia l’audio dopo la risoluzione, perché il Player carica un’applicazione prima che la sua pagina compaia: uno schermo il cui browser consente la riproduzione automatica lo avvia subito, mentre su uno il cui browser la rifiuta play() viene rifiutato con NotAllowedError; intercetta l’errore e riproduci senza audio.
const sr = window.screenrig;
async function start() {
render(); // the UI works with or without screenRIG
if (!sr) return;
for (;;) {
try { await sr.waitUntilActive(60000); break; }
catch (err) { if (err.code !== "activation_timeout") return; }
}
await sr.ready();
// From here: emit, emitConfirmed, log, kv, nextPage.
}
start();Controlla readyState === "active" prima di una chiamata SDK da un gestore eventi, timer o catch, e metti in coda l’input che arriva prima. Un log() da un gestore che gira mentre inert lancia un’eccezione, che può terminare l’avvio prima che venga inviato un evento.
screenrig.ready()#
Chiamalo dopo che waitUntilActive() si risolve e prima di dipendere da context, kv o nextPage, una volta che l’applicazione ha ciò che serve per essere sullo schermo. Se chiamato durante inert, genera un errore.
await window.screenrig.waitUntilActive();
await window.screenrig.ready();screenrig.nextPage()#
Chiamalo solo su una pagina di avanzamento applicazione dove questa primitiva è il controller, quando l’applicazione ha finito il suo turno. È one-shot: un’attivazione ottiene un avanzamento.
window.screenrig.nextPage();Il metodo è per una pagina il cui advance.mode è application, dove questa primitiva è il controller:
{
"advance": { "mode": "application", "max_ms": 60000 },
"primitives": [
{
"id": "app",
"primitive": "application",
"release_id": "rel_01EXAMPLERELEASE000000000",
"rect": { "x": 0, "y": 0, "width": 1920, "height": 1080 },
"layer": 0,
"content_fit": "fill",
"controller": true
}
]
}Esattamente una primitiva in quella pagina contiene controller: true e deve essere una primitiva applicativa. max_ms nella pagina avanza i limiti dell’oggetto turno.
screenrig.skip(reason)#
Chiamalo al posto di ready() quando l’applicazione non ha nulla da mostrare in questo momento. Lo schermo passa subito oltre con la normale transizione della pagina e questa apparizione non conta alcuna riproduzione. È una decisione presa all’avvio: chiamalo entro dieci secondi dall’attivazione e prima di ready().
await window.screenrig.waitUntilActive();
const events = await loadToday();
if (events.length === 0) {
await window.screenrig.skip("no events today");
} else {
render(events);
await window.screenrig.ready();
}Il controller della pagina, o l’applicazione da sola sulla sua pagina, ha la capacità, su una pagina senza immagini né video. Il metodo rifiuta con capability_denied senza di essa, con skip_after_ready dopo che ready() è stato chiamato e con not_supported su un Player che non lo supporta. Rifiuta con forbidden quando il Player mantiene la pagina: l’operatore la trattiene, il display è spento, nessun’altra pagina può essere riprodotta o anche tutte le altre pagine sono state saltate. Mostra allora il tuo contenuto di ripiego e chiama ready(). Una playlist di riquadri che saltano tutti mostra l’ultimo per tutta la sua durata invece di girare in ciclo. Il reason facoltativo (al massimo 64 caratteri) compare nel log del Player del progetto come player.application_skipped. skip() è incluso nel runtime che app pack e app upload iniettano, quindi reimpacchetta una release per darle il metodo.
screenrig.emit(code)#
Usalo quando l’agente deve sapere che qualcosa è successo: una pagina ha completato un passaggio, un modulo kiosk è stato inviato, l’applicazione ha dimostrato di essere eseguita. Questo è un evento applicativo nominato, che arriva nel registro eventi del progetto dove l’agente lo osserva con la CLI inclusa events list o events follow. Un codice, nessun corpo messaggio.
log non è un sostituto. Una diagnostica non è un evento applicativo e un agente che legge il registro eventi non lo vedrà.
window.screenrig.emit("menu.rendered");I metodi SDK emit() ed emitConfirmed() aggiungono record application.event la cui risorsa è lo schermo. Leggili con --type application.event, aggiungendo facoltativamente --screen-id. I campi restituiti details.primitive_id e details.code identificano la primitiva emittente e l’azione denominata. --app-id seleziona gli eventi della risorsa applicazione, delle release e delle voci K/V, quindi esclude questi eventi dello schermo.
screenrig events list --type application.event --screen-id scr_SCREEN| Parametro | Tipo | Note |
|---|---|---|
code | string | Sanificato a [A-Za-z0-9._-], massimo 64 caratteri. |
screenrig.emitConfirmed(code)#
Usalo quando l’applicazione deve sapere che l’evento è arrivato: un ordine kiosk è stato effettuato, un modulo inviato, una visita terminata. Invia lo stesso evento applicativo nominato di emit, e la sua promessa si risolve solo quando il Player conferma che il backend ha accettato l’evento.
Rifiuta con il problema backend quando l’evento è rifiutato, e con ack_timeout dopo 10 secondi senza risposta. Non riprovare automaticamente dopo timeout: il backend potrebbe aver già accettato l’evento. Una ricevuta prova che l’evento è nel log eventi progetto, non che qualcosa abbia ancora agito su di esso.
Le ricevute funzionano su ogni Player che esegue applicazioni.
await window.screenrig.emitConfirmed("order.placed");| Parametro | Tipo | Note |
|---|---|---|
code | string | Sanificato a [A-Za-z0-9._-], massimo 64 caratteri. |
screenrig.log({ level, code, message })#
Usalo per la diagnostica: il debug, info, warn e error sono testi che il Player e il runtime raccolgono mentre l’applicazione è sullo schermo. I log del runtime iniettato passano tramite questo metodo stesso. Il logging è limitato: 32 righe per client e al massimo 2048 byte per messaggio. Registra ciò che serve per il debug, non una riga per frame.
Non usare log quando intendi emit. Gli agenti non trattano le righe di log come eventi applicativi, quindi tutto ciò su cui l’agente deve agire appartiene a un codice emit.
window.screenrig.log({
level: "warn",
code: "menu.stale",
message: "Falling back to the cached menu."
});| Campo | Tipo | Note |
|---|---|---|
level | string | debug, info, warn o error. |
code | string | Sanificato a [A-Za-z0-9._-], massimo 64 caratteri. |
message | string | Al massimo 2048 byte. |
screenrig.onResize(handler)#
Iscriviti quando il layout può cambiare sotto di te invece di leggere context una volta. Il gestore riceve { viewport, primitive }, gli stessi due oggetti che porta context, e la chiamata restituisce la funzione che termina l’iscrizione.
const stopResize = window.screenrig.onResize(function (size) {
render(size.viewport, size.primitive);
});
stopResize();screenrig.onCapabilities(handler)#
Iscriviti quando le capacità concesse possono cambiare invece di decidere una volta all’avvio. Leggi screenrig.capabilities dentro il gestore per i booleani correnti e abilita o nascondi i controlli interessati; la chiamata restituisce la funzione che termina l’iscrizione.
const stopCapabilities = window.screenrig.onCapabilities(function () {
saveButton.hidden = !window.screenrig.capabilities["kv.write"];
});screenrig.destroy()#
Rimuovi i listener quando l’applicazione ha finito con il runtime. Un’applicazione che gira per tutto il suo turno e lascia che il Player sostituisca il documento non deve chiamarla.
screenrig.kv#
Il key/value store dell’applicazione, per lo stato live dell’app che sopravvive a un’attivazione. Cinque metodi propri: get, list, set, delete e onChange. Vedi il key/value store sotto.
Il database chiave/valore
Usa lo store per lo stato live dell’applicazione: il menu che l’applicazione rende, il testo che un operatore ha modificato stamattina, un contatore lasciato dall’ultima attivazione. Leggilo con kv.get e kv.list, scrivilo con kv.set e kv.delete, e ricevi notifiche di ogni modifica con kv.onChange.
Il negozio appartiene all’id applicazione in context.application_id, non a una release, quindi una voce sopravvive al prossimo app upload. I valori sono byte, quindi testo, JSON e piccoli binari fanno il round-trip. Le letture necessitano kv.read e le scritture kv.write; controlla la flag prima di chiamare.
Il negozio e la sua spinta di modifica girano su ogni lettore che esegue applicazioni: l’app web Player (PWA), Android, Amazon Signage Stick, macOS, Windows, Linux, Raspberry Pi, LG webOS Signage, BrightSign e Samsung Smart Signage (Tizen). Apple TV, iPhone e iPad non eseguono applicazioni; vedi supporto primitiva per piattaforma.
screenrig.kv.get(key)#
Leggi lo stato live dell’applicazione. Attendi la promessa.
const entry = await window.screenrig.kv.get("menu");screenrig.kv.list()#
Leggi lo stato live dell’applicazione quando non conosci ancora le chiavi: questo elenca le chiavi memorizzate dall’applicazione. Attendi la promessa.
const keys = await window.screenrig.kv.list();screenrig.kv.set(key, value, options)#
Scrivi stato live dell’applicazione. value è una stringa o un Uint8Array; options è opzionale.
await window.screenrig.kv.set("menu", JSON.stringify(menu), {
contentType: "application/json"
});
await window.screenrig.kv.set("badge.png", pngBytes, {
contentType: "image/png"
});| Parametro | Tipo | Obbligatorio | Note |
|---|---|---|---|
key | string | sì | Vedi chiavi. |
value | stringa o Uint8Array | sì | I byte da memorizzare. |
options.contentType | string | no | Predefinito a text/plain per una stringa e application/octet-stream per un Uint8Array. |
options.expectedRevision | intero non negativo | no | Scrivi solo se la voce è ancora a questa revisione. |
options.idempotencyKey | string | no | Ritenta la stessa scrittura senza applicarla due volte. |
screenrig.kv.delete(key, expectedRevision, options)#
Scrivi stato live dell’applicazione rimuovendo una voce. expectedRevision è opzionale: omettilo per eliminare la voce corrente, o forniscilo per rifiutare modifiche concorrenti.
await window.screenrig.kv.delete("menu");| Parametro | Tipo | Obbligatorio | Note |
|---|---|---|---|
key | string | sì | Vedi chiavi. |
expectedRevision | intero non negativo | no | La revisione a cui era l’elemento quando l’hai letta. |
options.idempotencyKey | string | no | Ritenta la stessa eliminazione senza applicarla due volte. |
screenrig.kv.onChange(handler)#
Aggiorna lo stato live dell’applicazione al cambiamento invece di interrogarlo. Il gestore si attiva ogni volta che una chiave di questa applicazione cambia, chiunque l’abbia modificata: l’agente con kv set, un sistema esterno tramite un webhook chiave/valore, o questa applicazione su qualsiasi schermo. Riceve quale chiave è cambiata, non il valore, quindi leggi il nuovo valore con kv.get. La chiamata restituisce la funzione che termina l’iscrizione.
const sr = window.screenrig;
async function showMenu() {
render(await sr.kv.get("menu"));
}
const stopChanges = sr.kv.onChange(function (change) {
if (change.key === "menu" && !change.deleted) showMenu();
});
await sr.waitUntilActive();
await sr.ready();
await showMenu();Iscriviti prima della prima lettura, così una modifica che arriva mentre leggi non viene persa; un gestore registrato prima dell’attivazione parte una volta che la pagina è attiva. Chiama stopChanges() per terminare l’iscrizione.
Una modifica raggiunge ogni schermo la cui playlist posiziona questa app entro secondi. Diverse scritture rapide a una chiave possono arrivare come una modifica che porta la revisione più recente, quindi considera una modifica come “leggi di nuovo questa chiave”, non come un conteggio di scritture. Una modifica è un segnale, non una storia: leggi ciò che serve all’avvio dell’app, poi segui le modifiche.
| Campo | Tipo | Note |
|---|---|---|
key | string | La chiave modificata. |
revision | intero, opzionale | La nuova revisione della voce. Assente quando deleted è true. |
deleted | boolean | true quando la chiave è stata eliminata. |
Chiavi
Una chiave è da 1 a 256 byte UTF-8. Il limite è in byte, non in caratteri, quindi una chiave con caratteri multi-byte lo raggiunge prima di quanto suggerisca la sua lunghezza. Una chiave non deve iniziare con _screenrig/; quel prefisso appartiene al runtime iniettato.
Revisioni e idempotenza
Ogni voce ha una revisione. Facoltativamente passa expectedRevision a screenrig.kv.set o screenrig.kv.delete per scrivere solo se la voce è ancora alla revisione letta. Una revisione obsoleta significa che qualcun altro ha scritto prima: rileggi la voce, riapplica la modifica e riprova.
idempotencyKey copre l’altra metà. Una scrittura che può essere ritentata dopo una risposta persa può portare la stessa chiave a ogni tentativo, e lo store la applica una volta.
Lo stesso store dalla CLI
L’agente può accedere a queste voci dall’esterno del browser con i comandi kv del CLI incluso contro l’id app_ da app upload. Questa è la vista dell’operatore del negozio. Non sostituisce i cinque metodi sopra: un’applicazione modifica i propri dati tramite screenrig.kv nel browser, mentre è sullo schermo. Una modifica scritta dall’agente raggiunge l’applicazione in esecuzione tramite kv.onChange.
Invia dati da un altro sistema
Un webhook chiave/valore è un URL che scrive una chiave di questa applicazione. Forniscilo a qualsiasi cosa possa inviare una richiesta HTTP POST, come un punto vendita, uno script di foglio di calcolo, un cron job o curl, e ogni post sostituisce il valore di quella chiave. Ogni schermo che esegue l’applicazione ne viene informato tramite kv.onChange in pochi secondi, senza nuove release e senza agente in mezzo.
L’agente ne crea uno per una chiave con il CLI incluso e ti fornisce il suo URL e segreto:
screenrig kv webhook create menu --app-id app_01EXAMPLEAPP00000000000 --description "Point of sale menu feed"La risposta include il url del webhook e il suo secret (srkw_…). Il segreto è mostrato solo alla creazione del webhook e alla rotazione del segreto, quindi inseriscilo subito nel sistema di invio. L’URL non è segreto; il segreto sì.
Il mittente invia il nuovo valore come corpo grezzo della richiesta, con il segreto nell’header Authorization:
curl https://api.screenrig.ai/api/applications/app_01EXAMPLEAPP00000000000/kv-webhooks/kvw_01EXAMPLEWEBHOOK00000/write \
-H "Authorization: Bearer $KV_WEBHOOK_SECRET" \
-H "Content-Type: application/json" \
--data '{"soup":"lentil","price":"6.50"}'Un mittente che parla solo autenticazione HTTP Basic usa l’id webhook come username e il segreto come password:
curl https://api.screenrig.ai/api/applications/app_01EXAMPLEAPP00000000000/kv-webhooks/kvw_01EXAMPLEWEBHOOK00000/write \
--user "kvw_01EXAMPLEWEBHOOK00000:$KV_WEBHOOK_SECRET" \
-H "Content-Type: application/json" \
--data '{"soup":"lentil","price":"6.50"}'- Il corpo, massimo 1 MiB, diventa il valore, e
Content-Typeil suo tipo di contenuto (application/octet-streamse l’header è assente). Il valore raggiunge l’applicazione browser, quindi non inviare mai una credenziale come valore. - Ogni post è una scrittura chiave/valore come
kv set: sostituisce il valore, incrementa la revisione ed è conteggiata per l’archiviazione come qualsiasi altra scrittura. - La risposta è i nuovi metadati della chiave (
key,revision,bytes,sha256,content_typeeupdated_at), mai il suo valore. - Aggiungi un’intestazione
Idempotency-Key(da 8 a 200 caratteri) per riprovare un post in sicurezza: entro 24 ore la stessa chiave vale una volta, e la stessa chiave con un corpo o tipo contenuto diverso è rifiutata conidempotency_mismatch. Senza, ogni post è una nuova scrittura. - Un webhook accetta fino a 120 post al minuto; oltre la risposta è
429conRetry-After. - Un segreto mancante o errato, o un webhook sconosciuto, risponde
401. Un segreto nell’URL o nella query string non è mai accettato. - Un’app ha fino a 20 webhook.
kv webhook rotate-secretemette un nuovo segreto e quello vecchio si ferma subito;kv webhook deleteferma subito l’URL e lascia il valore della chiave al suo posto.
Anche una scheda accetta webhook: un invio costruisce il suo documento dati, così com'è o tramite una mappatura (Webhook delle schede).
Il dispositivo
Un’applicazione che gestisce un pannello a muro o un chiosco può controllare lo schermo su cui gira. I flag device vanno al frame che controlla la sua pagina (il controller della pagina, o la sua unica applicazione), su un Player in grado di farlo su quel dispositivo: il Player Android concede device.display, device.keys e device.network, concede device.presence quando il dispositivo ha una fotocamera e la persona che ha configurato il dispositivo ha consentito al Player di usarla (Impostazioni di Android, App, screenRIG Player, Autorizzazioni, Fotocamera), device.light quando ha un sensore di luce e device.haptics quando ha un motore di vibrazione. I Player che non possono controllare un dispositivo lasciano a false ogni flag device. display.get(), display.set() e vibrate() rifiutano con not_supported su un Player che non li offre e con capability_denied senza il flag. onDisplay, onPresence, onKey, onLight e onNetwork possono essere registrati in qualsiasi momento e, come kv.onChange, semplicemente non vengono mai eseguiti senza il flag.
screenrig.device.display.set(state)#
Attenuare, oscurare o riattivare il display. brightness va da 0 a 1 (0 è il livello più basso della retroilluminazione, non lo spegnimento); on: false oscura il display e on: true lo riaccende. Ometti un membro per lasciarlo com’è. I tocchi raggiungono comunque l’applicazione mentre il display è scuro, quindi un tocco può riattivarlo. Una programmazione del display che lo tiene scuro prevale sull’applicazione, e il Player ripristina il display quando la pagina lascia lo schermo.
await window.screenrig.device.display.set({ brightness: 0.3 });
await window.screenrig.device.display.set({ on: false });screenrig.device.display.get()#
Lo stato attuale del display, come { on, brightness }.
screenrig.device.onDisplay(handler)#
Chiamato con { on, brightness } ogni volta che il display cambia, sia che lo abbia cambiato questa applicazione, una programmazione del display o un operatore.
screenrig.device.onPresence(handler)#
Chiamato quando il dispositivo vede qualcuno muoversi davanti allo schermo, al massimo una volta al secondo. Il Player legge la fotocamera del dispositivo e non conserva alcuna immagine: nessuna immagine viene memorizzata, registrata nel log o inviata. La fotocamera è attiva solo finché è registrato un gestore.
window.screenrig.device.onPresence(function () {
window.screenrig.device.display.set({ on: true, brightness: 1 });
});screenrig.device.onKey(handler)#
Chiamato con "volume_up" o "volume_down" a ogni pressione di un tasto volume fisico, ripetizioni incluse. Finché è registrato un gestore, i tasti appartengono all’applicazione e il volume del dispositivo resta com’è.
screenrig.device.onLight(handler)#
Chiamato con la luce ambientale in lux: la prima lettura dopo la registrazione del gestore, poi ogni volta che la luce cambia di almeno il 10% o attraversa 1 lux, al massimo una volta al secondo. Il dispositivo deve avere un sensore di luce.
window.screenrig.device.onLight(function (lux) {
document.body.classList.toggle("dim-room", lux < 10);
});screenrig.device.onNetwork(handler)#
Chiamato con true o false ogni volta che il dispositivo ottiene o perde la connettività internet convalidata dal sistema, e subito con lo stato corrente quando viene registrato il primo gestore.
window.screenrig.device.onNetwork(function (online) {
offlineBadge.hidden = online;
});screenrig.device.vibrate(ms)#
Riproduci un impulso aptico. ms è un numero intero di millisecondi da 1 a 200 e il valore predefinito è 12. La promessa si risolve senza valore non appena il Player ha avviato la vibrazione, e viene rifiutata con invalid_request, senza inviare nulla, per qualsiasi altro ms.
await window.screenrig.device.vibrate();
await window.screenrig.device.vibrate(40);Raggiungere i dispositivi nella rete dello schermo
Un’applicazione può recuperare dati da indirizzi http:// e ws:// oltre che https://, così può comunicare con un dispositivo o un server sulla rete stessa dello schermo, come un controller a http://192.168.1.20. I Player Android, Linux e Raspberry Pi, Windows e macOS lo consentono. Su un browser in modalità kiosk che esegue l’app web del Player, il proprietario del browser lo consente con un criterio aziendale: vedi Applicazioni sulla rete locale. Il server che chiami risponde a CORS per l’origine dell’applicazione; su macOS le richieste di un’applicazione riportano Origin: null, quindi su macOS il CORS del server consente quell’origine.
Un motore del browser blocca <img src="http://…"> in una pagina sicura, quindi carica le immagini da un indirizzo http:// con fetch() e URL.createObjectURL().
const response = await fetch("http://192.168.1.20/snapshot.jpg");
image.src = URL.createObjectURL(await response.blob());