phonypianistのメモ

調査したことなどをメモ代わりに書いています

UPnPによるDLNAサーバの探索

DLNAサーバ(おうちクラウドDIGA)にある音楽ファイルを、スマホで操作してGoogle Homeで再生したい。

スマホDLNAクライアントアプリを入れて、スマホGoogle Homeにキャストしてみたところ、再生はできるものの、アプリのせいなのかわからないが途中で止まる。
またスマホで別の操作をしていると(ゲームとか)、その音がGoogle Homeから流れ出てしまう。

これはよろしくない。

ということで、次のような構成で音楽を再生できるようにすることを目標として、いろいろ調べてみることにした。

f:id:phonypianist:20190130005558p:plain
最終構成(予定)

まずは、音楽データがあるDLNAサーバ(DMS)と通信できる必要がある。

ここの記事を参考にさせてもらい、Python 3.7でローカルネットワーク上のDLNAサーバを探すスクリプトを作って実行してみた。
DLNAってなんじゃらほい? - SSDPを喋ってみる - - 初老のボケ防止日記

import socket

timeout = 10

msearch_request_lines = (
    'M-SEARCH * HTTP/1.1',
    'HOST: 239.255.255.250:1900',
    'MAN: "ssdp:discover"',
    f'MX: {timeout}',
    'ST:ssdp:all',
    '',
    ''
)

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.settimeout(timeout)
msearch_request_body = '\r\n'.join(msearch_request_lines)
sock.sendto(msearch_request_body.encode('utf-8'), ('239.255.255.250', 1900))
while True:
    try:
        res, device = sock.recvfrom(4096)
        print(f'>>>>>>>>>> from {device} <<<<<<<<<<')
        print(res.decode('utf-8'))
    except socket.timeout:
        break

sock.close()

すると、やたらいっぱい応答が返ってきた。
その一部を載せておく。

>>>>>>>>>> from ('xxx.xxx.xxx.1', 1900) <<<<<<<<<<
HTTP/1.1 200 OK
CACHE-CONTROL: max-age=120
ST: upnp:rootdevice
USN: uuid:bc329e00-1dd8-11b2-8601-84afec3998c1::upnp:rootdevice
EXT:
SERVER: SDK 4.3.0.0 UPnP/1.0 MiniUPnPd/1.6
LOCATION: http://xxx.xxx.xxx.1:57323/WFADeviceDesc.xml


>>>>>>>>>> from ('xxx.xxx.xxx.1', 1900) <<<<<<<<<<
HTTP/1.1 200 OK
CACHE-CONTROL: max-age=120
ST: urn:schemas-wifialliance-org:device:WFADevice:1
USN: uuid:bc329e00-1dd8-11b2-8601-84afec3998c1::urn:schemas-wifialliance-org:device:WFADevice:1
EXT:
SERVER: SDK 4.3.0.0 UPnP/1.0 MiniUPnPd/1.6
LOCATION: http://xxx.xxx.xxx.1:57323/WFADeviceDesc.xml


>>>>>>>>>> from ('xxx.xxx.xxx.25', 1900) <<<<<<<<<<
HTTP/1.1 200 OK
CACHE-CONTROL: max-age=1800
DATE: Tue, 29 Jan 2019 15:04:54 GMT
EXT:
LOCATION: http://xxx.xxx.xxx.25:60607/D8AFF1C0AF18/Server1/ddd
SERVER: Linux/4.0 UPnP/1.0 Panasonic-UPnP-MW/1.0
ST: urn:schemas-upnp-org:service:RenderingControl:1
USN: uuid:4D454930-0300-1000-8000-D8AFF1C0AF18::urn:schemas-upnp-org:service:RenderingControl:1


>>>>>>>>>> from ('xxx.xxx.xxx.25', 1900) <<<<<<<<<<
HTTP/1.1 200 OK
CACHE-CONTROL: max-age=1800
DATE: Tue, 29 Jan 2019 15:04:54 GMT
EXT:
LOCATION: http://xxx.xxx.xxx.25:60607/D8AFF1C0AF18/Server1/ddd
SERVER: Linux/4.0 UPnP/1.0 Panasonic-UPnP-MW/1.0
ST: urn:schemas-upnp-org:service:ConnectionManager:1
USN: uuid:4D454930-0300-1000-8000-D8AFF1C0AF18::urn:schemas-upnp-org:service:ConnectionManager:1


>>>>>>>>>> from ('xxx.xxx.xxx.25', 1900) <<<<<<<<<<
HTTP/1.1 200 OK
CACHE-CONTROL: max-age=1800
DATE: Tue, 29 Jan 2019 15:04:52 GMT
EXT:
LOCATION: http://xxx.xxx.xxx:60606/D8AFF1C0AF18/Server0/ddd
SERVER: Linux/4.0 UPnP/1.0 Panasonic-UPnP-MW/1.0
ST: urn:schemas-upnp-org:service:ContentDirectory:2
USN: uuid:4D454930-0100-1000-8000-D8AFF1C0AF18::urn:schemas-upnp-org:service:ContentDirectory:2

・・・

xxx.xxx.xxx.1というのは無線ルータ。UPnPで応答するものはすべて何かしら返してくる様子。
音楽データがあるDLNAサーバはxxx.xxx.xxx.25。これからも複数の応答が返ってきている。役割毎に応答を返している様子。

今回はDLNAサーバにある音楽データを取得したいので、応答のUSNにContentDirectoryを含むものが対象。
上記の応答結果だと一番下に記載しているものが該当する。

とりあえずDLNAサーバの検知はできた。

次は、応答のLOCATIONに書かれているURIを辿って、実際の音楽データのURIを取得してみる予定。 →コンテンツの中身の探索