Mike Spadaru / physcom
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers rpc.h Source File

rpc.h

00001 #ifndef RPC_H
00002 #define RPC_H
00003 
00004 #include "mbed.h"
00005 
00006 namespace physcom {
00007     
00008 #define RPC_MAX_STRING 256
00009 
00010 /** 
00011  * The RPC class used to parse and call RPCFunctions
00012  * This class should not be instantiated. It is the base class of RPCFunction.
00013  * The only relevant use of this class is to call the static function RPC::call.
00014  *
00015  * A serial connection must be opened on the USB port of the mbed: 
00016  * @code
00017  * Serial pc(USBTX, USBRX);
00018  * @endcode
00019  *
00020  * In order not to block the execution of the program while awaiting input on the
00021  * serial connection, a callback function can be defined. This callback should
00022  * execute a call to the static function RPC::call(char* input, char* output).
00023  * An example callback function:
00024  * @code
00025  * void RPCSerial() {
00026  *    pc.gets(input, RPC_MAX_STRING);
00027  *    RPC::call(input, output); 
00028  *    pc.printf("%s\n", output);
00029  * }
00030  * @endcode
00031  *
00032  * This function can be attached as a callback and be executed each time new
00033  * input is received on the serial connection:
00034  * @code
00035  * pc.attach(&RPCSerial, Serial::RxIrq);
00036  * @endcode
00037  *
00038  * RPCFunctions can be defined by passing a pointer to a function to the 
00039  * constructor of the RPCFunction call. The RPCFunction must have two parameters
00040  * of type char*, representing the input arguments and output result of the 
00041  * function. In case multiple values are used as arguments or results, they 
00042  * should be separated by spaces. The folowing example implements a function
00043  * which doubles the values of two integer arguments and returns the results
00044  * to the RPC caller:
00045  * @code
00046  * void double_numbers(char * input, char * output);
00047  * RPCFunction MyDoubleRPC(&double_numbers, "MyDoubleRPC");
00048  * 
00049  * void double_numbers(char * input, char * output){
00050  *    const char *DELIMITER = " ";
00051  *    char* first_string = strtok (input, DELIMITER);
00052  *    char* second_string = strtok (NULL, DELIMITER);
00053  *    int first_int = atoi(first_string);
00054  *    int second_int = atoi(second_string);
00055  *    sprintf(output, "%d %d", first_int*2, second_int*2);
00056  * }
00057  * @endcode
00058  *
00059  * An Example mbed program can be seeen below:
00060  * @code
00061  * #include "mbed.h"
00062  * #include "physcom.h"
00063  * 
00064  * using namespace physcom;
00065  * 
00066  * Serial pc(USBTX, USBRX);
00067  * 
00068  * // Define RPC functions
00069  * void read_value(char * input, char * output);
00070  * RPCFunction ReadValue(&read_value, "ReadValue");
00071  * void set_value(char * input, char * output);
00072  * RPCFunction SetValue(&set_value, "SetValue");
00073  * 
00074  * // mbed-local variables
00075  * DigitalOut myled(LED1);
00076  * int local_value = 50; 
00077  * 
00078  * // receive commands, and send back the responses
00079  * char input[RPC_MAX_STRING], output[RPC_MAX_STRING];
00080  * 
00081  * // Callback exectued whenever there is new input on the serial connection
00082  * void RPCSerial() {
00083  *     pc.gets(input, RPC_MAX_STRING);
00084  *     RPC::call(input, output); 
00085  *     pc.printf("%s\n", output);
00086  * }
00087  * 
00088  * int main() {
00089  *     
00090  *     // Attaching the callback to the Serial interface 
00091  *     // RPCSerial() will be executed whenever a serial interrupt is generated
00092  *     pc.attach(&RPCSerial, Serial::RxIrq);
00093  *     
00094  *     while(1) {
00095  *         myled = 1;
00096  *         wait(0.2);
00097  *         myled = 0;
00098  *         wait(0.2);
00099  *     }
00100  * }
00101  * 
00102  * void read_value(char * input, char * output){
00103  *     sprintf(output, "%d", local_value);
00104  * }
00105  *  
00106  * void set_value(char * input, char * output){
00107  *     local_value = atoi(input);
00108  *     output[0] = '\0'; // No result, so setting an empty string as output
00109  * }
00110  * @endcode
00111  *
00112  *
00113  *
00114  * An example MATLAB program that calls the RPCFunctions defined on the mbed in 
00115  * the previous example:
00116  * @code
00117  * import mbed.*
00118  *
00119  * % Open a serial connection to mbed on port COM11
00120  * mymbed = SerialRPC('COM11', 9600)
00121  * mymbed.reset();
00122  * pause(0.5);
00123  * 
00124  * ME = []; % exception vector for try-catch
00125  * try 
00126  *     % Attach to an Existing RPCFunction on mbed
00127  *     ReadValue = RPCFunction(mymbed, 'ReadValue');
00128  *     SetValue = RPCFunction(mymbed, 'SetValue');
00129  *    
00130  *     % Run its methods
00131  *     value = ReadValue.run(' ')
00132  *     SetValue.run('45')
00133  *     value = ReadValue.run(' ')
00134  * catch ME
00135  *     disp('Error:');
00136  *     disp(ME.message);
00137  * end
00138  *
00139  * % cleanup
00140  * mymbed.delete;
00141  * clear;
00142  * @endcode
00143  */
00144 class RPC {
00145 
00146 public:
00147 
00148     RPC(const char *name = NULL);
00149 
00150     virtual ~RPC();
00151 
00152     /**
00153     * Static method. Should be called everytime input is read on the serial
00154     * connection. RPC::call(input, output) will parse the input and call the
00155     * apropriate RPCFunction to compute the output and populate the result 
00156     * string.
00157     * @param Input string received from the serial connection
00158     * @param Output string rcomputed by executing the RPC function. Should be 
00159     * sent back to the caller over the serial connection. 
00160     */ 
00161     static bool call(char *input, char *output);
00162 
00163     /* Function lookup
00164      *  Lookup and return the object that has the given name.
00165      *
00166      * Variables
00167      *  name - the name to lookup.
00168      */
00169     static RPC *lookup(const char *name);
00170     
00171     virtual void run(char *arguments, char *result);
00172 
00173 protected:
00174     static RPC *_head;
00175     RPC *_next;
00176     char *_name;
00177 
00178 };
00179 
00180 } // namespace physcom
00181 
00182 #endif