예제 #1
0
    def __init__(self):

        webos_store = {'auth': {}}
        try:
            webos_store = pickle.load(open("webos.auth", "rb"))
        except:
            print("Cant load webos auth, registering new one.")
            pass

        if not 'host' in webos_store:
            print("Searching tv...")
            webos_client = WebOSClient.discover()[0]
        else:
            print("Connecting to tv at {}".format(webos_store['host']))
            webos_client = WebOSClient(webos_store['host'])

        webos_client.connect()
        for status in webos_client.register(webos_store['auth']):
            if status == WebOSClient.PROMPTED:
                print("Please accept the connect on the TV!")
            elif status == WebOSClient.REGISTERED:
                print("Webos connection successful!")
                webos_store['host'] = webos_client.host
                pickle.dump(webos_store, open("webos.auth", "wb"))

        self.webos_system = SystemControl(webos_client)

        self.webos_media = MediaControl(webos_client)

        self.webos_inp = InputControl(webos_client)
        self.webos_inp.connect_input()

        self.notify("Skipper connected")
예제 #2
0
    def control(self):
        if self._control is None:
            self._control = InputControl(
                self.adapter.create(str(Path().home() / '.lgtv.yaml'),
                                    'living_room'))
            self._control.connect_input()

        return self._control
예제 #3
0
    def test_bad_mouse_socket(self):
        client = FakeClient()
        inp = InputControl(client, ws_class=FakeMouseClient)

        client.setup_response(
            "ssap://com.webos.service.networkinput/getPointerInputSocket",
            {"socketPath": ""})
        with raises(IOError):
            inp.connect_input()
예제 #4
0
    def test_enter(self):
        client = FakeClient()
        inp = InputControl(client)

        inp.enter(block=False)

        client.assert_sent_message_without_id({
            "type": "request",
            "uri": "ssap://com.webos.service.ime/sendEnterKey",
        })
예제 #5
0
    def test_delete(self):
        client = FakeClient()
        inp = InputControl(client)

        inp.delete(4, block=False)

        client.assert_sent_message_without_id({
            "type": "request",
            "uri": "ssap://com.webos.service.ime/deleteCharacters",
            "payload": {
                "count": 4,
            }
        })
예제 #6
0
    def test_type(self):
        client = FakeClient()
        inp = InputControl(client)

        inp.type("hello world", block=False)

        client.assert_sent_message_without_id({
            "type": "request",
            "uri": "ssap://com.webos.service.ime/insertText",
            "payload": {
                "text": "hello world",
                "replace": 0,
            }
        })
예제 #7
0
class InputButton(WebOsButton):
    @property
    @abstractmethod
    def command(self) -> str:
        raise NotImplementedError

    @property
    def control(self):
        if self._control is None:
            self._control = InputControl(
                self.adapter.create(str(Path().home() / '.lgtv.yaml'),
                                    'living_room'))
            self._control.connect_input()

        return self._control
예제 #8
0
    def __init__(self, client):
        self.client: WebOSClient = client

        self._system: SystemControl = SystemControl(client)
        self._media: MediaControl = MediaControl(client)
        self._app: ApplicationControl = ApplicationControl(client)
        self._inp: InputControl = InputControl(client)
예제 #9
0
    def connect_and_register_to_tv(self):
        # self.client = WebOSClient.discover()[0]
        self.client = WebOSClient(self.tv_context['local_address'])

        self.client.connect()
        register_status = self.client.register(store=self.tv_context)

        for status in register_status:
            if status == WebOSClient.PROMPTED:
                print("Please accept the connect on the TV!")
            elif status == WebOSClient.REGISTERED:
                print("Registration successful!")
                self.input_control = InputControl(self.client)
                self.input_control.connect_input()
                self.system_control = SystemControl(self.client)
                self.media_control = MediaControl(self.client)
예제 #10
0
def get_apis(client):
    media = MediaControl(client)
    system = SystemControl(client)
    app = ApplicationControl(client)
    inp = InputControl(client)

    return [
        ServerAPI(
            "mute", "Mute the TV",
            [ArgParameter("state", "True to mute, False to unmute", bool)],
            media.mute),
        ServerAPI("volume_up", "Increase Volume", [], media.volume_up),
        ServerAPI("volume_down", "Decrease Volume", [], media.volume_down),
        ServerAPI("set_volum", "Set Volume",
                  [ArgParameter("level", "Volume Level", int)],
                  media.set_volume),
        ServerAPI("play", "Play", [], media.play),
        ServerAPI("pause", "Pause", [], media.pause),
        ServerAPI("rewind", "Rewind", [], media.rewind),
        ServerAPI("fast_forward", "Fast Forward", [], media.fast_forward),
        ServerAPI("power_off", "Power off TV", [], system.power_off),
        ServerAPI("notify", "Send notification",
                  [ArgParameter("text", "Text to notify", str)],
                  system.notify),
        ServerAPI("type", "Send text input",
                  [ArgParameter("text", "Text to insert", str)], inp.type),
        ServerAPI("delete", "Delete text",
                  [ArgParameter("count", "No of characters to delete", int)],
                  inp.delete),
        ServerAPI("enter", "Press Enter", [], inp.enter),
    ]
