Обновление 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"}
Следующий код запускает всплывающее окно и получает ответ а также.
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-байтовый длинный Пакет на телевизор каждые четыре секунды. Я полагаю, это пинг / понг.
Как я могу продолжить расследование?