Upload awtrix sonos v0.0.1

This commit is contained in:
2025-10-27 12:27:16 +01:00
parent 3926304cd3
commit f8c801aea4
2 changed files with 346 additions and 0 deletions

View File

@@ -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);