예제 #11
0
 def __init__(self):
     self.ws = WebOSClient(S.config.get('host'))
     self.ws.connect()
     assert (2 in self.ws.register(S.config)), "Not registered to TV yet"
     self.ac = ApplicationControl(self.ws)
     self.ic = InputControl(self.ws)
     self.mc = MediaControl(self.ws)
     self.sc = SystemControl(self.ws)
     self.srcc = SourceControl(self.ws)
     self.tv = TvControl(self.ws)
예제 #12
0
 def get_control(self, controltype):
     if controltype not in self.clients:
         if controltype == 'media':
             control = MediaControl(self.client)
         elif controltype == 'input':
             control = InputControl(self.client)
             control.connect_input()
         elif controltype == 'system':
             control = SystemControl(self.client)
         elif controltype == 'source':
             control = SourceControl(self.client)
         self.clients[controltype] = control
     return self.clients[controltype]
예제 #13
0
def conn_attempt():
    global board, connection_status, tvClient, tvInputControl, tvMediaControl

    print('Attempting to connect')
    connection_status = 1
    board.led.state = Led.PULSE_QUICK
    board.button._pressed_callback = None

    client_list = WebOSClient.discover()

    if len(client_list) != 1:
        play_wav('errorsound.wav')
        print('connection failed: more than 1 tv found')
        connection_status = 0
        board.led.state = Led.OFF
        return

    tvClient = client_list[0]
    try:
        tvClient.connect()
        for status in tvClient.register(store):
            if status == WebOSClient.PROMPTED:
                play_wav('ding.wav')
                print('See TV prompt and press yes')
            elif status == WebOSClient.REGISTERED:
                play_wav('ding.wav')
                print('Successful connection')
                board.led.state = Led.ON
                connection_status = 2
                tvInputControl = InputControl(tvClient)
                tvInputControl.connect_input()
                tvMediaControl = MediaControl(tvClient)
    except Exception:
        play_wav('errorsound.wav')
        print('connection failed: you probably pressed no on the prompt')
        connection_status = 0
        board.led.state = Led.OFF
        return
예제 #14
0
파일: lgws.py 프로젝트: wookiesh/lgws
    def __init__(self, configFile="~/.config/lgtv"):
        log = logging.getLogger(__name__)
        self.config = self.load_config(configFile) or {}

        self.ws = WebOSClient(self.config.get('host'))
        self.ws.connect()
        assert (2 in self.ws.register(self.config)), "Not registered to TV yet"
        self.ac = ApplicationControl(self.ws)
        self.ic = InputControl(self.ws)
        self.mc = MediaControl(self.ws)
        self.sc = SystemControl(self.ws)
        self.srcc = SourceControl(self.ws)
        self.tv = TvControl(self.ws)

        self.apps = {a["id"]: a for a in self.ac.list_apps()}
        # self.ac.subscribe_get_current(self.__on_app_changed)
        # self.mc.subscribe_get_volume(self.__on_volume_changed)

        self.current = self.volume = None
예제 #15
0
    def test_input_commands(self, command, args, kwargs, data):
        client = FakeClient()
        inp = InputControl(client, ws_class=FakeMouseClient)

        client.setup_response(
            "ssap://com.webos.service.networkinput/getPointerInputSocket",
            {"socketPath": "x"})
        inp.connect_input()
        getattr(inp, command)(*args, block=False, **kwargs)
        inp.disconnect_input()

        split = data.split()
        expected = [x + ":" + y for x, y in zip(split[::2], split[1::2])]
        inp.mouse_ws.assert_sent_message("\n".join(expected) + "\n\n")
예제 #16
0
파일: key.py 프로젝트: flepied/lgtv
#!/usr/bin/env python3

import os
import sys

from pywebostv.controls import InputControl

from lib import init

client = init()

inp = InputControl(client)
inp.connect_input()

method = getattr(inp, os.path.basename(sys.argv[0]))
method(block=True)

# key.py ends here
예제 #17
0
 def test_invalid_input_command(self):
     client = FakeClient()
     inp = InputControl(client)
     with raises(AttributeError):
         inp.invalid_command()
