smart-home-engine 1.17.1 → 1.18.0
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.
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{m as O}from"./monaco-langs-Dt8a9eeo.js";import{t as I}from"./index-
|
|
1
|
+
import{m as O}from"./monaco-langs-Dt8a9eeo.js";import{t as I}from"./index-CEmLX_uw.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
|
@@ -172,7 +172,7 @@
|
|
|
172
172
|
}
|
|
173
173
|
})();
|
|
174
174
|
</script>
|
|
175
|
-
<script type="module" crossorigin src="/assets/index-
|
|
175
|
+
<script type="module" crossorigin src="/assets/index-CEmLX_uw.js"></script>
|
|
176
176
|
<link rel="modulepreload" crossorigin href="/assets/monaco-langs-Dt8a9eeo.js">
|
|
177
177
|
<link rel="stylesheet" crossorigin href="/assets/monaco-langs-DyX1CsEw.css">
|
|
178
178
|
<link rel="stylesheet" crossorigin href="/assets/index-BvKmwc2a.css">
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -192,6 +192,18 @@ const scriptTimers = new Map(); // scriptFile → Set<timer id>
|
|
|
192
192
|
|
|
193
193
|
const _global = {};
|
|
194
194
|
|
|
195
|
+
// ── Event-loop heartbeat ─────────────────────────────────────────────────────
|
|
196
|
+
let _blockingScript = null;
|
|
197
|
+
|
|
198
|
+
/** Wrap a user callback dispatch so the heartbeat can identify the active script. */
|
|
199
|
+
function _dispatch(label, fn) {
|
|
200
|
+
_blockingScript = label;
|
|
201
|
+
fn();
|
|
202
|
+
setImmediate(() => {
|
|
203
|
+
_blockingScript = null;
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
195
207
|
// Sun scheduling
|
|
196
208
|
|
|
197
209
|
const SUNCALC_EVENTS = new Set([
|
|
@@ -269,10 +281,10 @@ function sunScheduleEvent(obj, shift) {
|
|
|
269
281
|
// Event is less than 1s in the future or already in the past
|
|
270
282
|
// (options.random may have shifted us further to the past)
|
|
271
283
|
// call the callback immediately!
|
|
272
|
-
obj.domain.bind(obj.callback)
|
|
284
|
+
_dispatch(obj._script, obj.domain.bind(obj.callback));
|
|
273
285
|
} else {
|
|
274
286
|
// Schedule the event and track the job so it can be cancelled on script unload
|
|
275
|
-
obj._job = scheduler.scheduleJob(event, obj.domain.bind(obj.callback));
|
|
287
|
+
obj._job = scheduler.scheduleJob(event, () => _dispatch(obj._script, obj.domain.bind(obj.callback)));
|
|
276
288
|
}
|
|
277
289
|
}
|
|
278
290
|
}
|
|
@@ -372,6 +384,26 @@ require('./web/server').setStatsProvider(() => {
|
|
|
372
384
|
// Push current script:running state so the UI green dots survive a browser reload.
|
|
373
385
|
setWelcomeProvider(() => Object.keys(scripts).map((f) => ({ type: 'script:running', path: makeLabel(f).slice(0, -1), running: true })));
|
|
374
386
|
|
|
387
|
+
if (config.heartbeat?.enabled) {
|
|
388
|
+
const _hbInterval = typeof config.heartbeat.interval === 'number' ? config.heartbeat.interval : 50;
|
|
389
|
+
const _hbThreshold = typeof config.heartbeat.threshold === 'number' ? config.heartbeat.threshold : 300;
|
|
390
|
+
let _lastBeat = Date.now();
|
|
391
|
+
const _hbTimer = setInterval(() => {
|
|
392
|
+
const now = Date.now();
|
|
393
|
+
const lag = now - _lastBeat - _hbInterval;
|
|
394
|
+
_lastBeat = now;
|
|
395
|
+
if (lag > _hbThreshold) {
|
|
396
|
+
const label = _blockingScript ?? 'unknown';
|
|
397
|
+
if (lag > 2000) {
|
|
398
|
+
log.warn(`event loop blocked ${lag}ms — script: ${label}`);
|
|
399
|
+
} else {
|
|
400
|
+
log.warn(`event loop lag ${lag}ms — last active script: ${label}`);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}, _hbInterval);
|
|
404
|
+
_hbTimer.unref();
|
|
405
|
+
}
|
|
406
|
+
|
|
375
407
|
if (!config.url) {
|
|
376
408
|
log.warn('no MQTT broker URL configured — set "url" in ' + path.join(require('os').homedir(), '.she', 'config.json'));
|
|
377
409
|
}
|
|
@@ -400,7 +432,7 @@ if (config.url) {
|
|
|
400
432
|
log.debug('mqtt subscribe #');
|
|
401
433
|
mqtt.subscribe('#');
|
|
402
434
|
mqtt.subscribe('$SYS/#');
|
|
403
|
-
mqttEventCallbacks.filter((c) => c.event === 'connect').forEach((c) => c.callback());
|
|
435
|
+
mqttEventCallbacks.filter((c) => c.event === 'connect').forEach((c) => _dispatch(c._script, () => c.callback()));
|
|
404
436
|
|
|
405
437
|
if (!_started) {
|
|
406
438
|
// Cancel the “broker not connecting” startup timeout — we’re connected.
|
|
@@ -435,7 +467,7 @@ if (config.url) {
|
|
|
435
467
|
if (connected) {
|
|
436
468
|
connected = false;
|
|
437
469
|
log.info('mqtt closed ' + config.url);
|
|
438
|
-
mqttEventCallbacks.filter((c) => c.event === 'disconnect').forEach((c) => c.callback());
|
|
470
|
+
mqttEventCallbacks.filter((c) => c.event === 'disconnect').forEach((c) => _dispatch(c._script, () => c.callback()));
|
|
439
471
|
}
|
|
440
472
|
broadcast({ type: 'mqtt:status', ready: _started, connected: false });
|
|
441
473
|
});
|
|
@@ -604,7 +636,7 @@ function stateChange(topic, state, oldState, msg) {
|
|
|
604
636
|
* @param {object} objPrev - previous state - the whole state object
|
|
605
637
|
* @param {object} msg - the mqtt message as received from MQTT.js
|
|
606
638
|
*/
|
|
607
|
-
subs.callback(topic, state.val, state, oldState, msg);
|
|
639
|
+
_dispatch(subs._script, () => subs.callback(topic, state.val, state, oldState, msg));
|
|
608
640
|
}, delay);
|
|
609
641
|
}
|
|
610
642
|
});
|
|
@@ -844,12 +876,12 @@ function runScript(script, name, _origin) {
|
|
|
844
876
|
scheduler.scheduleJob(pattern, () => {
|
|
845
877
|
// Track the random-delay timer so it is cancelled on unload
|
|
846
878
|
// if the job fires in the same tick as the script is reloaded.
|
|
847
|
-
const id = setTimeout(scriptDomain.bind(callback), (parseFloat(options.random) || 0) * 1000 * Math.random());
|
|
879
|
+
const id = setTimeout(() => _dispatch(name, scriptDomain.bind(callback)), (parseFloat(options.random) || 0) * 1000 * Math.random());
|
|
848
880
|
_myTimers.add(id);
|
|
849
881
|
}),
|
|
850
882
|
);
|
|
851
883
|
} else {
|
|
852
|
-
_myJobs.push(scheduler.scheduleJob(pattern, scriptDomain.bind(callback)));
|
|
884
|
+
_myJobs.push(scheduler.scheduleJob(pattern, () => _dispatch(name, scriptDomain.bind(callback))));
|
|
853
885
|
}
|
|
854
886
|
},
|
|
855
887
|
|
|
@@ -969,7 +1001,7 @@ function runScript(script, name, _origin) {
|
|
|
969
1001
|
const varStoreKey = 'var::' + key.slice(5);
|
|
970
1002
|
const boundCb = scriptDomain.bind(callback);
|
|
971
1003
|
const varHandler = (changedKey, val, obj, prevObj) => {
|
|
972
|
-
if (changedKey === varStoreKey) boundCb(val, obj, prevObj);
|
|
1004
|
+
if (changedKey === varStoreKey) _dispatch(name, () => boundCb(val, obj, prevObj));
|
|
973
1005
|
};
|
|
974
1006
|
store.on('change', varHandler);
|
|
975
1007
|
varSubscriptions.push({ key: varStoreKey, handler: varHandler, _script: name });
|