Zusehen, wie es gebaut wird
Film / Kiosk-App mit dem SDK erstellen
3:07

Claude Code schreibt einen Lobby-Check-in-Kiosk gegen window.screenrig: waitUntilActive(), ready(), kv.get() und emitConfirmed(). Ein Besuchertipp erreicht den Agenten, und dieser antwortet an der Willkommenswand. Kapitel und Transkript →
Die Laufzeit ist bereits in der App
app pack und app upload nehmen ein bereits erstelltes statisches Verzeichnis mit einer Wurzel index.html. Der Packer injiziert _screenrig/runtime.js und fügt dessen Skript-Tag zu diesem Dokument hinzu. Die laufende Anwendung erhält window.screenrig ohne Build-Schritt und ohne npm-Abhängigkeit: Es gibt nichts zu installieren, nichts zu importieren und nichts zu konfigurieren.
Jede unveränderliche Anwendungsfreigabe läuft auf einer eigenen isolierten Origin unter apps.screenrig.ai. Die Anwendungs-ID überlebt die Freigabe, sodass Schlüssel/Wert-Daten, die von einer Freigabe geschrieben wurden, für die nächste noch vorhanden sind.
Die window.screenrig Oberfläche
Drei schreibgeschützte Eigenschaften, zehn Methoden, ein kv-Namespace mit fünf weiteren und ein device-Namespace für Bildschirm, Präsenz, Hardwaretasten, Lichtsensor, Netzwerkstatus und Haptik. Lesen Sie zuerst readyState und prüfen Sie capabilities, bevor Sie eine Methode aufrufen, die eine bestimmte Aktivierung möglicherweise nicht hat.
Jede Methode beantwortet eine andere Frage, beginnen Sie also mit dem, was Sie tun möchten:
| Um dies zu tun | Anruf |
|---|---|
| Warten Sie, bis der Player diese Seite aktiviert | screenrig.waitUntilActive() |
| Sagen, dass die Anwendung läuft und auf dem Bildschirm ist | screenrig.ready() |
| Diesen Anwendungsdurchlauf auf einer Anwendungs-Weiterleitungsseite beenden | screenrig.nextPage() |
| Dem Player mitteilen, dass diese Seite gerade nichts anzuzeigen hat | screenrig.skip(reason) |
| Dem Agenten mitteilen, dass etwas passiert ist | screenrig.emit(code) |
| Den Backend-Ereignisaufzeichnung kennen | screenrig.emitConfirmed(code) |
| Eine Diagnose hinterlassen, die Player und Laufzeit sammeln können | screenrig.log(...) |
| Live-Anwendungsstatus lesen | screenrig.kv.get(), screenrig.kv.list() |
| Live-Anwendungsstatus schreiben | screenrig.kv.set(), screenrig.kv.delete() |
| Aktualisieren, sobald sich der Live-Anwendungsstatus ändert | screenrig.kv.onChange() |
| Auf Größen- oder Fähigkeitsänderung reagieren | screenrig.onResize(), screenrig.onCapabilities() |
| Den Bildschirm dimmen, abdunkeln oder aufwecken | screenrig.device.display.set() |
| Mitbekommen, dass jemand an den Bildschirm getreten ist | screenrig.device.onPresence() |
| Die Hardware-Lautstärketasten übernehmen | screenrig.device.onKey() |
| Die Umgebungshelligkeit mitbekommen | screenrig.device.onLight() |
| Mitbekommen, dass das Gerät online oder offline gegangen ist | screenrig.device.onNetwork() |
| Einen haptischen Tick auslösen | screenrig.device.vibrate() |
| Listener abbauen, wenn die Anwendung die Laufzeit beendet hat | screenrig.destroy() |
screenrig.readyState#
Ob die injizierte Laufzeit angehängt ist. Jedes Dokument startet mit inert und wird active, wenn der Handshake und Kontext des Players eintreffen; eine Seite, die noch nicht auf dem Bildschirm ist, bleibt inert. Warten Sie auf active mit screenrig.waitUntilActive(); behandeln Sie inert beim Laden nicht als „außerhalb von screenRIG“. Bei failed oder wenn window.screenrig fehlt, rendern Sie Ihren eigenen Inhalt und überspringen Sie die darunterliegende Oberfläche, sodass derselbe Build auch außerhalb von screenRIG läuft. Während inert, ready(), log(), emit(), emitConfirmed(), nextPage(), skip() und das Lesen und Schreiben von kv mit Code inert werfen oder ablehnen; kv.onChange kann jederzeit registriert werden.
screenrig.context#
Wo dieses Dokument ausgeführt wird.
| Feld | Typ | Notizen |
|---|---|---|
application_id | string | Die app_ ID von app upload. Der Schlüssel/Wert-Speicher gehört dazu. |
release_id | string | Die unveränderliche Version, die diesen Ursprung bedient. |
primitive_id | string | Das Primitive, das dieses Dokument auf der aktuellen Seite füllt. |
viewport | { width, height } | Die Oberfläche, in die der Player rendert. |
primitive | { width, height } | Das Rechteck, das dieses Dokument innerhalb dieses Viewports einnimmt. |
capabilities | object | Dieselben Booleans wie screenrig.capabilities. |
screen_id | string, optional | Vorhanden, wenn die Laufzeit weiß, welcher Bildschirm gerade spielt. |
context ist Beschreibung, kein Anforderungsmaterial. Nichts darin soll signiert, weitergeleitet oder an screenRIG zurückgesendet werden; die untenstehenden Methoden tragen, was die Laufzeit benötigt.
Startparameter sind nicht Teil von context: Eine Playlist kann einer Anwendung params geben (siehe Bildschirm-Token in Iframe-Adressen und Anwendungsparametern), und der Player hängt jeden als Query-Parameter nach ticket an die Adresse der Seite an. Lesen Sie sie aus location.search, zum Beispiel new URLSearchParams(location.search).get("kiosk"). Sie sind Hinweise, keine Zugangsdaten, und jeder, der die Seite öffnen kann, kann beliebige Werte senden; behandeln Sie sie daher als nicht vertrauenswürdige Eingabe; context.screen_id bleibt der Weg, um zu erfahren, welcher Bildschirm spielt. Die Qt-, Android-, Apple- und Windows-Player laden eine Anwendung aus ihrem lokalen Paket, das keine Startadresse hat, und übergeben ihr keine Parameter.
screenrig.capabilities#
Zehn Booleans, die angeben, welche gesperrten Methoden für diese Aktivierung etwas bewirken. Die Schlüssel sind gepunktet, lesen Sie sie mit der Klammernotation.
| Markieren | Tore |
|---|---|
page.advance | screenrig.nextPage() |
page.skip | screenrig.skip() |
kv.read | screenrig.kv.get(), screenrig.kv.list() und screenrig.kv.onChange() |
kv.write | screenrig.kv.set() und screenrig.kv.delete() |
device.display | screenrig.device.display.get(), .set() und 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;
}Abonnieren Sie mit onCapabilities anstelle des einmaligen Lesens der Flags beim Start.
screenrig.waitUntilActive(timeoutMs)#
Rufen Sie es zuerst auf, vor jeder anderen Methode, und rendern Sie Ihre UI, während es wartet. Es wird aufgelöst, wenn der Player diese Seite aktiviert hat, oder sofort, wenn die Laufzeit bereits active ist, und es erklärt die Anwendung nicht als gerendert. Es lehnt mit activation_timeout nach timeoutMs ab (Standard 10000, maximal 300000); eine Seite, die auf ihren Zug wartet, kann einfach erneut warten. Starten Sie den Ton, nachdem es aufgelöst wurde, denn der Player lädt eine Anwendung, bevor ihre Seite erscheint: Ein Bildschirm, dessen Browser Autoplay erlaubt, startet ihn sofort; auf einem, dessen Browser es verweigert, wird play() mit NotAllowedError abgelehnt, fangen Sie den Fehler also ab und spielen Sie stumm ab.
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();Prüfen Sie readyState === "active" vor einem SDK-Aufruf aus einem Ereignishandler, Timer oder catch und fügen Sie Eingaben hinzu, die früher eintreffen. Ein log() von einem Handler, der während inert läuft, wirft ebenfalls eine Ausnahme, was den Start vor dem Senden eines Ereignisses beenden kann.
screenrig.ready()#
Rufen Sie es nach der Auflösung von waitUntilActive() auf und bevor Sie von context, kv oder nextPage abhängen, sobald die Anwendung alles hat, was sie für die Anzeige benötigt. Wird während inert aufgerufen, löst es einen Fehler aus.
await window.screenrig.waitUntilActive();
await window.screenrig.ready();screenrig.nextPage()#
Rufen Sie es nur auf einer Anwendungs-Advance-Seite auf, auf der dieses Primitive der Controller ist, wenn die Anwendung ihren Zug beendet hat. Es ist einmalig: eine Aktivierung erhält einen Advance.
window.screenrig.nextPage();Die Methode ist für eine Seite, deren advance.mode application ist, wobei dieses Primitive der Controller ist:
{
"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
}
]
}Genau ein Primitive auf dieser Seite trägt controller: true und es muss ein Anwendungsprimitive sein. max_ms auf dem Seitenfortschrittsobjekt begrenzt den Zug.
screenrig.skip(reason)#
Rufen Sie sie anstelle von ready() auf, wenn die Anwendung gerade nichts anzuzeigen hat. Der Bildschirm geht sofort mit dem normalen Übergang der Seite weiter, und dieser Auftritt zählt keine Wiedergabe. Es ist eine Entscheidung zum Start: Rufen Sie sie innerhalb von zehn Sekunden nach der Aktivierung und vor ready() auf.
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();
}Der Controller der Seite oder die Anwendung, die allein auf ihrer Seite ist, besitzt die Berechtigung, auf einer Seite ohne Bild oder Video. Die Methode lehnt ohne sie mit capability_denied ab, mit skip_after_ready, sobald ready() aufgerufen wurde, und mit not_supported auf einem Player, der sie nicht kennt. Sie lehnt mit forbidden ab, wenn der Player die Seite behält: Der Operator hält sie fest, der Bildschirm ist dunkel, keine andere Seite kann laufen, oder alle anderen Seiten wurden ebenfalls übersprungen. Zeigen Sie dann Ihren Ersatzinhalt an und rufen Sie ready() auf. Eine Playlist aus Kacheln, die alle überspringen, zeigt die letzte in voller Dauer, statt im Kreis zu laufen. Der optionale reason (höchstens 64 Zeichen) erscheint im Player-Protokoll des Projekts als player.application_skipped. skip() kommt mit der Laufzeit, die app pack und app upload einfügen, packen Sie ein Release also neu, um ihm die Methode zu geben.
screenrig.emit(code)#
Verwenden Sie es, wenn der Agent sehen soll, dass etwas passiert ist: eine Seite hat einen Schritt abgeschlossen, ein Kioskformular wurde abgeschickt, die Anwendung hat bewiesen, dass sie lief. Dies ist ein benanntes Anwendungsereignis, das im Ereignisprotokoll des Projekts landet, wo der Agent es mit dem mitgelieferten CLI events list oder events follow überwacht. Ein Code, keine Nachrichteninhalte.
log ist kein Ersatz. Eine Diagnose ist kein Anwendungsereignis, und ein Agent, der das Ereignisprotokoll liest, wird es nicht sehen.
window.screenrig.emit("menu.rendered");Die SDK-Methoden emit() und emitConfirmed() fügen application.event-Datensätze hinzu, deren Ressource der Bildschirm ist. Lesen Sie diese mit --type application.event und optional --screen-id. Die zurückgegebenen Felder details.primitive_id und details.code identifizieren das sendende Primitive und die benannte Aktion. --app-id wählt Ereignisse der Anwendungsressource, ihrer Releases und K/V-Einträge aus und schließt diese Bildschirmereignisse daher aus.
screenrig events list --type application.event --screen-id scr_SCREEN| Parameter | Typ | Notizen |
|---|---|---|
code | string | Bereinigt auf [A-Za-z0-9._-], höchstens 64 Zeichen. |
screenrig.emitConfirmed(code)#
Verwenden Sie es, wenn die Anwendung wissen muss, dass das Ereignis angekommen ist: eine Kioskbestellung wurde aufgegeben, ein Formular gesendet, ein Besuch beendet. Es sendet dasselbe benannte Anwendungsereignis wie emit, und sein Versprechen wird erst erfüllt, wenn der Player bestätigt, dass das Backend das Ereignis akzeptiert hat.
Sie lehnt mit dem Backend-Problem ab, wenn das Ereignis abgelehnt wird, und mit ack_timeout nach 10 Sekunden ohne Antwort. Nach einem Timeout nicht automatisch erneut versuchen: Das Backend hat das Ereignis möglicherweise bereits akzeptiert. Eine Empfangsbestätigung beweist, dass das Ereignis im Projekt-Ereignisprotokoll ist, nicht dass bereits etwas darauf reagiert hat.
Belege funktionieren auf jedem Player, der Anwendungen ausführt.
await window.screenrig.emitConfirmed("order.placed");| Parameter | Typ | Notizen |
|---|---|---|
code | string | Bereinigt auf [A-Za-z0-9._-], höchstens 64 Zeichen. |
screenrig.log({ level, code, message })#
Verwenden Sie es für Diagnosen: die debug, info, warn und error Texte, die der Player und die Laufzeit sammeln, während die Anwendung auf dem Bildschirm ist. Die injizierten Laufzeitprotokolle erfolgen über diese Methode selbst. Das Logging ist begrenzt: 32 Zeilen pro Client und maximal 2048 Bytes pro Nachricht. Protokollieren Sie, was Sie beim Debuggen benötigen, nicht eine Zeile pro Frame.
Greifen Sie nicht auf log zu, wenn Sie emit meinen. Agenten behandeln Protokollzeilen nicht als Anwendungsereignisse, daher gehört alles, worauf der Agent reagieren muss, in einen emit-Code.
window.screenrig.log({
level: "warn",
code: "menu.stale",
message: "Falling back to the cached menu."
});| Feld | Typ | Notizen |
|---|---|---|
level | string | debug, info, warn oder error. |
code | string | Bereinigt auf [A-Za-z0-9._-], höchstens 64 Zeichen. |
message | string | Maximal 2048 Bytes. |
screenrig.onResize(handler)#
Abonnieren, wenn sich das Layout unter Ihnen ändern kann, anstatt context einmal zu lesen. Der Handler erhält { viewport, primitive }, dieselben zwei Objekte, die context trägt, und der Aufruf gibt die Funktion zurück, die das Abonnement beendet.
const stopResize = window.screenrig.onResize(function (size) {
render(size.viewport, size.primitive);
});
stopResize();screenrig.onCapabilities(handler)#
Abonnieren, wenn sich die gewährten Fähigkeiten ändern können, anstatt einmalig beim Start zu entscheiden. Lesen Sie screenrig.capabilities im Handler für die aktuellen Booleans und aktivieren oder verbergen Sie die betroffenen Steuerelemente; der Aufruf gibt die Funktion zurück, die das Abonnement beendet.
const stopCapabilities = window.screenrig.onCapabilities(function () {
saveButton.hidden = !window.screenrig.capabilities["kv.write"];
});screenrig.destroy()#
Listener abbauen, wenn die Anwendung die Laufzeit beendet. Eine Anwendung, die ihre gesamte Runde läuft und den Player das Dokument ersetzen lässt, muss dies nicht aufrufen.
screenrig.kv#
Der Schlüssel/Wert-Speicher der Anwendung für den Live-Anwendungszustand, der eine Aktivierung überdauert. Fünf eigene Methoden: get, list, set, delete und onChange. Siehe den Schlüssel/Wert-Speicher unten.
Der Schlüssel-/Wert-Speicher
Verwenden Sie den Store für den Live-Anwendungsstatus: das Menü, das die Anwendung rendert, den Text, den ein Bediener heute Morgen geändert hat, einen Zähler, den die letzte Aktivierung hinterlassen hat. Lesen Sie ihn mit kv.get und kv.list, schreiben Sie ihn mit kv.set und kv.delete und erhalten Sie Benachrichtigungen über jede Änderung mit kv.onChange.
Der Store gehört zur Anwendungs-ID in context.application_id, nicht zu einem Release, sodass ein Eintrag die nächste app upload überdauert. Werte sind Bytes, sodass Text, JSON und kleine Binärdateien alle rundlaufen. Lesevorgänge benötigen kv.read und Schreibvorgänge kv.write; prüfen Sie die Flagge, bevor Sie aufrufen.
Der Store und sein Änderungs-Push laufen auf jedem Player, der Anwendungen ausführt: die Player-Web-App (PWA), Android, Amazon Signage Stick, macOS, Windows, Linux, Raspberry Pi, LG webOS Signage, BrightSign und Samsung Smart Signage (Tizen). Apple TV, iPhone und iPad führen keine Anwendungen aus; siehe Primitive-Unterstützung nach Plattform.
screenrig.kv.get(key)#
Live-Anwendungsstatus lesen. Warten Sie auf das Versprechen.
const entry = await window.screenrig.kv.get("menu");screenrig.kv.list()#
Live-Anwendungsstatus lesen, wenn Sie die Schlüssel noch nicht kennen: Dies listet die vom Programm gespeicherten Schlüssel auf. Warten Sie auf das Versprechen.
const keys = await window.screenrig.kv.list();screenrig.kv.set(key, value, options)#
Live-Anwendungsstatus schreiben. value ist ein String oder ein Uint8Array; options ist optional.
await window.screenrig.kv.set("menu", JSON.stringify(menu), {
contentType: "application/json"
});
await window.screenrig.kv.set("badge.png", pngBytes, {
contentType: "image/png"
});| Parameter | Typ | Erforderlich | Notizen |
|---|---|---|---|
key | string | ja | Siehe Schlüssel. |
value | string oder Uint8Array | ja | Die zu speichernden Bytes. |
options.contentType | string | nein | Standardmäßig text/plain für einen String und application/octet-stream für ein Uint8Array. |
options.expectedRevision | nicht negative ganze Zahl | nein | Nur schreiben, wenn der Eintrag noch auf dieser Revision ist. |
options.idempotencyKey | string | nein | Dasselbe Schreiben erneut versuchen, ohne es zweimal anzuwenden. |
screenrig.kv.delete(key, expectedRevision, options)#
Live-Anwendungsstatus schreiben, indem ein Eintrag entfernt wird. expectedRevision ist optional: Lassen Sie ihn weg, um den aktuellen Eintrag zu löschen, oder geben Sie ihn an, um gleichzeitige Änderungen abzulehnen.
await window.screenrig.kv.delete("menu");| Parameter | Typ | Erforderlich | Notizen |
|---|---|---|---|
key | string | ja | Siehe Schlüssel. |
expectedRevision | nicht negative ganze Zahl | nein | Die Revision, bei der der Eintrag gelesen wurde. |
options.idempotencyKey | string | nein | Dasselbe Löschen erneut versuchen, ohne es zweimal anzuwenden. |
screenrig.kv.onChange(handler)#
Aktualisieren Sie den Live-Anwendungsstatus bei Änderungen, anstatt ihn abzufragen. Der Handler wird ausgeführt, wann immer sich ein Schlüssel dieser Anwendung ändert, egal wer ihn geschrieben hat: der Agent mit kv set, ein externes System über einen Key/Value-Webhook oder diese Anwendung auf einem beliebigen Bildschirm. Er erhält, welcher Schlüssel sich geändert hat, nicht den Wert, daher lesen Sie den neuen Wert mit kv.get. Der Aufruf gibt die Funktion zurück, die das Abonnement beendet.
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();Abonnieren Sie vor der ersten Lektüre, damit eine Änderung, die während des Lesens eintrifft, nicht verpasst wird; ein vor der Aktivierung registrierter Handler startet, sobald die Seite aktiv ist. Rufen Sie stopChanges() auf, um das Abonnement zu beenden.
Eine Änderung erreicht jeden Bildschirm, dessen Playlist diese Anwendung innerhalb von Sekunden platziert. Mehrere schnelle Schreibvorgänge auf einen Schlüssel können als eine Änderung mit der neuesten Revision ankommen, behandeln Sie eine Änderung also als "Lese diesen Schlüssel erneut", nicht als Anzahl der Schreibvorgänge. Eine Änderung ist ein Signal, keine Historie: Lesen Sie, was Sie brauchen, wenn die Anwendung startet, und folgen Sie dann den Änderungen.
| Feld | Typ | Notizen |
|---|---|---|
key | string | Der geänderte Schlüssel. |
revision | integer, optional | Die neue Revision des Eintrags. Fehlt, wenn deleted true ist. |
deleted | boolean | true als Zeitpunkt der Löschung des Schlüssels. |
Schlüssel
Ein Schlüssel besteht aus 1 bis 256 UTF-8-Bytes. Die Grenze gilt für Bytes, nicht für Zeichen, sodass ein Schlüssel mit mehrbyteigen Zeichen die Grenze früher erreicht als seine Länge vermuten lässt. Ein Schlüssel darf nicht mit _screenrig/ beginnen; dieses Präfix gehört zur injizierten Laufzeit.
Revisionen und Idempotenz
Jeder Eintrag trägt eine Revision. Optional können expectedRevision an screenrig.kv.set oder screenrig.kv.delete übergeben werden, um nur zu schreiben, wenn der Eintrag noch auf der Revision ist, die Sie gelesen haben. Eine veraltete Revision bedeutet, dass jemand anderes zuerst geschrieben hat: Lesen Sie den Eintrag erneut, wenden Sie Ihre Änderung erneut an und versuchen Sie es erneut.
idempotencyKey deckt die andere Hälfte ab. Ein Schreibvorgang, der nach einer verlorenen Antwort erneut versucht werden kann, kann denselben Schlüssel bei jedem Versuch tragen, und der Speicher wendet ihn einmal an.
Dasselbe Store vom CLI
Der Agent kann über die gebündelten CLI-kv Befehle außerhalb des Browsers auf diese Einträge zugreifen, basierend auf der app_ ID aus app upload. Dies ist die Ansicht des Betreibers auf den Store. Es ersetzt nicht die fünf oben genannten Methoden: Eine Anwendung ändert ihre eigenen Daten über screenrig.kv im Browser, während sie auf dem Bildschirm ist. Eine Änderung, die der Agent schreibt, erreicht die laufende Anwendung über kv.onChange.
Daten aus einem anderen System übertragen
Ein Schlüssel/Wert-Webhook ist eine URL, die einen Schlüssel dieser Anwendung schreibt. Geben Sie ihn an alles weiter, was einen HTTP POST senden kann, wie eine Verkaufsstelle, ein Tabellenkalkulationsskript, einen Cron-Job oder curl. Jeder POST ersetzt den Wert dieses Schlüssels. Jeder Bildschirm, der die Anwendung ausführt, erfährt dies innerhalb von Sekunden über kv.onChange, ohne neue Veröffentlichung und ohne Agent im Ablauf.
Der Agent erstellt einen für einen Schlüssel mit dem gebündelten CLI und übergibt Ihnen dessen URL und Geheimnis:
screenrig kv webhook create menu --app-id app_01EXAMPLEAPP00000000000 --description "Point of sale menu feed"Die Antwort enthält die url und secret (srkw_…) des Webhooks. Das Geheimnis wird nur beim Erstellen des Webhooks und beim Rotieren seines Geheimnisses angezeigt, daher sofort im sendenden System eingeben. Die URL ist nicht geheim; das Geheimnis ist es.
Der Sender sendet den neuen Wert als rohen Anforderungskörper mit dem Geheimnis im Authorization-Header:
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"}'Ein Sender, der nur HTTP Basic Authentication spricht, verwendet die Webhook-ID als Benutzernamen und das Secret als Passwort:
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"}'- Der Body, höchstens 1 MiB, wird zum Wert, und
Content-Typeist sein Inhaltstyp (application/octet-streamwenn der Header fehlt). Der Wert erreicht die Browseranwendung, daher niemals eine Anmeldeinformation als solchen posten. - Jeder Beitrag ist ein Schlüssel/Wert-Schreibvorgang wie
kv set: Er ersetzt den Wert, erhöht die Revision und wird wie jeder andere Schreibvorgang auf den Speicher angerechnet. - Die Antwort sind die neuen Metadaten des Schlüssels (
key,revision,bytes,sha256,content_typeundupdated_at), niemals dessen Wert. - Fügen Sie einen
Idempotency-Key-Header (8 bis 200 Zeichen) hinzu, um einen Post sicher erneut zu versuchen: Innerhalb von 24 Stunden gilt derselbe Schlüssel einmal, und derselbe Schlüssel mit anderem Body oder Content-Type wird mitidempotency_mismatchabgelehnt. Ohne Header ist jeder Post ein neuer Schreibvorgang. - Ein Webhook verarbeitet bis zu 120 Posts pro Minute; darüber hinaus ist die Antwort
429mitRetry-After. - Ein fehlendes oder falsches Secret oder ein unbekannter Webhook antwortet mit
401. Ein Secret in der URL oder Abfragezeichenfolge wird niemals akzeptiert. - Eine Anwendung hat bis zu 20 Webhooks.
kv webhook rotate-secretgibt ein neues Geheimnis aus und das alte endet sofort;kv webhook deletestoppt die URL sofort und belässt den Schlüsselwert.
Auch eine Karte nimmt Webhooks entgegen: Ein Post erstellt ihr Datendokument, unverändert oder über ein Mapping (Karten-Webhooks).
Das Gerät
Eine Anwendung, die ein Wandpanel oder einen Kiosk betreibt, kann den Bildschirm steuern, auf dem sie läuft. Die device-Flags gehen an den Frame, der seine Seite steuert (den Controller der Seite oder seine einzige Anwendung), auf einem Player, der das auf diesem Gerät leisten kann: Der Android Player gewährt device.display, device.keys und device.network, gewährt device.presence, wenn das Gerät eine Kamera hat und die Person, die das Gerät eingerichtet hat, dem Player erlaubt hat, sie zu nutzen (Android-Einstellungen, Apps, screenRIG Player, Berechtigungen, Kamera), device.light, wenn es einen Lichtsensor hat, und device.haptics, wenn es einen Vibrationsmotor hat. Player, die kein Gerät steuern können, lassen jedes device-Flag auf false. display.get(), display.set() und vibrate() lehnen auf einem Player, der sie nicht anbietet, mit not_supported ab und ohne das Flag mit capability_denied. onDisplay, onPresence, onKey, onLight und onNetwork können jederzeit registriert werden und laufen, wie kv.onChange, ohne das Flag einfach nie.
screenrig.device.display.set(state)#
Den Bildschirm dimmen, abdunkeln oder aufwecken. brightness reicht von 0 bis 1 (0 ist die niedrigste Stufe der Hintergrundbeleuchtung, nicht aus); on: false dunkelt den Bildschirm ab und on: true schaltet ihn wieder ein. Lassen Sie ein Member weg, um es unverändert zu lassen. Berührungen erreichen die Anwendung weiterhin, während der Bildschirm dunkel ist, sodass eine Berührung ihn aufwecken kann. Ein Anzeigeplan, der den Bildschirm dunkel hält, hat Vorrang vor der Anwendung, und der Player stellt den Bildschirm wieder her, wenn die Seite ihn verlässt.
await window.screenrig.device.display.set({ brightness: 0.3 });
await window.screenrig.device.display.set({ on: false });screenrig.device.display.get()#
Der aktuelle Zustand des Bildschirms als { on, brightness }.
screenrig.device.onDisplay(handler)#
Wird mit { on, brightness } aufgerufen, sobald sich der Bildschirm ändert, ob diese Anwendung, ein Anzeigeplan oder ein Operator ihn geändert hat.
screenrig.device.onPresence(handler)#
Wird aufgerufen, wenn das Gerät sieht, dass sich jemand vor dem Bildschirm bewegt, höchstens einmal pro Sekunde. Der Player liest die Kamera des Geräts und behält kein Bild: Es wird kein Bild gespeichert, protokolliert oder gesendet. Die Kamera läuft nur, solange ein Handler registriert ist.
window.screenrig.device.onPresence(function () {
window.screenrig.device.display.set({ on: true, brightness: 1 });
});screenrig.device.onKey(handler)#
Wird mit "volume_up" oder "volume_down" bei jedem Druck auf eine Hardware-Lautstärketaste aufgerufen, Wiederholungen eingeschlossen. Solange ein Handler registriert ist, gehören die Tasten der Anwendung, und die Lautstärke des Geräts bleibt unverändert.
screenrig.device.onLight(handler)#
Wird mit dem Umgebungslicht in Lux aufgerufen: dem ersten Messwert nach der Registrierung des Handlers, danach jedes Mal, wenn sich das Licht um mindestens 10 % oder über 1 Lux hinweg ändert, höchstens einmal pro Sekunde. Das Gerät braucht einen Lichtsensor.
window.screenrig.device.onLight(function (lux) {
document.body.classList.toggle("dim-room", lux < 10);
});screenrig.device.onNetwork(handler)#
Wird mit true oder false aufgerufen, sobald das Gerät eine vom System validierte Internetverbindung erhält oder verliert, und sofort mit dem aktuellen Zustand, wenn der erste Handler registriert wird.
window.screenrig.device.onNetwork(function (online) {
offlineBadge.hidden = online;
});screenrig.device.vibrate(ms)#
Einen haptischen Tick auslösen. ms ist eine ganze Zahl von Millisekunden von 1 bis 200 und hat den Standardwert 12. Das Versprechen wird ohne Wert erfüllt, sobald der Player die Vibration gestartet hat, und wird mit invalid_request abgelehnt, ohne etwas zu senden, für jeden anderen ms.
await window.screenrig.device.vibrate();
await window.screenrig.device.vibrate(40);Geräte im Netzwerk des Bildschirms erreichen
Eine Anwendung kann neben https:// auch von http://- und ws://-Adressen abrufen und so mit einem Gerät oder Server im eigenen Netzwerk des Bildschirms sprechen, etwa mit einem Controller unter http://192.168.1.20. Die Player für Android, Linux und Raspberry Pi, Windows und macOS erlauben das. Auf einem Kiosk-Browser, der die Player-Web-App ausführt, erlaubt der Eigentümer des Browsers das mit einer Unternehmensrichtlinie: siehe Anwendungen im lokalen Netzwerk. Der Server, den Sie aufrufen, beantwortet CORS für den Origin der Anwendung; unter macOS tragen die Anfragen einer Anwendung Origin: null, sodass das CORS des Servers dort diesen Origin zulässt.
Eine Browser-Engine blockiert <img src="http://…"> auf einer sicheren Seite. Laden Sie daher Bilder von einer http://-Adresse mit fetch() und URL.createObjectURL().
const response = await fetch("http://192.168.1.20/snapshot.jpg");
image.src = URL.createObjectURL(await response.blob());