RPC Over TCP(telnet) Command format is same as serial RPC (not HTTP RPC). Please find attached Test Program(Processing and ActionScript3) at end of this file. Same functionality of Serial RPC via Serproxy.

Dependencies:   EthernetNetIf mbed

main.cpp

Committer:
xshige
Date:
2010-11-19
Revision:
0:a0cd4d9690f0

File content as of revision 0:a0cd4d9690f0:

/*
 *
 * RPC over TCP (RPC over telnet)
 * (Same functionality of Serial RPC via Serproxy )
 *
 * 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"
 *
 * Serproxy(Serial Proxy) source&binary can be downloaded from:
 *  http://cote.cc/blog/serialproxy-v014-can-use-com-ports-above-9
 *  http://cote.cc/sites/default/files/serproxy-0.1.4.win32.zip
 *  http://cote.cc/sites/default/files/serproxy-0.1.4.src_.zip
 *
 */

// 2010/11/20
// written by: xshige


// please change port# if you need
#define TCP_LISTENING_PORT 5335 // telnet port

#define DEBUG
//#define DHCP
//#define LIVE_LED

#include "mbed.h"
#include "EthernetNetIf.h"
#include "TCPSocket.h"
#include "rpc.h"

#ifdef DHCP
EthernetNetIf eth;
#else
// please set your mbed IP
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

#ifdef LIVE_LED
DigitalOut led4(LED4, "led4");
#endif


// receive commands, and send back the responses
char inbuf[512], outbuf[512];

TCPSocket ListeningSock;
TCPSocket* pConnectedSock; // for ConnectedSock
Host client;
TCPSocketErr err;

void onConnectedTCPSocketEvent(TCPSocketEvent e)
{
   switch(e)
    {
    case TCPSOCKET_CONNECTED:
        printf("TCP Socket Connected\r\n");
        break;
    case TCPSOCKET_WRITEABLE:
        //Can now write some data...
//        printf("TCP Socket Writable\r\n");
        break;
    case TCPSOCKET_READABLE:
        //Can now read dome data...
 //       printf("TCP Socket Readable\r\n");
//-------------------------------------
        // Read in any available data into the buffer
        int len = pConnectedSock->recv(inbuf, 512);
        inbuf[len] = 0;
#ifdef DEBUG        
        printf("\nReceived: %s", inbuf);
#endif        
        // do RPC
        if (len>0) {
            rpc(inbuf, outbuf); 
            outbuf[strlen(outbuf)]=0;
            // send result of RPC
            pConnectedSock->send(outbuf, strlen(outbuf));
#ifdef DEBUG            
            printf("Sent:%s\n",outbuf);
#endif
        }
       break;
//----------------------------------------
    case TCPSOCKET_CONTIMEOUT:
        printf("TCP Socket Timeout\r\n");
        break;
    case TCPSOCKET_CONRST:
        printf("TCP Socket CONRST\r\n");
        break;
    case TCPSOCKET_CONABRT:
        printf("TCP Socket CONABRT\r\n");
        break;
    case TCPSOCKET_ERROR:
        printf("TCP Socket Error\r\n");
        break;
    case TCPSOCKET_DISCONNECTED:
        printf("TCP Socket Disconnected\r\n");        
//        pConnectedSock->close();
        break;
    default:
        printf("DEFAULT\r\n"); 
      }
}


