NEWS
Sonoff NSPanel
-
@jobr99 sagte in Sonoff NSPanel:
die
pos_to_color(x, y)
macht aus der position nen rgb wert, ist halt python und kein java/typescript ne c++ version könnt ich vermutlich noch auftreiben, aber das will ja eigentlich auch keinerDanke, dass Stichwort reicht mir schon (C++ ist doch auch cool )
Da wo (nach den Icon-Updates) gestern noch ein nettes Icon für Audio-Devices (was du beim großen Online-Kaufhaus erwerben kannst) war, ist jetzt ein schwarzers Loch. Besteht die Chance, das zurück zu bekommen? --> "amazon-alexa"
-
@armilar said in Sonoff NSPanel:
amazon-alexa
https://github.com/Templarian/MaterialDesign/issues/5409
sieht so aus als ob das icon entfernt wurde
hab das cheatsheet im repo noch nicht geupdatet, das hier ist das aktuelle für die dev version
-
@jobr99 sagte in Sonoff NSPanel:
kein plan, wenn du die payload für die seite postest kann ich's ausprobieren (also die commands, die er für die seite zum panel schickt)
so etwas: bei den längeren Device-Namen brauchst du etwas länger.
entityUpd~Na denn ffn~alias.0.NSPanel_1.Alexa.PlayerBuero~alias.0.NSPanel_1.Alexa.PlayerBuero~~PINK - CAN WE PRETEND~radio ffn~27~~Echo Spot Buero~Echo Spot Buero?Echo Dot Schlafzimmer Kind?Echo Dot Badezimmer?Echo Dot Gästezimmer?Echo Dot Küche?Echo Dot Schlafzimmer Eltern?Echo Dot Arbeitszimmer?Echo Plus Esszimmer?Echo Studio 1 Wohnzimmer?Echo Studio 2 Wohnzimmer?Echo Esszimmer?Echo 4 Gartenhaus 1?Echo 4 Gartenhaus 2?Überall?Gartenhaus?Esszimmer?Heimkino~1
-
-
@jobr99 sagte in Sonoff NSPanel:
@armilar said in Sonoff NSPanel:
amazon-alexa
https://github.com/Templarian/MaterialDesign/issues/5409
sieht so aus als ob das icon entfernt wurde
hab das cheatsheet im repo noch nicht geupdatet, das hier ist das aktuelle für die dev version
Danke - tzz, 1000 Icons neu und das weg . Dann muss wohl ne Alternative rein
-
@armilar
in meinem backend sortiere ich das aktuell spielende device ans ende, damit man am anfang nicht zwei mal drücken mussansonsten reagiert das bei mir aber eigentlich völlig normal
-
@jobr99 ja, sieht gut aus - nicht am echtenPanel - kann nochmal versuchen die Leerzeichen mit Bindestrichen zu versehen und die beim einlesen wieder entfernen. Vielleicht hilft das
-
@jobr99 sagte in Sonoff NSPanel:
die
pos_to_color(x, y)
macht aus der position nen rgb wert, ist halt python und kein java/typescript ne c++ version könnt ich vermutlich noch auftreiben, aber das will ja eigentlich auch keineredit: das sollte dem kram auch ziemlich nahe kommen, kann nur sein, dass die segmente vertauscht sind oder sowas
Falls du den python-code zur hand hast, dann brauche ich mich nicht mit Verschiebungen rumschlagen - Wäre Top
-
-
-
@armilar @joBr99 Weiss eigentlich einer von Euch, wo man die Nextion Firmware her bekommen kann, wenn es ein Update gibt?
Einen HMI Editor hab ich ja schon einmal gefunden, muss nur noch die HMI Files, die die Grundlage für das NSPanel liefern suchen, dann kann ich das machen, was ich willDanke schonmal!
-
@great-sun das HMI von Sonoff ist nicht veröffentlicht und auch das tft file für das display, gibt es nicht zum download, die version, die man auf discord bekommt wurde aus nem dump vom flash chip extrahiert (und den dump bekommst du auch nicht über serial, da musst du mit kabeln direkt an den flash chip aufm display controller)
-
@jobr99 Aua!
Ich schätze, ich muss dann doch wohl oder übel mal eine andere Oberfläche drauf geben... Gibt es denn eine, die ähnlich aussieht, die ich da rauf packen kann?
Dann würde ich das auf dem zweiten NSPanel machen, das ich eh noch hier am Tisch habe...Vielen lieben Dank für Eure Unterstützung... Wie Ihr seht, ich bin nicht unbelehrbar
-
@great-sun
das meiste ist esphome zeugs, bei dem du in der esphome config und im nextion editor rumfummeln musst, dann gibts noch das hier (auch wenns da im moment afaik nur nen openhab "backend" gibt)
https://community.openhab.org/t/nxpanel-replacement-firmware-for-sonoff-nspanel/132869und meine, wenn's dir um die grid seite von der sock fw geht, sowas geht:
-
@great-sun sagte in Sonoff NSPanel:
@jobr99 Aua!
Ich schätze, ich muss dann doch wohl oder übel mal eine andere Oberfläche drauf geben... Gibt es denn eine, die ähnlich aussieht, die ich da rauf packen kann?
Dann würde ich das auf dem zweiten NSPanel machen, das ich eh noch hier am Tisch habe...Vielen lieben Dank für Eure Unterstützung... Wie Ihr seht, ich bin nicht unbelehrbar
Diese UI ist nicht in Granit gemeißelt und bekommt täglich Neuerungen - ebenso Updates
Wie du erkennen kannst, hast du direkten Kontakt mit Product-Owner und Developer und eine mächtige Community.
Die UI (mir gefällt sie) für dich im Moment nicht so einen "schicken" Farbverlauf wie das Sonoff, aber dafür sind die Seiten und Funktionen nahezu unbegrenzt (kommen auch täglich neue dazu). Also nicht auf 3 Seiten begrenzt mit wenigen Infos drauf.
Funktional kann das Sonoff-Original ja eigentlich fast gar nichts, wenn man auch bei Sonoff von den diversen Bugs (inbesondere beim Thermostaten und Bezeichnern) in der Firmware absieht. Und selbst wenn die ein Update über Sonoff bereitstellen, so stelle ich mir auch die Frage: "wie bekomme ich das denn auf mein Tasmota-Panel?"
Ich habe ein Smart-Home und es muss in erster Linie mal haptisch und bei mir intuitiv (bin gar nicht so versessen auf Tasten), virtualisiert funktionieren. Dann kann es hübsch aussehen.
P.S.: Die Oberflächen brauchen wir eher, wenn Oma mal auf den Hund aufpasst oder Besuch kommt - den Rest macht das Haus von selbst.
-
@Great-SUN
wenn du unbedingt willst, nimm dir das HMI und pass es an, da das Panel keine Transparenz kann (und das ziel von dem projekt ist möglichst nah an dem dashboard von HomeAssistant zu sein) werd ich kein background image einbauen, aber grundsätzlich funktioniert das(die meisten icons sind keine bilder sondern text, da sollte es reichen sta auf crop image umzustellen) und bei den wenigen icons die bilder sind, muss du den hintergrund in das bild vom icon reinbasteln
-
@armilar
DAnke für Dein Script, habe nur Problem das beim compilieren kommt :javascript.0 (1031) script.js.Displays.NSPanel022042022: TypeScript compilation failed: Kleiner; ^ ERROR: Cannot find name 'Kleiner'.
finde aber nicht den Begriff "Kleiner " im script, bzw habe ich keinen Plan was oder wo ich ansetzten kann
Mit freundlichen Grüßen
Mikewolf -
@mikewolf Schau dochmal im Script Editor. Auf der rechten Seite ist eine Miniaturansicht des Scriptes. Wenn da ein Fehler drin ist, wie bei dir, markiert er die betreffende Zeile mit einer roten Linie. Da mal nachschauen und ggf hier einstellen.
Ich habe auch kein "kleiner" in meinem script. -
@holgerwolf
Im scripteditor markiert er nichts ...? keine rote Linie ...
Fehler gefunden hat Mac zuviel kopiert , Fehler sitzt ja meistens vorm Bildschirm !!
DANKE!!!!! -
@mikewolf gerne
@dexxter @britzelpuf Das ColorWheel unter dem Alias-Typen "HUE" sollte nun auch funktionieren:
@joBr99 Die helper.py aus dem luibackend war doch sehr hilfreich. Die RGB-Werte in der ioBroker-Konsole sehen für mich überzeugend aus.
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 Forcast 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 alexaSpekerList definiert, dann werden Einträge verwendet, sonst alle relevanten Devices aus Alexa-Instanz // Spekerwechsel 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"}, <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: "amazon-alexa", 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 }; //Notification an Screensaver on({id: [popupNotifyHeading, popupNotifyText], change: "ne"}, async function (obj) { setState(config.panelSendTopic,(['notify~',getState(popupNotifyHeading).val,'~',getState(popupNotifyText).val].join(''))); }); // _________________________________ Ab hier keine Konfiguration mehr _____________________________________ 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("amazon-alexa"); let title = getState(id + ".TITLE").val; let author = getState(id + ".ARTIST").val; let volume = getState(id + ".VOLUME").val; var iconplaypause = Icons.GetIcon("pause"); //pause if (getState(id + ".STATE").val) { 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); //-------------------------------------------------------------------------------------------------------------- let onoffbutton = 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]; 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); switch (o.common.role) { case "dimmer": 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")) { brightness = Math.trunc(scale(getState(id + ".ACTUAL").val, 0, 100, 0, 100)) iconColor = GetIconColor(pageItem, brightness, false); 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(scale(getState(id + ".DIMMER").val, 0, 100, 0, 100)); RegisterDetailEntityWatcher(id + ".DIMMER", pageItem, type); } 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; else if (existsState(id + ".SET")) val = getState(id + ".SET").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 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), 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, }