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

Files at this revision

API Documentation at this revision

Comitter:
xshige
Date:
Mon Nov 15 17:16:23 2010 +0000
Child:
1:918ffa99c345
Commit message:

Changed in this revision

EthernetNetIf.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /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