Upload awtrix sonos v0.0.1
This commit is contained in:
207
ioBroker-Skripte/AWTRIX Now Playing Sonos/Readme.md
Normal file
207
ioBroker-Skripte/AWTRIX Now Playing Sonos/Readme.md
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
AWTRIX NowPlaying – Sonos → AWTRIX Custom App (ioBroker)
|
||||||
|
|
||||||
|
Zeigt den aktuell laufenden Song von Sonos als eigene AWTRIX Custom-App an:
|
||||||
|
🎵 Künstler — Titel (Album) – hält sich per Keep-Alive in der Rotation, solange ein Titel läuft.
|
||||||
|
|
||||||
|
Getestet mit ioBroker (Javascript Adapter) + MQTT Adapter und einer AWTRIX mit MQTT-Support für Custom-Apps.
|
||||||
|
|
||||||
|
Features
|
||||||
|
|
||||||
|
Liest Titel/Artist/Album aus Sonos-Datenpunkten.
|
||||||
|
|
||||||
|
Baut automatisch die Anzeige: 🎵 Künstler — Titel (Album).
|
||||||
|
|
||||||
|
Keep-Alive: hält die App per Refresh aktiv, solange der Titel vorhanden ist.
|
||||||
|
|
||||||
|
Automatisches Entfernen der App, sobald keine Titelinfos mehr da sind.
|
||||||
|
|
||||||
|
Optionales FORCE_SWITCH: bei jedem Refresh auf die App umschalten.
|
||||||
|
|
||||||
|
Debounce-Logik (200 ms) gegen „Datenpunkt-Flattern“ bei Trackwechseln.
|
||||||
|
|
||||||
|
Voraussetzungen
|
||||||
|
|
||||||
|
ioBroker mit:
|
||||||
|
|
||||||
|
Javascript Adapter (zum Ausführen des Skripts)
|
||||||
|
|
||||||
|
MQTT Adapter (als Client zum MQTT-Broker; verwendet sendMessage2Client)
|
||||||
|
|
||||||
|
Sonos Adapter (liefert current_title, current_artist, current_album)
|
||||||
|
|
||||||
|
AWTRIX (mit MQTT-Support für Custom-Apps)
|
||||||
|
|
||||||
|
Ein erreichbarer MQTT-Broker (falls nicht in ioBroker integriert)
|
||||||
|
|
||||||
|
Installation
|
||||||
|
|
||||||
|
In ioBroker den Javascript-Adapter öffnen → neues Script NowPlaying Sonos → AWTRIX anlegen.
|
||||||
|
|
||||||
|
Den Skript-Code aus nowplaying_sonos_awtrix.js einfügen und speichern.
|
||||||
|
|
||||||
|
Prüfen/Anpassen:
|
||||||
|
|
||||||
|
MQTT_INSTANCE, AWTRIX_PREFIX
|
||||||
|
|
||||||
|
Sonos-Datenpunkte unter DP.title / artist / album
|
||||||
|
|
||||||
|
Skript starten.
|
||||||
|
Beim ersten laufenden Titel sollte auf der AWTRIX die App NowPlaying erscheinen.
|
||||||
|
|
||||||
|
Konfiguration
|
||||||
|
Konstante Typ Default Beschreibung
|
||||||
|
MQTT_INSTANCE String "mqtt.0" ioBroker-Instanzname des MQTT-Adapters (für sendTo(..., "sendMessage2Client", ...)).
|
||||||
|
AWTRIX_PREFIX String "awtrix" MQTT-Prefix deiner AWTRIX (z. B. awtrix → Themen wie awtrix/custom/NowPlaying).
|
||||||
|
APP_NAME String "NowPlaying" Name der Custom-App (wird als Topic und Anzeigename genutzt).
|
||||||
|
LIFETIME_SEC Number 600 Lebensdauer der App in Sekunden, falls kein Refresh mehr kommt.
|
||||||
|
KEEPALIVE_SEC Number 10 Refresh-Intervall in Sekunden, solange Titel vorhanden ist.
|
||||||
|
FORCE_SWITCH Boolean false Bei jedem Refresh aktiv auf die App schalten (awtrix/switch).
|
||||||
|
ICON_MUSIC Number 29944 AWTRIX-Icon-ID für die Anzeige.
|
||||||
|
COLOR_RGB Array [255,255,255] Textfarbe als RGB.
|
||||||
|
TEXT_CASE Number 2 Textdarstellung lt. AWTRIX (z. B. 0=normal, 1=upper, 2=smart).
|
||||||
|
DP.title String Beispiel Sonos-Datenpunkt current_title.
|
||||||
|
DP.artist String Beispiel Sonos-Datenpunkt current_artist.
|
||||||
|
DP.album String Beispiel Sonos-Datenpunkt current_album.
|
||||||
|
|
||||||
|
Hinweis: Passe die Sonos-DPs an dein Gerät an (IP/Struktur im Sonos-Adapter kann variieren).
|
||||||
|
|
||||||
|
Funktionsweise (Kurz)
|
||||||
|
|
||||||
|
Trigger: on({ id: [title, artist, album], change: "ne" })
|
||||||
|
Bei Änderung wird mit Debounce (200 ms) updateAwtrix() aufgerufen.
|
||||||
|
|
||||||
|
Logik:
|
||||||
|
|
||||||
|
Wenn kein Titel/Artist/Album: App entfernen, Keep-Alive stoppen.
|
||||||
|
|
||||||
|
Bei neuem Track: Text bauen → sofort publishen → Keep-Alive-Timer starten.
|
||||||
|
|
||||||
|
Bei gleichem Track: nichts tun; Keep-Alive veröffentlicht regelmäßig neu.
|
||||||
|
|
||||||
|
Keep-Alive:
|
||||||
|
Alle KEEPALIVE_SEC Sekunden publishCustom(text); sobald title leer ist → App entfernen.
|
||||||
|
|
||||||
|
MQTT-Themen & Payloads
|
||||||
|
|
||||||
|
Custom-App veröffentlichen:
|
||||||
|
Topic:
|
||||||
|
|
||||||
|
<AWTRIX_PREFIX>/custom/<APP_NAME>
|
||||||
|
|
||||||
|
|
||||||
|
Payload (Beispiel):
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "NowPlaying",
|
||||||
|
"text": "🎵 Artist — Title (Album)",
|
||||||
|
"icon": 29944,
|
||||||
|
"color": [255, 255, 255],
|
||||||
|
"textCase": 2,
|
||||||
|
"lifetime": 600
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Auf App umschalten (optional):
|
||||||
|
Topic:
|
||||||
|
|
||||||
|
<AWTRIX_PREFIX>/switch
|
||||||
|
|
||||||
|
|
||||||
|
Payload:
|
||||||
|
|
||||||
|
{ "name": "NowPlaying" }
|
||||||
|
|
||||||
|
|
||||||
|
App entfernen:
|
||||||
|
Topic:
|
||||||
|
|
||||||
|
<AWTRIX_PREFIX>/custom/<APP_NAME>
|
||||||
|
|
||||||
|
|
||||||
|
Payload:
|
||||||
|
|
||||||
|
{ "name": "NowPlaying", "lifetime": 1 }
|
||||||
|
|
||||||
|
|
||||||
|
Das Skript sendet per sendTo("mqtt.X", "sendMessage2Client", { topic, message, retain:false, qos:0 }).
|
||||||
|
|
||||||
|
Anpassungen & Tipps
|
||||||
|
Mehrere Sonos-Player
|
||||||
|
|
||||||
|
Lege das Skript mehrfach an (kopieren) und passe je Instanz:
|
||||||
|
|
||||||
|
APP_NAME (z. B. NowPlaying_Kueche)
|
||||||
|
|
||||||
|
DP.* auf die jeweiligen Player-Datenpunkte
|
||||||
|
|
||||||
|
Kürzere/Längere Anzeige
|
||||||
|
|
||||||
|
Häufigkeit der Refreshs: KEEPALIVE_SEC
|
||||||
|
|
||||||
|
Max. Lebensdauer ohne Refresh: LIFETIME_SEC
|
||||||
|
|
||||||
|
Rotation „hart“ anstoßen
|
||||||
|
|
||||||
|
Setze FORCE_SWITCH = true, wenn viele Apps in der Rotation sind und du bei jedem Refresh zu NowPlaying springen willst.
|
||||||
|
|
||||||
|
Troubleshooting
|
||||||
|
|
||||||
|
Keine Anzeige auf der AWTRIX
|
||||||
|
|
||||||
|
Prüfe, ob der MQTT-Broker erreichbar ist und der ioBroker-MQTT-Adapter verbunden ist.
|
||||||
|
|
||||||
|
AWTRIX_PREFIX korrekt? (z. B. awtrix vs. matrix/awtrix).
|
||||||
|
|
||||||
|
APP_NAME stimmt? (Switch bezieht sich auf denselben Namen)
|
||||||
|
|
||||||
|
Läuft mindestens ein Titel (also DP.title nicht leer)?
|
||||||
|
|
||||||
|
Payload kommt an, aber keine/komische Darstellung
|
||||||
|
|
||||||
|
ICON_MUSIC existiert? Ggf. andere Icon-ID testen.
|
||||||
|
|
||||||
|
TEXT_CASE anpassen (0/1/2 – abhängig von deiner AWTRIX-Firmware).
|
||||||
|
|
||||||
|
App verschwindet zu schnell
|
||||||
|
|
||||||
|
LIFETIME_SEC erhöhen.
|
||||||
|
|
||||||
|
Prüfen, ob KEEPALIVE_SEC zu groß ist (seltener Refresh).
|
||||||
|
|
||||||
|
App „spammt“ die Rotation
|
||||||
|
|
||||||
|
FORCE_SWITCH = false belassen.
|
||||||
|
|
||||||
|
KEEPALIVE_SEC erhöhen (weniger häufige Refreshs).
|
||||||
|
|
||||||
|
Sonos-Datenpunkte ändern sich nicht
|
||||||
|
|
||||||
|
Sonos-Adapter prüfen; korrekte Instanz und Player-IDs?
|
||||||
|
|
||||||
|
Testweise die DPs im Objekt-Baum beobachten.
|
||||||
|
|
||||||
|
Code
|
||||||
|
|
||||||
|
Die vollständige Version liegt in nowplaying_sonos_awtrix.js.
|
||||||
|
|
||||||
|
Sicherheit
|
||||||
|
|
||||||
|
MQTT-Zugangsdaten werden im ioBroker-MQTT-Adapter gepflegt (nicht im Skript).
|
||||||
|
|
||||||
|
Das Skript sendet ohne Retain (retain:false) und mit qos:0.
|
||||||
|
|
||||||
|
Lizenz
|
||||||
|
|
||||||
|
MIT License – siehe LICENSE.
|
||||||
|
|
||||||
|
Credits
|
||||||
|
|
||||||
|
Idee & Umsetzung: Mike
|
||||||
|
|
||||||
|
AWTRIX Projekt & Icons: Respect an die AWTRIX-Community
|
||||||
|
|
||||||
|
ioBroker Adapter: Danke an die Maintainer von Sonos/MQTT/JS
|
||||||
|
|
||||||
|
Changelog
|
||||||
|
|
||||||
|
v0.0.1 – Erste Veröffentlichung
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
/******************************************************
|
||||||
|
* AWTRIX NowPlaying – Sonos → AWTRIX Custom App
|
||||||
|
* Version 0.0.1
|
||||||
|
* Autor: Mike
|
||||||
|
* Zweck: Zeigt "🎵 Künstler — Titel (Album)" auf der AWTRIX
|
||||||
|
* Trigger: Änderungen an Sonos-Datenpunkten (Titel/Artist/Album)
|
||||||
|
******************************************************/
|
||||||
|
|
||||||
|
/*********** Einstellungen ***********/
|
||||||
|
const MQTT_INSTANCE = "mqtt.0";
|
||||||
|
const AWTRIX_PREFIX = "awtrix"; // Dein Prefix
|
||||||
|
const APP_NAME = "NowPlaying";
|
||||||
|
const LIFETIME_SEC = 600; // Eintrag läuft ab, wenn kein Refresh kommt
|
||||||
|
const KEEPALIVE_SEC = 10; // alle x Sekunden Refresh solange Titel vorhanden
|
||||||
|
const FORCE_SWITCH = false; // bei jedem Refresh auf App schalten (falls viele Apps)
|
||||||
|
|
||||||
|
/* Anzeige */
|
||||||
|
const ICON_MUSIC = 29944;
|
||||||
|
const COLOR_RGB = [255, 255, 255];
|
||||||
|
const TEXT_CASE = 2;
|
||||||
|
|
||||||
|
/* Sonos-Datenpunkte (ggf. anpassen) */
|
||||||
|
const DP = {
|
||||||
|
title: "sonos.0.root.192_168_178_75.current_title",
|
||||||
|
artist: "sonos.0.root.192_168_178_75.current_artist",
|
||||||
|
album: "sonos.0.root.192_168_178_75.current_album"
|
||||||
|
};
|
||||||
|
/*************************************/
|
||||||
|
|
||||||
|
/*********** Helpers ***********/
|
||||||
|
function readVal(id) {
|
||||||
|
const st = getState(id);
|
||||||
|
return st ? (st.val ?? "") : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildText(artist, title, album) {
|
||||||
|
let base = "";
|
||||||
|
if (artist && title) base = `${artist} — ${title}`;
|
||||||
|
else if (title) base = title;
|
||||||
|
else if (artist) base = artist;
|
||||||
|
if (base && album) base += ` (${album})`;
|
||||||
|
if (!base) base = "—";
|
||||||
|
return `🎵 ${base}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendMQTT(topic, payloadObj) {
|
||||||
|
// ioBroker als Broker → sendMessage2Client
|
||||||
|
sendTo(MQTT_INSTANCE, "sendMessage2Client", {
|
||||||
|
topic,
|
||||||
|
message: JSON.stringify(payloadObj),
|
||||||
|
retain: false,
|
||||||
|
qos: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function publishCustom(text) {
|
||||||
|
const payload = {
|
||||||
|
name: APP_NAME,
|
||||||
|
text,
|
||||||
|
icon: ICON_MUSIC,
|
||||||
|
color: COLOR_RGB,
|
||||||
|
textCase: TEXT_CASE,
|
||||||
|
lifetime: LIFETIME_SEC
|
||||||
|
};
|
||||||
|
sendMQTT(`${AWTRIX_PREFIX}/custom/${APP_NAME}`, payload);
|
||||||
|
if (FORCE_SWITCH) sendMQTT(`${AWTRIX_PREFIX}/switch`, { name: APP_NAME });
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeApp() {
|
||||||
|
sendMQTT(`${AWTRIX_PREFIX}/custom/${APP_NAME}`, { name: APP_NAME, lifetime: 1 });
|
||||||
|
log("🛑 NowPlaying entfernt (keine Titelinfos)");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********** Kernlogik ***********/
|
||||||
|
let currentSig = ""; // artist|title|album
|
||||||
|
let keepAliveTmr = null; // setInterval-Handle
|
||||||
|
let debounceTmr = null;
|
||||||
|
|
||||||
|
function stopKeepAlive() {
|
||||||
|
if (keepAliveTmr) {
|
||||||
|
clearInterval(keepAliveTmr);
|
||||||
|
keepAliveTmr = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function startKeepAlive(text) {
|
||||||
|
stopKeepAlive();
|
||||||
|
// Erster Push sofort (sichtbar machen) …
|
||||||
|
publishCustom(text);
|
||||||
|
// … und dann regelmäßig solange Titel vorhanden ist
|
||||||
|
keepAliveTmr = setInterval(() => {
|
||||||
|
// Wenn Titel leer geworden ist, sofort stoppen und App entfernen
|
||||||
|
const t = String(readVal(DP.title)).trim();
|
||||||
|
if (!t) {
|
||||||
|
stopKeepAlive();
|
||||||
|
currentSig = "";
|
||||||
|
removeApp();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
publishCustom(text);
|
||||||
|
}, KEEPALIVE_SEC * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateAwtrix() {
|
||||||
|
const title = String(readVal(DP.title)).trim();
|
||||||
|
const artist = String(readVal(DP.artist)).trim();
|
||||||
|
const album = String(readVal(DP.album)).trim();
|
||||||
|
|
||||||
|
// Kein Lied → alles aus
|
||||||
|
if (!title && !artist && !album) {
|
||||||
|
stopKeepAlive();
|
||||||
|
if (currentSig) removeApp();
|
||||||
|
currentSig = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const text = buildText(artist, title, album);
|
||||||
|
const sig = `${artist}|${title}|${album}`;
|
||||||
|
|
||||||
|
// Neuer/anderer Track → Keep-Alive neu starten
|
||||||
|
if (sig !== currentSig) {
|
||||||
|
currentSig = sig;
|
||||||
|
log(`🎧 NowPlaying → ${text}`);
|
||||||
|
startKeepAlive(text);
|
||||||
|
} else {
|
||||||
|
// Gleicher Track: nichts weiter – Keep-Alive tickt von selbst
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********** Trigger & Initiallauf ***********/
|
||||||
|
function scheduleUpdate() {
|
||||||
|
if (debounceTmr) clearTimeout(debounceTmr);
|
||||||
|
debounceTmr = setTimeout(updateAwtrix, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
on({ id: [DP.title, DP.artist, DP.album], change: "ne" }, scheduleUpdate);
|
||||||
|
|
||||||
|
// Beim Start einmal versuchen
|
||||||
|
setTimeout(updateAwtrix, 1500);
|
||||||
Reference in New Issue
Block a user