Grousenet UPnP ﾌﾟﾛｸﾞﾗﾐﾝｸﾞﾏﾆｭｱﾙ 補足資料(Appendix)

Grousenet UPnP Full プログラミングマニュアル 補足資料(Appendix)

Appendix-A ： UPnP 開発の手引き - デバイス実装編─────────────────────────────────────────────────────

Appendix-A では、本 UPｎP ミドルウェアを使用した UPnP デバイスの実装方法例に関して、弊社提供のサン
プルコードを例に記載します。

01) 全体の流れ
本 UPｎP ミドルウェアを使用して UPnP デバイスを実装する場合の基本手順は、以下の通りです。
Step
アクション
説明
1
ディスクリプションドキュメントの準備
実装するデバイスに応じた・ デバイスディスクリプションドキュメント
・ サービスディスクリプションドキュメントを用意します。
2
起動・停止処理の実装
UPnP デバイスの起動・停止処理を実装します。
アドバタイズ定期送信処理の実装
アドバタイズの定期送信処理を実装し、UPnP 接続を可能にします。
3
デバイスイベントハンドラ関数の実装
デバイスイベントハンドラ関数を実装し、コントロー
ルポイントからの各種イベントに対応した制御を実装します。

02) ディスクリプションドキュメントの準備
ディスクリプションドキュメントは、UPnP 規定に則った形で記載して下さい。
ファイルフォーマットは、必ず UTF-8 で作成して下さい。
なお、提供サンプルコードで使用している RadioDevice は、UPnP フォーラムに規定されているデバイス
ではなく、オリジナルのデバイスです。
以下に、Radio Device の内容を記載します。
① デバイスディスクリプションドキュメント(devdesc.xml)
下記が、RadioDevice のデバイスディスクリプションドキュメントです。
記載されている内容のうち、UDN はデバイス毎に変更しなければならないデータです。
UPnP を起動する前に、MAC アドレス等の確実に重ならない値で UDN を生成し、デバイスディ
スクリプションドキュメントを自動生成するような制御を用意しておくと、同一製品を同一ネットワー
ク上で UPnP を動作させる場合の競合を防ぐことが出来ます。
☆ 提供サンプルコードでは、デバイスディスクリプションドキュメントの自動生成処理を行っております。
──────────────────────────────────────────
<?xml version="1.0" encoding="utf‑8"?><root xmlns="urn:schemas‑
upnp‑org:device‑1‑0"><specVersion><major>1</major><minor>0</minor></specVersion>

Grousenet UPnP ﾌﾟﾛｸﾞﾗﾐﾝｸﾞﾏﾆｭｱﾙ 補足資料(Appendix)<device><deviceType>urn:schemas‑upnp‑org:device:Radiodevice:1</deviceType><friendlyName>UPnP for S1S6xK Sample Device</friendlyName><manufacturer>SEC Corp.</manufacturer><manufacturerURL>http://www.hotweb.or.jp/grouse/</manufacturerURL><modelDescription>UPnP Sample Radio Device 1.0</modelDescription><modelName>Grousenet UPnP Series</modelName><modelNumber>1.0</modelNumber><modelURL>http://www.hotweb.or.jp/grouse/</modelURL><UDN>uuid:Upnp‑RadioEmulator‑1̲0‑0000000000001</UDN><serviceList><service><serviceType>urn:schemas‑
upnp‑org:service:RadioControl:1</serviceType><serviceId>urn:upnp‑org:serviceId:RadioControl1</serviceId><SCPDURL>/RaCoSCDP.xml</SCPDURL><controlURL>/upnp/control/RadioControl1</controlURL><eventSubURL>/upnp/event/RadioControl1</eventSubURL></service><service><serviceType>urn:schemas‑
upnp‑org:service:RadioSetting:1</serviceType><serviceId>urn:upnp‑org:serviceId:RadioSetting1</serviceId><SCPDURL>/RaSeSCDP.xml</SCPDURL><controlURL>/upnp/control/RadioSetting1</controlURL><eventSubURL>/upnp/event/RadioSetting1</eventSubURL></service></serviceList><presentationURL>/index.htm</presentationURL></device></root>──────────────────────────────────────────

② サービスディスクリプションドキュメント(RaCoSCDP.xml/RaSeSCDP.xml)
下記が、RadioDevice のコント ロールサ ービスのサ ービスディスク リプシ ョンドキュメ ント(RaCoSCDP.xml)です。アクション一覧などが定義されています。
☆ 提供サンプルコードでは、サービスディスクリプションドキュメントの自動生成処理を行っております。
──────────────────────────────────────────
<?xml version="1.0"?><scpd xmlns="urn:schemas‑
upnp‑org:service‑1‑0"><specVersion><major>1</major><minor>0</minor></specVersion><actionList><action><name>ModulationAM</name><argumentList><argument><retval /><name>Modulation</name><relatedStateVariable>Modulation</relatedStateVariable><direction>out</direction></argument></argumentList></action><action><name>ModulationFM</name><argumentList><argument><retval /><name>Modulation</name><relatedStateVariable>Modulation</relatedStateVariable><direction>out</direction></argument>

Grousenet UPnP ﾌﾟﾛｸﾞﾗﾐﾝｸﾞﾏﾆｭｱﾙ 補足資料(Appendix)</argumentList></action><action><name>ModulationTV</name><argumentList><argument><retval /><name>Modulation</name><relatedStateVariable>Modulation</relatedStateVariable><direction>out</direction></argument></argumentList></action><action><name>SetBand</name><argumentList><argument><name>Band</name><relatedStateVariable>Band</relatedStateVariable><direction>in</direction></argument><argument><name>NewBand</name><relatedStateVariable>Band</relatedStateVariable><direction>out</direction><retval /></argument></argumentList></action><action><name>IncreaseBand</name><argumentList><argument><name>Band</name><retval /><relatedStateVariable>Band</relatedStateVariable><direction>out</direction></argument></argumentList></action><action><name>DecreaseBand</name><argumentList><argument><name>Band</name><retval /><relatedStateVariable>Band</relatedStateVariable><direction>out</direction></argument></argumentList></action></actionList><serviceStateTable><stateVariable sendEvents="yes"><name>Modulation</name><dataType>i4</dataType><allowedValueRange><minimum>1</minimum><maximum>3</maximum></allowedValueRange><defaultValue>1</defaultValue></stateVariable><stateVariable sendEvents="yes"><name>Band</name><dataType>i4</dataType><allowedValueRange><minimum>0</minimum><maximum>200</maximum>

