UNPKG

iobroker.nspanel-lovelace-ui

Version:

NsPanel Lovelace UI is a Firmware for the nextion screen inside of NSPanel in the Design of Lovelace UI Design.

1,334 lines 81.7 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var panel_exports = {}; __export(panel_exports, { Panel: () => Panel }); module.exports = __toCommonJS(panel_exports); var import_panel_message = require("./panel-message"); var import_screensaver = require("../pages/screensaver"); var globals = __toESM(require("../types/function-and-const")); var import_library = require("./library"); var definition = __toESM(require("../const/definition")); var import_pageMedia = require("../pages/pageMedia"); var import_pageGrid = require("../pages/pageGrid"); var import_navigation = require("../classes/navigation"); var import_pageThermo = require("../pages/pageThermo"); var import_pagePower = require("../pages/pagePower"); var import_pageEntities = require("../pages/pageEntities"); var import_pagePopup = require("../pages/pagePopup"); var import_system_templates = require("../templates/system-templates"); var import_pageAlarm = require("../pages/pageAlarm"); var import_pageQR = require("../pages/pageQR"); var import_data_item = require("./data-item"); var import_Color = require("../const/Color"); var import_pageSchedule = require("../pages/pageSchedule"); var import_card = require("../templates/card"); var import_tools = require("../const/tools"); var import_pageChartBar = require("../pages/pageChartBar"); var import_pageChartLine = require("../pages/pageChartLine"); var import_pageThermo2 = require("../pages/pageThermo2"); var import_admin = require("../configuration/admin"); const DefaultOptions = { format: { weekday: "short", month: "short", year: "numeric", day: "numeric" }, CustomFormat: "", locale: "de-DE", pages: [] }; class Panel extends import_library.BaseClass { loopTimeout; pages = []; _activePage = void 0; data = {}; blockStartup = null; _isOnline = false; blockTouchEventsForMs = 200; // ms lastSendTypeDate = 0; isBuzzerAllowed = true; options; flashing = false; screenSaver; lastCard = ""; notifyIndex = -1; initDone = false; lightPopupV2 = true; // Enable Light Popup v2, created in 2025. overrideLightPopup = true; // Override light popup config type. hideCards = false; buttons; navigation; format; controller; topic; reivCallbacks = []; panelSend; statesControler; CustomFormat; sendToTasmota = () => { }; timeout; dim = { standby: definition.genericStateObjects.panel.panels.cmd.dim.standby.common.def, active: definition.genericStateObjects.panel.panels.cmd.dim.active.common.def, dayMode: definition.genericStateObjects.panel.panels.cmd.dim.dayMode.common.def, nightStandby: definition.genericStateObjects.panel.panels.cmd.dim.nightStandby.common.def, nightActive: definition.genericStateObjects.panel.panels.cmd.dim.nightActive.common.def, nightHourStart: definition.genericStateObjects.panel.panels.cmd.dim.nightHourStart.common.def, nightHourEnd: definition.genericStateObjects.panel.panels.cmd.dim.nightHourEnd.common.def, schedule: definition.genericStateObjects.panel.panels.cmd.dim.schedule.common.def }; screenSaverDoubleClick = true; detach = { left: false, right: false }; persistentPageItems = {}; info = { nspanel: { displayVersion: "", model: "", bigIconLeft: false, bigIconRight: false, onlineVersion: "", firmwareUpdate: 100, berryDriverVersion: 0, berryDriverVersionOnline: 0, currentPage: "", scriptVersion: "unknown" }, tasmota: { firmwareversion: "", onlineVersion: "", safeboot: false, mqttClient: "", net: { Hostname: "", IPAddress: "", Gateway: "", Subnetmask: "", DNSServer1: "", DNSServer2: "", Mac: "", IP6Global: "", IP6Local: "", Ethernet: { Hostname: "", IPAddress: "", Gateway: "", Subnetmask: "", DNSServer1: "", DNSServer2: "", Mac: "", IP6Global: "", IP6Local: "" }, Webserver: 0, HTTP_API: 0, WifiConfig: 0, WifiPower: 0 }, uptime: "", sts: { Time: "", Uptime: "", UptimeSec: 0, Heap: 0, SleepMode: "", Sleep: 0, LoadAvg: 0, MqttCount: 0, Berry: { HeapUsed: 0, Objects: 0 }, POWER1: "", POWER2: "", Wifi: { AP: 0, SSId: "", BSSId: "", Channel: 0, Mode: "", RSSI: 0, Signal: 0, LinkCount: 0, Downtime: "" } } } }; meetsVersion(version) { var _a, _b; if ((_b = (_a = this.info) == null ? void 0 : _a.nspanel) == null ? void 0 : _b.displayVersion) { return (0, import_tools.isVersionGreaterOrEqual)(this.info.nspanel.displayVersion, version); } return false; } constructor(adapter, options) { var _a, _b; super(adapter, options.name, (_a = options.friendlyName) != null ? _a : options.name); this.panelSend = new import_panel_message.PanelSend(adapter, { name: `${this.friendlyName}-SendClass`, mqttClient: options.controller.mqttClient, topic: options.topic, panel: this }); this.info.tasmota.mqttClient = this.library.cleandp(this.name); this.options = options; this.timeout = options.timeout || 15; this.buttons = options.buttons; this.CustomFormat = (_b = options.CustomFormat) != null ? _b : ""; this.format = { ...DefaultOptions.format, ...options.format }; this.controller = options.controller; this.topic = options.topic; if (typeof this.panelSend.addMessage === "function") { this.sendToPanelClass = this.panelSend.addMessage; } if (typeof this.panelSend.addMessageTasmota === "function") { this.sendToTasmota = this.panelSend.addMessageTasmota; } this.info.nspanel.scriptVersion = options.scriptVersion || "unknown"; this.info.tasmota.onlineVersion = this.controller.globalPanelInfo.availableTasmotaFirmwareVersion; this.info.nspanel.onlineVersion = this.controller.globalPanelInfo.availableTftFirmwareVersion; this.statesControler = options.controller.statesControler; const admin = new import_admin.AdminConfiguration(this.adapter); admin.processentrys(options); options.pages = options.pages.filter((b) => { var _a2, _b2, _c; if (((_a2 = b.config) == null ? void 0 : _a2.card) === "screensaver" || ((_b2 = b.config) == null ? void 0 : _b2.card) === "screensaver2" || ((_c = b.config) == null ? void 0 : _c.card) === "screensaver3") { return true; } if (options.navigation.find((c) => c && c.name === b.uniqueID)) { return true; } return false; }); options.pages = options.pages.concat(import_system_templates.systemPages); options.navigation = (options.navigation || []).concat(import_system_templates.systemNavigation); let scsFound = 0; for (let a = 0; a < options.pages.length; a++) { const pageConfig = options.pages[a] ? Panel.getPage(options.pages[a], this) : options.pages[a]; if (!pageConfig || !pageConfig.config) { continue; } const pmconfig = { card: pageConfig.config.card, panel: this, id: String(a), name: `${pageConfig.uniqueID}`, alwaysOn: pageConfig.alwaysOn, adapter: this.adapter, hidden: pageConfig.hidden || false, dpInit: pageConfig.dpInit }; const Page = this.newPage(pmconfig, pageConfig); if (Page) { this.pages[a] = Page; if (Page instanceof import_screensaver.Screensaver) { this.screenSaver = Page; scsFound += 1; } } } if (scsFound === 0) { throw new Error("no screensaver found! Stop!"); } const navConfig = { adapter: this.adapter, panel: this, navigationConfig: options.navigation }; this.navigation = new import_navigation.Navigation(navConfig); } newPage(pmconfig, pageConfig) { var _a, _b, _c; switch ((_a = pageConfig.config) == null ? void 0 : _a.card) { case "cardChart": { pageConfig = Panel.getPage(pageConfig, this); return new import_pageChartBar.PageChartBar(pmconfig, pageConfig); } case "cardLChart": { pageConfig = Panel.getPage(pageConfig, this); return new import_pageChartLine.PageChartLine(pmconfig, pageConfig); } case "cardEntities": { pageConfig = Panel.getPage(pageConfig, this); return new import_pageEntities.PageEntities(pmconfig, pageConfig); } case "cardSchedule": { pageConfig = Panel.getPage(pageConfig, this); return new import_pageSchedule.PageSchedule(pmconfig, pageConfig); } case "cardGrid3": case "cardGrid2": case "cardGrid": { pageConfig = Panel.getPage(pageConfig, this); return new import_pageGrid.PageGrid(pmconfig, pageConfig); } case "cardThermo": { pageConfig = Panel.getPage(pageConfig, this); return new import_pageThermo.PageThermo(pmconfig, pageConfig); } case "cardThermo2": { pageConfig = Panel.getPage(pageConfig, this); return new import_pageThermo2.PageThermo2(pmconfig, pageConfig); } case "cardMedia": { pageConfig = Panel.getPage(pageConfig, this); return new import_pageMedia.PageMedia(pmconfig, pageConfig); } case "cardQR": { pageConfig = Panel.getPage(pageConfig, this); return new import_pageQR.PageQR(pmconfig, pageConfig); } case "cardAlarm": { pageConfig = Panel.getPage(pageConfig, this); return new import_pageAlarm.PageAlarm(pmconfig, pageConfig); } case "cardPower": { pageConfig = Panel.getPage(pageConfig, this); return new import_pagePower.PagePower(pmconfig, pageConfig); } case "popupNotify": { pageConfig = Panel.getPage(pageConfig, this); return new import_pagePopup.PagePopup(pmconfig, pageConfig); } case "screensaver": case "screensaver2": case "screensaver3": { const ssconfig = { card: pageConfig.config.card, panel: this, id: pmconfig.id, name: `${pageConfig.uniqueID}`, adapter: this.adapter, dpInit: "" }; if (!pageConfig.config) { throw new Error(`Page config is missing for page ${pageConfig.uniqueID}`); } pageConfig.config.model = ((_c = (_b = this.adapter.config.panels) == null ? void 0 : _b.find((p) => p.topic === this.topic)) == null ? void 0 : _c.model) || "eu"; return new import_screensaver.Screensaver(ssconfig, pageConfig); } default: { throw new Error(`Page config is missing card property for page ${pageConfig.uniqueID}`); } } } init = async () => { var _a, _b, _c, _d; if (this.unload || this.adapter.unload) { return; } this.log.debug(`Panel ${this.name} is initialised!`); await this.controller.mqttClient.subscribe(`${this.topic}/tele/#`, this.onMessage); await this.controller.mqttClient.subscribe(`${this.topic}/stat/#`, this.onMessage); this.log.info(`Setting panel to offline until first message!`); this.isOnline = false; const channelObj = structuredClone(definition.genericStateObjects.panel.panels._channel); channelObj.common.name = this.friendlyName; channelObj.native = { topic: this.topic, tasmotaName: this.friendlyName, name: this.name }; if (await this.adapter.getStateAsync(`panels.${this.name}.cmd.dim.delay`)) { await this.adapter.delObjectAsync(`panels.${this.name}.cmd.dim.delay`); } await this.library.writedp(`panels.${this.name}`, void 0, channelObj); await this.library.writedp( `panels.${this.name}.cmd`, void 0, definition.genericStateObjects.panel.panels.cmd._channel ); await this.library.writedp( `panels.${this.name}.cmd.dim`, void 0, definition.genericStateObjects.panel.panels.cmd.dim._channel ); await this.library.writedp( `panels.${this.name}.pagePopup`, void 0, definition.genericStateObjects.panel.panels.pagePopup._channel ); await this.library.writedp( `panels.${this.name}.cmd.pagePopup`, void 0, definition.genericStateObjects.panel.panels.cmd.pagePopup._channel ); for (const key of Object.keys(definition.genericStateObjects.panel.panels.pagePopup)) { if (key !== "_channel") { await this.library.writedp( `panels.${this.name}.pagePopup.${key}`, void 0, definition.genericStateObjects.panel.panels.pagePopup[key] ); } } for (const key of Object.keys(definition.genericStateObjects.panel.panels.cmd.pagePopup)) { if (key !== "_channel") { await this.library.writedp( `panels.${this.name}.cmd.pagePopup.${key}`, void 0, definition.genericStateObjects.panel.panels.cmd.pagePopup[key] ); } } await this.library.writedp( `panels.${this.name}.cmd.isBuzzerAllowed`, void 0, definition.genericStateObjects.panel.panels.cmd.isBuzzerAllowed ); this.isBuzzerAllowed = !!((_b = (_a = this.library.readdb(`panels.${this.name}.cmd.isBuzzerAllowed`)) == null ? void 0 : _a.val) != null ? _b : true); await this.library.writedp( `panels.${this.name}.cmd.screenSaver`, void 0, definition.genericStateObjects.panel.panels.cmd.screenSaver._channel ); await this.library.writedp( `panels.${this.name}.buttons`, void 0, definition.genericStateObjects.panel.panels.buttons._channel ); await this.library.writedp( `panels.${this.name}.buttons.left`, true, definition.genericStateObjects.panel.panels.buttons.left ); await this.library.writedp( `panels.${this.name}.buttons.right`, true, definition.genericStateObjects.panel.panels.buttons.right ); const keys = Object.keys(this.dim); for (const key of keys) { if (!definition.isDimConfigKey(key)) { continue; } const state2 = this.library.readdb(`panels.${this.name}.cmd.dim.${key}`); if (state2 && state2.val != null && definition.isDimValueForKey(key, state2.val)) { this.dim[key] = state2.val; } await this.library.writedp( `panels.${this.name}.cmd.dim.${key}`, this.dim[key], definition.genericStateObjects.panel.panels.cmd.dim[key] ); } let state = this.library.readdb(`panels.${this.name}.cmd.screenSaver.doubleClick`); if (state && state.val != null) { this.screenSaverDoubleClick = !!state.val; } await this.library.writedp( `panels.${this.name}.cmd.screenSaver.doubleClick`, this.screenSaverDoubleClick, definition.genericStateObjects.panel.panels.cmd.screenSaver.doubleClick ); if (state && !state.val) { await this.library.writedp( `panels.${this.name}.buttons.screensaverGesture`, 0, definition.genericStateObjects.panel.panels.buttons.screensaverGesture ); } else { await this.library.writedp( `panels.${this.name}.buttons.screensaverGesture`, void 0, definition.genericStateObjects.panel.panels.buttons.screensaverGesture ); } state = this.library.readdb(`panels.${this.name}.cmd.hideCards`); if (state && state.val != null) { this.hideCards = !!state.val; } await this.library.writedp( `panels.${this.name}.cmd.hideCards`, this.hideCards, definition.genericStateObjects.panel.panels.cmd.hideCards ); await this.library.writedp( `panels.${this.name}.cmd.buzzer`, "", definition.genericStateObjects.panel.panels.cmd.buzzer ); state = this.library.readdb(`panels.${this.name}.cmd.detachRight`); if (state && state.val != null) { this.detach.right = !!state.val; } state = this.library.readdb(`panels.${this.name}.cmd.detachLeft`); if (state && state.val != null) { this.detach.left = !!state.val; } await this.library.writedp( `panels.${this.name}.cmd.detachRight`, this.detach.right, definition.genericStateObjects.panel.panels.cmd.detachRight ); await this.library.writedp( `panels.${this.name}.cmd.detachLeft`, this.detach.left, definition.genericStateObjects.panel.panels.cmd.detachLeft ); state = this.library.readdb(`panels.${this.name}.cmd.screenSaver.timeout`); if (state) { this.timeout = parseInt(String(state.val)); } await this.library.writedp( `panels.${this.name}.cmd.screenSaver.timeout`, this.timeout, definition.genericStateObjects.panel.panels.cmd.screenSaver.timeout ); let val = void 0; state = this.library.readdb(`panels.${this.name}.cmd.screenSaver.headingNotification`); if (state && typeof state.val === "string" && this.screenSaver) { this.screenSaver.headingNotification = state.val; val = state.val; } await this.library.writedp( `panels.${this.name}.cmd.screenSaver.headingNotification`, val, definition.genericStateObjects.panel.panels.cmd.screenSaver.headingNotification ); val = void 0; state = this.library.readdb(`panels.${this.name}.cmd.screenSaver.textNotification`); if (state && typeof state.val === "string" && this.screenSaver) { this.screenSaver.textNotification = state.val; val = state.val; } await this.library.writedp( `panels.${this.name}.cmd.screenSaver.textNotification`, val, definition.genericStateObjects.panel.panels.cmd.screenSaver.textNotification ); val = void 0; state = this.library.readdb(`panels.${this.name}.cmd.screenSaver.activateNotification`); if (state && state.val != null && this.screenSaver) { this.screenSaver.customNotification = !!state.val; val = !!state.val; } await this.library.writedp( `panels.${this.name}.cmd.screenSaver.activateNotification`, !!val, definition.genericStateObjects.panel.panels.cmd.screenSaver.activateNotification ); state = this.library.readdb(`panels.${this.name}.info.nspanel.firmwareUpdate`); await this.library.writedp( `panels.${this.name}.info.nspanel.firmwareUpdate`, state && typeof state.val === "number" ? state.val >= 99 ? 100 : state.val : void 0, definition.genericStateObjects.panel.panels.info.nspanel.firmwareUpdate ); for (const id in definition.InternalStates.panel) { const obj = definition.InternalStates.panel[id]; await this.statesControler.setInternalState( `${this.name}/${id}`, obj.val, obj.ack, obj.common, obj.noTrigger ? void 0 : this.onInternalCommand ); } for (const page of this.pages) { if (page && page.name) { if (this.adapter.config.debugLogPages) { this.log.debug( `Initialisation of page ${page.name} - card: ${page.card} - pageItems: ${(page.pageItemConfig || []).length}` ); } await page.init(); } else { this.log.error("Page failed or has no name!"); } } this.navigation.init(); if (this.adapter.config.debugLogPages) { this.log.debug(`Panel ${this.name} is initialised!`); } { const currentPage = this.library.readdb(`panels.${this.name}.cmd.mainNavigationPoint`); if (currentPage && currentPage.val) { this.navigation.setMainPageByName(String(currentPage.val)); } definition.genericStateObjects.panel.panels.cmd.mainNavigationPoint.common.states = this.navigation.buildCommonStates(); const page = this.navigation.getCurrentMainPoint(); await this.library.writedp( `panels.${this.name}.cmd.mainNavigationPoint`, page, definition.genericStateObjects.panel.panels.cmd.mainNavigationPoint ); } await this.adapter.delay(100); const currentScreensaver = this.library.readdb(`panels.${this.name}.cmd.screenSaver.layout`); const scs = this.pages.filter( (a) => a && (a.card === "screensaver" || a.card === "screensaver2" || a.card === "screensaver3") ); if (currentScreensaver && currentScreensaver.val != null) { if (scs && scs[0]) { this.screenSaver = scs[0]; if (globals.isScreenSaverModeAsNumber(currentScreensaver.val)) { this.screenSaver.overwriteModel(currentScreensaver.val, true); } } } await this.library.writedp( `panels.${this.name}.cmd.screenSaver.layout`, this.screenSaver && this.screenSaver.mode ? import_screensaver.Screensaver.mapModeToNumber(this.screenSaver.mode) : 0, definition.genericStateObjects.panel.panels.cmd.screenSaver.layout ); state = this.library.readdb(`panels.${this.name}.cmd.screenSaver.rotationTime`); let temp = 0; if (state && typeof state.val === "number") { temp = state.val === 0 ? state.val : state.val < 3 ? 3 : state.val > 3600 ? 3600 : state.val; if (this.screenSaver) { this.screenSaver.rotationTime = temp * 1e3; } } await this.library.writedp( `panels.${this.name}.cmd.screenSaver.rotationTime`, temp, definition.genericStateObjects.panel.panels.cmd.screenSaver.rotationTime ); state = this.library.readdb(`panels.${this.name}.cmd.screenSaver.infoIcon`); if (state && typeof state.val === "string" && this.screenSaver) { this.screenSaver.infoIcon = state.val; } await this.library.writedp( `panels.${this.name}.cmd.screenSaver.infoIcon`, (_d = (_c = this.screenSaver) == null ? void 0 : _c.infoIcon) != null ? _d : "", definition.genericStateObjects.panel.panels.cmd.screenSaver.infoIcon ); if (this.buttons && this.screenSaver) { const entries = Object.entries(this.buttons); const inits = []; for (const [key, button] of entries) { if (!button) { continue; } switch (button.mode) { case "page": break; case "switch": case "button": { if (typeof button.state === "string") { const di = new import_data_item.Dataitem( this.adapter, { type: "state", dp: button.state }, this.screenSaver, this.statesControler ); button.state = di; inits.push( di.isValidAndInit().then((ok) => { if (!ok) { if (this.buttons) { this.buttons[key] = null; } } }) ); } break; } } } await Promise.all(inits); } state = this.library.readdb(`panels.${this.name}.info.nspanel.bigIconLeft`); this.info.nspanel.bigIconLeft = state ? !!state.val : false; state = this.library.readdb(`panels.${this.name}.info.nspanel.bigIconRight`); this.info.nspanel.bigIconRight = state ? !!state.val : false; this.restartLoops(); }; sendToPanelClass = () => { }; sendToPanel = (payload, ackForType, force, opt) => { this.sendToPanelClass(payload, ackForType, force, opt); }; /** * Activate a page or toggle sleep on the current page. * * Behavior: * - If `_page` is a boolean: `true` wakes the current page, `false` puts it to sleep. * - If `_page` is a Page: activates that page; `_notSleep === true` keeps it awake, otherwise it starts asleep. * * @param _page Target page or boolean toggle for current page * @param _notSleep When `_page` is a Page, `true` means not sleeping (visible), `false` means sleeping * @returns Promise<void> */ async setActivePage(_page, _notSleep) { if (_page === void 0) { return; } let targetPage = this._activePage; let targetSleep = false; if (typeof _page === "boolean") { if (!this._activePage) { return; } targetSleep = !_page; } else { targetPage = _page; targetSleep = _notSleep != null ? _notSleep : false; } if (!this._activePage) { if (!targetPage) { return; } targetPage.setLastPage(void 0); if (!targetSleep) { await targetPage.setVisibility(true); } targetPage.sleep = targetSleep; this._activePage = targetPage; return; } if (targetPage && targetPage !== this._activePage) { await this._activePage.setVisibility(false); targetPage.setLastPage(this._activePage); if (!targetSleep) { await targetPage.setVisibility(true); } targetPage.sleep = targetSleep; this._activePage = targetPage; return; } if (targetSleep !== this._activePage.sleep) { this._activePage.sleep = targetSleep; if (!targetSleep) { this._activePage.sendType(true); await this._activePage.setVisibility(true); } return; } if (!targetSleep) { this.log.warn( `setActivePage called but nothing changed! Resending active page to panel. Page: ${this._activePage.name} - Sleep: ${this._activePage.sleep}` ); this._activePage.sendType(true); await this._activePage.update(); } } getActivePage() { if (!this._activePage) { throw new Error(`No active page here panel ${this.friendlyName}, check code!`); } return this._activePage; } get isOnline() { return this._isOnline; } set isOnline(s) { if (this.unload && s) { return; } if (s !== this._isOnline) { void this.library.writedp( `panels.${this.name}.info.isOnline`, s, definition.genericStateObjects.panel.panels.info.isOnline ); if (s) { this.log.info("is online!"); } else { this._activePage && void this._activePage.setVisibility(false); this.restartLoops(); this.log.warn("is offline!"); } } this._isOnline = s; } async isValid() { return true; } registerOnMessage(fn) { if (this.reivCallbacks.indexOf(fn) === -1) { this.reivCallbacks.push(fn); } } onMessage = async (topic, message) => { for (const fn of this.reivCallbacks) { if (fn) { await fn(topic, message); } } if (topic.endsWith(definition.ReiveTopicAppendix)) { const event = this.convertToEvent(message); if (event) { await this.HandleIncomingMessage(event); } else if (message) { let msg = null; try { msg = JSON.parse(message); } catch { this.log.warn(`Receive a broken msg from mqtt: ${msg}`); } if (!msg) { return; } if ("Flashing" in msg) { this.log.info(`Going offline for flashing!`); this.isOnline = false; this.flashing = msg.Flashing.complete < 99; this.log.info(`Flashing: ${msg.Flashing.complete}%`); await this.library.writedp( `panels.${this.name}.info.nspanel.firmwareUpdate`, msg.Flashing.complete >= 99 ? 100 : msg.Flashing.complete, definition.genericStateObjects.panel.panels.info.nspanel.firmwareUpdate ); return; } else if ("nlui_driver_version" in msg) { this.info.nspanel.berryDriverVersion = parseInt(msg.nlui_driver_version); await this.library.writedp( `panels.${this.name}.info.nspanel.berryDriverVersion`, this.info.nspanel.berryDriverVersion, definition.genericStateObjects.panel.panels.info.nspanel.berryDriverVersion ); if (this.unload || this.adapter.unload) { return; } this.adapter.setTimeout(async () => { let result = void 0; try { result = await this.adapter.fetch( "https://raw.githubusercontent.com/ticaki/ioBroker.nspanel-lovelace-ui/main/json/version.json" ); if (!result) { return; } const version = this.adapter.config.useBetaTFT ? result[`berry-beta`].split("_")[0] : result.berry.split("_")[0]; if (parseInt(version) != this.info.nspanel.berryDriverVersion && this.info.nspanel.berryDriverVersion != -1) { const url = `http://${this.info.tasmota.net.IPAddress}/cm?${this.adapter.config.useTasmotaAdmin ? `user=admin&password=${this.adapter.config.tasmotaAdminPassword}` : ``}&cmnd=Backlog UrlFetch https://raw.githubusercontent.com/ticaki/ioBroker.nspanel-lovelace-ui/main/tasmota/berry/${version}/autoexec.be; Restart 1`; this.log.info( `Automatic update of the berry driver version from ${this.info.nspanel.berryDriverVersion} to ${version} on tasmota with IP ${this.info.tasmota.net.IPAddress} and ${this.info.tasmota.net.Hostname}.` ); await this.adapter.fetch(url); } } catch { } }, 1); return; } } } else if (topic.endsWith("/tele/LWT")) { if (message === "Offline") { } } else if (topic.endsWith("/tele/INFO1")) { this.restartLoops(); } else { const command = (topic.match(/[0-9a-zA-Z]+?\/[0-9a-zA-Z]+$/g) || [])[0]; if (command) { switch (command) { case "stat/POWER2": { await this.library.writedp( `panels.${this.name}.cmd.power2`, message === "ON", definition.genericStateObjects.panel.panels.cmd.power2 ); await this.statesControler.setInternalState(`${this.name}/cmd/power2`, message === "ON", true); break; } case "stat/POWER1": { await this.library.writedp( `panels.${this.name}.cmd.power1`, message === "ON", definition.genericStateObjects.panel.panels.cmd.power1 ); await this.statesControler.setInternalState(`${this.name}/cmd/power1`, message === "ON", true); break; } case "stat/STATUS0": { const data = JSON.parse(message); if (this.name !== this.library.cleandp(data.StatusNET.Mac, false, true)) { this.log.error(`Receive wrong mac address ${data.StatusNET.Mac}! Update ur config!`); } const o = await this.adapter.getForeignObjectAsync(`system.adapter.${this.adapter.namespace}`); if (o && o.native) { if (this.name == this.library.cleandp(data.StatusNET.Mac, false, true)) { const index = o.native.panels.findIndex((a) => a.id === this.name); const ip = data.StatusNET.IPAddress; if (index !== -1 && o.native.panels[index].ip != ip) { o.native.panels[index].ip = ip; await this.adapter.setForeignObjectAsync(o._id, o); } } } await this.library.writedp( `panels.${this.name}.info`, void 0, definition.genericStateObjects.panel.panels.info._channel ); await this.library.writedp( `panels.${this.name}.info.status`, message, definition.genericStateObjects.panel.panels.info.status ); this.info.tasmota.mqttClient = data.StatusMQT.MqttClient; this.info.tasmota.net = data.StatusNET; this.info.tasmota.firmwareversion = data.StatusFWR.Version; this.info.tasmota.safeboot = data.StatusFWR.Version.includes("Safeboot"); this.info.tasmota.uptime = data.StatusSTS.Uptime; this.info.tasmota.sts = data.StatusSTS; await this.writeInfo(); break; } default: { if (this.adapter.config.debugLogMqtt) { this.log.debug(`Receive other message ${topic} with ${message}`); } } } } } }; sendRules() { this.sendToTasmota( `${this.topic}/cmnd/Rule3`, `ON CustomSend DO RuleTimer3 120 ENDON ON Rules#Timer=3 DO CustomSend pageType~pageStartup ENDON${this.detach.left ? ` ON Button1#state do Publish ${this.topic}/tele/RESULT {"CustomRecv":"event,button1"} ENDON` : ""}${this.detach.right ? ` ON Button2#state do Publish ${this.topic}/tele/RESULT {"CustomRecv":"event,button2"} ENDON` : ""}` ); this.sendToTasmota(`${this.topic}/cmnd/Rule3`, "1"); } async onStateChange(id, state) { var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u; if (state.ack) { return; } if (id.split(".")[1] === this.name) { const cmd = id.replace(`panels.${this.name}.cmd.`, ""); switch (cmd) { case "power1": { this.sendToTasmota(`${this.topic}/cmnd/POWER1`, state.val ? "ON" : "OFF"); break; } case "power2": { this.sendToTasmota(`${this.topic}/cmnd/POWER2`, state.val ? "ON" : "OFF"); break; } case "mainNavigationPoint": { const v = state.val; if (typeof v === "string") { this.navigation.setMainPageByName(v ? v : "main"); await this.library.writedp(`panels.${this.name}.cmd.mainNavigationPoint`, v ? v : "main"); } break; } case "goToNavigationPoint": { if (typeof state.val === "string") { await this.navigation.setTargetPageByName(state.val ? String(state.val) : "main"); } break; } case "screenSaver.timeout": { if (state && state.val != null && typeof state.val === "number") { await this.statesControler.setInternalState( `${this.name}/cmd/screenSaverTimeout`, parseInt(String(state.val)), false ); } break; } case "dim.standby": { if (state && state.val != null && typeof state.val === "number") { await this.statesControler.setInternalState( `${this.name}/cmd/dimStandby`, parseInt(String(state.val)), false ); } break; } case "dim.active": { if (state && state.val != null && typeof state.val === "number") { await this.statesControler.setInternalState( `${this.name}/cmd/dimActive`, parseInt(String(state.val)), false ); } break; } case "dim.dayMode": { if (this.dim.schedule) { this.log.warn("Dim schedule is active - User input ignored!"); } else { this.dim.dayMode = !!state.val; this.sendDimmode(); } await this.library.writedp( `panels.${this.name}.cmd.dim.dayMode`, this.dim.dayMode, definition.genericStateObjects.panel.panels.cmd.dim.dayMode ); break; } case "dim.schedule": { this.dim.schedule = !!state.val; if (this.dim.schedule) { this.sendDimmode(); } await this.library.writedp( `panels.${this.name}.cmd.dim.schedule`, this.dim.schedule, definition.genericStateObjects.panel.panels.cmd.dim.schedule ); break; } case "dim.nightActive": { if (state && state.val != null && typeof state.val === "number") { await this.statesControler.setInternalState( `${this.name}/cmd/dimNightActive`, parseInt(String(state.val)), false ); } break; } case "dim.nightStandby": { if (state && state.val != null && typeof state.val === "number") { await this.statesControler.setInternalState( `${this.name}/cmd/dimNightStandby`, parseInt(String(state.val)), false ); } break; } case "dim.nightHourStart": { if (state && state.val != null && typeof state.val === "number") { if (state.val <= 23 && state.val >= 0 && state.val % 1 === 0) { await this.statesControler.setInternalState( `${this.name}/cmd/dimNightHourStart`, parseInt(String(state.val)), false ); } } break; } case "dim.nightHourEnd": { if (state && state.val != null && typeof state.val === "number") { if (state.val <= 23 && state.val >= 0 && state.val % 1 === 0) { await this.statesControler.setInternalState( `${this.name}/cmd/dimNightHourEnd`, parseInt(String(state.val)), false ); } } break; } case "screenSaver.infoIcon": { if (state && state.val != null && typeof state.val === "string") { await this.statesControler.setInternalState( `${this.name}/cmd/screenSaverInfoIcon`, state.val, false ); } break; } case "screenSaver.doubleClick": { if (state && state.val != null) { await this.statesControler.setInternalState( `${this.name}/cmd/screenSaverDoubleClick`, !!state.val, false ); } break; } case "detachLeft": { await this.statesControler.setInternalState(`${this.name}/cmd/detachLeft`, !!state.val, false); break; } case "detachRight": { await this.statesControler.setInternalState(`${this.name}/cmd/detachRight`, !!state.val, false); break; } case "screenSaver.layout": { if (typeof state.val === "number" && globals.isScreenSaverModeAsNumber(state.val)) { await this.statesControler.setInternalState( `${this.name}/cmd/screenSaverLayout`, state.val, false ); } break; } case "screenSaver.rotationTime": { if (state && state.val != null && typeof state.val === "number") { await this.statesControler.setInternalState( `${this.name}/cmd/screenSaverRotationTime`, parseInt(String(state.val)), false ); } break; } case "screenSaver.activateNotification": { if (state && state.val != null) { await this.statesControler.setInternalState( `${this.name}/cmd/screensaverActivateNotification`, !!state.val, false ); } break; } case "screenSaver.headingNotification": { if (state && state.val != null && typeof state.val === "string") { await this.statesControler.setInternalState( `${this.name}/cmd/screensaverHeadingNotification`, String(state.val), false ); } break; } case "screenSaver.textNotification": { if (state && state.val != null && typeof state.val === "string") { await this.statesControler.setInternalState( `${this.name}/cmd/screensaverTextNotification`, String(state.val), false ); } break; } /* case 'hideCards': { if (state && state.val != null) { this.hideCards = !!state.val; await this.library.writedp( `panels.${this.name}.cmd.hideCards`, this.hideCards, definition.genericStateObjects.panel.panels.cmd.hideCards, ); } break; } */ case "hideCards": { if (state && state.val != null) { await this.statesControler.setInternalState(`${this.name}/cmd/hideCards`, !!state.val, false); } break; } case "buzzer": { if (state && state.val != null && typeof state.val === "string" && state.val.trim()) { this.sendToTasmota(`${this.topic}/cmnd/Buzzer`, state.val.trim()); await this.statesControler.setInternalState(`${this.name}/cmd/buzzer`, "", true); } break; } case "pagePopup.activate": { const global = (_a = this.library.readdb(`panels.${this.name}.cmd.pagePopup.global`)) == null ? void 0 : _a.val; const details = { id: ((_b = this.library.readdb(`panels.${this.name}.cmd.pagePopup.id`)) == null ? void 0 : _b.val) || "", priority: (_c = this.library.readdb(`panels.${this.name}.cmd.pagePopup.priority`)) == null ? void 0 : _c.val, global: !!global, type: ((_d = this.library.readdb(`panels.${this.name}.cmd.pagePopup.type`)) == null ? void 0 : _d.val) || "information", headline: ((_e = this.library.readdb(`panels.${this.name}.cmd.pagePopup.headline`)) == null ? void 0 : _e.val) || "", text: ((_f = this.library.readdb(`panels.${this.name}.cmd.pagePopup.text`)) == null ? void 0 : _f.val) || "", buttonLeft: ((_g = this.library.readdb(`panels.${this.name}.cmd.pagePopup.buttonLeft`)) == null ? void 0 : _g.val) || "", buttonMid: ((_h = this.library.readdb(`panels.${this.name}.cmd.pagePopup.buttonMid`)) == null ? void 0 : _h.val) || "", buttonRight: ((_i = this.library.readdb(`panels.${this.name}.cmd.pagePopup.buttonRight`)) == null ? void 0 : _i.val) || "", colorHeadline: (0, import_tools.getRGBFromValue)( ((_j = this.library.readdb(`panels.${this.name}.cmd.pagePopup.colorHeadline`)) == null ? void 0 : _j.val) || "#FFFFFF" ), colorText: (0, import_tools.getRGBFromValue)( ((_k = this.library.readdb(`panels.${this.name}.cmd.pagePopup.colorText`)) == null ? void 0 : _k.val) || "#FFFFFF" ), colorButtonLeft: (0, import_tools.getRGBFromValue)( ((_l = this.library.readdb(`panels.${this.name}.cmd.pagePopup.colorButtonLeft`)) == null ? void 0 : _l.val) || "#FFFFFF" ), colorButtonMid: (0, import_tools.getRGBFromValue)( ((_m = this.library.readdb(`panels.${this.name}.cmd.pagePopup.colorButtonMid`)) == null ? void 0 : _m.val) || "#FFFFFF" ), colorButtonRight: (0, import_tools.getRGBFromValue)( ((_n = this.library.readdb(`panels.${this.name}.cmd.pagePopup.colorButtonRight`)) == null ? void 0 : _n.val) || "#FFFFFF" ), icon: ((_o = this.library.readdb(`panels.${this.name}.cmd.pagePopup.icon`)) == null ? void 0 : _o.val) || void 0, textSize: String((_p = this.library.readdb(`panels.${this.name}.cmd.pagePopup.textSize`)) == null ? void 0 : _p.val) || "3", iconColor: (0, import_tools.getRGBFromValue)( ((_q = this.library.readdb(`panels.${this.name}.cmd.pagePopup.iconColor`)) == null ? void 0 : _q.val) || "#FFFFFF" ), alwaysOn: !!((_s = (_r = this.library.readdb(`panels.${this.name}.cmd.pagePopup.alwaysOn`)) == null ? void 0 : _r.val) != null ? _s : true), buzzer: !!((_u = (_t = this.library.readdb(`panels.${this.name}.cmd.pagePopup.buzzer`)) == null ? void 0 : _t.val) != null ? _u : false) }; let panels = [this]; if (global) { panels = this.controller.panels; } for (const panel of panels) { await this.statesControler.setInternalState( `${panel.name}/cmd/popupNotificationCustom`, JSON.stringify(details), false ); } break; } case "isBuzzerAllowed": { if (state && state.val != null) { await this.statesControler.setInternalState( `${this.name}/cmd/isBuzzerAllowed`, !!state.val, false ); } break; } } } } /** * timeout screensaver after sec * * @param sec seconds for timeout */ sendScreensaverTimeout(sec) { if (this.unload) { return; } this.log.debug(`Set screeensaver timeout to ${sec}s.`); this.sendToPanel(`timeout~${sec}`, false); } sendDimmode() { const hour = (/* @__PURE__ */ new Date()).getHours(); const oldDayMode = this.dim.dayMode; if (this.dim.schedule) { if (this.dim.nightHourStart > this.dim.nightHourEnd) { if (hour >= this.dim.nightHourStart || hour < this.dim.nightHourEnd) { this.dim.dayMode = false; } else { this.dim.dayMode = true; } } else { if (hour >= this.dim.nightHourStart && hour < this.dim.nightHourEnd) { this.dim.dayMode = false; } else { this.dim.dayMode = true; } } } let cmd = `${import_Color.Color.rgb_dec565(import_Color.Color.Black)}~${import_Color.Color.rgb_dec565(import_Color.Color.foreground)}`; this.log.debug( `set color to RGB ${JSON.stringify(import_Color.Color.foreground)} -> ${import_Color.Color.rgb_dec565(import_Color.Color.foreground)}` ); if (this.dim.dayMode) { cmd = `dimmode~${this.dim.standby}~${this.dim.active}~${cmd}`; } else { cmd = `dimmode~${this.dim.nightStandby}~${this.dim.nightActive}~${cmd}`; } if (this.dim.dayMode !== oldDayMode) { void this.library.writedp( `panels.${this.name}.cmd.dim.dayMode`, this.dim.dayMode, definition.genericStateObjects.panel.panels.cmd.dim.dayMode ); } if (this.unload) { return; } this.sendToPanel(cmd, false); } restartLoops() { if (this.loopTimeout) { this.adapter.clearTimeout(this.loopTimeout); } if (this.unload || this.adapter.unload) { return; } this.loopTimeout = this.adapter.setTimeout(() => { this.loop(); }, 200); } loop = () => { this.pages = this.pages.filter((a) => a && !a.unload); let t = Math.random() * 3e4 + 1e4; if (!this.isOnline) { t = 5e3; if (!this.flashing) { this.panelSend.resetMessageDB(); this.sendToPanel("pageType~pageStartup", false, true, { retain: true }); } } if (this.unload || this.adapter.unload) { return; } this.loopTimeout = this.adapter.setTimeout(() => this.loop, t); }; requestStatusTasmota() { this.sendToTasmota(`${this.topic}/cmnd/STATUS0`, ""); } async delete() { var _a; this.unload = true; this.sendToPanel("pageType~pageStartup", false, true, { retain: true }); if (this.blockStartup) { this.adapter.clearTimeout(this.blockStartup); } this.log.info("Goint offline because delete panel!"); this.isOnline = false; if (this.loopTimeout) { this.adapter.clearTimeout(this.loopTimeout); } await this.library.writedp( `panels.${this.name}.info.isOnline`, false, definition.genericStateObjects.panel.panels.info.isOnline ); await this.navigation.delete(); await ((_a = this.screenSaver) == null ? void 0 : _a.delete()); this.screenSaver = void 0; for (const a of this.pages) { if (a) { await a.delete(); } } await this.panelSend.delete(); this.controller.mqttClient.removeByFunction(this.onMessage); await this.statesControler.deletePageLoop(this.onInternalCommand); this.persistentPageItems = {}; this.pages = []; this._activePage = void 0; this.data = {}; await super.delete(); } getPagebyUniqueID(uniqueID) { var _a; if (!uniqueID) { return null; } const index = this.pages.findIndex((a) => a && a.name && a.name === uniqueID); return (_a = this.pages[index]) != null ? _a : null; } getPageIndexbyUnique