Привет, хабра гиктаймс-читатель! Сегодня я научу тебя как из бесполезного функционала получить полезный. Получать будем на примере умного дома от небезызвестной компании Xiaomi и её продукта в виде ZigBee-шлюза.

Владельцы компонентов умного дома от 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, он начнет создавать сегменты со звуком с вашей звуковой карты, запустите приложение на телефоне и выберите вашу станцию — через секунду-две должен пойти звук с ПК.