@victronenergy/mfd-modules 9.5.0 → 9.5.2

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.
Files changed (23) hide show
  1. package/dist/eslint.config.d.mts +13 -0
  2. package/dist/eslint.config.d.mts.map +1 -0
  3. package/dist/eslint.config.mjs +28 -0
  4. package/dist/eslint.config.mjs.map +1 -0
  5. package/dist/src/Modules/Mqtt/Mqtt.store.d.ts.map +1 -1
  6. package/dist/src/Modules/Mqtt/Mqtt.store.js +0 -1
  7. package/dist/src/Modules/Mqtt/Mqtt.store.js.map +1 -1
  8. package/dist/src/Modules/SwitchableOutputs/SwitchableOutput.provider.d.ts.map +1 -1
  9. package/dist/src/Modules/SwitchableOutputs/SwitchableOutput.provider.js.map +1 -1
  10. package/dist/src/Modules/SwitchableOutputs/SwitchableOutputs.provider.d.ts.map +1 -1
  11. package/dist/src/Modules/SwitchableOutputs/SwitchableOutputs.provider.js +105 -35
  12. package/dist/src/Modules/SwitchableOutputs/SwitchableOutputs.provider.js.map +1 -1
  13. package/dist/src/Modules/SwitchableOutputs/SwitchableOutputs.store.d.ts +13 -0
  14. package/dist/src/Modules/SwitchableOutputs/SwitchableOutputs.store.d.ts.map +1 -1
  15. package/dist/src/Modules/SwitchableOutputs/SwitchableOutputs.store.js +58 -3
  16. package/dist/src/Modules/SwitchableOutputs/SwitchableOutputs.store.js.map +1 -1
  17. package/dist/src/Modules/SwitchableOutputs/SwitchingDevice.provider.d.ts.map +1 -1
  18. package/dist/src/Modules/SwitchableOutputs/SwitchingDevice.provider.js +6 -2
  19. package/dist/src/Modules/SwitchableOutputs/SwitchingDevice.provider.js.map +1 -1
  20. package/dist/src/Modules/SwitchableOutputs/SwitchingDevices.store.d.ts.map +1 -1
  21. package/dist/src/Modules/SwitchableOutputs/SwitchingDevices.store.js +1 -1
  22. package/dist/src/Modules/SwitchableOutputs/SwitchingDevices.store.js.map +1 -1
  23. package/package.json +10 -3
