RPC - リモートプロシージャコール
RPC - リモートプロシージャコール
mbed とパソコンやサーバを繋いで使う機会はよくあります。
そのたびごとにパソコン=mbed間のプロトコルを決めてプログラムを作っていては面倒です。
そんなときUNIXなどでメジャーな RPC を使い、簡単に mbed のハードウェアにアクセスすることができます。
mbed は RPCコマンドを受信し解釈することが可能です。
RPCコマンドはいろいろなプロトコルを通じて送ることができます。
ここでは RPC を使うための mbed のプログラムコードを紹介します。
PCやサーバ側のプログラム向けのライブラリはさまざまなものが開発されています。
MATLAB,
LabVIEW,
Python,
Java,
JavaScript,
.NET
※ RPC (Remote Procedure Call)とは、プログラムから別のアドレス空間(別のCPUだったり、ネットワーク越しのPCだったり)にあるプログラムを実行する技術。
(Wikipedia参照)
Information
mbedのRPCコマンドの形式は次のとおりです。
/<Object Name>/<Method Name>
"/" だけ送ると、使用できるObject Nameを返します。
"/<Object Name>" だけ送ると、使用できるMethod Nameを返します。
Warning
最近、RPCは BASEクラス から分離されました。
最近のmbedライブラリを使用する場合は、mbed-rpcライブラリをインポートし、
#include "mbed_rpc.h"
を追記し、 このページの例は "Base::" を "RPC::" へ書き換えてください。
rpc()関数も RPC::call() へ書き換えてください。
AnalogInがエラーになる問題は、va009039さんが修正されています。
http://va009039.blogspot.jp/2013/02/mbed-rpc_16.html
・・・と、思っていたら、元のライブラリのリビジョンがだいぶ変わってしまったので、Revision 5 をベースに独自に修正しました。
Import librarymbed-rpc
mbed rpc
例:main.cpp
#include "mbed.h" #include "mbed_rpc.h" int main () { RPC::add_rpc_class<RpcDigitalIn>(); RPC::add_rpc_class<RpcDigitalOut>(); RPC::add_rpc_class<RpcDigitalInOut>(); RPC::add_rpc_class<RpcAnalogIn>(); RPC::add_rpc_class<RpcAnalogOut>(); RPC::add_rpc_class<RpcPwmOut>(); RPC::add_rpc_class<RpcSPI>(); RPC::add_rpc_class<RpcSerial>(); RPC::add_rpc_class<RpcTimer>(); : char inbuf[40], outbuf[40]; strcpy(inbuf, "/DigitalOut/new LED1 myled"); RPC::call(inbuf, outbuf); printf("%s\r\n", outbuf); strcpy(inbuf, "/myled/write 1"); RPC::call(inbuf, outbuf); printf("%s\r\n", outbuf);
以下、少し古い情報
RPCコマンドの例
/DigitalOut/new LED1 myled /myled/write 1
mbed 側の定義例
char buf[256], outbuf[256]; strcpy(buf, "/DigitalOut/new LED1 myled"); rpc(buf, outbuf);
I2Cはライブラリにないが、SPIなんかもRPC経由でアクセスできる。
Base::add_rpc_class<SPI>(); と定義しておけば /SPI/new spi p5 p6 p7
RPC Over Serial
シリアル経由で RPCコマンド を受け付けるサンプルです。
Import programRPC_Serial
Program to interface with mbed using RPC over Serial
#include "mbed.h" #include "rpc.h" Serial pc(USBTX, USBRX); int main() { // setup the classes that can be created dynamically Base::add_rpc_class<AnalogIn>(); Base::add_rpc_class<AnalogOut>(); Base::add_rpc_class<DigitalIn>(); Base::add_rpc_class<DigitalOut>(); Base::add_rpc_class<DigitalInOut>(); Base::add_rpc_class<PwmOut>(); Base::add_rpc_class<Timer>(); Base::add_rpc_class<SPI>(); Base::add_rpc_class<BusOut>(); Base::add_rpc_class<BusIn>(); Base::add_rpc_class<BusInOut>(); Base::add_rpc_class<Serial>(); // receive commands, and send back the responses char buf[256], outbuf[256]; while(1) { pc.gets(buf, 256); rpc(buf, outbuf); pc.printf("%s\n", outbuf); } }
上のプログラムを mbed 上で実行し、PCシリアルより次のように操作します。
sample
/DigitalOut/new LED1 myled これはmbedのプログラムで DigitalOut myled(LED1); を実行したのと同じです。 成功すると myled と返ってきます。 /myled/write 1 これはmbedのプログラムで myled.write(1); を実行したのと同じです。
RPC Over HTTP
ウェブブラウザからも RPC を使用して、 mbed のハードウェアをコントロールすることができます。
グローバルIPアドレス(WAN)で使う場合はセキュリティ機能(認証など)を載せたほうがいいでしょう。
Information
HTTP経由のRPCコマンドの形式は http://<url of mbed>/rpc/<Object name>/<Method name> <Arguments separated by spaces>
svr.addHandler<RPCHandler>("/rpc");
Import programRPC_HTTP
A slight Alteration to Donatien's HTTP Server Example so that it registers all the classes with RPC support to demonstrate RPC over HTTP
上のプログラムを mbed 上で実行し、ブラウザより次のURLへアクセスして操作します。
sample
http://192.168.0.123/rpc/DigitalIn/new p5 myport これはmbedのプログラムで DigitalIn myport(p5); を実行したのと同じです。 成功すると myport と返ってきます。 http://192.168.0.123/rpc/myport/read これはmbedのプログラムで myport.read(); を実行したのと同じです。 ポートの状態 0 または 1 が返ってきます。
※ 192.168.0.123 はユーザーの環境に合わせてください。
また、上のプログラムは mbed のUSBストレージ(USBメモリ)にもアクセスできますので RPCを使ったhtmlファイルを入れておくといいでしょう。
sample
http://192.168.0.123/files/mbed.htm
RPC 実装
ユーザーが独自に作成した関数(クラス)をRPCに対応させるサンプル。
Import programMyRPC_Serial
http://mbed.org/users/okini3939/notebook/RPC_jp/
クラス内に get_rpc_methods(), get_rpc_class() を用意する。
MyRPC::MyRPC(PinName pin, const char *name) : Base(name), _pin(pin) {} void MyRPC::blink(int n) { : } int MyRPC::number() { : return r; } const rpc_method *MyRPC::get_rpc_methods() { static const rpc_method rpc_methods[] = { { "blink", rpc_method_caller<MyRPC, int, &MyRPC::blink>}, { "number", rpc_method_caller<int, MyRPC, &MyRPC::number> }, RPC_METHOD_SUPER(Base) }; return rpc_methods; } rpc_class *MyRPC::get_rpc_class() { static const rpc_function funcs[] = { "new", rpc_function_caller<const char*, PinName, const char*, &Base::construct<MyRPC,PinName,const char*> >, RPC_METHOD_END }; static rpc_class c = { "MyRPC", funcs, NULL }; return &c; }
このサンプルは、PCシリアルより次のように操作します。
sample
/MyRPC/new LED2 myled /myled/blink 10 /myled/number
Please log in to post comments.