mbedを使ったUPnPデバイスの作り方

mbedを使ったUPnPデバイスの作り方です。

 UPnPで何が出来るのか

UPnP(ユニバーサルプラグアンドプレイ)デバイスは、ネットワークに接続するだけで利用できるネットワーク機器です。UPnPデバイスとして動作するmbedは、ネットワーク設定を行わずにコンピュータから検出し、アクセスし、操作することが出来ます。

/media/uploads/nyatla/upnp-exploler.png この画像はWindows7で認識した様子です。

MiMicを使ったUPnPの機能

MiMicのUPnPモジュールは、アドレッシング、ディスカバリ、デスクリプション、プレゼンテーションの機能をサポートしています。 これらの機能から、最も単純なUPnPデバイス UPnPBasicDevice:1を構成することが出来ます。

※現在のバージョンでは、コントロール、イベント機能はありません。

UPnPデバイスを実行してみる

以下のプロジェクトはUPnPBasicDevice:1の実装です。

Import programUPnPBasicDevice

Simplest UPnP basic device example. This program to run UPnP basic device on the mbed.

ファームウェアを書き込んだmbedをネットワークに接続すると、UPnPデバイスとしてOS(Windows)から認識することが出来ます。

新たにUPnPデバイスを作る場合は、これをベースにすることができます。

ソースコード

プログラム構造はHttpServerにUPnP処理を追加した形をしています。パーツとしてはHttpServer機能を提供するUPnPBasicDeviceHttpdクラスと、起動する為の手続きを記述したmain関数の2つに分かれます。

UPnPBasicdevice::main.cpp 全文

/**
 * @file
 * Simplest UPnP basic device.<br/>
 * This program is upnp:BasicDeveice:1 template.
 * 
 * <p>
 * After starting program, check "network" by Exproler.
 * MiMic basic device will be appeared.
 * </p>
 */
#include "mbed.h"
#include "rtos.h"
#include "SDFileSystem.h"
#include "mimic.h"
#include "utils/PlatformInfo.h"
#include "fsdata.h"
 
 
Net* net;
 
/**
 * Httpd for UPnPService and presentation.
 */
class UPnPBasicDeviceHttpd:public MiMic::Httpd
{
private:
    ModUPnPDevice modupnp;
    ModRomFiles modromfs; //ROM file module    
public:
    UPnPBasicDeviceHttpd(NetConfig& i_cfg):Httpd(i_cfg.getHttpPort())
    {
        //prepare fs data (presentation.html,icon,image.)
        this->modromfs.setParam("rom",FSDATA,3);
        //bind upnp service to module.
        this->modupnp.setParam(*net);
    }
    virtual void onRequest(HttpdConnection& i_connection)
    {
        //try to ModRomFS module. for icon,images.
        if(this->modromfs.execute(i_connection)){
            return;
        }        
        //try to UPnP service. for descriptions.
        if(this->modupnp.execute(i_connection)){
            return;
        }
        //Otherwise, Send the redirect response to /rom/index.html
        i_connection.sendHeader(302,
            "text/html",
            "Status: 302:Moved Temporarily\r\n"
            "Location: /rom/index.html\r\n");     
    }
};
 
NetConfig cfg; //create network configulation
 
int main()
{
    net=new Net();//Net constructor must be created after started RTOS
    //Prepare configulation.
    cfg.setUPnPIcon(64,64,8,"image/png","/rom/icon.png");//set upnp icon address
    cfg.setUPnPUdn(0xe29f7103,0x4ba2,0x01e0,0); //set application timebase-uuid time and sequence field.
    cfg.setFriendlyName("UPnPBasicDevice(LPC176x)"); //set friendly name
    cfg.setUPnPPresentationURL("/rom/index.html"); //set presentationURL
    cfg.setZeroconf(true);//AutoIP enable
 
    UPnPBasicDeviceHttpd httpd(cfg); //create a httpd instance.
    net->start(cfg);
    httpd.loop();  //start httpd loop.
    return 0;
}

HttpServerクラス

20-54行はHttpServerの実装です。httpdはメイン関数から起動します。

Httpd部分

class UPnPBasicDeviceHttpd:public MiMic::Httpd
{
private:
    ModUPnPDevice modupnp;
    ModRomFiles modromfs; //ROM file module    
public:
    UPnPBasicDeviceHttpd(NetConfig& i_cfg):Httpd(i_cfg.getHttpPort())
    {
        //prepare fs data (presentation.html,icon,image.)
        this->modromfs.setParam("rom",FSDATA,3);
        //bind upnp service to module.
        this->modupnp.setParam(*net);
    }
    virtual void onRequest(HttpdConnection& i_connection)
    {
        //try to ModRomFS module. for icon,images.
        if(this->modromfs.execute(i_connection)){
            return;
        }        
        //try to UPnP service. for descriptions.
        if(this->modupnp.execute(i_connection)){
            return;
        }
        //Otherwise, Send the redirect response to /rom/index.html
        i_connection.sendHeader(302,
            "text/html",
            "Status: 302:Moved Temporarily\r\n"
            "Location: /rom/index.html\r\n");     
    }
};