@@ -0,0 +1,13 @@
1
+ declare const _default: ({
2
+ readonly rules: Readonly<import("eslint").Linter.RulesRecord>;
3
+ } | import("typescript-eslint/dist/compatibility-types").CompatibleConfig | {
4
+ files: string[];
5
+ plugins: {
6
+ prettier: import("eslint").ESLint.Plugin;
7
+ };
8
+ rules: {
9
+ 'prettier/prettier': string;
10
+ };
11
+ })[];
12
+ export default _default;
13
+ //# sourceMappingURL=eslint.config.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eslint.config.d.mts","sourceRoot":"/","sources":["eslint.config.mjs"],"names":[],"mappings":""}
@@ -0,0 +1,28 @@
1
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
2
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
3
+ if (ar || !(i in from)) {
4
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
5
+ ar[i] = from[i];
6
+ }
7
+ }
8
+ return to.concat(ar || Array.prototype.slice.call(from));
9
+ };
10
+ import js from '@eslint/js';
11
+ import tseslint from 'typescript-eslint';
12
+ import eslintConfigPrettier from 'eslint-config-prettier';
13
+ import eslintPluginPrettier from 'eslint-plugin-prettier';
14
+ export default __spreadArray(__spreadArray([
15
+ js.configs.recommended
16
+ ], tseslint.configs.recommended, true), [
17
+ {
18
+ files: ['**/*.ts', '**/*.tsx'],
19
+ plugins: {
20
+ prettier: eslintPluginPrettier,
21
+ },
22
+ rules: {
23
+ 'prettier/prettier': 'warn', // or 'error'
24
+ },
25
+ },
26
+ eslintConfigPrettier,
27
+ ], false);
28
+ //# sourceMappingURL=eslint.config.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eslint.config.mjs","sourceRoot":"/","sources":["eslint.config.mjs"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,QAAQ,MAAM,mBAAmB,CAAC;AACzC,OAAO,oBAAoB,MAAM,wBAAwB,CAAC;AAC1D,OAAO,oBAAoB,MAAM,wBAAwB,CAAC;AAE1D;IACE,EAAE,CAAC,OAAO,CAAC,WAAW;GACnB,QAAQ,CAAC,OAAO,CAAC,WAAW;IAC/B;QACE,KAAK,EAAE,CAAC,SAAS,EAAE,UAAU,CAAC;QAC9B,OAAO,EAAE;YACP,QAAQ,EAAE,oBAAoB;SAC/B;QACD,KAAK,EAAE;YACL,mBAAmB,EAAE,MAAM,EAAE,aAAa;SAC3C;KACF;IACD,oBAAoB;UACpB","sourcesContent":["import js from '@eslint/js';\nimport tseslint from 'typescript-eslint';\nimport eslintConfigPrettier from 'eslint-config-prettier';\nimport eslintPluginPrettier from 'eslint-plugin-prettier';\n\nexport default [\n js.configs.recommended,\n ...tseslint.configs.recommended,\n {\n files: ['**/*.ts', '**/*.tsx'],\n plugins: {\n prettier: eslintPluginPrettier,\n },\n rules: {\n 'prettier/prettier': 'warn', // or 'error'\n },\n },\n eslintConfigPrettier,\n];\n"]}
@@ -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;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
+ {"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,UAU7D;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"}
@@ -226,7 +226,6 @@ var MqttStore = /** @class */ (function () {
226
226
  var _a, _b;
227
227
  // Logger.log(`DEBUG: addMessage: topic: ${topic}, urgentPrefixes: ${JSON.stringify(this.urgentTopicPrefixes)}`)
228
228
  if (_this.urgentTopicPrefixes.some(function (prefix) { return topic.startsWith(prefix); })) {
229
- Logger.log("DEBUG: addMessage: topic: ".concat(topic));
230
229
  // NOTE: If topic starts with one of the urgent prefixes, deliver it immediately
231
230
  _this.messages[topic] = (_a = message.value) !== null && _a !== void 0 ? _a : undefined;
232
231
  }
@@ -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 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}"]}
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 // 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}"]}
@@ -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,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"}
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,GACzC,UAAU,QAAQ,EAClB,UAAU,yBAAyB,EACnC,UAAU,kBAAkB;;;;;;;;;;;;;;;;CAiB5B,CAAA;AAEF,eAAO,MAAM,8BAA8B,GACzC,UAAU,QAAQ,EAClB,UAAU,yBAAyB,EACnC,UAAU,kBAAkB;;;;CAK5B,CAAA;AAEF,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,yBAAyB,EACnC,QAAQ,EAAE,kBAAkB,GAC3B,wBAAwB,CAgB1B"}
@@ -1 +1 @@
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
+ {"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 = (\n portalId: PortalId,\n deviceId: SwitchingDeviceInstanceId,\n outputId: SwitchableOutputId\n) => ({\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 = (\n portalId: PortalId,\n deviceId: SwitchingDeviceInstanceId,\n outputId: SwitchableOutputId\n) => ({\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(\n deviceId: SwitchingDeviceInstanceId,\n outputId: SwitchableOutputId\n): SwitchableOutputProvider {\n const mqtt = useMqtt()\n const topics = useMemo(\n () => getSwitchableOutputStateTopics(mqtt.portalId, deviceId, outputId),\n [mqtt.portalId, deviceId, outputId]\n )\n const writeTopics = useMemo(\n () => getSwitchableOutputWriteTopics(mqtt.portalId, deviceId, outputId),\n [mqtt.portalId, deviceId, outputId]\n )\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,kEA6DhC,CAAA"}
1
+ {"version":3,"file":"SwitchableOutputs.provider.d.ts","sourceRoot":"/","sources":["src/Modules/SwitchableOutputs/SwitchableOutputs.provider.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,oBAAoB,kEA6IhC,CAAA"}
@@ -20,62 +20,132 @@ export var useSwitchableOutputs = function () {
20
20
  var switchableOutputsStore = useSwitchableOutputsStore();
21
21
  var getTopics = function (portalId) { return ({
22
22
  switchableOutputs: "N/".concat(portalId, "/switch/+/SwitchableOutput/+/Settings/+"),
23
+ switchingDevices: "N/".concat(portalId, "/switch/+"),
23
24
  }); };
24
25
  var mqtt = useMqtt();
25
26
  var topics = useMemo(function () { return getTopics(mqtt.portalId); }, [mqtt.portalId]);
26
27
  var messagesForSwitchableOutputs = mqtt.messagesByWildcard(topics.switchableOutputs);
28
+ var messagesForSwitchingDevices = mqtt.messagesByWildcard(topics.switchingDevices);
27
29
  // Examine MQTT to find all available switchable outputs and their group assignments
28
30
  useEffect(function () {
29
31
  if (!messagesForSwitchableOutputs || Object.entries(messagesForSwitchableOutputs).length === 0) {
30
32
  Logger.log("Waiting for switchable outputs...");
31
33
  }
32
34
  else {
35
+ // All switchable outputs in array sorted by topic
33
36
  var availableSwitchableOutputs_1 = Object.keys(messagesForSwitchableOutputs)
34
- .filter(function (key) { return key.endsWith('/Settings/Group'); })
37
+ .filter(function (key) { return key.endsWith("/Settings/Group"); })
35
38
  .sort();
36
- var customGroupAssigments_1 = availableSwitchableOutputs_1
37
- .filter(function (topic) { return topic.endsWith('/Settings/Group'); })
38
- .map(function (topic) { return messagesForSwitchableOutputs[topic]; });
39
+ // All switchable outputs group assignments in array sorted by topic
40
+ var customGroupAssigments_1 = availableSwitchableOutputs_1.map(function (topic) {
41
+ return messagesForSwitchableOutputs[topic];
42
+ });
43
+ // All switchable outputs types in array sorted by topic
44
+ var availableSwitchableOutputTypes_1 = availableSwitchableOutputs_1.map(function (topic) {
45
+ return messagesForSwitchableOutputs["".concat(topic.slice(0, -"/Group".length), "/Type")];
46
+ });
47
+ // All switchable outputs visibility in array sorted by topic
48
+ var availableSwitchableOutputVisibilityFlags_1 = availableSwitchableOutputs_1.map(function (topic) {
49
+ return messagesForSwitchableOutputs["".concat(topic.slice(0, -"/Group".length), "/ShowUIControl")];
50
+ });
51
+ // All switching devices in array sorted by instance number
52
+ var availableSwitchingDevices_1 = Object.keys(messagesForSwitchingDevices)
53
+ .filter(function (key) { return key.endsWith("/DeviceInstance"); })
54
+ .sort();
55
+ // All switching device names in array sorted by instance number
56
+ var availableSwitchingDeviceNames_1 = availableSwitchingDevices_1.map(function (topic) {
57
+ var topicPrefix = topic.slice(0, -"/DeviceInstance".length);
58
+ return (messagesForSwitchingDevices["".concat(topicPrefix, "/CustomName")] ||
59
+ messagesForSwitchingDevices["".concat(topicPrefix, "/ProductName")]);
60
+ });
39
61
  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);
62
+ var oldAssignments = switchableOutputsStore.customGroupAssignments;
63
+ var newAssignments = customGroupAssigments_1;
64
+ var groupAssignmentsChanged = !arraysEqual(oldAssignments, newAssignments);
65
+ if (groupAssignmentsChanged) {
66
+ switchableOutputsStore.setCustomGroupAssignments(newAssignments);
67
+ Logger.log("Switchable outputs group assignments changed, recomputing...");
68
+ }
69
+ var oldOutputTypes = switchableOutputsStore.outputTypes;
70
+ var newOutputTypes = availableSwitchableOutputTypes_1;
71
+ var outputTypesChanged = !arraysEqual(oldOutputTypes, newOutputTypes);
72
+ if (outputTypesChanged) {
73
+ switchableOutputsStore.setOutputTypes(newOutputTypes);
74
+ Logger.log("Switchable outputs types changed, recomputing...");
75
+ }
76
+ var oldOutputVisibilityFlags = switchableOutputsStore.outputVisibilityFlags;
77
+ var newOutputVisibilityFlags = availableSwitchableOutputVisibilityFlags_1;
78
+ var outputVisibilityFlagsChanged = !arraysEqual(oldOutputVisibilityFlags, newOutputVisibilityFlags);
79
+ if (outputVisibilityFlagsChanged) {
80
+ switchableOutputsStore.setOutputVisibilityFlags(newOutputVisibilityFlags);
81
+ Logger.log("Switchable outputs visibility flags changed, recomputing...");
82
+ }
83
+ var oldSwitchingDevices = switchableOutputsStore.switchingDevices;
84
+ var newSwitchingDevices = availableSwitchingDevices_1;
85
+ var switchingDevicesChanged = !arraysEqual(oldSwitchingDevices, newSwitchingDevices);
86
+ if (switchingDevicesChanged) {
87
+ switchableOutputsStore.setSwitchingDevices(newSwitchingDevices);
88
+ Logger.log("Switching devices changed, recomputing...");
89
+ }
90
+ var oldSwitchingDeviceNames = switchableOutputsStore.switchingDeviceNames;
91
+ var newSwitchingDeviceNames = availableSwitchingDeviceNames_1;
92
+ var switchingDeviceNamesChanged = !arraysEqual(oldSwitchingDeviceNames, newSwitchingDeviceNames);
93
+ if (switchingDeviceNamesChanged) {
94
+ switchableOutputsStore.setSwitchingDeviceNames(newSwitchingDeviceNames);
95
+ Logger.log("Switching device names changed, recomputing...");
96
+ }
97
+ if (groupAssignmentsChanged ||
98
+ outputTypesChanged ||
99
+ outputVisibilityFlagsChanged ||
100
+ switchingDevicesChanged ||
101
+ switchingDeviceNamesChanged) {
102
+ // New groups mapping array of switches to group name key
103
+ var newGroups_1 = {};
104
+ // Walk the array of all switchable outputs, determine to which group it belongs
105
+ // and populate its initial state
106
+ availableSwitchableOutputs_1.forEach(function (output, index) {
107
+ var swo = extractSwitchableOutputInfo(output);
108
+ var switchingDevice = mqtt.messagesByTopics(getSwitchingDeviceStateTopics(mqtt.portalId, swo.deviceId));
109
+ var customGroupAssignment = customGroupAssigments_1[index].trim();
110
+ var groupName = customGroupAssignment === ""
111
+ ? switchingDevice.customName || switchingDevice.productName
112
+ : customGroupAssignment;
113
+ var switchableOutput = mqtt.messagesByTopics(getSwitchableOutputStateTopics(mqtt.portalId, swo.deviceId, swo.outputId));
114
+ // Ignore hidden controls
115
+ if (switchableOutput.showUIControl === 0) {
116
+ return;
117
+ }
118
+ newGroups_1[groupName] || (newGroups_1[groupName] = []);
119
+ newGroups_1[groupName].push(__assign(__assign({}, switchableOutput), { deviceId: swo.deviceId, outputId: swo.outputId }));
120
+ });
121
+ Logger.log("New switchable output groups: ".concat(JSON.stringify(Object.keys(newGroups_1))));
122
+ // Sort switches in a group by name
123
+ Object.values(newGroups_1).forEach(function (array) {
124
+ array.sort(function (a, b) {
125
+ var aName = a.customName || a.name;
126
+ var bName = b.customName || b.name;
127
+ return aName.localeCompare(bName);
128
+ });
64
129
  });
65
- });
66
- switchableOutputsStore.setGroups(newGroups);
130
+ switchableOutputsStore.setGroups(newGroups_1);
131
+ }
67
132
  });
68
133
  return function () { return dispose_1(); };
69
134
  }
