Brings device:command (reboot / screen_off / screen_on / shutdown / update /
launch) to the Tizen player, at parity with the Android player. Previously app.js
only handled device:reload and device:command did nothing on SSSP panels.
- NEW tizen/js/device-control.js: self-contained IIFE (window.STDeviceControl =
{ run, capabilities, backend }). Feature-detects two Samsung surfaces newest-first
— webapis.systemcontrol.* (Tizen 6.5/7, synchronous/throws) then
b2bapis.b2bcontrol.* (SSSP/Tizen 4, async onSuccess/onError) — and normalises both
to Promises, re-probing each call since the APIs can be injected late. run() never
rejects; it resolves a uniform { ok, supported, action, note, reload }. Panel power
tries setPanelMute (mute ON = backlight OFF) then falls back to setDisplayPanel /
setPanelStatus before declaring unsupported. shutdown is honest: SSSP web API has
no true power-off, so it mutes the panel and says so. update/reload resolve
reload:true.
- tizen/js/app.js: keep device:reload; add a device:command handler that calls
STDeviceControl.run and reports the outcome via reportCmd (device:log tag=command,
which surfaces as dashboard:device-log, plus a structured device:command-result),
reloading ~1.2s later when result.reload so the log reaches the server first.
reportCapabilities() runs on device:registered so the dashboard sees the backend
("none" on web/consumer TV).
- tizen/config.xml: add partner-level b2bcontrol + systemcontrol privileges, with a
note that they need a Samsung Partner distributor cert and are ignored (not fatal)
on unsigned/URL-Launcher/web/consumer builds.
- tizen/index.html: load $WEBAPIS/webapis.js + $B2BAPIS/b2bapis.js before the app
scripts (404 harmlessly off-hardware) and device-control.js just before app.js.
- tizen/README.md: document the mapping table + partner-signing caveat; update the
"Not yet ported" note now that remote control exists.
Verified: node --check on both JS files; config.xml well-formed (xmllint). Not yet
validated on a real SSSP panel — the control surface only takes effect on a
partner-signed .wgt (backend reports "none" on the dev/URL-Launcher build).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|---|---|---|
| .. | ||
| css | ||
| js | ||
| .gitignore | ||
| build-wgt.sh | ||
| config.xml | ||
| icon.png | ||
| index.html | ||
| README.md | ||
ScreenTinker — Tizen TV Player (.wgt)
A Samsung Tizen TV / signage web port of the ScreenTinker player. It speaks the
exact same /device socket.io protocol as the Android player, so a Tizen
display pairs and plays from the same dashboard with no server changes.
What it does
- Enter a server URL → connects to
{server}/device(socket.io v4). - Registers, shows a 6-digit pairing code; you claim it in the dashboard
(Devices → Pair a display). On
device:pairedit switches to playback. - Reconnects automatically with a stored
device_id+device_token. - Renders fullscreen single-zone playlists, looping:
- image → shown for
duration_sec(min 3s) - video (
/api/content/{id}/fileorremote_url) → plays to end, then next; single item loops - YouTube (
mime video/youtube) → muted autoplay<iframe>embed - widget →
<iframe>of{server}/api/widgets/{id}/render
- image → shown for
- Sends
device:heartbeatevery 15s (with best-effort Tizen telemetry). - Keeps the screen awake (
tizen.power/ Samsungappcommonscreensaver-off).
Files
config.xml Tizen TV web-app manifest (privileges, profile, icon)
index.html setup / pairing / stage screens
css/style.css
js/app.js device protocol client (register, pair, heartbeat, state)
js/device-control.js Samsung B2B/system fleet control (device:command) — #125
js/player.js fullscreen playlist renderer
js/socket.io.min.js socket.io-client v4.7.5 (bundled)
icon.png
build-wgt.sh package (signed if Tizen CLI present, else unsigned)
Fleet control / device:command (#125)
The dashboard can send device:command { type, payload }; js/device-control.js
maps it onto a Samsung panel-control surface and reports the outcome back via
device:log (tag command, shown live on the device-detail screen) plus a
structured device:command-result. If a command needs a content re-pull, the
player reloads ~1.2s after reporting.
type |
Action on a Samsung panel |
|---|---|
reboot |
rebootDevice() |
screen_off |
setPanelMute("ON") — mute ON = backlight OFF (note the inversion) |
screen_on |
setPanelMute("OFF") |
shutdown |
setPanelMute("ON") + note: SSSP web API has no true power-off |
update |
reload to re-pull URL-Launcher content (no in-app OTA) |
launch |
no-op (already foreground) |
reload / refresh |
reload |
| unknown | reported as unsupported |
Two surfaces are feature-detected, newest first: webapis.systemcontrol.*
(Tizen 6.5/7, synchronous) then b2bapis.b2bcontrol.* (SSSP/Tizen 4, async).
For panel power, setPanelMute is tried first, falling back to setDisplayPanel /
setPanelStatus on older firmware before declaring it unsupported. run() never
throws — it always resolves a uniform { ok, supported, action, note, reload }.
Partner-signing caveat. The
b2bcontrol/systemcontrolprivileges inconfig.xmlonly take effect on a partner-signed.wgtrunning on a real SSSP panel. On the dev/URL-Launcher/web build (or a consumer TV) the surfaces are absent, so every command returns "unsupported" and the startup capability log reportsbackend=none. Only a partner-signed build on real hardware fully validates reboot / panel power.
Build
./build-wgt.sh # -> ScreenTinker.wgt
Without the Tizen CLI this is an unsigned .wgt.
Why the released
.wgtis unsigned: Samsung distributor certificates are locked to the DUID of the signer's own TVs, so a.wgtwe signed would not install on your TV anyway. Releases therefore ship it unsigned (for inspection only). To actually run it, use path A (no signing) or sign it yourself with your own certificate (path B).
Deploy — two paths
A) URL Launcher / TV browser (easiest, no signing)
No package, no Tizen Studio. Point the TV's URL Launcher (or just its web
browser) at your server's built-in web player: https://<your-instance>/player.
The TV runs it as a web app on boot, pairs with a 6-digit code, and plays - best
for Samsung B2B signage (SSSP). (You can instead self-host this tizen/ folder
and point the URL Launcher at …/index.html for the Tizen-specific build.)
B) Signed .wgt (installed app)
A signing profile is already set up on the build box (Tizen Studio CLI 6.1):
- Profile
ScreenTinker= a self-signed author cert (~/tizen-studio-data/keystore/author/st_author.p12) + the default Tizen distributor cert../build-wgt.shauto-detects the CLI and signs with it, producing a.wgtwithauthor-signature.xml+signature1.xml. - This installs on developer-mode Samsung TVs and the Tizen emulator —
the right path for a self-hosted fleet you control (enable Developer Mode
on each TV once: Apps → enter
12345→ set the host IP).
Install onto a dev-mode TV:
sdb connect <tv-ip>
tizen install -n ScreenTinker.wgt -t <tv-device>
Production / retail (no developer mode): re-sign with a Samsung Partner
or Public distributor certificate from the Tizen Certificate Manager
(free Samsung account; distributor cert tied to each TV's DUID), then
./build-wgt.sh <thatProfile>. The self-signed author cert is not committed (it
lives in ~/tizen-studio-data, password screentinker).
Validated (2026-06-09)
- Protocol: headless test against the live server passed end-to-end —
register(pairing_code) → device:registered → pair → reconnect(device_id+token) → device:playlist-update(2 items) → GET /api/content/{id}/file = 200. - Runtime: loads + renders in Chromium with no JS errors (setup screen verified).
- Not yet on real Tizen hardware — needs signing + a TV (or URL Launcher).
Not yet ported (Android player has these; fullscreen single-zone covers most signage)
Multi-zone layouts, video walls (wall:sync), screenshots, and remote touch.
Self-OTA is N/A (Tizen apps update via Samsung's store / URL Launcher refresh, not
the Android PackageInstaller flow). Fleet control (device:command: reboot /
screen on-off / shutdown / update / launch) is now wired — see the section above
(needs a partner-signed build on real SSSP hardware to fully take effect).