веб-сокеты неожиданно закрываются - PullRequest
1 голос
/ 10 апреля 2020

Обновление 13. Апр: код дротика работает согласованно

Справочная информация:

Мой телевизор (Samsung 2019 RU7000) предлагает безопасное соединение через веб-сокет, с которым json пакетов можно отправить на пульт управления им. Например,

"method":"ms.remote.control", 
"params":{ "Cmd": "Click", "DataOfCmd":"KEY_MUTE" }

можно отправить для отключения звука на телевизоре.

Чтобы разрешить доступ, выполняется квитирование. Клиент подключается к wss://ip:8002/api/v2/samsung.remote.control?name=value, где значение name является строкой в ​​кодировке base64. После успешного подключения на телевизоре появляется всплывающее окно, которое необходимо принять. Если пользователь принимает запрос, телевизор отправляет ответ JSON, содержащий токен:

"data":{
    "clients":[ ... ],
    "id":"...",
    "token":"28852140"
},
"event":"ms.channel.connect"

Этот токен используется для проверки подлинности соединений с тем же именем путем присоединения &token=value к URL-адресу. Отправка команд до того, как пользователь примет всплывающее окно, игнорируется.

Что работает

Подходы командной строки с wscat и curl работают. Телевизор показывает всплывающее окно и отправляет ответ:

$ wscat -n -c https://192.168.0.227:8002/api/v2/channels/samsung.remote.control?name=aW9Ccm9rZXI=
Connected (press CTRL+C to quit)
< {"data":{"clients":[...], "id":"...", "token":"57940060"}, "event":"ms.channel.connect"}

dart - dart.io.WebSocket

Следующий код запускает всплывающее окно и получает ответ а также.

  WebSocket ws = await WebSocket.connect(url,
      compression: CompressionOptions.compressionOff);
  ws.pingInterval = Duration(seconds: 10000);

  ws.listen(print, onError: print, onDone: () {
    print("done");
    print(ws.closeCode);
    print(ws.closeReason);
  });

  await Future.delayed(Duration(seconds: 30));
  ws.close();

Проблема

Я хочу использовать python для подключения к веб-сокету, аутентификации моего сеанса и отправки команд удаленного управления. Это не работает для следующих реализаций.

python - websocket liris

Всплывающее окно не появляется и нет ответа от телевизора. Сокет не закрывается.

from websocket import create_connection
from ssl import CERT_NONE 

sock = create_connection(url, sslopt={"cert_reqs": CERT_NONE})

print(sock.recv())

python - websockets aaugustin

Всплывающее окно не появляется, и кажется, что соединение закрыто телевизор.

from websockets.client import connect, WebSocketClientProtocol
import ssl
import asyncio

async def connect():
    async with connect(url, ssl=ssl.CERT_NONE) as websocket:
        res = await websocket.recv()
        print(res)

asyncio.get_event_loop().run_until_complete(connect())

Журнал wireshark показывает, что он отправляет HTTP-запрос GET с просьбой обновить веб-сокет. Телевизор отвечает, закрывая соединение с помощью FIN и RST.


Наблюдения

Соединения с общедоступными серверами веб-сокетов не имеют общих проблем, с которыми я сталкиваюсь.

Многие популярные пульты дистанционного управления, доступные для python, имеют две библиотеки веб-сокетов в качестве реализованного решения. Ни один из них не работал для меня.

Сравнение пакетов, отправленных реализациями python и инструментами командной строки, не показывает заметной разницы для меня.

wscat отправляет 80-байтовый длинный Пакет на телевизор каждые четыре секунды. Я полагаю, это пинг / понг.

Как я могу продолжить расследование?

Ответы [ 3 ]

2 голосов
/ 18 апреля 2020

Как насчет попытки реализации веб-сокета Tornado?

async def samsung_ws():
    ws_req = HTTPRequest("wss://ip:8002/api/v2/samsung.remote.control?name=value", validate_cert=False)
    ws = await websocket_connect(ws_req)
    ws.write_message("hello")
    while True:
        msg = await ws.read_message()
        if not msg:
            break
        print(msg)

В зависимости от того, как построен веб-сервер, вам может потребоваться запросить веб-страницу перед подключением к веб-сокету, потому что в вашем примере wscat я заметил, что вы используя https:// вместо wss://.

Можете ли вы опубликовать образец пробега дротика (с использованием url)?

0 голосов
/ 17 апреля 2020

Гм .... У меня есть некоторый опыт подключения веб-сокетов с использованием python веб-сокетов. В статье вы указываете, что ваши соединения веб-сокетов будут автоматически отключаться от сервера.

Я думаю, что вызов механизма "ping-pong" в модуле веб-сокетов вызывает эту проблему.

Механизм по умолчанию статус true, это означает, что вы будете периодически отправлять пинг-знак серверу веб-сокетов, если сервер не отправляет вам pong, модуль будет считать, что сервер был выключен. Для этого вам просто нужно установить «ping» -pong "

status to False.

    async def connect():
    async with connect(url, ssl=ssl.CERT_NONE,close_timeout = None,ping_interval = None) as websocket:
        res = await websocket.recv()
        print(res)

asyncio.get_event_loop().run_until_complete(connect())

Это все мое личное мнение, вы можете попробовать это.

0 голосов
/ 15 апреля 2020

Почему бы не использовать модуль более высокого уровня Python, такой как requests? Вы можете попробовать следующее:

import requests

params = (
    ('name', 'aW9Ccm9rZXI='),
)

response = requests.get('https://192.168.0.227:8002/api/v2/channels/samsung.remote.control', params=params)
...