smart-home-engine 1.20.0 → 1.20.1
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-nf1nG74s.css → index-CjRDTePT.css} +1 -1
- package/dist/web/assets/index-DxR31sxM.js +234 -0
- package/dist/web/assets/{tsMode-Dbzvu1EX.js → tsMode-BNcOSQVq.js} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/src/influx.js +16 -3
- package/src/sandbox/influx-sandbox.js +35 -16
- package/dist/web/assets/index-BUev42o8.js +0 -234
|
@@ -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-DxR31sxM.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,10 +172,10 @@
|
|
|
172
172
|
}
|
|
173
173
|
})();
|
|
174
174
|
</script>
|
|
175
|
-
<script type="module" crossorigin src="/assets/index-
|
|
175
|
+
<script type="module" crossorigin src="/assets/index-DxR31sxM.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
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
178
|
+
<link rel="stylesheet" crossorigin href="/assets/index-CjRDTePT.css">
|
|
179
179
|
</head>
|
|
180
180
|
<body>
|
|
181
181
|
<div id="app"></div>
|
package/package.json
CHANGED
package/src/influx.js
CHANGED
|
@@ -6,6 +6,10 @@ let _mode = null; // 'v1' | 'v2' | null
|
|
|
6
6
|
|
|
7
7
|
const V1_TIMEOUT_MS = 10000;
|
|
8
8
|
|
|
9
|
+
function v1Timeout() {
|
|
10
|
+
return Number(_opts.timeout) || V1_TIMEOUT_MS;
|
|
11
|
+
}
|
|
12
|
+
|
|
9
13
|
/**
|
|
10
14
|
* Initialise the InfluxDB client. Called from index.js when config.influx is set.
|
|
11
15
|
*
|
|
@@ -119,7 +123,7 @@ async function v1Write(lines) {
|
|
|
119
123
|
method: 'POST',
|
|
120
124
|
headers: v1Headers(),
|
|
121
125
|
body: lines,
|
|
122
|
-
signal: AbortSignal.timeout(
|
|
126
|
+
signal: AbortSignal.timeout(v1Timeout()),
|
|
123
127
|
});
|
|
124
128
|
if (!res.ok) {
|
|
125
129
|
const body = await res.text().catch(() => '');
|
|
@@ -139,7 +143,7 @@ async function v1Query(q) {
|
|
|
139
143
|
const params = new URLSearchParams({ db: _opts.database, q, epoch: 'ms' });
|
|
140
144
|
const res = await fetch(`${_opts.url.replace(/\/$/, '')}/query?${params}`, {
|
|
141
145
|
headers: v1Headers(),
|
|
142
|
-
signal: AbortSignal.timeout(
|
|
146
|
+
signal: AbortSignal.timeout(v1Timeout()),
|
|
143
147
|
});
|
|
144
148
|
if (!res.ok) {
|
|
145
149
|
const body = await res.text().catch(() => '');
|
|
@@ -170,4 +174,13 @@ function escapeQL(s) {
|
|
|
170
174
|
return String(s).replace(/\\/g, '\\\\').replace(/'/g, "\\'");
|
|
171
175
|
}
|
|
172
176
|
|
|
173
|
-
|
|
177
|
+
/**
|
|
178
|
+
* Escape a string for use inside an InfluxQL double-quoted identifier
|
|
179
|
+
* (measurement/tag/field name).
|
|
180
|
+
* @param {string} s
|
|
181
|
+
*/
|
|
182
|
+
function escapeIdent(s) {
|
|
183
|
+
return String(s).replace(/"/g, '\\"');
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
module.exports = { init, getClient, getOpts, getMode, buildLine, v1Write, v1Query, escapeQL, escapeIdent };
|
|
@@ -35,6 +35,18 @@ function v1RowVal(row) {
|
|
|
35
35
|
return null;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Map v1 result rows to the { ts, val } shape, newest-trimmed to n (LIMIT
|
|
40
|
+
* applies per series in InfluxQL, so multi-series results must be merged and
|
|
41
|
+
* re-trimmed), sorted oldest-first.
|
|
42
|
+
* @param {object[]} rows
|
|
43
|
+
* @param {number} [n]
|
|
44
|
+
*/
|
|
45
|
+
function v1Points(rows, n) {
|
|
46
|
+
const pts = rows.map((r) => ({ ts: r.time, val: v1RowVal(r) })).sort((a, b) => b.ts - a.ts);
|
|
47
|
+
return (n ? pts.slice(0, Number(n)) : pts).reverse();
|
|
48
|
+
}
|
|
49
|
+
|
|
38
50
|
module.exports = function (she) {
|
|
39
51
|
she.influx = {
|
|
40
52
|
/**
|
|
@@ -101,10 +113,12 @@ module.exports = function (she) {
|
|
|
101
113
|
},
|
|
102
114
|
|
|
103
115
|
/**
|
|
104
|
-
* Return the last N recorded values for an MQTT topic.
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
116
|
+
* Return the last N recorded values for an MQTT topic (last 30 days).
|
|
117
|
+
* v2: assumes points carry a "topic" tag, value from "_value".
|
|
118
|
+
* v1: tries a measurement named like the topic first (influx4mqtt-style
|
|
119
|
+
* schema), then falls back to a "topic" tag scan; value from the
|
|
120
|
+
* "value" field, falling back to the first data column.
|
|
121
|
+
* Results are sorted oldest-first.
|
|
108
122
|
* @param {string} topic
|
|
109
123
|
* @param {number} n
|
|
110
124
|
* @returns {Promise<{ ts: number, val: any }[]>}
|
|
@@ -113,16 +127,16 @@ module.exports = function (she) {
|
|
|
113
127
|
const mode = influx.getMode();
|
|
114
128
|
if (!mode) return Promise.resolve([]);
|
|
115
129
|
if (mode === 'v1') {
|
|
116
|
-
//
|
|
117
|
-
//
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
);
|
|
130
|
+
// Fast path: measurement named like the topic (the common
|
|
131
|
+
// mqtt-to-influx v1 schema, e.g. influx4mqtt). Fallback: points
|
|
132
|
+
// stored with a "topic" tag — that needs a scan across all
|
|
133
|
+
// measurements, so keep it time-bounded (30d, like the v2 path).
|
|
134
|
+
const mQl = `SELECT * FROM "${influx.escapeIdent(topic)}" WHERE time >= now() - 30d ORDER BY time DESC LIMIT ${Number(n)}`;
|
|
135
|
+
return influx.v1Query(mQl).then((rows) => {
|
|
136
|
+
if (rows.length) return v1Points(rows, n);
|
|
137
|
+
const tagQl = `SELECT * FROM /.*/ WHERE "topic" = '${influx.escapeQL(topic)}' AND time >= now() - 30d ORDER BY time DESC LIMIT ${Number(n)}`;
|
|
138
|
+
return influx.v1Query(tagQl).then((tagRows) => v1Points(tagRows, n));
|
|
139
|
+
});
|
|
126
140
|
}
|
|
127
141
|
const opts = influx.getOpts();
|
|
128
142
|
const safeTopic = topic.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
@@ -143,8 +157,13 @@ module.exports = function (she) {
|
|
|
143
157
|
if (mode === 'v1') {
|
|
144
158
|
const fromMs = new Date(from).getTime();
|
|
145
159
|
const toMs = new Date(to).getTime();
|
|
146
|
-
const
|
|
147
|
-
|
|
160
|
+
const bounds = `time >= ${fromMs}ms AND time <= ${toMs}ms`;
|
|
161
|
+
const mQl = `SELECT * FROM "${influx.escapeIdent(topic)}" WHERE ${bounds}`;
|
|
162
|
+
return influx.v1Query(mQl).then((rows) => {
|
|
163
|
+
if (rows.length) return v1Points(rows);
|
|
164
|
+
const tagQl = `SELECT * FROM /.*/ WHERE "topic" = '${influx.escapeQL(topic)}' AND ${bounds}`;
|
|
165
|
+
return influx.v1Query(tagQl).then((tagRows) => v1Points(tagRows));
|
|
166
|
+
});
|
|
148
167
|
}
|
|
149
168
|
const opts = influx.getOpts();
|
|
150
169
|
const safeTopic = topic.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|