void onListeningTCPSocketEvent(TCPSocketEvent e)
{
    switch(e)
    {
    case TCPSOCKET_ACCEPT:
        printf("Listening: TCP Socket Accepted\r\n");
        // Accepts connection from client and gets connected socket.   
        err=ListeningSock.accept(&client, &pConnectedSock);
        if (err) {
            printf("onListeningTcpSocketEvent : Could not accept connection.\r\n");
            return; //Error in accept, discard connection
        }
        // Setup the new socket events
        pConnectedSock->setOnEvent(&onConnectedTCPSocketEvent);
        // We can find out from where the connection is coming by looking at the
        // Host parameter of the accept() method
        IpAddr clientIp = client.getIp();
        printf("Listening: Incoming TCP connection from %d.%d.%d.%d\r\n", 
           clientIp[0], clientIp[1], clientIp[2], clientIp[3]);
       break;
    // the following cases will not happen
    case TCPSOCKET_CONNECTED:
        printf("Listening: TCP Socket Connected\r\n");
        break;
    case TCPSOCKET_WRITEABLE:
        printf("Listening: TCP Socket Writable\r\n");
        break;
    case TCPSOCKET_READABLE:
        printf("Listening: TCP Socket Readable\r\n");
        break;
    case TCPSOCKET_CONTIMEOUT:
        printf("Listening: TCP Socket Timeout\r\n");
        break;
    case TCPSOCKET_CONRST:
        printf("Listening: TCP Socket CONRST\r\n");
        break;
    case TCPSOCKET_CONABRT:
        printf("Listening: TCP Socket CONABRT\r\n");
        break;
    case TCPSOCKET_ERROR:
        printf("Listening: TCP Socket Error\r\n");
        break;
    case TCPSOCKET_DISCONNECTED:
    //Close socket...
        printf("Listening: TCP Socket Disconnected\r\n");       
     //  keep socket for next connection //ListeningSock.close();
        break;
    default:
        printf("DEFAULT\r\n"); 
     };
}


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("\r\n");
    printf("Setting up...\r\n");
    EthernetErr ethErr = eth.setup();
    if(ethErr)
    {
        printf("Error %d in setup.\r\n", ethErr);
        return -1;
    }
    printf("RPC over TCP(telnet) Setup OK\r\n");

    IpAddr ip = eth.getIp();
    printf("mbed IP Address is %d.%d.%d.%d:%d\r\n", ip[0], ip[1], ip[2], ip[3],(TCP_LISTENING_PORT));

    // Set the callbacks for Listening
    ListeningSock.setOnEvent(&onListeningTCPSocketEvent); 
  
    // bind and listen on TCP
    err=ListeningSock.bind(Host(IpAddr(), TCP_LISTENING_PORT));
    printf("Binding..\r\n");
    if(err)
    {
        //Deal with that error...
        printf("Binding Error\n");
    }
    
    err=ListeningSock.listen(); // Starts listening
    printf("Listening...\r\n");
    if(err)
    {
        printf("Listening Error\r\n");
    }
 
#ifdef LIVE_LED 
  Timer tmr;
  tmr.start();
#endif


  while(true)
  {
    Net::poll();

#ifdef LIVE_LED
    if(tmr.read() > 0.2) // sec
    {
      led4=!led4; //Show that we are alive
      tmr.reset();
    }
#endif
  }  
}
#if 0
//------------------------------------------------------------------------
// Test Program (written in processing)

/*
 *
 * RPC over TCP(telnet) or
 * Serial RPC (via Serproxy)
 * Test Program
 * 
 */
    
import processing.net.*; 

// please setup remoteIP for yor enviroment
String remoteIP = "192.168.0.25"; // server IP
//String remoteIP = "127.0.0.1"; // (Serproxy case)
int TELNET_PORT = 5335;

Client myClient; 
String dataIn; 
 
void setup() { 
  size(200, 200); 
  myClient = new Client(this, remoteIP, TELNET_PORT); 
} 
    
void draw() {}  // Empty draw keeps the program running

/* 
 * on key pressed event:
 * pressing a key sends predefined command
 */
void keyPressed() {
    String cmd="";
// Real Serial RPC needs terminator("\r\n")
    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
    // ***  Serial RPC needs terminator("\n") **
    myClient.write(cmd+"\n");
 
}

// ClientEvent message is generated when the server 
// sends data to an existing client.
void clientEvent(Client someClient) {
    if (someClient.available()>0) {
      dataIn = someClient.readString(); 
      //println(dataIn);       
      print(dataIn); 
    }

}
#endif
//------------------------------------------------------------------------
//------------------------------------------------------------------------
#if 0
// TelnetClient.as

/*
 *
 * RPC over TCP(telnet) or
 * Serial RPC (via Serproxy)
 * Test Program
 * 
 */