Grousenet UPnP ﾌﾟﾛｸﾞﾗﾐﾝｸﾞﾏﾆｭｱﾙ 補足資料(Appendix)<step>1</step></allowedValueRange><defaultValue>78</defaultValue></stateVariable></serviceStateTable></scpd>──────────────────────────────────────────Grousenet UPnP ﾌﾟﾛｸﾞﾗﾐﾝｸﾞﾏﾆｭｱﾙ 補足資料(Appendix)

03) UPnP 起動関数・停止関数
ディスクリプションドキュメントの準備が出来たら、次はユーザアプリケーションを実装します。まずは
UPnP デバイスの起動及び停止処理を実装します。
起動関数：RadioDeviceStart
起動処理は、デバイス起動時に一度だけ Call するように実装します。
Step

実装

ソースコード記載

1

デバイスハンドルの準備

2

config 構造体メンバ設定/*****************************************************************UPnP Device により供給されるデバイスハンドル******************************************************************/
UpnpDevice̲Handle device̲handle = ‑1;/* config 構造体メンバ設定 */memset(&config, 0, sizeof(tUpnp̲Conf));
memcpy(config.Ipaddress,ip̲address,sizeof(config.Ipaddress));
config.PortNo = port;
config.UseWebserver = DUPNP̲OFF;// 既製 Web サーバ使用
config.TcpPortNo = TCP̲PORTNO;// UPnP で使用する TCP ポート番号
config.UdpPortNo = UDP̲PORTNO;// UPnP で使用する UDP ポート番号
config.UpnpTaskPri = UPNP̲TASK̲PRI;// UPnP タスクプライオリティ
config.ClsTimAcp = CLS̲TIM̲ACP;// TCP Connection クローズ待ちタイマー
config.IPTTL = DEF̲IP̲TTL;// SSDP にて使用する UDP TTL=4(RadioDeviceStart 関 数
Call 前)config.UpnpMplSize = UPNP̲BUFSIZ;
3

ﾕｰｻﾞｱﾌﾟﾘｹｰｼｮﾝ内部データの初期化(RadioDeviceStart 関 数
Call 前)4

UpnpInit 関数によるミド
ルウェアの初期化(RadioDeviceStart 関 数
Call 前)5

UpnpRegisterRootDevice
関 数によ るルート デバイ
スの登録

6

UpnpRegisterRootDeviceの結果を確認。
UpnpSendAdvertisement 関
数 による アドバタ イズ送信の開始。

// UPnP メモリプールサイズ設定 128KByte// 本 APL の初期化
SampleUtil̲Initialize();☆SampleUtil̲Initialize 関数の詳細は実際の関数実装を確認して下さい。
ret = UpnpInit( &config );if(ret != UPNP̲E̲SUCCESS ){//Upnp 初期化に失敗したなら
UpnpFinish();return ret;}// ポート番号が省略された場合の対処
if(port == 0){
port = UPNP̲SAMPLE̲PORT;}
sprintf( (char *)desc̲doc̲url,"http://%d.%d.%d.%d:%d/%s",
ip̲address[0],ip̲address[1],ip̲address[2],ip̲address[3],port, desc̲doc̲name );/* Root Device の登録 */ret = UpnpRegisterRootDevice( (char *)desc̲doc̲name,RadioDeviceCallbackEventHandler,&device̲handle, &device̲handle );if(ret != UPNP̲E̲SUCCESS ){//ルートデバイスの登録に失敗したなら
UpnpFinish(); //UPnP 終了
return ret;}else{//Radio デバイス状態テーブル初期化
RadioDeviceStateTableInit((char *)desc̲doc̲name, (char *)desc̲doc̲url );☆Radio デバイス状態テーブル初期化処理の詳細は、実際の関数実装を確認して下さい。

Grousenet UPnP ﾌﾟﾛｸﾞﾗﾐﾝｸﾞﾏﾆｭｱﾙ 補足資料(Appendix)// ディスクリプション(アドバタイズ送信)開始
ret = UpnpSendAdvertisement( device̲handle, default̲advr̲expire );if( ret != UPNP̲E̲SUCCESS ){//アドバタイズメント(広告)送信に失敗したなら
UpnpFinish( );//Upnp 終了
return ret;}}
return (ret);}

停止関数：RadioDeviceStop
停止処理は、デバイス終了時に一度だけ Call するように実装します。
IP アドレスの変更など、ネットワーク状態が変更になった場合や、別なデバイスを起動したい場合などは、一旦本関数でデバイスを終了し、再度デバイスを起動します。
Step
1

実装

ソースコード記載

UpnpUnRegisterRootDevice

UpnpUnRegisterRootDevice( device̲handle ); //ルートデバイス登録解除

関数 Call によるルートデバイスの削除UpnpFinish 関数による、ミ2

UpnpFinish(); //Upnp 終了

ドルウェアの終了
ﾕｰｻﾞｱﾌﾟﾘｹｰｼｮﾝ内部データ

3の開放

SampleUtil̲Finish( ); //サンプル終了☆SampleUtil̲Finish 関数の詳細は実際の関数実装を確認して下さい。

上記に示すとおり、UPnP デバイスの起動後は、結果を見て、UpnpSendAdvertisement 関数によりデバイスアドバタイズメントの定期送信機能を開始して下さい。
本関数 Call により、指定した時間間隔で、NOTIFY(ssdp:alive)が送信され、コントロールポイントにデバイスの存在を通知できるようになります。
UpnpRegisterRootDevice 関数 で指 定す る デバ イ スイ ベ ント ハ ン ドラ 関 数 (RadioDeviceCallback
EventHandler)は、下記のように実装しています。詳細はデバイスイベントハンドラの項を参照して下さい。
引数 EventType で何のイベントを受信したかを判定し、それぞれの処理関数を Call するような実装にしています。
──────────────────────────────────────────
ER RadioDeviceCallbackEventHandler( Upnp̲EventType EventType,
void *Event,
void *Cookie ){switch ( EventType ){//イベントのタイプ
case UPNP̲EVENT̲SUBSCRIPTION̲REQUEST: //サブスクリプション(購読)要求{
RadioDeviceHandleSubscriptionRequest( ( structUpnp̲Subscription̲Request* )Event );//Radio デバイスサブスクリプション要求操作
break;}
case UPNP̲CONTROL̲GET̲VAR̲REQUEST: //変数獲得要求{
RadioDeviceHandleGetVarRequest( ( struct Upnp̲State̲Var̲Request

Grousenet UPnP ﾌﾟﾛｸﾞﾗﾐﾝｸﾞﾏﾆｭｱﾙ 補足資料(Appendix)* )Event );//Radio デバイス変数獲得要求操作
break;}
case UPNP̲CONTROL̲ACTION̲REQUEST: //動作要求{
RadioDeviceHandleActionRequest( ( struct Upnp̲Action̲Request * )Event );//Radio デバイス動作要求操作
break;}
default: //不正なイベントタイプ// 無視する。
break;}
return ( E̲OK );}──────────────────────────────────────────