예제 #18
0
class PyTVCursor:
    '''
    Implements a smaller coordinate window of size self.width x self.height within the larger coordinate system.
    This window is shifted within the larger coordinate system such that the cursor drags the window along with it.

    The current x,y position of the window within the larger coodinate system is given by self.minx and self.miny

    The position of the cursor within the window is given by self._x and self._y

    The pos properties are used to pass the current external coordinate and retrieve the internal coordinate
    '''

    def __init__(self):
        # X, Y, Height, width of window in world coordinates +y up
        self.world_window_height = 100.0
        self.world_window_width = 120.0
        self.world_window_x = -60.0
        self.world_window_y = -50.0

        # Height and width of window in tv coordinates
        self.tv_window_half_height = 50
        self.tv_window_half_width = 85

        # Current cursor coordinate in tv coordinates, starts in center of screen +y down
        self.tv_cursor_x = 0
        self.tv_cursor_y = 0

        self.last_click_ms = 0
        self.paused = False
        self.verbose = True

        self.client = None
        self.input_control = None
        self.system_control = None
        self.media_control = None

        self.tv_context = {
            'client_key': 'c8bfd5128b861d24a0ffbf6644eb6f18',
            'local_address': '10.0.0.214'  # client.peer_address[0]
        }

        self.connect_and_register_to_tv()

    def update_world_coordinate(self, pos):

        if pos is None or len(pos) != 2:
            return

        # shift window in x direction
        self.world_window_x = min(pos[0], self.world_window_x)
        if pos[0] > self.world_window_x + self.world_window_width:
            self.world_window_x = pos[0] - self.world_window_width

        world_window_x_center = self.world_window_x + 0.5 * self.world_window_width
        x_unit_vector = (pos[0] - world_window_x_center) / (self.world_window_width * 0.5)

        # shift window in y direction and calculate vector
        self.world_window_y = min(pos[1], self.world_window_y)
        if pos[1] > self.world_window_y + self.world_window_height:
            self.world_window_y = pos[1] - self.world_window_height

        world_window_y_center = self.world_window_y + 0.5 * self.world_window_height
        y_unit_vector = (pos[1] - world_window_y_center) / (self.world_window_height * 0.5)

        new_x_coord = x_unit_vector * self.tv_window_half_width * -1
        new_y_coord = y_unit_vector * self.tv_window_half_height

        self.normalized_cursor_move(new_x_coord, new_y_coord)

    def normalized_cursor_move(self, new_x_coord, new_y_coord):
        try:
            while True:
                # always move in increments of 5, and move both x and y at once if possible
                x_step = 0 if int(new_x_coord) == self.tv_cursor_x else math.copysign(5, int(new_x_coord) - self.tv_cursor_x)
                y_step = 0 if int(new_y_coord) == self.tv_cursor_y else math.copysign(5, int(new_y_coord) - self.tv_cursor_y)
                if x_step == 0 and y_step == 0:
                    return
                self.input_control.move(x_step, y_step)
                self.tv_cursor_x += x_step / 5
                self.tv_cursor_y += y_step / 5

        except Exception as e:
            print('pytv move failed with {}'.format(e))
            self.input_control.connect_input()

    def connect_and_register_to_tv(self):
        # self.client = WebOSClient.discover()[0]
        self.client = WebOSClient(self.tv_context['local_address'])

        self.client.connect()
        register_status = self.client.register(store=self.tv_context)

        for status in register_status:
            if status == WebOSClient.PROMPTED:
                print("Please accept the connect on the TV!")
            elif status == WebOSClient.REGISTERED:
                print("Registration successful!")
                self.input_control = InputControl(self.client)
                self.input_control.connect_input()
                self.system_control = SystemControl(self.client)
                self.media_control = MediaControl(self.client)

    def click(self):
        # De-bounce the click
        click_time = int(round(time.time() * 1000))
        if click_time < self.last_click_ms + 500:
            return
        self.last_click_ms = click_time

        # perform the click
        try:
            print('click emulated')
            self.input_control.click()
        except Exception as e:
            print('pytv click failed with {}'.format(e))
            self.input_control.connect_input()

    def center(self):
        for i in range(18):
            tv.move(-20, -20)
            # time.sleep(0.01)
        for i in range(16):
            tv.move(15, 10)
            # time.sleep(0.01)

    def move(self, x, y):
        self.input_control.move(x, y)

    def toggle_pause(self):
        if self.paused:
            self.media_control.play()
            self.paused = False
            if self.verbose:
                self.system_control.notify("Play")
        else:
            self.media_control.pause()
            self.paused = True
            if self.verbose:
                self.system_control.notify("Pause")

    def keypad_up(self):
        self.input_control.up()

    def keypad_down(self):
        self.input_control.down()

    def keypad_left(self):
        self.input_control.left()

    def keypad_right(self):
        self.input_control.right()

    def keypad_ok(self):
        self.input_control.ok()
        if self.verbose:
            self.system_control.notify("Ok")

    def keypad_back(self):
        self.input_control.back()
        if self.verbose:
            self.system_control.notify("Back")

    def keypad_home(self):
        self.input_control.home()
        if self.verbose:
            self.system_control.notify("Home")

    def test_amazon_profiles(self):
        self.center()
        print('start')
        for i in range(9):
            self.move(-15, 0)
        time.sleep(1)
        self.center()
        for i in range(5):
            self.move(-15, 0)
        time.sleep(1)
        self.center()
        time.sleep(1)
        self.center()
        for i in range(6):
            self.move(15, 0)
        time.sleep(1)
        self.center()
        for i in range(8):
            self.move(15, 0)

    def test_multi_path(self):
        self.center()
        print('start')
        for i in range(8):
            self.move(-15, 0)
        self.system_control.notify("Path 1 complete")
        time.sleep(5)
        self.center()

        for i in range(10):
            self.move(-12, 0)
        self.system_control.notify("Path 2 complete")
        time.sleep(5)
        self.center()

        for i in range(12):
            self.move(-10, 0)
        self.system_control.notify("Path 3 complete")
        time.sleep(5)

    # Validates the TV width/height by moving cursor in a figure-eight pattern
    def test_figure_eight(self):
        # Right
        for i in range(85):
            tv.move(5, 0)
            time.sleep(.01)
        # Down
        for i in range(50):
            tv.move(0, 5)
            time.sleep(.01)
        # Left
        for i in range(85):
            tv.move(-5, 0)
            time.sleep(.01)
        # Up
        for i in range(50):
            tv.move(0, -5)
            time.sleep(.01)
        # Left
        for i in range(85):
            tv.move(-5, 0)
            time.sleep(.01)
        # Up
        for i in range(50):
            tv.move(0, -5)
            time.sleep(.01)
        # Right
        for i in range(85):
            tv.move(5, 0)
            time.sleep(.01)
        # Down
        for i in range(50):
            tv.move(0, 5)
            time.sleep(.01)

    def test_world_coordinate_translation(self):
        self.update_world_coordinate((0.0, 0.0))
        time.sleep(1)
        self.update_world_coordinate((50.0, 0.0))
        time.sleep(1)
        self.update_world_coordinate((50.0, 50.0))
        time.sleep(1)
        self.update_world_coordinate((0.0, 50.0))
        time.sleep(1)
        self.update_world_coordinate((0.0, 0.0))
        time.sleep(1)
        self.update_world_coordinate((-100.0, 0.0))
        time.sleep(1)
        self.update_world_coordinate((-200.0, 0.0))
        time.sleep(1)
        self.update_world_coordinate((0.0, 200.0))
        time.sleep(1)