HttpServerには2つのサービスモジュールを実装します。

  • ModRomFiles - 構造体に格納したファイルイメージを返却するモジュール。ファイルイメージはfsdat.hに構造体で定義します。プレゼンテーション用のindex.html,HTMLコンテンツを提供します。
  • ModUPnPDevice - UPnPのデスクリプション処理を行うモジュール。UPnPから要求されるHttpリクエストを処理します。

main関数

UPnPBasicdevice::main関数

int main()
{
    net=new Net();//Net constructor must be created after started RTOS
    //Prepare configulation.
    cfg.setUPnPIcon(64,64,8,"image/png","/rom/icon.png");//set upnp icon address
    cfg.setUPnPUdn(0xe29f7103,0x4ba2,0x01e0,0); //set application timebase-uuid time and sequence field.
    cfg.setFriendlyName("UPnPBasicDevice(LPC176x)"); //set friendly name
    cfg.setUPnPPresentationURL("/rom/index.html"); //set presentationURL
    cfg.setZeroconf(true);//AutoIP enable
 
    UPnPBasicDeviceHttpd httpd(cfg); //create a httpd instance.
    net->start(cfg);
    httpd.loop();  //start httpd loop.
    return 0;
}

main関数はネットワークサービスの生成、ネットワークコンフィギュレーションの設定、Httpdの生成、ネットワークの起動の後、httpdのループ処理を実行します。

Tips

httpd.loopを別のタスクで実行する

サンプルコードでは、httpd.loop();を実行後に他の処理を行うことができず、Httpリクエストに反応する以外の動作が出来ません。main関数のスレッドをそのまま利用するときは、 httpd.loop();の変わりに httpd.loopTask();関数を使います。

httpd.loopTask

int main()
{
    net=new Net();//Net constructor must be created after started RTOS
    //Prepare configulation.
    cfg.setUPnPIcon(64,64,8,"image/png","/rom/icon.png");//set upnp icon address
    cfg.setUPnPUdn(0xe29f7103,0x4ba2,0x01e0,0); //set application timebase-uuid time and sequence field.
    cfg.setFriendlyName("UPnPBasicDevice(LPC176x)"); //set friendly name
    cfg.setUPnPPresentationURL("/rom/index.html"); //set presentationURL
    cfg.setZeroconf(true);//AutoIP enable
 
    UPnPBasicDeviceHttpd httpd(cfg); //create a httpd instance.
    net->start(cfg);
    //httpd.loop();  //start httpd loop.
    httpd.loopTask();  //start httpd loop with new task
    for(;;){
        Thread::wait(1000);
    }
    return 0;
    
}

httpd.loopTask();関数は約300バイトのメモリを消費して別タスクでhttpdの処理を行います。

プレゼンテーションをカスタマイズする

プレゼンテーションページ(UPnPデバイスのアイコンをダブルクリックすると出てくるページ)は好みのものに変更することが出来ます。サンプルでは、fsdata.hにコンテンツファイルのデータを格納した構造体があります。

fsdata.h

#include "mimic.h"

struct NyLPC_TRomFileData FSDATA[3]=
{
    {
        //filename
        "icon.png",
        //size
        2271,
        //mimetype
        "image/png", 
        //file image
        "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x..."
    },
    {
        "logo.png",
        9040,
        //mimetype
        "image/png", 
        //file image
         "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\..."
    },
    {
        "index.html",
        1122,
        "text/html",
        "\x3C\x21\x44\x4F\x43\x54\x59\x50\x45\x20\x68\x74\x6D\x6C\x3E\..."
    }
};

必要な情報は、ファイル名,サイズ,mimetype,ファイルイメージのデータです。ファイルイメージは文字列形式なので、バイナリファイルの場合はテキスト形式に変換してください。

ファイル→構造体の変換プログラムはこちらからダウンロードできます。

File2FileStruct http://sourceforge.jp/projects/mimic/releases/?package_id=13836

Httpdのホストするファイルは容量の許す限り追加することが出来ます。さらに多くのファイルをホストする場合は、mbedファイルシステムやSDカードなどの外部デバイスを利用できます。

機器情報を変更する

アイコンを右クリックしてみることが出来るUPnPの機器情報は、NetConfigの関数で変更することが出来ます。

  • NetConfig::setFriendlyName - デバイスの表示名を指定できます。
  • NetConfig::setUPnPUdn - デバイスIDを指定できます。IDはTimeBaseUUID(Version1)です。指定できるのはタイムフィールドとシーケンスフィールドです。NodeフィールドはmbedのMACアドレスが使われます。 IDの生成はhttp://www.famkruithof.net/uuid/uuidgenなどを利用してください。
  • NetConfig::setUPnPManufactur - 製品製造者の情報やURLを指定できます。
  • NetConfig::setUPnPModel - 製品のモデル情報や製品ページの情報を指定できます。
  • NetConfig::setUPnPSerialNumber - シリアル番号を指定できます。
  • NetConfig::setUPnPPresentationURL - プレゼンテーションページのURLを指定します。サンプルでは、プレゼンテーションページは/rom/index.htmlになっています。


Please log in to post comments.