RPC Over UDP Command format is same as serial RPC (not HTTP RPC). Please find attached Test Program(processing & ActionScript3) at end of this file.
Dependencies: EthernetNetIf mbed
main.cpp
- Committer:
- xshige
- Date:
- 2010-11-16
- Revision:
- 1:918ffa99c345
- Parent:
- 0:797742779818
File content as of revision 1:918ffa99c345:
/* * * RPC Over UDP * * Command format is same as serial RPC (not HTTP RPC) * * (example) * So you can control mbed by sending the followng command (over UDP) * /DigitalOut/new LED1 myled * /myled/write 1 * /AnalogIn/new p20 ain * /ain/read * * Please find attached Test Programs(processing & ActionScript3) at end of this file as comment "#if 0" * */ // 2010/11/16 // Fixed test program(processing) // to run it in both windows and linux. // 2010/11/15 // written by: xshige #define DEBUG // Send Port (RPC output) #define OUTPUT_PORT 8001 // Receive Port (RPC input) #define INPUT_PORT 8000 #define DEBUG // please comment out if you want two way unicast #define SENDBACK_UNICAST #define DHCP #include "mbed.h" #include "EthernetNetIf.h" #include "UDPSocket.h" #include "rpc.h" Serial pc(USBTX, USBRX); #ifdef DHCP EthernetNetIf eth; #else EthernetNetIf eth( IpAddr(192,168,0,25), //IP Address IpAddr(255,255,255,0), //Network Mask IpAddr(192,168,0,1), //Gateway IpAddr(192,168,0,1) //DNS ); #endif UDPSocket udpRec; UDPSocket udpSend; // mulitcast UDP #ifdef SENDBACK_UNICAST Host recHost(IpAddr(239, 255, 0, 1), INPUT_PORT, NULL); // Receive Port (RPC input) // multicast IP // "224.0.0.1" works correctly. // "224.0.0.2" does not work(can Not receive) // "239.255.0.0"-"239.255.255.255" (Site-Local Scope) maybe work #else // please change IP address to fit your enviroment // unicast IUDP Host sendHost(IpAddr(192, 168, 0, 7), OUTPUT_PORT, NULL); // Send Port (RPC output) Host recHost(IpAddr(192, 168, 0, 7), INPUT_PORT, NULL); // Receive Port (RPC input) //Host sendHost(IpAddr(239, 255, 0, 1), OUTPUT_PORT, NULL); // Send Port (RPC output) //Host recHost(IpAddr(239, 255, 0, 1), INPUT_PORT, NULL); // Receive Port (RPC input) #endif // receive commands, and send back the responses char inbuf[512], outbuf[512]; void onUDPSocketEvent(UDPSocketEvent e) { switch(e) { case UDPSOCKET_READABLE: //The only event for now Host host; while( int len = udpRec.recvfrom( inbuf, 512, &host ) ) { if( len <= 0 ) break; inbuf[len]=0; #ifdef DEBUG printf("\r\nFrom %d.%d.%d.%d: %s\r\n", host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3], inbuf); #endif #ifdef SENDBACK_UNICAST Host sendHost(IpAddr( host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3]), OUTPUT_PORT, NULL); // Send Port (RPC output) #endif udpSend.bind(sendHost); #ifdef DEBUG printf("debug1:%d %s\r\n",len,inbuf); #endif if (len>0) { rpc(inbuf, outbuf); udpSend.sendto( outbuf, strlen(outbuf), &sendHost); } #ifdef DEBUG printf("debug2:%s\r\n", outbuf); #endif } break; } } int main() { // make debug port Fast Serial pc(USBTX, USBRX); // pc.baud(9600); pc.baud(115200); // pc.baud(230400); // 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>(); // setup network printf("Setting up...\r\n"); EthernetErr ethErr = eth.setup(); if(ethErr) { printf("Error %d in setup.\r\n", ethErr); return -1; } printf("UDP RPC Setup OK\r\n"); udpRec.setOnEvent(&onUDPSocketEvent); udpRec.bind(recHost); while(1) { Net::poll(); #if 0 // debug code Host host; int len = udpRec.recvfrom( inbuf, 512, &host ); printf("debug:%d %s\r\n",len,inbuf); len=1; if (len>0) { rpc(inbuf, outbuf); strcpy(outbuf,"RPC UDP Test"); udpSend.sendto( outbuf, strlen(outbuf), &sendHost ); memset(inbuf,0,512); } printf("debug:%s\r\n", outbuf); memset(outbuf,0,512); wait(1); #endif } } #if 0 //------------------------------------------------------------------------ // Test Program (written in processing) // Important Note: // this program can NOT work in windows enviroment (only Linux enviroment) // // 2010/11/16: // Above bug fixed. Now it can work in both windows and linux. // Note: Please set your host IP. /** * RCP over UDP (by mbed) * Test Program * * you can get UDP library from: * http://ubaa.net/shared/processing/udp/ * */ // import UDP library import hypermedia.net.*; String remoteIP = "239.255.0.1"; // multicast IP String localIP = "192.168.0.7"; // please set your host IP (2010/11/16) int INPUT_PORT = 8000; int OUTPUT_PORT = 8001; UDP udp; // define the UDP object /** * init */ void setup() { // create a new datagram connection on port OUTPUT_PORT // and wait for incomming message udp = new UDP( this, OUTPUT_PORT, localIP ); // (2010/11/16) // udp.log( true ); // <-- printout the connection activity udp.listen( true ); } //process events void draw() {;} /* * on key pressed event: * pressing a key sends predefined command */ void keyPressed() { String cmd=""; if (key == '1') cmd="/"; // if (key == '2') cmd="/AnalogIn/new p20 ain"; if (key == '3') cmd="/ain/read"; // if (key == '4') cmd="/AnalogOut/new p18 aout"; if (key == '5') cmd="/aout/"; if (key == '6') cmd="/aout/write_u16 4123"; // if (key == '4') cmd="/BusIn/new bin p23 p22 p21"; // if (key == '5') cmd="/bin/read"; // if (key == '8') cmd="/DigitalOut/new LED4 myled4"; if (key == '9') cmd="/myled4/write 1"; if (key == '0') cmd="/myled4/write 0"; // send the command udp.send( cmd, remoteIP, INPUT_PORT ); } /* * To perform any action on datagram reception */ void receive( byte[] data, String ip, int port ) { data = subset(data, 0, data.length); String message = new String( data ); // print the result println( "received: \""+message+"\" from "+ip+" on port "+port ); } //---------------------------------------------------------------------------- #endif #if 0 //------------------------------------------------------------------------ // Test Program (written in ActionScript3) // Important Note: // this program can work in both windows and Linux enviroment. // DatagramSocketExample.as // // This program is comming from: // http://help.adobe.com/en_US/FlashPlatform/beta/reference/actionscript/3/flash/net/DatagramSocket.html // // I changed some parameters(IP address, port# etc ) for testing mbed HTTP over UDP // You can send command over UDP by changing "message:" field // // You must build it as AIR application to utilize UDP capability. // localIP should be changed to fit your enviroment. // package { import flash.display.Sprite; import flash.events.DatagramSocketDataEvent; import flash.events.Event; import flash.events.MouseEvent; import flash.events.TimerEvent; import flash.net.DatagramSocket; import flash.text.TextField; import flash.text.TextFieldAutoSize; import flash.text.TextFieldType; import flash.utils.ByteArray; import flash.utils.Timer; public class DatagramSocketExample extends Sprite { private var datagramSocket:DatagramSocket = new DatagramSocket();; private var localIP:TextField; private var localPort:TextField; private var logField:TextField; private var targetIP:TextField; private var targetPort:TextField; private var message:TextField; public function DatagramSocketExample() { setupUI(); } private function bind( event:Event ):void { if( datagramSocket.bound ) { datagramSocket.close(); datagramSocket = new DatagramSocket(); } datagramSocket.bind( parseInt( localPort.text ), localIP.text ); datagramSocket.addEventListener( DatagramSocketDataEvent.DATA, dataReceived ); datagramSocket.receive(); log( "Bound to: " + datagramSocket.localAddress + ":" + datagramSocket.localPort ); } private function dataReceived( event:DatagramSocketDataEvent ):void { //Read the data from the datagram log("Received from " + event.srcAddress + ":" + event.srcPort + "> " + event.data.readUTFBytes( event.data.bytesAvailable ) ); } private function send( event:Event ):void { //Create a message in a ByteArray var data:ByteArray = new ByteArray(); data.writeUTFBytes( message.text ); //Send a datagram to the target try { datagramSocket.send( data, 0, 0, targetIP.text, parseInt( targetPort.text )); log( "Sent message to " + targetIP.text + ":" + targetPort.text ); } catch ( error:Error ) { log( error.message ); } } private function log( text:String ):void { logField.appendText( text + "\n" ); logField.scrollV = logField.maxScrollV; trace( text ); } private function setupUI():void { // targetIP = createTextField( 10, 10, "Target IP:", "192.168.0.1" ); // targetPort = createTextField( 10, 35, "Target port:", "8989" ); targetIP = createTextField( 10, 10, "Target IP:", "239.255.0.1" ); targetPort = createTextField( 10, 35, "Target port:", "8000" ); message = createTextField( 10, 60, "Message:", "/AnalogIn/new p20 ain" ); // localIP = createTextField( 10, 85, "Local IP", "0.0.0.0"); // localPort = createTextField( 10, 110, "Local port:", "0" ); localIP = createTextField( 10, 85, "Local IP", "192.168.0.7"); // set your host IP localPort = createTextField( 10, 110, "Local port:", "8001" ); createTextButton( 250, 135, "Bind", bind ); createTextButton( 300, 135, "Send", send ); logField = createTextField( 10, 160, "Log:", "", false, 200 ) this.stage.nativeWindow.activate(); } private function createTextField( x:int, y:int, label:String, defaultValue:String = '', editable:Boolean = true, height:int = 20 ):TextField { var labelField:TextField = new TextField(); labelField.text = label; labelField.type = TextFieldType.DYNAMIC; labelField.width = 180; labelField.x = x; labelField.y = y; var input:TextField = new TextField(); input.text = defaultValue; input.type = TextFieldType.INPUT; input.border = editable; input.selectable = editable; input.width = 280; input.height = height; input.x = x + labelField.width; input.y = y; this.addChild( labelField ); this.addChild( input ); return input; } private function createTextButton( x:int, y:int, label:String, clickHandler:Function ):TextField { var button:TextField = new TextField(); button.htmlText = "<u><b>" + label + "</b></u>"; button.type = TextFieldType.DYNAMIC; button.selectable = false; button.width = 180; button.x = x; button.y = y; button.addEventListener( MouseEvent.CLICK, clickHandler ); this.addChild( button ); return button; } } } //------------------------------------------------------------------------ #endif