70
- }, [messagesForSwitchableOutputs]);
135
+ }, [messagesForSwitchableOutputs, messagesForSwitchingDevices]);
71
136
  return switchableOutputsStore;
72
137
  };
73
138
  function extractSwitchableOutputInfo(topic) {
74
- var switchStart = topic.indexOf('/switch/') + 8; // length of `/switch/`
75
- var outputStart = topic.indexOf('/SwitchableOutput/') + 18; // length of `/SwitchableOutput/`
139
+ var switchStart = topic.indexOf("/switch/") + 8; // length of `/switch/`
140
+ var outputStart = topic.indexOf("/SwitchableOutput/") + 18; // length of `/SwitchableOutput/`
76
141
  return {
77
- deviceId: topic.substring(switchStart, topic.indexOf('/', switchStart)),
78
- outputId: topic.substring(outputStart, topic.indexOf('/', outputStart))
142
+ deviceId: topic.substring(switchStart, topic.indexOf("/", switchStart)),
143
+ outputId: topic.substring(outputStart, topic.indexOf("/", outputStart)),
79
144
  };
80
145
  }
146
+ function arraysEqual(a, b) {
147
+ if (a.length !== b.length)
148
+ return false;
149
+ return a.every(function (element, index) { return b[index] === element; });
150
+ }
81
151
  //# sourceMappingURL=SwitchableOutputs.provider.js.map
