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
Revision 0:797742779818, committed 2010-11-15
- Comitter:
- xshige
- Date:
- Mon Nov 15 17:16:23 2010 +0000
- Child:
- 1:918ffa99c345
- Commit message:
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/EthernetNetIf.lib Mon Nov 15 17:16:23 2010 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/donatien/code/EthernetNetIf/#bc7df6da7589
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon Nov 15 17:16:23 2010 +0000 @@ -0,0 +1,412 @@ +/* + * + * 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/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" does not work(can Not receive) +// "224.0.0.2" works correcly. +// "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) +#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) + +/** + * 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 +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 ); +// 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 \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Mon Nov 15 17:16:23 2010 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/9114680c05da