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

Committer:
xshige
Date:
Mon Nov 15 17:16:23 2010 +0000
Revision:
0:797742779818
Child:
1:918ffa99c345

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
xshige 0:797742779818 1 /*
xshige 0:797742779818 2 *
xshige 0:797742779818 3 * RPC Over UDP
xshige 0:797742779818 4 *
xshige 0:797742779818 5 * Command format is same as serial RPC (not HTTP RPC)
xshige 0:797742779818 6 *
xshige 0:797742779818 7 * (example)
xshige 0:797742779818 8 * So you can control mbed by sending the followng command (over UDP)
xshige 0:797742779818 9 * /DigitalOut/new LED1 myled
xshige 0:797742779818 10 * /myled/write 1
xshige 0:797742779818 11 * /AnalogIn/new p20 ain
xshige 0:797742779818 12 * /ain/read
xshige 0:797742779818 13 *
xshige 0:797742779818 14 * Please find attached Test Programs(processing & ActionScript3) at end of this file as comment "#if 0"
xshige 0:797742779818 15 *
xshige 0:797742779818 16 */
xshige 0:797742779818 17
xshige 0:797742779818 18 // 2010/11/15
xshige 0:797742779818 19 // written by: xshige
xshige 0:797742779818 20
xshige 0:797742779818 21
xshige 0:797742779818 22 #define DEBUG
xshige 0:797742779818 23
xshige 0:797742779818 24 // Send Port (RPC output)
xshige 0:797742779818 25 #define OUTPUT_PORT 8001
xshige 0:797742779818 26 // Receive Port (RPC input)
xshige 0:797742779818 27 #define INPUT_PORT 8000
xshige 0:797742779818 28
xshige 0:797742779818 29 #define DEBUG
xshige 0:797742779818 30
xshige 0:797742779818 31 // please comment out if you want two way unicast
xshige 0:797742779818 32 #define SENDBACK_UNICAST
xshige 0:797742779818 33
xshige 0:797742779818 34 #define DHCP
xshige 0:797742779818 35
xshige 0:797742779818 36 #include "mbed.h"
xshige 0:797742779818 37 #include "EthernetNetIf.h"
xshige 0:797742779818 38 #include "UDPSocket.h"
xshige 0:797742779818 39
xshige 0:797742779818 40 #include "rpc.h"
xshige 0:797742779818 41 Serial pc(USBTX, USBRX);
xshige 0:797742779818 42
xshige 0:797742779818 43 #ifdef DHCP
xshige 0:797742779818 44 EthernetNetIf eth;
xshige 0:797742779818 45 #else
xshige 0:797742779818 46 EthernetNetIf eth(
xshige 0:797742779818 47 IpAddr(192,168,0,25), //IP Address
xshige 0:797742779818 48 IpAddr(255,255,255,0), //Network Mask
xshige 0:797742779818 49 IpAddr(192,168,0,1), //Gateway
xshige 0:797742779818 50 IpAddr(192,168,0,1) //DNS
xshige 0:797742779818 51 );
xshige 0:797742779818 52 #endif
xshige 0:797742779818 53
xshige 0:797742779818 54 UDPSocket udpRec;
xshige 0:797742779818 55 UDPSocket udpSend;
xshige 0:797742779818 56
xshige 0:797742779818 57
xshige 0:797742779818 58 // mulitcast UDP
xshige 0:797742779818 59 #ifdef SENDBACK_UNICAST
xshige 0:797742779818 60 Host recHost(IpAddr(239, 255, 0, 1), INPUT_PORT, NULL); // Receive Port (RPC input)
xshige 0:797742779818 61 // multicast IP
xshige 0:797742779818 62 // "224.0.0.1" does not work(can Not receive)
xshige 0:797742779818 63 // "224.0.0.2" works correcly.
xshige 0:797742779818 64 // "239.255.0.0"-"239.255.255.255" (Site-Local Scope) maybe work
xshige 0:797742779818 65 #else
xshige 0:797742779818 66 // please change IP address to fit your enviroment
xshige 0:797742779818 67 // unicast IUDP
xshige 0:797742779818 68 Host sendHost(IpAddr(192, 168, 0, 7), OUTPUT_PORT, NULL); // Send Port (RPC output)
xshige 0:797742779818 69 Host recHost(IpAddr(192, 168, 0, 7), INPUT_PORT, NULL); // Receive Port (RPC input)
xshige 0:797742779818 70 #endif
xshige 0:797742779818 71
xshige 0:797742779818 72 // receive commands, and send back the responses
xshige 0:797742779818 73 char inbuf[512], outbuf[512];
xshige 0:797742779818 74
xshige 0:797742779818 75 void onUDPSocketEvent(UDPSocketEvent e)
xshige 0:797742779818 76 {
xshige 0:797742779818 77
xshige 0:797742779818 78 switch(e)
xshige 0:797742779818 79 {
xshige 0:797742779818 80 case UDPSOCKET_READABLE: //The only event for now
xshige 0:797742779818 81
xshige 0:797742779818 82 Host host;
xshige 0:797742779818 83 while( int len = udpRec.recvfrom( inbuf, 512, &host ) )
xshige 0:797742779818 84 {
xshige 0:797742779818 85 if( len <= 0 )
xshige 0:797742779818 86 break;
xshige 0:797742779818 87 inbuf[len]=0;
xshige 0:797742779818 88 #ifdef DEBUG
xshige 0:797742779818 89 printf("\r\nFrom %d.%d.%d.%d: %s\r\n",
xshige 0:797742779818 90 host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3], inbuf);
xshige 0:797742779818 91 #endif
xshige 0:797742779818 92
xshige 0:797742779818 93 #ifdef SENDBACK_UNICAST
xshige 0:797742779818 94 Host sendHost(IpAddr(
xshige 0:797742779818 95 host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3]),
xshige 0:797742779818 96 OUTPUT_PORT, NULL); // Send Port (RPC output)
xshige 0:797742779818 97 #endif
xshige 0:797742779818 98
xshige 0:797742779818 99 udpSend.bind(sendHost);
xshige 0:797742779818 100
xshige 0:797742779818 101 #ifdef DEBUG
xshige 0:797742779818 102 printf("debug1:%d %s\r\n",len,inbuf);
xshige 0:797742779818 103 #endif
xshige 0:797742779818 104 if (len>0) {
xshige 0:797742779818 105 rpc(inbuf, outbuf);
xshige 0:797742779818 106 udpSend.sendto( outbuf, strlen(outbuf), &sendHost);
xshige 0:797742779818 107 }
xshige 0:797742779818 108 #ifdef DEBUG
xshige 0:797742779818 109 printf("debug2:%s\r\n", outbuf);
xshige 0:797742779818 110 #endif
xshige 0:797742779818 111 }
xshige 0:797742779818 112 break;
xshige 0:797742779818 113 }
xshige 0:797742779818 114 }
xshige 0:797742779818 115
xshige 0:797742779818 116 int main() {
xshige 0:797742779818 117 // make debug port Fast
xshige 0:797742779818 118 Serial pc(USBTX, USBRX);
xshige 0:797742779818 119 // pc.baud(9600);
xshige 0:797742779818 120 pc.baud(115200);
xshige 0:797742779818 121 // pc.baud(230400);
xshige 0:797742779818 122
xshige 0:797742779818 123 // setup the classes that can be created dynamically
xshige 0:797742779818 124 Base::add_rpc_class<AnalogIn>();
xshige 0:797742779818 125 Base::add_rpc_class<AnalogOut>();
xshige 0:797742779818 126 Base::add_rpc_class<DigitalIn>();
xshige 0:797742779818 127 Base::add_rpc_class<DigitalOut>();
xshige 0:797742779818 128 Base::add_rpc_class<DigitalInOut>();
xshige 0:797742779818 129 Base::add_rpc_class<PwmOut>();
xshige 0:797742779818 130 Base::add_rpc_class<Timer>();
xshige 0:797742779818 131 Base::add_rpc_class<SPI>();
xshige 0:797742779818 132 Base::add_rpc_class<BusOut>();
xshige 0:797742779818 133 Base::add_rpc_class<BusIn>();
xshige 0:797742779818 134 Base::add_rpc_class<BusInOut>();
xshige 0:797742779818 135 Base::add_rpc_class<Serial>();
xshige 0:797742779818 136
xshige 0:797742779818 137 // setup network
xshige 0:797742779818 138 printf("Setting up...\r\n");
xshige 0:797742779818 139 EthernetErr ethErr = eth.setup();
xshige 0:797742779818 140 if(ethErr) {
xshige 0:797742779818 141 printf("Error %d in setup.\r\n", ethErr);
xshige 0:797742779818 142 return -1;
xshige 0:797742779818 143 }
xshige 0:797742779818 144
xshige 0:797742779818 145 printf("UDP RPC Setup OK\r\n");
xshige 0:797742779818 146
xshige 0:797742779818 147 udpRec.setOnEvent(&onUDPSocketEvent);
xshige 0:797742779818 148
xshige 0:797742779818 149 udpRec.bind(recHost);
xshige 0:797742779818 150
xshige 0:797742779818 151
xshige 0:797742779818 152 while(1) {
xshige 0:797742779818 153 Net::poll();
xshige 0:797742779818 154 #if 0
xshige 0:797742779818 155 // debug code
xshige 0:797742779818 156 Host host;
xshige 0:797742779818 157 int len = udpRec.recvfrom( inbuf, 512, &host );
xshige 0:797742779818 158 printf("debug:%d %s\r\n",len,inbuf);
xshige 0:797742779818 159 len=1;
xshige 0:797742779818 160 if (len>0) {
xshige 0:797742779818 161 rpc(inbuf, outbuf);
xshige 0:797742779818 162 strcpy(outbuf,"RPC UDP Test");
xshige 0:797742779818 163 udpSend.sendto( outbuf, strlen(outbuf), &sendHost );
xshige 0:797742779818 164 memset(inbuf,0,512);
xshige 0:797742779818 165 }
xshige 0:797742779818 166 printf("debug:%s\r\n", outbuf);
xshige 0:797742779818 167 memset(outbuf,0,512);
xshige 0:797742779818 168 wait(1);
xshige 0:797742779818 169 #endif
xshige 0:797742779818 170 }
xshige 0:797742779818 171
xshige 0:797742779818 172 }
xshige 0:797742779818 173
xshige 0:797742779818 174 #if 0
xshige 0:797742779818 175 //------------------------------------------------------------------------
xshige 0:797742779818 176 // Test Program (written in processing)
xshige 0:797742779818 177
xshige 0:797742779818 178 // Important Note:
xshige 0:797742779818 179 // this program can NOT work in windows enviroment (only Linux enviroment)
xshige 0:797742779818 180
xshige 0:797742779818 181 /**
xshige 0:797742779818 182 * RCP over UDP (by mbed)
xshige 0:797742779818 183 * Test Program
xshige 0:797742779818 184 *
xshige 0:797742779818 185 * you can get UDP library from:
xshige 0:797742779818 186 * http://ubaa.net/shared/processing/udp/
xshige 0:797742779818 187 *
xshige 0:797742779818 188 */
xshige 0:797742779818 189
xshige 0:797742779818 190 // import UDP library
xshige 0:797742779818 191 import hypermedia.net.*;
xshige 0:797742779818 192
xshige 0:797742779818 193 String remoteIP = "239.255.0.1"; // multicast IP
xshige 0:797742779818 194 int INPUT_PORT = 8000;
xshige 0:797742779818 195 int OUTPUT_PORT = 8001;
xshige 0:797742779818 196
xshige 0:797742779818 197 UDP udp; // define the UDP object
xshige 0:797742779818 198
xshige 0:797742779818 199 /**
xshige 0:797742779818 200 * init
xshige 0:797742779818 201 */
xshige 0:797742779818 202 void setup() {
xshige 0:797742779818 203 // create a new datagram connection on port OUTPUT_PORT
xshige 0:797742779818 204 // and wait for incomming message
xshige 0:797742779818 205 udp = new UDP( this, OUTPUT_PORT );
xshige 0:797742779818 206 // udp.log( true ); // <-- printout the connection activity
xshige 0:797742779818 207 udp.listen( true );
xshige 0:797742779818 208 }
xshige 0:797742779818 209
xshige 0:797742779818 210 //process events
xshige 0:797742779818 211 void draw() {;}
xshige 0:797742779818 212
xshige 0:797742779818 213 /*
xshige 0:797742779818 214 * on key pressed event:
xshige 0:797742779818 215 * pressing a key sends predefined command
xshige 0:797742779818 216 */
xshige 0:797742779818 217 void keyPressed() {
xshige 0:797742779818 218 String cmd="";
xshige 0:797742779818 219 if (key == '1') cmd="/";
xshige 0:797742779818 220 //
xshige 0:797742779818 221 if (key == '2') cmd="/AnalogIn/new p20 ain";
xshige 0:797742779818 222 if (key == '3') cmd="/ain/read";
xshige 0:797742779818 223 //
xshige 0:797742779818 224 if (key == '4') cmd="/AnalogOut/new p18 aout";
xshige 0:797742779818 225 if (key == '5') cmd="/aout/";
xshige 0:797742779818 226 if (key == '6') cmd="/aout/write_u16 4123";
xshige 0:797742779818 227 // if (key == '4') cmd="/BusIn/new bin p23 p22 p21";
xshige 0:797742779818 228 // if (key == '5') cmd="/bin/read";
xshige 0:797742779818 229 //
xshige 0:797742779818 230 if (key == '8') cmd="/DigitalOut/new LED4 myled4";
xshige 0:797742779818 231 if (key == '9') cmd="/myled4/write 1";
xshige 0:797742779818 232 if (key == '0') cmd="/myled4/write 0";
xshige 0:797742779818 233
xshige 0:797742779818 234 // send the command
xshige 0:797742779818 235 udp.send( cmd, remoteIP, INPUT_PORT );
xshige 0:797742779818 236
xshige 0:797742779818 237 }
xshige 0:797742779818 238
xshige 0:797742779818 239 /*
xshige 0:797742779818 240 * To perform any action on datagram reception
xshige 0:797742779818 241 */
xshige 0:797742779818 242
xshige 0:797742779818 243 void receive( byte[] data, String ip, int port ) {
xshige 0:797742779818 244
xshige 0:797742779818 245 data = subset(data, 0, data.length);
xshige 0:797742779818 246 String message = new String( data );
xshige 0:797742779818 247
xshige 0:797742779818 248 // print the result
xshige 0:797742779818 249 println( "received: \""+message+"\" from "+ip+" on port "+port );
xshige 0:797742779818 250 }
xshige 0:797742779818 251 //----------------------------------------------------------------------------
xshige 0:797742779818 252 #endif
xshige 0:797742779818 253
xshige 0:797742779818 254 #if 0
xshige 0:797742779818 255 //------------------------------------------------------------------------
xshige 0:797742779818 256 // Test Program (written in ActionScript3)
xshige 0:797742779818 257
xshige 0:797742779818 258 // Important Note:
xshige 0:797742779818 259 // this program can work in both windows and Linux enviroment.
xshige 0:797742779818 260
xshige 0:797742779818 261 // DatagramSocketExample.as
xshige 0:797742779818 262 //
xshige 0:797742779818 263 // This program is comming from:
xshige 0:797742779818 264 // http://help.adobe.com/en_US/FlashPlatform/beta/reference/actionscript/3/flash/net/DatagramSocket.html
xshige 0:797742779818 265 //
xshige 0:797742779818 266 // I changed some parameters(IP address, port# etc ) for testing mbed HTTP over UDP
xshige 0:797742779818 267 // You can send command over UDP by changing "message:" field
xshige 0:797742779818 268 //
xshige 0:797742779818 269 // You must build it as AIR application to utilize UDP capability.
xshige 0:797742779818 270 // localIP should be changed to fit your enviroment.
xshige 0:797742779818 271 //
xshige 0:797742779818 272 package
xshige 0:797742779818 273 {
xshige 0:797742779818 274 import flash.display.Sprite;
xshige 0:797742779818 275 import flash.events.DatagramSocketDataEvent;
xshige 0:797742779818 276 import flash.events.Event;
xshige 0:797742779818 277 import flash.events.MouseEvent;
xshige 0:797742779818 278 import flash.events.TimerEvent;
xshige 0:797742779818 279 import flash.net.DatagramSocket;
xshige 0:797742779818 280 import flash.text.TextField;
xshige 0:797742779818 281 import flash.text.TextFieldAutoSize;
xshige 0:797742779818 282 import flash.text.TextFieldType;
xshige 0:797742779818 283 import flash.utils.ByteArray;
xshige 0:797742779818 284 import flash.utils.Timer;
xshige 0:797742779818 285
xshige 0:797742779818 286 public class DatagramSocketExample extends Sprite
xshige 0:797742779818 287 {
xshige 0:797742779818 288 private var datagramSocket:DatagramSocket = new DatagramSocket();;
xshige 0:797742779818 289
xshige 0:797742779818 290 private var localIP:TextField;
xshige 0:797742779818 291 private var localPort:TextField;
xshige 0:797742779818 292 private var logField:TextField;
xshige 0:797742779818 293 private var targetIP:TextField;
xshige 0:797742779818 294 private var targetPort:TextField;
xshige 0:797742779818 295 private var message:TextField;
xshige 0:797742779818 296
xshige 0:797742779818 297 public function DatagramSocketExample()
xshige 0:797742779818 298 {
xshige 0:797742779818 299 setupUI();
xshige 0:797742779818 300 }
xshige 0:797742779818 301
xshige 0:797742779818 302 private function bind( event:Event ):void
xshige 0:797742779818 303 {
xshige 0:797742779818 304 if( datagramSocket.bound )
xshige 0:797742779818 305 {
xshige 0:797742779818 306 datagramSocket.close();
xshige 0:797742779818 307 datagramSocket = new DatagramSocket();
xshige 0:797742779818 308
xshige 0:797742779818 309 }
xshige 0:797742779818 310 datagramSocket.bind( parseInt( localPort.text ), localIP.text );
xshige 0:797742779818 311 datagramSocket.addEventListener( DatagramSocketDataEvent.DATA, dataReceived );
xshige 0:797742779818 312 datagramSocket.receive();
xshige 0:797742779818 313 log( "Bound to: " + datagramSocket.localAddress + ":" + datagramSocket.localPort );
xshige 0:797742779818 314 }
xshige 0:797742779818 315
xshige 0:797742779818 316 private function dataReceived( event:DatagramSocketDataEvent ):void
xshige 0:797742779818 317 {
xshige 0:797742779818 318 //Read the data from the datagram
xshige 0:797742779818 319 log("Received from " + event.srcAddress + ":" + event.srcPort + "> " +
xshige 0:797742779818 320 event.data.readUTFBytes( event.data.bytesAvailable ) );
xshige 0:797742779818 321 }
xshige 0:797742779818 322
xshige 0:797742779818 323 private function send( event:Event ):void
xshige 0:797742779818 324 {
xshige 0:797742779818 325 //Create a message in a ByteArray
xshige 0:797742779818 326 var data:ByteArray = new ByteArray();
xshige 0:797742779818 327 data.writeUTFBytes( message.text );
xshige 0:797742779818 328
xshige 0:797742779818 329 //Send a datagram to the target
xshige 0:797742779818 330 try
xshige 0:797742779818 331 {
xshige 0:797742779818 332 datagramSocket.send( data, 0, 0, targetIP.text, parseInt( targetPort.text ));
xshige 0:797742779818 333 log( "Sent message to " + targetIP.text + ":" + targetPort.text );
xshige 0:797742779818 334 }
xshige 0:797742779818 335 catch ( error:Error )
xshige 0:797742779818 336 {
xshige 0:797742779818 337 log( error.message );
xshige 0:797742779818 338 }
xshige 0:797742779818 339 }
xshige 0:797742779818 340
xshige 0:797742779818 341 private function log( text:String ):void
xshige 0:797742779818 342 {
xshige 0:797742779818 343 logField.appendText( text + "\n" );
xshige 0:797742779818 344 logField.scrollV = logField.maxScrollV;
xshige 0:797742779818 345 trace( text );
xshige 0:797742779818 346 }
xshige 0:797742779818 347 private function setupUI():void
xshige 0:797742779818 348 {
xshige 0:797742779818 349 // targetIP = createTextField( 10, 10, "Target IP:", "192.168.0.1" );
xshige 0:797742779818 350 // targetPort = createTextField( 10, 35, "Target port:", "8989" );
xshige 0:797742779818 351
xshige 0:797742779818 352 targetIP = createTextField( 10, 10, "Target IP:", "239.255.0.1" );
xshige 0:797742779818 353 targetPort = createTextField( 10, 35, "Target port:", "8000" );
xshige 0:797742779818 354
xshige 0:797742779818 355 message = createTextField( 10, 60, "Message:", "/AnalogIn/new p20 ain" );
xshige 0:797742779818 356 // localIP = createTextField( 10, 85, "Local IP", "0.0.0.0");
xshige 0:797742779818 357 // localPort = createTextField( 10, 110, "Local port:", "0" );
xshige 0:797742779818 358
xshige 0:797742779818 359 localIP = createTextField( 10, 85, "Local IP", "192.168.0.7"); // set your host IP
xshige 0:797742779818 360 localPort = createTextField( 10, 110, "Local port:", "8001" );
xshige 0:797742779818 361
xshige 0:797742779818 362 createTextButton( 250, 135, "Bind", bind );
xshige 0:797742779818 363 createTextButton( 300, 135, "Send", send );
xshige 0:797742779818 364 logField = createTextField( 10, 160, "Log:", "", false, 200 )
xshige 0:797742779818 365
xshige 0:797742779818 366 this.stage.nativeWindow.activate();
xshige 0:797742779818 367 }
xshige 0:797742779818 368
xshige 0:797742779818 369 private function createTextField( x:int, y:int, label:String, defaultValue:String = '', editable:Boolean = true, height:int = 20 ):TextField
xshige 0:797742779818 370 {
xshige 0:797742779818 371 var labelField:TextField = new TextField();
xshige 0:797742779818 372 labelField.text = label;
xshige 0:797742779818 373 labelField.type = TextFieldType.DYNAMIC;
xshige 0:797742779818 374 labelField.width = 180;
xshige 0:797742779818 375 labelField.x = x;
xshige 0:797742779818 376 labelField.y = y;
xshige 0:797742779818 377
xshige 0:797742779818 378 var input:TextField = new TextField();
xshige 0:797742779818 379 input.text = defaultValue;
xshige 0:797742779818 380 input.type = TextFieldType.INPUT;
xshige 0:797742779818 381 input.border = editable;
xshige 0:797742779818 382 input.selectable = editable;
xshige 0:797742779818 383 input.width = 280;
xshige 0:797742779818 384 input.height = height;
xshige 0:797742779818 385 input.x = x + labelField.width;
xshige 0:797742779818 386 input.y = y;
xshige 0:797742779818 387
xshige 0:797742779818 388 this.addChild( labelField );
xshige 0:797742779818 389 this.addChild( input );
xshige 0:797742779818 390
xshige 0:797742779818 391 return input;
xshige 0:797742779818 392 }
xshige 0:797742779818 393
xshige 0:797742779818 394 private function createTextButton( x:int, y:int, label:String, clickHandler:Function ):TextField
xshige 0:797742779818 395 {
xshige 0:797742779818 396 var button:TextField = new TextField();
xshige 0:797742779818 397 button.htmlText = "<u><b>" + label + "</b></u>";
xshige 0:797742779818 398 button.type = TextFieldType.DYNAMIC;
xshige 0:797742779818 399 button.selectable = false;
xshige 0:797742779818 400 button.width = 180;
xshige 0:797742779818 401 button.x = x;
xshige 0:797742779818 402 button.y = y;
xshige 0:797742779818 403 button.addEventListener( MouseEvent.CLICK, clickHandler );
xshige 0:797742779818 404
xshige 0:797742779818 405 this.addChild( button );
xshige 0:797742779818 406 return button;
xshige 0:797742779818 407
xshige 0:797742779818 408 }
xshige 0:797742779818 409 }
xshige 0:797742779818 410 }
xshige 0:797742779818 411 //------------------------------------------------------------------------
xshige 0:797742779818 412 #endif