smart-home-engine 0.27.2 → 0.27.5
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/web/assets/{index-6dbanXAb.css → index-CYeO3Jr9.css} +1 -1
- package/dist/web/assets/{index-sPBEVtGF.js → index-DlX_4aUV.js} +56 -56
- package/dist/web/assets/{tsMode-C0zTO8Xc.js → tsMode-B7dtAHLr.js} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/src/index.js +41 -14
- package/src/lib/shedb-worker.js +1 -1
- package/src/web/log-ws.js +17 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{m as O}from"./monaco-langs-BW2J83t5.js";import{t as I}from"./index-
|
|
1
|
+
import{m as O}from"./monaco-langs-BW2J83t5.js";import{t as I}from"./index-DlX_4aUV.js";/*!-----------------------------------------------------------------------------
|
|
2
2
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
3
|
* Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
|
|
4
4
|
* Released under the MIT license
|
package/dist/web/index.html
CHANGED
|
@@ -155,10 +155,10 @@
|
|
|
155
155
|
}
|
|
156
156
|
})();
|
|
157
157
|
</script>
|
|
158
|
-
<script type="module" crossorigin src="/assets/index-
|
|
158
|
+
<script type="module" crossorigin src="/assets/index-DlX_4aUV.js"></script>
|
|
159
159
|
<link rel="modulepreload" crossorigin href="/assets/monaco-langs-BW2J83t5.js">
|
|
160
160
|
<link rel="stylesheet" crossorigin href="/assets/monaco-langs-DyX1CsEw.css">
|
|
161
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
161
|
+
<link rel="stylesheet" crossorigin href="/assets/index-CYeO3Jr9.css">
|
|
162
162
|
</head>
|
|
163
163
|
<body>
|
|
164
164
|
<div id="app"></div>
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -47,7 +47,7 @@ const _pino = require('pino')(
|
|
|
47
47
|
}),
|
|
48
48
|
);
|
|
49
49
|
// Lazy import — log-ws exports a no-op broadcastLog when the HTTP server is not started.
|
|
50
|
-
const { broadcastLog, broadcast } = require('./web/log-ws');
|
|
50
|
+
const { broadcastLog, broadcast, setWelcomeProvider } = require('./web/log-ws');
|
|
51
51
|
const shedb = require('./web/shedb');
|
|
52
52
|
const log = {
|
|
53
53
|
debug: (...args) => {
|
|
@@ -243,10 +243,11 @@ let connected = false;
|
|
|
243
243
|
|
|
244
244
|
// Deferred start — wait for retained MQTT state before running scripts
|
|
245
245
|
let _started = false;
|
|
246
|
-
let _startupTimeout = null;
|
|
247
|
-
let
|
|
248
|
-
|
|
246
|
+
let _startupTimeout = null; // fires if broker never connects
|
|
247
|
+
let _sentinelTimeout = null; // fires if sentinel never arrives after connecting
|
|
248
|
+
let _sentinelValue = null; // unique value for this boot's sentinel
|
|
249
249
|
const _STARTUP_TIMEOUT_MS = 10000; // ms to wait for broker before starting anyway
|
|
250
|
+
const _SENTINEL_TIMEOUT_MS = 15000; // ms to wait for sentinel after connecting
|
|
250
251
|
|
|
251
252
|
function startOnce(reason) {
|
|
252
253
|
if (_started) return;
|
|
@@ -255,11 +256,12 @@ function startOnce(reason) {
|
|
|
255
256
|
clearTimeout(_startupTimeout);
|
|
256
257
|
_startupTimeout = null;
|
|
257
258
|
}
|
|
258
|
-
if (
|
|
259
|
-
clearTimeout(
|
|
260
|
-
|
|
259
|
+
if (_sentinelTimeout) {
|
|
260
|
+
clearTimeout(_sentinelTimeout);
|
|
261
|
+
_sentinelTimeout = null;
|
|
261
262
|
}
|
|
262
263
|
if (reason) log.info(reason);
|
|
264
|
+
broadcast({ type: 'mqtt:status', ready: true });
|
|
263
265
|
start();
|
|
264
266
|
}
|
|
265
267
|
|
|
@@ -325,6 +327,10 @@ require('./web/server').setStatsProvider(() => {
|
|
|
325
327
|
};
|
|
326
328
|
});
|
|
327
329
|
|
|
330
|
+
// Inform newly-connected WebSocket clients of the current mqtt:status so the
|
|
331
|
+
// UI shows the correct indicator even if the browser opened after the event fired.
|
|
332
|
+
setWelcomeProvider(() => ({ type: 'mqtt:status', ready: _started }));
|
|
333
|
+
|
|
328
334
|
if (!config.url) {
|
|
329
335
|
log.warn('no MQTT broker URL configured — set "url" in ' + path.join(require('os').homedir(), '.she', 'config.json'));
|
|
330
336
|
}
|
|
@@ -346,10 +352,29 @@ if (config.url) {
|
|
|
346
352
|
mqtt.subscribe('#');
|
|
347
353
|
mqttEventCallbacks.filter((c) => c.event === 'connect').forEach((c) => c.callback());
|
|
348
354
|
|
|
349
|
-
// Arm the quiet-period timer (only needed on first connect, before scripts start)
|
|
350
355
|
if (!_started) {
|
|
351
|
-
|
|
352
|
-
|
|
356
|
+
// Cancel the “broker not connecting” startup timeout — we’re connected.
|
|
357
|
+
if (_startupTimeout) {
|
|
358
|
+
clearTimeout(_startupTimeout);
|
|
359
|
+
_startupTimeout = null;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Publish a non-retained sentinel immediately after subscribing to #.
|
|
363
|
+
// MQTT.js sends packets in order on a single TCP connection, so the
|
|
364
|
+
// broker receives SUBSCRIBE before this PUBLISH. Retained messages are
|
|
365
|
+
// queued for us when SUBSCRIBE is processed; the sentinel is queued
|
|
366
|
+
// afterwards. Receiving the sentinel means all retained messages have
|
|
367
|
+
// been delivered — deterministic, no heuristic timer needed.
|
|
368
|
+
_sentinelValue = String(Date.now());
|
|
369
|
+
mqtt.publish(config.name + '/she-sentinel', _sentinelValue, { retain: false });
|
|
370
|
+
log.debug('mqtt: waiting for retained-state sentinel');
|
|
371
|
+
broadcast({ type: 'mqtt:status', ready: false });
|
|
372
|
+
|
|
373
|
+
// Fallback: if sentinel never arrives (e.g. abnormal broker behaviour)
|
|
374
|
+
_sentinelTimeout = setTimeout(() => {
|
|
375
|
+
log.warn('mqtt sentinel timeout — starting scripts without full retained state');
|
|
376
|
+
startOnce();
|
|
377
|
+
}, _SENTINEL_TIMEOUT_MS);
|
|
353
378
|
}
|
|
354
379
|
});
|
|
355
380
|
|
|
@@ -368,10 +393,12 @@ if (config.url) {
|
|
|
368
393
|
mqtt.on('message', (topic, payload, msg) => {
|
|
369
394
|
_mqttMsgCount++;
|
|
370
395
|
|
|
371
|
-
//
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
396
|
+
// Sentinel detection: a non-retained message we publish to ourselves right
|
|
397
|
+
// after subscribing to #. When it arrives, all retained messages from the
|
|
398
|
+
// broker have already been delivered and stored.
|
|
399
|
+
if (!_started && _sentinelValue !== null && !msg.retain && topic === config.name + '/she-sentinel' && payload.toString() === _sentinelValue) {
|
|
400
|
+
startOnce('mqtt: retained state ready, starting scripts');
|
|
401
|
+
return; // sentinel is internal — don’t process further
|
|
375
402
|
}
|
|
376
403
|
|
|
377
404
|
if (shedb.handleMqttMessage(topic, payload)) return;
|
package/src/lib/shedb-worker.js
CHANGED
|
@@ -144,7 +144,7 @@ parentPort.on('message', (msg) => {
|
|
|
144
144
|
|
|
145
145
|
case 'delQuery':
|
|
146
146
|
delete queries[msg.id];
|
|
147
|
-
queue
|
|
147
|
+
queue.delete(msg.id);
|
|
148
148
|
parentPort.postMessage({ type: 'view', id: msg.id, deleted: true });
|
|
149
149
|
break;
|
|
150
150
|
}
|
package/src/web/log-ws.js
CHANGED
|
@@ -4,6 +4,17 @@ const { WebSocketServer } = require('ws');
|
|
|
4
4
|
|
|
5
5
|
let _wss = null;
|
|
6
6
|
const _clients = new Set();
|
|
7
|
+
let _welcomeProvider = null;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Register a function that returns a welcome message to send to each new
|
|
11
|
+
* WebSocket client immediately after it connects. Useful for pushing
|
|
12
|
+
* current state (e.g. mqtt:status) without waiting for the next broadcast.
|
|
13
|
+
* @param {() => object} fn
|
|
14
|
+
*/
|
|
15
|
+
function setWelcomeProvider(fn) {
|
|
16
|
+
_welcomeProvider = fn;
|
|
17
|
+
}
|
|
7
18
|
|
|
8
19
|
// Ring buffer of recent log entries for the AI tool get_script_logs
|
|
9
20
|
const _logBuffer = [];
|
|
@@ -31,6 +42,11 @@ function attachWss(httpServer, authCheck = () => true) {
|
|
|
31
42
|
_clients.add(ws);
|
|
32
43
|
ws.on('close', () => _clients.delete(ws));
|
|
33
44
|
ws.on('error', () => _clients.delete(ws));
|
|
45
|
+
// Send current state to this new client immediately
|
|
46
|
+
if (_welcomeProvider) {
|
|
47
|
+
const welcome = _welcomeProvider();
|
|
48
|
+
if (welcome) ws.send(JSON.stringify(welcome));
|
|
49
|
+
}
|
|
34
50
|
});
|
|
35
51
|
|
|
36
52
|
// Keepalive ping every 30 s
|
|
@@ -90,4 +106,4 @@ function closeWss() {
|
|
|
90
106
|
});
|
|
91
107
|
}
|
|
92
108
|
|
|
93
|
-
module.exports = { attachWss, broadcast, broadcastLog, closeWss, getLogBuffer };
|
|
109
|
+
module.exports = { attachWss, broadcast, broadcastLog, closeWss, getLogBuffer, setWelcomeProvider };
|