@victronenergy/mfd-modules 11.1.1 → 11.1.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.
@@ -1 +1 @@
1
- {"version":3,"file":"Mqtt.store.d.ts","sourceRoot":"/","sources":["src/Modules/Mqtt/Mqtt.store.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,qBAAqB,EAAE,UAAU,EAAE,MAAM,MAAM,CAAA;AACxD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAU,MAAM,EAAE,MAAM,SAAS,CAAA;AAQ7E,qBAAa,SAAS;IACpB,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,UAAU,CAAC,OAAO,WAAW,CAAC,GAAG,SAAS,CAAA;IAC/D,WAAW,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,SAAS,CAAA;IACtD,2BAA2B,EAAE,MAAM,CAAI;IACvC,mBAAmB,EAAE,MAAM,EAAE,CAAK;IAClC,mBAAmB,EAAE,OAAO,CAAQ;IAEpC;;;;;;;;;;;;;;;;OAgBG;IACH,gBAAgB,WACL,MAAM,iBAMhB;IAED;;;;;;;;;;;;;;;;;;UAkBM;IACN,gBAAgB,YACJ,MAAM;;MAsBjB;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,kBAAkB,cACJ,MAAM,SAsBnB;;IAqBD,IAAI,WAAW,YAEd;IAED,gBAAgB,GAAI,QAAQ,MAAM,UAqBjC;IAED,qBAAqB;IASrB,UAAU,GAAI,OAAO,MAAM,EAAE,SAAS;QAAE,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,UAUlE;IAED,mBAAmB,aAGlB;IAED,oBAAoB,aAOnB;IAED,2BAA2B,GAAI,SAAS,MAAM,UAW7C;IAED,gBAAgB,aAKf;IAED,iBAAiB,aAKhB;IAED,WAAW,GAAI,UAAU,MAAM,UAO9B;IAED,SAAS,CAAC,MAAM,EAAE,MAAM;IAIxB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO;IAIvC,IAAI,GACF,UAAU,MAAM,EAChB,MAAM,MAAM,YAAc,EAC1B,MAAM,MAAM,GAAG,IAAI,EACnB,OAAM,MAAyB,EAC/B,SAAQ,OAAe,EACvB,WAAW,MAAM,UAoGlB;IAED,oBAAoB,aA4BnB;IAED,uBAAuB,aAQtB;IAED,iBAAiB,aAOhB;IAED,mBAAmB,aAMlB;IAED,mBAAmB,aAMlB;IAED,OAAO,GAAI,OAAO,MAAM,EAAE,MAAM,MAAM,GAAG,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,EAAE,UAAU,qBAAqB,UAWjG;CACF;AA2BD,wBAAgB,OAAO,cAEtB"}
1
+ {"version":3,"file":"Mqtt.store.d.ts","sourceRoot":"/","sources":["src/Modules/Mqtt/Mqtt.store.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,qBAAqB,EAAE,UAAU,EAAE,MAAM,MAAM,CAAA;AACxD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAU,MAAM,EAAE,MAAM,SAAS,CAAA;AAQ7E,qBAAa,SAAS;IACpB,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,UAAU,CAAC,OAAO,WAAW,CAAC,GAAG,SAAS,CAAA;IAC/D,WAAW,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,SAAS,CAAA;IACtD,2BAA2B,EAAE,MAAM,CAAI;IACvC,mBAAmB,EAAE,MAAM,EAAE,CAAK;IAClC,mBAAmB,EAAE,OAAO,CAAQ;IAEpC;;;;;;;;;;;;;;;;OAgBG;IACH,gBAAgB,WACL,MAAM,iBAMhB;IAED;;;;;;;;;;;;;;;;;;UAkBM;IACN,gBAAgB,YACJ,MAAM;;MAsBjB;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,kBAAkB,cACJ,MAAM,SAsBnB;;IAqBD,IAAI,WAAW,YAEd;IAED,gBAAgB,GAAI,QAAQ,MAAM,UAqBjC;IAED,qBAAqB;IASrB,UAAU,GAAI,OAAO,MAAM,EAAE,SAAS;QAAE,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,UAUlE;IAED,mBAAmB,aAGlB;IAED,oBAAoB,aAQnB;IAED,2BAA2B,GAAI,SAAS,MAAM,UAW7C;IAED,gBAAgB,aAKf;IAED,iBAAiB,aAKhB;IAED,WAAW,GAAI,UAAU,MAAM,UAO9B;IAED,SAAS,CAAC,MAAM,EAAE,MAAM;IAIxB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO;IAIvC,IAAI,GACF,UAAU,MAAM,EAChB,MAAM,MAAM,YAAc,EAC1B,MAAM,MAAM,GAAG,IAAI,EACnB,OAAM,MAAyB,EAC/B,SAAQ,OAAe,EACvB,WAAW,MAAM,UAqGlB;IAED,oBAAoB,aA4BnB;IAED,uBAAuB,aAOtB;IAED,iBAAiB,aAOhB;IAED,mBAAmB,aAMlB;IAED,mBAAmB,aAMlB;IAED,OAAO,GAAI,OAAO,MAAM,EAAE,MAAM,MAAM,GAAG,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,EAAE,UAAU,qBAAqB,UAWjG;CACF;AA6BD,wBAAgB,OAAO,cAEtB"}
@@ -255,7 +255,8 @@ export class MqttStore {
255
255
  configurable: true,
256
256
  writable: true,
257
257
  value: () => {
258
- if (Object.values(this.messageQueue).length > 0) {
258
+ // keys() avoids materializing all values just to check emptiness
259
+ if (Object.keys(this.messageQueue).length > 0) {
259
260
  // Logger.log(`DEBUG: addMessagesFromQueue: in queue: ${JSON.stringify(Object.values(this.messageQueue).length)}`)
260
261
  assign(this.messages, this.messageQueue);
261
262
  // Logger.log(`DEBUG: addMessagesFromQueue: to process: ${JSON.stringify(Object.values(this.messages).length)}`)
@@ -325,7 +326,7 @@ export class MqttStore {
325
326
  client.end(true);
326
327
  this.client = undefined;
327
328
  this.portalId = undefined;
328
- this.topicsSubscribed = new Set();
329
+ this.topicsSubscribed.clear();
329
330
  this.urgentTopicPrefixes = [];
330
331
  this.initialLoadComplete = false;
331
332
  }
@@ -383,24 +384,25 @@ export class MqttStore {
383
384
  });
384
385
  client.on("message", (topic, message) => {
385
386
  // Logger.log(`DEBUG: Message received: ${topic} - ${message.toString()}`)
387
+ const str = message.toString();
388
+ if (str === "")
389
+ return;
390
+ const parsed = getMessageJson(str);
386
391
  if (topic.endsWith("/system/0/Serial") && !this.portalId) {
387
- const portalId = getMessageJson(message).value;
388
- if (this.portalId !== portalId && portalId !== undefined) {
389
- this.setPortalId(portalId);
392
+ if (this.portalId !== parsed.value && parsed.value !== undefined) {
393
+ this.setPortalId(parsed.value);
390
394
  }
391
395
  runInAction(() => this.subscribeToAllTopics());
392
396
  }
393
- if (topic.endsWith("full_publish_completed")) {
394
- const uniqueId = getMessageJson(message)["full-publish-completed-echo"] || "";
397
+ if (!this.initialLoadComplete && topic.endsWith("full_publish_completed")) {
398
+ const uniqueId = parsed["full-publish-completed-echo"] || "";
395
399
  Logger.log(`Received full_publish_completed for ${this.portalId} with full-publish-completed-echo: '${uniqueId}'`);
396
400
  if (uniqueId === this.uniqueId) {
397
401
  this.completeInitialLoad();
398
402
  this.setupQueueWorker();
399
403
  }
400
404
  }
401
- if (message.toString() !== "") {
402
- this.addMessage(topic, getMessageJson(message));
403
- }
405
+ this.addMessage(topic, parsed);
404
406
  });
405
407
  Logger.log("MQTT booted");
406
408
  }
@@ -445,10 +447,9 @@ export class MqttStore {
445
447
  value: () => {
446
448
  var _a;
447
449
  if (this.portalId) {
448
- const options = JSON.stringify({ "keepalive-options": ["suppress-republish"] });
449
450
  const topic = `R/${this.portalId}/keepalive`;
450
- Logger.log(`Sending keepalive for ${this.portalId} with ${options}`);
451
- (_a = this.client) === null || _a === void 0 ? void 0 : _a.publish(topic, options);
451
+ Logger.log(`Sending keepalive for ${this.portalId} with ${SUPPRESSED_KEEPALIVE_OPTIONS}`);
452
+ (_a = this.client) === null || _a === void 0 ? void 0 : _a.publish(topic, SUPPRESSED_KEEPALIVE_OPTIONS);
452
453
  }
453
454
  }
454
455
  });
@@ -537,6 +538,7 @@ export class MqttStore {
537
538
  this.error = error;
538
539
  }
539
540
  }
541
+ const SUPPRESSED_KEEPALIVE_OPTIONS = JSON.stringify({ "keepalive-options": ["suppress-republish"] });
540
542
  /**
541
543
  * Compute mean by providing existing mean, number of samples, and new sample.
542
544
  *
@@ -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: ReturnType<typeof setInterval> | undefined\n queueWorker: ReturnType<typeof setTimeout> | undefined\n meanQueueWorkerPassDuration: number = 0\n urgentTopicPrefixes: string[] = []\n initialLoadComplete: boolean = false\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(\n (topic?: string) => {\n // Logger.log(`DEBUG: messageFromTopic: ${JSON.stringify(topic)}`)\n // trace()\n return topic ? this.messages[topic] : undefined\n },\n { name: \"Mqtt.store.messageFromTopic\", equals: comparer.identity }\n )\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(\n (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 },\n { name: \"Mqtt.store.messagesByTopics\", equals: comparer.identity }\n )\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(\n (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(\n ([_key, message]) =>\n message !== undefined &&\n message !== null &&\n (!Array.isArray(message) ||\n (message.length !== 0 && !message.every((v) => v === undefined || v === null)))\n )\n )\n },\n { name: \"Mqtt.store.messagesByWildcard\", equals: comparer.identity }\n )\n\n constructor() {\n makeAutoObservable(this, {\n messageQueue: false,\n urgentTopicPrefixes: false,\n initialLoadComplete: false,\n completeInitialLoad: 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 if (granted !== undefined && granted[0]) {\n Logger.log(`Subscribed to ${granted[0].topic} with Qos ${granted[0].qos}`)\n } else {\n Logger.log(`Subscribed to ${topic} with Qos unknown`)\n }\n })\n\n this.topicsSubscribed.add(topic)\n }\n }\n\n clearSubscribedTopics() {\n this.topicsSubscribed.clear()\n this.urgentTopicPrefixes = []\n this.initialLoadComplete = false\n runInAction(() => {\n this.portalId = undefined\n })\n }\n\n addMessage = (topic: string, message: { value: string | undefined }) => {\n // Logger.log(`DEBUG: addMessage: topic: ${topic}, urgentPrefixes: ${JSON.stringify(this.urgentTopicPrefixes)}`)\n if (this.initialLoadComplete && 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\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\n }\n }\n\n completeInitialLoad = () => {\n this.addMessagesFromQueue()\n this.initialLoadComplete = true\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 clearTimeout(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/${portalId}/system/0/SwitchableOutput`,\n `N/${portalId}/system/0/GenericInput`,\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 this.initialLoadComplete = false\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\", (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(\n `Received full_publish_completed for ${this.portalId} with full-publish-completed-echo: '${uniqueId}'`\n )\n if (uniqueId === this.uniqueId) {\n this.completeInitialLoad()\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 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 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?.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 | { raw: string }, options?: IClientPublishOptions) => {\n if (this.status !== STATUS.CONNECTED || !this.client) {\n Logger.log(\"Could not publish value, not connected to MQTT broker\")\n return\n }\n const message =\n typeof data === \"object\" && data !== null && \"raw\" in data ? data.raw : 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}\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: ReturnType<typeof setInterval> | undefined\n queueWorker: ReturnType<typeof setTimeout> | undefined\n meanQueueWorkerPassDuration: number = 0\n urgentTopicPrefixes: string[] = []\n initialLoadComplete: boolean = false\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(\n (topic?: string) => {\n // Logger.log(`DEBUG: messageFromTopic: ${JSON.stringify(topic)}`)\n // trace()\n return topic ? this.messages[topic] : undefined\n },\n { name: \"Mqtt.store.messageFromTopic\", equals: comparer.identity }\n )\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(\n (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 },\n { name: \"Mqtt.store.messagesByTopics\", equals: comparer.identity }\n )\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(\n (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(\n ([_key, message]) =>\n message !== undefined &&\n message !== null &&\n (!Array.isArray(message) ||\n (message.length !== 0 && !message.every((v) => v === undefined || v === null)))\n )\n )\n },\n { name: \"Mqtt.store.messagesByWildcard\", equals: comparer.identity }\n )\n\n constructor() {\n makeAutoObservable(this, {\n messageQueue: false,\n urgentTopicPrefixes: false,\n initialLoadComplete: false,\n completeInitialLoad: 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 if (granted !== undefined && granted[0]) {\n Logger.log(`Subscribed to ${granted[0].topic} with Qos ${granted[0].qos}`)\n } else {\n Logger.log(`Subscribed to ${topic} with Qos unknown`)\n }\n })\n\n this.topicsSubscribed.add(topic)\n }\n }\n\n clearSubscribedTopics() {\n this.topicsSubscribed.clear()\n this.urgentTopicPrefixes = []\n this.initialLoadComplete = false\n runInAction(() => {\n this.portalId = undefined\n })\n }\n\n addMessage = (topic: string, message: { value: string | undefined }) => {\n // Logger.log(`DEBUG: addMessage: topic: ${topic}, urgentPrefixes: ${JSON.stringify(this.urgentTopicPrefixes)}`)\n if (this.initialLoadComplete && 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\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\n }\n }\n\n completeInitialLoad = () => {\n this.addMessagesFromQueue()\n this.initialLoadComplete = true\n }\n\n addMessagesFromQueue = () => {\n // keys() avoids materializing all values just to check emptiness\n if (Object.keys(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 clearTimeout(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/${portalId}/system/0/SwitchableOutput`,\n `N/${portalId}/system/0/GenericInput`,\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.clear()\n this.urgentTopicPrefixes = []\n this.initialLoadComplete = false\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\", (topic, message) => {\n // Logger.log(`DEBUG: Message received: ${topic} - ${message.toString()}`)\n\n const str = message.toString()\n if (str === \"\") return\n\n const parsed = getMessageJson(str)\n\n if (topic.endsWith(\"/system/0/Serial\") && !this.portalId) {\n if (this.portalId !== parsed.value && parsed.value !== undefined) {\n this.setPortalId(parsed.value)\n }\n\n runInAction(() => this.subscribeToAllTopics())\n }\n if (!this.initialLoadComplete && topic.endsWith(\"full_publish_completed\")) {\n const uniqueId = (parsed[\"full-publish-completed-echo\"] as string) || \"\"\n Logger.log(\n `Received full_publish_completed for ${this.portalId} with full-publish-completed-echo: '${uniqueId}'`\n )\n if (uniqueId === this.uniqueId) {\n this.completeInitialLoad()\n this.setupQueueWorker()\n }\n }\n\n this.addMessage(topic, parsed)\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 const topic = `R/${this.portalId}/keepalive`\n\n Logger.log(`Sending keepalive for ${this.portalId} with ${SUPPRESSED_KEEPALIVE_OPTIONS}`)\n this.client?.publish(topic, SUPPRESSED_KEEPALIVE_OPTIONS)\n }\n }\n\n sendFullKeepalive = () => {\n if (this.portalId) {\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?.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 | { raw: string }, options?: IClientPublishOptions) => {\n if (this.status !== STATUS.CONNECTED || !this.client) {\n Logger.log(\"Could not publish value, not connected to MQTT broker\")\n return\n }\n const message =\n typeof data === \"object\" && data !== null && \"raw\" in data ? data.raw : JSON.stringify({ value: data })\n\n Logger.log(`Publishing to ${topic}: ${message}`)\n\n this.client?.publish(topic, message, options ?? {})\n }\n}\n\nconst SUPPRESSED_KEEPALIVE_OPTIONS = JSON.stringify({ \"keepalive-options\": [\"suppress-republish\"] })\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}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@victronenergy/mfd-modules",
3
- "version": "11.1.1",
3
+ "version": "11.1.2",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",