I have problem showing a float variable in an Arduino webserver - c

I am using Arduino Uno, ENC28j60. using rbbb_server example.
the library I am using: <EtherCard.h>
as can be seen in the code below I am trying to convert my Float var to Str using dtostrf() in the homepage function since emit_p() can not accept float vars. although Serial.println(temp1) is working correctly, but in the browser, I have a problem showing the variable(pic added). I've been looking for a solution but couldn't find any, unfortunately. would appreciate any suggestion.
#include <EtherCard.h>
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
static byte myip[] = { 192,168,1,203 };
byte Ethernet::buffer[500];
BufferFiller bfill;
static word homePage() {
String temp1;
float val = 311.322;
char s1[10];
temp1 = dtostrf(val,3,2,s1);
bfill = ether.tcpOffset();
bfill.emit_p(PSTR(
"HTTP/1.0 200 OK\r\n"
"Content-Type: text/html\r\n"
"Pragma: no-cache\r\n"
"\r\n"
"<meta http-equiv='refresh' content='1'/>"
"<title>RBBB server</title>"
"<h1>my val:$S</h1>"),
temp1);
Serial.println(temp1);
return bfill.position();
}
void setup () {
Serial.begin(57600);
if (ether.begin(sizeof Ethernet::buffer, mymac, SS) == 0)
Serial.println(F("Failed to access Ethernet controller"));
ether.staticSetup(myip);
}
void loop () {
word len = ether.packetReceive();
word pos = ether.packetLoop(len);
if (pos)
ether.httpServerReply(homePage());
}
output in browser

I think I see your problem, but I can't test it.
dtostrf returns a char * pointer to the string you want to print here's the docs
It looks like that function is being called and assigning that string to the temp variable which is a String type (idk your experience, but working with text in Arduino can be very confusing check out this thread ).
Try changing temp1 to be a char * like this:
char * temp1;

Related

Using function inside a call back in different function

I'm working on USB CDC on ATSAMD21. The code which i'm using is ATMEL START example for USB CD Echo on D21. I'm working on atmel studio.
Requirement:
In my application the host send data to the device and i need to read that data and send back different data to the host from different function.
Here in echo example the data reception and transfer is using the call back. I'm not aware how to use a write call inside another function. Here i'm attaching the code below
Read & Echo the data:
Here in this function it is for read the data and echo it back to the host.
static bool usb_device_cb_state_c(usb_cdc_control_signal_t state)
{
if (state.rs232.DTR ) {
/* Callbacks must be registered after endpoint allocation */
cdcdf_acm_register_callback(CDCDF_ACM_CB_READ, (FUNC_PTR)usb_device_cb_bulk_out);
cdcdf_acm_register_callback(CDCDF_ACM_CB_WRITE, (FUNC_PTR)usb_device_cb_bulk_in);
/* Start Rx */
cdcdf_acm_read((uint8_t *)usbd_cdc_buffer, sizeof(usbd_cdc_buffer));
}
/* No error. */
return false;
}
/////////////////////////////////////
Read the data from host:
static bool usb_device_cb_bulk_out(const uint8_t ep, const enum
usb_xfer_code rc, const uint32_t count)
{
cdcdf_acm_write((uint8_t *)usbd_cdc_buffer, count);
return false;
}
Write back the data:
static bool usb_device_cb_bulk_in(const uint8_t ep, const enum usb_xfer_code rc, const uint32_t count)
{
/* Echo data. */
cdcdf_acm_read((uint8_t *)usbd_cdc_buffer, sizeof(usbd_cdc_buffer));
/* No error. */
return false;
}
I need to use this read call inside another function outside. I used the read call directly in another function, it was not able to send the data.
How can i make this call use in another function.Any help will be appreciated.
Here the callback will direct to the read and write functions.
This is a fun one!
From the main loop, using a stack allocated char buffer:
const char hello[] = "Hi There!\r\n";
cdcdf_acm_write((void*)hello, 11);
works for me, but curiously using a pointer to a string constant:
const char* hello = "Hi There!\r\n";
cdcdf_acm_write((void*)hello, 11);
does not output anything! Similarly, a static const buffer
const char hello[] = "Hi There!\r\n";
int main(void)
{
// init ...
while (1)
{
delay_ms(200);
cdcdf_acm_write((void*)hello, 11);
}
}
doesn't work either, but a non-const static buffer:
char hello[] = "Hi There!\r\n";
int main(void)
{
// init ...
while (1)
{
delay_ms(200);
cdcdf_acm_write((void*)hello, 11);
}
}
does!
My hypothesis is that cdcdf_acm_write() has a problem somewhere in the USB stack that cannot read data straight from flash, which seems like a very unexpected pitfall, especially as outputting a string constant is probably the first thing one does while implementing the communication functionality!

