8000 Alexa should handle channelMetadata: "name" as a valid channel. · Issue #29274 · home-assistant/core · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Alexa should handle channelMetadata: "name" as a valid channel. #29274

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
clapbr opened this issue Nov 30, 2019 · 11 comments · Fixed by #29279
Closed

Alexa should handle channelMetadata: "name" as a valid channel. #29274

clapbr opened this issue Nov 30, 2019 · 11 comments · Fixed by #29279

Comments

@clapbr
Copy link
Contributor
clapbr commented Nov 30, 2019

Home Assistant release with the issue: 0.102

Last working Home Assistant release (if known):

Operating environment (Hass.io/Docker/Windows/etc.): Ubuntu venv

Integration: Alexa smart home (https://www.home-assistant.io/integrations/alexa.smart_home/)

Description of problem:
Relevant API: https://developer.amazon.com/docs/device-apis/alexa-channelcontroller.html
@Dilbert66 recently implemented the channel changer and it handles the case where Alexa requests a channel's number or callSign. IE:

      "channel": {
          "number": "1234",
          "callSign": "KSTATION1",
          "affiliateCallSign": "KSTATION2",
          "uri": "someUrl"
      }

In my case it wasn't working for channel names because Alexa sent the requested channel as:

      "channelMetadata": {
          "name": "fox",
      }

The handler function is this one: https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/alexa/handlers.py#L1143 - I'm not a dev but quickly tweaked the function to this and it worked well:

async def async_api_changechannel(hass, config, directive, context):
    """Process a change channel request."""
    channel = "0"
    entity = directive.entity
    payload = directive.payload["channel"]
    payload_name = "number"
    metapayload = directive.payload["channelMetadata"]
    if "number" in payload:
        channel = payload["number"]
        payload_name = "number"
    elif "callSign" in payload:
        channel = payload["callSign"]
        payload_name = "callSign"
    elif "affiliateCallSign" in payload:
        channel = payload["affiliateCallSign"]
        payload_name = "affiliateCallSign"
    elif "uri" in payload:
        channel = payload["uri"]
        payload_name = "uri"
    elif "name" in metapayload:
        channel = metapayload["name"]
        payload_name = "name"

For reference this is how openhab handles it.
@ochlocracy @balloob Pinging you guys since you maintain the component.

@Dilbert66
Copy link
Contributor
Dilbert66 commented Dec 1, 2019

Are you indicating that the Alexa api never sent any other data in the "channel" payload and only sent the channelMetadata payload? I have not see this? As it is coded now, any field in the channel payload that is not a null value or an empty string will be the final value used and it will not flow through to any following elif check such as the "name" field. For the name value to be used , all previous checks would need to be null or empty. I will do some tests to see what payload i get for various Alexa calls. What was the Alexa command you asked to generate the name response?
Your code changes are fine. It won't hurt anything at all to add them as is. I'm just curious as to this behaviour.

Edit: ok, just tested and when a named channel is requested for which the Alexa api has no info, an empty "channel" field is sent in payload and the named channel value is sent in the name field of the channelMetada payload section. I will modify the code to implement this change and submit a pull request.

Regards, Alain

@clapbr
Copy link
Contributor Author
clapbr commented Dec 1, 2019

Are you indicating that the Alexa api never sent any other data in the "channel" payload and only sent the channelMetadata payload? I have not see this? As it is coded now, any field in the channel payload that is not a null value or an empty string will be the final value used and it will not flow through to any following elif check such as the "name" field. For the name value to be used , all previous checks would need to be null or empty. I will do some tests to see what payload i get for various Alexa calls. What was the Alexa command you asked to generate the name response?
Your code changes are fine. It won't hurt anything at all to add them as is. I'm just curious as to this behaviour.

Edit: ok, just tested and when a named channel is requested for which the Alexa api has no info, an empty "channel" field is sent in payload and the named channel value is sent in the name field of the channelMetada payload section. I will modify the code to implement this change and submit a pull request.

Regards, Alain

Correct, it happens for me for most channels because Alexa doesn't have channel metadata for my region. A few select channels are matched and I get proper callSigns though, so YMMV.

Thanks for the quick PR.

a bit related: I'm also getting a weird behavior that after some time Alexa forgets about the endpoint having ChannelController capabilities until manually deleted+rediscovered. I'm currently experimenting with ReportState'ing channel interface properties along with playback state but that is not trivial because HA itself doesn't seems to have a proper standardized channel api (guess media_content_type=channel is the closest we've got). I need to investigate more before opening a proper issue but would like to hear your thoughts on it since not many people are using this feature yet.

@Dilbert66
Copy link
Contributor

I have not encountered the issue with the lost channelcontroller capabilities. Ive been using it for many months now. Do you have HA debug log entries regarding the issue? Looks like a re-discovery is happening on that media player device that returns different capabilities intermittently? I don't think that's an Alexa issue though. I'm currently using it with SmartIR as a media_player. I agree , the media_player api as is, leaves a bit to be desired to support channels and volume control in a more optimal way. The changes will need to be able to apply to other applications before they would get accepted into the base media_player model I suspect.

@Dilbert66
Copy link
Contributor
Dilbert66 commented Dec 1, 2019

FYI, the code checks for the attribute SUPPORT_PLAY_MEDIA as a capability to determine if a device supports the channelController function.

@clapbr
Copy link
Contributor Author
clapbr commented Dec 1, 2019

I have not encountered the issue with the lost channelcontroller capabilities. Ive been using it for many months now. Do you have HA debug log entries regarding the issue? Looks like a re-discovery is happening on that media player device that returns different capabilities intermittently? I don't think that's an Alexa issue though. I'm currently using it with SmartIR as a media_player. I agree , the media_player api as is, leaves a bit to be desired to support channels and volume control in a more optimal way. The changes will need to be able to apply to other applications before they would get accepted into the base media_player model I suspect.

Yeah I use your modded SmartIR for this too, hope you re-open the PR there someday.

When the bug happen no specific logs are shown since Alexa doesn't even try to request the channel change (just answers "Device_name can't do that"). Anything that happen in-between are normal playback state events. I'm now experimenting sending both ReportStates and ChangeReports explicitly including the channel interface with a static 500 channel property and it's been working fine since but I'll monitor it. It's a similar solution to answering a blank channel in response to skipChannel/nextChannel but for state reporting instead. Not sure if I'm being clear but looks like this:

2019-11-30 23:23:44 DEBUG (MainThread) [homeassistant.components.alexa.state_report] Sent: {"event": {"header": {"namespace": "Alexa", "name": "ChangeReport", "messageId": "4739c61f-1d82-4d25-ba6b-6d3596138935", "payloadVersion": "3"}, "payload": {"change": {"cause": {"type": "APP_INTERACTION"}, "properties": [{"name": "powerState", "namespace": "Alexa.PowerController", "value": "ON", "timeOfSample": "2019-12-01T02:23:43.0Z", "uncertaintyInMilliseconds": 0}, {"name": "playbackState", "namespace": "Alexa.PlaybackStateReporter", "value": {"state": "PLAYING"}, "timeOfSample": "2019-12-01T02:23:43.0Z", "uncertaintyInMilliseconds": 0}, {"name": "channel", "namespace": "Alexa.ChannelController", "value": {"number": "500"}, "timeOfSample": "2019-12-01T02:23:43.0Z", "uncertaintyInMilliseconds": 0}, {"name": "connectivity", "namespace": "Alexa.EndpointHealth", "value": {"value": "OK"}, "timeOfSample": "2019-12-01T02:23:43.0Z", "uncertaintyInMilliseconds": 0}]}}, "endpoint": {"scope": {"type": "BearerToken", "token": "xxxxxxxx"}, "endpointId": "media_player#televisao"}}}
2019-11-30 23:23:44 DEBUG (MainThread) [homeassistant.components.alexa.state_report] Received (202): 

The other issue I opened might be related too.

FYI, the code checks for the attribute SUPPORT_PLAY_MEDIA as a capability to determine if a device supports the channelController function.

Does it ever check it again after initial discovery?

@Dilbert66
Copy link
Contributor
Dilbert66 commented Dec 1, 2019

Actually, I'm not sure about the re-discovery. No need for it. Status changes, yes. I thought I saw something in debug logs a while back but can't see anything in my current logs. Are you seeing your device status go offline in the alexa app? I assume you've checked that you also don't have another similar named device ? I had that happen when it would pick the wrong device. In testing I had forgotten a previous device in the app.

I never really worried too much about the channel state reporting back since the tv can have it's channel changed from various sources besides HA so getting state from an IR device is pointless. Unless you have smarttv with an API so why use IR to control it.

@Dilbert66
Copy link
Contributor

As to the smartir, I might re-submit the PR. I was thinking of going a different route. I'm not sure I like his use of external code files. I was going to implement the channel change control as a service that can be used by the universal media player. Make it a more versatile component.

< 8000 /div>

@clapbr
Copy link
Contributor Author
clapbr commented Dec 1, 2019

Actually, I'm not sure about the re-discovery. No need for it. Status changes, yes. I thought I saw something in debug logs a while back but can't see anything in my current logs. Are you seeing your device status go offline in the alexa app? I assume you've checked that you also don't have another similar named device ? I had that happen when it would pick the wrong device. In testing I had forgotten a previous device in the app.

I never really worried too much about the channel state reporting back since the tv can have it's channel changed from various sources besides HA so getting state from an IR device is pointless. Unless you have smarttv with an API so why use IR to control it.

As to the smartir, I might re-submit the PR. I was thinking of going a different route. I'm not sure I like his use of external code files. I was going to implement the channel change control as a service that can be used by the universal media player. Make it a more versatile component.

Ok you helped me figuring the root issue. I'm using only a universal media_player entity exposed to Alexa and whenever it's active child changed to a media_player without SUPPORT_PLAY_MEDIA it reports playback state without the channel interface, and then even if I switch back to an active child with SUPPORT_PLAY_MEDIA it stops recognizing it until discovery. Now looking for clues directly in the universal code, likely here.

edit: works with this quick hack

    @property
    def supported_features(self):
        """Flag media player features that are supported."""
        flags = self._child_attr(ATTR_SUPPORTED_FEATURES) or 0

        if SERVICE_TURN_ON in self._cmds:
            flags |= SUPPORT_TURN_ON
        if SERVICE_TURN_OFF in self._cmds:
            flags |= SUPPORT_TURN_OFF
        if any([cmd in self._cmds for cmd in [SERVICE_VOLUME_UP, SERVICE_VOLUME_DOWN]]):
            flags |= SUPPORT_VOLUME_STEP
        if SERVICE_VOLUME_SET in self._cmds:
            flags |= SUPPORT_VOLUME_SET

        if SERVICE_VOLUME_MUTE in self._cmds and ATTR_MEDIA_VOLUME_MUTED in self._attrs:
            flags |= SUPPORT_VOLUME_MUTE

        if SERVICE_SELECT_SOURCE in self._cmds:
            flags |= SUPPORT_SELECT_SOURCE

        if SERVICE_CLEAR_PLAYLIST in self._cmds:
            flags |= SUPPORT_CLEAR_PLAYLIST

        if SERVICE_SHUFFLE_SET in self._cmds and ATTR_MEDIA_SHUFFLE in self._attrs:
            flags |= SUPPORT_SHUFFLE_SET
        # Force play_media support always as a alexa changechannel interface workaround
        flags |= SUPPORT_PLAY_MEDIA

        return flags

Will monitor if I ever lose capability again.

Thanks for the fyi

@Dilbert66
Copy link
Contributor
Dilbert66 commented Dec 1, 2019

That's why I want to add the channel change service and add a new command to the universal media_player. I would add the SERVICE_PLAY_MEDIA command and when it is available, it would add the SUPPORT_PLAY_MEDIA flag. This way, the flags would correctly reflect all the capabilities of the player. ie: if SERVICE_PLAY_MEDIA in self._cmds:
flags |= SUPPORT_PLAY_MEDIA

Most of the logic is there. It's just missing the service_media_play section as you noted. Are you using the play_media command in your universal config?

@clapbr
Copy link
Contributor Author
clapbr commented Dec 1, 2019

That's why I want to add the channel change service and add a new command to the universal media_player. I would add the SERVICE_PLAY_MEDIA co 8000 mmand and when it is available, it would add the SUPPORT_PLAY_MEDIA flag. This way, the flags would correctly reflect all the capabilities of the player. ie: if SERVICE_PLAY_MEDIA in self._cmds:
flags |= SUPPORT_PLAY_MEDIA

Most of the logic is there. It's just missing the service_media_play section as you noted. Are you using the play_media command in your universal config?

Yeah I first tried to simply add:

if SERVICE_PLAY_MEDIA in self._cmds: flags |= SUPPORT_PLAY_MEDIA
and then when active child changed it properly sent the channel interface in the playback state payload but I still hit the bug where Alexa thinks there isn't a channel interface anymore.

I ended up forcing the flag regardless of active child actual capability and it's been working fine since yesterday, but it may be worth trying Amazon dev support to figure out why this happens in their blackbox.

Btw, overriding the play_media command directly on universal config won't work as overrides are implemented for a few specific commands only, so you're usually stuck with sending play_media to the active child. My solution was using this tweaked universal with active_child_template support.

    active_child_template: >
      {% if (state_attr('media_player.tv', 'source')=='HDMI 3/ARC') %}
      media_player.net_tv
      {% else %}
      media_player.android_tv
      {% endif %}

@Dilbert66
Copy link
Contributor

What I mean, for the overriding is you also need to use your own command ie: "play_media:" that points to the media_play service of your channel change child. If you add the SERVICE_PLAY_MEDIA check it should now work since it will now be part of the _cmds array

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants
0