net_radio almost works on RX-A2010 on 0.7.0rc2
@wuub After your changes for #58 I went ahead and tried 0.7.0rc2 on my RX-A2010
It failed with some errors, I'm not an expert in python so I can't really send a PR but I'm sure I have enough info for you to fix it quickly. This was the main error after executing
rx.net_radio('My Stations>Favourites>MNM')
Traceback (most recent call last):
File "test.py", line 3, in <module>
rx.net_radio('My Stations>Favourites>MNM')
File "/usr/local/lib/python3.8/site-packages/rxv/rxv.py", line 865, in net_radio
self.menu_reset()
File "/usr/local/lib/python3.8/site-packages/rxv/rxv.py", line 708, in menu_reset
while self.menu_status().layer > 1:
File "/usr/local/lib/python3.8/site-packages/rxv/rxv.py", line 608, in menu_status
ready = (next(res.iter("Menu_Status")).text == "Ready")
StopIteration
The call for
<NET_RADIO><List_Info>GetParam</List_Info></NET_RADIO>
responds on this system with:
<YAMAHA_AV rsp="GET" RC="0"><NET_RADIO><List_Info><Menu_Layer>2</Menu_Layer><Menu_Name>Radiobrowser</Menu_Name><Current_List><Line_1><Txt>Genres</Txt><Attribute>Container</Attribute></Line_1><Line_2><Txt>Countries</Txt><Attribute>Container</Attribute></Line_2><Line_3><Txt>Languages</Txt><Attribute>Container</Attribute></Line_3><Line_4><Txt>Most Popular</Txt><Attribute>Container</Attribute></Line_4><Line_5><Txt></Txt><Attribute>Unselectable</Attribute></Line_5><Line_6><Txt></Txt><Attribute>Unselectable</Attribute></Line_6><Line_7><Txt></Txt><Attribute>Unselectable</Attribute></Line_7><Line_8><Txt></Txt><Attribute>Unselectable</Attribute></Line_8></Current_List><Cursor_Position><Current_Line>1</Current_Line><Max_Line>4</Max_Line></Cursor_Position></List_Info></NET_RADIO></YAMAHA_AV>
In this receiver, there is no Menu_Status. I hacked it on my local install by doing - not sure if we can do something smarter there to set it to "not_available" or something (see later)
ready = 1
Inside the loop I did sleep as well (since there is no ready) state, maybe we can only sleep if "not_available" is set ?
868 if menu.ready:
869 time.sleep(1)
870 for line, value in menu.current_list.items():
This went a little further, until the CURSOR_RETURN which does not seem to exist here.
I changed CURSOR_RETURN to "Back" and that seems to work.
CURSOR_RETURN = "Back"
So with these 3 changes it should also work on RX-A20** models I suppose. If you need some desc.xml posted, just let me know, glad to assist!
@slyoldfox having the portion of the desc.xml that relates to the net radio feature would be helpful.
Look for the part that contains YNC_Tag="NET_RADIO", then find the very next occurrence of Menu Func="Cursor". This lists the valid commands for the net radio feature.
Example: https://github.com/wuub/rxv/blob/da90b758da6e1cd5082bd8931f183662e54b1903/tests/samples/rx-v675-desc.xml#L1859-L1865
This should give you all you need:
<Menu Func="Source_Device" YNC_Tag="NET_RADIO">
<Menu Func="Status" Title_1="Device">
<Get>
<Cmd ID="G3">Feature_Availability=Param_1</Cmd>
<Param_1>
<Direct Func="Status_Ready">Ready</Direct>
<Direct Func="Status_Not Connected" Title_1="Not Ready">Not Connected</Direct>
</Param_1>
</Get>
</Menu>
<Menu Func="Play_Control" Title_1="Play Control">
<Menu Func="Playback" Title_1="Play">
<Put_1 ID="P1" Func="Play">Play</Put_1>
<Put_1 ID="P1" Func="Stop">Stop</Put_1>
<Get>
<Cmd ID="G1">Playback_Info=Param_1</Cmd>
<Param_1>
<Direct Func="Play">Play</Direct>
<Direct Func="Stop">Stop</Direct>
</Param_1>
</Get>
</Menu>
<Menu Func="Preset" Title_1="Preset" List_Type="Slider">
<Put_2>
<Cmd ID="P6">Param_1</Cmd>
<Param_1>
<Indirect ID="G4"/>
</Param_1>
</Put_2>
</Menu>
</Menu>
<Menu Func="Play_Info" List_Type="With_Pic" Title_1="Play Info.">
<Menu Func="Station" Title_1="Station">
<Get>
<Cmd ID="G1">Meta_Info,Station=Param_1</Cmd>
<Param_1>
<Text>0,128,UTF-8</Text>
</Param_1>
</Get>
</Menu>
<Menu Func="Status" Title_1="Device">
<Get>
<Cmd ID="G1">Feature_Availability=Param_1</Cmd>
<Param_1>
<Direct Func="Status_Ready">Ready</Direct>
<Direct Func="Status_Not_Connected" Title_1="Not Ready">Not Connected</Direct>
</Param_1>
</Get>
</Menu>
<Menu Func="Playback" Title_1="Status">
<Get>
<Cmd ID="G1">Playback_Info=Param_1</Cmd>
<Param_1>
<Direct Func="Play">Play</Direct>
<Direct Func="Stop">Stop</Direct>
</Param_1>
</Get>
</Menu>
<Menu Func="Album_ART_URL" Title_1="AlbumART URL">
<Get>
<Cmd ID="G1">Album_ART,URL=Param_1</Cmd>
<Param_1>
<Text>0,128,UTF-8</Text>
</Param_1>
</Get>
</Menu>
<Menu Func="Album_ART_ID" Title_1="AlbumART ID">
<Get>
<Cmd ID="G1">Album_ART,ID=Param_1</Cmd>
<Param_1>
<Range>0,255,1</Range>
</Param_1>
</Get>
</Menu>
<Menu Func="Album_ART_Format" Title_1="AlbumART Format">
<Get>
<Cmd ID="G1">Album_ART,Format=Param_1</Cmd>
<Param_1>
<Direct Func="BMP">BMP</Direct>
<Direct Func="YMF">YMF</Direct>
</Param_1>
</Get>
</Menu>
</Menu>
<Menu Func="List_Browse" Title_1="List Browse">
<Menu Func="List_Control" Title_1="List Control">
<Menu Func="Direct_Sel" Title_1="Direct Cursor Select">
<Put_2>
<Cmd ID="P2">Param_1</Cmd>
<Param_1>
<Range>1,8,1,Line_%</Range>
</Param_1>
</Put_2>
</Menu>
<Menu Func="Cursor" List_Type="Cursor" Title_1="Cursor">
<Put_1 ID="P4" Func="Cursor_Up">Up</Put_1>
<Put_1 ID="P4" Func="Cursor_Down">Down</Put_1>
<Put_1 ID="P4" Func="Cursor_Left">Back</Put_1>
<Put_1 ID="P4" Func="Cursor_Sel">Sel</Put_1>
<Put_1 ID="P4" Func="Cursor_Home">Back to Home</Put_1>
</Menu>
<Menu Func="Jump_Line" Title_1="Jump Page">
<Put_2>
<Cmd ID="P3">Param_1</Cmd>
<Param_1>
<Range>1,65536,1</Range>
</Param_1>
</Put_2>
</Menu>
<Menu Func="Page_Up_Down" Title_1="Page">
<Put_1 ID="P5" Func="Page_Up_1">Up</Put_1>
<Put_1 ID="P5" Func="Page_Down_1">Down</Put_1>
</Menu>
<Menu Func="Bookmark" Title_1="Bookmark">
<Put_1 ID="P7" Func="Bookmark_On">On</Put_1>
<Put_1 ID="P7" Func="Bookmark_Off">Off</Put_1>
</Menu>
</Menu>
<Menu Func="List_Info" Title_1="List Info.">
<Menu Func="Menu_Layer" Title_1="Menu Layer">
<Get>
<Cmd ID="G2">Menu_Layer=Param_1</Cmd>
<Param_1>
<Range>1,16,1</Range>
</Param_1>
</Get>
</Menu>
<Menu Func="Menu_Name" Title_1="Menu Name">
<Get>
<Cmd ID="G2">Menu_Name=Param_1</Cmd>
<Param_1>
<Text>0,128,UTF-8</Text>
</Param_1>
</Get>
</Menu>
<Menu Func="Menu_List" Title_1="Menu List">
<Menu Func="Menu_Line" Title_1="Line 1">
<Put_1 ID="P2">Line_1</Put_1>
<Get>
<Cmd Type="Container" ID="G2">Current_List,Line_1,Txt=Param_1:Current_List,Line_1,Attribute=Param_2</Cmd>
<Param_1 Func="Menu_Txt">
<Text>0,128,UTF-8</Text>
</Param_1>
<Param_2 Func="Menu_Type">
<Direct Func="Menu_Next">Container</Direct>
<Direct Func="Menu_Stay">Unplayable Item</Direct>
<Direct Func="Menu_Play">Item</Direct>
<Direct Func="Menu_Prohibit">Unselectable</Direct>
</Param_2>
</Get>
</Menu>
<Menu Func="Menu_Line" Title_1="Line 2">
<Put_1 ID="P2">Line_2</Put_1>
<Get>
<Cmd Type="Container" ID="G2">Current_List,Line_2,Txt=Param_1:Current_List,Line_2,Attribute=Param_2</Cmd>
<Param_1 Func="Menu_Txt">
<Text>0,128,UTF-8</Text>
</Param_1>
<Param_2 Func="Menu_Type">
<Direct Func="Menu_Next">Container</Direct>
<Direct Func="Menu_Stay">Unplayable Item</Direct>
<Direct Func="Menu_Play">Item</Direct>
<Direct Func="Menu_Prohibit">Unselectable</Direct>
</Param_2>
</Get>
</Menu>
<Menu Func="Menu_Line" Title_1="Line 3">
<Put_1 ID="P2">Line_3</Put_1>
<Get>
<Cmd Type="Container" ID="G2">Current_List,Line_3,Txt=Param_1:Current_List,Line_3,Attribute=Param_2</Cmd>
<Param_1 Func="Menu_Txt">
<Text>0,128,UTF-8</Text>
</Param_1>
<Param_2 Func="Menu_Type">
<Direct Func="Menu_Next">Container</Direct>
<Direct Func="Menu_Stay">Unplayable Item</Direct>
<Direct Func="Menu_Play">Item</Direct>
<Direct Func="Menu_Prohibit">Unselectable</Direct>
</Param_2>
</Get>
</Menu>
<Menu Func="Menu_Line" Title_1="Line 4">
<Put_1 ID="P2">Line_4</Put_1>
<Get>
<Cmd Type="Container" ID="G2">Current_List,Line_4,Txt=Param_1:Current_List,Line_4,Attribute=Param_2</Cmd>
<Param_1 Func="Menu_Txt">
<Text>0,128,UTF-8</Text>
</Param_1>
<Param_2 Func="Menu_Type">
<Direct Func="Menu_Next">Container</Direct>
<Direct Func="Menu_Stay">Unplayable Item</Direct>
<Direct Func="Menu_Play">Item</Direct>
<Direct Func="Menu_Prohibit">Unselectable</Direct>
</Param_2>
</Get>
</Menu>
<Menu Func="Menu_Line" Title_1="Line 5">
<Put_1 ID="P2">Line_5</Put_1>
<Get>
<Cmd Type="Container" ID="G2">Current_List,Line_5,Txt=Param_1:Current_List,Line_5,Attribute=Param_2</Cmd>
<Param_1 Func="Menu_Txt">
<Text>0,128,UTF-8</Text>
</Param_1>
<Param_2 Func="Menu_Type">
<Direct Func="Menu_Next">Container</Direct>
<Direct Func="Menu_Stay">Unplayable Item</Direct>
<Direct Func="Menu_Play">Item</Direct>
<Direct Func="Menu_Prohibit">Unselectable</Direct>
</Param_2>
</Get>
</Menu>
<Menu Func="Menu_Line" Title_1="Line 6">
<Put_1 ID="P2">Line_6</Put_1>
<Get>
<Cmd Type="Container" ID="G2">Current_List,Line_6,Txt=Param_1:Current_List,Line_6,Attribute=Param_2</Cmd>
<Param_1 Func="Menu_Txt">
<Text>0,128,UTF-8</Text>
</Param_1>
<Param_2 Func="Menu_Type">
<Direct Func="Menu_Next">Container</Direct>
<Direct Func="Menu_Stay">Unplayable Item</Direct>
<Direct Func="Menu_Play">Item</Direct>
<Direct Func="Menu_Prohibit">Unselectable</Direct>
</Param_2>
</Get>
</Menu>
<Menu Func="Menu_Line" Title_1="Line 7">
<Put_1 ID="P2">Line_7</Put_1>
<Get>
<Cmd Type="Container" ID="G2">Current_List,Line_7,Txt=Param_1:Current_List,Line_7,Attribute=Param_2</Cmd>
<Param_1 Func="Menu_Txt">
<Text>0,128,UTF-8</Text>
</Param_1>
<Param_2 Func="Menu_Type">
<Direct Func="Menu_Next">Container</Direct>
<Direct Func="Menu_Stay">Unplayable Item</Direct>
<Direct Func="Menu_Play">Item</Direct>
<Direct Func="Menu_Prohibit">Unselectable</Direct>
</Param_2>
</Get>
</Menu>
<Menu Func="Menu_Line" Title_1="Line 8">
<Put_1 ID="P2">Line_8</Put_1>
<Get>
<Cmd Type="Container" ID="G2">Current_List,Line_8,Txt=Param_1:Current_List,Line_8,Attribute=Param_2</Cmd>
<Param_1 Func="Menu_Txt">
<Text>0,128,UTF-8</Text>
</Param_1>
<Param_2 Func="Menu_Type">
<Direct Func="Menu_Next">Container</Direct>
<Direct Func="Menu_Stay">Unplayable Item</Direct>
<Direct Func="Menu_Play">Item</Direct>
<Direct Func="Menu_Prohibit">Unselectable</Direct>
</Param_2>
</Get>
</Menu>
</Menu>
<Menu Func="Current_Line" Title_1="Cursor Line">
<Get>
<Cmd ID="G2">Cursor_Position,Current_Line=Param_1</Cmd>
<Param_1>
<Range>1,65536,1</Range>
</Param_1>
</Get>
</Menu>
<Menu Func="Max_Line" Title_1="Max. Line">
<Get>
<Cmd ID="G2">Cursor_Position,Max_Line=Param_1</Cmd>
<Param_1>
<Range>0,65536,1</Range>
</Param_1>
</Get>
</Menu>
</Menu>
</Menu>
<FKey Title="Title_1">
<Path>"Play Info."</Path>
<F3 Title_1="Preset">"Play Control","Preset"</F3>
</FKey>
<FKey Title="Title_1">
<Path>"List Browse"</Path>
<F3 Title_1="Play Info.">"Play Info."</F3>
</FKey>
<FKey Title="Title_1">
<Path/>
<F3 Title_1="Play Info.">"Play Info."</F3>
</FKey>
<SKey Title="Title_1">
<Path/>
<Play>
<Put_1 ID="P1">Play</Put_1>
</Play>
<Stop>
<Put_1 ID="P1">Stop</Put_1>
</Stop>
</SKey>
<Top Title="Title_1">"List Browse"</Top>
<Cmd_List>
<Define ID="P1">NET_RADIO,Play_Control,Playback</Define>
<Define ID="P2">NET_RADIO,List_Control,Direct_Sel</Define>
<Define ID="P3">NET_RADIO,List_Control,Jump_Line</Define>
<Define ID="P4">NET_RADIO,List_Control,Cursor</Define>
<Define ID="P5">NET_RADIO,List_Control,Page</Define>
<Define ID="P6">NET_RADIO,Play_Control,Preset,Preset_Sel</Define>
<Define ID="P7">NET_RADIO,List_Control,Bookmark</Define>
<Define ID="G1">NET_RADIO,Play_Info</Define>
<Define ID="G2">NET_RADIO,List_Info</Define>
<Define ID="G3">NET_RADIO,Config</Define>
<Define ID="G4">NET_RADIO,Play_Control,Preset,Preset_Sel_Item</Define>
</Cmd_List>
</Menu>
basically:
<Menu Func="Cursor" List_Type="Cursor" Title_1="Cursor">
<Put_1 ID="P4" Func="Cursor_Up">Up</Put_1>
<Put_1 ID="P4" Func="Cursor_Down">Down</Put_1>
<Put_1 ID="P4" Func="Cursor_Left">Back</Put_1>
<Put_1 ID="P4" Func="Cursor_Sel">Sel</Put_1>
<Put_1 ID="P4" Func="Cursor_Home">Back to Home</Put_1>
</Menu>
I've been trying to use Home Assistant to change my "NET RADIO" station, but I appear to be experiencing this issue as well. The error in the HA logs is:
sk_wakeup()]>, <Future at 0x...StopIteration>) at /usr/local/
lib/python3.10/asyncio/futures.py:379
Traceback (most recent call last):
File "/usr/local/lib/python3.10/asyncio/events.py", line 80, in _run
self._context.run(self._callback, *self._args)
File "/usr/local/lib/python3.10/asyncio/futures.py", line 381, in _set_state
_copy_future_state(other, future)
File "/usr/local/lib/python3.10/asyncio/futures.py", line 357, in _copy_future_state
dest.set_exception(_convert_future_exc(exception))
TypeError: StopIteration interacts badly with generators and cannot be raised into a Future
2023-01-16 10:05:50.461 WARNING (MainThread) [homeassistant.components.media_player] Updating yamaha medi
a_player took longer than the scheduled update interval 0:00:10
Is this the same issue, and is there a fix possible or coming? Thanks.
@lindsaymarkward I have revisited this today to make it work with my Home Assistant installation 2023.6.2 and RX-A2010
I have tried to make it as painless as possible to patch the existing HA installation (since new releases for this library probably won't happen anytime). Personally I am running HA Core so depending if you are using HA inside Docker you might need to (re)apply this when your container is recreated.
I have pushed a v0.7.0 on my repository https://github.com/slyoldfox/rxv/releases/tag/v0.7.0. On my HA Core installation I can now install it with:
$ source homeassistant/bin/activate # Drop myself in the virtual-env
$ pip3 -v install git+https://github.com/slyoldfox/[email protected]
I created the v0.7.0 tag (which is two commits ahead) so that pip3 install generates the correct version.py otherwise HA overwrites it during startup (because it would generate a random version.py)
Hopefully this works for you!
Thanks! I'll give it a try when I get some time, hopefully soon. 👍