Parse C char array sent via web server into (JSON or JavaScript) variables

Desired outcome: Send a struct of GPS data from C using a web server and have the data ( lat, long, etc.) display on a web page.
Using: Linux, libwebsockets (LWS) library for web server. C code is implemented as a standalone plugin in the LWSWS (web server) app.
Current understanding/work on project: Casting struct from plugin to a char array and trying to parse the array (using JSON) into the individual members of the original struct. Then display each variable on a web page.
I am new to Linux, LWS, HTML, JavaScript, and JSON. I can use JSON or Javascript to work with the variables, whichever makes more sense. I am not completely sure of my plan on either side (C/JS) of this part of the project.
What is the best way to transfer this information and convert for use on the web page?
Here is my struct:
struct per_session_data__gps_rcvr {
struct time_struct{
int month;
int day;
int year;
int hour;
int minute;
double second;
}time;
double latitude;
char lat_indicator;
double longitude;
char lon_indicator;
double heading;
int quality;
int satellites;
};
Sending struct out, cast to a char pointer:
// Write GPS data to GUI
n = lws_snprintf( (char *)p, sizeof(buf) - LWS_PRE, "%s", (char *)pss );
m = lws_write(wsi, p, n, LWS_WRITE_TEXT);
if (m < n) {
lwsl_err("ERROR %d writing to di socket\n", n);
return -1;
}
break;
The test code I am modifying appears to receive data in a variable called "msg". I am assuming I need to parse the data sent in the char array into chunks that correspond to the members of the original struct. Then I can display each piece of GPS data on the web page.
var socket_gps;
if (use_lws_meta)
socket_gps = lws_meta.new_ws("", "gps-rcvr-protocol");
else
socket_gps = new_ws(get_appropriate_ws_url(""), "gps-rcvr-protocol");
try {
socket_gps.onopen = function() {
document.getElementById("wsdi_statustd").style.backgroundColor = "#40ff40";
document.getElementById("wsdi_status").innerHTML =
" <b>websocket connection opened</b><br>" +
san(socket_gps.extensions);
}
socket_gps.onmessage =function got_packet(msg) {
document.getElementById(" **VARIABLE GOES HERE** ").textContent = msg.data + "\n";
}
socket_gps.onclose = function(){
document.getElementById("wsdi_statustd").style.backgroundColor = "#ff4040";
document.getElementById("wsdi_status").textContent = " websocket connection CLOSED ";
}
}
catch(exception) {
alert('<p>Error' + exception);
}
Please let me know if there is a better way to send the data out from C, and/or if I have correctly configured the data. In my research, it was mentioned that data could be sent as binary, but sending plain text messages and using JSON seemed like a better plan.
It looks like JSON can "stringify" info, but only if it's typed in or in JavaScript format already? I'm not sure. I have not seen any way to parse out a char array, a set number of characters at a time, and save those segments as variables on the HTML side. That is what I was hoping for.
Thank you for your suggestions!
Like this:
n = snprintf( (char *)p, sizeof(buf), "{\"NameofParam1\":\"%d\",\"NameofParam2\":\"%d\"}", param1, param2 );
That gives you your whole JSON string in one go (stored in buffer). Just use the appropriate flag (%s, %X, %c, %f, etc.) to capture your parameter.

Is my method of passing a struct as both value and reference correct?