@@ -1 +1 @@
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
+ {"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 switchingDevices: `N/${portalId}/switch/+`,\n })\n\n const mqtt = useMqtt()\n const topics = useMemo(() => getTopics(mqtt.portalId), [mqtt.portalId])\n\n const messagesForSwitchableOutputs = mqtt.messagesByWildcard(topics.switchableOutputs)\n const messagesForSwitchingDevices = mqtt.messagesByWildcard(topics.switchingDevices)\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 // All switchable outputs in array sorted by topic\n const availableSwitchableOutputs = Object.keys(messagesForSwitchableOutputs)\n .filter((key) => key.endsWith(\"/Settings/Group\"))\n .sort() as string[]\n\n // All switchable outputs group assignments in array sorted by topic\n const customGroupAssigments = availableSwitchableOutputs.map((topic) => {\n return messagesForSwitchableOutputs[topic]\n })\n // All switchable outputs types in array sorted by topic\n const availableSwitchableOutputTypes = availableSwitchableOutputs.map((topic) => {\n return messagesForSwitchableOutputs[`${topic.slice(0, -\"/Group\".length)}/Type`]\n })\n // All switchable outputs visibility in array sorted by topic\n const availableSwitchableOutputVisibilityFlags = availableSwitchableOutputs.map((topic) => {\n return messagesForSwitchableOutputs[`${topic.slice(0, -\"/Group\".length)}/ShowUIControl`]\n })\n\n // All switching devices in array sorted by instance number\n const availableSwitchingDevices = Object.keys(messagesForSwitchingDevices)\n .filter((key) => key.endsWith(\"/DeviceInstance\"))\n .sort() as string[]\n // All switching device names in array sorted by instance number\n const availableSwitchingDeviceNames = availableSwitchingDevices.map((topic) => {\n const topicPrefix = topic.slice(0, -\"/DeviceInstance\".length)\n return (\n messagesForSwitchingDevices[`${topicPrefix}/CustomName`] ||\n messagesForSwitchingDevices[`${topicPrefix}/ProductName`]\n )\n })\n\n const dispose = autorun(() => {\n const oldAssignments = switchableOutputsStore.customGroupAssignments\n const newAssignments = customGroupAssigments\n const groupAssignmentsChanged = !arraysEqual(oldAssignments, newAssignments)\n if (groupAssignmentsChanged) {\n switchableOutputsStore.setCustomGroupAssignments(newAssignments)\n Logger.log(`Switchable outputs group assignments changed, recomputing...`)\n }\n\n const oldOutputTypes = switchableOutputsStore.outputTypes\n const newOutputTypes = availableSwitchableOutputTypes\n const outputTypesChanged = !arraysEqual(oldOutputTypes, newOutputTypes)\n if (outputTypesChanged) {\n switchableOutputsStore.setOutputTypes(newOutputTypes)\n Logger.log(`Switchable outputs types changed, recomputing...`)\n }\n\n const oldOutputVisibilityFlags = switchableOutputsStore.outputVisibilityFlags\n const newOutputVisibilityFlags = availableSwitchableOutputVisibilityFlags\n const outputVisibilityFlagsChanged = !arraysEqual(oldOutputVisibilityFlags, newOutputVisibilityFlags)\n if (outputVisibilityFlagsChanged) {\n switchableOutputsStore.setOutputVisibilityFlags(newOutputVisibilityFlags)\n Logger.log(`Switchable outputs visibility flags changed, recomputing...`)\n }\n\n const oldSwitchingDevices = switchableOutputsStore.switchingDevices\n const newSwitchingDevices = availableSwitchingDevices\n const switchingDevicesChanged = !arraysEqual(oldSwitchingDevices, newSwitchingDevices)\n if (switchingDevicesChanged) {\n switchableOutputsStore.setSwitchingDevices(newSwitchingDevices)\n Logger.log(`Switching devices changed, recomputing...`)\n }\n\n const oldSwitchingDeviceNames = switchableOutputsStore.switchingDeviceNames\n const newSwitchingDeviceNames = availableSwitchingDeviceNames\n const switchingDeviceNamesChanged = !arraysEqual(oldSwitchingDeviceNames, newSwitchingDeviceNames)\n if (switchingDeviceNamesChanged) {\n switchableOutputsStore.setSwitchingDeviceNames(newSwitchingDeviceNames)\n Logger.log(`Switching device names changed, recomputing...`)\n }\n\n if (\n groupAssignmentsChanged ||\n outputTypesChanged ||\n outputVisibilityFlagsChanged ||\n switchingDevicesChanged ||\n switchingDeviceNamesChanged\n ) {\n // New groups mapping array of switches to group name key\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 =\n customGroupAssignment === \"\"\n ? switchingDevice.customName || switchingDevice.productName\n : customGroupAssignment\n const switchableOutput = mqtt.messagesByTopics(\n getSwitchableOutputStateTopics(mqtt.portalId, swo.deviceId, swo.outputId)\n ) as unknown as SwitchableOutputState\n\n // Ignore hidden controls\n if (switchableOutput.showUIControl === 0) {\n return\n }\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, messagesForSwitchingDevices])\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}\n\nfunction arraysEqual<T>(a: T[], b: T[]): boolean {\n if (a.length !== b.length) return false\n return a.every((element, index) => b[index] === element)\n}\n"]}
@@ -1,15 +1,24 @@
1
1
  import { SwitchableOutputState } from "./SwitchableOutput.provider";
