Diese Seite richtet sich an Entwickler. Wie du die Signage OS Integration in Flyo einrichtest und Bildschirme verwaltest, erfährst du auf der Hauptseite der Integration.
Ein Applet ist eine kleine Webapplikation (HTML, CSS, JavaScript), die von SignageOS auf dem Digital Signage Gerät ausgeführt wird. Das Applet definiert das Layout und Verhalten der Anzeige (Formatvorlage), während Flyo die Inhalte liefert und die Geräte automatisch aktualisiert. Einmal entwickelt, kann dasselbe Applet von beliebig vielen Integrationen und Bildschirmen verwendet werden.
Beispiel-Applets
Als Startpunkt für ein eigenes Applet stehen zwei Beispiel-Repositories zur Verfügung:
- flyocloud/signageos-js-example: Minimales Applet in reinem JavaScript, das die Inhalte aus Flyo als Slideshow anzeigt.
- flyocloud/signageos-vue2-example: Beispiel-Applet auf Basis von Vue 2.
Nützliche Links von SignageOS:
So erhält das Applet seine Daten
Beim Speichern der Integration weist Flyo das gewählte Applet den ausgewählten Geräten zu. Dabei übergibt Flyo dem Applet in der Konfiguration den Parameter api mit der URL der Datenschnittstelle. Im Applet liest du diese URL über das SignageOS SDK aus und lädst die Daten mit einem einfachen fetch:
import sos from '@signageos/front-applet';
sos.onReady().then(async () => {
// Während der lokalen Entwicklung ist sos.config nicht gesetzt,
// dann kann als Fallback direkt die API-URL der Integration verwendet werden.
const api = sos.config?.api || 'https://api.flyo.cloud/integration/signageos/<id>/<token>';
const response = await fetch(api);
const { data, config, vars } = await response.json();
// config.timeout: Anzeigedauer pro Slide in Millisekunden
// data: die Inhalte (siehe Slides oder Strukturiert)
// vars: die in der Integration erfassten Variabeln (siehe Variabeln)
});Die Antwort der Datenschnittstelle hat immer diese Grundstruktur:
{
"data": "...",
"config": {
"timeout": 15000
},
"vars": {}
}config.timeout: Die in der Integration gewählte «Anzeigedauer pro Slide» in Millisekunden.
data: Die Inhalte aus den verknüpften Content Pools. Die Struktur hängt von der in der Integration gewählten Datenstruktur ab, siehe Slides oder Strukturiert. Content Pools sind freiwillig: Eine Integration, die ausschliesslich mit Variabeln arbeitet, liefert hier eine leere Liste. Das Applet sollte diesen Fall abfangen.
vars: Die in der Integration frei erfassten Werte, siehe Variabeln. Ein leeres Objekt, wenn keine Variabeln konfiguriert sind.
Das Applet muss die Daten nicht regelmässig abfragen: Ändern sich Inhalte in Flyo, aktualisiert Flyo die Datenschnittstelle und löst auf allen verbundenen Geräten automatisch einen Applet-Refresh aus. Standardmässig geschieht das mit einer verzögerten Aktualisierung von 5 Minuten.
OpenAPI-Definition
Jede konfigurierte SignageOS Integration stellt eine OpenAPI-Definition ihrer Datenschnittstelle bereit. Du findest sie in der Integration im Tab «Entwickler», zusammen mit der API URL. Die Definition beschreibt alle Felder und Daten, welche die Schnittstelle liefert, inklusive der konfigurierten Variabeln mit ihrem jeweiligen Typ, und eignet sich auch zum Generieren von Typen oder Clients.
Slides oder Strukturiert
Im Tab «Inhalte» der Integration wird unter «Verknüpfung der Inhalte» die Datenstruktur festgelegt, in der die Inhalte an das Applet geliefert werden. Diese Wahl bestimmt massgeblich, wie du das Applet entwickelst.
Slides
Jeder Eintrag im Content Pool entspricht einem einzelnen Slide. data ist ein flaches Array; die Einträge aller verknüpften Content Pools werden nacheinander in dasselbe Array gelegt. Das ist die richtige Wahl für klassische Diashows, bei denen alle Inhalte nacheinander abgespielt werden.
Pro Content Pool können die Standard-Felder Bild, Titel, Text, QR Code Link und Sortierreihenfolge verknüpft werden. Zusätzlich definierte eigene Felder landen im Objekt custom.
{
"data": [
{
"image": "https://storage.flyo.cloud/welcome_ab12cd34.jpg",
"title": "Willkommen",
"teaser": "Neue Wasserwelten",
"uid": "f8855c2b6709de28df52df51aabe6ab6",
"entity_id": 29,
"entity_type": "poi",
"pool_id": 1,
"item_identifier": "hero",
"metric": "https://flyo.cloud/integration/metric/h/c3f0d71ed0a5bd97...",
"qrcode": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5v...",
"scanurl": "https://api.flyo.cloud/integration/sosc/12/1712000000/f8855c2b...",
"custom": {
"preis": "CHF 10.00"
}
}
],
"config": {
"timeout": 15000
}
}Jeder Slide enthält folgende Felder:
| Feld | Beschreibung |
|---|---|
image | URL des verknüpften Bildes |
title | Titel (leerer String, wenn nicht verknüpft) |
teaser | Text (leerer String, wenn nicht verknüpft) |
link | Der verknüpfte QR Code Link als Roh-URL (nur wenn verknüpft) |
hiddensort | Wert der verknüpften Sortierreihenfolge; wird nicht angezeigt, sondern dient nur der Sortierung |
uid | Eindeutige ID des Eintrags |
entity_id | ID der Entität |
entity_type | Typ der Entität, z.B. poi, event, file, tag |
pool_id | ID des Content Pools, aus dem der Eintrag stammt |
item_identifier | Der Entwicklungs-Identifier des Content Pools (optional) |
metric | URL für das Messen mit Flyo Metriken; ein Aufruf erfasst eine Anzeige des Slides |
qrcode | Fertiger QR-Code als SVG Data-URI, direkt als src eines img-Elements verwendbar; false, wenn kein Link verknüpft ist |
scanurl | Die URL, auf die der QR-Code zeigt; false, wenn kein Link verknüpft ist |
custom | Objekt mit den zusätzlich definierten eigenen Feldern (Schlüssel = Feldname aus der Integration) |
Strukturiert
Die Inhalte werden anhand des Entwicklungs-Identifiers gruppiert. data ist ein Objekt, dessen Schlüssel die Entwicklungs-Identifier der verknüpften Content Pools sind; jede Gruppe kann im Applet unabhängig verarbeitet oder gestaltet werden. Das ist die richtige Wahl für Layouts mit mehreren Bereichen, zum Beispiel einem Hero-Bereich, einer Infospalte oder einer Menükarte.
Im strukturierten Modus gibt es keine vorgegebenen Inhaltsfelder: Ausser dem QR Code Link definierst du alle Felder selbst. Die verknüpften Felder landen mit ihrem Feldnamen direkt im Eintrag (nicht in einem custom-Objekt). Der Entwicklungs-Identifier ist in diesem Modus für jeden Content Pool zwingend und muss pro Integration eindeutig sein.
{
"data": {
"hero": [
{
"titel": "Willkommen",
"bild": "https://storage.flyo.cloud/welcome_ab12cd34.jpg",
"uid": "f8855c2b6709de28df52df51aabe6ab6",
"qrcode": false,
"scanurl": false
}
],
"info": [
{
"titel": "Öffnungszeiten",
"text": "Mo bis Fr, 08:00 bis 18:00 Uhr",
"uid": "0c627b93419b41ebc3f0d71ed0a5bd97",
"qrcode": false,
"scanurl": false
},
{
"titel": "Adresse",
"text": "Bahnhofstrasse 1",
"uid": "41ebc3f0d71ed0a5bd970c627b93419b",
"qrcode": false,
"scanurl": false
}
]
},
"config": {
"timeout": 15000
}
}Jeder Eintrag einer Gruppe enthält neben den selbst definierten Feldern automatisch:
| Feld | Beschreibung |
|---|---|
uid | Eindeutige ID des Eintrags |
link | Der verknüpfte QR Code Link als Roh-URL (nur wenn verknüpft) |
qrcode | Fertiger QR-Code als SVG Data-URI; false, wenn kein Link verknüpft ist |
scanurl | Die URL, auf die der QR-Code zeigt; false, wenn kein Link verknüpft ist |
Variabeln
Neben den Inhalten aus den Content Pools kann eine Integration Werte enthalten, die direkt in Flyo erfasst werden: ein Wochentitel, ein Hinweistext, ein Coverbild, eine Menükarte. Sie werden im Tab «Konfiguration» der Integration festgelegt und im Tab «Inhalte» befüllt, siehe Variabeln.
Im Applet stehen sie unter vars, jeweils unter dem Identifier, der in der Integration vergeben wurde:
const { vars } = await response.json();
document.querySelector('h1').textContent = vars.wochentitel;
document.querySelector('img').src = vars.coverbild.source;{
"vars": {
"wochentitel": "Frühlingserwachen",
"coverbild": {
"source": "https://storage.flyo.cloud/cover_ab12cd34.jpg",
"caption": "Neue Wasserwelten",
"copyright": "Zoo Zürich",
"name": "cover.jpg",
"id": 4711,
"mime_type": "image/jpeg"
},
"menuekarte": [
{ "gericht": "Tagesteller", "preis": "18.50" },
{ "gericht": "Suppe", "preis": "7.00" }
]
}
}Variabeln liefern den vollen Wert ihres Typs
Das ist der wichtigste Unterschied zu den verknüpften Feldern eines Slides. Ein Slide-Feld wird immer auf einen Text reduziert, weil dort erst beim Verknüpfen feststeht, was für ein Inhalt kommt. Eine Variable dagegen wird mit ihrem Typ deklariert, also liefert sie den vollständigen Wert dieses Typs:
| Feldtyp | im Slide (data) | als Variable (vars) |
|---|---|---|
| Bild | die URL als Text | Objekt mit source, caption, copyright, name, id, mime_type |
| Link | die URL als Text | Objekt mit href, type, target, raw und extras |
| Text Editor (WYSIWYG) | das HTML als Text | Objekt mit html und json |
| Dropdown | das Label als Text | Objekt mit value, label und allen options |
| Mehrfacheingabe | nicht verfügbar | Array mit einem Objekt pro Zeile |
Welche Felder eine bestimmte Integration liefert und wie sie typisiert sind, steht in ihrer OpenAPI-Definition. Sie wird aus den Deklarationen erzeugt, ist also immer aktuell und eignet sich direkt zum Generieren von Typen.
Variabeln ohne gültigen Identifier werden nicht ausgeliefert. Ein Identifier beginnt mit einem Buchstaben oder einem Unterstrich und enthält danach nur Buchstaben, Zahlen und Unterstriche.
Ändert sich der Wert einer Variable, wird die Datenschnittstelle wie bei einer Inhaltsänderung aktualisiert und die verbundenen Bildschirme laden das Applet neu.
Der Entwicklungs-Identifier
Der Entwicklungs-Identifier kann im Tab «Inhalte» unter «Verknüpfung der Inhalte» pro Content Pool gesetzt werden. Das Feld ist nur für die Entwicklung vorgesehen und wird nie auf dem Bildschirm angezeigt. Es definiert, wie Inhalte aus dem Content Pool innerhalb des Applets strukturiert, gruppiert und im Frontend verwendet werden können:
- Bei Slides ist der Identifier optional und Teil jedes Datensatzes (Feld
item_identifier). Er dient der Zuordnung oder Filterung, zum Beispiel um Einträge aus einem bestimmten Content Pool im Applet anders darzustellen. - Bei Strukturiert ist der Identifier zwingend und wird zum Gruppenschlüssel im
data-Objekt.
Der Entwicklungs-Identifier ermöglicht es, Layouts, Komponenten oder Logik gezielt an eine bestimmte Datenstruktur oder Inhaltsgruppe anzupassen.
QR-Codes und Metriken
Wird in der Integration das Feld «QR Code Link» verknüpft, generiert Flyo für jeden Eintrag automatisch einen QR-Code:
qrcodeenthält den fertigen QR-Code als SVG Data-URI und kann im Applet direkt als Bildquelle verwendet werden.scanurlist die URL hinter dem QR-Code. Beim Scannen erfasst Flyo die Interaktion in den Flyo Metriken und leitet anschliessend auf den hinterlegten Link weiter.metric(nur bei Slides) ist eine URL, die das Applet aufrufen kann, wenn ein Slide angezeigt wird. So lassen sich die Anzeigen der Inhalte in den Flyo Metriken messen.
Applet hochladen
Upload nur via CLI: Das Applet muss via CLI in die SignageOS-Plattform hochgeladen werden. Nach dem erfolgreichen Upload ist das Applet in der Flyo Integration im Tab «Konfiguration» unter «Applet» verfügbar und kann ausgewählt werden.
- Clone das Beispiel-Repository (oder dein eigenes) auf deinen Computer:
git clone https://github.com/flyocloud/signageos-js-example.gitodergit clone https://github.com/flyocloud/signageos-vue2-example.git - Führe im Ordner des Clones den Befehl
npm installaus. - Installiere das globale SignageOS CLI Script mittels
npm install @signageos/cli -g - Logge dich mit dem Befehl
sos loginein (aktiver SignageOS Box Account vorausgesetzt). - Stelle die Standard-Organisation ein:
sos organization set-default - Lade das Applet mittels
npm run releasehoch. Das Ergebnis auf diesen Befehl sollte lauten: «Applet XYZ version 1.0.0 has been uploaded.»
Lokale Entwicklung
Für die lokale Entwicklung startest du das Applet mit npm start (im JavaScript-Beispiel läuft es danach unter http://localhost:8090). Da das Applet lokal keine Konfiguration von SignageOS erhält, hinterlegst du als Fallback die API-URL deiner Integration direkt im Code (siehe Codebeispiel oben). Die URL der Datenschnittstelle findest du in der OpenAPI-Definition der Integration.
Hinweis von SignageOS zum Testen im Emulator: Problem mit dem Emulator in Chrome (Adblock)

