smart-home-engine 1.0.6 → 1.0.9

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-BW2J83t5.js";import{t as I}from"./index-BQ_d2xRZ.js";/*!-----------------------------------------------------------------------------
1
+ import{m as O}from"./monaco-langs-BW2J83t5.js";import{t as I}from"./index-BYavlZcf.js";/*!-----------------------------------------------------------------------------
2
2
  * Copyright (c) Microsoft Corporation. All rights reserved.
3
3
  * Version: 0.52.2(404545bded1df6ffa41ea0af4e8ddb219018c6c1)
4
4
  * Released under the MIT license
@@ -162,10 +162,10 @@
162
162
  }
163
163
  })();
164
164
  </script>
165
- <script type="module" crossorigin src="/assets/index-BQ_d2xRZ.js"></script>
165
+ <script type="module" crossorigin src="/assets/index-BYavlZcf.js"></script>
166
166
  <link rel="modulepreload" crossorigin href="/assets/monaco-langs-BW2J83t5.js">
167
167
  <link rel="stylesheet" crossorigin href="/assets/monaco-langs-DyX1CsEw.css">
168
- <link rel="stylesheet" crossorigin href="/assets/index-hs5iZLtu.css">
168
+ <link rel="stylesheet" crossorigin href="/assets/index-B_L247qc.css">
169
169
  </head>
170
170
  <body>
171
171
  <div id="app"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "smart-home-engine",
3
- "version": "1.0.6",
3
+ "version": "1.0.9",
4
4
  "description": "Node.js based script runner for use in MQTT based Smart Home environments",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
package/src/config.js CHANGED
@@ -61,6 +61,11 @@ const config = require('yargs')
61
61
  timezone: '',
62
62
  mqttVersion: '',
63
63
  })
64
+ .option('sentinel-timeout', {
65
+ describe: 'ms to wait for the retained-state sentinel after connecting to MQTT (default: 5000)',
66
+ default: 5000,
67
+ type: 'number',
68
+ })
64
69
  .option('install', {
65
70
  describe: 'create system user and install systemd service, then exit (run as root)',
66
71
  type: 'boolean',
package/src/index.js CHANGED
@@ -253,7 +253,7 @@ let _startupTimeout = null; // fires if broker never connects
253
253
  let _sentinelTimeout = null; // fires if sentinel never arrives after connecting
254
254
  let _sentinelValue = null; // unique value for this boot's sentinel
255
255
  const _STARTUP_TIMEOUT_MS = 10000; // ms to wait for broker before starting anyway
256
- const _SENTINEL_TIMEOUT_MS = 5000; // ms to wait for sentinel after connecting
256
+ const _SENTINEL_TIMEOUT_MS = config.sentinelTimeout; // ms to wait for sentinel after connecting
257
257
 
258
258
  function startOnce(reason) {
259
259
  if (_started) return;
@@ -267,7 +267,7 @@ function startOnce(reason) {
267
267
  _sentinelTimeout = null;
268
268
  }
269
269
  if (reason) log.info(reason);
270
- broadcast({ type: 'mqtt:status', ready: true });
270
+ broadcast({ type: 'mqtt:status', ready: true, connected });
271
271
  start();
272
272
  }
273
273
 
@@ -319,7 +319,7 @@ require('./web/server').setStatsProvider(() => {
319
319
  }
320
320
  return {
321
321
  scripts: Object.keys(scripts).length,
322
- runningScripts: Object.keys(scripts).map(f => makeLabel(f).slice(0, -1)),
322
+ runningScripts: Object.keys(scripts).map((f) => makeLabel(f).slice(0, -1)),
323
323
  topics,
324
324
  mqttMsgPerSec,
325
325
  matterEnabled: !!config.matterStorage,
@@ -334,19 +334,17 @@ require('./web/server').setStatsProvider(() => {
334
334
  };
335
335
  });
336
336
 
337
- // Inform newly-connected WebSocket clients of the current mqtt:status so the
338
- // UI shows the correct indicator even if the browser opened after the event fired.
339
- setWelcomeProvider(() => ({ type: 'mqtt:status', ready: _started }));
340
337
  // Push current script:running state so the UI green dots survive a browser reload.
341
- setWelcomeProvider(() =>
342
- Object.keys(scripts).map((f) => ({ type: 'script:running', path: makeLabel(f).slice(0, -1), running: true }))
343
- );
338
+ setWelcomeProvider(() => Object.keys(scripts).map((f) => ({ type: 'script:running', path: makeLabel(f).slice(0, -1), running: true })));
344
339
 
345
340
  if (!config.url) {
346
341
  log.warn('no MQTT broker URL configured — set "url" in ' + path.join(require('os').homedir(), '.she', 'config.json'));
347
342
  }
348
343
 
349
344
  if (config.url) {
345
+ // Inform newly-connected WS clients of the current MQTT broker connection state.
346
+ setWelcomeProvider(() => ({ type: 'mqtt:status', ready: _started, connected }));
347
+
350
348
  const _mqttOpts = { will: { topic: config.name + '/connected', payload: '0', retain: true } };
351
349
  if (config.mqttUsername) _mqttOpts.username = config.mqttUsername;
352
350
  if (config.mqttPassword) _mqttOpts.password = config.mqttPassword;
@@ -380,13 +378,16 @@ if (config.url) {
380
378
  _sentinelValue = String(Date.now());
381
379
  mqtt.publish(config.name + '/she-sentinel', _sentinelValue, { retain: false });
382
380
  log.debug('mqtt: waiting for retained-state sentinel');
383
- broadcast({ type: 'mqtt:status', ready: false });
381
+ broadcast({ type: 'mqtt:status', ready: false, connected: true });
384
382
 
385
383
  // Fallback: if sentinel never arrives (e.g. abnormal broker behaviour)
386
384
  _sentinelTimeout = setTimeout(() => {
387
385
  log.warn('mqtt sentinel timeout — starting scripts without full retained state');
388
386
  startOnce();
389
387
  }, _SENTINEL_TIMEOUT_MS);
388
+ } else {
389
+ // Reconnect after a previous disconnect: scripts are already running.
390
+ broadcast({ type: 'mqtt:status', ready: true, connected: true });
390
391
  }
391
392
  });
392
393
 
@@ -396,6 +397,7 @@ if (config.url) {
396
397
  log.info('mqtt closed ' + config.url);
397
398
  mqttEventCallbacks.filter((c) => c.event === 'disconnect').forEach((c) => c.callback());
398
399
  }
400
+ broadcast({ type: 'mqtt:status', ready: _started, connected: false });
399
401
  });
400
402
 
401
403
  mqtt.on('error', () => {
@@ -11,7 +11,7 @@ const DEFAULT_CONFIG_PATH = getConfigPath();
11
11
  * Config keys that are consumed only by the frontend (no daemon restart needed).
12
12
  * All other keys require a daemon restart when changed.
13
13
  */
