OnSign TV players inject a Javascript object, named signage
into all running Apps, which is accessible via the Window object. Through this object, your apps will be able to retrieve useful information regarding the player and content being played.
Important: Not all methods in the signage
object are available on all platforms and most of them are not available before the "signageloaded"
event is fired. Check the compatibility matrix at the bottom of this page to know when you can use each method and protect uses with a try {} catch (e) {}
.
In order to receive any event or use any method listed in this documentation you'll need to load the Signage SDK and wait for it to finish loading.
To load the SDK you must add a {{ __loadsdk__ }}
directive to your app. This will be required for all apps with a <script>
tag imported after February 2023.
Important: The {{ __loadsdk__ }}
directive must be placed before any {{ __config__ }}
or {{ __datafeed__ }}
directives, as well as before any <script>
tag on your app.
If you are using the signage.playbackLoops()
API this directive must be changed to {{ __loadsdk__(contentinfo=True) }}
in order to have the name and attributes of every content available locally in the player, otherwise only the Content ID
is guaranteed to exist. Please mind that enabling names and attributes increases the bandwidth used by your player.
Click here to expand and view an example.
<!DOCTYPE html>
<html>
<head lang="en">
<title>Sample App with Events</title>
{# When using Javascript you need to load the Signage SDK first #}
{{ __loadsdk__ }}
{# After loading you can add your configuration #}
{{
__config__(type="color", name="background_color",
label="Text background color", value="#FFFFFF")
}}
</head>
<div style="background-color: {{ background_color }};">
SIZE: <span id="width">?</span>x<span id="height">?</span>
</div>
<script>
// Now you can use sizechanged event.
document.addEventListener("sizechanged").then(function (event) {
document.getElementById("width").innerHTML = event.detail.width;
document.getElementById("height").innerHTML = event.detail.height;
});
</script>
</html>
The Signage Javascript SDK injects some events into the document
of your app. You can use document.addEventListener(eventName, fn)
to listen to them.
Check below for more information on each event, specially the signageloaded
and show
events.
This event fires when methods in the window.signage
object are ready to be called.
Not all methods are available on every player version or operating system, so check the compatibility matrix before using them.
Important: This event is guaranteed to fire after the window.onload
and is available on all platforms and versions, so it is safe to be used instead of the load event.
In case you need this event as a Promise
you can use the window.signageLoaded
Promise.
Most of the time your app will be loaded ahead of time to avoid displaying an unfinished page to end users. When that happens the player will load your app in an invisible area of the screen and then instantly display it when the time comes. The duration of this preload vary from platform to platform, from 1 to 5 seconds.
If you have animations or other time-based transitions you need to wait for your app to actually be displayed to the end users before starting those animations and timers.
For instance, a news app that displays one article every X seconds, can only start its internal timer once the show
event is fired. Also, since timers in Javascript aren't synchronized with the Player timers it is usually a good idea to wait up to a second after the show event is received before initializing internal timers.
Important: This event is guaranteed to fire after the window.onload
and the signageloaded
event. For compatibility reasons it may take up to five seconds to fire on older player versions.
In case you need this event as a Promise
you can use the window.signageVisible
Promise.
This event fires when the app is being looped, meaning it should refresh information. It's useful for when the app is permanently on screen. It's up to the developer to make use of this or not, depending on the application.
Do note that you can instead set the force-reload
meta tag documented on Force App Reload, since that tag ensures the page always gets reloaded between consecutive app playbacks.
Event fired when the app changes size, either due to a resize by the end-user during preview or the player repositioning the iframe due to layout changes.
Contrary to the native window.onresize
event, the sizechange
event is properly debounced so you won't get hundreds of events for user-generated resizes.
// Handle resize of the app. You can get the current size through event.detail
document.addEventListener('sizechanged', function (event) {
var width = event.detail.width;
var height = event.detail.height;
});
Some changes are not propagated through the document
element, like player property or attribute changes. Those events require you to listen directly on the signage
object and therefore cannot be registered before the signageloaded
event is fired.
This event fires when one of the player attribute changes. Player attributes can change when an user edits them on the platform or locally through the signage.getPlayerAttribute("name")
and signage.setPlayerAttribute("name", "value")
methods.
signage.addEventListener('attrchanged', function (event) {
// Name of the attribute that changed value
var attrName = event.detail.name;
// New value of the attribute. Can be a string, a number, or a list of strings.
var attrValue = event.detail.value;
});
This event fires when one of the player property changes. Property changes when user changes edit them on the platform, through a predetermined schedule or locally through the API.
There are two currently supported properties: "brightness"
and "volume"
.
signage.addEventListener('propchanged', function (event) {
// Name of the property. Could be "brightness" or "volume".
var propName = event.detail.name;
// New value of the property.
var propValue = event.detail.value;
});
This event fires when data is read from the RS-232 Serial Port named in the "alias"
parameter. The serial port configuration and alias are set on your OnSign TV player settings page.
signage.addEventListener("serialportdata", "alias", function (event) {
var portAlias = event.detail.name; // will contain the port alias.
var readValue = event.detail.value; // will contain the data read.
});
The event.detail.value
can either be an ASCII String
containing a single character, an ASCII String
containing a line of text or an ArrayBuffer
containing the binary data read. This will depend on the configuration done by the user on OnSign TV.
Mode | detail.value type |
Behavior |
---|---|---|
Binary | ArrayBuffer |
Fires at fixed intervals depending on the source of the data. |
Character | ASCII String |
Fires one event per character read from the serial port. |
Line | ASCII String |
Fires one event per line of text read from the serial port. The event.detail.value will not include line ending characters. |
This event fires whenever the given ContentID
is changed.
The ContentID
must be acquired from a configuration option or from a media file. Any other method of acquiring that ID can't assume the file will exist in the player, because only published files are downloaded. Listening to changes of an unknown ContentID
is not considered an error, the event will just never be fired.
signage.addEventListener("contentchanged", "ContentID", function (event) {
var contentId = event.detail.id; // will contain the given "ContentID".
});
This event fires whenever the content currently playing changed.
If you need to keep track of playback changes use this event instead of calling signage.playbackLoops()
periodically.
signage.addEventListener("playbackloopschanged", function (event) {
var playback = event.detail.value; // has the same value as signage.playbackLoops().
});
Some events are also available as top-level promises that can be used with other promises and combined in new ways.
The window.signageLoaded
promise is guaranteed to only be resolved after the 'signageloaded'
event fires, so you can also use this promise to check all your script files and the platform SDK have finished loading.
The window.signageVisible
promise is guaranteed to only be resolved after the 'show'
event fires so you can use it to start timers in your app.
Click here to expand and view an example.
<!DOCTYPE html>
<html>
<head lang="en">
<title>Sample App with Visible Promise</title>
{# When using Javascript you need to load the Signage SDK first #}
{{ __loadsdk__ }}
</head>
<div id="result"></div>
<script>
// Now you can use the signagevisible promise.
window.signageVisible.then(function () {
document.getElementById("result").innerHTML = "VISIBLE";
});
</script>
</html>
App configuration options that have the js
parameter set to True
on the {{ __config__ }}
directive will be available to scripts through the window.appConfig
global object.
If the configuration was marked as optional and no value was defined by the user, accessing its value on the window.appConfig
object will return undefined
.
If at least one configuration option was marked as js=True
and the app contains internationalization options, the current locale setting will also be available on window.appConfig.__lang__
.
Important: Configuration types currently supported on the window.appConfig
object: bool
, choice
, color
, date
, datetime
, float
, multichoice
, number
, paragraph
, richtext
, text
, time
, url
.
Click here to expand and view an example.
<!DOCTYPE html>
<html lang="{{ __lang__ }}">
<head>
<title>appConfig Example</title>
{{ __loadsdk__ }}
{{ __config__(name="userDate", type="date", label="Date to be displayed", js=True) }}
</head>
<body>
<div id="date-display"></div>
<script type="text/javascript">
window.signageLoaded.then(function() {
var userDateInput = new Date(window.appConfig.userDate);
var formatter = new Intl.DateTimeFormat(window.appConfig.__lang__);
document.getElementById("date-display").innerText = formatter.format(userDateInput);
});
</script>
</body>
</html>
The following methods are on the window.signage
object. They are available to use after the signageloaded
event fires or the window.signageLoaded
Promise is resolved.
Please check the compatibility matrix to view which method is supported on which player version.
signage.playbackInfo()
signage.playbackLoops()
signage.width()
signage.height()
signage.isVisible()
signage.getCurrentPosition()
signage.getGeoLocation()
signage.triggerInteractivity("value" [, {"param": "pvalue"}])
signage.readContent("ContentId", {"encoding": "utf8"})
signage.stopCurrentCampaign()
signage.stopThisItem(delay, [stopParentCampaign, [isPartialPlayback]])
signage.getPlayerAttribute("name")
signage.setPlayerAttribute("name", "value")
signage.setPlayerAttributes({"name": "value"})
signage.sendEvent("level", "code", [, "message", {"extra": "values object"}])
signage.log("level", "domain", "message")
signage.playAudio("file:///path")
There are a few methods that manipulate the player hardware:
signage.getBrightness()
signage.setBrightness(percent)
signage.setVolume(percent)
signage.getVolume()
signage.ledOn(red, green, blue)
signage.ledOff()
Additionally there are a few methods for Text-To-Speech, on players that support such functionality.
signage.ttsSetLanguage("en")
signage.ttsSetPitch(0.9)
signage.ttsSetRate(1.5)
signage.ttsSpeak("text to be spoken" [, {language: "es", rate: 0.8}])
signage.ttsSilence(2000)
signage.ttsStop()
signage.ttsFlush()
Returns a stringified JSON object that bundles information about the player and the current campaign. This object can be expanded in the future to contain other types of information.
Object Model:
{
// Reason this campaign was played. If there is no reason, type is defined as "unknown"
"reason": {
"type": "time", // Other values: "touch", "key", "geo", "timeout", "ondemand", "api" and "unknown"
"timestamp": 15467551, // unix timestamp
// For type === "touch"
"x": 230, // X,Y values returned are based on a virtual screen of 100000x100000 pixels.
"y": 470,
// For type === "key"
"keys": "abcd",
// For type === "api", when using /trigger/text or signage.triggerInteractivity("text")
"value": "text",
// For type === "geo"
"lat": -27.5967811,
"long": -48.5201524,
"direction": "in", // other possible value is "out".
// For type === "ondemand" or type === "api"
"params": { // Always an object, contains extra parameters passed through the URL.
"foo": "bar"
}
},
"campaign": {
"id": "13132",
"name": "campaign name",
"duration": 20, // in seconds
"tags": ["tag1", "tag2"], // Always an array, even without tags,
"attrs": { // Always an object, even without attributes.
"key 1": "value 1"
}
},
"player": {
"id": "21313",
"name": "player name",
"version": "5.2.0-develop",
"tags": ["tag1", "tag2"], // Always an array, even without tags.
"attrs": { // Always an object, even without attributes.
"key 1": "value1",
"key 2": "value2"
}
}
}
Example:
// In the example below, it is important to wrap the code using a try/catch statement for two reasons:
// 1. The signage object might not be available;
// 2. The JSON.parse() might throw an exception if data is not valid.
try {
// Get the stringified JSON object representing the `playbackInfo` data from the signage object.
var data = signage.playbackInfo();
// Parse data into a JSON object
var playbackInfo = JSON.parse(data);
// Log the player name:
console.log(playbackInfo.player.name);
} catch (ex) {
console.error('Signage object not available or data var does not contain a valid JSON string.');
}
Returns a Promise
that resolves to an object with information about what is currently being displayed on the screen.
While signage.playbackInfo()
only returns information about the app that called the method, this API returns all content being played.
Content being played belongs to a loop and is playing for a reason. All loops play concurrently. A loop might be temporary, might be created by an interactivity or be scheduled through the platform.
In order to save bandwidth not all content have their name and attributes locally available on the player. If that information is required by your app, you must declare {{ __loadsdk__(contentinfo=True) }}
when configuring the SDK. Without this only the Content ID
is guaranteed to exist.
Please mind that this API returns a lot of data and is CPU-intensive. Calling it more than once a second might cause visible delays to playback, so use it with parsimony.
If you need to be notified on when the content being played changed, use the signage.addEventListener("playbackloopschanged")
event.
window.signageLoaded.then(function() {
signage.playbackLoops().then(function(info) {
// Check the sample below to view the structure available on info.
});
});
Click here to expand and view an example of the data returned.
{
"ts": 1702061023000,
"loops": [
{
"name": "PRIMARY",
"start": 1702060000000,
"rect": [0, 0, 1920, 1080],
"content": {
"id": "32UXjbLV",
"playId": "#c122",
"kind": "TRACKS",
"name": "Playlist With Multiple Items",
"attrs": {
"__tags__": ["playlist-tag"],
"Customer Name": "some brand"
},
"reason": "LOOP",
"start": 1702061023000,
"tracks": [
{
"name": "__32UXjbLV#0__",
"rect": [0, 0, 1920, 1080],
"content": {
"id": "02Ub7L1x",
"playId": "#c123",
"kind": "TRACKS",
"name": "Campaign With Two Timelines And Audio Track",
"attrs": {
"__tags__": ["some-tag", "other tag"],
"__category__": "Category",
"Customer Value": 55
},
"reason": "LOOP",
"start": 1702061023000,
"tracks": [
{
"name": "user-defined track name",
"rect": [0, 0, 1920, 700],
"content": {
"id": "jaUpoPKV",
"playId": "#c124",
"kind": "IMAGE",
"name": "a.png",
"attrs": {
"__tags__": ["another-tag"]
},
"reason": "LOOP",
"start": 1702061023000,
}
},
{
"name": "__02Ub7L1x#0__",
"rect": [0, 700, 1920, 340],
"content": {
"id": "32UXZyPl",
"playId": "#c124",
"kind": "IMAGE",
"name": "b.png",
"attrs": {},
"reason": "TOUCH",
"start": 1702061028000,
}
},
{
"name": "empty named track",
"rect": [0, 0, 1920, 1080]
}
{
"name": "__02Ub7L1x#3__",
"content": {
"id": "jaUpoPKV",
"playId": "#c124",
"kind": "AUDIO",
"name": "misery.mp3",
"attrs": {},
"reason": "LOOP",
"start": 1702061023000
}
}
]
}
}
]
}
}
]
}
Below is a description of all objects returned by this API.
Important: Fields marked with ?
are optional. You should check if they exist before using them.
Property | Type | Description |
---|---|---|
"ts" |
number |
Current local time, in number of milliseconds elapsed since the epoch, as seen by the playback engine. Should be used instead of Date.now() to calculate durations in order to account for the inherent latency in calling this API. |
"loops" |
LoopInfo |
Every loop that has content playing. Please mind that some loops are not visible on screen, for example audio loops, and some loops are ephemeral, as for loops created by on-demand content. Loops are stacked on top of each other. This list is ordered from bottom-most to top-most loop. |
Information about a particular loop being played.
Property | Type | Description |
---|---|---|
"name" |
LoopName |
The name of this loop. Check the linked documentation for more. |
"start" |
number |
Local time of when this loop started, in number of milliseconds elapsed since the epoch. |
"rect" ? |
Array[number] |
An array of 4 numbers containing the values for x position , y position , width and height of the loop on the player window. Position 0, 0 is at top left. If absent, this loop is hidden. |
"content" |
ContentInfo |
The content that is currently playing in this loop. |
Information about the content being played.
Property | Type | Description |
---|---|---|
"id" |
string |
The ID of this content. Matches the one visible on the platform and available through the GraphQL API. |
"playId" |
string |
An identifier for each individual playback of this content in this player. It is not guaranteed to be unique across players or restarts of the player app. |
"kind" |
ContentKind |
Kind of the content being played. Please be mindful that new kinds might be available in the future. |
"name" |
string |
The user-defined name of this content on the platform. Might contain unescaped HTML characters. |
"attrs" |
object |
User-defined attributes on the content. They might be custom attributes or platform-level ones. Platform-level attributes are: "__tags__" containing an Array[string] with the tags and "__category__" containing a string with the user-given category. Both properties and values of this object might contain unescaped HTML characters. |
"reason" |
PlayReason |
The reason this content is currently playing. Check the linked documentation for more. |
"start" |
number |
Local time of when this content started playing, in number of milliseconds elapsed since the epoch. |
"tracks" ? |
Array[TrackInfo] |
When "kind" === "TRACKS" these are the individual tracks that are playing content. Tracks are stacked on top of each other. This list is ordered from bottom-most to top-most track. |
Information about a particular track.
Property | Type | Description |
---|---|---|
"name" |
string |
The user-given name for this track. If the user did not name this track, the player will create a random name that exists only on this player. Might contain unescaped HTML characters. |
"start" |
number |
Number of milliseconds elapsed since the epoch, in local time, when this loop started. |
"rect" ? |
Array[number] |
An array of 4 numbers containing the values for x position , y position , width and height of the track on the player window. Position 0, 0 is at top left. If absent, this track is hidden. |
"content" ? |
ContentInfo |
Content currently playing in this track. If absent, this track is empty. |
Name of the loop being played.
Name | Description |
---|---|
"WELCOME" |
Played exactly once, every time the player starts. Does not loop once finished. |
"PRIMARY" |
Played repeatedly once the "WELCOME" loop finishes. |
"FALLBACK" |
Played when "PRIMARY" loop is empty or every item in "PRIMARY" was restricted from being played. |
"AUDIO" |
Audio content that plays concurrently with other loops. |
"AUTOMATION" |
HTML content that plays concurrently with other loops. |
"SECONDARY" |
Content played on the secondary screen, for players that support two displays. Is played concurrently with other loops. |
"DYNAMIC.${N}" |
Created by on-demand content or interactivity and played exactly once, concurrently with other loops. ${N} is a numeric value that increases every time a new loop is created. |
Kind of the content being played.
Kind | Description |
---|---|
"TRACKS" |
Contains one or more tracks of content. Please mind that campaigns, playlists and audio playlists all have the "TRACKS" kind on this API. |
"APP" |
HTML app. |
"AUDIO" |
Audio content, such as an MP3 file. |
"VIDEO" |
Video content, such as an WebM file. |
"IMAGE" |
Image content, such as a JPEG or a SVG file. |
Reason why the content is playing.
Reason | Description |
---|---|
"LOOP" |
Content was scheduled in a loop. |
"GEO" |
Content was triggered by a change in player geolocation. |
"TOUCH" |
Content was triggered by a touch. |
"KEY" |
Content was triggered by input on a keyboard. |
"TIMEOUT" |
Content was triggered because of a configured timeout interactivity. |
"TIME" |
Content was triggered by a scheduled time trigger. |
"ONDEMAND" |
Content was triggered through a remote on demand call. |
"API" |
Content was triggered through a local API, either Local Web API or the signage.triggerInteractivity() method. |
"ATTR" |
Content was triggered by a change in a player attribute. |
Returns the region (where the App is being displayed) width in pixels.
Example:
console.log('Width:', signage.width());
Please, note that the Webview viewport size might be different than the region resolution. "The screen density (the number of pixels per inch) on an Android-powered device affects the resolution and size at which a web page is displayed. The Android Browser and WebView compensate for variations in the screen density by scaling a web page so that all devices display the web page at the same perceivable size as a medium-density screen." More info here
Returns the region (where the App is being displayed) height in pixels.
Example:
console.log('Height:', signage.height());
Please, note that the WebView viewport size might be different than the region resolution. "The screen density (the number of pixels per inch) on an Android-powered device affects the resolution and size at which a web page is displayed. The Android Browser and WebView compensate for variations in the screen density by scaling a web page so that all devices display the web page at the same perceivable size as a medium-density screen." More info here
Returns a boolean representing the app visibility.
Example:
console.log('App is visible?', signage.isVisible());
OnSign TV players usually preload all campaign assets, including apps, a few seconds before starting the playback. As soon as the campaign starts the apps are already loaded, creating a better visual experience.
Returns a stringified JSON object containing the player location data. Might contain stale data if the app has not been reloaded in a while.
When possible use signage.getGeoLocation()
to get the current location.
Position Model:
{
coords: {
accuracy: null,
altitude: null,
altitudeAccuracy: null,
heading: null,
latitude: 43.01256284360166,
longitude: -89.44531987692744,
speed: null
},
timestamp: 1479930166006
}
Example:
try {
// Get the stringified location data.
var data = signage.getCurrentPosition();
// Parse the location data into a Position object.
// > The result object will be exactly the same as the one returned by the
// native `Geolocation.getCurrentPosition()` method.
var position = JSON.parse(data);
// Log player's latitude and longitude
console.log('Latitude:', position.coords.latitude);
console.log('Longitude:', position.coords.longitude);
} catch (ex) {
console.log('Signage.getCurrentPosition() method is not available or data is not valid.');
}
Returns a Promise
that contains the player location, as good as can be determined.
In contrast to signage.getCurrentPosition()
, this method will fallback to the location configured in the Player Settings page or derived from the Player IP address. The position obtained by this method will be the same used to check for geographic restrictions on content publications.
if (signage && signage.getGeoLocation) {
signage.getGeoLocation().then(function(geo) {
console.log(geo.src, geo.lat, geo.lng);
});
}
When the promise is fulfilled the result will contain an object with three attributes: lat
, lng
and src
.
{
"src": "ip", // can be one of "gps", "user", or "ip", based on the source of the location.
"lat": -27.5967811, // player latitude
"lng": -48.5201524, // player longitude
}
Triggers the Local API interactivity with user-defined "value".
For this method to have an effect a "Local API" interactivity needs to be defined – either on the player or the current content hierarchy – with a regular expression that matches the parameter "value"
of this method.
What will happen when this interactivity is triggered is defined in the Interactivity Configuration UI.
This method has an optional second parameter with a plain object containing keys and values that will be present in the signage.playbackInfo()
of the triggered content, if any content is triggered.
For instance, in one app you can trigger an interactivity, passing an object containing parameters
try {
signage.triggerInteractivity('show-content', {
'content': 'contentValue'
});
} catch (ex) {
console.error('Signage object not available');
}
If the interactivity matches any configuration those parameters can be retrieved in the content that just started playing.
var playbackParams = {};
// In the example below, it is important to wrap the code using a try/catch statement for two reasons:
// 1. The signage object might not be available;
// 2. The JSON.parse() might throw an exception if data is not valid.
try {
// Get the stringified JSON object representing the `playbackInfo` data from the signage object.
var playbackInfo = JSON.parse(signage.playbackInfo());
// Sanity checks to see whether the parameter was set.
if (typeof playbackInfo.reason === 'object' && typeof playbackInfo.reason.params === 'object') {
playbackParams = playbackInfo.reason.params;
}
} catch (ex) {
console.error('Signage object not available or data var does not contain a valid JSON string.');
}
// If this content is playing because of that interactivity, this will be true.
console.log(playbackParams['content'] === 'contentValue');
Immediately stops the current campaign, moving to the next one in the loop. The campaign is reported as being partially played, so will only show in reports that have the "Include Partial Playback" option checked.
Usage of this method will result in flash of black or white screens because there is no time to preload the next content. Replace uses with signage.stopThisItem()
with a few seconds of delay to give the player ample time to preload the next content and avoid blank screens.
Stops the app that called this function in delay
milliseconds. If delay
parameter is 0
or missing the app is stopped immediately.
Given that all apps are "preloaded" before being displayed, if you call signage.stopThisItem(0)
before the show
event, the next content will be preloaded and displayed without causing a black screen.
The delay
time starts running as soon as you call this function. In order to display an app for a specific duration you need to listen to the show
event before calling signage.stopThisItem()
, in order to account for the variable preload duration:
<!DOCTYPE html>
<title>This App is Displayed for 30 Seconds</title>
{# guarantee the show event works on all platforms by loading the SDK #}
{{ __loadsdk__ }}
<script type="text/javascript">
document.addEventListener('show', function() {
signage.stopThisItem(30000);
});
</script>
If you call this function after the show
event, ensure that the delay is at least 5000
milliseconds so there is enough time to preload the next content and avoid a black screen.
This function will have no effect if delay
is greater than the remaining playback duration of this app, as configured through the signage platform. Calling it more than once, regardless of parameters, will also have no effect.
Heads up! If this function is used to skip different apps multiple times in a row there might not be enough time to preload a new content and a black screen might occur.
The stopParentCampaign
parameter controls whether the campaign holding this item should also be stopped. It has no effect if this app was published directly to a playlist or player. If false
or missing, the parent campaign is not stopped. Please mind that if the campaign duration is not set as Variable in the platform, this might cause a black screen depending on how your campaign is structured.
The isPartialPlayback
controls whether this app was interrupted before its natural ending or not. Apps that are interrupted only show in reports created with the "Include Partial Playback" option checked. If not given or false
the playback is not reported as partial.
Retrieves the current value of the player attribute called "name".
Attributes need to be created on the platform before they can be retrieved. If an attribute with that name doesn't exist or the value is not set for the current player this method will return null
.
Otherwise it will return the value for the current player, which can be a Javascript number
or string
, according to the type specified when creating the attribute on the platform.
Sets the current value of the player attribute called "name"
to "value"
.
Player attributes need to be created on the platform before they can be set. The value parameter must be either a Javascript number
or string
, according to the type specified when creating the attribute on the platform.
If an attribute with the given name does not exist or the value type is incorrect, this call will have no effect.
Attributes set using this function are persisted only until the player reboots and affects attribute restrictions on content playback for this player until reboot.
Update the current value of multiple player attributes based on the given object.
Player attributes need to be created on the platform before they can be set. The object values must be either a Javascript number
or string
, according to the type specified when creating the attribute on the platform.
If an attribute in the object does not exist or its value type is incorrect, it will be ignored.
Attributes set using this function are persisted only until the player reboots and affects attribute restrictions on content playback for this player until reboot.
Adds custom messages to the event listing page of the player.
The first parameter is the level of this event. Must be one of the following strings: "debug"
, "info"
, "warning"
, "error"
or "fatal"
. Events with "debug"
level are hidden from the end-user, while "error"
or "fatal"
events will cause a notification to be sent to their email. Please use them sparingly.
The second parameter is a machine-readable event code. It is used to aggregate events of the same code. It must contain only letters, numbers, dashes and underscores, matching this regular expression ^[_a-zA-Z][-_0-9a-zA-Z]*$
, with up to 128 characters in length.
The third parameter is the message that will be shown to the end-user, or sent to their email for "error"
or "fatal"
events. Can be up to 1024 characters in length.
The last parameter is an object containing data you want to attach to this event. The sum of the length of all keys and values must be less then 16 Kilobytes.
If the player is offline, the event will be saved in persistent storage and be sent when the player comes back online.
Events are rate-limited, with each player being able to send up to 200 events per hour.
signage.sendEvent("info", "connection-status", "Connected to the network.", {"status": true});
signage.sendEvent("error", "connection-status", "Unable to connect to the network.", {"status": false});
Writes data
to the given RS-232 Serial Port called "alias"
. The serial port configuration and alias are set on your OnSign TV player settings page.
The second parameter, data
, is an ASCII String
to be written. Trying to write non-ASCII characters might cause the write to fail or the non-ASCII characters to be rejected, depending on the platform.
Returns a Promise
that is fulfilled when the write succeeds or is rejected when the write fails. A write might fail due to the serial port being disconnected, not configured or temporarily busy.
There is no automatic retry of writes. Writes are always enqueue before being executed, so that multiple apps can write to the same serial port without interweaving the data.
Reads a file as a String
. The file is referenced by its ContentID
and converted to string according to the given encoding.
The first parameter is the ContentID
, which must be acquired from a configuration option or from a media file. Any other method of acquiring that ID can't assume the file will exist in the player, because only published files are downloaded.
The second parameter is an object specifying the encoding of the file. Currently the only supported encoding is "utf8"
, but other encodings might be supported in the future.
Returns a Promise
that is fulfilled with the contents of the file as a String
. The promise is rejected if the content does not exist, doesn't have an associated file, could not be read or its encoding is not valid UTF-8
.
You can use signage.addEventListner("contentchanged", "ContentID", cb)
to be notified of any changes to this content file.
Click here to expand and view an sample using this API.
<!DOCTYPE html>
<title>Example of reading an XML file</title>
{{ __loadsdk__ }}
{{ __config__(name="config_file", type="xml", label="XML config") }}
<script type="text/javascript">
window.signageLoaded.then(function () {
signage
.readContent("{{ config_file.id }}", { encoding: "utf8" })
.then(function (fileData) {
// You can use the fileData string any way you want.
}, function (error) {
// something went wrong and we couldn't read the file.
});
});
</script>
Logs internal messages that can be used by support staff to understand app issues. These messages are not end-user visible and are available on request.
This function is not rate-limited like signage.sendEvent
, therefore it is suitable for debugging.
Plays the local file referenced by the ID. Usually this file is uploaded alongside the app, so you can get the URI when rendering the template:
<!DOCTYPE html>
<title>Example of referencing an audio</title>
{{ __loadsdk__ }}
<script type="text/javascript">
window.signageLoaded.then(function() {
signage.playAudio("{{ media.bell_ring.url }}");
});
</script>
Get the current value of screen brightness, from 0
to 100
.
Brightness can be configured either through hardware or software and that configuration is done through the platform.
Set the current value of screen brightness, from 0
to 100
.
Brightness can be set either through hardware or software, depending on the configuration done through the platform. If not configured there, using this method will cause the player to fallback to software brightness.
Get the current hardware volume, from 0
to 100
. This method represents the volume of the hardware itself, not the volume your app is configured to use.
Even if your app is muted, signage.getVolume()
might return 100 if the operating system volume is at max value.
Sets the current hardware volume, from 0
to 100
. This method changes the volume of the hardware itself, not the volume your app is configured to use.
For players that have a status LED around the screen, such as the Philips T-Line devices, it is possible to control that LED with this method. It accepts three values, from 0
to 255
, for setting the intensity of the red, green and blue components of the LED.
For players that have a status LED around the screen, such as the Philips T-Line devices, it is possible to poweroff that LED with this method.
Text-To-Speech provides access to the underlying platform's ability to transform text into spoken word. Each text to be spoken is called an utterance and contains information about the language, pitch and rate of the text to be spoken.
All utterances are queued and spoken in First-In-First-Out order. To interrupt any utterance currently being spoken the signage.ttsStop()
can be called. This will cause the TTS engine to start speaking the next queued utterance. If you want to make sure the engine is idle, call signage.ttsFlush()
before calling signage.ttsStop()
.
Sets the language, locale and voice that will be used for future signage.ttsSpeak("text to be spoken")
calls that don't provide the language
option.
The parameter is the IETF language tag followed by the voice name. Per the document, the two or three letter language code is to be picked from ISO 639-1 or ISO 639-2. The country code is picked from ISO 3166-1. The language tag and country subtag have to be separated using a hyphen.
The voice is platform dependent, goes from Voice1
to Voice9
, with Voice1
being the default voice for the given locale. It is also used if the requested voice does not exist. To comply to the IETF format, the selected voice must be preceded by -x-
, e.g. "en-GB-x-Voice2"
or "pt-BR-x-Voice3"
.
Sets the pitch that will be used for future signage.ttsSpeak("text to be spoken")
calls that don't provide the pitch
option.
Value ranges from 0.0
to 4.0
. 1.0
is the normal pitch, lower values lower the tone of the synthesized voice, greater values increase it.
Sets the rate that will be used for future signage.ttsSpeak("text to be spoken")
calls that don't provide the rate
option.
Value ranges from 0.0
to 4.0
. 1.0
is the normal speech rate, lower values slow down the speech (0.5
is half the normal speech rate), greater values accelerate it (2.0
is twice the normal speech rate).
If the Text-To-Speech engine is idle, begins speaking text
immediately. Otherwise, enqueues text
the utterance queue.
When provided, options
is an object that specifies the behavior for this utterance. The available options are:
language
: overrides the language for the given text.pitch
: overrides the pitch for the given text.rate
: overrides the rate for the given text.
signage.ttsSpeak("the train will arrive in 5 minutes", {language: "en-US"});
signage.ttsSpeak("el tren llegará en 5 minutos", {language: "es", rate: 1.1});
This function also supports the signage.ttsSpeak(text, language)
signature for simplicity.
signage.ttsSpeak("el tren llegará en 5 minutos", "es-ES");
Returns a Promise
that will be fulfilled with a boolean parameter signifying whether the text was spoken until the end. The promise will be rejected when TTS engine is unable to speak the utterance due to an error.
signage.ttsSpeak("speaking might fail").then(function(spoken) {
if (spoken) {
console.log("the phrase was spoken");
} else {
console.log("the phrase was interrupted or cancelled");
}
}).catch(function() {
console.log("failed to speak the phrase");
});
Causes the engine to pause for the given duration instead of speaking the next utterance. Duration is given in milliseconds.
Returns a Promise
that will be fulfilled with a boolean parameter signifying whether the silence was maintained until the end. The promise will be rejected when TTS engine is unable to pause due to an error.
Remove all enqueued utterances. If there are no utterance enqueued, calling this function is a no-op. The utterance currently being spoken, if any, will not be stopped. For that you must call signage.ttsStop()
.
Stops any utterance currently being spoken. If there are enqueued utterances, the oldest one is immediately dequeued and started. To completely stop the engine, call signage.ttsFlush()
before calling signage.ttsStop()
.
Before using a method of the Javascript API please check to see whether they are available on your target platform.
Method | Android | Windows | Linux | Samsung SSP | BrightSign | LG WebOS | ChromeOS | Raspberry Pi |
---|---|---|---|---|---|---|---|---|
signage.getBrightness() |
5.1.0 | 10.1.0 | 10.1.0 | 10.1.0 | 10.1.0 | 10.1.0 | - | 10.1.0 |
signage.getCurrentPosition() |
5.3.5 | 10.0.6 | 10.0.6 | 10.1.0 | 10.1.0 | 10.1.0 | - | - |
signage.getGeoLocation() |
9.9.5 | 10.0.6 | 10.0.6 | 10.1.0 | 10.1.0 | 10.1.0 | - | 10.1.0 |
signage.getPlayerAttribute() |
9.8.11 | 9.3.13 | 10.1.0 | 10.1.0 | 10.1.0 | 10.1.0 | - | 10.1.0 |
signage.getVolume() |
8.3.0 | 10.1.0 | - | 10.1.0 | 10.1.0 | 10.1.0 | - | 10.1.0 |
signage.height() |
4.3.0 | 5.9.0 | 5.9.0 | 2.4.0 | 2.4.0 | 2.4.0 | 2.4.0 | 10.0.0 |
signage.isVisible() |
4.0.11 | 2.0.4 | 2.0.4 | 2.4.0 | 2.4.0 | 2.4.0 | 2.4.0 | 10.0.0 |
signage.ledOff() |
8.1.0 | - | - | - | - | - | - | - |
signage.ledOn() |
8.1.0 | - | - | - | - | - | - | - |
signage.log() |
9.1.0 | 10.1.0 | 10.1.0 | 10.1.0 | 10.1.0 | 10.1.0 | - | 10.1.0 |
signage.playAudio() |
4.0.9 | 2.0.4 | 2.0.4 | 10.1.0 | 10.1.0 | 10.1.0 | - | - |
signage.playbackInfo() |
5.3.5 | 5.9.0 | 5.9.0 | 1.0.8 | 1.1.1 | 1.0.8 | 1.1.1 | 10.0.0 |
signage.readContent() |
10.2.0 | 10.2.0 | 10.2.0 | 10.2.0 | 10.2.0 | 10.2.0 | - | - |
signage.playbackLoops() |
- | - | - | - | - | - | - | - |
signage.sendEvent() |
10.1.0 | 10.0.20 | 10.0.20 | 10.1.0 | 10.1.0 | 10.1.0 | - | 10.1.0 |
signage.serialPortWrite() |
10.2.0 | 10.2.2 | 10.2.2 | - | 10.1.1 | - | - | - |
signage.setBrightness() |
5.1.0 | 10.1.0 | 10.1.0 | 10.1.0 | 10.1.0 | 10.1.0 | - | 10.1.0 |
signage.setPlayerAttribute() |
9.8.11 | 9.3.13 | 9.3.13 | 10.1.0 | 10.1.0 | 10.1.0 | - | 10.1.0 |
signage.setPlayerAttributes() |
10.1.1 | 10.1.6 | 10.1.6 | 10.1.0 | 10.1.0 | 10.1.0 | - | 10.1.0 |
signage.setVolume() |
8.3.0 | 10.1.0 | 10.1.0 | 10.1.0 | 10.1.0 | 10.1.0 | - | 10.1.0 |
signage.stopCurrentCampaign() |
8.3.0 | 9.3.13 | 9.3.13 | 10.1.0 | 10.1.0 | 10.1.0 | - | 10.1.0 |
signage.stopThisItem() |
10.1.0 | 10.1.0 | 10.1.0 | 10.1.0 | 10.1.0 | 10.1.0 | - | 10.1.0 |
signage.triggerInteractivity() |
9.8.11 | 9.3.13 | 9.3.13 | 10.1.0 | 10.1.0 | 10.1.0 | - | 10.1.0 |
signage.ttsFlush() |
10.1.0 | 10.0.20 | 10.0.20 | - | - | - | - | - |
signage.ttsSetLanguage() |
10.1.0 | 10.0.20 | 10.0.20 | - | - | - | - | - |
signage.ttsSetPitch() |
10.1.0 | 10.0.20 | 10.0.20 | - | - | - | - | - |
signage.ttsSetRate() |
10.1.0 | 10.0.20 | 10.0.20 | - | - | - | - | - |
signage.ttsSilence() |
10.1.0 | 10.0.20 | 10.0.20 | - | - | - | - | - |
signage.ttsSpeak() |
10.1.0 | 10.0.20 | 10.0.20 | - | - | - | - | - |
signage.ttsStop() |
10.1.0 | 10.0.20 | 10.0.20 | - | - | - | - | - |
signage.width() |
4.3.0 | 5.9.0 | 5.9.0 | 2.4.0 | 2.4.0 | 2.4.0 | 2.4.0 | 10.0.0 |
window.signageLoaded |
All | All | All | All | All | All | All | All |
window.signageVisible |
All | All | All | All | All | All | All | All |
document.addEventListener("signageloaded") |
All | All | All | All | All | All | All | All |
document.addEventListener("show") |
All | All | All | All | All | All | All | All |
document.addEventListener("restart") |
All | All | All | All | All | All | All | All |
document.addEventListener("sizechanged") |
All | All | All | All | All | All | All | All |
signage.addEventListener("attrchanged") |
10.2.0 | 10.1.9 | 10.1.9 | 10.1.5 | 10.1.5 | 10.1.5 | - | - |
signage.addEventListener("propchanged") |
10.2.0 | 10.1.9 | 10.1.9 | 10.1.5 | 10.1.5 | 10.1.5 | - | - |
signage.addEventListener("serialportdata") |
10.2.0 | 10.2.2 | 10.2.1 | - | 10.1.5 | - | - | - |
signage.addEventListener("contentchanged") |
10.2.0 | 10.2.0 | 10.2.0 | 10.2.0 | 10.2.0 | 10.2.0 | - | - |
signage.addEventListener("playbackloopschanged") |
10.3.0 | 10.3.0 | 10.3.0 | 10.3.0 | 10.3.0 | 10.3.0 | - | - |