以下に、それぞれのイベント毎の実装方法について記載します。

Grousenet UPnP ﾌﾟﾛｸﾞﾗﾐﾝｸﾞﾏﾆｭｱﾙ 補足資料(Appendix)04) コールバック関数の実装 Part1−SUBSCRIBE 受信処理
SUBSCRIBE 受信時は、デバイスイベントハンドラの、★部分のルートを通ります。
──────────────────────────────────────────
ER RadioDeviceCallbackEventHandler( Upnp̲EventType EventType,
void *Event,
void *Cookie ){switch ( EventType ){//イベントのタイプ★
case UPNP̲EVENT̲SUBSCRIPTION̲REQUEST: //サブスクリプション(購読)要求★
{★
RadioDeviceHandleSubscriptionRequest( ( struct★
Upnp̲Subscription̲Request★
* )Event );★
//Radio デバイスサブスクリプション要求操作★
break;★
}
──────────────────────────────────────────RadioDeviceHandleSubscriptionRequest 関数では、以下のように、UpnpAcceptSubscription 関数を使用してサブスクリプション受付処理を実装しています。
コントロールポイントからは、サービス毎に SUBSCRIBE リクエストが来ますので、SUBSCRIBE リクエ
ストで指定された UDN 及びサービス ID が、自分のデバイス情報と合致する場合のみ、サブスクリプショ
ン受付処理を行うようにして下さい。
──────────────────────────────────────────
ER RadioDeviceHandleSubscriptionRequest(
struct Upnp̲Subscription̲Request *sr̲event ){ER̲ID ercd; // 戻り値
UINT i ;ercd = wai̲sem(dUPnP̲SampleSemID); //セマフォ資源獲得
if(ercd != E̲OK){
return ercd; //セマフォ資源獲得失敗}
for( i = 0; i < RADIO̲SERVICE̲SERVCOUNT; i++ ){// サービスの数(ここではコントロールとセッティング 2 つ分)だけループ
if( ( strcmp( sr̲event‑>UDN, Radio̲service̲table[i].UDN ) == 0 ) &&( strcmp( sr̲event‑>ServiceId, Radio̲service̲table[i].ServiceId )== 0 ) ){ //UDN とサービス ID のチェックで問題なければ//サブスクリプションの受け入れ関数コール
UpnpAcceptSubscription( device̲handle,sr̲event‑>UDN,
sr̲event‑>ServiceId,(char ** )Radio̲service̲table[i].

Grousenet UPnP ﾌﾟﾛｸﾞﾗﾐﾝｸﾞﾏﾆｭｱﾙ 補足資料(Appendix)
VariableName,(char ** )Radio̲service̲table[i].
VariableStrVal,
Radio̲service̲table[i].VariableCount,sr̲event‑>Sid );}}
ercd = sig̲sem(dUPnP̲SampleSemID); //セマフォ資源返却
if(ercd != E̲OK){
return ercd; //返却失敗}
return 1;}/* RadioDeviceHandleSubscriptionRequest */なお、最大サブスクリプション数を制限したい場合は UpnpSetMaxSubscriptions 関数、サブスクリプシ
ョン有効期限を制限したい場合は UpnpSetMaxSubscriptionTimeOut 関数を使用します。
UpnpSetMaxSubscriptions 関数は、UpnpRegisterRootDevice 関数 Call 後、UpnpSendAdvertisement
関数 Call 前に本関数を Call するようにして下さい。
上記関数を使用しない場合、最大サブスクリプション数は無制限になり、サブスクリプション有効期限は基本的に、SUBSCRIBE リクエストの TIMEOUT ヘッダに設定されている値に従います。

Grousenet UPnP ﾌﾟﾛｸﾞﾗﾐﾝｸﾞﾏﾆｭｱﾙ 補足資料(Appendix)05) コールバック関数の実装 Part2−SOAP ACTION 受信処理
SOAP ACTION 受信時は、デバイスイベントハンドラの、★部分のルートを通ります。
──────────────────────────────────────────
ER RadioDeviceCallbackEventHandler( Upnp̲EventType EventType,
void *Event,
void *Cookie ){switch ( EventType ){//イベントのタイプ
case UPNP̲EVENT̲SUBSCRIPTION̲REQUEST: //サブスクリプション(購読)要求{
RadioDeviceHandleSubscriptionRequest( ( structUpnp̲Subscription̲Request* )Event );//Radio デバイスサブスクリプション要求操作
break;}
case UPNP̲CONTROL̲GET̲VAR̲REQUEST: //変数獲得要求{
RadioDeviceHandleGetVarRequest( ( struct Upnp̲State̲Var̲Request* )Event );//Radio デバイス変数獲得要求操作
break;}★ case UPNP̲CONTROL̲ACTION̲REQUEST: //動作要求★ {★
RadioDeviceHandleActionRequest( ( struct Upnp̲Action̲Request * )★
Event );★
//Radio デバイス動作要求操作★
break;★ }default: //不正なイベントタイプ// 無視する。
break;}
return ( E̲OK );}──────────────────────────────────────────RadioDeviceHandleActionRequest 関数以降、以下の手順で、・ SOAP ACTION の受信によるデバイスのコントロール制御。
・ 状態変化に伴い、UpnpNotify 関数を使用した NOTIFY(ｲﾍﾞﾝﾄﾒｯｾｰｼﾞ) の送信。
・ UpnpAddToActionResponse 関数を使用した SOAP ACTION レスポンスの生成及びデバイ
スイベントハンドラ関数の終了に伴うレスポンス送信処理。
の制御を行います。SOAP ACTION 受信時は、上記 3 つの制御を行う必要があります。
① 受信した SOAP ACTION の内容を解析し、デバイスのコントロール制御を行います。
──────────────────────────────────────────
ER RadioDeviceHandleActionRequest( struct Upnp̲Action̲Request *ca̲event ){int action̲found = 0; //動作発見フラグ
int i = 0;

Grousenet UPnP ﾌﾟﾛｸﾞﾗﾐﾝｸﾞﾏﾆｭｱﾙ 補足資料(Appendix)

int service = ‑1;
int retCode = 0;char *errorString = NULL;
ca̲event‑>ErrCode = 0;ca̲event‑>ActionResult = NULL;
if((strcmp(ca̲event‑>DevUDN, Radio̲service̲table[RADIO̲SERVICE̲CONTROL].UDN ) == 0) &&(strcmp(ca̲event‑>ServiceID, Radio̲service̲table[RADIO̲SERVICE̲CONTROL].ServiceId) == 0)){// UDN とサービス ID のチェックを行いコントロールサービスであれば// Radio デバイスコントロールサービスの動作を要求する
service = RADIO̲SERVICE̲CONTROL; //サービス名(コントロール)の設定}
else if((strcmp(ca̲event‑>DevUDN, Radio̲service̲table[RADIO̲SERVICE̲SETTING].UDN ) == 0)&&( strcmp(ca̲event‑>ServiceID, Radio̲service̲table[RADIO̲SERVICE̲SETTING].ServiceId ) == 0)){// UDN とサービス ID のチェックを行いセッティングであれば// Radio デバイスセッティングサービスの動作を要求する
service = RADIO̲SERVICE̲SETTING; //サービス名(セッティング)の設定}/*************************************************************//* ACTION 名称に従って、それぞれの動作を行う関数を Call します。*//* 関数へのポインタは、初期化処理で設定しています。

*//*************************************************************/// 最大動作数を超えるか、ACTION 名に NULL が出現するまでループ
for(i=0;((i<RADIO̲MAXACTIONS)&&(Radio̲service̲table[service].ActionNames[i]!=NULL));i++ ){if(!strcmp(ca̲event‑>ActionName,Radio̲service̲table[service].ActionNames[i])){// アクション名が合致した。
// Power が ON のときの場合、または OFF のときだが PowerOn を指示された場合
if((!strcmp(Radio̲service̲table[RADIO̲SERVICE̲CONTROL].VariableStrVal[RADIO̲CONTROL̲POWER],"1"))￨￨(!strcmp( ca̲event‑>ActionName, "PowerOn"))){// Mute が ON のときは音量設定無効
if(((!strcmp( ca̲event‑>ActionName, "SetVolume")) ￨￨(!strcmp( ca̲event‑>ActionName, "IncreaseVolume")) ￨￨(!strcmp( ca̲event‑>ActionName, "DecreaseVolume"))) &&(!strcmp(Radio̲service̲table[RADIO̲SERVICE̲CONTROL].VariableStrVal[RADIO̲CONTROL̲MUTE],"1"))){// Mute 中ですエラーメッセージ設定
errorString = "Mute is On. Volume can't set.";retCode = UPNP̲E̲INTERNAL̲ERROR;}
else{//アクション実行
retCode = Radio̲service̲table[service].actions[i](ca̲event‑>ActionRequest,&ca̲event‑>ActionResult,

事前に ACTION 毎に関数へのポイン
タ登録をしたテーブルを用意しており、該当した ACTION の関数 Callをしています。各関数ともに同じインタフェースにしており、ActionRequest に応答メッセージが設定されリターンされるような実装になっています。

&errorString );
}
}

：<略>
──────────────────────────────────────────Grousenet UPnP ﾌﾟﾛｸﾞﾗﾐﾝｸﾞﾏﾆｭｱﾙ 補足資料(Appendix)

以下は、上記のアクション実行が、仮に IncreaseVolume(ボリュームを１上げる)だった場合のアクション関数です。
──────────────────────────────────────────
ER RadioDeviceIncreaseVolume(

IXML̲Document * in,
IXML̲Document ** out,char **errorString ){return UpdateVolume( 1, in, out, errorString );//音量値更新関数 Call して音量を上げる。
}

──────────────────────────────────────────ER UpdateVolume(int incr, IXML̲Document * in, IXML̲Document ** out, char **errorString ){INT curvolume, newvolume;char *actionName = NULL;
char value[RADIO̲MAX̲VAL̲LEN];
ER̲ID

ercd; // 戻り値

if( incr > 0 ) {actionName = "IncreaseVolume";} else {actionName = "DecreaseVolume";}
ercd = wai̲sem(dUPnP̲SampleSemID); //セマフォ資源獲得
if(ercd != E̲OK) {return ercd; //セマフォ資源獲得失敗}// 現在の値を格納
curvolume = atoi( Radio̲service̲table[RADIO̲SERVICE̲CONTROL]. VariableStrVal[RADIO̲CONTROL̲VOLUME] );ercd = sig̲sem(dUPnP̲SampleSemID); //セマフォ資源返却
if(ercd != E̲OK) {return ercd; //返却失敗}// 新値 = 現在値＋変更値
newvolume = curvolume + incr;
if( newvolume < MIN̲VOLUME ￨￨newvolume > MAX̲VOLUME ) {/* 値不正 */( *errorString ) = "Invalid Volume";
return UPNP̲E̲INVALID̲PARAM;}/* Volume 設定に関するベンダー固有処理はここで記載します。*//**********************************************//* Radio デバイスサービステーブル値の更新*//* この関数で、SUBSCRIBER へ NOTIFY を送信します *//**********************************************/
sprintf( value, "%d", newvolume );ercd = RadioDeviceSetServiceTableVar( RADIO̲SERVICE̲CONTROL, RADIO̲CONTROL̲VOLUME, value );if( ercd ) {Grousenet UPnP ﾌﾟﾛｸﾞﾗﾐﾝｸﾞﾏﾆｭｱﾙ 補足資料(Appendix)：<略>──────────────────────────────────────────Grousenet UPnP ﾌﾟﾛｸﾞﾗﾐﾝｸﾞﾏﾆｭｱﾙ 補足資料(Appendix)② 正常に状態変化を行った場合は、UpnpNotify 関数で、状態変化を通知します。
──────────────────────────────────────────
ER RadioDeviceSetServiceTableVar(UINT service, UINT variable, char *value ){ER̲ID ercd;
if( ( service >= RADIO̲SERVICE̲SERVCOUNT )￨￨( variable >= Radio̲service̲table[service].VariableCount )￨￨( strlen( value ) >= RADIO̲MAX̲VAL̲LEN ) ){// サービス数が定義数以上または、サービス内変数数以上または、// 動作値が定義数以上の場合は終了
return ( 0 );}ercd = wai̲sem(dUPnP̲SampleSemID); //セマフォ資源獲得
if(ercd != E̲OK){

変数の値はユーザ側で管理して下さい。

return ercd; //セマフォ資源獲得失敗}// 指定のサービスの値変更

strcpy( Radio̲service̲table[service].VariableStrVal[variable], value );状態変化を NOTIFY(ｲﾍﾞﾝﾄﾒｯｾｰｼﾞ)で通知します。

// NOTIFY 送信
UpnpNotify( device̲handle,
Radio̲service̲table[service].UDN,
Radio̲service̲table[service].ServiceId,(char **)&Radio̲service̲table[service].VariableName[variable],(char **)&Radio̲service̲table[service].VariableStrVal[variable],
1 );ercd = sig̲sem(dUPnP̲SampleSemID); //セマフォ資源返却
if(ercd != E̲OK){
return ercd; //返却失敗}
return ( 1 );}/* RadioDeviceSetServiceTableVar */──────────────────────────────────────────

③ 結果が正常な場合は、SOAPACTION レスポンスイベントハンドラ関数引数の ErrCode、ErrStr、ActionResult に結果を保存し、結果が正常な場合は、SOAPACTION レスポンスイベントハンドラ
関数を終了します。
──────────────────────────────────────────ER UpdateVolume(int incr, IXML̲Document * in, IXML̲Document ** out, char **errorString ){：<略>/**********************************************//* Radio デバイスサービステーブル値の更新*//* この関数で、SUBSCRIBER へ NOTIFY を送信します *//**********************************************/

SOAP ACTION レスポンスを生成しています。

sprintf( value, "%d", newvolume );ercd = RadioDeviceSetServiceTableVar( RADIO̲SERVICE̲CONTROL, RADIO̲CONTROL̲VOLUME, value );if( ercd ) {/**** Action Response 追加 ****/
ercd = UpnpAddToActionResponse( out, actionName,

Grousenet UPnP ﾌﾟﾛｸﾞﾗﾐﾝｸﾞﾏﾆｭｱﾙ 補足資料(Appendix)

RadioServiceType[RADIO̲SERVICE̲CONTROL],"Volume", value );if( ercd != UPNP̲E̲SUCCESS ) {( *out ) = NULL;( *errorString ) = "Internal Error";
return UPNP̲E̲INTERNAL̲ERROR;}
return UPNP̲E̲SUCCESS;} else {( *errorString ) = "Internal Error";
return UPNP̲E̲INTERNAL̲ERROR;}}──────────────────────────────────────────
ER RadioDeviceHandleActionRequest( struct Upnp̲Action̲Request *ca̲event ){：<略>//アクション実行
retCode = Radio̲service̲table[service].actions[i](ca̲event‑>ActionRequest,&ca̲event‑>ActionResult,&errorString );}}：<略>
action̲found = 1; //動作発見
break;}}

ActionRequest に応答メッセージが設定されリターンされるような実装になっています。

if( !action̲found ) { //ACTION が無い//エラー設定ca̲event‑>ActionResult = NULL;
strcpy( ca̲event‑>ErrStr, "Invalid Action" );ca̲event‑>ErrCode = 401;
} else {Action 名不一致の場合の処理です。

// 処理成功？
if( retCode == UPNP̲E̲SUCCESS ) {// 正常完了ca̲event‑>ErrCode = UPNP̲E̲SUCCESS;} else {//異常終了ならエラーメッセージ設定
strcpy( ca̲event‑>ErrStr, errorString );switch ( retCode ){case UPNP̲E̲INVALID̲PARAM:{ca̲event‑>ErrCode = 402;

Action 正常終了の場合のルートです。ErrStr は設定不要。
ActionRequest はアクション実行時に設定されているため、ここではErrCode に UPNP̲E̲SUCCESS を設定
するだけです。

break;}
default:{ca̲event‑>ErrCode = 501;
break;}}}}
return ( ca̲event‑>ErrCode );Action 異常終了の場合のルートです。

Grousenet UPnP ﾌﾟﾛｸﾞﾗﾐﾝｸﾞﾏﾆｭｱﾙ 補足資料(Appendix)}/* RadioDeviceHandleActionRequest */──────────────────────────────────────────Grousenet UPnP ﾌﾟﾛｸﾞﾗﾐﾝｸﾞﾏﾆｭｱﾙ 補足資料(Appendix)

06) コールバック関数の実装 Part3−SOAP QUERY 受信処理
SOAP QUERY 受信時は、デバイスイベントハンドラの、★部分のルートを通ります。
──────────────────────────────────────────
ER RadioDeviceCallbackEventHandler( Upnp̲EventType EventType,
void *Event,
void *Cookie ){switch ( EventType ){//イベントのタイプ
case UPNP̲EVENT̲SUBSCRIPTION̲REQUEST: //サブスクリプション(購読)要求{
RadioDeviceHandleSubscriptionRequest( ( structUpnp̲Subscription̲Request* )Event );//Radio デバイスサブスクリプション要求操作
break;}★ case UPNP̲CONTROL̲GET̲VAR̲REQUEST: //変数獲得要求★ {★
RadioDeviceHandleGetVarRequest( ( struct Upnp̲State̲Var̲Request★
* )Event );★
//Radio デバイス変数獲得要求操作★
break;★ }case UPNP̲CONTROL̲ACTION̲REQUEST: //動作要求{
RadioDeviceHandleActionRequest( ( struct Upnp̲Action̲Request * )Event );//Radio デバイス動作要求操作
break;}
default: //不正なイベントタイプ// 無視する。
break;}
return ( E̲OK );}──────────────────────────────────────────

SOAP QUERY 受信時のデバイスイベントハンドラ関数では、引数 Event->CurrentVal に、現在の変数値を設定し、デバイスイベントハンドラ関数をリターンすると、ミドルウェア内で SOAP QUERY レスポンス
を送信します。
RadioDeviceHandleGetVarRequest 関数では、・ 該当する変数値の確定。
・ 現在の変数値の取得及び引数 Event->CurrentVal への設定の制御を行います。
──────────────────────────────────────────
ER RadioDeviceHandleGetVarRequest(struct Upnp̲State̲Var̲Request *cgv̲event ){UINT i,j;
INT getvar̲succeeded = 0; //変数獲得成功フラグ
ER̲ID ercd;

Grousenet UPnP ﾌﾟﾛｸﾞﾗﾐﾝｸﾞﾏﾆｭｱﾙ 補足資料(Appendix)

cgv̲event‑>CurrentVal = NULL; //現在値
ercd = wai̲sem(dUPnP̲SampleSemID); //セマフォ資源獲得
if(ercd != E̲OK){
return ercd; //セマフォ資源獲得失敗}
for( i = 0; i < RADIO̲SERVICE̲SERVCOUNT; i++ ){ //サービスの数だけループ
if((strcmp( cgv̲event‑>DevUDN, Radio̲service̲table[i].UDN ) == 0 ) &&( strcmp( cgv̲event‑>ServiceID, Radio̲service̲table[i].ServiceId ) == 0)){
for( j = 0; j < Radio̲service̲table[i].VariableCount; j++ ){ //各サービスの機能数だけループ
if( strcmp( cgv̲event‑>StateVarName,Radio̲service̲table[i].VariableName[j] ) == 0 ){// 変数取得成功フラグ
getvar̲succeeded = 1;// 指定変数の現在値取得
cgv̲event‑>CurrentVal = ixmlCloneDOMString( Radio̲service̲table[i].
VariableStrVal[j] );break;}
CurrentVal への変数値の設}}
定は、ixmlCloneDOMString 関}数を使用します。
if( getvar̲succeeded ){cgv̲event‑>ErrCode = UPNP̲E̲SUCCESS;}
変数値異常などの場合は、こelseのように ErrCode と ErrStr{
へエラー情報を設定します。
// エラーコード(404)設定
cgv̲event‑>ErrCode = 404;
strcpy( cgv̲event‑>ErrStr, "Invalid Variable" );}ercd = sig̲sem(dUPnP̲SampleSemID); //セマフォ資源返却
if(ercd != E̲OK){
return ercd; //返却失敗}
return ( cgv̲event‑>ErrCode == UPNP̲E̲SUCCESS );}/* RadioDeviceHandleGetVarRequest */──────────────────────────────────────────Grousenet UPnP ﾌﾟﾛｸﾞﾗﾐﾝｸﾞﾏﾆｭｱﾙ 補足資料(Appendix)

Appendix-B ： UPnP 開発の手引き – コントロールポイント実装編─────────────────────────────────────────────────────

Appendix-B では、本 UPｎP ミドルウェアを使用した UPnP コントロールポイントの実装方法例に関して、弊社提供のサンプルコードを例に記載します。

01) 全体の流れ
本 UPｎP ミドルウェアを使用して UPnP コントロールポイントを実装する場合の基本手順は、以下の通
りです。
Step
アクション
説明
1
起動・停止処理の実装
UPnP コントロールポイントの起動・停止処理を実装します。
2
M-SEARCH 送信処理の実装
M-SEARCH 送信処理を実装し、UPnP デバイス検索を可能にします。
3
SUBSCRIBE 送信処理の実装
SUBSCRIBE 送信処理を実装し、状態変更通知登録を可能にします。
4
UNSUBSCRIBE 送信処理の実装
SUBSCRIBE 送信処理を実装し、状態変更通知解除を可能にします。
5
ACTION 送信処理の実装
ACTION 送信処理を実装し、コントロールを可能にします。
6
QUERY 送信処理の実装
QUERY 送信処理を実装し、状態取得を可能にします。
7
SSDP NOTIFY 受信処理の実装
SSDP NOTIFY 受信処理を実装し、UPnP デバイス
存在確認を可能にします。
8
SSDP BYEBYE 受信処理の実装
SSDP BYEBYE 受信処理を実装し、UPnP デバイ
ス消滅確認を可能とします。
9
GENA NOTIFY 受信処理の実装
GENA 受信処理を実装し、UPnP デバイスの状態
変更通知を受信可能にします。
10
SUBSCRIBE RENEWAL 失敗時処理の SUBSCRIBE RENEWAL 失敗の判断を可能にしま実装す。

02) 起動関数・停止関数
ユーザアプリケーションの実装を行うにあたって、まずは UPnP コントロールポイントの起動及び停止処理を実装します。
起動関数：CtrlPointStart
起動処理は、デバイス起動時に一度だけ Call するように実装します。
Step
1

実装

ソースコード記載

コントロー ルポイントハンド

UpnpClient̲Handle cp̲handle = ‑1;

ルの準備
2

config 構造体メンバ設定(CtrlPointStart 関数 Call前)/* config 構造体メンバ設定 */memset(&config, 0, sizeof(tUpnp̲Conf));
memcpy(config.Ipaddress,ip̲address,sizeof(config.Ipaddress));
config.PortNo = port;
config.UseWebserver = DUPNP̲OFF;// 既製 Web サーバ使用

Grousenet UPnP ﾌﾟﾛｸﾞﾗﾐﾝｸﾞﾏﾆｭｱﾙ 補足資料(Appendix)

3

ﾕｰｻﾞｱﾌﾟﾘｹｰｼｮﾝ内部データの初期化(CtrlPointStart 関数 Call
前)

4

UpnpInit 関数によるミド
ルウェアの初期化(CtrlPointStart 関数 Call
前)5

UpnpRegisterClient
関 数によ るコント ロール
ポイントの登録config.TcpPortNo = TCP̲PORTNO;
config.UdpPortNo = UDP̲PORTNO;
config.UpnpTaskPri = UPNP̲TASK̲PRI;
config.ClsTimAcp = CLS̲TIM̲ACP;
config.IPTTL = DEF̲IP̲TTL;// UPnP で使用する TCP ポート番号// UPnP で使用する UDP ポート番号// UPnP タスクプライオリティ// TCP Connection クローズ待ちタイマー// SSDP にて使用する UDP TTL=4

config.UpnpMplSize = UPNP̲BUFSIZ;// UPnP メモリプールサイズ設定 128KByte// 本 APL の初期化
SampleUtil̲Initialize();☆SampleUtil̲Initialize 関数の詳細は実際の関数実装を確認して下さい。
ret = UpnpInit( &config );if(ret != UPNP̲E̲SUCCESS ){//Upnp 初期化に失敗したなら
UpnpFinish();return ret;}
ret = UpnpRegisterClient(CtrlPointCallbackEventHandler, &cp̲handle, &cp̲handle);// ↑callback 関数↑cookie↑ハンドル
if(ret != UPNP̲E̲SUCCESS){
UpnpFinish(); //UPnP 終了
return ret;}

停止関数：CtrlPointStop
停止処理は、コントロールポイント終了時に一度だけ Call するように実装します。
IP アドレスの変更など、ネットワーク状態が変更になった場合や、別なデバイスを起動したい場合などは、一旦本関数でデバイスを終了し、再度デバイスを起動します。
Step
1

実装

ソースコード記載

UpnpUnRegisterClient

UpnpUnRegisterClient(cp̲handle);関数によるコントロールポ
イントの削除2

UpnpFinish 関数による、ミUpnpFinish(); //Upnp 終了

ドルウェアの終了(CtrlPointStop 関数 Call 後)
3

ﾕｰｻﾞｱﾌﾟﾘｹｰｼｮﾝ内部データの開放

SampleUtil̲Finish( ); //サンプル終了☆SampleUtil̲Finish 関数の詳細は実際の関数実装を確認して下さい。

03) M-SEARCH 送信処理の実装 Part1−送信関数処理
送信関数：UpnpSearchAsync
関数 Call の度に M‑
SEARCH が送信されます。引数 SEARCH ターゲットを変更することができます。
Step
1

実装

ソースコード記載

UpnpSearchAsync

ret = UpnpSearchAsync(cp̲handle, timeout, "upnp:rootdevice", NULL);//ﾊﾝﾄﾞﾙ
//ﾀｲﾑｱｳﾄ値 //ｻｰﾁﾀｰｹﾞｯﾄ

M‑SEARCH 送信04) M-SEARCH 送信処理の実装 Part2−コールバック関数処理
コールバック関数：CtrlPointCallbackEventHandler
M‑
SEARCH 後、応答があった場合または受信タイムアウトとなった場合、UpnpRegisterClient 関数にて登録した関数（サンプルでは CtrlPointCallbackEventHandler）が Call されます。関数内で引数 Upnp̲EventType
EventType の値に応じた処理を行います。また、本コールバック関数で、UPnPDownloadXmlDoc 関数にて、ディGrousenet UPnP ﾌﾟﾛｸﾞﾗﾐﾝｸﾞﾏﾆｭｱﾙ 補足資料(Appendix)

スクリプションドキュメントの取得を行い、デバイス情報の収集を行います。
Step
1

実装

ソースコード記載

EventType =case UPNP̲DISCOVERY̲SEARCH̲RESULT:{
struct Upnp̲Discovery *d̲event = //デバイス応答情報取得( struct Upnp̲Discovery * )Event;

UPNP̲DISCOVERY̲SEARCH̲RESULT
M‑SEARCH 応答受信//ここで応答受信時の処理を記述します//(例)デバイスディスクリプションドキュメントの取得
IXML̲Document *DescDoc = NULL;//と宣言しているものとする//XML 取得
ret = UpnpDownloadXmlDoc(d̲event‑>Location,&DescDoc);//応答情報の LocationURL
break;
2

EventType =UPNP̲DISCOVERY̲SEARCH̲RESULT
M‑SEARCH 受信タイムアウト}
case UPNP̲DISCOVERY̲SEARCH̲TIMEOUT://ここでタイムアウト時の処理を記述します
break;05) SUBSCRIBE 送信処理の実装 Part1−送信関数処理
送信関数：UpnpSubscribeAsync
引数で指定する EventURL に対して SUBSCRIBE します。
Step
1