14
- const FRONTEND_ONLY_KEYS = new Set(['gitAutoCommit', 'gitAutoPush']);
14
+ const FRONTEND_ONLY_KEYS = new Set(['gitAutoCommit', 'gitAutoPush', 'pinnedPackages']);
15
15
 
16
16
  const router = express.Router();
17
17
 
@@ -10,7 +10,17 @@ Scripts run in a sandboxed VM. The `she` object is injected automatically.
10
10
  ### MQTT
11
11
  ```
12
12
  she.mqtt.sub(topic, [opts], cb) Subscribe; wildcards: + (1 level) # (multi)
13
- opts.change: true = only fire when value changes
13
+ opts.change: only fire when value changes
14
+ opts.retain: also fire for retained msgs on connect and script start
15
+ opts.shift: delay execution by N seconds
16
+ opts.random: additional random delay in seconds
17
+ opts.condition: fn(val) or JS string — skip cb if falsy
18
+ cb(topic, val, obj, objPrev, msg)
19
+ topic: the topic that fired
20
+ val: new value (parsed)
21
+ obj: full new state { val, ts, lc }
22
+ objPrev: previous state object
23
+ msg: raw MQTT.js message object
14
24
  she.mqtt.pub(topic, payload, [opts]) Publish; opts: { qos, retain }
15
25
  she.mqtt.get(topic) Current retained value (sync)
16
26
  she.mqtt.link(src, target, [fn]) Forward src changes to target; optional transform