Владельцы компонентов умного дома от Xiaomi знают, что большая часть их делится на умеющие общаться по zigbee или bluetooth. Нас будет интересовать шлюз для zigbee девайсов версии 2, т.к. именно там появился функционал радио, который по дефолту может воспроизводить только китайские интернет-радиостанции.
Конечно, в интернете есть проект, с помощью которого можно не хитро добавить различные другие радиостанции, но мы пойдем другим путем и будем делать из шлюза беспроводную колонку.
Что нужно?
Для успешного осуществления операции нужно:
- Собственно, сам ZigBee шлюз версии не менее 2 (в ней появилось радио)
- Любой веб-сервер
- Смартфон на котором есть рут и установленная софтина MiHome c выбранной страной China Mainland
Что будем делать?
Для того, чтобы сделать из нашего шлюза беспроводную колонку нужно прикинуться интернет-радио потоком и обучить шлюз, что стучаться за списком станций нужно именно к нам, а не на китайское API.
Для того, чтобы понять, как приложение на телефоне общается с китайскими серверами, можно поснифить трафик, но я избавлю вас от этого геморроя 🙂 Желающие расширить свой кругозор — можете заняться этим факультативно.
Итак, нас будут интересовать три запроса и, соответственно, ответа к китайскому API, которое живет по адресу api.ximalaya.com:
- /openapi-gateway-app/live/radios
- /openapi-gateway-app/live/get_radios_by_ids
- /openapi-gateway-app/search/radios
Слово openapi в пути намекает на что-то открытое, но публичной спецификации я не нашел. Запрос идет с параметрами, которые для наших целей не нужны, поэтому отбрасываем их.
Я использовал в качестве вебсервера nginx, вот конфиг:
server { listen *:80; server_name api.io.mi.com ximalaya.com www.ximalaya.com api.ximalaya.com mobile.ximalaya.com open.ximalaya.com ximiraga.ru www.ximiraga.ru; root /opt/xiaomiradio/www; index index.php index.html index.htm; access_log /var/log/nginx/radio_access.log; error_log /var/log/nginx/radio_error.log; location @ximalaya { proxy_pass http://api.ximalaya.com; } }
Создайте в корне вашего вебсервера такую же иерархию. Дополнительно создайте в корне вебсервера папки radio и hls. Все обращения по этим путям должны выводить один и тот же JSON, поэтому есть смысл сделать их ссылками на файл, который назовем stations.json
Вот его содержимое:
{ "total_page":1, "total_count":1, "current_page":0, "radios":[ { "id":527782023, "kind":"radio", "program_name":"AirSound1", "radio_name":"AirSound1", "radio_desc":"", "schedule_id":0, "support_bitrates":[ 64 ], "rate24_aac_url":"", "rate64_aac_url":"http://<ваш адрес в локальной сети>/hls/live1.m3u8", "rate24_ts_url":"", "rate64_ts_url":"", "radio_play_count":1, "cover_url_small":"http://<ваш адрес в локальной сети>/radio/527782023/cover_small.png", "cover_url_large":"http://<ваш адрес в локальной сети>/radio/527782023/cover_big.png", "updated_at":0, "created_at":0 } ] }
Как можно видеть, тут всё просто — мы отдаем массив радио с указанием, где искать поток. Если у вас несколько шлюзов — можете сделать несколько каналов. Важное замечаение — указываемый тут адрес должен быть доступен со шлюза!
Для того, чтобы приложение увидело ваши изменения необходимо отредактировать hosts на смартфоне и прописать туда соответствие api.ximalaya.com адресу вашего вебсервера.
Теперь о том, как получить поток. Я решил выводить всё со своей звуковой карты с ПК, на котором развернут веб-сервер. Для этого будем использовать ffmpeg:
#!/bin/bash ffmpeg -f alsa -i hw:Loopback,1,0 -c:a libfdk_aac -b:a 64k -f ssegment -segment_list /opt/xiaomiradio/hls/live1.m3u8 -segment_list_flags +live -segment_time 1 -segment_list_size 1 -segment_wrap 5 -segment_list_entry_prefix http://<ваш адрес в локальной сети>/hls/ /opt/xiaomiradio/hls/64%03d.aac
Обратите внимание на пути и адрес веб-сервера — подставьте ваши.
В принципе, это всё для успешной работы — запустите скрипт ffmpeg, он начнет создавать сегменты со звуком с вашей звуковой карты, запустите приложение на телефоне и выберите вашу станцию — через секунду-две должен пойти звук с ПК.
Источник