I have looked at the examples of passing a struct by both value and reference. My code compiles but is not working as it should. I am using C to program a micro-controller so it is hard to check if it is working properly, but I am not getting the desired output.
So, as per instructions, I first define my structure:
struct package //define a structure type called package.
{
unsigned char
wavType,startFreq1,startFreq2,startFreq3,startFreq4,
stopFreq1,stopFreq2,
stopFreq3,stopFreq4,step,dura,amp,sett; //define bytes to use
};
In the main method I create an instance of it:
struct package p; //create a new instance of Package
Now I pass it by reference (pointer - because I'm using C) to a function:
getPackage(&p);
Within the function getpackage() I update the values of the respective elements of p:
getPackage(struct package *p) //Get data package
{
p->wavType = receive();
p->startFreq1 = receive();
p->startFreq2 = receive();
p->startFreq3 = receive();
p->startFreq4 = receive();
p->stopFreq1 = receive();
p->stopFreq2 = receive();
p->stopFreq3 = receive();
p->stopFreq4 = receive();
p->step = receive();
p->dura = receive();
p->amp = receive();
p->sett = receive();
}
This is the receive function:
unsigned char receive(void)
{
unsigned char dataR = 0x00;
for(signed char i = 0; i <=7 ;i++)
{
dataR |= PORTBbits.RB1 << i; //move the value on the data pin to a bit in dataR
}
return dataR;
}
QUESTION: Will this correctly update the bytes in the package p? Also, does package p need to be returned if I want to use it elsewhere? I ask this because....
I now pass the package p, by value, into another function using:
sendSine(p);
This function makes use of the value of the bytes in the package p:
void sendSine(struct package p)
{
dataL = p.startFreq1;
dataH = p.startFreq2;
send(dataL,dataH);
dataL = p.startFreq3;
dataH = p.startFreq4;
send(dataL,dataH);
}
I know the function send(dataL,dataH) is working because I have tested it by setting dataL and dataH by hand and I get the required result, so there must be an error along the way with the struct - I just cant figure out where... Can anyone help me with were it might be?
The receive function seems to be the procedure in question. Try writing a stub-replacement for receive, such as:
unsigned char receive(void)
{
unsigned char X = 'a';
// or whatever value you want to simulate as being received
return X;
}
and then try running your complete application, tf it works then go back and re-think your original receive per some of the comments that have already been made.

Why is it evbuffer_add_printf will only accept static variables and not "dynamic" ones?

So far I have gotten my libev code to successfully return a static sting that says "OMP OMP", however when I write a function that returns a "static" string it never seems to work. (Sidenote: the idea is to turn that same function into a dynamic response but just for agile testing purposes I need this to work first). My code for the libev read callback is as the following...
void p2pserver_network_buf_read_callback(struct bufferevent *incoming, void *arg){
//Define function local variables
struct evbuffer *evreturn;
char *req;
//Begin function local logic
req = evbuffer_readline(incoming->input);
if (req == NULL){
return;
}
char *response;
parse_json_command(req, response);
//response = "OMP OMP";
g_print("PARSED");
evreturn = evbuffer_new();
evbuffer_add_printf(evreturn, "%s", response);
bufferevent_write_buffer(incoming,evreturn);
evbuffer_free(evreturn);
free(req);
g_print("%s", response);
}
The parse_json_command function is as the following...
void parse_json_command(char json_command, char *response){
//Define Local Variables
g_print("PARSING");
response = "YOU KNOW";
//Print out the recieved message....
//g_message("%s", json_command);
/**
* TODO: check if the JSON is valid before parsing
* to prevent "Segmentation Defaults"
* and its good sanity checks.
**/
//Parse JSON incomming
/*json_object * jobj = json_tokener_parse(json_command);
enum json_type type;
json_object_object_foreach(jobj, key, val){
g_print("%s\n", key);
if(g_utf8_collate(key, "cmd") >= 0){
//Looks like the user has sent a "cmd" (command), lets analyze the "val" (value) of that command to see what the caller/client needs to be attending to...
//Is the client requesting an "Identity Update" (Pings server: if this is the first time ping, the server and client will exachange keys if the relationship exists the server just accepts the encrypted "ping" packet update)
type = json_object_get_type(val);
if(type == json_type_string){
char* cmd_value;
cmd_value = json_object_get_string(val);
//g_print("VALUE:%d\n", g_utf8_collate(cmd_value, "identupdate"));
if(g_utf8_collate(cmd_value, "identupdate") == 0){
//Call "Identity Update Response"
//char return_response = p2pserver_json_identupdate_response(json_command);
}
}
}
}
*/
return;
}
If you want to see the complete code (only a couple of pages big at the time of this writing) you can go to the source code at the following link: https://github.com/Xenland/P2PCrypt-Server
Thanks for your time and help!
c passes arguments by value, not by reference. You problem is here:
void parse_json_command(char json_command, char *response){
[...]
response = "YOU KNOW";
[...]
}
char *response;
parse_json_command(req, response);
response is a uninitialized pointer to a string. You are assigning a pointer to a static string to the response pointer in the function, but that does not modify response outside of the function, it just changes response within the function. There are different ways to fix this. Probably the easiest one for a quick fix would be to change the function's prototype to return a char * instead of void:
char * parse_json_command(char json_command){
char *response;
[...]
response = "YOU KNOW";
[...]
return response;
}
char *response;
response = parse_json_command(req);
Also, the json_command argument should probably be a char * or const char *, not just a single char, if you want to pass more than a single byte there.

Splitting a comma-delimited string of integers

My background is not in C (it's in Real Studio - similar to VB) and I'm really struggling to split a comma-delimited string since I'm not used to low-level string handling.
I'm sending strings to an Arduino over serial. These strings are commands in a certain format. For instance:
#20,2000,5!
#10,423,0!
'#' is the header indicating a new command and '!' is the terminating footer marking the end of a command. The first integer after '#' is the command id and the remaining integers are data (the number of integers passed as data may be anywhere from 0 - 10 integers).
I've written a sketch that gets the command (stripped of the '#' and '!') and calls a function called handleCommand() when there is a command to handle. The problem is, I really don't know how to split this command up to handle it!
Here's the sketch code:
String command; // a string to hold the incoming command
boolean commandReceived = false; // whether the command has been received in full
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
// main loop
handleCommand();
}
void serialEvent(){
while (Serial.available()) {
// all we do is construct the incoming command to be handled in the main loop
// get the incoming byte from the serial stream
char incomingByte = (char)Serial.read();
if (incomingByte == '!')
{
// marks the end of a command
commandReceived = true;
return;
}
else if (incomingByte == '#')
{
// marks the start of a new command
command = "";
commandReceived = false;
return;
}
else
{
command += incomingByte;
return;
}
}
}
void handleCommand() {
if (!commandReceived) return; // no command to handle
// variables to hold the command id and the command data
int id;
int data[9];
// NOT SURE WHAT TO DO HERE!!
// flag that we've handled the command
commandReceived = false;
}
Say my PC sends the Arduino the string "#20,2000,5!". My sketch ends up with a String variable (called command) that contains "20,2000,5" and the commandRecieved boolean variable is set to True so the handleCommand() function is called.
What I would like to do in the (currently useless) handleCommand() function is assign 20 to a variable called id and 2000 and 5 to an array of integers called data, i.e: data[0] = 2000, data[1] = 5, etc.
I've read about strtok() and atoi() but frankly I just can't get my head around them and the concept of pointers. I'm sure my Arduino sketch could be optimised too.
Since you're using the Arduino core String type, strtok and other string.h functions aren't appropriate. Note that you can change your code to use standard C null-terminated strings instead, but using Arduino String will let you do this without using pointers.
The String type gives you indexOf and substring.
Assuming a String with the # and ! stripped off, finding your command and arguments would look something like this:
// given: String command
int data[MAX_ARGS];
int numArgs = 0;
int beginIdx = 0;
int idx = command.indexOf(",");
String arg;
char charBuffer[16];
while (idx != -1)
{
arg = command.substring(beginIdx, idx);
arg.toCharArray(charBuffer, 16);
// add error handling for atoi:
data[numArgs++] = atoi(charBuffer);
beginIdx = idx + 1;
idx = command.indexOf(",", beginIdx);
}
data[numArgs++] = command.substring(beginIdx);
This will give you your entire command in the data array, including the command number at data[0], while you've specified that only the args should be in data. But the necessary changes are minor.
seems to work, could be buggy:
#include<stdio.h>
#include <string.h>
int main(){
char string[]="20,2000,5";
int a,b,c;
sscanf(string,"%i,%i,%i",&a,&b,&c);
printf("%i %i %i\n",a,b,c);
a=b=c=0;
a=atoi(strtok(string,","));
b=atoi(strtok(0,","));
c=atoi(strtok(0,","));
printf("%i %i %i\n",a,b,c);
return 0;
}

Resources