実装

ソースコード記載

UpnpSubscribeAsync

ret = UpnpSubscribeAsync(cp̲handle,SvcTbl[sn].EventURL,//ﾊﾝﾄﾞﾙ
//EventURL
timeout,CtrlPointCallbackEventHandler,NULL);//更新ﾀｲﾑ値 //ｺｰﾙﾊﾞｯｸ関数

SUBSCRIBE 送信

06) SUBSCRIBE 送信処理の実装 Part2−コールバック関数処理
コールバック関数：CtrlPointCallbackEventHandler
SUBSCRIBE 送信後、応答があった場合、UpnpSubscribeAsync 関数にて登録した関数（※注※サンプルでは、
UpnpRegisterClient 関数と同じ CtrlPointCallbackEventHandler を登録していますが、専用のコールバック関
数を登録することも可能です。
）が Call されます。関数内で引数 Upnp̲EventType EventType の値に応じた処理を行います。
Step
1

実装

ソースコード記載

EventType =case UPNP̲EVENT̲SUBSCRIBE̲COMPLETE:{
struct Upnp̲Event̲Subscribe *es̲event = //応答情報取得( struct Upnp̲Event̲Subscribe * )Event;//ここで応答受信時の処理を記述します
break;}

UPNP̲EVENT̲SUBSCRIBE̲COMPLETE
SUBSCRIBE 応答受信