예제 #19
0
    if len(rfds) > 0 or len(wfds) > 0 or len(efds) > 0:
        key = sys.stdin.read(1)
        # keyboard arrows are a 'triplet' (3 codes), so if the keycode
        # begin with x1b, we asume the rest are the 2 remaining keycodes
        if key == "\x1b":
            key += sys.stdin.read(2)
            termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)
        return key
    else:
        return None


if __name__ == "__main__":
    client = init()

    inp = InputControl(client)
    inp.connect_input()
    try:
        while True:
            settings = termios.tcgetattr(sys.stdin)
            key = getKey()
            termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)
            if key == 'q' or key == 'Q':
                break
            if key in ('y', 'Y'):
                print('youtube')
                launch_app("youtube", client)
            elif key in ('n', 'N'):
                print('netflix')
                launch_app("netflix", client)
            elif key in ('a', 'A'):
예제 #20
0
# The 'store' gets populated during the registration process. If it is empty, a registration prompt
# will show up on the TV. You can pass any dictionary-like interface instead.
store = {}

client = WebOSClient("<TV IP>")
client.connect()
for status in client.register(store):
    if status == WebOSClient.PROMPTED:
        print("\nPlease accept the connect on the TV!")
    elif status == WebOSClient.REGISTERED:
        print("\nRegistration successful!")
        # print(store)

media = MediaControl(client)
system = SystemControl(client)
inp = InputControl(client)


def volume_set():
    while True:
        print('\nWhat volume level do you want? [0-100]')
        try:  # Ask the user what level they want the volume
            volume_level = int(input('> '))
            if -1 < volume_level < 101:  # Check that input is in valid range of 1-100
                # Set the volume based on the user's input number
                media.set_volume(volume_level)
            else:
                print('Not a valid range, please use a range of 1-100.')
                continue
        except ValueError:
            print('That\'s not a valid number. Try again')