2
+ import { SwitchableOutputType } from "utils/constants";
2
3
  export interface SwitchableOutputsState {
3
4
  groups: {
4
5
  [key: string]: SwitchableOutputState[];
5
6
  };
6
7
  customGroupAssignments: string[];
8
+ outputTypes: SwitchableOutputType[];
9
+ outputVisibilityFlags: (0 | 1)[];
10
+ switchingDevices: string[];
11
+ switchingDeviceNames: string[];
7
12
  }
8
13
  export declare class SwitchableOutputsStore {
9
14
  groups: {
10
15
  [key: string]: SwitchableOutputState[];
11
16
  };
12
17
  customGroupAssignments: string[];
18
+ outputTypes: SwitchableOutputType[];
19
+ outputVisibilityFlags: (0 | 1)[];
20
+ switchingDevices: string[];
21
+ switchingDeviceNames: string[];
13
22
  constructor();
14
23
  setGroups: (groups: {
15
24
  [key: string]: SwitchableOutputState[];
@@ -17,6 +26,10 @@ export declare class SwitchableOutputsStore {
17
26
  [key: string]: SwitchableOutputState[];
18
27
  };
19
28
  setCustomGroupAssignments: (assignments: string[]) => string[];
29
+ setOutputTypes: (outputTypes: SwitchableOutputType[]) => SwitchableOutputType[];
30
+ setOutputVisibilityFlags: (outputVisibilityFlags: (0 | 1)[]) => (0 | 1)[];
31
+ setSwitchingDevices: (switchingDevices: string[]) => string[];
32
+ setSwitchingDeviceNames: (switchingDeviceNames: string[]) => string[];
20
33
  }
21
34
  export declare function useSwitchableOutputsStore(): SwitchableOutputsStore;
22
35
  //# sourceMappingURL=SwitchableOutputs.store.d.ts.map
@@ -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;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"}
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;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AAItD,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,qBAAqB,EAAE,CAAA;KAAE,CAAA;IAElD,sBAAsB,EAAE,MAAM,EAAE,CAAA;IAEhC,WAAW,EAAE,oBAAoB,EAAE,CAAA;IAEnC,qBAAqB,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAA;IAEhC,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAE1B,oBAAoB,EAAE,MAAM,EAAE,CAAA;CAC/B;AAED,qBAAa,sBAAsB;IACjC,MAAM,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,qBAAqB,EAAE,CAAA;KAAE,CAAK;IACvD,sBAAsB,EAAE,MAAM,EAAE,CAAK;IACrC,WAAW,EAAE,oBAAoB,EAAE,CAAK;IACxC,qBAAqB,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAK;IACrC,gBAAgB,EAAE,MAAM,EAAE,CAAK;IAC/B,oBAAoB,EAAE,MAAM,EAAE,CAAK;;IAanC,SAAS,GAAI,QAAQ;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,qBAAqB,EAAE,CAAA;KAAE;;MAA2B;IAC1F,yBAAyB,GAAI,aAAa,MAAM,EAAE,cAAgD;IAClG,cAAc,GAAI,aAAa,oBAAoB,EAAE,4BAAqC;IAC1F,wBAAwB,GAAI,uBAAuB,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,eAAyD;IACrH,mBAAmB,GAAI,kBAAkB,MAAM,EAAE,cAA+C;IAChG,uBAAuB,GAAI,sBAAsB,MAAM,EAAE,cAAuD;CACjH;AAYD,wBAAgB,yBAAyB,2BAExC"}
@@ -16,19 +16,74 @@ var SwitchableOutputsStore = /** @class */ (function () {
16
16
  writable: true,
17
17
  value: []
18
18
  });
19
+ Object.defineProperty(this, "outputTypes", {
20
+ enumerable: true,
21
+ configurable: true,
22
+ writable: true,
23
+ value: []
24
+ });
25
+ Object.defineProperty(this, "outputVisibilityFlags", {
26
+ enumerable: true,
27
+ configurable: true,
28
+ writable: true,
29
+ value: []
30
+ });
31
+ Object.defineProperty(this, "switchingDevices", {
32
+ enumerable: true,
33
+ configurable: true,
34
+ writable: true,
35
+ value: []
36
+ });
37
+ Object.defineProperty(this, "switchingDeviceNames", {
38
+ enumerable: true,
39
+ configurable: true,
40
+ writable: true,
41
+ value: []
42
+ });
19
43
  Object.defineProperty(this, "setGroups", {
20
44
  enumerable: true,
21
45
  configurable: true,
22
46
  writable: true,
23
- value: function (groups) { return _this.groups = groups; }
47
+ value: function (groups) { return (_this.groups = groups); }
24
48
  });
25
49
  Object.defineProperty(this, "setCustomGroupAssignments", {
26
50
  enumerable: true,
27
51
  configurable: true,
28
52
  writable: true,
29
- value: function (assignments) { return _this.customGroupAssignments = assignments; }
53
+ value: function (assignments) { return (_this.customGroupAssignments = assignments); }
54
+ });
55
+ Object.defineProperty(this, "setOutputTypes", {
56
+ enumerable: true,
57
+ configurable: true,
58
+ writable: true,
59
+ value: function (outputTypes) { return (_this.outputTypes = outputTypes); }
60
+ });
61
+ Object.defineProperty(this, "setOutputVisibilityFlags", {
62
+ enumerable: true,
63
+ configurable: true,
64
+ writable: true,
65
+ value: function (outputVisibilityFlags) { return (_this.outputVisibilityFlags = outputVisibilityFlags); }
66
+ });
67
+ Object.defineProperty(this, "setSwitchingDevices", {
68
+ enumerable: true,
69
+ configurable: true,
70
+ writable: true,
71
+ value: function (switchingDevices) { return (_this.switchingDevices = switchingDevices); }
72
+ });
73
+ Object.defineProperty(this, "setSwitchingDeviceNames", {
74
+ enumerable: true,
75
+ configurable: true,
76
+ writable: true,
77
+ value: function (switchingDeviceNames) { return (_this.switchingDeviceNames = switchingDeviceNames); }
78
+ });
79
+ makeAutoObservable(this, {
80
+ setGroups: action,
81
+ setCustomGroupAssignments: action,
82
+ setOutputTypes: action,
83
+ setOutputVisibilityFlags: action,
84
+ setSwitchingDevices: action,
85
+ setSwitchingDeviceNames: action,
30
86
  });
31
- makeAutoObservable(this, { setGroups: action, setCustomGroupAssignments: action });
32
87
  }
33
88
  return SwitchableOutputsStore;
34
89
  }());
