RPCVariable is not a template

10 Apr 2011

RPCVariable is not a template (E864) ???????

What am I doing wrong or is RPCVariable not working at all? Please have a look at my compiler output.

/media/uploads/microfreak/bildschirmfoto_2011-04-10_um_11.08.15.jpg

10 Apr 2011

Okay thanks a lot i'll answer my question myself. I had to #include "SerialRPCInterface.h". So does this means that RPCVariable is rubbish when you want to use it within a HTTP environment ???????

Any comments like before are welcome.

10 Apr 2011

Hi

RPCVariables will work over http.

To use RPCVariable you don't need to include SerialRPCInterface.h but you do need to include "RPCVariable.h". (You need to make sure you are using the newest version of the Library as there was a bug which meant that you did have to include the SerialRPCInterface header to use RPCVariable but that was fixed ages ago.)

Using RPCVariables by including SerialRPCInterface.h rather than RPCVariable.h doesn't mean that they won't work with HTTP, it just means that you've also defined the SerialRPCInterface Class as the SerialRPCInterface.h file includes RPCVariable.h for you. However unless you create an instance of SerialRPCInterface eg with the line

SerialRPCInterface SerialInterface(USBTX, USBRX);

Then it won't do anything over serial and RPCVariables will work over http.

Incidently you could even set it up so RPC commands were received over both serial and HTTP, you'd need to set up the mbed with both the HTTP server and looking for RPC commands over serial.

The RPCVariables (and any other objects controlled using RPC) are completely independant to the method of exchanging the RPC commands, they register with the RPC functionality defined in the mbed libraries. The HTTPServer and the SerialRPCInterface class both just provide different methods of passing the string of rpc commands into the rpc function and returning the response.

The absolute simplest way of doing this with a serial port is shown on the Interfacing Using RPC page, its just:

while(1){
     pc.gets(buf, 256);
     rpc(buf, outbuf); 
     pc.printf("%s\n", outbuf);
}

The SerialRPCInterface class does the above but using the serial interrupt rather than a while loop.

So in summary RPCVariables (and RPCFunctions) will work over HTTP, you can either include "SerialRPCInterface.h" or "RPCVariable.h"

Hope this helps.

Michael

10 Apr 2011

Thanks Michael for your really quick help. As a expert could you give me a short sample of how to create such a RPC call "http://mbedipaddress/rpc/myrpc/t1,21,2,55"

10 Apr 2011

Hi

Not quite sure what you mean by create such an RPC call, do you mean how would create an object and method that could be called by the command /myrpc/t1,21,2,55 If so look here

Or do you mean how would you communicate with an RPCVariable ie the url to write and read would be

http://<mbed ip address>/rpc/temperature_h/write,0.5
http://<mbed ip address/rpc/temperature_h/read

