Posted at

VIERAを操作する方法

More than 3 years have passed since last update.


はじめに

パナソニックのテレビ「VIERA」を操作する方法を紹介します。

パナソニックは、「TV Remote」というテレビの操作やスマートフォンなどの動画や写真を表示したり共有するためのスマートフォンアプリを提供しています。

このスマートフォンアプリを使えば、同一LANにあるVIERAを発見、操作することが可能です。

また、このスマートフォンアプリに対応しているVIERAは、内部でHTTPサーバが起動しており、XMLをVIERAに送信することで操作が可能です。


機器を発見する

「TV Remote」には、同一LANにあるVIERAを発見する機能があります。

UPnPで規定されたSSDPを利用して機器を発見します。

UPnPは機器をネットワークに接続すると複雑な設定作業を行わなくても他の機器と通信したり利用できるようにするプロトコルです。

またSSDPは、UPnPで用いられるプロトコルの1つで機器の発見や応答を行うためのものです。

サンプルコードをSwift(バージョンは1.2)で記述します。

はじめにヘッダファイルをインポートします。


Bridging_Header.h

#import "AsyncUdpSocket.h"


次に以下のテキストを239.255.255.250:1900に送信します。


M-SEARCH * HTTP/1.1'

ST: urn:panasonic-com:device:p00RemoteController:1

MX: 1

MAN: \"ssdp:discover\"

HOST: 239.255.255.250:1900



sample1.swift

let data = "M-SEARCH * HTTP/1.1'\r\nST: urn:panasonic-com:device:p00RemoteController:1\r\nMX: 1\r\nMAN: \"ssdp:discover\"\r\nHOST: 239.255.255.250:1900\r\n\r\n\r\n" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!

let sock:AsyncUdpSocket = AsyncUdpSocket(delegate: self)
sock.enableBroadcast(true, error: nil)
sock.bindToPort(0, error: nil)
sock.joinMulticastGroup(239.255.255.250, error: nil)
sock.sendData(data, toHost: 239.255.255.250, port: 1900, withTimeout: -1, tag: 1)
sock.receiveWithTimeout(-1, tag: 1)


VIERAが見つかると以下の関数が呼ばれます。hostがVIERAのIPアドレスです。


sample2.swift

func onUdpSocket(sock: AsyncUdpSocket!, didReceiveData data: NSData!, withTag tag: Int, fromHost host: String!, port: UInt16) -> Bool {

println(host) // IPアドレス

return true
}



リモコンキーの送信

発見したVIERAにリモコンキーを送信します。

リモコンキーはリモコンのキー一つ一つに割り当てられたキーのことです。

例えば、次のようなキーがあります。

「NRC_CH_UP-ONOFF」はチャンネルを1つ進めます。

「NRC_VOLUP-ONOFF」はボリュームを1つ高くします。

「NRC_TV-ONOFF」はテレビの電源を切ります。機器によっては内部のHTTPサーバも停止してしまうため再度電源を入れるにはリモコンを使うか、直接電源ボタンを押さなければなりません。

「NRC_RED-ONOFF」はデータ放送の赤ボタンです。

リモコンキーはtomokas/pyvieraを参考にしました。

リモコンキーのXMLは以下のフォーマットです。


sample.xml

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<u:X_SendKey xmlns:u="urn:panasonic-com:service:p00NetworkControl:1">
<X_KeyEvent>NRC_TV-ONOFF</X_KeyEvent>
</u:X_SendKey>
</s:Body>
</s:Envelope>

リモコンキー送信時にヘッダが必要です。

SOAPACTION: "urn:panasonic-com:service:p00NetworkControl:1#X_SendKey"

これをhttp://<IP Address>:55000/nrc/control_0に送信します。

具体的には以下のようなコードになります。

NSMutableURLRequestを組み立て、NSURLConnectionを使ってリモコンキーを送信します。


sample4.swif

    /**

URLリクエストを返します。

:param: host IPアドレス
:param: code リモコンキー
:returns: URLリクエスト
*/
private func commonURLRequest(host: String, code: String) -> NSMutableURLRequest {
let action = "X_SendKey"
let option = "<X_KeyEvent>" + code + "</X_KeyEvent>
let xml = "
<?xml version=\"1.0\" encoding=\"utf-8\"?><s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body><u:%@ xmlns:u=\"urn:panasonic-com:service:p00NetworkControl:1\">%@</u:%@></s:Body></s:Envelope>"
let header = NSString(format: "\"urn:panasonic-com:service:p00NetworkControl:1#%@\"", action)
let input = NSString(format: xml, action, option, action)
let url = "http://" + host + ":55000/nrc/control_0"
let request = NSMutableURLRequest(URL: NSURL(string: url)!)
request.HTTPMethod = "POST"
request.HTTPBody = input.dataUsingEncoding(NSUTF8StringEncoding)
request.addValue(header as String, forHTTPHeaderField: "SOAPACTION")

return request
}



最後に

今回の内容をまとめたライブラリをGitHubで公開しています。