@@ -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;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}"]}
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;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAI/B,IAAI,KAA6B,CAAA;AAgBjC;IAQE;QAAA,iBASC;QAhBD;;;;mBAAqD,EAAE;WAAA;QACvD;;;;mBAAmC,EAAE;WAAA;QACrC;;;;mBAAsC,EAAE;WAAA;QACxC;;;;mBAAmC,EAAE;WAAA;QACrC;;;;mBAA6B,EAAE;WAAA;QAC/B;;;;mBAAiC,EAAE;WAAA;QAanC;;;;mBAAY,UAAC,MAAkD,IAAK,OAAA,CAAC,KAAI,CAAC,MAAM,GAAG,MAAM,CAAC,EAAtB,CAAsB;WAAA;QAC1F;;;;mBAA4B,UAAC,WAAqB,IAAK,OAAA,CAAC,KAAI,CAAC,sBAAsB,GAAG,WAAW,CAAC,EAA3C,CAA2C;WAAA;QAClG;;;;mBAAiB,UAAC,WAAmC,IAAK,OAAA,CAAC,KAAI,CAAC,WAAW,GAAG,WAAW,CAAC,EAAhC,CAAgC;WAAA;QAC1F;;;;mBAA2B,UAAC,qBAAgC,IAAK,OAAA,CAAC,KAAI,CAAC,qBAAqB,GAAG,qBAAqB,CAAC,EAApD,CAAoD;WAAA;QACrH;;;;mBAAsB,UAAC,gBAA0B,IAAK,OAAA,CAAC,KAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC,EAA1C,CAA0C;WAAA;QAChG;;;;mBAA0B,UAAC,oBAA8B,IAAK,OAAA,CAAC,KAAI,CAAC,oBAAoB,GAAG,oBAAoB,CAAC,EAAlD,CAAkD;WAAA;QAf9G,kBAAkB,CAAC,IAAI,EAAE;YACvB,SAAS,EAAE,MAAM;YACjB,yBAAyB,EAAE,MAAM;YACjC,cAAc,EAAE,MAAM;YACtB,wBAAwB,EAAE,MAAM;YAChC,mBAAmB,EAAE,MAAM;YAC3B,uBAAuB,EAAE,MAAM;SAChC,CAAC,CAAA;IACJ,CAAC;IAQH,6BAAC;AAAD,CAAC,AAzBD,IAyBC;;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 } from \"mobx\"\nimport { useMemo } from \"react\"\nimport { SwitchableOutputState } from \"./SwitchableOutput.provider\"\nimport { SwitchableOutputType } from \"utils/constants\"\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 // types of switchable outputs sorted by their topic path\n outputTypes: SwitchableOutputType[]\n // visibility status of switchable outputs sorted by their topic path\n outputVisibilityFlags: (0 | 1)[]\n // switching devices\n switchingDevices: string[]\n // switching devices custom names\n switchingDeviceNames: string[]\n}\n\nexport class SwitchableOutputsStore {\n groups: { [key: string]: SwitchableOutputState[] } = {}\n customGroupAssignments: string[] = []\n outputTypes: SwitchableOutputType[] = []\n outputVisibilityFlags: (0 | 1)[] = []\n switchingDevices: string[] = []\n switchingDeviceNames: string[] = []\n\n constructor() {\n makeAutoObservable(this, {\n setGroups: action,\n setCustomGroupAssignments: action,\n setOutputTypes: action,\n setOutputVisibilityFlags: action,\n setSwitchingDevices: action,\n setSwitchingDeviceNames: action,\n })\n }\n\n setGroups = (groups: { [key: string]: SwitchableOutputState[] }) => (this.groups = groups)\n setCustomGroupAssignments = (assignments: string[]) => (this.customGroupAssignments = assignments)\n setOutputTypes = (outputTypes: SwitchableOutputType[]) => (this.outputTypes = outputTypes)\n setOutputVisibilityFlags = (outputVisibilityFlags: (0 | 1)[]) => (this.outputVisibilityFlags = outputVisibilityFlags)\n setSwitchingDevices = (switchingDevices: string[]) => (this.switchingDevices = switchingDevices)\n setSwitchingDeviceNames = (switchingDeviceNames: string[]) => (this.switchingDeviceNames = switchingDeviceNames)\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}\n"]}
@@ -1 +1 @@
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
+ {"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,CAK9F;AAED,wBAAgB,mBAAmB,6DAuClC"}
@@ -30,10 +30,14 @@ export function useSwitchingDevices() {
30
30
  var deviceInstances_1 = Object.values(messagesForSwitchingDevices);
31
31
  var dispose_1 = autorun(function () {
32
32
  var oldDevices = switchingDevicesStore.devices;
33
- var newDevices = deviceInstances_1.map(function (deviceId) { return mqtt.messagesByTopics(getSwitchingDeviceStateTopics(mqtt.portalId, deviceId)); });
33
+ var newDevices = deviceInstances_1.map(function (deviceId) {
34
+ return mqtt.messagesByTopics(getSwitchingDeviceStateTopics(mqtt.portalId, deviceId));
35
+ });
34
36
  // TODO: check unordered structural identify of old and new state
35
37
  // 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); })) {
38
+ if (oldDevices.length === 0 ||
39
+ oldDevices.length != newDevices.length ||
40
+ !newDevices.every(function (id) { return deviceInstances_1.includes(id); })) {
37
41
  Logger.log("New switching devices instances: ".concat(JSON.stringify(deviceInstances_1)));
38
42
  switchingDevicesStore.setDevices(newDevices);
39
43
  }
@@ -1 +1 @@
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
+ {"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 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) =>\n mqtt.messagesByTopics(getSwitchingDeviceStateTopics(mqtt.portalId, deviceId))\n ) 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 (\n oldDevices.length === 0 ||\n oldDevices.length != newDevices.length ||\n !newDevices.every((id) => deviceInstances.includes(id))\n ) {\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}\n"]}
@@ -1 +1 @@
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
+ {"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,cAA6B;CAChF;AAYD,wBAAgB,wBAAwB,0BAEvC"}
@@ -14,7 +14,7 @@ var SwitchingDevicesStore = /** @class */ (function () {
14
14
  enumerable: true,
15
15
  configurable: true,
16
16
  writable: true,
17
- value: function (devices) { return _this.devices = devices; }
17
+ value: function (devices) { return (_this.devices = devices); }
18
18
  });
19
19
  makeAutoObservable(this, { setDevices: action });
20
20
  }
@@ -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,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}"]}
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,CAAC,KAAI,CAAC,OAAO,GAAG,OAAO,CAAC,EAAxB,CAAwB;WAAA;QAH7E,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}\n"]}
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "@victronenergy/mfd-modules",
3
- "version": "9.5.0",
3
+ "version": "9.5.2",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "scripts": {
8
8
  "test": "echo \"Error: no test specified\" && exit 1",
9
9
  "build": "tsc",
10
- "semantic-release": "semantic-release"
10
+ "semantic-release": "semantic-release",
11
+ "lint": "eslint src/ --fix"
11
12
  },
12
13
  "publishConfig": {
13
14
  "access": "public"
@@ -28,13 +29,19 @@
28
29
  "mqtt": "^4.3.8"
29
30
  },
30
31
  "devDependencies": {
32
+ "@eslint/js": "^9.37.0",
31
33
  "@semantic-release/git": "^10.0.1",
32
34
  "@semantic-release/npm": "^12.0.2",
33
35
  "@types/js-cookie": "^3.0.6",
34
36
  "@types/lodash-es": "^4.17.12",
35
37
  "@types/react": "^18.3.11",
38
+ "eslint": "^9.37.0",
39
+ "eslint-config-prettier": "^10.1.8",
40
+ "eslint-plugin-prettier": "^5.5.4",
41
+ "prettier": "^3.6.2",
36
42
  "semantic-release": "^24.2.9",
37
- "typescript": "^5.9.3"
43
+ "typescript": "^5.9.3",
44
+ "typescript-eslint": "^8.46.0"
38
45
  },
39
46
  "peerDependencies": {
40
47
  "react": "17 || 18"