mirror of
https://github.com/joBr99/nspanel-lovelace-ui.git
synced 2025-12-21 15:04:24 +01:00
v3.5.0.4 Reengineering Media Subscriptions
This commit is contained in:
@@ -1,20 +1,16 @@
|
||||
/*-----------------------------------------------------------------------
|
||||
TypeScript v3.5.0.2 zur Steuerung des SONOFF NSPanel mit dem ioBroker by @Armilar/@Britzelpuf
|
||||
TypeScript v3.5.0.4 zur Steuerung des SONOFF NSPanel mit dem ioBroker by @Armilar/@Sternmiere/@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)
|
||||
@@ -45,6 +41,7 @@ ReleaseNotes:
|
||||
- 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 Upgrade TFT 42
|
||||
- 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
|
||||
@@ -56,6 +53,7 @@ ReleaseNotes:
|
||||
- 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 Upgrade TFT 43
|
||||
- 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
|
||||
@@ -63,14 +61,13 @@ ReleaseNotes:
|
||||
- 26.10.2022 - v3.5.0.1 Fix Thermostat for tado Support (by Sternmiere)
|
||||
- 27.10.2022 - v3.5.0.1 Add VirtualDevice Gate
|
||||
- 27.10.2022 - v3.5.0.2 Applied Boy Scout Rule (Fixed some typos, changed var to let, fixed min/max colorTemp Bug)
|
||||
- 27.10.2022 - v3.5.0.3 Fixed Media Play/Pause icon for alexa (and others) devices
|
||||
|
||||
- 30.10.2022 - v3.5.0.3 Fixed Media Play/Pause icon for alexa (and others) devices
|
||||
- 31.10.2022 - v3.5.0.4 Reengineering Media Subscriptions
|
||||
Wenn Rule definiert, dann können die Hardware-Tasten ebenfalls für Seitensteuerung (dann nicht mehr als Relais) 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öchsttemperatur) oder zur Anzeige definierter Infos konfiguriert werden)
|
||||
@@ -80,13 +77,11 @@ Mögliche Seiten-Ansichten:
|
||||
cardMedia Page - Mediaplayer - Ausnahme: Alias sollte mit Alias-Manager automatisch über Alexa-Verzeichnis 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", "Farbtemperatur" und "Farbauswahl" bereitgestellt
|
||||
popupShutter Page - die Shutter-Position (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)
|
||||
@@ -111,17 +106,14 @@ Mögliche Aliase: (Vorzugsweise mit ioBroker-Adapter "Geräte verwalten" konfigu
|
||||
Feuchtigkeit - Anzeige von Humidity - Datenpunkten, analog 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 AccuWeather-Icon (Icon) für Screensaver
|
||||
|
||||
Interne Sonoff-Sensoren (über Tasmota):
|
||||
ESP-Temperatur - wird in 0_userdata.0. abgelegt, kann als Alias importiert werden --> SetOption146 1
|
||||
Temperatur - Raumtemperatur - wird in 0_userdata.0. abgelegt, kann als Alias importiert 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:
|
||||
AccuWeather: - Bei Nutzung der Wetterfunktionen (und zur Icon-Konvertierung) im Screensaver
|
||||
Alexa2: - Bei Nutzung der dynamischen SpeakerList in der cardMedia
|
||||
@@ -129,14 +121,11 @@ Erforderliche Adapter:
|
||||
Alias-Manager - !!! ausschließ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
|
||||
---------------------------------------------------------------------------------------
|
||||
*/
|
||||
import { config } from './NsPanelTs'
|
||||
|
||||
let Icons = new IconsSelector();
|
||||
let timeoutSlider: any;
|
||||
let manually_Update = false;
|
||||
@@ -232,10 +221,47 @@ let vwIconColor = [];
|
||||
|
||||
//-- 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,
|
||||
mrIcon1ScreensaverEntity: { ScreensaverEntity: null, ScreensaverEntityIcon: 'light-switch', ScreensaverEntityOnColor: On, ScreensaverEntityOffColor: Off },
|
||||
mrIcon2ScreensaverEntity: { ScreensaverEntity: null, 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');
|
||||
|
||||
let useMediaEvents: boolean = false;
|
||||
let timeoutMedia: any;
|
||||
|
||||
//---------------------Begin PageNavi
|
||||
async function InitPageNavi() {
|
||||
try {
|
||||
@@ -1103,6 +1129,7 @@ function HandleMessage(typ: string, method: string, page: number, words: Array<s
|
||||
GeneratePage(config.pages[0]);
|
||||
break;
|
||||
case 'sleepReached':
|
||||
useMediaEvents = false;
|
||||
screensaverEnabled = true;
|
||||
if (pageId < 0)
|
||||
pageId = 0;
|
||||
@@ -1172,6 +1199,7 @@ function GeneratePage(page: Page): void {
|
||||
SendToPanel(GenerateGridPage(<PageGrid>page));
|
||||
break;
|
||||
case 'cardMedia':
|
||||
useMediaEvents = true;
|
||||
SendToPanel(GenerateMediaPage(<PageMedia>page));
|
||||
break;
|
||||
case 'cardAlarm':
|
||||
@@ -2052,12 +2080,40 @@ function GenerateThermoPage(page: PageThermo): Payload[] {
|
||||
}
|
||||
}
|
||||
|
||||
function unsubscribeMediaSubscriptions(): void {
|
||||
for (let i = 0; i < config.pages.length; i++) {
|
||||
if (config.pages[i].type == 'cardMedia') {
|
||||
let mediaID = config.pages[i].items[0].id;
|
||||
unsubscribe(mediaID + '.STATE')
|
||||
unsubscribe(mediaID + '.ARTIST')
|
||||
unsubscribe(mediaID + '.TITLE')
|
||||
unsubscribe(mediaID + '.ALBUM')
|
||||
unsubscribe(mediaID + '.VOLUME')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function subscribeMediaSubscriptions(id: string): void {
|
||||
on({id: [].concat([id + '.STATE']).concat([id + '.VOLUME']).concat([id + '.ARTIST']).concat([id + '.ALBUM']).concat([id + '.TITLE']), change: "ne"}, async function () {
|
||||
(function () { if (timeoutMedia) { clearTimeout(timeoutMedia); timeoutMedia = null; } })();
|
||||
timeoutMedia = setTimeout(async function () {
|
||||
if (useMediaEvents) {
|
||||
GeneratePage(activePage);
|
||||
}
|
||||
},25)
|
||||
});
|
||||
}
|
||||
|
||||
function GenerateMediaPage(page: PageMedia): Payload[] {
|
||||
try {
|
||||
let id = page.items[0].id
|
||||
|
||||
let out_msgs: Array<Payload> = [];
|
||||
|
||||
unsubscribeMediaSubscriptions();
|
||||
|
||||
subscribeMediaSubscriptions(id);
|
||||
|
||||
out_msgs.push({ payload: 'pageType~cardMedia' });
|
||||
if (existsObject(id)) {
|
||||
let name = getState(id + '.ALBUM').val;
|
||||
@@ -2077,11 +2133,9 @@ function GenerateMediaPage(page: PageMedia): Payload[] {
|
||||
name = getState(id + '.CONTEXT_DESCRIPTION').val;
|
||||
let nameLength = name.length;
|
||||
if (name.substring(0,9) == 'Playlist:') {
|
||||
let nameLength = name.length;
|
||||
name = name.slice(10, nameLength);
|
||||
name = name.slice(10, 26) + '...';
|
||||
} else if (name.substring(0,6) == 'Album:') {
|
||||
let nameLength = name.length;
|
||||
name = name.slice(10, nameLength);
|
||||
name = name.slice(7, 23) + '...';
|
||||
} else if (name.substring(0,6) == 'Track') {
|
||||
name = 'Spotify-Premium';
|
||||
}
|
||||
@@ -2144,12 +2198,14 @@ function GenerateMediaPage(page: PageMedia): Payload[] {
|
||||
}
|
||||
|
||||
//Ausnahme für squeezebox, da State = Power
|
||||
if (getState(id + '.PAUSE').val === false && v2Adapter == 'squeezeboxrpc') {
|
||||
if (v2Adapter == 'squeezeboxrpc') {
|
||||
if (getState(id + '.PAUSE').val === false) {
|
||||
onoffbutton = 65535;
|
||||
iconplaypause = Icons.GetIcon('pause'); //pause
|
||||
} else {
|
||||
iconplaypause = Icons.GetIcon('play'); //play
|
||||
}
|
||||
}
|
||||
|
||||
if (Debug) {
|
||||
console.log(v2Adapter);
|
||||
@@ -2204,8 +2260,8 @@ function GenerateMediaPage(page: PageMedia): Payload[] {
|
||||
iconplaypause + '~' + //playpauseicon
|
||||
currentSpeaker + '~' + //currentSpeaker
|
||||
speakerList + '~' + //speakerList-seperated-by-?
|
||||
onoffbutton
|
||||
}); //On/Off Button Color
|
||||
onoffbutton //On/Off Button Color
|
||||
});
|
||||
}
|
||||
if (Debug) {
|
||||
console.log(out_msgs);
|
||||
@@ -2752,11 +2808,6 @@ function HandleButtonEvent(words): void {
|
||||
break;
|
||||
case 'media-back':
|
||||
setIfExists(id + '.PREV', true);
|
||||
on({id: id + '.TITLE', change: "ne"}, async function () {
|
||||
setTimeout(function(){
|
||||
GeneratePage(activePage);
|
||||
},25)
|
||||
});
|
||||
break;
|
||||
case 'media-pause':
|
||||
let pageItemTemp = findPageItem(id);
|
||||
@@ -2777,24 +2828,9 @@ function HandleButtonEvent(words): void {
|
||||
setIfExists(id + '.PLAY', true);
|
||||
}
|
||||
}
|
||||
on({id: id + '.STATE', val: true}, async function () {
|
||||
on({id: [].concat([id + '.ARTIST']).concat([id + '.ALBUM']).concat([id + '.TITLE']), change: "ne"}, async function () {
|
||||
setTimeout(function(){
|
||||
GeneratePage(activePage);
|
||||
},25)
|
||||
});
|
||||
});
|
||||
on({id: id + '.STATE', val: false}, async function () {
|
||||
GeneratePage(activePage);
|
||||
});
|
||||
break;
|
||||
case 'media-next':
|
||||
setIfExists(id + '.NEXT', true);
|
||||
on({id: id + '.TITLE', change: "ne"}, async function () {
|
||||
setTimeout(function(){
|
||||
GeneratePage(activePage);
|
||||
},25)
|
||||
});
|
||||
break;
|
||||
case 'volumeSlider':
|
||||
setIfExists(id + '.VOLUME', parseInt(words[4]))
|
||||
|
||||
Reference in New Issue
Block a user