mirror of
https://github.com/joBr99/nspanel-lovelace-ui.git
synced 2025-12-21 15:04:24 +01:00
In the tado adapter, the level.temperature DP can be null if AWAY or power is off. In this case, use the configured minValue.
4300 lines
215 KiB
TypeScript
4300 lines
215 KiB
TypeScript
/*-----------------------------------------------------------------------
|
|
TypeScript v3.5.0 zur Steuerung des SONOFF NSPanel mit dem ioBroker by @Armilar/@Britzelpuf
|
|
- abgestimmt auf TFT 43 / v3.5.0 / BerryDriver 4 / Tasmota 12.2.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
|
|
WIKI zu diesem Projekt unter: https://github.com/joBr99/nspanel-lovelace-ui/wiki (siehe Sidebar)
|
|
Icons unter: https://htmlpreview.github.io/?https://github.com/jobr99/Generate-HASP-Fonts/blob/master/cheatsheet.html
|
|
|
|
*******************************************************************************
|
|
Achtung Änderung des Sonoff ESP-Temperatursensors
|
|
!!! Bitte "SetOption146 1" in der Tasmota-Console ausführen !!!
|
|
*******************************************************************************
|
|
|
|
ReleaseNotes:
|
|
Bugfixes und Erweiterungen:
|
|
- cardQR (für Gäste WLAN)
|
|
- cardThermo (Neues Design für Alias Thermostat und zusätzlich für Alias Klimaanlage)
|
|
- 08.05.2022 - v2.9.0 - Menüpfeile bei HardwareButtons (button1Page; button2Page) mit Navigation auf Page 0
|
|
- 08.05.2022 - v2.9.0 - Standard-Brightness über neuen Parameter active einstellbar (Test mit 2.9.3)
|
|
- 08.05.2022 - v2.9.0 - Schalter (Licht, Dimmer, Hue, etc) in cardGrid lassen sich wieder schalten
|
|
- 14.06.2022 - v2.9.0 - Aktion auf Submenüs schaltet unmittelbar auf vorheriges Mainmenu (Many thanks to Grrzzz)
|
|
- 14.06.2022 - v2.9.0 - Menü-Pfeile in Subpages (z.B. card QR, cardMedia, etc) (Many thanks to Grrzzz)
|
|
- 15.06.2022 - v3.0.0 - Date/Time im Screensaver auf Basis localString (de-DE/en-EN/nl-NL/etc.)
|
|
- 16.06.2022 - v3.0.0 - Multilingual - config.locale (en-EN, de-DE, nl-NL, da-DK, es-ES, fr-FR, it-IT, ru-RU, etc.)
|
|
- 16.06.2022 - v3.0.0 - Bugfix by Grrzzz - Subpages
|
|
- 18.06.2022 - v3.1.0 - Längere Textfelder in cardEntities
|
|
- 18.06.2022 - V3.1.0 - Detail-Page Lights/Shutter hat neuen Parameter "id"
|
|
- 19.06.2022 - v3.1.0 - Bugfix toLocalTimeString in en-EN/en-US
|
|
- 19.06.2022 - v3.1.0 - Fehler in findLocale abgefangen
|
|
- 19.06.2022 - v3.1.0 - Umstellung auf "Home Assistant" Sprachfile
|
|
- 19.06.2022 - v3.1.0 - Alias "light" und "socket" haben optionalen Parameter icon2 für negative Zustände
|
|
- 29.06.2022 - v3.1.1 - Bugfix Github #286 (Active Page) + Bugfix pageThermo, pageMedia, pageAlarm as first Page
|
|
- 25.08.2022 - v3.1.0 - Code-Verbesserungen (klein0r)
|
|
- 26.08.2022 - v3.2.0 - pageItem mit CIE (XY) Parameter für ColorWheel (Steuerung für z.B Deconz-Farben bei denen Hue nicht greift)
|
|
- 28.08.2022 - v3.2.0 - Wechsel zwischen Weather-Forecast und eigenen Datenpunkten im Screensaver (minütlich)
|
|
- 28.08.2022 - v3.2.0 - Bugfix für 3.2.0 in GenerateDetailPage: Color-Language nicht über findLocales, da nicht in Sprachfile enthalten
|
|
- 29.08.2022 - v3.3.0 - Upgrade TFT 40
|
|
- 29.08.2022 - v3.3.1 - Upgrade TFT 41
|
|
- 04.09.2022 - v3.3.1 - Überarbeitung und BugFix für cardAlarm
|
|
- 13.09.2022 - v3.3.1.3 BugFix Screensaver Toggle
|
|
- 13.09.2022 - v3.3.1.3 Überarbeitung und BugFix und Refresh Features für cardMedia (Breaking Changes)
|
|
- 13.09.2022 - v3.3.1.3 Hinzufügen von SpotifyPremium, Sonos und Chromecast (Google home) zur cardMedia-Logik
|
|
- 15.09.2022 - V3.4.0 - BugFix Dimmode
|
|
- 15.09.2022 - V3.4.0 - Colormode für Screensaver + AutoColor WeatherForecast
|
|
- 16.09.2022 - v3.4.0.1 Visualisierung der Relay Zustände (MRIcons) im Screensaver + Bugfix Screensaver MRIcon2
|
|
- 17.09.2022 - v3.4.0.2 Bugfix for screensaver icons with scaled colors
|
|
- 17.09.2022 - v3.4.0.3 Bugfix bNext / bPrev by joBr99
|
|
- 18.09.2022 - v3.4.0.4 Add On/Off Colors in config.mrIcon1ScreensaverEntity and config.mrIcon2ScreensaverEntity
|
|
- 19.09.2022 - v3.4.0.5 Add Mode to cardThermo (Alias Thermostat)
|
|
- 03.10.2022 - v3.4.0.6 Add 5 Entities in US Panel Version to cardEntities
|
|
- 03.10.2022 - v3.4.0.6 Fix screenSaverDoubleClick
|
|
- 03.10.2022 - v3.4.0.6 Add cardPower (experimental)
|
|
- 05.10.2022 - v3.4.0.6 Add sueezeboxrpc to cardMedia
|
|
- 07.10.2022 - v3.4.0.6 Time-configurable change for screensaver icons
|
|
- 07.10.2022 - v3.5.0 Add Backgroundcolor to Pages
|
|
- 08.10.2022 - v3.5.0 Add Tilt-Slider and TILT_Fucntions (Open/Stop/Close) to Blinds/Cover/Shutter popUp
|
|
- 12.10.2022 - v3.5.0 Add PageNavigation via Datapoint
|
|
- 25.10.2022 - v3.5.0 Add New Parameters to popUpNotify / Layout 2
|
|
|
|
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)
|
|
cardEntities 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
|
|
cardPower Page - Energiefluss
|
|
|
|
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 --> SetOption146 1
|
|
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-v3.5.0.tft
|
|
---------------------------------------------------------------------------------------
|
|
*/
|
|
var Icons = new IconsSelector();
|
|
var timeoutSlider: any;
|
|
var manually_Update = false;
|
|
|
|
const NSPanel_Path = '0_userdata.0.NSPanel.1.';
|
|
const NSPanel_Alarm_Path = '0_userdata.0.NSPanel.'; //Neuer Pfad für gemeinsame Nutzung durch mehrere Panels (bei Nutzung der cardAlarm)
|
|
const Debug = false;
|
|
|
|
// Variablen zur Steuerung der Wettericons auf dem Screensaver (Steuerung in 0_userdata.0.XPANELX.ScreensaverInfo)
|
|
// Wenn weatherForecastTimer auf true, dann Wechsel zwischen Datenpunkten und Wettervorhersage (30 Sekunden nach Minute (Zeit))
|
|
// Wenn weatherForecastTimer auf false, dann Möglichkeit über weatherForecast, ob Datenpunkte oder Wettervorhersage (true = WeatherForecast/false = Datenpunkte)
|
|
var weatherForecast: boolean; //Änderung zum Video --> Einstellung siehe Wiki
|
|
|
|
const HMIOff: RGB = { red: 68, green: 115, blue: 158 }; // Blau-Off - Original Entity Off
|
|
const HMIDark: RGB = { red: 29, green: 29, blue: 29 }; // Original Background Color
|
|
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 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 DarkBlue: RGB = { red: 0, green: 0, blue: 136 };
|
|
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 };
|
|
|
|
//Dynamische Indikatoren
|
|
const colorScale0: RGB = { red: 99, green: 190, blue: 123 };
|
|
const colorScale1: RGB = { red: 129, green: 199, blue: 126 };
|
|
const colorScale2: RGB = { red: 161, green: 208, blue: 127 };
|
|
const colorScale3: RGB = { red: 129, green: 217, blue: 126 };
|
|
const colorScale4: RGB = { red: 222, green: 226, blue: 131 };
|
|
const colorScale5: RGB = { red: 254, green: 235, blue: 132 };
|
|
const colorScale6: RGB = { red: 255, green: 210, blue: 129 };
|
|
const colorScale7: RGB = { red: 251, green: 185, blue: 124 };
|
|
const colorScale8: RGB = { red: 251, green: 158, blue: 117 };
|
|
const colorScale9: RGB = { red: 248, green: 131, blue: 111 };
|
|
const colorScale10: RGB = { red: 248, green: 105, blue: 107 };
|
|
|
|
//Screensaver Default Theme Colors
|
|
const scbackground: RGB = { red: 0, green: 0, blue: 0};
|
|
const sctime: RGB = { red: 255, green: 255, blue: 255};
|
|
const sctimeAMPM: RGB = { red: 255, green: 255, blue: 255};
|
|
const scdate: RGB = { red: 255, green: 255, blue: 255};
|
|
const sctMainIcon: RGB = { red: 255, green: 255, blue: 255};
|
|
const sctMainText: RGB = { red: 255, green: 255, blue: 255};
|
|
const sctForecast1: RGB = { red: 255, green: 255, blue: 255};
|
|
const sctForecast2: RGB = { red: 255, green: 255, blue: 255};
|
|
const sctForecast3: RGB = { red: 255, green: 255, blue: 255};
|
|
const sctForecast4: RGB = { red: 255, green: 255, blue: 255};
|
|
const sctF1Icon: RGB = { red: 255, green: 235, blue: 156};
|
|
const sctF2Icon: RGB = { red: 255, green: 235, blue: 156};
|
|
const sctF3Icon: RGB = { red: 255, green: 235, blue: 156};
|
|
const sctF4Icon: RGB = { red: 255, green: 235, blue: 156};
|
|
const sctForecast1Val: RGB = { red: 255, green: 255, blue: 255};
|
|
const sctForecast2Val: RGB = { red: 255, green: 255, blue: 255};
|
|
const sctForecast3Val: RGB = { red: 255, green: 255, blue: 255};
|
|
const sctForecast4Val: RGB = { red: 255, green: 255, blue: 255};
|
|
const scbar: RGB = { red: 255, green: 255, blue: 255};
|
|
const sctMainIconAlt: RGB = { red: 255, green: 255, blue: 255};
|
|
const sctMainTextAlt: RGB = { red: 255, green: 255, blue: 255};
|
|
const sctTimeAdd: RGB = { red: 255, green: 255, blue: 255};
|
|
|
|
//Auto-Weather-Colors
|
|
const swClearNight: RGB = { red: 150, green: 150, blue: 100};
|
|
const swCloudy: RGB = { red: 75, green: 75, blue: 75};
|
|
const swExceptional: RGB = { red: 255, green: 50, blue: 50};
|
|
const swFog: RGB = { red: 150, green: 150, blue: 150};
|
|
const swHail: RGB = { red: 200, green: 200, blue: 200};
|
|
const swLightning: RGB = { red: 200, green: 200, blue: 0};
|
|
const swLightningRainy: RGB = { red: 200, green: 200, blue: 150};
|
|
const swPartlycloudy: RGB = { red: 150, green: 150, blue: 150};
|
|
const swPouring: RGB = { red: 50, green: 50, blue: 255};
|
|
const swRainy: RGB = { red: 100, green: 100, blue: 255};
|
|
const swSnowy: RGB = { red: 150, green: 150, blue: 150};
|
|
const swSnowyRainy: RGB = { red: 150, green: 150, blue: 255};
|
|
const swSunny: RGB = { red: 255, green: 255, blue: 0};
|
|
const swWindy: RGB = { red: 150, green: 150, blue: 150};
|
|
|
|
var vwIconColor = [];
|
|
|
|
//-- Anfang der Variablen für Seitengestaltung -- Aliase erforderlich ----------------
|
|
|
|
|
|
|
|
//-- ENDE der Variablen für Seitengestaltung -- Aliase erforderlich ------------------
|
|
|
|
export const config: Config = {
|
|
panelRecvTopic: 'mqtt.0.SmartHome.NSPanel_1.tele.RESULT', // anpassen
|
|
panelSendTopic: 'mqtt.0.SmartHome.NSPanel_1.cmnd.CustomSend', // anpassen
|
|
firstScreensaverEntity: { ScreensaverEntity: 'accuweather.0.Hourly.h0.PrecipitationProbability', ScreensaverEntityIcon: 'weather-pouring', ScreensaverEntityText: 'Regen', ScreensaverEntityUnitText: '%', ScreensaverEntityIconColor: {'val_min': 0, 'val_max': 100} },
|
|
secondScreensaverEntity: { ScreensaverEntity: 'accuweather.0.Current.WindSpeed', ScreensaverEntityIcon: 'weather-windy', ScreensaverEntityText: "Wind", ScreensaverEntityUnitText: 'km/h', ScreensaverEntityIconColor: {'val_min': 0, 'val_max': 120} },
|
|
thirdScreensaverEntity: { ScreensaverEntity: 'accuweather.0.Current.UVIndex', ScreensaverEntityIcon: 'solar-power', ScreensaverEntityText: 'UV', ScreensaverEntityUnitText: '', ScreensaverEntityIconColor: {'val_min': 0, 'val_max': 9} },
|
|
fourthScreensaverEntity: { ScreensaverEntity: 'accuweather.0.Current.RelativeHumidity', ScreensaverEntityIcon: 'water-percent', ScreensaverEntityText: 'Luft', ScreensaverEntityUnitText: '%', ScreensaverEntityIconColor: {'val_min': 0, 'val_max': 100, 'val_best': 65} },
|
|
alternativeScreensaverLayout: false,
|
|
autoWeatherColorScreensaverLayout: true,
|
|
//!!!! Achtung anpassen !!!!
|
|
mrIcon1ScreensaverEntity: { ScreensaverEntity: 'mqtt.0.SmartHome.NSPanel_1.stat.POWER1', ScreensaverEntityIcon: 'light-switch', ScreensaverEntityOnColor: On, ScreensaverEntityOffColor: Off },
|
|
mrIcon2ScreensaverEntity: { ScreensaverEntity: 'mqtt.0.SmartHome.NSPanel_1.stat.POWER2', ScreensaverEntityIcon: 'lightbulb', ScreensaverEntityOnColor: On, ScreensaverEntityOffColor: Off },
|
|
timeoutScreensaver: 20,
|
|
dimmode: 20,
|
|
active: 100, //Standard-Brightness TFT
|
|
screenSaverDoubleClick: true,
|
|
locale: 'de-DE', // en-US, de-DE, nl-NL, da-DK, es-ES, fr-FR, it-IT, ru-RU, etc.
|
|
timeFormat: '%H:%M', // currently not used
|
|
dateFormat: '%A, %d. %B %Y', // currently not used
|
|
weatherEntity: 'alias.0.Wetter', // Dieser Alias muss erstellt werden, damit die 4 kleineren Icons (Wetter oder DP) angezeigt werden können
|
|
defaultOffColor: Off,
|
|
defaultOnColor: On,
|
|
defaultColor: Off,
|
|
defaultBackgroundColor: Black, //New Parameter
|
|
temperatureUnit: '°C',
|
|
pages: [
|
|
|
|
],
|
|
subPages: [
|
|
|
|
],
|
|
button1Page: null, //Beispiel-Seite auf Button 1, wenn Rule2 definiert - Wenn nicht definiert --> button1Page: null,
|
|
button2Page: null //Beispiel-Seite auf Button 2, wenn Rule2 definiert - Wenn nicht definiert --> button1Page: null,
|
|
};
|
|
|
|
// _________________________________ Ab hier keine Konfiguration mehr _____________________________________
|
|
|
|
const request = require('request');
|
|
|
|
//---------------------Begin PageNavi
|
|
async function InitPageNavi() {
|
|
try {
|
|
if (!existsState(NSPanel_Path + 'PageNavi')) {
|
|
await createStateAsync(NSPanel_Path + 'PageNavi', <iobJS.StateCommon>{ type: 'string' });
|
|
await setStateAsync(NSPanel_Path + 'PageNavi', <iobJS.State>{ val: {"pagetype": "page","pageId": 0}, ack: true });
|
|
}
|
|
} catch (err) {
|
|
console.log('function InitPageNavi: ' + err.message);
|
|
}
|
|
}
|
|
InitPageNavi();
|
|
|
|
//PageNavi
|
|
on({id: [].concat([NSPanel_Path + 'PageNavi']), change: "any"}, async function (obj) {
|
|
if (existsState(NSPanel_Path + 'PageNavi')) {
|
|
let vObj = JSON.parse(obj.state.val);
|
|
if (vObj.pagetype == 'page') {
|
|
GeneratePage(config.pages[vObj.pageId]);
|
|
} else if (vObj.pagetype == 'subpage') {
|
|
GeneratePage(config.subPages[vObj.pageId]);
|
|
}
|
|
}
|
|
});
|
|
|
|
//----------------------Begin Dimmode
|
|
|
|
function ScreensaverDimmode(timeDimMode: DimMode) {
|
|
try {
|
|
if (Debug) console.log(rgb_dec565(HMIDark))
|
|
if (Debug) console.log('Dimmode='+ timeDimMode.dimmodeOn)
|
|
if (timeDimMode.dimmodeOn != undefined ? timeDimMode.dimmodeOn : false) {
|
|
if (compareTime(timeDimMode.timeNight != undefined ? timeDimMode.timeNight : '22:00', timeDimMode.timeDay != undefined ? timeDimMode.timeDay : '07:00', 'not between', undefined)) {
|
|
SendToPanel({ payload: 'dimmode~' + timeDimMode.brightnessDay + '~' + config.active + '~' + rgb_dec565(config.defaultBackgroundColor) });
|
|
if (Debug) console.log('Day Payload: ' + 'dimmode~' + timeDimMode.brightnessDay + '~' + config.active )
|
|
} else {
|
|
SendToPanel({ payload: 'dimmode~' + timeDimMode.brightnessNight + '~' + config.active + '~' + rgb_dec565(config.defaultBackgroundColor) });
|
|
if (Debug) console.log('Night Payload: ' + 'dimmode~' + timeDimMode.brightnessNight + '~' + config.active )
|
|
}
|
|
} else {
|
|
SendToPanel({ payload: 'dimmode~' + config.dimmode + '~' + config.active + '~' + rgb_dec565(config.defaultBackgroundColor) });
|
|
}
|
|
} catch (err) {
|
|
console.warn('function ScreensaverDimmode: ' + err.message);
|
|
}
|
|
}
|
|
|
|
async function InitWeatherForecast() {
|
|
try {
|
|
//----Möglichkeit, im Screensaver zwischen Accu-Weather Forecast oder selbstdefinierten Werten zu wählen---------------------------------
|
|
if (existsState(NSPanel_Path + "ScreensaverInfo.weatherForecast") == false ||
|
|
existsState(NSPanel_Path + "ScreensaverInfo.weatherForecastTimer") == false ||
|
|
existsState(NSPanel_Path + "ScreensaverInfo.entityChangeTime") == false) {
|
|
await createStateAsync(NSPanel_Path + "ScreensaverInfo.weatherForecast", true, { type: 'boolean' });
|
|
await createStateAsync(NSPanel_Path + "ScreensaverInfo.weatherForecastTimer", true, { type: 'boolean' });
|
|
await createStateAsync(NSPanel_Path + "ScreensaverInfo.entityChangeTime", 60, { type: 'number' });
|
|
};
|
|
} catch (err) {
|
|
console.warn('function InitWeatherForecast: ' + err.message);
|
|
}
|
|
}
|
|
|
|
InitWeatherForecast();
|
|
|
|
async function InitDimmode() {
|
|
try {
|
|
// Screensaver nachts auf dunkel ("brightnessNight: z.B. 2") oder aus ("brightnessNight:0")
|
|
if (!existsState(NSPanel_Path + 'NSPanel_Dimmode_brightnessDay')) {
|
|
await createStateAsync(NSPanel_Path + 'NSPanel_Dimmode_brightnessDay', <iobJS.StateCommon>{ type: 'number' });
|
|
await setStateAsync(NSPanel_Path + 'NSPanel_Dimmode_brightnessDay', <iobJS.State>{ val: 8, ack: true });
|
|
}
|
|
|
|
if (!existsState(NSPanel_Path + 'NSPanel_Dimmode_hourDay')) {
|
|
await createStateAsync(NSPanel_Path + 'NSPanel_Dimmode_hourDay', <iobJS.StateCommon>{ type: 'number' });
|
|
await setStateAsync(NSPanel_Path + 'NSPanel_Dimmode_hourDay', <iobJS.State>{ val: 7, ack: true });
|
|
}
|
|
|
|
if (!existsState(NSPanel_Path + 'NSPanel_Dimmode_brightnessNight')) {
|
|
await createStateAsync(NSPanel_Path + 'NSPanel_Dimmode_brightnessNight', <iobJS.StateCommon>{ type: 'number' });
|
|
await setStateAsync(NSPanel_Path + 'NSPanel_Dimmode_brightnessNight', <iobJS.State>{ val: 1, ack: true });
|
|
}
|
|
|
|
if (!existsState(NSPanel_Path + 'NSPanel_Dimmode_hourNight')) {
|
|
await createStateAsync(NSPanel_Path + 'NSPanel_Dimmode_hourNight', <iobJS.StateCommon>{ type: 'number' });
|
|
await setStateAsync(NSPanel_Path + 'NSPanel_Dimmode_hourNight', <iobJS.State>{ val: 22, ack: true });
|
|
}
|
|
|
|
const vTimeDay = getState(NSPanel_Path + 'NSPanel_Dimmode_hourDay').val;
|
|
const vTimeNight = getState(NSPanel_Path + 'NSPanel_Dimmode_hourNight').val;
|
|
|
|
const timeDimMode = <DimMode>{
|
|
dimmodeOn: true,
|
|
brightnessDay: getState(NSPanel_Path + 'NSPanel_Dimmode_brightnessDay').val,
|
|
brightnessNight: getState(NSPanel_Path + 'NSPanel_Dimmode_brightnessNight').val,
|
|
timeDay: (vTimeDay < 10) ? `0${vTimeDay}:00` : `${vTimeDay}:00`,
|
|
timeNight: (vTimeNight < 10) ? `0${vTimeNight}:00` : `${vTimeNight}:00`
|
|
};
|
|
|
|
// timeDimMode Day
|
|
schedule({ hour: getState(NSPanel_Path + 'NSPanel_Dimmode_hourDay').val, minute: 0 }, () => {
|
|
ScreensaverDimmode(timeDimMode);
|
|
});
|
|
|
|
// timeDimMode Night
|
|
schedule({ hour: getState(NSPanel_Path + 'NSPanel_Dimmode_hourNight').val, minute: 0 }, () => {
|
|
ScreensaverDimmode(timeDimMode);
|
|
});
|
|
|
|
ScreensaverDimmode(timeDimMode);
|
|
} catch (err) {
|
|
console.warn('function InitDimmode: ' + err.message);
|
|
}
|
|
}
|
|
|
|
InitDimmode();
|
|
|
|
//--------------------End Dimmode
|
|
|
|
// Datenpunkte für Nachricht an Screensaver
|
|
const screensaverNotifyHeading = NSPanel_Path + 'ScreensaverInfo.popupNotifyHeading';
|
|
const screensaverNotifyText = NSPanel_Path + 'ScreensaverInfo.popupNotifyText';
|
|
|
|
// Datenpunkte für Nachricht popupNotify Page
|
|
const popupNotifyHeading = NSPanel_Path + 'popupNotify.popupNotifyHeading';
|
|
const popupNotifyHeadingColor = NSPanel_Path + 'popupNotify.popupNotifyHeadingColor';
|
|
const popupNotifyText = NSPanel_Path + 'popupNotify.popupNotifyText';
|
|
const popupNotifyTextColor = NSPanel_Path + 'popupNotify.popupNotifyTextColor';
|
|
const popupNotifyInternalName = NSPanel_Path + 'popupNotify.popupNotifyInternalName'; // Wird mit Button-Action zurückgeschrieben
|
|
const popupNotifyButton1TextColor = NSPanel_Path + 'popupNotify.popupNotifyButton1TextColor';
|
|
const popupNotifyButton1Text = NSPanel_Path + 'popupNotify.popupNotifyButton1Text';
|
|
const popupNotifyButton2TextColor = NSPanel_Path + 'popupNotify.popupNotifyButton2TextColor';
|
|
const popupNotifyButton2Text = NSPanel_Path + 'popupNotify.popupNotifyButton2Text';
|
|
const popupNotifySleepTimeout = NSPanel_Path + 'popupNotify.popupNotifySleepTimeout'; // in sek. / wenn 0, dann bleibt die Nachricht stehen
|
|
const popupNotifyAction = NSPanel_Path + 'popupNotify.popupNotifyAction'; // Antwort aus dem Panel true/false
|
|
const popupNotifyLayout = NSPanel_Path + 'popupNotify.popupNotifyLayout';
|
|
const popupNotifyFontIdText = NSPanel_Path + 'popupNotify.popupNotifyFontIdText'; 1 - 5
|
|
const popupNotifyIcon = NSPanel_Path + 'popupNotify.popupNotifyIcon'; 1 - 5
|
|
const popupNotifyIconColor = NSPanel_Path + 'popupNotify.popupNotifyIconColor'; 1 - 5
|
|
|
|
async function InitPopupNotify() {
|
|
try {
|
|
if (!existsState(screensaverNotifyHeading)) {
|
|
await createStateAsync(screensaverNotifyHeading, <iobJS.StateCommon>{ type: 'string' });
|
|
await setStateAsync(screensaverNotifyHeading, <iobJS.State>{ val: '', ack: true });
|
|
}
|
|
|
|
if (!existsState(screensaverNotifyText)) {
|
|
await createStateAsync(screensaverNotifyText, <iobJS.StateCommon>{ type: 'string' });
|
|
await setStateAsync(screensaverNotifyText, <iobJS.State>{ val: '', ack: true });
|
|
}
|
|
|
|
await createStateAsync(popupNotifyHeading, <iobJS.StateCommon>{ type: 'string' });
|
|
await createStateAsync(popupNotifyHeadingColor, <iobJS.StateCommon>{ type: 'string' });
|
|
await createStateAsync(popupNotifyText, <iobJS.StateCommon>{ type: 'string' });
|
|
await createStateAsync(popupNotifyTextColor, <iobJS.StateCommon>{ type: 'string' });
|
|
await createStateAsync(popupNotifyInternalName, <iobJS.StateCommon>{ type: 'string' });
|
|
await createStateAsync(popupNotifyButton1Text, <iobJS.StateCommon>{ type: 'string' });
|
|
await createStateAsync(popupNotifyButton1TextColor, <iobJS.StateCommon>{ type: 'string' });
|
|
await createStateAsync(popupNotifyButton2Text, <iobJS.StateCommon>{ type: 'string' });
|
|
await createStateAsync(popupNotifyButton2TextColor, <iobJS.StateCommon>{ type: 'string' });
|
|
await createStateAsync(popupNotifySleepTimeout, <iobJS.StateCommon>{ type: 'number' });
|
|
await createStateAsync(popupNotifyAction, <iobJS.StateCommon>{ type: 'boolean' });
|
|
await createStateAsync(popupNotifyLayout, <iobJS.StateCommon>{ type: 'number' });
|
|
await createStateAsync(popupNotifyFontIdText, <iobJS.StateCommon>{ type: 'number' });
|
|
await createStateAsync(popupNotifyIcon, <iobJS.StateCommon>{ type: 'string' });
|
|
await createStateAsync(popupNotifyIconColor, <iobJS.StateCommon>{ type: 'string' });
|
|
|
|
// Notification to screensaver
|
|
on({ id: [screensaverNotifyHeading, screensaverNotifyText], change: 'ne', ack: false }, async (obj) => {
|
|
const heading = getState(screensaverNotifyHeading).val;
|
|
const text = getState(screensaverNotifyText).val;
|
|
|
|
setIfExists(config.panelSendTopic, `notify~${heading}~${text}`);
|
|
|
|
if (obj.id) {
|
|
await setStateAsync(obj.id, <iobJS.State>{ val: obj.state.val, ack: true }); // ack new value
|
|
}
|
|
});
|
|
|
|
// popupNotify - Notification an separate Seite
|
|
on({ id: [popupNotifyInternalName], change: 'ne' }, async (obj) => {
|
|
|
|
var notification : string = ''
|
|
|
|
let v_popupNotifyHeadingColor = (getState(popupNotifyHeadingColor).val != null) ? getState(popupNotifyHeadingColor).val : '65504'// Farbe Headline - gelb 65504
|
|
let v_popupNotifyButton1TextColor = (getState(popupNotifyButton1TextColor).val != null) ? getState(popupNotifyButton1TextColor).val : '63488'// Farbe Headline - gelb 65504
|
|
let v_popupNotifyButton2TextColor = (getState(popupNotifyButton2TextColor).val != null) ? getState(popupNotifyButton2TextColor).val : '2016'// Farbe Headline - gelb 65504
|
|
let v_popupNotifyTextColor = (getState(popupNotifyTextColor).val != null) ? getState(popupNotifyTextColor).val : '65535'// Farbe Headline - gelb 65504
|
|
let v_popupNotifyIconColor = (getState(popupNotifyIconColor).val != null) ? getState(popupNotifyIconColor).val : '65535'// Farbe Headline - gelb 65504
|
|
let v_popupNotifyFontIdText = (getState(popupNotifyFontIdText).val != null) ? getState(popupNotifyFontIdText).val : '1'
|
|
let v_popupNotifyIcon = (getState(popupNotifyIcon).val != null) ? getState(popupNotifyIcon).val : 'alert'
|
|
|
|
notification = 'entityUpdateDetail' + '~'
|
|
+ getState(popupNotifyInternalName).val + '~'
|
|
+ getState(popupNotifyHeading).val + '~'
|
|
+ v_popupNotifyHeadingColor + '~'
|
|
+ getState(popupNotifyButton1Text).val + '~'
|
|
+ v_popupNotifyButton1TextColor + '~'
|
|
+ getState(popupNotifyButton2Text).val + '~'
|
|
+ v_popupNotifyButton2TextColor + '~'
|
|
+ getState(popupNotifyText).val + '~'
|
|
+ v_popupNotifyTextColor + '~'
|
|
+ getState(popupNotifySleepTimeout).val;
|
|
|
|
if (getState(popupNotifyLayout).val == 2) {
|
|
notification = notification + '~'
|
|
+ v_popupNotifyFontIdText + '~'
|
|
+ Icons.GetIcon(v_popupNotifyIcon) + '~'
|
|
+ v_popupNotifyIconColor;
|
|
}
|
|
|
|
setIfExists(config.panelSendTopic, 'pageType~popupNotify');
|
|
setIfExists(config.panelSendTopic, notification);
|
|
|
|
});
|
|
} catch (err) {
|
|
console.warn('function InitPopupNotify: ' + err.message);
|
|
}
|
|
}
|
|
|
|
InitPopupNotify();
|
|
|
|
let subscriptions: any = {};
|
|
let screensaverEnabled: boolean = false;
|
|
let pageId = 0;
|
|
|
|
// Neu für Subpages
|
|
let activePage = undefined;
|
|
|
|
//Uhrzeit an NSPanel senden
|
|
schedule('* * * * *', () => {
|
|
try {
|
|
SendTime();
|
|
} catch (err) {
|
|
console.warn('schedule: ' + err.message);
|
|
}
|
|
});
|
|
|
|
//Wechsel zwischen Screensaver Enities und WeatherForecast
|
|
schedule('*/' + getState(NSPanel_Path + 'ScreensaverInfo.entityChangeTime').val + ' * * * * *', () => {
|
|
try {
|
|
//WeatherForcast true/false Umschaltung verzögert
|
|
if (getState(NSPanel_Path + "ScreensaverInfo.popupNotifyHeading").val == '' && getState(NSPanel_Path + "ScreensaverInfo.popupNotifyText").val == '' && getState(NSPanel_Path + "ScreensaverInfo.weatherForecast").val == true && getState(NSPanel_Path + "ScreensaverInfo.weatherForecastTimer").val == true) {
|
|
setStateDelayed(NSPanel_Path + "ScreensaverInfo.weatherForecast", false, (getState(NSPanel_Path + 'ScreensaverInfo.entityChangeTime').val / 2 * 1000), false);
|
|
} else if (getState(NSPanel_Path + "ScreensaverInfo.popupNotifyHeading").val == '' && getState(NSPanel_Path + "ScreensaverInfo.popupNotifyText").val == '' && getState(NSPanel_Path + "ScreensaverInfo.weatherForecast").val == false && getState(NSPanel_Path + "ScreensaverInfo.weatherForecastTimer").val == true) {
|
|
setStateDelayed(NSPanel_Path + "ScreensaverInfo.weatherForecast", true, (getState(NSPanel_Path + 'ScreensaverInfo.entityChangeTime').val / 2 * 1000), false);
|
|
}
|
|
} catch (err) {
|
|
console.warn('schedule: ' + err.message);
|
|
}
|
|
});
|
|
|
|
function InitHWButton1Color() {
|
|
try {
|
|
if (config.mrIcon1ScreensaverEntity.ScreensaverEntity != null || config.mrIcon1ScreensaverEntity.ScreensaverEntity != undefined) {
|
|
on({id: config.mrIcon1ScreensaverEntity.ScreensaverEntity, change: "ne"}, async function (obj) {
|
|
HandleScreensaverUpdate();
|
|
});
|
|
}
|
|
} catch (err) {
|
|
console.warn('function InitHWButton1Color: ' + err.message);
|
|
}
|
|
}
|
|
InitHWButton1Color();
|
|
|
|
function InitHWButton2Color() {
|
|
try {
|
|
if (config.mrIcon2ScreensaverEntity.ScreensaverEntity != null || config.mrIcon2ScreensaverEntity.ScreensaverEntity != undefined) {
|
|
on({id: config.mrIcon2ScreensaverEntity.ScreensaverEntity, change: "ne"}, async function (obj) {
|
|
HandleScreensaverUpdate();
|
|
});
|
|
}
|
|
} catch (err) {
|
|
console.warn('function InitHWButton2Color: ' + err.message);
|
|
}
|
|
}
|
|
InitHWButton2Color();
|
|
|
|
//Wechsel zwischen Datenpunkten und Weather-Forecast im Screensaver
|
|
on({id: [].concat([NSPanel_Path + "ScreensaverInfo.weatherForecast"]), change: "ne"}, async function (obj) {
|
|
weatherForecast = obj.state.val;
|
|
HandleScreensaverUpdate();
|
|
});
|
|
|
|
schedule('0 * * * *', () => {
|
|
SendDate();
|
|
});
|
|
|
|
// 3:30 Uhr Startup durchführen und aktuelle TFT-Version empfangen
|
|
schedule({ hour: 3, minute: 30 }, async () => {
|
|
await setStateAsync(config.panelSendTopic, 'pageType~pageStartup');
|
|
});
|
|
|
|
// Updates vergleichen aktuell alle 12 Stunden
|
|
schedule('{"time":{"start":"00:00","end":"23:59","mode":"hours","interval":12},"period":{"days":1}}', () => {
|
|
get_tasmota_status0();
|
|
get_panel_update_data();
|
|
check_updates();
|
|
});
|
|
|
|
// Mit Start auf Updates checken
|
|
get_locales();
|
|
setState(config.panelSendTopic, 'pageType~pageStartup');
|
|
get_tasmota_status0();
|
|
get_panel_update_data();
|
|
check_updates();
|
|
|
|
//------------------Begin Update Functions
|
|
|
|
function get_locales() {
|
|
try {
|
|
if (Debug) console.log('Requesting locales');
|
|
request({
|
|
url: 'https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/ioBroker/ioBroker_NSPanel_locales.json',
|
|
headers: {
|
|
'User-Agent': 'ioBroker'
|
|
}
|
|
}, async (error, response, result) => {
|
|
try {
|
|
if (result) {
|
|
await createStateAsync(NSPanel_Path + 'NSPanel_locales_json', <iobJS.StateCommon>{ type: 'string', role: 'json' });
|
|
await setStateAsync(NSPanel_Path + 'NSPanel_locales_json', <iobJS.State>{ val: result, ack: true });
|
|
}
|
|
} catch (err) {
|
|
console.log('get_locales: ' + err.message);
|
|
}
|
|
});
|
|
} catch (err) {
|
|
console.error('error requesting locales in function get_locales: ' + err.message);
|
|
}
|
|
}
|
|
|
|
async function check_updates() {
|
|
try {
|
|
const desired_display_firmware_version = 43;
|
|
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
|
|
|
|
await setStateAsync(NSPanel_Path + 'Tasmota_Firmware.currentVersion', <iobJS.State>{ val: getState(NSPanel_Path + 'Tasmota_Firmware.onlineVersion').val, ack: true });
|
|
} else {
|
|
// Auf Tasmota-Updates hinweisen
|
|
if (Debug) console.log('Automatische Updates aus');
|
|
|
|
const InternalName = 'TasmotaFirmwareUpdate';
|
|
const Headline = 'Tasmota-Firmware Update';
|
|
const 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('');
|
|
const Button1 = 'Nein';
|
|
const Button2 = 'Ja';
|
|
const Timeout = 0;
|
|
|
|
await setStateAsync(popupNotifyHeading, <iobJS.State>{ val: Headline, ack: false });
|
|
await setStateAsync(popupNotifyText, <iobJS.State>{ val: [formatDate(getDateObject((new Date().getTime())), 'TT.MM.JJJJ SS:mm:ss'), '\r\n', '\r\n', Text].join(''), ack: false });
|
|
await setStateAsync(popupNotifyButton1Text, <iobJS.State>{ val: Button1, ack: false });
|
|
await setStateAsync(popupNotifyButton2Text, <iobJS.State>{ val: Button2, ack: false });
|
|
await setStateAsync(popupNotifySleepTimeout, <iobJS.State>{ val: Timeout, ack: false });
|
|
await setStateAsync(popupNotifyInternalName, <iobJS.State>{ val: InternalName, ack: 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
|
|
await setStateAsync(NSPanel_Path + 'Berry_Driver.currentVersion', <iobJS.State>{ val: getState(NSPanel_Path + 'Berry_Driver.onlineVersion').val, ack: true });
|
|
|
|
if (Debug) console.log('Berry-Driver automatisch aktualisiert');
|
|
} else {
|
|
//Auf BerryDriver-Update hinweisen
|
|
if (Debug) console.log('Automatische Updates aus');
|
|
|
|
const InternalName = 'BerryDriverUpdate';
|
|
const Headline = 'Berry-Driver Update';
|
|
const 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('');
|
|
const Button1 = 'Nein';
|
|
const Button2 = 'Ja';
|
|
const Timeout = 0;
|
|
|
|
await setStateAsync(popupNotifyHeading, <iobJS.State>{ val: Headline, ack: false });
|
|
await setStateAsync(popupNotifyText, <iobJS.State>{ val: [formatDate(getDateObject((new Date().getTime())), 'TT.MM.JJJJ SS:mm:ss'), '\r\n', '\r\n', Text].join(''), ack: false });
|
|
await setStateAsync(popupNotifyButton1Text, <iobJS.State>{ val: Button1, ack: false });
|
|
await setStateAsync(popupNotifyButton2Text, <iobJS.State>{ val: Button2, ack: false });
|
|
await setStateAsync(popupNotifySleepTimeout, <iobJS.State>{ val: Timeout, ack: false });
|
|
await setStateAsync(popupNotifyInternalName, <iobJS.State>{ val: InternalName, ack: 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
|
|
await setStateAsync(NSPanel_Path + 'Display_Firmware.currentVersion', <iobJS.State>{ val: getState(NSPanel_Path + 'Display_Firmware.onlineVersion').val, ack: true });
|
|
|
|
if (Debug) console.log('Display_Firmware automatisch aktualisiert');
|
|
} else {
|
|
// Auf TFT-Firmware hinweisen
|
|
if (Debug) console.log('Automatische Updates aus');
|
|
|
|
const InternalName = 'TFTFirmwareUpdate';
|
|
const Headline = 'TFT-Firmware Update';
|
|
const 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('');
|
|
const Button1 = 'Nein';
|
|
const Button2 = 'Ja';
|
|
const Timeout = 0;
|
|
|
|
await setStateAsync(popupNotifyHeading, <iobJS.State>{ val: Headline, ack: false });
|
|
await setStateAsync(popupNotifyText, <iobJS.State>{ val: [formatDate(getDateObject((new Date().getTime())), 'TT.MM.JJJJ SS:mm:ss'), '\r\n', '\r\n', Text].join(''), ack: false });
|
|
await setStateAsync(popupNotifyButton1Text, <iobJS.State>{ val: Button1, ack: false });
|
|
await setStateAsync(popupNotifyButton2Text, <iobJS.State>{ val: Button2, ack: false });
|
|
await setStateAsync(popupNotifySleepTimeout, <iobJS.State>{ val: Timeout, ack: false });
|
|
await setStateAsync(popupNotifyInternalName, <iobJS.State>{ val: InternalName, ack: false });
|
|
}
|
|
}
|
|
} else {
|
|
if (Debug) console.log('Display_Firmware auf NSPanel aktuell');
|
|
}
|
|
}
|
|
} catch (err) {
|
|
console.warn('function check_updates: ' + err.message);
|
|
}
|
|
}
|
|
|
|
on({ id: NSPanel_Path + 'popupNotify.popupNotifyAction', change: 'any' }, async function (obj) {
|
|
try {
|
|
const val = obj.state ? obj.state.val : false;
|
|
|
|
if (!val) {
|
|
manually_Update = false;
|
|
if (Debug) console.log('Es wurde Button1 gedrückt');
|
|
} else if (val) {
|
|
if (manually_Update) {
|
|
const internalName = getState(NSPanel_Path + 'popupNotify.popupNotifyInternalName').val;
|
|
|
|
if (internalName == 'TasmotaFirmwareUpdate') {
|
|
update_tasmota_firmware();
|
|
} else if (internalName == 'BerryDriverUpdate') {
|
|
update_berry_driver_version();
|
|
} else if (internalName == 'TFTFirmwareUpdate') {
|
|
update_tft_firmware();
|
|
}
|
|
}
|
|
|
|
if (Debug) console.log('Es wurde Button2 gedrückt');
|
|
}
|
|
} catch (err) {
|
|
console.warn('Trigger popupNotifyAction: ' + err.message);
|
|
}
|
|
});
|
|
|
|
async function get_panel_update_data() {
|
|
try {
|
|
await createStateAsync(NSPanel_Path + 'NSPanel_autoUpdate', false, <iobJS.StateCommon>{ read: true, write: true, name: 'Auto-Update', type: 'boolean', def: false });
|
|
|
|
await createStateAsync(NSPanel_Path + 'NSPanel_ipAddress', <iobJS.StateCommon>{ type: 'string' });
|
|
await setStateAsync(NSPanel_Path + 'NSPanel_ipAddress', <iobJS.State>{ val: get_current_tasmota_ip_address(), ack: true });
|
|
|
|
get_online_tasmota_firmware_version();
|
|
get_current_berry_driver_version();
|
|
get_online_berry_driver_version();
|
|
check_version_tft_firmware();
|
|
check_online_display_firmware();
|
|
} catch (err) {
|
|
console.warn('function get_panel_update_data: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function get_current_tasmota_ip_address() {
|
|
try {
|
|
const infoObjId = config.panelRecvTopic.substring(0, config.panelRecvTopic.length - 'RESULT'.length) + 'INFO2';
|
|
const infoObj = JSON.parse(getState(infoObjId).val);
|
|
|
|
if (Debug) console.log(`get_current_tasmota_ip_address: ${infoObj.Info2.IPAddress}`);
|
|
|
|
return infoObj.Info2.IPAddress;
|
|
} catch (err) {
|
|
console.warn('function get_current_tasmota_ip_address: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function get_online_tasmota_firmware_version() {
|
|
try {
|
|
if (Debug) console.log('Requesting tasmota firmware version');
|
|
request({
|
|
url: 'https://api.github.com/repositories/80286288/releases/latest',
|
|
headers: {
|
|
'User-Agent': 'ioBroker'
|
|
}
|
|
}, async (error, response, result) => {
|
|
try {
|
|
const Tasmota_JSON = JSON.parse(result); // JSON Resultat in Variable Schreiben
|
|
const TasmotaTagName = Tasmota_JSON.tag_name; // JSON nach "tag_name" filtern und in Variable schreiben
|
|
const TasmotaVersionOnline = TasmotaTagName.replace(/v/i, ''); // Aus Variable überflüssiges "v" filtern und in Release-Variable schreiben
|
|
|
|
await createStateAsync(NSPanel_Path + 'Tasmota_Firmware.onlineVersion', <iobJS.StateCommon>{ type: 'string' });
|
|
await setStateAsync(NSPanel_Path + 'Tasmota_Firmware.onlineVersion', <iobJS.State>{ val: TasmotaVersionOnline, ack: true });
|
|
} catch (err) {
|
|
console.log('get_online_tasmota_firmware_version: ' + err.message);
|
|
}
|
|
});
|
|
} catch (err) {
|
|
console.warn('error requesting firmware in function get_online_tasmota_firmware_version: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function get_current_berry_driver_version() {
|
|
try {
|
|
if (Debug) console.log('Requesting current berry driver version');
|
|
request({
|
|
url: `http://${get_current_tasmota_ip_address()}/cm?cmnd=GetDriverVersion`,
|
|
headers: {
|
|
'User-Agent': 'ioBroker'
|
|
}
|
|
}, async (error, response, result) => {
|
|
try {
|
|
await createStateAsync(NSPanel_Path + 'Berry_Driver.currentVersion', <iobJS.StateCommon>{ type: 'number' });
|
|
await setStateAsync(NSPanel_Path + 'Berry_Driver.currentVersion', <iobJS.State>{ val: JSON.parse(result).nlui_driver_version, ack: true });
|
|
} catch (err) {
|
|
console.warn('get_current_berry_driver_version: ' + err.message);
|
|
}
|
|
});
|
|
} catch (err) {
|
|
console.warn('error requesting firmware in function get_current_berry_driver_version: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function get_tasmota_status0() {
|
|
try {
|
|
if (Debug) console.log('Requesting tasmota status0');
|
|
request({
|
|
url: `http://${get_current_tasmota_ip_address()}/cm?cmnd=Status0`,
|
|
headers: {
|
|
'User-Agent': 'ioBroker'
|
|
}
|
|
}, async (error, response, result) => {
|
|
await createStateAsync(NSPanel_Path + 'Tasmota_Firmware.currentVersion', <iobJS.StateCommon>{ type: 'string' });
|
|
await createStateAsync(NSPanel_Path + 'Tasmota.Uptime', <iobJS.StateCommon>{ type: 'string' });
|
|
await createStateAsync(NSPanel_Path + 'Tasmota.Version', <iobJS.StateCommon>{ type: 'string' });
|
|
await createStateAsync(NSPanel_Path + 'Tasmota.Hardware', <iobJS.StateCommon>{ type: 'string' });
|
|
await createStateAsync(NSPanel_Path + 'Tasmota.Wifi.AP', <iobJS.StateCommon>{ type: 'number' });
|
|
await createStateAsync(NSPanel_Path + 'Tasmota.Wifi.SSId', <iobJS.StateCommon>{ type: 'string' });
|
|
await createStateAsync(NSPanel_Path + 'Tasmota.Wifi.BSSId', <iobJS.StateCommon>{ type: 'string' });
|
|
await createStateAsync(NSPanel_Path + 'Tasmota.Wifi.Channel', <iobJS.StateCommon>{ type: 'number' });
|
|
await createStateAsync(NSPanel_Path + 'Tasmota.Wifi.Mode', <iobJS.StateCommon>{ type: 'string' });
|
|
await createStateAsync(NSPanel_Path + 'Tasmota.Wifi.RSSI', <iobJS.StateCommon>{ type: 'number' });
|
|
await createStateAsync(NSPanel_Path + 'Tasmota.Wifi.Signal', <iobJS.StateCommon>{ type: 'number' });
|
|
|
|
try {
|
|
const Tasmota_JSON = JSON.parse(result);
|
|
const tasmoVersion = Tasmota_JSON.StatusFWR.Version.indexOf('(') > -1 ? Tasmota_JSON.StatusFWR.Version.split('(')[0] : Tasmota_JSON.StatusFWR.Version;
|
|
|
|
await setStateAsync(NSPanel_Path + 'Tasmota_Firmware.currentVersion', <iobJS.State>{ val: tasmoVersion, ack: true });
|
|
await setStateAsync(NSPanel_Path + 'Tasmota.Uptime', <iobJS.State>{ val: Tasmota_JSON.StatusPRM.Uptime, ack: true });
|
|
await setStateAsync(NSPanel_Path + 'Tasmota.Version', <iobJS.State>{ val: Tasmota_JSON.StatusFWR.Version, ack: true });
|
|
await setStateAsync(NSPanel_Path + 'Tasmota.Hardware', <iobJS.State>{ val: Tasmota_JSON.StatusFWR.Hardware, ack: true });
|
|
await setStateAsync(NSPanel_Path + 'Tasmota.Wifi.AP', <iobJS.State>{ val: Tasmota_JSON.StatusSTS.Wifi.AP, ack: true });
|
|
await setStateAsync(NSPanel_Path + 'Tasmota.Wifi.SSId', <iobJS.State>{ val: Tasmota_JSON.StatusSTS.Wifi.SSId, ack: true });
|
|
await setStateAsync(NSPanel_Path + 'Tasmota.Wifi.BSSId', <iobJS.State>{ val: Tasmota_JSON.StatusSTS.Wifi.BSSId, ack: true });
|
|
await setStateAsync(NSPanel_Path + 'Tasmota.Wifi.Channel', <iobJS.State>{ val: Tasmota_JSON.StatusSTS.Wifi.Channel, ack: true });
|
|
await setStateAsync(NSPanel_Path + 'Tasmota.Wifi.Mode', <iobJS.State>{ val: Tasmota_JSON.StatusSTS.Wifi.Mode, ack: true });
|
|
await setStateAsync(NSPanel_Path + 'Tasmota.Wifi.RSSI', <iobJS.State>{ val: Tasmota_JSON.StatusSTS.Wifi.RSSI, ack: true });
|
|
await setStateAsync(NSPanel_Path + 'Tasmota.Wifi.Signal', <iobJS.State>{ val: Tasmota_JSON.StatusSTS.Wifi.Signal, ack: true });
|
|
} catch (err) {
|
|
console.warn('get_tasmota_status0' + err.message);
|
|
}
|
|
});
|
|
} catch (err) {
|
|
console.warn('error requesting firmware in function get_tasmota_status0: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function get_online_berry_driver_version() {
|
|
try {
|
|
if (Debug) console.log('Requesting online berry driver version');
|
|
request({
|
|
url: 'https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be',
|
|
headers: {
|
|
'User-Agent': 'ioBroker'
|
|
}
|
|
}, async (error, response, result) => {
|
|
if (result) {
|
|
try {
|
|
const BerryDriverVersionOnline = result.substring((result.indexOf('version_of_this_script = ') + 24), result.indexOf('version_of_this_script = ') + 27).replace(/\s+/g, '');
|
|
await createStateAsync(NSPanel_Path + 'Berry_Driver.onlineVersion', <iobJS.StateCommon>{ type: 'string' });
|
|
await setStateAsync(NSPanel_Path + 'Berry_Driver.onlineVersion', <iobJS.State>{ val: BerryDriverVersionOnline, ack: true });
|
|
} catch (err) {
|
|
console.log('get_online_berry_driver_version' + err.message);
|
|
}
|
|
}
|
|
});
|
|
} catch (err) {
|
|
console.warn('error requesting firmware in function get_online_berry_driver_version: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function check_version_tft_firmware() {
|
|
try {
|
|
if (Debug) console.log('Requesting online TFT version');
|
|
request({
|
|
url: 'https://api.github.com/repos/joBr99/nspanel-lovelace-ui/releases/latest',
|
|
headers: {
|
|
'User-Agent': 'ioBroker'
|
|
}
|
|
}, async (error, response, result) => {
|
|
if (result) {
|
|
try {
|
|
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
|
|
|
|
await createStateAsync(NSPanel_Path + 'TFT_Firmware.onlineVersion', <iobJS.StateCommon>{ type: 'string' });
|
|
await setStateAsync(NSPanel_Path + 'TFT_Firmware.onlineVersion', <iobJS.State>{ val: NSPanelVersion, ack: true });
|
|
} catch (err) {
|
|
console.log('check_version_tft_firmware: ' + err.message);
|
|
}
|
|
}
|
|
});
|
|
} catch (err) {
|
|
console.warn('error requesting firmware in function check_version_tft_firmware: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function check_online_display_firmware() {
|
|
try {
|
|
if (Debug) console.log('Requesting online firmware version');
|
|
request({
|
|
url: 'https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/apps/nspanel-lovelace-ui/nspanel-lovelace-ui.py',
|
|
headers: {
|
|
'User-Agent': 'ioBroker'
|
|
}
|
|
}, async (error, response, result) => {
|
|
if (result) {
|
|
try {
|
|
let desired_display_firmware_version = result.substring((result.indexOf('desired_display_firmware_version =') + 34), result.indexOf('desired_display_firmware_version =') + 38).replace(/\s+/g, '');
|
|
|
|
await createStateAsync(NSPanel_Path + 'Display_Firmware.onlineVersion', <iobJS.StateCommon>{ type: 'string' });
|
|
await setStateAsync(NSPanel_Path + 'Display_Firmware.onlineVersion', <iobJS.State>{ val: desired_display_firmware_version, ack: true });
|
|
} catch (err) {
|
|
console.warn('check_online_display_firmware' + err.message);
|
|
}
|
|
}
|
|
});
|
|
} catch (err) {
|
|
console.warn('error requesting firmware in function check_online_display_firmware: ' + err.message);
|
|
}
|
|
}
|
|
|
|
on({ id: config.panelRecvTopic }, async (obj) => {
|
|
if (obj.state.val.startsWith('\{"CustomRecv":')) {
|
|
try {
|
|
var json = JSON.parse(obj.state.val);
|
|
var split = json.CustomRecv.split(',');
|
|
if (split[0] == 'event' && split[1] == 'startup') {
|
|
await createStateAsync(NSPanel_Path + 'Display_Firmware.currentVersion', <iobJS.StateCommon>{ type: 'string' });
|
|
await createStateAsync(NSPanel_Path + 'NSPanel_Version', <iobJS.StateCommon>{ type: 'string' });
|
|
|
|
await setStateAsync(NSPanel_Path + 'Display_Firmware.currentVersion', <iobJS.State>{ val: split[2], ack: true });
|
|
await setStateAsync(NSPanel_Path + 'NSPanel_Version', <iobJS.State>{ val: split[3], ack: true });
|
|
}
|
|
} catch (err) {
|
|
console.warn('error rceiving CustomRecv: ' + err.message);
|
|
}
|
|
}
|
|
});
|
|
|
|
function update_berry_driver_version() {
|
|
try {
|
|
request({
|
|
url: `http://${get_current_tasmota_ip_address()}/cm?cmnd=Backlog UpdateDriverVersion https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be; Restart 1`,
|
|
headers: {
|
|
'User-Agent': 'ioBroker'
|
|
}
|
|
}, async function (error, response, result) {
|
|
|
|
});
|
|
} catch (err) {
|
|
console.warn('error at function update_berry_driver_version: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function update_tft_firmware() {
|
|
const tft_version: string = 'v3.5.0';
|
|
const desired_display_firmware_url = `http://nspanel.pky.eu/lovelace-ui/github/nspanel-${tft_version}.tft`;
|
|
try {
|
|
request({
|
|
url: `http://${get_current_tasmota_ip_address()}/cm?cmnd=FlashNextion ${desired_display_firmware_url}`,
|
|
headers: {
|
|
'User-Agent': 'ioBroker'
|
|
}
|
|
}, async function (error, response, result) {
|
|
await createStateAsync(NSPanel_Path + 'TFT_Firmware.onlineVersion', <iobJS.StateCommon>{ type: 'string' });
|
|
await setStateAsync(NSPanel_Path + 'TFT_Firmware.onlineVersion', <iobJS.State>{ val: tft_version, ack: true });
|
|
});
|
|
} catch (err) {
|
|
console.warn('error at function update_tft_firmware: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function update_tasmota_firmware() {
|
|
try {
|
|
request({
|
|
url: `http://${get_current_tasmota_ip_address()}/cm?cmnd=Upgrade 1`,
|
|
headers: {
|
|
'User-Agent': 'ioBroker'
|
|
}
|
|
}, async function (error, response, result) {
|
|
});
|
|
} catch (err) {
|
|
console.warn('error at function update_tasmota_firmware: ' + err.message);
|
|
}
|
|
}
|
|
//------------------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)
|
|
}
|
|
if (config.secondScreensaverEntity !== null && config.secondScreensaverEntity.ScreensaverEntity != null && existsState(config.secondScreensaverEntity.ScreensaverEntity)) {
|
|
updateArray.push(config.secondScreensaverEntity.ScreensaverEntity)
|
|
}
|
|
if (config.thirdScreensaverEntity !== null && config.thirdScreensaverEntity.ScreensaverEntity != null && existsState(config.thirdScreensaverEntity.ScreensaverEntity)) {
|
|
updateArray.push(config.thirdScreensaverEntity.ScreensaverEntity)
|
|
}
|
|
if (config.fourthScreensaverEntity !== null && config.fourthScreensaverEntity.ScreensaverEntity != null && existsState(config.fourthScreensaverEntity.ScreensaverEntity)) {
|
|
updateArray.push(config.fourthScreensaverEntity.ScreensaverEntity)
|
|
}
|
|
if (updateArray.length > 0) {
|
|
on(updateArray, () => {
|
|
HandleScreensaverUpdate();
|
|
});
|
|
}
|
|
|
|
on({ id: config.panelRecvTopic }, function (obj) {
|
|
try {
|
|
if (obj.state.val.startsWith('\{"CustomRecv":')) {
|
|
try {
|
|
var json = JSON.parse(obj.state.val);
|
|
|
|
var split = json.CustomRecv.split(',');
|
|
HandleMessage(split[0], split[1], parseInt(split[2]), split);
|
|
} catch (err) {
|
|
console.warn(err.message);
|
|
}
|
|
}
|
|
} catch (err) {
|
|
console.warn('Trigger panelRecTopic: ' + err.message);
|
|
}
|
|
});
|
|
|
|
function SendToPanel(val: Payload | Payload[]): void {
|
|
try {
|
|
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);
|
|
}
|
|
} catch (err) {
|
|
console.warn('function SendToPanel: ' + err.message);
|
|
}
|
|
}
|
|
|
|
on({ id: NSPanel_Alarm_Path + 'Alarm.AlarmState', change: 'ne' }, async (obj) => {
|
|
try {
|
|
if ((obj.state ? obj.state.val : '') == 'armed' || (obj.state ? obj.state.val : '') == 'disarmed' || (obj.state ? obj.state.val : '') == 'triggered') {
|
|
if (Debug) console.log(activePage);
|
|
if (NSPanel_Path == getState(NSPanel_Alarm_Path + 'Alarm.PANEL').val) {
|
|
GeneratePage(activePage);
|
|
}
|
|
}
|
|
} catch (err) {
|
|
console.warn('Trigger AlarmState: ' + err.message);
|
|
}
|
|
});
|
|
|
|
function HandleMessage(typ: string, method: string, page: number, words: Array<string>): void {
|
|
try {
|
|
if (typ == 'event') {
|
|
switch (method) {
|
|
case 'startup':
|
|
screensaverEnabled = false;
|
|
UnsubscribeWatcher();
|
|
HandleStartupProcess();
|
|
pageId = 0;
|
|
GeneratePage(config.pages[0]);
|
|
break;
|
|
case 'sleepReached':
|
|
screensaverEnabled = true;
|
|
if (pageId < 0)
|
|
pageId = 0;
|
|
HandleScreensaver();
|
|
break;
|
|
case 'pageOpenDetail':
|
|
screensaverEnabled = false;
|
|
UnsubscribeWatcher();
|
|
let pageItem = findPageItem(words[3]);
|
|
if (pageItem !== undefined)
|
|
SendToPanel(GenerateDetailPage(words[2], pageItem));
|
|
case 'buttonPress2':
|
|
screensaverEnabled = false;
|
|
HandleButtonEvent(words);
|
|
if (Debug) console.log(words[0] + ' - ' + words[1] + ' - ' + words[2] + ' - ' + words[3] + ' - ' + words[4]);
|
|
break;
|
|
case 'button1':
|
|
case 'button2':
|
|
screensaverEnabled = false;
|
|
HandleHardwareButton(method);
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
} catch (err) {
|
|
console.warn('function HandleMessage: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function findPageItem(searching: String): PageItem {
|
|
try {
|
|
|
|
let pageItem = activePage.items.find(e => e.id === searching);
|
|
|
|
if (pageItem !== undefined) {
|
|
return pageItem;
|
|
}
|
|
|
|
config.subPages.every(sp => {
|
|
pageItem = sp.items.find(e => e.id === searching);
|
|
if (pageItem !== undefined) {
|
|
return false;
|
|
}
|
|
return true;
|
|
});
|
|
|
|
return pageItem;
|
|
} catch (err) {
|
|
console.warn('function findPageItem: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function GeneratePage(page: Page): void {
|
|
try {
|
|
activePage = page;
|
|
switch (page.type) {
|
|
case 'cardEntities':
|
|
SendToPanel(GenerateEntitiesPage(<PageEntities>page));
|
|
break;
|
|
case 'cardThermo':
|
|
SendToPanel(GenerateThermoPage(<PageThermo>page));
|
|
break;
|
|
case 'cardGrid':
|
|
SendToPanel(GenerateGridPage(<PageGrid>page));
|
|
break;
|
|
case 'cardMedia':
|
|
SendToPanel(GenerateMediaPage(<PageMedia>page));
|
|
break;
|
|
case 'cardAlarm':
|
|
SendToPanel(GenerateAlarmPage(<PageAlarm>page));
|
|
break;
|
|
case 'cardQR':
|
|
SendToPanel(GenerateQRPage(<PageQR>page));
|
|
break;
|
|
case 'cardPower':
|
|
SendToPanel(GeneratePowerPage(<PagePower>page));
|
|
break;
|
|
}
|
|
} catch (err) {
|
|
console.warn('function GeneratePage: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function HandleHardwareButton(method: string): void {
|
|
try {
|
|
let page: (PageThermo | PageMedia | PageAlarm | PageEntities | PageGrid | PageQR | PagePower);
|
|
if (config.button1Page !== null && method == 'button1') {
|
|
page = config.button1Page;
|
|
pageId = -1;
|
|
} else if (config.button2Page !== null && method == 'button2') {
|
|
page = config.button2Page;
|
|
pageId = -2;
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
GeneratePage(page);
|
|
} catch (err) {
|
|
console.warn('function HandleHardwareButton: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function HandleStartupProcess(): void {
|
|
SendDate();
|
|
SendTime();
|
|
SendToPanel({ payload: 'timeout~' + config.timeoutScreensaver });
|
|
}
|
|
|
|
function SendDate(): void {
|
|
try {
|
|
const date = new Date();
|
|
const options: any = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
|
|
const _SendDate = date.toLocaleDateString(config.locale, options);
|
|
|
|
SendToPanel(<Payload>{ payload: 'date~' + _SendDate });
|
|
} catch (err) {
|
|
console.warn('function SendDate: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function SendTime(): void {
|
|
try {
|
|
const d = new Date();
|
|
const hr = (d.getHours() < 10 ? '0' : '') + d.getHours();
|
|
const min = (d.getMinutes() < 10 ? '0' : '') + d.getMinutes();
|
|
|
|
SendToPanel(<Payload>{ payload: 'time~' + hr + ':' + min });
|
|
} catch (err) {
|
|
console.warn('function SendTime: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function GenerateEntitiesPage(page: PageEntities): Payload[] {
|
|
try {
|
|
var out_msgs: Array<Payload> = [];
|
|
out_msgs = [{ payload: 'pageType~cardEntities' }]
|
|
out_msgs.push({ payload: GeneratePageElements(page) });
|
|
return out_msgs
|
|
} catch (err) {
|
|
console.warn('function GenerateEntitiesPage: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function GenerateGridPage(page: PageGrid): Payload[] {
|
|
try {
|
|
var out_msgs: Array<Payload> = [];
|
|
out_msgs = [{ payload: 'pageType~cardGrid' }]
|
|
out_msgs.push({ payload: GeneratePageElements(page) });
|
|
return out_msgs
|
|
} catch (err) {
|
|
console.warn('function GenerateGridPage: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function GeneratePageElements(page: Page): string {
|
|
try {
|
|
activePage = page;
|
|
let maxItems = 0;
|
|
switch (page.type) {
|
|
case 'cardThermo':
|
|
maxItems = 1;
|
|
break;
|
|
case 'cardAlarm':
|
|
maxItems = 1;
|
|
break;
|
|
case 'cardMedia':
|
|
maxItems = 1;
|
|
break;
|
|
case 'cardQR':
|
|
maxItems = 1;
|
|
break;
|
|
case 'cardEntities':
|
|
if (getState(NSPanel_Path + 'NSPanel_Version').val == 'eu') {
|
|
maxItems = 4;
|
|
} else {
|
|
maxItems = 5;
|
|
}
|
|
break;
|
|
case 'cardGrid':
|
|
maxItems = 6;
|
|
break;
|
|
}
|
|
|
|
let pageData = 'entityUpd~' + page.heading + '~' + GetNavigationString(pageId);
|
|
|
|
for (let index = 0; index < maxItems; index++) {
|
|
if (page.items[index] !== undefined) {
|
|
pageData += CreateEntity(page.items[index], index + 1, page.useColor);
|
|
}
|
|
}
|
|
return pageData;
|
|
} catch (err) {
|
|
console.warn('function GeneratePageElements: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function CreateEntity(pageItem: PageItem, placeId: number, useColors: boolean = false): string {
|
|
try {
|
|
var iconId = '0';
|
|
if (pageItem.id == 'delete') {
|
|
return '~delete~~~~~';
|
|
}
|
|
|
|
var name: string;
|
|
var type: string;
|
|
|
|
// ioBroker
|
|
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;
|
|
|
|
if (existsState(pageItem.id + '.GET')) {
|
|
val = getState(pageItem.id + '.GET').val;
|
|
RegisterEntityWatcher(pageItem.id + '.GET');
|
|
} else if (existsState(pageItem.id + '.SET')) {
|
|
val = getState(pageItem.id + '.SET').val;
|
|
RegisterEntityWatcher(pageItem.id + '.SET');
|
|
}
|
|
|
|
// Fallback if no name is given
|
|
name = pageItem.name !== undefined ? pageItem.name : o.common.name.de;
|
|
|
|
switch (o.common.role) {
|
|
case 'socket':
|
|
case 'light':
|
|
type = 'light';
|
|
iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : o.common.role == 'socket' ? Icons.GetIcon('power-socket-de') : Icons.GetIcon('lightbulb');
|
|
var iconId2 = pageItem.icon2 !== undefined ? Icons.GetIcon(pageItem.icon2) : o.common.role == 'socket' ? Icons.GetIcon('power-socket-de') : Icons.GetIcon('lightbulb');
|
|
var optVal = '0';
|
|
|
|
if (val === true || val === 'true') {
|
|
optVal = '1';
|
|
iconColor = GetIconColor(pageItem, true, useColors);
|
|
} else {
|
|
iconColor = GetIconColor(pageItem, false, useColors);
|
|
if (pageItem.icon !== undefined) {
|
|
if (pageItem.icon2 !== undefined) {
|
|
iconId = iconId2;
|
|
}
|
|
}
|
|
}
|
|
|
|
return '~' + type + '~' + pageItem.id + '~' + iconId + '~' + iconColor + '~' + name + '~' + optVal;
|
|
|
|
case 'hue':
|
|
type = 'light';
|
|
iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon('lightbulb');
|
|
var optVal = '0';
|
|
|
|
if (existsState(pageItem.id + '.ON_ACTUAL')) {
|
|
val = getState(pageItem.id + '.ON_ACTUAL').val;
|
|
RegisterEntityWatcher(pageItem.id + '.ON_ACTUAL');
|
|
}
|
|
|
|
if (val === true || val === 'true') {
|
|
optVal = '1';
|
|
iconColor = GetIconColor(pageItem, existsState(pageItem.id + '.DIMMER') ? 100 - getState(pageItem.id + '.DIMMER').val : true, useColors);
|
|
}
|
|
|
|
if (pageItem.interpolateColor != undefined && pageItem.interpolateColor == true) {
|
|
if (existsState(pageItem.id + '.HUE')) {
|
|
if (getState(pageItem.id + '.HUE').val != null) {
|
|
let huecolor = hsv2rgb(getState(pageItem.id + '.HUE').val, 1, 1);
|
|
let rgb = <RGB>{ red: Math.round(huecolor[0]), green: Math.round(huecolor[1]), blue: Math.round(huecolor[2]) };
|
|
iconColor = rgb_dec565(pageItem.interpolateColor !== undefined ? rgb : config.defaultOnColor);
|
|
// RegisterDetailEntityWatcher(id + '.HUE');
|
|
}
|
|
}
|
|
}
|
|
|
|
return '~' + type + '~' + pageItem.id + '~' + iconId + '~' + iconColor + '~' + name + '~' + optVal;
|
|
|
|
case 'ct':
|
|
type = 'light';
|
|
iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon('lightbulb');
|
|
var optVal = '0';
|
|
|
|
if (existsState(pageItem.id + '.ON')) {
|
|
val = getState(pageItem.id + '.ON').val;
|
|
RegisterEntityWatcher(pageItem.id + '.ON');
|
|
}
|
|
|
|
if (val === true || val === 'true') {
|
|
optVal = '1';
|
|
iconColor = GetIconColor(pageItem, existsState(pageItem.id + '.DIMMER') ? 100 - getState(pageItem.id + '.DIMMER').val : true, useColors);
|
|
}
|
|
|
|
return '~' + type + '~' + pageItem.id + '~' + iconId + '~' + iconColor + '~' + name + '~' + optVal;
|
|
|
|
case 'rgb':
|
|
type = 'light';
|
|
iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon('lightbulb');
|
|
var optVal = '0';
|
|
|
|
if (existsState(pageItem.id + '.ON_ACTUAL')) {
|
|
val = getState(pageItem.id + '.ON_ACTUAL').val;
|
|
RegisterEntityWatcher(pageItem.id + '.ON_ACTUAL');
|
|
}
|
|
|
|
if (val === true || val === 'true') {
|
|
optVal = '1';
|
|
iconColor = GetIconColor(pageItem, existsState(pageItem.id + '.DIMMER') ? 100 - getState(pageItem.id + '.DIMMER').val : true, useColors);
|
|
}
|
|
|
|
if (existsState(pageItem.id + '.RED') && existsState(pageItem.id + '.GREEN') && existsState(pageItem.id + '.BLUE')) {
|
|
if (getState(pageItem.id + '.RED').val != null && getState(pageItem.id + '.GREEN').val != null && getState(pageItem.id + '.BLUE').val != null) {
|
|
let rgbRed = getState(pageItem.id + '.RED').val;
|
|
let rgbGreen = getState(pageItem.id + '.GREEN').val;
|
|
let rgbBlue = getState(pageItem.id + '.BLUE').val;
|
|
let rgb = <RGB>{ red: Math.round(rgbRed), green: Math.round(rgbGreen), blue: Math.round(rgbBlue) };
|
|
iconColor = rgb_dec565(pageItem.interpolateColor !== undefined ? rgb : config.defaultOnColor);
|
|
}
|
|
}
|
|
|
|
return '~' + type + '~' + pageItem.id + '~' + iconId + '~' + iconColor + '~' + name + '~' + optVal;
|
|
|
|
case 'rgbSingle':
|
|
type = 'light';
|
|
iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon('lightbulb');
|
|
var optVal = '0';
|
|
|
|
if (existsState(pageItem.id + '.ON_ACTUAL')) {
|
|
val = getState(pageItem.id + '.ON_ACTUAL').val;
|
|
RegisterEntityWatcher(pageItem.id + '.ON_ACTUAL');
|
|
}
|
|
|
|
if (val === true || val === 'true') {
|
|
optVal = '1'
|
|
iconColor = GetIconColor(pageItem, existsState(pageItem.id + '.DIMMER') ? 100 - getState(pageItem.id + '.DIMMER').val : true, useColors);
|
|
}
|
|
|
|
if (existsState(pageItem.id + '.RGB')) {
|
|
if (getState(pageItem.id + '.RGB').val != null) {
|
|
var hex = getState(pageItem.id + '.RGB').val;
|
|
var hexRed = parseInt(hex[1] + hex[2], 16);
|
|
var hexGreen = parseInt(hex[3] + hex[4], 16);
|
|
var hexBlue = parseInt(hex[5] + hex[6], 16);
|
|
let rgb = <RGB>{ red: Math.round(hexRed), green: Math.round(hexGreen), blue: Math.round(hexBlue) };
|
|
iconColor = rgb_dec565(pageItem.interpolateColor !== undefined ? rgb : config.defaultOnColor);
|
|
}
|
|
}
|
|
|
|
return '~' + type + '~' + pageItem.id + '~' + iconId + '~' + iconColor + '~' + name + '~' + optVal;
|
|
|
|
case 'dimmer':
|
|
type = 'light';
|
|
iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon('lightbulb');
|
|
var optVal = '0';
|
|
|
|
if (existsState(pageItem.id + '.ON_ACTUAL')) {
|
|
val = getState(pageItem.id + '.ON_ACTUAL').val;
|
|
RegisterEntityWatcher(pageItem.id + '.ON_ACTUAL');
|
|
} else if (existsState(pageItem.id + '.ON_SET')) {
|
|
val = getState(pageItem.id + '.ON_SET').val;
|
|
RegisterEntityWatcher(pageItem.id + '.ON_SET');
|
|
}
|
|
|
|
if (val === true || val === 'true') {
|
|
optVal = '1';
|
|
iconColor = GetIconColor(pageItem, existsState(pageItem.id + '.ACTUAL') ? 100 - getState(pageItem.id + '.ACTUAL').val : true, useColors);
|
|
}
|
|
|
|
return '~' + type + '~' + pageItem.id + '~' + iconId + '~' + iconColor + '~' + name + '~' + optVal;
|
|
|
|
case 'blind':
|
|
type = 'shutter';
|
|
iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon('window-open');
|
|
iconColor = GetIconColor(pageItem, existsState(pageItem.id + '.ACTUAL') ? getState(pageItem.id + '.ACTUAL').val : true, useColors);
|
|
|
|
return '~' + type + '~' + pageItem.id + '~' + iconId + '~' + iconColor + '~' + name + '~';
|
|
|
|
case 'door':
|
|
case 'window':
|
|
type = 'text';
|
|
|
|
if (existsState(pageItem.id + '.ACTUAL')) {
|
|
if (getState(pageItem.id + '.ACTUAL').val) {
|
|
iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : o.common.role == 'door' ? Icons.GetIcon('door-open') : Icons.GetIcon('window-open-variant');
|
|
iconColor = GetIconColor(pageItem, false, useColors);
|
|
var windowState = findLocale('window', 'opened');
|
|
} else {
|
|
iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : o.common.role == 'door' ? Icons.GetIcon('door-closed') : Icons.GetIcon('window-closed-variant');
|
|
//iconId = Icons.GetIcon('window-closed-variant');
|
|
iconColor = GetIconColor(pageItem, true, useColors);
|
|
var windowState = findLocale('window', 'closed');
|
|
}
|
|
|
|
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.window':
|
|
|
|
case 'thermostat':
|
|
type = 'text';
|
|
iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : o.common.role == 'value.temperature' || o.common.role == 'thermostat' ? Icons.GetIcon('thermometer') : Icons.GetIcon('information-outline');
|
|
let unit = '';
|
|
var optVal = '0';
|
|
|
|
if (existsState(pageItem.id + '.ON_ACTUAL')) {
|
|
optVal = getState(pageItem.id + '.ON_ACTUAL').val;
|
|
unit = pageItem.unit !== undefined ? pageItem.unit : GetUnitOfMeasurement(pageItem.id + '.ON_ACTUAL');
|
|
RegisterEntityWatcher(pageItem.id + '.ON_ACTUAL');
|
|
} else if (existsState(pageItem.id + '.ACTUAL')) {
|
|
optVal = getState(pageItem.id + '.ACTUAL').val;
|
|
unit = pageItem.unit !== undefined ? pageItem.unit : GetUnitOfMeasurement(pageItem.id + '.ACTUAL');
|
|
RegisterEntityWatcher(pageItem.id + '.ACTUAL');
|
|
}
|
|
|
|
if (o.common.role == 'value.temperature') {
|
|
iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon('thermometer');
|
|
}
|
|
|
|
iconColor = GetIconColor(pageItem, parseInt(optVal), useColors);
|
|
|
|
return '~' + type + '~' + pageItem.id + '~' + iconId + '~' + iconColor + '~' + name + '~' + optVal + ' ' + unit;
|
|
|
|
case 'buttonSensor':
|
|
case 'button':
|
|
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 + '~' + 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 = findLocale('lock', 'UNLOCK');
|
|
} else {
|
|
iconId = pageItem.icon !== undefined ? Icons.GetIcon(pageItem.icon) : Icons.GetIcon('lock-open-variant');
|
|
iconColor = GetIconColor(pageItem, false, useColors);
|
|
var lockState = findLocale('lock', 'LOCK');
|
|
}
|
|
lockState = pageItem.buttonText !== undefined ? pageItem.buttonText : lockState;
|
|
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~~~~~';
|
|
} catch (err) {
|
|
console.warn('function CreateEntity: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function findLocale(controlsObject: string, controlsState: string): string {
|
|
const locale = config.locale;
|
|
const strJson = getState(NSPanel_Path + 'NSPanel_locales_json').val;
|
|
|
|
if (Debug) console.log(controlsObject + ' - ' + controlsState);
|
|
|
|
try {
|
|
const obj = JSON.parse(strJson);
|
|
const strLocale = obj[controlsObject][controlsState][locale];
|
|
|
|
if (strLocale != undefined) {
|
|
return strLocale;
|
|
} else {
|
|
return controlsState;
|
|
}
|
|
|
|
} catch (err) {
|
|
if (err.message.substring(0, 35) == 'Cannot read properties of undefined') {
|
|
if (Debug) console.log('function findLocale: missing translation: ' + controlsObject + ' - ' + controlsState);
|
|
} else {
|
|
console.warn('function findLocale: ' + err.message);
|
|
}
|
|
return controlsState;
|
|
}
|
|
}
|
|
|
|
function GetIconColor(pageItem: PageItem, value: (boolean | number), useColors: boolean): number {
|
|
try {
|
|
// dimmer
|
|
if ((pageItem.useColor || useColors) && pageItem.interpolateColor && typeof (value) === 'number') {
|
|
let maxValue = pageItem.maxValueBrightness !== undefined ? pageItem.maxValueBrightness : 100;
|
|
let minValue = pageItem.minValueBrightness !== undefined ? pageItem.minValueBrightness : 0;
|
|
if (pageItem.maxValue !== undefined) maxValue = pageItem.maxValue;
|
|
if (pageItem.minValue !== undefined) minValue = pageItem.minValue;
|
|
value = value > maxValue ? maxValue : value;
|
|
value = value < minValue ? minValue : value;
|
|
|
|
return rgb_dec565(
|
|
Interpolate(
|
|
pageItem.offColor !== undefined ? pageItem.offColor : config.defaultOffColor,
|
|
pageItem.onColor !== undefined ? pageItem.onColor : config.defaultOnColor,
|
|
scale(value, minValue, maxValue, 0, 1)
|
|
)
|
|
);
|
|
}
|
|
|
|
if ((pageItem.useColor || useColors) && ((typeof (value) === 'boolean' && value) || value > (pageItem.minValueBrightness !== undefined ? pageItem.minValueBrightness : 0))) {
|
|
return rgb_dec565(pageItem.onColor !== undefined ? pageItem.onColor : config.defaultOnColor)
|
|
}
|
|
|
|
return rgb_dec565(pageItem.offColor !== undefined ? pageItem.offColor : config.defaultOffColor);
|
|
} catch (err) {
|
|
console.warn('function GetIconColor: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function RegisterEntityWatcher(id: string): void {
|
|
try {
|
|
if (subscriptions.hasOwnProperty(id)) {
|
|
return;
|
|
}
|
|
|
|
subscriptions[id] = (on({ id: id, change: 'any' }, (data) => {
|
|
if (pageId == -1 && config.button1Page != undefined) {
|
|
SendToPanel({ payload: GeneratePageElements(config.button1Page) });
|
|
}
|
|
if (pageId == -2 && config.button2Page != undefined) {
|
|
SendToPanel({ payload: GeneratePageElements(config.button2Page) });
|
|
}
|
|
if (activePage !== undefined) {
|
|
SendToPanel({ payload: GeneratePageElements(activePage) });
|
|
}
|
|
}));
|
|
} catch (err) {
|
|
console.warn('function RegisterEntityWatcher: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function RegisterDetailEntityWatcher(id: string, pageItem: PageItem, type: string): void {
|
|
try {
|
|
if (subscriptions.hasOwnProperty(id)) {
|
|
return;
|
|
}
|
|
|
|
subscriptions[id] = (on({ id: id, change: 'any' }, () => {
|
|
SendToPanel(GenerateDetailPage(type, pageItem));
|
|
}))
|
|
} catch (err) {
|
|
console.warn('function RegisterDetailEntityWatcher: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function GetUnitOfMeasurement(id: string): string {
|
|
try {
|
|
if (!existsObject(id))
|
|
return '';
|
|
|
|
let obj = getObject(id);
|
|
if (typeof obj.common.unit !== 'undefined') {
|
|
return obj.common.unit
|
|
}
|
|
|
|
if (typeof obj.common.alias !== 'undefined' && typeof obj.common.alias.id !== 'undefined') {
|
|
return GetUnitOfMeasurement(obj.common.alias.id);
|
|
}
|
|
|
|
return '';
|
|
} catch (err) {
|
|
console.warn('function GetUnitOfMeasurement: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function GenerateThermoPage(page: PageThermo): Payload[] {
|
|
try {
|
|
var id = page.items[0].id
|
|
var out_msgs: Array<Payload> = [];
|
|
out_msgs.push({ payload: 'pageType~cardThermo' });
|
|
|
|
// ioBroker
|
|
if (existsObject(id)) {
|
|
let o = getObject(id);
|
|
let name = page.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);
|
|
}
|
|
|
|
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 // 0,5° Schritte
|
|
|
|
let destTemp = 0;
|
|
if (existsState(id + '.SET')) {
|
|
// using minValue, if .SET is null (e.g. for tado AWAY or tado is off)
|
|
let setValue = getState(id + '.SET').val;
|
|
if (setValue == null) {
|
|
setValue = minTemp;
|
|
}
|
|
|
|
destTemp = setValue.toFixed(2) * 10;
|
|
}
|
|
let statusStr: String = 'MANU';
|
|
let status = '';
|
|
if (existsState(id + '.MODE'))
|
|
status = getState(id + '.MODE').val;
|
|
|
|
//Attribute hinzufügen, wenn im Alias definiert
|
|
let i_list = Array.prototype.slice.apply($('[state.id="' + id + '.*"]'));
|
|
if ((i_list.length - 3) != 0) {
|
|
|
|
var i = 0;
|
|
var bt = ['~~~~', '~~~~', '~~~~', '~~~~', '~~~~', '~~~~', '~~~~', '~~~~', '~~~~'];
|
|
|
|
if (o.common.role == 'thermostat') {
|
|
|
|
if (existsState(id + '.AUTOMATIC') && getState(id + '.AUTOMATIC').val != null) {
|
|
if (getState(id + '.AUTOMATIC').val) {
|
|
bt[i++] = Icons.GetIcon('alpha-a-circle') + '~' + rgb_dec565(On) + '~1~' + 'AUTT' + '~';
|
|
statusStr = 'AUTO';
|
|
} else {
|
|
bt[i++] = Icons.GetIcon('alpha-a-circle') + '~33840~1~' + 'AUTT' + '~';
|
|
}
|
|
}
|
|
if (existsState(id + '.MANUAL') && getState(id + '.MANUAL').val != null) {
|
|
if (getState(id + '.MANUAL').val) {
|
|
bt[i++] = Icons.GetIcon('alpha-m-circle') + '~' + rgb_dec565(On) + '~1~' + 'MANT' + '~';
|
|
statusStr = 'MANU';
|
|
} else {
|
|
bt[i++] = Icons.GetIcon('alpha-m-circle') + '~33840~1~' + 'MANT' + '~';
|
|
}
|
|
}
|
|
if (existsState(id + '.PARTY') && getState(id + '.PARTY').val != null) {
|
|
if (getState(id + '.PARTY').val) {
|
|
bt[i++] = Icons.GetIcon('party-popper') + '~' + rgb_dec565(On) + '~1~' + 'PART' + '~';
|
|
statusStr = 'PARTY';
|
|
} else {
|
|
bt[i++] = Icons.GetIcon('party-popper') + '~33840~1~' + 'PART' + '~';
|
|
}
|
|
}
|
|
if (existsState(id + '.VACATION') && getState(id + '.VACATION').val != null) {
|
|
if (getState(id + '.VACATION').val) {
|
|
bt[i++] = Icons.GetIcon('palm-tree') + '~' + rgb_dec565(On) + '~1~' + 'VACT' + '~';
|
|
statusStr = 'VAC';
|
|
} else {
|
|
bt[i++] = Icons.GetIcon('palm-tree') + '~33840~1~' + 'VACT' + '~';
|
|
}
|
|
}
|
|
if (existsState(id + '.BOOST') && getState(id + '.BOOST').val != null) {
|
|
if (getState(id + '.BOOST').val) {
|
|
bt[i++] = Icons.GetIcon('fast-forward-60') + '~' + rgb_dec565(On) + '~1~' + 'BOOT' + '~';
|
|
statusStr = 'BOOST';
|
|
} else {
|
|
bt[i++] = Icons.GetIcon('fast-forward-60') + '~33840~1~' + 'BOOT' + '~';
|
|
}
|
|
}
|
|
|
|
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~' + 'HUM' + '~';
|
|
} else if (parseInt(getState(id + '.HUMIDITY').val) < 30) {
|
|
bt[i - 1] = Icons.GetIcon('water-percent') + '~63488~1~' + 'HUM' + '~';
|
|
} else if (parseInt(getState(id + '.HUMIDITY').val) >= 40) {
|
|
bt[i - 1] = Icons.GetIcon('water-percent') + '~2016~1~' + 'HUM' + '~';
|
|
} else if (parseInt(getState(id + '.HUMIDITY').val) > 65) {
|
|
bt[i - 1] = Icons.GetIcon('water-percent') + '~65504~1~' + 'HUM' + '~';
|
|
} else if (parseInt(getState(id + '.HUMIDITY').val) > 75) {
|
|
bt[i - 1] = Icons.GetIcon('water-percent') + '~63488~1~' + 'HUM' + '~';
|
|
}
|
|
} 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~' + 'LBAT' + '~';
|
|
} else {
|
|
bt[i - 1] = Icons.GetIcon('battery-high') + '~2016~1~' + 'LBAT' + '~';
|
|
}
|
|
} 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('account-wrench') + '~60897~1~' + 'MAIN' + '~';
|
|
} else {
|
|
bt[i - 1] = Icons.GetIcon('account-wrench') + '~33840~1~' + 'MAIN' + '~';
|
|
}
|
|
} 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~' + 'WLAN' + '~';
|
|
} else {
|
|
bt[i - 1] = Icons.GetIcon('wifi') + '~2016~1~' + 'WLAN' + '~';
|
|
}
|
|
} 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~' + 'POW' + '~';
|
|
} else {
|
|
bt[i - 1] = Icons.GetIcon('power-standby') + '~33840~1~' + 'POW' + '~';
|
|
}
|
|
} 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~' + 'ERR' + '~';
|
|
} else {
|
|
bt[i - 1] = Icons.GetIcon('alert-circle') + '~33840~1~' + 'ERR' + '~';
|
|
}
|
|
} 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~' + 'WORK' + '~';
|
|
} else {
|
|
bt[i - 1] = Icons.GetIcon('briefcase-check') + '~33840~1~' + 'WORK' + '~';
|
|
}
|
|
} else i--;
|
|
break;
|
|
default:
|
|
i--;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
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];
|
|
|
|
out_msgs.push({
|
|
payload: 'entityUpd~'
|
|
+ name + '~' // Heading
|
|
+ GetNavigationString(pageId) + '~' // Page Navigation
|
|
+ id + '~' // internalNameEntiy
|
|
+ currentTemp + config.temperatureUnit + '~' // 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
|
|
+ findLocale('thermostat', 'Currently') + '~' // Bezeicher vor Aktueller Raumtemperatur
|
|
+ findLocale('thermostat', 'State') + '~' // Bezeicner vor
|
|
+ '~' // Bezeichner vor HVAC -- Gibt es nicht mehr
|
|
+ config.temperatureUnit + '~' // Bezeichner hinter Solltemp
|
|
+ '' + '~' // iconTemperature dstTempTwoTempMode
|
|
+ '' // dstTempTwoTempMode
|
|
});
|
|
|
|
}
|
|
|
|
if (Debug) console.log(out_msgs);
|
|
return out_msgs
|
|
} catch (err) {
|
|
console.warn('function GenerateThermoPage: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function GenerateMediaPage(page: PageMedia): Payload[] {
|
|
try {
|
|
var id = page.items[0].id
|
|
|
|
var out_msgs: Array<Payload> = [];
|
|
|
|
out_msgs.push({ payload: 'pageType~cardMedia' });
|
|
if (existsObject(id)) {
|
|
let name = getState(id + '.ALBUM').val;
|
|
let title = getState(id + '.TITLE').val;
|
|
let author = getState(id + '.ARTIST').val;
|
|
|
|
let vInstance = page.items[0].adapterPlayerInstance;
|
|
let v1Adapter = vInstance.split('.');
|
|
let v2Adapter = v1Adapter[0];
|
|
|
|
//Alexa + neue Adpter/Player
|
|
let media_icon = Icons.GetIcon('playlist-music');
|
|
|
|
//Spotify-Premium
|
|
if (v2Adapter == 'spotify-premium') {
|
|
media_icon = Icons.GetIcon('spotify');
|
|
name = getState(id + '.CONTEXT_DESCRIPTION').val;
|
|
let nameLenght = name.length;
|
|
if (name.substring(0,9) == 'Playlist:') {
|
|
let nameLenght = name.length;
|
|
name = name.slice(10, nameLenght);
|
|
} else if (name.substring(0,6) == 'Album:') {
|
|
let nameLenght = name.length;
|
|
name = name.slice(10, nameLenght);
|
|
} else if (name.substring(0,6) == 'Track') {
|
|
name = 'Spotify-Premium';
|
|
}
|
|
if (nameLenght == 0) {
|
|
name = 'Spotify-Premium';
|
|
}
|
|
author = getState(id + '.ARTIST').val + ' | ' + getState(id + '.ALBUM').val;
|
|
if (author.length > 30) {
|
|
author = getState(id + '.ARTIST').val;
|
|
}
|
|
if ((getState(id + '.ARTIST').val).length == 0) {
|
|
author = 'no music to control';
|
|
}
|
|
}
|
|
|
|
//Sonos
|
|
if (v2Adapter == 'sonos') {
|
|
media_icon = Icons.GetIcon('music');
|
|
name = getState(id + '.CONTEXT_DESCRIPTION').val;
|
|
let nameLenght = name.length;
|
|
if (nameLenght == 0) {
|
|
name = 'Sonos Player';
|
|
}
|
|
author = getState(id + '.ARTIST').val + ' | ' + getState(id + '.ALBUM').val;
|
|
if ((getState(id + '.ARTIST').val).length == 0) {
|
|
author = 'no music to control';
|
|
}
|
|
}
|
|
|
|
//Logitech Squeezebox RPC
|
|
if (v2Adapter == 'squeezeboxrpc') {
|
|
media_icon = Icons.GetIcon('dlna');
|
|
let nameLenght = name.length;
|
|
if (nameLenght == 0) {
|
|
name = 'Squeezebox RPC';
|
|
author = 'no music to control';
|
|
}
|
|
}
|
|
|
|
//Alexa2
|
|
if (v2Adapter == 'alexa2') {
|
|
media_icon = Icons.GetIcon('playlist-music');
|
|
let nameLenght = name.length;
|
|
if (nameLenght == 0) {
|
|
name = 'Alexa Player';
|
|
author = 'no music to control';
|
|
}
|
|
}
|
|
|
|
let volume = getState(id + '.VOLUME').val;
|
|
var iconplaypause = Icons.GetIcon('pause'); //pause
|
|
var onoffbutton = 1374;
|
|
|
|
//Für alle Player
|
|
if (getState(id + '.STATE').val) {
|
|
onoffbutton = 65535;
|
|
iconplaypause = Icons.GetIcon('pause'); //pause
|
|
} else {
|
|
iconplaypause = Icons.GetIcon('play'); //play
|
|
}
|
|
|
|
//Ausnahme für squeezebox, da State = Power
|
|
if (getState(id + '.PAUSE').val === false && v2Adapter == 'squeezeboxrpc') {
|
|
onoffbutton = 65535;
|
|
iconplaypause = Icons.GetIcon('pause'); //pause
|
|
} else {
|
|
iconplaypause = Icons.GetIcon('play'); //play
|
|
}
|
|
|
|
if (Debug) console.log(v2Adapter);
|
|
|
|
let currentSpeaker = 'kein Speaker gefunden';
|
|
|
|
if (v2Adapter == 'alexa2') {
|
|
currentSpeaker = getState(([page.items[0].adapterPlayerInstance, 'Echo-Devices.', page.items[0].mediaDevice, '.Info.name'].join(''))).val;
|
|
} else if (v2Adapter == 'spotify-premium') {
|
|
currentSpeaker = getState(([page.items[0].adapterPlayerInstance, 'player.device.name'].join(''))).val;
|
|
} else if (v2Adapter == 'sonos') {
|
|
currentSpeaker = getState(([page.items[0].adapterPlayerInstance, 'root.', page.items[0].mediaDevice, '.members'].join(''))).val;
|
|
} else if (v2Adapter == 'squeezeboxrpc') {
|
|
if(existsObject(([page.items[0].adapterPlayerInstance, 'Playername'].join('')))) {
|
|
currentSpeaker = getState(([page.items[0].adapterPlayerInstance, 'Playername'].join(''))).val;
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------
|
|
// nachfolgend alle Alexa-Devices (ist Online / Player- und Commands-Verzeichnis vorhanden) auflisten und verketten
|
|
// Wenn Konstante alexaSpeakerList mind. einen Eintrag enthält, wird die Konstante verwendet - ansonsten Alle Devices aus dem Alexa Adapter
|
|
let speakerlist = '';
|
|
if (page.items[0].speakerList.length > 0) {
|
|
for (let i_index in page.items[0].speakerList) {
|
|
speakerlist = speakerlist + page.items[0].speakerList[i_index] + '?';
|
|
}
|
|
} else {
|
|
let i_list = Array.prototype.slice.apply($('[state.id="' + page.items[0].adapterPlayerInstance + '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(([page.items[0].adapterPlayerInstance, 'Echo-Devices.', deviceId[3], '.online'].join(''))).val &&
|
|
existsObject(([page.items[0].adapterPlayerInstance, 'Echo-Devices.', deviceId[3], '.Player'].join(''))) &&
|
|
existsObject(([page.items[0].adapterPlayerInstance, 'Echo-Devices.', deviceId[3], '.Commands'].join('')))) {
|
|
speakerlist = speakerlist + getState(i).val + '?';
|
|
}
|
|
}
|
|
}
|
|
speakerlist = speakerlist.substring(0, speakerlist.length - 1);
|
|
//--------------------------------------------------------------------------------------------------------------
|
|
|
|
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
|
|
} catch (err) {
|
|
console.warn('function GenerateMediaPage: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function GenerateAlarmPage(page: PageAlarm): Payload[] {
|
|
try {
|
|
activePage = page;
|
|
var id = page.items[0].id
|
|
|
|
var out_msgs: Array<Payload> = [];
|
|
out_msgs.push({ payload: 'pageType~cardAlarm' });
|
|
var nsPath = NSPanel_Alarm_Path + 'Alarm.';
|
|
|
|
if (existsState(nsPath + 'AlarmPin') == false || existsState(nsPath + 'AlarmState') == false || existsState(nsPath + 'AlarmType') == false || existsState(nsPath + 'PIN_Failed') == false || existsState(nsPath + 'PANEL') == 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', 'D1', { type: 'string' }, function () { setState(nsPath + 'AlarmType', 'D1') });
|
|
createState(nsPath + 'PIN_Failed', 0, { type: 'number' }, function () { setState(nsPath + 'PIN_Failed', 0) });
|
|
createState(nsPath + 'PANEL', NSPanel_Path, { type: 'string' }, function () { setState(nsPath + 'PANEL', NSPanel_Path) });
|
|
}
|
|
|
|
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
|
|
}
|
|
} catch (err) {
|
|
console.warn('function GenerateAlarmPage: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function GenerateQRPage(page: PageQR): Payload[] {
|
|
try {
|
|
activePage = page;
|
|
|
|
var id = page.items[0].id
|
|
var out_msgs: Array<Payload> = [];
|
|
out_msgs.push({ payload: 'pageType~cardQR' });
|
|
|
|
let o = getObject(id)
|
|
|
|
var heading = page.heading !== undefined ? page.heading : o.common.name.de
|
|
var textQR = page.items[0].id + '.ACTUAL' !== undefined ? getState(page.items[0].id + '.ACTUAL').val : 'WIFI:T:undefined;S:undefined;P:undefined;H:undefined;'
|
|
var hiddenPWD = false;
|
|
if (page.items[0].hidePassword !== undefined && page.items[0].hidePassword == true) {
|
|
hiddenPWD = true
|
|
}
|
|
|
|
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';
|
|
|
|
if (hiddenPWD) {
|
|
type2 = 'disable';
|
|
iconId2 = '';
|
|
displayName2 = '';
|
|
}
|
|
|
|
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
|
|
|
|
} catch (err) {
|
|
console.warn('function GenerateQRPage: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function GeneratePowerPage(page: PagePower): Payload[] {
|
|
try {
|
|
activePage = page;
|
|
|
|
if (Debug) console.log(page.items[0].id);
|
|
|
|
var demoMode = false;
|
|
|
|
try {
|
|
var id = page.items[0].id
|
|
} catch (err) {
|
|
console.log("Kein PageItem definiert - cardPower Demo-Modus aktiv");
|
|
demoMode = true;
|
|
}
|
|
|
|
let heading = 'cardPower Example';
|
|
if (demoMode != true) {
|
|
let o = getObject(id)
|
|
heading = page.heading !== undefined ? page.heading : o.common.name.de
|
|
}
|
|
|
|
const obj = JSON.parse((getState(page.items[0].id + '.ACTUAL').val));
|
|
|
|
var out_msgs: Array<Payload> = [];
|
|
out_msgs.push({ payload: 'pageType~cardPower' });
|
|
|
|
//Demo Data if no pageItem present
|
|
let array_icon_color = [White, MSGreen, MSYellow, MSGreen, MSYellow, MSGreen, MSRed];
|
|
let array_icon = ['home', 'battery-charging-60', 'solar-power-variant', 'wind-turbine', 'shape', 'transmission-tower', 'car'];
|
|
let array_powerspeed = ['', '-1', '2', '4', '1', '1', '5'];
|
|
let array_powerstate = ['', '0,5 kW', '0,9 kW', '2,8 kW', '0,2 kW', '0,1 kW', '4,6 kW'];
|
|
|
|
let arrayColorScale = [colorScale0, colorScale1, colorScale2, colorScale3, colorScale4, colorScale5, colorScale6, colorScale7, colorScale8, colorScale9, colorScale10]
|
|
|
|
if (!demoMode) {
|
|
for (let obji = 0; obji < 6; obji++) {
|
|
array_icon_color[obji + 1] = arrayColorScale[obj[obji].iconColor];
|
|
array_icon[obji + 1] = obj[obji].icon;
|
|
array_powerspeed[obji + 1] = obj[obji].speed;
|
|
array_powerstate[obji + 1] = obj[obji].value + ' ' + obj[obji].unit ;
|
|
}
|
|
}
|
|
|
|
let power_string : any = '';
|
|
|
|
for (let i = 1; i < 7; i++ ) {
|
|
power_string = power_string + rgb_dec565(array_icon_color[i]) + '~'; // icon_color~
|
|
power_string = power_string + Icons.GetIcon(array_icon[i]) + '~'; // icon~
|
|
power_string = power_string + array_powerspeed[i] + '~'; // speed~
|
|
power_string = power_string + array_powerstate[i] + '~'; // entity.state~
|
|
}
|
|
|
|
power_string = power_string.substring(0, power_string.length - 1);
|
|
|
|
out_msgs.push({
|
|
payload: 'entityUpd~' + //entityUpd~*
|
|
heading + '~' + //internalNameEntity*~*
|
|
GetNavigationString(pageId) + '~' + //navigation*~*
|
|
rgb_dec565(array_icon_color[0]) + '~' + // icon_color~ Mitte
|
|
Icons.GetIcon(array_icon[0]) + '~' + // icon~ Mitte
|
|
array_powerspeed[0] + '~' + // entity.state~ Mitte
|
|
power_string
|
|
});
|
|
|
|
return out_msgs
|
|
|
|
} catch (err) {
|
|
console.warn('function GeneratePowerPage: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function setIfExists(id: string, value: any, type: string | null = null): boolean {
|
|
try {
|
|
if (type === null) {
|
|
if (existsState(id)) {
|
|
setState(id, value);
|
|
return true;
|
|
}
|
|
} else {
|
|
const obj = getObject(id);
|
|
if (existsState(id) && obj.common.type !== undefined && obj.common.type === type) {
|
|
setState(id, value);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
} catch (err) {
|
|
console.warn('function setIfExists: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function toggleState(id: string): boolean {
|
|
try {
|
|
const obj = getObject(id);
|
|
if (existsState(id) && obj.common.type !== undefined && obj.common.type === 'boolean') {
|
|
setIfExists(id, !getState(id).val);
|
|
return true;
|
|
}
|
|
return false;
|
|
} catch (err) {
|
|
console.warn('function toggleState: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function HandleButtonEvent(words): void {
|
|
try {
|
|
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;
|
|
}
|
|
|
|
if (Debug) console.log(buttonAction);
|
|
|
|
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) + config.pages.length) % config.pages.length;
|
|
pageId = pageNum;
|
|
UnsubscribeWatcher();
|
|
GeneratePage(config.pages[pageId]);
|
|
break;
|
|
case 'bPrev':
|
|
var pageNum = (((pageId - 1) % config.pages.length) + config.pages.length) % config.pages.length;
|
|
pageId = pageNum;
|
|
UnsubscribeWatcher();
|
|
if (activePage != undefined && activePage.parent != undefined) {
|
|
//update pageID
|
|
for (let i = 0; i < config.pages.length; i++) {
|
|
if (config.pages[i] == activePage.parent) {
|
|
pageId = i;
|
|
break;
|
|
}
|
|
}
|
|
GeneratePage(activePage.parent);
|
|
}
|
|
else {
|
|
GeneratePage(config.pages[pageId]);
|
|
}
|
|
break;
|
|
case 'bExit':
|
|
if (config.screenSaverDoubleClick && words[2] == 'screensaver') {
|
|
if (words[4] == 2) {
|
|
setIfExists(NSPanel_Path + 'ScreensaverInfo.popupNotifyHeading', '');
|
|
setIfExists(NSPanel_Path + 'ScreensaverInfo.popupNotifyText', '');
|
|
GeneratePage(config.pages[pageId]);
|
|
}
|
|
} else {
|
|
if (Debug) console.log('bExit: ' + words[4] + ' - ' + pageId);
|
|
setIfExists(NSPanel_Path + 'ScreensaverInfo.popupNotifyHeading', '');
|
|
setIfExists(NSPanel_Path + 'ScreensaverInfo.popupNotifyText', '');
|
|
GeneratePage(activePage);
|
|
}
|
|
break;
|
|
case 'notifyAction':
|
|
if (words[4] == 'yes') {
|
|
setState(popupNotifyInternalName, <iobJS.State>{ val: words[2], ack: true });
|
|
setState(popupNotifyAction, <iobJS.State>{ val: true, ack: true });
|
|
} else if (words[4] == 'no') {
|
|
setState(popupNotifyInternalName, <iobJS.State>{ val: words[2], ack: true });
|
|
setState(popupNotifyAction, <iobJS.State>{ val: false, ack: true });
|
|
}
|
|
|
|
setIfExists(config.panelSendTopic, 'exitPopup');
|
|
|
|
break;
|
|
case 'OnOff':
|
|
if (existsObject(id)) {
|
|
var action = false
|
|
if (words[4] == '1')
|
|
action = true;
|
|
let o = getObject(id);
|
|
switch (o.common.role) {
|
|
case 'socket':
|
|
case 'light':
|
|
setIfExists(id + '.SET', action);
|
|
break;
|
|
case 'dimmer':
|
|
setIfExists(id + '.ON_SET', action) ? true : setIfExists(id + '.ON_ACTUAL', action);
|
|
break;
|
|
case 'ct':
|
|
setIfExists(id + '.ON', action);
|
|
break;
|
|
case 'rgb':
|
|
case 'rgbSingle':
|
|
case 'hue': // Armilar
|
|
setIfExists(id + '.ON_ACTUAL', action);
|
|
}
|
|
}
|
|
break;
|
|
case 'button':
|
|
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 'up':
|
|
setIfExists(id + '.OPEN', true);
|
|
break;
|
|
case 'stop':
|
|
setIfExists(id + '.STOP', true);
|
|
break;
|
|
case 'down':
|
|
setIfExists(id + '.CLOSE', true);
|
|
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]));
|
|
}, 250);
|
|
break;
|
|
case 'tiltOpen':
|
|
setIfExists(id + '.TILT_OPEN', true);
|
|
break;
|
|
case 'tiltStop':
|
|
setIfExists(id + '.TILT_STOP', true);
|
|
break;
|
|
case 'tiltClose':
|
|
setIfExists(id + '.TILT_CLOSE', true);
|
|
break;
|
|
case 'tiltSlider':
|
|
(function () { if (timeoutSlider) { clearTimeout(timeoutSlider); timeoutSlider = null; } })();
|
|
timeoutSlider = setTimeout(async function () {
|
|
setIfExists(id + '.TILT_SET', parseInt(words[4])) ? true : setIfExists(id + '.TILT_ACTUAL', parseInt(words[4]));
|
|
}, 250);
|
|
break;
|
|
case 'brightnessSlider':
|
|
(function () { if (timeoutSlider) { clearTimeout(timeoutSlider); timeoutSlider = null; } })();
|
|
timeoutSlider = setTimeout(async function () {
|
|
if (existsObject(id)) {
|
|
let o = getObject(id);
|
|
let pageItem = findPageItem(id);
|
|
|
|
switch (o.common.role) {
|
|
case 'dimmer':
|
|
if (pageItem.minValueBrightness != undefined && pageItem.maxValueBrightness != undefined) {
|
|
let sliderPos = Math.trunc(scale(parseInt(words[4]), 0, 100, pageItem.maxValueBrightness, pageItem.minValueBrightness))
|
|
setIfExists(id + '.SET', sliderPos) ? true : setIfExists(id + '.ACTUAL', sliderPos);
|
|
} else {
|
|
setIfExists(id + '.SET', parseInt(words[4])) ? true : setIfExists(id + '.ACTUAL', parseInt(words[4]));
|
|
}
|
|
break;
|
|
case 'rgb':
|
|
case 'ct':
|
|
case 'rgbSingle':
|
|
case 'hue':
|
|
if (pageItem.minValueBrightness != undefined && pageItem.maxValueBrightness != undefined) {
|
|
let sliderPos = Math.trunc(scale(parseInt(words[4]), 0, 100, pageItem.maxValueBrightness, pageItem.minValueBrightness))
|
|
setIfExists(id + '.DIMMER', sliderPos);
|
|
} else {
|
|
setIfExists(id + '.DIMMER', parseInt(words[4]));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}, 250);
|
|
break;
|
|
case 'colorTempSlider': // Armilar - Slider tickt verkehrt - Hell = 0 / Dunkel = 100 -> Korrektur
|
|
(function () { if (timeoutSlider) { clearTimeout(timeoutSlider); timeoutSlider = null; } })();
|
|
timeoutSlider = setTimeout(async function () {
|
|
let pageItem = findPageItem(id);
|
|
if (pageItem.minValueColorTemp !== undefined && pageItem.minValueColorTemp !== undefined) {
|
|
let colorTempK = Math.trunc(scale(parseInt(words[4]), 0, 100, pageItem.minValueColorTemp, pageItem.maxValueColorTemp));
|
|
setIfExists(id + '.TEMPERATURE', (colorTempK));
|
|
} else {
|
|
setIfExists(id + '.TEMPERATURE', 100 - words[4]);
|
|
}
|
|
}, 250);
|
|
break;
|
|
case 'colorWheel':
|
|
let colorCoordinates = words[4].split('|');
|
|
let rgb = pos_to_color(colorCoordinates[0], colorCoordinates[1]);
|
|
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':
|
|
setIfExists(id + '.HUE', getHue(rgb.red, rgb.green, rgb.blue));
|
|
break;
|
|
case 'rgb':
|
|
setIfExists(id + '.RED', rgb.red);
|
|
setIfExists(id + '.GREEN', rgb.green);
|
|
setIfExists(id + '.BLUE', rgb.blue);
|
|
break;
|
|
case 'rgbSingle':
|
|
let pageItem = findPageItem(id);
|
|
if (pageItem.colormode == "xy") {
|
|
//Für z.B. Deconz XY
|
|
setIfExists(id + ".RGB", rgb_to_cie(rgb.red, rgb.green, rgb.blue));
|
|
if (Debug) console.log(rgb_to_cie(rgb.red, rgb.green, rgb.blue));
|
|
}
|
|
else {
|
|
//Für RGB
|
|
setIfExists(id + ".RGB", ConvertRGBtoHex(rgb.red, rgb.green, rgb.blue));
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
case 'tempUpd':
|
|
setIfExists(id + '.SET', parseInt(words[4]) / 10);
|
|
break;
|
|
case 'media-back':
|
|
setIfExists(id + '.PREV', true);
|
|
setTimeout(function(){
|
|
GeneratePage(activePage);
|
|
},3000)
|
|
break;
|
|
case 'media-pause':
|
|
let pageItemTemp = findPageItem(id);
|
|
let adaInstanceSplit = pageItemTemp.adapterPlayerInstance.split('.');
|
|
if (adaInstanceSplit[0] == 'squeezeboxrpc') {
|
|
let stateVal = getState(pageItemTemp.adapterPlayerInstance + 'state').val
|
|
if (stateVal == 0) {
|
|
setState(pageItemTemp.adapterPlayerInstance + 'state', 1)
|
|
} else if (stateVal == 1) {
|
|
setState(pageItemTemp.adapterPlayerInstance + 'state', 0)
|
|
} else if (stateVal == null) {
|
|
setState(pageItemTemp.adapterPlayerInstance + 'state', 1)
|
|
}
|
|
} else {
|
|
if (getState(id + '.STATE').val === true) {
|
|
setIfExists(id + '.PAUSE', true);
|
|
} else {
|
|
setIfExists(id + '.PLAY', true);
|
|
}
|
|
}
|
|
setTimeout(function(){
|
|
GeneratePage(activePage);
|
|
},3000)
|
|
break;
|
|
case 'media-next':
|
|
setIfExists(id + '.NEXT', true);
|
|
setTimeout(function(){
|
|
GeneratePage(activePage);
|
|
},3000)
|
|
break;
|
|
case 'volumeSlider':
|
|
setIfExists(id + '.VOLUME', parseInt(words[4]))
|
|
break;
|
|
case 'speaker-sel':
|
|
let pageItem = findPageItem(id);
|
|
let adapterInstance = pageItem.adapterPlayerInstance;
|
|
let adapter = adapterInstance.split('.')
|
|
let deviceAdapter = adapter[0];
|
|
|
|
switch (deviceAdapter) {
|
|
case 'spotify-premium':
|
|
var strDeviceID = spotifyGetDeviceID(words[4]);
|
|
setState(adapterInstance + 'devices.' + strDeviceID + ".useForPlayback", true);
|
|
break;
|
|
case 'alexa2':
|
|
let i_list = Array.prototype.slice.apply($('[state.id="' + adapterInstance + 'Echo-Devices.*.Info.name"]'));
|
|
for (let i_index in i_list) {
|
|
let i = i_list[i_index];
|
|
if ((getState(i).val) === words[4]) {
|
|
let deviceId = i;
|
|
deviceId = deviceId.split('.');
|
|
setIfExists(adapterInstance + 'Echo-Devices.' + pageItem.mediaDevice + '.Commands.textCommand', 'Schiebe meine Musik auf ' + words[4]);
|
|
pageItem.mediaDevice = deviceId[3];
|
|
}
|
|
}
|
|
break;
|
|
case 'sonos':
|
|
break;
|
|
case 'chromecast':
|
|
break;
|
|
}
|
|
break;
|
|
case 'media-OnOff':
|
|
let pageItemTem = findPageItem(id);
|
|
let adaInstanceSpli = pageItemTem.adapterPlayerInstance.split('.');
|
|
if (adaInstanceSpli[0] == 'squeezeboxrpc') {
|
|
let stateVal = getState(pageItemTem.adapterPlayerInstance + 'Power').val
|
|
if (stateVal === 0) {
|
|
setState(pageItemTem.adapterPlayerInstance + 'Power', 1)
|
|
setIfExists(id + '.STOP', false)
|
|
setIfExists(id + '.STATE', 1)
|
|
} else {
|
|
setState(pageItemTem.adapterPlayerInstance + 'Power', 0)
|
|
setIfExists(id + '.STOP', true)
|
|
setIfExists(id + '.STATE', 0)
|
|
}
|
|
} else {
|
|
setIfExists(id + '.STOP', true)
|
|
}
|
|
break;
|
|
case 'hvac_action':
|
|
if (words[4] == 'BOOT' || words[4] == 'PART' || words[4] == 'AUTT' || words[4] == 'MANT' || words[4] == 'VACT') {
|
|
|
|
switch (words[4]) {
|
|
case 'BOOT':
|
|
setIfExists(words[2] + '.' + 'BOOST', !getState(words[2] + '.' + 'BOOST').val)
|
|
break;
|
|
case 'PART':
|
|
setIfExists(words[2] + '.' + 'PARTY', !getState(words[2] + '.' + 'PARTY').val)
|
|
break;
|
|
case 'AUTT':
|
|
setIfExists(words[2] + '.' + 'AUTOMATIC', !getState(words[2] + '.' + 'AUTOMATIC').val)
|
|
break;
|
|
case 'MANT':
|
|
setIfExists(words[2] + '.' + 'MANUAL', !getState(words[2] + '.' + 'MANUAL').val)
|
|
break;
|
|
case 'VACT':
|
|
setIfExists(words[2] + '.' + 'VACATION', !getState(words[2] + '.' + 'VACATION').val)
|
|
break;
|
|
}
|
|
let modes = ['BOOT', 'PART', 'AUTT', 'MANT', 'VACT']
|
|
let modesDP = ['BOOST', 'PARTY', 'AUTOMATIC', 'MANUAL', 'VACATION']
|
|
for (let mode=0; mode < 5; mode++) {
|
|
if (words[4] != modes[mode]) {
|
|
setIfExists(words[2] + '.' + modesDP[mode], false)
|
|
}
|
|
}
|
|
GeneratePage(config.pages[pageId]);
|
|
} 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');
|
|
setIfExists(id + '.PANEL', NSPanel_Path);
|
|
}
|
|
setTimeout(function(){
|
|
GeneratePage(activePage);
|
|
},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');
|
|
setIfExists(id + '.PANEL', NSPanel_Path);
|
|
}
|
|
setTimeout(function(){
|
|
GeneratePage(activePage);
|
|
},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');
|
|
setIfExists(id + '.PANEL', NSPanel_Path);
|
|
}
|
|
setTimeout(function(){
|
|
GeneratePage(activePage);
|
|
},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');
|
|
setIfExists(id + '.PANEL', NSPanel_Path);
|
|
}
|
|
setTimeout(function(){
|
|
GeneratePage(activePage);
|
|
},250)
|
|
break;
|
|
case 'D1': // Alarm-Page Alarm Deaktivieren
|
|
if (Debug) console.log('D1: ' + getState(id + '.PIN').val);
|
|
if (Debug) console.log(words[4]);
|
|
if (words[4] != '') {
|
|
if (getState(id + '.PIN').val == words[4]) {
|
|
setIfExists(id + '.PIN', '0000');
|
|
setIfExists(id + '.TYPE', 'D1');
|
|
setIfExists(id + '.ACTUAL', 'pending');
|
|
setIfExists(id + '.PIN_Failed', 0);
|
|
} else {
|
|
setIfExists(id + '.PIN_Failed', getState(id + '.PIN_Failed').val + 1);
|
|
setIfExists(id + '.ACTUAL', 'triggered');
|
|
}
|
|
setIfExists(id + '.PANEL', NSPanel_Path);
|
|
setTimeout(function(){
|
|
GeneratePage(activePage);
|
|
},500)
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
} catch (err) {
|
|
console.log('function HandleButtonEvent: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function GetNavigationString(pageId: number): string {
|
|
try {
|
|
|
|
if (Debug) console.log(pageId);
|
|
|
|
if (activePage.subPage)
|
|
return '1|0';
|
|
|
|
switch (pageId) {
|
|
case 0:
|
|
return '0|1';
|
|
case config.pages.length - 1:
|
|
return '1|0';
|
|
case -1:
|
|
return '2|0';
|
|
case -2:
|
|
return '2|0';
|
|
default:
|
|
return '1|1';
|
|
}
|
|
} catch (err) {
|
|
console.log('function GetNavigationString: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function GenerateDetailPage(type: string, pageItem: PageItem): Payload[] {
|
|
try {
|
|
var out_msgs: Array<Payload> = [];
|
|
let id = pageItem.id
|
|
|
|
if (existsObject(id)) {
|
|
var o = getObject(id)
|
|
var val: (boolean | number) = 0;
|
|
let icon = Icons.GetIcon('lightbulb');
|
|
var iconColor = rgb_dec565(config.defaultColor);
|
|
|
|
if (type == 'popupLight') {
|
|
let switchVal = '0';
|
|
let brightness = 0;
|
|
if (o.common.role == 'light' || o.common.role == 'socket') {
|
|
if (existsState(id + '.GET')) {
|
|
val = getState(id + '.GET').val;
|
|
RegisterDetailEntityWatcher(id + '.GET', pageItem, type);
|
|
} else if (existsState(id + '.SET')) {
|
|
val = getState(id + '.SET').val;
|
|
RegisterDetailEntityWatcher(id + '.SET', pageItem, type);
|
|
}
|
|
|
|
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, true);
|
|
} else {
|
|
iconColor = GetIconColor(pageItem, false, true);
|
|
}
|
|
|
|
out_msgs.push({
|
|
payload: 'entityUpdateDetail' + '~' // entityUpdateDetail
|
|
+ id + '~'
|
|
+ icon + '~' // iconId
|
|
+ iconColor + '~' // iconColor
|
|
+ switchVal + '~' // buttonState
|
|
+ 'disable' + '~' // sliderBrightnessPos
|
|
+ 'disable' + '~' // sliderColorTempPos
|
|
+ 'disable' + '~' // colorMode
|
|
+ '' + '~' // Color-Bezeichnung
|
|
+ findLocale('lights', 'Temperature') + '~' // Temperature-Bezeichnung
|
|
+ findLocale('lights', 'Brightness')
|
|
}); // Brightness-Bezeichnung
|
|
}
|
|
|
|
// Dimmer
|
|
if (o.common.role == 'dimmer') {
|
|
if (existsState(id + '.ON_ACTUAL')) {
|
|
val = getState(id + '.ON_ACTUAL').val;
|
|
RegisterDetailEntityWatcher(id + '.ON_ACTUAL', pageItem, type);
|
|
} else if (existsState(id + '.ON_SET')) {
|
|
val = getState(id + '.ON_SET').val;
|
|
RegisterDetailEntityWatcher(id + '.ON_SET', pageItem, type);
|
|
}
|
|
|
|
if (val === true) {
|
|
var iconColor = GetIconColor(pageItem, val, false);
|
|
switchVal = '1'
|
|
}
|
|
|
|
if (existsState(id + '.ACTUAL')) {
|
|
if (pageItem.minValueBrightness != undefined && pageItem.maxValueBrightness != undefined) {
|
|
brightness = Math.trunc(scale(getState(id + '.ACTUAL').val, pageItem.minValueBrightness, pageItem.maxValueBrightness, 100, 0));
|
|
} else {
|
|
brightness = getState(id + '.ACTUAL').val;
|
|
}
|
|
} else {
|
|
console.warn('Alisas-Datenpunkt: ' + id + '.ACTUAL could not be read');
|
|
}
|
|
|
|
if (val === true) {
|
|
iconColor = GetIconColor(pageItem, 100 - brightness, true);
|
|
switchVal = '1';
|
|
} else {
|
|
iconColor = GetIconColor(pageItem, false, true);
|
|
}
|
|
|
|
RegisterDetailEntityWatcher(id + '.ACTUAL', pageItem, type);
|
|
|
|
out_msgs.push({
|
|
payload: 'entityUpdateDetail' + '~' //entityUpdateDetail
|
|
+ id + '~'
|
|
+ icon + '~' //iconId
|
|
+ iconColor + '~' //iconColor
|
|
+ switchVal + '~' //buttonState
|
|
+ brightness + '~' //sliderBrightnessPos
|
|
+ 'disable' + '~' //sliderColorTempPos
|
|
+ 'disable' + '~' //colorMod
|
|
+ '' + '~' //Color-Bezeichnung
|
|
+ findLocale('lights', 'Temperature') + '~' //Temperature-Bezeichnung
|
|
+ findLocale('lights', 'Brightness')
|
|
}); //Brightness-Bezeichnung
|
|
|
|
console.log('light.' + id)
|
|
|
|
}
|
|
|
|
// HUE-Licht
|
|
if (o.common.role == 'hue') {
|
|
|
|
if (existsState(id + '.ON_ACTUAL')) {
|
|
val = getState(id + '.ON_ACTUAL').val;
|
|
RegisterDetailEntityWatcher(id + '.ON_ACTUAL', pageItem, type);
|
|
}
|
|
|
|
if (existsState(id + '.DIMMER')) {
|
|
if (pageItem.minValueBrightness != undefined && pageItem.maxValueBrightness != undefined) {
|
|
brightness = Math.trunc(scale(getState(id + '.DIMMER').val, pageItem.minValueBrightness, pageItem.maxValueBrightness, 100, 0));
|
|
} else {
|
|
brightness = getState(id + '.DIMMER').val;
|
|
}
|
|
RegisterDetailEntityWatcher(id + '.DIMMER', pageItem, type);
|
|
} else {
|
|
console.warn('Alias-Datenpunkt: ' + id + '.DIMMER could not be read');
|
|
}
|
|
|
|
if (val === true) {
|
|
iconColor = GetIconColor(pageItem, 100 - brightness, true);
|
|
switchVal = '1';
|
|
} else {
|
|
iconColor = GetIconColor(pageItem, false, true);
|
|
}
|
|
|
|
var colorMode = 'disable';
|
|
if (existsState(id + '.HUE')) {
|
|
if (getState(id + '.HUE').val != null) {
|
|
colorMode = 'enable';
|
|
let huecolor = hsv2rgb(getState(id + '.HUE').val, 1, 1);
|
|
let rgb = <RGB>{ red: Math.round(huecolor[0]), green: Math.round(huecolor[1]), blue: Math.round(huecolor[2]) }
|
|
iconColor = rgb_dec565(pageItem.interpolateColor !== undefined ? rgb : config.defaultOnColor);
|
|
//RegisterDetailEntityWatcher(id + '.HUE', pageItem, type);
|
|
}
|
|
}
|
|
|
|
var colorTemp = 0;
|
|
if (existsState(id + '.TEMPERATURE')) {
|
|
if (getState(id + '.TEMPERATURE').val != null) {
|
|
if (pageItem.minValueColorTemp !== undefined && pageItem.minValueColorTemp !== undefined) {
|
|
colorTemp = Math.trunc(scale(getState(id + '.TEMPERATURE').val, pageItem.minValueColorTemp, pageItem.maxValueColorTemp, 0, 100));
|
|
} else {
|
|
colorTemp = 100 - getState(id + '.TEMPERATURE').val;
|
|
}
|
|
//RegisterDetailEntityWatcher(id + '.TEMPERATURE', pageItem, type);
|
|
}
|
|
} else {
|
|
console.warn('Alias-Datenpunkt: ' + id + '.TEMPERATURE could not be read');
|
|
}
|
|
|
|
out_msgs.push({
|
|
payload: 'entityUpdateDetail' + '~' //entityUpdateDetail
|
|
+ id + '~'
|
|
+ icon + '~' //iconId
|
|
+ iconColor + '~' //iconColor
|
|
+ switchVal + '~' //buttonState
|
|
+ brightness + '~' //sliderBrightnessPos
|
|
+ colorTemp + '~' //sliderColorTempPos
|
|
+ colorMode + '~' //colorMode (if hue-alias without hue-datapoint, then disable)
|
|
+ 'Color' + '~' //Color-Bezeichnung
|
|
+ findLocale('lights', 'Temperature') + '~' //Temperature-Bezeichnung
|
|
+ findLocale('lights', 'Brightness')
|
|
}); //Brightness-Bezeichnung
|
|
}
|
|
|
|
// RGB-Licht
|
|
if (o.common.role == 'rgb') {
|
|
|
|
if (existsState(id + '.ON_ACTUAL')) {
|
|
val = getState(id + '.ON_ACTUAL').val;
|
|
RegisterDetailEntityWatcher(id + '.ON_ACTUAL', pageItem, type);
|
|
}
|
|
|
|
if (existsState(id + '.DIMMER')) {
|
|
if (pageItem.minValueBrightness != undefined && pageItem.maxValueBrightness != undefined) {
|
|
brightness = Math.trunc(scale(getState(id + '.DIMMER').val, pageItem.minValueBrightness, pageItem.maxValueBrightness, 100, 0));
|
|
} else {
|
|
brightness = getState(id + '.DIMMER').val;
|
|
}
|
|
RegisterDetailEntityWatcher(id + '.DIMMER', pageItem, type);
|
|
} else {
|
|
console.warn('Alias-Datenpunkt: ' + id + '.DIMMER could not be read');
|
|
}
|
|
|
|
if (val === true) {
|
|
iconColor = GetIconColor(pageItem, 100 - brightness, true);
|
|
switchVal = '1';
|
|
} else {
|
|
iconColor = GetIconColor(pageItem, false, true);
|
|
}
|
|
|
|
var colorMode = 'disable';
|
|
if (existsState(id + '.RED') && existsState(id + '.GREEN') && existsState(id + '.BLUE')) {
|
|
if (getState(id + '.RED').val != null && getState(id + '.GREEN').val != null && getState(id + '.BLUE').val != null) {
|
|
colorMode = 'enable';
|
|
let rgb = <RGB>{ red: Math.round(getState(id + '.RED').val), green: Math.round(getState(id + '.GREEN').val), blue: Math.round(getState(id + '.BLUE').val) }
|
|
iconColor = rgb_dec565(pageItem.interpolateColor !== undefined ? rgb : config.defaultOnColor);
|
|
//RegisterDetailEntityWatcher(id + '.HUE', pageItem, type);
|
|
}
|
|
}
|
|
|
|
var colorTemp = 0;
|
|
if (existsState(id + '.TEMPERATURE')) {
|
|
if (getState(id + '.TEMPERATURE').val != null) {
|
|
if (pageItem.minValueColorTemp !== undefined && pageItem.minValueColorTemp !== undefined) {
|
|
colorTemp = Math.trunc(scale(getState(id + '.TEMPERATURE').val, pageItem.minValueColorTemp, pageItem.maxValueColorTemp, 0, 100));
|
|
} else {
|
|
colorTemp = 100 - getState(id + '.TEMPERATURE').val;
|
|
}
|
|
//RegisterDetailEntityWatcher(id + '.TEMPERATURE', pageItem, type);
|
|
}
|
|
} else {
|
|
console.warn('Alias-Datenpunkt: ' + id + '.TEMPERATURE could not be read');
|
|
}
|
|
|
|
out_msgs.push({
|
|
payload: 'entityUpdateDetail' + '~' //entityUpdateDetail
|
|
+ id + '~'
|
|
+ icon + '~' //iconId
|
|
+ iconColor + '~' //iconColor
|
|
+ switchVal + '~' //buttonState
|
|
+ brightness + '~' //sliderBrightnessPos
|
|
+ colorTemp + '~' //sliderColorTempPos
|
|
+ colorMode + '~' //colorMode (if hue-alias without hue-datapoint, then disable)
|
|
+ 'Color' + '~' //Color-Bezeichnung
|
|
+ findLocale('lights', 'Temperature') + '~' //Temperature-Bezeichnung
|
|
+ findLocale('lights', 'Brightness')
|
|
}); //Brightness-Bezeichnung
|
|
}
|
|
|
|
// RGB-Licht-einzeln (HEX)
|
|
if (o.common.role == 'rgbSingle') {
|
|
|
|
if (existsState(id + '.ON_ACTUAL')) {
|
|
val = getState(id + '.ON_ACTUAL').val;
|
|
RegisterDetailEntityWatcher(id + '.ON_ACTUAL', pageItem, type);
|
|
}
|
|
|
|
if (existsState(id + '.DIMMER')) {
|
|
if (pageItem.minValueBrightness != undefined && pageItem.maxValueBrightness != undefined) {
|
|
brightness = Math.trunc(scale(getState(id + '.DIMMER').val, pageItem.minValueBrightness, pageItem.maxValueBrightness, 100, 0));
|
|
} else {
|
|
brightness = getState(id + '.DIMMER').val;
|
|
}
|
|
RegisterDetailEntityWatcher(id + '.DIMMER', pageItem, type);
|
|
} else {
|
|
console.warn('Alias-Datenpunkt: ' + id + '.DIMMER could not be read');
|
|
}
|
|
|
|
if (val === true) {
|
|
iconColor = GetIconColor(pageItem, 100 - brightness, true);
|
|
switchVal = '1';
|
|
} else {
|
|
iconColor = GetIconColor(pageItem, false, true);
|
|
}
|
|
|
|
var colorMode = 'disable';
|
|
if (existsState(id + '.RGB')) {
|
|
if (getState(id + '.RGB').val != null) {
|
|
colorMode = 'enable';
|
|
var hex = getState(id + '.RGB').val;
|
|
var hexRed = parseInt(hex[1] + hex[2], 16);
|
|
var hexGreen = parseInt(hex[3] + hex[4], 16);
|
|
var hexBlue = parseInt(hex[5] + hex[6], 16);
|
|
let rgb = <RGB>{ red: Math.round(hexRed), green: Math.round(hexGreen), blue: Math.round(hexBlue) }
|
|
iconColor = rgb_dec565(pageItem.interpolateColor !== undefined ? rgb : config.defaultOnColor);
|
|
//RegisterDetailEntityWatcher(id + '.HUE', pageItem, type);
|
|
}
|
|
}
|
|
|
|
var colorTemp = 0;
|
|
if (existsState(id + '.TEMPERATURE')) {
|
|
if (getState(id + '.TEMPERATURE').val != null) {
|
|
if (pageItem.minValueColorTemp !== undefined && pageItem.minValueColorTemp !== undefined) {
|
|
colorTemp = Math.trunc(scale(getState(id + '.TEMPERATURE').val, pageItem.minValueColorTemp, pageItem.maxValueColorTemp, 0, 100));
|
|
} else {
|
|
colorTemp = 100 - getState(id + '.TEMPERATURE').val;
|
|
}
|
|
//RegisterDetailEntityWatcher(id + '.TEMPERATURE', pageItem, type);
|
|
}
|
|
} else {
|
|
console.warn('Alias-Datenpunkt: ' + id + '.TEMPERATURE could not be read');
|
|
}
|
|
|
|
out_msgs.push({
|
|
payload: 'entityUpdateDetail' + '~' //entityUpdateDetail
|
|
+ id + '~'
|
|
+ icon + '~' //iconId
|
|
+ iconColor + '~' //iconColor
|
|
+ switchVal + '~' //buttonState
|
|
+ brightness + '~' //sliderBrightnessPos
|
|
+ colorTemp + '~' //sliderColorTempPos
|
|
+ colorMode + '~' //colorMode (if hue-alias without hue-datapoint, then disable)
|
|
+ 'Color' + '~' //Color-Bezeichnung
|
|
+ findLocale('lights', 'Temperature') + '~' //Temperature-Bezeichnung
|
|
+ findLocale('lights', 'Brightness')
|
|
}); //Brightness-Bezeichnung
|
|
}
|
|
|
|
// Farbtemperatur
|
|
if (o.common.role == 'ct') {
|
|
|
|
if (existsState(id + '.ON')) {
|
|
val = getState(id + '.ON').val;
|
|
RegisterDetailEntityWatcher(id + '.ON', pageItem, type);
|
|
}
|
|
|
|
if (existsState(id + '.DIMMER')) {
|
|
if (pageItem.minValueBrightness != undefined && pageItem.maxValueBrightness != undefined) {
|
|
brightness = Math.trunc(scale(getState(id + '.DIMMER').val, pageItem.minValueBrightness, pageItem.maxValueBrightness, 100, 0));
|
|
} else {
|
|
brightness = getState(id + '.DIMMER').val;
|
|
}
|
|
RegisterDetailEntityWatcher(id + '.DIMMER', pageItem, type);
|
|
} else {
|
|
console.warn('Alias-Datenpunkt: ' + id + '.DIMMER could not be read');
|
|
}
|
|
|
|
if (val === true) {
|
|
iconColor = GetIconColor(pageItem, 100 - brightness, true);
|
|
switchVal = '1';
|
|
} else {
|
|
iconColor = GetIconColor(pageItem, false, true);
|
|
}
|
|
|
|
var colorMode = 'disable';
|
|
|
|
var colorTemp = 0;
|
|
if (existsState(id + '.TEMPERATURE')) {
|
|
if (getState(id + '.TEMPERATURE').val != null) {
|
|
if (pageItem.minValueColorTemp !== undefined && pageItem.minValueColorTemp !== undefined) {
|
|
colorTemp = Math.trunc(scale(getState(id + '.TEMPERATURE').val, pageItem.minValueColorTemp, pageItem.maxValueColorTemp, 0, 100));
|
|
} else {
|
|
colorTemp = 100 - getState(id + '.TEMPERATURE').val;
|
|
}
|
|
//RegisterDetailEntityWatcher(id + '.TEMPERATURE', pageItem, type);
|
|
}
|
|
} else {
|
|
console.warn('Alias-Datenpunkt: ' + id + '.TEMPERATURE could not be read');
|
|
}
|
|
|
|
out_msgs.push({
|
|
payload: 'entityUpdateDetail' + '~' //entityUpdateDetail
|
|
+ id + '~'
|
|
+ icon + '~' //iconId
|
|
+ iconColor + '~' //iconColor
|
|
+ switchVal + '~' //buttonState
|
|
+ brightness + '~' //sliderBrightnessPos
|
|
+ colorTemp + '~' //sliderColorTempPos
|
|
+ colorMode + '~' //colorMode (if hue-alias without hue-datapoint, then disable)
|
|
+ 'Color' + '~' //Color-Bezeichnung
|
|
+ findLocale('lights', 'Temperature') + '~' //Temperature-Bezeichnung
|
|
+ findLocale('lights', '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);
|
|
} else if (existsState(id + '.SET')) {
|
|
val = getState(id + '.SET').val;
|
|
RegisterDetailEntityWatcher(id + '.SET', pageItem, type);
|
|
}
|
|
var tilt_position: any = 'disabled'
|
|
if (existsState(id + '.TILT_ACTUAL')) {
|
|
tilt_position = getState(id + '.TILT_ACTUAL').val;
|
|
RegisterDetailEntityWatcher(id + '.TILT_ACTUAL', pageItem, type);
|
|
} else if (existsState(id + '.TILT_SET')) {
|
|
tilt_position = getState(id + '.TILT_SET').val;
|
|
RegisterDetailEntityWatcher(id + '.TILT_SET', pageItem, type);
|
|
}
|
|
|
|
let textSecondRow = '';
|
|
let icon_id = icon;
|
|
let icon_up = Icons.GetIcon('arrow-up');
|
|
let icon_stop = Icons.GetIcon('stop');
|
|
let icon_down = Icons.GetIcon('arrow-down');
|
|
let icon_up_status = getState(id + '.ACTUAL').val != 100 ? 'enable' : 'disable';
|
|
let icon_stop_status = 'enable';
|
|
let icon_down_status = getState(id + '.ACTUAL').val != 0 ? 'enable' : 'disable';
|
|
let textTilt = '';
|
|
let iconTiltLeft = '';
|
|
let iconTiltStop = '';
|
|
let iconTiltRight = '';
|
|
let iconTiltLeftStatus = 'disable';
|
|
let iconTiltStopStatus = 'disable';
|
|
let iconTiltRightStatus = 'disable';
|
|
let tilt_pos = 'disable';
|
|
|
|
if (existsState(id + '.TILT_SET')) {
|
|
textTilt = findLocale('blinds', 'Tilt');
|
|
iconTiltLeft = Icons.GetIcon('arrow-top-right');
|
|
iconTiltStop = Icons.GetIcon('stop');
|
|
iconTiltRight = Icons.GetIcon('arrow-bottom-left');
|
|
iconTiltLeftStatus = getState(id + '.TILT_ACTUAL').val != 100 ? 'enable' : 'disable';
|
|
iconTiltStopStatus = 'enable';
|
|
iconTiltRightStatus = getState(id + '.TILT_ACTUAL').val != 0 ? 'enable' : 'disable';
|
|
tilt_pos = tilt_position;
|
|
}
|
|
|
|
if (pageItem.secondRow != undefined) {
|
|
textSecondRow = pageItem.secondRow;
|
|
}
|
|
|
|
out_msgs.push({
|
|
payload: 'entityUpdateDetail' + '~' //entityUpdateDetail
|
|
+ id + '~' //entity_id
|
|
+ val + '~' //Shutterposition
|
|
+ textSecondRow + '~' //pos_status 2.line
|
|
+ findLocale('blinds', 'Position') + '~' //pos_translation
|
|
+ icon_id + '~' //{icon_id}~
|
|
+ icon_up + '~' //{icon_up}~
|
|
+ icon_stop + '~' //{icon_stop}~
|
|
+ icon_down + '~' //{icon_down}~
|
|
+ icon_up_status + '~' //{icon_up_status}~
|
|
+ icon_stop_status + '~' //{icon_stop_status}~
|
|
+ icon_down_status + '~' //{icon_down_status}~
|
|
+ textTilt + '~' //{textTilt}~
|
|
+ iconTiltLeft + '~' //{iconTiltLeft}~
|
|
+ iconTiltStop + '~' //{iconTiltStop}~
|
|
+ iconTiltRight + '~' //{iconTiltRight}~
|
|
+ iconTiltLeftStatus + '~' //{iconTiltLeftStatus}~
|
|
+ iconTiltStopStatus + '~' //{iconTiltStopStatus}~
|
|
+ iconTiltRightStatus + '~' //{iconTiltRightStatus}~
|
|
+ tilt_pos //{tilt_pos}")
|
|
});
|
|
}
|
|
}
|
|
|
|
return out_msgs;
|
|
|
|
} catch (err) {
|
|
console.log('function GenerateDetailPage: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function scale(number: number, inMin: number, inMax: number, outMin: number, outMax: number): number {
|
|
try {
|
|
return (outMax + outMin) - ((number - inMin) * (outMax - outMin) / (inMax - inMin) + outMin);
|
|
} catch (err) {
|
|
console.log('function scale: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function UnsubscribeWatcher(): void {
|
|
try {
|
|
for (const [key, value] of Object.entries(subscriptions)) {
|
|
unsubscribe(value);
|
|
delete subscriptions[key];
|
|
}
|
|
} catch (err) {
|
|
console.log('function UnsubscribeWatcher: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function HandleScreensaver(): void {
|
|
SendToPanel({ payload: 'pageType~screensaver' });
|
|
UnsubscribeWatcher();
|
|
HandleScreensaverUpdate();
|
|
HandleScreensaverColors();
|
|
}
|
|
|
|
function HandleScreensaverUpdate(): void {
|
|
try {
|
|
if (screensaverEnabled && config.weatherEntity != null && existsObject(config.weatherEntity)) {
|
|
var icon = getState(config.weatherEntity + '.ICON').val;
|
|
|
|
let temperature =
|
|
existsState(config.weatherEntity + '.ACTUAL') ? getState(config.weatherEntity + '.ACTUAL').val :
|
|
existsState(config.weatherEntity + '.TEMP') ? getState(config.weatherEntity + '.TEMP').val : 'null';
|
|
|
|
if (config.alternativeScreensaverLayout) {
|
|
temperature = parseInt(Math.round(temperature).toFixed());
|
|
}
|
|
|
|
let payloadString =
|
|
'weatherUpdate~' + Icons.GetIcon(GetAccuWeatherIcon(parseInt(icon))) + '~'
|
|
+ temperature + ' ' + config.temperatureUnit + '~';
|
|
|
|
vwIconColor[0] = GetAccuWeatherIconColor(parseInt(icon));
|
|
if (Debug) console.log(GetAccuWeatherIconColor(parseInt(icon)));
|
|
|
|
if (weatherForecast) {
|
|
// Accu-Weather Forecast Tag 2 - Tag 5 -- Wenn weatherForecast = true
|
|
for (let i = 2; i < 6; i++) {
|
|
let TempMax = getState('accuweather.0.Summary.TempMax_d' + i).val;
|
|
let DayOfWeek = getState('accuweather.0.Summary.DayOfWeek_d' + i).val;
|
|
let WeatherIcon = GetAccuWeatherIcon(getState('accuweather.0.Summary.WeatherIcon_d' + i).val);
|
|
vwIconColor[i-1] = GetAccuWeatherIconColor(getState('accuweather.0.Summary.WeatherIcon_d' + i).val);
|
|
if (Debug) console.log(vwIconColor[i-1]);
|
|
payloadString += DayOfWeek + '~' + Icons.GetIcon(WeatherIcon) + '~' + TempMax + ' ' + config.temperatureUnit + '~';
|
|
}
|
|
} else {
|
|
payloadString += GetScreenSaverEntityString(config.firstScreensaverEntity);
|
|
payloadString += GetScreenSaverEntityString(config.secondScreensaverEntity);
|
|
payloadString += GetScreenSaverEntityString(config.thirdScreensaverEntity);
|
|
payloadString += GetScreenSaverEntityString(config.fourthScreensaverEntity);
|
|
|
|
const colorScale0: RGB = { red: 99, green: 190, blue: 123 };
|
|
const colorScale1: RGB = { red: 129, green: 199, blue: 126 };
|
|
const colorScale2: RGB = { red: 161, green: 208, blue: 127 };
|
|
const colorScale3: RGB = { red: 129, green: 217, blue: 126 };
|
|
const colorScale4: RGB = { red: 222, green: 226, blue: 131 };
|
|
const colorScale5: RGB = { red: 254, green: 235, blue: 132 };
|
|
const colorScale6: RGB = { red: 255, green: 210, blue: 129 };
|
|
const colorScale7: RGB = { red: 251, green: 185, blue: 124 };
|
|
const colorScale8: RGB = { red: 251, green: 158, blue: 117 };
|
|
const colorScale9: RGB = { red: 248, green: 131, blue: 111 };
|
|
const colorScale10: RGB = { red: 248, green: 105, blue: 107 };
|
|
|
|
if (config.firstScreensaverEntity.ScreensaverEntityIconColor != undefined) {
|
|
if (typeof getState(config.firstScreensaverEntity.ScreensaverEntity).val == 'boolean') {
|
|
vwIconColor[1] = (getState(config.firstScreensaverEntity.ScreensaverEntity).val == true) ? rgb_dec565(colorScale10) : rgb_dec565(colorScale0);
|
|
} else if (typeof config.firstScreensaverEntity.ScreensaverEntityIconColor == 'object') {
|
|
let iconvalmin = (config.firstScreensaverEntity.ScreensaverEntityIconColor.val_min != undefined) ? config.firstScreensaverEntity.ScreensaverEntityIconColor.val_min : 0 ;
|
|
let iconvalmax = (config.firstScreensaverEntity.ScreensaverEntityIconColor.val_max != undefined) ? config.firstScreensaverEntity.ScreensaverEntityIconColor.val_max : 100 ;
|
|
let iconvalbest = (config.firstScreensaverEntity.ScreensaverEntityIconColor.val_best != undefined) ? config.firstScreensaverEntity.ScreensaverEntityIconColor.val_best : iconvalmin ;
|
|
let valueScale = getState(config.firstScreensaverEntity.ScreensaverEntity).val;
|
|
|
|
if (iconvalmin == 0 && iconvalmax == 1) {
|
|
vwIconColor[1] = (getState(config.firstScreensaverEntity.ScreensaverEntity).val == 1) ? rgb_dec565(colorScale0) : rgb_dec565(colorScale10);
|
|
} else {
|
|
if (iconvalbest == iconvalmin) {
|
|
valueScale = scale(valueScale,iconvalmin, iconvalmax, 10, 0)
|
|
} else {
|
|
if (valueScale < iconvalbest) {
|
|
valueScale = scale(valueScale,iconvalmin, iconvalbest, 0, 10)
|
|
} else if (valueScale > iconvalbest || iconvalbest != iconvalmin) {
|
|
valueScale = scale(valueScale,iconvalbest, iconvalmax, 10, 0)
|
|
} else {
|
|
valueScale = scale(valueScale,iconvalmin, iconvalmax, 10, 0)
|
|
}
|
|
}
|
|
let valueScaletemp = (Math.round(valueScale)).toFixed();
|
|
if (Debug) console.log(valueScaletemp);
|
|
switch (valueScaletemp) {
|
|
case '0':
|
|
vwIconColor[1] = rgb_dec565(colorScale0);
|
|
break;
|
|
case '1':
|
|
vwIconColor[1] = rgb_dec565(colorScale1);
|
|
break;
|
|
case '2':
|
|
vwIconColor[1] = rgb_dec565(colorScale2);
|
|
break;
|
|
case '3':
|
|
vwIconColor[1] = rgb_dec565(colorScale3);
|
|
break;
|
|
case '4':
|
|
vwIconColor[1] = rgb_dec565(colorScale4);
|
|
break;
|
|
case '5':
|
|
vwIconColor[1] = rgb_dec565(colorScale5);
|
|
break;
|
|
case '6':
|
|
vwIconColor[1] = rgb_dec565(colorScale6);
|
|
break;
|
|
case '7':
|
|
vwIconColor[1] = rgb_dec565(colorScale7);
|
|
break;
|
|
case '8':
|
|
vwIconColor[1] = rgb_dec565(colorScale8);
|
|
break;
|
|
case '9':
|
|
vwIconColor[1] = rgb_dec565(colorScale9);
|
|
break;
|
|
case '10':
|
|
vwIconColor[1] = rgb_dec565(colorScale10);
|
|
break;
|
|
}
|
|
}
|
|
if (config.firstScreensaverEntity.ScreensaverEntityIconColor.val_min == undefined) {
|
|
vwIconColor[1] = rgb_dec565(config.firstScreensaverEntity.ScreensaverEntityIconColor);
|
|
}
|
|
} else {
|
|
vwIconColor[1] = rgb_dec565(sctF1Icon);
|
|
}
|
|
} else {
|
|
vwIconColor[1] = rgb_dec565(sctF1Icon);
|
|
}
|
|
|
|
if (config.secondScreensaverEntity.ScreensaverEntityIconColor != undefined) {
|
|
if (typeof getState(config.secondScreensaverEntity.ScreensaverEntity).val == 'boolean') {
|
|
vwIconColor[2] = (getState(config.secondScreensaverEntity.ScreensaverEntity).val == true) ? rgb_dec565(colorScale10) : rgb_dec565(colorScale0);
|
|
} else if (typeof config.secondScreensaverEntity.ScreensaverEntityIconColor == 'object') {
|
|
|
|
let iconvalmin = (config.secondScreensaverEntity.ScreensaverEntityIconColor.val_min != undefined) ? config.secondScreensaverEntity.ScreensaverEntityIconColor.val_min : 0 ;
|
|
let iconvalmax = (config.secondScreensaverEntity.ScreensaverEntityIconColor.val_max != undefined) ? config.secondScreensaverEntity.ScreensaverEntityIconColor.val_max : 100 ;
|
|
let iconvalbest = (config.secondScreensaverEntity.ScreensaverEntityIconColor.val_best != undefined) ? config.secondScreensaverEntity.ScreensaverEntityIconColor.val_best : iconvalmin ;
|
|
let valueScale = getState(config.secondScreensaverEntity.ScreensaverEntity).val;
|
|
|
|
if (iconvalmin == 0 && iconvalmax == 1) {
|
|
vwIconColor[2] = (getState(config.secondScreensaverEntity.ScreensaverEntity).val == 1) ? rgb_dec565(colorScale0) : rgb_dec565(colorScale10);
|
|
} else {
|
|
if (iconvalbest == iconvalmin) {
|
|
valueScale = scale(valueScale,iconvalmin, iconvalmax, 10, 0)
|
|
} else {
|
|
if (valueScale < iconvalbest) {
|
|
valueScale = scale(valueScale,iconvalmin, iconvalbest, 0, 10)
|
|
} else if (valueScale > iconvalbest || iconvalbest != iconvalmin) {
|
|
valueScale = scale(valueScale,iconvalbest, iconvalmax, 10, 0)
|
|
} else {
|
|
valueScale = scale(valueScale,iconvalmin, iconvalmax, 10, 0)
|
|
}
|
|
}
|
|
let valueScaletemp = (Math.round(valueScale)).toFixed();
|
|
if (Debug) console.log(valueScaletemp);
|
|
switch (valueScaletemp) {
|
|
case '0':
|
|
vwIconColor[2] = rgb_dec565(colorScale0);
|
|
break;
|
|
case '1':
|
|
vwIconColor[2] = rgb_dec565(colorScale1);
|
|
break;
|
|
case '2':
|
|
vwIconColor[2] = rgb_dec565(colorScale2);
|
|
break;
|
|
case '3':
|
|
vwIconColor[2] = rgb_dec565(colorScale3);
|
|
break;
|
|
case '4':
|
|
vwIconColor[2] = rgb_dec565(colorScale4);
|
|
break;
|
|
case '5':
|
|
vwIconColor[2] = rgb_dec565(colorScale5);
|
|
break;
|
|
case '6':
|
|
vwIconColor[2] = rgb_dec565(colorScale6);
|
|
break;
|
|
case '7':
|
|
vwIconColor[2] = rgb_dec565(colorScale7);
|
|
break;
|
|
case '8':
|
|
vwIconColor[2] = rgb_dec565(colorScale8);
|
|
break;
|
|
case '9':
|
|
vwIconColor[2] = rgb_dec565(colorScale9);
|
|
break;
|
|
case '10':
|
|
vwIconColor[2] = rgb_dec565(colorScale10);
|
|
break;
|
|
}
|
|
}
|
|
if (config.secondScreensaverEntity.ScreensaverEntityIconColor.val_min == undefined) {
|
|
vwIconColor[2] = rgb_dec565(config.secondScreensaverEntity.ScreensaverEntityIconColor);
|
|
}
|
|
} else {
|
|
vwIconColor[2] = rgb_dec565(sctF2Icon);
|
|
}
|
|
} else {
|
|
vwIconColor[2] = rgb_dec565(sctF2Icon);
|
|
}
|
|
|
|
if (config.thirdScreensaverEntity.ScreensaverEntityIconColor != undefined) {
|
|
if (typeof getState(config.thirdScreensaverEntity.ScreensaverEntity).val == 'boolean') {
|
|
vwIconColor[3] = (getState(config.thirdScreensaverEntity.ScreensaverEntity).val == true) ? rgb_dec565(colorScale10) : rgb_dec565(colorScale0);
|
|
} else if (typeof config.thirdScreensaverEntity.ScreensaverEntityIconColor == 'object') {
|
|
|
|
let iconvalmin = (config.thirdScreensaverEntity.ScreensaverEntityIconColor.val_min != undefined) ? config.thirdScreensaverEntity.ScreensaverEntityIconColor.val_min : 0 ;
|
|
let iconvalmax = (config.thirdScreensaverEntity.ScreensaverEntityIconColor.val_max != undefined) ? config.thirdScreensaverEntity.ScreensaverEntityIconColor.val_max : 100 ;
|
|
let iconvalbest = (config.thirdScreensaverEntity.ScreensaverEntityIconColor.val_best != undefined) ? config.thirdScreensaverEntity.ScreensaverEntityIconColor.val_best : iconvalmin ;
|
|
let valueScale = getState(config.thirdScreensaverEntity.ScreensaverEntity).val;
|
|
|
|
if (iconvalmin == 0 && iconvalmax == 1) {
|
|
vwIconColor[3] = (getState(config.thirdScreensaverEntity.ScreensaverEntity).val == 1) ? rgb_dec565(colorScale0) : rgb_dec565(colorScale10);
|
|
} else {
|
|
if (iconvalbest == iconvalmin) {
|
|
valueScale = scale(valueScale,iconvalmin, iconvalmax, 10, 0)
|
|
} else {
|
|
if (valueScale < iconvalbest) {
|
|
valueScale = scale(valueScale,iconvalmin, iconvalbest, 0, 10)
|
|
} else if (valueScale > iconvalbest || iconvalbest != iconvalmin) {
|
|
valueScale = scale(valueScale,iconvalbest, iconvalmax, 10, 0)
|
|
} else {
|
|
valueScale = scale(valueScale,iconvalmin, iconvalmax, 10, 0)
|
|
}
|
|
}
|
|
let valueScaletemp = (Math.round(valueScale)).toFixed();
|
|
if (Debug) console.log(valueScaletemp);
|
|
switch (valueScaletemp) {
|
|
case '0':
|
|
vwIconColor[3] = rgb_dec565(colorScale0);
|
|
break;
|
|
case '1':
|
|
vwIconColor[3] = rgb_dec565(colorScale1);
|
|
break;
|
|
case '2':
|
|
vwIconColor[3] = rgb_dec565(colorScale2);
|
|
break;
|
|
case '3':
|
|
vwIconColor[3] = rgb_dec565(colorScale3);
|
|
break;
|
|
case '4':
|
|
vwIconColor[3] = rgb_dec565(colorScale4);
|
|
break;
|
|
case '5':
|
|
vwIconColor[3] = rgb_dec565(colorScale5);
|
|
break;
|
|
case '6':
|
|
vwIconColor[3] = rgb_dec565(colorScale6);
|
|
break;
|
|
case '7':
|
|
vwIconColor[3] = rgb_dec565(colorScale7);
|
|
break;
|
|
case '8':
|
|
vwIconColor[3] = rgb_dec565(colorScale8);
|
|
break;
|
|
case '9':
|
|
vwIconColor[3] = rgb_dec565(colorScale9);
|
|
break;
|
|
case '10':
|
|
vwIconColor[3] = rgb_dec565(colorScale10);
|
|
break;
|
|
}
|
|
}
|
|
if (config.thirdScreensaverEntity.ScreensaverEntityIconColor.val_min == undefined) {
|
|
vwIconColor[3] = rgb_dec565(config.thirdScreensaverEntity.ScreensaverEntityIconColor);
|
|
}
|
|
} else {
|
|
vwIconColor[3] = rgb_dec565(sctF2Icon);
|
|
}
|
|
} else {
|
|
vwIconColor[3] = rgb_dec565(sctF2Icon);
|
|
}
|
|
|
|
if (config.fourthScreensaverEntity.ScreensaverEntityIconColor != undefined) {
|
|
if (typeof getState(config.fourthScreensaverEntity.ScreensaverEntity).val == 'boolean') {
|
|
vwIconColor[4] = (getState(config.fourthScreensaverEntity.ScreensaverEntity).val == true) ? rgb_dec565(colorScale10) : rgb_dec565(colorScale0);
|
|
} else if (typeof config.fourthScreensaverEntity.ScreensaverEntityIconColor == 'object') {
|
|
|
|
let iconvalmin = (config.fourthScreensaverEntity.ScreensaverEntityIconColor.val_min != undefined) ? config.fourthScreensaverEntity.ScreensaverEntityIconColor.val_min : 0 ;
|
|
let iconvalmax = (config.fourthScreensaverEntity.ScreensaverEntityIconColor.val_max != undefined) ? config.fourthScreensaverEntity.ScreensaverEntityIconColor.val_max : 100 ;
|
|
let iconvalbest = (config.fourthScreensaverEntity.ScreensaverEntityIconColor.val_best != undefined) ? config.fourthScreensaverEntity.ScreensaverEntityIconColor.val_best : iconvalmin ;
|
|
let valueScale = getState(config.fourthScreensaverEntity.ScreensaverEntity).val;
|
|
|
|
if (iconvalmin == 0 && iconvalmax == 1) {
|
|
vwIconColor[4] = (getState(config.fourthScreensaverEntity.ScreensaverEntity).val == 1) ? rgb_dec565(colorScale0) : rgb_dec565(colorScale10);
|
|
} else {
|
|
if (iconvalbest == iconvalmin) {
|
|
valueScale = scale(valueScale,iconvalmin, iconvalmax, 10, 0)
|
|
} else {
|
|
if (valueScale < iconvalbest) {
|
|
valueScale = scale(valueScale,iconvalmin, iconvalbest, 0, 10)
|
|
} else if (valueScale > iconvalbest || iconvalbest != iconvalmin) {
|
|
valueScale = scale(valueScale,iconvalbest, iconvalmax, 10, 0)
|
|
} else {
|
|
valueScale = scale(valueScale,iconvalmin, iconvalmax, 10, 0)
|
|
}
|
|
}
|
|
let valueScaletemp = (Math.round(valueScale)).toFixed();
|
|
if (Debug) console.log(valueScaletemp);
|
|
switch (valueScaletemp) {
|
|
case '0':
|
|
vwIconColor[4] = rgb_dec565(colorScale0);
|
|
break;
|
|
case '1':
|
|
vwIconColor[4] = rgb_dec565(colorScale1);
|
|
break;
|
|
case '2':
|
|
vwIconColor[4] = rgb_dec565(colorScale2);
|
|
break;
|
|
case '3':
|
|
vwIconColor[4] = rgb_dec565(colorScale3);
|
|
break;
|
|
case '4':
|
|
vwIconColor[4] = rgb_dec565(colorScale4);
|
|
break;
|
|
case '5':
|
|
vwIconColor[4] = rgb_dec565(colorScale5);
|
|
break;
|
|
case '6':
|
|
vwIconColor[4] = rgb_dec565(colorScale6);
|
|
break;
|
|
case '7':
|
|
vwIconColor[4] = rgb_dec565(colorScale7);
|
|
break;
|
|
case '8':
|
|
vwIconColor[4] = rgb_dec565(colorScale8);
|
|
break;
|
|
case '9':
|
|
vwIconColor[4] = rgb_dec565(colorScale9);
|
|
break;
|
|
case '10':
|
|
vwIconColor[4] = rgb_dec565(colorScale10);
|
|
break;
|
|
}
|
|
}
|
|
if (config.fourthScreensaverEntity.ScreensaverEntityIconColor.val_min == undefined) {
|
|
vwIconColor[4] = rgb_dec565(config.fourthScreensaverEntity.ScreensaverEntityIconColor);
|
|
}
|
|
} else {
|
|
vwIconColor[4] = rgb_dec565(sctF2Icon);
|
|
}
|
|
} else {
|
|
vwIconColor[4] = rgb_dec565(sctF2Icon);
|
|
}
|
|
}
|
|
|
|
//AltLayout
|
|
if (config.alternativeScreensaverLayout) {
|
|
payloadString += parseInt(getState(config.fourthScreensaverEntity.ScreensaverEntity).val) + '~';
|
|
payloadString += config.fourthScreensaverEntity.ScreensaverEntityUnitText + '~'
|
|
} else {
|
|
payloadString += '~~'
|
|
}
|
|
|
|
let hwBtn1Col: any = config.mrIcon1ScreensaverEntity.ScreensaverEntityOffColor;
|
|
if (config.mrIcon1ScreensaverEntity.ScreensaverEntity != null) {
|
|
if (typeof (getState(config.mrIcon1ScreensaverEntity.ScreensaverEntity).val) == 'string') {
|
|
let hwBtn1: string = getState(config.mrIcon1ScreensaverEntity.ScreensaverEntity).val;
|
|
if (hwBtn1 == 'ON') {
|
|
hwBtn1Col = config.mrIcon1ScreensaverEntity.ScreensaverEntityOnColor;
|
|
}
|
|
payloadString += Icons.GetIcon(config.mrIcon1ScreensaverEntity.ScreensaverEntityIcon) + '~' + rgb_dec565(hwBtn1Col) + '~';
|
|
} else if (typeof (getState(config.mrIcon1ScreensaverEntity.ScreensaverEntity).val) == 'boolean') {
|
|
let hwBtn1: boolean = getState(config.mrIcon1ScreensaverEntity.ScreensaverEntity).val;
|
|
if (hwBtn1) {
|
|
hwBtn1Col = config.mrIcon1ScreensaverEntity.ScreensaverEntityOnColor;
|
|
}
|
|
payloadString += Icons.GetIcon(config.mrIcon1ScreensaverEntity.ScreensaverEntityIcon) + '~' + rgb_dec565(hwBtn1Col) + '~';
|
|
}
|
|
} else {
|
|
hwBtn1Col = Black;
|
|
payloadString += '~~';
|
|
}
|
|
|
|
let hwBtn2Col: any = config.mrIcon2ScreensaverEntity.ScreensaverEntityOffColor;
|
|
if (config.mrIcon2ScreensaverEntity.ScreensaverEntity != null) {
|
|
if (typeof (getState(config.mrIcon2ScreensaverEntity.ScreensaverEntity).val) == 'string') {
|
|
let hwBtn2: string = getState(config.mrIcon2ScreensaverEntity.ScreensaverEntity).val;
|
|
if (hwBtn2 == 'ON') {
|
|
hwBtn2Col = config.mrIcon2ScreensaverEntity.ScreensaverEntityOnColor;
|
|
}
|
|
payloadString += Icons.GetIcon(config.mrIcon2ScreensaverEntity.ScreensaverEntityIcon) + '~' + rgb_dec565(hwBtn2Col) + '~';
|
|
} else if (typeof (getState(config.mrIcon2ScreensaverEntity.ScreensaverEntity).val) == 'boolean') {
|
|
let hwBtn2: boolean = getState(config.mrIcon2ScreensaverEntity.ScreensaverEntity).val;
|
|
if (hwBtn2) {
|
|
hwBtn2Col = config.mrIcon2ScreensaverEntity.ScreensaverEntityOnColor;
|
|
}
|
|
payloadString += Icons.GetIcon(config.mrIcon2ScreensaverEntity.ScreensaverEntityIcon) + '~' + rgb_dec565(hwBtn2Col) + '~';
|
|
}
|
|
} else {
|
|
hwBtn2Col = Black;
|
|
payloadString += '~~';
|
|
}
|
|
HandleScreensaverColors();
|
|
|
|
SendToPanel(<Payload>{ payload: payloadString });
|
|
|
|
}
|
|
} catch (err) {
|
|
console.log('HandleScreensaverUpdate: ' + err.message);
|
|
}
|
|
}
|
|
|
|
function HandleScreensaverColors(): void {
|
|
try {
|
|
let vwIcon = [];
|
|
if (config.autoWeatherColorScreensaverLayout) {
|
|
vwIcon[0] = vwIconColor[0];
|
|
vwIcon[1] = vwIconColor[1];
|
|
vwIcon[2] = vwIconColor[2];
|
|
vwIcon[3] = vwIconColor[3];
|
|
vwIcon[4] = vwIconColor[4];
|
|
} else {
|
|
if (weatherForecast) {
|
|
vwIcon[0] = rgb_dec565(sctMainIcon);
|
|
vwIcon[1] = rgb_dec565(sctF1Icon);
|
|
vwIcon[2] = rgb_dec565(sctF2Icon);
|
|
vwIcon[3] = rgb_dec565(sctF3Icon);
|
|
vwIcon[4] = rgb_dec565(sctF4Icon);
|
|
} else {
|
|
vwIcon[0] = rgb_dec565(sctMainIcon);
|
|
vwIcon[1] = vwIconColor[1];
|
|
vwIcon[2] = vwIconColor[2];
|
|
vwIcon[3] = vwIconColor[3];
|
|
vwIcon[4] = vwIconColor[4];
|
|
}
|
|
}
|
|
|
|
let payloadString = 'color' + '~' +
|
|
rgb_dec565(scbackground) + '~' + //background
|
|
rgb_dec565(sctime) + '~' + //time
|
|
rgb_dec565(sctimeAMPM) + '~' + //timeAMPM~
|
|
rgb_dec565(scdate) + '~' + //date~
|
|
vwIcon[0] + '~' + //tMainIcon~ rgb_dec565(sctMainIcon)
|
|
rgb_dec565(sctMainText) + '~' + //tMainText~
|
|
rgb_dec565(sctForecast1) + '~' + //tForecast1~
|
|
rgb_dec565(sctForecast2) + '~' + //tForecast2~
|
|
rgb_dec565(sctForecast3) + '~' + //tForecast3~
|
|
rgb_dec565(sctForecast4) + '~' + //tForecast4~
|
|
vwIcon[1] + '~' + //tF1Icon~ rgb_dec565(sctF1Icon)
|
|
vwIcon[2] + '~' + //tF2Icon~ rgb_dec565(sctF2Icon)
|
|
vwIcon[3] + '~' + //tF3Icon~ rgb_dec565(sctF3Icon)
|
|
vwIcon[4] + '~' + //tF4Icon~ rgb_dec565(sctF4Icon)
|
|
rgb_dec565(sctForecast1Val) + '~' + //tForecast1Val~
|
|
rgb_dec565(sctForecast2Val) + '~' + //tForecast2Val~
|
|
rgb_dec565(sctForecast3Val) + '~' + //tForecast3Val~
|
|
rgb_dec565(sctForecast4Val) + '~' + //tForecast4Val~
|
|
rgb_dec565(scbar) + '~' + //bar~
|
|
rgb_dec565(sctMainIconAlt) + '~' + //tMainIconAlt
|
|
rgb_dec565(sctMainTextAlt) + '~' + //tMainTextAlt
|
|
rgb_dec565(sctTimeAdd);
|
|
//true;
|
|
|
|
SendToPanel(<Payload>{ payload: payloadString });
|
|
} catch (err) {
|
|
console.warn('HandleScreensaverColors: '+ err.message);
|
|
}
|
|
}
|
|
|
|
function GetScreenSaverEntityString(configElement: ScreenSaverElement | null): string {
|
|
try {
|
|
if (configElement != null && configElement.ScreensaverEntity != null && existsState(configElement.ScreensaverEntity)) {
|
|
let u1 = getState(configElement.ScreensaverEntity).val;
|
|
|
|
return configElement.ScreensaverEntityText + '~' + Icons.GetIcon(configElement.ScreensaverEntityIcon) + '~' + u1 + ' ' + configElement.ScreensaverEntityUnitText + '~';
|
|
}
|
|
else {
|
|
return '~~~';
|
|
}
|
|
} catch (err) {
|
|
console.warn('GetScreenSaverEntityString: '+ err.message);
|
|
}
|
|
}
|
|
|
|
function GetAccuWeatherIcon(icon: number): string {
|
|
try {
|
|
switch (icon) {
|
|
case 24: // Ice
|
|
case 30: // Hot
|
|
case 31: // Cold
|
|
return 'window-open'; // exceptional
|
|
|
|
case 7: // Cloudy
|
|
case 8: // Dreary (Overcast)
|
|
case 38: // Mostly Cloudy
|
|
return 'weather-cloudy'; // cloudy
|
|
|
|
case 11: // fog
|
|
return 'weather-fog'; // fog
|
|
|
|
case 25: // Sleet
|
|
return 'weather-hail'; // Hail
|
|
|
|
case 15: // T-Storms
|
|
return 'weather-lightning'; // lightning
|
|
|
|
case 16: // Mostly Cloudy w/ T-Storms
|
|
case 17: // Partly Sunny w/ T-Storms
|
|
case 41: // Partly Cloudy w/ T-Storms
|
|
case 42: // Mostly Cloudy w/ T-Storms
|
|
return 'weather-lightning-rainy'; // lightning-rainy
|
|
|
|
case 33: // Clear
|
|
case 34: // Mostly Clear
|
|
case 37: // Hazy Moonlight
|
|
return 'weather-night';
|
|
|
|
case 3: // Partly Sunny
|
|
case 4: // Intermittent Clouds
|
|
case 6: // Mostly Cloudy
|
|
case 35: // Partly Cloudy
|
|
case 36: // Intermittent Clouds
|
|
return 'weather-partly-cloudy'; // partlycloudy
|
|
|
|
case 18: // pouring
|
|
return 'weather-pouring'; // pouring
|
|
|
|
case 12: // Showers
|
|
case 13: // Mostly Cloudy w/ Showers
|
|
case 14: // Partly Sunny w/ Showers
|
|
case 26: // Freezing Rain
|
|
case 39: // Partly Cloudy w/ Showers
|
|
case 40: // Mostly Cloudy w/ Showers
|
|
return 'weather-rainy'; // rainy
|
|
|
|
case 19: // Flurries
|
|
case 20: // Mostly Cloudy w/ Flurries
|
|
case 21: // Partly Sunny w/ Flurries
|
|
case 22: // Snow
|
|
case 23: // Mostly Cloudy w/ Snow
|
|
case 43: // Mostly Cloudy w/ Flurries
|
|
case 44: // Mostly Cloudy w/ Snow
|
|
return 'weather-snowy'; // snowy
|
|
|
|
case 29: // Rain and Snow
|
|
return 'weather-snowy-rainy'; // snowy-rainy
|
|
|
|
case 1: // Sunny
|
|
case 2: // Mostly Sunny
|
|
case 5: // Hazy Sunshine
|
|
return 'weather-sunny'; // sunny
|
|
|
|
case 32: // windy
|
|
return 'weather-windy'; // windy
|
|
|
|
default:
|
|
return 'alert-circle-outline';
|
|
}
|
|
} catch (err) {
|
|
console.warn('GetAccuWeatherIcon: '+ err.message);
|
|
}
|
|
}
|
|
|
|
function GetAccuWeatherIconColor(icon: number): number {
|
|
try{
|
|
switch (icon) {
|
|
case 24: // Ice
|
|
case 30: // Hot
|
|
case 31: // Cold
|
|
return rgb_dec565(swExceptional); // exceptional
|
|
|
|
case 7: // Cloudy
|
|
case 8: // Dreary (Overcast)
|
|
case 38: // Mostly Cloudy
|
|
return rgb_dec565(swCloudy); // cloudy
|
|
|
|
case 11: // fog
|
|
return rgb_dec565(swFog); // fog
|
|
|
|
case 25: // Sleet
|
|
return rgb_dec565(swHail); // Hail
|
|
|
|
case 15: // T-Storms
|
|
return rgb_dec565(swLightning); // lightning
|
|
|
|
case 16: // Mostly Cloudy w/ T-Storms
|
|
case 17: // Partly Sunny w/ T-Storms
|
|
case 41: // Partly Cloudy w/ T-Storms
|
|
case 42: // Mostly Cloudy w/ T-Storms
|
|
return rgb_dec565(swLightningRainy); // lightning-rainy
|
|
|
|
case 33: // Clear
|
|
case 34: // Mostly Clear
|
|
case 37: // Hazy Moonlight
|
|
return rgb_dec565(swClearNight);
|
|
|
|
case 3: // Partly Sunny
|
|
case 4: // Intermittent Clouds
|
|
case 6: // Mostly Cloudy
|
|
case 35: // Partly Cloudy
|
|
case 36: // Intermittent Clouds
|
|
return rgb_dec565(swPartlycloudy); // partlycloudy
|
|
|
|
case 18: // pouring
|
|
return rgb_dec565(swPouring); // pouring
|
|
|
|
case 12: // Showers
|
|
case 13: // Mostly Cloudy w/ Showers
|
|
case 14: // Partly Sunny w/ Showers
|
|
case 26: // Freezing Rain
|
|
case 39: // Partly Cloudy w/ Showers
|
|
case 40: // Mostly Cloudy w/ Showers
|
|
return rgb_dec565(swRainy); // rainy
|
|
|
|
case 19: // Flurries
|
|
case 20: // Mostly Cloudy w/ Flurries
|
|
case 21: // Partly Sunny w/ Flurries
|
|
case 22: // Snow
|
|
case 23: // Mostly Cloudy w/ Snow
|
|
case 43: // Mostly Cloudy w/ Flurries
|
|
case 44: // Mostly Cloudy w/ Snow
|
|
return rgb_dec565(swSnowy); // snowy
|
|
|
|
case 29: // Rain and Snow
|
|
return rgb_dec565(swSnowyRainy); // snowy-rainy
|
|
|
|
case 1: // Sunny
|
|
case 2: // Mostly Sunny
|
|
case 5: // Hazy Sunshine
|
|
return rgb_dec565(swSunny); // sunny
|
|
|
|
case 32: // windy
|
|
return rgb_dec565(swWindy); // windy
|
|
|
|
default:
|
|
return rgb_dec565(White);
|
|
}
|
|
} catch (err) {
|
|
console.warn('GetAccuWeatherIconColor: '+ err.message);
|
|
}
|
|
}
|
|
|
|
//------------------Begin Read Internal Sensor Data
|
|
on({ id: config.panelRecvTopic.substring(0, config.panelRecvTopic.length - 'RESULT'.length) + 'SENSOR' }, async (obj) => {
|
|
try {
|
|
const Tasmota_Sensor = JSON.parse(obj.state.val);
|
|
|
|
await createStateAsync(NSPanel_Path + 'Sensor.Time', <iobJS.StateCommon>{ type: 'string' });
|
|
await createStateAsync(NSPanel_Path + 'Sensor.TempUnit', <iobJS.StateCommon>{ type: 'string' });
|
|
await createStateAsync(NSPanel_Path + 'Sensor.ANALOG.Temperature', <iobJS.StateCommon>{ type: 'number', 'unit': '°C' });
|
|
await createStateAsync(NSPanel_Path + 'Sensor.ESP32.Temperature', <iobJS.StateCommon>{ type: 'number', 'unit': '°C' });
|
|
|
|
await setStateAsync(NSPanel_Path + 'Sensor.Time', <iobJS.State>{ val: Tasmota_Sensor.Time, ack: true });
|
|
await setStateAsync(NSPanel_Path + 'Sensor.TempUnit', <iobJS.State>{ val: '°' + Tasmota_Sensor.TempUnit, ack: true });
|
|
await setStateAsync(NSPanel_Path + 'Sensor.ANALOG.Temperature', <iobJS.State>{ val: parseFloat(Tasmota_Sensor.ANALOG.Temperature1), ack: true });
|
|
await setStateAsync(NSPanel_Path + 'Sensor.ESP32.Temperature', <iobJS.State>{ val: parseFloat(Tasmota_Sensor.ESP32.Temperature), ack: true });
|
|
} catch (err) {
|
|
console.warn('error with reading senor-data: '+ err.message);
|
|
}
|
|
});
|
|
//------------------End Read Internal Sensor Data
|
|
|
|
function GetBlendedColor(percentage: number): RGB {
|
|
if (percentage < 50) {
|
|
return Interpolate(config.defaultOffColor, config.defaultOnColor, percentage / 50.0);
|
|
}
|
|
|
|
return Interpolate(Red, White, (percentage - 50) / 50.0);
|
|
}
|
|
|
|
function Interpolate(color1: RGB, color2: RGB, fraction: number): RGB {
|
|
var r: number = InterpolateNum(color1.red, color2.red, fraction);
|
|
var g: number = InterpolateNum(color1.green, color2.green, fraction);
|
|
var b: number = InterpolateNum(color1.blue, color2.blue, fraction);
|
|
return <RGB>{ red: Math.round(r), green: Math.round(g), blue: Math.round(b) };
|
|
}
|
|
|
|
function InterpolateNum(d1: number, d2: number, fraction: number): number {
|
|
return d1 + (d2 - d1) * fraction;
|
|
}
|
|
|
|
function rgb_dec565(rgb: RGB): number {
|
|
//return ((Math.floor(rgb.red / 255 * 31) << 11) | (Math.floor(rgb.green / 255 * 63) << 5) | (Math.floor(rgb.blue / 255 * 31)));
|
|
return ((rgb.red >> 3) << 11) | ((rgb.green >> 2)) << 5 | ((rgb.blue) >> 3)
|
|
}
|
|
|
|
/* 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;
|
|
}
|
|
|
|
function ColorToHex(color) {
|
|
var hexadecimal = color.toString(16);
|
|
return hexadecimal.length == 1 ? '0' + hexadecimal : hexadecimal;
|
|
}
|
|
|
|
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;
|
|
let x = chroma * (1 - Math.abs((hue % 2) - 1));
|
|
let rgb = hue <= 1 ? [chroma, x, 0] :
|
|
hue <= 2 ? [x, chroma, 0] :
|
|
hue <= 3 ? [0, chroma, x] :
|
|
hue <= 4 ? [0, x, chroma] :
|
|
hue <= 5 ? [x, 0, chroma] :
|
|
[chroma, 0, x];
|
|
|
|
return rgb.map(v => (v + value - chroma) * 255);
|
|
}
|
|
|
|
function getHue(red: number, green: number, blue: number) {
|
|
|
|
var min = Math.min(Math.min(red, green), blue);
|
|
var max = Math.max(Math.max(red, green), blue);
|
|
|
|
if (min == max) {
|
|
return 0;
|
|
}
|
|
|
|
var hue = 0;
|
|
if (max == red) {
|
|
hue = (green - blue) / (max - min);
|
|
|
|
} else if (max == green) {
|
|
hue = 2 + (blue - red) / (max - min);
|
|
|
|
} else {
|
|
hue = 4 + (red - green) / (max - min);
|
|
}
|
|
|
|
hue = hue * 60;
|
|
if (hue < 0) hue = hue + 360;
|
|
|
|
return Math.round(hue);
|
|
}
|
|
|
|
function pos_to_color(x: number, y: number): RGB {
|
|
var r = 160 / 2;
|
|
var x = Math.round((x - r) / r * 100) / 100;
|
|
var y = Math.round((r - y) / r * 100) / 100;
|
|
|
|
r = Math.sqrt(x * x + y * y);
|
|
let sat = 0
|
|
if (r > 1) {
|
|
sat = 0;
|
|
} else {
|
|
sat = r;
|
|
}
|
|
|
|
var hsv = rad2deg(Math.atan2(y, x));
|
|
var rgb = hsv2rgb(hsv, sat, 1);
|
|
|
|
return <RGB>{ red: Math.round(rgb[0]), green: Math.round(rgb[1]), blue: Math.round(rgb[2]) };
|
|
}
|
|
|
|
function rgb_to_cie(red, green, blue)
|
|
{
|
|
//Apply a gamma correction to the RGB values, which makes the color more vivid and more the like the color displayed on the screen of your device
|
|
let vred = (red > 0.04045) ? Math.pow((red + 0.055) / (1.0 + 0.055), 2.4) : (red / 12.92);
|
|
let vgreen = (green > 0.04045) ? Math.pow((green + 0.055) / (1.0 + 0.055), 2.4) : (green / 12.92);
|
|
let vblue = (blue > 0.04045) ? Math.pow((blue + 0.055) / (1.0 + 0.055), 2.4) : (blue / 12.92);
|
|
|
|
//RGB values to XYZ using the Wide RGB D65 conversion formula
|
|
let X = vred * 0.664511 + vgreen * 0.154324 + vblue * 0.162028;
|
|
let Y = vred * 0.283881 + vgreen * 0.668433 + vblue * 0.047685;
|
|
let Z = vred * 0.000088 + vgreen * 0.072310 + vblue * 0.986039;
|
|
|
|
//Calculate the xy values from the XYZ values
|
|
let ciex = (X / (X + Y + Z)).toFixed(4);
|
|
let ciey = (Y / (X + Y + Z)).toFixed(4);
|
|
let cie = "[" + ciex + "," + ciey + "]"
|
|
|
|
return cie;
|
|
}
|
|
|
|
function spotifyGetDeviceID(vDeviceString) {
|
|
const availableDeviceIDs = getState("spotify-premium.0.devices.availableDeviceListIds").val;
|
|
const availableDeviceNames = getState("spotify-premium.0.devices.availableDeviceListString").val;
|
|
var arrayDeviceListIds = availableDeviceIDs.split(";");
|
|
var arrayDeviceListSting = availableDeviceNames.split(";");
|
|
var indexPos = arrayDeviceListSting.indexOf(vDeviceString);
|
|
var strDevID = arrayDeviceListIds[indexPos];
|
|
return strDevID;
|
|
}
|
|
|
|
type RGB = {
|
|
red: number,
|
|
green: number,
|
|
blue: number
|
|
};
|
|
|
|
type Payload = {
|
|
payload: string;
|
|
};
|
|
|
|
type Page = {
|
|
type: string,
|
|
heading: string,
|
|
items: PageItem[],
|
|
useColor: boolean,
|
|
subPage: boolean,
|
|
parent: Page,
|
|
};
|
|
|
|
interface PageEntities extends Page {
|
|
type: 'cardEntities',
|
|
items: PageItem[],
|
|
};
|
|
|
|
interface PageGrid extends Page {
|
|
type: 'cardGrid',
|
|
items: PageItem[],
|
|
};
|
|
|
|
interface PageThermo extends Page {
|
|
type: 'cardThermo',
|
|
items: PageItem[],
|
|
};
|
|
|
|
interface PageMedia extends Page {
|
|
type: 'cardMedia',
|
|
items: PageItem[],
|
|
};
|
|
|
|
interface PageAlarm extends Page {
|
|
type: 'cardAlarm',
|
|
items: PageItem[],
|
|
};
|
|
|
|
interface PageQR extends Page {
|
|
type: 'cardQR',
|
|
items: PageItem[],
|
|
};
|
|
|
|
interface PagePower extends Page {
|
|
type: 'cardPower',
|
|
items: PageItem[],
|
|
};
|
|
|
|
type PageItem = {
|
|
id: string,
|
|
icon: (string | undefined),
|
|
icon2: (string | undefined),
|
|
onColor: (RGB | undefined),
|
|
offColor: (RGB | undefined),
|
|
useColor: (boolean | undefined),
|
|
interpolateColor: (boolean | undefined),
|
|
minValueBrightness: (number | undefined),
|
|
maxValueBrightness: (number | undefined),
|
|
minValueColorTemp: (number | undefined),
|
|
maxValueColorTemp: (number | undefined),
|
|
minValue: (number | undefined),
|
|
maxValue: (number | undefined),
|
|
name: (string | undefined),
|
|
secondRow: (string | undefined),
|
|
buttonText: (string | undefined),
|
|
unit: (string | undefined),
|
|
navigate: (boolean | undefined),
|
|
colormode: (string | undefined),
|
|
adapterPlayerInstance: (string | undefined),
|
|
mediaDevice: (string | undefined),
|
|
targetPage: (string | undefined),
|
|
speakerList: (string[] | undefined),
|
|
hidePassword: (boolean | undefined)
|
|
}
|
|
|
|
type DimMode = {
|
|
dimmodeOn: (boolean | undefined),
|
|
brightnessDay: (number | undefined),
|
|
brightnessNight: (number | undefined),
|
|
timeDay: (string | undefined),
|
|
timeNight: (string | undefined)
|
|
}
|
|
|
|
type Config = {
|
|
panelRecvTopic: string,
|
|
panelSendTopic: string,
|
|
timeoutScreensaver: number,
|
|
dimmode: number,
|
|
active: number,
|
|
locale: string,
|
|
timeFormat: string,
|
|
dateFormat: string,
|
|
weatherEntity: string | null,
|
|
screenSaverDoubleClick: boolean,
|
|
temperatureUnit: string,
|
|
firstScreensaverEntity: ScreenSaverElement | null,
|
|
secondScreensaverEntity: ScreenSaverElement | null,
|
|
thirdScreensaverEntity: ScreenSaverElement | null,
|
|
fourthScreensaverEntity: ScreenSaverElement | null,
|
|
alternativeScreensaverLayout: boolean,
|
|
autoWeatherColorScreensaverLayout: boolean,
|
|
mrIcon1ScreensaverEntity: ScreenSaverMRElement | null,
|
|
mrIcon2ScreensaverEntity: ScreenSaverMRElement | null,
|
|
defaultColor: RGB,
|
|
defaultOnColor: RGB,
|
|
defaultOffColor: RGB,
|
|
defaultBackgroundColor: RGB,
|
|
pages: (PageThermo | PageMedia | PageAlarm | PageQR | PageEntities | PageGrid | PagePower)[],
|
|
subPages: (PageThermo | PageMedia | PageAlarm | PageQR | PageEntities | PageGrid | PagePower)[],
|
|
button1Page: (PageThermo | PageMedia | PageAlarm | PageQR | PageEntities | PageGrid | PagePower | null),
|
|
button2Page: (PageThermo | PageMedia | PageAlarm | PageQR | PageEntities | PageGrid | PagePower| null),
|
|
};
|
|
|
|
type ScreenSaverElement = {
|
|
ScreensaverEntity: string | null,
|
|
ScreensaverEntityIcon: string | null,
|
|
ScreensaverEntityText: string | null,
|
|
ScreensaverEntityUnitText: string | null,
|
|
ScreensaverEntityIconColor: any | null,
|
|
}
|
|
|
|
type ScreenSaverMRElement = {
|
|
ScreensaverEntity: string | null,
|
|
ScreensaverEntityIcon: string | null,
|
|
ScreensaverEntityOnColor: RGB,
|
|
ScreensaverEntityOffColor: RGB,
|
|
}
|