From 29de0b9d850bc4d323a078c7885d570a3f1de063 Mon Sep 17 00:00:00 2001 From: Armilar <102996011+Armilar@users.noreply.github.com> Date: Mon, 9 May 2022 11:54:13 +0200 Subject: [PATCH 01/23] More functions (Subpages, Auto-Update, Aliases) --- ioBroker/NsPanelTs.ts | 1109 ++++++++++++++++++++++++++++++++++------- 1 file changed, 935 insertions(+), 174 deletions(-) diff --git a/ioBroker/NsPanelTs.ts b/ioBroker/NsPanelTs.ts index 991037f1..55edb63e 100644 --- a/ioBroker/NsPanelTs.ts +++ b/ioBroker/NsPanelTs.ts @@ -1,109 +1,228 @@ /*----------------------------------------------------------------------- joBr99 Projekt: https://github.com/joBr99/nspanel-lovelace-ui/tree/main/ioBroker +- abgestimmt auf TFT 34 / v2.8.2 (LATEST) / BerryDriver 4 / Tasmota 11.1.0 + NsPanelTs.ts (dieses TypeScript in ioBroker) Stable: https://github.com/joBr99/nspanel-lovelace-ui/blob/main/ioBroker/NsPanelTs.ts icon_mapping.ts: https://github.com/joBr99/nspanel-lovelace-ui/blob/main/ioBroker/icon_mapping.ts (TypeScript muss in global liegen) Mögliche Aliase: - Info - Werte aus Datenpunkt - Licht - An/Aus (Schalter) - Steckdose - An/Aus (Schalter) - Dimmer - An/Aus, Brightness - Farbtemperatur - An/Aus, Farbtemperatur und Brightness - HUE-Licht - Zum Schalten von Color-Leuchtmitteln über HUE-Wert, Brightness, Farbtemperatur, An/Aus (HUE kann auch fehlen) - RGB-Licht - RGB-Leuchtmitteln/Stripes welche Rot/Grün/ und Blau separat benötigen (Tasmota, WifiLight, etc.) + Brightness, Farbtemperatur - RGB-Licht-einzeln - RGB-Leuchtmitteln/Stripes welche HEX-Farbwerte benötigen (Tasmota, WifiLight, etc.) + Brightness, Farbtemperatur - Jalousien - Up, Stop, Down, Position - Fenster - Sensor open - Tür - Sensor open - Taste - Für Szenen oder Radiosender, etc. --> Nur Funktionsaufruf - Kein Taster wie MonoButton - True/False - ??? wahrscheinlich wäre Tastensensor besser geeignet, um Alias-Taste langfristig für einen MonoButton (Taster) zu verwenden ??? - Thermostat - Aktuelle Raumtemperatur, Setpoint, etc. - Feuchtigkeit - Anzeige von Humidity - Datenpunkten, ananlog Info - Medien - Steuerung von Alexa - Über Alias-Manager im Verzeichnis Player automatisch anlegen (Geräte-Manager funktioniert nicht) - Wetter - Aktuelle Außen-Temperatur und aktuelles Accu-Wheather-Icon für Screensaver + Info - Werte aus Datenpunkt + Schieberegler - Slider numerische Werte (SET/ACTUAL) + Lautstärke: - Volume (SET/ACTUAL) und MUTE + Lautstärke-Gruppe: - analog Lautstärke + Licht - An/Aus (Schalter) + Steckdose - An/Aus (Schalter) + Dimmer - An/Aus, Brightness + Farbtemperatur - An/Aus, Farbtemperatur und Brightness + HUE-Licht - Zum Schalten von Color-Leuchtmitteln über HUE-Wert, Brightness, Farbtemperatur, An/Aus (HUE kann auch fehlen) + RGB-Licht - RGB-Leuchtmitteln/Stripes welche Rot/Grün/ und Blau separat benötigen (Tasmota, WifiLight, etc.) + Brightness, Farbtemperatur + RGB-Licht-einzeln - RGB-Leuchtmitteln/Stripes welche HEX-Farbwerte benötigen (Tasmota, WifiLight, etc.) + Brightness, Farbtemperatur + Jalousien - Up, Stop, Down, Position + Fenster - Sensor open + Tür - Sensor open + Verschluss - Türschloss SET/ACTUAL/OPEN + Taste - Für Szenen oder Radiosender, etc. --> Nur Funktionsaufruf - Kein Taster wie MonoButton - True/False + Tastensensor - analog Taste + Thermostat - Aktuelle Raumtemperatur, Setpoint, etc. + Temperatur - Anzeige von Temperture - Datenpunkten, ananlog Info + Feuchtigkeit - Anzeige von Humidity - Datenpunkten, ananlog Info + Medien - Steuerung von Alexa - Über Alias-Manager im Verzeichnis Player automatisch anlegen (Geräte-Manager funktioniert nicht) + Wettervorhersage - Aktuelle Außen-Temperatur (Temp) und aktuelles Accu-Wheather-Icon (Icon) für Screensaver + +Erforderliche Adapter: + Accu-Wheater: - Bei Nutzung der Wetterfunktionen im Screensaver + Alexa2: - Bei Nutzung der dynamischen SpeakerList in der cardMedia + +Upgrades in Konsole: +Tasmota BerryDriver : Backlog UpdateDriverVersion https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be; Restart 1 +TFT EU STABLE Version : FlashNextion http://nspanel.pky.eu/lui-release.tft +TFT EU DEV Version : FlashNextion http://nspanel.pky.eu/lui.tft --------------------------------------------------------------------------------------- */ + var Icons = new IconsSelector(); -var timeoutSlider; +var timeoutSlider: any; +var NSPanel_Path = "0_userdata.0.NSPanel.1." +var Debug = false; 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 Red: RGB = { red: 255, green: 0, blue: 0 }; -const White: RGB = { red: 255, green: 255, blue: 255 }; -const Yellow: RGB = { red: 253, green: 216, blue: 53 }; -const Green: RGB = { red: 96, green: 176, blue: 62 } -const Brown: RGB = { red: 120, green: 80, blue: 59 } -const Gray: RGB = { red: 69, green: 69, blue: 69 } -const Off: RGB = { red: 68, green: 115, blue: 158 }; +//const Off: RGB = { red: 68, green: 115, blue: 158 }; //Blau-Off +const Off: RGB = { red: 253, green: 128, blue: 0 }; //Orange-Off - schönere Farbübergänge const On: RGB = { red: 253, green: 216, blue: 53 }; -const BatteryFull: RGB = { red: 96, green: 176, blue: 62 } -const BatteryEmpty: RGB = { red: 179, green: 45, blue: 25 } +const MSRed: RGB = { red: 251, green: 105, blue: 98 }; +const MSYellow: RGB = { red: 255, green: 235, blue: 156 }; +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 }; +//----------------------Begin Dimmode +//Screensaver nachts auf dunkel ("brightnessNight: z.B. 2") oder aus ("brightnessNight:0") +if (existsState(NSPanel_Path + "NSPanel_Dimmode_brightnessDay") == false || existsState(NSPanel_Path + "NSPanel_Dimmode_hourDay") == false || existsState(NSPanel_Path + "NSPanel_Dimmode_brightnessNight") == false || existsState(NSPanel_Path + "NSPanel_Dimmode_hourNight") == false) { + createState(NSPanel_Path + "NSPanel_Dimmode_brightnessDay", 8, {type: 'number'}, function() {setState(NSPanel_Path + "NSPanel_Dimmode_brightnessDay", 8)}); + createState(NSPanel_Path + "NSPanel_Dimmode_hourDay", 7, {type: 'number'}, function() {setState(NSPanel_Path + "NSPanel_Dimmode_hourDay", 7)}); + createState(NSPanel_Path + "NSPanel_Dimmode_brightnessNight", 1, {type: 'number'}, function() {setState(NSPanel_Path + "NSPanel_Dimmode_brightnessNight", 1)}); + createState(NSPanel_Path + "NSPanel_Dimmode_hourNight", 22, {type: 'number'}, function() {setState(NSPanel_Path + "NSPanel_Dimmode_hourNight", 22)}); +} +var vBrightnessDay = getState(NSPanel_Path + "NSPanel_Dimmode_brightnessDay").val; +var vBrightnessNight = getState(NSPanel_Path + "NSPanel_Dimmode_brightnessNight").val; +var vTimeDay = getState(NSPanel_Path + "NSPanel_Dimmode_hourDay").val; +if (vTimeDay < 10) { + var TimeDay = "0" + vTimeDay.toString() + ":00"; +} else { + var TimeDay = vTimeDay.toString() + ":00"; +} +var vTimeNight = getState(NSPanel_Path + "NSPanel_Dimmode_hourNight").val; +if (vTimeNight < 10) { + var TimeNight = "0" + vTimeNight.toString() + ":00"; +} else { + var TimeNight = vTimeNight.toString() + ":00"; +} +var timeDimMode = {dimmodeOn: true, brightnessDay: vBrightnessDay, brightnessNight: vBrightnessNight, timeDay: TimeDay, timeNight: TimeNight}; +//--------------------End Dimmode -//----Ability to choose between Accu-Weather Forcast or self-defined values in the screensaver--------------------------------- +//----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 ... -//Alexa2-Instanz +//Alexa-Instanz var alexaInstanz = "alexa2.0" -var alexaDevice = "G0XXXXXXXXXXXXXX"; //Primär zu steuendes Device -//If alexaSpeakerList is defined, then entries are used, otherwise all relevant devices from the ioBroker Alexa2 adapter -const alexaSpeakerList = []; //Example ["Echo Spot Buero","Überall","Gartenhaus","Esszimmer","Heimkino"]; +var alexaDevice = "G070RR1075220388"; //Primär zu steuerndes Device (Seriennummer) + +// 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.WzDisplay.popupNotifyHeading"; -var popupNotifyText = "0_userdata.0.WzDisplay.popupNotifyText"; +var popupNotifyHeading = NSPanel_Path + "popupNotifyHeading"; +var popupNotifyText = NSPanel_Path + "popupNotifyText"; + +var tasmotaOTAURL = "http://ota.tasmota.com/tasmota32/release/tasmota32-DE.bin" + +//cardAlarm - Konfiguration +// .... var Test_Licht: PageEntities = { "type": "cardEntities", "heading": "Color Aliase", "useColor": true, + "subPage": false, "items": [ { id: "alias.0.NSPanel_1.TestRGBLichteinzeln", name: "RGB-Licht Hex-Color", interpolateColor: true}, //{ id: "alias.0.NSPanel_1.TestFarbtemperatur", name: "Farbtemperatur", interpolateColor: true}, - { id: "alias.0.NSPanel_1.TestRGBLicht", name: "RGB-Licht", minValueBrightness: 0, maxValueBrightness: 70, interpolateColor: true}, + { id: "alias.0.NSPanel_1.TestRGBLicht", name: "RGB-Licht", minValueBrightness: 0, maxValueBrightness: 100, interpolateColor: true}, { id: "alias.0.NSPanel_1.TestCTmitHUE", name: "HUE-Licht-CT", minValueBrightness: 0, maxValueBrightness: 70, minValueColorTemp: 500, maxValueColorTemp: 6500, interpolateColor: true}, { id: "alias.0.NSPanel_1.TestHUELicht", name: "HUE-Licht-Color", minValueColorTemp: 500, maxValueColorTemp: 6500, interpolateColor: true} ] }; -var Wohnen: PageEntities = +var Test_Funktionen: PageEntities = { "type": "cardEntities", - "heading": "Haus", + "heading": "Sonstige Aliase", "useColor": true, + "subPage": false, "items": [ - { id: "alias.0.Stern", name: "Sternsteckdose"}, - { id: "alias.0.Erker"}, - { id: "alias.0.Küche", interpolateColor: true }, - { id: "alias.0.Wand" } + { id: "alias.0.NSPanel_1.TestLautstärke", offColor: MSRed /*if mute=true*/, onColor: MSGreen ,name: "Echo Spot Büro", minValue: 0, maxValue: 100}, + { id: "alias.0.NSPanel_1.TestTemperatur",name: "Temperatur außen", icon: "thermometer", onColor: White}, + { id: "alias.0.NSPanel_1.TestFeuchtigkeit", name: "Luftfeuchte außen", icon: "water-percent", unit: "%H", onColor: White}, + { id: "alias.0.NSPanel_1.TestInfo", name: "Windstärke", icon: "wind-power-outline", offColor: MSRed, onColor: MSGreen, unit: "bft", minValue: 0, maxValue: 12, interpolateColor: true, useColor: true} ] }; -var Strom: PageEntities = +var Buero_Seite_1: PageEntities = { "type": "cardEntities", - "heading": "Strom", + "heading": "Büro", "useColor": true, + "subPage": false, "items": [ - { id: "alias.0.Netz", icon: "flash", interpolateColor: true, offColor: BatteryFull, onColor: Red, minValue: -1000, maxValue: 1000 }, - { id: "alias.0.Hausverbrauch", icon: "flash", interpolateColor: true, offColor: BatteryFull, onColor: Red, maxValue: 1000 }, - { id: "alias.0.Pv", icon: "solar-power", interpolateColor: true, offColor: Off, onColor: BatteryFull, maxValue: 1000 }, - { id: "alias.0.Batterie", icon: "battery-medium", interpolateColor: true, offColor: BatteryEmpty, onColor: BatteryFull } + { id: "alias.0.NSPanel_1.Schreibtischlampe", interpolateColor: true}, + { id: "alias.0.NSPanel_1.Deckenbeleuchtung", interpolateColor: true}, + { id: "alias.0.NSPanel_1.Testlampe2", name: "Filamentlampe", minValueBrightness: 0, maxValueBrightness: 70, interpolateColor: true}, + { id: "alias.0.NSPanel_1.Luftreiniger", icon: "power", offColor: MSRed, onColor: MSGreen} ] }; -var Müll: PageEntities = +var Fenster_1: PageEntities = { "type": "cardEntities", - "heading": "Müllkalender", + "heading": "Fenster und Türen", "useColor": true, + "subPage": false, "items": [ - { id: "alias.0.WzNsPanel.Müll.Bio_Tonne" ,unit:"Tage", icon: "trash-can",onColor: Brown}, - { id: "alias.0.WzNsPanel.Müll.Graue_Tonne" ,unit:"Tage",icon: "trash-can",onColor: Gray}, - { id: "alias.0.WzNsPanel.Müll.Grüne_Tonne" ,unit:"Tage",icon: "trash-can",onColor: Green}, - { id: "alias.0.WzNsPanel.Müll.Gelbe_Tonne" ,unit:"Tage",icon: "trash-can",onColor: Yellow} + { id: "alias.0.NSPanel_1.TestFenster", offColor: MSRed, onColor: MSGreen, name: "Büro Fenster"}, + { id: "alias.0.NSPanel_1.Haustuer", offColor: MSRed, onColor: MSGreen, name: "Haustür"}, + { id: "alias.0.NSPanel_1.TestBlind", onColor: White, name: "IKEA Fyrtur"}, + { id: "alias.0.NSPanel_1.TestDoorlock", offColor: MSRed, onColor: MSGreen, name: "Türschloss"}, + ] +}; + +var Button_1: PageEntities = +{ + "type": "cardEntities", + "heading": "Button Aliase", + "useColor": true, + "subPage": false, + "items": [ + { id: "alias.0.NSPanel_1.TestTastensensor", name: "Tastensensor (FFN)"}, + { id: "alias.0.NSPanel_1.Radio.NDR2", icon: "radio", name: "Taste (NDR2)", onColor: colorRadio}, + ] +}; + +var Subpages_1: PageEntities = +{ + "type": "cardEntities", + "heading": "Test Subpages", + "useColor": true, + "subPage": false, + "items": [ + { navigate: true, id: "Abfall", onColor: White, name: "Abfallkalender"}, + { navigate: true, id: "Buero_Seite_2", onColor: White, name: "Büro Card Grid"} + ] +}; + +//Subpage 1 von Subpages_1 +var Abfall: PageEntities = +{ + "type": "cardEntities", + "heading": "Abfallkalender", + "useColor": true, + "subPage": true, + "items": [ + { id: "alias.0.NSPanel_1.Abfall.event1",icon: "trash-can"}, + { id: "alias.0.NSPanel_1.Abfall.event2",icon: "trash-can"}, + { id: "alias.0.NSPanel_1.Abfall.event3",icon: "trash-can"}, + { id: "alias.0.NSPanel_1.Abfall.event4",icon: "trash-can"} + ] +}; + +//Subpage 2 von Subpages_1 +var Buero_Seite_2: PageGrid = +{ + "type": "cardGrid", + "heading": "Büro 2", + "useColor": true, + "subPage": true, + "items": [ + { id: "alias.0.NSPanel_1.Schreibtischlampe", name: "Schreibtisch"}, + { id: "alias.0.NSPanel_1.Deckenbeleuchtung", name: "Deckenlampe"}, + { id: "alias.0.NSPanel_1.TestFenster", offColor: MSRed, onColor: MSGreen, name: "Büro Fenster"}, + { id: "alias.0.NSPanel_1.Luftreiniger", icon: "power", offColor: MSRed, onColor: MSGreen}, + { id: "alias.0.NSPanel_1.TestBlind", icon: "projector-screen", onColor: White, name: "Beamer"}, + { id: "alias.0.NSPanel_1.Radio.TuneIn", icon: "play", onColor: White} ] }; @@ -112,40 +231,121 @@ var Alexa: PageMedia = "type": "cardMedia", "heading": "Alexa", "useColor": true, + "subPage": false, "items": [{ id: "alias.0.NSPanel_1.Alexa.PlayerBuero" }] }; +var Buero_Themostat: PageThermo = +{ + "type": "cardThermo", + "heading": "Thermostat", + "useColor": true, + "subPage": false, + "items": [{ id: "alias.0.NSPanel_1.Thermostat_Büro" }] +}; + +var Buero_Alarm: PageAlarm = +{ + "type": "cardAlarm", + "heading": "Alarm", + "useColor": true, + "subPage": false, + "items": [{ id: "alias.0.NSPanel_1.Alarm" }] +}; + var button1Page: PageGrid = { "type": "cardGrid", "heading": "Radio", "useColor": true, + "subPage": false, "items": [ - { id: "alias.0.Radio.NJoy" }, - { id: "alias.0.Radio.Delta_Radio" }, - { id: "alias.0.Radio.NDR2" }, + { id: "alias.0.NSPanel_1.Radio.FFN", icon: "radio", name: "FFN", onColor: colorRadio}, + { id: "alias.0.NSPanel_1.Radio.Antenne" , icon: "radio", name: "Antenne Nds.", onColor: colorRadio}, + { id: "alias.0.NSPanel_1.Radio.NDR2", icon: "radio", name: "NDR2", onColor: colorRadio}, + { id: "alias.0.NSPanel_1.Radio.Bob", icon: "radio", name: "Radio BOB", onColor: colorRadio}, + { id: "alias.0.NSPanel_1.Radio.Spotify", icon: "spotify", name: "Party Playlist", onColor: colorSpotify}, + { id: "alias.0.NSPanel_1.Radio.Alexa", icon: "playlist-music", name: "Playlist 2021", onColor: colorAlexa} ] }; - var button2Page: PageEntities = { "type": "cardEntities", - "heading": "Knopf2", + "heading": "Büro", "useColor": true, + "subPage": false, "items": [ - { id: "alias.0.Schlafen" }, - { id: "alias.0.Stern" } + { id: "alias.0.NSPanel_1.Schreibtischlampe"}, + { id: "alias.0.NSPanel_1.Deckenbeleuchtung"} + ] +}; + +//Subpages 2 (+ Info) +var Service: PageEntities = +{ + "type": "cardEntities", + "heading": "NSPanel Service", + "useColor": true, + "subPage": false, + "items": [ + { id: "alias.0.NSPanel_1.NSPanel_AutoUpdate", name: "Auto-Updates" ,icon: "update", offColor: MSRed, onColor: MSGreen}, + { navigate: true, id: "NSPanel_Infos", icon: "information-outline", onColor: White, name: "NSPanel Infos"}, + { navigate: true, id: "NSPanel_Firmware_Updates", icon: "update", onColor: White, name: "Manuelle-Updates"}, + { navigate: true, id: "NSPanel_Einstellungen", icon: "wrench-outline", onColor: White, name: "Einstellungen"} + ] +}; + +//Subpage 1 von Subpages_2 +var NSPanel_Infos: PageEntities = +{ + "type": "cardEntities", + "heading": "NSPanel Infos", + "useColor": true, + "subPage": true, + "items": [ + { id: "alias.0.NSPanel_1.NSPanel_Hardware", name: "Hardware", icon: "memory", offColor: MSYellow, onColor: MSYellow, useColor: true}, + { id: "alias.0.NSPanel_1.NSPanel_ESP_Temp", name: "ESP Temperatur", icon: "thermometer", unit: "°C", offColor: MSYellow, onColor: MSYellow, useColor: true}, + { id: "alias.0.NSPanel_1.NSPanel_UpTime", name: "Uptime", icon: "timeline-clock-outline", offColor: MSYellow, onColor: MSYellow, useColor: true}, + { id: "alias.0.NSPanel_1.NSPanel_RSSI", name: "Wifi-Signal", icon: "signal-distance-variant", unit: "dBm", offColor: MSYellow, onColor: MSYellow, useColor: true} + ] +}; + +//Subpage 2 von Subpages_2 +var NSPanel_Einstellungen: PageEntities = +{ + "type": "cardEntities", + "heading": "Screensaver", + "useColor": true, + "subPage": true, + "items": [ + { id: "alias.0.NSPanel_1.Dimmode_BrightnessDay", name: "Brightness Tag", icon: "brightness-5", offColor: MSYellow, onColor: MSYellow, useColor: true, minValue: 5, maxValue: 10}, + { id: "alias.0.NSPanel_1.Dimmode_BrightnessNight", name: "Brightness Nacht", icon: "brightness-4", offColor: MSYellow, onColor: MSYellow, useColor: true, minValue: 0, maxValue: 4}, + { id: "alias.0.NSPanel_1.Dimmode_HourDay", name: "Stunde Tag", icon: "sun-clock", offColor: MSYellow, onColor: MSYellow, useColor: true, minValue: 0, maxValue: 23}, + { id: "alias.0.NSPanel_1.Dimmode_HourNight", name: "Stunde Nacht", icon: "sun-clock-outline", offColor: MSYellow, onColor: MSYellow, useColor: true, minValue: 0, maxValue: 23} + ] +}; + +//Subpage 3 von Subpages_2 +var NSPanel_Firmware_Updates: PageEntities = +{ + "type": "cardEntities", + "heading": "Firmware-Updates", + "useColor": true, + "subPage": true, + "items": [ + { id: "alias.0.NSPanel_1.Tasmota_Version", name: "Tasmota Firmware", useColor: true}, + { id: "alias.0.NSPanel_1.TFT_Firmware", name: "TFT-Firmware", useColor: true}, ] }; export const config: Config = { - panelRecvTopic: "mqtt.0.tele.WzDisplay.RESULT", - panelSendTopic: "mqtt.0.cmnd.WzDisplay.CustomSend", - firstScreensaverEntity: { ScreensaverEntity: "alias.0.Wetter.HUMIDITY", ScreensaverEntityIcon: "water-percent", ScreensaverEntityText: "Luft", ScreensaverEntityUnitText: "%" }, - secondScreensaverEntity: { ScreensaverEntity: "alias.0.Wetter.PRECIPITATION_CHANCE", ScreensaverEntityIcon: "weather-pouring", ScreensaverEntityText: "Regen", ScreensaverEntityUnitText: "%" }, - thirdScreensaverEntity: { ScreensaverEntity: "alias.0.Batterie.ACTUAL", ScreensaverEntityIcon: "battery-medium", ScreensaverEntityText: "Batterie", ScreensaverEntityUnitText: "%" }, - fourthScreensaverEntity: { ScreensaverEntity: "alias.0.Pv.ACTUAL", ScreensaverEntityIcon: "solar-power", ScreensaverEntityText: "PV", ScreensaverEntityUnitText: "W" }, + 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, @@ -158,28 +358,35 @@ export const config: Config = { defaultColor: Off, temperatureUnit: "°C", pages: [ - //Test_Licht, - Wohnen, - Strom, - Müll, + Buero_Seite_1, + Button_1, + Test_Licht, + Test_Funktionen, + Fenster_1, + Subpages_1, Alexa, - { - "type": "cardThermo", - "heading": "Thermostat", - "useColor": true, - "items": [{ id: "alias.0.WzNsPanel", name: "Wohnzimmer" }] - } + Buero_Themostat, + Buero_Alarm, + Service ], button1Page: button1Page, button2Page: button2Page }; -// _________________________________ End configuration _____________________________________ +// _________________________________ 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; +//Neu für Subpages +var subPage_open = false; + schedule("* * * * *", function () { SendTime(); }); @@ -187,6 +394,197 @@ schedule("0 * * * *", function () { SendDate(); }); +//3:30 Uhr Startup durchführen und aktuelle TFT-Version empfangen +schedule({hour: 3, minute: 30}, function () { + setState(config.panelSendTopic, 'pageType~pageStartup'); +}); + +//Updates vergleichen aktuell alle 30 Minuten +schedule("*/30 * * * *", function () { + get_tasmota_status0(); + get_panel_update_data(); + check_updates(); +}); + +//Mit Start auf Updates checken +setState(config.panelSendTopic, 'pageType~pageStartup'); +get_tasmota_status0() +get_panel_update_data(); +check_updates(); + +//------------------Begin Update Functions +function check_updates() { + //Tasmota-Firmware-Vergleich + if (existsObject(NSPanel_Path + "Tasmota_Firmware.currentVersion") && existsObject(NSPanel_Path + "Tasmota_Firmware.onlineVersion")) { + if (getState(NSPanel_Path + "Tasmota_Firmware.currentVersion").val !== getState(NSPanel_Path + "Tasmota_Firmware.onlineVersion").val) { + if (existsState(NSPanel_Path + "NSPanel_autoUpdate")) { + if (getState(NSPanel_Path + "NSPanel_autoUpdate").val) { + //Tasmota Upgrade durchführen + update_tasmota_firmware() + //Aktuelle Tasmota Version = Online Tasmota Version + setState(NSPanel_Path + "Tasmota_Firmware.currentVersion", getState(NSPanel_Path + "Tasmota_Firmware.onlineVersion").val); + } + } + } else { + if (Debug) console.log("Tasmota-Version auf NSPanel aktuell"); + } + } + //Tasmota-Berry-Driver-Vergleich + if (existsObject(NSPanel_Path + "Berry_Driver.currentVersion") && existsObject(NSPanel_Path + "Berry_Driver.onlineVersion")) { + if (getState(NSPanel_Path + "Berry_Driver.currentVersion").val !== getState(NSPanel_Path + "Berry_Driver.onlineVersion").val) { + if (existsState(NSPanel_Path + "NSPanel_autoUpdate")) { + if (getState(NSPanel_Path + "NSPanel_autoUpdate").val) { + //Tasmota Berry-Driver Update durchführen + update_berry_driver_version() + //Aktuelle Berry-Driver Version = Online Berry-Driver Version + setState(NSPanel_Path + "Berry_Driver.currentVersion", getState(NSPanel_Path + "Berry_Driver.onlineVersion").val); + } + } + } else { + if (Debug) console.log("Berry-Driver auf NSPanel aktuell"); + } + } + //TFT-Firmware-Vergleich + if (existsObject(NSPanel_Path + "Display_Firmware.currentVersion") && existsObject(NSPanel_Path + "Display_Firmware.onlineVersion")) { + if (getState(NSPanel_Path + "Display_Firmware.currentVersion").val !== getState(NSPanel_Path + "Display_Firmware.onlineVersion").val) { + if (existsState(NSPanel_Path + "NSPanel_autoUpdate")) { + if (getState(NSPanel_Path + "NSPanel_autoUpdate").val) { + //TFT-Firmware Update durchführen + update_tft_firmware() + //Aktuelle TFT-Firmware Version = Online TFT-Firmware Version + setState(NSPanel_Path + "Display_Firmware.currentVersion", getState(NSPanel_Path + "Display_Firmware.onlineVersion").val); + } + } + } else { + if (Debug) console.log("Display_Firmware auf NSPanel aktuell"); + } + } +} + +function get_panel_update_data() { + createState(NSPanel_Path + "NSPanel_autoUpdate", false, {read: true, write: true, name: "Auto-Updater", type: "boolean", def: false}); + createState(NSPanel_Path + "NSPanel_ipAddress"); + setIfExists(NSPanel_Path + "NSPanel_ipAddress", get_current_tasmota_ip_address()); + get_online_tasmota_firmware_version(); + get_current_berry_driver_version(); + get_online_berry_driver_version(); + check_version_tft_firmware(); + check_online_display_firmware(); +} + +function get_current_tasmota_ip_address() { + let mqttInfo2 = config.panelRecvTopic.substring(0, config.panelRecvTopic.length - 6) + "INFO2"; + let Tasmota_Info2 = JSON.parse(getState(mqttInfo2).val); + return Tasmota_Info2.Info2.IPAddress; +} + +function get_online_tasmota_firmware_version() { + exec('curl -X GET -k \'https://api.github.com/repositories/80286288/releases/latest\'', function (error, result, stderr){ //GitAPI aufruf für JSON Inhalt von Latest Tasmota Release + var Tasmota_JSON = JSON.parse(result) //JSON Resultat in Variable Schreiben + var TasmotaTagName = Tasmota_JSON.tag_name //JSON nach "tag_name" filtern und in Variable schreiben + var TasmotaVersionOnline = TasmotaTagName.replace(/v/i, ""); //Aus Variable überflüssiges "v" filtern und in Release-Variable schreiben + createState(NSPanel_Path + "Tasmota_Firmware.onlineVersion"); + setIfExists(NSPanel_Path + "Tasmota_Firmware.onlineVersion", TasmotaVersionOnline); + }); +} + +function get_current_berry_driver_version() { + require("request")((['http://',get_current_tasmota_ip_address(),'/cm?cmnd=GetDriverVersion'].join('')), async function (error, response, result) { + createState(NSPanel_Path + "Berry_Driver.currentVersion"); + setIfExists(NSPanel_Path + 'Berry_Driver.currentVersion', getAttr(result, 'nlui_driver_version')); + }); +} + +function get_tasmota_status0() { + require("request")((['http://',get_current_tasmota_ip_address(),'/cm?cmnd=Status0'].join('')), async function (error, response, result) { + createState(NSPanel_Path + "Tasmota_Firmware.currentVersion"); + createState(NSPanel_Path + "Tasmota.Uptime"); + createState(NSPanel_Path + "Tasmota.Version"); + createState(NSPanel_Path + "Tasmota.Hardware"); + createState(NSPanel_Path + "Tasmota.Wifi.AP"); + createState(NSPanel_Path + "Tasmota.Wifi.SSId"); + createState(NSPanel_Path + "Tasmota.Wifi.BSSId"); + createState(NSPanel_Path + "Tasmota.Wifi.Channel"); + createState(NSPanel_Path + "Tasmota.Wifi.Mode"); + createState(NSPanel_Path + "Tasmota.Wifi.RSSI"); + createState(NSPanel_Path + "Tasmota.Wifi.Signal"); + + var Tasmota_JSON = JSON.parse(result) + let tasmoVersion = Tasmota_JSON.StatusFWR.Version.split("("); + setIfExists(NSPanel_Path + "Tasmota_Firmware.currentVersion", tasmoVersion[0]); + setIfExists(NSPanel_Path + "Tasmota.Uptime", Tasmota_JSON.StatusPRM.Uptime); + setIfExists(NSPanel_Path + "Tasmota.Version", Tasmota_JSON.StatusFWR.Version); + setIfExists(NSPanel_Path + "Tasmota.Hardware", Tasmota_JSON.StatusFWR.Hardware); + setIfExists(NSPanel_Path + "Tasmota.Wifi.AP", Tasmota_JSON.StatusSTS.Wifi.AP); + setIfExists(NSPanel_Path + "Tasmota.Wifi.SSId", Tasmota_JSON.StatusSTS.Wifi.SSId); + setIfExists(NSPanel_Path + "Tasmota.Wifi.BSSId", Tasmota_JSON.StatusSTS.Wifi.BSSId); + setIfExists(NSPanel_Path + "Tasmota.Wifi.Channel", Tasmota_JSON.StatusSTS.Wifi.Channel); + setIfExists(NSPanel_Path + "Tasmota.Wifi.Mode", Tasmota_JSON.StatusSTS.Wifi.Mode); + setIfExists(NSPanel_Path + "Tasmota.Wifi.RSSI", Tasmota_JSON.StatusSTS.Wifi.RSSI); + setIfExists(NSPanel_Path + "Tasmota.Wifi.Signal", Tasmota_JSON.StatusSTS.Wifi.Signal); + }); +} + +function get_online_berry_driver_version() { + exec('curl https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be', function (error, result, stderr){ + if (result) { + let BerryDriverVersionOnline = result.substring((result.indexOf("version_of_this_script = ") + 24), result.indexOf("version_of_this_script = ") + 27).replace(/\s+/g, ''); + createState(NSPanel_Path + "Berry_Driver.onlineVersion"); + setIfExists(NSPanel_Path + 'Berry_Driver.onlineVersion', BerryDriverVersionOnline); + } + }); +} + +function check_version_tft_firmware() { + exec('curl -X GET -k \'https://api.github.com/repos/joBr99/nspanel-lovelace-ui/releases/latest\'', function (error, result, stderr){ //GitAPI aufruf für JSON Inhalt von Latest Tasmota Release + var NSPanel_JSON = JSON.parse(result) //JSON Resultat in Variable Schreiben + var NSPanelTagName = NSPanel_JSON.tag_name //created_at; published_at; name ; draft ; prerelease + var NSPanelVersion = NSPanelTagName.replace(/v/i, ""); //Aus Variable überflüssiges "v" filtern und in Release-Variable schreiben + createState(NSPanel_Path + "TFT_Firmware.currentVersion"); + setIfExists(NSPanel_Path + 'TFT_Firmware.currentVersion', NSPanelVersion); + }); +} + +function check_online_display_firmware() { + exec('curl https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/apps/nspanel-lovelace-ui/nspanel-lovelace-ui.py', function (error, result, stderr){ + if (result) { + let desired_display_firmware_version = result.substring((result.indexOf("desired_display_firmware_version =") + 34), result.indexOf("desired_display_firmware_version =") + 38).replace(/\s+/g, ''); + createState(NSPanel_Path + "Display_Firmware.onlineVersion"); + setIfExists(NSPanel_Path + 'Display_Firmware.onlineVersion', desired_display_firmware_version); + } + }); +} + +on({ id: config.panelRecvTopic }, function (obj) { + if (obj.state.val.startsWith('\{"CustomRecv":')) { + var json = JSON.parse(obj.state.val); + var split = json.CustomRecv.split(","); + if (split[0] == "event" && split[1] == "startup") { + createState(NSPanel_Path + 'Display_Firmware.currentVersion',{ type:'string'}); + createState(NSPanel_Path + 'NSPanel_Version',{ type:'string'}); + setIfExists(NSPanel_Path + 'Display_Firmware.currentVersion',split[2]); + setIfExists(NSPanel_Path + 'NSPanel_Version',split[3]); + } + } +}); + +function update_berry_driver_version() { + require("request")((['http://',get_current_tasmota_ip_address(),'/cm?cmnd=Backlog UpdateDriverVersion https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be; Restart 1'].join('')), async function (error, response, result) { + }); +} + +function update_tft_firmware() { + require("request")((['http://',get_current_tasmota_ip_address(),'/cm?cmnd=FlashNextion http://nspanel.pky.eu/lui.tft'].join('')), async function (error, response, result) { + }); +} + +function update_tasmota_firmware() { + require("request")((['http://',get_current_tasmota_ip_address(),'/cm?cmnd=Upgrade 1'].join('')), async function (error, response, result) { + }); +} + +//------------------End Update Functions + // Only monitor the extra nodes if present var updateArray: string[] = []; if (config.firstScreensaverEntity !== null && config.firstScreensaverEntity.ScreensaverEntity != null && existsState(config.firstScreensaverEntity.ScreensaverEntity)) { @@ -201,12 +599,12 @@ if (config.thirdScreensaverEntity !== null && config.thirdScreensaverEntity.Scre 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); @@ -220,6 +618,7 @@ function SendToPanel(val: Payload | Payload[]): void { if (Array.isArray(val)) { val.forEach(function (id, i) { setState(config.panelSendTopic, id.payload); + if (Debug) console.log(id.payload); }); } else @@ -238,7 +637,7 @@ function HandleMessage(typ: string, method: string, page: number, words: Arraypage)); break; + case "cardAlarm": + SendToPanel(GenerateAlarmPage(page)); + break; } } function HandleHardwareButton(method: string): void { - let page: (PageThermo | PageMedia | PageEntities | PageGrid); + let page: (PageThermo | PageMedia | PageAlarm | PageEntities | PageGrid); if (config.button1Page !== null && method == "button1") { page = config.button1Page; pageId = -1; @@ -324,6 +726,20 @@ function SendTime(): void { min = "0" + d.getMinutes().toString(); } SendToPanel({ payload: "time~" + hr + ":" + min }); + + ScreensaverDimmode(); +} + +function ScreensaverDimmode() { + if (timeDimMode.dimmodeOn != undefined ? timeDimMode.dimmodeOn : false) { + if (compareTime(timeDimMode.timeNight != undefined ? timeDimMode.timeNight : "23:00", timeDimMode.timeDay != undefined ? timeDimMode.timeDay : "06:00", "not between", null)) { + SendToPanel({ payload: "dimmode~" + timeDimMode.brightnessDay}); + } else { + SendToPanel({ payload: "dimmode~" + timeDimMode.brightnessNight}); + } + } else { + SendToPanel({ payload: "dimmode~" + config.dimmode }); + } } function GenerateEntitiesPage(page: PageEntities): Payload[] { @@ -346,6 +762,9 @@ function GeneratePageElements(page: Page): string { case "cardThermo": maxItems = 1; break; + case "cardAlarm": + maxItems = 1; + break; case "cardMedia": maxItems = 1; break; @@ -356,14 +775,26 @@ function GeneratePageElements(page: Page): string { maxItems = 6; break; } - let pageData = "entityUpd~" + page.heading + "~" + GetNavigationString(pageId) + + let pageData = "entityUpd~" + page.heading + "~" + GetNavigationString(pageId); + +//--------------------------------------Subpage---------------- + if (page.subPage) { + subPage_open = true; + pageData = "entityUpd~" + page.heading + "~" + "1|0"; + } +//--------------------------------------------------------- for (let index = 0; index < maxItems; index++) { if (page.items[index] !== undefined) { pageData += CreateEntity(page.items[index], index + 1, page.useColor); } +/* else { - pageData += CreateEntity({ id: "delete" }, index + 1); + pageData += CreateEntity({ id: "delete" }, index + 1); + //muss das wirklich? Wo erforderlich wird es mitgegeben! + } +*/ } return pageData; } @@ -375,11 +806,21 @@ function CreateEntity(pageItem: PageItem, placeId: number, useColors: boolean = } var name: string; var type: string; + // ioBroker - if (existsObject(pageItem.id)) { + if (existsObject(pageItem.id) || pageItem.navigate === true) { + var iconColor = rgb_dec565(config.defaultColor); + + if (pageItem.navigate) { + type = "button"; + iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("gesture-tap-button"); + iconColor = GetIconColor(pageItem, true, useColors); + let buttonText = pageItem.buttonText !== undefined ? pageItem.buttonText : "PRESS"; + return "~" + type + "~" + "navigate." + pageItem.id + "~" + iconId + "~" + iconColor + "~" + pageItem.name + "~" + buttonText; + } + 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; @@ -389,13 +830,15 @@ function CreateEntity(pageItem: PageItem, placeId: number, useColors: boolean = val = getState(pageItem.id + ".SET").val; RegisterEntityWatcher(pageItem.id + ".SET"); } - var iconColor = rgb_dec565(config.defaultColor); + + name = pageItem.name !== undefined ? pageItem.name : o.common.name.de switch (o.common.role) { - case "socket": + 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"); + 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") { @@ -406,7 +849,10 @@ function CreateEntity(pageItem: PageItem, placeId: number, useColors: boolean = } return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + optVal; - +/*--------------------------------------------------------- + case "wled": + type = "number" +----------------------------------------------------------*/ case "hue": type = "light" @@ -428,7 +874,7 @@ function CreateEntity(pageItem: PageItem, placeId: number, useColors: boolean = let huecolor = hsv2rgb(getState(pageItem.id + ".HUE").val,1,1); let 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); + //RegisterDetailEntityWatcher(id + ".HUE"); } } @@ -508,7 +954,7 @@ function CreateEntity(pageItem: PageItem, placeId: number, useColors: boolean = } return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + optVal; - + case "dimmer": type = "light" iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("lightbulb"); @@ -527,15 +973,15 @@ function CreateEntity(pageItem: PageItem, placeId: number, useColors: boolean = } 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")) { @@ -552,12 +998,19 @@ function CreateEntity(pageItem: PageItem, placeId: number, useColors: boolean = RegisterEntityWatcher(pageItem.id + ".ACTUAL"); } return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + windowState; - + case "info": + case "humidity": + + case "temperature": + case "value.temperature": + case "value.humidity": - case "sensor.door": + + case "sensor.door": + case "sensor.window": case "thermostat": @@ -584,18 +1037,92 @@ function CreateEntity(pageItem: PageItem, placeId: number, useColors: boolean = return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + optVal + " " + unit; + case "buttonSensor": 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; + let buttonText = pageItem.buttonText !== undefined ? pageItem.buttonText : "PRESS"; + return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + buttonText; + + case "lock": + type = "button"; + iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("lock"); + iconColor = GetIconColor(pageItem, true, useColors); + + if (existsState(pageItem.id + ".ACTUAL")) { + if (getState(pageItem.id + ".ACTUAL").val) { + iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("lock"); + iconColor = GetIconColor(pageItem, true, useColors); + var lockState = "UNLOCK" + } else { + iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("lock-open-variant"); + iconColor = GetIconColor(pageItem, false, useColors); + var lockState = "LOCK" + } + RegisterEntityWatcher(pageItem.id + ".ACTUAL"); + } + + return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + lockState; + + case "slider": + type = "number"; + iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("plus-minus-variant"); + if (existsState(pageItem.id + ".SET")) { + val = getState(pageItem.id + ".SET").val; + RegisterEntityWatcher(pageItem.id + ".SET"); + } + if (existsState(pageItem.id + ".ACTUAL")) { + val = getState(pageItem.id + ".ACTUAL").val; + RegisterEntityWatcher(pageItem.id + ".ACTUAL"); + } + + iconColor = GetIconColor(pageItem, false, useColors) + + return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + val + "|" + pageItem.minValue + "|" + pageItem.maxValue; + + case "volumeGroup": + case "volume": + type = "number"; + if (existsState(pageItem.id + ".SET")) { + val = getState(pageItem.id + ".SET").val; + RegisterEntityWatcher(pageItem.id + ".SET"); + } + if (existsState(pageItem.id + ".ACTUAL")) { + val = getState(pageItem.id + ".ACTUAL").val; + RegisterEntityWatcher(pageItem.id + ".ACTUAL"); + } + + iconColor = GetIconColor(pageItem, false, useColors) + if (existsState(pageItem.id + ".MUTE")) { + getState(pageItem.id + ".MUTE").val ? iconColor = GetIconColor(pageItem, false, useColors) : iconColor = GetIconColor(pageItem, true, useColors); + RegisterEntityWatcher(pageItem.id + ".MUTE"); + } + + if (val > 0 && val <= 33 && !getState(pageItem.id + ".MUTE").val) { + iconId = Icons.GetIcon("volume-low"); + } else if (val > 33 && val <= 66 && !getState(pageItem.id + ".MUTE").val) { + iconId = Icons.GetIcon("volume-medium"); + } else if (val > 66 && val <= 100 && !getState(pageItem.id + ".MUTE").val) { + iconId = Icons.GetIcon("volume-high"); + } else { + iconId = Icons.GetIcon("volume-mute"); + } + + return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + val + "|" + pageItem.minValue + "|" + pageItem.maxValue; + + 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~~~~~" } @@ -616,7 +1143,7 @@ function GetIconColor(pageItem: PageItem, value: (boolean | number), useColors: )); } - if ((pageItem.useColor || useColors) && ((typeof (value) === "boolean" && value) || value > (pageItem.minValueBrightness !== undefined ? pageItem.minValueBrightness : 0) || value > (pageItem.minValue !== undefined ? pageItem.minValue : 0))) { + 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) } @@ -637,7 +1164,6 @@ function RegisterEntityWatcher(id: string): void { })) } - function RegisterDetailEntityWatcher(id: string, pageItem: PageItem, type: string): void { if (subscriptions.hasOwnProperty(id)) { return; @@ -683,15 +1209,15 @@ function GenerateThermoPage(page: PageThermo): Payload[] { let status = "" if (existsState(id + ".MODE")) status = getState(id + ".MODE").val; - let minTemp = 180 //Min Temp 5°C + let minTemp = 50 //Min Temp 5°C let maxTemp = 300 //Max Temp 30°C let stepTemp = 5 - //Dynamically add attributes if defined in alias + //Attribute hinzufügen, wenn im Alias definiert var thermButton = 0; let i_list = Array.prototype.slice.apply($('[state.id="' + id + '.*"]')); if ((i_list.length - 3) != 0) { - console.log(i_list.length -3) + if (Debug) console.log(i_list.length -3); if ((i_list.length -3)%2 == 0) { if ((i_list.length - 3) == 2) { thermButton = 6; @@ -715,92 +1241,94 @@ function GenerateThermoPage(page: PageThermo): Payload[] { } for (let i_index in i_list) { let thermostatState = i_list[i_index].split('.'); - if (thermostatState[thermostatState.length-1] != "SET" && thermostatState[thermostatState.length-1] != "ACTUAL" && thermostatState[thermostatState.length-1] != "MODE") { + if (thermostatState[thermostatState.length-1] != "SET" && + thermostatState[thermostatState.length-1] != "ACTUAL" && + thermostatState[thermostatState.length-1] != "MODE") { i++; switch (thermostatState[thermostatState.length-1]) { case "HUMIDITY": if (existsState(id + ".HUMIDITY") && getState(id + ".HUMIDITY").val != null) { if (parseInt(getState(id + ".HUMIDITY").val) < 40) { - bt[i-1] = Icons.GetIcon("water-percent") + "~65504~1~bt" + (i-1) + "~"; + bt[i-1] = Icons.GetIcon("water-percent") + "~65504~1~" + "HUMIDITY" + "~"; } else if (parseInt(getState(id + ".HUMIDITY").val) < 30) { - bt[i-1] = Icons.GetIcon("water-percent") + "~63488~1~bt" + (i-1) + "~"; + bt[i-1] = Icons.GetIcon("water-percent") + "~63488~1~" + "HUMIDITY" + "~"; } else if (parseInt(getState(id + ".HUMIDITY").val) > 65) { - bt[i-1] = Icons.GetIcon("water-percent") + "~65504~1~bt" + (i-1) + "~"; + bt[i-1] = Icons.GetIcon("water-percent") + "~65504~1~" + "HUMIDITY" + "~"; } else if (parseInt(getState(id + ".HUMIDITY").val) > 75) { - bt[i-1] = Icons.GetIcon("water-percent") + "~63488~1~bt" + (i-1) + "~"; + bt[i-1] = Icons.GetIcon("water-percent") + "~63488~1~" + "HUMIDITY" + "~"; } } else i--; break; case "LOWBAT": if (existsState(id + ".LOWBAT") && getState(id + ".LOWBAT").val != null) { if (getState(id + ".LOWBAT").val) { - bt[i-1] = Icons.GetIcon("battery-low") + "~63488~1~bt" + (i-1) + "~"; + bt[i-1] = Icons.GetIcon("battery-low") + "~63488~1~" + "LOWBAT" + "~"; } else { - bt[i-1] = Icons.GetIcon("battery-high") + "~2016~1~bt" + (i-1) + "~"; + bt[i-1] = Icons.GetIcon("battery-high") + "~2016~1~" + "LOWBAT" + "~"; } } else i--; break; case "MAINTAIN": if (existsState(id + ".MAINTAIN") && getState(id + ".MAINTAIN").val != null) { if (getState(id + ".MAINTAIN").val >> .1) { - bt[i-1] = Icons.GetIcon("fire") + "~60897~1~bt" + (i-1) + "~"; + bt[i-1] = Icons.GetIcon("fire") + "~60897~1~" + "MAINTAIN" + "~"; } else { - bt[i-1] = Icons.GetIcon("fire") + "~33840~0~bt" + (i-1) + "~"; + bt[i-1] = Icons.GetIcon("fire") + "~33840~0~" + "MAINTAIN" + "~"; } } else i--; break; case "UNREACH": if (existsState(id + ".UNREACH") && getState(id + ".UNREACH").val != null) { if (getState(id + ".UNREACH").val) { - bt[i-1] = Icons.GetIcon("wifi-off") + "~63488~1~bt" + (i-1) + "~"; + bt[i-1] = Icons.GetIcon("wifi-off") + "~63488~1~" + "UNREACH" + "~"; } else { - bt[i-1] = Icons.GetIcon("wifi") + "~2016~1~bt" + (i-1) + "~"; + bt[i-1] = Icons.GetIcon("wifi") + "~2016~1~" + "UNREACH" + "~"; } } else i--; break; case "POWER": if (existsState(id + ".POWER") && getState(id + ".POWER").val != null) { if (getState(id + ".POWER").val) { - bt[i-1] = Icons.GetIcon("power-standby") + "~2016~1~bt" + (i-1) + "~"; + bt[i-1] = Icons.GetIcon("power-standby") + "~2016~1~" + "POWER" + "~"; } else { - bt[i-1] = Icons.GetIcon("power-standby") + "~33840~1~bt" + (i-1) + "~"; + bt[i-1] = Icons.GetIcon("power-standby") + "~33840~1~" + "POWER" + "~"; } } else i--; break; case "ERROR": if (existsState(id + ".ERROR") && getState(id + ".ERROR").val != null) { if (getState(id + ".ERROR").val) { - bt[i-1] = Icons.GetIcon("alert-circle") + "~63488~1~bt" + (i-1) + "~"; + bt[i-1] = Icons.GetIcon("alert-circle") + "~63488~1~" + "ERROR" + "~"; } else { - bt[i-1] = Icons.GetIcon("alert-circle") + "~33840~1~bt" + (i-1) + "~"; + bt[i-1] = Icons.GetIcon("alert-circle") + "~33840~1~" + "ERROR" + "~"; } } else i--; break; case "WORKING": if (existsState(id + ".WORKING") && getState(id + ".WORKING").val != null) { if (getState(id + ".WORKING").val) { - bt[i-1] = Icons.GetIcon("briefcase-check") + "~2016~1~bt" + (i-1) + "~"; + bt[i-1] = Icons.GetIcon("briefcase-check") + "~2016~1~" + "WORKING" + "~"; } else { - bt[i-1] = Icons.GetIcon("briefcase-check") + "~33840~1~bt" + (i-1) + "~"; + bt[i-1] = Icons.GetIcon("briefcase-check") + "~33840~1~" + "WORKING" + "~"; } } else i--; break; case "BOOST": if (existsState(id + ".BOOST") && getState(id + ".BOOST").val != null) { if (getState(id + ".BOOST").val) { - bt[i-1] = Icons.GetIcon("fast-forward-60") + "~2016~1~bt" + (i-1) + "~"; + bt[i-1] = Icons.GetIcon("fast-forward-60") + "~2016~1~" + "BOOST" + "~"; } else { - bt[i-1] = Icons.GetIcon("fast-forward-60") + "~33840~1~bt" + (i-1) + "~"; + bt[i-1] = Icons.GetIcon("fast-forward-60") + "~33840~1~" + "BOOST" + "~"; } } else i--; break; case "PARTY": if (existsState(id + ".PARTY") && getState(id + ".PARTY").val != null) { if (getState(id + ".PARTY").val) { - bt[i-1] = Icons.GetIcon("party-popper") + "~2016~1~bt" + (i-1) + "~"; + bt[i-1] = Icons.GetIcon("party-popper") + "~2016~1~" + "PARTY" + "~"; } else { - bt[i-1] = Icons.GetIcon("party-popper") + "~33840~1~bt" + (i-1) + "~"; + bt[i-1] = Icons.GetIcon("party-popper") + "~33840~1~" + "PARTY" + "~"; } } else i--; break; @@ -821,6 +1349,7 @@ function GenerateThermoPage(page: PageThermo): Payload[] { out_msgs.push({ payload: "entityUpd~" + name + "~" + GetNavigationString(pageId) + "~" + id + "~" + currentTemp + "~" + destTemp + "~" + status + "~" + minTemp + "~" + maxTemp + "~" + stepTemp + "~" +icon_res}) } + if (Debug) console.log(out_msgs); return out_msgs } @@ -829,7 +1358,8 @@ function GenerateMediaPage(page: PageMedia): Payload[] { var out_msgs: Array = []; out_msgs.push({ payload: "pageType~cardMedia" }); if (existsObject(id)) { - let name = getState(id + ".ALBUM").val; + + 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; @@ -843,7 +1373,6 @@ function GenerateMediaPage(page: PageMedia): Payload[] { 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 @@ -852,14 +1381,14 @@ function GenerateMediaPage(page: PageMedia): Payload[] { 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 && + 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 + "?"; @@ -868,19 +1397,91 @@ function GenerateMediaPage(page: PageMedia): Payload[] { } speakerlist = speakerlist.substring(0,speakerlist.length-1); //-------------------------------------------------------------------------------------------------------------- - out_msgs.push({ payload: "entityUpd~" + - name + "~" + - id + "~" + - id + "~" + //???? - media_icon + "~" + - title + "~" + - author + "~" + - volume + "~" + - iconplaypause + "~" + - currentSpeaker + "~" + - speakerlist + "~" + - onoffbutton}); + + out_msgs.push({ payload: "entityUpd~" + //entityUpd + name + "~" + //heading + GetNavigationString(pageId) + "~" + //navigation + id + "~" + //internalNameEntiy + media_icon + "~" + //icon + title + "~" + //title + author + "~" + //author + volume + "~" + //volume + iconplaypause + "~" + //playpauseicon + currentSpeaker + "~" + //currentSpeaker + speakerlist + "~" + //speakerList-seperated-by-? + onoffbutton}); //On/Off Button Color } + if (Debug) console.log(out_msgs); + return out_msgs +} + +function GenerateAlarmPage(page: PageAlarm): Payload[] { + var id = page.items[0].id + var out_msgs: Array = []; + 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 = "disable"; //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 = "disable"; //flashing* + } + + flashing = "disable" + var entityState = "arming" + if (entityState == "arming" || entityState == "pending") { + iconcolor = rgb_dec565({ red: 243, green: 179, blue: 0 }); + icon = Icons.GetIcon("shield"); + flashing = "enable" + } + if (entityState == "triggered") { + iconcolor = rgb_dec565({ red: 223, green: 76, blue: 30 }); + icon = Icons.GetIcon("bell-ring"); + flashing = "enable" + } + + out_msgs.push({ payload: "entityUpd~" + //entityUpd~* + id + "~" + //internalNameEntity*~* + GetNavigationString(pageId) + "~" + //navigation*~* --> hiddenCards + 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* + + if (Debug) console.log(out_msgs); + return out_msgs } @@ -914,6 +1515,15 @@ function HandleButtonEvent(words): void { let id = words[2] let buttonAction = words[3]; + if (Debug) { + console.log(words[0] + " - " + words[1] + " - " + words[2] + " - " + words[3] + " - " + words[4] + " - PageId: " + pageId); + } + + if ((words[2]).substring(0, 8) == "navigate"){ + GeneratePage(eval((words[2]).substring(9, (words[2]).length))); + return; + } + switch (buttonAction) { case "bNext": var pageNum = ((pageId + 1) % config.pages.length); @@ -926,22 +1536,31 @@ function HandleButtonEvent(words): void { pageId = Math.abs(pageNum); UnsubscribeWatcher(); GeneratePage(config.pages[pageId]); + +//-------------Subpage + if (subPage_open) { + subPage_open = false; + HandleButtonEvent(['event','buttonPress2','cardEntities','bNext']) + } +//-------------------------------- break; case "bExit": if (config.screenSaverDoubleClick) { - if (words[4] == 2) + if (words[4] == 2) { GeneratePage(config.pages[pageId]); - } - else + } + } else { GeneratePage(config.pages[pageId]); + } break; case "OnOff": if (existsObject(id)) { var action = false if (words[4] == "1") - action = true + action = true; let o = getObject(id) switch (o.common.role) { + case "socket": case "light": setIfExists(id + ".SET", action); break; @@ -968,13 +1587,20 @@ function HandleButtonEvent(words): void { setIfExists(id + ".CLOSE", true) break; case "button": - toggleState(id + ".SET") ? true : toggleState(id + ".ON_SET") + let obj = getObject(id); + switch (obj.common.role) { + case "lock": + case "button": + toggleState(id + ".SET") ? true : toggleState(id + ".ON_SET"); + break; + case "buttonSensor": + toggleState(id + ".ACTUAL"); + } break; case "positionSlider": (function () {if (timeoutSlider) {clearTimeout(timeoutSlider); timeoutSlider = null;}})(); timeoutSlider = setTimeout(async function () { setIfExists(id + ".SET", parseInt(words[4])) ? true : setIfExists(id + ".ACTUAL", parseInt(words[4])); - //console.log("PositionSlider feuert"); }, 250); break; case "brightnessSlider": @@ -983,14 +1609,12 @@ function HandleButtonEvent(words): void { if (existsObject(id)) { let o = getObject(id); let pageItem = config.pages[pageId].items.find(e => e.id === id); - //console.log(o.common.role); 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])); setIfExists(id + ".SET", parseInt(words[4])) ? true : setIfExists(id + ".ACTUAL", parseInt(words[4])); } break; @@ -1040,6 +1664,9 @@ function HandleButtonEvent(words): void { setIfExists(id + ".RGB", ConvertRGBtoHex(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; @@ -1048,7 +1675,7 @@ function HandleButtonEvent(words): void { setIfExists(id + ".PAUSE", true) } else { setIfExists(id + ".PLAY", true) - } + } break; case "media-next": setIfExists(id + ".NEXT", true) @@ -1071,13 +1698,34 @@ function HandleButtonEvent(words): void { case "media-OnOff": setIfExists(id + ".STOP", true) break; - case "tempUpd": - setIfExists(id + ".SET", parseInt(words[4]) / 10) + case "hvac_action": + if (words[4] == "POWER" || words[4] == "BOOST" || words[4] == "PARTY") { + setIfExists(words[2] + "." + words[4], !getState(words[2] + "." + words[4]).val) + } break; + case "number-set": + setIfExists(id + ".SET", parseInt(words[4])) ? true : setIfExists(id + ".ACTUAL", parseInt(words[4])); + 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: @@ -1104,7 +1752,7 @@ function GenerateDetailPage(type: string, pageItem: PageItem): Payload[] { if (type == "popupLight") { let switchVal = "0" let brightness = 0; - if (o.common.role == "light") { + if (o.common.role == "light" || o.common.role == "socket") { if (existsState(id + ".GET")) { val = getState(id + ".GET").val; RegisterDetailEntityWatcher(id + ".GET", pageItem, type); @@ -1114,12 +1762,25 @@ function GenerateDetailPage(type: string, pageItem: PageItem): Payload[] { RegisterDetailEntityWatcher(id + ".SET", pageItem, type); } + icon = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : o.common.role == "socket" ? Icons.GetIcon("power-socket-de") : Icons.GetIcon("lightbulb"); + if (val) { switchVal = "1"; - iconColor = GetIconColor(pageItem, true, false); + iconColor = GetIconColor(pageItem, true, true); + } else { + iconColor = GetIconColor(pageItem, false, true); } - out_msgs.push({ payload: "entityUpdateDetail~" + icon + "~" + + iconColor + "~" + switchVal + ",disable,disable,disable" + "~Color~Temperature~Brightness" }) + out_msgs.push({ payload: "entityUpdateDetail" + "~" //entityUpdateDetail + + icon + "~" //iconId + + iconColor + "~" //iconColor + + switchVal + "~" //buttonState + + "disable" + "~" //sliderBrightnessPos + + "disable" + "~" //sliderColorTempPos + + "disable" + "~" //colorMode + + "Color" + "~" //Color-Bezeichnung + + "Temperature" + "~" //Temperature-Bezeichnung + + "Brightness" }) //Brightness-Bezeichnung } //Dimmer @@ -1156,12 +1817,20 @@ function GenerateDetailPage(type: string, pageItem: PageItem): Payload[] { } RegisterDetailEntityWatcher(id + ".ACTUAL", pageItem, type); - - let colorTemp = "disable" - let colorMode = "disable" - out_msgs.push({ payload: "entityUpdateDetail~" + icon + "~" + iconColor + "~" + switchVal + "~" + brightness + "~" + colorTemp + "~" + colorMode + "~Color~Temperature~Brightness" }) + out_msgs.push({ payload: "entityUpdateDetail" + "~" //entityUpdateDetail + + icon + "~" //iconId + + iconColor + "~" //iconColor + + switchVal + "~" //buttonState + + brightness + "~" //sliderBrightnessPos + + "disable" + "~" //sliderColorTempPos + + "disable" + "~" //colorMod + + "Color" + "~" //Color-Bezeichnung + + "Temperature" + "~" //Temperature-Bezeichnung + + "Brightness" }) //Brightness-Bezeichnung + } + //HUE-Licht if (o.common.role == "hue") { @@ -1213,7 +1882,16 @@ function GenerateDetailPage(type: string, pageItem: PageItem): Payload[] { console.warn("Alias-Datenpunkt: " + id + ".TEMPERATURE could not be read"); } - out_msgs.push({ payload: "entityUpdateDetail~" + icon + "~" + iconColor + "~" + switchVal + "~" + brightness + "~" + colorTemp + "~" + colorMode + "~Color~Temperature~Brightness" }) + out_msgs.push({ payload: "entityUpdateDetail" + "~" //entityUpdateDetail + + icon + "~" //iconId + + iconColor + "~" //iconColor + + switchVal + "~" //buttonState + + brightness + "~" //sliderBrightnessPos + + colorTemp + "~" //sliderColorTempPos + + colorMode + "~" //colorMode (if hue-alias without hue-datapoint, then disable) + + "Color" + "~" //Color-Bezeichnung + + "Temperature" + "~" //Temperature-Bezeichnung + + "Brightness" }) //Brightness-Bezeichnung } //RGB-Licht @@ -1266,7 +1944,16 @@ function GenerateDetailPage(type: string, pageItem: PageItem): Payload[] { console.warn("Alias-Datenpunkt: " + id + ".TEMPERATURE could not be read"); } - out_msgs.push({ payload: "entityUpdateDetail~" + icon + "~" + iconColor + "~" + switchVal + "~" + brightness + "~" + colorTemp + "~" + colorMode + "~Color~Temperature~Brightness" }) + out_msgs.push({ payload: "entityUpdateDetail" + "~" //entityUpdateDetail + + icon + "~" //iconId + + iconColor + "~" //iconColor + + switchVal + "~" //buttonState + + brightness + "~" //sliderBrightnessPos + + colorTemp + "~" //sliderColorTempPos + + colorMode + "~" //colorMode (if hue-alias without hue-datapoint, then disable) + + "Color" + "~" //Color-Bezeichnung + + "Temperature" + "~" //Temperature-Bezeichnung + + "Brightness" }) //Brightness-Bezeichnung } //RGB-Licht-einzeln (HEX) @@ -1323,7 +2010,16 @@ function GenerateDetailPage(type: string, pageItem: PageItem): Payload[] { console.warn("Alias-Datenpunkt: " + id + ".TEMPERATURE could not be read"); } - out_msgs.push({ payload: "entityUpdateDetail~" + icon + "~" + iconColor + "~" + switchVal + "~" + brightness + "~" + colorTemp + "~" + colorMode + "~Color~Temperature~Brightness" }) + out_msgs.push({ payload: "entityUpdateDetail" + "~" //entityUpdateDetail + + icon + "~" //iconId + + iconColor + "~" //iconColor + + switchVal + "~" //buttonState + + brightness + "~" //sliderBrightnessPos + + colorTemp + "~" //sliderColorTempPos + + colorMode + "~" //colorMode (if hue-alias without hue-datapoint, then disable) + + "Color" + "~" //Color-Bezeichnung + + "Temperature" + "~" //Temperature-Bezeichnung + + "Brightness" }) //Brightness-Bezeichnung) } //Farbtemperatur @@ -1368,12 +2064,22 @@ function GenerateDetailPage(type: string, pageItem: PageItem): Payload[] { console.warn("Alias-Datenpunkt: " + id + ".TEMPERATURE could not be read"); } - out_msgs.push({ payload: "entityUpdateDetail~" + icon + "~" + iconColor + "~" + switchVal + "~" + brightness + "~" + colorTemp + "~" + colorMode + "~Color~Temperature~Brightness" }) + out_msgs.push({ payload: "entityUpdateDetail" + "~" //entityUpdateDetail + + icon + "~" //iconId + + iconColor + "~" //iconColor + + switchVal + "~" //buttonState + + brightness + "~" //sliderBrightnessPos + + colorTemp + "~" //sliderColorTempPos + + colorMode + "~" //colorMode (if hue-alias without hue-datapoint, then disable) + + "Color" + "~" //Color-Bezeichnung + + "Temperature" + "~" //Temperature-Bezeichnung + + "Brightness" }) //Brightness-Bezeichnung } } if (type == "popupShutter") { + icon = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("window-open"); if (existsState(id + ".ACTUAL")) { val = getState(id + ".ACTUAL").val; RegisterDetailEntityWatcher(id + ".ACTUAL", pageItem, type); @@ -1381,7 +2087,10 @@ function GenerateDetailPage(type: string, pageItem: PageItem): Payload[] { val = getState(id + ".SET").val; RegisterDetailEntityWatcher(id + ".SET", pageItem, type); } - out_msgs.push({ payload: "entityUpdateDetail~" + val + "~~Position" }) + out_msgs.push({ payload: "entityUpdateDetail" + "~" //entityUpdateDetail + + val + "~" //Shutterposition + + "" + "~" + + "Position"}) //Position-Bezeichnung } } return out_msgs @@ -1407,15 +2116,16 @@ function HandleScreensaver(): void { 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++) { @@ -1432,7 +2142,7 @@ function HandleScreensaverUpdate(): void { payloadString += GetScreenSaverEntityString(config.thirdScreensaverEntity); payloadString += GetScreenSaverEntityString(config.fourthScreensaverEntity); } - +/*-------------------------------------------------------------------------------------------------------------------------------------*/ SendToPanel({ payload: payloadString }); } } @@ -1522,6 +2232,21 @@ function GetAccuWeatherIcon(icon: number): string { } } +//------------------Begin Read Internal Sensor Data +on({ id: config.panelRecvTopic.substring(0, config.panelRecvTopic.length - 6) + "SENSOR" }, function (obj) { + let mqttSensor = config.panelRecvTopic.substring(0, config.panelRecvTopic.length - 6) + "SENSOR"; + let Tasmota_Sensor = JSON.parse(getState(mqttSensor).val); + createState(NSPanel_Path + 'Sensor.Time'); + createState(NSPanel_Path + 'Sensor.TempUnit'); + createState(NSPanel_Path + 'Sensor.ANALOG.Temperature'); + createState(NSPanel_Path + 'Sensor.ESP32.Temperature'); + setIfExists(NSPanel_Path + 'Sensor.Time', Tasmota_Sensor.Time); + setIfExists(NSPanel_Path + 'Sensor.TempUnit', "°" + Tasmota_Sensor.TempUnit); + setIfExists(NSPanel_Path + 'Sensor.ANALOG.Temperature', Tasmota_Sensor.ANALOG.Temperature1); + setIfExists(NSPanel_Path + 'Sensor.ESP32.Temperature', Tasmota_Sensor.ESP32.Temperature); +}); +//------------------End Read Internal Sensor Data + function GetBlendedColor(percentage: number): RGB { if (percentage < 50) return Interpolate(config.defaultOffColor, config.defaultOnColor, percentage / 50.0); @@ -1543,6 +2268,10 @@ 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; } @@ -1556,6 +2285,12 @@ function ConvertRGBtoHex(red: number, green: number, blue: Number) { return "#" + ColorToHex(red) + ColorToHex(green) + ColorToHex(blue); } +/* 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; @@ -1566,29 +2301,37 @@ function hsv2rgb(hue: number, saturation: number, value: number) { 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 { +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; @@ -1600,8 +2343,10 @@ function pos_to_color(x: number, y: number): RGB { } else { sat = r; } + var hsv = rad2deg(Math.atan2(y, x)); var rgb = hsv2rgb(hsv,sat,1); + return { red: Math.round(rgb[0]), green: Math.round(rgb[1]), blue: Math.round(rgb[2]) }; } @@ -1619,14 +2364,15 @@ type Page = { type: string, heading: string, items: PageItem[], - useColor: boolean + useColor: boolean, + subPage: boolean, }; interface PageEntities extends Page { type: "cardEntities", items: PageItem[], - }; + interface PageGrid extends Page { type: "cardGrid", items: PageItem[], @@ -1642,6 +2388,11 @@ interface PageMedia extends Page { items: PageItem[], }; +interface PageAlarm extends Page { + type: "cardAlarm", + items: PageItem[], +}; + type PageItem = { id: string, icon: (string | undefined), @@ -1656,7 +2407,17 @@ type PageItem = { minValue: (number | undefined), maxValue: (number | undefined), name: (string | undefined), - unit: (string | undefined) + buttonText: (string | undefined), + unit: (string | undefined), + navigate: (boolean | undefined), +} + +type DimMode = { + dimmodeOn: (boolean | undefined), + brightnessDay: (number | undefined), + brightnessNight: (number | undefined), + timeDay: (string | undefined), + timeNight: (string | undefined) } type Config = { @@ -1678,9 +2439,9 @@ type Config = { defaultColor: RGB, defaultOnColor: RGB, defaultOffColor: RGB, - pages: (PageThermo | PageMedia | PageEntities | PageGrid)[], - button1Page: (PageThermo | PageMedia | PageEntities | PageGrid | null), - button2Page: (PageThermo | PageMedia | PageEntities | PageGrid | null), + pages: (PageThermo | PageMedia | PageAlarm | PageEntities | PageGrid)[], + button1Page: (PageThermo | PageMedia | PageAlarm | PageEntities | PageGrid | null), + button2Page: (PageThermo | PageMedia | PageAlarm | PageEntities | PageGrid | null), }; type ScreenSaverElement = { From e7d96e04389a9ef54a24ab3688f118c0f4eb5714 Mon Sep 17 00:00:00 2001 From: Armilar <102996011+Armilar@users.noreply.github.com> Date: Mon, 9 May 2022 11:56:00 +0200 Subject: [PATCH 02/23] Update NsPanelTs.ts --- ioBroker/NsPanelTs.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ioBroker/NsPanelTs.ts b/ioBroker/NsPanelTs.ts index 55edb63e..5e428799 100644 --- a/ioBroker/NsPanelTs.ts +++ b/ioBroker/NsPanelTs.ts @@ -97,7 +97,7 @@ var weatherForecast = true; //true = WheatherForecast 5 Days --- false = Config //Alexa-Instanz var alexaInstanz = "alexa2.0" -var alexaDevice = "G070RR1075220388"; //Primär zu steuerndes Device (Seriennummer) +var alexaDevice = "G0XXXXXXXXXXXXXX"; //Primär zu steuerndes Device (Seriennummer) // Wenn alexaSpeakerList definiert, dann werden Einträge verwendet, sonst alle relevanten Devices aus Alexa-Instanz // Speakerwechsel funktioniert nicht bei Radio/TuneIn sonden bei Playlists From 85eb4d7fed2d098c21a1179fbe61413bf29ba2ca Mon Sep 17 00:00:00 2001 From: Armilar <102996011+Armilar@users.noreply.github.com> Date: Mon, 9 May 2022 20:22:43 +0200 Subject: [PATCH 03/23] Update NsPanelTs.ts --- ioBroker/NsPanelTs.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/ioBroker/NsPanelTs.ts b/ioBroker/NsPanelTs.ts index 5e428799..737bcf02 100644 --- a/ioBroker/NsPanelTs.ts +++ b/ioBroker/NsPanelTs.ts @@ -37,7 +37,6 @@ Erforderliche Adapter: Upgrades in Konsole: Tasmota BerryDriver : Backlog UpdateDriverVersion https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be; Restart 1 TFT EU STABLE Version : FlashNextion http://nspanel.pky.eu/lui-release.tft -TFT EU DEV Version : FlashNextion http://nspanel.pky.eu/lui.tft --------------------------------------------------------------------------------------- */ @@ -849,10 +848,7 @@ function CreateEntity(pageItem: PageItem, placeId: number, useColors: boolean = } return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + optVal; -/*--------------------------------------------------------- - case "wled": - type = "number" -----------------------------------------------------------*/ + case "hue": type = "light" From 1238af926d9407618013e4535fdfc24070ce6ef1 Mon Sep 17 00:00:00 2001 From: Armilar <102996011+Armilar@users.noreply.github.com> Date: Mon, 9 May 2022 20:37:49 +0200 Subject: [PATCH 04/23] Update NsPanelTs.ts --- ioBroker/NsPanelTs.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ioBroker/NsPanelTs.ts b/ioBroker/NsPanelTs.ts index 737bcf02..f855cb5a 100644 --- a/ioBroker/NsPanelTs.ts +++ b/ioBroker/NsPanelTs.ts @@ -1,7 +1,7 @@ /*----------------------------------------------------------------------- joBr99 Projekt: https://github.com/joBr99/nspanel-lovelace-ui/tree/main/ioBroker -- abgestimmt auf TFT 34 / v2.8.2 (LATEST) / BerryDriver 4 / Tasmota 11.1.0 +- abgestimmt auf TFT 34 / v2.8.1 / BerryDriver 4 / Tasmota 11.1.0 NsPanelTs.ts (dieses TypeScript in ioBroker) Stable: https://github.com/joBr99/nspanel-lovelace-ui/blob/main/ioBroker/NsPanelTs.ts icon_mapping.ts: https://github.com/joBr99/nspanel-lovelace-ui/blob/main/ioBroker/icon_mapping.ts (TypeScript muss in global liegen) @@ -36,7 +36,7 @@ Erforderliche Adapter: Upgrades in Konsole: Tasmota BerryDriver : Backlog UpdateDriverVersion https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be; Restart 1 -TFT EU STABLE Version : FlashNextion http://nspanel.pky.eu/lui-release.tft +TFT EU STABLE Version : FlashNextion http://nspanel.pky.eu/lovelace-ui/github/nspanel-v2.8.1.tft --------------------------------------------------------------------------------------- */ From aaa0fd6063827e5e8c2cb6cae46a0562fd032824 Mon Sep 17 00:00:00 2001 From: Armilar <102996011+Armilar@users.noreply.github.com> Date: Mon, 9 May 2022 20:40:16 +0200 Subject: [PATCH 05/23] Update NsPanelTs.ts --- ioBroker/NsPanelTs.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ioBroker/NsPanelTs.ts b/ioBroker/NsPanelTs.ts index f855cb5a..81ae1f30 100644 --- a/ioBroker/NsPanelTs.ts +++ b/ioBroker/NsPanelTs.ts @@ -573,7 +573,7 @@ function update_berry_driver_version() { } function update_tft_firmware() { - require("request")((['http://',get_current_tasmota_ip_address(),'/cm?cmnd=FlashNextion http://nspanel.pky.eu/lui.tft'].join('')), async function (error, response, result) { + require("request")((['http://',get_current_tasmota_ip_address(),'/cm?cmnd=FlashNextion http://nspanel.pky.eu/lovelace-ui/github/nspanel-v2.8.1.tft'].join('')), async function (error, response, result) { }); } From 3188b28bdf4a772c2dfbb929cd66ed77500d5241 Mon Sep 17 00:00:00 2001 From: Armilar <102996011+Armilar@users.noreply.github.com> Date: Fri, 13 May 2022 11:42:16 +0200 Subject: [PATCH 06/23] Manuallay updates, card alarm, popupNotify Page and BugFixes - BugFix: automatically dim mode puts NSPanel in dim mode without screensaver in normal operation - Fix: auto-update in defined state - New: manuallly updates - New: card alarm active - New: popupNotify active --- ioBroker/NsPanelTs.ts | 439 ++++++++++++++++++++++++++++++++---------- 1 file changed, 340 insertions(+), 99 deletions(-) diff --git a/ioBroker/NsPanelTs.ts b/ioBroker/NsPanelTs.ts index 81ae1f30..dfbca2cb 100644 --- a/ioBroker/NsPanelTs.ts +++ b/ioBroker/NsPanelTs.ts @@ -1,12 +1,44 @@ /*----------------------------------------------------------------------- -joBr99 Projekt: https://github.com/joBr99/nspanel-lovelace-ui/tree/main/ioBroker +TypeScript zur Steuerung des SONOFF NSPanel mit dem ioBroker +- abgestimmt auf TFT 34 / v2.8.1 (LATEST) / BerryDriver 4 / Tasmota 11.1.0 -- abgestimmt auf TFT 34 / v2.8.1 / BerryDriver 4 / Tasmota 11.1.0 +joBr99 Projekt: https://github.com/joBr99/nspanel-lovelace-ui/tree/main/ioBroker NsPanelTs.ts (dieses TypeScript in ioBroker) Stable: https://github.com/joBr99/nspanel-lovelace-ui/blob/main/ioBroker/NsPanelTs.ts icon_mapping.ts: https://github.com/joBr99/nspanel-lovelace-ui/blob/main/ioBroker/icon_mapping.ts (TypeScript muss in global liegen) -Mögliche Aliase: +ioBroker-Unterstützung: https://forum.iobroker.net/topic/50888/sonoff-nspanel + +ReleaseNotes: +Bugfixes und Erweiterungen seit letzter Verion: + - Automatischer Dimmode versetzt NSPanel im Normalbetrieb in Dimmodus ohne Screensaver + - Auto-Update in definiertem Zustand + - manuelle Updates aktiv + - cardAlarm aktiv + - popupNotify aktiv + +Wenn Rule definiert, dann können die Hardware-Tasten ebenfalls für Seitensteuerung (dann nicht mehr als Releais) genutzt werden +Tasmota Konsole: + Rule2 on Button1#state do Publish %topic%/%prefix%/RESULT {"CustomRecv":"event,button1"} endon on Button2#state do Publish %topic%/%prefix%/RESULT {"CustomRecv":"event,button2"} endon + Rule2 1 (Rule aktivieren) + Rule2 0 (Rule deaktivieren) + +Mögliche Seiten-Ansichten: + screensaver Page - wird nach definiertem Zeitraum (config) mit Dimm-Modus aktiv (Uhrzeit, Datum, Aktuelle Temperatur mit Symbol) + (die 4 kleineren Icons können als Wetter-Vorschau + 4Tage (Symbol + Höschsttemperatur) oder zur Anzeige definierter Infos konfiguriert werden) + cardEtities Page - 4 vertikale angeordnete Steuerelemente - auch als Subpage + cardGrid Page - 6 horizontal angeordnete Steuerelemente in 2 Reihen a 3 Steuerelemente - auch als Subpage + cardThermo Page - Thermostat mit Solltemperatur, Isttemperatur, Mode - Weitere Eigenschaften können im Alias definiert werden + cardMedia Page - Mediaplayer - Ausnahme: Alias sollte mit Alias-Manager automatisch über Alexa-Verzeichnes Player angelegt werden + cardAlarm Page - Alarmseite mit Zustand und Tastenfeld + +Popup-Pages: + popupLight Page - in Abhängigkeit zum gewählten Alias werden "Helligkeit", "Farb-Temperatur" und "Farbauswahl" bereitgestellt + popupShutter Page - die Shutter-Potition (Rollo, Jalousie, Markise, Leinwand, etc.) kann über einen Slider verändert werden. + popupNotify Page - Info - Seite mit Headline Text und Buttons - Intern für manuelle Updates / Extern zur Befüllung von Datenpunkten unter 0_userdata + screensaver Notify - Über zwei externe Datenpunkte in 0_userdata können "Headline" und "Text" an den Screensaver zur Info gesendet werden + +Mögliche Aliase: (Vorzugsweise mit ioBroker-Adapter "Geräte verwalten" konfigurieren, da SET, GET, ACTUAL, etc. verwendet werden) Info - Werte aus Datenpunkt Schieberegler - Slider numerische Werte (SET/ACTUAL) Lautstärke: - Volume (SET/ACTUAL) und MUTE @@ -30,20 +62,30 @@ Mögliche Aliase: Medien - Steuerung von Alexa - Über Alias-Manager im Verzeichnis Player automatisch anlegen (Geräte-Manager funktioniert nicht) Wettervorhersage - Aktuelle Außen-Temperatur (Temp) und aktuelles Accu-Wheather-Icon (Icon) für Screensaver +Interne Sonoff-Sensoren (über Tasmota): + ESP-Temperatur - wird in 0_userdata.0. abgelegt, kann als Alias importieert werden + Temperatur - Raumtemperatur - wird in 0_userdata.0. abgelegt, kann als Alias importieert werden + (!!! Achtung: der interne Sonoff-Sensor liefert keine exakten Daten, da das NSPanel-Board und der ESP selbst Hitze produzieren !!! + ggf. Offset einplanen oder besser einen externen Sensor über Zigbee etc. verwenden) + Timestamp - wird in 0_userdata.0. Zeitpunkt der letzten Sensorübertragung + +Tasmota-Status0 - (zyklische Ausführung) + liefert relevanten Tasmota-Informationen und kann bei Bedarf in "function get_tasmota_status0()" erweitert werden. Daten werden in 0_userdata.0. abgelegt + Erforderliche Adapter: - Accu-Wheater: - Bei Nutzung der Wetterfunktionen im Screensaver + Accu-Wheater: - Bei Nutzung der Wetterfunktionen (und zur Icon-Konvertierung) im Screensaver Alexa2: - Bei Nutzung der dynamischen SpeakerList in der cardMedia Upgrades in Konsole: -Tasmota BerryDriver : Backlog UpdateDriverVersion https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be; Restart 1 -TFT EU STABLE Version : FlashNextion http://nspanel.pky.eu/lovelace-ui/github/nspanel-v2.8.1.tft + Tasmota BerryDriver : Backlog UpdateDriverVersion https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be; Restart 1 + TFT EU STABLE Version : FlashNextion http://nspanel.pky.eu/lovelace-ui/github/nspanel-v2.8.1.tft --------------------------------------------------------------------------------------- */ - var Icons = new IconsSelector(); var timeoutSlider: any; -var NSPanel_Path = "0_userdata.0.NSPanel.1." -var Debug = false; +const NSPanel_Path = "0_userdata.0.NSPanel.1." +const Debug = false; +var manually_Update = true; const Months = ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"]; const Days = ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"]; @@ -96,7 +138,7 @@ var weatherForecast = true; //true = WheatherForecast 5 Days --- false = Config //Alexa-Instanz var alexaInstanz = "alexa2.0" -var alexaDevice = "G0XXXXXXXXXXXXXX"; //Primär zu steuerndes Device (Seriennummer) +var alexaDevice = "G0XXXXXXXXXXXXXX"; //Primär zu steuerndes Device oder Gruppe aus alexa2-Adapter (Seriennummer) // Wenn alexaSpeakerList definiert, dann werden Einträge verwendet, sonst alle relevanten Devices aus Alexa-Instanz // Speakerwechsel funktioniert nicht bei Radio/TuneIn sonden bei Playlists @@ -104,13 +146,26 @@ var alexaDevice = "G0XXXXXXXXXXXXXX"; //Primär zu steuerndes Device (Seriennumm const alexaSpeakerList = ["Echo Spot Buero","Überall","Gartenhaus","Esszimmer","Heimkino","Echo Dot Küche"]; //Datenpunkte für Nachricht an Screensaver -var popupNotifyHeading = NSPanel_Path + "popupNotifyHeading"; -var popupNotifyText = NSPanel_Path + "popupNotifyText"; +var screensaverNotifyHeading = NSPanel_Path + "ScreensaverInfo.popupNotifyHeading"; +var screensaverNotifyText = NSPanel_Path + "ScreensaverInfo.popupNotifyText"; +createState(screensaverNotifyHeading, {type: 'string'}); +createState(screensaverNotifyText, {type: 'string'}); -var tasmotaOTAURL = "http://ota.tasmota.com/tasmota32/release/tasmota32-DE.bin" - -//cardAlarm - Konfiguration -// .... +//Datenpunkte für Nachricht popupNotify Page +var popupNotifyHeading = NSPanel_Path + "popupNotify.popupNotifyHeading"; +var popupNotifyText = NSPanel_Path + "popupNotify.popupNotifyText"; +var popupNotifyInternalName = NSPanel_Path + "popupNotify.popupNotifyInternalName"; // Wird mit Button-Action zurückgeschrieben +var popupNotifyButton1Text = NSPanel_Path + "popupNotify.popupNotifyButton1Text"; +var popupNotifyButton2Text = NSPanel_Path + "popupNotify.popupNotifyButton2Text"; +var popupNotifySleepTimeout = NSPanel_Path + "popupNotify.popupNotifySleepTimeout"; // in sek. / wenn 0, dann bleibt die Nachricht stehen +var popupNotifyAction = NSPanel_Path + "popupNotify.popupNotifyAction"; // Antwort aus dem Panel true/false +createState(popupNotifyHeading, {type: 'string'}); +createState(popupNotifyText, {type: 'string'}); +createState(popupNotifyInternalName, {type: 'string'}); +createState(popupNotifyButton1Text, {type: 'string'}); +createState(popupNotifyButton2Text, {type: 'string'}); +createState(popupNotifySleepTimeout, {type: 'number'}); +createState(popupNotifyAction, {type: 'boolean'}); var Test_Licht: PageEntities = { @@ -375,10 +430,30 @@ export const config: Config = { // _________________________________ Ab hier keine Konfiguration mehr _____________________________________ //Notification an Screensaver -on({id: [popupNotifyHeading, popupNotifyText], change: "ne"}, async function (obj) { +on({id: [screensaverNotifyHeading, screensaverNotifyText], change: "ne"}, async function (obj) { setState(config.panelSendTopic,(['notify~',getState(popupNotifyHeading).val,'~',getState(popupNotifyText).val].join(''))); }); +//popupNotify - Notification an separate Seite +on({id: [popupNotifyInternalName, popupNotifyHeading, popupNotifyText, popupNotifyButton1Text, popupNotifyButton2Text, popupNotifySleepTimeout], change: "ne"}, async function (obj) { + var notification = "entityUpdateDetail" + "~" + + getState(popupNotifyInternalName).val + "~" + + getState(popupNotifyHeading).val + "~" + + "65504" + "~" //Farbe Headline - gelb + + getState(popupNotifyButton1Text).val + "~" + + "63488" + "~" //Farbe Button1 - rot + + getState(popupNotifyButton2Text).val + "~" + + "2016" + "~" //Farbe Button2 - grün + + getState(popupNotifyText).val + "~" + + "65535" + "~" //Farbe Text - weiß + + getState(popupNotifySleepTimeout).val; + clearTimeout(timer); + var timer = setTimeout(function() { + setState(config.panelSendTopic, "pageType~popupNotify"); + setState(config.panelSendTopic, notification); + }, 500); +}); + var subscriptions: any = {}; var screensaverEnabled : boolean = false; var pageId = 0; @@ -398,6 +473,16 @@ schedule({hour: 3, minute: 30}, function () { setState(config.panelSendTopic, 'pageType~pageStartup'); }); +//´timeDimMode Day +schedule({hour: getState(NSPanel_Path+ "NSPanel_Dimmode_hourDay").val, minute: 0}, function () { + ScreensaverDimmode(); +}); + +//´timeDimMode Night +schedule({hour: getState(NSPanel_Path+ "NSPanel_Dimmode_hourNight").val, minute: 0}, function () { + ScreensaverDimmode(); +}); + //Updates vergleichen aktuell alle 30 Minuten schedule("*/30 * * * *", function () { get_tasmota_status0(); @@ -413,45 +498,102 @@ check_updates(); //------------------Begin Update Functions function check_updates() { + + const desired_display_firmware_version = 34; + const berry_driver_version = 4; + + if (Debug) console.log("Check-Updates"); //Tasmota-Firmware-Vergleich if (existsObject(NSPanel_Path + "Tasmota_Firmware.currentVersion") && existsObject(NSPanel_Path + "Tasmota_Firmware.onlineVersion")) { if (getState(NSPanel_Path + "Tasmota_Firmware.currentVersion").val !== getState(NSPanel_Path + "Tasmota_Firmware.onlineVersion").val) { if (existsState(NSPanel_Path + "NSPanel_autoUpdate")) { if (getState(NSPanel_Path + "NSPanel_autoUpdate").val) { + if (Debug) console.log("Auto-Updates eingeschaltet - Update wird durchgeführt"); //Tasmota Upgrade durchführen update_tasmota_firmware() //Aktuelle Tasmota Version = Online Tasmota Version setState(NSPanel_Path + "Tasmota_Firmware.currentVersion", getState(NSPanel_Path + "Tasmota_Firmware.onlineVersion").val); - } + } else { + //Auf Tasmota-Updates hinweisen + if (Debug) console.log("Automatische Updates aus"); + let Path = NSPanel_Path + 'popupNotify.'; + let InternalName = 'TasmotaFirmwareUpdate'; + let Headline = 'Tasmota-Firmware Update'; + let Text = ['Es ist eine neue Version der Tasmota-Firmware','\r\n','verfügbar','\r\n','\r\n','Installierte Version: ' + String(getState((String(NSPanel_Path) + 'Tasmota_Firmware.currentVersion')).val),'\r\n','Verfügbare Version: ' + String(getState((String(NSPanel_Path) + 'Tasmota_Firmware.onlineVersion')).val),'\r\n','\r\n','Upgrade durchführen?'].join(''); + let Button1 = 'Nein'; + let Button2 = 'Ja'; + let Timeout = 0; + setStateDelayed((String(Path) + 'popupNotifyHeading'), Headline, false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifyText'), ([formatDate(getDateObject((new Date().getTime())), "TT.MM.JJJJ SS:mm:ss"),'\r\n','\r\n',Text].join('')), false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifyButton1Text'), Button1, false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifyButton2Text'), Button2, false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifySleepTimeout'), Timeout, false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifyInternalName'), InternalName, false, parseInt(((0) || "").toString(), 60000), false); + } } } else { if (Debug) console.log("Tasmota-Version auf NSPanel aktuell"); } } //Tasmota-Berry-Driver-Vergleich - if (existsObject(NSPanel_Path + "Berry_Driver.currentVersion") && existsObject(NSPanel_Path + "Berry_Driver.onlineVersion")) { - if (getState(NSPanel_Path + "Berry_Driver.currentVersion").val !== getState(NSPanel_Path + "Berry_Driver.onlineVersion").val) { + if (existsObject(NSPanel_Path + "Berry_Driver.currentVersion")) { + if (getState(NSPanel_Path + "Berry_Driver.currentVersion").val < berry_driver_version) { if (existsState(NSPanel_Path + "NSPanel_autoUpdate")) { if (getState(NSPanel_Path + "NSPanel_autoUpdate").val) { //Tasmota Berry-Driver Update durchführen update_berry_driver_version() //Aktuelle Berry-Driver Version = Online Berry-Driver Version setState(NSPanel_Path + "Berry_Driver.currentVersion", getState(NSPanel_Path + "Berry_Driver.onlineVersion").val); + if (Debug) console.log("Berry-Driver automatisch aktualisiert"); + } else { + //Auf BerryDriver-Update hinweisen + if (Debug) console.log("Automatische Updates aus"); + let Path = NSPanel_Path + 'popupNotify.'; + let InternalName = 'BerryDriverUpdate'; + let Headline = 'Berry-Driver Update'; + let Text = ['Es ist eine neue Version des Berry-Drivers','\r\n','(Tasmota) verfügbar','\r\n','\r\n','Installierte Version: ' + String(getState((String(NSPanel_Path) + 'Berry_Driver.currentVersion')).val),'\r\n','Verfügbare Version: ' + String(berry_driver_version),'\r\n','\r\n','Upgrade durchführen?'].join(''); + let Button1 = 'Nein'; + let Button2 = 'Ja'; + let Timeout = 0; + setStateDelayed((String(Path) + 'popupNotifyHeading'), Headline, false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifyText'), ([formatDate(getDateObject((new Date().getTime())), "TT.MM.JJJJ SS:mm:ss"),'\r\n','\r\n',Text].join('')), false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifyButton1Text'), Button1, false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifyButton2Text'), Button2, false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifySleepTimeout'), Timeout, false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifyInternalName'), InternalName, false, parseInt(((0) || "").toString(), 60000), false); } - } + } } else { if (Debug) console.log("Berry-Driver auf NSPanel aktuell"); } } //TFT-Firmware-Vergleich - if (existsObject(NSPanel_Path + "Display_Firmware.currentVersion") && existsObject(NSPanel_Path + "Display_Firmware.onlineVersion")) { - if (getState(NSPanel_Path + "Display_Firmware.currentVersion").val !== getState(NSPanel_Path + "Display_Firmware.onlineVersion").val) { + if (existsObject(NSPanel_Path + "Display_Firmware.currentVersion")) { + if (parseInt(getState(NSPanel_Path + "Display_Firmware.currentVersion").val) !== desired_display_firmware_version) { if (existsState(NSPanel_Path + "NSPanel_autoUpdate")) { if (getState(NSPanel_Path + "NSPanel_autoUpdate").val) { //TFT-Firmware Update durchführen update_tft_firmware() //Aktuelle TFT-Firmware Version = Online TFT-Firmware Version setState(NSPanel_Path + "Display_Firmware.currentVersion", getState(NSPanel_Path + "Display_Firmware.onlineVersion").val); + + if (Debug) console.log("Display_Firmware automatisch aktualisiert"); + } else { + //Auf TFT-Firmware hinweisen + if (Debug) console.log("Automatische Updates aus"); + let Path = NSPanel_Path + 'popupNotify.'; + let InternalName = 'TFTFirmwareUpdate'; + let Headline = 'TFT-Firmware Update'; + let Text = ['Es ist eine neue Version der TFT-Firmware','\r\n','verfügbar','\r\n','\r\n','Installierte Version: ' + String(getState((String(NSPanel_Path) + 'Display_Firmware.currentVersion')).val),'\r\n','Verfügbare Version: ' + String(desired_display_firmware_version),'\r\n','\r\n','Upgrade durchführen?'].join(''); + let Button1 = 'Nein'; + let Button2 = 'Ja'; + let Timeout = 0; + setStateDelayed((String(Path) + 'popupNotifyHeading'), Headline, false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifyText'), ([formatDate(getDateObject((new Date().getTime())), "TT.MM.JJJJ SS:mm:ss"),'\r\n','\r\n',Text].join('')), false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifyButton1Text'), Button1, false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifyButton2Text'), Button2, false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifySleepTimeout'), Timeout, false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifyInternalName'), InternalName, false, parseInt(((0) || "").toString(), 60000), false); } } } else { @@ -460,6 +602,24 @@ function check_updates() { } } +on({id: [].concat([NSPanel_Path + 'popupNotify.popupNotifyAction']), change: "any"}, async function (obj) { + if ((obj.state ? obj.state.val : "") == false) { + manually_Update = false + if (Debug) console.log('Es wurde Button1 gedrückt'); + } else if ((obj.state ? obj.state.val : "") == true) { + if (manually_Update) { + if (getState(NSPanel_Path + "popupNotify.popupNotifyInternalName").val = "TasmotaFirmwareUpdate") { + update_tasmota_firmware(); + } else if (getState(NSPanel_Path + "popupNotify.popupNotifyInternalName").val = "BerryDriverUpdate") { + update_berry_driver_version(); + } else if (getState(NSPanel_Path + "popupNotify.popupNotifyInternalName").val = "TFTFirmwareUpdate") { + update_tft_firmware(); + } + } + if (Debug) console.log('Es wurde Button2 gedrückt'); + } +}); + function get_panel_update_data() { createState(NSPanel_Path + "NSPanel_autoUpdate", false, {read: true, write: true, name: "Auto-Updater", type: "boolean", def: false}); createState(NSPanel_Path + "NSPanel_ipAddress"); @@ -539,8 +699,8 @@ function check_version_tft_firmware() { var NSPanel_JSON = JSON.parse(result) //JSON Resultat in Variable Schreiben var NSPanelTagName = NSPanel_JSON.tag_name //created_at; published_at; name ; draft ; prerelease var NSPanelVersion = NSPanelTagName.replace(/v/i, ""); //Aus Variable überflüssiges "v" filtern und in Release-Variable schreiben - createState(NSPanel_Path + "TFT_Firmware.currentVersion"); - setIfExists(NSPanel_Path + 'TFT_Firmware.currentVersion', NSPanelVersion); + createState(NSPanel_Path + "TFT_Firmware.onlineVersion"); + setIfExists(NSPanel_Path + 'TFT_Firmware.onlineVersion', NSPanelVersion); }); } @@ -573,7 +733,11 @@ function update_berry_driver_version() { } function update_tft_firmware() { - require("request")((['http://',get_current_tasmota_ip_address(),'/cm?cmnd=FlashNextion http://nspanel.pky.eu/lovelace-ui/github/nspanel-v2.8.1.tft'].join('')), async function (error, response, result) { + const tft_version : string = "v2.8.1"; + var desired_display_firmware_url = "http://nspanel.pky.eu/lovelace-ui/github/nspanel-" + tft_version + ".tft" + require("request")((['http://',get_current_tasmota_ip_address(),'/cm?cmnd=FlashNextion ', desired_display_firmware_url].join('')), async function (error, response, result) { + createState(NSPanel_Path + "TFT_Firmware.onlineVersion"); + setIfExists(NSPanel_Path + 'TFT_Firmware.onlineVersion', tft_version); }); } @@ -581,11 +745,11 @@ function update_tasmota_firmware() { require("request")((['http://',get_current_tasmota_ip_address(),'/cm?cmnd=Upgrade 1'].join('')), async function (error, response, result) { }); } - //------------------End Update Functions // 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) } @@ -624,6 +788,13 @@ function SendToPanel(val: Payload | Payload[]): void { setState(config.panelSendTopic, val.payload); } + +on({id: [].concat([NSPanel_Path + 'Alarm.AlarmState']), change: "ne"}, async function (obj) { + if ((obj.state ? obj.state.val : "") == 'armed' || (obj.state ? obj.state.val : "") == 'disarmed' || (obj.state ? obj.state.val : "") == 'triggered') { + GeneratePage(config.pages[8]); //----------- muss noch dynamisch gefunden werden ------------------------------------------- + } +}); + function HandleMessage(typ: string, method: string, page: number, words: Array): void { if (typ == "event") { switch (method) { @@ -649,6 +820,7 @@ function HandleMessage(typ: string, method: string, page: number, words: Array{ payload: "time~" + hr + ":" + min }); - - ScreensaverDimmode(); } function ScreensaverDimmode() { @@ -1415,70 +1585,92 @@ function GenerateAlarmPage(page: PageAlarm): Payload[] { var id = page.items[0].id var out_msgs: Array = []; out_msgs.push({ payload: "pageType~cardAlarm" }); + var nsPath = NSPanel_Path + "Alarm." - 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 = "disable"; //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 = "disable"; //flashing* + if (existsState(nsPath + "AlarmPin") == false || existsState(nsPath + "AlarmState") == false || existsState(nsPath + "AlarmType") == false) { + createState(nsPath + "AlarmPin", "0000", {type: 'string'}, function() {setState(nsPath + "AlarmPin", "0000")}); + createState(nsPath + "AlarmState", "disarmed", {type: 'string'}, function() {setState(nsPath + "AlarmState", "disarmed")}); + createState(nsPath + "AlarmType", "0", {type: 'string'}, function() {setState(nsPath + "AlarmType", "0")}); } - flashing = "disable" - var entityState = "arming" - if (entityState == "arming" || entityState == "pending") { - iconcolor = rgb_dec565({ red: 243, green: 179, blue: 0 }); - icon = Icons.GetIcon("shield"); - flashing = "enable" - } - if (entityState == "triggered") { - iconcolor = rgb_dec565({ red: 223, green: 76, blue: 30 }); - icon = Icons.GetIcon("bell-ring"); - flashing = "enable" - } - - out_msgs.push({ payload: "entityUpd~" + //entityUpd~* - id + "~" + //internalNameEntity*~* - GetNavigationString(pageId) + "~" + //navigation*~* --> hiddenCards - 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* + if (existsState(nsPath + "AlarmPin") && existsState(nsPath + "AlarmState") && existsState(nsPath + "AlarmType")) { + var entityPin = getState(nsPath + "AlarmPin").val; + var entityState = getState(nsPath + "AlarmState").val; + var entityType = getState(nsPath + "AlarmType").val + var arm1: string, arm2: string, arm3: string, arm4: string; + var arm1ActionName: string, arm2ActionName: string, arm3ActionName: string, arm4ActionName: string; + var icon = "0"; + var iconcolor = 63488; + var numpadStatus = "disable"; + var flashing = "disable"; + + console.log(id); + + if (entityState == "armed" || entityState == "triggered") { + arm1 = "Deaktivieren"; //arm1*~* + arm1ActionName = "D1"; //arm1ActionName*~* + arm2 = ""; //arm2*~* + arm2ActionName = ""; //arm2ActionName*~* + arm3 = ""; //arm3*~* + arm3ActionName = ""; //arm3ActionName*~* + arm4 = ""; //arm4*~* + arm4ActionName = ""; //arm4ActionName*~* + } + if (entityState == "disarmed" || entityState == "arming" || entityState == "pending") { + arm1 = "Vollschutz"; //arm1*~* + arm1ActionName = "A1"; //arm1ActionName*~* + arm2 = "Zuhause"; //arm2*~* + arm2ActionName = "A2"; //arm2ActionName*~* + arm3 = "Nacht"; //arm3*~* + arm3ActionName = "A3"; //arm3ActionName*~* + arm4 = "Besuch"; //arm4*~* + arm4ActionName = "A4"; //arm4ActionName*~* + } + + if (entityState == "armed") { + icon = Icons.GetIcon("shield-home"); //icon*~* + iconcolor = 63488; //iconcolor*~* + numpadStatus = "enable"; //numpadStatus*~* + flashing = "disable"; //flashing* + } + if (entityState == "disarmed") { + icon = Icons.GetIcon("shield-off"); //icon*~* + iconcolor = 2016; //iconcolor*~* + numpadStatus = "enable"; //numpadStatus*~* + flashing = "disable"; //flashing* + } + if (entityState == "arming" || entityState == "pending") { + icon = Icons.GetIcon("shield"); //icon*~* + iconcolor = rgb_dec565({ red: 243, green: 179, blue: 0 }); //iconcolor*~* + numpadStatus = "disable"; //numpadStatus*~* + flashing = "enable" //flashing* + } + if (entityState == "triggered") { + iconcolor = rgb_dec565({ red: 223, green: 76, blue: 30 }); //icon*~* + icon = Icons.GetIcon("bell-ring"); //iconcolor*~* + numpadStatus = "enable"; //numpadStatus*~* + flashing = "enable" //flashing* + } + + out_msgs.push({ payload: "entityUpd~" + //entityUpd~* + id + "~" + //internalNameEntity*~* + GetNavigationString(pageId) + "~" + //navigation*~* --> hiddenCards + arm1 + "~" + //arm1*~* + arm1ActionName + "~" + //arm1ActionName*~* + arm2 + "~" + //arm2*~* + arm2ActionName + "~" + //arm2ActionName*~* + arm3 + "~" + //arm3*~* + arm3ActionName + "~" + //arm3ActionName*~* + arm4 + "~" + //arm4*~* + arm4ActionName + "~" + //arm4ActionName*~* + icon + "~" + //icon*~* + iconcolor + "~" + //iconcolor*~* + numpadStatus + "~" + //numpadStatus*~* + flashing}); //flashing* if (Debug) console.log(out_msgs); - return out_msgs + } } function setIfExists(id: string, value: any, type: string | null = null): boolean { @@ -1508,8 +1700,8 @@ function toggleState(id: string): boolean { } function HandleButtonEvent(words): void { - let id = words[2] - let buttonAction = words[3]; + var id = words[2] + var buttonAction = words[3]; if (Debug) { console.log(words[0] + " - " + words[1] + " - " + words[2] + " - " + words[3] + " - " + words[4] + " - PageId: " + pageId); @@ -1546,9 +1738,20 @@ function HandleButtonEvent(words): void { GeneratePage(config.pages[pageId]); } } else { + if (Debug) console.log("bExit: " + words[4] + " - "+ pageId) GeneratePage(config.pages[pageId]); } break; + case "notifyAction": + if (words[4] == "yes") { + setIfExists(popupNotifyInternalName, words[2]); + setIfExists(popupNotifyAction , true); + } else if (words[4] == "no") { + setIfExists(popupNotifyInternalName, words[2]); + setIfExists(popupNotifyAction , false) + } + setIfExists(config.panelSendTopic, "exitPopup") + break; case "OnOff": if (existsObject(id)) { var action = false @@ -1644,8 +1847,8 @@ function HandleButtonEvent(words): void { 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)); + if (Debug) console.log(rgb); + if (Debug) console.log(getHue(rgb.red, rgb.green, rgb.blue)); let o = getObject(id); switch (o.common.role) { case "hue": @@ -1703,19 +1906,57 @@ function HandleButtonEvent(words): void { setIfExists(id + ".SET", parseInt(words[4])) ? true : setIfExists(id + ".ACTUAL", parseInt(words[4])); break; case "A1": //Alarm-Page Alarm 1 aktivieren - console.log("auf mediaAlarm - Alarm 1 - Wert: " + words[4] + " - reagieren - noch nicht implementiert"); - break; + if (words[4] != "") { + setIfExists(id + ".TYPE", "A1"); + setIfExists(id + ".PIN", words[4]); + setIfExists(id + ".ACTUAL", "arming"); + setTimeout(function(){ + GeneratePage(config.pages[pageId]); + },250) + } + break; case "A2": //Alarm-Page Alarm 2 aktivieren - console.log("auf mediaAlarm - Alarm 1 - Wert: " + words[4] + " - reagieren - noch nicht implementiert"); - break; + if (words[4] != "") { + setIfExists(id + ".TYPE", "A2"); + setIfExists(id + ".PIN", words[4]); + setIfExists(id + ".ACTUAL", "arming"); + setTimeout(function(){ + GeneratePage(config.pages[pageId]); + },250) + } + break; case "A3": //Alarm-Page Alarm 3 aktivieren - console.log("auf mediaAlarm - Alarm 1 - Wert: " + words[4] + " - reagieren - noch nicht implementiert"); - break; + if (words[4] != "") { + setIfExists(id + ".TYPE", "A3"); + setIfExists(id + ".PIN", words[4]); + setIfExists(id + ".ACTUAL", "arming"); + setTimeout(function(){ + GeneratePage(config.pages[pageId]); + },250) + } + break; case "A4": //Alarm-Page Alarm 4 aktivieren - console.log("auf mediaAlarm - Alarm 1 - Wert: " + words[4] + " - reagieren - noch nicht implementiert"); + if (words[4] != "") { + setIfExists(id + ".TYPE", "A4"); + setIfExists(id + ".PIN", words[4]); + setIfExists(id + ".ACTUAL", "arming"); + setTimeout(function(){ + GeneratePage(config.pages[pageId]); + },250) + } break; case "D1": //Alarm-Page Alarm Deaktivieren - console.log("auf mediaAlarm - Alarm 1 - Wert: " + words[4] + " - reagieren - noch nicht implementiert"); + if (Debug) console.log("D1: " + getState(id + ".PIN").val); + if (words[4] != "") { + if (getState(id + ".PIN").val == words[4]) { + setIfExists(id + ".PIN", "0000"); + setIfExists(id + ".TYPE", "D1"); + setIfExists(id + ".ACTUAL", "pending"); + setTimeout(function(){ + GeneratePage(config.pages[pageId]); + },250) + } + } break; default: break; From efb943991c5deec4067e5a14b5f977a5fb2536d6 Mon Sep 17 00:00:00 2001 From: Armilar <102996011+Armilar@users.noreply.github.com> Date: Mon, 30 May 2022 12:22:27 +0200 Subject: [PATCH 07/23] Update NsPanelTs.ts --- ioBroker/NsPanelTs.ts | 490 +++++++++++++++++++++++++++++------------- 1 file changed, 336 insertions(+), 154 deletions(-) diff --git a/ioBroker/NsPanelTs.ts b/ioBroker/NsPanelTs.ts index dfbca2cb..8769df10 100644 --- a/ioBroker/NsPanelTs.ts +++ b/ioBroker/NsPanelTs.ts @@ -1,21 +1,14 @@ /*----------------------------------------------------------------------- TypeScript zur Steuerung des SONOFF NSPanel mit dem ioBroker -- abgestimmt auf TFT 34 / v2.8.1 (LATEST) / BerryDriver 4 / Tasmota 11.1.0 - +- abgestimmt auf TFT 36 / v2.9.0 / BerryDriver 4 / Tasmota 11.1.0 joBr99 Projekt: https://github.com/joBr99/nspanel-lovelace-ui/tree/main/ioBroker - NsPanelTs.ts (dieses TypeScript in ioBroker) Stable: https://github.com/joBr99/nspanel-lovelace-ui/blob/main/ioBroker/NsPanelTs.ts icon_mapping.ts: https://github.com/joBr99/nspanel-lovelace-ui/blob/main/ioBroker/icon_mapping.ts (TypeScript muss in global liegen) - ioBroker-Unterstützung: https://forum.iobroker.net/topic/50888/sonoff-nspanel - ReleaseNotes: Bugfixes und Erweiterungen seit letzter Verion: - - Automatischer Dimmode versetzt NSPanel im Normalbetrieb in Dimmodus ohne Screensaver - - Auto-Update in definiertem Zustand - - manuelle Updates aktiv - - cardAlarm aktiv - - popupNotify aktiv + - cardQR (für Gäste WLAN) + - cardThermo (Neues Design für Alias Thermostat und zusätzlich für Alias Klimaanlage) Wenn Rule definiert, dann können die Hardware-Tasten ebenfalls für Seitensteuerung (dann nicht mehr als Releais) genutzt werden Tasmota Konsole: @@ -57,6 +50,7 @@ Mögliche Aliase: (Vorzugsweise mit ioBroker-Adapter "Geräte verwalten" konfigu Taste - Für Szenen oder Radiosender, etc. --> Nur Funktionsaufruf - Kein Taster wie MonoButton - True/False Tastensensor - analog Taste Thermostat - Aktuelle Raumtemperatur, Setpoint, etc. + Klimaanlage - Buttons zur Steuerung der Klimaanlage im unteren Bereich Temperatur - Anzeige von Temperture - Datenpunkten, ananlog Info Feuchtigkeit - Anzeige von Humidity - Datenpunkten, ananlog Info Medien - Steuerung von Alexa - Über Alias-Manager im Verzeichnis Player automatisch anlegen (Geräte-Manager funktioniert nicht) @@ -75,10 +69,14 @@ Tasmota-Status0 - (zyklische Ausführung) Erforderliche Adapter: Accu-Wheater: - Bei Nutzung der Wetterfunktionen (und zur Icon-Konvertierung) im Screensaver Alexa2: - Bei Nutzung der dynamischen SpeakerList in der cardMedia + Geräte verwalten - Für Erstellung der Aliase + Alias-Manager - !!! ausschießlich für MEDIA-Alias + MQTT-Adapter - Für Kommunikation zwischen Skript und Tasmota + JavaScript-Adapter Upgrades in Konsole: Tasmota BerryDriver : Backlog UpdateDriverVersion https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be; Restart 1 - TFT EU STABLE Version : FlashNextion http://nspanel.pky.eu/lovelace-ui/github/nspanel-v2.8.1.tft + TFT EU STABLE Version : FlashNextion http://nspanel.pky.eu/lovelace-ui/github/nspanel-v2.9.0.tft --------------------------------------------------------------------------------------- */ var Icons = new IconsSelector(); @@ -142,8 +140,8 @@ var alexaDevice = "G0XXXXXXXXXXXXXX"; //Primär zu steuerndes Device oder Gruppe // 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"]; +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 screensaverNotifyHeading = NSPanel_Path + "ScreensaverInfo.popupNotifyHeading"; @@ -292,10 +290,28 @@ var Alexa: PageMedia = var Buero_Themostat: PageThermo = { "type": "cardThermo", - "heading": "Thermostat", + "heading": "Test Thermostat", "useColor": true, "subPage": false, - "items": [{ id: "alias.0.NSPanel_1.Thermostat_Büro" }] + "items": [{ id: "alias.0.NSPanel_1.Thermostat_Büro", minValue: 50, maxValue: 300 }] +}; + +var Buero_Klimaanlage: PageThermo = +{ + "type": "cardThermo", + "heading": "Test Klimaanlage", + "useColor": true, + "subPage": false, + "items": [{ id: "alias.0.NSPanel_1.TestKlimaanlage", minValue: 170, maxValue: 250}] +}; + +var WLAN: PageQR = +{ + "type": "cardQR", + "heading": "Gäste WLAN", + "useColor": true, + "subPage": false, + "items": [{ id: "alias.0.NSPanel_1.Guest_Wifi" }] }; var Buero_Alarm: PageAlarm = @@ -413,6 +429,8 @@ export const config: Config = { temperatureUnit: "°C", pages: [ Buero_Seite_1, + Buero_Klimaanlage, + WLAN, Button_1, Test_Licht, Test_Funktionen, @@ -431,7 +449,7 @@ export const config: Config = { //Notification an Screensaver on({id: [screensaverNotifyHeading, screensaverNotifyText], change: "ne"}, async function (obj) { - setState(config.panelSendTopic,(['notify~',getState(popupNotifyHeading).val,'~',getState(popupNotifyText).val].join(''))); + setState(config.panelSendTopic,(['notify~',getState(screensaverNotifyHeading).val,'~',getState(screensaverNotifyText).val].join(''))); }); //popupNotify - Notification an separate Seite @@ -443,7 +461,7 @@ on({id: [popupNotifyInternalName, popupNotifyHeading, popupNotifyText, popupNoti + getState(popupNotifyButton1Text).val + "~" + "63488" + "~" //Farbe Button1 - rot + getState(popupNotifyButton2Text).val + "~" - + "2016" + "~" //Farbe Button2 - grün + + "2016" + "~" //Farbe Button2 - grün + getState(popupNotifyText).val + "~" + "65535" + "~" //Farbe Text - weiß + getState(popupNotifySleepTimeout).val; @@ -499,7 +517,7 @@ check_updates(); //------------------Begin Update Functions function check_updates() { - const desired_display_firmware_version = 34; + const desired_display_firmware_version = 36; const berry_driver_version = 4; if (Debug) console.log("Check-Updates"); @@ -733,7 +751,7 @@ function update_berry_driver_version() { } function update_tft_firmware() { - const tft_version : string = "v2.8.1"; + const tft_version : string = "v2.9.0"; var desired_display_firmware_url = "http://nspanel.pky.eu/lovelace-ui/github/nspanel-" + tft_version + ".tft" require("request")((['http://',get_current_tasmota_ip_address(),'/cm?cmnd=FlashNextion ', desired_display_firmware_url].join('')), async function (error, response, result) { createState(NSPanel_Path + "TFT_Firmware.onlineVersion"); @@ -849,11 +867,14 @@ function GeneratePage(page: Page): void { case "cardAlarm": SendToPanel(GenerateAlarmPage(page)); break; + case "cardQR": + SendToPanel(GenerateQRPage(page)); + break; } } function HandleHardwareButton(method: string): void { - let page: (PageThermo | PageMedia | PageAlarm | PageEntities | PageGrid); + let page: (PageThermo | PageMedia | PageAlarm | PageEntities | PageGrid | PageQR); if (config.button1Page !== null && method == "button1") { page = config.button1Page; pageId = -1; @@ -937,6 +958,9 @@ function GeneratePageElements(page: Page): string { case "cardMedia": maxItems = 1; break; + case "cardQR": + maxItems = 1; + break; case "cardEntities": maxItems = 4; break; @@ -961,7 +985,6 @@ function GeneratePageElements(page: Page): string { else { pageData += CreateEntity({ id: "delete" }, index + 1); //muss das wirklich? Wo erforderlich wird es mitgegeben! - } */ } @@ -1362,163 +1385,225 @@ function GenerateThermoPage(page: PageThermo): Payload[] { // ioBroker if (existsObject(id)) { let o = getObject(id) - let name = page.items[0].name !== undefined ? page.items[0].name : o.common.name.de + let name = page.heading !== undefined ? page.heading : o.common.name.de let currentTemp = 0; if (existsState(id + ".ACTUAL")) - currentTemp = (Math.round(parseFloat(getState(id + ".ACTUAL").val) * 10)/10)*10; + currentTemp = (Math.round(parseFloat(getState(id + ".ACTUAL").val) * 10)/10); let destTemp = 0; if (existsState(id + ".SET")) { destTemp = getState(id + ".SET").val.toFixed(2) * 10; } - + let statusStr : String = "MANU" 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 minTemp = page.items[0].minValue !== undefined ? page.items[0].minValue : 50; //Min Temp 5°C + let maxTemp = page.items[0].maxValue !== undefined ? page.items[0].maxValue : 300; //Max Temp 30°C let stepTemp = 5 //Attribute hinzufügen, wenn im Alias definiert - var thermButton = 0; let i_list = Array.prototype.slice.apply($('[state.id="' + id + '.*"]')); if ((i_list.length - 3) != 0) { - if (Debug) console.log(i_list.length -3); - if ((i_list.length -3)%2 == 0) { - if ((i_list.length - 3) == 2) { - thermButton = 6; - } else { - thermButton = 5; - } - } else { - if ((i_list.length - 3) == 1) { - thermButton = 2; - } else if ((i_list.length - 3) == 3) { - thermButton = 1; - } else { - thermButton = 0; - } - } - + var i = 0; - var bt = ["","","","","","","","",""]; - for (i = 0; i < thermButton; i++) { - bt[i] = "~~~~"; - } - for (let i_index in i_list) { - let thermostatState = i_list[i_index].split('.'); - if (thermostatState[thermostatState.length-1] != "SET" && - thermostatState[thermostatState.length-1] != "ACTUAL" && - thermostatState[thermostatState.length-1] != "MODE") { - i++; - - switch (thermostatState[thermostatState.length-1]) { - case "HUMIDITY": - if (existsState(id + ".HUMIDITY") && getState(id + ".HUMIDITY").val != null) { - if (parseInt(getState(id + ".HUMIDITY").val) < 40) { - bt[i-1] = Icons.GetIcon("water-percent") + "~65504~1~" + "HUMIDITY" + "~"; - } else if (parseInt(getState(id + ".HUMIDITY").val) < 30) { - bt[i-1] = Icons.GetIcon("water-percent") + "~63488~1~" + "HUMIDITY" + "~"; - } else if (parseInt(getState(id + ".HUMIDITY").val) > 65) { - bt[i-1] = Icons.GetIcon("water-percent") + "~65504~1~" + "HUMIDITY" + "~"; - } else if (parseInt(getState(id + ".HUMIDITY").val) > 75) { - bt[i-1] = Icons.GetIcon("water-percent") + "~63488~1~" + "HUMIDITY" + "~"; - } - } else i--; - break; - case "LOWBAT": - if (existsState(id + ".LOWBAT") && getState(id + ".LOWBAT").val != null) { - if (getState(id + ".LOWBAT").val) { - bt[i-1] = Icons.GetIcon("battery-low") + "~63488~1~" + "LOWBAT" + "~"; - } else { - bt[i-1] = Icons.GetIcon("battery-high") + "~2016~1~" + "LOWBAT" + "~"; - } - } else i--; - break; - case "MAINTAIN": - if (existsState(id + ".MAINTAIN") && getState(id + ".MAINTAIN").val != null) { - if (getState(id + ".MAINTAIN").val >> .1) { - bt[i-1] = Icons.GetIcon("fire") + "~60897~1~" + "MAINTAIN" + "~"; - } else { - bt[i-1] = Icons.GetIcon("fire") + "~33840~0~" + "MAINTAIN" + "~"; - } - } else i--; - break; - case "UNREACH": - if (existsState(id + ".UNREACH") && getState(id + ".UNREACH").val != null) { - if (getState(id + ".UNREACH").val) { - bt[i-1] = Icons.GetIcon("wifi-off") + "~63488~1~" + "UNREACH" + "~"; - } else { - bt[i-1] = Icons.GetIcon("wifi") + "~2016~1~" + "UNREACH" + "~"; - } - } else i--; - break; - case "POWER": - if (existsState(id + ".POWER") && getState(id + ".POWER").val != null) { - if (getState(id + ".POWER").val) { - bt[i-1] = Icons.GetIcon("power-standby") + "~2016~1~" + "POWER" + "~"; - } else { - bt[i-1] = Icons.GetIcon("power-standby") + "~33840~1~" + "POWER" + "~"; - } - } else i--; - break; - case "ERROR": - if (existsState(id + ".ERROR") && getState(id + ".ERROR").val != null) { - if (getState(id + ".ERROR").val) { - bt[i-1] = Icons.GetIcon("alert-circle") + "~63488~1~" + "ERROR" + "~"; - } else { - bt[i-1] = Icons.GetIcon("alert-circle") + "~33840~1~" + "ERROR" + "~"; - } - } else i--; - break; - case "WORKING": - if (existsState(id + ".WORKING") && getState(id + ".WORKING").val != null) { - if (getState(id + ".WORKING").val) { - bt[i-1] = Icons.GetIcon("briefcase-check") + "~2016~1~" + "WORKING" + "~"; - } else { - bt[i-1] = Icons.GetIcon("briefcase-check") + "~33840~1~" + "WORKING" + "~"; - } - } else i--; - break; - case "BOOST": - if (existsState(id + ".BOOST") && getState(id + ".BOOST").val != null) { - if (getState(id + ".BOOST").val) { - bt[i-1] = Icons.GetIcon("fast-forward-60") + "~2016~1~" + "BOOST" + "~"; - } else { - bt[i-1] = Icons.GetIcon("fast-forward-60") + "~33840~1~" + "BOOST" + "~"; - } - } else i--; - break; - case "PARTY": - if (existsState(id + ".PARTY") && getState(id + ".PARTY").val != null) { - if (getState(id + ".PARTY").val) { - bt[i-1] = Icons.GetIcon("party-popper") + "~2016~1~" + "PARTY" + "~"; - } else { - bt[i-1] = Icons.GetIcon("party-popper") + "~33840~1~" + "PARTY" + "~"; - } - } else i--; - break; - default: - i--; - break; + var bt = ["~~~~","~~~~","~~~~","~~~~","~~~~","~~~~","~~~~","~~~~","~~~~"]; + + if (o.common.role == "thermostat") { + for (let i_index in i_list) { + let thermostatState = i_list[i_index].split('.'); + if (thermostatState[thermostatState.length-1] != "SET" && + thermostatState[thermostatState.length-1] != "ACTUAL" && + thermostatState[thermostatState.length-1] != "MODE") { + i++; + + switch (thermostatState[thermostatState.length-1]) { + case "HUMIDITY": + if (existsState(id + ".HUMIDITY") && getState(id + ".HUMIDITY").val != null) { + if (parseInt(getState(id + ".HUMIDITY").val) < 40) { + bt[i-1] = Icons.GetIcon("water-percent") + "~65504~1~" + "HUMIDITY" + "~"; + } else if (parseInt(getState(id + ".HUMIDITY").val) < 30) { + bt[i-1] = Icons.GetIcon("water-percent") + "~63488~1~" + "HUMIDITY" + "~"; + } else if (parseInt(getState(id + ".HUMIDITY").val) >= 40) { + bt[i-1] = Icons.GetIcon("water-percent") + "~2016~1~" + "HUMIDITY" + "~"; + } else if (parseInt(getState(id + ".HUMIDITY").val) > 65) { + bt[i-1] = Icons.GetIcon("water-percent") + "~65504~1~" + "HUMIDITY" + "~"; + } else if (parseInt(getState(id + ".HUMIDITY").val) > 75) { + bt[i-1] = Icons.GetIcon("water-percent") + "~63488~1~" + "HUMIDITY" + "~"; + } + } else i--; + break; + case "LOWBAT": + if (existsState(id + ".LOWBAT") && getState(id + ".LOWBAT").val != null) { + if (getState(id + ".LOWBAT").val) { + bt[i-1] = Icons.GetIcon("battery-low") + "~63488~1~" + "LOWBAT" + "~"; + } else { + bt[i-1] = Icons.GetIcon("battery-high") + "~2016~1~" + "LOWBAT" + "~"; + } + } else i--; + break; + case "MAINTAIN": + if (existsState(id + ".MAINTAIN") && getState(id + ".MAINTAIN").val != null) { + if (getState(id + ".MAINTAIN").val >> .1) { + bt[i-1] = Icons.GetIcon("fire") + "~60897~1~" + "MAINTAIN" + "~"; + } else { + bt[i-1] = Icons.GetIcon("fire") + "~33840~0~" + "MAINTAIN" + "~"; + } + } else i--; + break; + case "UNREACH": + if (existsState(id + ".UNREACH") && getState(id + ".UNREACH").val != null) { + if (getState(id + ".UNREACH").val) { + bt[i-1] = Icons.GetIcon("wifi-off") + "~63488~1~" + "UNREACH" + "~"; + } else { + bt[i-1] = Icons.GetIcon("wifi") + "~2016~1~" + "UNREACH" + "~"; + } + } else i--; + break; + case "POWER": + if (existsState(id + ".POWER") && getState(id + ".POWER").val != null) { + if (getState(id + ".POWER").val) { + bt[i-1] = Icons.GetIcon("power-standby") + "~2016~1~" + "POWER" + "~"; + } else { + bt[i-1] = Icons.GetIcon("power-standby") + "~33840~1~" + "POWER" + "~"; + } + } else i--; + break; + case "ERROR": + if (existsState(id + ".ERROR") && getState(id + ".ERROR").val != null) { + if (getState(id + ".ERROR").val) { + bt[i-1] = Icons.GetIcon("alert-circle") + "~63488~1~" + "ERROR" + "~"; + } else { + bt[i-1] = Icons.GetIcon("alert-circle") + "~33840~1~" + "ERROR" + "~"; + } + } else i--; + break; + case "WORKING": + if (existsState(id + ".WORKING") && getState(id + ".WORKING").val != null) { + if (getState(id + ".WORKING").val) { + bt[i-1] = Icons.GetIcon("briefcase-check") + "~2016~1~" + "WORKING" + "~"; + } else { + bt[i-1] = Icons.GetIcon("briefcase-check") + "~33840~1~" + "WORKING" + "~"; + } + } else i--; + break; + case "BOOST": + if (existsState(id + ".BOOST") && getState(id + ".BOOST").val != null) { + if (getState(id + ".BOOST").val) { + bt[i-1] = Icons.GetIcon("fast-forward-60") + "~2016~1~" + "BOOST" + "~"; + } else { + bt[i-1] = Icons.GetIcon("fast-forward-60") + "~33840~1~" + "BOOST" + "~"; + } + } else i--; + break; + case "PARTY": + if (existsState(id + ".PARTY") && getState(id + ".PARTY").val != null) { + if (getState(id + ".PARTY").val) { + bt[i-1] = Icons.GetIcon("party-popper") + "~2016~1~" + "PARTY" + "~"; + } else { + bt[i-1] = Icons.GetIcon("party-popper") + "~33840~1~" + "PARTY" + "~"; + } + } else i--; + break; + default: + i--; + break; + } } } + for (let j = i; j < 9; j++) { + bt[j] = "~~~~"; + } } - for (let j = i; j < 9; j++) { - bt[j] = "~~~~"; + + if (o.common.role == "airCondition") { + if (existsState(id + ".MODE") && getState(id + ".MODE").val != null) { + let Mode = getState(id + ".MODE").val + if (existsState(id + ".POWER") && getState(id + ".POWER").val != null) { + if (Mode != 0 || getState(id + ".POWER").val) { //0=ON oder .POWER = true + bt[0] = Icons.GetIcon("power-standby") + "~2016~1~" + "POWER" + "~"; + statusStr = "ON"; + } else { + bt[0] = Icons.GetIcon("power-standby") + "~35921~0~" + "POWER" + "~"; + statusStr = "OFF"; + } + } + if (Mode == 1) { //1=AUTO + bt[1] = Icons.GetIcon("air-conditioner") + "~1024~1~" + "AUTO" + "~"; + statusStr = "AUTO"; + } else { + bt[1] = Icons.GetIcon("air-conditioner") + "~35921~0~" + "AUTO" + "~"; + } + if (Mode == 2) { //2=COOL + bt[2] = Icons.GetIcon("snowflake") + "~11487~1~" + "COOL" + "~"; + statusStr = "COOL"; + } else { + bt[2] = Icons.GetIcon("snowflake") + "~35921~0~" + "COOL" + "~"; + } + if (Mode == 3) { //3=HEAT + bt[3] = Icons.GetIcon("fire") + "~64512~1~" + "HEAT" + "~"; + statusStr = "HEAT"; + } else { + bt[3] = Icons.GetIcon("fire") + "~35921~0~" + "HEAT" + "~"; + } + if (Mode == 4) { //4=ECO + bt[4] = Icons.GetIcon("alpha-e-circle-outline") + "~2016~1~" + "ECO" + "~"; + statusStr = "ECO"; + } else { + bt[4] = Icons.GetIcon("alpha-e-circle-outline") + "~35921~0~" + "ECO" + "~"; + } + if (Mode == 5) { //5=FANONLY + bt[5] = Icons.GetIcon("fan") + "~11487~1~" + "FAN" + "~"; + statusStr = "FAN ONLY"; + } else { + bt[5] = Icons.GetIcon("fan") + "~35921~0~" + "FAN" + "~"; + } + if (Mode == 6) { //6=DRY + bt[6] = Icons.GetIcon("water-percent") + "~60897~1~" + "DRY" + "~"; + statusStr = "DRY"; + } else { + bt[6] = Icons.GetIcon("water-percent") + "~35921~0~" + "DRY" + "~"; + } + if (existsState(id + ".SWING") && getState(id + ".SWING").val != null) { + if (getState(id + ".POWER").val && getState(id + ".SWING").val == 1) { //0=ON oder .SWING = true + bt[7] = Icons.GetIcon("swap-vertical-bold") + "~2016~1~" + "SWING" + "~"; + } else { + bt[7] = Icons.GetIcon("swap-vertical-bold") + "~35921~0~" + "SWING" + "~"; + } + } + } } } - - let icon_res = bt[0] + bt[1] + bt[2] + bt[3] + bt[4] + bt[5] + bt[6] + bt[7] + bt[8]; + + let icon_res = bt[0] + bt[1] + bt[2] + bt[3] + bt[4] + bt[5] + bt[6] + bt[7]; - out_msgs.push({ payload: "entityUpd~" + name + "~" + GetNavigationString(pageId) + "~" + id + "~" + currentTemp + "~" + destTemp + "~" + status + "~" + minTemp + "~" + maxTemp + "~" + stepTemp + "~" +icon_res}) + + out_msgs.push({ payload: "entityUpd~" + + name + "~" //Heading + + GetNavigationString(pageId) + "~" //Page Navigation + + id + "~" //internalNameEntiy + + currentTemp + "°C" + "~" //Ist-Temperatur (String) + + destTemp + "~" //Soll-Temperatur (numerisch ohne Komma) + + statusStr + "~" //Mode + + minTemp + "~" //Thermostat Min-Temperatur + + maxTemp + "~" //Thermostat Max-Temperatur + + stepTemp + "~" //Schritte für Soll (5°C) + + icon_res //Icons Status + + "Aktuell" + "~" //Bezeicher vor Aktueller Raumtemperatur + + "Status" + "~" //Bezeicner vor + + "HVAC" + "~" //Bezeichner vor HVAC + + "°C"}) //Bezeichner Hinter Solltemp + } + if (Debug) console.log(out_msgs); return out_msgs } + function GenerateMediaPage(page: PageMedia): Payload[] { var id = page.items[0].id var out_msgs: Array = []; @@ -1604,7 +1689,7 @@ function GenerateAlarmPage(page: PageAlarm): Payload[] { var numpadStatus = "disable"; var flashing = "disable"; - console.log(id); + if (Debug) console.log(id); if (entityState == "armed" || entityState == "triggered") { arm1 = "Deaktivieren"; //arm1*~* @@ -1673,6 +1758,57 @@ function GenerateAlarmPage(page: PageAlarm): Payload[] { } } +function GenerateQRPage(page: PageQR): Payload[] { + var id = page.items[0].id + var out_msgs: Array = []; + out_msgs.push({ payload: "pageType~cardQR" }); + + let o = getObject(id) + + var heading = page.heading !== undefined ? page.heading : o.common.name.de + let minTemp = page.items[0].minValue !== undefined ? page.items[0].minValue : 50; + var textQR = page.items[0].id + ".ACTUAL" !== undefined ? getState(page.items[0].id + ".ACTUAL").val : "WIFI:T:undefined;S:undefined;P:undefined;H:undefined;" + + const tempstr = textQR.split(";"); + for (let w = 0; w < tempstr.length - 1; w++) { + if (tempstr[w].substring(0,1) == "S") { + var optionalValue1 = tempstr[w].slice(2); + } + if (tempstr[w].substring(0,1) == "P") { + var optionalValue2 = tempstr[w].slice(2); + } + } + + var type1 = "text" + var internalName1 = "SSID" + var iconId1 = Icons.GetIcon("wifi"); + var displayName1 = "SSID" + var type2 = "text" + var internalName2 = "Passwort" + var iconId2 = Icons.GetIcon("key"); + var displayName2 = "Passwort" + + out_msgs.push({ payload: "entityUpd~" + //entityUpd + heading + "~" + //heading + GetNavigationString(pageId) + "~" + //navigation + textQR + "~" + //textQR + type1 + "~" + //type + internalName1 + "~" + //internalName + iconId1 + "~" + //iconId + 65535 + "~" + //iconColor + displayName1 + "~" + //displayName + optionalValue1 + "~" + //optionalValue + type2 + "~" + //type + internalName2 + "~" + //internalName + iconId2 + "~" + //iconId + 65535 + "~" + //iconColor + displayName2 + "~" + //displayName + optionalValue2}); //optionalValue + + //entityUpd,heading,navigation,textQR[,type,internalName,iconId,displayName,optionalValue]x2 + return out_msgs +} + function setIfExists(id: string, value: any, type: string | null = null): boolean { if (type === null) { if (existsState(id)) { @@ -1898,9 +2034,50 @@ function HandleButtonEvent(words): void { setIfExists(id + ".STOP", true) break; case "hvac_action": - if (words[4] == "POWER" || words[4] == "BOOST" || words[4] == "PARTY") { + if (words[4] == "BOOST" || words[4] == "PARTY") { setIfExists(words[2] + "." + words[4], !getState(words[2] + "." + words[4]).val) + } + else { + var HVACMode = 0; + switch (words[4]) { + case "POWER": + HVACMode = 0; + setIfExists(words[2] + "." + words[4], !getState(words[2] + "." + words[4]).val) + if (getState(words[2] + "." + words[4]).val) { + HVACMode = 1; + } + break; + case "AUTO": + HVACMode = 1; + break; + case "COOL": + HVACMode = 2; + break; + case "HEAT": + HVACMode = 3; + break; + case "ECO": + HVACMode = 4; + break; + case "FAN": + HVACMode = 5; + break; + case "DRY": + HVACMode = 6; + break; + case "SWING": + HVACMode = getState(words[2] + "." + "MODE").val; + if (getState(words[2] + "." + "SWING").val == 0) { + setIfExists(words[2] + "." + "SWING", 1) + } else { + setIfExists(words[2] + "." + "SWING", 0) + } + break; + } + setIfExists(words[2] + "." + "MODE", HVACMode) + GeneratePage(config.pages[pageId]); } + break; case "number-set": setIfExists(id + ".SET", parseInt(words[4])) ? true : setIfExists(id + ".ACTUAL", parseInt(words[4])); @@ -2630,6 +2807,11 @@ interface PageAlarm extends Page { items: PageItem[], }; +interface PageQR extends Page { + type: "cardQR", + items: PageItem[], +}; + type PageItem = { id: string, icon: (string | undefined), @@ -2676,9 +2858,9 @@ type Config = { 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), + pages: (PageThermo | PageMedia | PageAlarm | PageQR | PageEntities | PageGrid)[], + button1Page: (PageThermo | PageMedia | PageAlarm | PageQR | PageEntities | PageGrid | null), + button2Page: (PageThermo | PageMedia | PageAlarm | PageQR | PageEntities | PageGrid | null), }; type ScreenSaverElement = { From 374b1f610be3dd7ed6d574527306edb0c4ef1023 Mon Sep 17 00:00:00 2001 From: Armilar <102996011+Armilar@users.noreply.github.com> Date: Mon, 30 May 2022 12:27:10 +0200 Subject: [PATCH 08/23] cardQR, Alias airCondition, new Thermostat-Template, Bugfixes --- ioBroker/NsPanelTs.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/ioBroker/NsPanelTs.ts b/ioBroker/NsPanelTs.ts index 8769df10..46b8698a 100644 --- a/ioBroker/NsPanelTs.ts +++ b/ioBroker/NsPanelTs.ts @@ -9,6 +9,7 @@ ReleaseNotes: Bugfixes und Erweiterungen seit letzter Verion: - cardQR (für Gäste WLAN) - cardThermo (Neues Design für Alias Thermostat und zusätzlich für Alias Klimaanlage) + - Bugfixes Wenn Rule definiert, dann können die Hardware-Tasten ebenfalls für Seitensteuerung (dann nicht mehr als Releais) genutzt werden Tasmota Konsole: From 00e70db76c00e509d835a70a4a3b6771a1e66a5f Mon Sep 17 00:00:00 2001 From: Armilar <102996011+Armilar@users.noreply.github.com> Date: Wed, 8 Jun 2022 12:42:56 +0200 Subject: [PATCH 09/23] New brightness parameter; Menu arrows (buttonXPage) - New parameter "active" for standard brightness in Config - Menu arrows in Hardware Button Pages (button1Page; button2Page) lead to page 0 --- ioBroker/NsPanelTs.ts | 49 +++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/ioBroker/NsPanelTs.ts b/ioBroker/NsPanelTs.ts index 46b8698a..a77413a4 100644 --- a/ioBroker/NsPanelTs.ts +++ b/ioBroker/NsPanelTs.ts @@ -5,11 +5,18 @@ joBr99 Projekt: https://github.com/joBr99/nspanel-lovelace-ui/tree/main/ioBroker NsPanelTs.ts (dieses TypeScript in ioBroker) Stable: https://github.com/joBr99/nspanel-lovelace-ui/blob/main/ioBroker/NsPanelTs.ts icon_mapping.ts: https://github.com/joBr99/nspanel-lovelace-ui/blob/main/ioBroker/icon_mapping.ts (TypeScript muss in global liegen) ioBroker-Unterstützung: https://forum.iobroker.net/topic/50888/sonoff-nspanel + ReleaseNotes: -Bugfixes und Erweiterungen seit letzter Verion: - - cardQR (für Gäste WLAN) - - cardThermo (Neues Design für Alias Thermostat und zusätzlich für Alias Klimaanlage) - - Bugfixes + Bugfixes und Erweiterungen seit letzter Verion: + - cardQR (für Gäste WLAN) + - cardThermo (Neues Design für Alias Thermostat und zusätzlich für Alias Klimaanlage) + - 08.05.2022 - Menüpfeile bei HardwareButtons (button1Page; button2Page) mit Navigation auf Page 0 + - 08.05.2022 - Standard-Brightness über neuen Parameter active einstellbar (Test mit 2.9.3) + + Known-Bugs --> Bugfix folgt: + - cardGrid - Schalter funktionieren nicht + - Aktion auf Submenüs schaltet unmittelbar auf vorheriges Mainmenu + - Menü-Pfeile in Subpages (z.B. card QR, cardMedia, etc) Wenn Rule definiert, dann können die Hardware-Tasten ebenfalls für Seitensteuerung (dann nicht mehr als Releais) genutzt werden Tasmota Konsole: @@ -137,12 +144,12 @@ var weatherForecast = true; //true = WheatherForecast 5 Days --- false = Config //Alexa-Instanz var alexaInstanz = "alexa2.0" -var alexaDevice = "G0XXXXXXXXXXXXXX"; //Primär zu steuerndes Device oder Gruppe aus alexa2-Adapter (Seriennummer) +var alexaDevice = "G0XXXXXXXXXXXXXXX"; //Primär zu steuerndes Device oder Gruppe aus alexa2-Adapter (Seriennummer) // 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"]; +//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 screensaverNotifyHeading = NSPanel_Path + "ScreensaverInfo.popupNotifyHeading"; @@ -243,6 +250,7 @@ var Subpages_1: PageEntities = "subPage": false, "items": [ { navigate: true, id: "Abfall", onColor: White, name: "Abfallkalender"}, + { navigate: true, id: "WLAN", onColor: White, name: "Gäste WLAN"}, { navigate: true, id: "Buero_Seite_2", onColor: White, name: "Büro Card Grid"} ] }; @@ -311,7 +319,7 @@ var WLAN: PageQR = "type": "cardQR", "heading": "Gäste WLAN", "useColor": true, - "subPage": false, + "subPage": true, "items": [{ id: "alias.0.NSPanel_1.Guest_Wifi" }] }; @@ -419,6 +427,7 @@ export const config: Config = { fourthScreensaverEntity: { ScreensaverEntity: "accuweather.0.Current.UVIndex", ScreensaverEntityIcon: "solar-power", ScreensaverEntityText: "UV", ScreensaverEntityUnitText: "" }, timeoutScreensaver: 15, dimmode: 8, + active: 100, //Standard-Brightness TFT screenSaverDoubleClick: false, locale: "de_DE", timeFormat: "%H:%M", @@ -430,8 +439,8 @@ export const config: Config = { temperatureUnit: "°C", pages: [ Buero_Seite_1, - Buero_Klimaanlage, - WLAN, + Buero_Klimaanlage, + //WLAN, Button_1, Test_Licht, Test_Funktionen, @@ -894,7 +903,7 @@ function HandleStartupProcess(): void { SendDate(); SendTime(); SendToPanel({ payload: "timeout~" + config.timeoutScreensaver }); - SendToPanel({ payload: "dimmode~" + config.dimmode }); + SendToPanel({ payload: "dimmode~" + config.dimmode + "~" + config.active}); } function SendDate(): void { @@ -1850,6 +1859,15 @@ function HandleButtonEvent(words): void { } switch (buttonAction) { + case "bUp": + if (pageId < 0) { //Prüfen, ob button1page oder button2page + pageId = 0; + } else { + pageId = Math.abs(pageNum); + } + UnsubscribeWatcher(); + GeneratePage(config.pages[pageId]); + break; case "bNext": var pageNum = ((pageId + 1) % config.pages.length); pageId = Math.abs(pageNum); @@ -2142,13 +2160,18 @@ function HandleButtonEvent(words): void { } function GetNavigationString(pageId: number): string { + if (Debug) console.log(pageId); + if (Debug) console.log(subPage_open); + switch (pageId) { case 0: return "0|1"; case config.pages.length - 1: return "1|0"; case -1: - return "0|0"; + return "2|0"; + case -2: + return "2|0"; default: return "1|1"; } @@ -2845,7 +2868,7 @@ type Config = { panelSendTopic: string, timeoutScreensaver: number, dimmode: number, - //brightnessScreensaver: + active: number, locale: string, timeFormat: string, dateFormat: string, From d8c9355e51b202ed2d01de2eb079c4c8bda49f60 Mon Sep 17 00:00:00 2001 From: Armilar <102996011+Armilar@users.noreply.github.com> Date: Wed, 8 Jun 2022 13:38:12 +0200 Subject: [PATCH 10/23] BugFix: cardGrit switch (socket/lights) - Turn switches (light, socket) as before in the cardGrid --- ioBroker/NsPanelTs.ts | 50 ++++++++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/ioBroker/NsPanelTs.ts b/ioBroker/NsPanelTs.ts index a77413a4..88dfacc4 100644 --- a/ioBroker/NsPanelTs.ts +++ b/ioBroker/NsPanelTs.ts @@ -12,9 +12,9 @@ ReleaseNotes: - cardThermo (Neues Design für Alias Thermostat und zusätzlich für Alias Klimaanlage) - 08.05.2022 - Menüpfeile bei HardwareButtons (button1Page; button2Page) mit Navigation auf Page 0 - 08.05.2022 - Standard-Brightness über neuen Parameter active einstellbar (Test mit 2.9.3) + - 08.05.2022 - Schalter (Licht, Dimmer, Hue, etc) in cardGrid lassen sich wieder schalten Known-Bugs --> Bugfix folgt: - - cardGrid - Schalter funktionieren nicht - Aktion auf Submenüs schaltet unmittelbar auf vorheriges Mainmenu - Menü-Pfeile in Subpages (z.B. card QR, cardMedia, etc) @@ -144,7 +144,7 @@ var weatherForecast = true; //true = WheatherForecast 5 Days --- false = Config //Alexa-Instanz var alexaInstanz = "alexa2.0" -var alexaDevice = "G0XXXXXXXXXXXXXXX"; //Primär zu steuerndes Device oder Gruppe aus alexa2-Adapter (Seriennummer) +var alexaDevice = "G070RR1075220388"; //Primär zu steuerndes Device oder Gruppe aus alexa2-Adapter (Seriennummer) // Wenn alexaSpeakerList definiert, dann werden Einträge verwendet, sonst alle relevanten Devices aus Alexa-Instanz // Speakerwechsel funktioniert nicht bei Radio/TuneIn sonden bei Playlists @@ -251,7 +251,6 @@ var Subpages_1: PageEntities = "items": [ { navigate: true, id: "Abfall", onColor: White, name: "Abfallkalender"}, { navigate: true, id: "WLAN", onColor: White, name: "Gäste WLAN"}, - { navigate: true, id: "Buero_Seite_2", onColor: White, name: "Büro Card Grid"} ] }; @@ -270,20 +269,19 @@ var Abfall: PageEntities = ] }; -//Subpage 2 von Subpages_1 var Buero_Seite_2: PageGrid = { "type": "cardGrid", "heading": "Büro 2", "useColor": true, - "subPage": true, + "subPage": false, "items": [ { id: "alias.0.NSPanel_1.Schreibtischlampe", name: "Schreibtisch"}, { id: "alias.0.NSPanel_1.Deckenbeleuchtung", name: "Deckenlampe"}, { id: "alias.0.NSPanel_1.TestFenster", offColor: MSRed, onColor: MSGreen, name: "Büro Fenster"}, { id: "alias.0.NSPanel_1.Luftreiniger", icon: "power", offColor: MSRed, onColor: MSGreen}, { id: "alias.0.NSPanel_1.TestBlind", icon: "projector-screen", onColor: White, name: "Beamer"}, - { id: "alias.0.NSPanel_1.Radio.TuneIn", icon: "play", onColor: White} + { id: "alias.0.NSPanel_1.Radio.Bob", icon: "play", onColor: White, name: "TuneIn"} ] }; @@ -314,6 +312,7 @@ var Buero_Klimaanlage: PageThermo = "items": [{ id: "alias.0.NSPanel_1.TestKlimaanlage", minValue: 170, maxValue: 250}] }; +//Subpage 2 von Subpages_1 var WLAN: PageQR = { "type": "cardQR", @@ -438,6 +437,7 @@ export const config: Config = { defaultColor: Off, temperatureUnit: "°C", pages: [ + Buero_Seite_2, Buero_Seite_1, Buero_Klimaanlage, //WLAN, @@ -1839,7 +1839,7 @@ function setIfExists(id: string, value: any, type: string | null = null): boolea 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); + setIfExists(id, !getState(id).val); return true; } return false; @@ -1941,14 +1941,34 @@ function HandleButtonEvent(words): void { setIfExists(id + ".CLOSE", true) break; case "button": - let obj = getObject(id); - switch (obj.common.role) { - case "lock": - case "button": - toggleState(id + ".SET") ? true : toggleState(id + ".ON_SET"); - break; - case "buttonSensor": - toggleState(id + ".ACTUAL"); + if (existsObject(id)) { + var action = false + if (words[4] == "1") + action = true; + let o = getObject(id) + switch (o.common.role) { + case "lock": + case "button": + toggleState(id + ".SET") ? true : toggleState(id + ".ON_SET"); + break; + case "buttonSensor": + toggleState(id + ".ACTUAL"); + break; + case "socket": + case "light": + toggleState(id + ".SET") ? true : toggleState(id + ".ON_SET"); + break; + case "dimmer": + toggleState(id + ".ON_SET") ? true : toggleState(id + ".ON_ACTUAL"); + break; + case "ct": + toggleState(id + ".ON"); + break; + case "rgb": + case "rgbSingle": + case "hue": // Armilar + toggleState(id + ".ON_ACTUAL"); + } } break; case "positionSlider": From b9a777f09424e09a4989c7e7df42ae7a82432b50 Mon Sep 17 00:00:00 2001 From: Armilar <102996011+Armilar@users.noreply.github.com> Date: Wed, 8 Jun 2022 13:56:27 +0200 Subject: [PATCH 11/23] Update NsPanelTs.ts --- ioBroker/NsPanelTs.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ioBroker/NsPanelTs.ts b/ioBroker/NsPanelTs.ts index 88dfacc4..ba67bad3 100644 --- a/ioBroker/NsPanelTs.ts +++ b/ioBroker/NsPanelTs.ts @@ -144,7 +144,7 @@ var weatherForecast = true; //true = WheatherForecast 5 Days --- false = Config //Alexa-Instanz var alexaInstanz = "alexa2.0" -var alexaDevice = "G070RR1075220388"; //Primär zu steuerndes Device oder Gruppe aus alexa2-Adapter (Seriennummer) +var alexaDevice = "G0XXXXXXXXXXXXXXX"; //Primär zu steuerndes Device oder Gruppe aus alexa2-Adapter (Seriennummer) // Wenn alexaSpeakerList definiert, dann werden Einträge verwendet, sonst alle relevanten Devices aus Alexa-Instanz // Speakerwechsel funktioniert nicht bei Radio/TuneIn sonden bei Playlists From bea5153a54642c23400181be0cb2b152d1e39636 Mon Sep 17 00:00:00 2001 From: Armilar <102996011+Armilar@users.noreply.github.com> Date: Wed, 8 Jun 2022 14:13:28 +0200 Subject: [PATCH 12/23] Update NsPanelTs.ts --- ioBroker/NsPanelTs.ts | 1790 ++++++++++++++++++++++++++++++++++------- 1 file changed, 1502 insertions(+), 288 deletions(-) diff --git a/ioBroker/NsPanelTs.ts b/ioBroker/NsPanelTs.ts index 5f2c8dec..505015bd 100644 --- a/ioBroker/NsPanelTs.ts +++ b/ioBroker/NsPanelTs.ts @@ -1,109 +1,278 @@ /*----------------------------------------------------------------------- +TypeScript zur Steuerung des SONOFF NSPanel mit dem ioBroker +- abgestimmt auf TFT 36 / v2.9.0 / BerryDriver 4 / Tasmota 11.1.0 joBr99 Projekt: https://github.com/joBr99/nspanel-lovelace-ui/tree/main/ioBroker - NsPanelTs.ts (dieses TypeScript in ioBroker) Stable: https://github.com/joBr99/nspanel-lovelace-ui/blob/main/ioBroker/NsPanelTs.ts icon_mapping.ts: https://github.com/joBr99/nspanel-lovelace-ui/blob/main/ioBroker/icon_mapping.ts (TypeScript muss in global liegen) - -Mögliche Aliase: - Info - Werte aus Datenpunkt - Licht - An/Aus (Schalter) - Steckdose - An/Aus (Schalter) - Dimmer - An/Aus, Brightness - Farbtemperatur - An/Aus, Farbtemperatur und Brightness - HUE-Licht - Zum Schalten von Color-Leuchtmitteln über HUE-Wert, Brightness, Farbtemperatur, An/Aus (HUE kann auch fehlen) - RGB-Licht - RGB-Leuchtmitteln/Stripes welche Rot/Grün/ und Blau separat benötigen (Tasmota, WifiLight, etc.) + Brightness, Farbtemperatur - RGB-Licht-einzeln - RGB-Leuchtmitteln/Stripes welche HEX-Farbwerte benötigen (Tasmota, WifiLight, etc.) + Brightness, Farbtemperatur - Jalousien - Up, Stop, Down, Position - Fenster - Sensor open - Tür - Sensor open - Taste - Für Szenen oder Radiosender, etc. --> Nur Funktionsaufruf - Kein Taster wie MonoButton - True/False - ??? wahrscheinlich wäre Tastensensor besser geeignet, um Alias-Taste langfristig für einen MonoButton (Taster) zu verwenden ??? - Thermostat - Aktuelle Raumtemperatur, Setpoint, etc. - Feuchtigkeit - Anzeige von Humidity - Datenpunkten, ananlog Info - Medien - Steuerung von Alexa - Über Alias-Manager im Verzeichnis Player automatisch anlegen (Geräte-Manager funktioniert nicht) - Wetter - Aktuelle Außen-Temperatur und aktuelles Accu-Wheather-Icon für Screensaver +ioBroker-Unterstützung: https://forum.iobroker.net/topic/50888/sonoff-nspanel +ReleaseNotes: + Bugfixes und Erweiterungen seit letzter Verion: + - cardQR (für Gäste WLAN) + - cardThermo (Neues Design für Alias Thermostat und zusätzlich für Alias Klimaanlage) + - 08.05.2022 - Menüpfeile bei HardwareButtons (button1Page; button2Page) mit Navigation auf Page 0 + - 08.05.2022 - Standard-Brightness über neuen Parameter active einstellbar (Test mit 2.9.3) + - 08.05.2022 - Schalter (Licht, Dimmer, Hue, etc) in cardGrid lassen sich wieder schalten + Known-Bugs --> Bugfix folgt: + - Aktion auf Submenüs schaltet unmittelbar auf vorheriges Mainmenu + - Menü-Pfeile in Subpages (z.B. card QR, cardMedia, etc) + +Wenn Rule definiert, dann können die Hardware-Tasten ebenfalls für Seitensteuerung (dann nicht mehr als Releais) genutzt werden +Tasmota Konsole: + Rule2 on Button1#state do Publish %topic%/%prefix%/RESULT {"CustomRecv":"event,button1"} endon on Button2#state do Publish %topic%/%prefix%/RESULT {"CustomRecv":"event,button2"} endon + Rule2 1 (Rule aktivieren) + Rule2 0 (Rule deaktivieren) +Mögliche Seiten-Ansichten: + screensaver Page - wird nach definiertem Zeitraum (config) mit Dimm-Modus aktiv (Uhrzeit, Datum, Aktuelle Temperatur mit Symbol) + (die 4 kleineren Icons können als Wetter-Vorschau + 4Tage (Symbol + Höschsttemperatur) oder zur Anzeige definierter Infos konfiguriert werden) + cardEtities Page - 4 vertikale angeordnete Steuerelemente - auch als Subpage + cardGrid Page - 6 horizontal angeordnete Steuerelemente in 2 Reihen a 3 Steuerelemente - auch als Subpage + cardThermo Page - Thermostat mit Solltemperatur, Isttemperatur, Mode - Weitere Eigenschaften können im Alias definiert werden + cardMedia Page - Mediaplayer - Ausnahme: Alias sollte mit Alias-Manager automatisch über Alexa-Verzeichnes Player angelegt werden + cardAlarm Page - Alarmseite mit Zustand und Tastenfeld +Popup-Pages: + popupLight Page - in Abhängigkeit zum gewählten Alias werden "Helligkeit", "Farb-Temperatur" und "Farbauswahl" bereitgestellt + popupShutter Page - die Shutter-Potition (Rollo, Jalousie, Markise, Leinwand, etc.) kann über einen Slider verändert werden. + popupNotify Page - Info - Seite mit Headline Text und Buttons - Intern für manuelle Updates / Extern zur Befüllung von Datenpunkten unter 0_userdata + screensaver Notify - Über zwei externe Datenpunkte in 0_userdata können "Headline" und "Text" an den Screensaver zur Info gesendet werden +Mögliche Aliase: (Vorzugsweise mit ioBroker-Adapter "Geräte verwalten" konfigurieren, da SET, GET, ACTUAL, etc. verwendet werden) + Info - Werte aus Datenpunkt + Schieberegler - Slider numerische Werte (SET/ACTUAL) + Lautstärke: - Volume (SET/ACTUAL) und MUTE + Lautstärke-Gruppe: - analog Lautstärke + Licht - An/Aus (Schalter) + Steckdose - An/Aus (Schalter) + Dimmer - An/Aus, Brightness + Farbtemperatur - An/Aus, Farbtemperatur und Brightness + HUE-Licht - Zum Schalten von Color-Leuchtmitteln über HUE-Wert, Brightness, Farbtemperatur, An/Aus (HUE kann auch fehlen) + RGB-Licht - RGB-Leuchtmitteln/Stripes welche Rot/Grün/ und Blau separat benötigen (Tasmota, WifiLight, etc.) + Brightness, Farbtemperatur + RGB-Licht-einzeln - RGB-Leuchtmitteln/Stripes welche HEX-Farbwerte benötigen (Tasmota, WifiLight, etc.) + Brightness, Farbtemperatur + Jalousien - Up, Stop, Down, Position + Fenster - Sensor open + Tür - Sensor open + Verschluss - Türschloss SET/ACTUAL/OPEN + Taste - Für Szenen oder Radiosender, etc. --> Nur Funktionsaufruf - Kein Taster wie MonoButton - True/False + Tastensensor - analog Taste + Thermostat - Aktuelle Raumtemperatur, Setpoint, etc. + Klimaanlage - Buttons zur Steuerung der Klimaanlage im unteren Bereich + Temperatur - Anzeige von Temperture - Datenpunkten, ananlog Info + Feuchtigkeit - Anzeige von Humidity - Datenpunkten, ananlog Info + Medien - Steuerung von Alexa - Über Alias-Manager im Verzeichnis Player automatisch anlegen (Geräte-Manager funktioniert nicht) + Wettervorhersage - Aktuelle Außen-Temperatur (Temp) und aktuelles Accu-Wheather-Icon (Icon) für Screensaver +Interne Sonoff-Sensoren (über Tasmota): + ESP-Temperatur - wird in 0_userdata.0. abgelegt, kann als Alias importieert werden + Temperatur - Raumtemperatur - wird in 0_userdata.0. abgelegt, kann als Alias importieert werden + (!!! Achtung: der interne Sonoff-Sensor liefert keine exakten Daten, da das NSPanel-Board und der ESP selbst Hitze produzieren !!! + ggf. Offset einplanen oder besser einen externen Sensor über Zigbee etc. verwenden) + Timestamp - wird in 0_userdata.0. Zeitpunkt der letzten Sensorübertragung +Tasmota-Status0 - (zyklische Ausführung) + liefert relevanten Tasmota-Informationen und kann bei Bedarf in "function get_tasmota_status0()" erweitert werden. Daten werden in 0_userdata.0. abgelegt +Erforderliche Adapter: + Accu-Wheater: - Bei Nutzung der Wetterfunktionen (und zur Icon-Konvertierung) im Screensaver + Alexa2: - Bei Nutzung der dynamischen SpeakerList in der cardMedia + Geräte verwalten - Für Erstellung der Aliase + Alias-Manager - !!! ausschießlich für MEDIA-Alias + MQTT-Adapter - Für Kommunikation zwischen Skript und Tasmota + JavaScript-Adapter +Upgrades in Konsole: + Tasmota BerryDriver : Backlog UpdateDriverVersion https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be; Restart 1 + TFT EU STABLE Version : FlashNextion http://nspanel.pky.eu/lovelace-ui/github/nspanel-v2.9.0.tft --------------------------------------------------------------------------------------- */ var Icons = new IconsSelector(); -var timeoutSlider; +var timeoutSlider: any; +const NSPanel_Path = "0_userdata.0.NSPanel.1." +const Debug = false; +var manually_Update = true; 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 Red: RGB = { red: 255, green: 0, blue: 0 }; -const White: RGB = { red: 255, green: 255, blue: 255 }; -const Yellow: RGB = { red: 253, green: 216, blue: 53 }; -const Green: RGB = { red: 96, green: 176, blue: 62 } -const Brown: RGB = { red: 120, green: 80, blue: 59 } -const Gray: RGB = { red: 69, green: 69, blue: 69 } -const Off: RGB = { red: 68, green: 115, blue: 158 }; +//const Off: RGB = { red: 68, green: 115, blue: 158 }; //Blau-Off +const Off: RGB = { red: 253, green: 128, blue: 0 }; //Orange-Off - schönere Farbübergänge const On: RGB = { red: 253, green: 216, blue: 53 }; -const BatteryFull: RGB = { red: 96, green: 176, blue: 62 } -const BatteryEmpty: RGB = { red: 179, green: 45, blue: 25 } +const MSRed: RGB = { red: 251, green: 105, blue: 98 }; +const MSYellow: RGB = { red: 255, green: 235, blue: 156 }; +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 }; +//----------------------Begin Dimmode +//Screensaver nachts auf dunkel ("brightnessNight: z.B. 2") oder aus ("brightnessNight:0") +if (existsState(NSPanel_Path + "NSPanel_Dimmode_brightnessDay") == false || existsState(NSPanel_Path + "NSPanel_Dimmode_hourDay") == false || existsState(NSPanel_Path + "NSPanel_Dimmode_brightnessNight") == false || existsState(NSPanel_Path + "NSPanel_Dimmode_hourNight") == false) { + createState(NSPanel_Path + "NSPanel_Dimmode_brightnessDay", 8, {type: 'number'}, function() {setState(NSPanel_Path + "NSPanel_Dimmode_brightnessDay", 8)}); + createState(NSPanel_Path + "NSPanel_Dimmode_hourDay", 7, {type: 'number'}, function() {setState(NSPanel_Path + "NSPanel_Dimmode_hourDay", 7)}); + createState(NSPanel_Path + "NSPanel_Dimmode_brightnessNight", 1, {type: 'number'}, function() {setState(NSPanel_Path + "NSPanel_Dimmode_brightnessNight", 1)}); + createState(NSPanel_Path + "NSPanel_Dimmode_hourNight", 22, {type: 'number'}, function() {setState(NSPanel_Path + "NSPanel_Dimmode_hourNight", 22)}); +} +var vBrightnessDay = getState(NSPanel_Path + "NSPanel_Dimmode_brightnessDay").val; +var vBrightnessNight = getState(NSPanel_Path + "NSPanel_Dimmode_brightnessNight").val; +var vTimeDay = getState(NSPanel_Path + "NSPanel_Dimmode_hourDay").val; +if (vTimeDay < 10) { + var TimeDay = "0" + vTimeDay.toString() + ":00"; +} else { + var TimeDay = vTimeDay.toString() + ":00"; +} +var vTimeNight = getState(NSPanel_Path + "NSPanel_Dimmode_hourNight").val; +if (vTimeNight < 10) { + var TimeNight = "0" + vTimeNight.toString() + ":00"; +} else { + var TimeNight = vTimeNight.toString() + ":00"; +} +var timeDimMode = {dimmodeOn: true, brightnessDay: vBrightnessDay, brightnessNight: vBrightnessNight, timeDay: TimeDay, timeNight: TimeNight}; +//--------------------End Dimmode -//----Ability to choose between Accu-Weather Forcast or self-defined values in the screensaver--------------------------------- +//----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 ... -//Alexa2-Instanz +//Alexa-Instanz var alexaInstanz = "alexa2.0" -var alexaDevice = "G0XXXXXXXXXXXXXX"; //Primär zu steuendes Device -//If alexaSpeakerList is defined, then entries are used, otherwise all relevant devices from the ioBroker Alexa2 adapter -const alexaSpeakerList = []; //Example ["Echo Spot Buero","Überall","Gartenhaus","Esszimmer","Heimkino"]; +var alexaDevice = "G0XXXXXXXXXXXXXXX"; //Primär zu steuerndes Device oder Gruppe aus alexa2-Adapter (Seriennummer) + +// 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.WzDisplay.popupNotifyHeading"; -var popupNotifyText = "0_userdata.0.WzDisplay.popupNotifyText"; +var screensaverNotifyHeading = NSPanel_Path + "ScreensaverInfo.popupNotifyHeading"; +var screensaverNotifyText = NSPanel_Path + "ScreensaverInfo.popupNotifyText"; +createState(screensaverNotifyHeading, {type: 'string'}); +createState(screensaverNotifyText, {type: 'string'}); + +//Datenpunkte für Nachricht popupNotify Page +var popupNotifyHeading = NSPanel_Path + "popupNotify.popupNotifyHeading"; +var popupNotifyText = NSPanel_Path + "popupNotify.popupNotifyText"; +var popupNotifyInternalName = NSPanel_Path + "popupNotify.popupNotifyInternalName"; // Wird mit Button-Action zurückgeschrieben +var popupNotifyButton1Text = NSPanel_Path + "popupNotify.popupNotifyButton1Text"; +var popupNotifyButton2Text = NSPanel_Path + "popupNotify.popupNotifyButton2Text"; +var popupNotifySleepTimeout = NSPanel_Path + "popupNotify.popupNotifySleepTimeout"; // in sek. / wenn 0, dann bleibt die Nachricht stehen +var popupNotifyAction = NSPanel_Path + "popupNotify.popupNotifyAction"; // Antwort aus dem Panel true/false +createState(popupNotifyHeading, {type: 'string'}); +createState(popupNotifyText, {type: 'string'}); +createState(popupNotifyInternalName, {type: 'string'}); +createState(popupNotifyButton1Text, {type: 'string'}); +createState(popupNotifyButton2Text, {type: 'string'}); +createState(popupNotifySleepTimeout, {type: 'number'}); +createState(popupNotifyAction, {type: 'boolean'}); var Test_Licht: PageEntities = { "type": "cardEntities", "heading": "Color Aliase", "useColor": true, + "subPage": false, "items": [ { id: "alias.0.NSPanel_1.TestRGBLichteinzeln", name: "RGB-Licht Hex-Color", interpolateColor: true}, //{ id: "alias.0.NSPanel_1.TestFarbtemperatur", name: "Farbtemperatur", interpolateColor: true}, - { id: "alias.0.NSPanel_1.TestRGBLicht", name: "RGB-Licht", minValueBrightness: 0, maxValueBrightness: 70, interpolateColor: true}, + { id: "alias.0.NSPanel_1.TestRGBLicht", name: "RGB-Licht", minValueBrightness: 0, maxValueBrightness: 100, interpolateColor: true}, { id: "alias.0.NSPanel_1.TestCTmitHUE", name: "HUE-Licht-CT", minValueBrightness: 0, maxValueBrightness: 70, minValueColorTemp: 500, maxValueColorTemp: 6500, interpolateColor: true}, { id: "alias.0.NSPanel_1.TestHUELicht", name: "HUE-Licht-Color", minValueColorTemp: 500, maxValueColorTemp: 6500, interpolateColor: true} ] }; -var Wohnen: PageEntities = +var Test_Funktionen: PageEntities = { "type": "cardEntities", - "heading": "Haus", + "heading": "Sonstige Aliase", "useColor": true, + "subPage": false, "items": [ - { id: "alias.0.Stern", name: "Sternsteckdose"}, - { id: "alias.0.Erker"}, - { id: "alias.0.Küche", interpolateColor: true }, - { id: "alias.0.Wand" } + { id: "alias.0.NSPanel_1.TestLautstärke", offColor: MSRed /*if mute=true*/, onColor: MSGreen ,name: "Echo Spot Büro", minValue: 0, maxValue: 100}, + { id: "alias.0.NSPanel_1.TestTemperatur",name: "Temperatur außen", icon: "thermometer", onColor: White}, + { id: "alias.0.NSPanel_1.TestFeuchtigkeit", name: "Luftfeuchte außen", icon: "water-percent", unit: "%H", onColor: White}, + { id: "alias.0.NSPanel_1.TestInfo", name: "Windstärke", icon: "wind-power-outline", offColor: MSRed, onColor: MSGreen, unit: "bft", minValue: 0, maxValue: 12, interpolateColor: true, useColor: true} ] }; -var Strom: PageEntities = +var Buero_Seite_1: PageEntities = { "type": "cardEntities", - "heading": "Strom", + "heading": "Büro", "useColor": true, + "subPage": false, "items": [ - { id: "alias.0.Netz", icon: "flash", interpolateColor: true, offColor: BatteryFull, onColor: Red, minValue: -1000, maxValue: 1000 }, - { id: "alias.0.Hausverbrauch", icon: "flash", interpolateColor: true, offColor: BatteryFull, onColor: Red, maxValue: 1000 }, - { id: "alias.0.Pv", icon: "solar-power", interpolateColor: true, offColor: Off, onColor: BatteryFull, maxValue: 1000 }, - { id: "alias.0.Batterie", icon: "battery-medium", interpolateColor: true, offColor: BatteryEmpty, onColor: BatteryFull } + { id: "alias.0.NSPanel_1.Schreibtischlampe", interpolateColor: true}, + { id: "alias.0.NSPanel_1.Deckenbeleuchtung", interpolateColor: true}, + { id: "alias.0.NSPanel_1.Testlampe2", name: "Filamentlampe", minValueBrightness: 0, maxValueBrightness: 70, interpolateColor: true}, + { id: "alias.0.NSPanel_1.Luftreiniger", icon: "power", offColor: MSRed, onColor: MSGreen} ] }; -var Müll: PageEntities = +var Fenster_1: PageEntities = { "type": "cardEntities", - "heading": "Müllkalender", + "heading": "Fenster und Türen", "useColor": true, + "subPage": false, "items": [ - { id: "alias.0.WzNsPanel.Müll.Bio_Tonne" ,unit:"Tage", icon: "trash-can",onColor: Brown}, - { id: "alias.0.WzNsPanel.Müll.Graue_Tonne" ,unit:"Tage",icon: "trash-can",onColor: Gray}, - { id: "alias.0.WzNsPanel.Müll.Grüne_Tonne" ,unit:"Tage",icon: "trash-can",onColor: Green}, - { id: "alias.0.WzNsPanel.Müll.Gelbe_Tonne" ,unit:"Tage",icon: "trash-can",onColor: Yellow} + { id: "alias.0.NSPanel_1.TestFenster", offColor: MSRed, onColor: MSGreen, name: "Büro Fenster"}, + { id: "alias.0.NSPanel_1.Haustuer", offColor: MSRed, onColor: MSGreen, name: "Haustür"}, + { id: "alias.0.NSPanel_1.TestBlind", onColor: White, name: "IKEA Fyrtur"}, + { id: "alias.0.NSPanel_1.TestDoorlock", offColor: MSRed, onColor: MSGreen, name: "Türschloss"}, + ] +}; + +var Button_1: PageEntities = +{ + "type": "cardEntities", + "heading": "Button Aliase", + "useColor": true, + "subPage": false, + "items": [ + { id: "alias.0.NSPanel_1.TestTastensensor", name: "Tastensensor (FFN)"}, + { id: "alias.0.NSPanel_1.Radio.NDR2", icon: "radio", name: "Taste (NDR2)", onColor: colorRadio}, + ] +}; + +var Subpages_1: PageEntities = +{ + "type": "cardEntities", + "heading": "Test Subpages", + "useColor": true, + "subPage": false, + "items": [ + { navigate: true, id: "Abfall", onColor: White, name: "Abfallkalender"}, + { navigate: true, id: "WLAN", onColor: White, name: "Gäste WLAN"}, + ] +}; + +//Subpage 1 von Subpages_1 +var Abfall: PageEntities = +{ + "type": "cardEntities", + "heading": "Abfallkalender", + "useColor": true, + "subPage": true, + "items": [ + { id: "alias.0.NSPanel_1.Abfall.event1",icon: "trash-can"}, + { id: "alias.0.NSPanel_1.Abfall.event2",icon: "trash-can"}, + { id: "alias.0.NSPanel_1.Abfall.event3",icon: "trash-can"}, + { id: "alias.0.NSPanel_1.Abfall.event4",icon: "trash-can"} + ] +}; + +var Buero_Seite_2: PageGrid = +{ + "type": "cardGrid", + "heading": "Büro 2", + "useColor": true, + "subPage": false, + "items": [ + { id: "alias.0.NSPanel_1.Schreibtischlampe", name: "Schreibtisch"}, + { id: "alias.0.NSPanel_1.Deckenbeleuchtung", name: "Deckenlampe"}, + { id: "alias.0.NSPanel_1.TestFenster", offColor: MSRed, onColor: MSGreen, name: "Büro Fenster"}, + { id: "alias.0.NSPanel_1.Luftreiniger", icon: "power", offColor: MSRed, onColor: MSGreen}, + { id: "alias.0.NSPanel_1.TestBlind", icon: "projector-screen", onColor: White, name: "Beamer"}, + { id: "alias.0.NSPanel_1.Radio.Bob", icon: "play", onColor: White, name: "TuneIn"} ] }; @@ -112,43 +281,143 @@ var Alexa: PageMedia = "type": "cardMedia", "heading": "Alexa", "useColor": true, + "subPage": false, "items": [{ id: "alias.0.NSPanel_1.Alexa.PlayerBuero" }] }; +var Buero_Themostat: PageThermo = +{ + "type": "cardThermo", + "heading": "Test Thermostat", + "useColor": true, + "subPage": false, + "items": [{ id: "alias.0.NSPanel_1.Thermostat_Büro", minValue: 50, maxValue: 300 }] +}; + +var Buero_Klimaanlage: PageThermo = +{ + "type": "cardThermo", + "heading": "Test Klimaanlage", + "useColor": true, + "subPage": false, + "items": [{ id: "alias.0.NSPanel_1.TestKlimaanlage", minValue: 170, maxValue: 250}] +}; + +//Subpage 2 von Subpages_1 +var WLAN: PageQR = +{ + "type": "cardQR", + "heading": "Gäste WLAN", + "useColor": true, + "subPage": true, + "items": [{ id: "alias.0.NSPanel_1.Guest_Wifi" }] +}; + +var Buero_Alarm: PageAlarm = +{ + "type": "cardAlarm", + "heading": "Alarm", + "useColor": true, + "subPage": false, + "items": [{ id: "alias.0.NSPanel_1.Alarm" }] +}; + var button1Page: PageGrid = { "type": "cardGrid", "heading": "Radio", "useColor": true, + "subPage": false, "items": [ - { id: "alias.0.Radio.NJoy" }, - { id: "alias.0.Radio.Delta_Radio" }, - { id: "alias.0.Radio.NDR2" }, + { id: "alias.0.NSPanel_1.Radio.FFN", icon: "radio", name: "FFN", onColor: colorRadio}, + { id: "alias.0.NSPanel_1.Radio.Antenne" , icon: "radio", name: "Antenne Nds.", onColor: colorRadio}, + { id: "alias.0.NSPanel_1.Radio.NDR2", icon: "radio", name: "NDR2", onColor: colorRadio}, + { id: "alias.0.NSPanel_1.Radio.Bob", icon: "radio", name: "Radio BOB", onColor: colorRadio}, + { id: "alias.0.NSPanel_1.Radio.Spotify", icon: "spotify", name: "Party Playlist", onColor: colorSpotify}, + { id: "alias.0.NSPanel_1.Radio.Alexa", icon: "playlist-music", name: "Playlist 2021", onColor: colorAlexa} ] }; - var button2Page: PageEntities = { "type": "cardEntities", - "heading": "Knopf2", + "heading": "Büro", "useColor": true, + "subPage": false, "items": [ - { id: "alias.0.Schlafen" }, - { id: "alias.0.Stern" } + { id: "alias.0.NSPanel_1.Schreibtischlampe"}, + { id: "alias.0.NSPanel_1.Deckenbeleuchtung"} + ] +}; + +//Subpages 2 (+ Info) +var Service: PageEntities = +{ + "type": "cardEntities", + "heading": "NSPanel Service", + "useColor": true, + "subPage": false, + "items": [ + { id: "alias.0.NSPanel_1.NSPanel_AutoUpdate", name: "Auto-Updates" ,icon: "update", offColor: MSRed, onColor: MSGreen}, + { navigate: true, id: "NSPanel_Infos", icon: "information-outline", onColor: White, name: "NSPanel Infos"}, + { navigate: true, id: "NSPanel_Firmware_Updates", icon: "update", onColor: White, name: "Manuelle-Updates"}, + { navigate: true, id: "NSPanel_Einstellungen", icon: "wrench-outline", onColor: White, name: "Einstellungen"} + ] +}; + +//Subpage 1 von Subpages_2 +var NSPanel_Infos: PageEntities = +{ + "type": "cardEntities", + "heading": "NSPanel Infos", + "useColor": true, + "subPage": true, + "items": [ + { id: "alias.0.NSPanel_1.NSPanel_Hardware", name: "Hardware", icon: "memory", offColor: MSYellow, onColor: MSYellow, useColor: true}, + { id: "alias.0.NSPanel_1.NSPanel_ESP_Temp", name: "ESP Temperatur", icon: "thermometer", unit: "°C", offColor: MSYellow, onColor: MSYellow, useColor: true}, + { id: "alias.0.NSPanel_1.NSPanel_UpTime", name: "Uptime", icon: "timeline-clock-outline", offColor: MSYellow, onColor: MSYellow, useColor: true}, + { id: "alias.0.NSPanel_1.NSPanel_RSSI", name: "Wifi-Signal", icon: "signal-distance-variant", unit: "dBm", offColor: MSYellow, onColor: MSYellow, useColor: true} + ] +}; + +//Subpage 2 von Subpages_2 +var NSPanel_Einstellungen: PageEntities = +{ + "type": "cardEntities", + "heading": "Screensaver", + "useColor": true, + "subPage": true, + "items": [ + { id: "alias.0.NSPanel_1.Dimmode_BrightnessDay", name: "Brightness Tag", icon: "brightness-5", offColor: MSYellow, onColor: MSYellow, useColor: true, minValue: 5, maxValue: 10}, + { id: "alias.0.NSPanel_1.Dimmode_BrightnessNight", name: "Brightness Nacht", icon: "brightness-4", offColor: MSYellow, onColor: MSYellow, useColor: true, minValue: 0, maxValue: 4}, + { id: "alias.0.NSPanel_1.Dimmode_HourDay", name: "Stunde Tag", icon: "sun-clock", offColor: MSYellow, onColor: MSYellow, useColor: true, minValue: 0, maxValue: 23}, + { id: "alias.0.NSPanel_1.Dimmode_HourNight", name: "Stunde Nacht", icon: "sun-clock-outline", offColor: MSYellow, onColor: MSYellow, useColor: true, minValue: 0, maxValue: 23} + ] +}; + +//Subpage 3 von Subpages_2 +var NSPanel_Firmware_Updates: PageEntities = +{ + "type": "cardEntities", + "heading": "Firmware-Updates", + "useColor": true, + "subPage": true, + "items": [ + { id: "alias.0.NSPanel_1.Tasmota_Version", name: "Tasmota Firmware", useColor: true}, + { id: "alias.0.NSPanel_1.TFT_Firmware", name: "TFT-Firmware", useColor: true}, ] }; export const config: Config = { - panelRecvTopic: "mqtt.0.tele.WzDisplay.RESULT", - panelSendTopic: "mqtt.0.cmnd.WzDisplay.CustomSend", - firstScreensaverEntity: { ScreensaverEntity: "alias.0.Wetter.HUMIDITY", ScreensaverEntityIcon: "water-percent", ScreensaverEntityText: "Luft", ScreensaverEntityUnitText: "%" }, - secondScreensaverEntity: { ScreensaverEntity: "alias.0.Wetter.PRECIPITATION_CHANCE", ScreensaverEntityIcon: "weather-pouring", ScreensaverEntityText: "Regen", ScreensaverEntityUnitText: "%" }, - thirdScreensaverEntity: { ScreensaverEntity: "alias.0.Batterie.ACTUAL", ScreensaverEntityIcon: "battery-medium", ScreensaverEntityText: "Batterie", ScreensaverEntityUnitText: "%" }, - fourthScreensaverEntity: { ScreensaverEntity: "alias.0.Pv.ACTUAL", ScreensaverEntityIcon: "solar-power", ScreensaverEntityText: "PV", ScreensaverEntityUnitText: "W" }, + 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, - active: 100, + active: 100, //Standard-Brightness TFT screenSaverDoubleClick: false, locale: "de_DE", timeFormat: "%H:%M", @@ -159,28 +428,58 @@ export const config: Config = { defaultColor: Off, temperatureUnit: "°C", pages: [ - //Test_Licht, - Wohnen, - Strom, - Müll, + Buero_Seite_2, + Buero_Seite_1, + Buero_Klimaanlage, + //WLAN, + Button_1, + Test_Licht, + Test_Funktionen, + Fenster_1, + Subpages_1, Alexa, - { - "type": "cardThermo", - "heading": "Thermostat", - "useColor": true, - "items": [{ id: "alias.0.WzNsPanel", name: "Wohnzimmer" }] - } + Buero_Themostat, + Buero_Alarm, + Service ], button1Page: button1Page, button2Page: button2Page }; -// _________________________________ End configuration _____________________________________ +// _________________________________ Ab hier keine Konfiguration mehr _____________________________________ + +//Notification an Screensaver +on({id: [screensaverNotifyHeading, screensaverNotifyText], change: "ne"}, async function (obj) { + setState(config.panelSendTopic,(['notify~',getState(screensaverNotifyHeading).val,'~',getState(screensaverNotifyText).val].join(''))); +}); + +//popupNotify - Notification an separate Seite +on({id: [popupNotifyInternalName, popupNotifyHeading, popupNotifyText, popupNotifyButton1Text, popupNotifyButton2Text, popupNotifySleepTimeout], change: "ne"}, async function (obj) { + var notification = "entityUpdateDetail" + "~" + + getState(popupNotifyInternalName).val + "~" + + getState(popupNotifyHeading).val + "~" + + "65504" + "~" //Farbe Headline - gelb + + getState(popupNotifyButton1Text).val + "~" + + "63488" + "~" //Farbe Button1 - rot + + getState(popupNotifyButton2Text).val + "~" + + "2016" + "~" //Farbe Button2 - grün + + getState(popupNotifyText).val + "~" + + "65535" + "~" //Farbe Text - weiß + + getState(popupNotifySleepTimeout).val; + clearTimeout(timer); + var timer = setTimeout(function() { + setState(config.panelSendTopic, "pageType~popupNotify"); + setState(config.panelSendTopic, notification); + }, 500); +}); var subscriptions: any = {}; var screensaverEnabled : boolean = false; var pageId = 0; +//Neu für Subpages +var subPage_open = false; + schedule("* * * * *", function () { SendTime(); }); @@ -188,8 +487,288 @@ schedule("0 * * * *", function () { SendDate(); }); +//3:30 Uhr Startup durchführen und aktuelle TFT-Version empfangen +schedule({hour: 3, minute: 30}, function () { + setState(config.panelSendTopic, 'pageType~pageStartup'); +}); + +//´timeDimMode Day +schedule({hour: getState(NSPanel_Path+ "NSPanel_Dimmode_hourDay").val, minute: 0}, function () { + ScreensaverDimmode(); +}); + +//´timeDimMode Night +schedule({hour: getState(NSPanel_Path+ "NSPanel_Dimmode_hourNight").val, minute: 0}, function () { + ScreensaverDimmode(); +}); + +//Updates vergleichen aktuell alle 30 Minuten +schedule("*/30 * * * *", function () { + get_tasmota_status0(); + get_panel_update_data(); + check_updates(); +}); + +//Mit Start auf Updates checken +setState(config.panelSendTopic, 'pageType~pageStartup'); +get_tasmota_status0() +get_panel_update_data(); +check_updates(); + +//------------------Begin Update Functions +function check_updates() { + + const desired_display_firmware_version = 36; + const berry_driver_version = 4; + + if (Debug) console.log("Check-Updates"); + //Tasmota-Firmware-Vergleich + if (existsObject(NSPanel_Path + "Tasmota_Firmware.currentVersion") && existsObject(NSPanel_Path + "Tasmota_Firmware.onlineVersion")) { + if (getState(NSPanel_Path + "Tasmota_Firmware.currentVersion").val !== getState(NSPanel_Path + "Tasmota_Firmware.onlineVersion").val) { + if (existsState(NSPanel_Path + "NSPanel_autoUpdate")) { + if (getState(NSPanel_Path + "NSPanel_autoUpdate").val) { + if (Debug) console.log("Auto-Updates eingeschaltet - Update wird durchgeführt"); + //Tasmota Upgrade durchführen + update_tasmota_firmware() + //Aktuelle Tasmota Version = Online Tasmota Version + setState(NSPanel_Path + "Tasmota_Firmware.currentVersion", getState(NSPanel_Path + "Tasmota_Firmware.onlineVersion").val); + } else { + //Auf Tasmota-Updates hinweisen + if (Debug) console.log("Automatische Updates aus"); + let Path = NSPanel_Path + 'popupNotify.'; + let InternalName = 'TasmotaFirmwareUpdate'; + let Headline = 'Tasmota-Firmware Update'; + let Text = ['Es ist eine neue Version der Tasmota-Firmware','\r\n','verfügbar','\r\n','\r\n','Installierte Version: ' + String(getState((String(NSPanel_Path) + 'Tasmota_Firmware.currentVersion')).val),'\r\n','Verfügbare Version: ' + String(getState((String(NSPanel_Path) + 'Tasmota_Firmware.onlineVersion')).val),'\r\n','\r\n','Upgrade durchführen?'].join(''); + let Button1 = 'Nein'; + let Button2 = 'Ja'; + let Timeout = 0; + setStateDelayed((String(Path) + 'popupNotifyHeading'), Headline, false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifyText'), ([formatDate(getDateObject((new Date().getTime())), "TT.MM.JJJJ SS:mm:ss"),'\r\n','\r\n',Text].join('')), false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifyButton1Text'), Button1, false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifyButton2Text'), Button2, false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifySleepTimeout'), Timeout, false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifyInternalName'), InternalName, false, parseInt(((0) || "").toString(), 60000), false); + } + } + } else { + if (Debug) console.log("Tasmota-Version auf NSPanel aktuell"); + } + } + //Tasmota-Berry-Driver-Vergleich + if (existsObject(NSPanel_Path + "Berry_Driver.currentVersion")) { + if (getState(NSPanel_Path + "Berry_Driver.currentVersion").val < berry_driver_version) { + if (existsState(NSPanel_Path + "NSPanel_autoUpdate")) { + if (getState(NSPanel_Path + "NSPanel_autoUpdate").val) { + //Tasmota Berry-Driver Update durchführen + update_berry_driver_version() + //Aktuelle Berry-Driver Version = Online Berry-Driver Version + setState(NSPanel_Path + "Berry_Driver.currentVersion", getState(NSPanel_Path + "Berry_Driver.onlineVersion").val); + if (Debug) console.log("Berry-Driver automatisch aktualisiert"); + } else { + //Auf BerryDriver-Update hinweisen + if (Debug) console.log("Automatische Updates aus"); + let Path = NSPanel_Path + 'popupNotify.'; + let InternalName = 'BerryDriverUpdate'; + let Headline = 'Berry-Driver Update'; + let Text = ['Es ist eine neue Version des Berry-Drivers','\r\n','(Tasmota) verfügbar','\r\n','\r\n','Installierte Version: ' + String(getState((String(NSPanel_Path) + 'Berry_Driver.currentVersion')).val),'\r\n','Verfügbare Version: ' + String(berry_driver_version),'\r\n','\r\n','Upgrade durchführen?'].join(''); + let Button1 = 'Nein'; + let Button2 = 'Ja'; + let Timeout = 0; + setStateDelayed((String(Path) + 'popupNotifyHeading'), Headline, false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifyText'), ([formatDate(getDateObject((new Date().getTime())), "TT.MM.JJJJ SS:mm:ss"),'\r\n','\r\n',Text].join('')), false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifyButton1Text'), Button1, false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifyButton2Text'), Button2, false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifySleepTimeout'), Timeout, false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifyInternalName'), InternalName, false, parseInt(((0) || "").toString(), 60000), false); + } + } + } else { + if (Debug) console.log("Berry-Driver auf NSPanel aktuell"); + } + } + //TFT-Firmware-Vergleich + if (existsObject(NSPanel_Path + "Display_Firmware.currentVersion")) { + if (parseInt(getState(NSPanel_Path + "Display_Firmware.currentVersion").val) !== desired_display_firmware_version) { + if (existsState(NSPanel_Path + "NSPanel_autoUpdate")) { + if (getState(NSPanel_Path + "NSPanel_autoUpdate").val) { + //TFT-Firmware Update durchführen + update_tft_firmware() + //Aktuelle TFT-Firmware Version = Online TFT-Firmware Version + setState(NSPanel_Path + "Display_Firmware.currentVersion", getState(NSPanel_Path + "Display_Firmware.onlineVersion").val); + + if (Debug) console.log("Display_Firmware automatisch aktualisiert"); + } else { + //Auf TFT-Firmware hinweisen + if (Debug) console.log("Automatische Updates aus"); + let Path = NSPanel_Path + 'popupNotify.'; + let InternalName = 'TFTFirmwareUpdate'; + let Headline = 'TFT-Firmware Update'; + let Text = ['Es ist eine neue Version der TFT-Firmware','\r\n','verfügbar','\r\n','\r\n','Installierte Version: ' + String(getState((String(NSPanel_Path) + 'Display_Firmware.currentVersion')).val),'\r\n','Verfügbare Version: ' + String(desired_display_firmware_version),'\r\n','\r\n','Upgrade durchführen?'].join(''); + let Button1 = 'Nein'; + let Button2 = 'Ja'; + let Timeout = 0; + setStateDelayed((String(Path) + 'popupNotifyHeading'), Headline, false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifyText'), ([formatDate(getDateObject((new Date().getTime())), "TT.MM.JJJJ SS:mm:ss"),'\r\n','\r\n',Text].join('')), false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifyButton1Text'), Button1, false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifyButton2Text'), Button2, false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifySleepTimeout'), Timeout, false, parseInt(((0) || "").toString(), 60000), false); + setStateDelayed((String(Path) + 'popupNotifyInternalName'), InternalName, false, parseInt(((0) || "").toString(), 60000), false); + } + } + } else { + if (Debug) console.log("Display_Firmware auf NSPanel aktuell"); + } + } +} + +on({id: [].concat([NSPanel_Path + 'popupNotify.popupNotifyAction']), change: "any"}, async function (obj) { + if ((obj.state ? obj.state.val : "") == false) { + manually_Update = false + if (Debug) console.log('Es wurde Button1 gedrückt'); + } else if ((obj.state ? obj.state.val : "") == true) { + if (manually_Update) { + if (getState(NSPanel_Path + "popupNotify.popupNotifyInternalName").val = "TasmotaFirmwareUpdate") { + update_tasmota_firmware(); + } else if (getState(NSPanel_Path + "popupNotify.popupNotifyInternalName").val = "BerryDriverUpdate") { + update_berry_driver_version(); + } else if (getState(NSPanel_Path + "popupNotify.popupNotifyInternalName").val = "TFTFirmwareUpdate") { + update_tft_firmware(); + } + } + if (Debug) console.log('Es wurde Button2 gedrückt'); + } +}); + +function get_panel_update_data() { + createState(NSPanel_Path + "NSPanel_autoUpdate", false, {read: true, write: true, name: "Auto-Updater", type: "boolean", def: false}); + createState(NSPanel_Path + "NSPanel_ipAddress"); + setIfExists(NSPanel_Path + "NSPanel_ipAddress", get_current_tasmota_ip_address()); + get_online_tasmota_firmware_version(); + get_current_berry_driver_version(); + get_online_berry_driver_version(); + check_version_tft_firmware(); + check_online_display_firmware(); +} + +function get_current_tasmota_ip_address() { + let mqttInfo2 = config.panelRecvTopic.substring(0, config.panelRecvTopic.length - 6) + "INFO2"; + let Tasmota_Info2 = JSON.parse(getState(mqttInfo2).val); + return Tasmota_Info2.Info2.IPAddress; +} + +function get_online_tasmota_firmware_version() { + exec('curl -X GET -k \'https://api.github.com/repositories/80286288/releases/latest\'', function (error, result, stderr){ //GitAPI aufruf für JSON Inhalt von Latest Tasmota Release + var Tasmota_JSON = JSON.parse(result) //JSON Resultat in Variable Schreiben + var TasmotaTagName = Tasmota_JSON.tag_name //JSON nach "tag_name" filtern und in Variable schreiben + var TasmotaVersionOnline = TasmotaTagName.replace(/v/i, ""); //Aus Variable überflüssiges "v" filtern und in Release-Variable schreiben + createState(NSPanel_Path + "Tasmota_Firmware.onlineVersion"); + setIfExists(NSPanel_Path + "Tasmota_Firmware.onlineVersion", TasmotaVersionOnline); + }); +} + +function get_current_berry_driver_version() { + require("request")((['http://',get_current_tasmota_ip_address(),'/cm?cmnd=GetDriverVersion'].join('')), async function (error, response, result) { + createState(NSPanel_Path + "Berry_Driver.currentVersion"); + setIfExists(NSPanel_Path + 'Berry_Driver.currentVersion', getAttr(result, 'nlui_driver_version')); + }); +} + +function get_tasmota_status0() { + require("request")((['http://',get_current_tasmota_ip_address(),'/cm?cmnd=Status0'].join('')), async function (error, response, result) { + createState(NSPanel_Path + "Tasmota_Firmware.currentVersion"); + createState(NSPanel_Path + "Tasmota.Uptime"); + createState(NSPanel_Path + "Tasmota.Version"); + createState(NSPanel_Path + "Tasmota.Hardware"); + createState(NSPanel_Path + "Tasmota.Wifi.AP"); + createState(NSPanel_Path + "Tasmota.Wifi.SSId"); + createState(NSPanel_Path + "Tasmota.Wifi.BSSId"); + createState(NSPanel_Path + "Tasmota.Wifi.Channel"); + createState(NSPanel_Path + "Tasmota.Wifi.Mode"); + createState(NSPanel_Path + "Tasmota.Wifi.RSSI"); + createState(NSPanel_Path + "Tasmota.Wifi.Signal"); + + var Tasmota_JSON = JSON.parse(result) + let tasmoVersion = Tasmota_JSON.StatusFWR.Version.split("("); + setIfExists(NSPanel_Path + "Tasmota_Firmware.currentVersion", tasmoVersion[0]); + setIfExists(NSPanel_Path + "Tasmota.Uptime", Tasmota_JSON.StatusPRM.Uptime); + setIfExists(NSPanel_Path + "Tasmota.Version", Tasmota_JSON.StatusFWR.Version); + setIfExists(NSPanel_Path + "Tasmota.Hardware", Tasmota_JSON.StatusFWR.Hardware); + setIfExists(NSPanel_Path + "Tasmota.Wifi.AP", Tasmota_JSON.StatusSTS.Wifi.AP); + setIfExists(NSPanel_Path + "Tasmota.Wifi.SSId", Tasmota_JSON.StatusSTS.Wifi.SSId); + setIfExists(NSPanel_Path + "Tasmota.Wifi.BSSId", Tasmota_JSON.StatusSTS.Wifi.BSSId); + setIfExists(NSPanel_Path + "Tasmota.Wifi.Channel", Tasmota_JSON.StatusSTS.Wifi.Channel); + setIfExists(NSPanel_Path + "Tasmota.Wifi.Mode", Tasmota_JSON.StatusSTS.Wifi.Mode); + setIfExists(NSPanel_Path + "Tasmota.Wifi.RSSI", Tasmota_JSON.StatusSTS.Wifi.RSSI); + setIfExists(NSPanel_Path + "Tasmota.Wifi.Signal", Tasmota_JSON.StatusSTS.Wifi.Signal); + }); +} + +function get_online_berry_driver_version() { + exec('curl https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be', function (error, result, stderr){ + if (result) { + let BerryDriverVersionOnline = result.substring((result.indexOf("version_of_this_script = ") + 24), result.indexOf("version_of_this_script = ") + 27).replace(/\s+/g, ''); + createState(NSPanel_Path + "Berry_Driver.onlineVersion"); + setIfExists(NSPanel_Path + 'Berry_Driver.onlineVersion', BerryDriverVersionOnline); + } + }); +} + +function check_version_tft_firmware() { + exec('curl -X GET -k \'https://api.github.com/repos/joBr99/nspanel-lovelace-ui/releases/latest\'', function (error, result, stderr){ //GitAPI aufruf für JSON Inhalt von Latest Tasmota Release + var NSPanel_JSON = JSON.parse(result) //JSON Resultat in Variable Schreiben + var NSPanelTagName = NSPanel_JSON.tag_name //created_at; published_at; name ; draft ; prerelease + var NSPanelVersion = NSPanelTagName.replace(/v/i, ""); //Aus Variable überflüssiges "v" filtern und in Release-Variable schreiben + createState(NSPanel_Path + "TFT_Firmware.onlineVersion"); + setIfExists(NSPanel_Path + 'TFT_Firmware.onlineVersion', NSPanelVersion); + }); +} + +function check_online_display_firmware() { + exec('curl https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/apps/nspanel-lovelace-ui/nspanel-lovelace-ui.py', function (error, result, stderr){ + if (result) { + let desired_display_firmware_version = result.substring((result.indexOf("desired_display_firmware_version =") + 34), result.indexOf("desired_display_firmware_version =") + 38).replace(/\s+/g, ''); + createState(NSPanel_Path + "Display_Firmware.onlineVersion"); + setIfExists(NSPanel_Path + 'Display_Firmware.onlineVersion', desired_display_firmware_version); + } + }); +} + +on({ id: config.panelRecvTopic }, function (obj) { + if (obj.state.val.startsWith('\{"CustomRecv":')) { + var json = JSON.parse(obj.state.val); + var split = json.CustomRecv.split(","); + if (split[0] == "event" && split[1] == "startup") { + createState(NSPanel_Path + 'Display_Firmware.currentVersion',{ type:'string'}); + createState(NSPanel_Path + 'NSPanel_Version',{ type:'string'}); + setIfExists(NSPanel_Path + 'Display_Firmware.currentVersion',split[2]); + setIfExists(NSPanel_Path + 'NSPanel_Version',split[3]); + } + } +}); + +function update_berry_driver_version() { + require("request")((['http://',get_current_tasmota_ip_address(),'/cm?cmnd=Backlog UpdateDriverVersion https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be; Restart 1'].join('')), async function (error, response, result) { + }); +} + +function update_tft_firmware() { + const tft_version : string = "v2.9.0"; + var desired_display_firmware_url = "http://nspanel.pky.eu/lovelace-ui/github/nspanel-" + tft_version + ".tft" + require("request")((['http://',get_current_tasmota_ip_address(),'/cm?cmnd=FlashNextion ', desired_display_firmware_url].join('')), async function (error, response, result) { + createState(NSPanel_Path + "TFT_Firmware.onlineVersion"); + setIfExists(NSPanel_Path + 'TFT_Firmware.onlineVersion', tft_version); + }); +} + +function update_tasmota_firmware() { + require("request")((['http://',get_current_tasmota_ip_address(),'/cm?cmnd=Upgrade 1'].join('')), async function (error, response, result) { + }); +} +//------------------End Update Functions + // 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) } @@ -202,12 +781,12 @@ if (config.thirdScreensaverEntity !== null && config.thirdScreensaverEntity.Scre 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); @@ -221,12 +800,20 @@ function SendToPanel(val: Payload | Payload[]): void { if (Array.isArray(val)) { val.forEach(function (id, i) { setState(config.panelSendTopic, id.payload); + if (Debug) console.log(id.payload); }); } else setState(config.panelSendTopic, val.payload); } + +on({id: [].concat([NSPanel_Path + 'Alarm.AlarmState']), change: "ne"}, async function (obj) { + if ((obj.state ? obj.state.val : "") == 'armed' || (obj.state ? obj.state.val : "") == 'disarmed' || (obj.state ? obj.state.val : "") == 'triggered') { + GeneratePage(config.pages[8]); //----------- muss noch dynamisch gefunden werden ------------------------------------------- + } +}); + function HandleMessage(typ: string, method: string, page: number, words: Array): void { if (typ == "event") { switch (method) { @@ -239,7 +826,7 @@ function HandleMessage(typ: string, method: string, page: number, words: Arraypage)); break; + case "cardAlarm": + SendToPanel(GenerateAlarmPage(page)); + break; + case "cardQR": + SendToPanel(GenerateQRPage(page)); + break; } } function HandleHardwareButton(method: string): void { - let page: (PageThermo | PageMedia | PageEntities | PageGrid); + let page: (PageThermo | PageMedia | PageAlarm | PageEntities | PageGrid | PageQR); if (config.button1Page !== null && method == "button1") { page = config.button1Page; pageId = -1; @@ -300,7 +894,7 @@ function HandleStartupProcess(): void { SendDate(); SendTime(); SendToPanel({ payload: "timeout~" + config.timeoutScreensaver }); - SendToPanel({ payload: "dimmode~" + config.dimmode + "~" + config.active }); + SendToPanel({ payload: "dimmode~" + config.dimmode + "~" + config.active}); } function SendDate(): void { @@ -327,6 +921,18 @@ function SendTime(): void { SendToPanel({ payload: "time~" + hr + ":" + min }); } +function ScreensaverDimmode() { + if (timeDimMode.dimmodeOn != undefined ? timeDimMode.dimmodeOn : false) { + if (compareTime(timeDimMode.timeNight != undefined ? timeDimMode.timeNight : "23:00", timeDimMode.timeDay != undefined ? timeDimMode.timeDay : "06:00", "not between", null)) { + SendToPanel({ payload: "dimmode~" + timeDimMode.brightnessDay}); + } else { + SendToPanel({ payload: "dimmode~" + timeDimMode.brightnessNight}); + } + } else { + SendToPanel({ payload: "dimmode~" + config.dimmode }); + } +} + function GenerateEntitiesPage(page: PageEntities): Payload[] { var out_msgs: Array = []; out_msgs = [{ payload: "pageType~cardEntities" }] @@ -347,9 +953,15 @@ function GeneratePageElements(page: Page): string { case "cardThermo": maxItems = 1; break; + case "cardAlarm": + maxItems = 1; + break; case "cardMedia": maxItems = 1; break; + case "cardQR": + maxItems = 1; + break; case "cardEntities": maxItems = 4; break; @@ -357,14 +969,25 @@ function GeneratePageElements(page: Page): string { maxItems = 6; break; } - let pageData = "entityUpd~" + page.heading + "~" + GetNavigationString(pageId) + + let pageData = "entityUpd~" + page.heading + "~" + GetNavigationString(pageId); + +//--------------------------------------Subpage---------------- + if (page.subPage) { + subPage_open = true; + pageData = "entityUpd~" + page.heading + "~" + "1|0"; + } +//--------------------------------------------------------- for (let index = 0; index < maxItems; index++) { if (page.items[index] !== undefined) { pageData += CreateEntity(page.items[index], index + 1, page.useColor); } +/* else { - pageData += CreateEntity({ id: "delete" }, index + 1); + pageData += CreateEntity({ id: "delete" }, index + 1); + //muss das wirklich? Wo erforderlich wird es mitgegeben! } +*/ } return pageData; } @@ -376,11 +999,21 @@ function CreateEntity(pageItem: PageItem, placeId: number, useColors: boolean = } var name: string; var type: string; + // ioBroker - if (existsObject(pageItem.id)) { + if (existsObject(pageItem.id) || pageItem.navigate === true) { + var iconColor = rgb_dec565(config.defaultColor); + + if (pageItem.navigate) { + type = "button"; + iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("gesture-tap-button"); + iconColor = GetIconColor(pageItem, true, useColors); + let buttonText = pageItem.buttonText !== undefined ? pageItem.buttonText : "PRESS"; + return "~" + type + "~" + "navigate." + pageItem.id + "~" + iconId + "~" + iconColor + "~" + pageItem.name + "~" + buttonText; + } + 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; @@ -390,13 +1023,15 @@ function CreateEntity(pageItem: PageItem, placeId: number, useColors: boolean = val = getState(pageItem.id + ".SET").val; RegisterEntityWatcher(pageItem.id + ".SET"); } - var iconColor = rgb_dec565(config.defaultColor); + + name = pageItem.name !== undefined ? pageItem.name : o.common.name.de switch (o.common.role) { - case "socket": + 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"); + 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") { @@ -429,7 +1064,7 @@ function CreateEntity(pageItem: PageItem, placeId: number, useColors: boolean = let huecolor = hsv2rgb(getState(pageItem.id + ".HUE").val,1,1); let 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); + //RegisterDetailEntityWatcher(id + ".HUE"); } } @@ -509,7 +1144,7 @@ function CreateEntity(pageItem: PageItem, placeId: number, useColors: boolean = } return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + optVal; - + case "dimmer": type = "light" iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("lightbulb"); @@ -528,15 +1163,15 @@ function CreateEntity(pageItem: PageItem, placeId: number, useColors: boolean = } 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")) { @@ -553,12 +1188,19 @@ function CreateEntity(pageItem: PageItem, placeId: number, useColors: boolean = RegisterEntityWatcher(pageItem.id + ".ACTUAL"); } return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + windowState; - + case "info": + case "humidity": + + case "temperature": + case "value.temperature": + case "value.humidity": - case "sensor.door": + + case "sensor.door": + case "sensor.window": case "thermostat": @@ -585,18 +1227,92 @@ function CreateEntity(pageItem: PageItem, placeId: number, useColors: boolean = return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + optVal + " " + unit; + case "buttonSensor": 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; + let buttonText = pageItem.buttonText !== undefined ? pageItem.buttonText : "PRESS"; + return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + buttonText; + + case "lock": + type = "button"; + iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("lock"); + iconColor = GetIconColor(pageItem, true, useColors); + + if (existsState(pageItem.id + ".ACTUAL")) { + if (getState(pageItem.id + ".ACTUAL").val) { + iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("lock"); + iconColor = GetIconColor(pageItem, true, useColors); + var lockState = "UNLOCK" + } else { + iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("lock-open-variant"); + iconColor = GetIconColor(pageItem, false, useColors); + var lockState = "LOCK" + } + RegisterEntityWatcher(pageItem.id + ".ACTUAL"); + } + + return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + lockState; + + case "slider": + type = "number"; + iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("plus-minus-variant"); + if (existsState(pageItem.id + ".SET")) { + val = getState(pageItem.id + ".SET").val; + RegisterEntityWatcher(pageItem.id + ".SET"); + } + if (existsState(pageItem.id + ".ACTUAL")) { + val = getState(pageItem.id + ".ACTUAL").val; + RegisterEntityWatcher(pageItem.id + ".ACTUAL"); + } + + iconColor = GetIconColor(pageItem, false, useColors) + + return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + val + "|" + pageItem.minValue + "|" + pageItem.maxValue; + + case "volumeGroup": + case "volume": + type = "number"; + if (existsState(pageItem.id + ".SET")) { + val = getState(pageItem.id + ".SET").val; + RegisterEntityWatcher(pageItem.id + ".SET"); + } + if (existsState(pageItem.id + ".ACTUAL")) { + val = getState(pageItem.id + ".ACTUAL").val; + RegisterEntityWatcher(pageItem.id + ".ACTUAL"); + } + + iconColor = GetIconColor(pageItem, false, useColors) + if (existsState(pageItem.id + ".MUTE")) { + getState(pageItem.id + ".MUTE").val ? iconColor = GetIconColor(pageItem, false, useColors) : iconColor = GetIconColor(pageItem, true, useColors); + RegisterEntityWatcher(pageItem.id + ".MUTE"); + } + + if (val > 0 && val <= 33 && !getState(pageItem.id + ".MUTE").val) { + iconId = Icons.GetIcon("volume-low"); + } else if (val > 33 && val <= 66 && !getState(pageItem.id + ".MUTE").val) { + iconId = Icons.GetIcon("volume-medium"); + } else if (val > 66 && val <= 100 && !getState(pageItem.id + ".MUTE").val) { + iconId = Icons.GetIcon("volume-high"); + } else { + iconId = Icons.GetIcon("volume-mute"); + } + + return "~" + type + "~" + pageItem.id + "~" + iconId + "~" + iconColor + "~" + name + "~" + val + "|" + pageItem.minValue + "|" + pageItem.maxValue; + + 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~~~~~" } @@ -617,7 +1333,7 @@ function GetIconColor(pageItem: PageItem, value: (boolean | number), useColors: )); } - if ((pageItem.useColor || useColors) && ((typeof (value) === "boolean" && value) || value > (pageItem.minValueBrightness !== undefined ? pageItem.minValueBrightness : 0) || value > (pageItem.minValue !== undefined ? pageItem.minValue : 0))) { + 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) } @@ -638,7 +1354,6 @@ function RegisterEntityWatcher(id: string): void { })) } - function RegisterDetailEntityWatcher(id: string, pageItem: PageItem, type: string): void { if (subscriptions.hasOwnProperty(id)) { return; @@ -671,166 +1386,232 @@ function GenerateThermoPage(page: PageThermo): Payload[] { // ioBroker if (existsObject(id)) { let o = getObject(id) - let name = page.items[0].name !== undefined ? page.items[0].name : o.common.name.de + let name = page.heading !== undefined ? page.heading : o.common.name.de let currentTemp = 0; if (existsState(id + ".ACTUAL")) - currentTemp = (Math.round(parseFloat(getState(id + ".ACTUAL").val) * 10)/10)*10; + currentTemp = (Math.round(parseFloat(getState(id + ".ACTUAL").val) * 10)/10); let destTemp = 0; if (existsState(id + ".SET")) { destTemp = getState(id + ".SET").val.toFixed(2) * 10; } - + let statusStr : String = "MANU" let status = "" if (existsState(id + ".MODE")) status = getState(id + ".MODE").val; - let minTemp = 180 //Min Temp 5°C - let maxTemp = 300 //Max Temp 30°C + + let minTemp = page.items[0].minValue !== undefined ? page.items[0].minValue : 50; //Min Temp 5°C + let maxTemp = page.items[0].maxValue !== undefined ? page.items[0].maxValue : 300; //Max Temp 30°C let stepTemp = 5 - //Dynamically add attributes if defined in alias - var thermButton = 0; + //Attribute hinzufügen, wenn im Alias definiert let i_list = Array.prototype.slice.apply($('[state.id="' + id + '.*"]')); if ((i_list.length - 3) != 0) { - console.log(i_list.length -3) - if ((i_list.length -3)%2 == 0) { - if ((i_list.length - 3) == 2) { - thermButton = 6; - } else { - thermButton = 5; - } - } else { - if ((i_list.length - 3) == 1) { - thermButton = 2; - } else if ((i_list.length - 3) == 3) { - thermButton = 1; - } else { - thermButton = 0; - } - } - + var i = 0; - var bt = ["","","","","","","","",""]; - for (i = 0; i < thermButton; i++) { - bt[i] = "~~~~"; - } - for (let i_index in i_list) { - let thermostatState = i_list[i_index].split('.'); - if (thermostatState[thermostatState.length-1] != "SET" && thermostatState[thermostatState.length-1] != "ACTUAL" && thermostatState[thermostatState.length-1] != "MODE") { - i++; - - switch (thermostatState[thermostatState.length-1]) { - case "HUMIDITY": - if (existsState(id + ".HUMIDITY") && getState(id + ".HUMIDITY").val != null) { - if (parseInt(getState(id + ".HUMIDITY").val) < 40) { - bt[i-1] = Icons.GetIcon("water-percent") + "~65504~1~bt" + (i-1) + "~"; - } else if (parseInt(getState(id + ".HUMIDITY").val) < 30) { - bt[i-1] = Icons.GetIcon("water-percent") + "~63488~1~bt" + (i-1) + "~"; - } else if (parseInt(getState(id + ".HUMIDITY").val) > 65) { - bt[i-1] = Icons.GetIcon("water-percent") + "~65504~1~bt" + (i-1) + "~"; - } else if (parseInt(getState(id + ".HUMIDITY").val) > 75) { - bt[i-1] = Icons.GetIcon("water-percent") + "~63488~1~bt" + (i-1) + "~"; - } - } else i--; - break; - case "LOWBAT": - if (existsState(id + ".LOWBAT") && getState(id + ".LOWBAT").val != null) { - if (getState(id + ".LOWBAT").val) { - bt[i-1] = Icons.GetIcon("battery-low") + "~63488~1~bt" + (i-1) + "~"; - } else { - bt[i-1] = Icons.GetIcon("battery-high") + "~2016~1~bt" + (i-1) + "~"; - } - } else i--; - break; - case "MAINTAIN": - if (existsState(id + ".MAINTAIN") && getState(id + ".MAINTAIN").val != null) { - if (getState(id + ".MAINTAIN").val >> .1) { - bt[i-1] = Icons.GetIcon("fire") + "~60897~1~bt" + (i-1) + "~"; - } else { - bt[i-1] = Icons.GetIcon("fire") + "~33840~0~bt" + (i-1) + "~"; - } - } else i--; - break; - case "UNREACH": - if (existsState(id + ".UNREACH") && getState(id + ".UNREACH").val != null) { - if (getState(id + ".UNREACH").val) { - bt[i-1] = Icons.GetIcon("wifi-off") + "~63488~1~bt" + (i-1) + "~"; - } else { - bt[i-1] = Icons.GetIcon("wifi") + "~2016~1~bt" + (i-1) + "~"; - } - } else i--; - break; - case "POWER": - if (existsState(id + ".POWER") && getState(id + ".POWER").val != null) { - if (getState(id + ".POWER").val) { - bt[i-1] = Icons.GetIcon("power-standby") + "~2016~1~bt" + (i-1) + "~"; - } else { - bt[i-1] = Icons.GetIcon("power-standby") + "~33840~1~bt" + (i-1) + "~"; - } - } else i--; - break; - case "ERROR": - if (existsState(id + ".ERROR") && getState(id + ".ERROR").val != null) { - if (getState(id + ".ERROR").val) { - bt[i-1] = Icons.GetIcon("alert-circle") + "~63488~1~bt" + (i-1) + "~"; - } else { - bt[i-1] = Icons.GetIcon("alert-circle") + "~33840~1~bt" + (i-1) + "~"; - } - } else i--; - break; - case "WORKING": - if (existsState(id + ".WORKING") && getState(id + ".WORKING").val != null) { - if (getState(id + ".WORKING").val) { - bt[i-1] = Icons.GetIcon("briefcase-check") + "~2016~1~bt" + (i-1) + "~"; - } else { - bt[i-1] = Icons.GetIcon("briefcase-check") + "~33840~1~bt" + (i-1) + "~"; - } - } else i--; - break; - case "BOOST": - if (existsState(id + ".BOOST") && getState(id + ".BOOST").val != null) { - if (getState(id + ".BOOST").val) { - bt[i-1] = Icons.GetIcon("fast-forward-60") + "~2016~1~bt" + (i-1) + "~"; - } else { - bt[i-1] = Icons.GetIcon("fast-forward-60") + "~33840~1~bt" + (i-1) + "~"; - } - } else i--; - break; - case "PARTY": - if (existsState(id + ".PARTY") && getState(id + ".PARTY").val != null) { - if (getState(id + ".PARTY").val) { - bt[i-1] = Icons.GetIcon("party-popper") + "~2016~1~bt" + (i-1) + "~"; - } else { - bt[i-1] = Icons.GetIcon("party-popper") + "~33840~1~bt" + (i-1) + "~"; - } - } else i--; - break; - default: - i--; - break; + var bt = ["~~~~","~~~~","~~~~","~~~~","~~~~","~~~~","~~~~","~~~~","~~~~"]; + + if (o.common.role == "thermostat") { + for (let i_index in i_list) { + let thermostatState = i_list[i_index].split('.'); + if (thermostatState[thermostatState.length-1] != "SET" && + thermostatState[thermostatState.length-1] != "ACTUAL" && + thermostatState[thermostatState.length-1] != "MODE") { + i++; + + switch (thermostatState[thermostatState.length-1]) { + case "HUMIDITY": + if (existsState(id + ".HUMIDITY") && getState(id + ".HUMIDITY").val != null) { + if (parseInt(getState(id + ".HUMIDITY").val) < 40) { + bt[i-1] = Icons.GetIcon("water-percent") + "~65504~1~" + "HUMIDITY" + "~"; + } else if (parseInt(getState(id + ".HUMIDITY").val) < 30) { + bt[i-1] = Icons.GetIcon("water-percent") + "~63488~1~" + "HUMIDITY" + "~"; + } else if (parseInt(getState(id + ".HUMIDITY").val) >= 40) { + bt[i-1] = Icons.GetIcon("water-percent") + "~2016~1~" + "HUMIDITY" + "~"; + } else if (parseInt(getState(id + ".HUMIDITY").val) > 65) { + bt[i-1] = Icons.GetIcon("water-percent") + "~65504~1~" + "HUMIDITY" + "~"; + } else if (parseInt(getState(id + ".HUMIDITY").val) > 75) { + bt[i-1] = Icons.GetIcon("water-percent") + "~63488~1~" + "HUMIDITY" + "~"; + } + } else i--; + break; + case "LOWBAT": + if (existsState(id + ".LOWBAT") && getState(id + ".LOWBAT").val != null) { + if (getState(id + ".LOWBAT").val) { + bt[i-1] = Icons.GetIcon("battery-low") + "~63488~1~" + "LOWBAT" + "~"; + } else { + bt[i-1] = Icons.GetIcon("battery-high") + "~2016~1~" + "LOWBAT" + "~"; + } + } else i--; + break; + case "MAINTAIN": + if (existsState(id + ".MAINTAIN") && getState(id + ".MAINTAIN").val != null) { + if (getState(id + ".MAINTAIN").val >> .1) { + bt[i-1] = Icons.GetIcon("fire") + "~60897~1~" + "MAINTAIN" + "~"; + } else { + bt[i-1] = Icons.GetIcon("fire") + "~33840~0~" + "MAINTAIN" + "~"; + } + } else i--; + break; + case "UNREACH": + if (existsState(id + ".UNREACH") && getState(id + ".UNREACH").val != null) { + if (getState(id + ".UNREACH").val) { + bt[i-1] = Icons.GetIcon("wifi-off") + "~63488~1~" + "UNREACH" + "~"; + } else { + bt[i-1] = Icons.GetIcon("wifi") + "~2016~1~" + "UNREACH" + "~"; + } + } else i--; + break; + case "POWER": + if (existsState(id + ".POWER") && getState(id + ".POWER").val != null) { + if (getState(id + ".POWER").val) { + bt[i-1] = Icons.GetIcon("power-standby") + "~2016~1~" + "POWER" + "~"; + } else { + bt[i-1] = Icons.GetIcon("power-standby") + "~33840~1~" + "POWER" + "~"; + } + } else i--; + break; + case "ERROR": + if (existsState(id + ".ERROR") && getState(id + ".ERROR").val != null) { + if (getState(id + ".ERROR").val) { + bt[i-1] = Icons.GetIcon("alert-circle") + "~63488~1~" + "ERROR" + "~"; + } else { + bt[i-1] = Icons.GetIcon("alert-circle") + "~33840~1~" + "ERROR" + "~"; + } + } else i--; + break; + case "WORKING": + if (existsState(id + ".WORKING") && getState(id + ".WORKING").val != null) { + if (getState(id + ".WORKING").val) { + bt[i-1] = Icons.GetIcon("briefcase-check") + "~2016~1~" + "WORKING" + "~"; + } else { + bt[i-1] = Icons.GetIcon("briefcase-check") + "~33840~1~" + "WORKING" + "~"; + } + } else i--; + break; + case "BOOST": + if (existsState(id + ".BOOST") && getState(id + ".BOOST").val != null) { + if (getState(id + ".BOOST").val) { + bt[i-1] = Icons.GetIcon("fast-forward-60") + "~2016~1~" + "BOOST" + "~"; + } else { + bt[i-1] = Icons.GetIcon("fast-forward-60") + "~33840~1~" + "BOOST" + "~"; + } + } else i--; + break; + case "PARTY": + if (existsState(id + ".PARTY") && getState(id + ".PARTY").val != null) { + if (getState(id + ".PARTY").val) { + bt[i-1] = Icons.GetIcon("party-popper") + "~2016~1~" + "PARTY" + "~"; + } else { + bt[i-1] = Icons.GetIcon("party-popper") + "~33840~1~" + "PARTY" + "~"; + } + } else i--; + break; + default: + i--; + break; + } } } + for (let j = i; j < 9; j++) { + bt[j] = "~~~~"; + } } - for (let j = i; j < 9; j++) { - bt[j] = "~~~~"; + + if (o.common.role == "airCondition") { + if (existsState(id + ".MODE") && getState(id + ".MODE").val != null) { + let Mode = getState(id + ".MODE").val + if (existsState(id + ".POWER") && getState(id + ".POWER").val != null) { + if (Mode != 0 || getState(id + ".POWER").val) { //0=ON oder .POWER = true + bt[0] = Icons.GetIcon("power-standby") + "~2016~1~" + "POWER" + "~"; + statusStr = "ON"; + } else { + bt[0] = Icons.GetIcon("power-standby") + "~35921~0~" + "POWER" + "~"; + statusStr = "OFF"; + } + } + if (Mode == 1) { //1=AUTO + bt[1] = Icons.GetIcon("air-conditioner") + "~1024~1~" + "AUTO" + "~"; + statusStr = "AUTO"; + } else { + bt[1] = Icons.GetIcon("air-conditioner") + "~35921~0~" + "AUTO" + "~"; + } + if (Mode == 2) { //2=COOL + bt[2] = Icons.GetIcon("snowflake") + "~11487~1~" + "COOL" + "~"; + statusStr = "COOL"; + } else { + bt[2] = Icons.GetIcon("snowflake") + "~35921~0~" + "COOL" + "~"; + } + if (Mode == 3) { //3=HEAT + bt[3] = Icons.GetIcon("fire") + "~64512~1~" + "HEAT" + "~"; + statusStr = "HEAT"; + } else { + bt[3] = Icons.GetIcon("fire") + "~35921~0~" + "HEAT" + "~"; + } + if (Mode == 4) { //4=ECO + bt[4] = Icons.GetIcon("alpha-e-circle-outline") + "~2016~1~" + "ECO" + "~"; + statusStr = "ECO"; + } else { + bt[4] = Icons.GetIcon("alpha-e-circle-outline") + "~35921~0~" + "ECO" + "~"; + } + if (Mode == 5) { //5=FANONLY + bt[5] = Icons.GetIcon("fan") + "~11487~1~" + "FAN" + "~"; + statusStr = "FAN ONLY"; + } else { + bt[5] = Icons.GetIcon("fan") + "~35921~0~" + "FAN" + "~"; + } + if (Mode == 6) { //6=DRY + bt[6] = Icons.GetIcon("water-percent") + "~60897~1~" + "DRY" + "~"; + statusStr = "DRY"; + } else { + bt[6] = Icons.GetIcon("water-percent") + "~35921~0~" + "DRY" + "~"; + } + if (existsState(id + ".SWING") && getState(id + ".SWING").val != null) { + if (getState(id + ".POWER").val && getState(id + ".SWING").val == 1) { //0=ON oder .SWING = true + bt[7] = Icons.GetIcon("swap-vertical-bold") + "~2016~1~" + "SWING" + "~"; + } else { + bt[7] = Icons.GetIcon("swap-vertical-bold") + "~35921~0~" + "SWING" + "~"; + } + } + } } } - - let icon_res = bt[0] + bt[1] + bt[2] + bt[3] + bt[4] + bt[5] + bt[6] + bt[7] + bt[8]; + + let icon_res = bt[0] + bt[1] + bt[2] + bt[3] + bt[4] + bt[5] + bt[6] + bt[7]; - out_msgs.push({ payload: "entityUpd~" + name + "~" + GetNavigationString(pageId) + "~" + id + "~" + currentTemp + "~" + destTemp + "~" + status + "~" + minTemp + "~" + maxTemp + "~" + stepTemp + "~" +icon_res}) + + out_msgs.push({ payload: "entityUpd~" + + name + "~" //Heading + + GetNavigationString(pageId) + "~" //Page Navigation + + id + "~" //internalNameEntiy + + currentTemp + "°C" + "~" //Ist-Temperatur (String) + + destTemp + "~" //Soll-Temperatur (numerisch ohne Komma) + + statusStr + "~" //Mode + + minTemp + "~" //Thermostat Min-Temperatur + + maxTemp + "~" //Thermostat Max-Temperatur + + stepTemp + "~" //Schritte für Soll (5°C) + + icon_res //Icons Status + + "Aktuell" + "~" //Bezeicher vor Aktueller Raumtemperatur + + "Status" + "~" //Bezeicner vor + + "HVAC" + "~" //Bezeichner vor HVAC + + "°C"}) //Bezeichner Hinter Solltemp + } + + if (Debug) console.log(out_msgs); return out_msgs } + function GenerateMediaPage(page: PageMedia): Payload[] { var id = page.items[0].id var out_msgs: Array = []; out_msgs.push({ payload: "pageType~cardMedia" }); if (existsObject(id)) { - let name = getState(id + ".ALBUM").val; + + 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; @@ -844,7 +1625,6 @@ function GenerateMediaPage(page: PageMedia): Payload[] { 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 @@ -853,14 +1633,14 @@ function GenerateMediaPage(page: PageMedia): Payload[] { 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 && + 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 + "?"; @@ -869,19 +1649,164 @@ function GenerateMediaPage(page: PageMedia): Payload[] { } speakerlist = speakerlist.substring(0,speakerlist.length-1); //-------------------------------------------------------------------------------------------------------------- - out_msgs.push({ payload: "entityUpd~" + - name + "~" + - id + "~" + - id + "~" + //???? - media_icon + "~" + - title + "~" + - author + "~" + - volume + "~" + - iconplaypause + "~" + - currentSpeaker + "~" + - speakerlist + "~" + - onoffbutton}); + + out_msgs.push({ payload: "entityUpd~" + //entityUpd + name + "~" + //heading + GetNavigationString(pageId) + "~" + //navigation + id + "~" + //internalNameEntiy + media_icon + "~" + //icon + title + "~" + //title + author + "~" + //author + volume + "~" + //volume + iconplaypause + "~" + //playpauseicon + currentSpeaker + "~" + //currentSpeaker + speakerlist + "~" + //speakerList-seperated-by-? + onoffbutton}); //On/Off Button Color } + if (Debug) console.log(out_msgs); + return out_msgs +} + +function GenerateAlarmPage(page: PageAlarm): Payload[] { + var id = page.items[0].id + var out_msgs: Array = []; + out_msgs.push({ payload: "pageType~cardAlarm" }); + var nsPath = NSPanel_Path + "Alarm." + + if (existsState(nsPath + "AlarmPin") == false || existsState(nsPath + "AlarmState") == false || existsState(nsPath + "AlarmType") == false) { + createState(nsPath + "AlarmPin", "0000", {type: 'string'}, function() {setState(nsPath + "AlarmPin", "0000")}); + createState(nsPath + "AlarmState", "disarmed", {type: 'string'}, function() {setState(nsPath + "AlarmState", "disarmed")}); + createState(nsPath + "AlarmType", "0", {type: 'string'}, function() {setState(nsPath + "AlarmType", "0")}); + } + + if (existsState(nsPath + "AlarmPin") && existsState(nsPath + "AlarmState") && existsState(nsPath + "AlarmType")) { + var entityPin = getState(nsPath + "AlarmPin").val; + var entityState = getState(nsPath + "AlarmState").val; + var entityType = getState(nsPath + "AlarmType").val + var arm1: string, arm2: string, arm3: string, arm4: string; + var arm1ActionName: string, arm2ActionName: string, arm3ActionName: string, arm4ActionName: string; + var icon = "0"; + var iconcolor = 63488; + var numpadStatus = "disable"; + var flashing = "disable"; + + if (Debug) console.log(id); + + if (entityState == "armed" || entityState == "triggered") { + arm1 = "Deaktivieren"; //arm1*~* + arm1ActionName = "D1"; //arm1ActionName*~* + arm2 = ""; //arm2*~* + arm2ActionName = ""; //arm2ActionName*~* + arm3 = ""; //arm3*~* + arm3ActionName = ""; //arm3ActionName*~* + arm4 = ""; //arm4*~* + arm4ActionName = ""; //arm4ActionName*~* + } + if (entityState == "disarmed" || entityState == "arming" || entityState == "pending") { + arm1 = "Vollschutz"; //arm1*~* + arm1ActionName = "A1"; //arm1ActionName*~* + arm2 = "Zuhause"; //arm2*~* + arm2ActionName = "A2"; //arm2ActionName*~* + arm3 = "Nacht"; //arm3*~* + arm3ActionName = "A3"; //arm3ActionName*~* + arm4 = "Besuch"; //arm4*~* + arm4ActionName = "A4"; //arm4ActionName*~* + } + + if (entityState == "armed") { + icon = Icons.GetIcon("shield-home"); //icon*~* + iconcolor = 63488; //iconcolor*~* + numpadStatus = "enable"; //numpadStatus*~* + flashing = "disable"; //flashing* + } + if (entityState == "disarmed") { + icon = Icons.GetIcon("shield-off"); //icon*~* + iconcolor = 2016; //iconcolor*~* + numpadStatus = "enable"; //numpadStatus*~* + flashing = "disable"; //flashing* + } + if (entityState == "arming" || entityState == "pending") { + icon = Icons.GetIcon("shield"); //icon*~* + iconcolor = rgb_dec565({ red: 243, green: 179, blue: 0 }); //iconcolor*~* + numpadStatus = "disable"; //numpadStatus*~* + flashing = "enable" //flashing* + } + if (entityState == "triggered") { + iconcolor = rgb_dec565({ red: 223, green: 76, blue: 30 }); //icon*~* + icon = Icons.GetIcon("bell-ring"); //iconcolor*~* + numpadStatus = "enable"; //numpadStatus*~* + flashing = "enable" //flashing* + } + + out_msgs.push({ payload: "entityUpd~" + //entityUpd~* + id + "~" + //internalNameEntity*~* + GetNavigationString(pageId) + "~" + //navigation*~* --> hiddenCards + arm1 + "~" + //arm1*~* + arm1ActionName + "~" + //arm1ActionName*~* + arm2 + "~" + //arm2*~* + arm2ActionName + "~" + //arm2ActionName*~* + arm3 + "~" + //arm3*~* + arm3ActionName + "~" + //arm3ActionName*~* + arm4 + "~" + //arm4*~* + arm4ActionName + "~" + //arm4ActionName*~* + icon + "~" + //icon*~* + iconcolor + "~" + //iconcolor*~* + numpadStatus + "~" + //numpadStatus*~* + flashing}); //flashing* + + if (Debug) console.log(out_msgs); + return out_msgs + } +} + +function GenerateQRPage(page: PageQR): Payload[] { + var id = page.items[0].id + var out_msgs: Array = []; + out_msgs.push({ payload: "pageType~cardQR" }); + + let o = getObject(id) + + var heading = page.heading !== undefined ? page.heading : o.common.name.de + let minTemp = page.items[0].minValue !== undefined ? page.items[0].minValue : 50; + var textQR = page.items[0].id + ".ACTUAL" !== undefined ? getState(page.items[0].id + ".ACTUAL").val : "WIFI:T:undefined;S:undefined;P:undefined;H:undefined;" + + const tempstr = textQR.split(";"); + for (let w = 0; w < tempstr.length - 1; w++) { + if (tempstr[w].substring(0,1) == "S") { + var optionalValue1 = tempstr[w].slice(2); + } + if (tempstr[w].substring(0,1) == "P") { + var optionalValue2 = tempstr[w].slice(2); + } + } + + var type1 = "text" + var internalName1 = "SSID" + var iconId1 = Icons.GetIcon("wifi"); + var displayName1 = "SSID" + var type2 = "text" + var internalName2 = "Passwort" + var iconId2 = Icons.GetIcon("key"); + var displayName2 = "Passwort" + + out_msgs.push({ payload: "entityUpd~" + //entityUpd + heading + "~" + //heading + GetNavigationString(pageId) + "~" + //navigation + textQR + "~" + //textQR + type1 + "~" + //type + internalName1 + "~" + //internalName + iconId1 + "~" + //iconId + 65535 + "~" + //iconColor + displayName1 + "~" + //displayName + optionalValue1 + "~" + //optionalValue + type2 + "~" + //type + internalName2 + "~" + //internalName + iconId2 + "~" + //iconId + 65535 + "~" + //iconColor + displayName2 + "~" + //displayName + optionalValue2}); //optionalValue + + //entityUpd,heading,navigation,textQR[,type,internalName,iconId,displayName,optionalValue]x2 return out_msgs } @@ -905,17 +1830,35 @@ function setIfExists(id: string, value: any, type: string | null = null): boolea 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); + setIfExists(id, !getState(id).val); return true; } return false; } function HandleButtonEvent(words): void { - let id = words[2] - let buttonAction = words[3]; + var id = words[2] + var buttonAction = words[3]; + + if (Debug) { + console.log(words[0] + " - " + words[1] + " - " + words[2] + " - " + words[3] + " - " + words[4] + " - PageId: " + pageId); + } + + if ((words[2]).substring(0, 8) == "navigate"){ + GeneratePage(eval((words[2]).substring(9, (words[2]).length))); + return; + } switch (buttonAction) { + case "bUp": + if (pageId < 0) { //Prüfen, ob button1page oder button2page + pageId = 0; + } else { + pageId = Math.abs(pageNum); + } + UnsubscribeWatcher(); + GeneratePage(config.pages[pageId]); + break; case "bNext": var pageNum = ((pageId + 1) % config.pages.length); pageId = Math.abs(pageNum); @@ -927,22 +1870,42 @@ function HandleButtonEvent(words): void { pageId = Math.abs(pageNum); UnsubscribeWatcher(); GeneratePage(config.pages[pageId]); + +//-------------Subpage + if (subPage_open) { + subPage_open = false; + HandleButtonEvent(['event','buttonPress2','cardEntities','bNext']) + } +//-------------------------------- break; case "bExit": if (config.screenSaverDoubleClick) { - if (words[4] == 2) + if (words[4] == 2) { GeneratePage(config.pages[pageId]); - } - else + } + } else { + if (Debug) console.log("bExit: " + words[4] + " - "+ pageId) GeneratePage(config.pages[pageId]); + } + break; + case "notifyAction": + if (words[4] == "yes") { + setIfExists(popupNotifyInternalName, words[2]); + setIfExists(popupNotifyAction , true); + } else if (words[4] == "no") { + setIfExists(popupNotifyInternalName, words[2]); + setIfExists(popupNotifyAction , false) + } + setIfExists(config.panelSendTopic, "exitPopup") break; case "OnOff": if (existsObject(id)) { var action = false if (words[4] == "1") - action = true + action = true; let o = getObject(id) switch (o.common.role) { + case "socket": case "light": setIfExists(id + ".SET", action); break; @@ -969,13 +1932,40 @@ function HandleButtonEvent(words): void { setIfExists(id + ".CLOSE", true) break; case "button": - toggleState(id + ".SET") ? true : toggleState(id + ".ON_SET") + if (existsObject(id)) { + var action = false + if (words[4] == "1") + action = true; + let o = getObject(id) + switch (o.common.role) { + case "lock": + case "button": + toggleState(id + ".SET") ? true : toggleState(id + ".ON_SET"); + break; + case "buttonSensor": + toggleState(id + ".ACTUAL"); + break; + case "socket": + case "light": + toggleState(id + ".SET") ? true : toggleState(id + ".ON_SET"); + break; + case "dimmer": + toggleState(id + ".ON_SET") ? true : toggleState(id + ".ON_ACTUAL"); + break; + case "ct": + toggleState(id + ".ON"); + break; + case "rgb": + case "rgbSingle": + case "hue": // Armilar + toggleState(id + ".ON_ACTUAL"); + } + } break; case "positionSlider": (function () {if (timeoutSlider) {clearTimeout(timeoutSlider); timeoutSlider = null;}})(); timeoutSlider = setTimeout(async function () { setIfExists(id + ".SET", parseInt(words[4])) ? true : setIfExists(id + ".ACTUAL", parseInt(words[4])); - //console.log("PositionSlider feuert"); }, 250); break; case "brightnessSlider": @@ -984,14 +1974,12 @@ function HandleButtonEvent(words): void { if (existsObject(id)) { let o = getObject(id); let pageItem = config.pages[pageId].items.find(e => e.id === id); - //console.log(o.common.role); 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])); setIfExists(id + ".SET", parseInt(words[4])) ? true : setIfExists(id + ".ACTUAL", parseInt(words[4])); } break; @@ -1025,8 +2013,8 @@ function HandleButtonEvent(words): void { 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)); + if (Debug) console.log(rgb); + if (Debug) console.log(getHue(rgb.red, rgb.green, rgb.blue)); let o = getObject(id); switch (o.common.role) { case "hue": @@ -1041,6 +2029,9 @@ function HandleButtonEvent(words): void { setIfExists(id + ".RGB", ConvertRGBtoHex(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; @@ -1049,7 +2040,7 @@ function HandleButtonEvent(words): void { setIfExists(id + ".PAUSE", true) } else { setIfExists(id + ".PLAY", true) - } + } break; case "media-next": setIfExists(id + ".NEXT", true) @@ -1072,21 +2063,126 @@ function HandleButtonEvent(words): void { case "media-OnOff": setIfExists(id + ".STOP", true) break; - case "tempUpd": - setIfExists(id + ".SET", parseInt(words[4]) / 10) + case "hvac_action": + if (words[4] == "BOOST" || words[4] == "PARTY") { + setIfExists(words[2] + "." + words[4], !getState(words[2] + "." + words[4]).val) + } + else { + var HVACMode = 0; + switch (words[4]) { + case "POWER": + HVACMode = 0; + setIfExists(words[2] + "." + words[4], !getState(words[2] + "." + words[4]).val) + if (getState(words[2] + "." + words[4]).val) { + HVACMode = 1; + } + break; + case "AUTO": + HVACMode = 1; + break; + case "COOL": + HVACMode = 2; + break; + case "HEAT": + HVACMode = 3; + break; + case "ECO": + HVACMode = 4; + break; + case "FAN": + HVACMode = 5; + break; + case "DRY": + HVACMode = 6; + break; + case "SWING": + HVACMode = getState(words[2] + "." + "MODE").val; + if (getState(words[2] + "." + "SWING").val == 0) { + setIfExists(words[2] + "." + "SWING", 1) + } else { + setIfExists(words[2] + "." + "SWING", 0) + } + break; + } + setIfExists(words[2] + "." + "MODE", HVACMode) + GeneratePage(config.pages[pageId]); + } + break; + case "number-set": + setIfExists(id + ".SET", parseInt(words[4])) ? true : setIfExists(id + ".ACTUAL", parseInt(words[4])); + break; + case "A1": //Alarm-Page Alarm 1 aktivieren + if (words[4] != "") { + setIfExists(id + ".TYPE", "A1"); + setIfExists(id + ".PIN", words[4]); + setIfExists(id + ".ACTUAL", "arming"); + setTimeout(function(){ + GeneratePage(config.pages[pageId]); + },250) + } + break; + case "A2": //Alarm-Page Alarm 2 aktivieren + if (words[4] != "") { + setIfExists(id + ".TYPE", "A2"); + setIfExists(id + ".PIN", words[4]); + setIfExists(id + ".ACTUAL", "arming"); + setTimeout(function(){ + GeneratePage(config.pages[pageId]); + },250) + } + break; + case "A3": //Alarm-Page Alarm 3 aktivieren + if (words[4] != "") { + setIfExists(id + ".TYPE", "A3"); + setIfExists(id + ".PIN", words[4]); + setIfExists(id + ".ACTUAL", "arming"); + setTimeout(function(){ + GeneratePage(config.pages[pageId]); + },250) + } + break; + case "A4": //Alarm-Page Alarm 4 aktivieren + if (words[4] != "") { + setIfExists(id + ".TYPE", "A4"); + setIfExists(id + ".PIN", words[4]); + setIfExists(id + ".ACTUAL", "arming"); + setTimeout(function(){ + GeneratePage(config.pages[pageId]); + },250) + } + break; + case "D1": //Alarm-Page Alarm Deaktivieren + if (Debug) console.log("D1: " + getState(id + ".PIN").val); + if (words[4] != "") { + if (getState(id + ".PIN").val == words[4]) { + setIfExists(id + ".PIN", "0000"); + setIfExists(id + ".TYPE", "D1"); + setIfExists(id + ".ACTUAL", "pending"); + setTimeout(function(){ + GeneratePage(config.pages[pageId]); + },250) + } + } + break; default: break; } } + function GetNavigationString(pageId: number): string { + if (Debug) console.log(pageId); + if (Debug) console.log(subPage_open); + switch (pageId) { case 0: return "0|1"; case config.pages.length - 1: return "1|0"; case -1: - return "0|0"; + return "2|0"; + case -2: + return "2|0"; default: return "1|1"; } @@ -1105,7 +2201,7 @@ function GenerateDetailPage(type: string, pageItem: PageItem): Payload[] { if (type == "popupLight") { let switchVal = "0" let brightness = 0; - if (o.common.role == "light") { + if (o.common.role == "light" || o.common.role == "socket") { if (existsState(id + ".GET")) { val = getState(id + ".GET").val; RegisterDetailEntityWatcher(id + ".GET", pageItem, type); @@ -1115,12 +2211,25 @@ function GenerateDetailPage(type: string, pageItem: PageItem): Payload[] { RegisterDetailEntityWatcher(id + ".SET", pageItem, type); } + icon = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : o.common.role == "socket" ? Icons.GetIcon("power-socket-de") : Icons.GetIcon("lightbulb"); + if (val) { switchVal = "1"; - iconColor = GetIconColor(pageItem, true, false); + iconColor = GetIconColor(pageItem, true, true); + } else { + iconColor = GetIconColor(pageItem, false, true); } - out_msgs.push({ payload: "entityUpdateDetail~" + icon + "~" + + iconColor + "~" + switchVal + ",disable,disable,disable" + "~Color~Temperature~Brightness" }) + out_msgs.push({ payload: "entityUpdateDetail" + "~" //entityUpdateDetail + + icon + "~" //iconId + + iconColor + "~" //iconColor + + switchVal + "~" //buttonState + + "disable" + "~" //sliderBrightnessPos + + "disable" + "~" //sliderColorTempPos + + "disable" + "~" //colorMode + + "Color" + "~" //Color-Bezeichnung + + "Temperature" + "~" //Temperature-Bezeichnung + + "Brightness" }) //Brightness-Bezeichnung } //Dimmer @@ -1157,12 +2266,20 @@ function GenerateDetailPage(type: string, pageItem: PageItem): Payload[] { } RegisterDetailEntityWatcher(id + ".ACTUAL", pageItem, type); - - let colorTemp = "disable" - let colorMode = "disable" - out_msgs.push({ payload: "entityUpdateDetail~" + icon + "~" + iconColor + "~" + switchVal + "~" + brightness + "~" + colorTemp + "~" + colorMode + "~Color~Temperature~Brightness" }) + out_msgs.push({ payload: "entityUpdateDetail" + "~" //entityUpdateDetail + + icon + "~" //iconId + + iconColor + "~" //iconColor + + switchVal + "~" //buttonState + + brightness + "~" //sliderBrightnessPos + + "disable" + "~" //sliderColorTempPos + + "disable" + "~" //colorMod + + "Color" + "~" //Color-Bezeichnung + + "Temperature" + "~" //Temperature-Bezeichnung + + "Brightness" }) //Brightness-Bezeichnung + } + //HUE-Licht if (o.common.role == "hue") { @@ -1214,7 +2331,16 @@ function GenerateDetailPage(type: string, pageItem: PageItem): Payload[] { console.warn("Alias-Datenpunkt: " + id + ".TEMPERATURE could not be read"); } - out_msgs.push({ payload: "entityUpdateDetail~" + icon + "~" + iconColor + "~" + switchVal + "~" + brightness + "~" + colorTemp + "~" + colorMode + "~Color~Temperature~Brightness" }) + out_msgs.push({ payload: "entityUpdateDetail" + "~" //entityUpdateDetail + + icon + "~" //iconId + + iconColor + "~" //iconColor + + switchVal + "~" //buttonState + + brightness + "~" //sliderBrightnessPos + + colorTemp + "~" //sliderColorTempPos + + colorMode + "~" //colorMode (if hue-alias without hue-datapoint, then disable) + + "Color" + "~" //Color-Bezeichnung + + "Temperature" + "~" //Temperature-Bezeichnung + + "Brightness" }) //Brightness-Bezeichnung } //RGB-Licht @@ -1267,7 +2393,16 @@ function GenerateDetailPage(type: string, pageItem: PageItem): Payload[] { console.warn("Alias-Datenpunkt: " + id + ".TEMPERATURE could not be read"); } - out_msgs.push({ payload: "entityUpdateDetail~" + icon + "~" + iconColor + "~" + switchVal + "~" + brightness + "~" + colorTemp + "~" + colorMode + "~Color~Temperature~Brightness" }) + out_msgs.push({ payload: "entityUpdateDetail" + "~" //entityUpdateDetail + + icon + "~" //iconId + + iconColor + "~" //iconColor + + switchVal + "~" //buttonState + + brightness + "~" //sliderBrightnessPos + + colorTemp + "~" //sliderColorTempPos + + colorMode + "~" //colorMode (if hue-alias without hue-datapoint, then disable) + + "Color" + "~" //Color-Bezeichnung + + "Temperature" + "~" //Temperature-Bezeichnung + + "Brightness" }) //Brightness-Bezeichnung } //RGB-Licht-einzeln (HEX) @@ -1324,7 +2459,16 @@ function GenerateDetailPage(type: string, pageItem: PageItem): Payload[] { console.warn("Alias-Datenpunkt: " + id + ".TEMPERATURE could not be read"); } - out_msgs.push({ payload: "entityUpdateDetail~" + icon + "~" + iconColor + "~" + switchVal + "~" + brightness + "~" + colorTemp + "~" + colorMode + "~Color~Temperature~Brightness" }) + out_msgs.push({ payload: "entityUpdateDetail" + "~" //entityUpdateDetail + + icon + "~" //iconId + + iconColor + "~" //iconColor + + switchVal + "~" //buttonState + + brightness + "~" //sliderBrightnessPos + + colorTemp + "~" //sliderColorTempPos + + colorMode + "~" //colorMode (if hue-alias without hue-datapoint, then disable) + + "Color" + "~" //Color-Bezeichnung + + "Temperature" + "~" //Temperature-Bezeichnung + + "Brightness" }) //Brightness-Bezeichnung) } //Farbtemperatur @@ -1369,12 +2513,22 @@ function GenerateDetailPage(type: string, pageItem: PageItem): Payload[] { console.warn("Alias-Datenpunkt: " + id + ".TEMPERATURE could not be read"); } - out_msgs.push({ payload: "entityUpdateDetail~" + icon + "~" + iconColor + "~" + switchVal + "~" + brightness + "~" + colorTemp + "~" + colorMode + "~Color~Temperature~Brightness" }) + out_msgs.push({ payload: "entityUpdateDetail" + "~" //entityUpdateDetail + + icon + "~" //iconId + + iconColor + "~" //iconColor + + switchVal + "~" //buttonState + + brightness + "~" //sliderBrightnessPos + + colorTemp + "~" //sliderColorTempPos + + colorMode + "~" //colorMode (if hue-alias without hue-datapoint, then disable) + + "Color" + "~" //Color-Bezeichnung + + "Temperature" + "~" //Temperature-Bezeichnung + + "Brightness" }) //Brightness-Bezeichnung } } if (type == "popupShutter") { + icon = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon("window-open"); if (existsState(id + ".ACTUAL")) { val = getState(id + ".ACTUAL").val; RegisterDetailEntityWatcher(id + ".ACTUAL", pageItem, type); @@ -1382,7 +2536,10 @@ function GenerateDetailPage(type: string, pageItem: PageItem): Payload[] { val = getState(id + ".SET").val; RegisterDetailEntityWatcher(id + ".SET", pageItem, type); } - out_msgs.push({ payload: "entityUpdateDetail~" + val + "~~Position" }) + out_msgs.push({ payload: "entityUpdateDetail" + "~" //entityUpdateDetail + + val + "~" //Shutterposition + + "" + "~" + + "Position"}) //Position-Bezeichnung } } return out_msgs @@ -1408,15 +2565,16 @@ function HandleScreensaver(): void { 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++) { @@ -1433,7 +2591,7 @@ function HandleScreensaverUpdate(): void { payloadString += GetScreenSaverEntityString(config.thirdScreensaverEntity); payloadString += GetScreenSaverEntityString(config.fourthScreensaverEntity); } - +/*-------------------------------------------------------------------------------------------------------------------------------------*/ SendToPanel({ payload: payloadString }); } } @@ -1523,6 +2681,21 @@ function GetAccuWeatherIcon(icon: number): string { } } +//------------------Begin Read Internal Sensor Data +on({ id: config.panelRecvTopic.substring(0, config.panelRecvTopic.length - 6) + "SENSOR" }, function (obj) { + let mqttSensor = config.panelRecvTopic.substring(0, config.panelRecvTopic.length - 6) + "SENSOR"; + let Tasmota_Sensor = JSON.parse(getState(mqttSensor).val); + createState(NSPanel_Path + 'Sensor.Time'); + createState(NSPanel_Path + 'Sensor.TempUnit'); + createState(NSPanel_Path + 'Sensor.ANALOG.Temperature'); + createState(NSPanel_Path + 'Sensor.ESP32.Temperature'); + setIfExists(NSPanel_Path + 'Sensor.Time', Tasmota_Sensor.Time); + setIfExists(NSPanel_Path + 'Sensor.TempUnit', "°" + Tasmota_Sensor.TempUnit); + setIfExists(NSPanel_Path + 'Sensor.ANALOG.Temperature', Tasmota_Sensor.ANALOG.Temperature1); + setIfExists(NSPanel_Path + 'Sensor.ESP32.Temperature', Tasmota_Sensor.ESP32.Temperature); +}); +//------------------End Read Internal Sensor Data + function GetBlendedColor(percentage: number): RGB { if (percentage < 50) return Interpolate(config.defaultOffColor, config.defaultOnColor, percentage / 50.0); @@ -1544,6 +2717,10 @@ 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; } @@ -1557,6 +2734,12 @@ function ConvertRGBtoHex(red: number, green: number, blue: Number) { return "#" + ColorToHex(red) + ColorToHex(green) + ColorToHex(blue); } +/* 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; @@ -1567,29 +2750,37 @@ function hsv2rgb(hue: number, saturation: number, value: number) { 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 { +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; @@ -1601,8 +2792,10 @@ function pos_to_color(x: number, y: number): RGB { } else { sat = r; } + var hsv = rad2deg(Math.atan2(y, x)); var rgb = hsv2rgb(hsv,sat,1); + return { red: Math.round(rgb[0]), green: Math.round(rgb[1]), blue: Math.round(rgb[2]) }; } @@ -1620,14 +2813,15 @@ type Page = { type: string, heading: string, items: PageItem[], - useColor: boolean + useColor: boolean, + subPage: boolean, }; interface PageEntities extends Page { type: "cardEntities", items: PageItem[], - }; + interface PageGrid extends Page { type: "cardGrid", items: PageItem[], @@ -1643,6 +2837,16 @@ interface PageMedia extends Page { items: PageItem[], }; +interface PageAlarm extends Page { + type: "cardAlarm", + items: PageItem[], +}; + +interface PageQR extends Page { + type: "cardQR", + items: PageItem[], +}; + type PageItem = { id: string, icon: (string | undefined), @@ -1657,7 +2861,17 @@ type PageItem = { minValue: (number | undefined), maxValue: (number | undefined), name: (string | undefined), - unit: (string | undefined) + buttonText: (string | undefined), + unit: (string | undefined), + navigate: (boolean | undefined), +} + +type DimMode = { + dimmodeOn: (boolean | undefined), + brightnessDay: (number | undefined), + brightnessNight: (number | undefined), + timeDay: (string | undefined), + timeNight: (string | undefined) } type Config = { @@ -1665,7 +2879,7 @@ type Config = { panelSendTopic: string, timeoutScreensaver: number, dimmode: number, - //brightnessScreensaver: + active: number, locale: string, timeFormat: string, dateFormat: string, @@ -1679,9 +2893,9 @@ type Config = { defaultColor: RGB, defaultOnColor: RGB, defaultOffColor: RGB, - pages: (PageThermo | PageMedia | PageEntities | PageGrid)[], - button1Page: (PageThermo | PageMedia | PageEntities | PageGrid | null), - button2Page: (PageThermo | PageMedia | PageEntities | PageGrid | null), + pages: (PageThermo | PageMedia | PageAlarm | PageQR | PageEntities | PageGrid)[], + button1Page: (PageThermo | PageMedia | PageAlarm | PageQR | PageEntities | PageGrid | null), + button2Page: (PageThermo | PageMedia | PageAlarm | PageQR | PageEntities | PageGrid | null), }; type ScreenSaverElement = { From ceeee8a72485d1b2db431e24b3d37d9692e559db Mon Sep 17 00:00:00 2001 From: Armilar <102996011+Armilar@users.noreply.github.com> Date: Wed, 8 Jun 2022 17:05:47 +0200 Subject: [PATCH 13/23] Update NsPanelTs.ts --- ioBroker/NsPanelTs.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ioBroker/NsPanelTs.ts b/ioBroker/NsPanelTs.ts index 505015bd..22b375cb 100644 --- a/ioBroker/NsPanelTs.ts +++ b/ioBroker/NsPanelTs.ts @@ -929,7 +929,7 @@ function ScreensaverDimmode() { SendToPanel({ payload: "dimmode~" + timeDimMode.brightnessNight}); } } else { - SendToPanel({ payload: "dimmode~" + config.dimmode }); + SendToPanel({ payload: "dimmode~" + config.dimmode + "~" + config.active }); } } From ee554bec3cd8e81f5383eda500947391cf9010b0 Mon Sep 17 00:00:00 2001 From: Armilar <102996011+Armilar@users.noreply.github.com> Date: Wed, 8 Jun 2022 17:07:47 +0200 Subject: [PATCH 14/23] Update NsPanelTs.ts --- ioBroker/NsPanelTs.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ioBroker/NsPanelTs.ts b/ioBroker/NsPanelTs.ts index ba67bad3..52cc9c56 100644 --- a/ioBroker/NsPanelTs.ts +++ b/ioBroker/NsPanelTs.ts @@ -938,7 +938,7 @@ function ScreensaverDimmode() { SendToPanel({ payload: "dimmode~" + timeDimMode.brightnessNight}); } } else { - SendToPanel({ payload: "dimmode~" + config.dimmode }); + SendToPanel({ payload: "dimmode~" + config.dimmode + "~" + config.active }); } } From aa9ad5d3605ecf7978c1ddfd12e8181f31a0b50e Mon Sep 17 00:00:00 2001 From: joBr99 Date: Wed, 8 Jun 2022 20:00:12 +0000 Subject: [PATCH 15/23] closes #266 code on screensaver page is now the same on every version, is checking for the width of the screen (add nextion2text) --- HMI/US/landscape/diff-eu-version.txt | 8 ++++---- .../landscape/n2t-out-visual/screensaver.txt | 2 +- HMI/US/landscape/n2t-out/screensaver.txt | 2 +- HMI/US/portrait/diff-eu-version.txt | 16 ++++++++-------- HMI/US/portrait/diff-filtered.txt | 18 +++++++++--------- HMI/US/portrait/n2t-out-visual/screensaver.txt | 8 ++++---- HMI/US/portrait/n2t-out/screensaver.txt | 2 +- HMI/n2t-out-visual/nspanel_Stats.txt | 8 ++++---- HMI/n2t-out-visual/screensaver.txt | 2 +- HMI/n2t-out/screensaver.txt | 2 +- 10 files changed, 34 insertions(+), 34 deletions(-) diff --git a/HMI/US/landscape/diff-eu-version.txt b/HMI/US/landscape/diff-eu-version.txt index 6504e71e..94104924 100644 --- a/HMI/US/landscape/diff-eu-version.txt +++ b/HMI/US/landscape/diff-eu-version.txt @@ -1,6 +1,6 @@ diff -bur HMI/n2t-out/Program.s.txt HMI/US/landscape/n2t-out/Program.s.txt ---- HMI/n2t-out/Program.s.txt 2022-06-06 20:43:14.701325786 +0000 -+++ HMI/US/landscape/n2t-out/Program.s.txt 2022-06-06 20:43:15.757379552 +0000 +--- HMI/n2t-out/Program.s.txt 2022-06-08 20:00:07.004980492 +0000 ++++ HMI/US/landscape/n2t-out/Program.s.txt 2022-06-08 20:00:08.089056883 +0000 @@ -11,6 +11,4 @@ // dim value int dimValue=40 @@ -9,8 +9,8 @@ diff -bur HMI/n2t-out/Program.s.txt HMI/US/landscape/n2t-out/Program.s.txt - lcd_dev fffb 0002 0000 0020 page pageStartup diff -bur HMI/n2t-out/pageStartup.txt HMI/US/landscape/n2t-out/pageStartup.txt ---- HMI/n2t-out/pageStartup.txt 2022-06-06 20:43:14.705325989 +0000 -+++ HMI/US/landscape/n2t-out/pageStartup.txt 2022-06-06 20:43:15.757379552 +0000 +--- HMI/n2t-out/pageStartup.txt 2022-06-08 20:00:07.004980492 +0000 ++++ HMI/US/landscape/n2t-out/pageStartup.txt 2022-06-08 20:00:08.089056883 +0000 @@ -177,7 +177,7 @@ recmod=1 bauds=115200 diff --git a/HMI/US/landscape/n2t-out-visual/screensaver.txt b/HMI/US/landscape/n2t-out-visual/screensaver.txt index 5629385b..ad414fec 100644 --- a/HMI/US/landscape/n2t-out-visual/screensaver.txt +++ b/HMI/US/landscape/n2t-out-visual/screensaver.txt @@ -1041,7 +1041,7 @@ Timer tmSerial //alternative layout //tMRIcon spstr strCommand.txt,tMRIcon.txt,"~",15 - if(tMRIcon.txt!="") + if(tMRIcon.txt!=""&&p0.w!=320) { //value for tMRIcon, activate alternative layout vis tMainIcon,0 diff --git a/HMI/US/landscape/n2t-out/screensaver.txt b/HMI/US/landscape/n2t-out/screensaver.txt index 84c004cc..3fe97b40 100644 --- a/HMI/US/landscape/n2t-out/screensaver.txt +++ b/HMI/US/landscape/n2t-out/screensaver.txt @@ -476,7 +476,7 @@ Timer tmSerial //alternative layout //tMRIcon spstr strCommand.txt,tMRIcon.txt,"~",15 - if(tMRIcon.txt!="") + if(tMRIcon.txt!=""&&p0.w!=320) { //value for tMRIcon, activate alternative layout vis tMainIcon,0 diff --git a/HMI/US/portrait/diff-eu-version.txt b/HMI/US/portrait/diff-eu-version.txt index f9ef7ea2..f82ff3a5 100644 --- a/HMI/US/portrait/diff-eu-version.txt +++ b/HMI/US/portrait/diff-eu-version.txt @@ -1,6 +1,6 @@ diff -bur HMI/n2t-out/Program.s.txt HMI/US/portrait/n2t-out/Program.s.txt ---- HMI/n2t-out/Program.s.txt 2022-06-06 20:43:14.701325786 +0000 -+++ HMI/US/portrait/n2t-out/Program.s.txt 2022-06-06 20:43:15.217352058 +0000 +--- HMI/n2t-out/Program.s.txt 2022-06-08 20:00:07.004980492 +0000 ++++ HMI/US/portrait/n2t-out/Program.s.txt 2022-06-08 20:00:07.521016838 +0000 @@ -11,6 +11,6 @@ // dim value int dimValue=40 @@ -11,8 +11,8 @@ diff -bur HMI/n2t-out/Program.s.txt HMI/US/portrait/n2t-out/Program.s.txt + //lcd_dev fffb 0002 0000 0020 page pageStartup diff -bur HMI/n2t-out/cardEntities.txt HMI/US/portrait/n2t-out/cardEntities.txt ---- HMI/n2t-out/cardEntities.txt 2022-06-06 20:43:14.705325989 +0000 -+++ HMI/US/portrait/n2t-out/cardEntities.txt 2022-06-06 20:43:15.217352058 +0000 +--- HMI/n2t-out/cardEntities.txt 2022-06-08 20:00:07.004980492 +0000 ++++ HMI/US/portrait/n2t-out/cardEntities.txt 2022-06-08 20:00:07.521016838 +0000 @@ -63,6 +63,16 @@ vis bText4,0 vis hSlider4,0 @@ -468,8 +468,8 @@ diff -bur HMI/n2t-out/cardEntities.txt HMI/US/portrait/n2t-out/cardEntities.txt if(tInstruction.txt=="pageType") { diff -bur HMI/n2t-out/cardMedia.txt HMI/US/portrait/n2t-out/cardMedia.txt ---- HMI/n2t-out/cardMedia.txt 2022-06-06 20:43:14.705325989 +0000 -+++ HMI/US/portrait/n2t-out/cardMedia.txt 2022-06-06 20:43:15.217352058 +0000 +--- HMI/n2t-out/cardMedia.txt 2022-06-08 20:00:07.004980492 +0000 ++++ HMI/US/portrait/n2t-out/cardMedia.txt 2022-06-08 20:00:07.521016838 +0000 @@ -45,12 +45,6 @@ Scope: local Value: 0 @@ -518,8 +518,8 @@ diff -bur HMI/n2t-out/cardMedia.txt HMI/US/portrait/n2t-out/cardMedia.txt if(tInstruction.txt=="time") { diff -bur HMI/n2t-out/pageStartup.txt HMI/US/portrait/n2t-out/pageStartup.txt ---- HMI/n2t-out/pageStartup.txt 2022-06-06 20:43:14.705325989 +0000 -+++ HMI/US/portrait/n2t-out/pageStartup.txt 2022-06-06 20:43:15.217352058 +0000 +--- HMI/n2t-out/pageStartup.txt 2022-06-08 20:00:07.004980492 +0000 ++++ HMI/US/portrait/n2t-out/pageStartup.txt 2022-06-08 20:00:07.525017120 +0000 @@ -142,7 +142,7 @@ Disable release event after dragging: 0 Send Component ID : disabled diff --git a/HMI/US/portrait/diff-filtered.txt b/HMI/US/portrait/diff-filtered.txt index 2db9cb62..c9c00a94 100644 --- a/HMI/US/portrait/diff-filtered.txt +++ b/HMI/US/portrait/diff-filtered.txt @@ -1,8 +1,8 @@ -+++ HMI/US/portrait/diff-eu-version.txt 2022-06-06 20:43:15.233352872 +0000 -+--- HMI/n2t-out/Program.s.txt 2022-06-06 20:43:14.701325786 +0000 -++++ HMI/US/portrait/n2t-out/Program.s.txt 2022-06-06 20:43:15.217352058 +0000 -+--- HMI/n2t-out/cardEntities.txt 2022-06-06 20:43:14.705325989 +0000 -++++ HMI/US/portrait/n2t-out/cardEntities.txt 2022-06-06 20:43:15.217352058 +0000 ++++ HMI/US/portrait/diff-eu-version.txt 2022-06-08 20:00:07.557019374 +0000 ++--- HMI/n2t-out/Program.s.txt 2022-06-08 20:00:07.004980492 +0000 +++++ HMI/US/portrait/n2t-out/Program.s.txt 2022-06-08 20:00:07.521016838 +0000 ++--- HMI/n2t-out/cardEntities.txt 2022-06-08 20:00:07.004980492 +0000 +++++ HMI/US/portrait/n2t-out/cardEntities.txt 2022-06-08 20:00:07.521016838 +0000 +@@ -63,6 +63,16 @@ +@@ -120,6 +130,18 @@ +@@ -156,6 +178,15 @@ @@ -13,8 +13,8 @@ +@@ -1075,6 +1281,28 @@ +@@ -1850,6 +2078,169 @@ +diff -bur HMI/n2t-out/cardMedia.txt HMI/US/portrait/n2t-out/cardMedia.txt -+--- HMI/n2t-out/cardMedia.txt 2022-06-06 20:43:14.705325989 +0000 -++++ HMI/US/portrait/n2t-out/cardMedia.txt 2022-06-06 20:43:15.217352058 +0000 ++--- HMI/n2t-out/cardMedia.txt 2022-06-08 20:00:07.004980492 +0000 +++++ HMI/US/portrait/n2t-out/cardMedia.txt 2022-06-08 20:00:07.521016838 +0000 +@@ -45,12 +45,6 @@ + Scope: local + Value: 0 @@ -59,5 +59,5 @@ + } + if(tInstruction.txt=="time") + { -+--- HMI/n2t-out/pageStartup.txt 2022-06-06 20:43:14.705325989 +0000 -++++ HMI/US/portrait/n2t-out/pageStartup.txt 2022-06-06 20:43:15.217352058 +0000 ++--- HMI/n2t-out/pageStartup.txt 2022-06-08 20:00:07.004980492 +0000 +++++ HMI/US/portrait/n2t-out/pageStartup.txt 2022-06-08 20:00:07.525017120 +0000 diff --git a/HMI/US/portrait/n2t-out-visual/screensaver.txt b/HMI/US/portrait/n2t-out-visual/screensaver.txt index e34cce40..08821900 100644 --- a/HMI/US/portrait/n2t-out-visual/screensaver.txt +++ b/HMI/US/portrait/n2t-out-visual/screensaver.txt @@ -901,9 +901,9 @@ Picture p0 Send Component ID : disabled Opacity : 127 x coordinate : 0 - y coordinate : 1 - Width : 319 - Height : 479 + y coordinate : 0 + Width : 320 + Height : 480 Effect : load Effect Priority : 0 Effect Time : 300 @@ -1041,7 +1041,7 @@ Timer tmSerial //alternative layout //tMRIcon spstr strCommand.txt,tMRIcon.txt,"~",15 - if(tMRIcon.txt!="") + if(tMRIcon.txt!=""&&p0.w!=320) { //value for tMRIcon, activate alternative layout vis tMainIcon,0 diff --git a/HMI/US/portrait/n2t-out/screensaver.txt b/HMI/US/portrait/n2t-out/screensaver.txt index 647f08fa..f371cc91 100644 --- a/HMI/US/portrait/n2t-out/screensaver.txt +++ b/HMI/US/portrait/n2t-out/screensaver.txt @@ -476,7 +476,7 @@ Timer tmSerial //alternative layout //tMRIcon spstr strCommand.txt,tMRIcon.txt,"~",15 - if(tMRIcon.txt!="") + if(tMRIcon.txt!=""&&p0.w!=320) { //value for tMRIcon, activate alternative layout vis tMainIcon,0 diff --git a/HMI/n2t-out-visual/nspanel_Stats.txt b/HMI/n2t-out-visual/nspanel_Stats.txt index 6256bab1..977e968f 100644 --- a/HMI/n2t-out-visual/nspanel_Stats.txt +++ b/HMI/n2t-out-visual/nspanel_Stats.txt @@ -22,10 +22,6 @@ popupLight 27 Component(s) 352 Line(s) of event code 191 Unique line(s) of event code -screensaver - 38 Component(s) - 319 Line(s) of event code - 253 Unique line(s) of event code cardMedia 34 Component(s) 363 Line(s) of event code @@ -50,6 +46,10 @@ cardThermo 53 Component(s) 555 Line(s) of event code 292 Unique line(s) of event code +screensaver + 38 Component(s) + 319 Line(s) of event code + 253 Unique line(s) of event code cardEntities 65 Component(s) 1133 Line(s) of event code diff --git a/HMI/n2t-out-visual/screensaver.txt b/HMI/n2t-out-visual/screensaver.txt index 03469e38..00fb5d90 100644 --- a/HMI/n2t-out-visual/screensaver.txt +++ b/HMI/n2t-out-visual/screensaver.txt @@ -1041,7 +1041,7 @@ Timer tmSerial //alternative layout //tMRIcon spstr strCommand.txt,tMRIcon.txt,"~",15 - if(tMRIcon.txt!="") + if(tMRIcon.txt!=""&&p0.w!=320) { //value for tMRIcon, activate alternative layout vis tMainIcon,0 diff --git a/HMI/n2t-out/screensaver.txt b/HMI/n2t-out/screensaver.txt index 84c004cc..3fe97b40 100644 --- a/HMI/n2t-out/screensaver.txt +++ b/HMI/n2t-out/screensaver.txt @@ -476,7 +476,7 @@ Timer tmSerial //alternative layout //tMRIcon spstr strCommand.txt,tMRIcon.txt,"~",15 - if(tMRIcon.txt!="") + if(tMRIcon.txt!=""&&p0.w!=320) { //value for tMRIcon, activate alternative layout vis tMainIcon,0 From 69a661ca63af0cd788d4c7288947aabead0fb688 Mon Sep 17 00:00:00 2001 From: Armilar <102996011+Armilar@users.noreply.github.com> Date: Thu, 9 Jun 2022 00:30:28 +0200 Subject: [PATCH 16/23] Update NsPanelTs.ts --- ioBroker/NsPanelTs.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ioBroker/NsPanelTs.ts b/ioBroker/NsPanelTs.ts index 22b375cb..f9b01b59 100644 --- a/ioBroker/NsPanelTs.ts +++ b/ioBroker/NsPanelTs.ts @@ -924,9 +924,9 @@ function SendTime(): void { function ScreensaverDimmode() { if (timeDimMode.dimmodeOn != undefined ? timeDimMode.dimmodeOn : false) { if (compareTime(timeDimMode.timeNight != undefined ? timeDimMode.timeNight : "23:00", timeDimMode.timeDay != undefined ? timeDimMode.timeDay : "06:00", "not between", null)) { - SendToPanel({ payload: "dimmode~" + timeDimMode.brightnessDay}); + SendToPanel({ payload: "dimmode~" + timeDimMode.brightnessDay + "~" + config.active }); } else { - SendToPanel({ payload: "dimmode~" + timeDimMode.brightnessNight}); + SendToPanel({ payload: "dimmode~" + timeDimMode.brightnessNight + "~" + config.active }); } } else { SendToPanel({ payload: "dimmode~" + config.dimmode + "~" + config.active }); From 16e972b0849d1adabc9469c109dd9c07d194d531 Mon Sep 17 00:00:00 2001 From: Armilar <102996011+Armilar@users.noreply.github.com> Date: Thu, 9 Jun 2022 00:31:50 +0200 Subject: [PATCH 17/23] Update NsPanelTs.ts --- ioBroker/NsPanelTs.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ioBroker/NsPanelTs.ts b/ioBroker/NsPanelTs.ts index 52cc9c56..0038b2c2 100644 --- a/ioBroker/NsPanelTs.ts +++ b/ioBroker/NsPanelTs.ts @@ -933,9 +933,9 @@ function SendTime(): void { function ScreensaverDimmode() { if (timeDimMode.dimmodeOn != undefined ? timeDimMode.dimmodeOn : false) { if (compareTime(timeDimMode.timeNight != undefined ? timeDimMode.timeNight : "23:00", timeDimMode.timeDay != undefined ? timeDimMode.timeDay : "06:00", "not between", null)) { - SendToPanel({ payload: "dimmode~" + timeDimMode.brightnessDay}); + SendToPanel({ payload: "dimmode~" + timeDimMode.brightnessDay + "~" + config.active }); } else { - SendToPanel({ payload: "dimmode~" + timeDimMode.brightnessNight}); + SendToPanel({ payload: "dimmode~" + timeDimMode.brightnessNight + "~" + config.active }); } } else { SendToPanel({ payload: "dimmode~" + config.dimmode + "~" + config.active }); From b2d042e8a92f139bcb52a08080414a1add862eee Mon Sep 17 00:00:00 2001 From: Armilar <102996011+Armilar@users.noreply.github.com> Date: Thu, 9 Jun 2022 12:24:30 +0200 Subject: [PATCH 18/23] Update NsPanelTs.ts --- ioBroker/NsPanelTs.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/ioBroker/NsPanelTs.ts b/ioBroker/NsPanelTs.ts index 2a8ece67..b4f66c7a 100644 --- a/ioBroker/NsPanelTs.ts +++ b/ioBroker/NsPanelTs.ts @@ -74,9 +74,6 @@ Interne Sonoff-Sensoren (über Tasmota): Tasmota-Status0 - (zyklische Ausführung) liefert relevanten Tasmota-Informationen und kann bei Bedarf in "function get_tasmota_status0()" erweitert werden. Daten werden in 0_userdata.0. abgelegt -Tasmota-Status0 - (zyklische Ausführung) - liefert relevanten Tasmota-Informationen und kann bei Bedarf in "function get_tasmota_status0()" erweitert werden. Daten werden in 0_userdata.0. abgelegt - Erforderliche Adapter: Accu-Wheater: - Bei Nutzung der Wetterfunktionen (und zur Icon-Konvertierung) im Screensaver Alexa2: - Bei Nutzung der dynamischen SpeakerList in der cardMedia From d2460f47f66784fb77f4fda4f1df4e4033d30291 Mon Sep 17 00:00:00 2001 From: Johannes Date: Thu, 9 Jun 2022 17:48:30 +0200 Subject: [PATCH 19/23] set maxsplit to 3 for iText #270 --- apps/nspanel-lovelace-ui/luibackend/pages.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/nspanel-lovelace-ui/luibackend/pages.py b/apps/nspanel-lovelace-ui/luibackend/pages.py index 1e93c66a..054650e1 100644 --- a/apps/nspanel-lovelace-ui/luibackend/pages.py +++ b/apps/nspanel-lovelace-ui/luibackend/pages.py @@ -179,8 +179,8 @@ class LuiPagesGen(object): else: return f"~text~{entityId}~{get_icon_id('alert-circle-outline')}~17299~page not found~" if entityType == "iText": - key = entityId.split(".")[1] - value = entityId.split(".")[2] + key = entityId.split(".", 3)[1] + value = entityId.split(".", 3)[2] icon_id = get_icon_id(icon) if icon is not None else get_icon_id("alert-circle-outline") return f"~text~{entityId}~{icon_id}~17299~{key}~{value}" if not self._ha_api.entity_exists(entityId): From c401dc7d3d665257d1eb655e43e2462ec48b1e1f Mon Sep 17 00:00:00 2001 From: Johannes Date: Thu, 9 Jun 2022 17:56:01 +0200 Subject: [PATCH 20/23] Update pages.py --- apps/nspanel-lovelace-ui/luibackend/pages.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/nspanel-lovelace-ui/luibackend/pages.py b/apps/nspanel-lovelace-ui/luibackend/pages.py index 054650e1..5e9d35cf 100644 --- a/apps/nspanel-lovelace-ui/luibackend/pages.py +++ b/apps/nspanel-lovelace-ui/luibackend/pages.py @@ -179,10 +179,10 @@ class LuiPagesGen(object): else: return f"~text~{entityId}~{get_icon_id('alert-circle-outline')}~17299~page not found~" if entityType == "iText": - key = entityId.split(".", 3)[1] - value = entityId.split(".", 3)[2] + value = entityId.split(".", 2)[1] + name = name if name is not None else "conf name missing" icon_id = get_icon_id(icon) if icon is not None else get_icon_id("alert-circle-outline") - return f"~text~{entityId}~{icon_id}~17299~{key}~{value}" + return f"~text~{entityId}~{icon_id}~17299~{name}~{value}" if not self._ha_api.entity_exists(entityId): return f"~text~{entityId}~{get_icon_id('alert-circle-outline')}~17299~Not found check~ apps.yaml" From e3971ce7e422cfa5ac4b2823fd0af98c5aa217f5 Mon Sep 17 00:00:00 2001 From: Johannes Date: Thu, 9 Jun 2022 17:56:51 +0200 Subject: [PATCH 21/23] Update README.md --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 075040bc..ef83719d 100644 --- a/README.md +++ b/README.md @@ -354,9 +354,11 @@ nspanel-1: title: Guest Wifi qrCode: "WIFI:S:test_ssid;T:WPA;P:test_pw;;" entities: - - entity: iText.Name.test_ssid + - entity: iText.test_ssid + name: Name icon: mdi:wifi - - entity: iText.Password.test_pw + - entity: iText.test_pw + name: Password icon: mdi:key ``` From 8d4ccf792021455ee74256a61b06c05fb2763a6a Mon Sep 17 00:00:00 2001 From: Johannes Date: Fri, 10 Jun 2022 17:36:55 +0200 Subject: [PATCH 22/23] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index ef83719d..fac5d625 100644 --- a/README.md +++ b/README.md @@ -246,6 +246,10 @@ Support for ESPHome is WIP, see this third-party [ESPHome component](https://git ## Configuration +Note this is the documentation of the current development version and might have changed since latest release, so see the documentation of the current release visit: + +https://github.com/joBr99/nspanel-lovelace-ui/tree/v2.9.3 + ### Configuring the MQTT integration in AppDaemon For the app to work you need a working MQTT Configuration in AppDaemon. Please add the configuration of your mqtt server, user and password to your existing `appdaemon.yaml` From 39c94690f30b28872c2d2c033db0076f5598e48c Mon Sep 17 00:00:00 2001 From: Johannes Date: Sat, 11 Jun 2022 09:20:34 +0200 Subject: [PATCH 23/23] fixed #269 --- README.md | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/README.md b/README.md index fac5d625..c3275e1f 100644 --- a/README.md +++ b/README.md @@ -176,7 +176,7 @@ You only need to do one **Tasmota** OR **ESPHome** ### Flash Tasmota to your NSPanel -You need to connect to your nspanel via serial and flash the [tasmota32-nspanel.bin](https://github.com/tasmota/install/raw/main/firmware/unofficial/tasmota32-nspanel.bin) to your NSPanel. +You need to connect to your nspanel via serial and flash tasmtoa [tasmota32-nspanel.factory.bin](https://tasmota.github.io/install/firmware/development/tasmota32-nspanel.factory.bin) to your NSPanel. You can use the Tasmota Web Installer to do so. [Tasmota Web Installer](https://tasmota.github.io/install/) Make sure to come back to this guide, before uploading the nspanel.be/autoexec.be files. For more deatils see the [NSPanel Page of the Tasmota Template Repository](https://templates.blakadder.com/sonoff_NSPanel.html). @@ -774,11 +774,6 @@ Since release 1.1 you can update the berry driver directly from the Tasmota Cons ## FAQ - Frequently Asked Questions -### Flashing of the Display Firmware with FlashNextion doesn't work - -1. Make sure to use the [tasmota32-nspanel.bin](https://github.com/tasmota/install/raw/main/firmware/unofficial/tasmota32-nspanel.bin) Tasmota build. -2. Make sure to use HTTP and **not HTTPS** - ### Waiting for content - This is taking longer than usual on the screen Please check your MQTT Topics in your apps.yaml and your mqtt configuration on tasmota.