package {
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.IOErrorEvent;
        import flash.events.KeyboardEvent;
        import flash.events.ProgressEvent;
        import flash.events.SecurityErrorEvent;
        import flash.net.Socket;
        import flash.text.*;
        import flash.ui.Keyboard;

        public class TelnetClient extends Sprite
        {
				// please set your mbed IP
				private var targetIP:String = "192.168.0.25";
				//private var targetIP:String = "127.0.0.1";
				//
				private var targetPort:String = "5335";
				//private var targetPort:String = "5334";

				private var socket:Socket;
                private var textView:TextField;
                private var textBoard:TextField;
				
                public function TelnetClient()
                {
						// setup text field
                        textView        = addTextField( 5, 10, 640, 340+190 );
                        textBoard       = addTextField( 5, 340+200, 640, 20 ); // input field

			            // Create a new Socket object and assign event listeners.
						socket = new Socket();
						
                        socket.addEventListener( Event.CONNECT, onConnect );
                        socket.addEventListener( Event.CLOSE, onClose );
                        socket.addEventListener( SecurityErrorEvent.SECURITY_ERROR, onSecurtyError );
                        socket.addEventListener( IOErrorEvent.IO_ERROR,onIOError );
                        socket.addEventListener(ProgressEvent.SOCKET_DATA, onRead );
                        addEventListener( KeyboardEvent.KEY_DOWN, onWriteBoard );

			            // Attempt to connect to remote socket server.
            			try {
                			writeView("trying to connect to " + targetIP + ":" + targetPort +'\n');
               				 socket.connect(targetIP, parseInt(targetPort));
            			} catch (error:Error) {
                		/*
                    		Unable to connect to remote server, display error
                    		message and close connection.
                		*/
                			writeView(error.message+'\n');
                			socket.close();
            			}

                }

                public function onConnect( event:Event ):void
                {
                        writeView( "server connected\n" );
                }

                public function onClose( event:Event ):void
                {
                        writeView( "server close\n" );
                }

                public function onSecurtyError( ev:Event ):void
                {
                        writeView( "Security error.\n" );
                }

                public function onIOError( ev:Event ):void
                {
                       writeView( "IOError.\n" );
                }

                public function onRead( event:Event ):void
                {
                        writeView( socket.readUTFBytes(socket.bytesAvailable ) );
                }

                public function onWriteBoard( event:KeyboardEvent ):void
                {
                        if( !socket.connected ) return;
                        if( event.keyCode == Keyboard.ENTER )
                        {
							// Shortcut Keys for testing RPC
							if (textBoard.text == "1") textBoard.text = "/";
							if (textBoard.text == "2") textBoard.text = "/AnalogIn/new p20 ain";
							if (textBoard.text == "3") textBoard.text = "/ain/read";	
							//
							//if (textBoard.text == "4") textBoard.text = "/AnalogOut/new p18 aout";	
							//if (textBoard.text == "5") textBoard.text = "/aout/";	
							//if (textBoard.text == "6") textBoard.text = "/aout/write_u16 4123";	
							//
							if (textBoard.text == "4") textBoard.text = "/BusOut/new b0 LED1 LED2 LED3 LED4";	
							if (textBoard.text == "5") textBoard.text = "/bo/write  13";	
							//   
							if (textBoard.text == "8") textBoard.text = "/DigitalOut/new LED4 myled4";	
							if (textBoard.text == "9") textBoard.text = "/myled4/write 1";	
							if (textBoard.text == "0") textBoard.text = "/myled4/write 0";	
							//
							socket.writeUTFBytes( textBoard.text + '\n' );
							socket.flush();
                            textBoard.text = '';
                        }
                }

                public function writeView( str:String ):void
                {
                        if( textView.text == '' )
                        {
                                textView.text = str;
                        }
                        else {
                        //        textView.text = textView.text + '\n' + str;
                        //        textView.text = textView.text + str;
							textView.appendText(str+'\n'); // serial RPC via serproxy
						}
						//	
						textView.scrollV++; // make scroll
                }

                private function addTextField( x:int, y:int, w:uint,h:uint ):TextField
                {
                        var textField:TextField = new TextField();
                        addChild( textField );
                        textField.x             = x;
                        textField.y             = y;
                        textField.width         = w;
                        textField.height        = h;
                        textField.text          = "";
                        textField.selectable    = true;
                        textField.border        = true;
                        textField.type          = TextFieldType.INPUT;
						textField.wordWrap		= true;
                        return textField;
                }

        }
}
#endif
//------------------------------------------------------------------------