Giter Club home page Giter Club logo

pyheos's People

Contributors

andrewsayre avatar scop avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

pyheos's Issues

Containers and options

pyheos version with the issue: 6.0

**Python version and environment:**3.7 - windows 10 64

Description of problem:
Good morning, everyone,

I'm trying to develop a python 3.7 application to drive a denon ceol n10 Heos chain.
The pyheos library is great because it offers almost the whole toolkit to do this.
However, I'm encountering small difficulties with some pyheos elements.

Problem 1

Indeed, the browsecontainer function is not implemented in source.py.
Browsecontainer requires to pass both source_id and container_id parameters, whereas browse only requests source_id.
Moreover, the payload in response to browsecontainer does not return source_id (it is in the question, but heosource does not return source_id).
don't flip it. And finally, when exploring a local or remote server, only the first level of container
contains a source_id, then to go down in the folder hierarchy you have to use the same source_id.
The solution to this problem is relatively simple, here is what I propose to integrate:

1 in source.py

async def browsecontainer(self,lesid) -> 'Sequence[HeosSource]':
"""Browse the contents of the current source container.""""
if not self._source_id,self:
self._source_id = lesid
items = await self._commands.browsecontainer(self._source_id,self._container_id)
return [HeosSource(self._commands, item) for item in items]

2 in command.py

async def browsecontainer(self, source_id: int,container_id: int) -> Sequence[dict]:
"""Browse a music source container."""
params = {
'sid': source_id, 'cid': container_id
}
response = await self._connection.command(
const.COMMAND_BROWSE, params)
return response.payload

Problem 2

Some commands (such as browsecontainer for example) return a response containing a third
part: Options.
For the containers this option is 21 and allows to know if a container is playable or not.
In other cases the option allows to display other choices like add to the list, or add to favorites etc...
Is it possible to integrate the option in the answer and if so how?

Below is an excerpt from the Heos Cli4.4.4 Browse Source Containers documentation
Command: heos://browse/browse?sid=source_id&cid=container_id&range=start#, end#
Attribute Description Enumeration
sid Source id returned by 'get_music_sources'
command
N/A
cid Container id returned by 'browse' or'search' command
N/A
range Range is start and end record index toreturn. Range parameter is optional.
Omitting range parameter returns allrecords up to a maximum of either 50 or100 records per response.The default maximum number of recordsdepend on the service type.
range starts from 0
count Total number of items available in the container.
NOTE: count value of '0' indicates unknown container size. Controllers
needs to query until the return payload is empty (returned attribute is 0).
0 - unknown

1 - valid count
returned Number of items returned in current response
N/A
id (options) Options available for current browse level Various options are presented as part of
'Browse Source container' command
response.
Supported options under each browse
menu depends on service type and container type.Possible options under browse menu are
listed below:
1 - Add Track to Library
2 - Add Album to Library
3 - Add Station to Library
4 - Add Playlist to Library
5 - Remove Track from Library
6 - Remove Album from Library
7 - Remove Station from Library
8 - Remove Playlist from Library
13 - Create New Station
19 - Add to HEOS Favorites
21 - Playable Container
The following are valid media types:
song
station
genre
artist
album
container
Note: A "yes" for the "container" field as well as the "playable" field implies that the container supports adding all media items to the play queue. Adding all media items of the container to the play queue is performed through "Add containers to queue"command. Note:
The option '21 - Playable Container' indicates that the container that is serving the tracks is playable. This option is mainly helpful with the Windows media share. With the Windows media container, HEOS can't determine if a container has playable tracks or not until the container is browsed for its items. When this option appears in browse response, the Controller software could add a virtual item i.e.
'Play all Tracks' along with presenting tracks in the container. When user selects the virtual item, the controller software could then send play command to play the container.
Note: Following response provides examples of the various media types. The actual response will depend on the source browsed and the hierarchy supported by that source.
Thank you for any suggestions.

Runtime error in connection.py under homeassistant

pyheos version with the issue:
I guess this is the latest pyheos version, running in homeassistant 2021.3.4

Python version and environment:
python 3.8

Description of problem:
I got 21 error messages in home-assistant.log, with increasingly longer tracebacks. The first traceback is shown below.

