NEWS
Sonoff NSPanel
-
@armilar das mit den farben hast du ganz schnell wieder vergessen ;D
-
@armilar said in Sonoff NSPanel:
@dexxter sagte in Sonoff NSPanel:
@armilar
Ich bin grade dran.
Aktuell passiert es das der Brightnessslider nicht den eingestellten Wert behält.
Also, ich schiebe den Slider auf 20%.....gehe dann da raus, wieder rein und der Slider steht auf 100%.
Der Temperaturslider funktioniert wie er soll.
EDIT: Das verält sich beim "normalen" Dimmer genau so.Ich denke, dass da ein ALIAS noch nicht den Datenpunkt erreicht hat. Habe diverse Lampen unterschiedlichster Art und habe das Verhalten nicht
Moin @Armilar ,
ich hab mir das grade noch mal mit frischem Kopf angeschaut.
Lustigerweise hat der "normale" Dimmer dieses Verhalten heute nicht mehr aber der "hue".
Jetzt habe ich mir mal den Code angeschaut und das hier gefunden :
Kann es sein das da der .ACTUAL Wert fehlt?
Greetz Dexxter -
@dexxter sagte in Sonoff NSPanel:
@armilar said in Sonoff NSPanel:
@dexxter sagte in Sonoff NSPanel:
@armilar
Ich bin grade dran.
Aktuell passiert es das der Brightnessslider nicht den eingestellten Wert behält.
Also, ich schiebe den Slider auf 20%.....gehe dann da raus, wieder rein und der Slider steht auf 100%.
Der Temperaturslider funktioniert wie er soll.
EDIT: Das verält sich beim "normalen" Dimmer genau so.Ich denke, dass da ein ALIAS noch nicht den Datenpunkt erreicht hat. Habe diverse Lampen unterschiedlichster Art und habe das Verhalten nicht
Moin @Armilar ,
ich hab mir das grade noch mal mit frischem Kopf angeschaut.
Lustigerweise hat der "normale" Dimmer dieses Verhalten heute nicht mehr aber der "hue".
Jetzt habe ich mir mal den Code angeschaut und das hier gefunden :
Kann es sein das da der .ACTUAL Wert fehlt?
Greetz DexxterDer Alias Dimmer hat einen .ACTUAL
Der Alias Hue hat keinen .ACTUAL, sondern DIMMER
Der bekommt in der Detailseite auch sein on() über den RegisterDetailEntityWatcher und sollte sich aktualisieren
Daher werden die beiden Aliase unterschiedlich behandelt.
An der Stelle, an der du nachgesehen hast, wird der aktuelle Wert vom Panel übergeben. Wenn ich dich richtig verstehe macht er das auch. Erst beim nächsten Aufbau der Seite, nachdem Sie geschlossen war ist der Wert nicht mehr drin (siehe letzter Screenshot), oder?
Es sei denn JavaScript (ioBroker) sieht den Alias-Datenpunkt "Dimmer" bei dir nicht. Habe ich auch schon gehabt - im Alias stehen alle Datenpunkte, aber Javascript kommt mit existsState = false zurück und der Datenpunkt wird nicht wirklich aktualisiert. Beim schreiben in dem von dir aufgeführten Code-Segment wird setIfExists auch nicht wirklich in den Datenpunkt schreiben, da er wahrscheinlich nicht "existiert", obwohl du ihn siehst!
In dem Fall geh mal in den Datenpunkt vom Dimmer (glaube gelesen zu haben, bei dir der Zigbee-Adapter) und schreibe da von Hand einen anderen Wert rein, so das der Alias einen neuen Wert sieht und aufgeweckt wird.
-
@dexxter habe die Antwort eben noch erweitert
-
@dexxter kannst du aber schnell herausbekommen, wenn du an der Stelle den else-Zweig erweiterst:
let brightness = 0; if (existsState(id + ".DIMMER")) { brightness = Math.trunc(scale(getState(id + ".DIMMER").val, 0, 100, 0, 100)); RegisterDetailEntityWatcher(id + ".DIMMER", pageItem, type); } else { console.warn("Datenpunkt: " + id + ".DIMMER kann nicht gelesen werden"); }
-
@jobr99 @Armilar So, jetzt steh ich gerade wie der Ochs vorm Walde... Ich bin mir nicht sicher, ob ich jetzt einfach nur durch oder dumm bin, oder ob ich einfach falsch an die Sache heran gehe...
Was ich möchte/erwarte:
- NSPanel hat eine lokale Konfiguration für die Anzeige(n) und Widgets
- Ich bekomme Änderungen per MQTT (HTTP(S) mit JSON geht auch) geschickt
- Werte auf dem Display kann ich auch remote (per JSON load oder MQTT syncen)
Was ich finde:
- Eine Menge an Doku und Integrationen
- Zusätzliche Services, die auch wieder irgendwo laufen und quasi als Sync-Server dienen
- Adapter, die mit vorgefertigten Buttons, Screens etc. das Panel bestücken
Jetzt die Frage: Kann ich das mit Deiner Firmware @joBr99 oder wo finde ich eine entsprechende Doku für andere Firmwares?
Bislang kann hab ich in dem NSPanel mit der Orig-Firmware die Widgets im nspanel.be konfiguriert und das hat Änderungen per MQTT geschickt. Der Einfachheit halber habe ich meine Änderungen per NSPSend implementiert, um verschiedenste Anpassungen machen zu können.Beispiel:
Im Wohnzimmer habe 8 Lampen hinter einem Dimmer, die einzeln, als Gruppe etc. schaltbar sind. Der Dimmer muss dafür aber immer einen Mindeststrom liefern, daher habe ich den Schalter vom Widget an die Gruppe für alle Lampen dran und den Slider an den Dimmer.Was kann ich jetzt wie mit einer anderen Firmware machen und... Könntet Ihr mir bitte entsprechende Links schicken?
VIELEN VIELEN LIEBEN DANK !!!
-
ups... falscher thread
-
@great-sun sagte in Sonoff NSPanel:
ups... falscher thread
Nee, diesmal nicht. Bezieht sich ja auf Sonoff Panel und nicht auf technisch Fragen zu adressierbaren Stripes
Zu deinen Erwartungen:
-
NSPanel hat eine lokale Konfiguration für die Anzeige(n) und Widgets
In der nspanel.be von blakadder lassen sich die Widgets anlegen. Ist auch kein Problem, da diese statisch in der Original Sonoff Firmware sind und der Bezug zum Widget erhalten bleibt. Hier funktioniert das nicht - hier wird alles dynamisch aus dem TypeScript instanziert -
Ich bekomme Änderungen per MQTT (HTTP(S) mit JSON geht auch) geschickt
MQTT Payloads über CustomSend (ähnlich NSPSend, jedoch nicht "NSPSend") und Receive -
Werte auf dem Display kann ich auch remote (per JSON load oder MQTT syncen)
funktioniert auch hier Prima über MQTT, da die Datenpunkte getriggert werden
Zu den restlichen Fragen, wo du etwas zu anderer Firmware wissen möchtest kann ich nichts sagen. Da müsstest du schon bei openHAB, etc. googlen, da es aktuell außer der Version von blakadder oder @joBr99 keine weitere ioBroker-Integrationen gibt und die openHAB's da mehr Content haben. Ist dann aber auch nicht JavaScript, sondern Python - was der Grund ist, weshalb wir den Aufwand betreiben. Wenn du etwas anderes findest, dann musst du die Logik natürlich noch bauen.
Zum Beispiel:
Warum sollte das nicht gehen? Wenn es jetzt unter dem Sonoff-Panel funktioniert - dann funktioniert das in der lovelace-ui auch. Sind ja "nur" Schalter und Dimmer.
Was man mit lovelace-ui machen kann, steht hier im Thread. Wo es andere gibt und was die können - Kann ich nicht beantworten.VG
Armilar -
-
@armilar said in Sonoff NSPanel:
@dexxter habe die Antwort eben noch erweitert
Hi @Armilar
Ich habe eben mal wie Du empfohlen hast den Dimmwert händisch eingegeben und folgendes beobachten können.
Der Slider wird tatsächlich doch aktualisiert aber genau falsch herum.
Also wenn ich 5% von Hand eingebe springt der Slider auf 95%
Bei 20% springt er auf 80% usw.
Er gibt aber die richtigen Werte raus wenn ich ihn schiebe.
Also, schiebe ich den Slider auf 20% werden diese auch eingestellt aber der Slider springt dann auf 80%.
Kurz und knapp......Funktion ist da, Anzeige verkehrt herum. -
@dexxter sagte in Sonoff NSPanel:
@armilar said in Sonoff NSPanel:
@dexxter habe die Antwort eben noch erweitert
Hi @Armilar
Ich habe eben mal wie Du empfohlen hast den Dimmwert händisch eingegeben und folgendes beobachten können.
Der Slider wird tatsächlich doch aktualisiert aber genau falsch herum.
Also wenn ich 5% von Hand eingebe springt der Slider auf 95%
Bei 20% springt er auf 80% usw.
Er gibt aber die richtigen Werte raus wenn ich ihn schiebe.
Also, schiebe ich den Slider auf 20% werden diese auch eingestellt aber der Slider springt dann auf 80%.
Kurz und knapp......Funktion ist da, Anzeige verkehrt herum.Hatte ich gestern auch
Hab noch Anpassungen gemacht. Dimmer lässt sich auch begrenzen: Beispiel hinterlegt mit 70% maxValue
var Icons = new IconsSelector(); const Months = ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"]; const Days = ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"]; const Off: RGB = { red: 68, green: 115, blue: 158 }; const On: RGB = { red: 253, green: 216, blue: 53 }; const MSRed: RGB = { red: 251, green: 105, blue: 98 }; const MSGreen: RGB = { red: 121, green: 222, blue: 121 }; const Red: RGB = { red: 255, green: 0, blue: 0 }; const White: RGB = { red: 255, green: 255, blue: 255 }; const Yellow: RGB = { red: 255, green: 255, blue: 0 }; const Green: RGB = { red: 0, green: 255, blue: 0 }; const Blue: RGB = { red: 0, green: 0, blue: 255 }; const Gray: RGB = { red: 136, green: 136, blue: 136 }; const Black: RGB = { red: 0, green: 0, blue: 0 }; const colorSpotify: RGB = { red: 30, green: 215, blue: 96 }; const colorAlexa: RGB = { red: 49, green: 196, blue: 243 }; const colorRadio: RGB = { red: 255, green: 127, blue: 0 }; const BatteryFull: RGB = { red: 96, green: 176, blue: 62 }; const BatteryEmpty: RGB = { red: 179, green: 45, blue: 25 }; //----Möglichkeit, im Screensaver zwischen Accu-Weather Forecast oder selbstdefinierten Werten zu wählen--------------------------------- var weatherForecast = true; //true = WheatherForecast 5 Days --- false = Config --> firstScreensaverEntity - fourthScreensaverEntity ... //Alexa-Instanz var alexaInstanz = "alexa2.0" var alexaDevice = "G0XXXXXXXXXXXXXX"; //Primär zu steuendes Device // Wenn alexaSpeakerList definiert, dann werden Einträge verwendet, sonst alle relevanten Devices aus Alexa-Instanz // Speakerwechsel funktioniert nicht bei Radio/TuneIn sonden bei Playlists const alexaSpeakerList = []; //Beispiel ["Echo Spot Buero","Überall","Gartenhaus","Esszimmer","Heimkino"]; //const alexaSpeakerList = ["Echo Spot Buero","Überall","Gartenhaus","Esszimmer","Heimkino","Echo Dot Küche"]; //Datenpunkte für Nachricht an Screensaver var popupNotifyHeading = "0_userdata.0.NSPanel.1.popupNotifyHeading"; var popupNotifyText = "0_userdata.0.NSPanel.1.popupNotifyText"; var Test_Licht: PageEntities = { "type": "cardEntities", "heading": "Büro", "useColor": true, "items": [ <PageItem>{ id: "alias.0.NSPanel_1.Schreibtischlampe"}, <PageItem>{ id: "alias.0.NSPanel_1.Testlampe2", name: "Filamentlampe", minValue: 0, maxValue: 70}, <PageItem>{ id: "alias.0.NSPanel_1.TestCTmitHUE", name: "HUE-Light-CT"}, <PageItem>{ id: "alias.0.NSPanel_1.TestHUELicht", name: "HUE-Light-Color", minValue: 500, maxValue: 6500} ] }; var Buero_Seite_1: PageEntities = { "type": "cardEntities", "heading": "Büro", "useColor": true, "items": [ <PageItem>{ id: "alias.0.NSPanel_1.Schreibtischlampe"}, <PageItem>{ id: "alias.0.NSPanel_1.Deckenbeleuchtung"}, <PageItem>{ id: "alias.0.NSPanel_1.Testlampe2"}, <PageItem>{ id: "alias.0.NSPanel_1.Luftreiniger", icon: "power", offColor: MSRed, onColor: MSGreen} ] }; var Fenster_1: PageEntities = { "type": "cardEntities", "heading": "Fenster und Türen", "useColor": true, "items": [ <PageItem>{ id: "alias.0.NSPanel_1.TestFenster", offColor: MSRed, onColor: MSGreen, name: "Büro Fenster"}, <PageItem>{ id: "alias.0.NSPanel_1.Haustuer", offColor: MSRed, onColor: MSGreen, name: "Haustür"}, <PageItem>{ id: "alias.0.NSPanel_1.TestBlind", onColor: White, name: "IKEA Fyrtur"} ] }; var Abfall: PageEntities = { "type": "cardEntities", "heading": "Abfallkalender", "useColor": true, "items": [ <PageItem>{ id: "alias.0.NSPanel_1.Abfall.event1",icon: "trash-can"}, <PageItem>{ id: "alias.0.NSPanel_1.Abfall.event2",icon: "trash-can"}, <PageItem>{ id: "alias.0.NSPanel_1.Abfall.event3",icon: "trash-can"}, <PageItem>{ id: "alias.0.NSPanel_1.Abfall.event4",icon: "trash-can"} ] }; var Buero_Seite_2: PageGrid = { "type": "cardGrid", "heading": "Büro 2", "useColor": true, "items": [ <PageItem>{ id: "alias.0.NSPanel_1.Schreibtischlampe", name: "Schreibtisch"}, <PageItem>{ id: "alias.0.NSPanel_1.Deckenbeleuchtung", name: "Deckenlampe"}, <PageItem>{ id: "alias.0.NSPanel_1.TestFenster", offColor: MSRed, onColor: MSGreen, name: "Büro Fenster"}, <PageItem>{ id: "alias.0.NSPanel_1.Luftreiniger", icon: "power", offColor: MSRed, onColor: MSGreen}, <PageItem>{ id: "alias.0.NSPanel_1.TestBlind", icon: "projector-screen", onColor: White, name: "Beamer"}, <PageItem>{ id: "alias.0.NSPanel_1.Radio.TuneIn", icon: "play", onColor: White} ] }; var Alexa: PageMedia = { "type": "cardMedia", "heading": "Alexa", "useColor": true, "items": [<PageItem>{ id: "alias.0.NSPanel_1.Alexa.PlayerBuero" }] }; var Buero_Themostat: PageThermo = { "type": "cardThermo", "heading": "Thermostat", "useColor": true, "items": [<PageItem>{ id: "alias.0.NSPanel_1.Thermostat_Büro" }] }; var Buero_Alarm: PageAlarm = { "type": "cardAlarm", "heading": "Alarm", "useColor": true, "items": [<PageItem>{ id: "alias.0.NSPanel_1.Alarm" }] }; var button1Page: PageGrid = { "type": "cardGrid", "heading": "Radio", "useColor": true, "items": [ <PageItem>{ id: "alias.0.NSPanel_1.Radio.FFN", icon: "radio", name: "FFN", onColor: colorRadio}, <PageItem>{ id: "alias.0.NSPanel_1.Radio.Antenne" , icon: "radio", name: "Antenne Nds.", onColor: colorRadio}, <PageItem>{ id: "alias.0.NSPanel_1.Radio.NDR2", icon: "radio", name: "NDR2", onColor: colorRadio}, <PageItem>{ id: "alias.0.NSPanel_1.Radio.Bob", icon: "radio", name: "Radio BOB", onColor: colorRadio}, <PageItem>{ id: "alias.0.NSPanel_1.Radio.Spotify", icon: "spotify", name: "Party Playlist", onColor: colorSpotify}, <PageItem>{ id: "alias.0.NSPanel_1.Radio.Alexa", icon: "playlist-music", name: "Playlist 2021", onColor: colorAlexa} ] }; var button2Page: PageEntities = { "type": "cardEntities", "heading": "Büro", "useColor": true, "items": [ <PageItem>{ id: "alias.0.NSPanel_1.Schreibtischlampe"}, <PageItem>{ id: "alias.0.NSPanel_1.Deckenbeleuchtung"} ] }; export const config: Config = { panelRecvTopic: "mqtt.0.SmartHome.NSPanel_1.tele.RESULT", //anpassen panelSendTopic: "mqtt.0.SmartHome.NSPanel_1.cmnd.CustomSend", //anpassen firstScreensaverEntity: { ScreensaverEntity: "hmip.0.devices.3014F711A000185BE9922BCF.channels.1.humidity", ScreensaverEntityIcon: "water-percent", ScreensaverEntityText: "Luft", ScreensaverEntityUnitText: "%" }, secondScreensaverEntity: { ScreensaverEntity: "accuweather.0.Daily.Day1.Day.PrecipitationProbability", ScreensaverEntityIcon: "weather-pouring", ScreensaverEntityText: "Regen", ScreensaverEntityUnitText: "%" }, thirdScreensaverEntity: { ScreensaverEntity: "0_userdata.0.Wetter.Windstaerke_homaticIP", ScreensaverEntityIcon: "weather-windy", ScreensaverEntityText: "Wind", ScreensaverEntityUnitText: "bft" }, fourthScreensaverEntity: { ScreensaverEntity: "accuweather.0.Current.UVIndex", ScreensaverEntityIcon: "solar-power", ScreensaverEntityText: "UV", ScreensaverEntityUnitText: "" }, timeoutScreensaver: 15, dimmode: 8, screenSaverDoubleClick: false, locale: "de_DE", timeFormat: "%H:%M", dateFormat: "%A, %d. %B %Y", weatherEntity: "alias.0.Wetter.Wetter", defaultOffColor: Off, defaultOnColor: On, defaultColor: Off, temperatureUnit: "°C", pages: [ Buero_Seite_1, //Test_Licht, Fenster_1, Abfall, //Buero_Seite_2, Alexa, Buero_Themostat, Buero_Alarm ], button1Page: button1Page, button2Page: button2Page }; // _________________________________ Ab hier keine Konfiguration mehr _____________________________________ //Notification an Screensaver on({id: [popupNotifyHeading, popupNotifyText], change: "ne"}, async function (obj) { setState(config.panelSendTopic,(['notify~',getState(popupNotifyHeading).val,'~',getState(popupNotifyText).val].join(''))); }); var subscriptions: any = {}; var screensaverEnabled : boolean = false; var pageId = 0; schedule("* * * * *", function () { SendTime(); }); schedule("0 * * * *", function () { SendDate(); }); // Only monitor the extra nodes if present var updateArray: string[] = []; if (config.firstScreensaverEntity !== null && config.firstScreensaverEntity.ScreensaverEntity != null && existsState(config.firstScreensaverEntity.ScreensaverEntity)) { updateArray.push(config.firstScreensaverEntity.ScreensaverEntity) } if (config.secondScreensaverEntity !== null && config.secondScreensaverEntity.ScreensaverEntity != null && existsState(config.secondScreensaverEntity.ScreensaverEntity)) { updateArray.push(config.secondScreensaverEntity.ScreensaverEntity) } if (config.thirdScreensaverEntity !== null && config.thirdScreensaverEntity.ScreensaverEntity != null && existsState(config.thirdScreensaverEntity.ScreensaverEntity)) { updateArray.push(config.thirdScreensaverEntity.ScreensaverEntity) } if (config.fourthScreensaverEntity !== null && config.fourthScreensaverEntity.ScreensaverEntity != null && existsState(config.fourthScreensaverEntity.ScreensaverEntity)) { updateArray.push(config.fourthScreensaverEntity.ScreensaverEntity) } if (updateArray.length > 0) { on(updateArray, function () { HandleScreensaverUpdate(); }) } on({ id: config.panelRecvTopic }, function (obj) { if (obj.state.val.startsWith('\{"CustomRecv":')) { var json = JSON.parse(obj.state.val); var split = json.CustomRecv.split(","); HandleMessage(split[0], split[1], parseInt(split[2]), split); } }); function SendToPanel(val: Payload | Payload[]): void { if (Array.isArray(val)) { val.forEach(function (id, i) { setState(config.panelSendTopic, id.payload); }); } else setState(config.panelSendTopic, val.payload); } function HandleMessage(typ: string, method: string, page: number, words: Array<string>): void { if (typ == "event") { switch (method) { case "startup": screensaverEnabled = false; UnsubscribeWatcher(); HandleStartupProcess(); pageId = 0; GeneratePage(config.pages[0]); break; case "sleepReached": screensaverEnabled = true; if (pageId < 0) pageId = 0; HandleScreensaver(); break; case "pageOpenDetail": screensaverEnabled = false; UnsubscribeWatcher(); let pageItem = config.pages[pageId].items.find(e => e.id === words[3]); if (pageItem !== undefined) SendToPanel(GenerateDetailPage(words[2], pageItem)); case "buttonPress2": screensaverEnabled = false; HandleButtonEvent(words); break; case "button1": case "button2": screensaverEnabled = false; HandleHardwareButton(method); default: break; } } } function GeneratePage(page: Page): void { switch (page.type) { case "cardEntities": SendToPanel(GenerateEntitiesPage(<PageEntities>page)); break; case "cardThermo": SendToPanel(GenerateThermoPage(<PageThermo>page)); break; case "cardGrid": SendToPanel(GenerateGridPage(<PageGrid>page)); break; case "cardMedia": SendToPanel(GenerateMediaPage(<PageMedia>page)); break; case "cardAlarm": SendToPanel(GenerateAlarmPage(<PageAlarm>page)); break; } } function HandleHardwareButton(method: string): void { let page: (PageThermo | PageMedia | PageAlarm | PageEntities | PageGrid); if (config.button1Page !== null && method == "button1") { page = config.button1Page; pageId = -1; } else if (config.button2Page !== null && method == "button2") { page = config.button2Page; pageId = -2; } else { return; } GeneratePage(page); } function HandleStartupProcess(): void { SendDate(); SendTime(); SendToPanel({ payload: "timeout~" + config.timeoutScreensaver }); SendToPanel({ payload: "dimmode~" + config.dimmode }); } function SendDate(): void { var d = new Date(); var day = Days[d.getDay()]; var date = d.getDate(); var month = Months[d.getMonth()]; var year = d.getFullYear(); var _sendDate = "date~" + day + " " + date + " " + month + " " + year; SendToPanel(<Payload>{ payload: _sendDate }); } function SendTime(): void { var d = new Date(); var hr = d.getHours().toString(); var min = d.getMinutes().toString(); if (d.getHours() < 10) { hr = "0" + d.getHours().toString(); } if (d.getMinutes() < 10) { min = "0" + d.getMinutes().toString(); } SendToPanel(<Payload>{ payload: "time~" + hr + ":" + min }); } function GenerateEntitiesPage(page: PageEntities): Payload[] { var out_msgs: Array<Payload> = []; out_msgs = [{ payload: "pageType~cardEntities" }] out_msgs.push({ payload: GeneratePageElements(page) }); return out_msgs } function GenerateGridPage(page: PageGrid): Payload[] { var out_msgs: Array<Payload> = []; out_msgs = [{ payload: "pageType~cardGrid" }] out_msgs.push({ payload: GeneratePageElements(page) }); return out_msgs } function GeneratePageElements(page: Page): string { let maxItems = 0; switch (page.type) { case "cardThermo": maxItems = 1; break; case "cardAlarm": maxItems = 1; break; case "cardMedia": maxItems = 1; break; case "cardEntities": maxItems = 4; break; case "cardGrid": maxItems = 6; break; } let pageData = "entityUpd~" + page.heading + "~" + GetNavigationString(pageId) for (let index = 0; index < maxItems; index++) { if (page.items[index] !== undefined) { pageData += CreateEntity(page.items[index], index + 1, page.useColor); } else { pageData += CreateEntity(<PageItem>{ id: "delete" }, index + 1); } } return pageData; } function CreateEntity(pageItem: PageItem, placeId: number, useColors: boolean = false): string { var iconId = "0" if (pageItem.id == "delete") { return "~delete~~~~~" } var name: string; var type: string; // ioBroker if (existsObject(pageItem.id)) { let o = getObject(pageItem.id) var val = null; name = pageItem.name !== undefined ? pageItem.name : o.common.name.de if (existsState(pageItem.id + ".GET")) { val = getState(pageItem.id + ".GET").val; RegisterEntityWatcher(pageItem.id + ".GET"); } else if (existsState(pageItem.id + ".SET")) { val = getState(pageItem.id + ".SET").val; RegisterEntityWatcher(pageItem.id + ".SET"); } var iconColor = rgb_dec565(config.defaultColor); switch (o.common.role) { case "socket": case "light": type = "light" iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : o.common.role == "socket" ? Icons.GetIcon("power-socket-de") : Icons.GetIcon("lightbulb"); var optVal = "0" if (val === true || val === "true") { optVal = "1" iconColor = GetIconColor(pageItem, true, useColors); } else { iconColor = GetIconColor(pageItem, false, useColors); } return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + optVal; case "hue": type = "light" iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("lightbulb"); var optVal = "0" if (existsState(pageItem.id + ".ON_ACTUAL")) { val = getState(pageItem.id + ".ON_ACTUAL").val; RegisterEntityWatcher(pageItem.id + ".ON_ACTUAL"); } if (val === true || val === "true") { optVal = "1" iconColor = GetIconColor(pageItem, existsState(pageItem.id + ".ON") ? getState(pageItem.id + ".ON").val : true, useColors); } return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + optVal; case "dimmer": type = "light" iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("lightbulb"); var optVal = "0" if (existsState(pageItem.id + ".ON_ACTUAL")) { val = getState(pageItem.id + ".ON_ACTUAL").val; RegisterEntityWatcher(pageItem.id + ".ON_ACTUAL"); } else if (existsState(pageItem.id + ".ON_SET")) { val = getState(pageItem.id + ".ON_SET").val; RegisterEntityWatcher(pageItem.id + ".ON_SET"); } if (val === true || val === "true") { optVal = "1" iconColor = GetIconColor(pageItem, existsState(pageItem.id + ".ACTUAL") ? getState(pageItem.id + ".ACTUAL").val : true, useColors); } return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + optVal; case "blind": type = "shutter" iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("window-open"); iconColor = GetIconColor(pageItem, existsState(pageItem.id + ".ACTUAL") ? getState(pageItem.id + ".ACTUAL").val : true, useColors); return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" case "door": case "window": type = "text"; if (existsState(pageItem.id + ".ACTUAL")) { if (getState(pageItem.id + ".ACTUAL").val) { iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : o.common.role == "door" ? Icons.GetIcon("door-open") : Icons.GetIcon("window-open-variant"); iconColor = GetIconColor(pageItem, false, useColors); var windowState = "opened" } else { iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : o.common.role == "door" ? Icons.GetIcon("door-closed") : Icons.GetIcon("window-closed-variant"); //iconId = Icons.GetIcon("window-closed-variant"); iconColor = GetIconColor(pageItem, true, useColors); var windowState = "closed" } RegisterEntityWatcher(pageItem.id + ".ACTUAL"); } return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + windowState; case "info": case "humidity": case "value.temperature": case "value.humidity": case "sensor.door": case "sensor.window": case "thermostat": type = "text"; iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : o.common.role == "value.temperature" || o.common.role == "thermostat" ? Icons.GetIcon("thermometer") : Icons.GetIcon("information-outline"); let unit = ""; var optVal = "0" if (existsState(pageItem.id + ".ON_ACTUAL")) { optVal = getState(pageItem.id + ".ON_ACTUAL").val; unit = pageItem.unit !== undefined ? pageItem.unit : GetUnitOfMeasurement(pageItem.id + ".ON_ACTUAL"); RegisterEntityWatcher(pageItem.id + ".ON_ACTUAL"); } else if (existsState(pageItem.id + ".ACTUAL")) { optVal = getState(pageItem.id + ".ACTUAL").val; unit = pageItem.unit !== undefined ? pageItem.unit : GetUnitOfMeasurement(pageItem.id + ".ACTUAL"); RegisterEntityWatcher(pageItem.id + ".ACTUAL"); } if (o.common.role == "value.temperature") { iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("thermometer"); } iconColor = GetIconColor(pageItem, parseInt(optVal), useColors); return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + optVal + " " + unit; case "button": type = "button"; iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("gesture-tap-button"); let buttonText = pageItem.name !== undefined ? pageItem.name : "PRESS"; iconColor = GetIconColor(pageItem, true, useColors); return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + buttonText; case "warning": type = "text"; iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("alert-outline"); iconColor = getState(([pageItem.id,'.LEVEL'].join(''))).val; let itemName = getState(([pageItem.id,'.TITLE'].join(''))).val; let itemInfo = getState(([pageItem.id,'.INFO'].join(''))).val; return "~" + type + "~" + itemName + "~" + iconId + "~" + iconColor + "~" + itemName + "~" + itemInfo; default: return "~delete~~~~~"; } } return "~delete~~~~~" } function GetIconColor(pageItem: PageItem, value: (boolean | number), useColors: boolean): number { // dimmer if ((pageItem.useColor || useColors) && pageItem.interpolateColor && typeof (value) === "number") { let maxValue = pageItem.maxValue !== undefined ? pageItem.maxValue : 100; let minValue = pageItem.minValue !== undefined ? pageItem.minValue : 0; value = value > maxValue ? maxValue : value; value = value < minValue ? minValue : value; return rgb_dec565( Interpolate( pageItem.offColor !== undefined ? pageItem.offColor : config.defaultOffColor, pageItem.onColor !== undefined ? pageItem.onColor : config.defaultOnColor, scale(value, minValue, maxValue, 0, 1) )); } if ((pageItem.useColor || useColors) && ((typeof (value) === "boolean" && value) || value > (pageItem.minValue !== undefined ? pageItem.minValue : 0))) { return rgb_dec565(pageItem.onColor !== undefined ? pageItem.onColor : config.defaultOnColor) } return rgb_dec565(pageItem.offColor !== undefined ? pageItem.offColor : config.defaultOffColor); } function RegisterEntityWatcher(id: string): void { if (subscriptions.hasOwnProperty(id)) { return; } subscriptions[id] = (on({ id: id, change: 'any' }, function (data) { if(pageId >= 0) SendToPanel({ payload: GeneratePageElements(config.pages[pageId]) }); if(pageId == -1 && config.button1Page != undefined) SendToPanel({ payload: GeneratePageElements(config.button1Page) }); if(pageId == -2 && config.button2Page != undefined) SendToPanel({ payload: GeneratePageElements(config.button2Page) }); })) } function RegisterDetailEntityWatcher(id: string, pageItem: PageItem, type: string): void { if (subscriptions.hasOwnProperty(id)) { return; } subscriptions[id] = (on({ id: id, change: 'any' }, function () { SendToPanel(GenerateDetailPage(type, pageItem)); })) } function GetUnitOfMeasurement(id: string): string { if (!existsObject(id)) return ""; let obj = getObject(id); if (typeof obj.common.unit !== 'undefined') { return obj.common.unit } if (typeof obj.common.alias !== 'undefined' && typeof obj.common.alias.id !== 'undefined') { return GetUnitOfMeasurement(obj.common.alias.id); } return ""; } function GenerateThermoPage(page: PageThermo): Payload[] { var id = page.items[0].id var out_msgs: Array<Payload> = []; out_msgs.push({ payload: "pageType~cardThermo" }); // ioBroker if (existsObject(id)) { let o = getObject(id) let name = page.items[0].name !== undefined ? page.items[0].name : o.common.name.de let currentTemp = 0; if (existsState(id + ".ACTUAL")) currentTemp = (Math.round(parseFloat(getState(id + ".ACTUAL").val) * 10)/10)*10; let destTemp = 0; if (existsState(id + ".SET")) { destTemp = getState(id + ".SET").val.toFixed(2) * 10; } let status = "" if (existsState(id + ".MODE")) status = getState(id + ".MODE").val; let minTemp = 50 //Min Temp 5°C let maxTemp = 300 //Max Temp 30°C let stepTemp = 5 //0-4 verwendet bei ungerader Anzahl Parametern let bt0 = "~~~~"; //verwendet bei ungleichen Parametern let bt1 = "~~~~"; //verwendet bei ungleichen Parametern let bt2 = "~~~~"; //verwendet bei ungleichen Parametern let bt3 = "~~~~"; //verwendet bei ungleichen Parametern let bt4 = "~~~~"; //verwendet bei ungleichen Parametern //5-8 verwendet bei gerader Anzahl Parametern let bt5 = Icons.GetIcon("water-percent") + "~0~1~~"; let bt6 = Icons.GetIcon("fire") + "~0~1~~"; let bt7 = Icons.GetIcon("wifi") + "~0~1~~"; let bt8 = Icons.GetIcon("battery-high") + "~0~1~~"; if (existsState(id + ".HUMIDITY")){ bt5 = Icons.GetIcon("water-percent") + "~2016~1~bt8~"; if (parseInt(getState(id + ".HUMIDITY").val) < 40) { bt5 = Icons.GetIcon("water-percent") + "~65504~1~bt8~"; } else if (parseInt(getState(id + ".HUMIDITY").val) < 30) { bt5 = Icons.GetIcon("water-percent") + "~63488~1~bt8~"; } else if (parseInt(getState(id + ".HUMIDITY").val) > 65) { bt5 = Icons.GetIcon("water-percent") + "~65504~1~bt8~"; } else if (parseInt(getState(id + ".HUMIDITY").val) > 75) { bt5 = Icons.GetIcon("water-percent") + "~63488~1~bt8~"; } } if (existsState(id + ".MAINTAIN")){ if (getState(id + ".MAINTAIN").val >> .1) { bt6 = Icons.GetIcon("fire") + "~60897~1~bt8~"; } else { bt6 = Icons.GetIcon("fire") + "~33840~0~bt8~"; } } if (existsState(id + ".UNREACH")){ if (getState(id + ".UNREACH").val) { bt7 = Icons.GetIcon("wifi-off") + "~63488~1~bt8~"; } else { bt7 = Icons.GetIcon("wifi") + "~2016~1~bt8~"; } } if (existsState(id + ".LOWBAT")){ if (getState(id + ".LOWBAT").val) { bt8 = Icons.GetIcon("battery-low") + "~63488~1~bt8~"; } else { bt8 = Icons.GetIcon("battery-high") + "~2016~1~bt8~"; } } let icon_res = bt0 + bt1 + bt2 + bt3 + bt4 + bt5 + bt6 + bt7 + bt8; out_msgs.push({ payload: "entityUpd~" + name + "~" + GetNavigationString(pageId) + "~" + id + "~" + currentTemp + "~" + destTemp + "~" + status + "~" + minTemp + "~" + maxTemp + "~" + stepTemp + "~" +icon_res}) } return out_msgs } function GenerateMediaPage(page: PageMedia): Payload[] { var id = page.items[0].id var out_msgs: Array<Payload> = []; out_msgs.push({ payload: "pageType~cardMedia" }); if (existsObject(id)) { let name = getState(id + ".ALBUM").val; let media_icon = Icons.GetIcon("playlist-music"); let title = getState(id + ".TITLE").val; let author = getState(id + ".ARTIST").val; let volume = getState(id + ".VOLUME").val; var iconplaypause = Icons.GetIcon("pause"); //pause var onoffbutton = 1374; if (getState(id + ".STATE").val) { onoffbutton = 65535; iconplaypause = Icons.GetIcon("pause"); //pause } else { iconplaypause = Icons.GetIcon("play"); //play } let currentSpeaker = getState(([alexaInstanz,'.Echo-Devices.',alexaDevice,'.Info.name'].join(''))).val; //console.log(id); //------------------------------------------------------------------------------------------------------------- // nachfolgend alle Alexa-Devices (ist Online / Player- und Commands-Verzeichnis vorhanden) auflisten und verketten // Wenn Konstante alexaSpeakerList mind. einen Eintrag enthält, wird die Konstante verwendet - ansonsten Alle Devices aus dem Alexa Adapter let speakerlist = ""; if (alexaSpeakerList.length > 0) { for (let i_index in alexaSpeakerList) { speakerlist = speakerlist + alexaSpeakerList[i_index] + "?"; } } else { let i_list = Array.prototype.slice.apply($('[state.id="' + alexaInstanz + '.Echo-Devices.*.Info.name"]')); for (let i_index in i_list) { let i = i_list[i_index]; let deviceId = i; deviceId = deviceId.split('.'); if (getState(([alexaInstanz,'.Echo-Devices.',deviceId[3],'.online'].join(''))).val && existsObject(([alexaInstanz,'.Echo-Devices.',deviceId[3],'.Player'].join(''))) && existsObject(([alexaInstanz,'.Echo-Devices.',deviceId[3],'.Commands'].join('')))) { speakerlist = speakerlist + getState(i).val + "?"; } } } speakerlist = speakerlist.substring(0,speakerlist.length-1); //-------------------------------------------------------------------------------------------------------------- out_msgs.push({ payload: "entityUpd~" + name + "~" + id + "~" + id + "~" + //???? media_icon + "~" + title + "~" + author + "~" + volume + "~" + iconplaypause + "~" + currentSpeaker + "~" + speakerlist + "~" + onoffbutton}); } return out_msgs } function GenerateAlarmPage(page: PageAlarm): Payload[] { var id = page.items[0].id var out_msgs: Array<Payload> = []; out_msgs.push({ payload: "pageType~cardAlarm" }); var armed: boolean = true; if (armed) { var arm1 = "Deaktivieren"; //arm1*~* var arm1ActionName = "D1"; //arm1ActionName*~* var arm2 = ""; //arm2*~* var arm2ActionName = ""; //arm2ActionName*~* var arm3 = ""; //arm3*~* var arm3ActionName = ""; //arm3ActionName*~* var arm4 = ""; //arm4*~* var arm4ActionName = ""; //arm4ActionName*~* var icon = Icons.GetIcon("shield-home"); //icon*~* var iconcolor = 63488; //iconcolor*~* var numpadStatus = 1; //numpadStatus*~* var flashing = 1; //flashing* } else { var arm1 = "Alarm 1"; //arm1*~* var arm1ActionName = "A1"; //arm1ActionName*~* var arm2 = "Alarm 2"; //arm2*~* var arm2ActionName = "A2"; //arm2ActionName*~* var arm3 = "Alarm 3"; //arm3*~* var arm3ActionName = "A3"; //arm3ActionName*~* var arm4 = "Alarm 4"; //arm4*~* var arm4ActionName = "A4"; //arm4ActionName*~* var icon = Icons.GetIcon("shield-off"); //icon*~* var iconcolor = 2016; //iconcolor*~* var numpadStatus = 1; //numpadStatus*~* var flashing = 1; //flashing* } out_msgs.push({ payload: "entityUpd~" + //entityUpd~* id + "~" + //internalNameEntity*~* //navigation*~* "~" + //??? arm1 + "~" + //arm1*~* arm1ActionName + "~" + //arm1ActionName*~* arm2 + "~" + //arm2*~* arm2ActionName + "~" + //arm2ActionName*~* arm3 + "~" + //arm3*~* arm3ActionName + "~" + //arm3ActionName*~* arm4 + "~" + //arm4*~* arm4ActionName + "~" + //arm4ActionName*~* icon + "~" + //icon*~* 39=Disarmed 35=Shield_Home, 40 iconcolor + "~" + //iconcolor*~* 2016=green 63488=red numpadStatus + "~" + //numpadStatus*~* flashing}); //flashing* return out_msgs } function setIfExists(id: string, value: any, type: string | null = null): boolean { if (type === null) { if (existsState(id)) { setState(id, value); return true; } } else { let obj = getObject(id); if (existsState(id) && obj.common.type !== undefined && obj.common.type === type) { setState(id, value); return true; } } return false; } function toggleState(id: string): boolean { let obj = getObject(id); if (existsState(id) && obj.common.type !== undefined && obj.common.type === "boolean") { setState(id, !getState(id).val); return true; } return false; } function HandleButtonEvent(words): void { let id = words[2] let buttonAction = words[3]; console.log(words[0] + " - " + words[1] + " - " + words[2] + " - " + words[3] + " - " + words[4] + " - PageId: " + pageId); switch (buttonAction) { case "bNext": var pageNum = ((pageId + 1) % config.pages.length); pageId = Math.abs(pageNum); UnsubscribeWatcher(); GeneratePage(config.pages[pageId]); break; case "bPrev": var pageNum = ((pageId - 1) % config.pages.length); pageId = Math.abs(pageNum); UnsubscribeWatcher(); GeneratePage(config.pages[pageId]); break; case "bExit": if (config.screenSaverDoubleClick) { if (words[4] == 2) GeneratePage(config.pages[pageId]); } else GeneratePage(config.pages[pageId]); break; case "OnOff": if (existsObject(id)) { var action = false if (words[4] == "1") action = true let o = getObject(id) switch (o.common.role) { case "light": setIfExists(id + ".SET", action); break; case "dimmer": setIfExists(id + ".ON_SET", action) ? true : setIfExists(id + ".ON_ACTUAL", action); break; case "hue": // Armilar setIfExists(id + ".ON_ACTUAL", action); } } break; case "up": setIfExists(id + ".OPEN", true) break; case "stop": setIfExists(id + ".STOP", true) break; case "down": setIfExists(id + ".CLOSE", true) break; case "button": toggleState(id + ".SET") ? true : toggleState(id + ".ON_SET") break; case "positionSlider": setIfExists(id + ".SET", parseInt(words[4])) ? true : setIfExists(id + ".ACTUAL", parseInt(words[4])); break; case "brightnessSlider": if (existsObject(id)) { let o = getObject(id); let pageItem = config.pages[pageId].items.find(e => e.id === id); switch (o.common.role) { case "dimmer": if (pageItem.minValue != undefined && pageItem.maxValue != undefined) { let sliderPos = Math.trunc(scale(parseInt(words[4]), 0, 100, pageItem.maxValue, pageItem.minValue)) setIfExists(id + ".SET", sliderPos) ? true : setIfExists(id + ".ACTUAL", sliderPos); } else { setIfExists(id + ".SET", parseInt(words[4])) ? true : setIfExists(id + ".ACTUAL", parseInt(words[4])); } break; case "hue": setIfExists(id + ".DIMMER", parseInt(words[4])); } } break; case "colorTempSlider": // Armilar - Slider tickt verkehrt - Hell = 0 / Dunkel = 100 -> Korrektur let pageItem = config.pages[pageId].items.find(e => e.id === id); if (pageItem.minValue !== undefined && pageItem.minValue !== undefined) { let colorTempK = Math.trunc(scale(parseInt(words[4]), 0, 100, pageItem.minValue, pageItem.maxValue)); setIfExists(id + ".TEMPERATURE", (colorTempK)); } else { setIfExists(id + ".TEMPERATURE", 100 - words[4]); } break; case "colorWheel": let colorCoordinates = words[4].split('|'); let rgb = pos_to_color(colorCoordinates[0], colorCoordinates[1]); //console.log(rgb); //console.log(getHue(rgb.red, rgb.green, rgb.blue)); setIfExists(id + ".HUE", getHue(rgb.red, rgb.green, rgb.blue)); break; case "tempUpd": setIfExists(id + ".SET", parseInt(words[4]) / 10) break; case "media-back": setIfExists(id + ".PREV", true) break; case "media-pause": if (getState(id + ".STATE").val === true) { setIfExists(id + ".PAUSE", true) } else { setIfExists(id + ".PLAY", true) } break; case "media-next": setIfExists(id + ".NEXT", true) break; case "volumeSlider": setIfExists(id + ".VOLUME", parseInt(words[4])) break; case "speaker-sel": let i_list = Array.prototype.slice.apply($('[state.id="' + alexaInstanz + '.Echo-Devices.*.Info.name"]')); for (let i_index in i_list) { let i = i_list[i_index]; if ((getState(i).val) === words[4]){ let deviceId = i; deviceId = deviceId.split('.'); setIfExists(alexaInstanz + ".Echo-Devices." + alexaDevice + ".Commands.textCommand", "Schiebe meine Musik auf " + words[4]); alexaDevice = deviceId[3] } } break; case "media-OnOff": setIfExists(id + ".STOP", true) break; case "A1": //Alarm-Page Alarm 1 aktivieren console.log("auf mediaAlarm - Alarm 1 - Wert: " + words[4] + " - reagieren - noch nicht implementiert"); break; case "A2": //Alarm-Page Alarm 2 aktivieren console.log("auf mediaAlarm - Alarm 1 - Wert: " + words[4] + " - reagieren - noch nicht implementiert"); break; case "A3": //Alarm-Page Alarm 3 aktivieren console.log("auf mediaAlarm - Alarm 1 - Wert: " + words[4] + " - reagieren - noch nicht implementiert"); break; case "A4": //Alarm-Page Alarm 4 aktivieren console.log("auf mediaAlarm - Alarm 1 - Wert: " + words[4] + " - reagieren - noch nicht implementiert"); break; case "D1": //Alarm-Page Alarm Deaktivieren console.log("auf mediaAlarm - Alarm 1 - Wert: " + words[4] + " - reagieren - noch nicht implementiert"); break; default: break; } } function GetNavigationString(pageId: number): string { switch (pageId) { case 0: return "0|1"; case config.pages.length - 1: return "1|0"; case -1: return "0|0"; default: return "1|1"; } } function GenerateDetailPage(type: string, pageItem: PageItem): Payload[] { var out_msgs: Array<Payload> = []; let id = pageItem.id if (existsObject(id)) { var o = getObject(id) var val: (boolean | number) = 0; let icon = Icons.GetIcon("lightbulb"); var iconColor = rgb_dec565(config.defaultColor); if (type == "popupLight") { let switchVal = "0" if (o.common.role == "light") { if (existsState(id + ".GET")) { val = getState(id + ".GET").val; RegisterDetailEntityWatcher(id + ".GET", pageItem, type); } else if (existsState(id + ".SET")) { val = getState(id + ".SET").val; RegisterDetailEntityWatcher(id + ".SET", pageItem, type); } if (val) { switchVal = "1"; iconColor = GetIconColor(pageItem, true, false); } out_msgs.push({ payload: "entityUpdateDetail~" + icon + "~" + + iconColor + "~" + switchVal + ",disable,disable,disable" }) } if (o.common.role == "dimmer") { if (existsState(id + ".ON_ACTUAL")) { val = getState(id + ".ON_ACTUAL").val; RegisterDetailEntityWatcher(id + ".ON_ACTUAL", pageItem, type); } else if (existsState(id + ".ON_SET")) { val = getState(id + ".ON_SET").val; RegisterDetailEntityWatcher(id + ".ON_SET", pageItem, type); } if (val === true) { var iconColor = GetIconColor(pageItem, val, false); switchVal = "1" } let brightness = 0; if (existsState(id + ".ACTUAL")) { if (pageItem.minValue != undefined && pageItem.maxValue != undefined) { brightness = Math.trunc(scale(getState(id + ".ACTUAL").val, pageItem.minValue, pageItem.maxValue, 100, 0)); } else { brightness = getState(id + ".ACTUAL").val; } } else { console.warn("Datenpunkt: " + id + ".DIMMER kann nicht gelesen werden"); } //iconColor = GetIconColor(pageItem, brightness, false); //Farbe muss noch korrekt ermittelt werden if (val === true) { iconColor = GetIconColor(pageItem, true, true); switchVal = "1"; } else { iconColor = GetIconColor(pageItem, false, true); } RegisterDetailEntityWatcher(id + ".ACTUAL", pageItem, type); let colorTemp = "disable" let colorMode = "disable" //let attr_support_color = attr.supported_color_modes //if (attr_support_color.includes("color_temp")) // colortemp = Math.trunc(scale(attr.color_temp, attr.min_mireds, attr.max_mireds, 0, 100)) out_msgs.push({ payload: "entityUpdateDetail~" + icon + "~" + iconColor + "~" + switchVal + "~" + brightness + "~" + colorTemp + "~" + colorMode }) } if (o.common.role == "hue") { if (existsState(id + ".ON_ACTUAL")) { val = getState(id + ".ON_ACTUAL").val; RegisterDetailEntityWatcher(id + ".ON_ACTUAL", pageItem, type); } //Farbe muss noch korrekt ermittelt werden if (val === true) { iconColor = GetIconColor(pageItem, true, true); switchVal = "1"; } else { iconColor = GetIconColor(pageItem, false, true); } let brightness = 0; if (existsState(id + ".DIMMER")) { brightness = Math.trunc(scale2(getState(id + ".DIMMER").val, 0, 100, 0, 100)); RegisterDetailEntityWatcher(id + ".DIMMER", pageItem, type); } else { console.warn("Datenpunkt: " + id + ".DIMMER kann nicht gelesen werden"); } var colorMode = "disable"; if (existsState(id + ".HUE")) { if (getState(id + ".HUE").val != null) colorMode = "enable"; } var colorTemp = 0; if (existsState(id + ".TEMPERATURE")) { if (getState(id + ".TEMPERATURE").val != null) { if (pageItem.minValue !== undefined && pageItem.minValue !== undefined) { colorTemp = Math.trunc(scale(getState(id + ".TEMPERATURE").val, pageItem.minValue, pageItem.maxValue, 0, 100)); } else { colorTemp = 100 - getState(id + ".TEMPERATURE").val; } RegisterDetailEntityWatcher(id + ".TEMPERATURE", pageItem, type); } } //let attr_support_color = attr.supported_color_modes //if (attr_support_color.includes("color_temp")) //let colortemp = Math.trunc(scale(attr.color_temp, attr.min_mireds, attr.max_mireds, 0, 100)) out_msgs.push({ payload: "entityUpdateDetail~" + icon + "~" + iconColor + "~" + switchVal + "~" + brightness + "~" + colorTemp + "~" + colorMode }) } } if (type == "popupShutter") { if (existsState(id + ".ACTUAL")) { val = getState(id + ".ACTUAL").val; RegisterDetailEntityWatcher(id + ".ACTUAL", pageItem, type); console.log(val); } else if (existsState(id + ".SET")) { val = getState(id + ".SET").val; RegisterDetailEntityWatcher(id + ".SET", pageItem, type); console.log(val); } out_msgs.push({ payload: "entityUpdateDetail~" + val }) } } return out_msgs } function scale(number: number, inMin: number, inMax: number, outMin: number, outMax: number): number { return (outMax+outMin)-((number - inMin) * (outMax - outMin) / (inMax - inMin) + outMin); } function scale2(number: number, inMin: number, inMax: number, outMin: number, outMax: number): number { return (number - inMin) * (outMax - outMin) / (inMax - inMin) + outMin; } function UnsubscribeWatcher(): void { for (const [key, value] of Object.entries(subscriptions)) { unsubscribe(value); delete subscriptions[key] } } function HandleScreensaver(): void { SendToPanel({ payload: "pageType~screensaver"}) UnsubscribeWatcher(); HandleScreensaverUpdate(); } function HandleScreensaverUpdate(): void { if (screensaverEnabled && config.weatherEntity != null && existsObject(config.weatherEntity)) { var icon = getState(config.weatherEntity + ".ICON").val; let temperature: string = existsState(config.weatherEntity + ".ACTUAL") ? getState(config.weatherEntity + ".ACTUAL").val : existsState(config.weatherEntity + ".TEMP") ? getState(config.weatherEntity + ".TEMP").val : "null"; let payloadString = "weatherUpdate~" + Icons.GetIcon(GetAccuWeatherIcon(parseInt(icon))) + "~" + temperature + " " + config.temperatureUnit + "~" /*-------------------------------------------------------------------------------------------------------------------------------------*/ if (weatherForecast == true) { // Accu-Weather Forecast Tag 2 - Tag 5 -- Wenn weatherForecast = true for (let i = 2; i < 6; i++) { let TempMax = getState("accuweather.0.Summary.TempMax_d" + i).val; let DayOfWeek = getState("accuweather.0.Summary.DayOfWeek_d" + i).val; let WeatherIcon = GetAccuWeatherIcon(getState("accuweather.0.Summary.WeatherIcon_d" + i).val); payloadString += DayOfWeek + "~" + Icons.GetIcon(WeatherIcon) + "~" + TempMax + " °C~"; } } else { //In Config definierte Zustände wenn weatherForecast = false payloadString += GetScreenSaverEntityString(config.firstScreensaverEntity); payloadString += GetScreenSaverEntityString(config.secondScreensaverEntity); payloadString += GetScreenSaverEntityString(config.thirdScreensaverEntity); payloadString += GetScreenSaverEntityString(config.fourthScreensaverEntity); } /*-------------------------------------------------------------------------------------------------------------------------------------*/ SendToPanel(<Payload>{ payload: payloadString }); } } function GetScreenSaverEntityString(configElement: ScreenSaverElement | null): string { if (configElement != null && configElement.ScreensaverEntity != null && existsState(configElement.ScreensaverEntity)) { let u1 = getState(configElement.ScreensaverEntity).val; return configElement.ScreensaverEntityText + "~" + Icons.GetIcon(configElement.ScreensaverEntityIcon) + "~" + u1 + " " + configElement.ScreensaverEntityUnitText + "~"; } else { return "~~~"; } } function GetAccuWeatherIcon(icon: number): string { switch (icon) { case 24: // Ice case 30: // Hot case 31: // Cold return "window-open"; // exceptional case 7: // Cloudy case 8: // Dreary (Overcast) case 38: // Mostly Cloudy return "weather-cloudy"; // cloudy case 11: // fog return "weather-fog"; // fog case 25: // Sleet return "weather-hail"; // Hail case 15: // T-Storms return "weather-lightning"; // lightning case 16: // Mostly Cloudy w/ T-Storms case 17: // Partly Sunny w/ T-Storms case 41: // Partly Cloudy w/ T-Storms case 42: // Mostly Cloudy w/ T-Storms return "weather-lightning-rainy"; // lightning-rainy case 33: // Clear case 34: // Mostly Clear case 37: // Hazy Moonlight return "weather-night"; case 3: // Partly Sunny case 4: // Intermittent Clouds case 6: // Mostly Cloudy case 35: // Partly Cloudy case 36: // Intermittent Clouds return "weather-partly-cloudy"; // partlycloudy case 18: // pouring return "weather-pouring"; // pouring case 12: // Showers case 13: // Mostly Cloudy w/ Showers case 14: // Partly Sunny w/ Showers case 26: // Freezing Rain case 39: // Partly Cloudy w/ Showers case 40: // Mostly Cloudy w/ Showers return "weather-rainy"; // rainy case 19: // Flurries case 20: // Mostly Cloudy w/ Flurries case 21: // Partly Sunny w/ Flurries case 22: // Snow case 23: // Mostly Cloudy w/ Snow case 43: // Mostly Cloudy w/ Flurries case 44: // Mostly Cloudy w/ Snow return "weather-snowy"; // snowy case 29: // Rain and Snow return "weather-snowy-rainy"; // snowy-rainy case 1: // Sunny case 2: // Mostly Sunny case 5: // Hazy Sunshine return "weather-sunny"; // sunny case 32: // windy return "weather-windy"; // windy default: return "alert-circle-outline"; } } function sleep(milliseconds) { const date = Date.now(); let currentDate = null; do { currentDate = Date.now(); } while (currentDate - date < milliseconds); } function GetBlendedColor(percentage: number): RGB { if (percentage < 50) return Interpolate(config.defaultOffColor, config.defaultOnColor, percentage / 50.0); return Interpolate(Red, White, (percentage - 50) / 50.0); } function Interpolate(color1: RGB, color2: RGB, fraction: number): RGB { var r: number = InterpolateNum(color1.red, color2.red, fraction); var g: number = InterpolateNum(color1.green, color2.green, fraction); var b: number = InterpolateNum(color1.blue, color2.blue, fraction); return <RGB>{ red: Math.round(r), green: Math.round(g), blue: Math.round(b) }; } function InterpolateNum(d1: number, d2: number, fraction: number): number { return d1 + (d2 - d1) * fraction; } function rgb_dec565(rgb: RGB): number { return ((Math.floor(rgb.red / 255 * 31) << 11) | (Math.floor(rgb.green / 255 * 63) << 5) | (Math.floor(rgb.blue / 255 * 31))); } /* Convert radians to degrees rad - radians to convert, expects rad in range +/- PI per Math.atan2 returns {number} degrees equivalent of rad */ function rad2deg(rad) { return (360 + 180 * rad / Math.PI) % 360; } /* Convert h,s,v values to r,g,b hue - in range [0, 360] saturation - in range 0 to 1 value - in range 0 to 1 returns {Array|number} [r, g,b] in range 0 to 255 */ function hsv2rgb(hue: number, saturation: number, value: number) { hue /= 60; let chroma = value * saturation; let x = chroma * (1 - Math.abs((hue % 2) - 1)); let rgb = hue <= 1? [chroma, x, 0]: hue <= 2? [x, chroma, 0]: hue <= 3? [0, chroma, x]: hue <= 4? [0, x, chroma]: hue <= 5? [x, 0, chroma]: [chroma, 0, x]; return rgb.map(v => (v + value - chroma) * 255); } function getHue(red: number, green: number, blue:number) { var min = Math.min(Math.min(red, green), blue); var max = Math.max(Math.max(red, green), blue); if (min == max) { return 0; } var hue = 0; if (max == red) { hue = (green - blue) / (max - min); } else if (max == green) { hue = 2 + (blue - red) / (max - min); } else { hue = 4 + (red - green) / (max - min); } hue = hue * 60; if (hue < 0) hue = hue + 360; return Math.round(hue); } function pos_to_color(x: number, y: number): RGB { var r = 160/2; var x = Math.round((x - r) / r * 100) / 100; var y = Math.round((r - y) / r * 100) / 100; r = Math.sqrt(x*x + y*y); let sat = 0 if (r > 1) { sat = 0; } else { sat = r; } var hsv = rad2deg(Math.atan2(y, x)); var rgb = hsv2rgb(hsv,sat,1); return <RGB>{ red: Math.round(rgb[0]), green: Math.round(rgb[1]), blue: Math.round(rgb[2]) }; } type RGB = { red: number, green: number, blue: number }; type Payload = { payload: string; }; type Page = { type: string, heading: string, items: PageItem[], useColor: boolean }; interface PageEntities extends Page { type: "cardEntities", items: PageItem[], }; interface PageGrid extends Page { type: "cardGrid", items: PageItem[], }; interface PageThermo extends Page { type: "cardThermo", items: PageItem[], }; interface PageMedia extends Page { type: "cardMedia", items: PageItem[], }; interface PageAlarm extends Page { type: "cardAlarm", items: PageItem[], }; type PageItem = { id: string, icon: (string | undefined), onColor: (RGB | undefined), offColor: (RGB | undefined), useColor: (boolean | undefined), interpolateColor: (boolean | undefined), minValue: (number | undefined), maxValue: (number | undefined), name: (string | undefined), unit: (string | undefined) } type Config = { panelRecvTopic: string, panelSendTopic: string, timeoutScreensaver: number, dimmode: number, //brightnessScreensaver: locale: string, timeFormat: string, dateFormat: string, weatherEntity: string | null, screenSaverDoubleClick: boolean, temperatureUnit: string, firstScreensaverEntity: ScreenSaverElement | null, secondScreensaverEntity: ScreenSaverElement | null, thirdScreensaverEntity: ScreenSaverElement | null, fourthScreensaverEntity: ScreenSaverElement | null, defaultColor: RGB, defaultOnColor: RGB, defaultOffColor: RGB, pages: (PageThermo | PageMedia | PageAlarm | PageEntities | PageGrid)[], button1Page: (PageThermo | PageMedia | PageAlarm | PageEntities | PageGrid | null), button2Page: (PageThermo | PageMedia | PageAlarm | PageEntities | PageGrid | null), }; type ScreenSaverElement = { ScreensaverEntity: string | null, ScreensaverEntityIcon: string | null, ScreensaverEntityText: string | null, ScreensaverEntityUnitText: string | null, }
Der Slider liefert seit je her jeden Wert zwischen 0 und 100. Ich versuche die Zwischenwerte zu eliminieren, damit nicht im Worst-Case 100 x der Datenpunkt verändert werden muss. Dann hört das Slider-hüpfen auch bald auf.
-
@armilar Evtl. habe ich mich nicht richtig ausgedrückt...
Dass das alles aus iobroker heraus aktiviert wird ist das eine, naja, ok, da muss ich dann mit leben...
Das nächste ist dann aber die Kommunikation. Ich möchte das gerne aufgrund der speziellen Anforderungen, die ich habe, alles selbst im Griff haben, weswegen ich keine "Middleware" zur Kommunikation mit dem Panel oder lovelace im ioBroker einsetzen möchte.
Ich würde gerne alle Daten weiterhin nur mit MQTT bekommen und dann auch direkt die Widgets aus meinem JavaScript aktualisieren können.
Eine Übersetzung des TypeScript auf JavaScript, damit ich die Widgets erstelle, sollte erstmal kein Problem sein.Die Anleitungen scheinen mir aber alle recht speziell auf eine komplette Integration abzuzielen und sind scheinbar nicht dafür gedacht, dass jemand wie ich versteht, wie er selbst kommunizieren kann.
Conclusion wäre, wenn das so ist: Damit ich eine alternative Firmware einsetzen kann, muss ich mich durch deren oder den code der bestehenden Integrationen wälzen. Da mir das ohne Beistand wirklich zuviel ist, müsste ich dann doch bei der Orig bleiben.
Da ich es aber bevorzugen würde, das nicht zu tun, hatte ich mir erhofft, es gibt auch andere Doku.Deswegen hab ich gedacht, dass ich zu doof bin die richtige Doku zu finden.
-
@armilar
Also das läuft für mich schon "fast" perfekt
Das einzige Problem was ich jetzt noch habe ist das ich ja den Dimmerslider vom Hue Gerät begrenzen muss.
Und da dort ja schon minValue und maxValue für die Farbtemperatur vergeben sind wird das so ja nicht gehen.
Ich habe mal ein bisschen in Deinem Code rumgepfuscht ( sorry, ich hab da echt keine Ahnung von ) und versucht noch nen anderen Übergabewert hinein zu bekommen.
Der nennt sich dann
minValueBRI
und
maxValueBRI.
Sollte dann für den Brightnessslider im Hue Gerät sein und dort den Dimmwert begrenzen.
So wie ich das verpfuscht habe läuft das Script auch nicht.
Wenn Du mal herzlich lachen möchtest dann kannst Du Dir das ja mal anschauen.var Icons = new IconsSelector(); const Months = ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"]; const Days = ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"]; const Off: RGB = { red: 68, green: 115, blue: 158 }; const On: RGB = { red: 253, green: 216, blue: 53 }; const MSRed: RGB = { red: 251, green: 105, blue: 98 }; const MSGreen: RGB = { red: 121, green: 222, blue: 121 }; const Red: RGB = { red: 255, green: 0, blue: 0 }; const White: RGB = { red: 255, green: 255, blue: 255 }; const Yellow: RGB = { red: 255, green: 255, blue: 0 }; const Green: RGB = { red: 0, green: 255, blue: 0 }; const Blue: RGB = { red: 0, green: 0, blue: 255 }; const Gray: RGB = { red: 136, green: 136, blue: 136 }; const Black: RGB = { red: 0, green: 0, blue: 0 }; const colorSpotify: RGB = { red: 30, green: 215, blue: 96 }; const colorAlexa: RGB = { red: 49, green: 196, blue: 243 }; const colorRadio: RGB = { red: 255, green: 127, blue: 0 }; const BatteryFull: RGB = { red: 96, green: 176, blue: 62 }; const BatteryEmpty: RGB = { red: 179, green: 45, blue: 25 }; //----Möglichkeit, im Screensaver zwischen Accu-Weather Forecast oder selbstdefinierten Werten zu wählen--------------------------------- var weatherForecast = false; //true = WheatherForecast 5 Days --- false = Config --> firstScreensaverEntity - fourthScreensaverEntity ... //Alexa-Instanz var alexaInstanz = "alexa2.0" var alexaDevice = "G0XXXXXXXXXXXXXX"; //Primär zu steuendes Device // Wenn alexaSpeakerList definiert, dann werden Einträge verwendet, sonst alle relevanten Devices aus Alexa-Instanz // Speakerwechsel funktioniert nicht bei Radio/TuneIn sonden bei Playlists const alexaSpeakerList = []; //Beispiel ["Echo Spot Buero","Überall","Gartenhaus","Esszimmer","Heimkino"]; //const alexaSpeakerList = ["Echo Spot Buero","Überall","Gartenhaus","Esszimmer","Heimkino","Echo Dot Küche"]; //Datenpunkte für Nachricht an Screensaver var popupNotifyHeading = "0_userdata.0.NSPanel.1.popupNotifyHeading"; var popupNotifyText = "0_userdata.0.NSPanel.1.popupNotifyText"; var Test_Licht: PageEntities = { "type": "cardEntities", "heading": "Büro", "useColor": true, "items": [ <PageItem>{ id: "alias.0.NSPanel_1.Schreibtischlampe"}, <PageItem>{ id: "alias.0.NSPanel_1.Testlampe2", name: "Filamentlampe", minValue: 0, maxValue: 70}, <PageItem>{ id: "alias.0.NSPanel_1.TestCTmitHUE", name: "HUE-Light-CT"}, <PageItem>{ id: "alias.0.NSPanel_1.TestHUELicht", name: "HUE-Light-Color", minValue: 500, maxValue: 6500} ] }; var Buero_Seite_1: PageEntities = { "type": "cardEntities", "heading": "Büro", "useColor": true, "items": [ <PageItem>{ id: "alias.0.CTmitHUE", name: "Computer Decke", minValue: 500, maxValue: 6500, minValueBRI: 1, maxValueBRI: 70}, //HUE o.a. über --> Alias HUE mit CT ohne Color <PageItem>{ id: "alias.0.COMPUTER_LED", name: "Computer Tisch", minValue: 0, maxValue: 70}, //Dimmer <PageItem>{ id: "alias.0.NSPanel_1.Testlampe2"}, <PageItem>{ id: "alias.0.NSPanel_1.Luftreiniger", icon: "power", offColor: MSRed, onColor: MSGreen} ] }; var Fenster_1: PageEntities = { "type": "cardEntities", "heading": "Fenster und Türen", "useColor": true, "items": [ <PageItem>{ id: "alias.0.NSPanel_1.TestFenster", offColor: MSRed, onColor: MSGreen, name: "Büro Fenster"}, <PageItem>{ id: "alias.0.NSPanel_1.Haustuer", offColor: MSRed, onColor: MSGreen, name: "Haustür"}, <PageItem>{ id: "alias.0.NSPanel_1.TestBlind", onColor: White, name: "IKEA Fyrtur"} ] }; var Abfall: PageEntities = { "type": "cardEntities", "heading": "Abfallkalender", "useColor": true, "items": [ <PageItem>{ id: "alias.0.NSPanel_1.Abfall.event1",icon: "trash-can"}, <PageItem>{ id: "alias.0.NSPanel_1.Abfall.event2",icon: "trash-can"}, <PageItem>{ id: "alias.0.NSPanel_1.Abfall.event3",icon: "trash-can"}, <PageItem>{ id: "alias.0.NSPanel_1.Abfall.event4",icon: "trash-can"} ] }; var Buero_Seite_2: PageGrid = { "type": "cardGrid", "heading": "Büro 2", "useColor": true, "items": [ <PageItem>{ id: "alias.0.NSPanel_1.Schreibtischlampe", name: "Schreibtisch"}, <PageItem>{ id: "alias.0.NSPanel_1.Deckenbeleuchtung", name: "Deckenlampe"}, <PageItem>{ id: "alias.0.NSPanel_1.TestFenster", offColor: MSRed, onColor: MSGreen, name: "Büro Fenster"}, <PageItem>{ id: "alias.0.NSPanel_1.Luftreiniger", icon: "power", offColor: MSRed, onColor: MSGreen}, <PageItem>{ id: "alias.0.NSPanel_1.TestBlind", icon: "projector-screen", onColor: White, name: "Beamer"}, <PageItem>{ id: "alias.0.NSPanel_1.Radio.TuneIn", icon: "play", onColor: White} ] }; var Alexa: PageMedia = { "type": "cardMedia", "heading": "Alexa", "useColor": true, "items": [<PageItem>{ id: "alias.0.NSPanel_1.Alexa.PlayerBuero" }] }; var Buero_Themostat: PageThermo = { "type": "cardThermo", "heading": "Thermostat", "useColor": true, "items": [<PageItem>{ id: "alias.0.NSPanel_1.Thermostat_Büro" }] }; var Buero_Alarm: PageAlarm = { "type": "cardAlarm", "heading": "Alarm", "useColor": true, "items": [<PageItem>{ id: "alias.0.NSPanel_1.Alarm" }] }; var button1Page: PageGrid = { "type": "cardGrid", "heading": "Radio", "useColor": true, "items": [ <PageItem>{ id: "alias.0.NSPanel_1.Radio.FFN", icon: "radio", name: "FFN", onColor: colorRadio}, <PageItem>{ id: "alias.0.NSPanel_1.Radio.Antenne" , icon: "radio", name: "Antenne Nds.", onColor: colorRadio}, <PageItem>{ id: "alias.0.NSPanel_1.Radio.NDR2", icon: "radio", name: "NDR2", onColor: colorRadio}, <PageItem>{ id: "alias.0.NSPanel_1.Radio.Bob", icon: "radio", name: "Radio BOB", onColor: colorRadio}, <PageItem>{ id: "alias.0.NSPanel_1.Radio.Spotify", icon: "spotify", name: "Party Playlist", onColor: colorSpotify}, <PageItem>{ id: "alias.0.NSPanel_1.Radio.Alexa", icon: "playlist-music", name: "Playlist 2021", onColor: colorAlexa} ] }; var button2Page: PageEntities = { "type": "cardEntities", "heading": "Büro", "useColor": true, "items": [ <PageItem>{ id: "alias.0.NSPanel_1.Schreibtischlampe"}, <PageItem>{ id: "alias.0.NSPanel_1.Deckenbeleuchtung"} ] }; export const config: Config = { panelRecvTopic: "mqtt.0.tele.WzDisplay.RESULT", //anpassen panelSendTopic: "mqtt.0.cmnd.WzDisplay.CustomSend", //anpassen firstScreensaverEntity: { ScreensaverEntity: "hm-rpc.0.000EDA4995B568.1.HUMIDITY", ScreensaverEntityIcon: "water-percent", ScreensaverEntityText: "Luft", ScreensaverEntityUnitText: "%" }, secondScreensaverEntity: { ScreensaverEntity: "alias.0.Wetter.PRECIPITATION_CHANCE", ScreensaverEntityIcon: "weather-pouring", ScreensaverEntityText: "Regen", ScreensaverEntityUnitText: "%" }, thirdScreensaverEntity: { ScreensaverEntity: "alias.0.Wetter.Wind_SPEED", ScreensaverEntityIcon: "weather-windy", ScreensaverEntityText: "Wind", ScreensaverEntityUnitText: "bft" }, fourthScreensaverEntity: { ScreensaverEntity: "accuweather.0.Current.UVIndex", ScreensaverEntityIcon: "solar-power", ScreensaverEntityText: "UV", ScreensaverEntityUnitText: "" }, timeoutScreensaver: 5, dimmode: 8, screenSaverDoubleClick: false, locale: "de_DE", timeFormat: "%H:%M", dateFormat: "%A, %d. %B %Y", weatherEntity: "alias.0.Wetter", defaultOffColor: Off, defaultOnColor: On, defaultColor: Off, temperatureUnit: "°C", pages: [ Buero_Seite_1, //Test_Licht, Fenster_1, Abfall, //Buero_Seite_2, Alexa, Buero_Themostat, Buero_Alarm ], button1Page: button1Page, button2Page: button2Page }; // _________________________________ Ab hier keine Konfiguration mehr _____________________________________ //Notification an Screensaver on({id: [popupNotifyHeading, popupNotifyText], change: "ne"}, async function (obj) { setState(config.panelSendTopic,(['notify~',getState(popupNotifyHeading).val,'~',getState(popupNotifyText).val].join(''))); }); var subscriptions: any = {}; var screensaverEnabled : boolean = false; var pageId = 0; schedule("* * * * *", function () { SendTime(); }); schedule("0 * * * *", function () { SendDate(); }); // Only monitor the extra nodes if present var updateArray: string[] = []; if (config.firstScreensaverEntity !== null && config.firstScreensaverEntity.ScreensaverEntity != null && existsState(config.firstScreensaverEntity.ScreensaverEntity)) { updateArray.push(config.firstScreensaverEntity.ScreensaverEntity) } if (config.secondScreensaverEntity !== null && config.secondScreensaverEntity.ScreensaverEntity != null && existsState(config.secondScreensaverEntity.ScreensaverEntity)) { updateArray.push(config.secondScreensaverEntity.ScreensaverEntity) } if (config.thirdScreensaverEntity !== null && config.thirdScreensaverEntity.ScreensaverEntity != null && existsState(config.thirdScreensaverEntity.ScreensaverEntity)) { updateArray.push(config.thirdScreensaverEntity.ScreensaverEntity) } if (config.fourthScreensaverEntity !== null && config.fourthScreensaverEntity.ScreensaverEntity != null && existsState(config.fourthScreensaverEntity.ScreensaverEntity)) { updateArray.push(config.fourthScreensaverEntity.ScreensaverEntity) } if (updateArray.length > 0) { on(updateArray, function () { HandleScreensaverUpdate(); }) } on({ id: config.panelRecvTopic }, function (obj) { if (obj.state.val.startsWith('\{"CustomRecv":')) { var json = JSON.parse(obj.state.val); var split = json.CustomRecv.split(","); HandleMessage(split[0], split[1], parseInt(split[2]), split); } }); function SendToPanel(val: Payload | Payload[]): void { if (Array.isArray(val)) { val.forEach(function (id, i) { setState(config.panelSendTopic, id.payload); }); } else setState(config.panelSendTopic, val.payload); } function HandleMessage(typ: string, method: string, page: number, words: Array<string>): void { if (typ == "event") { switch (method) { case "startup": screensaverEnabled = false; UnsubscribeWatcher(); HandleStartupProcess(); pageId = 0; GeneratePage(config.pages[0]); break; case "sleepReached": screensaverEnabled = true; if (pageId < 0) pageId = 0; HandleScreensaver(); break; case "pageOpenDetail": screensaverEnabled = false; UnsubscribeWatcher(); let pageItem = config.pages[pageId].items.find(e => e.id === words[3]); if (pageItem !== undefined) SendToPanel(GenerateDetailPage(words[2], pageItem)); case "buttonPress2": screensaverEnabled = false; HandleButtonEvent(words); break; case "button1": case "button2": screensaverEnabled = false; HandleHardwareButton(method); default: break; } } } function GeneratePage(page: Page): void { switch (page.type) { case "cardEntities": SendToPanel(GenerateEntitiesPage(<PageEntities>page)); break; case "cardThermo": SendToPanel(GenerateThermoPage(<PageThermo>page)); break; case "cardGrid": SendToPanel(GenerateGridPage(<PageGrid>page)); break; case "cardMedia": SendToPanel(GenerateMediaPage(<PageMedia>page)); break; case "cardAlarm": SendToPanel(GenerateAlarmPage(<PageAlarm>page)); break; } } function HandleHardwareButton(method: string): void { let page: (PageThermo | PageMedia | PageAlarm | PageEntities | PageGrid); if (config.button1Page !== null && method == "button1") { page = config.button1Page; pageId = -1; } else if (config.button2Page !== null && method == "button2") { page = config.button2Page; pageId = -2; } else { return; } GeneratePage(page); } function HandleStartupProcess(): void { SendDate(); SendTime(); SendToPanel({ payload: "timeout~" + config.timeoutScreensaver }); SendToPanel({ payload: "dimmode~" + config.dimmode }); } function SendDate(): void { var d = new Date(); var day = Days[d.getDay()]; var date = d.getDate(); var month = Months[d.getMonth()]; var year = d.getFullYear(); var _sendDate = "date~" + day + " " + date + " " + month + " " + year; SendToPanel(<Payload>{ payload: _sendDate }); } function SendTime(): void { var d = new Date(); var hr = d.getHours().toString(); var min = d.getMinutes().toString(); if (d.getHours() < 10) { hr = "0" + d.getHours().toString(); } if (d.getMinutes() < 10) { min = "0" + d.getMinutes().toString(); } SendToPanel(<Payload>{ payload: "time~" + hr + ":" + min }); } function GenerateEntitiesPage(page: PageEntities): Payload[] { var out_msgs: Array<Payload> = []; out_msgs = [{ payload: "pageType~cardEntities" }] out_msgs.push({ payload: GeneratePageElements(page) }); return out_msgs } function GenerateGridPage(page: PageGrid): Payload[] { var out_msgs: Array<Payload> = []; out_msgs = [{ payload: "pageType~cardGrid" }] out_msgs.push({ payload: GeneratePageElements(page) }); return out_msgs } function GeneratePageElements(page: Page): string { let maxItems = 0; switch (page.type) { case "cardThermo": maxItems = 1; break; case "cardAlarm": maxItems = 1; break; case "cardMedia": maxItems = 1; break; case "cardEntities": maxItems = 4; break; case "cardGrid": maxItems = 6; break; } let pageData = "entityUpd~" + page.heading + "~" + GetNavigationString(pageId) for (let index = 0; index < maxItems; index++) { if (page.items[index] !== undefined) { pageData += CreateEntity(page.items[index], index + 1, page.useColor); } else { pageData += CreateEntity(<PageItem>{ id: "delete" }, index + 1); } } return pageData; } function CreateEntity(pageItem: PageItem, placeId: number, useColors: boolean = false): string { var iconId = "0" if (pageItem.id == "delete") { return "~delete~~~~~" } var name: string; var type: string; // ioBroker if (existsObject(pageItem.id)) { let o = getObject(pageItem.id) var val = null; name = pageItem.name !== undefined ? pageItem.name : o.common.name.de if (existsState(pageItem.id + ".GET")) { val = getState(pageItem.id + ".GET").val; RegisterEntityWatcher(pageItem.id + ".GET"); } else if (existsState(pageItem.id + ".SET")) { val = getState(pageItem.id + ".SET").val; RegisterEntityWatcher(pageItem.id + ".SET"); } var iconColor = rgb_dec565(config.defaultColor); switch (o.common.role) { case "socket": case "light": type = "light" iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : o.common.role == "socket" ? Icons.GetIcon("power-socket-de") : Icons.GetIcon("lightbulb"); var optVal = "0" if (val === true || val === "true") { optVal = "1" iconColor = GetIconColor(pageItem, true, useColors); } else { iconColor = GetIconColor(pageItem, false, useColors); } return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + optVal; case "hue": type = "light" iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("lightbulb"); var optVal = "0" if (existsState(pageItem.id + ".ON_ACTUAL")) { val = getState(pageItem.id + ".ON_ACTUAL").val; RegisterEntityWatcher(pageItem.id + ".ON_ACTUAL"); } if (val === true || val === "true") { optVal = "1" iconColor = GetIconColor(pageItem, existsState(pageItem.id + ".ON") ? getState(pageItem.id + ".ON").val : true, useColors); } return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + optVal; case "dimmer": type = "light" iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("lightbulb"); var optVal = "0" if (existsState(pageItem.id + ".ON_ACTUAL")) { val = getState(pageItem.id + ".ON_ACTUAL").val; RegisterEntityWatcher(pageItem.id + ".ON_ACTUAL"); } else if (existsState(pageItem.id + ".ON_SET")) { val = getState(pageItem.id + ".ON_SET").val; RegisterEntityWatcher(pageItem.id + ".ON_SET"); } if (val === true || val === "true") { optVal = "1" iconColor = GetIconColor(pageItem, existsState(pageItem.id + ".ACTUAL") ? getState(pageItem.id + ".ACTUAL").val : true, useColors); } return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + optVal; case "blind": type = "shutter" iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("window-open"); iconColor = GetIconColor(pageItem, existsState(pageItem.id + ".ACTUAL") ? getState(pageItem.id + ".ACTUAL").val : true, useColors); return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" case "door": case "window": type = "text"; if (existsState(pageItem.id + ".ACTUAL")) { if (getState(pageItem.id + ".ACTUAL").val) { iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : o.common.role == "door" ? Icons.GetIcon("door-open") : Icons.GetIcon("window-open-variant"); iconColor = GetIconColor(pageItem, false, useColors); var windowState = "opened" } else { iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : o.common.role == "door" ? Icons.GetIcon("door-closed") : Icons.GetIcon("window-closed-variant"); //iconId = Icons.GetIcon("window-closed-variant"); iconColor = GetIconColor(pageItem, true, useColors); var windowState = "closed" } RegisterEntityWatcher(pageItem.id + ".ACTUAL"); } return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + windowState; case "info": case "humidity": case "value.temperature": case "value.humidity": case "sensor.door": case "sensor.window": case "thermostat": type = "text"; iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : o.common.role == "value.temperature" || o.common.role == "thermostat" ? Icons.GetIcon("thermometer") : Icons.GetIcon("information-outline"); let unit = ""; var optVal = "0" if (existsState(pageItem.id + ".ON_ACTUAL")) { optVal = getState(pageItem.id + ".ON_ACTUAL").val; unit = pageItem.unit !== undefined ? pageItem.unit : GetUnitOfMeasurement(pageItem.id + ".ON_ACTUAL"); RegisterEntityWatcher(pageItem.id + ".ON_ACTUAL"); } else if (existsState(pageItem.id + ".ACTUAL")) { optVal = getState(pageItem.id + ".ACTUAL").val; unit = pageItem.unit !== undefined ? pageItem.unit : GetUnitOfMeasurement(pageItem.id + ".ACTUAL"); RegisterEntityWatcher(pageItem.id + ".ACTUAL"); } if (o.common.role == "value.temperature") { iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("thermometer"); } iconColor = GetIconColor(pageItem, parseInt(optVal), useColors); return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + optVal + " " + unit; case "button": type = "button"; iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("gesture-tap-button"); let buttonText = pageItem.name !== undefined ? pageItem.name : "PRESS"; iconColor = GetIconColor(pageItem, true, useColors); return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + buttonText; case "warning": type = "text"; iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("alert-outline"); iconColor = getState(([pageItem.id,'.LEVEL'].join(''))).val; let itemName = getState(([pageItem.id,'.TITLE'].join(''))).val; let itemInfo = getState(([pageItem.id,'.INFO'].join(''))).val; return "~" + type + "~" + itemName + "~" + iconId + "~" + iconColor + "~" + itemName + "~" + itemInfo; default: return "~delete~~~~~"; } } return "~delete~~~~~" } function GetIconColor(pageItem: PageItem, value: (boolean | number), useColors: boolean): number { // dimmer if ((pageItem.useColor || useColors) && pageItem.interpolateColor && typeof (value) === "number") { let maxValue = pageItem.maxValue !== undefined ? pageItem.maxValue : 100; let minValue = pageItem.minValue !== undefined ? pageItem.minValue : 0; let maxValueBRI = pageItem.maxValueBRI !== undefined ? pageItem.maxValueBRI : 100; let minValueBRI = pageItem.minValueBRI !== undefined ? pageItem.minValueBRI : 0; value = value > maxValue ? maxValue : value; value = value < minValue ? minValue : value; value = value > maxValueBRI ? maxValueBRI : value; value = value < minValueBRI ? minValueBRI : value; return rgb_dec565( Interpolate( pageItem.offColor !== undefined ? pageItem.offColor : config.defaultOffColor, pageItem.onColor !== undefined ? pageItem.onColor : config.defaultOnColor, scale(value, minValue, maxValue, 0, 1), scale(value, minValueBRI, maxValueBRI, 0, 1) )); } if ((pageItem.useColor || useColors) && ((typeof (value) === "boolean" && value) || value > (pageItem.minValue !== undefined ? pageItem.minValue : 0))) { return rgb_dec565(pageItem.onColor !== undefined ? pageItem.onColor : config.defaultOnColor) } return rgb_dec565(pageItem.offColor !== undefined ? pageItem.offColor : config.defaultOffColor); } function RegisterEntityWatcher(id: string): void { if (subscriptions.hasOwnProperty(id)) { return; } subscriptions[id] = (on({ id: id, change: 'any' }, function (data) { if(pageId >= 0) SendToPanel({ payload: GeneratePageElements(config.pages[pageId]) }); if(pageId == -1 && config.button1Page != undefined) SendToPanel({ payload: GeneratePageElements(config.button1Page) }); if(pageId == -2 && config.button2Page != undefined) SendToPanel({ payload: GeneratePageElements(config.button2Page) }); })) } function RegisterDetailEntityWatcher(id: string, pageItem: PageItem, type: string): void { if (subscriptions.hasOwnProperty(id)) { return; } subscriptions[id] = (on({ id: id, change: 'any' }, function () { SendToPanel(GenerateDetailPage(type, pageItem)); })) } function GetUnitOfMeasurement(id: string): string { if (!existsObject(id)) return ""; let obj = getObject(id); if (typeof obj.common.unit !== 'undefined') { return obj.common.unit } if (typeof obj.common.alias !== 'undefined' && typeof obj.common.alias.id !== 'undefined') { return GetUnitOfMeasurement(obj.common.alias.id); } return ""; } function GenerateThermoPage(page: PageThermo): Payload[] { var id = page.items[0].id var out_msgs: Array<Payload> = []; out_msgs.push({ payload: "pageType~cardThermo" }); // ioBroker if (existsObject(id)) { let o = getObject(id) let name = page.items[0].name !== undefined ? page.items[0].name : o.common.name.de let currentTemp = 0; if (existsState(id + ".ACTUAL")) currentTemp = (Math.round(parseFloat(getState(id + ".ACTUAL").val) * 10)/10)*10; let destTemp = 0; if (existsState(id + ".SET")) { destTemp = getState(id + ".SET").val.toFixed(2) * 10; } let status = "" if (existsState(id + ".MODE")) status = getState(id + ".MODE").val; let minTemp = 50 //Min Temp 5°C let maxTemp = 300 //Max Temp 30°C let stepTemp = 5 //0-4 verwendet bei ungerader Anzahl Parametern let bt0 = "~~~~"; //verwendet bei ungleichen Parametern let bt1 = "~~~~"; //verwendet bei ungleichen Parametern let bt2 = "~~~~"; //verwendet bei ungleichen Parametern let bt3 = "~~~~"; //verwendet bei ungleichen Parametern let bt4 = "~~~~"; //verwendet bei ungleichen Parametern //5-8 verwendet bei gerader Anzahl Parametern let bt5 = Icons.GetIcon("water-percent") + "~0~1~~"; let bt6 = Icons.GetIcon("fire") + "~0~1~~"; let bt7 = Icons.GetIcon("wifi") + "~0~1~~"; let bt8 = Icons.GetIcon("battery-high") + "~0~1~~"; if (existsState(id + ".HUMIDITY")){ bt5 = Icons.GetIcon("water-percent") + "~2016~1~bt8~"; if (parseInt(getState(id + ".HUMIDITY").val) < 40) { bt5 = Icons.GetIcon("water-percent") + "~65504~1~bt8~"; } else if (parseInt(getState(id + ".HUMIDITY").val) < 30) { bt5 = Icons.GetIcon("water-percent") + "~63488~1~bt8~"; } else if (parseInt(getState(id + ".HUMIDITY").val) > 65) { bt5 = Icons.GetIcon("water-percent") + "~65504~1~bt8~"; } else if (parseInt(getState(id + ".HUMIDITY").val) > 75) { bt5 = Icons.GetIcon("water-percent") + "~63488~1~bt8~"; } } if (existsState(id + ".MAINTAIN")){ if (getState(id + ".MAINTAIN").val >> .1) { bt6 = Icons.GetIcon("fire") + "~60897~1~bt8~"; } else { bt6 = Icons.GetIcon("fire") + "~33840~0~bt8~"; } } if (existsState(id + ".UNREACH")){ if (getState(id + ".UNREACH").val) { bt7 = Icons.GetIcon("wifi-off") + "~63488~1~bt8~"; } else { bt7 = Icons.GetIcon("wifi") + "~2016~1~bt8~"; } } if (existsState(id + ".LOWBAT")){ if (getState(id + ".LOWBAT").val) { bt8 = Icons.GetIcon("battery-low") + "~63488~1~bt8~"; } else { bt8 = Icons.GetIcon("battery-high") + "~2016~1~bt8~"; } } let icon_res = bt0 + bt1 + bt2 + bt3 + bt4 + bt5 + bt6 + bt7 + bt8; out_msgs.push({ payload: "entityUpd~" + name + "~" + GetNavigationString(pageId) + "~" + id + "~" + currentTemp + "~" + destTemp + "~" + status + "~" + minTemp + "~" + maxTemp + "~" + stepTemp + "~" +icon_res}) } return out_msgs } function GenerateMediaPage(page: PageMedia): Payload[] { var id = page.items[0].id var out_msgs: Array<Payload> = []; out_msgs.push({ payload: "pageType~cardMedia" }); if (existsObject(id)) { let name = getState(id + ".ALBUM").val; let media_icon = Icons.GetIcon("playlist-music"); let title = getState(id + ".TITLE").val; let author = getState(id + ".ARTIST").val; let volume = getState(id + ".VOLUME").val; var iconplaypause = Icons.GetIcon("pause"); //pause var onoffbutton = 1374; if (getState(id + ".STATE").val) { onoffbutton = 65535; iconplaypause = Icons.GetIcon("pause"); //pause } else { iconplaypause = Icons.GetIcon("play"); //play } let currentSpeaker = getState(([alexaInstanz,'.Echo-Devices.',alexaDevice,'.Info.name'].join(''))).val; //console.log(id); //------------------------------------------------------------------------------------------------------------- // nachfolgend alle Alexa-Devices (ist Online / Player- und Commands-Verzeichnis vorhanden) auflisten und verketten // Wenn Konstante alexaSpeakerList mind. einen Eintrag enthält, wird die Konstante verwendet - ansonsten Alle Devices aus dem Alexa Adapter let speakerlist = ""; if (alexaSpeakerList.length > 0) { for (let i_index in alexaSpeakerList) { speakerlist = speakerlist + alexaSpeakerList[i_index] + "?"; } } else { let i_list = Array.prototype.slice.apply($('[state.id="' + alexaInstanz + '.Echo-Devices.*.Info.name"]')); for (let i_index in i_list) { let i = i_list[i_index]; let deviceId = i; deviceId = deviceId.split('.'); if (getState(([alexaInstanz,'.Echo-Devices.',deviceId[3],'.online'].join(''))).val && existsObject(([alexaInstanz,'.Echo-Devices.',deviceId[3],'.Player'].join(''))) && existsObject(([alexaInstanz,'.Echo-Devices.',deviceId[3],'.Commands'].join('')))) { speakerlist = speakerlist + getState(i).val + "?"; } } } speakerlist = speakerlist.substring(0,speakerlist.length-1); //-------------------------------------------------------------------------------------------------------------- out_msgs.push({ payload: "entityUpd~" + name + "~" + id + "~" + id + "~" + //???? media_icon + "~" + title + "~" + author + "~" + volume + "~" + iconplaypause + "~" + currentSpeaker + "~" + speakerlist + "~" + onoffbutton}); } return out_msgs } function GenerateAlarmPage(page: PageAlarm): Payload[] { var id = page.items[0].id var out_msgs: Array<Payload> = []; out_msgs.push({ payload: "pageType~cardAlarm" }); var armed: boolean = true; if (armed) { var arm1 = "Deaktivieren"; //arm1*~* var arm1ActionName = "D1"; //arm1ActionName*~* var arm2 = ""; //arm2*~* var arm2ActionName = ""; //arm2ActionName*~* var arm3 = ""; //arm3*~* var arm3ActionName = ""; //arm3ActionName*~* var arm4 = ""; //arm4*~* var arm4ActionName = ""; //arm4ActionName*~* var icon = Icons.GetIcon("shield-home"); //icon*~* var iconcolor = 63488; //iconcolor*~* var numpadStatus = 1; //numpadStatus*~* var flashing = 1; //flashing* } else { var arm1 = "Alarm 1"; //arm1*~* var arm1ActionName = "A1"; //arm1ActionName*~* var arm2 = "Alarm 2"; //arm2*~* var arm2ActionName = "A2"; //arm2ActionName*~* var arm3 = "Alarm 3"; //arm3*~* var arm3ActionName = "A3"; //arm3ActionName*~* var arm4 = "Alarm 4"; //arm4*~* var arm4ActionName = "A4"; //arm4ActionName*~* var icon = Icons.GetIcon("shield-off"); //icon*~* var iconcolor = 2016; //iconcolor*~* var numpadStatus = 1; //numpadStatus*~* var flashing = 1; //flashing* } out_msgs.push({ payload: "entityUpd~" + //entityUpd~* id + "~" + //internalNameEntity*~* //navigation*~* "~" + //??? arm1 + "~" + //arm1*~* arm1ActionName + "~" + //arm1ActionName*~* arm2 + "~" + //arm2*~* arm2ActionName + "~" + //arm2ActionName*~* arm3 + "~" + //arm3*~* arm3ActionName + "~" + //arm3ActionName*~* arm4 + "~" + //arm4*~* arm4ActionName + "~" + //arm4ActionName*~* icon + "~" + //icon*~* 39=Disarmed 35=Shield_Home, 40 iconcolor + "~" + //iconcolor*~* 2016=green 63488=red numpadStatus + "~" + //numpadStatus*~* flashing}); //flashing* return out_msgs } function setIfExists(id: string, value: any, type: string | null = null): boolean { if (type === null) { if (existsState(id)) { setState(id, value); return true; } } else { let obj = getObject(id); if (existsState(id) && obj.common.type !== undefined && obj.common.type === type) { setState(id, value); return true; } } return false; } function toggleState(id: string): boolean { let obj = getObject(id); if (existsState(id) && obj.common.type !== undefined && obj.common.type === "boolean") { setState(id, !getState(id).val); return true; } return false; } function HandleButtonEvent(words): void { let id = words[2] let buttonAction = words[3]; console.log(words[0] + " - " + words[1] + " - " + words[2] + " - " + words[3] + " - " + words[4] + " - PageId: " + pageId); switch (buttonAction) { case "bNext": var pageNum = ((pageId + 1) % config.pages.length); pageId = Math.abs(pageNum); UnsubscribeWatcher(); GeneratePage(config.pages[pageId]); break; case "bPrev": var pageNum = ((pageId - 1) % config.pages.length); pageId = Math.abs(pageNum); UnsubscribeWatcher(); GeneratePage(config.pages[pageId]); break; case "bExit": if (config.screenSaverDoubleClick) { if (words[4] == 2) GeneratePage(config.pages[pageId]); } else GeneratePage(config.pages[pageId]); break; case "OnOff": if (existsObject(id)) { var action = false if (words[4] == "1") action = true let o = getObject(id) switch (o.common.role) { case "light": setIfExists(id + ".SET", action); break; case "dimmer": setIfExists(id + ".ON_SET", action) ? true : setIfExists(id + ".ON_ACTUAL", action); break; case "hue": // Armilar setIfExists(id + ".ON_ACTUAL", action); } } break; case "up": setIfExists(id + ".OPEN", true) break; case "stop": setIfExists(id + ".STOP", true) break; case "down": setIfExists(id + ".CLOSE", true) break; case "button": toggleState(id + ".SET") ? true : toggleState(id + ".ON_SET") break; case "positionSlider": setIfExists(id + ".SET", parseInt(words[4])) ? true : setIfExists(id + ".ACTUAL", parseInt(words[4])); break; case "brightnessSlider": if (existsObject(id)) { let o = getObject(id); let pageItem = config.pages[pageId].items.find(e => e.id === id); switch (o.common.role) { case "dimmer": if (pageItem.minValue != undefined && pageItem.maxValue != undefined) { let sliderPos = Math.trunc(scale(parseInt(words[4]), 0, 100, pageItem.maxValue, pageItem.minValue)) setIfExists(id + ".SET", sliderPos) ? true : setIfExists(id + ".ACTUAL", sliderPos); } else { setIfExists(id + ".SET", parseInt(words[4])) ? true : setIfExists(id + ".ACTUAL", parseInt(words[4])); } break; case "hue": if (pageItem.minValueBRI != undefined && pageItem.maxValueBRI != undefined) { let sliderPos = Math.trunc(scale(parseInt(words[4]), 0, 100, pageItem.maxValueBRI, pageItem.minValueBRI)) setIfExists(id + ".DIMMER", parseInt(words[4])); } } break; case "colorTempSlider": // Armilar - Slider tickt verkehrt - Hell = 0 / Dunkel = 100 -> Korrektur let pageItem = config.pages[pageId].items.find(e => e.id === id); if (pageItem.minValue !== undefined && pageItem.minValue !== undefined) { let colorTempK = Math.trunc(scale(parseInt(words[4]), 0, 100, pageItem.minValue, pageItem.maxValue)); setIfExists(id + ".TEMPERATURE", (colorTempK)); } else { setIfExists(id + ".TEMPERATURE", 100 - words[4]); } break; case "colorWheel": let colorCoordinates = words[4].split('|'); let rgb = pos_to_color(colorCoordinates[0], colorCoordinates[1]); //console.log(rgb); //console.log(getHue(rgb.red, rgb.green, rgb.blue)); setIfExists(id + ".HUE", getHue(rgb.red, rgb.green, rgb.blue)); break; case "tempUpd": setIfExists(id + ".SET", parseInt(words[4]) / 10) break; case "media-back": setIfExists(id + ".PREV", true) break; case "media-pause": if (getState(id + ".STATE").val === true) { setIfExists(id + ".PAUSE", true) } else { setIfExists(id + ".PLAY", true) } break; case "media-next": setIfExists(id + ".NEXT", true) break; case "volumeSlider": setIfExists(id + ".VOLUME", parseInt(words[4])) break; case "speaker-sel": let i_list = Array.prototype.slice.apply($('[state.id="' + alexaInstanz + '.Echo-Devices.*.Info.name"]')); for (let i_index in i_list) { let i = i_list[i_index]; if ((getState(i).val) === words[4]){ let deviceId = i; deviceId = deviceId.split('.'); setIfExists(alexaInstanz + ".Echo-Devices." + alexaDevice + ".Commands.textCommand", "Schiebe meine Musik auf " + words[4]); alexaDevice = deviceId[3] } } break; case "media-OnOff": setIfExists(id + ".STOP", true) break; case "A1": //Alarm-Page Alarm 1 aktivieren console.log("auf mediaAlarm - Alarm 1 - Wert: " + words[4] + " - reagieren - noch nicht implementiert"); break; case "A2": //Alarm-Page Alarm 2 aktivieren console.log("auf mediaAlarm - Alarm 1 - Wert: " + words[4] + " - reagieren - noch nicht implementiert"); break; case "A3": //Alarm-Page Alarm 3 aktivieren console.log("auf mediaAlarm - Alarm 1 - Wert: " + words[4] + " - reagieren - noch nicht implementiert"); break; case "A4": //Alarm-Page Alarm 4 aktivieren console.log("auf mediaAlarm - Alarm 1 - Wert: " + words[4] + " - reagieren - noch nicht implementiert"); break; case "D1": //Alarm-Page Alarm Deaktivieren console.log("auf mediaAlarm - Alarm 1 - Wert: " + words[4] + " - reagieren - noch nicht implementiert"); break; default: break; } } function GetNavigationString(pageId: number): string { switch (pageId) { case 0: return "0|1"; case config.pages.length - 1: return "1|0"; case -1: return "0|0"; default: return "1|1"; } } function GenerateDetailPage(type: string, pageItem: PageItem): Payload[] { var out_msgs: Array<Payload> = []; let id = pageItem.id if (existsObject(id)) { var o = getObject(id) var val: (boolean | number) = 0; let icon = Icons.GetIcon("lightbulb"); var iconColor = rgb_dec565(config.defaultColor); if (type == "popupLight") { let switchVal = "0" if (o.common.role == "light") { if (existsState(id + ".GET")) { val = getState(id + ".GET").val; RegisterDetailEntityWatcher(id + ".GET", pageItem, type); } else if (existsState(id + ".SET")) { val = getState(id + ".SET").val; RegisterDetailEntityWatcher(id + ".SET", pageItem, type); } if (val) { switchVal = "1"; iconColor = GetIconColor(pageItem, true, false); } out_msgs.push({ payload: "entityUpdateDetail~" + icon + "~" + + iconColor + "~" + switchVal + ",disable,disable,disable" }) } if (o.common.role == "dimmer") { if (existsState(id + ".ON_ACTUAL")) { val = getState(id + ".ON_ACTUAL").val; RegisterDetailEntityWatcher(id + ".ON_ACTUAL", pageItem, type); } else if (existsState(id + ".ON_SET")) { val = getState(id + ".ON_SET").val; RegisterDetailEntityWatcher(id + ".ON_SET", pageItem, type); } if (val === true) { var iconColor = GetIconColor(pageItem, val, false); switchVal = "1" } let brightness = 0; if (existsState(id + ".ACTUAL")) { if (pageItem.minValue != undefined && pageItem.maxValue != undefined) { brightness = Math.trunc(scale(getState(id + ".ACTUAL").val, pageItem.minValue, pageItem.maxValue, 100, 0)); } else { brightness = getState(id + ".ACTUAL").val; } } else { console.warn("Datenpunkt: " + id + ".DIMMER kann nicht gelesen werden"); } //iconColor = GetIconColor(pageItem, brightness, false); //Farbe muss noch korrekt ermittelt werden if (val === true) { iconColor = GetIconColor(pageItem, true, true); switchVal = "1"; } else { iconColor = GetIconColor(pageItem, false, true); } RegisterDetailEntityWatcher(id + ".ACTUAL", pageItem, type); let colorTemp = "disable" let colorMode = "disable" //let attr_support_color = attr.supported_color_modes //if (attr_support_color.includes("color_temp")) // colortemp = Math.trunc(scale(attr.color_temp, attr.min_mireds, attr.max_mireds, 0, 100)) out_msgs.push({ payload: "entityUpdateDetail~" + icon + "~" + iconColor + "~" + switchVal + "~" + brightness + "~" + colorTemp + "~" + colorMode }) } if (o.common.role == "hue") { if (existsState(id + ".ON_ACTUAL")) { val = getState(id + ".ON_ACTUAL").val; RegisterDetailEntityWatcher(id + ".ON_ACTUAL", pageItem, type); } //Farbe muss noch korrekt ermittelt werden if (val === true) { iconColor = GetIconColor(pageItem, true, true); switchVal = "1"; } else { iconColor = GetIconColor(pageItem, false, true); } let brightness = 0; if (existsState(id + ".DIMMER")) { if (pageItem.minValueBRI !== undefined && pageItem.minValueBRI !== undefined) { brightness = Math.trunc(scale2(getState(id + ".DIMMER").val, 0, 100, 0, 100)); RegisterDetailEntityWatcher(id + ".DIMMER", pageItem, type); } else { console.warn("Datenpunkt: " + id + ".DIMMER kann nicht gelesen werden"); } var colorMode = "disable"; if (existsState(id + ".HUE")) { if (getState(id + ".HUE").val != null) colorMode = "enable"; } var colorTemp = 0; if (existsState(id + ".TEMPERATURE")) { if (getState(id + ".TEMPERATURE").val != null) { if (pageItem.minValue !== undefined && pageItem.minValue !== undefined) { colorTemp = Math.trunc(scale(getState(id + ".TEMPERATURE").val, pageItem.minValue, pageItem.maxValue, 0, 100)); } else { colorTemp = 100 - getState(id + ".TEMPERATURE").val; } RegisterDetailEntityWatcher(id + ".TEMPERATURE", pageItem, type); } } //let attr_support_color = attr.supported_color_modes //if (attr_support_color.includes("color_temp")) //let colortemp = Math.trunc(scale(attr.color_temp, attr.min_mireds, attr.max_mireds, 0, 100)) out_msgs.push({ payload: "entityUpdateDetail~" + icon + "~" + iconColor + "~" + switchVal + "~" + brightness + "~" + colorTemp + "~" + colorMode }) } } if (type == "popupShutter") { if (existsState(id + ".ACTUAL")) { val = getState(id + ".ACTUAL").val; RegisterDetailEntityWatcher(id + ".ACTUAL", pageItem, type); console.log(val); } else if (existsState(id + ".SET")) { val = getState(id + ".SET").val; RegisterDetailEntityWatcher(id + ".SET", pageItem, type); console.log(val); } out_msgs.push({ payload: "entityUpdateDetail~" + val }) } } return out_msgs } function scale(number: number, inMin: number, inMax: number, outMin: number, outMax: number): number { return (outMax+outMin)-((number - inMin) * (outMax - outMin) / (inMax - inMin) + outMin); } function scale2(number: number, inMin: number, inMax: number, outMin: number, outMax: number): number { return (number - inMin) * (outMax - outMin) / (inMax - inMin) + outMin; } function UnsubscribeWatcher(): void { for (const [key, value] of Object.entries(subscriptions)) { unsubscribe(value); delete subscriptions[key] } } function HandleScreensaver(): void { SendToPanel({ payload: "pageType~screensaver"}) UnsubscribeWatcher(); HandleScreensaverUpdate(); } function HandleScreensaverUpdate(): void { if (screensaverEnabled && config.weatherEntity != null && existsObject(config.weatherEntity)) { var icon = getState(config.weatherEntity + ".ICON").val; let temperature: string = existsState(config.weatherEntity + ".ACTUAL") ? getState(config.weatherEntity + ".ACTUAL").val : existsState(config.weatherEntity + ".TEMP") ? getState(config.weatherEntity + ".TEMP").val : "null"; let payloadString = "weatherUpdate~" + Icons.GetIcon(GetAccuWeatherIcon(parseInt(icon))) + "~" + temperature + " " + config.temperatureUnit + "~" /*-------------------------------------------------------------------------------------------------------------------------------------*/ if (weatherForecast == true) { // Accu-Weather Forecast Tag 2 - Tag 5 -- Wenn weatherForecast = true for (let i = 2; i < 6; i++) { let TempMax = getState("accuweather.0.Summary.TempMax_d" + i).val; let DayOfWeek = getState("accuweather.0.Summary.DayOfWeek_d" + i).val; let WeatherIcon = GetAccuWeatherIcon(getState("accuweather.0.Summary.WeatherIcon_d" + i).val); payloadString += DayOfWeek + "~" + Icons.GetIcon(WeatherIcon) + "~" + TempMax + " °C~"; } } else { //In Config definierte Zustände wenn weatherForecast = false payloadString += GetScreenSaverEntityString(config.firstScreensaverEntity); payloadString += GetScreenSaverEntityString(config.secondScreensaverEntity); payloadString += GetScreenSaverEntityString(config.thirdScreensaverEntity); payloadString += GetScreenSaverEntityString(config.fourthScreensaverEntity); } /*-------------------------------------------------------------------------------------------------------------------------------------*/ SendToPanel(<Payload>{ payload: payloadString }); } } function GetScreenSaverEntityString(configElement: ScreenSaverElement | null): string { if (configElement != null && configElement.ScreensaverEntity != null && existsState(configElement.ScreensaverEntity)) { let u1 = getState(configElement.ScreensaverEntity).val; return configElement.ScreensaverEntityText + "~" + Icons.GetIcon(configElement.ScreensaverEntityIcon) + "~" + u1 + " " + configElement.ScreensaverEntityUnitText + "~"; } else { return "~~~"; } } function GetAccuWeatherIcon(icon: number): string { switch (icon) { case 24: // Ice case 30: // Hot case 31: // Cold return "window-open"; // exceptional case 7: // Cloudy case 8: // Dreary (Overcast) case 38: // Mostly Cloudy return "weather-cloudy"; // cloudy case 11: // fog return "weather-fog"; // fog case 25: // Sleet return "weather-hail"; // Hail case 15: // T-Storms return "weather-lightning"; // lightning case 16: // Mostly Cloudy w/ T-Storms case 17: // Partly Sunny w/ T-Storms case 41: // Partly Cloudy w/ T-Storms case 42: // Mostly Cloudy w/ T-Storms return "weather-lightning-rainy"; // lightning-rainy case 33: // Clear case 34: // Mostly Clear case 37: // Hazy Moonlight return "weather-night"; case 3: // Partly Sunny case 4: // Intermittent Clouds case 6: // Mostly Cloudy case 35: // Partly Cloudy case 36: // Intermittent Clouds return "weather-partly-cloudy"; // partlycloudy case 18: // pouring return "weather-pouring"; // pouring case 12: // Showers case 13: // Mostly Cloudy w/ Showers case 14: // Partly Sunny w/ Showers case 26: // Freezing Rain case 39: // Partly Cloudy w/ Showers case 40: // Mostly Cloudy w/ Showers return "weather-rainy"; // rainy case 19: // Flurries case 20: // Mostly Cloudy w/ Flurries case 21: // Partly Sunny w/ Flurries case 22: // Snow case 23: // Mostly Cloudy w/ Snow case 43: // Mostly Cloudy w/ Flurries case 44: // Mostly Cloudy w/ Snow return "weather-snowy"; // snowy case 29: // Rain and Snow return "weather-snowy-rainy"; // snowy-rainy case 1: // Sunny case 2: // Mostly Sunny case 5: // Hazy Sunshine return "weather-sunny"; // sunny case 32: // windy return "weather-windy"; // windy default: return "alert-circle-outline"; } } function sleep(milliseconds) { const date = Date.now(); let currentDate = null; do { currentDate = Date.now(); } while (currentDate - date < milliseconds); } function GetBlendedColor(percentage: number): RGB { if (percentage < 50) return Interpolate(config.defaultOffColor, config.defaultOnColor, percentage / 50.0); return Interpolate(Red, White, (percentage - 50) / 50.0); } function Interpolate(color1: RGB, color2: RGB, fraction: number): RGB { var r: number = InterpolateNum(color1.red, color2.red, fraction); var g: number = InterpolateNum(color1.green, color2.green, fraction); var b: number = InterpolateNum(color1.blue, color2.blue, fraction); return <RGB>{ red: Math.round(r), green: Math.round(g), blue: Math.round(b) }; } function InterpolateNum(d1: number, d2: number, fraction: number): number { return d1 + (d2 - d1) * fraction; } function rgb_dec565(rgb: RGB): number { return ((Math.floor(rgb.red / 255 * 31) << 11) | (Math.floor(rgb.green / 255 * 63) << 5) | (Math.floor(rgb.blue / 255 * 31))); } /* Convert radians to degrees rad - radians to convert, expects rad in range +/- PI per Math.atan2 returns {number} degrees equivalent of rad */ function rad2deg(rad) { return (360 + 180 * rad / Math.PI) % 360; } /* Convert h,s,v values to r,g,b hue - in range [0, 360] saturation - in range 0 to 1 value - in range 0 to 1 returns {Array|number} [r, g,b] in range 0 to 255 */ function hsv2rgb(hue: number, saturation: number, value: number) { hue /= 60; let chroma = value * saturation; let x = chroma * (1 - Math.abs((hue % 2) - 1)); let rgb = hue <= 1? [chroma, x, 0]: hue <= 2? [x, chroma, 0]: hue <= 3? [0, chroma, x]: hue <= 4? [0, x, chroma]: hue <= 5? [x, 0, chroma]: [chroma, 0, x]; return rgb.map(v => (v + value - chroma) * 255); } function getHue(red: number, green: number, blue:number) { var min = Math.min(Math.min(red, green), blue); var max = Math.max(Math.max(red, green), blue); if (min == max) { return 0; } var hue = 0; if (max == red) { hue = (green - blue) / (max - min); } else if (max == green) { hue = 2 + (blue - red) / (max - min); } else { hue = 4 + (red - green) / (max - min); } hue = hue * 60; if (hue < 0) hue = hue + 360; return Math.round(hue); } function pos_to_color(x: number, y: number): RGB { var r = 160/2; var x = Math.round((x - r) / r * 100) / 100; var y = Math.round((r - y) / r * 100) / 100; r = Math.sqrt(x*x + y*y); let sat = 0 if (r > 1) { sat = 0; } else { sat = r; } var hsv = rad2deg(Math.atan2(y, x)); var rgb = hsv2rgb(hsv,sat,1); return <RGB>{ red: Math.round(rgb[0]), green: Math.round(rgb[1]), blue: Math.round(rgb[2]) }; } type RGB = { red: number, green: number, blue: number }; type Payload = { payload: string; }; type Page = { type: string, heading: string, items: PageItem[], useColor: boolean }; interface PageEntities extends Page { type: "cardEntities", items: PageItem[], }; interface PageGrid extends Page { type: "cardGrid", items: PageItem[], }; interface PageThermo extends Page { type: "cardThermo", items: PageItem[], }; interface PageMedia extends Page { type: "cardMedia", items: PageItem[], }; interface PageAlarm extends Page { type: "cardAlarm", items: PageItem[], }; type PageItem = { id: string, icon: (string | undefined), onColor: (RGB | undefined), offColor: (RGB | undefined), useColor: (boolean | undefined), interpolateColor: (boolean | undefined), minValue: (number | undefined), maxValue: (number | undefined), name: (string | undefined), unit: (string | undefined) } type Config = { panelRecvTopic: string, panelSendTopic: string, timeoutScreensaver: number, dimmode: number, //brightnessScreensaver: locale: string, timeFormat: string, dateFormat: string, weatherEntity: string | null, screenSaverDoubleClick: boolean, temperatureUnit: string, firstScreensaverEntity: ScreenSaverElement | null, secondScreensaverEntity: ScreenSaverElement | null, thirdScreensaverEntity: ScreenSaverElement | null, fourthScreensaverEntity: ScreenSaverElement | null, defaultColor: RGB, defaultOnColor: RGB, defaultOffColor: RGB, pages: (PageThermo | PageMedia | PageAlarm | PageEntities | PageGrid)[], button1Page: (PageThermo | PageMedia | PageAlarm | PageEntities | PageGrid | null), button2Page: (PageThermo | PageMedia | PageAlarm | PageEntities | PageGrid | null), }; type ScreenSaverElement = { ScreensaverEntity: string | null, ScreensaverEntityIcon: string | null, ScreensaverEntityText: string | null, ScreensaverEntityUnitText: string | null, }
-
@great-sun sagte in Sonoff NSPanel:
@armilar Evtl. habe ich mich nicht richtig ausgedrückt...
Dass das alles aus iobroker heraus aktiviert wird ist das eine, naja, ok, da muss ich dann mit leben...
Das nächste ist dann aber die Kommunikation. Ich möchte das gerne aufgrund der speziellen Anforderungen, die ich habe, alles selbst im Griff haben, weswegen ich keine "Middleware" zur Kommunikation mit dem Panel oder lovelace im ioBroker einsetzen möchte.
Ich würde gerne alle Daten weiterhin nur mit MQTT bekommen und dann auch direkt die Widgets aus meinem JavaScript aktualisieren können.
Eine Übersetzung des TypeScript auf JavaScript, damit ich die Widgets erstelle, sollte erstmal kein Problem sein.Die Anleitungen scheinen mir aber alle recht speziell auf eine komplette Integration abzuzielen und sind scheinbar nicht dafür gedacht, dass jemand wie ich versteht, wie er selbst kommunizieren kann.
Conclusion wäre, wenn das so ist: Damit ich eine alternative Firmware einsetzen kann, muss ich mich durch deren oder den code der bestehenden Integrationen wälzen. Da mir das ohne Beistand wirklich zuviel ist, müsste ich dann doch bei der Orig bleiben.
Da ich es aber bevorzugen würde, das nicht zu tun, hatte ich mir erhofft, es gibt auch andere Doku.Deswegen hab ich gedacht, dass ich zu doof bin die richtige Doku zu finden.
Nee, nicht falsch verstehen - ich habe "kein" lovelace auf meinem ioBroker am laufen. Da macht das NSPanel mit der Firmware von @joBr99
Mit zum Beispiel dem TypeScript was hier permanent auftaucht + der icons kannst du bereits alles steuern.Reines Customizing in der TypeScript und @britzelpuf wird auch noch einen Adapter schreiben. Dann bauchst du auch kein TypeScript mehr und kannst die Config im Adapter machen.
Wie man das Panel flasht, haben wir ein paar Posts vorher schon aufgezeigt. Ebenso wie die Upgrades laufen
-
@dexxter sehe ich mir morgen mal an. Musste mal die Stadt verlassen und bin nur noch mobil
-
@armilar
Alles klar, dann wünsch ich Dir mal noch einen schönen RestSonntag -
@armilar @joBr99 : OK, also... ich hab jetzt alles soweit fertig gemacht, aber ich komme zu einem Problem, das vielleicht auch keines ist..
15:49:23.163 MQT: tele/tasmota_0CD9C0/RESULT = {"Flashing":{"complete": 0, "time_elapsed": 0}} 15:49:28.010 MQT: tele/tasmota_0CD9C0/RESULT = {"Flashing":{"complete": 1, "time_elapsed": 5}} 15:49:32.434 MQT: tele/tasmota_0CD9C0/RESULT = {"Flashing":{"complete": 2, "time_elapsed": 9}} 15:49:37.691 MQT: tele/tasmota_0CD9C0/RESULT = {"Flashing":{"complete": 3, "time_elapsed": 14}} 15:50:13.769 MQT: tele/tasmota_0CD9C0/STATE = {"Time":"2022-04-24T15:50:13","Uptime":"0T00:15:09","UptimeSec":909,"Heap":166,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":20,"MqttCount":1,"Berry":{"HeapUsed":14,"Objects":223},"POWER1":"OFF","POWER2":"OFF","Wifi":{"AP":1,"SSId":"SVGCast2","BSSId":"F0:2F:74:55:CF:E0","Channel":10,"Mode":"11n","RSSI":100,"Signal":-46,"LinkCount":1,"Downtime":"0T00:00:03"}} 15:50:13.782 MQT: tele/tasmota_0CD9C0/SENSOR = {"Time":"2022-04-24T15:50:13","ANALOG":{"Temperature1":2.0},"ESP32":{"Temperature":38.9},"TempUnit":"C"} 15:55:13.761 MQT: tele/tasmota_0CD9C0/STATE = {"Time":"2022-04-24T15:55:13","Uptime":"0T00:20:09","UptimeSec":1209,"Heap":166,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":20,"MqttCount":1,"Berry":{"HeapUsed":14,"Objects":223},"POWER1":"OFF","POWER2":"OFF","Wifi":{"AP":1,"SSId":"SVGCast2","BSSId":"F0:2F:74:55:CF:E0","Channel":10,"Mode":"11n","RSSI":100,"Signal":-50,"LinkCount":1,"Downtime":"0T00:00:03"}} 15:55:13.781 MQT: tele/tasmota_0CD9C0/SENSOR = {"Time":"2022-04-24T15:55:13","ANALOG":{"Temperature1":2.4},"ESP32":{"Temperature":38.3},"TempUnit":"C"}
Ist das normal, dass der nach 3 % dann ewig braucht, bis er wieder was von sich gibt?
Der steht jetzt bei etwa 10min auf den 3%...Die Tasmota Console reagiert aber noch, Status0 funktioniert und kommt zurück.
-
Also, da geht gar nichts mehr. Nicht einmal ein Reset
Jemand ne Ahnung, wie ich das wieder unbricked bekomme?
-
@great-sun sagte in Sonoff NSPanel:
Also, da geht gar nichts mehr. Nicht einmal ein Reset
Jemand ne Ahnung, wie ich das wieder unbricked bekomme?
um 17:00 Uhr war die Tasmota-Konsole noch da - ist das immer noch so?
Falls ja,- lösch mal in "Verwalte Dateisystem" (Tasmota Konsolen) alle Files raus. autoexec.be/bec
- lege die "autoexec.be": https://github.com/joBr99/nspanel-lovelace-ui/blob/main/tasmota/autoexec.be neu an
- "FlashNextion http://nspanel.pky.eu/lui.tft" in der Tasmota Konsole ausführen
Falls nein, (dann ist dein Tasmota wohl hin; Der ESP32 wird sicher noch okay sein)
- Panel neu mit Tasmota tasmota32-nspanel.bin neu flashen
- die 3 Punkte unter "Falls ja" ausführen
-
@armilar Tasmota ist alles noch da. Mach ich dann heute Abend oder so mal.
Vielen lieben Dank!
-
Deine eigenen Versuche waren im Prinzip nicht schlecht. Wenn du den "type PageItem" entsprechend erweitert hättest (sehr weit unten), hätte es sogar fast funktioniert.
Habe jetzt zusätzlich minValueBrightness/maxValueBrightness und minValueColorTemp/maxValueColorTemp neu hinzugefügt. Wir würden irgendwann mit den Bezeichnern durcheinander kommen. minValue und maxValue können weiterhin verwendet werden, um z.B. Infos zu visualisieren (Batteriezustand, etc.)
Wie im Beispiel (Alias HUE, Brightness auf 70% begrenzt, Farbtemperatur zwischen 500 und 6500K):
<PageItem>{ id: "alias.0.NSPanel_1.TestCTmitHUE", name: "HUE-Light-CT", minValueBrightness: 0, maxValueBrightness: 70, minValueColorTemp: 500, maxValueColorTemp: 6500},
Das Ergebnis (vollständiges TypeScript):
var Icons = new IconsSelector(); const Months = ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"]; const Days = ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"]; //const Off: RGB = { red: 68, green: 115, blue: 158 }; //Blau-Off const Off: RGB = { red: 253, green: 128, blue: 0 }; //Orange-Off const On: RGB = { red: 253, green: 216, blue: 53 }; const MSRed: RGB = { red: 251, green: 105, blue: 98 }; const MSGreen: RGB = { red: 121, green: 222, blue: 121 }; const Red: RGB = { red: 255, green: 0, blue: 0 }; const White: RGB = { red: 255, green: 255, blue: 255 }; const Yellow: RGB = { red: 255, green: 255, blue: 0 }; const Green: RGB = { red: 0, green: 255, blue: 0 }; const Blue: RGB = { red: 0, green: 0, blue: 255 }; const Gray: RGB = { red: 136, green: 136, blue: 136 }; const Black: RGB = { red: 0, green: 0, blue: 0 }; const colorSpotify: RGB = { red: 30, green: 215, blue: 96 }; const colorAlexa: RGB = { red: 49, green: 196, blue: 243 }; const colorRadio: RGB = { red: 255, green: 127, blue: 0 }; const BatteryFull: RGB = { red: 96, green: 176, blue: 62 }; const BatteryEmpty: RGB = { red: 179, green: 45, blue: 25 }; //----Möglichkeit, im Screensaver zwischen Accu-Weather Forecast oder selbstdefinierten Werten zu wählen--------------------------------- var weatherForecast = true; //true = WheatherForecast 5 Days --- false = Config --> firstScreensaverEntity - fourthScreensaverEntity ... //Alexa-Instanz var alexaInstanz = "alexa2.0" var alexaDevice = "G0XXXXXXXXXXXXXXX"; //Primär zu steuendes Device // Wenn alexaSpeakerList definiert, dann werden Einträge verwendet, sonst alle relevanten Devices aus Alexa-Instanz // Speakerwechsel funktioniert nicht bei Radio/TuneIn sonden bei Playlists const alexaSpeakerList = []; //Beispiel ["Echo Spot Buero","Überall","Gartenhaus","Esszimmer","Heimkino"]; //const alexaSpeakerList = ["Echo Spot Buero","Überall","Gartenhaus","Esszimmer","Heimkino","Echo Dot Küche"]; //Datenpunkte für Nachricht an Screensaver var popupNotifyHeading = "0_userdata.0.NSPanel.1.popupNotifyHeading"; var popupNotifyText = "0_userdata.0.NSPanel.1.popupNotifyText"; var Test_Licht: PageEntities = { "type": "cardEntities", "heading": "Büro", "useColor": true, "items": [ <PageItem>{ id: "alias.0.NSPanel_1.Schreibtischlampe", interpolateColor: true}, <PageItem>{ id: "alias.0.NSPanel_1.TestRGBLicht", name: "RGB-Licht", minValueBrightness: 0, maxValueBrightness: 70, interpolateColor: true}, <PageItem>{ id: "alias.0.NSPanel_1.TestCTmitHUE", name: "HUE-Licht-CT", minValueBrightness: 0, maxValueBrightness: 70, minValueColorTemp: 500, maxValueColorTemp: 6500, interpolateColor: true}, <PageItem>{ id: "alias.0.NSPanel_1.TestHUELicht", name: "HUE-Licht-Color", minValueColorTemp: 500, maxValueColorTemp: 6500, interpolateColor: true} ] }; var Buero_Seite_1: PageEntities = { "type": "cardEntities", "heading": "Büro", "useColor": true, "items": [ <PageItem>{ id: "alias.0.NSPanel_1.Schreibtischlampe", interpolateColor: true}, <PageItem>{ id: "alias.0.NSPanel_1.Deckenbeleuchtung"}, <PageItem>{ id: "alias.0.NSPanel_1.Testlampe2", name: "Filamentlampe", minValueBrightness: 0, maxValueBrightness: 70, interpolateColor: true}, <PageItem>{ id: "alias.0.NSPanel_1.Luftreiniger", icon: "power", offColor: MSRed, onColor: MSGreen} ] }; var Fenster_1: PageEntities = { "type": "cardEntities", "heading": "Fenster und Türen", "useColor": true, "items": [ <PageItem>{ id: "alias.0.NSPanel_1.TestFenster", offColor: MSRed, onColor: MSGreen, name: "Büro Fenster"}, <PageItem>{ id: "alias.0.NSPanel_1.Haustuer", offColor: MSRed, onColor: MSGreen, name: "Haustür"}, <PageItem>{ id: "alias.0.NSPanel_1.TestBlind", onColor: White, name: "IKEA Fyrtur"} ] }; var Abfall: PageEntities = { "type": "cardEntities", "heading": "Abfallkalender", "useColor": true, "items": [ <PageItem>{ id: "alias.0.NSPanel_1.Abfall.event1",icon: "trash-can"}, <PageItem>{ id: "alias.0.NSPanel_1.Abfall.event2",icon: "trash-can"}, <PageItem>{ id: "alias.0.NSPanel_1.Abfall.event3",icon: "trash-can"}, <PageItem>{ id: "alias.0.NSPanel_1.Abfall.event4",icon: "trash-can"} ] }; var Buero_Seite_2: PageGrid = { "type": "cardGrid", "heading": "Büro 2", "useColor": true, "items": [ <PageItem>{ id: "alias.0.NSPanel_1.Schreibtischlampe", name: "Schreibtisch"}, <PageItem>{ id: "alias.0.NSPanel_1.Deckenbeleuchtung", name: "Deckenlampe"}, <PageItem>{ id: "alias.0.NSPanel_1.TestFenster", offColor: MSRed, onColor: MSGreen, name: "Büro Fenster"}, <PageItem>{ id: "alias.0.NSPanel_1.Luftreiniger", icon: "power", offColor: MSRed, onColor: MSGreen}, <PageItem>{ id: "alias.0.NSPanel_1.TestBlind", icon: "projector-screen", onColor: White, name: "Beamer"}, <PageItem>{ id: "alias.0.NSPanel_1.Radio.TuneIn", icon: "play", onColor: White} ] }; var Alexa: PageMedia = { "type": "cardMedia", "heading": "Alexa", "useColor": true, "items": [<PageItem>{ id: "alias.0.NSPanel_1.Alexa.PlayerBuero" }] }; var Buero_Themostat: PageThermo = { "type": "cardThermo", "heading": "Thermostat", "useColor": true, "items": [<PageItem>{ id: "alias.0.NSPanel_1.Thermostat_Büro" }] }; var Buero_Alarm: PageAlarm = { "type": "cardAlarm", "heading": "Alarm", "useColor": true, "items": [<PageItem>{ id: "alias.0.NSPanel_1.Alarm" }] }; var button1Page: PageGrid = { "type": "cardGrid", "heading": "Radio", "useColor": true, "items": [ <PageItem>{ id: "alias.0.NSPanel_1.Radio.FFN", icon: "radio", name: "FFN", onColor: colorRadio}, <PageItem>{ id: "alias.0.NSPanel_1.Radio.Antenne" , icon: "radio", name: "Antenne Nds.", onColor: colorRadio}, <PageItem>{ id: "alias.0.NSPanel_1.Radio.NDR2", icon: "radio", name: "NDR2", onColor: colorRadio}, <PageItem>{ id: "alias.0.NSPanel_1.Radio.Bob", icon: "radio", name: "Radio BOB", onColor: colorRadio}, <PageItem>{ id: "alias.0.NSPanel_1.Radio.Spotify", icon: "spotify", name: "Party Playlist", onColor: colorSpotify}, <PageItem>{ id: "alias.0.NSPanel_1.Radio.Alexa", icon: "playlist-music", name: "Playlist 2021", onColor: colorAlexa} ] }; var button2Page: PageEntities = { "type": "cardEntities", "heading": "Büro", "useColor": true, "items": [ <PageItem>{ id: "alias.0.NSPanel_1.Schreibtischlampe"}, <PageItem>{ id: "alias.0.NSPanel_1.Deckenbeleuchtung"} ] }; export const config: Config = { panelRecvTopic: "mqtt.0.SmartHome.NSPanel_1.tele.RESULT", //anpassen panelSendTopic: "mqtt.0.SmartHome.NSPanel_1.cmnd.CustomSend", //anpassen firstScreensaverEntity: { ScreensaverEntity: "hmip.0.devices.3014F711A000185BE9922BCF.channels.1.humidity", ScreensaverEntityIcon: "water-percent", ScreensaverEntityText: "Luft", ScreensaverEntityUnitText: "%" }, secondScreensaverEntity: { ScreensaverEntity: "accuweather.0.Daily.Day1.Day.PrecipitationProbability", ScreensaverEntityIcon: "weather-pouring", ScreensaverEntityText: "Regen", ScreensaverEntityUnitText: "%" }, thirdScreensaverEntity: { ScreensaverEntity: "0_userdata.0.Wetter.Windstaerke_homaticIP", ScreensaverEntityIcon: "weather-windy", ScreensaverEntityText: "Wind", ScreensaverEntityUnitText: "bft" }, fourthScreensaverEntity: { ScreensaverEntity: "accuweather.0.Current.UVIndex", ScreensaverEntityIcon: "solar-power", ScreensaverEntityText: "UV", ScreensaverEntityUnitText: "" }, timeoutScreensaver: 15, dimmode: 8, screenSaverDoubleClick: false, locale: "de_DE", timeFormat: "%H:%M", dateFormat: "%A, %d. %B %Y", weatherEntity: "alias.0.Wetter.Wetter", defaultOffColor: Off, defaultOnColor: On, defaultColor: Off, temperatureUnit: "°C", pages: [ Buero_Seite_1, Test_Licht, Fenster_1, Abfall, Buero_Seite_2, Alexa, Buero_Themostat, Buero_Alarm ], button1Page: button1Page, button2Page: button2Page }; // _________________________________ Ab hier keine Konfiguration mehr _____________________________________ //Notification an Screensaver on({id: [popupNotifyHeading, popupNotifyText], change: "ne"}, async function (obj) { setState(config.panelSendTopic,(['notify~',getState(popupNotifyHeading).val,'~',getState(popupNotifyText).val].join(''))); }); var subscriptions: any = {}; var screensaverEnabled : boolean = false; var pageId = 0; schedule("* * * * *", function () { SendTime(); }); schedule("0 * * * *", function () { SendDate(); }); // Only monitor the extra nodes if present var updateArray: string[] = []; if (config.firstScreensaverEntity !== null && config.firstScreensaverEntity.ScreensaverEntity != null && existsState(config.firstScreensaverEntity.ScreensaverEntity)) { updateArray.push(config.firstScreensaverEntity.ScreensaverEntity) } if (config.secondScreensaverEntity !== null && config.secondScreensaverEntity.ScreensaverEntity != null && existsState(config.secondScreensaverEntity.ScreensaverEntity)) { updateArray.push(config.secondScreensaverEntity.ScreensaverEntity) } if (config.thirdScreensaverEntity !== null && config.thirdScreensaverEntity.ScreensaverEntity != null && existsState(config.thirdScreensaverEntity.ScreensaverEntity)) { updateArray.push(config.thirdScreensaverEntity.ScreensaverEntity) } if (config.fourthScreensaverEntity !== null && config.fourthScreensaverEntity.ScreensaverEntity != null && existsState(config.fourthScreensaverEntity.ScreensaverEntity)) { updateArray.push(config.fourthScreensaverEntity.ScreensaverEntity) } if (updateArray.length > 0) { on(updateArray, function () { HandleScreensaverUpdate(); }) } on({ id: config.panelRecvTopic }, function (obj) { if (obj.state.val.startsWith('\{"CustomRecv":')) { var json = JSON.parse(obj.state.val); var split = json.CustomRecv.split(","); HandleMessage(split[0], split[1], parseInt(split[2]), split); } }); function SendToPanel(val: Payload | Payload[]): void { if (Array.isArray(val)) { val.forEach(function (id, i) { setState(config.panelSendTopic, id.payload); }); } else setState(config.panelSendTopic, val.payload); } function HandleMessage(typ: string, method: string, page: number, words: Array<string>): void { if (typ == "event") { switch (method) { case "startup": screensaverEnabled = false; UnsubscribeWatcher(); HandleStartupProcess(); pageId = 0; GeneratePage(config.pages[0]); break; case "sleepReached": screensaverEnabled = true; if (pageId < 0) pageId = 0; HandleScreensaver(); break; case "pageOpenDetail": screensaverEnabled = false; UnsubscribeWatcher(); let pageItem = config.pages[pageId].items.find(e => e.id === words[3]); if (pageItem !== undefined) SendToPanel(GenerateDetailPage(words[2], pageItem)); case "buttonPress2": screensaverEnabled = false; HandleButtonEvent(words); break; case "button1": case "button2": screensaverEnabled = false; HandleHardwareButton(method); default: break; } } } function GeneratePage(page: Page): void { switch (page.type) { case "cardEntities": SendToPanel(GenerateEntitiesPage(<PageEntities>page)); break; case "cardThermo": SendToPanel(GenerateThermoPage(<PageThermo>page)); break; case "cardGrid": SendToPanel(GenerateGridPage(<PageGrid>page)); break; case "cardMedia": SendToPanel(GenerateMediaPage(<PageMedia>page)); break; case "cardAlarm": SendToPanel(GenerateAlarmPage(<PageAlarm>page)); break; } } function HandleHardwareButton(method: string): void { let page: (PageThermo | PageMedia | PageAlarm | PageEntities | PageGrid); if (config.button1Page !== null && method == "button1") { page = config.button1Page; pageId = -1; } else if (config.button2Page !== null && method == "button2") { page = config.button2Page; pageId = -2; } else { return; } GeneratePage(page); } function HandleStartupProcess(): void { SendDate(); SendTime(); SendToPanel({ payload: "timeout~" + config.timeoutScreensaver }); SendToPanel({ payload: "dimmode~" + config.dimmode }); } function SendDate(): void { var d = new Date(); var day = Days[d.getDay()]; var date = d.getDate(); var month = Months[d.getMonth()]; var year = d.getFullYear(); var _sendDate = "date~" + day + " " + date + " " + month + " " + year; SendToPanel(<Payload>{ payload: _sendDate }); } function SendTime(): void { var d = new Date(); var hr = d.getHours().toString(); var min = d.getMinutes().toString(); if (d.getHours() < 10) { hr = "0" + d.getHours().toString(); } if (d.getMinutes() < 10) { min = "0" + d.getMinutes().toString(); } SendToPanel(<Payload>{ payload: "time~" + hr + ":" + min }); } function GenerateEntitiesPage(page: PageEntities): Payload[] { var out_msgs: Array<Payload> = []; out_msgs = [{ payload: "pageType~cardEntities" }] out_msgs.push({ payload: GeneratePageElements(page) }); return out_msgs } function GenerateGridPage(page: PageGrid): Payload[] { var out_msgs: Array<Payload> = []; out_msgs = [{ payload: "pageType~cardGrid" }] out_msgs.push({ payload: GeneratePageElements(page) }); return out_msgs } function GeneratePageElements(page: Page): string { let maxItems = 0; switch (page.type) { case "cardThermo": maxItems = 1; break; case "cardAlarm": maxItems = 1; break; case "cardMedia": maxItems = 1; break; case "cardEntities": maxItems = 4; break; case "cardGrid": maxItems = 6; break; } let pageData = "entityUpd~" + page.heading + "~" + GetNavigationString(pageId) for (let index = 0; index < maxItems; index++) { if (page.items[index] !== undefined) { pageData += CreateEntity(page.items[index], index + 1, page.useColor); } else { pageData += CreateEntity(<PageItem>{ id: "delete" }, index + 1); } } return pageData; } function CreateEntity(pageItem: PageItem, placeId: number, useColors: boolean = false): string { var iconId = "0" if (pageItem.id == "delete") { return "~delete~~~~~" } var name: string; var type: string; // ioBroker if (existsObject(pageItem.id)) { let o = getObject(pageItem.id) var val = null; name = pageItem.name !== undefined ? pageItem.name : o.common.name.de if (existsState(pageItem.id + ".GET")) { val = getState(pageItem.id + ".GET").val; RegisterEntityWatcher(pageItem.id + ".GET"); } else if (existsState(pageItem.id + ".SET")) { val = getState(pageItem.id + ".SET").val; RegisterEntityWatcher(pageItem.id + ".SET"); } var iconColor = rgb_dec565(config.defaultColor); switch (o.common.role) { case "socket": case "light": type = "light" iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : o.common.role == "socket" ? Icons.GetIcon("power-socket-de") : Icons.GetIcon("lightbulb"); var optVal = "0" if (val === true || val === "true") { optVal = "1" iconColor = GetIconColor(pageItem, true, useColors); } else { iconColor = GetIconColor(pageItem, false, useColors); } return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + optVal; case "hue": type = "light" iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("lightbulb"); var optVal = "0" if (existsState(pageItem.id + ".ON_ACTUAL")) { val = getState(pageItem.id + ".ON_ACTUAL").val; RegisterEntityWatcher(pageItem.id + ".ON_ACTUAL"); } if (val === true || val === "true") { optVal = "1" iconColor = GetIconColor(pageItem, existsState(pageItem.id + ".DIMMER") ? 100 - getState(pageItem.id + ".DIMMER").val : true, useColors); } if (existsState(pageItem.id + ".HUE")) { if (getState(pageItem.id + ".HUE").val != null) { let huecolor = hsv2rgb(getState(pageItem.id + ".HUE").val,1,1); let rgb = <RGB>{ red: Math.round(huecolor[0]), green: Math.round(huecolor[1]), blue: Math.round(huecolor[2])} iconColor = rgb_dec565(pageItem.interpolateColor !== undefined ? rgb : config.defaultOnColor); //RegisterDetailEntityWatcher(id + ".HUE", pageItem, type); } } return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + optVal; case "rgb": type = "light" iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("lightbulb"); var optVal = "0" if (existsState(pageItem.id + ".ON_ACTUAL")) { val = getState(pageItem.id + ".ON_ACTUAL").val; RegisterEntityWatcher(pageItem.id + ".ON_ACTUAL"); } if (val === true || val === "true") { optVal = "1" iconColor = GetIconColor(pageItem, existsState(pageItem.id + ".DIMMER") ? 100 - getState(pageItem.id + ".DIMMER").val : true, useColors); } if (existsState(pageItem.id + ".RED") && existsState(pageItem.id + ".GREEN") && existsState(pageItem.id + ".BLUE")) { if (getState(pageItem.id + ".RED").val != null && getState(pageItem.id + ".GREEN").val != null && getState(pageItem.id + ".BLUE").val != null) { let rgbRed = getState(pageItem.id + ".RED").val; let rgbGreen = getState(pageItem.id + ".GREEN").val; let rgbBlue = getState(pageItem.id + ".BLUE").val; let rgb = <RGB>{ red: Math.round(rgbRed), green: Math.round(rgbGreen), blue: Math.round(rgbBlue)} iconColor = rgb_dec565(pageItem.interpolateColor !== undefined ? rgb : config.defaultOnColor); } } return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + optVal; case "dimmer": type = "light" iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("lightbulb"); var optVal = "0" if (existsState(pageItem.id + ".ON_ACTUAL")) { val = getState(pageItem.id + ".ON_ACTUAL").val; RegisterEntityWatcher(pageItem.id + ".ON_ACTUAL"); } else if (existsState(pageItem.id + ".ON_SET")) { val = getState(pageItem.id + ".ON_SET").val; RegisterEntityWatcher(pageItem.id + ".ON_SET"); } if (val === true || val === "true") { optVal = "1" iconColor = GetIconColor(pageItem, existsState(pageItem.id + ".ACTUAL") ? 100 - getState(pageItem.id + ".ACTUAL").val : true, useColors); } return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + optVal; case "blind": type = "shutter" iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("window-open"); iconColor = GetIconColor(pageItem, existsState(pageItem.id + ".ACTUAL") ? getState(pageItem.id + ".ACTUAL").val : true, useColors); return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" case "door": case "window": type = "text"; if (existsState(pageItem.id + ".ACTUAL")) { if (getState(pageItem.id + ".ACTUAL").val) { iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : o.common.role == "door" ? Icons.GetIcon("door-open") : Icons.GetIcon("window-open-variant"); iconColor = GetIconColor(pageItem, false, useColors); var windowState = "opened" } else { iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : o.common.role == "door" ? Icons.GetIcon("door-closed") : Icons.GetIcon("window-closed-variant"); //iconId = Icons.GetIcon("window-closed-variant"); iconColor = GetIconColor(pageItem, true, useColors); var windowState = "closed" } RegisterEntityWatcher(pageItem.id + ".ACTUAL"); } return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + windowState; case "info": case "humidity": case "value.temperature": case "value.humidity": case "sensor.door": case "sensor.window": case "thermostat": type = "text"; iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : o.common.role == "value.temperature" || o.common.role == "thermostat" ? Icons.GetIcon("thermometer") : Icons.GetIcon("information-outline"); let unit = ""; var optVal = "0" if (existsState(pageItem.id + ".ON_ACTUAL")) { optVal = getState(pageItem.id + ".ON_ACTUAL").val; unit = pageItem.unit !== undefined ? pageItem.unit : GetUnitOfMeasurement(pageItem.id + ".ON_ACTUAL"); RegisterEntityWatcher(pageItem.id + ".ON_ACTUAL"); } else if (existsState(pageItem.id + ".ACTUAL")) { optVal = getState(pageItem.id + ".ACTUAL").val; unit = pageItem.unit !== undefined ? pageItem.unit : GetUnitOfMeasurement(pageItem.id + ".ACTUAL"); RegisterEntityWatcher(pageItem.id + ".ACTUAL"); } if (o.common.role == "value.temperature") { iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("thermometer"); } iconColor = GetIconColor(pageItem, parseInt(optVal), useColors); return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + optVal + " " + unit; case "button": type = "button"; iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("gesture-tap-button"); let buttonText = pageItem.name !== undefined ? pageItem.name : "PRESS"; iconColor = GetIconColor(pageItem, true, useColors); return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + buttonText; case "warning": type = "text"; iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("alert-outline"); iconColor = getState(([pageItem.id,'.LEVEL'].join(''))).val; let itemName = getState(([pageItem.id,'.TITLE'].join(''))).val; let itemInfo = getState(([pageItem.id,'.INFO'].join(''))).val; return "~" + type + "~" + itemName + "~" + iconId + "~" + iconColor + "~" + itemName + "~" + itemInfo; default: return "~delete~~~~~"; } } return "~delete~~~~~" } function GetIconColor(pageItem: PageItem, value: (boolean | number), useColors: boolean): number { // dimmer if ((pageItem.useColor || useColors) && pageItem.interpolateColor && typeof (value) === "number") { let maxValue = pageItem.maxValueBrightness !== undefined ? pageItem.maxValueBrightness : 100; let minValue = pageItem.minValueBrightness !== undefined ? pageItem.minValueBrightness : 0; if (pageItem.maxValue !== undefined) maxValue = pageItem.maxValue; if (pageItem.minValue !== undefined) minValue = pageItem.minValue; value = value > maxValue ? maxValue : value; value = value < minValue ? minValue : value; return rgb_dec565( Interpolate( pageItem.offColor !== undefined ? pageItem.offColor : config.defaultOffColor, pageItem.onColor !== undefined ? pageItem.onColor : config.defaultOnColor, scale(value, minValue, maxValue, 0, 1) )); } if ((pageItem.useColor || useColors) && ((typeof (value) === "boolean" && value) || value > (pageItem.minValueBrightness !== undefined ? pageItem.minValueBrightness : 0))) { return rgb_dec565(pageItem.onColor !== undefined ? pageItem.onColor : config.defaultOnColor) } return rgb_dec565(pageItem.offColor !== undefined ? pageItem.offColor : config.defaultOffColor); } function RegisterEntityWatcher(id: string): void { if (subscriptions.hasOwnProperty(id)) { return; } subscriptions[id] = (on({ id: id, change: 'any' }, function (data) { if(pageId >= 0) SendToPanel({ payload: GeneratePageElements(config.pages[pageId]) }); if(pageId == -1 && config.button1Page != undefined) SendToPanel({ payload: GeneratePageElements(config.button1Page) }); if(pageId == -2 && config.button2Page != undefined) SendToPanel({ payload: GeneratePageElements(config.button2Page) }); })) } function RegisterDetailEntityWatcher(id: string, pageItem: PageItem, type: string): void { if (subscriptions.hasOwnProperty(id)) { return; } subscriptions[id] = (on({ id: id, change: 'any' }, function () { SendToPanel(GenerateDetailPage(type, pageItem)); })) } function GetUnitOfMeasurement(id: string): string { if (!existsObject(id)) return ""; let obj = getObject(id); if (typeof obj.common.unit !== 'undefined') { return obj.common.unit } if (typeof obj.common.alias !== 'undefined' && typeof obj.common.alias.id !== 'undefined') { return GetUnitOfMeasurement(obj.common.alias.id); } return ""; } function GenerateThermoPage(page: PageThermo): Payload[] { var id = page.items[0].id var out_msgs: Array<Payload> = []; out_msgs.push({ payload: "pageType~cardThermo" }); // ioBroker if (existsObject(id)) { let o = getObject(id) let name = page.items[0].name !== undefined ? page.items[0].name : o.common.name.de let currentTemp = 0; if (existsState(id + ".ACTUAL")) currentTemp = (Math.round(parseFloat(getState(id + ".ACTUAL").val) * 10)/10)*10; let destTemp = 0; if (existsState(id + ".SET")) { destTemp = getState(id + ".SET").val.toFixed(2) * 10; } let status = "" if (existsState(id + ".MODE")) status = getState(id + ".MODE").val; let minTemp = 50 //Min Temp 5°C let maxTemp = 300 //Max Temp 30°C let stepTemp = 5 //0-4 verwendet bei ungerader Anzahl Parametern let bt0 = "~~~~"; //verwendet bei ungleichen Parametern let bt1 = "~~~~"; //verwendet bei ungleichen Parametern let bt2 = "~~~~"; //verwendet bei ungleichen Parametern let bt3 = "~~~~"; //verwendet bei ungleichen Parametern let bt4 = "~~~~"; //verwendet bei ungleichen Parametern //5-8 verwendet bei gerader Anzahl Parametern let bt5 = Icons.GetIcon("water-percent") + "~0~1~~"; let bt6 = Icons.GetIcon("fire") + "~0~1~~"; let bt7 = Icons.GetIcon("wifi") + "~0~1~~"; let bt8 = Icons.GetIcon("battery-high") + "~0~1~~"; if (existsState(id + ".HUMIDITY")){ bt5 = Icons.GetIcon("water-percent") + "~2016~1~bt8~"; if (parseInt(getState(id + ".HUMIDITY").val) < 40) { bt5 = Icons.GetIcon("water-percent") + "~65504~1~bt8~"; } else if (parseInt(getState(id + ".HUMIDITY").val) < 30) { bt5 = Icons.GetIcon("water-percent") + "~63488~1~bt8~"; } else if (parseInt(getState(id + ".HUMIDITY").val) > 65) { bt5 = Icons.GetIcon("water-percent") + "~65504~1~bt8~"; } else if (parseInt(getState(id + ".HUMIDITY").val) > 75) { bt5 = Icons.GetIcon("water-percent") + "~63488~1~bt8~"; } } if (existsState(id + ".MAINTAIN")){ if (getState(id + ".MAINTAIN").val >> .1) { bt6 = Icons.GetIcon("fire") + "~60897~1~bt8~"; } else { bt6 = Icons.GetIcon("fire") + "~33840~0~bt8~"; } } if (existsState(id + ".UNREACH")){ if (getState(id + ".UNREACH").val) { bt7 = Icons.GetIcon("wifi-off") + "~63488~1~bt8~"; } else { bt7 = Icons.GetIcon("wifi") + "~2016~1~bt8~"; } } if (existsState(id + ".LOWBAT")){ if (getState(id + ".LOWBAT").val) { bt8 = Icons.GetIcon("battery-low") + "~63488~1~bt8~"; } else { bt8 = Icons.GetIcon("battery-high") + "~2016~1~bt8~"; } } let icon_res = bt0 + bt1 + bt2 + bt3 + bt4 + bt5 + bt6 + bt7 + bt8; out_msgs.push({ payload: "entityUpd~" + name + "~" + GetNavigationString(pageId) + "~" + id + "~" + currentTemp + "~" + destTemp + "~" + status + "~" + minTemp + "~" + maxTemp + "~" + stepTemp + "~" +icon_res}) } return out_msgs } function GenerateMediaPage(page: PageMedia): Payload[] { var id = page.items[0].id var out_msgs: Array<Payload> = []; out_msgs.push({ payload: "pageType~cardMedia" }); if (existsObject(id)) { let name = getState(id + ".ALBUM").val; let media_icon = Icons.GetIcon("playlist-music"); let title = getState(id + ".TITLE").val; let author = getState(id + ".ARTIST").val; let volume = getState(id + ".VOLUME").val; var iconplaypause = Icons.GetIcon("pause"); //pause var onoffbutton = 1374; if (getState(id + ".STATE").val) { onoffbutton = 65535; iconplaypause = Icons.GetIcon("pause"); //pause } else { iconplaypause = Icons.GetIcon("play"); //play } let currentSpeaker = getState(([alexaInstanz,'.Echo-Devices.',alexaDevice,'.Info.name'].join(''))).val; //console.log(id); //------------------------------------------------------------------------------------------------------------- // nachfolgend alle Alexa-Devices (ist Online / Player- und Commands-Verzeichnis vorhanden) auflisten und verketten // Wenn Konstante alexaSpeakerList mind. einen Eintrag enthält, wird die Konstante verwendet - ansonsten Alle Devices aus dem Alexa Adapter let speakerlist = ""; if (alexaSpeakerList.length > 0) { for (let i_index in alexaSpeakerList) { speakerlist = speakerlist + alexaSpeakerList[i_index] + "?"; } } else { let i_list = Array.prototype.slice.apply($('[state.id="' + alexaInstanz + '.Echo-Devices.*.Info.name"]')); for (let i_index in i_list) { let i = i_list[i_index]; let deviceId = i; deviceId = deviceId.split('.'); if (getState(([alexaInstanz,'.Echo-Devices.',deviceId[3],'.online'].join(''))).val && existsObject(([alexaInstanz,'.Echo-Devices.',deviceId[3],'.Player'].join(''))) && existsObject(([alexaInstanz,'.Echo-Devices.',deviceId[3],'.Commands'].join('')))) { speakerlist = speakerlist + getState(i).val + "?"; } } } speakerlist = speakerlist.substring(0,speakerlist.length-1); //-------------------------------------------------------------------------------------------------------------- out_msgs.push({ payload: "entityUpd~" + name + "~" + id + "~" + id + "~" + //???? media_icon + "~" + title + "~" + author + "~" + volume + "~" + iconplaypause + "~" + currentSpeaker + "~" + speakerlist + "~" + onoffbutton}); } return out_msgs } function GenerateAlarmPage(page: PageAlarm): Payload[] { var id = page.items[0].id var out_msgs: Array<Payload> = []; out_msgs.push({ payload: "pageType~cardAlarm" }); var armed: boolean = true; if (armed) { var arm1 = "Deaktivieren"; //arm1*~* var arm1ActionName = "D1"; //arm1ActionName*~* var arm2 = ""; //arm2*~* var arm2ActionName = ""; //arm2ActionName*~* var arm3 = ""; //arm3*~* var arm3ActionName = ""; //arm3ActionName*~* var arm4 = ""; //arm4*~* var arm4ActionName = ""; //arm4ActionName*~* var icon = Icons.GetIcon("shield-home"); //icon*~* var iconcolor = 63488; //iconcolor*~* var numpadStatus = 1; //numpadStatus*~* var flashing = 1; //flashing* } else { var arm1 = "Alarm 1"; //arm1*~* var arm1ActionName = "A1"; //arm1ActionName*~* var arm2 = "Alarm 2"; //arm2*~* var arm2ActionName = "A2"; //arm2ActionName*~* var arm3 = "Alarm 3"; //arm3*~* var arm3ActionName = "A3"; //arm3ActionName*~* var arm4 = "Alarm 4"; //arm4*~* var arm4ActionName = "A4"; //arm4ActionName*~* var icon = Icons.GetIcon("shield-off"); //icon*~* var iconcolor = 2016; //iconcolor*~* var numpadStatus = 1; //numpadStatus*~* var flashing = 1; //flashing* } out_msgs.push({ payload: "entityUpd~" + //entityUpd~* id + "~" + //internalNameEntity*~* //navigation*~* "~" + //??? arm1 + "~" + //arm1*~* arm1ActionName + "~" + //arm1ActionName*~* arm2 + "~" + //arm2*~* arm2ActionName + "~" + //arm2ActionName*~* arm3 + "~" + //arm3*~* arm3ActionName + "~" + //arm3ActionName*~* arm4 + "~" + //arm4*~* arm4ActionName + "~" + //arm4ActionName*~* icon + "~" + //icon*~* 39=Disarmed 35=Shield_Home, 40 iconcolor + "~" + //iconcolor*~* 2016=green 63488=red numpadStatus + "~" + //numpadStatus*~* flashing}); //flashing* return out_msgs } function setIfExists(id: string, value: any, type: string | null = null): boolean { if (type === null) { if (existsState(id)) { setState(id, value); return true; } } else { let obj = getObject(id); if (existsState(id) && obj.common.type !== undefined && obj.common.type === type) { setState(id, value); return true; } } return false; } function toggleState(id: string): boolean { let obj = getObject(id); if (existsState(id) && obj.common.type !== undefined && obj.common.type === "boolean") { setState(id, !getState(id).val); return true; } return false; } function HandleButtonEvent(words): void { let id = words[2] let buttonAction = words[3]; //console.log(words[0] + " - " + words[1] + " - " + words[2] + " - " + words[3] + " - " + words[4] + " - PageId: " + pageId); switch (buttonAction) { case "bNext": var pageNum = ((pageId + 1) % config.pages.length); pageId = Math.abs(pageNum); UnsubscribeWatcher(); GeneratePage(config.pages[pageId]); break; case "bPrev": var pageNum = ((pageId - 1) % config.pages.length); pageId = Math.abs(pageNum); UnsubscribeWatcher(); GeneratePage(config.pages[pageId]); break; case "bExit": if (config.screenSaverDoubleClick) { if (words[4] == 2) GeneratePage(config.pages[pageId]); } else GeneratePage(config.pages[pageId]); break; case "OnOff": if (existsObject(id)) { var action = false if (words[4] == "1") action = true let o = getObject(id) switch (o.common.role) { case "light": setIfExists(id + ".SET", action); break; case "dimmer": setIfExists(id + ".ON_SET", action) ? true : setIfExists(id + ".ON_ACTUAL", action); break; case "hue": // Armilar setIfExists(id + ".ON_ACTUAL", action); } } break; case "up": setIfExists(id + ".OPEN", true) break; case "stop": setIfExists(id + ".STOP", true) break; case "down": setIfExists(id + ".CLOSE", true) break; case "button": toggleState(id + ".SET") ? true : toggleState(id + ".ON_SET") break; case "positionSlider": setIfExists(id + ".SET", parseInt(words[4])) ? true : setIfExists(id + ".ACTUAL", parseInt(words[4])); break; case "brightnessSlider": if (existsObject(id)) { let o = getObject(id); let pageItem = config.pages[pageId].items.find(e => e.id === id); switch (o.common.role) { case "dimmer": if (pageItem.minValueBrightness != undefined && pageItem.maxValueBrightness != undefined) { let sliderPos = Math.trunc(scale(parseInt(words[4]), 0, 100, pageItem.maxValueBrightness, pageItem.minValueBrightness)) setIfExists(id + ".SET", sliderPos) ? true : setIfExists(id + ".ACTUAL", sliderPos); } else { setIfExists(id + ".SET", parseInt(words[4])) ? true : setIfExists(id + ".ACTUAL", parseInt(words[4])); } break; case "hue": case "rgb": setIfExists(id + ".DIMMER", parseInt(words[4])); } } break; case "colorTempSlider": // Armilar - Slider tickt verkehrt - Hell = 0 / Dunkel = 100 -> Korrektur let pageItem = config.pages[pageId].items.find(e => e.id === id); if (pageItem.minValueColorTemp !== undefined && pageItem.minValueColorTemp !== undefined) { let colorTempK = Math.trunc(scale(parseInt(words[4]), 0, 100, pageItem.minValueColorTemp, pageItem.maxValueColorTemp)); setIfExists(id + ".TEMPERATURE", (colorTempK)); } else { setIfExists(id + ".TEMPERATURE", 100 - words[4]); } break; case "colorWheel": let colorCoordinates = words[4].split('|'); let rgb = pos_to_color(colorCoordinates[0], colorCoordinates[1]); //console.log(rgb); //console.log(getHue(rgb.red, rgb.green, rgb.blue)); let o = getObject(id); switch (o.common.role) { case "hue": setIfExists(id + ".HUE", getHue(rgb.red, rgb.green, rgb.blue)); break; case "rgb": setIfExists(id + ".RED", rgb.red); setIfExists(id + ".GREEN", rgb.green); setIfExists(id + ".BLUE", rgb.blue); } break; case "tempUpd": setIfExists(id + ".SET", parseInt(words[4]) / 10) break; case "media-back": setIfExists(id + ".PREV", true) break; case "media-pause": if (getState(id + ".STATE").val === true) { setIfExists(id + ".PAUSE", true) } else { setIfExists(id + ".PLAY", true) } break; case "media-next": setIfExists(id + ".NEXT", true) break; case "volumeSlider": setIfExists(id + ".VOLUME", parseInt(words[4])) break; case "speaker-sel": let i_list = Array.prototype.slice.apply($('[state.id="' + alexaInstanz + '.Echo-Devices.*.Info.name"]')); for (let i_index in i_list) { let i = i_list[i_index]; if ((getState(i).val) === words[4]){ let deviceId = i; deviceId = deviceId.split('.'); setIfExists(alexaInstanz + ".Echo-Devices." + alexaDevice + ".Commands.textCommand", "Schiebe meine Musik auf " + words[4]); alexaDevice = deviceId[3] } } break; case "media-OnOff": setIfExists(id + ".STOP", true) break; case "A1": //Alarm-Page Alarm 1 aktivieren console.log("auf mediaAlarm - Alarm 1 - Wert: " + words[4] + " - reagieren - noch nicht implementiert"); break; case "A2": //Alarm-Page Alarm 2 aktivieren console.log("auf mediaAlarm - Alarm 1 - Wert: " + words[4] + " - reagieren - noch nicht implementiert"); break; case "A3": //Alarm-Page Alarm 3 aktivieren console.log("auf mediaAlarm - Alarm 1 - Wert: " + words[4] + " - reagieren - noch nicht implementiert"); break; case "A4": //Alarm-Page Alarm 4 aktivieren console.log("auf mediaAlarm - Alarm 1 - Wert: " + words[4] + " - reagieren - noch nicht implementiert"); break; case "D1": //Alarm-Page Alarm Deaktivieren console.log("auf mediaAlarm - Alarm 1 - Wert: " + words[4] + " - reagieren - noch nicht implementiert"); break; default: break; } } function GetNavigationString(pageId: number): string { switch (pageId) { case 0: return "0|1"; case config.pages.length - 1: return "1|0"; case -1: return "0|0"; default: return "1|1"; } } function GenerateDetailPage(type: string, pageItem: PageItem): Payload[] { var out_msgs: Array<Payload> = []; let id = pageItem.id if (existsObject(id)) { var o = getObject(id) var val: (boolean | number) = 0; let icon = Icons.GetIcon("lightbulb"); var iconColor = rgb_dec565(config.defaultColor); if (type == "popupLight") { let switchVal = "0" let brightness = 0; if (o.common.role == "light") { if (existsState(id + ".GET")) { val = getState(id + ".GET").val; RegisterDetailEntityWatcher(id + ".GET", pageItem, type); } else if (existsState(id + ".SET")) { val = getState(id + ".SET").val; RegisterDetailEntityWatcher(id + ".SET", pageItem, type); } if (val) { switchVal = "1"; iconColor = GetIconColor(pageItem, true, false); } out_msgs.push({ payload: "entityUpdateDetail~" + icon + "~" + + iconColor + "~" + switchVal + ",disable,disable,disable" }) } if (o.common.role == "dimmer") { if (existsState(id + ".ON_ACTUAL")) { val = getState(id + ".ON_ACTUAL").val; RegisterDetailEntityWatcher(id + ".ON_ACTUAL", pageItem, type); } else if (existsState(id + ".ON_SET")) { val = getState(id + ".ON_SET").val; RegisterDetailEntityWatcher(id + ".ON_SET", pageItem, type); } if (val === true) { var iconColor = GetIconColor(pageItem, val, false); switchVal = "1" } if (existsState(id + ".ACTUAL")) { if (pageItem.minValueBrightness != undefined && pageItem.maxValueBrightness != undefined) { brightness = Math.trunc(scale(getState(id + ".ACTUAL").val, pageItem.minValueBrightness, pageItem.maxValueBrightness, 100, 0)); } else { brightness = getState(id + ".ACTUAL").val; } } else { console.warn("Alisas-Datenpunkt: " + id + ".ACTUAL could not be read"); } if (val === true) { iconColor = GetIconColor(pageItem, 100 - brightness, true); switchVal = "1"; } else { iconColor = GetIconColor(pageItem, false, true); } RegisterDetailEntityWatcher(id + ".ACTUAL", pageItem, type); let colorTemp = "disable" let colorMode = "disable" out_msgs.push({ payload: "entityUpdateDetail~" + icon + "~" + iconColor + "~" + switchVal + "~" + brightness + "~" + colorTemp + "~" + colorMode }) } //HUE-Licht if (o.common.role == "hue") { if (existsState(id + ".ON_ACTUAL")) { val = getState(id + ".ON_ACTUAL").val; RegisterDetailEntityWatcher(id + ".ON_ACTUAL", pageItem, type); } if (existsState(id + ".DIMMER")) { if (pageItem.minValueBrightness != undefined && pageItem.maxValueBrightness != undefined) { brightness = Math.trunc(scale(getState(id + ".DIMMER").val, pageItem.minValueBrightness, pageItem.maxValueBrightness, 100, 0)); } else { brightness = getState(id + ".DIMMER").val; } RegisterDetailEntityWatcher(id + ".DIMMER", pageItem, type); } else { console.warn("Alias-Datenpunkt: " + id + ".DIMMER could not be read"); } if (val === true) { iconColor = GetIconColor(pageItem, 100 - brightness, true); switchVal = "1"; } else { iconColor = GetIconColor(pageItem, false, true); } var colorMode = "disable" if (existsState(id + ".HUE")) { if (getState(id + ".HUE").val != null) { colorMode = "enable"; let huecolor = hsv2rgb(getState(id + ".HUE").val,1,1); let rgb = <RGB>{ red: Math.round(huecolor[0]), green: Math.round(huecolor[1]), blue: Math.round(huecolor[2])} iconColor = rgb_dec565(pageItem.interpolateColor !== undefined ? rgb : config.defaultOnColor); //RegisterDetailEntityWatcher(id + ".HUE", pageItem, type); } } var colorTemp = 0; if (existsState(id + ".TEMPERATURE")) { if (getState(id + ".TEMPERATURE").val != null) { if (pageItem.minValueColorTemp !== undefined && pageItem.minValueColorTemp !== undefined) { colorTemp = Math.trunc(scale(getState(id + ".TEMPERATURE").val, pageItem.minValueColorTemp, pageItem.maxValueColorTemp, 0, 100)); } else { colorTemp = 100 - getState(id + ".TEMPERATURE").val; } //RegisterDetailEntityWatcher(id + ".TEMPERATURE", pageItem, type); } } else { console.warn("Alias-Datenpunkt: " + id + ".TEMPERATURE could not be read"); } out_msgs.push({ payload: "entityUpdateDetail~" + icon + "~" + iconColor + "~" + switchVal + "~" + brightness + "~" + colorTemp + "~" + colorMode }) } //RGB-Licht if (o.common.role == "rgb") { if (existsState(id + ".ON_ACTUAL")) { val = getState(id + ".ON_ACTUAL").val; RegisterDetailEntityWatcher(id + ".ON_ACTUAL", pageItem, type); } if (existsState(id + ".DIMMER")) { if (pageItem.minValueBrightness != undefined && pageItem.maxValueBrightness != undefined) { brightness = Math.trunc(scale(getState(id + ".DIMMER").val, pageItem.minValueBrightness, pageItem.maxValueBrightness, 100, 0)); } else { brightness = getState(id + ".DIMMER").val; } RegisterDetailEntityWatcher(id + ".DIMMER", pageItem, type); } else { console.warn("Alias-Datenpunkt: " + id + ".DIMMER could not be read"); } if (val === true) { iconColor = GetIconColor(pageItem, 100 - brightness, true); switchVal = "1"; } else { iconColor = GetIconColor(pageItem, false, true); } var colorMode = "disable" if (existsState(id + ".RED") && existsState(id + ".GREEN") && existsState(id + ".BLUE")) { if (getState(id + ".RED").val != null && getState(id + ".GREEN").val != null && getState(id + ".BLUE").val != null) { colorMode = "enable"; let rgb = <RGB>{ red: Math.round(getState(id + ".RED").val), green: Math.round(getState(id + ".GREEN").val), blue: Math.round(getState(id + ".BLUE").val)} iconColor = rgb_dec565(pageItem.interpolateColor !== undefined ? rgb : config.defaultOnColor); //RegisterDetailEntityWatcher(id + ".HUE", pageItem, type); } } var colorTemp = 0; if (existsState(id + ".TEMPERATURE")) { if (getState(id + ".TEMPERATURE").val != null) { if (pageItem.minValueColorTemp !== undefined && pageItem.minValueColorTemp !== undefined) { colorTemp = Math.trunc(scale(getState(id + ".TEMPERATURE").val, pageItem.minValueColorTemp, pageItem.maxValueColorTemp, 0, 100)); } else { colorTemp = 100 - getState(id + ".TEMPERATURE").val; } //RegisterDetailEntityWatcher(id + ".TEMPERATURE", pageItem, type); } } else { console.warn("Alias-Datenpunkt: " + id + ".TEMPERATURE could not be read"); } out_msgs.push({ payload: "entityUpdateDetail~" + icon + "~" + iconColor + "~" + switchVal + "~" + brightness + "~" + colorTemp + "~" + colorMode }) } } if (type == "popupShutter") { if (existsState(id + ".ACTUAL")) { val = getState(id + ".ACTUAL").val; RegisterDetailEntityWatcher(id + ".ACTUAL", pageItem, type); } else if (existsState(id + ".SET")) { val = getState(id + ".SET").val; RegisterDetailEntityWatcher(id + ".SET", pageItem, type); } out_msgs.push({ payload: "entityUpdateDetail~" + val }) } } return out_msgs } function scale(number: number, inMin: number, inMax: number, outMin: number, outMax: number): number { return (outMax+outMin)-((number - inMin) * (outMax - outMin) / (inMax - inMin) + outMin); } function UnsubscribeWatcher(): void { for (const [key, value] of Object.entries(subscriptions)) { unsubscribe(value); delete subscriptions[key] } } function HandleScreensaver(): void { SendToPanel({ payload: "pageType~screensaver"}) UnsubscribeWatcher(); HandleScreensaverUpdate(); } function HandleScreensaverUpdate(): void { if (screensaverEnabled && config.weatherEntity != null && existsObject(config.weatherEntity)) { var icon = getState(config.weatherEntity + ".ICON").val; let temperature: string = existsState(config.weatherEntity + ".ACTUAL") ? getState(config.weatherEntity + ".ACTUAL").val : existsState(config.weatherEntity + ".TEMP") ? getState(config.weatherEntity + ".TEMP").val : "null"; let payloadString = "weatherUpdate~" + Icons.GetIcon(GetAccuWeatherIcon(parseInt(icon))) + "~" + temperature + " " + config.temperatureUnit + "~" /*-------------------------------------------------------------------------------------------------------------------------------------*/ if (weatherForecast == true) { // Accu-Weather Forecast Tag 2 - Tag 5 -- Wenn weatherForecast = true for (let i = 2; i < 6; i++) { let TempMax = getState("accuweather.0.Summary.TempMax_d" + i).val; let DayOfWeek = getState("accuweather.0.Summary.DayOfWeek_d" + i).val; let WeatherIcon = GetAccuWeatherIcon(getState("accuweather.0.Summary.WeatherIcon_d" + i).val); payloadString += DayOfWeek + "~" + Icons.GetIcon(WeatherIcon) + "~" + TempMax + " °C~"; } } else { //In Config definierte Zustände wenn weatherForecast = false payloadString += GetScreenSaverEntityString(config.firstScreensaverEntity); payloadString += GetScreenSaverEntityString(config.secondScreensaverEntity); payloadString += GetScreenSaverEntityString(config.thirdScreensaverEntity); payloadString += GetScreenSaverEntityString(config.fourthScreensaverEntity); } /*-------------------------------------------------------------------------------------------------------------------------------------*/ SendToPanel(<Payload>{ payload: payloadString }); } } function GetScreenSaverEntityString(configElement: ScreenSaverElement | null): string { if (configElement != null && configElement.ScreensaverEntity != null && existsState(configElement.ScreensaverEntity)) { let u1 = getState(configElement.ScreensaverEntity).val; return configElement.ScreensaverEntityText + "~" + Icons.GetIcon(configElement.ScreensaverEntityIcon) + "~" + u1 + " " + configElement.ScreensaverEntityUnitText + "~"; } else { return "~~~"; } } function GetAccuWeatherIcon(icon: number): string { switch (icon) { case 24: // Ice case 30: // Hot case 31: // Cold return "window-open"; // exceptional case 7: // Cloudy case 8: // Dreary (Overcast) case 38: // Mostly Cloudy return "weather-cloudy"; // cloudy case 11: // fog return "weather-fog"; // fog case 25: // Sleet return "weather-hail"; // Hail case 15: // T-Storms return "weather-lightning"; // lightning case 16: // Mostly Cloudy w/ T-Storms case 17: // Partly Sunny w/ T-Storms case 41: // Partly Cloudy w/ T-Storms case 42: // Mostly Cloudy w/ T-Storms return "weather-lightning-rainy"; // lightning-rainy case 33: // Clear case 34: // Mostly Clear case 37: // Hazy Moonlight return "weather-night"; case 3: // Partly Sunny case 4: // Intermittent Clouds case 6: // Mostly Cloudy case 35: // Partly Cloudy case 36: // Intermittent Clouds return "weather-partly-cloudy"; // partlycloudy case 18: // pouring return "weather-pouring"; // pouring case 12: // Showers case 13: // Mostly Cloudy w/ Showers case 14: // Partly Sunny w/ Showers case 26: // Freezing Rain case 39: // Partly Cloudy w/ Showers case 40: // Mostly Cloudy w/ Showers return "weather-rainy"; // rainy case 19: // Flurries case 20: // Mostly Cloudy w/ Flurries case 21: // Partly Sunny w/ Flurries case 22: // Snow case 23: // Mostly Cloudy w/ Snow case 43: // Mostly Cloudy w/ Flurries case 44: // Mostly Cloudy w/ Snow return "weather-snowy"; // snowy case 29: // Rain and Snow return "weather-snowy-rainy"; // snowy-rainy case 1: // Sunny case 2: // Mostly Sunny case 5: // Hazy Sunshine return "weather-sunny"; // sunny case 32: // windy return "weather-windy"; // windy default: return "alert-circle-outline"; } } function GetBlendedColor(percentage: number): RGB { if (percentage < 50) return Interpolate(config.defaultOffColor, config.defaultOnColor, percentage / 50.0); return Interpolate(Red, White, (percentage - 50) / 50.0); } function Interpolate(color1: RGB, color2: RGB, fraction: number): RGB { var r: number = InterpolateNum(color1.red, color2.red, fraction); var g: number = InterpolateNum(color1.green, color2.green, fraction); var b: number = InterpolateNum(color1.blue, color2.blue, fraction); return <RGB>{ red: Math.round(r), green: Math.round(g), blue: Math.round(b) }; } function InterpolateNum(d1: number, d2: number, fraction: number): number { return d1 + (d2 - d1) * fraction; } function rgb_dec565(rgb: RGB): number { return ((Math.floor(rgb.red / 255 * 31) << 11) | (Math.floor(rgb.green / 255 * 63) << 5) | (Math.floor(rgb.blue / 255 * 31))); } /* Convert radians to degrees rad - radians to convert, expects rad in range +/- PI per Math.atan2 returns {number} degrees equivalent of rad */ function rad2deg(rad) { return (360 + 180 * rad / Math.PI) % 360; } /* Convert h,s,v values to r,g,b hue - in range [0, 360] saturation - in range 0 to 1 value - in range 0 to 1 returns {Array|number} [r, g,b] in range 0 to 255 */ function hsv2rgb(hue: number, saturation: number, value: number) { hue /= 60; let chroma = value * saturation; let x = chroma * (1 - Math.abs((hue % 2) - 1)); let rgb = hue <= 1? [chroma, x, 0]: hue <= 2? [x, chroma, 0]: hue <= 3? [0, chroma, x]: hue <= 4? [0, x, chroma]: hue <= 5? [x, 0, chroma]: [chroma, 0, x]; return rgb.map(v => (v + value - chroma) * 255); } function getHue(red: number, green: number, blue:number) { var min = Math.min(Math.min(red, green), blue); var max = Math.max(Math.max(red, green), blue); if (min == max) { return 0; } var hue = 0; if (max == red) { hue = (green - blue) / (max - min); } else if (max == green) { hue = 2 + (blue - red) / (max - min); } else { hue = 4 + (red - green) / (max - min); } hue = hue * 60; if (hue < 0) hue = hue + 360; return Math.round(hue); } function pos_to_color(x: number, y: number): RGB { var r = 160/2; var x = Math.round((x - r) / r * 100) / 100; var y = Math.round((r - y) / r * 100) / 100; r = Math.sqrt(x*x + y*y); let sat = 0 if (r > 1) { sat = 0; } else { sat = r; } var hsv = rad2deg(Math.atan2(y, x)); var rgb = hsv2rgb(hsv,sat,1); return <RGB>{ red: Math.round(rgb[0]), green: Math.round(rgb[1]), blue: Math.round(rgb[2]) }; } type RGB = { red: number, green: number, blue: number }; type Payload = { payload: string; }; type Page = { type: string, heading: string, items: PageItem[], useColor: boolean }; interface PageEntities extends Page { type: "cardEntities", items: PageItem[], }; interface PageGrid extends Page { type: "cardGrid", items: PageItem[], }; interface PageThermo extends Page { type: "cardThermo", items: PageItem[], }; interface PageMedia extends Page { type: "cardMedia", items: PageItem[], }; interface PageAlarm extends Page { type: "cardAlarm", items: PageItem[], }; type PageItem = { id: string, icon: (string | undefined), onColor: (RGB | undefined), offColor: (RGB | undefined), useColor: (boolean | undefined), interpolateColor: (boolean | undefined), minValueBrightness: (number | undefined), maxValueBrightness: (number | undefined), minValueColorTemp: (number | undefined), maxValueColorTemp: (number | undefined), minValue: (number | undefined), maxValue: (number | undefined), name: (string | undefined), unit: (string | undefined) } type Config = { panelRecvTopic: string, panelSendTopic: string, timeoutScreensaver: number, dimmode: number, //brightnessScreensaver: locale: string, timeFormat: string, dateFormat: string, weatherEntity: string | null, screenSaverDoubleClick: boolean, temperatureUnit: string, firstScreensaverEntity: ScreenSaverElement | null, secondScreensaverEntity: ScreenSaverElement | null, thirdScreensaverEntity: ScreenSaverElement | null, fourthScreensaverEntity: ScreenSaverElement | null, defaultColor: RGB, defaultOnColor: RGB, defaultOffColor: RGB, pages: (PageThermo | PageMedia | PageAlarm | PageEntities | PageGrid)[], button1Page: (PageThermo | PageMedia | PageAlarm | PageEntities | PageGrid | null), button2Page: (PageThermo | PageMedia | PageAlarm | PageEntities | PageGrid | null), }; type ScreenSaverElement = { ScreensaverEntity: string | null, ScreensaverEntityIcon: string | null, ScreensaverEntityText: string | null, ScreensaverEntityUnitText: string | null, }
P.S.: Der Alias-Typ "RGB-Licht" sollte jetzt auch gehen...