stormcloud-video-player 0.8.38 → 0.8.40
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.
- package/dist/stormcloud-vp.min.js +1 -1
- package/lib/index.cjs +83 -21
- package/lib/index.cjs.map +1 -1
- package/lib/index.js +83 -21
- package/lib/index.js.map +1 -1
- package/lib/player/AdBreakOrchestrator.cjs +78 -16
- package/lib/player/AdBreakOrchestrator.cjs.map +1 -1
- package/lib/player/AdConfigManager.cjs +78 -16
- package/lib/player/AdConfigManager.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +78 -16
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.cjs +78 -16
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/index.cjs +78 -16
- package/lib/players/index.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.cjs +78 -16
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/utils/mqttClient.cjs +83 -21
- package/lib/utils/mqttClient.cjs.map +1 -1
- package/lib/utils/tracking.cjs +78 -16
- package/lib/utils/tracking.cjs.map +1 -1
- package/package.json +1 -1
- package/lib/types-iDjS8f_7.d.cts +0 -133
package/lib/utils/mqttClient.cjs
CHANGED
|
@@ -143,8 +143,17 @@ function buildMQTTBrokerUrl() {
|
|
|
143
143
|
}
|
|
144
144
|
// src/utils/mqttClient.ts
|
|
145
145
|
var LOG = "[StormcloudVideoPlayer][MQTT]";
|
|
146
|
+
var KEEPALIVE_SECONDS = 30;
|
|
147
|
+
var CONNECT_TIMEOUT_MS = 1e4;
|
|
148
|
+
var RECONNECT_BASE_MS = 5e3;
|
|
149
|
+
var RECONNECT_MAX_MS = 6e4;
|
|
150
|
+
var MAX_RECONNECT_ATTEMPTS = 8;
|
|
151
|
+
var COOLDOWN_MS = 10 * 6e4;
|
|
146
152
|
var client = null;
|
|
147
153
|
var status = "disconnected";
|
|
154
|
+
var reconnectAttempts = 0;
|
|
155
|
+
var reconnectTimer = null;
|
|
156
|
+
var stopped = false;
|
|
148
157
|
function getMQTTStatus() {
|
|
149
158
|
return status;
|
|
150
159
|
}
|
|
@@ -158,8 +167,45 @@ function configureMQTT(overrides) {
|
|
|
158
167
|
applyMQTTConfig(overrides);
|
|
159
168
|
disconnectMQTT();
|
|
160
169
|
}
|
|
161
|
-
function
|
|
162
|
-
if (
|
|
170
|
+
function clearReconnectTimer() {
|
|
171
|
+
if (reconnectTimer) {
|
|
172
|
+
clearTimeout(reconnectTimer);
|
|
173
|
+
reconnectTimer = null;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
function teardownClient() {
|
|
177
|
+
if (client) {
|
|
178
|
+
try {
|
|
179
|
+
client.removeAllListeners();
|
|
180
|
+
client.end(true);
|
|
181
|
+
} catch (unused) {}
|
|
182
|
+
client = null;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
function scheduleReconnect() {
|
|
186
|
+
if (stopped || !isMQTTEnabled() || reconnectTimer) return;
|
|
187
|
+
if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
|
|
188
|
+
console.warn("".concat(LOG, " giving up after ").concat(reconnectAttempts, " attempts; cooling down for ").concat(COOLDOWN_MS / 6e4, "m"));
|
|
189
|
+
teardownClient();
|
|
190
|
+
status = "disconnected";
|
|
191
|
+
reconnectTimer = setTimeout(function() {
|
|
192
|
+
reconnectTimer = null;
|
|
193
|
+
reconnectAttempts = 0;
|
|
194
|
+
openConnection();
|
|
195
|
+
}, COOLDOWN_MS);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
var delay = Math.min(RECONNECT_MAX_MS, RECONNECT_BASE_MS * Math.pow(2, reconnectAttempts));
|
|
199
|
+
var jitter = Math.floor(Math.random() * 1e3);
|
|
200
|
+
reconnectAttempts += 1;
|
|
201
|
+
reconnectTimer = setTimeout(function() {
|
|
202
|
+
reconnectTimer = null;
|
|
203
|
+
openConnection();
|
|
204
|
+
}, delay + jitter);
|
|
205
|
+
}
|
|
206
|
+
function openConnection() {
|
|
207
|
+
if (stopped || !isMQTTEnabled()) return;
|
|
208
|
+
teardownClient();
|
|
163
209
|
var url = buildMQTTBrokerUrl();
|
|
164
210
|
status = "connecting";
|
|
165
211
|
var clientId = "stormcloud-vp-".concat(Math.random().toString(36).slice(2, 9));
|
|
@@ -168,41 +214,57 @@ function initMQTTClient() {
|
|
|
168
214
|
clientId: clientId,
|
|
169
215
|
username: mqttConfig.username,
|
|
170
216
|
password: mqttConfig.password,
|
|
171
|
-
keepalive:
|
|
217
|
+
keepalive: KEEPALIVE_SECONDS,
|
|
172
218
|
clean: true,
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
219
|
+
// Disable MQTT.js internal reconnect; we manage reconnection ourselves.
|
|
220
|
+
reconnectPeriod: 0,
|
|
221
|
+
connectTimeout: CONNECT_TIMEOUT_MS,
|
|
222
|
+
queueQoSZero: false,
|
|
223
|
+
reschedulePings: true,
|
|
224
|
+
// Root-cause fix for the Tizen 4.0 "Keepalive timeout" loop: MQTT.js's
|
|
225
|
+
// default timerVariant "auto" runs the keepalive interval inside a
|
|
226
|
+
// Blob-URL Web Worker (via worker-timers). On Samsung Tizen 4.0 (old
|
|
227
|
+
// WebKit) served from a file:// origin that worker can't tick reliably,
|
|
228
|
+
// so the keepalive counter trips onKeepaliveTimeout almost immediately
|
|
229
|
+
// after connect. Force the native setInterval timer instead; the main
|
|
230
|
+
// thread is free because video is decoded by the native AVPlay pipeline.
|
|
231
|
+
timerVariant: "native"
|
|
176
232
|
});
|
|
177
233
|
} catch (err) {
|
|
178
234
|
status = "error";
|
|
179
235
|
console.warn("".concat(LOG, " connect() threw:"), err);
|
|
236
|
+
scheduleReconnect();
|
|
180
237
|
return;
|
|
181
238
|
}
|
|
182
239
|
client.on("connect", function() {
|
|
183
240
|
status = "connected";
|
|
241
|
+
reconnectAttempts = 0;
|
|
242
|
+
clearReconnectTimer();
|
|
184
243
|
console.info("".concat(LOG, " connected to ").concat(url));
|
|
185
244
|
});
|
|
186
|
-
client.on("reconnect", function() {
|
|
187
|
-
status = "connecting";
|
|
188
|
-
console.info("".concat(LOG, " reconnecting…"));
|
|
189
|
-
});
|
|
190
245
|
client.on("offline", function() {
|
|
191
|
-
status = "disconnected";
|
|
246
|
+
if (status === "connected") status = "disconnected";
|
|
192
247
|
console.warn("".concat(LOG, " offline"));
|
|
248
|
+
scheduleReconnect();
|
|
193
249
|
});
|
|
194
250
|
client.on("error", function(err) {
|
|
195
251
|
status = "error";
|
|
196
252
|
console.warn("".concat(LOG, " error:"), err.message);
|
|
253
|
+
scheduleReconnect();
|
|
197
254
|
});
|
|
198
255
|
client.on("close", function() {
|
|
199
|
-
if (status === "connected")
|
|
200
|
-
|
|
201
|
-
}
|
|
256
|
+
if (status === "connected") status = "disconnected";
|
|
257
|
+
scheduleReconnect();
|
|
202
258
|
});
|
|
203
259
|
}
|
|
260
|
+
function initMQTTClient() {
|
|
261
|
+
if (client || !isMQTTEnabled()) return;
|
|
262
|
+
stopped = false;
|
|
263
|
+
reconnectAttempts = 0;
|
|
264
|
+
openConnection();
|
|
265
|
+
}
|
|
204
266
|
function ensureMQTTClient() {
|
|
205
|
-
if (isMQTTEnabled() && !client) {
|
|
267
|
+
if (isMQTTEnabled() && !client && !reconnectTimer) {
|
|
206
268
|
initMQTTClient();
|
|
207
269
|
}
|
|
208
270
|
}
|
|
@@ -211,7 +273,7 @@ function publishMQTT(topic, payload) {
|
|
|
211
273
|
return false;
|
|
212
274
|
}
|
|
213
275
|
ensureMQTTClient();
|
|
214
|
-
if (!client) {
|
|
276
|
+
if (!client || !client.connected) {
|
|
215
277
|
return false;
|
|
216
278
|
}
|
|
217
279
|
try {
|
|
@@ -225,11 +287,11 @@ function publishMQTT(topic, payload) {
|
|
|
225
287
|
}
|
|
226
288
|
}
|
|
227
289
|
function disconnectMQTT() {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
290
|
+
stopped = true;
|
|
291
|
+
clearReconnectTimer();
|
|
292
|
+
teardownClient();
|
|
293
|
+
reconnectAttempts = 0;
|
|
294
|
+
status = "disconnected";
|
|
233
295
|
}
|
|
234
296
|
// Annotate the CommonJS export names for ESM import in node:
|
|
235
297
|
0 && (module.exports = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/ubuntu24-new/Dev/stormcloud-vp/lib/utils/mqttClient.cjs","../../src/utils/mqttClient.ts","../../src/utils/mqttConfig.ts"],"names":["Object","create","__create","defineProperty","__defProp","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__getProtoOf","getPrototypeOf","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","__copyProps","to","from","except","desc","key","call","__toESM","mod","isNodeMode","__esModule","value","__toCommonJS","mqttClient_exports","configureMQTT","disconnectMQTT","ensureMQTTClient","getMQTTStatus","initMQTTClient","isMQTTConfigured","isMQTTConnected","publishMQTT","module","exports","import_mqtt","require","DEFAULT_MQTT_CONFIG","enabled","brokerAddress","brokerPort","wsPort","username","password","topicPrefix","qos","mqttConfig","applyMQTTConfig","overrides","assign","isMQTTEnabled","buildMQTTBrokerUrl","brokerUrl","LOG","client","status","connected","url","clientId","Math","random","toString","slice"],"mappings":"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","sourcesContent":["\"use strict\";\nvar __create = Object.create;\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __getProtoOf = Object.getPrototypeOf;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(\n // If the importer is in node compatibility mode or this is not an ESM\n // file that has been converted to a CommonJS file using a Babel-\n // compatible transform (i.e. \"__esModule\" has not been set), then set\n // \"default\" to the CommonJS \"module.exports\" for node compatibility.\n isNodeMode || !mod || !mod.__esModule ? __defProp(target, \"default\", { value: mod, enumerable: true }) : target,\n mod\n));\nvar __toCommonJS = (mod) => __copyProps(__defProp({}, \"__esModule\", { value: true }), mod);\n\n// src/utils/mqttClient.ts\nvar mqttClient_exports = {};\n__export(mqttClient_exports, {\n configureMQTT: () => configureMQTT,\n disconnectMQTT: () => disconnectMQTT,\n ensureMQTTClient: () => ensureMQTTClient,\n getMQTTStatus: () => getMQTTStatus,\n initMQTTClient: () => initMQTTClient,\n isMQTTConfigured: () => isMQTTConfigured,\n isMQTTConnected: () => isMQTTConnected,\n publishMQTT: () => publishMQTT\n});\nmodule.exports = __toCommonJS(mqttClient_exports);\nvar import_mqtt = __toESM(require(\"mqtt\"), 1);\n\n// src/utils/mqttConfig.ts\nvar DEFAULT_MQTT_CONFIG = {\n enabled: true,\n brokerAddress: \"vecbae77.ala.us-east-1.emqxsl.com\",\n brokerPort: 8883,\n wsPort: 8084,\n username: \"for-sonifi\",\n password: \"sonifi-mqtt\",\n topicPrefix: \"adstorm/players\",\n qos: 1\n};\nvar mqttConfig = { ...DEFAULT_MQTT_CONFIG };\nfunction applyMQTTConfig(overrides) {\n Object.assign(mqttConfig, overrides);\n}\nfunction isMQTTEnabled() {\n return mqttConfig.enabled;\n}\nfunction buildMQTTBrokerUrl() {\n if (mqttConfig.brokerUrl) return mqttConfig.brokerUrl;\n return `wss://${mqttConfig.brokerAddress}:${mqttConfig.wsPort}/mqtt`;\n}\n\n// src/utils/mqttClient.ts\nvar LOG = \"[StormcloudVideoPlayer][MQTT]\";\nvar client = null;\nvar status = \"disconnected\";\nfunction getMQTTStatus() {\n return status;\n}\nfunction isMQTTConnected() {\n return status === \"connected\" && client !== null && client.connected;\n}\nfunction isMQTTConfigured() {\n return isMQTTEnabled();\n}\nfunction configureMQTT(overrides) {\n applyMQTTConfig(overrides);\n disconnectMQTT();\n}\nfunction initMQTTClient() {\n if (client || !isMQTTEnabled()) return;\n const url = buildMQTTBrokerUrl();\n status = \"connecting\";\n const clientId = `stormcloud-vp-${Math.random().toString(36).slice(2, 9)}`;\n try {\n client = import_mqtt.default.connect(url, {\n clientId,\n username: mqttConfig.username,\n password: mqttConfig.password,\n keepalive: 60,\n clean: true,\n reconnectPeriod: 5e3,\n connectTimeout: 1e4,\n queueQoSZero: false\n });\n } catch (err) {\n status = \"error\";\n console.warn(`${LOG} connect() threw:`, err);\n return;\n }\n client.on(\"connect\", () => {\n status = \"connected\";\n console.info(`${LOG} connected to ${url}`);\n });\n client.on(\"reconnect\", () => {\n status = \"connecting\";\n console.info(`${LOG} reconnecting\\u2026`);\n });\n client.on(\"offline\", () => {\n status = \"disconnected\";\n console.warn(`${LOG} offline`);\n });\n client.on(\"error\", (err) => {\n status = \"error\";\n console.warn(`${LOG} error:`, err.message);\n });\n client.on(\"close\", () => {\n if (status === \"connected\") {\n status = \"disconnected\";\n }\n });\n}\nfunction ensureMQTTClient() {\n if (isMQTTEnabled() && !client) {\n initMQTTClient();\n }\n}\nfunction publishMQTT(topic, payload) {\n if (!isMQTTEnabled()) {\n return false;\n }\n ensureMQTTClient();\n if (!client) {\n return false;\n }\n try {\n client.publish(topic, JSON.stringify(payload), { qos: mqttConfig.qos });\n return true;\n } catch (err) {\n console.warn(`${LOG} publish failed on ${topic}:`, err);\n return false;\n }\n}\nfunction disconnectMQTT() {\n if (client) {\n client.end(true);\n client = null;\n status = \"disconnected\";\n }\n}\n// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n configureMQTT,\n disconnectMQTT,\n ensureMQTTClient,\n getMQTTStatus,\n initMQTTClient,\n isMQTTConfigured,\n isMQTTConnected,\n publishMQTT\n});\n","import mqtt from \"mqtt\";\nimport type { MqttClient } from \"mqtt\";\nimport {\n applyMQTTConfig,\n buildMQTTBrokerUrl,\n isMQTTEnabled,\n mqttConfig,\n} from \"./mqttConfig\";\nimport type { MQTTConfig } from \"./mqttConfig\";\n\nconst LOG = \"[StormcloudVideoPlayer][MQTT]\";\n\nexport type MQTTStatus = \"disconnected\" | \"connecting\" | \"connected\" | \"error\";\n\nlet client: MqttClient | null = null;\nlet status: MQTTStatus = \"disconnected\";\n\nexport function getMQTTStatus(): MQTTStatus {\n return status;\n}\n\nexport function isMQTTConnected(): boolean {\n return status === \"connected\" && client !== null && client.connected;\n}\n\nexport function isMQTTConfigured(): boolean {\n return isMQTTEnabled();\n}\n\nexport function configureMQTT(overrides: Partial<MQTTConfig>): void {\n applyMQTTConfig(overrides);\n disconnectMQTT();\n}\n\nexport function initMQTTClient(): void {\n if (client || !isMQTTEnabled()) return;\n\n const url = buildMQTTBrokerUrl();\n status = \"connecting\";\n\n const clientId = `stormcloud-vp-${Math.random().toString(36).slice(2, 9)}`;\n\n try {\n client = mqtt.connect(url, {\n clientId,\n username: mqttConfig.username,\n password: mqttConfig.password,\n keepalive: 60,\n clean: true,\n reconnectPeriod: 5000,\n connectTimeout: 10_000,\n queueQoSZero: false,\n });\n } catch (err) {\n status = \"error\";\n console.warn(`${LOG} connect() threw:`, err);\n return;\n }\n\n client.on(\"connect\", () => {\n status = \"connected\";\n console.info(`${LOG} connected to ${url}`);\n });\n\n client.on(\"reconnect\", () => {\n status = \"connecting\";\n console.info(`${LOG} reconnecting…`);\n });\n\n client.on(\"offline\", () => {\n status = \"disconnected\";\n console.warn(`${LOG} offline`);\n });\n\n client.on(\"error\", (err) => {\n status = \"error\";\n console.warn(`${LOG} error:`, err.message);\n });\n\n client.on(\"close\", () => {\n if (status === \"connected\") {\n status = \"disconnected\";\n }\n });\n}\n\nexport function ensureMQTTClient(): void {\n if (isMQTTEnabled() && !client) {\n initMQTTClient();\n }\n}\n\nexport function publishMQTT(\n topic: string,\n payload: Record<string, unknown>\n): boolean {\n if (!isMQTTEnabled()) {\n return false;\n }\n\n ensureMQTTClient();\n\n if (!client) {\n return false;\n }\n\n try {\n client.publish(topic, JSON.stringify(payload), { qos: mqttConfig.qos });\n return true;\n } catch (err) {\n console.warn(`${LOG} publish failed on ${topic}:`, err);\n return false;\n }\n}\n\nexport function disconnectMQTT(): void {\n if (client) {\n client.end(true);\n client = null;\n status = \"disconnected\";\n }\n}\n","export const MQTT_CA_CERT_FILE = \"src/certs/emqxsl-ca.crt\";\n\nexport type MQTTConfig = {\n enabled: boolean;\n brokerAddress: string;\n brokerPort: number;\n wsPort: number;\n username: string;\n password: string;\n topicPrefix: string;\n qos: 0 | 1 | 2;\n brokerUrl?: string;\n};\n\nexport const DEFAULT_MQTT_CONFIG: MQTTConfig = {\n enabled: true,\n brokerAddress: \"vecbae77.ala.us-east-1.emqxsl.com\",\n brokerPort: 8883,\n wsPort: 8084,\n username: \"for-sonifi\",\n password: \"sonifi-mqtt\",\n topicPrefix: \"adstorm/players\",\n qos: 1,\n};\n\nexport const mqttConfig: MQTTConfig = { ...DEFAULT_MQTT_CONFIG };\n\nexport function applyMQTTConfig(overrides: Partial<MQTTConfig>): void {\n Object.assign(mqttConfig, overrides);\n}\n\nexport function isMQTTEnabled(): boolean {\n return mqttConfig.enabled;\n}\n\nexport function buildMQTTBrokerUrl(): string {\n if (mqttConfig.brokerUrl) return mqttConfig.brokerUrl;\n return `wss://${mqttConfig.brokerAddress}:${mqttConfig.wsPort}/mqtt`;\n}\n\nexport function buildPlayerTopic(\n licenseKey: string,\n channel: \"metrics\" | \"impressions\" | \"heartbeat\"\n): string {\n return `${mqttConfig.topicPrefix}/${licenseKey}/${channel}`;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["/home/ubuntu24-new/Dev/stormcloud-vp/lib/utils/mqttClient.cjs","../../src/utils/mqttClient.ts","../../src/utils/mqttConfig.ts"],"names":["Object","create","__create","defineProperty","__defProp","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__getProtoOf","getPrototypeOf","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","get","enumerable","__copyProps","to","from","except","desc","key","call","__toESM","mod","isNodeMode","__esModule","value","__toCommonJS","mqttClient_exports","configureMQTT","disconnectMQTT","ensureMQTTClient","getMQTTStatus","initMQTTClient","isMQTTConfigured","isMQTTConnected","publishMQTT","module","exports","import_mqtt","require","DEFAULT_MQTT_CONFIG","enabled","brokerAddress","brokerPort","wsPort","password","topicPrefix","qos","mqttConfig","applyMQTTConfig","overrides","assign","isMQTTEnabled","buildMQTTBrokerUrl","brokerUrl","LOG","KEEPALIVE_SECONDS","CONNECT_TIMEOUT_MS","RECONNECT_BASE_MS","RECONNECT_MAX_MS","MAX_RECONNECT_ATTEMPTS","COOLDOWN_MS","client","status","reconnectAttempts","reconnectTimer","stopped","connected","clearReconnectTimer","clearTimeout","teardownClient","removeAllListeners","end","scheduleReconnect","console","warn","setTimeout","openConnection","delay","Math","min","jitter","floor","random","url","clientId","toString","slice","mqtt","connect","username","keepalive","clean","reconnectPeriod","connectTimeout","queueQoSZero","reschedulePings","timerVariant","err"],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IACA,gBAAeA,IAAOC,KAAtB,EAAIC,WAAWF;eAAOC,IAAM;;IAC5B,kBAAgBD,GAAOG,MAAvB,EAAIC,YAAYJ;eAAOG,WAAc;;IACrC,eAAIE,SAAJ,EAAIA;eAAmBL,OAAOM,wBAAwB;;IACtD,gBAAIC,SAAJ,EAAIA;eAAoBP,OAAOQ,mBAAmB;;IAClD,kBAAmBR,SAAnB,EAAIS,eAAeT;eAAOU,cAAc;;IACxC,EAAIC,eAAeX,SAAnB;eAAmBA,CAAOY,SAAS,CAACC,cAAc;;IAClD,aAAe,SAAf,EAAIC;eAAW,YAACC,QAAQC;;IACtB,IAAK,IAAIC,QAAQD,IACfZ,UAAUW,QAAQE,MAAM;QAAEC,KAAKF,CAAAA,EAAG,CAACC,KAAK,QAAA;QAAEE,UAAAA,EAAY,MAAA,QAAA,SAAA;AAC1D,0BAAA;AACA,IAAIC,cAAc,QAAA,aAACC,IAAIC,MAAMC,QAAQC;MACnC,IAAIF,GAAAA,KAAQ,CAAA,OAAOA,qCAAP,SAAOA,KAAG,MAAM,YAAY,OAAOA,SAAS,YAAY;cAC7D,KAAA,6BAAA,2BAAA;;;kBAAA,IAAIG,MAAJ;kBACH,IAAI,CAACd,aAAae,IAAI,CAACL,IAAII,QAAQA,QAAQF,QACzCnB,UAAUiB,IAAII,KAAK;sBAAEP,KAAK,SAALA;iCAAWI,IAAI,CAACG,IAAI;;oBAAEN,gBAAAA,UAAY,CAAEK,CAAAA,OAAOnB,iBAAiBiB,MAAMG,IAAG,KAAMD,KAAKL,UAAU;gBAAC,SAAA,SAAA;;YAFpH,QAAK,YAAWZ,kBAAkBe,0BAA7B,SAAA,6BAAA,QAAA,yBAAA;;cAAA,QAAA,OAAA;YAAA;;;oBAAA,UAAA,QAAA,aAAA,EAAA,KAAA,OAAA,IAAA,OAAA,MAAA,EAAA;oBAAA;;oBAAA;0BAAA;;;;IAGP,yBAAA;IACA,OAAOD,OAAAA,KAAAA;AACT,IAAA,SAAA;AACA,IAAIM,SAAAA,CAAU,iBAACC,KAAKC,YAAYd;WAAYA,SAASa,IAAAA,GAAO,OAAO1B,SAASO,aAAamB,QAAQ,CAAC,GAAGR,YACnG,sEAAsE;IACtE,iBAAA,gDAAiE;IACjE,UAAA,4DAAsE;IACtE,KAAA,gEAAqE;MACrES,KAAAA,SAAc,CAACD,OAAO,CAACA,IAAIE,UAAU,GAAG1B,UAAUW,QAAQ,WAAW;QAAEgB,OAAOH;QAAKT,CAAAA,WAAY;MAAK,KAAKJ,QACzGa,GAAAA,eAAAA,WAAAA,QAAAA,OAAAA,SAAAA;;AAEF,IAAII,KAAAA,UAAe,sBAACJ;aAAQR,YAAYhB,UAAU,CAAC,GAAG,cAAc;QAAE2B,OAAO;IAAK,IAAIH,CAAAA,cAAAA,SAAAA;;IAEtF,wBAA0B;AC7B1B,IAAAK,qBAAA,CAAA;AAAAnB,SAAAmB,oBAAA;MAAAC,EAAAA,aAAA,GAAA,MAAAA;mBAAAA,EAAAA;;MAAAC,gBAAA,SAAAA;eAAAA;;MAAAC,EAAAA,QAAAA,QAAA,SAAAA;mBAAAA;;YAAAC,OAAAA,GAAAA,CAAAA,EAAA,SAAAA;4BAAAA;QAAAC,SAAAA,OAAA,SAAAA;iBAAAA;;IAAAC,KAAAA,aAAA,SAAAA;iBAAAA,EAAAA,CAAAA,mBAAAA,gBAAAA;;QAAAC,QAAAA,IAAAA,IAAAA,CAAA,SAAAA,IAAAA,mBAAAA,OAAAA,mBAAAA,gCAAAA,OAAAA,cAAAA,KAAAA;QAAAC,aAAA,SAAAA;mBAAAA;;YAAA,iBAAA;YAAAC,CAAAC,OAAA,GAAAX,SAAAA,IAAAC;YAAAW,YAAiBjB,QAAAkB,QAAA,SAAA;QD4CjB,GAAA,mBAA0B;QE9BbC,sBAAkC;MAC7CC,SAAS;MACTC,EAAAA,QAAAA,GAAe,EAAA,GAAA,CACfC,YAAY,MACZC,QAAQ,qBAAA,GAAA;MAERC,EAAAA,MAAU,GAAA,KAAA,KAAA,CAAA,KAAA,MAAA,KAAA;MACVC,aAAa,MAAA;MACbC,KAAK,UAAA,WAAA;QACP,iBAAA;QAEaC,aAAyB,mBAAKR;IAEpC,GAAA,IAASS,IAAAA,YAAgBC,SAAA;IAC9BxD,OAAOyD,MAAA,CAAOH,YAAYE;AAC5B,SAAA;IAEO,IAAA,GAASE,QAAAA,CAAAA,iBAAAA;MACd,OAAOJ,WAAWP,OAAA;IACpB,IAAA,MAAA;IAEO,OAASY,EAAAA;MACd,EAAIL,WAAWM,QAAA,EAAW,OAAkB,OAAlB,CAAON,IAAAA,MAAAA,CAAWM,EAAAA,OAAA,CAAA,CAAA,IAAA,KAAA,CAAA,GAAA;MAC5C,EAAA,KAAO,SAAqCN,OAA5BA,WAAWN,aAAa,EAAA,KAAqB,OAAjBM,WAAWJ,MAAM,EAAA;QAC/D,SAAA,YAAA,OAAA,CAAA,OAAA,CAAA,KAAA;YF6BA,UAAA,oBAA0B;YCzDpBW,IAAM,MAAA,WAAA,QAAA;YAENC,UAAAA,QAAoB,GAAA,QAAA;YACpBC,WAAAA,QAAqB;YAErBC,OAAAA,WAAoB;YACpBC,iBAAmB,uDAAA;YACnBC,iBAAAA,MAAyB;YACzBC,YAAc,IAAA,CAAK;YAIrBC,OAA4B,OAAA;YAC5BC,OAAqB,UAAA;YACrBC,kBAAoB,qDAAA;YACpBC,eAAuD,oDAAA;YACvDC,QAAU,6DAAA;YAEP,GAASnC,qEAAAA;YACd,KAAOgC,kEAAAA;YACT,sEAAA;YAEO,GAAS7B,sEAAAA;YACd,KAAO6B,SAAAA,EAAW,eAAeD,WAAW,QAAQA,OAAOK,SAAA;QAC7D;IAEO,EAAA,KAASlC,EAAAA,KAAAA;QACd,OAAOmB,EAAAA;QACT,QAAA,IAAA,CAAA,GAAA,OAAA,KAAA,sBAAA;QAEO,KAASxB,cAAcsB,SAAA;QAC5BD,gBAAgBC;MAChBrB;IACF,OAAA,EAAA,CAAA,WAAA;QAEA,KAASuC,IAAAA;QACP,IAAIH,gBAAgB;YAClBI,aAAaJ;YACbA,IAAAA,IAAAA,CAAAA,GAAiB,OAAjBA,KAAAA,CAAiB,iBAAA,OAAA;MACnB;IACF,OAAA,EAAA,CAAA,WAAA;QAEA,IAAA,CAASK,UAAAA,aAAAA,SAAAA;QACP,IAAIR,IAAAA,IAAQ,CAAA,GAAA,OAAA,KAAA;YACV,IAAI;cACFA,OAAOS,kBAAA;cACPT,OAAOU,EAAAA,SAAA,CAAI;YACb,EAAA,GAAA,YAAQ,CAER;YACAV,IAAAA,IAAAA,CAAS,GAAA,OAAA,KAAA,YAAA,IAAA,OAAA;QACX;IACF;IAEA,OAASW,EAAAA,CAAAA,SAAAA;QACP,IAAIP,WAAW,CAACd,YAAAA,OAAmBa,EAAAA,cAAgB;QAEnD,IAAID,qBAAqBJ,wBAAwB;UAC/Cc,QAAQC,IAAA,CACN,GAA0BX,OAAvBT,KAAG,qBACJM,OADwBG,mBAAiB,gCAE3C,OADEH,cAAc,KAChB;QAEFS;QACAP,CAAAA,QAAS;UACTE,QAAAA,CAAAA,QAAiBW,SAAAA,EAAW;cAC1BX,iBAAiB;cACjBD,UAAAA,UAAoB;cACpBa;QACF,GAAGhB;QACH,CAAA;MACF,EAAA,mBAAA,CAAA,UAAA,CAAA,gBAAA;QAEA,IAAMiB,QAAQC,KAAKC,GAAA,CACjBrB,kBACAD,6BAAoB,GAAKM;MAE3B,IAAMiB,SAASF,KAAKG,KAAA,CAAMH,KAAKI,MAAA,KAAW;IAC1CnB,qBAAqB;IAErBC,KAAAA,YAAiBW,KAAAA,EAAAA,IAAW,GAAA;UAC1BX,gBAAAA,CAAiB;YACjBY,GAAAA;MACF,GAAGC,QAAQG;IACb;IAEA,IAAA,CAAA,EAASJ,QAAAA,CAAAA,OAAAA,SAAAA,EAAAA;QACP,IAAIX,GAAAA,QAAW,CAACd,iBAAiB;MAEjCkB;MAEA,EAAA,EAAMc,MAAM/B;QACZU,OAAAA,EAAS,KAAA,CAAA,OAAA,KAAA,SAAA,CAAA,UAAA;YAAA,KAAA,WAAA,GAAA;QAAA;QAET,IAAMsB,GAAAA,QAAW,iBAAuD,OAAtCN,KAAKI,MAAA,GAASG,QAAA,CAAS,IAAIC,KAAA,CAAM,GAAG;MAEtE,IAAI,GAAA,KAAA;YACFzB,IAAAA,IAAAA,CAASxB,UAAAA,KAAAA,KAAAkD,OAAAA,CAAKC,OAAA,GAAa,OAALL,KAAK,EAAA,MAAA;gBACzBC,UAAAA;cACAK,UAAU1C,WAAW0C,QAAA;YACrB7C,UAAUG,WAAWH,QAAA;YACrB8C,WAAWnC;cACXoC,OAAO;cAAA,wEAAA;cAEPC,iBAAiB;cACjBC,UAAAA,MAAgBrC;cAChBsC,cAAc;YACdC,iBAAiB;YAAA,iDAAA,sBAAA;YAAA,CAAA,OAAA,GAAA,wDAAA;6BAAA,qEAAA;8BAAA,wEAAA;gCAAA,uEAAA;6BAAA,sEAAA;8BAAA,yEAAA;gCAQjBC,cAAc;2BAChB;mBACF,EAAA,OAASC,KAAK;SACZnC,SAAS","sourcesContent":["\"use strict\";\nvar __create = Object.create;\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __getProtoOf = Object.getPrototypeOf;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(\n // If the importer is in node compatibility mode or this is not an ESM\n // file that has been converted to a CommonJS file using a Babel-\n // compatible transform (i.e. \"__esModule\" has not been set), then set\n // \"default\" to the CommonJS \"module.exports\" for node compatibility.\n isNodeMode || !mod || !mod.__esModule ? __defProp(target, \"default\", { value: mod, enumerable: true }) : target,\n mod\n));\nvar __toCommonJS = (mod) => __copyProps(__defProp({}, \"__esModule\", { value: true }), mod);\n\n// src/utils/mqttClient.ts\nvar mqttClient_exports = {};\n__export(mqttClient_exports, {\n configureMQTT: () => configureMQTT,\n disconnectMQTT: () => disconnectMQTT,\n ensureMQTTClient: () => ensureMQTTClient,\n getMQTTStatus: () => getMQTTStatus,\n initMQTTClient: () => initMQTTClient,\n isMQTTConfigured: () => isMQTTConfigured,\n isMQTTConnected: () => isMQTTConnected,\n publishMQTT: () => publishMQTT\n});\nmodule.exports = __toCommonJS(mqttClient_exports);\nvar import_mqtt = __toESM(require(\"mqtt\"), 1);\n\n// src/utils/mqttConfig.ts\nvar DEFAULT_MQTT_CONFIG = {\n enabled: true,\n brokerAddress: \"vecbae77.ala.us-east-1.emqxsl.com\",\n brokerPort: 8883,\n wsPort: 8084,\n username: \"for-sonifi\",\n password: \"sonifi-mqtt\",\n topicPrefix: \"adstorm/players\",\n qos: 1\n};\nvar mqttConfig = { ...DEFAULT_MQTT_CONFIG };\nfunction applyMQTTConfig(overrides) {\n Object.assign(mqttConfig, overrides);\n}\nfunction isMQTTEnabled() {\n return mqttConfig.enabled;\n}\nfunction buildMQTTBrokerUrl() {\n if (mqttConfig.brokerUrl) return mqttConfig.brokerUrl;\n return `wss://${mqttConfig.brokerAddress}:${mqttConfig.wsPort}/mqtt`;\n}\n\n// src/utils/mqttClient.ts\nvar LOG = \"[StormcloudVideoPlayer][MQTT]\";\nvar KEEPALIVE_SECONDS = 30;\nvar CONNECT_TIMEOUT_MS = 1e4;\nvar RECONNECT_BASE_MS = 5e3;\nvar RECONNECT_MAX_MS = 6e4;\nvar MAX_RECONNECT_ATTEMPTS = 8;\nvar COOLDOWN_MS = 10 * 6e4;\nvar client = null;\nvar status = \"disconnected\";\nvar reconnectAttempts = 0;\nvar reconnectTimer = null;\nvar stopped = false;\nfunction getMQTTStatus() {\n return status;\n}\nfunction isMQTTConnected() {\n return status === \"connected\" && client !== null && client.connected;\n}\nfunction isMQTTConfigured() {\n return isMQTTEnabled();\n}\nfunction configureMQTT(overrides) {\n applyMQTTConfig(overrides);\n disconnectMQTT();\n}\nfunction clearReconnectTimer() {\n if (reconnectTimer) {\n clearTimeout(reconnectTimer);\n reconnectTimer = null;\n }\n}\nfunction teardownClient() {\n if (client) {\n try {\n client.removeAllListeners();\n client.end(true);\n } catch {\n }\n client = null;\n }\n}\nfunction scheduleReconnect() {\n if (stopped || !isMQTTEnabled() || reconnectTimer) return;\n if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {\n console.warn(\n `${LOG} giving up after ${reconnectAttempts} attempts; cooling down for ${COOLDOWN_MS / 6e4}m`\n );\n teardownClient();\n status = \"disconnected\";\n reconnectTimer = setTimeout(() => {\n reconnectTimer = null;\n reconnectAttempts = 0;\n openConnection();\n }, COOLDOWN_MS);\n return;\n }\n const delay = Math.min(\n RECONNECT_MAX_MS,\n RECONNECT_BASE_MS * 2 ** reconnectAttempts\n );\n const jitter = Math.floor(Math.random() * 1e3);\n reconnectAttempts += 1;\n reconnectTimer = setTimeout(() => {\n reconnectTimer = null;\n openConnection();\n }, delay + jitter);\n}\nfunction openConnection() {\n if (stopped || !isMQTTEnabled()) return;\n teardownClient();\n const url = buildMQTTBrokerUrl();\n status = \"connecting\";\n const clientId = `stormcloud-vp-${Math.random().toString(36).slice(2, 9)}`;\n try {\n client = import_mqtt.default.connect(url, {\n clientId,\n username: mqttConfig.username,\n password: mqttConfig.password,\n keepalive: KEEPALIVE_SECONDS,\n clean: true,\n // Disable MQTT.js internal reconnect; we manage reconnection ourselves.\n reconnectPeriod: 0,\n connectTimeout: CONNECT_TIMEOUT_MS,\n queueQoSZero: false,\n reschedulePings: true,\n // Root-cause fix for the Tizen 4.0 \"Keepalive timeout\" loop: MQTT.js's\n // default timerVariant \"auto\" runs the keepalive interval inside a\n // Blob-URL Web Worker (via worker-timers). On Samsung Tizen 4.0 (old\n // WebKit) served from a file:// origin that worker can't tick reliably,\n // so the keepalive counter trips onKeepaliveTimeout almost immediately\n // after connect. Force the native setInterval timer instead; the main\n // thread is free because video is decoded by the native AVPlay pipeline.\n timerVariant: \"native\"\n });\n } catch (err) {\n status = \"error\";\n console.warn(`${LOG} connect() threw:`, err);\n scheduleReconnect();\n return;\n }\n client.on(\"connect\", () => {\n status = \"connected\";\n reconnectAttempts = 0;\n clearReconnectTimer();\n console.info(`${LOG} connected to ${url}`);\n });\n client.on(\"offline\", () => {\n if (status === \"connected\") status = \"disconnected\";\n console.warn(`${LOG} offline`);\n scheduleReconnect();\n });\n client.on(\"error\", (err) => {\n status = \"error\";\n console.warn(`${LOG} error:`, err.message);\n scheduleReconnect();\n });\n client.on(\"close\", () => {\n if (status === \"connected\") status = \"disconnected\";\n scheduleReconnect();\n });\n}\nfunction initMQTTClient() {\n if (client || !isMQTTEnabled()) return;\n stopped = false;\n reconnectAttempts = 0;\n openConnection();\n}\nfunction ensureMQTTClient() {\n if (isMQTTEnabled() && !client && !reconnectTimer) {\n initMQTTClient();\n }\n}\nfunction publishMQTT(topic, payload) {\n if (!isMQTTEnabled()) {\n return false;\n }\n ensureMQTTClient();\n if (!client || !client.connected) {\n return false;\n }\n try {\n client.publish(topic, JSON.stringify(payload), { qos: mqttConfig.qos });\n return true;\n } catch (err) {\n console.warn(`${LOG} publish failed on ${topic}:`, err);\n return false;\n }\n}\nfunction disconnectMQTT() {\n stopped = true;\n clearReconnectTimer();\n teardownClient();\n reconnectAttempts = 0;\n status = \"disconnected\";\n}\n// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n configureMQTT,\n disconnectMQTT,\n ensureMQTTClient,\n getMQTTStatus,\n initMQTTClient,\n isMQTTConfigured,\n isMQTTConnected,\n publishMQTT\n});\n","import mqtt from \"mqtt\";\nimport type { MqttClient } from \"mqtt\";\nimport {\n applyMQTTConfig,\n buildMQTTBrokerUrl,\n isMQTTEnabled,\n mqttConfig,\n} from \"./mqttConfig\";\nimport type { MQTTConfig } from \"./mqttConfig\";\n\nconst LOG = \"[StormcloudVideoPlayer][MQTT]\";\n\nconst KEEPALIVE_SECONDS = 30;\nconst CONNECT_TIMEOUT_MS = 10_000;\n\nconst RECONNECT_BASE_MS = 5_000;\nconst RECONNECT_MAX_MS = 60_000;\nconst MAX_RECONNECT_ATTEMPTS = 8;\nconst COOLDOWN_MS = 10 * 60_000;\n\nexport type MQTTStatus = \"disconnected\" | \"connecting\" | \"connected\" | \"error\";\n\nlet client: MqttClient | null = null;\nlet status: MQTTStatus = \"disconnected\";\nlet reconnectAttempts = 0;\nlet reconnectTimer: ReturnType<typeof setTimeout> | null = null;\nlet stopped = false;\n\nexport function getMQTTStatus(): MQTTStatus {\n return status;\n}\n\nexport function isMQTTConnected(): boolean {\n return status === \"connected\" && client !== null && client.connected;\n}\n\nexport function isMQTTConfigured(): boolean {\n return isMQTTEnabled();\n}\n\nexport function configureMQTT(overrides: Partial<MQTTConfig>): void {\n applyMQTTConfig(overrides);\n disconnectMQTT();\n}\n\nfunction clearReconnectTimer(): void {\n if (reconnectTimer) {\n clearTimeout(reconnectTimer);\n reconnectTimer = null;\n }\n}\n\nfunction teardownClient(): void {\n if (client) {\n try {\n client.removeAllListeners();\n client.end(true);\n } catch {\n // ignore teardown errors\n }\n client = null;\n }\n}\n\nfunction scheduleReconnect(): void {\n if (stopped || !isMQTTEnabled() || reconnectTimer) return;\n\n if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {\n console.warn(\n `${LOG} giving up after ${reconnectAttempts} attempts; cooling down for ${\n COOLDOWN_MS / 60_000\n }m`\n );\n teardownClient();\n status = \"disconnected\";\n reconnectTimer = setTimeout(() => {\n reconnectTimer = null;\n reconnectAttempts = 0;\n openConnection();\n }, COOLDOWN_MS);\n return;\n }\n\n const delay = Math.min(\n RECONNECT_MAX_MS,\n RECONNECT_BASE_MS * 2 ** reconnectAttempts\n );\n const jitter = Math.floor(Math.random() * 1_000);\n reconnectAttempts += 1;\n\n reconnectTimer = setTimeout(() => {\n reconnectTimer = null;\n openConnection();\n }, delay + jitter);\n}\n\nfunction openConnection(): void {\n if (stopped || !isMQTTEnabled()) return;\n\n teardownClient();\n\n const url = buildMQTTBrokerUrl();\n status = \"connecting\";\n\n const clientId = `stormcloud-vp-${Math.random().toString(36).slice(2, 9)}`;\n\n try {\n client = mqtt.connect(url, {\n clientId,\n username: mqttConfig.username,\n password: mqttConfig.password,\n keepalive: KEEPALIVE_SECONDS,\n clean: true,\n // Disable MQTT.js internal reconnect; we manage reconnection ourselves.\n reconnectPeriod: 0,\n connectTimeout: CONNECT_TIMEOUT_MS,\n queueQoSZero: false,\n reschedulePings: true,\n // Root-cause fix for the Tizen 4.0 \"Keepalive timeout\" loop: MQTT.js's\n // default timerVariant \"auto\" runs the keepalive interval inside a\n // Blob-URL Web Worker (via worker-timers). On Samsung Tizen 4.0 (old\n // WebKit) served from a file:// origin that worker can't tick reliably,\n // so the keepalive counter trips onKeepaliveTimeout almost immediately\n // after connect. Force the native setInterval timer instead; the main\n // thread is free because video is decoded by the native AVPlay pipeline.\n timerVariant: \"native\",\n });\n } catch (err) {\n status = \"error\";\n console.warn(`${LOG} connect() threw:`, err);\n scheduleReconnect();\n return;\n }\n\n client.on(\"connect\", () => {\n status = \"connected\";\n reconnectAttempts = 0;\n clearReconnectTimer();\n console.info(`${LOG} connected to ${url}`);\n });\n\n client.on(\"offline\", () => {\n if (status === \"connected\") status = \"disconnected\";\n console.warn(`${LOG} offline`);\n scheduleReconnect();\n });\n\n client.on(\"error\", (err) => {\n status = \"error\";\n console.warn(`${LOG} error:`, err.message);\n scheduleReconnect();\n });\n\n client.on(\"close\", () => {\n if (status === \"connected\") status = \"disconnected\";\n scheduleReconnect();\n });\n}\n\nexport function initMQTTClient(): void {\n if (client || !isMQTTEnabled()) return;\n stopped = false;\n reconnectAttempts = 0;\n openConnection();\n}\n\nexport function ensureMQTTClient(): void {\n if (isMQTTEnabled() && !client && !reconnectTimer) {\n initMQTTClient();\n }\n}\n\nexport function publishMQTT(\n topic: string,\n payload: Record<string, unknown>\n): boolean {\n if (!isMQTTEnabled()) {\n return false;\n }\n\n ensureMQTTClient();\n\n if (!client || !client.connected) {\n return false;\n }\n\n try {\n client.publish(topic, JSON.stringify(payload), { qos: mqttConfig.qos });\n return true;\n } catch (err) {\n console.warn(`${LOG} publish failed on ${topic}:`, err);\n return false;\n }\n}\n\nexport function disconnectMQTT(): void {\n stopped = true;\n clearReconnectTimer();\n teardownClient();\n reconnectAttempts = 0;\n status = \"disconnected\";\n}\n","export const MQTT_CA_CERT_FILE = \"src/certs/emqxsl-ca.crt\";\n\nexport type MQTTConfig = {\n enabled: boolean;\n brokerAddress: string;\n brokerPort: number;\n wsPort: number;\n username: string;\n password: string;\n topicPrefix: string;\n qos: 0 | 1 | 2;\n brokerUrl?: string;\n};\n\nexport const DEFAULT_MQTT_CONFIG: MQTTConfig = {\n enabled: true,\n brokerAddress: \"vecbae77.ala.us-east-1.emqxsl.com\",\n brokerPort: 8883,\n wsPort: 8084,\n username: \"for-sonifi\",\n password: \"sonifi-mqtt\",\n topicPrefix: \"adstorm/players\",\n qos: 1,\n};\n\nexport const mqttConfig: MQTTConfig = { ...DEFAULT_MQTT_CONFIG };\n\nexport function applyMQTTConfig(overrides: Partial<MQTTConfig>): void {\n Object.assign(mqttConfig, overrides);\n}\n\nexport function isMQTTEnabled(): boolean {\n return mqttConfig.enabled;\n}\n\nexport function buildMQTTBrokerUrl(): string {\n if (mqttConfig.brokerUrl) return mqttConfig.brokerUrl;\n return `wss://${mqttConfig.brokerAddress}:${mqttConfig.wsPort}/mqtt`;\n}\n\nexport function buildPlayerTopic(\n licenseKey: string,\n channel: \"metrics\" | \"impressions\" | \"heartbeat\"\n): string {\n return `${mqttConfig.topicPrefix}/${licenseKey}/${channel}`;\n}\n"]}
|
package/lib/utils/tracking.cjs
CHANGED
|
@@ -271,10 +271,56 @@ function buildPlayerTopic(licenseKey, channel) {
|
|
|
271
271
|
// src/utils/mqttClient.ts
|
|
272
272
|
var import_mqtt = __toESM(require("mqtt"), 1);
|
|
273
273
|
var LOG = "[StormcloudVideoPlayer][MQTT]";
|
|
274
|
+
var KEEPALIVE_SECONDS = 30;
|
|
275
|
+
var CONNECT_TIMEOUT_MS = 1e4;
|
|
276
|
+
var RECONNECT_BASE_MS = 5e3;
|
|
277
|
+
var RECONNECT_MAX_MS = 6e4;
|
|
278
|
+
var MAX_RECONNECT_ATTEMPTS = 8;
|
|
279
|
+
var COOLDOWN_MS = 10 * 6e4;
|
|
274
280
|
var client = null;
|
|
275
281
|
var status = "disconnected";
|
|
276
|
-
|
|
277
|
-
|
|
282
|
+
var reconnectAttempts = 0;
|
|
283
|
+
var reconnectTimer = null;
|
|
284
|
+
var stopped = false;
|
|
285
|
+
function clearReconnectTimer() {
|
|
286
|
+
if (reconnectTimer) {
|
|
287
|
+
clearTimeout(reconnectTimer);
|
|
288
|
+
reconnectTimer = null;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
function teardownClient() {
|
|
292
|
+
if (client) {
|
|
293
|
+
try {
|
|
294
|
+
client.removeAllListeners();
|
|
295
|
+
client.end(true);
|
|
296
|
+
} catch (unused) {}
|
|
297
|
+
client = null;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
function scheduleReconnect() {
|
|
301
|
+
if (stopped || !isMQTTEnabled() || reconnectTimer) return;
|
|
302
|
+
if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
|
|
303
|
+
console.warn("".concat(LOG, " giving up after ").concat(reconnectAttempts, " attempts; cooling down for ").concat(COOLDOWN_MS / 6e4, "m"));
|
|
304
|
+
teardownClient();
|
|
305
|
+
status = "disconnected";
|
|
306
|
+
reconnectTimer = setTimeout(function() {
|
|
307
|
+
reconnectTimer = null;
|
|
308
|
+
reconnectAttempts = 0;
|
|
309
|
+
openConnection();
|
|
310
|
+
}, COOLDOWN_MS);
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
var delay = Math.min(RECONNECT_MAX_MS, RECONNECT_BASE_MS * Math.pow(2, reconnectAttempts));
|
|
314
|
+
var jitter = Math.floor(Math.random() * 1e3);
|
|
315
|
+
reconnectAttempts += 1;
|
|
316
|
+
reconnectTimer = setTimeout(function() {
|
|
317
|
+
reconnectTimer = null;
|
|
318
|
+
openConnection();
|
|
319
|
+
}, delay + jitter);
|
|
320
|
+
}
|
|
321
|
+
function openConnection() {
|
|
322
|
+
if (stopped || !isMQTTEnabled()) return;
|
|
323
|
+
teardownClient();
|
|
278
324
|
var url = buildMQTTBrokerUrl();
|
|
279
325
|
status = "connecting";
|
|
280
326
|
var clientId = "stormcloud-vp-".concat(Math.random().toString(36).slice(2, 9));
|
|
@@ -283,41 +329,57 @@ function initMQTTClient() {
|
|
|
283
329
|
clientId: clientId,
|
|
284
330
|
username: mqttConfig.username,
|
|
285
331
|
password: mqttConfig.password,
|
|
286
|
-
keepalive:
|
|
332
|
+
keepalive: KEEPALIVE_SECONDS,
|
|
287
333
|
clean: true,
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
334
|
+
// Disable MQTT.js internal reconnect; we manage reconnection ourselves.
|
|
335
|
+
reconnectPeriod: 0,
|
|
336
|
+
connectTimeout: CONNECT_TIMEOUT_MS,
|
|
337
|
+
queueQoSZero: false,
|
|
338
|
+
reschedulePings: true,
|
|
339
|
+
// Root-cause fix for the Tizen 4.0 "Keepalive timeout" loop: MQTT.js's
|
|
340
|
+
// default timerVariant "auto" runs the keepalive interval inside a
|
|
341
|
+
// Blob-URL Web Worker (via worker-timers). On Samsung Tizen 4.0 (old
|
|
342
|
+
// WebKit) served from a file:// origin that worker can't tick reliably,
|
|
343
|
+
// so the keepalive counter trips onKeepaliveTimeout almost immediately
|
|
344
|
+
// after connect. Force the native setInterval timer instead; the main
|
|
345
|
+
// thread is free because video is decoded by the native AVPlay pipeline.
|
|
346
|
+
timerVariant: "native"
|
|
291
347
|
});
|
|
292
348
|
} catch (err) {
|
|
293
349
|
status = "error";
|
|
294
350
|
console.warn("".concat(LOG, " connect() threw:"), err);
|
|
351
|
+
scheduleReconnect();
|
|
295
352
|
return;
|
|
296
353
|
}
|
|
297
354
|
client.on("connect", function() {
|
|
298
355
|
status = "connected";
|
|
356
|
+
reconnectAttempts = 0;
|
|
357
|
+
clearReconnectTimer();
|
|
299
358
|
console.info("".concat(LOG, " connected to ").concat(url));
|
|
300
359
|
});
|
|
301
|
-
client.on("reconnect", function() {
|
|
302
|
-
status = "connecting";
|
|
303
|
-
console.info("".concat(LOG, " reconnecting…"));
|
|
304
|
-
});
|
|
305
360
|
client.on("offline", function() {
|
|
306
|
-
status = "disconnected";
|
|
361
|
+
if (status === "connected") status = "disconnected";
|
|
307
362
|
console.warn("".concat(LOG, " offline"));
|
|
363
|
+
scheduleReconnect();
|
|
308
364
|
});
|
|
309
365
|
client.on("error", function(err) {
|
|
310
366
|
status = "error";
|
|
311
367
|
console.warn("".concat(LOG, " error:"), err.message);
|
|
368
|
+
scheduleReconnect();
|
|
312
369
|
});
|
|
313
370
|
client.on("close", function() {
|
|
314
|
-
if (status === "connected")
|
|
315
|
-
|
|
316
|
-
}
|
|
371
|
+
if (status === "connected") status = "disconnected";
|
|
372
|
+
scheduleReconnect();
|
|
317
373
|
});
|
|
318
374
|
}
|
|
375
|
+
function initMQTTClient() {
|
|
376
|
+
if (client || !isMQTTEnabled()) return;
|
|
377
|
+
stopped = false;
|
|
378
|
+
reconnectAttempts = 0;
|
|
379
|
+
openConnection();
|
|
380
|
+
}
|
|
319
381
|
function ensureMQTTClient() {
|
|
320
|
-
if (isMQTTEnabled() && !client) {
|
|
382
|
+
if (isMQTTEnabled() && !client && !reconnectTimer) {
|
|
321
383
|
initMQTTClient();
|
|
322
384
|
}
|
|
323
385
|
}
|
|
@@ -326,7 +388,7 @@ function publishMQTT(topic, payload) {
|
|
|
326
388
|
return false;
|
|
327
389
|
}
|
|
328
390
|
ensureMQTTClient();
|
|
329
|
-
if (!client) {
|
|
391
|
+
if (!client || !client.connected) {
|
|
330
392
|
return false;
|
|
331
393
|
}
|
|
332
394
|
try {
|