@victronenergy/mfd-modules 9.3.0 → 9.5.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.
- package/dist/src/Modules/Mqtt/Mqtt.store.d.ts +57 -2
- package/dist/src/Modules/Mqtt/Mqtt.store.d.ts.map +1 -1
- package/dist/src/Modules/Mqtt/Mqtt.store.js +118 -121
- package/dist/src/Modules/Mqtt/Mqtt.store.js.map +1 -1
- package/dist/src/Modules/SwitchableOutputs/SwitchableOutput.provider.d.ts +3 -3
- package/dist/src/Modules/SwitchableOutputs/SwitchableOutput.provider.d.ts.map +1 -1
- package/dist/src/Modules/SwitchableOutputs/SwitchableOutput.provider.js +1 -1
- package/dist/src/Modules/SwitchableOutputs/SwitchableOutput.provider.js.map +1 -1
- package/dist/src/Modules/SwitchableOutputs/SwitchableOutputs.provider.d.ts.map +1 -1
- package/dist/src/Modules/SwitchableOutputs/SwitchableOutputs.provider.js +35 -55
- package/dist/src/Modules/SwitchableOutputs/SwitchableOutputs.provider.js.map +1 -1
- package/dist/src/Modules/SwitchableOutputs/SwitchableOutputs.store.d.ts +0 -4
- package/dist/src/Modules/SwitchableOutputs/SwitchableOutputs.store.d.ts.map +1 -1
- package/dist/src/Modules/SwitchableOutputs/SwitchableOutputs.store.js +1 -13
- package/dist/src/Modules/SwitchableOutputs/SwitchableOutputs.store.js.map +1 -1
- package/dist/src/Modules/SwitchableOutputs/SwitchingDevice.provider.d.ts +1 -0
- package/dist/src/Modules/SwitchableOutputs/SwitchingDevice.provider.d.ts.map +1 -1
- package/dist/src/Modules/SwitchableOutputs/SwitchingDevice.provider.js +34 -1
- package/dist/src/Modules/SwitchableOutputs/SwitchingDevice.provider.js.map +1 -1
- package/dist/src/Modules/SwitchableOutputs/SwitchingDevices.store.d.ts +4 -4
- package/dist/src/Modules/SwitchableOutputs/SwitchingDevices.store.d.ts.map +1 -1
- package/dist/src/Modules/SwitchableOutputs/SwitchingDevices.store.js.map +1 -1
- package/package.json +1 -1
|
@@ -12,10 +12,65 @@ export declare class MqttStore {
|
|
|
12
12
|
keepAliveHandlerRef: any;
|
|
13
13
|
queueWorker: any;
|
|
14
14
|
meanQueueWorkerPassDuration: number;
|
|
15
|
+
urgentTopicPrefixes: string[];
|
|
16
|
+
/**
|
|
17
|
+
* Returns the current cached message for a given MQTT topic.
|
|
18
|
+
*
|
|
19
|
+
* React Components using this method will re-render when their specific
|
|
20
|
+
* topic's message changes.
|
|
21
|
+
*
|
|
22
|
+
* Using comparer.identity will trigger the re-renders any time
|
|
23
|
+
* a message arrives for the given topic. We rely on the fact
|
|
24
|
+
* that MQTT will only re-send a message when the value changes,
|
|
25
|
+
* or on a full keep alive.
|
|
26
|
+
*
|
|
27
|
+
* Note: Receiving the same message for a given topic will cause re-renders,
|
|
28
|
+
* as we do not check structural identity of the message.
|
|
29
|
+
*
|
|
30
|
+
* @param topic - The MQTT topic to retrieve the message for
|
|
31
|
+
* @returns The message object for the topic, or undefined if topic is not provided or not found
|
|
32
|
+
*/
|
|
15
33
|
messageFromTopic: (topic?: string) => MqttMessage;
|
|
34
|
+
/**
|
|
35
|
+
* Returns the current cached messages for a given set of MQTT topics.
|
|
36
|
+
*
|
|
37
|
+
* This is a memoized computed function - each set of topics has its own cached value.
|
|
38
|
+
*
|
|
39
|
+
* React Components using this method will re-render when
|
|
40
|
+
* any of the messages for specified topics change.
|
|
41
|
+
*
|
|
42
|
+
* Using comparer.identity will trigger the re-renders any time
|
|
43
|
+
* a message arrives for any of the specified topics. We rely on the fact
|
|
44
|
+
* that MQTT will only re-send a message when the value changes,
|
|
45
|
+
* or on a full keep alive.
|
|
46
|
+
|
|
47
|
+
* Note: Receiving the same message for a given topic will cause re-renders,
|
|
48
|
+
* as we do not check structural identity of the message.
|
|
49
|
+
*
|
|
50
|
+
* @param topics - The MQTT topics to retrieve the messages for
|
|
51
|
+
* @returns The messages objects for the given topics, or empty dictionary if topics not found
|
|
52
|
+
*/
|
|
16
53
|
messagesByTopics: (topics?: Topics) => {
|
|
17
54
|
[key: string]: MqttMessage | MqttMessage[];
|
|
18
55
|
};
|
|
56
|
+
/**
|
|
57
|
+
* Returns the current cached messages for MQTT topics specified via regex.
|
|
58
|
+
*
|
|
59
|
+
* React Components using this method will re-render when
|
|
60
|
+
* values of any of the matched topics change. The components also re-render
|
|
61
|
+
* when new MQTT topics are received and match needs to be checked.
|
|
62
|
+
*
|
|
63
|
+
* Using comparer.identity will trigger the re-renders any time
|
|
64
|
+
* a message arrives for any of the matched topics. We rely on the fact
|
|
65
|
+
* that MQTT will only re-send a message when the value changes,
|
|
66
|
+
* or on a full keep alive.
|
|
67
|
+
*
|
|
68
|
+
* Note: Receiving the same message for a given topic will cause re-renders,
|
|
69
|
+
* as we do not check structural identity of the message.
|
|
70
|
+
*
|
|
71
|
+
* @param wildcard - The MQTT wildcard to retrieve the message for
|
|
72
|
+
* @returns The messages objects for the given topics, or empty dictionary if topics not found
|
|
73
|
+
*/
|
|
19
74
|
messagesByWildcard: (wildcard?: string) => any;
|
|
20
75
|
constructor();
|
|
21
76
|
get isConnected(): boolean;
|
|
@@ -23,8 +78,8 @@ export declare class MqttStore {
|
|
|
23
78
|
clearSubscribedTopics(): void;
|
|
24
79
|
addMessage: (topic: string, message: {
|
|
25
80
|
value: string | null;
|
|
26
|
-
}) =>
|
|
27
|
-
addMessagesFromQueue: () =>
|
|
81
|
+
}) => void;
|
|
82
|
+
addMessagesFromQueue: () => void;
|
|
28
83
|
scheduleNextQueueWorkerPass: (timeout: number) => void;
|
|
29
84
|
setupQueueWorker: () => void;
|
|
30
85
|
removeQueueWorker: () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Mqtt.store.d.ts","sourceRoot":"/","sources":["src/Modules/Mqtt/Mqtt.store.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,qBAAqB,EAAE,UAAU,EAAC,MAAM,MAAM,CAAA;AACtD,OAAO,EAAC,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAU,MAAM,EAAC,MAAM,SAAS,CAAA;AAQ3E,qBAAa,SAAS;IAClB,MAAM,CAAC,EAAE,UAAU,GAAG,IAAI,CAAA;IAC1B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAA;IAC/B,MAAM,EAAE,MAAM,CAAoB;IAClC,QAAQ,EAAE,YAAY,CAAK;IAC3B,YAAY,EAAE,YAAY,CAAK;IAC/B,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAoB;IACjD,QAAQ,EAAE,QAAQ,CAAA;IAClB,QAAQ,EAAE,MAAM,CAA0C;IAC1D,mBAAmB,EAAE,GAAG,CAAA;IACxB,WAAW,EAAE,GAAG,CAAA;IAChB,2BAA2B,EAAE,MAAM,CAAI;
|
|
1
|
+
{"version":3,"file":"Mqtt.store.d.ts","sourceRoot":"/","sources":["src/Modules/Mqtt/Mqtt.store.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,qBAAqB,EAAE,UAAU,EAAC,MAAM,MAAM,CAAA;AACtD,OAAO,EAAC,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAU,MAAM,EAAC,MAAM,SAAS,CAAA;AAQ3E,qBAAa,SAAS;IAClB,MAAM,CAAC,EAAE,UAAU,GAAG,IAAI,CAAA;IAC1B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAA;IAC/B,MAAM,EAAE,MAAM,CAAoB;IAClC,QAAQ,EAAE,YAAY,CAAK;IAC3B,YAAY,EAAE,YAAY,CAAK;IAC/B,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAoB;IACjD,QAAQ,EAAE,QAAQ,CAAA;IAClB,QAAQ,EAAE,MAAM,CAA0C;IAC1D,mBAAmB,EAAE,GAAG,CAAA;IACxB,WAAW,EAAE,GAAG,CAAA;IAChB,2BAA2B,EAAE,MAAM,CAAI;IACvC,mBAAmB,EAAE,MAAM,EAAE,CAAK;IAElC;;;;;;;;;;;;;;;;QAgBI;IACJ,gBAAgB,WAAuB,MAAM,iBAIyB;IAEtE;;;;;;;;;;;;;;;;;;QAkBI;IACJ,gBAAgB,YAAwB,MAAM;;MAoBwB;IAEtE;;;;;;;;;;;;;;;;;QAiBI;IACJ,kBAAkB,cAA0B,MAAM,SAiBsB;;IAmBxE,IAAI,WAAW,YAEd;IAED,gBAAgB,GAAI,QAAQ,MAAM,UAmBjC;IAED,qBAAqB;IAMrB,UAAU,GAAI,OAAO,MAAM,EAAE,SAAS;QAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,UAW7D;IAED,oBAAoB,aAOnB;IAED,2BAA2B,GAAI,SAAS,MAAM,UAW7C;IAED,gBAAgB,aAKf;IAED,iBAAiB,aAKhB;IAED,WAAW,GAAI,UAAU,MAAM,UAK9B;IAED,SAAS,CAAC,MAAM,EAAE,MAAM;IAIxB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO;IAIvC,IAAI,GACA,UAAU,MAAM,EAChB,MAAM,MAAM,YAAc,EAC1B,MAAM,MAAM,GAAG,IAAI,EACnB,OAAM,MAAyB,EAC/B,SAAQ,OAAe,EACvB,WAAW,MAAM,UAkGpB;IAED,oBAAoB,aA4BnB;IAED,uBAAuB,aAStB;IAED,iBAAiB,aAQhB;IAED,mBAAmB,aAMlB;IAED,mBAAmB,aAMlB;IAED,OAAO,GAAI,OAAO,MAAM,EAAE,MAAM,MAAM,GAAG,MAAM,EAAE,UAAU,qBAAqB,UAS/E;CACJ;AA2BD,wBAAgB,OAAO,cAEtB"}
|
|
@@ -1,39 +1,3 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
11
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
12
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
13
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
14
|
-
function step(op) {
|
|
15
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
16
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
17
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
18
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
19
|
-
switch (op[0]) {
|
|
20
|
-
case 0: case 1: t = op; break;
|
|
21
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
22
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
23
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
24
|
-
default:
|
|
25
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
26
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
27
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
28
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
29
|
-
if (t[2]) _.ops.pop();
|
|
30
|
-
_.trys.pop(); continue;
|
|
31
|
-
}
|
|
32
|
-
op = body.call(thisArg, _);
|
|
33
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
34
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
1
|
import { comparer, makeAutoObservable, runInAction } from "mobx";
|
|
38
2
|
import { computedFn } from "mobx-utils";
|
|
39
3
|
import * as mqtt from "mqtt";
|
|
@@ -112,10 +76,29 @@ var MqttStore = /** @class */ (function () {
|
|
|
112
76
|
writable: true,
|
|
113
77
|
value: 0
|
|
114
78
|
});
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
79
|
+
Object.defineProperty(this, "urgentTopicPrefixes", {
|
|
80
|
+
enumerable: true,
|
|
81
|
+
configurable: true,
|
|
82
|
+
writable: true,
|
|
83
|
+
value: []
|
|
84
|
+
});
|
|
85
|
+
/**
|
|
86
|
+
* Returns the current cached message for a given MQTT topic.
|
|
87
|
+
*
|
|
88
|
+
* React Components using this method will re-render when their specific
|
|
89
|
+
* topic's message changes.
|
|
90
|
+
*
|
|
91
|
+
* Using comparer.identity will trigger the re-renders any time
|
|
92
|
+
* a message arrives for the given topic. We rely on the fact
|
|
93
|
+
* that MQTT will only re-send a message when the value changes,
|
|
94
|
+
* or on a full keep alive.
|
|
95
|
+
*
|
|
96
|
+
* Note: Receiving the same message for a given topic will cause re-renders,
|
|
97
|
+
* as we do not check structural identity of the message.
|
|
98
|
+
*
|
|
99
|
+
* @param topic - The MQTT topic to retrieve the message for
|
|
100
|
+
* @returns The message object for the topic, or undefined if topic is not provided or not found
|
|
101
|
+
*/
|
|
119
102
|
Object.defineProperty(this, "messageFromTopic", {
|
|
120
103
|
enumerable: true,
|
|
121
104
|
configurable: true,
|
|
@@ -126,10 +109,25 @@ var MqttStore = /** @class */ (function () {
|
|
|
126
109
|
return topic ? _this.messages[topic] : undefined;
|
|
127
110
|
}, { name: "Mqtt.store.messageFromTopic", equals: comparer.identity })
|
|
128
111
|
});
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
112
|
+
/**
|
|
113
|
+
* Returns the current cached messages for a given set of MQTT topics.
|
|
114
|
+
*
|
|
115
|
+
* This is a memoized computed function - each set of topics has its own cached value.
|
|
116
|
+
*
|
|
117
|
+
* React Components using this method will re-render when
|
|
118
|
+
* any of the messages for specified topics change.
|
|
119
|
+
*
|
|
120
|
+
* Using comparer.identity will trigger the re-renders any time
|
|
121
|
+
* a message arrives for any of the specified topics. We rely on the fact
|
|
122
|
+
* that MQTT will only re-send a message when the value changes,
|
|
123
|
+
* or on a full keep alive.
|
|
124
|
+
|
|
125
|
+
* Note: Receiving the same message for a given topic will cause re-renders,
|
|
126
|
+
* as we do not check structural identity of the message.
|
|
127
|
+
*
|
|
128
|
+
* @param topics - The MQTT topics to retrieve the messages for
|
|
129
|
+
* @returns The messages objects for the given topics, or empty dictionary if topics not found
|
|
130
|
+
*/
|
|
133
131
|
Object.defineProperty(this, "messagesByTopics", {
|
|
134
132
|
enumerable: true,
|
|
135
133
|
configurable: true,
|
|
@@ -156,16 +154,24 @@ var MqttStore = /** @class */ (function () {
|
|
|
156
154
|
return result;
|
|
157
155
|
}, { name: "Mqtt.store.messagesByTopics", equals: comparer.identity })
|
|
158
156
|
});
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
157
|
+
/**
|
|
158
|
+
* Returns the current cached messages for MQTT topics specified via regex.
|
|
159
|
+
*
|
|
160
|
+
* React Components using this method will re-render when
|
|
161
|
+
* values of any of the matched topics change. The components also re-render
|
|
162
|
+
* when new MQTT topics are received and match needs to be checked.
|
|
163
|
+
*
|
|
164
|
+
* Using comparer.identity will trigger the re-renders any time
|
|
165
|
+
* a message arrives for any of the matched topics. We rely on the fact
|
|
166
|
+
* that MQTT will only re-send a message when the value changes,
|
|
167
|
+
* or on a full keep alive.
|
|
168
|
+
*
|
|
169
|
+
* Note: Receiving the same message for a given topic will cause re-renders,
|
|
170
|
+
* as we do not check structural identity of the message.
|
|
171
|
+
*
|
|
172
|
+
* @param wildcard - The MQTT wildcard to retrieve the message for
|
|
173
|
+
* @returns The messages objects for the given topics, or empty dictionary if topics not found
|
|
174
|
+
*/
|
|
169
175
|
Object.defineProperty(this, "messagesByWildcard", {
|
|
170
176
|
enumerable: true,
|
|
171
177
|
configurable: true,
|
|
@@ -216,52 +222,49 @@ var MqttStore = /** @class */ (function () {
|
|
|
216
222
|
enumerable: true,
|
|
217
223
|
configurable: true,
|
|
218
224
|
writable: true,
|
|
219
|
-
value: function (topic, message) {
|
|
220
|
-
var _a;
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
225
|
+
value: function (topic, message) {
|
|
226
|
+
var _a, _b;
|
|
227
|
+
// Logger.log(`DEBUG: addMessage: topic: ${topic}, urgentPrefixes: ${JSON.stringify(this.urgentTopicPrefixes)}`)
|
|
228
|
+
if (_this.urgentTopicPrefixes.some(function (prefix) { return topic.startsWith(prefix); })) {
|
|
229
|
+
Logger.log("DEBUG: addMessage: topic: ".concat(topic));
|
|
230
|
+
// NOTE: If topic starts with one of the urgent prefixes, deliver it immediately
|
|
231
|
+
_this.messages[topic] = (_a = message.value) !== null && _a !== void 0 ? _a : undefined;
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
// NOTE: Otherwise store message to the queue, and move messages from the queue
|
|
235
|
+
// NOTE: to the React components that are MobX observers periodically and in batches
|
|
236
|
+
_this.messageQueue[topic] = (_b = message.value) !== null && _b !== void 0 ? _b : undefined;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
226
239
|
});
|
|
227
240
|
Object.defineProperty(this, "addMessagesFromQueue", {
|
|
228
241
|
enumerable: true,
|
|
229
242
|
configurable: true,
|
|
230
243
|
writable: true,
|
|
231
|
-
value: function () {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
return [2 /*return*/];
|
|
240
|
-
});
|
|
241
|
-
}); }
|
|
244
|
+
value: function () {
|
|
245
|
+
if (Object.values(_this.messageQueue).length > 0) {
|
|
246
|
+
// Logger.log(`DEBUG: addMessagesFromQueue: in queue: ${JSON.stringify(Object.values(this.messageQueue).length)}`)
|
|
247
|
+
assign(_this.messages, _this.messageQueue);
|
|
248
|
+
// Logger.log(`DEBUG: addMessagesFromQueue: to process: ${JSON.stringify(Object.values(this.messages).length)}`)
|
|
249
|
+
_this.messageQueue = {};
|
|
250
|
+
}
|
|
251
|
+
}
|
|
242
252
|
});
|
|
243
253
|
Object.defineProperty(this, "scheduleNextQueueWorkerPass", {
|
|
244
254
|
enumerable: true,
|
|
245
255
|
configurable: true,
|
|
246
256
|
writable: true,
|
|
247
257
|
value: function (timeout) {
|
|
248
|
-
_this.queueWorker = setTimeout(function () {
|
|
249
|
-
var started
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
this.meanQueueWorkerPassDuration = addToMean(this.meanQueueWorkerPassDuration, 10, ended - started);
|
|
259
|
-
newTimeout = Math.max(1000, Math.min(this.meanQueueWorkerPassDuration * 50, 3000));
|
|
260
|
-
this.scheduleNextQueueWorkerPass(newTimeout);
|
|
261
|
-
return [2 /*return*/];
|
|
262
|
-
}
|
|
263
|
-
});
|
|
264
|
-
}); }, timeout);
|
|
258
|
+
_this.queueWorker = setTimeout(function () {
|
|
259
|
+
var started = performance.now();
|
|
260
|
+
_this.addMessagesFromQueue();
|
|
261
|
+
var ended = performance.now();
|
|
262
|
+
_this.meanQueueWorkerPassDuration = addToMean(_this.meanQueueWorkerPassDuration, 10, ended - started);
|
|
263
|
+
// Schedule next update after 1 - 3 seconds
|
|
264
|
+
// depending on how fast we were able to process the incoming messages
|
|
265
|
+
var newTimeout = Math.max(1000, Math.min(_this.meanQueueWorkerPassDuration * 50, 3000));
|
|
266
|
+
_this.scheduleNextQueueWorkerPass(newTimeout);
|
|
267
|
+
}, timeout);
|
|
265
268
|
}
|
|
266
269
|
});
|
|
267
270
|
Object.defineProperty(this, "setupQueueWorker", {
|
|
@@ -291,6 +294,9 @@ var MqttStore = /** @class */ (function () {
|
|
|
291
294
|
writable: true,
|
|
292
295
|
value: function (portalId) {
|
|
293
296
|
_this.portalId = portalId;
|
|
297
|
+
_this.urgentTopicPrefixes = [
|
|
298
|
+
"N/".concat(portalId, "/switch/"),
|
|
299
|
+
];
|
|
294
300
|
}
|
|
295
301
|
});
|
|
296
302
|
Object.defineProperty(this, "boot", {
|
|
@@ -308,6 +314,7 @@ var MqttStore = /** @class */ (function () {
|
|
|
308
314
|
_this.client = undefined;
|
|
309
315
|
_this.portalId = undefined;
|
|
310
316
|
_this.topicsSubscribed = new Set();
|
|
317
|
+
_this.urgentTopicPrefixes = [];
|
|
311
318
|
}
|
|
312
319
|
var url;
|
|
313
320
|
if (remote) {
|
|
@@ -361,39 +368,27 @@ var MqttStore = /** @class */ (function () {
|
|
|
361
368
|
_this.setupKeepaliveTimer();
|
|
362
369
|
});
|
|
363
370
|
});
|
|
364
|
-
client.on("message", function (topic, message) {
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
// Logger.log(`DEBUG: Message received: ${topic} - ${message.toString()}`)
|
|
371
|
-
if (topic.endsWith("/system/0/Serial") && !this.portalId) {
|
|
372
|
-
portalId_1 = getMessageJson(message).value;
|
|
373
|
-
if (this.portalId !== portalId_1 && portalId_1 !== undefined) {
|
|
374
|
-
this.setPortalId(portalId_1);
|
|
375
|
-
}
|
|
376
|
-
runInAction(function () { return _this.subscribeToAllTopics(); });
|
|
377
|
-
}
|
|
378
|
-
if (!topic.endsWith("full_publish_completed")) return [3 /*break*/, 2];
|
|
379
|
-
uniqueId = getMessageJson(message)["full-publish-completed-echo"] || "";
|
|
380
|
-
Logger.log("Received full_publish_completed for ".concat(this.portalId, " with full-publish-completed-echo: '").concat(uniqueId, "'"));
|
|
381
|
-
if (!(uniqueId === this.uniqueId)) return [3 /*break*/, 2];
|
|
382
|
-
return [4 /*yield*/, this.addMessagesFromQueue()];
|
|
383
|
-
case 1:
|
|
384
|
-
_a.sent();
|
|
385
|
-
this.setupQueueWorker();
|
|
386
|
-
_a.label = 2;
|
|
387
|
-
case 2:
|
|
388
|
-
if (!(message.toString() !== "")) return [3 /*break*/, 4];
|
|
389
|
-
return [4 /*yield*/, this.addMessage(topic, getMessageJson(message))];
|
|
390
|
-
case 3:
|
|
391
|
-
_a.sent();
|
|
392
|
-
_a.label = 4;
|
|
393
|
-
case 4: return [2 /*return*/];
|
|
371
|
+
client.on("message", function (topic, message) {
|
|
372
|
+
// Logger.log(`DEBUG: Message received: ${topic} - ${message.toString()}`)
|
|
373
|
+
if (topic.endsWith("/system/0/Serial") && !_this.portalId) {
|
|
374
|
+
var portalId_1 = getMessageJson(message).value;
|
|
375
|
+
if (_this.portalId !== portalId_1 && portalId_1 !== undefined) {
|
|
376
|
+
_this.setPortalId(portalId_1);
|
|
394
377
|
}
|
|
395
|
-
|
|
396
|
-
|
|
378
|
+
runInAction(function () { return _this.subscribeToAllTopics(); });
|
|
379
|
+
}
|
|
380
|
+
if (topic.endsWith("full_publish_completed")) {
|
|
381
|
+
var uniqueId = getMessageJson(message)["full-publish-completed-echo"] || "";
|
|
382
|
+
Logger.log("Received full_publish_completed for ".concat(_this.portalId, " with full-publish-completed-echo: '").concat(uniqueId, "'"));
|
|
383
|
+
if (uniqueId === _this.uniqueId) {
|
|
384
|
+
_this.addMessagesFromQueue();
|
|
385
|
+
_this.setupQueueWorker();
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
if (message.toString() !== "") {
|
|
389
|
+
_this.addMessage(topic, getMessageJson(message));
|
|
390
|
+
}
|
|
391
|
+
});
|
|
397
392
|
Logger.log("MQTT booted");
|
|
398
393
|
}
|
|
399
394
|
});
|
|
@@ -495,6 +490,7 @@ var MqttStore = /** @class */ (function () {
|
|
|
495
490
|
});
|
|
496
491
|
makeAutoObservable(this, {
|
|
497
492
|
messageQueue: false,
|
|
493
|
+
urgentTopicPrefixes: false,
|
|
498
494
|
setupKeepaliveTimer: false,
|
|
499
495
|
clearKeepaliveTimer: false,
|
|
500
496
|
sendFullKeepalive: false,
|
|
@@ -521,6 +517,7 @@ var MqttStore = /** @class */ (function () {
|
|
|
521
517
|
value: function () {
|
|
522
518
|
this.topicsSubscribed.clear();
|
|
523
519
|
this.portalId = undefined;
|
|
520
|
+
this.urgentTopicPrefixes = [];
|
|
524
521
|
}
|
|
525
522
|
});
|
|
526
523
|
Object.defineProperty(MqttStore.prototype, "setStatus", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Mqtt.store.js","sourceRoot":"/","sources":["src/Modules/Mqtt/Mqtt.store.ts"],"names":[],"mappings":"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","sourcesContent":["import {comparer, makeAutoObservable, runInAction} from \"mobx\"\nimport {computedFn} from \"mobx-utils\"\nimport * as mqtt from \"mqtt\"\nimport {IClientPublishOptions, MqttClient} from \"mqtt\"\nimport {MqttMessage, MqttMessages, PortalId, STATUS, Topics} from \"../Mqtt\"\nimport Logger from \"../../utils/logger\"\nimport {getMessageJson} from \"../../utils/util\"\nimport {useMemo} from \"react\"\nimport {assign} from \"lodash-es\"\n\nlet store: MqttStore\n\nexport class MqttStore {\n client?: MqttClient | null\n error?: object | null | boolean\n status: string = STATUS.CONNECTING\n messages: MqttMessages = {}\n messageQueue: MqttMessages = {}\n topicsSubscribed: Set<string> = new Set<string>()\n portalId: PortalId\n uniqueId: string = Math.random().toString(16).substr(2, 8)\n keepAliveHandlerRef: any\n queueWorker: any\n meanQueueWorkerPassDuration: number = 0\n\n // Use comparer.identity to check the message we get for given topic.\n // Will cause re-render when new message for given topic arrives.\n // We rely on the fact that MQTT will only re-send a message when it\n // changes, and on full keep alive only.\n messageFromTopic = computedFn((topic?: string) => {\n // Logger.log(`DEBUG: messageFromTopic: ${JSON.stringify(topic)}`)\n // trace()\n return topic ? this.messages[topic] : undefined\n }, { name: \"Mqtt.store.messageFromTopic\", equals: comparer.identity })\n\n // Use comparer.identity to check the messages we get for given topics.\n // Will cause re-render when any new message for one of the topics arrives.\n // We rely on the fact that MQTT will only re-send a message when it\n // changes, and on full keep alive only.\n messagesByTopics = computedFn((topics?: Topics) => {\n // Logger.log(`DEBUG: messagesByTopics: ${JSON.stringify(topics)}`)\n // trace()\n if (!topics) {\n return {}\n }\n\n const result: { [key: string]: MqttMessage | MqttMessage[] } = {}\n\n Object.entries(topics).forEach(([label, topic]) => {\n if (Array.isArray(topic)) {\n result[label] = topic.map((t) => this.messageFromTopic(t))\n } else if (topic === undefined) {\n result[label] = undefined\n } else {\n result[label] = this.messageFromTopic(topic)\n }\n })\n\n return result\n }, { name: \"Mqtt.store.messagesByTopics\", equals: comparer.identity })\n\n // Use comparer.identity to check the messages we get for given topics.\n // Will cause re-render when any new message for one of the topic arrives,\n // or when we receive a new (yet unseen) topic.\n // We rely on the fact that MQTT will only re-send a message when it\n // changes, and on full keep alive\n // Only access Object.keys(this.messages),\n // and this.messages[k], where k matches the wildcard regex,\n // to make sure we invalidate:\n // - when new topics arrive\n // - when message with matching topic changes\n messagesByWildcard = computedFn((wildcard?: string) => {\n // Logger.log(`DEBUG: messagesByWildcard: ${JSON.stringify(wildcard)}`)\n // trace()\n if (wildcard === undefined || wildcard === \"\" || wildcard === null) return {}\n\n const topicRegex = new RegExp(wildcard.replace(/\\+/g, \"\\\\w*\")) // + in mqtt is anything -> .*\n\n return Object.fromEntries(\n Object.keys(this.messages)\n .filter((topic) => topic.match(topicRegex))\n .map((topic) => [topic, this.messages[topic]])\n // Filter out empty results\n .filter(([_, message]) =>\n message !== undefined && message !== null\n && (!Array.isArray(message) || (message.length !== 0 && !message.every((v) => v === undefined || v === null)))\n ),\n )\n }, { name: \"Mqtt.store.messagesByWildcard\", equals: comparer.identity })\n\n constructor() {\n makeAutoObservable(this, {\n messageQueue: false,\n setupKeepaliveTimer: false,\n clearKeepaliveTimer: false,\n sendFullKeepalive: false,\n sendSuppressedKeepalive: false,\n setupQueueWorker: false,\n removeQueueWorker: false,\n scheduleNextQueueWorkerPass: false,\n subscribeToTopic: false,\n subscribeToAllTopics: false,\n clearSubscribedTopics: false,\n })\n }\n\n get isConnected() {\n return this.status === STATUS.CONNECTED\n }\n\n subscribeToTopic = (topic?: string) => {\n if (!topic) return\n if (topic.includes(\"undefined\")) return\n\n if (!this.topicsSubscribed.has(topic)) {\n Logger.log(`Subscribing to ${topic}`)\n this.client?.subscribe(topic, (err, granted) => {\n if (err) {\n Logger.error(err)\n return\n }\n\n (granted !== undefined && granted[0])\n ? Logger.log(`Subscribed to ${granted[0].topic} with Qos ${granted[0].qos}`)\n : Logger.log(`Subscribed to ${topic} with Qos unknown`);\n })\n\n this.topicsSubscribed.add(topic)\n }\n }\n\n clearSubscribedTopics() {\n this.topicsSubscribed.clear()\n this.portalId = undefined\n }\n\n addMessage = async (topic: string, message: { value: string | null }) => {\n this.messageQueue[topic] = message.value ?? undefined\n }\n\n addMessagesFromQueue = async () => {\n if (Object.values(this.messageQueue).length > 0) {\n // Logger.log(`DEBUG: addMessagesFromQueue: in queue: ${JSON.stringify(Object.values(this.messageQueue).length)}`)\n assign(this.messages, this.messageQueue)\n // Logger.log(`DEBUG: addMessagesFromQueue: to process: ${JSON.stringify(Object.values(this.messages).length)}`)\n this.messageQueue = {}\n }\n }\n\n scheduleNextQueueWorkerPass = (timeout: number) => {\n this.queueWorker = setTimeout(async () => {\n const started = performance.now()\n await this.addMessagesFromQueue()\n const ended = performance.now()\n this.meanQueueWorkerPassDuration = addToMean(this.meanQueueWorkerPassDuration, 10, ended - started)\n // Schedule next update after 1 - 3 seconds\n // depending on how fast we were able to process the incoming messages\n const newTimeout = Math.max(1000, Math.min(this.meanQueueWorkerPassDuration * 50, 3000))\n this.scheduleNextQueueWorkerPass(newTimeout)\n }, timeout)\n }\n\n setupQueueWorker = () => {\n this.removeQueueWorker()\n\n this.meanQueueWorkerPassDuration = 20 // ms\n this.scheduleNextQueueWorkerPass(1000) // ms\n }\n\n removeQueueWorker = () => {\n if (this.queueWorker) {\n clearInterval(this.queueWorker)\n }\n this.queueWorker = undefined\n }\n\n setPortalId = (portalId: string) => {\n this.portalId = portalId\n }\n\n setStatus(status: string) {\n this.status = status\n }\n\n setError(error: object | null | boolean) {\n this.error = error\n }\n\n boot = (\n protocol: string,\n host: string = \"localhost\",\n port: number | null,\n path: string = \"websocket-mqtt\",\n remote: boolean = false,\n portalId?: string,\n ) => {\n Logger.log(\"MQTT booting\")\n\n let client = this.client\n\n if (client) {\n client.end(true)\n this.client = undefined\n this.portalId = undefined\n this.topicsSubscribed = new Set<string>()\n }\n\n let url\n if (remote) {\n if (!host) {\n return\n }\n // remote connection to VRM broker always uses MQTTS over 443\n url = `mqtts://${host}:443`\n } else {\n // local connection derives websocket protocol from web app protocol\n const wsproto = protocol === \"https:\" ? \"wss:\" : \"ws:\"\n if (port) {\n url = `${wsproto}//${host}:${port}/${path}`\n } else {\n url = `${wsproto}//${host}/${path}`\n }\n }\n\n Logger.log(`MQTT connecting to ${url}`)\n client = mqtt.connect(url, { resubscribe: false })\n\n this.client = client\n this.portalId = portalId\n\n client.on(\"error\", (error) => {\n Logger.log(\"MQTT error\")\n runInAction(() => {\n this.setError(error)\n this.setStatus(STATUS.DISCONNECTED)\n })\n this.removeQueueWorker()\n this.clearKeepaliveTimer()\n this.clearSubscribedTopics()\n })\n\n client.on(\"offline\", () => {\n Logger.log(\"MQTT offline\")\n runInAction(() => {\n this.setError(true)\n this.setStatus(STATUS.OFFLINE)\n })\n this.removeQueueWorker()\n this.clearKeepaliveTimer()\n this.clearSubscribedTopics()\n })\n\n client.on(\"connect\", () => {\n Logger.log(\"MQTT connected\")\n runInAction(() => {\n this.setError(null)\n this.setStatus(STATUS.CONNECTED)\n // Never use wildcard when connecting remotely\n this.subscribeToTopic(`N/${remote ? portalId : \"+\"}/system/0/Serial`)\n this.setupKeepaliveTimer()\n })\n })\n\n client.on(\"message\", async (topic, message) => {\n // Logger.log(`DEBUG: Message received: ${topic} - ${message.toString()}`)\n\n if (topic.endsWith(\"/system/0/Serial\") && !this.portalId) {\n const portalId = getMessageJson(message).value\n\n if (this.portalId !== portalId && portalId !== undefined) {\n this.setPortalId(portalId)\n }\n\n runInAction(() => this.subscribeToAllTopics())\n }\n if (topic.endsWith(\"full_publish_completed\")) {\n const uniqueId = getMessageJson(message)[\"full-publish-completed-echo\"] || \"\"\n Logger.log(`Received full_publish_completed for ${this.portalId} with full-publish-completed-echo: '${uniqueId}'`)\n if (uniqueId === this.uniqueId) {\n await this.addMessagesFromQueue()\n this.setupQueueWorker()\n }\n }\n\n if (message.toString() !== \"\") {\n await this.addMessage(topic, getMessageJson(message))\n }\n })\n\n Logger.log(\"MQTT booted\")\n }\n\n subscribeToAllTopics = () => {\n const topics = [\n `N/${this.portalId}/settings/#`,\n `N/${this.portalId}/system/#`,\n `N/${this.portalId}/vebus/#`,\n `N/${this.portalId}/alternator/#`,\n `N/${this.portalId}/battery/#`,\n `N/${this.portalId}/charger/#`,\n `N/${this.portalId}/dcsource/#`,\n `N/${this.portalId}/generator/#`,\n `N/${this.portalId}/genset/#`,\n `N/${this.portalId}/dcgenset/#`,\n `N/${this.portalId}/inverter/#`,\n `N/${this.portalId}/tank/#`,\n `N/${this.portalId}/temperature/#`,\n `N/${this.portalId}/switch/#`,\n `N/${this.portalId}/full_publish_completed`\n ]\n\n this.client?.subscribe(topics, err => {\n if (err) {\n Logger.error(err)\n return\n }\n\n // When we received all topics we send a full keepalive.\n this.sendFullKeepalive()\n })\n }\n\n sendSuppressedKeepalive = () => {\n if (this.portalId) {\n\n const options = JSON.stringify({\"keepalive-options\": [\"suppress-republish\"]})\n const topic = `R/${this.portalId}/keepalive`\n\n Logger.log(`Sending keepalive for ${this.portalId} with ${options}`)\n this.client?.publish(topic, options)\n }\n }\n\n sendFullKeepalive = () => {\n if (this.portalId) {\n\n const topic = `R/${this.portalId}/keepalive`\n\n Logger.log(`Sending first keepalive for ${this.portalId} with full-publish-completed-echo: '${this.uniqueId}'`)\n this.client && this.client?.publish(topic, `{ \"keepalive-options\" : [ {\"full-publish-completed-echo\": \"${this.uniqueId}\" } ] }`)\n }\n }\n\n setupKeepaliveTimer = () => {\n this.clearKeepaliveTimer()\n\n this.keepAliveHandlerRef = setInterval(this.sendSuppressedKeepalive, 30000)\n\n this.sendFullKeepalive()\n }\n\n clearKeepaliveTimer = () => {\n const ref = this.keepAliveHandlerRef\n if (ref) {\n clearInterval(ref)\n }\n this.keepAliveHandlerRef = undefined\n }\n\n publish = (topic: string, data: string | number, options?: IClientPublishOptions) => {\n if (this.status !== STATUS.CONNECTED || !this.client) {\n Logger.log(\"Could not publish value, not connected to MQTT broker\")\n }\n const message = JSON.stringify({value: data})\n\n Logger.log(`Publishing to ${topic}: ${message}`)\n\n this.client?.publish(topic, message, options ?? {})\n }\n}\n\n/**\n * Compute mean by providing existing mean, number of samples, and new sample.\n *\n * @param {number} mean current mean\n * @param {number} n number of sampled values\n * @param {number} newValue the sample\n * @returns {number} the new mean\n *\n * @example\n * addToMean(14, 5, 53); // => 20.5\n */\nfunction addToMean(mean: number, n: number, newValue: number): number {\n return mean + (newValue - mean) / (n + 1);\n}\n\nfunction initializeStore() {\n const _store = store ?? new MqttStore()\n // For SSG and SSR always create a new store\n if (typeof window === \"undefined\") return _store\n // Create the store once in the client\n if (!store) store = _store\n\n return _store\n}\n\nexport function useMqtt() {\n return useMemo(() => initializeStore(), [])\n}"]}
|
|
1
|
+
{"version":3,"file":"Mqtt.store.js","sourceRoot":"/","sources":["src/Modules/Mqtt/Mqtt.store.ts"],"names":[],"mappings":"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","sourcesContent":["import {comparer, makeAutoObservable, runInAction} from \"mobx\"\nimport {computedFn} from \"mobx-utils\"\nimport * as mqtt from \"mqtt\"\nimport {IClientPublishOptions, MqttClient} from \"mqtt\"\nimport {MqttMessage, MqttMessages, PortalId, STATUS, Topics} from \"../Mqtt\"\nimport Logger from \"../../utils/logger\"\nimport {getMessageJson} from \"../../utils/util\"\nimport {useMemo} from \"react\"\nimport {assign} from \"lodash-es\"\n\nlet store: MqttStore\n\nexport class MqttStore {\n client?: MqttClient | null\n error?: object | null | boolean\n status: string = STATUS.CONNECTING\n messages: MqttMessages = {}\n messageQueue: MqttMessages = {}\n topicsSubscribed: Set<string> = new Set<string>()\n portalId: PortalId\n uniqueId: string = Math.random().toString(16).substr(2, 8)\n keepAliveHandlerRef: any\n queueWorker: any\n meanQueueWorkerPassDuration: number = 0\n urgentTopicPrefixes: string[] = []\n\n /**\n * Returns the current cached message for a given MQTT topic.\n *\n * React Components using this method will re-render when their specific\n * topic's message changes.\n *\n * Using comparer.identity will trigger the re-renders any time\n * a message arrives for the given topic. We rely on the fact\n * that MQTT will only re-send a message when the value changes,\n * or on a full keep alive.\n *\n * Note: Receiving the same message for a given topic will cause re-renders,\n * as we do not check structural identity of the message.\n *\n * @param topic - The MQTT topic to retrieve the message for\n * @returns The message object for the topic, or undefined if topic is not provided or not found\n */\n messageFromTopic = computedFn((topic?: string) => {\n // Logger.log(`DEBUG: messageFromTopic: ${JSON.stringify(topic)}`)\n // trace()\n return topic ? this.messages[topic] : undefined\n }, { name: \"Mqtt.store.messageFromTopic\", equals: comparer.identity })\n\n /**\n * Returns the current cached messages for a given set of MQTT topics.\n *\n * This is a memoized computed function - each set of topics has its own cached value.\n *\n * React Components using this method will re-render when\n * any of the messages for specified topics change.\n *\n * Using comparer.identity will trigger the re-renders any time\n * a message arrives for any of the specified topics. We rely on the fact\n * that MQTT will only re-send a message when the value changes,\n * or on a full keep alive.\n\n * Note: Receiving the same message for a given topic will cause re-renders,\n * as we do not check structural identity of the message.\n *\n * @param topics - The MQTT topics to retrieve the messages for\n * @returns The messages objects for the given topics, or empty dictionary if topics not found\n */\n messagesByTopics = computedFn((topics?: Topics) => {\n // Logger.log(`DEBUG: messagesByTopics: ${JSON.stringify(topics)}`)\n // trace()\n if (!topics) {\n return {}\n }\n\n const result: { [key: string]: MqttMessage | MqttMessage[] } = {}\n\n Object.entries(topics).forEach(([label, topic]) => {\n if (Array.isArray(topic)) {\n result[label] = topic.map((t) => this.messageFromTopic(t))\n } else if (topic === undefined) {\n result[label] = undefined\n } else {\n result[label] = this.messageFromTopic(topic)\n }\n })\n\n return result\n }, { name: \"Mqtt.store.messagesByTopics\", equals: comparer.identity })\n\n /**\n * Returns the current cached messages for MQTT topics specified via regex.\n *\n * React Components using this method will re-render when\n * values of any of the matched topics change. The components also re-render\n * when new MQTT topics are received and match needs to be checked.\n *\n * Using comparer.identity will trigger the re-renders any time\n * a message arrives for any of the matched topics. We rely on the fact\n * that MQTT will only re-send a message when the value changes,\n * or on a full keep alive.\n *\n * Note: Receiving the same message for a given topic will cause re-renders,\n * as we do not check structural identity of the message.\n *\n * @param wildcard - The MQTT wildcard to retrieve the message for\n * @returns The messages objects for the given topics, or empty dictionary if topics not found\n */\n messagesByWildcard = computedFn((wildcard?: string) => {\n // Logger.log(`DEBUG: messagesByWildcard: ${JSON.stringify(wildcard)}`)\n // trace()\n if (wildcard === undefined || wildcard === \"\" || wildcard === null) return {}\n\n const topicRegex = new RegExp(wildcard.replace(/\\+/g, \"\\\\w*\")) // + in mqtt is anything -> .*\n\n return Object.fromEntries(\n Object.keys(this.messages)\n .filter((topic) => topic.match(topicRegex))\n .map((topic) => [topic, this.messages[topic]])\n // Filter out empty results\n .filter(([_, message]) =>\n message !== undefined && message !== null\n && (!Array.isArray(message) || (message.length !== 0 && !message.every((v) => v === undefined || v === null)))\n ),\n )\n }, { name: \"Mqtt.store.messagesByWildcard\", equals: comparer.identity })\n\n constructor() {\n makeAutoObservable(this, {\n messageQueue: false,\n urgentTopicPrefixes: false,\n setupKeepaliveTimer: false,\n clearKeepaliveTimer: false,\n sendFullKeepalive: false,\n sendSuppressedKeepalive: false,\n setupQueueWorker: false,\n removeQueueWorker: false,\n scheduleNextQueueWorkerPass: false,\n subscribeToTopic: false,\n subscribeToAllTopics: false,\n clearSubscribedTopics: false,\n })\n }\n\n get isConnected() {\n return this.status === STATUS.CONNECTED\n }\n\n subscribeToTopic = (topic?: string) => {\n if (!topic) return\n if (topic.includes(\"undefined\")) return\n\n if (!this.topicsSubscribed.has(topic)) {\n Logger.log(`Subscribing to ${topic}`)\n this.client?.subscribe(topic, (err, granted) => {\n if (err) {\n Logger.error(err)\n return\n }\n\n (granted !== undefined && granted[0])\n ? Logger.log(`Subscribed to ${granted[0].topic} with Qos ${granted[0].qos}`)\n : Logger.log(`Subscribed to ${topic} with Qos unknown`);\n })\n\n this.topicsSubscribed.add(topic)\n }\n }\n\n clearSubscribedTopics() {\n this.topicsSubscribed.clear()\n this.portalId = undefined\n this.urgentTopicPrefixes = []\n }\n\n addMessage = (topic: string, message: { value: string | null }) => {\n // Logger.log(`DEBUG: addMessage: topic: ${topic}, urgentPrefixes: ${JSON.stringify(this.urgentTopicPrefixes)}`)\n if (this.urgentTopicPrefixes.some((prefix) => topic.startsWith(prefix))) {\n Logger.log(`DEBUG: addMessage: topic: ${topic}`)\n // NOTE: If topic starts with one of the urgent prefixes, deliver it immediately\n this.messages[topic] = message.value ?? undefined\n } else {\n // NOTE: Otherwise store message to the queue, and move messages from the queue\n // NOTE: to the React components that are MobX observers periodically and in batches\n this.messageQueue[topic] = message.value ?? undefined\n }\n }\n\n addMessagesFromQueue = () => {\n if (Object.values(this.messageQueue).length > 0) {\n // Logger.log(`DEBUG: addMessagesFromQueue: in queue: ${JSON.stringify(Object.values(this.messageQueue).length)}`)\n assign(this.messages, this.messageQueue)\n // Logger.log(`DEBUG: addMessagesFromQueue: to process: ${JSON.stringify(Object.values(this.messages).length)}`)\n this.messageQueue = {}\n }\n }\n\n scheduleNextQueueWorkerPass = (timeout: number) => {\n this.queueWorker = setTimeout(() => {\n const started = performance.now()\n this.addMessagesFromQueue()\n const ended = performance.now()\n this.meanQueueWorkerPassDuration = addToMean(this.meanQueueWorkerPassDuration, 10, ended - started)\n // Schedule next update after 1 - 3 seconds\n // depending on how fast we were able to process the incoming messages\n const newTimeout = Math.max(1000, Math.min(this.meanQueueWorkerPassDuration * 50, 3000))\n this.scheduleNextQueueWorkerPass(newTimeout)\n }, timeout)\n }\n\n setupQueueWorker = () => {\n this.removeQueueWorker()\n\n this.meanQueueWorkerPassDuration = 20 // ms\n this.scheduleNextQueueWorkerPass(1000) // ms\n }\n\n removeQueueWorker = () => {\n if (this.queueWorker) {\n clearInterval(this.queueWorker)\n }\n this.queueWorker = undefined\n }\n\n setPortalId = (portalId: string) => {\n this.portalId = portalId\n this.urgentTopicPrefixes = [\n `N/${portalId}/switch/`,\n ]\n }\n\n setStatus(status: string) {\n this.status = status\n }\n\n setError(error: object | null | boolean) {\n this.error = error\n }\n\n boot = (\n protocol: string,\n host: string = \"localhost\",\n port: number | null,\n path: string = \"websocket-mqtt\",\n remote: boolean = false,\n portalId?: string,\n ) => {\n Logger.log(\"MQTT booting\")\n\n let client = this.client\n\n if (client) {\n client.end(true)\n this.client = undefined\n this.portalId = undefined\n this.topicsSubscribed = new Set<string>()\n this.urgentTopicPrefixes = []\n }\n\n let url\n if (remote) {\n if (!host) {\n return\n }\n // remote connection to VRM broker always uses MQTTS over 443\n url = `mqtts://${host}:443`\n } else {\n // local connection derives websocket protocol from web app protocol\n const wsproto = protocol === \"https:\" ? \"wss:\" : \"ws:\"\n if (port) {\n url = `${wsproto}//${host}:${port}/${path}`\n } else {\n url = `${wsproto}//${host}/${path}`\n }\n }\n\n Logger.log(`MQTT connecting to ${url}`)\n client = mqtt.connect(url, { resubscribe: false })\n\n this.client = client\n this.portalId = portalId\n\n client.on(\"error\", (error) => {\n Logger.log(\"MQTT error\")\n runInAction(() => {\n this.setError(error)\n this.setStatus(STATUS.DISCONNECTED)\n })\n this.removeQueueWorker()\n this.clearKeepaliveTimer()\n this.clearSubscribedTopics()\n })\n\n client.on(\"offline\", () => {\n Logger.log(\"MQTT offline\")\n runInAction(() => {\n this.setError(true)\n this.setStatus(STATUS.OFFLINE)\n })\n this.removeQueueWorker()\n this.clearKeepaliveTimer()\n this.clearSubscribedTopics()\n })\n\n client.on(\"connect\", () => {\n Logger.log(\"MQTT connected\")\n runInAction(() => {\n this.setError(null)\n this.setStatus(STATUS.CONNECTED)\n // Never use wildcard when connecting remotely\n this.subscribeToTopic(`N/${remote ? portalId : \"+\"}/system/0/Serial`)\n this.setupKeepaliveTimer()\n })\n })\n\n client.on(\"message\",\n (topic, message) => {\n // Logger.log(`DEBUG: Message received: ${topic} - ${message.toString()}`)\n\n if (topic.endsWith(\"/system/0/Serial\") && !this.portalId) {\n const portalId = getMessageJson(message).value\n\n if (this.portalId !== portalId && portalId !== undefined) {\n this.setPortalId(portalId)\n }\n\n runInAction(() => this.subscribeToAllTopics())\n }\n if (topic.endsWith(\"full_publish_completed\")) {\n const uniqueId = getMessageJson(message)[\"full-publish-completed-echo\"] || \"\"\n Logger.log(`Received full_publish_completed for ${this.portalId} with full-publish-completed-echo: '${uniqueId}'`)\n if (uniqueId === this.uniqueId) {\n this.addMessagesFromQueue()\n this.setupQueueWorker()\n }\n }\n\n if (message.toString() !== \"\") {\n this.addMessage(topic, getMessageJson(message))\n }\n })\n\n Logger.log(\"MQTT booted\")\n }\n\n subscribeToAllTopics = () => {\n const topics = [\n `N/${this.portalId}/settings/#`,\n `N/${this.portalId}/system/#`,\n `N/${this.portalId}/vebus/#`,\n `N/${this.portalId}/alternator/#`,\n `N/${this.portalId}/battery/#`,\n `N/${this.portalId}/charger/#`,\n `N/${this.portalId}/dcsource/#`,\n `N/${this.portalId}/generator/#`,\n `N/${this.portalId}/genset/#`,\n `N/${this.portalId}/dcgenset/#`,\n `N/${this.portalId}/inverter/#`,\n `N/${this.portalId}/tank/#`,\n `N/${this.portalId}/temperature/#`,\n `N/${this.portalId}/switch/#`,\n `N/${this.portalId}/full_publish_completed`\n ]\n\n this.client?.subscribe(topics, err => {\n if (err) {\n Logger.error(err)\n return\n }\n\n // When we received all topics we send a full keepalive.\n this.sendFullKeepalive()\n })\n }\n\n sendSuppressedKeepalive = () => {\n if (this.portalId) {\n\n const options = JSON.stringify({\"keepalive-options\": [\"suppress-republish\"]})\n const topic = `R/${this.portalId}/keepalive`\n\n Logger.log(`Sending keepalive for ${this.portalId} with ${options}`)\n this.client?.publish(topic, options)\n }\n }\n\n sendFullKeepalive = () => {\n if (this.portalId) {\n\n const topic = `R/${this.portalId}/keepalive`\n\n Logger.log(`Sending first keepalive for ${this.portalId} with full-publish-completed-echo: '${this.uniqueId}'`)\n this.client && this.client?.publish(topic, `{ \"keepalive-options\" : [ {\"full-publish-completed-echo\": \"${this.uniqueId}\" } ] }`)\n }\n }\n\n setupKeepaliveTimer = () => {\n this.clearKeepaliveTimer()\n\n this.keepAliveHandlerRef = setInterval(this.sendSuppressedKeepalive, 30000)\n\n this.sendFullKeepalive()\n }\n\n clearKeepaliveTimer = () => {\n const ref = this.keepAliveHandlerRef\n if (ref) {\n clearInterval(ref)\n }\n this.keepAliveHandlerRef = undefined\n }\n\n publish = (topic: string, data: string | number, options?: IClientPublishOptions) => {\n if (this.status !== STATUS.CONNECTED || !this.client) {\n Logger.log(\"Could not publish value, not connected to MQTT broker\")\n }\n const message = JSON.stringify({value: data})\n\n Logger.log(`Publishing to ${topic}: ${message}`)\n\n this.client?.publish(topic, message, options ?? {})\n }\n}\n\n/**\n * Compute mean by providing existing mean, number of samples, and new sample.\n *\n * @param {number} mean current mean\n * @param {number} n number of sampled values\n * @param {number} newValue the sample\n * @returns {number} the new mean\n *\n * @example\n * addToMean(14, 5, 53); // => 20.5\n */\nfunction addToMean(mean: number, n: number, newValue: number): number {\n return mean + (newValue - mean) / (n + 1);\n}\n\nfunction initializeStore() {\n const _store = store ?? new MqttStore()\n // For SSG and SSR always create a new store\n if (typeof window === \"undefined\") return _store\n // Create the store once in the client\n if (!store) store = _store\n\n return _store\n}\n\nexport function useMqtt() {\n return useMemo(() => initializeStore(), [])\n}"]}
|
|
@@ -10,7 +10,7 @@ export interface SwitchableOutputState {
|
|
|
10
10
|
name: string;
|
|
11
11
|
customName: string;
|
|
12
12
|
group: string;
|
|
13
|
-
|
|
13
|
+
showUIControl: 0 | 1;
|
|
14
14
|
auto: 0 | 1;
|
|
15
15
|
state: 0 | 1;
|
|
16
16
|
dimming?: number;
|
|
@@ -32,7 +32,7 @@ export interface SwitchableOutputTopics extends Topics {
|
|
|
32
32
|
name?: string;
|
|
33
33
|
customName?: string;
|
|
34
34
|
group?: string;
|
|
35
|
-
|
|
35
|
+
showUIControl?: string;
|
|
36
36
|
auto?: string;
|
|
37
37
|
state?: string;
|
|
38
38
|
dimming?: string;
|
|
@@ -49,7 +49,7 @@ export declare const getSwitchableOutputStateTopics: (portalId: PortalId, device
|
|
|
49
49
|
name: string;
|
|
50
50
|
customName: string;
|
|
51
51
|
group: string;
|
|
52
|
-
|
|
52
|
+
showUIControl: string;
|
|
53
53
|
auto: string;
|
|
54
54
|
state: string;
|
|
55
55
|
dimming: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SwitchableOutput.provider.d.ts","sourceRoot":"/","sources":["src/Modules/SwitchableOutputs/SwitchableOutput.provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAA2B,MAAM,SAAS,CAAA;AAEnE,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAA;AACtE,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AAEpF,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAA;AAEvC,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,yBAAyB,CAAA;IACnC,QAAQ,EAAE,kBAAkB,CAAA;IAC5B,IAAI,EAAE,oBAAoB,CAAA;IAC1B,MAAM,EAAE,sBAAsB,CAAA;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,
|
|
1
|
+
{"version":3,"file":"SwitchableOutput.provider.d.ts","sourceRoot":"/","sources":["src/Modules/SwitchableOutputs/SwitchableOutput.provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAA2B,MAAM,SAAS,CAAA;AAEnE,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAA;AACtE,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AAEpF,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAA;AAEvC,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,yBAAyB,CAAA;IACnC,QAAQ,EAAE,kBAAkB,CAAA;IAC5B,IAAI,EAAE,oBAAoB,CAAA;IAC1B,MAAM,EAAE,sBAAsB,CAAA;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,aAAa,EAAE,CAAC,GAAG,CAAC,CAAA;IACpB,IAAI,EAAE,CAAC,GAAG,CAAC,CAAA;IACX,KAAK,EAAE,CAAC,GAAG,CAAC,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;IAEjC,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,wBAAyB,SAAQ,qBAAqB;IACrE,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,KAAK,IAAI,CAAA;IACjC,WAAW,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,KAAK,IAAI,CAAA;IACnC,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CACzC;AAED,MAAM,WAAW,sBAAuB,SAAQ,MAAM;IACpD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,eAAO,MAAM,8BAA8B,GAAI,UAAU,QAAQ,EAAE,UAAU,yBAAyB,EAAE,UAAU,kBAAkB;;;;;;;;;;;;;;;;CAgBlI,CAAA;AAEF,eAAO,MAAM,8BAA8B,GAAI,UAAU,QAAQ,EAAE,UAAU,yBAAyB,EAAE,UAAU,kBAAkB;;;;CAIlI,CAAA;AAEF,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,yBAAyB,EAAE,QAAQ,EAAE,kBAAkB,GAAG,wBAAwB,CAW/H"}
|
|
@@ -17,7 +17,7 @@ export var getSwitchableOutputStateTopics = function (portalId, deviceId, output
|
|
|
17
17
|
name: "N/".concat(portalId, "/switch/").concat(deviceId, "/SwitchableOutput/").concat(outputId, "/Name"),
|
|
18
18
|
customName: "N/".concat(portalId, "/switch/").concat(deviceId, "/SwitchableOutput/").concat(outputId, "/Settings/CustomName"),
|
|
19
19
|
group: "N/".concat(portalId, "/switch/").concat(deviceId, "/SwitchableOutput/").concat(outputId, "/Settings/Group"),
|
|
20
|
-
|
|
20
|
+
showUIControl: "N/".concat(portalId, "/switch/").concat(deviceId, "/SwitchableOutput/").concat(outputId, "/Settings/ShowUIControl"),
|
|
21
21
|
auto: "N/".concat(portalId, "/switch/").concat(deviceId, "/SwitchableOutput/").concat(outputId, "/Auto"),
|
|
22
22
|
state: "N/".concat(portalId, "/switch/").concat(deviceId, "/SwitchableOutput/").concat(outputId, "/State"),
|
|
23
23
|
dimming: "N/".concat(portalId, "/switch/").concat(deviceId, "/SwitchableOutput/").concat(outputId, "/Dimming"),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SwitchableOutput.provider.js","sourceRoot":"/","sources":["src/Modules/SwitchableOutputs/SwitchableOutput.provider.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,OAAO,EAAoB,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AACnE,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAoD/B,MAAM,CAAC,IAAM,8BAA8B,GAAG,UAAC,QAAkB,EAAE,QAAmC,EAAE,QAA4B,IAAK,OAAA,CAAC;IACxI,IAAI,EAAE,YAAK,QAAQ,qBAAW,QAAQ,+BAAqB,QAAQ,mBAAgB;IACnF,MAAM,EAAE,YAAK,QAAQ,qBAAW,QAAQ,+BAAqB,QAAQ,YAAS;IAC9E,IAAI,EAAE,YAAK,QAAQ,qBAAW,QAAQ,+BAAqB,QAAQ,UAAO;IAC1E,UAAU,EAAE,YAAK,QAAQ,qBAAW,QAAQ,+BAAqB,QAAQ,yBAAsB;IAC/F,KAAK,EAAE,YAAK,QAAQ,qBAAW,QAAQ,+BAAqB,QAAQ,oBAAiB;IACrF,
|
|
1
|
+
{"version":3,"file":"SwitchableOutput.provider.js","sourceRoot":"/","sources":["src/Modules/SwitchableOutputs/SwitchableOutput.provider.ts"],"names":[],"mappings":"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","sourcesContent":["import { PortalId, Topics, useMqtt, useTopicsState } from \"../Mqtt\"\nimport { useMemo } from \"react\"\nimport { SwitchingDeviceInstanceId } from \"./SwitchingDevice.provider\"\nimport { SwitchableOutputStatus, SwitchableOutputType } from \"../../utils/constants\"\n\nexport type SwitchableOutputId = string\n\nexport interface SwitchableOutputState {\n deviceId: SwitchingDeviceInstanceId\n outputId: SwitchableOutputId\n type: SwitchableOutputType\n status: SwitchableOutputStatus\n name: string\n customName: string\n group: string\n showUIControl: 0 | 1\n auto: 0 | 1\n state: 0 | 1\n dimming?: number\n dimmingMin?: number\n dimmingMax?: number\n // NOTE: stepSize can be of any precision, respect the precision in the UI\n stepSize?: number\n measurement?: number\n unit: string | \"/S\" | \"/T\" | \"/V\"\n // NOTE: JSON encoded string array\n labels: string\n}\n\nexport interface SwitchableOutputProvider extends SwitchableOutputState {\n updateAuto: (auto: 0 | 1) => void\n updateState: (state: 0 | 1) => void\n updateDimming: (dimming: number) => void\n}\n\nexport interface SwitchableOutputTopics extends Topics {\n type?: string\n status?: string\n name?: string\n customName?: string\n group?: string\n showUIControl?: string\n auto?: string\n state?: string\n dimming?: string\n dimmingMin?: string\n dimmingMax?: string\n stepSize?: string\n measurement?: string\n unit?: string\n labels?: string\n}\n\nexport const getSwitchableOutputStateTopics = (portalId: PortalId, deviceId: SwitchingDeviceInstanceId, outputId: SwitchableOutputId) => ({\n type: `N/${portalId}/switch/${deviceId}/SwitchableOutput/${outputId}/Settings/Type`,\n status: `N/${portalId}/switch/${deviceId}/SwitchableOutput/${outputId}/Status`,\n name: `N/${portalId}/switch/${deviceId}/SwitchableOutput/${outputId}/Name`,\n customName: `N/${portalId}/switch/${deviceId}/SwitchableOutput/${outputId}/Settings/CustomName`,\n group: `N/${portalId}/switch/${deviceId}/SwitchableOutput/${outputId}/Settings/Group`,\n showUIControl: `N/${portalId}/switch/${deviceId}/SwitchableOutput/${outputId}/Settings/ShowUIControl`,\n auto: `N/${portalId}/switch/${deviceId}/SwitchableOutput/${outputId}/Auto`,\n state: `N/${portalId}/switch/${deviceId}/SwitchableOutput/${outputId}/State`,\n dimming: `N/${portalId}/switch/${deviceId}/SwitchableOutput/${outputId}/Dimming`,\n dimmingMin: `N/${portalId}/switch/${deviceId}/SwitchableOutput/${outputId}/DimmingMin`,\n dimmingMax: `N/${portalId}/switch/${deviceId}/SwitchableOutput/${outputId}/DimmingMax`,\n stepSize: `N/${portalId}/switch/${deviceId}/SwitchableOutput/${outputId}/StepSize`,\n measurement: `N/${portalId}/switch/${deviceId}/SwitchableOutput/${outputId}/Measurement`,\n unit: `N/${portalId}/switch/${deviceId}/SwitchableOutput/${outputId}/Unit`,\n labels: `N/${portalId}/switch/${deviceId}/SwitchableOutput/${outputId}/Labels`,\n})\n\nexport const getSwitchableOutputWriteTopics = (portalId: PortalId, deviceId: SwitchingDeviceInstanceId, outputId: SwitchableOutputId) => ({\n auto: `W/${portalId}/switch/${deviceId}/SwitchableOutput/${outputId}/Auto`,\n state: `W/${portalId}/switch/${deviceId}/SwitchableOutput/${outputId}/State`,\n dimming: `W/${portalId}/switch/${deviceId}/SwitchableOutput/${outputId}/Dimming`,\n})\n\nexport function useSwitchableOutput(deviceId: SwitchingDeviceInstanceId, outputId: SwitchableOutputId): SwitchableOutputProvider {\n\n const mqtt = useMqtt()\n const topics = useMemo(() => getSwitchableOutputStateTopics(mqtt.portalId, deviceId, outputId), [mqtt.portalId, deviceId, outputId])\n const writeTopics = useMemo(() => getSwitchableOutputWriteTopics(mqtt.portalId, deviceId, outputId), [mqtt.portalId, deviceId, outputId])\n\n const updateAuto = (auto: 0 | 1) => mqtt.publish(writeTopics!.auto, auto)\n const updateState = (state: 0 | 1) => mqtt.publish(writeTopics!.state, state)\n const updateDimming = (dimming: number) => mqtt.publish(writeTopics!.dimming, dimming)\n\n return { ...useTopicsState<SwitchableOutputState>(topics), updateAuto, updateState, updateDimming }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SwitchableOutputs.provider.d.ts","sourceRoot":"/","sources":["src/Modules/SwitchableOutputs/SwitchableOutputs.provider.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,oBAAoB,
|
|
1
|
+
{"version":3,"file":"SwitchableOutputs.provider.d.ts","sourceRoot":"/","sources":["src/Modules/SwitchableOutputs/SwitchableOutputs.provider.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,oBAAoB,kEA6DhC,CAAA"}
|
|
@@ -19,73 +19,53 @@ import { getSwitchableOutputStateTopics } from "./SwitchableOutput.provider";
|
|
|
19
19
|
export var useSwitchableOutputs = function () {
|
|
20
20
|
var switchableOutputsStore = useSwitchableOutputsStore();
|
|
21
21
|
var getTopics = function (portalId) { return ({
|
|
22
|
-
|
|
23
|
-
switchableOutputs: "N/".concat(portalId, "/switch/+/SwitchableOutput/+/Settings/Group"),
|
|
22
|
+
switchableOutputs: "N/".concat(portalId, "/switch/+/SwitchableOutput/+/Settings/+"),
|
|
24
23
|
}); };
|
|
25
24
|
var mqtt = useMqtt();
|
|
26
25
|
var topics = useMemo(function () { return getTopics(mqtt.portalId); }, [mqtt.portalId]);
|
|
27
|
-
var messagesForSwitchingDevices = mqtt.messagesByWildcard(topics.devices);
|
|
28
26
|
var messagesForSwitchableOutputs = mqtt.messagesByWildcard(topics.switchableOutputs);
|
|
29
|
-
// Examine MQTT to find all available switching devices
|
|
30
|
-
useEffect(function () {
|
|
31
|
-
if (!messagesForSwitchingDevices || Object.entries(messagesForSwitchingDevices).length === 0) {
|
|
32
|
-
Logger.log("Waiting for switching devices...");
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
35
|
-
var deviceInstances_1 = Object.values(messagesForSwitchingDevices);
|
|
36
|
-
var dispose_1 = autorun(function () {
|
|
37
|
-
var oldDevices = switchableOutputsStore.devices;
|
|
38
|
-
var newDevices = deviceInstances_1.map(function (deviceId) { return mqtt.messagesByTopics(getSwitchingDeviceStateTopics(mqtt.portalId, deviceId)); });
|
|
39
|
-
// TODO: check unordered structural identify of old and new state
|
|
40
|
-
// TODO: to avoid unnecessary re-rendering: O(n^2) baby
|
|
41
|
-
if (!oldDevices || oldDevices.length != newDevices.length || !newDevices.every(function (id) { return deviceInstances_1.includes(id); })) {
|
|
42
|
-
Logger.log("New switching devices instances: ".concat(JSON.stringify(deviceInstances_1)));
|
|
43
|
-
switchableOutputsStore.setDevices(newDevices);
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
return function () { return dispose_1(); };
|
|
47
|
-
}
|
|
48
|
-
}, [messagesForSwitchingDevices]);
|
|
49
27
|
// Examine MQTT to find all available switchable outputs and their group assignments
|
|
50
28
|
useEffect(function () {
|
|
51
29
|
if (!messagesForSwitchableOutputs || Object.entries(messagesForSwitchableOutputs).length === 0) {
|
|
52
30
|
Logger.log("Waiting for switchable outputs...");
|
|
53
31
|
}
|
|
54
32
|
else {
|
|
55
|
-
var availableSwitchableOutputs_1 = Object.keys(messagesForSwitchableOutputs)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
33
|
+
var availableSwitchableOutputs_1 = Object.keys(messagesForSwitchableOutputs)
|
|
34
|
+
.filter(function (key) { return key.endsWith('/Settings/Group'); })
|
|
35
|
+
.sort();
|
|
36
|
+
var customGroupAssigments_1 = availableSwitchableOutputs_1
|
|
37
|
+
.filter(function (topic) { return topic.endsWith('/Settings/Group'); })
|
|
38
|
+
.map(function (topic) { return messagesForSwitchableOutputs[topic]; });
|
|
39
|
+
var dispose_1 = autorun(function () {
|
|
40
|
+
switchableOutputsStore.setCustomGroupAssignments(customGroupAssigments_1);
|
|
41
|
+
var newGroups = {};
|
|
42
|
+
// Walk the array of all switchable outputs, determine to which group it belongs
|
|
43
|
+
// and populate its initial state
|
|
44
|
+
availableSwitchableOutputs_1.forEach(function (output, index) {
|
|
45
|
+
var swo = extractSwitchableOutputInfo(output);
|
|
46
|
+
var switchingDevice = mqtt.messagesByTopics(getSwitchingDeviceStateTopics(mqtt.portalId, swo.deviceId));
|
|
47
|
+
var customGroupAssignment = customGroupAssigments_1[index].trim();
|
|
48
|
+
var groupName = customGroupAssignment === "" ? switchingDevice.customName || switchingDevice.productName : customGroupAssignment;
|
|
49
|
+
var switchableOutput = mqtt.messagesByTopics(getSwitchableOutputStateTopics(mqtt.portalId, swo.deviceId, swo.outputId));
|
|
50
|
+
// Ignore hidden controls
|
|
51
|
+
if (switchableOutput.showUIControl === 0) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
newGroups[groupName] || (newGroups[groupName] = []);
|
|
55
|
+
newGroups[groupName].push(__assign(__assign({}, switchableOutput), { deviceId: swo.deviceId, outputId: swo.outputId }));
|
|
56
|
+
});
|
|
57
|
+
Logger.log("New switchable output groups: ".concat(JSON.stringify(Object.keys(newGroups))));
|
|
58
|
+
// Sort switches in a group by name
|
|
59
|
+
Object.values(newGroups).forEach(function (array) {
|
|
60
|
+
array.sort(function (a, b) {
|
|
61
|
+
var aName = a.customName || a.name;
|
|
62
|
+
var bName = b.customName || b.name;
|
|
63
|
+
return aName.localeCompare(bName);
|
|
84
64
|
});
|
|
85
|
-
|
|
86
|
-
|
|
65
|
+
});
|
|
66
|
+
switchableOutputsStore.setGroups(newGroups);
|
|
87
67
|
});
|
|
88
|
-
return function () { return
|
|
68
|
+
return function () { return dispose_1(); };
|
|
89
69
|
}
|
|
90
70
|
}, [messagesForSwitchableOutputs]);
|
|
91
71
|
return switchableOutputsStore;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SwitchableOutputs.provider.js","sourceRoot":"/","sources":["src/Modules/SwitchableOutputs/SwitchableOutputs.provider.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAC9B,OAAO,MAAM,MAAM,oBAAoB,CAAA;AACvC,OAAO,EAAY,OAAO,EAAE,MAAM,SAAS,CAAA;AAC3C,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAC1C,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAA;AACrE,OAAO,EAAE,6BAA6B,
|
|
1
|
+
{"version":3,"file":"SwitchableOutputs.provider.js","sourceRoot":"/","sources":["src/Modules/SwitchableOutputs/SwitchableOutputs.provider.ts"],"names":[],"mappings":"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","sourcesContent":["import { autorun } from \"mobx\"\nimport Logger from \"../../utils/logger\"\nimport { PortalId, useMqtt } from \"../Mqtt\"\nimport { useMemo, useEffect } from \"react\"\nimport { useSwitchableOutputsStore } from \"./SwitchableOutputs.store\"\nimport { getSwitchingDeviceStateTopics, SwitchingDeviceInstanceId } from \"./SwitchingDevice.provider\"\nimport { getSwitchableOutputStateTopics, SwitchableOutputId, SwitchableOutputState } from \"./SwitchableOutput.provider\"\n\nexport const useSwitchableOutputs = () => {\n const switchableOutputsStore = useSwitchableOutputsStore()\n\n const getTopics = (portalId: PortalId) => ({\n switchableOutputs: `N/${portalId}/switch/+/SwitchableOutput/+/Settings/+`,\n })\n\n const mqtt = useMqtt()\n const topics = useMemo(() => getTopics(mqtt.portalId), [mqtt.portalId])\n\n const messagesForSwitchableOutputs = mqtt.messagesByWildcard(topics.switchableOutputs)\n\n // Examine MQTT to find all available switchable outputs and their group assignments\n useEffect(() => {\n if (!messagesForSwitchableOutputs || Object.entries(messagesForSwitchableOutputs).length === 0) {\n Logger.log(\"Waiting for switchable outputs...\")\n } else {\n const availableSwitchableOutputs = Object.keys(messagesForSwitchableOutputs)\n .filter(key => key.endsWith('/Settings/Group'))\n .sort() as string[]\n const customGroupAssigments = availableSwitchableOutputs\n .filter(topic => topic.endsWith('/Settings/Group'))\n .map(topic => messagesForSwitchableOutputs[topic])\n const dispose = autorun(() => {\n switchableOutputsStore.setCustomGroupAssignments(customGroupAssigments)\n\n const newGroups: { [key: string] : SwitchableOutputState[]} = {}\n\n // Walk the array of all switchable outputs, determine to which group it belongs\n // and populate its initial state\n availableSwitchableOutputs.forEach((output, index) => {\n const swo = extractSwitchableOutputInfo(output)\n const switchingDevice = mqtt.messagesByTopics(getSwitchingDeviceStateTopics(mqtt.portalId, swo.deviceId))\n const customGroupAssignment = customGroupAssigments[index].trim()\n const groupName = customGroupAssignment === \"\" ? switchingDevice.customName || switchingDevice.productName : customGroupAssignment\n const switchableOutput = mqtt.messagesByTopics(getSwitchableOutputStateTopics(mqtt.portalId, swo.deviceId, swo.outputId)) as unknown as SwitchableOutputState\n\n // Ignore hidden controls\n if (switchableOutput.showUIControl === 0) { return }\n\n newGroups[groupName] ||= []\n newGroups[groupName].push({ ...switchableOutput, deviceId: swo.deviceId, outputId: swo.outputId })\n })\n\n Logger.log(`New switchable output groups: ${JSON.stringify(Object.keys(newGroups))}`);\n // Sort switches in a group by name\n Object.values(newGroups).forEach(array => {\n array.sort((a, b) => {\n const aName = a.customName || a.name\n const bName = b.customName || b.name\n return aName.localeCompare(bName);\n })\n })\n switchableOutputsStore.setGroups(newGroups)\n }\n )\n return () => dispose()\n }\n }, [messagesForSwitchableOutputs])\n\n return switchableOutputsStore\n}\n\nfunction extractSwitchableOutputInfo(topic: string) {\n const switchStart = topic.indexOf('/switch/') + 8 // length of `/switch/`\n const outputStart = topic.indexOf('/SwitchableOutput/') + 18 // length of `/SwitchableOutput/`\n \n return {\n deviceId: topic.substring(switchStart, topic.indexOf('/', switchStart)) as unknown as SwitchingDeviceInstanceId,\n outputId: topic.substring(outputStart, topic.indexOf('/', outputStart)) as unknown as SwitchableOutputId\n }\n}"]}
|
|
@@ -1,20 +1,16 @@
|
|
|
1
1
|
import { SwitchableOutputState } from "./SwitchableOutput.provider";
|
|
2
|
-
import { SwitchingDeviceInstanceId } from "./SwitchingDevice.provider";
|
|
3
2
|
export interface SwitchableOutputsState {
|
|
4
|
-
devices: SwitchingDeviceInstanceId[];
|
|
5
3
|
groups: {
|
|
6
4
|
[key: string]: SwitchableOutputState[];
|
|
7
5
|
};
|
|
8
6
|
customGroupAssignments: string[];
|
|
9
7
|
}
|
|
10
8
|
export declare class SwitchableOutputsStore {
|
|
11
|
-
devices: SwitchingDeviceInstanceId[];
|
|
12
9
|
groups: {
|
|
13
10
|
[key: string]: SwitchableOutputState[];
|
|
14
11
|
};
|
|
15
12
|
customGroupAssignments: string[];
|
|
16
13
|
constructor();
|
|
17
|
-
setDevices: (devices: SwitchingDeviceInstanceId[]) => number[];
|
|
18
14
|
setGroups: (groups: {
|
|
19
15
|
[key: string]: SwitchableOutputState[];
|
|
20
16
|
}) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SwitchableOutputs.store.d.ts","sourceRoot":"/","sources":["src/Modules/SwitchableOutputs/SwitchableOutputs.store.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAA;
|
|
1
|
+
{"version":3,"file":"SwitchableOutputs.store.d.ts","sourceRoot":"/","sources":["src/Modules/SwitchableOutputs/SwitchableOutputs.store.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAA;AAInE,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAI,qBAAqB,EAAE,CAAA;KAAE,CAAA;IAEnD,sBAAsB,EAAE,MAAM,EAAE,CAAA;CACjC;AAED,qBAAa,sBAAsB;IACjC,MAAM,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAI,qBAAqB,EAAE,CAAA;KAAE,CAAK;IACxD,sBAAsB,EAAE,MAAM,EAAE,CAAK;;IAMrC,SAAS,GAAI,QAAQ;QAAE,CAAC,GAAG,EAAE,MAAM,GAAI,qBAAqB,EAAE,CAAA;KAAE;;MAAyB;IACzF,yBAAyB,GAAI,aAAa,MAAM,EAAE,cAA8C;CACjG;AAYD,wBAAgB,yBAAyB,2BAExC"}
|
|
@@ -4,12 +4,6 @@ var store;
|
|
|
4
4
|
var SwitchableOutputsStore = /** @class */ (function () {
|
|
5
5
|
function SwitchableOutputsStore() {
|
|
6
6
|
var _this = this;
|
|
7
|
-
Object.defineProperty(this, "devices", {
|
|
8
|
-
enumerable: true,
|
|
9
|
-
configurable: true,
|
|
10
|
-
writable: true,
|
|
11
|
-
value: []
|
|
12
|
-
});
|
|
13
7
|
Object.defineProperty(this, "groups", {
|
|
14
8
|
enumerable: true,
|
|
15
9
|
configurable: true,
|
|
@@ -22,12 +16,6 @@ var SwitchableOutputsStore = /** @class */ (function () {
|
|
|
22
16
|
writable: true,
|
|
23
17
|
value: []
|
|
24
18
|
});
|
|
25
|
-
Object.defineProperty(this, "setDevices", {
|
|
26
|
-
enumerable: true,
|
|
27
|
-
configurable: true,
|
|
28
|
-
writable: true,
|
|
29
|
-
value: function (devices) { return _this.devices = devices; }
|
|
30
|
-
});
|
|
31
19
|
Object.defineProperty(this, "setGroups", {
|
|
32
20
|
enumerable: true,
|
|
33
21
|
configurable: true,
|
|
@@ -40,7 +28,7 @@ var SwitchableOutputsStore = /** @class */ (function () {
|
|
|
40
28
|
writable: true,
|
|
41
29
|
value: function (assignments) { return _this.customGroupAssignments = assignments; }
|
|
42
30
|
});
|
|
43
|
-
makeAutoObservable(this, {
|
|
31
|
+
makeAutoObservable(this, { setGroups: action, setCustomGroupAssignments: action });
|
|
44
32
|
}
|
|
45
33
|
return SwitchableOutputsStore;
|
|
46
34
|
}());
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SwitchableOutputs.store.js","sourceRoot":"/","sources":["src/Modules/SwitchableOutputs/SwitchableOutputs.store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAe,MAAM,MAAM,CAAA;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"SwitchableOutputs.store.js","sourceRoot":"/","sources":["src/Modules/SwitchableOutputs/SwitchableOutputs.store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAe,MAAM,MAAM,CAAA;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAG/B,IAAI,KAA6B,CAAA;AAQjC;IAIE;QAAA,iBAEC;QALD;;;;mBAAsD,EAAE;WAAA;QACxD;;;;mBAAmC,EAAE;WAAA;QAMrC;;;;mBAAY,UAAC,MAAmD,IAAK,OAAA,KAAI,CAAC,MAAM,GAAG,MAAM,EAApB,CAAoB;WAAA;QACzF;;;;mBAA4B,UAAC,WAAqB,IAAK,OAAA,KAAI,CAAC,sBAAsB,GAAG,WAAW,EAAzC,CAAyC;WAAA;QAJ9F,kBAAkB,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,yBAAyB,EAAE,MAAM,EAAE,CAAC,CAAA;IACpF,CAAC;IAIH,6BAAC;AAAD,CAAC,AAVD,IAUC;;AAED,SAAS,eAAe;IACtB,IAAM,MAAM,GAAG,KAAK,aAAL,KAAK,cAAL,KAAK,GAAI,IAAI,sBAAsB,EAAE,CAAA;IACpD,4CAA4C;IAC5C,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO,MAAM,CAAA;IAChD,sCAAsC;IACtC,IAAI,CAAC,KAAK;QAAE,KAAK,GAAG,MAAM,CAAA;IAE1B,OAAO,MAAM,CAAA;AACf,CAAC;AAED,MAAM,UAAU,yBAAyB;IACvC,OAAO,OAAO,CAAC,cAAM,OAAA,eAAe,EAAE,EAAjB,CAAiB,EAAE,EAAE,CAAC,CAAA;AAC7C,CAAC","sourcesContent":["import { action, makeAutoObservable, runInAction } from \"mobx\"\nimport { useMemo } from \"react\"\nimport { SwitchableOutputState } from \"./SwitchableOutput.provider\"\n\nlet store: SwitchableOutputsStore\n\nexport interface SwitchableOutputsState {\n groups: { [key: string] : SwitchableOutputState[] }\n // custom group assignments for available switchable outputs sorted by their topic path\n customGroupAssignments: string[]\n}\n\nexport class SwitchableOutputsStore {\n groups: { [key: string] : SwitchableOutputState[] } = {}\n customGroupAssignments: string[] = []\n\n constructor() {\n makeAutoObservable(this, { setGroups: action, setCustomGroupAssignments: action })\n }\n\n setGroups = (groups: { [key: string] : SwitchableOutputState[] }) => this.groups = groups\n setCustomGroupAssignments = (assignments: string[]) => this.customGroupAssignments = assignments\n}\n\nfunction initializeStore() {\n const _store = store ?? new SwitchableOutputsStore()\n // For SSG and SSR always create a new store\n if (typeof window === \"undefined\") return _store\n // Create the store once in the client\n if (!store) store = _store\n\n return _store\n}\n\nexport function useSwitchableOutputsStore() {\n return useMemo(() => initializeStore(), [])\n}"]}
|
|
@@ -18,4 +18,5 @@ export declare const getSwitchingDeviceStateTopics: (portalId: PortalId, instanc
|
|
|
18
18
|
instance: string;
|
|
19
19
|
};
|
|
20
20
|
export declare function useSwitchingDevice(instanceId: SwitchingDeviceInstanceId): SwitchingDeviceState;
|
|
21
|
+
export declare function useSwitchingDevices(): import("./SwitchingDevices.store").SwitchingDevicesStore;
|
|
21
22
|
//# sourceMappingURL=SwitchingDevice.provider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SwitchingDevice.provider.d.ts","sourceRoot":"/","sources":["src/Modules/SwitchableOutputs/SwitchingDevice.provider.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SwitchingDevice.provider.d.ts","sourceRoot":"/","sources":["src/Modules/SwitchableOutputs/SwitchingDevice.provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAA2B,MAAM,SAAS,CAAA;AAEnE,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAA;AAInE,MAAM,MAAM,yBAAyB,GAAG,MAAM,CAAA;AAE9C,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,iBAAiB,EAAE,qBAAqB,EAAE,CAAA;CAC3C;AAED,MAAM,WAAW,qBAAsB,SAAQ,MAAM;IACnD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,eAAO,MAAM,6BAA6B,GAAI,UAAU,QAAQ,EAAE,YAAY,yBAAyB;;;;CAIrG,CAAA;AAEF,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,yBAAyB,GAAG,oBAAoB,CAM9F;AAED,wBAAgB,mBAAmB,6DAiClC"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { useEffect, useMemo } from "react";
|
|
1
2
|
import { useMqtt, useTopicsState } from "../Mqtt";
|
|
2
|
-
import
|
|
3
|
+
import Logger from "../../utils/logger";
|
|
4
|
+
import { useSwitchingDevicesStore } from "./SwitchingDevices.store";
|
|
5
|
+
import { autorun } from "mobx";
|
|
3
6
|
export var getSwitchingDeviceStateTopics = function (portalId, instanceId) { return ({
|
|
4
7
|
productName: "N/".concat(portalId, "/switch/").concat(instanceId, "/ProductName"),
|
|
5
8
|
customName: "N/".concat(portalId, "/switch/").concat(instanceId, "/CustomName"),
|
|
@@ -10,4 +13,34 @@ export function useSwitchingDevice(instanceId) {
|
|
|
10
13
|
var topics = useMemo(function () { return getSwitchingDeviceStateTopics(portalId, instanceId); }, [portalId, instanceId]);
|
|
11
14
|
return useTopicsState(topics);
|
|
12
15
|
}
|
|
16
|
+
export function useSwitchingDevices() {
|
|
17
|
+
var switchingDevicesStore = useSwitchingDevicesStore();
|
|
18
|
+
var getTopics = function (portalId) { return ({
|
|
19
|
+
devices: "N/".concat(portalId, "/switch/+/DeviceInstance"),
|
|
20
|
+
}); };
|
|
21
|
+
var mqtt = useMqtt();
|
|
22
|
+
var topics = useMemo(function () { return getTopics(mqtt.portalId); }, [mqtt.portalId]);
|
|
23
|
+
var messagesForSwitchingDevices = mqtt.messagesByWildcard(topics.devices);
|
|
24
|
+
// Examine MQTT to find all available switching devices
|
|
25
|
+
useEffect(function () {
|
|
26
|
+
if (!messagesForSwitchingDevices || Object.entries(messagesForSwitchingDevices).length === 0) {
|
|
27
|
+
Logger.log("Waiting for switching devices...");
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
var deviceInstances_1 = Object.values(messagesForSwitchingDevices);
|
|
31
|
+
var dispose_1 = autorun(function () {
|
|
32
|
+
var oldDevices = switchingDevicesStore.devices;
|
|
33
|
+
var newDevices = deviceInstances_1.map(function (deviceId) { return mqtt.messagesByTopics(getSwitchingDeviceStateTopics(mqtt.portalId, deviceId)); });
|
|
34
|
+
// TODO: check unordered structural identify of old and new state
|
|
35
|
+
// TODO: to avoid unnecessary re-rendering: O(n^2) baby
|
|
36
|
+
if (!oldDevices || oldDevices.length != newDevices.length || !newDevices.every(function (id) { return deviceInstances_1.includes(id); })) {
|
|
37
|
+
Logger.log("New switching devices instances: ".concat(JSON.stringify(deviceInstances_1)));
|
|
38
|
+
switchingDevicesStore.setDevices(newDevices);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
return function () { return dispose_1(); };
|
|
42
|
+
}
|
|
43
|
+
}, [messagesForSwitchingDevices]);
|
|
44
|
+
return switchingDevicesStore;
|
|
45
|
+
}
|
|
13
46
|
//# sourceMappingURL=SwitchingDevice.provider.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SwitchingDevice.provider.js","sourceRoot":"/","sources":["src/Modules/SwitchableOutputs/SwitchingDevice.provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AACnE,OAAO,
|
|
1
|
+
{"version":3,"file":"SwitchingDevice.provider.js","sourceRoot":"/","sources":["src/Modules/SwitchableOutputs/SwitchingDevice.provider.ts"],"names":[],"mappings":"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","sourcesContent":["import { useEffect, useMemo } from \"react\"\nimport { PortalId, Topics, useMqtt, useTopicsState } from \"../Mqtt\"\nimport Logger from \"../../utils/logger\"\nimport { SwitchableOutputState } from \"./SwitchableOutput.provider\"\nimport { useSwitchingDevicesStore } from \"./SwitchingDevices.store\"\nimport { autorun } from \"mobx\"\n\nexport type SwitchingDeviceInstanceId = number\n\nexport interface SwitchingDeviceState {\n productName: string\n customName: string\n instance: number\n switchableOutputs: SwitchableOutputState[]\n}\n\nexport interface SwitchingDeviceTopics extends Topics {\n productName?: string\n customName?: string\n instance?: string\n}\n\nexport const getSwitchingDeviceStateTopics = (portalId: PortalId, instanceId: SwitchingDeviceInstanceId) => ({\n productName: `N/${portalId}/switch/${instanceId}/ProductName`,\n customName: `N/${portalId}/switch/${instanceId}/CustomName`,\n instance: `N/${portalId}/tank/${instanceId}/DeviceInstance`,\n})\n\nexport function useSwitchingDevice(instanceId: SwitchingDeviceInstanceId): SwitchingDeviceState {\n\n const { portalId } = useMqtt()\n const topics = useMemo(() => getSwitchingDeviceStateTopics(portalId, instanceId), [portalId, instanceId])\n\n return useTopicsState<SwitchingDeviceState>(topics)\n}\n\nexport function useSwitchingDevices() {\n const switchingDevicesStore = useSwitchingDevicesStore()\n\n const getTopics = (portalId: PortalId) => ({\n devices: `N/${portalId}/switch/+/DeviceInstance`,\n })\n\n const mqtt = useMqtt()\n const topics = useMemo(() => getTopics(mqtt.portalId), [mqtt.portalId])\n\n const messagesForSwitchingDevices = mqtt.messagesByWildcard(topics.devices)\n\n // Examine MQTT to find all available switching devices\n useEffect(() => {\n if (!messagesForSwitchingDevices || Object.entries(messagesForSwitchingDevices).length === 0) {\n Logger.log(\"Waiting for switching devices...\")\n } else {\n const deviceInstances = Object.values(messagesForSwitchingDevices) as SwitchingDeviceInstanceId[]\n const dispose = autorun(() => {\n const oldDevices = switchingDevicesStore.devices\n const newDevices = deviceInstances.map((deviceId) => mqtt.messagesByTopics(getSwitchingDeviceStateTopics(mqtt.portalId, deviceId))) as unknown as SwitchingDeviceInstanceId[]\n // TODO: check unordered structural identify of old and new state\n // TODO: to avoid unnecessary re-rendering: O(n^2) baby\n if (!oldDevices || oldDevices.length != newDevices.length || !newDevices.every((id) => deviceInstances.includes(id))) {\n Logger.log(`New switching devices instances: ${JSON.stringify(deviceInstances)}`);\n switchingDevicesStore.setDevices(newDevices)\n }\n })\n return () => dispose()\n }\n }, [messagesForSwitchingDevices])\n\n return switchingDevicesStore\n}"]}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SwitchingDeviceInstanceId } from "./SwitchingDevice.provider";
|
|
2
2
|
export interface SwitchingDevicesState {
|
|
3
|
-
devices:
|
|
3
|
+
devices: SwitchingDeviceInstanceId[];
|
|
4
4
|
}
|
|
5
5
|
export declare class SwitchingDevicesStore {
|
|
6
|
-
devices:
|
|
6
|
+
devices: SwitchingDeviceInstanceId[];
|
|
7
7
|
constructor();
|
|
8
|
-
setDevices: (devices:
|
|
8
|
+
setDevices: (devices: SwitchingDeviceInstanceId[]) => number[];
|
|
9
9
|
}
|
|
10
10
|
export declare function useSwitchingDevicesStore(): SwitchingDevicesStore;
|
|
11
11
|
//# sourceMappingURL=SwitchingDevices.store.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SwitchingDevices.store.d.ts","sourceRoot":"/","sources":["src/Modules/SwitchableOutputs/SwitchingDevices.store.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"SwitchingDevices.store.d.ts","sourceRoot":"/","sources":["src/Modules/SwitchableOutputs/SwitchingDevices.store.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAA;AAItE,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,yBAAyB,EAAE,CAAA;CACrC;AAED,qBAAa,qBAAqB;IAChC,OAAO,EAAE,yBAAyB,EAAE,CAAK;;IAMzC,UAAU,GAAI,SAAS,yBAAyB,EAAE,cAA2B;CAC9E;AAYD,wBAAgB,wBAAwB,0BAEvC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SwitchingDevices.store.js","sourceRoot":"/","sources":["src/Modules/SwitchableOutputs/SwitchingDevices.store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,kBAAkB,
|
|
1
|
+
{"version":3,"file":"SwitchingDevices.store.js","sourceRoot":"/","sources":["src/Modules/SwitchableOutputs/SwitchingDevices.store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,MAAM,CAAA;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAG/B,IAAI,KAA4B,CAAA;AAMhC;IAGE;QAAA,iBAEC;QAJD;;;;mBAAuC,EAAE;WAAA;QAMzC;;;;mBAAa,UAAC,OAAoC,IAAK,OAAA,KAAI,CAAC,OAAO,GAAG,OAAO,EAAtB,CAAsB;WAAA;QAH3E,kBAAkB,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CAAA;IAClD,CAAC;IAGH,4BAAC;AAAD,CAAC,AARD,IAQC;;AAED,SAAS,eAAe;IACtB,IAAM,MAAM,GAAG,KAAK,aAAL,KAAK,cAAL,KAAK,GAAI,IAAI,qBAAqB,EAAE,CAAA;IACnD,4CAA4C;IAC5C,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO,MAAM,CAAA;IAChD,sCAAsC;IACtC,IAAI,CAAC,KAAK;QAAE,KAAK,GAAG,MAAM,CAAA;IAE1B,OAAO,MAAM,CAAA;AACf,CAAC;AAED,MAAM,UAAU,wBAAwB;IACtC,OAAO,OAAO,CAAC,cAAM,OAAA,eAAe,EAAE,EAAjB,CAAiB,EAAE,EAAE,CAAC,CAAA;AAC7C,CAAC","sourcesContent":["import { action, makeAutoObservable } from \"mobx\"\nimport { useMemo } from \"react\"\nimport { SwitchingDeviceInstanceId } from \"./SwitchingDevice.provider\"\n\nlet store: SwitchingDevicesStore\n\nexport interface SwitchingDevicesState {\n devices: SwitchingDeviceInstanceId[]\n}\n\nexport class SwitchingDevicesStore {\n devices: SwitchingDeviceInstanceId[] = []\n\n constructor() {\n makeAutoObservable(this, { setDevices: action })\n }\n\n setDevices = (devices: SwitchingDeviceInstanceId[]) => this.devices = devices\n}\n\nfunction initializeStore() {\n const _store = store ?? new SwitchingDevicesStore()\n // For SSG and SSR always create a new store\n if (typeof window === \"undefined\") return _store\n // Create the store once in the client\n if (!store) store = _store\n\n return _store\n}\n\nexport function useSwitchingDevicesStore() {\n return useMemo(() => initializeStore(), [])\n}"]}
|