07) UNSUBSCRIBE 送信処理の実装 Part1−送信関数処理
送信関数：UpnpUnSubscribeAsync
登録 SID のサービスに対して UNSUBSCRIBE します。
Step
1

実装

ソースコード記載

UpnpUnSubscribeAsync

ret = UpnpUnSubscribeAsync(cp̲handle, SvcTbl[sn].SID,//ﾊﾝﾄﾞﾙ //SID

UNSUBSCRIBE 送信Grousenet UPnP ﾌﾟﾛｸﾞﾗﾐﾝｸﾞﾏﾆｭｱﾙ 補足資料(Appendix)
CtrlPointCallbackEventHandler,NULL);//ｺｰﾙﾊﾞｯｸ関数08) UNSUBSCRIBE 送信処理の実装 Part2−コールバック関数処理
コールバック関数：CtrlPointCallbackEventHandler
UNSUBSCRIBE 送信後、応答があった場合、UpnpUnSubscribeAsync 関数にて登録した関数（※注※サンプルでは、
UpnpRegisterClient 関数と同じ CtrlPointCallbackEventHandler を登録していますが、専用のコールバック関
数を登録することも可能です。
）が Call されます。関数内で引数 Upnp̲EventType EventType の値に応じた処理を行います。
Step
1

実装

