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
Child:
1:918ffa99c345
diff -r 000000000000 -r 797742779818 main.cpp
--- /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