Traceback (if applicable):

2021-03-22 11:05:33 ERROR (MainThread) [homeassistant] Error doing job: Task exception was never retrieved
Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/pyheos/connection.py", line 179, in _reconnect
    await self._disconnect()
  File "/usr/local/lib/python3.8/site-packages/pyheos/connection.py", line 143, in _disconnect
    await self._response_handler_task
  File "/usr/local/lib/python3.8/site-packages/pyheos/connection.py", line 219, in _response_handler
    commands.remove(event)
ValueError: list.remove(x): x not in list

Additional information:
Denon AVR-X1600H with firmware 1.544.240.

Stopping playback raises TimeoutError

pyheos version with the issue: pyheos==0.6.0

Python version and environment: MacOS 10.14.6 with Python 3.8.3

Description of problem: Second time stopping playback on Heos AMP always causes problems. Was initially debugging why Home Assistant, which is using PyHeos, never can stop playback but noticed that stopping causes problems.

Traceback (if applicable):

In [33]: await player.stop()

In [34]: await player.refresh_state()

In [35]: player.state
Out[35]: 'play'

In [36]: await player.stop()
Task exception was never retrieved
future: <Task finished name='Task-2275' coro=<HeosConnection._handle_event() done, defined at /usr/local/lib/python3.8/site-packages/pyheos/connection.py:280> exception=CommandError('Command timed out')>
Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/pyheos/connection.py", line 265, in command
    response = await asyncio.wait_for(event.wait(), self.timeout)
  File "/usr/local/Cellar/[email protected]/3.8.3_2/Frameworks/Python.framework/Versions/3.8/lib/python3.8/asyncio/tasks.py", line 490, in wait_for
    raise exceptions.TimeoutError()
