Modul für Yamaha Musiccast

Begonnen von Leugi, 10 März 2019, 16:07:57

Vorheriges Thema - Nächstes Thema

Leugi

Hallo,

das homebridgemapping sieht irgendwie doppelt aus, das in rot kann m.E. weg.

attr Stube homebridgeMapping On=state,valueOn=/on|mute|1/,valueOff=/off|standby|disappeared|0/,cmdOn=on,cmdOff=off Mute=mute::mute Volume=volume::volume,delay=trueMute=mute::mute Volume=volume::volume,delay=true

zusätzlich würde ich noch
attr Stube siriName "Tisch"
angeben und

vielleicht mal mit genericDeviceType Speaker statt Amplifier testen :
attr Stube genericDeviceType Speaker

Gruß
Leugi
FHEM auf RaspPi 2, USB-CUL V3, div. HM Aktoren

maeke

Hallo

habe die Fehler Korrigiert, Unter Home sehe ich aber nur ( wie gehabt) einen Schalter und beim draufklicken schaltet der Varstärker auch ein, beim gedrückt halten kommt ein Menu im gegensatz zu den FS20 wo ein Regler auftaucht. Somit geht auch kein Befehl wie:
setze Tisch 50 oder Setze Tisch Volume/Lautsprecher 50
Da du meinst es gehe mach Mut ich dachte das ginge evt noch nicht.
Unter Eve taucht ein Regler auf. Dort gibts halt kein Siri..
werde mich evt weiter mit homebridgeMapping befassen müssen.
Falls euch noch was einfällt wäre ich dankbar
anbei noch ein Bild des Menus evt hilfts euch.

Danke jedenfalls für das schnelle Feedback

gruss maeke

jhohmann

Da ich kein Yamaha Musiccast habe, kann ich hier vom Gerät her nicht mit reden, aber zu dem Homebridge Problem fällt mir auf, dass das Gerät Tisch in der Homebridge sichtbar ist, der genericDeviceType wird hier aber empfohlen, bei dem Gerät Stube zu pflegen.
Sollte das nicht am "Tisch" gepflegt werden?
Raspberry Pi 4 - bookworm / EnOcean - Rollo+Licht, deCONZ - Licht+Sensoren, ZWave - CO Messung, HMCCU mit piVCCU - Heizung+Rollo
plus dovecot, minidlna

F_Klee

Hallo Leugi,
habe tatsächlich "mal eben" alle MusicCast-Geräte bei einer befreundeten Familie in FHEM eingebunden. Das Modul ist echt klasse. Allerdings habe ich Probleme, die Geräte in smartVISU zu visualisieren. Hängen geblieben bin ich bei mute (der Rest kommt noch  ;) ). Dein Modul erwartet ein true oder false als Parameter. Zurückgeliefert wird aber 1 oder 0. Der basic.stateswitch in smartVISU könnte 1 oder 0 senden und empfangen. Optimal wäre, wenn man das Modul so ändern würde, das es 1 und 0 intern in true und false umsetzt und dann an das Gerät schickt. Dann bräuchte man noch nicht einmal einen speziellen Converter in fronthem. Außerdem wäre dann ein System darin und das Toggle-Problem, über das ich hier gelesen habe und das scheinbar immer noch existiert, ist dann vielleicht auch behoben. Aus Kompatibilitätsgründen kann man ja true und false beibehalten.
Da ich mir einen Konverter zusammengestrickt habe, ist es nicht eilig. Allerdings scheint bei dem Converter eine Rückmeldung, wenn der Anwender am Gerät selbst das Muting deaktiviert, nicht zu funktionieren. Damit kann ich aber leben.

Gruß
Frank

jhohmann

Ich habe inzwischen auch ein Musiccast Gerät zugelegt und das Modul funktioniert für meinen Einsatzzweck gut, vielen Dank für die Arbeit.
Mir ist nur aufgefallen, dass nach einem Neustart von FHEM und dann einem Einschalten des Geräts im Log von FHEM eine Fehlermeldung auftaucht.
2020.11.25 06:49:09 1: PERL WARNING: Use of uninitialized value in string eq at ./FHEM/71_YAMAHA_MC.pm line 2609.
2020.11.25 06:49:09 1: stacktrace:
2020.11.25 06:49:09 1:     main::__ANON__                      called by ./FHEM/71_YAMAHA_MC.pm (2609)
2020.11.25 06:49:09 1:     main::YAMAHA_MC_httpRequestQueue    called by ./FHEM/71_YAMAHA_MC.pm (766)
2020.11.25 06:49:09 1:     main::YAMAHA_MC_getInputs           called by ./FHEM/71_YAMAHA_MC.pm (668)
2020.11.25 06:49:09 1:     main::YAMAHA_MC_GetStatus           called by fhem.pl (3350)
2020.11.25 06:49:09 1:     main::HandleTimeout                 called by fhem.pl (685)

