PHPでnasneの録画情報を取得する
「brew 予約 秋アニメ2013」 とか出来てほしい
— ぜのぷ (@xenop) September 3, 2013
nasneなら出来そうな気がした
ソニーが出してるnasneというネットワークレコーダーがありまして、わしはこれを使って毎日アニメを録画する日々を送っています。かなり未視聴が貯まってますが。
- 出版社/メーカー: ソニー・コンピュータエンタテインメント
- 発売日: 2012/08/30
- メディア: Video Game
- 購入: 7人 クリック: 513回
- この商品を含むブログ (104件) を見る
その名の通りNASなのでネットワークに繋いで色々出来るんですね。
DTCP-IPっていうのに対応してるクライアントを使えばスマホやタブレットで録画番組が見れたり、CHAN-TORUっていうサイトにnasneを登録しておけば外出先からでも予約を入れられたり凄い便利なんです。
で、これならAPIとか探すだけで簡単に予約入れられそうな気がしたので調べてみました。
DLNA
こういったメディア機器間の通信は、DLNAという業界標準が策定されている模様。
今回はメディアのコーデックとかその辺はどうでもよくて、録画の操作をしたいだけなのでいろいろ割愛。
nasneは、このDLNAをさらに拡張して録画の投入や情報取得を行っているようなので、パケットを解析して調査。
nasneが提供しているService
http://(nasneのIPアドレス):58888/
に接続すると、以下のようなXMLが取得出来る
<root xmlns="urn:schemas-upnp-org:device-1-0" xmlns:dlna="urn:schemas-dlna-org:device-1-0" xmlns:av="urn:schemas-sony-com:av" xmlns:s-bras="urn:s-bras-org:s-bras"> <specVersion> <major>1</major> <minor>0</minor> </specVersion> <device> <dlna:X_DLNADOC xmlns:dlna="urn:schemas-dlna-org:device-1-0">DMS-1.50</dlna:X_DLNADOC> <dlna:X_DLNACAP xmlns:dlna="urn:schemas-dlna-org:device-1-0">dtcp-move</dlna:X_DLNACAP> <deviceType>urn:schemas-upnp-org:device:MediaServer:1</deviceType> <friendlyName>molonasne</friendlyName> <manufacturer>Sony Computer Entertainment Inc.</manufacturer> <manufacturerURL>http://www.playstation.com/</manufacturerURL> <modelDescription>nasne</modelDescription> <modelName>nasne</modelName> <av:standardCDS>5.0</av:standardCDS> <av:videoRoot>0/video</av:videoRoot> <av:musicRoot>0/music</av:musicRoot> <av:photoRoot>0/photo</av:photoRoot> <av:X_WakeupOnLAN>1</av:X_WakeupOnLAN> <av:videoLiveTunerContainer>0/video/LiveTuner</av:videoLiveTunerContainer> <s-bras:productName xmlns:s-bras="urn:s-bras-org:s-bras">CECH-ZNR1J</s-bras:productName> <serviceList> <service> <serviceType>urn:schemas-upnp-org:service:ContentDirectory:1</serviceType> <serviceId>urn:upnp-org:serviceId:ContentDirectory</serviceId> <SCPDURL> http://192.168.11.100:58888/MediaServer_ContentDirectory/scpd.xml </SCPDURL> <controlURL> http://192.168.11.100:58888/MediaServer_ContentDirectory/control </controlURL> <eventSubURL> http://192.168.11.100:58888/MediaServer_ContentDirectory/event </eventSubURL> </service> <service> <serviceType> urn:schemas-xsrs-org:service:X_ScheduledRecording:2 </serviceType> <serviceId>urn:xsrs-org:serviceId:X_ScheduledRecording</serviceId> <SCPDURL>http://192.168.11.100:64230/XSRS.xml</SCPDURL> <controlURL>http://192.168.11.100:64230/XSRS</controlURL> <eventSubURL>http://192.168.11.100:64230/XSRS</eventSubURL> </service> </serviceList> </device> </root>
一部省略しているが、SOAPでやりとり出来ることが分かる。
(192.168.11.100は、我が家のnasneのローカルIP)
この中でも「urn:schemas-upnp-org:service:ContentDirectory」などはDLNAで定義されている部分だが「urn:schemas-xsrs-org:service:X_ScheduledRecording」はnasneが拡張した部分っぽい。
XSRS.xmlをのぞいてみると
<scpd xmlns="urn:schemas-upnp-org:service-1-0"> <specVersion> <major>1</major> <minor>0</minor> </specVersion> <actionList> <action> <name>X_CreateRecordSchedule</name> <argumentList> <argument> <name>Elements</name> <relatedStateVariable>A_ARG_TYPE_Result</relatedStateVariable> <direction>in</direction> </argument> <argument> <name>RecordScheduleID</name> <relatedStateVariable>A_ARG_TYPE_ObjectID</relatedStateVariable> <direction>out</direction> </argument> <argument> <name>Result</name> <relatedStateVariable>A_ARG_TYPE_Result</relatedStateVariable> <direction>out</direction> </argument> <argument> <name>UpdateID</name> <relatedStateVariable>StateUpdateID</relatedStateVariable> <direction>out</direction> </argument> </argumentList> </action> </serviceStateTable> </scpd>
長いのでがっつり省略しているがこんな感じ。
まぁ提供しているAPIの種類と、パラメータなどが書いてある説明書みたいなものだと考えれば楽。
ではリクエストを投げてみましょう
SOAPなのでHTTPリクエストを投げればOKだけど、64230ポートから投げる必要がある。
PHPでfsockopenでソケットを開いて、HTTPリクエストを組み立ててそのまま送ってみた。これと同じことはTelnetでも出来る。
<?php $fp = fsockopen('192.168.11.100', 64230); $data = <<<EOM <?xml version="1.0" encoding="utf-8"?> <s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> <s:Body> <u:X_GetTitleList xmlns:u="urn:schemas-xsrs-org:service:X_ScheduledRecording:2"> <SearchCriteria /> <Filter /> <StartingIndex>0</StartingIndex> <RequestedCount>0</RequestedCount> <SortCriteria /> </u:X_GetTitleList> </s:Body> </s:Envelope> EOM; $data = str_replace("\n", "\r\n", $data); $length = strlen($data); $request = <<<EOM POST /XSRS HTTP/1.1 HOST: 192.168.11.100:64230 SOAPACTION: "urn:schemas-xsrs-org:service:X_ScheduledRecording:2#X_GetTitleList" CONTENT-TYPE: text/xml; charset="utf-8" Content-Length: {$length} EOM; $request = str_replace("\n", "\r\n", $request); fwrite($fp, $request . "\r\n\r\n" . $data); ob_start(); fpassthru($fp); $response = ob_get_clean(); fclose($fp); $response = explode("\r\n\r\n", $response, 2); var_dump($response);
192.168.11.100 になっている部分は、適宜自分の家のnasneのローカルIPに書き換えればOK
するとXMLが返ってくる。
XMLよりJSONの方が好きなので、JSONに変換すると以下のようなデータが取得できる。
[ { attributes: { id: "13779485880000000254" }, title: "きんいろモザイク #9", scheduledStartDateTime: "2013-08-31T20_29_49+0900", scheduledDuration: "1814", scheduledChannelID: "0x014d", desiredQualityMode: "230", genreID: "112", reservationCreatorID: "2210", titleProtectFlag: "0", titleNewFlag: "1", recordingFlag: "0", recordDestinationID: "USBHDD", recordSize: "634", lastPlaybackTime: "notplayed", portableRecordFile: "255" }, { attributes: { id: "13779611860000000255" }, title: "<物語>シリーズ セカンドシーズン", scheduledStartDateTime: "2013-08-31T23_59_46+0900", scheduledDuration: "1817", scheduledChannelID: "0x5c38", desiredQualityMode: "230", genreID: "112", reservationCreatorID: "2000", titleProtectFlag: "0", titleNewFlag: "0", recordingFlag: "0", recordDestinationID: "USBHDD", recordSize: "1480", lastPlaybackTime: "2013-09-02T01_33_25+0900", portableRecordFile: "276" }]
予約も入れたい
情報は取得出来たんだけど、予約を入れるパラメータがまだ解析し終わってないので入れられない。
そのうち時間があれば、予約入れる方法も確立して「$ php nasne.php rec 2013_autumn_anime」とか出来るようにしたいね…