asyncio.exceptions.TimeoutError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/pyheos/connection.py", line 285, in _handle_event
    if player and (await player.event_update(
  File "/usr/local/lib/python3.8/site-packages/pyheos/player.py", line 356, in event_update
    await self.refresh_now_playing_media()
  File "/usr/local/lib/python3.8/site-packages/pyheos/player.py", line 227, in refresh_now_playing_media
    payload = await self._commands.get_now_playing_state(self._player_id)
  File "/usr/local/lib/python3.8/site-packages/pyheos/command.py", line 75, in get_now_playing_state
    response = await self._connection.command(
  File "/usr/local/lib/python3.8/site-packages/pyheos/connection.py", line 271, in command
    raise CommandError(command, message) from error
pyheos.error.CommandError: Command timed out
Task exception was never retrieved
future: <Task finished name='Task-2282' coro=<HeosConnection._handle_event() done, defined at /usr/local/lib/python3.8/site-packages/pyheos/connection.py:280> exception=CommandError('Command timed out')>
Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/pyheos/connection.py", line 265, in command
    response = await asyncio.wait_for(event.wait(), self.timeout)
  File "/usr/local/Cellar/[email protected]/3.8.3_2/Frameworks/Python.framework/Versions/3.8/lib/python3.8/asyncio/tasks.py", line 490, in wait_for
    raise exceptions.TimeoutError()
asyncio.exceptions.TimeoutError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/pyheos/connection.py", line 285, in _handle_event
    if player and (await player.event_update(
  File "/usr/local/lib/python3.8/site-packages/pyheos/player.py", line 356, in event_update
    await self.refresh_now_playing_media()
  File "/usr/local/lib/python3.8/site-packages/pyheos/player.py", line 227, in refresh_now_playing_media
    payload = await self._commands.get_now_playing_state(self._player_id)
  File "/usr/local/lib/python3.8/site-packages/pyheos/command.py", line 75, in get_now_playing_state
    response = await self._connection.command(
  File "/usr/local/lib/python3.8/site-packages/pyheos/connection.py", line 271, in command
    raise CommandError(command, message) from error
pyheos.error.CommandError: Command timed out
Task exception was never retrieved
future: <Task finished name='Task-2283' coro=<HeosConnection._handle_event() done, defined at /usr/local/lib/python3.8/site-packages/pyheos/connection.py:280> exception=CommandError('Command timed out')>
Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/pyheos/connection.py", line 265, in command
    response = await asyncio.wait_for(event.wait(), self.timeout)
  File "/usr/local/Cellar/[email protected]/3.8.3_2/Frameworks/Python.framework/Versions/3.8/lib/python3.8/asyncio/tasks.py", line 490, in wait_for
    raise exceptions.TimeoutError()
asyncio.exceptions.TimeoutError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/pyheos/connection.py", line 285, in _handle_event
    if player and (await player.event_update(
  File "/usr/local/lib/python3.8/site-packages/pyheos/player.py", line 356, in event_update
    await self.refresh_now_playing_media()
  File "/usr/local/lib/python3.8/site-packages/pyheos/player.py", line 227, in refresh_now_playing_media
    payload = await self._commands.get_now_playing_state(self._player_id)
  File "/usr/local/lib/python3.8/site-packages/pyheos/command.py", line 75, in get_now_playing_state
    response = await self._connection.command(
  File "/usr/local/lib/python3.8/site-packages/pyheos/connection.py", line 271, in command
    raise CommandError(command, message) from error
pyheos.error.CommandError: Command timed out
Task exception was never retrieved
future: <Task finished name='Task-2284' coro=<HeosConnection._handle_event() done, defined at /usr/local/lib/python3.8/site-packages/pyheos/connection.py:280> exception=CommandError('Command timed out')>
Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/pyheos/connection.py", line 265, in command
    response = await asyncio.wait_for(event.wait(), self.timeout)
  File "/usr/local/Cellar/[email protected]/3.8.3_2/Frameworks/Python.framework/Versions/3.8/lib/python3.8/asyncio/tasks.py", line 490, in wait_for
    raise exceptions.TimeoutError()
asyncio.exceptions.TimeoutError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/pyheos/connection.py", line 285, in _handle_event
    if player and (await player.event_update(
  File "/usr/local/lib/python3.8/site-packages/pyheos/player.py", line 356, in event_update
    await self.refresh_now_playing_media()
  File "/usr/local/lib/python3.8/site-packages/pyheos/player.py", line 227, in refresh_now_playing_media
    payload = await self._commands.get_now_playing_state(self._player_id)
  File "/usr/local/lib/python3.8/site-packages/pyheos/command.py", line 75, in get_now_playing_state
    response = await self._connection.command(
  File "/usr/local/lib/python3.8/site-packages/pyheos/connection.py", line 271, in command
    raise CommandError(command, message) from error
pyheos.error.CommandError: Command timed out
Task exception was never retrieved
future: <Task finished name='Task-2285' coro=<HeosConnection._handle_event() done, defined at /usr/local/lib/python3.8/site-packages/pyheos/connection.py:280> exception=CommandError('Command timed out')>
Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/pyheos/connection.py", line 265, in command
    response = await asyncio.wait_for(event.wait(), self.timeout)
  File "/usr/local/Cellar/[email protected]/3.8.3_2/Frameworks/Python.framework/Versions/3.8/lib/python3.8/asyncio/tasks.py", line 490, in wait_for
    raise exceptions.TimeoutError()
asyncio.exceptions.TimeoutError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/pyheos/connection.py", line 285, in _handle_event
    if player and (await player.event_update(
  File "/usr/local/lib/python3.8/site-packages/pyheos/player.py", line 356, in event_update
    await self.refresh_now_playing_media()
  File "/usr/local/lib/python3.8/site-packages/pyheos/player.py", line 227, in refresh_now_playing_media
    payload = await self._commands.get_now_playing_state(self._player_id)
  File "/usr/local/lib/python3.8/site-packages/pyheos/command.py", line 75, in get_now_playing_state
    response = await self._connection.command(
  File "/usr/local/lib/python3.8/site-packages/pyheos/connection.py", line 271, in command
    raise CommandError(command, message) from error
pyheos.error.CommandError: Command timed out
Task exception was never retrieved
future: <Task finished name='Task-2287' coro=<HeosConnection._handle_event() done, defined at /usr/local/lib/python3.8/site-packages/pyheos/connection.py:280> exception=CommandError('Command timed out')>
Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/pyheos/connection.py", line 265, in command
    response = await asyncio.wait_for(event.wait(), self.timeout)
  File "/usr/local/Cellar/[email protected]/3.8.3_2/Frameworks/Python.framework/Versions/3.8/lib/python3.8/asyncio/tasks.py", line 490, in wait_for
    raise exceptions.TimeoutError()
asyncio.exceptions.TimeoutError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/pyheos/connection.py", line 285, in _handle_event
    if player and (await player.event_update(
  File "/usr/local/lib/python3.8/site-packages/pyheos/player.py", line 356, in event_update
    await self.refresh_now_playing_media()
  File "/usr/local/lib/python3.8/site-packages/pyheos/player.py", line 227, in refresh_now_playing_media
    payload = await self._commands.get_now_playing_state(self._player_id)
  File "/usr/local/lib/python3.8/site-packages/pyheos/command.py", line 75, in get_now_playing_state
    response = await self._connection.command(
  File "/usr/local/lib/python3.8/site-packages/pyheos/connection.py", line 271, in command
    raise CommandError(command, message) from error
pyheos.error.CommandError: Command timed out

Question on create_group()

Hello Andrew

I'm using your lib to develop a gnome-extension for controlling my heos

And thanks a lot cause pretty quick I got play/stop working :)

I cannot understand how to use the command create_group() and particulary what is expected in data: dict ?

Can you provide me more explanation please

pyheos version : 0.4.0
Python version 3.7
Os: ubuntu

Unstable connection with Home Assistant

pyheos version with the issue: 0.7.2

Python version and environment: 3.8 Home Assistant

Description of problem: Connection is not stable
In my Home Assistant and HEOS setup the connection to the HEOS devices are not stable. Typically it will only stay connected for a period of an hour up to 24 hours, sometimes indicating that some or all devices are disconnected or still showing a connected status for all devices but actually not working.
When looking at the logs I could see that an occasional command would fail (timeout) and the lib would go all haywire and create at lest 2 reconnection tasks which would eventually fail such that it thinks it is connected but actually is not, and the only way to get it to work again is to reload the integration in Home Assistant or restart Home Assistant.
I came to the conclusion that this happens when a lot of commands are queued at the same time, and in this situation it seems the HEOS device will just discard a command or maybe it just has a buffer overrun.
I have 11 HEOS devices in my home which means that quite a lot of commands are sometimes queued up when the HA integration tries to get status of all devices, a guess may be that it is perhaps not that common to have this many devices and that it triggers the problem more often.
So I did a small patch to add a lock function such that no new command is sent before the previous one is completed.
And it now looks like the problem is gone, granted that it is random so test time may need to accumulate before it is certain.

I am not sure if this is a good way to solve this, it may be a Home Assistant unique problem, so maybe it should be solved there.
Also, this is a kind of a quick workaround, it may have side effects and perhaps it would be better to limit the number of commands in the queue to a low number instead of just blocking until each command is completed.
So I am writing this in search of comments and discussion about this issue.
Would be interesting to know if someone else has similar stability issues also...

Changes:

In connection.py:HeosConnection:__init__ function:
        self._lock = asyncio.Lock()
        
In connection.py:HeosConnection:command function:
        await self._lock.acquire()
        # Send command
        try:
            self._writer.write((uri + SEPARATOR).encode())
            await self._writer.drain()
            response = await asyncio.wait_for(event.wait(), self.timeout)
        except (ConnectionError, asyncio.TimeoutError, OSError) as error:
            # Occurs when the connection breaks
            asyncio.ensure_future(self._handle_connection_error(error))
            message = format_error_message(error)
            _LOGGER.debug("Command failed '%s': %s", masked_uri, message)
            raise CommandError(command, message) from error
        finally:
            self._lock.release()

Additional information:

Player problem

Good morning, sir,
I have a Denon CEOL N10 in my office and I would like to run it from my computer. Denon offers an application for android and ios but nothing for windows 10. Therefore I'm thinking of creating a python application to drive my Ceol from my PC.
Your pyheos library seems pretty great and could allow me to realize this project.
I tested the Heos class which works perfectly. But I have a problem with the player class : I don't understand what parameter must be given to it in the initialization. Can you enlighten me on this subject.
Player = HeosPlayer(heos, data), what should be understood by heos and what should be provided as data?
Thank you for taking some time to answer me.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.