@tomorrowos/sdk 0.9.20 → 0.9.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -136,6 +136,15 @@ export declare class TomorrowOS extends EventEmitter {
136
136
  onOffTimer: DeviceOnOffTimer;
137
137
  pushed: boolean;
138
138
  }>;
139
+ /**
140
+ * Clear the daily on/off timer. The player keeps its current mute / power-save
141
+ * state until a new timer is set.
142
+ */
143
+ clearDeviceOnOffTimer(deviceId: string): Promise<{
144
+ deviceId: string;
145
+ onOffTimer: null;
146
+ pushed: boolean;
147
+ }>;
139
148
  private pushOnOffTimerToDevice;
140
149
  setDeviceName(deviceId: string, deviceName: string): Promise<{
141
150
  deviceId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"tomorrowos.d.ts","sourceRoot":"","sources":["../src/tomorrowos.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,IAAI,MAAM,MAAM,CAAC;AAYxB,OAAO,EAAE,eAAe,EAAE,KAAK,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAChF,OAAO,KAAK,EACV,gBAAgB,EAKhB,eAAe,EAEhB,MAAM,kBAAkB,CAAC;AAe1B,YAAY,EACV,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,aAAa,EACd,MAAM,oBAAoB,CAAC;AAE5B,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,eAAe,CAAC;IACvB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,eAAe,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAoED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mEAAmE;IACnE,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,kBAAkB,EAAE,KAAK,CAAC;QACxB,UAAU,EAAE,MAAM,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE;YACT,SAAS,CAAC,EAAE,MAAM,CAAC;YACnB,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,KAAK,CAAC,EAAE,MAAM,CAAC;YACf,GAAG,CAAC,EAAE,MAAM,CAAC;SACd,CAAC;KACH,CAAC,CAAC;IACH,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,gBAAgB,EAAE;QAChB,GAAG,EAAE,MAAM,CAAC;QACZ,UAAU,EAAE,MAAM,CAAC;KACpB,GAAG,IAAI,CAAC;IACT,2DAA2D;IAC3D,UAAU,EAAE,gBAAgB,GAAG,IAAI,CAAC;CACrC;AAoBD,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAwKD,qBAAa,UAAW,SAAQ,YAAY;IAC1C,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkB;IACxC,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmC;IAC3D,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAsC;IACxE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuC;IAClE,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,GAAG,CAAgC;IAC3C,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,eAAe,CAAgB;IACvC,wFAAwF;IACxF,OAAO,CAAC,eAAe,CAAuB;IAC9C,+DAA+D;IAC/D,OAAO,CAAC,UAAU,CAAuB;gBAE7B,OAAO,EAAE,iBAAiB;IAOtC,yFAAyF;IACnF,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QACxD,MAAM,EAAE,OAAO,CAAC;QAChB,MAAM,CAAC,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAC;KACtC,CAAC;YAkBY,iBAAiB;IAY/B,6EAA6E;IACvE,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IA4EhE,6EAA6E;IACvE,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;IAuCvF,OAAO;uBACU,MAAM;sBArHgC,MAAM;;2BAsHxC,MAAM;sBAzCgC,MAAM;sBAAY,OAAO;;MA0ClF;IAEF,kFAAkF;IAC5E,WAAW,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IAgF9C;;;OAGG;IACG,mBAAmB,CACvB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,OAAO,GAClB,OAAO,CAAC;QACT,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,gBAAgB,CAAC;QAC7B,MAAM,EAAE,OAAO,CAAC;KACjB,CAAC;YAqBY,sBAAsB;IAsB9B,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;QACjE,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IAyBF,0FAA0F;YAC5E,2BAA2B;YAW3B,0BAA0B;IAYxC,qFAAqF;YACvE,8BAA8B;IAY5C,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,aAAa;IAMrB,OAAO,CAAC,iBAAiB;IAKzB,OAAO,CAAC,gBAAgB;YAoBV,+BAA+B;YAsC/B,iBAAiB;YASjB,iBAAiB;YAqCjB,kBAAkB;IAUhC,uFAAuF;IACvF,OAAO,CAAC,kBAAkB;YAmBZ,gBAAgB;YAMhB,uBAAuB;IA0CrC,MAAM,CAAC,QAAQ,EAAE,MAAM;oBAGD,CAAC,oBACT,MAAM,WACN,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;;IAU5E,OAAO,CAAC,mBAAmB;IA6D3B,6EAA6E;IAC7E,OAAO,CAAC,kBAAkB;IAO1B,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAAC,MAAM;YAsD7B,iBAAiB;YAgDjB,uBAAuB;IA6ErC,OAAO,CAAC,oBAAoB;YASd,yBAAyB;YAQzB,4BAA4B;YAa5B,2CAA2C;YAO3C,iCAAiC;YA6BjC,wBAAwB;YAiBxB,cAAc;IAiD5B,OAAO,CAAC,uBAAuB;IAO/B,OAAO,CAAC,mBAAmB;YAOb,yBAAyB;YAwBzB,oBAAoB;YAkDpB,yBAAyB;YAsBzB,uBAAuB;YAcvB,UAAU;YA0WV,gBAAgB;IAqG9B,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,gBAAgB;CAkJzB"}
1
+ {"version":3,"file":"tomorrowos.d.ts","sourceRoot":"","sources":["../src/tomorrowos.ts"],"names":[],"mappings":"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"}
@@ -441,15 +441,33 @@ export class TomorrowOS extends EventEmitter {
441
441
  const pushed = await this.pushOnOffTimerToDevice(id);
442
442
  return { deviceId: id, onOffTimer, pushed };
443
443
  }
444
+ /**
445
+ * Clear the daily on/off timer. The player keeps its current mute / power-save
446
+ * state until a new timer is set.
447
+ */
448
+ async clearDeviceOnOffTimer(deviceId) {
449
+ const id = String(deviceId || "").trim();
450
+ if (!id) {
451
+ throw new Error("deviceId is required");
452
+ }
453
+ const existing = await this.store.getPairedDevice(id);
454
+ if (!existing) {
455
+ throw new Error("Device is not paired");
456
+ }
457
+ const { onOffTimer: _removed, ...rest } = existing;
458
+ await this.store.setPairedDevice(id, rest);
459
+ const pushed = await this.pushOnOffTimerToDevice(id);
460
+ return { deviceId: id, onOffTimer: null, pushed };
461
+ }
444
462
  async pushOnOffTimerToDevice(deviceId) {
445
463
  const existing = await this.store.getPairedDevice(deviceId);
446
- if (!existing?.onOffTimer)
464
+ if (!existing)
447
465
  return false;
448
466
  const ws = this.devices.get(deviceId);
449
467
  if (!ws || ws.readyState !== WebSocket.OPEN)
450
468
  return false;
451
469
  try {
452
- const result = await this.sendCommandToSocket(ws, deviceId, "device.display.setOnOffTimer", { onOffTimer: existing.onOffTimer }, 15_000);
470
+ const result = await this.sendCommandToSocket(ws, deviceId, "device.display.setOnOffTimer", { onOffTimer: existing.onOffTimer ?? null }, 15_000);
453
471
  return result.status === "success" || result.status === "accepted";
454
472
  }
455
473
  catch (err) {
@@ -1178,8 +1196,14 @@ export class TomorrowOS extends EventEmitter {
1178
1196
  const deviceId = decodeURIComponent(deviceOnOffTimer[1]);
1179
1197
  const body = (await readJsonBody(req));
1180
1198
  try {
1181
- const result = await this.setDeviceOnOffTimer(deviceId, body.onOffTimer ?? body);
1182
- sendJson(res, 200, { status: "success", ...result });
1199
+ if (body.clear === true || body.onOffTimer === null) {
1200
+ const result = await this.clearDeviceOnOffTimer(deviceId);
1201
+ sendJson(res, 200, { status: "success", ...result });
1202
+ }
1203
+ else {
1204
+ const result = await this.setDeviceOnOffTimer(deviceId, body.onOffTimer ?? body);
1205
+ sendJson(res, 200, { status: "success", ...result });
1206
+ }
1183
1207
  }
1184
1208
  catch (e) {
1185
1209
  const msg = e instanceof Error ? e.message : "On/off timer failed";
@@ -1187,6 +1211,18 @@ export class TomorrowOS extends EventEmitter {
1187
1211
  }
1188
1212
  return;
1189
1213
  }
1214
+ if (req.method === "DELETE" && deviceOnOffTimer) {
1215
+ const deviceId = decodeURIComponent(deviceOnOffTimer[1]);
1216
+ try {
1217
+ const result = await this.clearDeviceOnOffTimer(deviceId);
1218
+ sendJson(res, 200, { status: "success", ...result });
1219
+ }
1220
+ catch (e) {
1221
+ const msg = e instanceof Error ? e.message : "On/off timer clear failed";
1222
+ sendJson(res, 400, { status: "failed", error: msg });
1223
+ }
1224
+ return;
1225
+ }
1190
1226
  if (req.method === "GET" && pathname === "/playlists") {
1191
1227
  const playlists = await this.playlists.listPlaylists();
1192
1228
  sendJson(res, 200, { status: "success", playlists });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomorrowos/sdk",
3
- "version": "0.9.20",
3
+ "version": "0.9.21",
4
4
  "description": "TomorrowOS CMS server SDK - WebSocket transport, pairing, device commands, optional static CMS UI. Includes CLI (tomorrowos init / build) and starter templates.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "my-cms",
3
- "version": "0.9.20",
3
+ "version": "0.9.21",
4
4
  "description": "CMS server on @tomorrowos/sdk. Add your UI (React, static files, etc.) alongside this server.",
5
5
  "private": true,
6
6
  "type": "module",
@@ -13,7 +13,7 @@
13
13
  "build-player": "tomorrowos build --platform tizen"
14
14
  },
15
15
  "dependencies": {
16
- "@tomorrowos/sdk": "^0.9.20",
16
+ "@tomorrowos/sdk": "^0.9.21",
17
17
  "dotenv": "^17.2.3",
18
18
  "tsx": "^4.19.0"
19
19
  },
@@ -187,6 +187,7 @@
187
187
  <h2>On / off timer</h2>
188
188
  <p class="hint" id="onOffTimerModalHint">
189
189
  Daily on/off times follow the device clock. Off blacks the screen; the player stays powered and connected to the CMS.
190
+ Removing the timer stops the schedule and leaves the screen in its current on or off state until you set a timer again.
190
191
  </p>
191
192
  <div class="on-off-timer-grid">
192
193
  <label class="field-label">
@@ -200,6 +201,7 @@
200
201
  </div>
201
202
  <div class="modal-actions">
202
203
  <button type="button" id="onOffTimerSaveBtn" class="primary">Save</button>
204
+ <button type="button" id="onOffTimerRemoveBtn" class="danger hidden">Remove timer</button>
203
205
  <button type="button" data-close-on-off-timer-modal="1">Cancel</button>
204
206
  </div>
205
207
  </div>
@@ -1102,7 +1102,7 @@ function appendHardwareTimerStatusRow(meta, device) {
1102
1102
  row.className = "device-meta-row device-meta-row--timer-status";
1103
1103
 
1104
1104
  const dt = document.createElement("dt");
1105
- dt.textContent = "Hardware Timer Status";
1105
+ dt.textContent = "Hardware timer status";
1106
1106
 
1107
1107
  const dd = document.createElement("dd");
1108
1108
  const statusWrap = document.createElement("span");
@@ -1895,11 +1895,17 @@ function openOnOffTimerModal(deviceId) {
1895
1895
  const modal = document.getElementById("onOffTimerModal");
1896
1896
  const onEl = document.getElementById("onOffTimerTurnOnAt");
1897
1897
  const offEl = document.getElementById("onOffTimerTurnOffAt");
1898
+ const removeBtn = document.getElementById("onOffTimerRemoveBtn");
1898
1899
  if (!modal || !onEl || !offEl) return;
1899
1900
 
1900
1901
  const timer = device.onOffTimer || {};
1902
+ const configured = hasConfiguredOnOffTimer(device.onOffTimer);
1901
1903
  onEl.value = normalizeTimeInputValue(timer.turnOnAt, "06:00");
1902
1904
  offEl.value = normalizeTimeInputValue(timer.turnOffAt, "18:00");
1905
+ if (removeBtn) {
1906
+ removeBtn.classList.toggle("hidden", !configured);
1907
+ removeBtn.disabled = false;
1908
+ }
1903
1909
  modal.classList.remove("hidden");
1904
1910
  }
1905
1911
 
@@ -1916,6 +1922,7 @@ async function saveOnOffTimerModal() {
1916
1922
  const onEl = document.getElementById("onOffTimerTurnOnAt");
1917
1923
  const offEl = document.getElementById("onOffTimerTurnOffAt");
1918
1924
  const saveBtn = document.getElementById("onOffTimerSaveBtn");
1925
+ const removeBtn = document.getElementById("onOffTimerRemoveBtn");
1919
1926
  if (!onEl || !offEl) return;
1920
1927
 
1921
1928
  const onOffTimer = {
@@ -1929,6 +1936,7 @@ async function saveOnOffTimerModal() {
1929
1936
  }
1930
1937
 
1931
1938
  if (saveBtn) saveBtn.disabled = true;
1939
+ if (removeBtn) removeBtn.disabled = true;
1932
1940
  try {
1933
1941
  const res = await fetch(`/device/${encodeURIComponent(deviceId)}/on-off-timer`, {
1934
1942
  method: "POST",
@@ -1947,6 +1955,43 @@ async function saveOnOffTimerModal() {
1947
1955
  alert(err?.message || "Could not save on/off timer");
1948
1956
  } finally {
1949
1957
  if (saveBtn) saveBtn.disabled = false;
1958
+ if (removeBtn) removeBtn.disabled = false;
1959
+ }
1960
+ }
1961
+
1962
+ async function removeOnOffTimerModal() {
1963
+ const deviceId = onOffTimerModalDeviceId;
1964
+ if (!deviceId) return;
1965
+
1966
+ if (
1967
+ !confirm(
1968
+ "Remove the on/off timer? The screen will stay in its current on or off state until you set a timer again."
1969
+ )
1970
+ ) {
1971
+ return;
1972
+ }
1973
+
1974
+ const saveBtn = document.getElementById("onOffTimerSaveBtn");
1975
+ const removeBtn = document.getElementById("onOffTimerRemoveBtn");
1976
+ if (saveBtn) saveBtn.disabled = true;
1977
+ if (removeBtn) removeBtn.disabled = true;
1978
+ try {
1979
+ const res = await fetch(`/device/${encodeURIComponent(deviceId)}/on-off-timer`, {
1980
+ method: "DELETE"
1981
+ });
1982
+ const data = await res.json();
1983
+ if (!res.ok || data.status === "failed") {
1984
+ alert(data.error || "Could not remove on/off timer");
1985
+ return;
1986
+ }
1987
+ showResult({ deviceId, onOffTimer: null, pushed: data.pushed });
1988
+ closeOnOffTimerModal();
1989
+ await fetchDevices();
1990
+ } catch (err) {
1991
+ alert(err?.message || "Could not remove on/off timer");
1992
+ } finally {
1993
+ if (saveBtn) saveBtn.disabled = false;
1994
+ if (removeBtn) removeBtn.disabled = false;
1950
1995
  }
1951
1996
  }
1952
1997
 
@@ -2275,6 +2320,9 @@ document.addEventListener("DOMContentLoaded", () => {
2275
2320
  document
2276
2321
  .getElementById("onOffTimerSaveBtn")
2277
2322
  ?.addEventListener("click", () => void saveOnOffTimerModal());
2323
+ document
2324
+ .getElementById("onOffTimerRemoveBtn")
2325
+ ?.addEventListener("click", () => void removeOnOffTimerModal());
2278
2326
  document.querySelectorAll("[data-close-download-failed-modal]").forEach((el) => {
2279
2327
  el.addEventListener("click", closeDownloadFailedModal);
2280
2328
  });