supersaiyanmode / PyWebOSTV

Python API for controlling LG TVs (Web OS)
MIT License
261 stars 50 forks source link

add TV controls channel down and up #9

Closed Gustry closed 6 years ago

Gustry commented 6 years ago

add TV controls channel down and up

I tried to add the channel number, but no luck for now. I'm not sure how to give a parameter in my request. I have another look later maybe.

coveralls commented 6 years ago

Coverage Status

Coverage increased (+0.2%) to 69.758% when pulling 8bb2e6391948ed6e9eafe792e4c1f648d2672f3e on Gustry:tv_control into 0099e7c2b8dd4880f385417025fb7a37e64f7e18 on supersaiyanmode:master.

supersaiyanmode commented 6 years ago

Hi @Gustry can you please explain, what you mean by: "I'm not sure how to give a parameter in my request" ? May be with an example? Do you want to do: tv_control.set_channel(12) ?

Gustry commented 6 years ago

Yes exactly. But what I put in this PR is working. I didn't commit the set_channel(12).

supersaiyanmode commented 6 years ago

Ohh, please look at MediaControl(..).set_volume(..):

"set_volume": {
    "uri": "ssap://audio/setVolume",
    "args": [int],
    "payload": {"volume": arguments(0)}
},

Think of "payload" field as a template, which gets substituted by arguments. In the above code, argument(0) retrieves the first argument (=int_val1)that was passed when set_volume(int_val1) was called. After substitution the object is sent the the URI in the outer object.

In other words:

"custom_function": {
    "uri": "ssap://some/uri",
    "args": [int, str],
    "payload": {
        "field1": "blah",
        "field2": [argument(0), argument[1]],
        "field3": argument(1)
    }
},

upon invocation like: obj.custom_function(3, "hello") will produce a payload of {"field1": "blah", "field2": [3, "hello"], "field3": "hello"}.

supersaiyanmode commented 6 years ago

Thanks @Gustry for this PR! :+1:

dagavi commented 4 years ago

In the project referenced in the REAME we can see this: https://github.com/klattimer/LGWebOSRemote/blob/master/LGTV/remote.py#L207

They have:

    def inputChannelUp(self, callback=None):
        self.__send_command("request", "ssap://tv/channelUp", None, callback)

    def inputChannelDown(self, callback=None):
        self.__send_command("request", "ssap://tv/channelDown", None, callback)

    def setTVChannel(self, channel, callback=None):
        self.__send_command("request", "ssap://tv/openChannel", {"channelId": channel}, callback)

    def getTVChannel(self, callback=None):
        self.__send_command("request", "ssap://tv/getCurrentChannel", None, callback, "channels")

This merge implements channelUp and Down, so I supose that add setChannel, getChannel and getChannelList will be, with your explanition:

COMMANDS = {
    "channel_down": {"uri": "ssap://tv/channelDown"},
    "channel_up": {"uri": "ssap://tv/channelUp"},
    "set_channel": {
        "uri": "ssap://tv/openChannel",
        "args": [int],
        "payload": {
            "channelId": argument(0)
        }
    },
    # Based on get_volume
    "get_current_channel": {
        "uri": "ssap://tv/getCurrentChannel",
        "validation": standard_validation,
        "subscription": True
    },
    "channel_list": {"uri": "ssap://tv/getChannelList"}
 }

And then I will have available:

tv_control = TvControl(client)

tv_control.set_channel(10)

currentChannelOutput = tv_control.get_current_channel()
# I supose that currentChannelOutput  will be the response from the TV

tv_control.subscribe_get_volume(some_handler)

channelListOutput = tv_control.get_channel_list()

PD: Add comment https://github.com/supersaiyanmode/PyWebOSTV/pull/9#issuecomment-372805193 to the README or as a comment in the code. Is very useful to understand how this works and how you can use and extend.


Edit: I tried and its almost working!

class TvControl(WebOSControlBase):
    COMMANDS = {
        "channel_down": {"uri": "ssap://tv/channelDown"},
        "channel_up": {"uri": "ssap://tv/channelUp"},
        "set_channel_with_number": {
            "uri": "ssap://tv/openChannel",
            "args": [int],
            "payload": {
                "channelNumber": arguments(0)
            }
        },
        "set_channel_with_id": {
            "uri": "ssap://tv/openChannel",
            "args": [str],
            "payload": {
                "channelId": arguments(0)
            }
        },
        "get_current_channel": {
            "uri": "ssap://tv/getCurrentChannel",
            "validation": standard_validation,
            "subscription": True
        },
        "channel_list": {"uri": "ssap://tv/getChannelList"}
     }

The problem is that "with_number" it's not working (and is the more natural: set channel 12). It throws and error (at least in my TV). More people have the same problem: https://github.com/merdok/homebridge-webos-tv/issues/88#issuecomment-549167757

And I tested with channel ID (from channel_list) and it works. So you can perform an initial channel_list an index by number and then call set_channel_with_id(channel_number_to_id[12])

supersaiyanmode commented 4 years ago

Hi @dagavi, thanks so much! The new APIs around TV Channels sound good to me. Would you be open to creating a PR with only those commands that work (in other words minus the channel number)?