Which do you mean, create your own custom rpc class (that you've called myrpc above with method t1) or call an RPCVariable. If its creating your own custom class then you really need to start with the class definition as you can then add RPC to that.

10 Apr 2011

Hi

simply spoken i just would like to pass three Arguments to set a clock using RPC instead of calling

http://<mbed ip address>/rpc/hours_h/write,22
http://<mbed ip address>/rpc/minutes_h/write,05
http://<mbed ip address>/rpc/seconds_h/write,06

My idea is something like this

http://<mbed ip address>/rpc/time_h/22,05,06

Is that possible?

10 Apr 2011

Yes that is possible, there are roughly two ways you can do it

  • Create a class with a method that takes 3 arguments which it uses to set the clock, you can then add RPC to it, following the instructions in the link I gave above. This would be a good neat method if there were several methods you wanted to be able to call either to do with the time or your project as a whole. However it will take longer to set up.
  • Use an RPCFunction. This is probably the quickest to set up. Essentially you would pass the information as a string from which you could format out the information and use it to set the time. It would work something like this:

#include "RPCFunction.h"
void setTime(char * input, char * output);
RPCFunction rpc_setTime(&setTime, "setTime");

void setTime(char * input, char * output){
   int hours,mins,secs;
   sscanf(input, "%i,%i,%i", &hours, &mins, &secs);

   //Use the hours, mins, secs variables to set the time here

   sprintf(ouput, "Anything you want to output here - you don't really need it");
}

int main.....

In this case the url would be

http://<mbed ip address>/rpc/setTime/run 22,05,06

Note that the RPCFunction doesn't detect commas etc as argument seperators, it takes everything after the method name as a single char argument so you can then decide what delimits different arguments.

Also http://<mbed ip address>/rpc/time_h/22,05,06 is not exactly possible as you haven't specified a method name it needs to be http://<mbed ip address>/rpc/time_h/set 22,05,06 where set is the name of the method if you created a class and time_h was the name given to an instance of the class. When you use RPCFunctions or RPCVariables then you actually call the run/read/write methods of those classes.

If you want to follow the first option then make it work as a class first without any RPC. For the second I generally find it easier and quicker to test and develop things like this using rpc over serial as you don't need to worry about connecting to the network each time you want to test a new program.

10 Apr 2011

Another point. I'm not sure exactly what your program is doing but are you trying to set the mbed rtc or are you programming your own clock or just displaying times.

Your commands:

http://<mbed ip address>/rpc/hours_h/write,22
http://<mbed ip address>/rpc/minutes_h/write,05
http://<mbed ip address>/rpc/seconds_h/write,06

just changes the values of those variables in memory and so, depending on how you're implementing your project, may need to be followed by another command to trigger the transfer of those variables into the clock (eg the mbed rtc). Unless you've written a clock of your own where those variables are the actual variables that are incremented by the clock or there is someother trigger to actually set the clock.

This could for example be an RPCFunction in which case the commands would become something like:

http://<mbed ip address>/rpc/hours_h/write,22
http://<mbed ip address>/rpc/minutes_h/write,05
http://<mbed ip address>/rpc/seconds_h/write,06
http://<mbed ip address>/rpc/set_the_time/run

In which case you'd definatly be better off using one of the methods of both transferring the data and triggering the functionality to load that data into the clock in one rpc command. The point here is that RPCVariables just change the value of the variables whereas either using RPCFunctions or a custom class allows you to both change variables and trigger some functions to do something with those new values

Hope this helps

Michael

10 Apr 2011

Thanks Michael

it is already too late for me to try your suggestions. I will give it a try tomorrow.

Once again thanks a lot.

voy

11 Apr 2011

Hi

I just implemented your code to set my clock system via RPC. It works perfect. Thanks again.

Used code:

#include "RPCFunction.h"
void setTime(char * input, char * output);
RPCFunction rpc_setTime(&setTime, "setTime");

void sTime2(char * input, char * output){
   int m2hr,m2mn,m2se;
   sscanf(input, "%i,%i,%i", &m2hr, &m2mn, &m2se);

   sprintf(output, "Time 2 set to: %.2i:%.2i:%.2i\n", m2hr, m2mn, m2se);
}

As you are the RPC expert could you give me the next advice how to solve this problem.

I want to output the values of some variables but only the last one is displayed.

#include "RPCFunction.h"
void getSvalues(char * input, char * Output);
RPCFunction GetSvalues(&getSvalues, "gSvalues");

void getSvalues(char *input, char * Output){
    float s1 = 23;
    float s2 = 75;
    float s3 = 30;
    float s4 = 23;
    
    sprintf(Output, "s1: %f \n", s1);
    sprintf(Output, "s2: %f \n", s2);
    sprintf(Output, "s3: %f \n", s3);
    sprintf(Output, "s4: %f \n", s4);

}

No chance to use sprintf for several times ? I am not really big in C++.

11 Apr 2011

Hi

The Output variable that you're writing the variables into works a bit like the return value of a function. Only its implemented differently for various reasons.

So writing a value to Output doesn't mean that its written back out. Rather the value in Output when the function ends or returns is written back as the result. It's as though the last line of the function is "Return(Output);"

sprintf just writes the formatted data to a string, it doesn't transmit the data (unlike printf which writes formatted data to the standard output).

So in your code you keep changing the value in Output, and the value in Output at the end, s4 is the only one which is returned over RPC

You need the code to be like this:

sprintf(Output, "s1: %f, s2: %f, s3: %f s4: %f \n", s1, s2, s2, s4);

This site is a good reference for things like printf and sprintf

http://www.cplusplus.com/reference/clibrary/cstdio/printf/

http://www.cplusplus.com/reference/clibrary/cstdio/sprintf/

You might be wondering how it is that we are able to write the answer back out via an argument that we passed in, ie ouput is one of the parameters. This is because although I've said sprintf(Output... writes to Output this isn't strictly true. Char * Output isn't a string type variable but actually a pointer to a char array. When the RPCFunction run method calls your getSvalues function it passes the location of a char array in Output, sprintf then puts the result into the char array at the location given by Output.

Michael

11 Apr 2011

Ok I understand. But I need to output the variables in four lines and not in one as your example shows. Will it be ok to to fill the char array output with the desired characters to achieve a result? Like 23\n output[1]=32,output[2]=33,output[1]=10,output[1]=13 and so on.

voy

11 Apr 2011

You can only output one string but you can format it in any way you like, so you should be fine to include line breaks. Would this work for you:

sprintf(Output, "s1: %f\n s2: %f \n s3: %f\n s4: %f \n", s1, s2, s2, s4);
//Or this would be fine
sprintf(Output, "output[1]=%f,output[2]=%f,output[3]=%f,output[4]=%f\n", s1, s2, s2, s4);

You can use any characters within the char array, sprintf will just replace the %'s with the variable values. You may need to write code of some sort at the receiving end to extract your variables. You may not be able to format it exactly as you need it to be displayed. If trying to transfer different numeric values this way then I'd often delimit them using say commas and on the receiving end do the equivalent of sscanf in the language you are using to extract the values again.

RPCFunction is just a way of passing a string into a function and getting the response in a string . You can put whatever you want in the string. However, there is a limit of 64 characters, though you can easily edit the library in your program to increase this.

12 Apr 2011

Sorry but this doesn't work.

sprintf(Output, "s1: %f\n s2: %f \n s3: %f\n s4: %f \n", s1, s2, s3, s4);

The output is still like:

s1: 23 s2: 75 s3: 30 s4: 23

I would like to have:

s1: 23
s2: 75
s3: 30
s4: 23

voy

12 Apr 2011

What are you observing the output in, is that the output at a terminal such as teraterm, make sure that under new line receive is set to LF. Why do you need the output to be delimited by a new line and not by any other character.

12 Apr 2011

i am not using any terminal programm, i am calling mbed from IE8 using http://mbed_ip_address/rpc/gSensor/run

12 Apr 2011

Ah Okay. I've not tried it but does this work

sprintf(Output, "s1: %f<br> s2: %f<br> s3: %f<br> s4: %f", s1, s2, s3, s4);

If this doesn't work then I suggest you serve a html page from mbed which uses the JavaScript library to execute the RPCFunction. Then you can use JavaScript to format the values out of the string and display them on individual lines. You could also do things like make it so that the values are refreshed without reloading the page.

12 Apr 2011

Seems to work, but the programm hangs sometime after executing the gSensor/run command. How big is the output array and can it, or must it be increased?

12 Apr 2011

Great, you could include any html in the output string to make it look however you want. However, if you now use it with a terminal then "<br>" commands will be printed in the output.

The output (and input) array is 64 characters, and can easily be increased, just write click on the library in the compiler in your program and click edit. You'd need to change this line.

Make sure you are using the latest revision of the library as there was a problem if you ran many (many) times.

Import libraryRPCInterface

Library to provide a mechanism to make it easier to add RPC to custom code by using RPCFunction and RPCVariable objects. Also includes a class to receive and process RPC over serial.

Otherwise I wouldn't really expect it to hang so if it appears to do it quite often then you'd need to try and determine why. You could check how well the http server is serving web pages over the network or how well your RPCFunction works when used over serial, to try narrow it down.

Hope the rest of your project is successful

Michael

12 Apr 2011

Thanks for your help Michael. I'll go thru it and come back in a few days.

voy