ソースコード記載

EventType =case UPNP̲EVENT̲UNSUBSCRIBE̲COMPLETE:{
struct Upnp̲Event̲Subscribe *es̲event = //応答情報取得( struct Upnp̲Event̲Subscribe * )Event;//ここで応答受信時の処理を記述します
break;}

UPNP̲EVENT̲UNSUBSCRIBE̲COMPLETE
UNSUBSCRIBE 応答受信

09) ACTION 送信処理の実装 Part1−送信関数処理
送信関数：UpnpSendActionAsync
SOAP XML を生成し送信します。
Step
1

実装

ソースコード記載

UpnpAddToAction

ret = UpnpAddToAction(&actionNode, actionname, psvctype,//SOAP XML//ｱｸｼｮﾝ名//ｻｰﾋﾞｽﾀｲﾌﾟ
param̲name[param],param̲val[param] )
//変数名
//変数値
ret = UpnpSendActionAsync(cp̲handle,//ﾊﾝﾄﾞﾙ
SvcTbl[svcno].ControlURL,psvctype,NULL,//ControlURL//ｻｰﾋﾞｽﾀｲﾌﾟ
actionNode,CtrlPointCallbackEventHandler,//SOAP XML//ｺｰﾙﾊﾞｯｸ関数
NULL );ACTION SOAP XML 生成

