[Neues Modul] Snapcast

Begonnen von unimatrix, 11 Dezember 2016, 21:25:08

Vorheriges Thema - Nächstes Thema

unimatrix

Hallo,
ich habe ein Modul zur Steuerung des Snapcastservers erstellt: https://github.com/badaix/snapcast

Snapcast ist ein Multiroomaudiosystem, hierbei wird Sound über TCP Verbindungen im Netzwerk an eine oder mehrere Clients verteilt und vollkommen synchron wiedergegeben. Es ist eine einfache Alternative zu einer äquivalenten Lösung mit Hilfe von Pulseaudio. Durch die JSON RPC Schnittstelle wird gewährleistet, dass FHEM immer den genauen Zustand des Servers, der Streams und aller Clients kennt. Diese Infos werden alle als Reading bereitgestellt. Weiterhin können die Clients über entsprechende Set-Befehle gesteuert werden, z.B. in ihrer Lautstärke, oder welchem Stream sie zuhören.

Das Modul nutzt DevIo.pm, hat keine blockierenden Elemente und benötigt kein Polling. Eine kleine Doku befindet sich im commandref Format am Ende des Moduls.

Ich würde mich über Tester und Feedback freuen, gerne auch Anregungen für Erweiterungen.

Ein typisches Setup ist es, Snapcast gemeinsam mit mehreren MPD oder Mopidy Instanzen auf einem Server laufen zu lassen (dieser Server kann auch ein PI sein o.ä.) und dann in jedem Raum einen Client laufen zu lassen. Es kann auch ein Client auf dem Server selbst laufen (also lokale Soundausgabe). Es gibt Linux- und Android Clients.

Eine Diskussion zum Thema Multiroom und weiteren Ideen rundherum findet sich auch hier: https://forum.fhem.de/index.php/topic,59135.0.html

Die jeweils aktuellste Version findet ihr in meinem GIT: https://github.com/unimatrix27/fhemmodules/blob/master/96_Snapcast.pm

Sollte sich Interesse zeigen, und die gröbsten Bugs raus sein, werde ich mich gerne darum bemühen, das Modul in das SVN zu bekomemen. Bis dahin werde ich größere Änderungen hier bekannt geben.

Viel Spaß!

jeckyllhavok

Hi,
sehr geil, bin genau nach so etwas auf der Suche.
Werde ich gleich mal testen und berichten

VG

jeckyllhavok

LeoSum

Super Modul!

Ich würde noch einen Vorschlag machen:

Die Readings einzelner Clients werden momentan mit fortlaufender Nummer folgendermaßen angelegt:

clients_1_stream
clients_1_name
clients_2_stream
clients_2_name

Wenn der Snapserver neugestartet wird, kann es sein, dass die client Reihenfolge eine andere ist. Wenn man Notifies hat, die auf bestimmte Reading Änderungen reagieren, müssen diese auf die neue Client Nummer angepasst werden. Ich würde daher vorschlagen, anstelle der fortlaufenden Nummer die macadresse des clients im Namen der Readings zu verwenden.

Desweiteren sollten bei einem Update nicht mehr vorhanden clients aus der Reading Liste gelöscht werden.

Gruß
Leo

unimatrix

Das ist richtig, das kann so nicht bleiben. Bei Snapcast selbst ändert sich allerdings auch gerade einiges. Jeder Client wird eine feste ID bekommen. Die wird meistens der MAC entsprechen.

Habe heute ein Update gemacht. Es gehen jetzt auch Volume Steps.

unimatrix

Folgende Änderungen sind seit heute auf dem GIT verfügbar:

- Die Clients in den Readings werden nicht mehr nur nach Nummer aufgeführt, sondern nach ID. So bleiben die Readings immer gleich und man kann entsprechende notifies bauen
- Man kann pro Snapcast Client eine virtuelles Modul definieren. Dies ist dafür gedacht, dass man das ganze besser in bestehende Visualisierungslösungen einbauen kann, außerdem können so clientspezifische Attribute definiert werden.

Die durchnummerierten Readings plane ich mittelfristig zu entfernen. Sie sollten nicht mehr genutzt werden.

Doku ist im Modul unten als HTML für die Commandref.

LeoSum

Super, ich werde das am Wochenende testen!

Ich antworte mal hier auf eine ursprünglich im anderen (Multiroom Project) Thread gestellte Frage, das gehört eher hier her:
Zitat von: unimatrix am 09 Januar 2017, 17:47:40
Hallo, kann ich nicht reproduzieren. Das Modul hält eine offene Verbindung zum Snapcast Server und sollte eig. alle Readings updaten, die auch vom Server upgedated werden. Das betrifft ja gerade auch solche Updates, die von einem anderen Client, z.B. vom Android Client aus, angetriggert werden. Wenn ich bei mir im Android Client z.B. Mute und UnMute dann sehe ich das sofort in den Readings.

Ein Extra GetStatus wollte ich eigentlich vermeiden. Kannst du das Problem genauer beschreiben?

Ich meinte damit nicht, dass über Android gemacht Änderungen in FHEM nicht angezeigt werden. Das funktioniert wie du sagtest wunderbar!

