When reading a JSON string from the serial port on an ESP8266 it cuts off the beginning of the data.
I have tried reading data from the Serial port and printing each character, however it is cutting off part of the begging of the data.
void setup() {
Serial.begin(115200);
while (!Serial) {
;
}
}
void loop() {
int curSize = 30;
char* buffer = new char[curSize];
std::fill_n(buffer, curSize, 0);
int pos = 0;
Serial.print("Sending: ");
while(Serial.available() == false) delay(500);
while (Serial.available()) {
char c = Serial.read();
Serial.print(c);
if(pos == curSize-1){
char* newBuffer = increaseBuffer(buffer, curSize, curSize + 30);
curSize += 30;
delete[] buffer;
buffer = newBuffer;
}
if(c == '\n'){
buffer[pos] = 0;
pos = 0;
break;
}
buffer[pos++] = c;
}
if(buffer[0] != 0) {
sendBuffer(buffer);
}
delete[] buffer;
}
char* increaseBuffer(char* orig, int oldSize, int newSize){
char* data = new char[newSize];
std::fill_n(data, newSize, 0);
for(int i = 0; i < newSize; i++){
if(i < oldSize) data[i] = orig[i];
else data[i] = '\0';
}
return data;
}
JSON data used (and expected output)
{"type":0,"ver":"0.0.1","T":[28,29,29,29,29,29,29,29,29,29],"H":[59.1608,59.1608,60,59.1608,60,60,60,59.1608,59.1608,59.1608],"DP":[20.36254,20.36254,20.59363,20.36254,20.59363,20.59363,20.59363,20.36254,20.36254],"HI":[30.90588,30.90588,31.0335,30.90588,31.0335,31.0335,31.0335,30.90588,30.90588]}
examples of what is actually output
Example 1: 9,29,29,29,29,29,29,29,29],"H":[59.1608,59.1608,60,59.1608,60,60,60,59.1608,59.1608,59.1608],"DP":[20.36254,20.36254,20.59363,20.36254,20.59363,20.59363,20.59363,20.36254,20.36254],"HI":[30.90588,30.90588,31.0335,30.90588,31.0335,31.0335,31.0335,30.90588,30.90588]}
Example 2: 29,29,29,29,29,29,29,29,29],"H":[59.1608,59.1608,60,59.1608,60,60,60,59.1608,59.1608,59.1608],"DP":[20.36254,20.36254,20.59363,20.36254,20.59363,20.59363,20.59363,20.36254,20.36254],"HI":[30.90588,30.90588,31.0335,30.90588,31.0335,31.0335,31.0335,30.90588,30.90588]}
Try making the delay 1 instead of 500 in the blocking loop that's waiting for data to start coming in. I'm going to guess what happens is that on one iteration of that loop Serial.available() is false and during the delay you start to get data coming in that ends up getting written over by the time your delay ends to check again.
What I'm picturing is the following. If you were to expand out that delay(500) to be delay(1) called 500 times.
while(Serial.available() == false){
delay(1);
delay(1);
// ...
delay(1); // first character comes in
delay(1);
delay(1); // second character comes in
// ...
delay(1); // n character comes in
}
Then after the delay is over you start actually collecting the characters that are coming in.
Related
I'm trying to create a full HTML result with HTTP headers with the correct size for content-length as simple as possible.
I looked at setbuf() function but it only works with streams, but I want to directly buffer the output to memory without having a disk involved. Is there a simpler function that does what I'm trying to achieve?
I know in php, one can use ob_start() to start buffering data and ob_get_contents() to load the data in memory and determine the size so is there anything like this in C that I can use?
int main(){
char *mybuf=malloc(1048576); //Allocate 1MB memory for buffer
char *mytitle="Webpage title";
char *mydesc="This is a page version";
int myver=2;
//print HTTP header of known data
printf("HTTP/1.1 200 OK\r\n");
printf("Server: Something\r\n");
printf("Content-type: text/html; charset=UTF-8\r\n");
printf("Cache-control: no-cache\r\n");
//Buffer HTML output to get size (we don't print these 4 lines yet)
sprintf(mybuf,"<html><head><title>%s</title></head><body>\r\n",mytitle);
sprintf(mybuf+strlen(mybuf),"<h1>%s</h1>\r\n",mytitle);
sprintf(mybuf+strlen(mybuf),"<p>%s %d</p>\r\n",mydesc,myver);
sprintf(mybuf+strlen(mybuf),"</body></html>\r\n");
//Print content length header with size of buffered data
printf("Content-length: %d\r\n",strlen(mybuf));
//then print the rest of the data
printf("%s",mybuf);
free(mybuf);
return 0;
}
The C language specification does not define any facility for streams backed only by memory, without any underlying file. Your sprintf() based approach is not bad, but it could be improved by capturing and using the return value, which tells you how many characters were printed. You could use this to avoid all the strlen() calls, which could be a considerable savings if the content is large, especially if it is printed in many small pieces:
size_t total_bytes_written = 0;
long rval;
rval = sprintf(mybuf, "<html><head><title>%s</title></head><body>\r\n", mytitle);
if (rval < 0) {
// handle error ...
}
total_bytes_written += rval;
rval = sprintf(mybuf + total_bytes_written, "<h1>%s</h1>\r\n", mytitle);
// ...
Alternatively, if you are on a system that conforms to POSIX.1-2008 or later, and you are willing to limit your program to such systems, then you might find open_memstream() of interest. This gives you a stream backed by a dynamically managed block of memory. You would write to it with fprintf() or other stream IO functions, and when done, read back a pointer to the data and the total size. Something like this:
char *buf_ptr = NULL;
size_t buf_size = 0;
FILE *mem = open_memstream(&buf_ptr, &buf_size);
fprintf(mem, "<html><head><title>%s</title></head><body>\r\n", mytitle);
fprintf(mem, "<h1>%s</h1>\r\n", mytitle);
// ...
fclose(mem); // mandatory
printf("Content-length: %d\r\n", buf_size);
printf("%s", buf_ptr); // the data are guaranteed null-terminated
free(buf); // you are responsible for this
(All error checks omitted for brevity.)
This relieves you of the manual size tracking, and it gains you a dynamically-growing backing buffer so that you can handle both large and small outputs with reasonable memory efficiency.
There are multiple solutions to this problem:
your approach is OK, but you should use snprintf() to avoid potential buffer overflows:
int main() {
char *mybuf = malloc(1048576); //Allocate 1MB memory for buffer
const char *mytitle = "Webpage title";
const char *mydesc = "This is a page version";
int myver = 2;
size_t pos = 0;
//print HTTP header of known data
printf("HTTP/1.1 200 OK\r\n");
printf("Server: Something\r\n");
printf("Content-type: text/html; charset=UTF-8\r\n");
printf("Cache-control: no-cache\r\n");
//Buffer HTML output to get size (we don't print these 4 lines yet)
pos += snprintf(mybuf + pos, pos < sizeof mybuf ? sizeof mybuf - pos : 0,
"<html><head><title>%s</title></head><body>\r\n", mytitle);
pos += snprintf(mybuf + pos, pos < sizeof mybuf ? sizeof mybuf - pos : 0,
"<h1>%s</h1>\r\n", mytitle);
pos += snprintf(mybuf + pos, pos < sizeof mybuf ? sizeof mybuf - pos : 0,
"<p>%s %d</p>\r\n", mydesc, myver);
pos += snprintf(mybuf + pos, pos < sizeof mybuf ? sizeof mybuf - pos : 0,
"</body></html>\r\n");
//Print content length header with size of buffered data
printf("Content-length: %zu\r\n", pos);
printf("\r\n");
//then print the rest of the data
printf("%s", mybuf);
free(mybuf);
return 0;
}
Here is a simpler one, combining the calls and using snprintf to compute the length:
int main() {
const char *mytitle = "Webpage title";
const char *mydesc = "This is a page version";
int myver = 2;
size_t length = 0;
//print HTTP header of known data
printf("HTTP/1.1 200 OK\r\n");
printf("Server: Something\r\n");
printf("Content-type: text/html; charset=UTF-8\r\n");
printf("Cache-control: no-cache\r\n");
//Buffer HTML output to get size (we don't print these 4 lines yet)
length = snprintf(NULL, 0,
"<html><head><title>%s</title></head><body>\r\n"
"<h1>%s</h1>\r\n"
"<p>%s %d</p>\r\n"
"</body></html>\r\n",
mytitle, mytitle, mydesc, myver);
//Print content length header with size of buffered data
printf("Content-length: %zu\r\n", length);
printf("\r\n");
//then print the rest of the data
printf("<html><head><title>%s</title></head><body>\r\n"
"<h1>%s</h1>\r\n"
"<p>%s %d</p>\r\n"
"</body></html>\r\n",
mytitle, mytitle, mydesc, myver);
return 0;
}
you could use open_memstream() as explained by John Bollinger:
int main() {
const char *mytitle = "Webpage title";
const char *mydesc = "This is a page version";
int myver = 2;
size_t length = 0;
char *buf_ptr = NULL;
size_t buf_size = 0; // the buffer size
int length = 0; // the length of the output
FILE *mem = open_memstream(&buf_ptr, &buf_size);
//print HTTP header of known data
printf("HTTP/1.1 200 OK\r\n");
printf("Server: Something\r\n");
printf("Content-type: text/html; charset=UTF-8\r\n");
printf("Cache-control: no-cache\r\n");
//Buffer HTML output to get size (we don't print these 4 lines yet)
if (mem == NULL) {
// Deal with the error
printf("Internal error\r\n");
return 1;
}
length = fprintf(mem,
"<html><head><title>%s</title></head><body>\r\n"
"<h1>%s</h1>\r\n"
"<p>%s %d</p>\r\n"
"</body></html>\r\n",
mytitle, mytitle, mydesc, myver);
//Print content length header with size of buffered data
printf("Content-length: %zu\r\n", length);
printf("\r\n");
//then print the rest of the data
//beware that buf_ptr is not necessarily null terminated
printf("%.*s", length, buf_ptr);
//could also use fwrite(f, buf_ptr, 1, length, stdout);
free(buf_ptr);
return 0;
}
you can implement your own mem_printf() that allocates or reallocates a memory buffer:
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int mem_printf(char **bufp, size_t *lenp, const char *fmt, ...) {
char buf[1024];
va_list ap;
char *newbuf;
int len;
va_start(ap, fmt);
len = vsnprintf(buf, sizeof buf, fmt, ap);
va_end(ap);
if (len < 0)
return -1;
newbuf = realloc(*bufp, *lenp + len + 1);
if (newbuf == NULL)
return -1;
*bufp = newbuf;
if ((size_t)len < sizeof buf) {
memcpy(newbuf + *lenp, buf, len + 1);
} else {
va_start(ap, fmt);
vsnprintf(newbuf + *lenp, len + 1, fmt, ap);
va_end(ap);
}
*lenp += len;
return len;
}
int main() {
const char *mytitle = "Webpage title";
const char *mydesc = "This is a page version";
int myver = 2;
char *buf_ptr = NULL;
size_t buf_len = 0;
//print HTTP header of known data
printf("HTTP/1.1 200 OK\r\n");
printf("Server: Something\r\n");
printf("Content-type: text/html; charset=UTF-8\r\n");
printf("Cache-control: no-cache\r\n");
//Buffer HTML output to get size (we don't print these 4 lines yet)
mem_printf(&buf_ptr, &buf_len,
"<html><head><title>%s</title></head><body>\r\n"
"<h1>%s</h1>\r\n"
"<p>%s %d</p>\r\n"
"</body></html>\r\n",
mytitle, mytitle, mydesc, myver);
//Print content length header with size of buffered data
printf("Content-length: %zu\r\n", buf_len);
printf("\r\n");
//then print the rest of the data
fputs(buf_ptr, stdout);
free(buf_ptr);
return 0;
}
Content-Length, as you probably know, is the size of your body. This means you have to know at least the length of the body before you can generate the header (or use chunked transfer). sprintf returns the number of bytes written, either accumulate those, or squash it into a single call:
int n = snprintf(mybuf,
mybuf_len,
"<html><head><title>%s</title></head><body>\r\n"
...
"</body></html>\r\n",
mytitle, ..., myver
);
Then generate the header(n) with the n you figured out. If you pass in NULL for instead of mybuf, you get a size without writing anything, then you could do another write a pass in header with the count you got from the first call. If you want, wrap this in a function or two:
int response(const char *header, int body_len, const char body[body_len]) {
...
}
Consider picking a template library (I like the mustache format). It's kinda messy and error prune doing this by hand with raw strings. You have a 1 MB buffer allocated there but use like a .5k, and you will shoot yourself in the foot one day anyhow.
I have a simple RPM Simulator (opensource) that generates values through the tone() function.
I need to send the RPM wirelessly through an nrf24l01 to a second Arduino that uses the RPM as a shiftlight, both come from chippernut.
The tone() function only sends to the pin, trying to read the values did not work.
How can i get the value of x (RPM) after it leaves the tone function?
I have tried reading it through analogRead, digitalRead, BitRead, tried printing the value of x which stays constant, to no avail, and it updates very slowly if it reads the output pin.
This is the code:
float RPM_MIN = 2500;
float RPM_MAX = 8000;
int Accel_Rate = 20;
float pulses_per_rev = 2.0; // make sure to keep the decimal
boolean accel = false;
float x;
long previousMillis = 0;
unsigned long currentMillis=0;
//float RPM_PRINT; //my addition to get a value to print
void setup() {
Serial.begin(57600);
pinMode(5, OUTPUT);
RPM_MIN = (RPM_MIN / 60);
RPM_MAX = (RPM_MAX / 60);
x = RPM_MIN;
}
void loop() {
while (accel==false){
currentMillis = millis();
if(currentMillis - previousMillis > Accel_Rate) {
previousMillis = currentMillis;
x++;
tone(5,x*pulses_per_rev);
if (x>RPM_MAX){accel=true;}
}
}
while (accel==true){
currentMillis = millis();
if(currentMillis - previousMillis > Accel_Rate) {
previousMillis = currentMillis;
x--;
tone(5,x*pulses_per_rev);
if (x<RPM_MIN){accel=false;}
}
}
//RPM_PRINT = x*pulses_per_rev;
//RPM_PRINT = digitalRead(5);
//RPM_PRINT = analogRead(5);
//Serial.println(RPM_PRINT);
}
Expected Result is a Value between 2000-8000 that is constantly changing
actual result is 1/0 or 81,33 or 4,1 or 900-980 updating once every few seconds.
How can I solve?
I'm currently working on a server which is part of my course requirement. The specs require me to parse a request line and store the appropriate data as absolute path (abs_path) and query.
Here is my code:
bool parse(const char* line, char* abs_path, char* query)
{
int space = 0;
if (strchr(line, '"') != NULL)
{
error(400);
return false;
}
for (int i = 0; line[i] != '\0'; i++)
{
if (line[i] == ' ')
{
space++;
}
}
if (space != 2)
{
error(400);
return false;
}
if (strncmp("GET ", line, 4) != 0)
{
error(405);
return false;
}
line = strchr(line, ' ');
line++;
if (strncmp("/", line, 1) != 0)
{
error(501);
return false;
}
int j = 0;
int k = 4;
while (line[k] != ' ')
{
int m = k;
abs_path[j] = line[k];
j++;
if (line[k+1] == '?')
{
abs_path[j] = '\0';
int l = 0;
m = k+2;
while (line[m] != ' ')
{
query[l] = line[m];
l++;
m++;
}
if (line[m] == ' ' && l == 0)
{
query[0] = '\0';
}
}
k = m;
k++;
if (line[k] == ' ')
{
abs_path[j] = '\0';
break;
}
}
char* last = strrchr(line, ' ');
last++;
if (strcmp("HTTP/1.1", last) != 0)
{
error(505);
return false;
}
free(abs_path);
return true;
}
I keep getting a segmentation fault with this. After some debugging, I've found the segmentation fault to be eliminated if I declare, on line 20, abs_path as an array instead of a pointer. However, it is necessary for me to declare abs_path as a pointer, so I need another solution to this. Can someone explain to me what exactly I am doing wrong with regards to strings and their handling?
I have been quite rusty with this due to personal reasons so pardon me if I misunderstand something basic.
Thank you in advance!
You need to allocate memory for the char*. An array does this automatically during compile time. Try malloc.
char* abs_path = 0;
abs_path = (char*)malloc(256);
Essentially, malloc performs an operating system call to reserve sequential memory from the heap. The argument of malloc is how many bytes to reserve. Therefore, you should be aware that the example above enables the abs_path char* to point to a string that is at max 255 characters (leaving 1 byte for the null character '\0'). Don't let your code write more than 255 characters or you will overwrite other data in memory, which is why you received a seg-fault before.
As someone else noted, you should DEFINITELY free up memory reserved dynamically with malloc.
free(abs_path);
I am making a project for school and i need to make a system that keeps the temperature around a set temperature (this is done by a phidget sensor and turning a heating and cooling
element on and off.) the sensors values can be converted to degrees celcius with the formula ((Current Temperature + 50)*4) and i got it working for a stactic 20 degrees celcius, but now i am trying to get a temprature from a database and keep it around that temprature instead(so the temprature can be changed inside the room where the heating and cooling elements are). but when i try to convert the temperature that i got from the database to the sensor value with the formula the temp variable starts giving random numbers and i dont know why. Can someone explain or help?
(See comment toward bottom of code example for problem location)
//my code is a code written for controlling the temprature in a room
//this is done by a phidget sensor and turning a heating and cooling
//element on and of.
#include <phidget21.h> // voor phidgetfucties
#include <stdio.h> // voor printf()
#include <mysql/mysql.h> // voor mysql querys
#include <my_global.h>
int main (int argc, char* argv[])
{ //variables
int val;
int gewensteTempratuur = 280;
int gewensteGradenCelcius = 0;
int i = 0;
int temp = 0;
CPhidgetInterfaceKitHandle ifKit = 0;
CPhidgetInterfaceKit_create(&ifKit);
CPhidget_open((CPhidgetHandle)ifKit,-1);
for(;;)
{
CPhidgetInterfaceKit_getSensorValue(ifKit,0,&val);
printf("Value %d \n", val);
if(val < (gewensteTempratuur - 4)){
//verwarming
CPhidgetInterfaceKit_setOutputState(ifKit,0,1);
//airco
CPhidgetInterfaceKit_setOutputState(ifKit,1,0);
}
if(val > (gewensteTempratuur + 4)){
//verwarming
CPhidgetInterfaceKit_setOutputState(ifKit,0,0);
//airco
CPhidgetInterfaceKit_setOutputState(ifKit,1,1);
}
if((val < (gewensteTempratuur + 4)) && (val > (gewensteTempratuur - 4))) {
//verwarming
CPhidgetInterfaceKit_setOutputState(ifKit,0,0);
//airco
CPhidgetInterfaceKit_setOutputState(ifKit,1,0);
}
//Database Connection
MYSQL *conn;
//Verbings gegevens
char *server = "server";
char *user = "user";
char *password = "pass";
char *database = "database";
conn = mysql_init(NULL);
if (!mysql_real_connect(conn, server,
user, password, database, 0, NULL, 0)) {
fprintf(stderr, "%s\n", mysql_error(conn));
}
//getting information from the database
if (mysql_query(conn, "SELECT Gewenstetemperatuur FROM SensorValue")){
mysql_error(conn);
}
MYSQL_RES *result = mysql_store_result(conn);
if (result == NULL){
mysql_error(conn);
}
int num_fields = mysql_num_fields(result);
MYSQL_ROW row;
while ((row = mysql_fetch_row(result))){
for (i = 0; i < num_fields; i++){
printf("%s ", row[i] ? row[i] : "NULL");
gewensteGradenCelcius = (int)row[i];
temp = gewensteGradenCelcius;
printf("\n %s \n", gewensteGradenCelcius);
printf("%d \n",temp )
//Here is were is get stuck if i try to take the value and run it trough a
//formula like (gewensteGradenCelcius + 50) * 4 and the try to print the
//gewensteGradenCelcius just puts out nothing
}
printf("\n");
}
mysql_free_result(result);
usleep(1500000);
}
}
The conversion in your code of a number contained in string format ( row[i] ) is done incorrectly....
A C string cannot be copied into an int as you have attempted. C does provide several ways to do this, including the following... Change:
gewensteGradenCelcius = (int)row[i];//incorrect
To:
//EITHER
gewensteGradenCelcius = atoi(row[i]);//simple and legal C99, but not recommended
//OR
char *endptr;
gewensteGradenCelcius = (int)strtol(row[i], &endptr, 10);//recommended method
//OR
sscanf(row[i], "%d",&gewensteGradenCelcius);//recommended method
( why atoi() is not recommended )
Then, because gewensteGradenCelcius is an int your printf statement, use an int format specifier. Change:
printf("\n %s \n", gewensteGradenCelcius);//wrong format specifier for int
To:
printf("\n %d \n", gewensteGradenCelcius);//correct format specifier
^^
row[i] is a text (line "20" or "18"), so this line is wrong:
gewensteGradenCelcius = (int)row[i];
and you shoud rather write
gewensteGradenCelcius = atoi(row[i]);
I'm not too good with C++, however; my code compiled, but the function crashes my program, the below is a short sum-up of the code; it's not complete, however the function and call is there.
void rot13(char *ret, const char *in);
int main()
{
char* str;
MessageBox(NULL, _T("Test 1; Does get here!"), _T("Test 1"), MB_OK);
rot13(str, "uryyb jbeyq!"); // hello world!
/* Do stuff with char* str; */
MessageBox(NULL, _T("Test 2; Doesn't get here!"), _T("Test 2"), MB_OK);
return 0;
}
void rot13(char *ret, const char *in){
for( int i=0; i = sizeof(in); i++ ){
if(in[i] >= 'a' && in[i] <= 'm'){
// Crashes Here;
ret[i] += 13;
}
else if(in[i] > 'n' && in[i] <= 'z'){
// Possibly crashing Here too?
ret[i] -= 13;
}
else if(in[i] > 'A' && in[i] <= 'M'){
// Possibly crashing Here too?
ret[i] += 13;
}
else if(in[i] > 'N' && in[i] <= 'Z'){
// Possibly crashing Here too?
ret[i] -= 13;
}
}
}
The function gets to "Test 1; Does get Here!" - However it doesn't get to "Test 2; Doesn't get here!"
Thank you in advanced.
-Nick Daniels.
str is uninitialised and it is being dereferenced in rot13, causing the crash. Allocate memory for str before passing to rot13() (either on the stack or dynamically):
char str[1024] = ""; /* Large enough to hold string and initialised. */
The for loop inside rot13() is also incorrect (infinte loop):
for( int i=0; i = sizeof(in); i++ ){
change to:
for(size_t i = 0, len = strlen(in); i < len; i++ ){
You've got several problems:
You never allocate memory for your output - you never initialise the variable str. This is what's causing your crash.
Your loop condition always evaluates to true (= assigns and returns the assigned value, == tests for equality).
Your loop condition uses sizeof(in) with the intention of getting the size of the input string, but that will actually give you the size of the pointer. Use strlen instead.
Your algorithm increases or decreases the values in the return string by 13. The values you place in the output string are +/- 13 from the initial values in the output string, when they should be based on the input string.
Your algorithm doesn't handle 'A', 'n' or 'N'.
Your algorithm doesn't handle any non-alphabetic characters, yet the test string you use contains two.