2

UpnpSendActionAsync
ACTION SOAP XML 送信

10) ACTION 送信処理の実装 Part2−コールバック関数処理
コールバック関数：CtrlPointCallbackEventHandler
ACTION 送信後、応答があった場合、UpnpSendActionAsync 関数にて登録した関数（※注※サンプルでは、
UpnpRegisterClient 関数と同じ CtrlPointCallbackEventHandler を登録していますが、専用のコールバック関
数を登録することも可能です。
）が Call されます。関数内で引数 Upnp̲EventType EventType の値に応じた処理を行います。
Step
1

実装

ソースコード記載

EventType =case UPNP̲CONTROL̲ACTION̲COMPLETE:{
struct Upnp̲Action̲Complete *a̲event = //応答情報取得( struct Upnp̲Action̲Complete * )Event;//ここで応答受信時の処理を記述します
break;}

UPNP̲CONTROL̲ACTION̲COMPLETE
ACTION 応答受信Grousenet UPnP ﾌﾟﾛｸﾞﾗﾐﾝｸﾞﾏﾆｭｱﾙ 補足資料(Appendix)11) QUERY 送信処理の実装 Part1−送信関数処理
送信関数：UpnpGetServiceVarStatusAsync
QUERY を送信します。
Step
1

実装

ソースコード記載