Sagt das jemanden was?
Raspberry Pi 4 - bookworm / EnOcean - Rollo+Licht, deCONZ - Licht+Sensoren, ZWave - CO Messung, HMCCU mit piVCCU - Heizung+Rollo
plus dovecot, minidlna

Leugi

Hallo zusammen.

Es gibt nun ein Update des Moduls mit folgenden Änderungen :

1. der Befehl mute akzeptiert nun auch 0 und 1 als Parameter
2. Bei setSpeakerA und setSpeakerB habe ich die URL korrigiert auf YamahaExtendedControl/v2/system/..
    solte dadurch jetzt funktionieren, wenn der Receiver das unterstützt
3. ich habe jetzt in der reglemäßigen Aktualisierung die getFuncStatus auch mit ausgeführt,
    die Werte für SpeakerA und SpeakerB werden dadurch jetzt auch regelmäßgig

Gruß
Leugi
FHEM auf RaspPi 2, USB-CUL V3, div. HM Aktoren

mrnatcho

Moin Leugi et al,

erstmal danke für das Yamaha Modul! Macht schon viel Freude.

Ich bastel gerade für mein Tablet UI eine Steuerung für einen WX-021 basierend auf dem Sonos Beispiel von reinerlein (https://wiki.fhem.de/wiki/SONOS#Beispiele_f.C3.BCr_FTUI-Integrationen).

Jetzt hänge ich am Toggle Button für Repeat, zu dem ich in der Commandref nichts finden kann. Mein Device in FHEM zeigt auch kein Reading oder Internal für den Repeat status aus. In der API Referenz für Yamaha finde ich eine Transport Control:
Repeat (Toggle) http://192.168.5.219/YamahaExtendedControl/v1/netusb/toggleRepeat
Die kann ich auch über den Browser nutzen. Ist die in dem Modul nicht implementiert, oder bin ich nur zu blind sie zu finden?

Beste Grüße (und frohes neues Jahr)
MrNatcho
FHEM auf Ubuntu Server VM auf Synology NAS, Yamaha MC's, Technoline Temperatur-Sensoren über Lacrosse GW's, HM-IP Devices über virtual CCU aus Raspberry Pi

Leugi

Hallo mrnatcho

Ich habe die toggleRepeat Funktion jetzt mit aufgenommen.
Habe sie allerdings nicht getestet.
Vielleicht mal ausprobieren.

Gruß,
Leugi
FHEM auf RaspPi 2, USB-CUL V3, div. HM Aktoren

mrnatcho

Moin,

die Funktion funktioniert. Thx!

Es klingt jetzt so als würde ich hier faul auf der Couch sitzen und andere arbeiten lassen, aber meine Perl Kenntnisse sind leider zu beschränkt um direkt zum Yamaha Modul beizutragen. Könntest Du auch noch die Funktion "toggleShuffle" sowie die beiden Readings aus dem getPlayInfo mit aufnehmen (repeat, shuffle)?

Ansonsten sieht der Player schon mal so aus (MP3 von einem lokalen server): siehe Anhang
Was funktioniert:
- Anzeige Raumname
- Anzeige Albumcover bzw. Logo von Internerradio
- Anzeige Album / Track (Bzw. Sender und Trackinformation)
- Knöpfe Mute, Repeat, track vor, track zurück, play/pause
- Knopf Menu ist zwar sichtbar, macht aber noch nichts
- Vor- und Zurückspulen (leider ohne Anzeige wo im track man gerade ist, muss man das Spultempo halt raten)

Was noch zu tun ist:
- Integration Multi-room / Anzeige falls der Player in einem multi-room mitläuft
- Menu Funktionalität zur Auswahl Favoriten
- Genereller Menübutton zur Auswahl von Musik von einem lokalen server, suche nach netradio etc. (ist das über das Interface von Yamaha überhaupt möglich?)

Viele Grüße
MrNatcho
FHEM auf Ubuntu Server VM auf Synology NAS, Yamaha MC's, Technoline Temperatur-Sensoren über Lacrosse GW's, HM-IP Devices über virtual CCU aus Raspberry Pi

Leugi

Hallo MrNatcho,

das sieht ja schon super aus ! Vielleicht kannst du das hier teilen, wie du das erreicht hast ?

Ich habe nun toggleShuffle und die Readings für Repeat und Shuffle implementiert.
Ich habe auch noch die Werte für Total_Time und Play_Time übernommen, vielleicht hilft dir das ja.

Neue Version wird morgen produktiv.

Gruß,
Leugi
FHEM auf RaspPi 2, USB-CUL V3, div. HM Aktoren

mrnatcho

Moin,

Danke für die Readings, sind eingebaut.
Total_time und Play_time sind noch etwas unwillig, ich kriege für MP3 von einem lokalen DNLA Server nur die Play_Time zurück, damit ist die Darstellung wie im Sonos Original noch nichts. Aber auch in der Musiccast App sehe ich nur den aktuellen Stand und nicht die Tracklänge. Und auch nicht die Anzahl der Tracks in der Playlist sowie die Nummer des aktuellen Tracks. So lange bleiben die beiden Anzeiger aus der Sonos Vorlage erstmal auskommentiert.

Um den Player nachzubauen:
1. Styles und Script für die Scrolltexte entsprechend Anleitung von reinerlein (link siehe der vorherige Post) aufnehmen
2.  "widget_joinedlabel.js" entsprechend der Anleitung von reinerlein anpassen
3. Eine Verknüpfung zur HTML Seite für den Player in einem Gridster aufnehmen:
<li data-row="1" data-col="3" data-sizex="3" data-sizey="2" class="border-down-gray lesstransparent">
<div data-template="template_musik_yamaha.html" data-parameter='{"Device":"1OG.Gaestezimmer.MC"}'></div>
</li>


Und dann den folgenden Code in die als Template genannte Datei einfügen:

<header>
<!-- Multiroom Coding, noch nicht überarbeitet

<div data-type="classchanger" data-device="Device" data-get="SlavePlayerNotBonded" data-get-on='["[]"]' data-on-class="hide" data-off-class="mini" class="inline">
<div data-type="switch" data-device="Device" data-get="GroupMute" data-set="GroupMute"
data-icon="fa-deaf" data-background-icon="-"
data-on-color="#aa6900" data-off-color="gray"
data-get-on="1" data-get-off="0"
data-set-on="1" data-set-off="0" class="mini" style="margin-right: -5px;">
</div>
</div>

<div data-type="joinedlabel" data-device="Device" data-mask="[$1][ ($2)]" data-get='["roomName","ZoneGroupNameDetails"]' class="truncate inline"></div>

<div data-type="classchanger" data-device="Device" data-get="MasterPlayer" data-get-on="Device" data-on-class="hide" class="inline left-narrow">
<div data-type="push"
data-device="Device"
data-icon="fa-minus-circle"
data-background-icon="-"
data-set-on="MakeStandaloneGroup"
class="inline mini gray">
</div>
</div>

<div data-type="classchanger" data-device="Device" data-get="MasterPlayer" data-get-on="Device" data-off-class="hide" class="inline left-narrow">
<div data-type="popup" class="" data-width="400px" data-height="110px">
<div data-type="symbol"
data-icon="fa-chevron-circle-down"
class="mini"
style="height: 10px;">
</div>

<div class="dialog">
<header><div data-type="joinedlabel" data-device="Device" data-mask="Wiedergabegruppe[ für $1] anpassen" data-get='["roomName"]' class="inline"></div></header>

<div class="top-space-10 left-align left-space">
<div>
<div class="large middle inline">Player hinzufügen: </div>
<div data-type="select"
data-device="Device"
data-list="AvailablePlayerList"
data-alias="AvailablePlayerListAlias"
data-delimiter="|"
data-get="-"
data-set="AddMember"
class="inline w3x"
onchange="$('.dialog-close').trigger('click');"></div>
</div>

<div>
<div class="large middle inline">Player entfernen: </div>
<div data-type="select"
data-device="Device"
data-list="SlavePlayerNotBondedList"
data-alias="SlavePlayerNotBondedListAlias"
data-delimiter="|"
data-get="-"
data-set="RemoveMember"
class="inline w3x"
onchange="$('.dialog-close').trigger('click');"></div>
</div>
</div>
</div>
</div>
</div>
-->
</header


<div class="">
<div data-type="joinedlabel" data-device="Device" data-mask=" [~ $1 ~] " data-get='["location_name"]' class="bottom-narrow mini white" style="padding-top: 3px; background: rgba(170, 105, 0, 0.6);"></div>

<div data-type="popup" data-width="100%" data-height="100%">
<div style="margin-bottom: -40px;">
<div data-type="imagecover"
data-device="Device"
data-get="albumart_url"
data-opacity="1.0"
data-width="350px"
data-height="350px"
class=""
onclick="$('.dialog-close').trigger('click');"
style="margin-left: 12px; margin-top: 12px; border: 1px solid rgba(170, 105, 0, 0.6);">
</div>

<!-- Icon für Quelle der Mediendatei, z.B. Spotify einblenden, wenn vorhanden
Scheint bei Yamaha nicht zu existieren, könnte aber über die Quelle und lokale icons nachgebaut werden
-->
<!-- <div data-type="classchanger" data-device="Device" data-get="currentTrackProviderIconRoundURL" data-get-on="" data-on-class="hide">
<div class="inline" style="width: 40px; height: 40px; background: rgba(0, 0, 0, 0.40); position: relative; top: -349px; left: -152px;">
<div data-type="imagecover"
data-device="Device"
data-get="currentTrackProviderIconRoundURL"
data-opacity="1.0"
data-width="30px"
data-height="30px"
class=""
style="margin-left: 5px; margin-top: 5px;">
</div>
</div>
</div>-->
<!--
<div data-type="classchanger" data-device="Device" data-get="currentTrackProviderIconRoundURL" data-get-on="" data-off-class="hide">
<div class="inline" style="width: 40px; height: 40px; position: relative; top: -349px; left: -152px;">
</div>
</div> -->
</div>

<div class="dialog">
<header><div data-type="joinedlabel" data-device="Device" data-mask="Cover[ für $1]" data-get='["location_name"]' class="inline"></div></header>
<!-- ebenso fehlendes Icon des source providers
<div data-type="imagecover"
data-device="Device"
data-get="currentTrackProviderIconRoundURL"
data-opacity="1.0"
data-width="30px"
data-height="30px"
class=""
style="position: absolute; top: 25px; left: 5px;"
style="margin-left: 5px; margin-top: 5px;">
</div> -->

<div data-type="switch"
data-device="Device"
data-get="playback_status"
data-states='["play","pause","stop"]'
data-background-icon="-"
data-background-colors='["white","white","white"]'
data-colors='["white","white","white"]'
data-icons='["fa-play","fa-pause","fa-pause"]'
class="inline readonly"
style="position: absolute; top: 10px; right: -10px;"
onclick="$('.dialog-close').trigger('click');">
</div>


<div data-type="imagecover"
data-device="Device"
data-get="albumart_url"
data-opacity="1.0"
data-width="100%"
data-height="calc(100vh - 60px)"
class=""
onclick="$('.dialog-close').trigger('click');"
style="">
</div>
<!-- current position im track scheint vorhanden, gesamtlänge aber nicht...
<div data-type="classchanger" data-device="Device" data-get="currentNormalAudio" data-get-on="1" data-off-class="hide">
<div data-type="slider"
data-device="Device"
data-get="currentTrackPositionSimulatedSec"
data-max="currentTrackDurationSec" data-min="0"
data-step="1"
data-handle-diameter="5"
data-width="68%"
class="horizontal top-narrow readonly centered"></div>
</div>

<div data-type="classchanger" data-device="Device" data-get="playback_input" data-get-on="server" data-off-class="hide">
<div data-type="joinedlabel" data-device="Device" data-mask="[$1][ ~ $2][ ~ $3]" data-get='["track","station_name","album_name"]' class="truncate top-space"></div>
</div>
<div data-type="classchanger" data-device="Device" data-get="currentStreamAudio" data-get-on="1" data-off-class="hide">
<div data-type="joinedlabel" data-device="Device" data-mask="[$1 ~ ][$2][: $3]" data-get='["currentSenderInfo","currentSender","currentSenderCurrent"]' class="truncate top-space"></div>
</div>
-->
</div>
</div>
<!-- track lenght & current position & number of tracks not available on Yamaha
<div data-type="classchanger" data-device="Device" data-get="currentNormalAudio" data-get-on="1" data-off-class="hide">
<div data-type="label" data-device="Device" data-get="currentTrackPositionSimulated" class="inline" style="width: 3em;"></div>
<div data-type="slider"
data-device="Device"
data-set="CurrentTrackPosition"
data-get="currentTrackPositionSimulatedSec"
data-max="currentTrackDurationSec" data-min="0"
data-step="1"
data-handle-diameter="5"
data-width="250"
class="horizontal tap inline">
</div>
<div data-type="label" data-device="Device" data-get="currentTrackDuration" class="inline" style="width: 3em;"></div>

<div class="newline">
<div data-type="label" data-device="Device" data-get="currentTrack" class="inline center-align" style="width: 3em;"></div>
<div data-type="slider"
data-device="Device"
data-set="Track"
data-get="currentTrack"
data-max="currentMenumaxItems" data-min="0"
data-step="1"
data-handle-diameter="5"
data-width="250"
class="horizontal tap inline">
</div>
<div data-type="label" data-device="Device" data-get="numberOfTracks" class="inline center-align" style="width: 3em;"></div>
</div>
</div>
-->

<div data-type="classchanger" data-device="Device" data-get="playback_input" data-get-on="server" data-off-class="hide">
<div style="height: 40px;"> </div> <!-- Leerer Ersatz für die bei Server fehlende Positionsanzeige -->
</div>

<div data-type="classchanger" data-device="Device" data-get="playback_input" data-get-on="net_radio" data-off-class="hide">
<div style="height: 40px;"> </div> <!-- Leerer Ersatz für die bei Streams fehlende Positionsanzeige -->
</div>


<div class="large top-space">
<div data-type="classchanger" data-device="Device" data-get="playback_input" data-get-on="server" data-off-class="hide">
<div style="height: 21px;">
<div style="width: 355px; position: absolute; overflow: hidden; height: 21px; margin-left: 10px; margin-right: 10px;">
<div style="position: absolute;">
<div id="Device_Title" data-type="joinedlabel" data-device="Device" data-mask="[$1]" data-get='["track"]' data-onupdate="checkFlowAnimation('#Device_Title');" class="bold"></div>
</div>
</div>
</div>

<div style="height: 21px;">
<div style="width: 355px; position: absolute; overflow: hidden; height: 21px; margin-left: 10px; margin-right: 10px;">
<div style="position: absolute;">
<div id="Device_Interpret" data-type="joinedlabel" data-device="Device" data-mask="[$1]" data-get='["station_name"]' data-onupdate="checkFlowAnimation('#Device_Interpret');" class="">
</div>
</div>
</div>
</div>
</div>
<div data-type="classchanger" data-device="Device" data-get="playback_input" data-get-on="net_radio" data-off-class="hide">
<div style="height: 21px;">
<div style="width: 355px; position: absolute; overflow: hidden; height: 21px; margin-left: 10px; margin-right: 10px;">
<div style="position: absolute;">
<div id="Device_SenderInfo" data-type="joinedlabel" data-device="Device" data-mask="[$1]" data-get='["track"]' data-onupdate="checkFlowAnimation('#Device_SenderInfo');" class="bold"></div>
</div>
</div>
</div>

<div style="height: 21px;">
<div style="width: 355px; position: absolute; overflow: hidden; height: 21px; margin-left: 10px; margin-right: 10px;">
<div style="position: absolute;">
<div id="Device_Sender" data-type="joinedlabel" data-device="Device" data-mask="[$1]" data-get='["station_name"]' data-onupdate="checkFlowAnimation('#Device_Sender');"class=""></div>
</div>
</div>
</div>
</div>
</div>

<!-- Mute button -->
<div class="top-space">
<div data-type="switch" data-device="Device" data-get="mute" data-set="mute"
data-icon="fa-deaf" data-background-icon="-"
data-on-color="#aa6900" data-off-color="gray"
data-get-on="true" data-get-off="false"
data-set-on="true" data-set-off="false" class="inline mini">
</div>


<div data-type="classchanger" data-device="Device" data-get="playback_input" data-get-on="server" data-off-class="hide" class="inline top-space">
<!-- Toggle Repeat funktioniert grundsätzlich, braucht aber etwas bis der Status farblich richtig angezeigt wird und zeigt in der zwischenzeit die falsche Farbe. Warum?
-->
<div data-type="switch" data-device="Device"
data-get="repeat_status"
data-set="toggleRepeat"
data-background-icon="-"
data-states='["off","one","all"]'
data-icons='["fa-repeat","fa-repeat","fa-repeat"]'
data-colors='["gray","red","#aa6900"]'
data-set-states='["one","all","off"]'
class="inline mini">
</div>

<!-- track zurück -->
<div data-type="push" data-device="Device"
data-icon="fa-step-backward" data-background-icon="-"
data-off-color="#fff" data-on-color="#aa6900"
data-set-on="playback previous" class="inline mini">
</div>

<!-- fast backward -->
<div data-type="push" data-device="Device"
data-icon="fa-backward" data-background-icon="-"
data-off-color="#fff" data-on-color="#aa6900"
data-set-on="playback fast_reverse_start"
data-set-off="playback fast_reverse_end" class="inline mini">
</div>
</div>

<!-- play, pause, stop -->
<div data-type="switch"
data-device="Device"
data-get="playback_status"
data-states='["play","pause","stop"]'
data-set="playback"
data-set-states='["pause","play","play"]'
data-background-icon="fa-circle-thin"
data-background-colors='["#aa6900","white","white"]'
data-colors='["#aa6900","white","white"]'
data-icons='["fa-pause","fa-play","fa-play"]'
class="inline small">
</div>

<!-- fast forward -->
<div data-type="classchanger" data-device="Device" data-get="playback_input" data-get-on="server" data-off-class="hide" class="inline">
<div data-type="push" data-device="Device"
data-icon="fa-forward" data-background-icon="-"
data-off-color="#fff" data-on-color="#aa6900"
data-set-on="playback fast_forward_start"
data-set-off="playback fast_forward_end" class="inline mini">
</div>

<!-- next track -->
<div data-type="push" data-device="Device"
data-icon="fa-step-forward" data-background-icon="-"
data-off-color="#fff" data-on-color="#aa6900"
data-set-on="playback next" class="inline mini">
</div>

<!-- toggle shuffle -->
<div data-type="switch" data-device="Device" data-get="shuffle_status" data-set="toggleShuffle"
data-icon="fa-random" data-background-icon="-"
data-on-color="#aa6900" data-off-color="gray"
data-get-on="on" data-get-off="off"
data-set-on="1" data-set-off="0" class="inline mini">
</div>

</div>

<!-- Menu button -->
<div data-type="popup" class="inline" data-width="650px" data-height="210px">
<div data-type="push"
data-icon="fa-list" data-background-icon="-"
data-off-color="#fff" data-on-color="#aa6900"
class="mini">
</div>


<!--
Menü für Auswahl Favoriten noch in Arbeit, aktuelles Coding ist noch das Sonos Original ohne Funktion für Yamaha
-->
<div class="dialog">
<header><div data-type="joinedlabel" data-device="Device" data-mask="Musikauswahl[ für $1]" data-get='["location_name"]' class="inline"></div></header>

<div class="top-space-10 left-align left-space">
<div>
<div class="large middle inline">Favoriten: </div>
<div data-type="select"
data-device="Device"
data-list="FavouritesList"
data-alias="FavouritesListAlias"
data-delimiter="|"
data-quote="/"
data-get="currentFavouriteNameMasked"
data-set="StartFavourite"
class="inline w3x"
onchange="$('.dialog-close').trigger('click');"></div>
</div>

<div>
<div class="large middle inline">Playlists: </div>
<div data-type="select"
data-device="Device"
data-list="PlaylistsList"
data-alias="PlaylistsListAlias"
data-delimiter="|"
data-quote="/"
data-get="currentPlaylistNameMasked"
data-set="StartPlaylist"
class="inline w3x"
onchange="$('.dialog-close').trigger('click');"></div>
</div>

<div>
<div class="large middle inline">Radios: </div>
<div data-type="select"
data-device="Device"
data-list="RadiosList"
data-alias="RadiosListAlias"
data-delimiter="|"
data-quote="/"
data-get="currentRadioNameMasked"
data-set="StartRadio"
class="inline w3x"
onchange="$('.dialog-close').trigger('click');"></div>
</div>

<div>
<div class="large middle inline">Audio-Eingang: </div>
<div data-type="select"
data-device="Device"
data-list="Sonos:LineInPlayerList"
data-alias="Sonos:LineInPlayerListAlias"
data-delimiter="|"
data-get="currentAlbum"
data-set="PlayURI"
class="inline w3x"
onchange="$('.dialog-close').trigger('click');"></div>
</div>

<div>
<div class="large middle inline">Abspielliste: </div>
<div data-type="select"
data-device="Device"
data-list="QueueList"
data-alias="QueueListAlias"
data-delimiter="|"
data-get="currentTrack"
data-set="Track"
class="inline w3x"
onchange="$('.dialog-close').trigger('click');"></div>
</div>
</div>
</div>
</div>
</div>

<!-- Lautstärke einstellen -->
<div data-type="spinner"
data-device="Device"
data-get="volume"
data-set="volume"
data-max="100"
data-step="1"
data-width="350"
data-icon-left="fa-volume-down tall"
data-icon-right="fa-volume-up tall"
data-gradient-color='["orange","red"]'
class="tap value positiononly top-space centered">
</div>

</div>




Was jetzt noch offen ist:
- Play Time und Total Time: falls es irgendwie aus dem Yamaha rauszukriegen ist
- Icon für die Quelle der Musik (z.B. Spotify, Amazon Music etc.), scheint Yamaha nicht zu liefern aber könnte ja lokal nachgebaut werden
- Menü für die Ansteuerung der Favoriten, etc.
- Multi-Room setup
- Anzeige Toggle Repeat button: er funktioniert zwar richtig, und zeigt nach kurzer Zeit auch den Status richtig an, aber nach jedem Umschalten ist die Farbe kurz falsch, keine Plan warum
- Formatierung der Player Größe, die aktuelle Einstellung wäre richtig für zwei Player nebeneinander in einem Gridster mit sizex=5m daher sind bei sixex=3 die Knöpfe nicht richtig unter dem Cover zentriert
- und noch ordentlich testen, ich habe vor allem mit MP3 von einem lokalen Server getestet, und etwas net radio. Aber ich habe noch keine anderen Provider wie Amazon Music auf dem Gerät eingerichtet und getestet

Beste Grüße
MrNatcho
FHEM auf Ubuntu Server VM auf Synology NAS, Yamaha MC's, Technoline Temperatur-Sensoren über Lacrosse GW's, HM-IP Devices über virtual CCU aus Raspberry Pi

RockThisParty

Moin in die Runde!

Ich habe mal eine Frage, die leicht off-topic für diesen Thread ist, ich hoffe aber, dass hier am ehesten die Musiccast-Nutzer lesen:

Hat jemand von Euch Musiccast via FHEM mit Homebridge/Siri im Einsatz?

Ich rätsele noch, wie ich das am besten einbinde.

Danke und Grüße,
Stefan

jhohmann

Hallo,

bei mir hat das mit dem Modul YAMAHA_MC leider nicht gut funktioniert. Wenn das Modul in FHEM aktiv war, konnte ich bereits nach wenigen Tagen meine Box WX-021 nicht mehr erreichen, weder über FHEM noch über die Musicast App auf dem Handy. Nur ein Reset hat geholfen.
Woran das liegt, habe ich nicht weiter untersucht, da mir dafür ein Ansatz fehlt.

Da ich die Box aber weiterhin im Schlafzimmer als Berieselung morgens und abends einsetzen wollte, habe ich mir eine kleine Funktionssammlung zusammengestellt und diese über einen Dummy mit passendem Notofy nutzbar gemacht.
Um die Funktionen erstellen zu können, habe ich einige Infos und URLs aus einem Dokument mit dem Namen "Yamaha_Extended_Control_API_Specification_(Basic).pdf" entnommen. Wenn ihr das hier für euch erweitern wollt, einfach nach diesem Namen googlen.
Um die Perl-Funktionen einzubinden, muss die angehängte 99_myUtils_mc.pm im Ordner /opt/fhem/FHEM abgelegt und FHEM neu gestartet werden.

Dem Dummy habe ich einige User Attribute gegönnt:
HOST: IP des Musicast Geräts
zone: Die zu steuerende Zone (bei mir gibt es nur main).
defaultVolume: Die Lautstärke, die nach dem Einschalten aktiv sein soll.
defaultFavorite: Name des Favoriten, der nach dem Einschalten aktiv sein soll. Das Mapping zwischen den Namen von Favoriten und der internen Nummer muss händisch im Notify erfolgen.
Die Namen der im Gerät gespeicherten Favoriten sind im Attribut setList beim Dummy fest hinterlegt und muss von euch manuell gepflegt werden.
Einen automatischen Abgleich mit der Box gibt es hier nicht.
Der Dummy ist bei mir auch über das Handy über die Homebridge ansprechbar. Dafür sind die Attribute genericDeviceType und homebridgeMapping hier gepflegt.

Folgende Befehle können abgesetzt werden:
set <Name> on|off      Gerät ein- oder ausschalten
set <Name> volume <Zahl>   Lautstärke auf einen bestimmten Wert setzen
set <Name> volumeStep up|down   Lautstärke einen Schritt erhöhen/reduzieren
set <Name> favorite <...>      Favorit wechseln auf ...
set <Name> dimmer 0|1|2         LED Licht auf den Wert 0, 1 oder 2 setzen

Hier mein Dummy (als RAW Definition):

defmod SchlafzimmerBox dummy
attr SchlafzimmerBox userattr HOST zone defaultVolume defaultFavorite
attr SchlafzimmerBox HOST 192.168.168.20
attr SchlafzimmerBox defaultFavorite SWR3
attr SchlafzimmerBox defaultVolume 10
attr SchlafzimmerBox devStateIcon on:audio_volume_high@green off:audio_volume_low@red
attr SchlafzimmerBox event-on-change-reading .*
attr SchlafzimmerBox event-on-update-reading volumeStep
attr SchlafzimmerBox genericDeviceType media
attr SchlafzimmerBox homebridgeMapping clear\
Mute=state,valueOn=off,cmdOn=off,cmdOff=on\
On=state,valueOn=on,cmdOn=on,cmdOff=off\
Volume=volume::volume,minValue=10,maxValue=33,delay=1
attr SchlafzimmerBox icon audio_volume_high
attr SchlafzimmerBox readingList volumeStep volume favorite dimmer
attr SchlafzimmerBox room Homekit,Schlafzimmer
attr SchlafzimmerBox setList state:uzsuToggle,on,off volumeStep:down,up volume:slider,10,1,40 favorite:SWR3,1live,Meeresrauschen,Naturgeraeusche,Vogelstimmen,KleinerBach,Wasserplätschern dimmer:0,1,2
attr SchlafzimmerBox webCmd state:volumeStep:volume:favorite:dimmer
attr SchlafzimmerBox webCmdLabel State:VolumeStep:Volume:Favorite:Dimmer
attr SchlafzimmerBox zone main


Beim Notify und auch bei den Perl-Funktionen habe ich versucht, den Namen des Geräts selbst intern zu vermeiden. Somit ist die Anpassung an euren eigenen Namen hoffentlich sehr einfach machbar.
Und hier das Notify (ebenfalls als RAW Definition):

defmod ntSchlafzimmerBox notify SchlafzimmerBox:.* {\
my $status = ReadingsVal($NAME,"mute","off");;\
if ($EVENT eq "on") {\
  fhem("cancel idVolumeTimerFor".$NAME." quiet");;\
  fhem("cancel idOff".$NAME." quiet");;\
  fhem("setreading ".$NAME." mute on");;\
  mcSetPower($NAME, "on");;\
  fhem("sleep 4;;set ".$NAME." dimmer 1;;sleep 0.5;;set ".$NAME." favorite ".ReadingsVal($NAME,"defaultFavorite","SWR3"));;\
} elsif ($EVENT eq "standby" || $EVENT eq "off") {\
  fhem("cancel idVolumeTimerFor".$NAME." quiet");;\
  fhem("cancel idOff".$NAME." quiet");;\
  fhem("sleep 0.2;;set ".$NAME." favorite ".ReadingsVal($NAME,"defaultFavorite","SWR3").";;sleep 1;;set ".$NAME." volume ".AttrVal($NAME, "defaultVolume", 10).";;sleep 4;;{mcSetPower(\"".$NAME."\",\"standby\")};;setreading ".$NAME." mute off");;\
} elsif ($EVENT =~ /volumeStep/) {\
  my @array = split(/ /,$EVENT);;\
  if ($array[1] eq "up") {\
    my $vol = ReadingsNum($NAME,"volume",10);;\
my $newvol = $vol + 1;;\
    fhem("sleep 0.1;;set ".$NAME." volume ".$newvol);;\
  } elsif ($array[1] eq "down") {\
    my $vol = ReadingsNum($NAME,"volume",10);;\
my $newvol = $vol - 1;;\
    fhem("sleep 0.1;;set ".$NAME." volume ".$newvol);;\
  }\
} elsif ($EVENT =~ /volume/) {\
  my @array = split(/ /,$EVENT);;\
  mcSetVolume($NAME,$array[1]);;\
} elsif ($EVENT =~ /dimmer/) {\
  my @array = split(/ /,$EVENT);;\
  mcSetDimmer($NAME,$array[1]);;\
} elsif ($EVENT =~ /favorite/) {\
  fhem("cancel idOff".$NAME." quiet");;\
  my @array = split(/ /,$EVENT);;\
  # Hier wird dem Namen eines Favoriten zum einen die interne Nummer im Gerät zugewiesen (die Liste beginnt immer bei 1)\
  # weiterhin die zu setzende Lautstärke und eine Zeitdauer, die ein Timer in Sekunden zum Ausschalten haben soll (0 ist aus).\
  # Die letzte Angabe steuert, mit welchem Abstand bei einem Timer die Lautstärke reduziert werden soll.\
  my %favToNumber = (\
    "SWR3"=>"1,24,0,0",\
    "1live"=>"2,24,0,0",\
    "Meeresrauschen"=>"3,17,1200,30",\
    "Naturgeraeusche"=>"4,17,1200,30",\
    "Vogelstimmen"=>"5,20,1200,30",\
    "KleinerBach"=>"8,23,1200,30",\
    "Wasserplätschern"=>"9,20,1200,30",\
  );;\
  my $value = $favToNumber{$array[1]};;\
  my ($index,$lautstaerke,$timer,$pause) = split(/,/,$value);;\
  if ($timer > 0 && $pause > 0) {\
    fhem("sleep ".$timer." idOff".$NAME.";;set ".$NAME." dimmer 0;;sleep 0.5;;{mcVolumeDown(\"".$NAME."\", 1, 10, ".$pause.")}");;\
  }\
  mcSetFavorite($NAME, $index);;\
  fhem("sleep 0.5;;set ".$NAME." volume ".$lautstaerke);;\
}\
}

Wenn die Perl-Funktionen das Gerät erreichen können, wird in FHEM am Dummy ein Reading namens lastupdate aktualisiert. Das entspricht dann dem Wert von time (aktuelle Zeit als ganze Zahl).
Damit kann dann auch geprüft werden, ob eventuell die Verbindung abgebrochen ist.
Im Fehlerfall setzen die Perl-Funktionen den Dummy auf den state off.
Der Dummy hat den Nachteil, dass seine Readings quasi immer zuerst geändert werden, bevor das Notify die Funktion wirklich ausführt.
Beispiel: Gerät ist aus, aber die Lautstärke wird am Dummy verändert. Das Reading volume wird geändert, aber am Gerät selbst passiert nichts. Das kann also auseinander laufen!
Neben den reinen Perl-Funktionen zum Steuern habe ich noch zwei gesonderte Funktionen eingebaut. Damit kann die Lautstärke langsam erhöht werden. Das Gerät wird eingeschaltet, falls es vorher aus war.
Oder die Lautstärke wird langsam reduziert und das Gerät bei Erreichen einer Minimallautstärke ausgeschaltet.
Beispiel:
{mcVolumeUp("SchlafzimmerBox", 1, 22, 3)}
Gerät einschalten, falls aus. Dann in 1er Schritten die Lautstärke erhöhen bis 22 erreicht ist. Zwischen den Erhöhungen immer 3 Sekunden Pause.
{mcVolumeDown("SchlafzimmerBox", 1, 10, 30)}
Lautstärke am Gerät in 1er Schritten reduzieren bis 10 erreicht ist, dann ausschalten. Zwischen den Reduzierungen immer 30 Sekunden Pause. Wenn das Gerät aus war, passiert nichts weiter.
Raspberry Pi 4 - bookworm / EnOcean - Rollo+Licht, deCONZ - Licht+Sensoren, ZWave - CO Messung, HMCCU mit piVCCU - Heizung+Rollo
plus dovecot, minidlna

sprudelverduenner

Zitat von: Leugi am 16 Januar 2021, 18:47:56
Ich habe nun toggleShuffle und die Readings für Repeat und Shuffle implementiert.

Hallo Leugi,

für mich hätte es einen großen Nutzen, wenn ich den Shuffle explizit mit einem Befehl an oder aus und nicht nur toggeln könnte.

Wäre es möglich das zu implementieren?
Über das Webinterface meines MusicCast Gerätes kann ich den Shuffle auch direkt schalten...

Beste Grüße,
Sprudelverduenner
FHEM @ RaspberryPi 3, HMLAN, HMUART + HMRS485, Homematic, ESPEasy @ Sonoff / Shelly / ESP8266, ZigBee @ CC2531
Echo Dot, Dreambox, Yamaha MusicCast, Logitech Hub, LW-12, LD382
FRITZ!Box 7590 AX, Mesh @ FRITZ!Repeater 2400, FRITZ!Fon, iPhone 13, iPad Air 5, AppleWatch 8