miracle2k / onkyo-eiscp

Control Onkyo A/V receivers over the network; usuable as a script, or as a Python library.
MIT License
472 stars 110 forks source link

fireconnect / multiroom audio #158

Open rlKoekie opened 8 months ago

rlKoekie commented 8 months ago

More of a question than an issue: has anybody looked into the Onkyo Multiroom audio (aka FireConnect ) functionality? Inside the Onkyo android app this can be enabled via "edit group". Devices added to the group will replicate the audio playing on the first device.

bendamat commented 7 months ago

Hi @rlKoekie, yes I've automated grouping and ungrouping using raw events. You need to provide an XML message to tell the device to connect to the devices.

The easiest way I found is this: Prereq: You need to know the device IDs.

To group the devices, you need to sent the list of secondary devices to the primary device. To ungroup, you tell the secondary devices to quit the group.

Example: Grouping message sent to primary device: MGS<mgs zone="1"><groupid>1</groupid><maxdelay>500</maxdelay><devices><device id="primary_device_id" zoneid="1"/><device id="secondary_device_id" zoneid="1"/></devices></mgs>

Ungrouping message sent to secondary device: MGS<mgs zone="1"><groupid>0</groupid></mgs>

Hope that helps!

rlKoekie commented 7 months ago

Hey @bendamat, many thanks for this! I'll start playing with this a bit, it does not look too complex. If I manage to get it working I'll try to implement it into the python lib. Thanks again, this saves me a lot of searching

rlKoekie commented 7 months ago

@bendamat thanks again, your example made it quite easy to get this working. I've implemented a group_with function and made a pull request

rlKoekie commented 7 months ago

I've got a follow-up question, hoping @bendamat has more knowledge: Is there also a command to query the current grouping state of the receiver? The Onkyo android app knows how to do this (in the edit group menu), so it should be possible? I've been trying a few things to query this data from the receiver, but so far no luck...

bendamat commented 7 months ago

Hi @rlKoekie I don't recall exactly, but yes, I remember that there was a command that included the current grouping state. I'm going to see if I can find it again somewhere. I'll keep you posted

bendamat commented 7 months ago

I haven't tried it yet, I'm not able to test right now, but you could have a look at the NMS / net-usb-menu-status commands. Does the query command tell you the current state? I'd expect it to at least tell you that the device is part of a group.

rlKoekie commented 7 months ago

Hi @bendamat , thanks for getting back to me! Unfortunately the net-usb-menu-status command is not telling much:

onkyo --host 192.168.178.31 dock.net-usb-menu-status=query
NCP-302: net-usb-menu-status = Mxxxxx243
onkyo --host 192.168.178.30 dock.net-usb-menu-status=query
TX-NR676E: net-usb-menu-status = xxxxxxxff

(The TX-NR676E is the FireConnect host here) The message is the same with the devices grouped and ungrouped. The other possible argument for net-usb-menu-status is 'maabbstii', which generates a timeout in both cases. Also checking for non-matching responses (e.g. any candidate response which does not start with NMS) gives no clues. So more hints are very welcome :smile:

rlKoekie commented 7 months ago

I made some progress here. For others looking into this, a newer version of the documentation had some details. I found them here: https://github.com/mkulesh/onpc/tree/master/doc/ISCP (the 146 document)

The multiroom audio status can be queried with the MDIQSTN raw command. When my receivers are NOT grouped, the response looks something like this:

receiver.raw('MDIQSTN')
MDI<?xml version="1.0"?><mdi><deviceid>0009B0E7BE48</deviceid><netstandby>1</netstandby><currentversion>200</currentversion><zonelist><zone id="1" groupid="0" ch="ST" role="none" roomname="TX-NR676E - Main" groupname="" powerstate="1" iconid="9" color="0" delay="5000"/><zone id="2" groupid="0" ch="ST" role="none" roomname="TX-NR676E - Zone2" groupname="" powerstate="0" iconid="0" color="0" delay="5000"/><zone id="3" groupid="0" ch="ST" role="none" roomname="" groupname="" powerstate="0" iconid="0" color="0" delay="5000"/><zone id="4" groupid="0" ch="ST" role="none" roomname="" groupname="" powerstate="0" iconid="0" color="0" delay="5000"/></zonelist></mdi>

The important parts here are groupid="0" and role="none" in the zone id="1" section. When grouping the two receivers ("receiver" being the source, "receiver2" being the destination), it looks like this:

receiver.raw('MDIQSTN')
MDI<?xml version="1.0"?><mdi><deviceid>0009B0E7BE48</deviceid><netstandby>1</netstandby><currentversion>200</currentversion><zonelist><zone id="1" groupid="1" ch="ST" role="src" roomname="TX-NR676E - Main" groupname="" powerstate="1" iconid="9" color="0" delay="5000"/><zone id="2" groupid="0" ch="ST" role="none" roomname="TX-NR676E - Zone2" groupname="" powerstate="0" iconid="0" color="0" delay="5000"/><zone id="3" groupid="0" ch="ST" role="none" roomname="" groupname="" powerstate="0" iconid="0" color="0" delay="5000"/><zone id="4" groupid="0" ch="ST" role="none" roomname="" groupname="" powerstate="0" iconid="0" color="0" delay="5000"/></zonelist></mdi>

receiver2.raw('MDIQSTN')
MDI<?xml version="1.0"?><mdi><deviceid>0009B0E4B723</deviceid><netstandby>1</netstandby><currentversion>200</currentversion><zonelist><zone id="1" groupid="1" ch="ST" role="dst" roomname="" groupname="" powerstate="1" iconid="0" color="0" delay="3000"/><zone id="2" groupid="0" ch="ST" role="none" roomname="" groupname="" powerstate="0" iconid="0" color="0" delay="3000"/><zone id="3" groupid="0" ch="ST" role="none" roomname="" groupname="" powerstate="0" iconid="0" color="0" delay="3000"/><zone id="4" groupid="0" ch="ST" role="none" roomname="" groupname="" powerstate="0" iconid="0" color="0" delay="3000"/></zonelist></mdi>

Both receivers have switched to groupid="1" (it can also be another value, but non-zero and matching with the other devices in the group), and have their role="src" or role="dst" for source and destination.

I'll write some code to make this a bit more easy-to-use from the command line / python module.