UpnpGetServiceVarStatusAsync

ret = UpnpGetServiceVarStatusAsync(cp̲handle,//ﾊﾝﾄﾞﾙ
SvcTbl[svcno].ControlURL,//ControlURL
VarName,//変数名
CtrlPointCallbackEventHandler,//ｺｰﾙﾊﾞｯｸ関数
NULL );QUERY 送信12) QUERY 送信処理の実装 Part2−コールバック関数処理
コールバック関数：CtrlPointCallbackEventHandler
QUERY 送信後、応答があった場合、UpnpGetServiceVarStatusAsync 関数にて登録した関数（※注※サンプルでは、UpnpRegisterClient 関数と同じ CtrlPointCallbackEventHandler を登録していますが、専用のコールバッ
ク関数を登録することも可能です。
）が Call されます。関数内で引数 Upnp̲EventType EventType の値に応じた処理を行います。
Step
1

実装

ソースコード記載

EventType =case UPNP̲CONTROL̲GET̲VAR̲COMPLETE:{
struct Upnp̲State̲Var̲Complete *sv̲event = //応答情報取得( struct Upnp̲State̲Var̲Complete * )Event;//ここで応答受信時の処理を記述します
break;}

UPNP̲CONTROL̲GET̲VAR̲COMPLETEQUERY 応答受信

13) SSDP NOTIFY 受信処理の実装−コールバック関数処理
コールバック関数：CtrlPointCallbackEventHandler
SSDP NOTIFY を 受 信 し た 場 合 、 UpnpRegisterClient 関 数 に て 登 録 し た 関 数 （ サ ン プ ル で は
CtrlPointCallbackEventHandler）が Call されます。関数内で引数 Upnp̲EventType EventType の値に応じた処理を行います。
Step
1

実装

ソースコード記載

EventType =case UPNP̲DISCOVERY̲ADVERTISEMENT̲ALIVE:{struct Upnp̲Discovery *d̲event = //受信情報取得( struct Upnp̲Discovery * )Event;//ここで受信時の処理を記述します
break;}

UPNP̲DISCOVERY̲ADVERTISEMENT̲ALIVE
SSDP NOTIFY 受信

14) SSDP BYEBYE 受信処理の実装−コールバック関数処理
コールバック関数：CtrlPointCallbackEventHandler

Grousenet UPnP ﾌﾟﾛｸﾞﾗﾐﾝｸﾞﾏﾆｭｱﾙ 補足資料(Appendix)

SSDP BYEBYE を 受 信 し た 場 合 、 UpnpRegisterClient 関 数 に て 登 録 し た 関 数 （ サ ン プ ル で は
CtrlPointCallbackEventHandler）が Call されます。関数内で引数 Upnp̲EventType EventType の値に応じた処理を行います。
Step
1

実装

ソースコード記載

EventType =case UPNP̲DISCOVERY̲ADVERTISEMENT̲BYEBYE:{
struct Upnp̲Discovery *d̲event = //受信情報取得( struct Upnp̲Discovery * )Event;//ここで受信時の処理を記述します
break;}

UPNP̲DISCOVERY̲ADVERTISEMENT̲BYEBYE
SSDP BYEBYE 受信

15) GENA NOTIFY 受信処理の実装−コールバック関数処理
コールバック関数：CtrlPointCallbackEventHandler
SUBSCRIBE 登 録 済 み UPnP デ バ イ ス の 状 態 変 化 時 に 送 信 さ れ る GENA NOTIFY を 受 信 し た 場 合 、UpnpRegisterClient 関数にて登録した関数（サンプルでは CtrlPointCallbackEventHandler）が Call されます。関数内で引数 Upnp̲EventType EventType の値に応じた処理を行います。
Step
1

実装

ソースコード記載

EventType =case UPNP̲EVENT̲RECEIVED:{
struct Upnp̲Event *e̲event = //受信情報取得( struct Upnp̲Event * )Event;//ここで受信時の処理を記述します
break;}

UPNP̲EVENT̲RECEIVED
GENA NOTIFY 受信

16) SUBSCRIBE RENEWAL 失敗時処理の実装−コールバック関数処理
コールバック関数：CtrlPointCallbackEventHandler
SUBSCRIBE RENEWAL に 失 敗 し た 場 合 、 UpnpRegisterClient 関 数 に て 登 録 し た 関 数 （ サ ン プ ル で は
CtrlPointCallbackEventHandler）が Call されます。関数内で引数 Upnp̲EventType EventType の値に応じた処理を行います。
Step
1

実装

ソースコード記載

EventType =case UPNP̲EVENT̲AUTORENEWAL̲FAILED:{
struct Upnp̲Event̲Subscribe *es̲event = //受信情報取得( struct Upnp̲Event̲Subscribe * )Event;//ここで受信時の処理を記述します
break;}

UPNP̲EVENT̲AUTORENEWAL̲FAILEDSUBSCRIBE RENEWAL 失敗