Mein Problem ist folgendes, wofür ich den zusätzlichen GetStatus Befehl an entsprechender Stelle eingefügt habe:
Wenn ich über FHEM einen set befehel an einen snapclient sende, ändert sich das reading in FHEM nicht.
Ich vermute, dass der socket direkt nach dem Schreiben nicht direkt gelesen werden kann oder sowas. Im Android controller kommt die änderung (bspw. Mute oder Volume) aber direkt an.

Das hatte ich in meinem kümmerlichen Versuch ein Snapcast Modul zu schreiben damals auch festgestellt und mit dem mauellen GetStatus nach dem Setten gelöst.

Was spräche denn gegen ein zusätzliches GetStatus? Schlechter Stil? ;)

unimatrix

Jetzt verstehe ich was du meinst. Ich nehme an, dass dein snapcast server nicht innerhalb des Timeouts, den ich verwende (0,1 Sekunden) ein Result sendet, sonst würde das nämlich sehrwohl sofort im Reading angezeigt. Das war sowieso eine Fummellösung. 0,1 Sekunden ist kurz, aber auch so lange will ich FHEM nicht blocken. Ich werde das auf vollständig asynchrone Kommunikation umstellen, das erfordert aber noch ein wenig Logik drumherum, und dann wird das auch bei dir funktionieren. Das mit dem getStatus braucht man dann nicht und ich mag solche Lösungen nicht. Das soll von vorne herein richtig gehen :)

LeoSum

Alles klar.
Dann verschweige ich dir, dass ich bis du die saubere Lösung umgesetzt hast, diese Zeile in alle deine Versionen einfügen werde ;)

Ich bin froh, dass sich jetzt jemand, der offenbar Ahnung von der Materie hat mit diesem Modul befasst. Meins war mehr eine unsaubere Behelfslösung.

Auch toll, wie du Vorschläge berücksichtigst und sofort umsetzt! Danke!


unimatrix

Habe eben ein größeres Update eingecheckt. Das meiste unter der Haube:

- Die Kommunikation ist jetzt vollständig asynchron. Das Modul merkt sich, welcher Request mit welcher ID an den Snapcast-Server ging und verarbeitet die Antworten dann asynchron, egal wie lange der Server braucht und in welcher Reihenfolge er antwortet.
- Das Mute Toggling funktioniert jetzt. Einfach "set <name> mute" eingeben, ohne true oder false.
- Das Problem, dass das Modul nicht funktionierte, wenn man sehr viele Streams definiert hatte, sollte der Vergangenheit angehören.

Insgesamt habe ich eine Menge geändert, so dass sich natürlich auch neue Bugs eingeschlichen haben könnten. Daher bitte ich nach wie vor um Nachsicht. Ich bin mir aber sicher, dass der Weg so richtig ist. Ich plane auch keine nennenswerten Erweiterungen im Moment so dass ich dieses Modul wohl hoffentlich bald als 1. Stable-Version herausgeben kann.

drdownload

Ich hätte noch eine Frage:

was ist denn der Hintergrund, dass Clients es für einen Client 2x Readings gibt:
clients_7802f821777a_nr = 1
clients_1_id = 7802f821777a

und noch zwei Verbesserungsvorschlage:
Eine Liste der Clients und Streams jeweils als Dropdown beim Zuweisen
Beide Listen auch als Array in einem Reading
CUL 868 Slow-RF (FS20 Aktoren, Sender, FHT8V), CUL 868 (WMBUS-Empfang), Jeelink (PCA301), WS3600 (WH3080 über USB-Basis), Bewässerung mit ESP-Easy und Proplanta, RFXTRX433 Home-Easy Empfang und Senden, Oregon TH, WS001 TH), Blackbean IR, Mopidy-Snapcast MR Audio, Kodi, Forum-LED-Controller,

unimatrix

Neue Version online.

Änderungen:

- die alten Readings nach dem Schema clients_1_id gibt es nicht mehr. Das war noch ein Überbleibsel.
- Feature Volume Constraint implementiert. Details in der Commandref am Ende des Moduls.
- Code aufgeräumt
- kleinere Bugs beseitigt

@drdownload: Das mit dem Dropdown mach ich rein. Weiss aber gerade noch nicht wie das geht. Was meinst du mit Array? Ein Reading, wo alle Clients drin sind. Mit was für Infos? Das kann ja sehr lang werden.

Die Volume Constraints kann man leicht testen. Einfach mal folgendes Attribut anlegen (für ein Client-Modul, nicht für das Servermodul)

attr <snapcast_client_name> constraints standard|24:00 50

Damit ist die Lautstärke grundsätzlich auf 50% limitiert. Jetzt kann man auch in der App die Lautstärke nicht mehr höher stellen.

unimatrix

Info: Das Modul ist ab jetzt auch im SVN

maylow

Super, Danke für die Arbeit.

unimatrix

Es gab noch ein paar Bugs, aber die sind jetzt raus. Ich denke das Modul ist jetzt ziemlich stabil. Auf zum nächsten Modul... :)

unimatrix

Für all diejenigen, die Snapcast z .B. auf einem Rechner einsetzen, auf dem auch KODI läuft, habe ich den Snapcast Client etwas "gehackt", damit das Sounddevice freigegeben wird, wenn der Client auf Mute gesetzt wird. So kann man den Client immer laufen lassen, und muss ihn nur muten, wenn man was anderes benutzen will. Das ist nur eine Quick & Dirty Lösung, aber zumindest schonmal ganz hilfreich.
https://github.com/unimatrix27/snapcast/tree/develop