trying to deserialize JSON unsuccesfully - json

I am trying to deserialize an array of chars using the ArduinoJson Lib. The chars are coming from a I2C connection using Wire library. They come successfully so I don't think there is an issue there.
When trying to de-serialize at run time I get the message "deserializeJson() failed: EmptyInput".
From ArduinoJson Troubleshooter's report
The issue happens at run time
The issue concerns deserialization
deserializeJson() returns EmptyInput
Input comes neither from an HTTP response, nor a file, nor a stream
The part of code that deserialization fails is here:
void callback(char payload[], unsigned int msg_size) {
Serial.print("Message arrived ");
for (int i=0;i<msg_size;i++) {
Serial.print((payload[i]));
}
DeserializationError error = deserializeJson(doc, payload, msg_size);
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.f_str());
return;
}
const char* command = doc["cmd"];
Serial.print("command ");
Serial.println(command);
//rest of code
}
void setup() {
//communications
Wire.begin(0x8); // join i2c bus with address #8
Wire.onReceive(receiveEvent); // register event
Serial.begin(9600); // start serial for output
Serial.print("Start_");
Serial.println(ver);
}
void loop() {
// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
char buff[60];
Serial.print("how many=");
Serial.println(howMany);
//initialize buffers
buff[0] = '\0';
int i = 0;
while (0 < Wire.available()) { // loop through all but the last
//char c = Wire.read(); // receive byte as a character
char c = Wire.read();
Serial.print(c); // print the character
buff[i] = c;
buff[i+1] = '\0'; // Add a NULL after each character
i++;
}
int x = Wire.read(); // receive byte as an integer
Serial.println();
Serial.print("x:");
Serial.println(x); // print the integer
Serial.print("BUFFER:");
for (int j=0; j < howMany; j++) {
Serial.print(buff[j]);
}
Serial.println();
Serial.print("size:");
Serial.println(sizeof(buff));
callback(buff, howMany);
}
The print out from serial ide is here:
Start_v.0.1
how many=25
{"cmd":"demo","seq":"1"}
x:-1
BUFFER:{"cmd":"demo","seq":"1"}
size:60
Message arrived {"cmd":"demo","seq":"1"} deserializeJson() failed: EmptyInput
But the payload variable, as you see here is not empty.
Can you provide any debugging hints? Thank you
Edit: I have added more code that shows the i2c communication
from smbus import SMBus
addr = 0x8 # bus address
bus = SMBus(1) # indicates /dev/ic2-1
numb = 1
def StringToBytes(val):
retVal = []
for c in val:
retVal.append(ord(c))
return retVal
def writeData(arrayValue, i2c_address):
byteValue = StringToBytes(arrayValue)
# examples --->
bus.write_i2c_block_data(i2c_address,0x00,byteValue)
return -1
# main
print ("Enter command:")
while 1:
cmd = input(">>>> ")
writeData(str(cmd), addr)

I filtered the incoming i2c buffer for nulls and the de serialization of JSON worked. I am not sure why the nulls are sent by rpi/python.
void receiveEvent(int howMany) {
char buff[60];
Serial.print("how many=");
Serial.println(howMany);
//initialize buffers
buff[0] = '\0';
int i = 0;
while (0 < Wire.available()) { // loop through all but the last
char c = Wire.read(); // receive byte as a character
if (c == '\0') {
//ignore
} else {
//char c = Wire.read();
Serial.print(c); // print the character
buff[i] = c;
buff[i+1] = '\0'; // Add a NULL after each character
i++;
}
}
int x = Wire.read(); // receive byte as an integer
Serial.println();
Serial.print("x:");
Serial.println(x); // print the integer
Serial.print("BUFFER:");
for (int j=0; j < howMany; j++) {
Serial.print(buff[j]);
}
Serial.println();
Serial.print("size:");
Serial.println(sizeof(buff));
callback(buff, howMany);
}

Related

How can we read data file based on column in C [duplicate]

I have a .csv file:
lp;imie;nazwisko;ulica;numer;kod;miejscowosc;telefon;email;data_ur
1;Jan;Kowalski;ul. Nowa;1a;11-234;Budry;123-123-456;jan#go.xxx;1980.05.13
2;Jerzy;Nowak;ul. Konopnicka;13a/3;00-900;Lichowice;(55)333-44-55;jer#wu.to;1990.03.23
And I need to read this in C. I have some code, but only for the connection.
Hopefully this would get you started
See it live on http://ideone.com/l23He (using stdin)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char* getfield(char* line, int num)
{
const char* tok;
for (tok = strtok(line, ";");
tok && *tok;
tok = strtok(NULL, ";\n"))
{
if (!--num)
return tok;
}
return NULL;
}
int main()
{
FILE* stream = fopen("input", "r");
char line[1024];
while (fgets(line, 1024, stream))
{
char* tmp = strdup(line);
printf("Field 3 would be %s\n", getfield(tmp, 3));
// NOTE strtok clobbers tmp
free(tmp);
}
}
Output:
Field 3 would be nazwisko
Field 3 would be Kowalski
Field 3 would be Nowak
The following code is in plain c language and handles blank spaces.
It only allocates memory once, so one free() is needed, for each processed line.
http://ideone.com/mSCgPM
/* Tiny CSV Reader */
/* Copyright (C) 2015, Deligiannidis Konstantinos
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://w...content-available-to-author-only...u.org/licenses/>. */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* For more that 100 columns or lines (when delimiter = \n), minor modifications are needed. */
int getcols( const char * const line, const char * const delim, char ***out_storage )
{
const char *start_ptr, *end_ptr, *iter;
char **out;
int i; //For "for" loops in the old c style.
int tokens_found = 1, delim_size, line_size; //Calculate "line_size" indirectly, without strlen() call.
int start_idx[100], end_idx[100]; //Store the indexes of tokens. Example "Power;": loc('P')=1, loc(';')=6
//Change 100 with MAX_TOKENS or use malloc() for more than 100 tokens. Example: "b1;b2;b3;...;b200"
if ( *out_storage != NULL ) return -4; //This SHOULD be NULL: Not Already Allocated
if ( !line || !delim ) return -1; //NULL pointers Rejected Here
if ( (delim_size = strlen( delim )) == 0 ) return -2; //Delimiter not provided
start_ptr = line; //Start visiting input. We will distinguish tokens in a single pass, for good performance.
//Then we are allocating one unified memory region & doing one memory copy.
while ( ( end_ptr = strstr( start_ptr, delim ) ) ) {
start_idx[ tokens_found -1 ] = start_ptr - line; //Store the Index of current token
end_idx[ tokens_found - 1 ] = end_ptr - line; //Store Index of first character that will be replaced with
//'\0'. Example: "arg1||arg2||end" -> "arg1\0|arg2\0|end"
tokens_found++; //Accumulate the count of tokens.
start_ptr = end_ptr + delim_size; //Set pointer to the next c-string within the line
}
for ( iter = start_ptr; (*iter!='\0') ; iter++ );
start_idx[ tokens_found -1 ] = start_ptr - line; //Store the Index of current token: of last token here.
end_idx[ tokens_found -1 ] = iter - line; //and the last element that will be replaced with \0
line_size = iter - line; //Saving CPU cycles: Indirectly Count the size of *line without using strlen();
int size_ptr_region = (1 + tokens_found)*sizeof( char* ); //The size to store pointers to c-strings + 1 (*NULL).
out = (char**) malloc( size_ptr_region + ( line_size + 1 ) + 5 ); //Fit everything there...it is all memory.
//It reserves a contiguous space for both (char**) pointers AND string region. 5 Bytes for "Out of Range" tests.
*out_storage = out; //Update the char** pointer of the caller function.
//"Out of Range" TEST. Verify that the extra reserved characters will not be changed. Assign Some Values.
//char *extra_chars = (char*) out + size_ptr_region + ( line_size + 1 );
//extra_chars[0] = 1; extra_chars[1] = 2; extra_chars[2] = 3; extra_chars[3] = 4; extra_chars[4] = 5;
for ( i = 0; i < tokens_found; i++ ) //Assign adresses first part of the allocated memory pointers that point to
out[ i ] = (char*) out + size_ptr_region + start_idx[ i ]; //the second part of the memory, reserved for Data.
out[ tokens_found ] = (char*) NULL; //[ ptr1, ptr2, ... , ptrN, (char*) NULL, ... ]: We just added the (char*) NULL.
//Now assign the Data: c-strings. (\0 terminated strings):
char *str_region = (char*) out + size_ptr_region; //Region inside allocated memory which contains the String Data.
memcpy( str_region, line, line_size ); //Copy input with delimiter characters: They will be replaced with \0.
//Now we should replace: "arg1||arg2||arg3" with "arg1\0|arg2\0|arg3". Don't worry for characters after '\0'
//They are not used in standard c lbraries.
for( i = 0; i < tokens_found; i++) str_region[ end_idx[ i ] ] = '\0';
//"Out of Range" TEST. Wait until Assigned Values are Printed back.
//for ( int i=0; i < 5; i++ ) printf("c=%x ", extra_chars[i] ); printf("\n");
// *out memory should now contain (example data):
//[ ptr1, ptr2,...,ptrN, (char*) NULL, "token1\0", "token2\0",...,"tokenN\0", 5 bytes for tests ]
// |__________________________________^ ^ ^ ^
// |_______________________________________| | |
// |_____________________________________________| These 5 Bytes should be intact.
return tokens_found;
}
int main()
{
char in_line[] = "Arg1;;Th;s is not Del;m;ter;;Arg3;;;;Final";
char delim[] = ";;";
char **columns;
int i;
printf("Example1:\n");
columns = NULL; //Should be NULL to indicate that it is not assigned to allocated memory. Otherwise return -4;
int cols_found = getcols( in_line, delim, &columns);
for ( i = 0; i < cols_found; i++ ) printf("Column[ %d ] = %s\n", i, columns[ i ] ); //<- (1st way).
// (2nd way) // for ( i = 0; columns[ i ]; i++) printf("start_idx[ %d ] = %s\n", i, columns[ i ] );
free( columns ); //Release the Single Contiguous Memory Space.
columns = NULL; //Pointer = NULL to indicate it does not reserve space and that is ready for the next malloc().
printf("\n\nExample2, Nested:\n\n");
char example_file[] = "ID;Day;Month;Year;Telephone;email;Date of registration\n"
"1;Sunday;january;2009;123-124-456;jitter#go.xyz;2015-05-13\n"
"2;Monday;March;2011;(+30)333-22-55;buffer#wl.it;2009-05-23";
char **rows;
int j;
rows = NULL; //getcols() requires it to be NULL. (Avoid dangling pointers, leaks e.t.c).
getcols( example_file, "\n", &rows);
for ( i = 0; rows[ i ]; i++) {
{
printf("Line[ %d ] = %s\n", i, rows[ i ] );
char **columnX = NULL;
getcols( rows[ i ], ";", &columnX);
for ( j = 0; columnX[ j ]; j++) printf(" Col[ %d ] = %s\n", j, columnX[ j ] );
free( columnX );
}
}
free( rows );
rows = NULL;
return 0;
}
A complete example which leaves the fields as NULL-terminated strings in the original input buffer and provides access to them via an array of char pointers. The CSV processor has been confirmed to work with fields enclosed in "double quotes", ignoring any delimiter chars within them.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// adjust BUFFER_SIZE to suit longest line
#define BUFFER_SIZE 1024 * 1024
#define NUM_FIELDS 10
#define MAXERRS 5
#define RET_OK 0
#define RET_FAIL 1
#define FALSE 0
#define TRUE 1
// char* array will point to fields
char *pFields[NUM_FIELDS];
// field offsets into pFields array:
#define LP 0
#define IMIE 1
#define NAZWISKo 2
#define ULICA 3
#define NUMER 4
#define KOD 5
#define MIEJSCOw 6
#define TELEFON 7
#define EMAIL 8
#define DATA_UR 9
long loadFile(FILE *pFile, long *errcount);
static int loadValues(char *line, long lineno);
static char delim;
long loadFile(FILE *pFile, long *errcount){
char sInputBuf [BUFFER_SIZE];
long lineno = 0L;
if(pFile == NULL)
return RET_FAIL;
while (!feof(pFile)) {
// load line into static buffer
if(fgets(sInputBuf, BUFFER_SIZE-1, pFile)==NULL)
break;
// skip first line (headers)
if(++lineno==1)
continue;
// jump over empty lines
if(strlen(sInputBuf)==0)
continue;
// set pFields array pointers to null-terminated string fields in sInputBuf
if(loadValues(sInputBuf,lineno)==RET_FAIL){
(*errcount)++;
if(*errcount > MAXERRS)
break;
} else {
// On return pFields array pointers point to loaded fields ready for load into DB or whatever
// Fields can be accessed via pFields, e.g.
printf("lp=%s, imie=%s, data_ur=%s\n", pFields[LP], pFields[IMIE], pFields[DATA_UR]);
}
}
return lineno;
}
static int loadValues(char *line, long lineno){
if(line == NULL)
return RET_FAIL;
// chop of last char of input if it is a CR or LF (e.g.Windows file loading in Unix env.)
// can be removed if sure fgets has removed both CR and LF from end of line
if(*(line + strlen(line)-1) == '\r' || *(line + strlen(line)-1) == '\n')
*(line + strlen(line)-1) = '\0';
if(*(line + strlen(line)-1) == '\r' || *(line + strlen(line)-1 )== '\n')
*(line + strlen(line)-1) = '\0';
char *cptr = line;
int fld = 0;
int inquote = FALSE;
char ch;
pFields[fld]=cptr;
while((ch=*cptr) != '\0' && fld < NUM_FIELDS){
if(ch == '"') {
if(! inquote)
pFields[fld]=cptr+1;
else {
*cptr = '\0'; // zero out " and jump over it
}
inquote = ! inquote;
} else if(ch == delim && ! inquote){
*cptr = '\0'; // end of field, null terminate it
pFields[++fld]=cptr+1;
}
cptr++;
}
if(fld > NUM_FIELDS-1){
fprintf(stderr, "Expected field count (%d) exceeded on line %ld\n", NUM_FIELDS, lineno);
return RET_FAIL;
} else if (fld < NUM_FIELDS-1){
fprintf(stderr, "Expected field count (%d) not reached on line %ld\n", NUM_FIELDS, lineno);
return RET_FAIL;
}
return RET_OK;
}
int main(int argc, char **argv)
{
FILE *fp;
long errcount = 0L;
long lines = 0L;
if(argc!=3){
printf("Usage: %s csvfilepath delimiter\n", basename(argv[0]));
return (RET_FAIL);
}
if((delim=argv[2][0])=='\0'){
fprintf(stderr,"delimiter must be specified\n");
return (RET_FAIL);
}
fp = fopen(argv[1] , "r");
if(fp == NULL) {
fprintf(stderr,"Error opening file: %d\n",errno);
return(RET_FAIL);
}
lines=loadFile(fp,&errcount);
fclose(fp);
printf("Processed %ld lines, encountered %ld error(s)\n", lines, errcount);
if(errcount>0)
return(RET_FAIL);
return(RET_OK);
}
Use fscanf to read the file until you encounter ';' or \n, then just skip it with fscanf(f, "%*c").
int main()
{
char str[128];
int result;
FILE* f = fopen("test.txt", "r");
/*...*/
do {
result = fscanf(f, "%127[^;\n]", str);
if(result == 0)
{
result = fscanf(f, "%*c");
}
else
{
//Put here whatever you want to do with your value.
printf("%s\n", str);
}
} while(result != EOF);
return 0;
}
This code is fairly simple, but effective. It parses comma-separated files with parenthesis. You can easily modify it to suit your needs.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
// argv[1] path to csv file
// argv[2] number of lines to skip
// argv[3] length of longest value (in characters)
FILE *pfinput;
unsigned int nSkipLines, currentLine, lenLongestValue;
char *pTempValHolder;
int c;
unsigned int vcpm; // Value character marker
int QuotationOnOff; // 0 - off, 1 - on
nSkipLines = atoi(argv[2]);
lenLongestValue = atoi(argv[3]);
pTempValHolder = (char*)malloc(lenLongestValue);
if(pfinput = fopen(argv[1], "r")) {
rewind(pfinput);
currentLine = 1;
vcpm = 0;
QuotationOnOff = 0;
// currentLine > nSkipLines condition
// skips / ignores first argv[2] lines
while((c = fgetc(pfinput)) != EOF)
{
switch(c)
{
case ',':
if(!QuotationOnOff && currentLine > nSkipLines)
{
pTempValHolder[vcpm] = '\0';
printf("%s,", pTempValHolder);
vcpm = 0;
}
break;
case '\n':
if(currentLine > nSkipLines)
{
pTempValHolder[vcpm] = '\0';
printf("%s\n", pTempValHolder);
vcpm = 0;
}
currentLine++;
break;
case '\"':
if(currentLine > nSkipLines)
{
if(!QuotationOnOff) {
QuotationOnOff = 1;
pTempValHolder[vcpm] = c;
vcpm++;
} else {
QuotationOnOff = 0;
pTempValHolder[vcpm] = c;
vcpm++;
}
}
break;
default:
if(currentLine > nSkipLines)
{
pTempValHolder[vcpm] = c;
vcpm++;
}
break;
}
}
fclose(pfinput);
free(pTempValHolder);
}
return 0;
}
#include <conio.h>
#include <stdio.h>
#include <string.h>
// Driver Code
int main()
{
// Substitute the full file path
// for the string file_path
FILE* fp = fopen("Movie.csv", "r");
char *wrds[40];
if (!fp)
printf("Can't open file\n");
else {
// Here we have taken size of
// array 1024 you can modify it
char buffer[1024];
int row = 0;
int column = 0;
while (fgets(buffer, 1024, fp)) {
column = 0;
row++;
// To avoid printing of column
// names in file can be changed
// according to need
if (row == 1)
continue;
// Splitting the data
char* value = strtok(buffer, ", ");
while (value) {
// Column 1
if (column == 0) {
printf("Name :");
}
// Column 2
if (column == 1) {
printf("\tAccount No. :");
}
// Column 3
if (column == 2) {
printf("\tAmount :");
}
printf("%s", value);
wrds[column] = value;
value = strtok(NULL, ", ");
column++;
}
printf("\n");
}
// Close the file
fclose(fp);
}
getchar();
return 0;
}

How to take an Input integer from HTM? - Arduino / NodeMCU ESP32

Hi im currently doing Servo NodeMCU controlling. my plan is to create an Input Box where i can type, then whatever number i type will be use as servo angle using Webserver or 194.168.4.1 or so on. (ex: i type 90, servo angle will be 90) the problem i si do not know how to get it. here is the code:
#include<Servo.h>
Servo ServoPin;
int angle = 0;
#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiAP.h>
#define ServoPin 34; // Set the GPIO pin where you connected your test LED or comment this line out if your dev board has a built-in LED
// Set these to your desired credentials.
const char *ssid = "XXXXXX";
const char *password = "XXXXXX";
WiFiServer server(80);
void setup() {
Serial.begin(115200);
Serial.println();
Serial.println("Configuring access point...");
pinMode(ServoPin,OUTPUT);
// You can remove the password parameter if you want the AP to be open.
WiFi.softAP(ssid, password);
IPAddress myIP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(myIP);
server.begin();
Serial.println("Server started");
}
void loop() {
WiFiClient client = server.available(); // listen for incoming clients
if (client) { // if you get a client,
Serial.println("New Client."); // print a message out the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected()) { // loop while the client's connected
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println();
// the content of the HTTP response follows the header:
client.print("<!DOCTYPE html>");
client.print("<html>");
client.print("<body>");
client.print("<p>Change the text of the text field, and then click the button below.</p>"); //
client.print("INPUT NUMBER: <input type='number' id='servo'>"); //in this area, I WILL TYPE number 0-255.
client.print("<button type='button' '>Go</button>");
ServoPin.attach(number); //the area where i will assign the servo to the angle i type.
// break out of the while loop:
break;
} else { // if you got a newline, then clear currentLine:
currentLine = "";
}
} else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
}
}
// close the connection:
client.stop();
Serial.println("Client Disconnected.");
}
}
So as you can see in client.print"INPUT NUMBER.... so on line, that is the place where my code will design an input box. the problem is it is inside a " " or double quotation mark. i wonder what should i do to get the 'number' input then use it on ServoPin.attach(number);
im very beginner on HTML(zero actually) because i dont have knowledge here yet. this code is mostly taken from internet w3school website then i modify it a bit to Servo controlling. so im really hoping that someone can tell me how to do it....
Board: Node32
actual Board: NodeMCU ESP 32
Here is web server code that parses two variables from a GET response of a HTML form, I suppose it should be no problem to adopt it for your needs: http://playground.arduino.cc/Code/WebServerST
Hey so this is the how I do this, I've made a form in your html that would take the input and send a get request to the server and can be dealt with there. this is the process:
input put into form, sent to server in get request.
the get request is send stored char by char in header variable.
if statement checks if the parameter is in the header. The string is searched for the value and the value is saved into a string.
good luck this should work.
#include<Servo.h>
Servo ServoPin;
int angle = 0;
#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiAP.h>
#define ServoPin 34; // Set the GPIO pin where you connected your test LED or comment this line out if your dev board has a built-in LED
// Set these to your desired credentials.
const char *ssid = "XXXXXX";
const char *password = "";
WiFiServer server(80);
String header;
void setup() {
Serial.begin(115200);
Serial.println();
Serial.println("Configuring access point...");
pinMode(ServoPin,OUTPUT);
// You can remove the password parameter if you want the AP to be open.
WiFi.softAP(ssid, password);
IPAddress myIP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(myIP);
server.begin();
Serial.println("Server started");
}
void loop() {
WiFiClient client = server.available(); // listen for incoming clients
if (client) { // if you get a client,
Serial.println("New Client."); // print a message out the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected()) { // loop while the client's connected
if (client.available()) { // if there's bytes to read from the client,
char c = client.read();// read a byte, then
header += c; //write request to the header
Serial.write(c); // print it out the serial monitor
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println();
if (header.indexOf("input1=") >= 0) { //if input1 is in the header then...
Serial.println(header);
String input_string = "";
int reqEnd = header.indexOf(" HTTP/1.1");
for (int n = 16; n < reqEnd; ++n) { //put the input value from the header to the variable
input_string += header[n];
}
Serial.println(input_string);
}
// the content of the HTTP response follows the header:
client.print("<!DOCTYPE html>");
client.print("<html>");
client.print("<body>");
client.print("<form action=\"/get\">"); //added a form to take a text input and send a get request.
client.print("input1: <input type=\"text\" name=\"input1\">");
client.print("<input type=\"submit\" value=\"Submit\">");
client.print("</form><br>");
ServoPin.attach(number); //the area where i will assign the servo to the angle i type.
// break out of the while loop:
break;
} else { // if you got a newline, then clear currentLine:
currentLine = "";
}
} else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
}
}
// close the connection:
client.stop();
Serial.println("Client Disconnected.");
}
}
#include "WiFi.h"
#include "ESPAsyncWebServer.h"
const char* ssid = "yourNetworkName";
const char* password = "yourNetworkPass";
AsyncWebServer server(80);
void setup(){
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
Serial.println(WiFi.localIP());
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
int paramsNr = request->params();
Serial.println(paramsNr);
for(int i=0;i<paramsNr;i++){
AsyncWebParameter* p = request->getParam(i);
Serial.print("Param name: ");
Serial.println(p->name());
Serial.print("Param value: ");
Serial.println(p->value());
Serial.println("------");
}
request->send(200, "text/plain", "message received");
});
server.begin();
}
void loop()
{}

esp32 arduino ide Web Socket stream json no errors but no values

Thank you for considering this problem.
I'm streaming a small json from a Web socket and can see the stringified json arrive to the client because it prints to the serial monitor, but then it deserializes to a 1 or 0 instead of my key:value pairs. I just want it to parse the json so that the rest of my program can use the values. I get no errors. Tried both Dynamic and Static json docs. Tried triple the memory requirement.
Arduino:
#include <WiFi.h>
#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1
#include <ArduinoJson.h>
#include <StreamUtils.h>
const char* ssid = "ssid";
const char* password = "pw";
const char* host = "10.0.0.250";
void setup()
{
Serial.begin(115200);
delay(10);
// We start by connecting to a WiFi network
int loopCount = 0;
StaticJsonDocument<384> doc;
DeserializationError error;
void loop()
{
//delay(5000);
++loopCount;
if (loopCount > 1) return;
Serial.print("connecting to ");
Serial.println(host);
// Use WiFiClient class to create TCP connections
WiFiClient client;
const int httpPort = 1337;
if (!client.connect(host, httpPort)) {
Serial.println("connection failed");
return;
}
// This will send the request to the server
client.print(String("GET ") + "HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n\r\n");
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > 5000) {
Serial.println(">>> Client Timeout !");
client.stop();
return;
}
}
// Read all the lines of the reply from server and print them to Serial
while (client.available() > 0) {
ReadLoggingStream loggingClient(client, Serial);
error = deserializeJson(doc, loggingClient);
}
Serial.println("");
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.f_str());
return;
}
//this doesn't work
int id = doc["id"]; // Should be 5 but I get 0 for every value
Serial.print("id: "); Serial.println(id);
}
/*Serial monitor:
14:21:25.905 ->
07:16:36.574 -> WiFi connected
07:16:36.574 -> IP address:
07:16:36.574 -> 10.0.0.113
07:16:36.574 -> connecting to 10.0.0.250
07:16:36.849 -> "{\"id\":5,\"nom\":\"whynot\",\"delayStart\":200,\"rampePWM\":11,\"pulseWelding\":200,\"speedBalayage\":0.4,\"speedWelding\":0.5,\"speedWire\":1.1,\"balayage\":0.8,\"pulseWire\":5,\"retractWire\":7}"
07:16:36.849 -> id: 0
*/
The tcp-socket is in my node express setup. The file projet.json is only the json seen above ^^ no white space.
var net = require('net');
var serverN = net.createServer(function(socket) {
fs.readFile("./data/projet.json", 'utf-8', (err, data) => {
if (err) {
throw err;
}
socket.write(JSON.stringify(data));
socket.pipe(socket);
});
});
serverN.listen(1337, '10.0.0.250');
I can only show you how i use it to get the right values. i use a DynamicJsonDocument in my solution:
DynamicJsonDocument root(2048);
DeserializationError err = deserializeJson(root, http.getString());
String TravelTimes = root["travelTime"];
Otherwise you can also try to output the values directly via the jsonobject
JsonObject object = doc.to<JsonObject>();
const char* id = object["id"];
The code parses the JSON string but then calls JsonDocument::to<T>() to obtain a JsonObject. This method clears the document - from https://arduinojson.org/v6/api/jsondocument/to/
Clears the JsonDocument and converts it to the specified type.
JsonDocument::as<T>() should be used instead:
JsonObject object = doc.as<JsonObject>();
From https://arduinojson.org/v6/api/jsondocument/as/
Casts JsonDocument to the specified type.
Unlike JsonDocument::to(), this function doesn’t change the content of the JsonDocument.
You can also use serializeJsonPretty() to display the JsonObject on the serial output. Instead of:
JsonObject object = doc.to<JsonObject>();
Serial.println(object);
this can be done with:
serializeJsonPretty(doc, Serial);
Thanks to bblanchon of ArduinoJson - The node socket was stringifying the json twice. I changed the socket to socket.write(data) instead of socket.write(JSON.stringify(data)) and it works.
See full explanation here
https://github.com/bblanchon/ArduinoJson/issues/1507
Thanks again!

how do i publish the data on mqtt of the bme680 sensor using ESP32cam

I am using windows 10 and working on getting the gas readings from BME680 using esp32cam. I tried to add this:
#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
//#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BME680.h"
#include <Arduino_JSON.h>
//uint64_t mac;
//uint32_t high;
//uint32_t low;
// Replace the next variables with your SSID/Password combination
const char* ssid = "";
const char* password = "";
// Add your MQTT Broker IP address, example:
//const char* mqtt_server = "";
const char* mqtt_server = "";
const char* mqtt_port = "";
const char* mqtt_user = "";
const char* mqtt_password = "";
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;
//uncomment the following lines if you're using SPI
#include <SPI.h>
#define BME_SCK 14
#define BME_MISO 12
#define BME_MOSI 13
#define BME_CS 15
//Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
Adafruit_BME680 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI
float temperature = 0;
float humidity = 0;
float pressure = 0;
float gas = 0;
//Device ID
//uint64_t chip_id;
//chip_id=ESP.getEfuseMac();//The chip ID is essentially its MAC address(length: 6 bytes).
// LED Pin
const int ledPin = 4;
void setup() {
Serial.begin(115200);
// default settings
// (you can also pass in a Wire library object like &Wire2)
//status = bme.begin();
if (!bme.begin(0x76)) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
WiFi.begin();
}
setup_wifi();
client.setServer(mqtt_server,...);
client.setCallback(callback);
pinMode(ledPin, OUTPUT);
// Set up oversampling and filter initialization
bme.setTemperatureOversampling(BME680_OS_8X);
bme.setHumidityOversampling(BME680_OS_2X);
bme.setPressureOversampling(BME680_OS_4X);
bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
bme.setGasHeater(320, 150); // 320*C for 150 ms
}
void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void callback(char* topic, byte* message, unsigned int length) {
Serial.print("Message arrived on topic: ");
Serial.print(topic);
Serial.print(". Message: ");
String messageTemp;
for (int i = 0; i < length; i++) {
Serial.print((char)message[i]);
messageTemp += (char)message[i];
}
Serial.println();
// Feel free to add more if statements to control more GPIOs with MQTT
// If a message is received on the topic esp32/output, you check if the message is either "on" or "off".
// Changes the output state according to the message
if (String(topic) == "esp32/output") {
Serial.print("Changing output to ");
if(messageTemp == "on"){
Serial.println("on");
digitalWrite(ledPin, HIGH);
}
else if(messageTemp == "off"){
Serial.println("off");
digitalWrite(ledPin, LOW);
}
}
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect("ESP32Client", mqtt_user, mqtt_password)) {
Serial.println("connected");
// Subscribe
client.subscribe("esp32/output");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(20000);
}
}
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
long now = millis();
if (now - lastMsg > 5000) {
lastMsg = now;
// Temperature in Celsius
temperature = bme.readTemperature();
// Uncomment the next line to set temperature in Fahrenheit
// (and comment the previous temperature line)
//temperature = 1.8 * bme.readTemperature() + 32; // Temperature in Fahrenheit
// Convert the value to a char array
char tempString[8];
dtostrf(temperature, 1, 2, tempString);
//Serial.print("Temperature: ");
//Serial.println(tempString);
//client.publish("esp32/temperature", tempString);
humidity = bme.readHumidity();
// Convert the value to a char array
char humString[8];
dtostrf(humidity, 1, 2, humString);
//Serial.print("Humidity: ");
//Serial.println(humString);
//client.publish("esp32/humidity", humString);
pressure = bme.readPressure();
//Convert the value to a char array
char preString[16];
dtostrf(pressure, 1, 2, preString);
//Serial.print("Pressure: ");
//Serial.println(preString);
//client.publish("esp32/pressure", preString);
gas = bme.readGas();
//Serial.print(bme.gas_resistance / 1000.0);
char gasString[8];
dtostrf(gas, 1, 2, gasString);
//Serial.println(" KOhms");
char macValue[13]; // Don't forget one byte for the terminating NULL...
uint64_t mac = ESP.getEfuseMac();
sprintf(macValue, "%012x", mac);
//Serial.print("ChipID: ");
//Serial.println(chipId);
//client.publish("esp32/chipid", chipId);
JSONVar data;
data["temperature"] = temperature;
data["humidity"] = humidity;
data["pressure"] = pressure;
data["macValue"] = macValue;
data["gas"] = gas;
//Serial.print("data.keys() = ");
//Serial.println(data.keys());
//Serial.print("Data = ");
//Serial.println(data);
String jsonString = JSON.stringify(data);
//Serial.print("JSON.stringify(data) = ");
//Serial.println(jsonString);
client.publish("esp32/data", jsonString.c_str());
}
}
everything got compiled perfectly. But when i tried to upload the code, this error came up:
Arduino: 1.8.9 (Windows 10), Board: "ESP32 Wrover Module, Huge APP
(3MB No OTA), QIO, 80MHz, 115200, Verbose"
Sketch uses 789282 bytes (25%) of program storage space. Maximum
is 3145728 bytes.
Global variables use 40652 bytes (12%) of dynamic memory, leaving
287028 bytes for local variables. Maximum is 327680 bytes.
esptool.py v2.6
Serial port COM7
Connecting.....
Chip is .....(revision 1)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse,
Coding Scheme None
MAC: .....
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Warning: Could not auto-detect Flash size (FlashID=0xffffff,
SizeID=0xff), defaulting to 4MB
Compressed 8192 bytes to 47...
A fatal error occurred: Timed out waiting for packet content
A fatal error occurred: Timed out waiting for packet content
This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.
I don't know why is this thing coming up because previously everything was working fine when I tried to incorporate BME280 and publish the available data on MQTT. Now, I have switched to bme680.
EDIT:
I tried to disconnect BME from ESP32, then uploaded the code, then connected BME back. The error did not show up, but still, the data is not being shown this time, rather something like this, continually:
rst:0x10 (RTCWDT_RTC_RESET),boot:0x33 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371
ets Jun 8 2016 00:22:57
It looks to me that ESP32-CAM is not in the bootloader mode when you try to upload the code.
Did you connect IO0 and GND pins and push the reset button?
You should see the message that ESP32 is ready for upload in the terminal window.
Sorry for the late reply ... :)

Understanding how to use CGI programming with C and HTML

I'm attempting to use a local server made in C with an HTML page run on this server that will be able to interact with a program i made to be able to run bash commands which works perfectly outside of the html page but needs to be able to receive input from the user via text box on the web page, display the command entered as well as the output on the html page. Right now when i click the submit button on the html page it goes to localhost:PORT/pexec.cgi but shows absolutely no display at all, just white space. What am i doing wrong and how can i get this to work so that it will correctly display output?
WCServer.c
#include <sys/socket.h> // socket definitions
#include <sys/types.h> // socket types
#include <arpa/inet.h> // inet (3) funtions
#include <unistd.h> // misc. UNIX functions
#include <signal.h> // signal handling
#include <stdlib.h> // standard library
#include <stdio.h> // input/output library
#include <string.h> // string library
#include <errno.h> // error number library
#include <fcntl.h> // for O_* constants
#include <sys/mman.h> // mmap library
#include <sys/types.h> // various type definitions
#include <sys/stat.h> // more constants
// global constants
#define PORT 3838 // port to connect on
#define LISTENQ 10 // number of connections
int list_s; // listening socket
// structure to hold the return code and the filepath to serve to client.
typedef struct {
int returncode;
char *filename;
} httpRequest;
// Structure to hold variables that will be placed in shared memory
typedef struct {
pthread_mutex_t mutexlock;
int totalbytes;
} sharedVariables;
// headers to send to clients
char *header200 = "HTTP/1.0 200 OK\nServer: CS241Serv v0.1\nContent-Type: text/html\n\n";
char *header400 = "HTTP/1.0 400 Bad Request\nServer: CS241Serv v0.1\nContent-Type: text/html\n\n";
char *header404 = "HTTP/1.0 404 Not Found\nServer: CS241Serv v0.1\nContent-Type: text/html\n\n";
// get a message from the socket until a blank line is recieved
char *getMessage(int fd) {
// A file stream
FILE *sstream;
// Try to open the socket to the file stream and handle any failures
if( (sstream = fdopen(fd, "r")) == NULL)
{
fprintf(stderr, "Error opening file descriptor in getMessage()\n");
exit(EXIT_FAILURE);
}
// Size variable for passing to getline
size_t size = 1;
char *block;
// Allocate some memory for block and check it went ok
if( (block = malloc(sizeof(char) * size)) == NULL )
{
fprintf(stderr, "Error allocating memory to block in getMessage\n");
exit(EXIT_FAILURE);
}
// Set block to null
*block = '\0';
// Allocate some memory for tmp and check it went ok
char *tmp;
if( (tmp = malloc(sizeof(char) * size)) == NULL )
{
fprintf(stderr, "Error allocating memory to tmp in getMessage\n");
exit(EXIT_FAILURE);
}
// Set tmp to null
*tmp = '\0';
// Int to keep track of what getline returns
int end;
// Int to help use resize block
int oldsize = 1;
// While getline is still getting data
while( (end = getline( &tmp, &size, sstream)) > 0)
{
// If the line its read is a caridge return and a new line were at the end of the header so break
if( strcmp(tmp, "\r\n") == 0)
{
break;
}
// Resize block
block = realloc(block, size+oldsize);
// Set the value of oldsize to the current size of block
oldsize += size;
// Append the latest line we got to block
strcat(block, tmp);
}
// Free tmp a we no longer need it
free(tmp);
// Return the header
return block;
}
// send a message to a socket file descripter
int sendMessage(int fd, char *msg) {
return write(fd, msg, strlen(msg));
}
// Extracts the filename needed from a GET request and adds public_html to the front of it
char * getFileName(char* msg)
{
// Variable to store the filename in
char * file;
// Allocate some memory for the filename and check it went OK
if( (file = malloc(sizeof(char) * strlen(msg))) == NULL)
{
fprintf(stderr, "Error allocating memory to file in getFileName()\n");
exit(EXIT_FAILURE);
}
// Get the filename from the header
sscanf(msg, "GET %s HTTP/1.1", file);
// Allocate some memory not in read only space to store "public_html"
char *base;
if( (base = malloc(sizeof(char) * (strlen(file) + 18))) == NULL)
{
fprintf(stderr, "Error allocating memory to base in getFileName()\n");
exit(EXIT_FAILURE);
}
char* ph = "public_html";
// Copy public_html to the non read only memory
strcpy(base, ph);
// Append the filename after public_html
strcat(base, file);
// Free file as we now have the file name in base
free(file);
// Return public_html/filetheywant.html
return base;
}
// parse a HTTP request and return an object with return code and filename
httpRequest parseRequest(char *msg){
httpRequest ret;
// A variable to store the name of the file they want
char* filename;
// Allocate some memory to filename and check it goes OK
if( (filename = malloc(sizeof(char) * strlen(msg))) == NULL)
{
fprintf(stderr, "Error allocating memory to filename in parseRequest()\n");
exit(EXIT_FAILURE);
}
// Find out what page they want
filename = getFileName(msg);
// Check if its a directory traversal attack
char *badstring = "..";
char *test = strstr(filename, badstring);
// Check if they asked for / and give them input.html
int test2 = strcmp(filename, "public_html/");
// Check if the page they want exists
FILE *exists = fopen(filename, "r" );
// If the badstring is found in the filename
if( test != NULL )
{
// Return a 400 header and 400.html
ret.returncode = 400;
ret.filename = "400.html";
}
// If they asked for / return input.html
else if(test2 == 0)
{
ret.returncode = 200;
ret.filename = "public_html/input.html";
}
// If they asked for a specific page and it exists because we opened it sucessfully return it
else if( exists != NULL )
{
ret.returncode = 200;
ret.filename = filename;
// Close the file stream
fclose(exists);
}
// If we get here the file they want doesn't exist so return a 404
else
{
ret.returncode = 404;
ret.filename = "404.html";
}
// Return the structure containing the details
return ret;
}
// print a file out to a socket file descriptor
int printFile(int fd, char *filename) {
/* Open the file filename and echo the contents from it to the file descriptor fd */
// Attempt to open the file
FILE *read;
if( (read = fopen(filename, "r")) == NULL)
{
fprintf(stderr, "Error opening file in printFile()\n");
exit(EXIT_FAILURE);
}
// Get the size of this file for printing out later on
int totalsize;
struct stat st;
stat(filename, &st);
totalsize = st.st_size;
// Variable for getline to write the size of the line its currently printing to
size_t size = 1;
// Get some space to store each line of the file in temporarily
char *temp;
if( (temp = malloc(sizeof(char) * size)) == NULL )
{
fprintf(stderr, "Error allocating memory to temp in printFile()\n");
exit(EXIT_FAILURE);
}
// Int to keep track of what getline returns
int end;
// While getline is still getting data
while( (end = getline( &temp, &size, read)) > 0)
{
sendMessage(fd, temp);
}
// Final new line
sendMessage(fd, "\n");
// Free temp as we no longer need it
free(temp);
// Return how big the file we sent out was
return totalsize;
}
// clean up listening socket on ctrl-c
void cleanup(int sig) {
printf("Cleaning up connections and exiting.\n");
// try to close the listening socket
if (close(list_s) < 0) {
fprintf(stderr, "Error calling close()\n");
exit(EXIT_FAILURE);
}
// Close the shared memory we used
shm_unlink("/sharedmem");
// exit with success
exit(EXIT_SUCCESS);
}
int printHeader(int fd, int returncode)
{
// Print the header based on the return code
switch (returncode)
{
case 200:
sendMessage(fd, header200);
return strlen(header200);
break;
case 400:
sendMessage(fd, header400);
return strlen(header400);
break;
case 404:
sendMessage(fd, header404);
return strlen(header404);
break;
}
}
// Increment the global count of data sent out
int recordTotalBytes(int bytes_sent, sharedVariables *mempointer)
{
// Lock the mutex
pthread_mutex_lock(&(*mempointer).mutexlock);
// Increment bytes_sent
(*mempointer).totalbytes += bytes_sent;
// Unlock the mutex
pthread_mutex_unlock(&(*mempointer).mutexlock);
// Return the new byte count
return (*mempointer).totalbytes;
}
int main(int argc, char *argv[]) {
int conn_s; // connection socket
short int port = PORT; // port number
struct sockaddr_in servaddr; // socket address structure
// set up signal handler for ctrl-c
(void) signal(SIGINT, cleanup);
// create the listening socket
if ((list_s = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) {
fprintf(stderr, "Error creating listening socket.\n");
exit(EXIT_FAILURE);
}
// set all bytes in socket address structure to zero, and fill in the relevant data members
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(port);
// bind to the socket address
if (bind(list_s, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0 ) {
fprintf(stderr, "Error calling bind()\n");
exit(EXIT_FAILURE);
}
// Listen on socket list_s
if( (listen(list_s, 10)) == -1)
{
fprintf(stderr, "Error Listening\n");
exit(EXIT_FAILURE);
}
// Set up some shared memory to store our shared variables in
// Close the shared memory we use just to be safe
shm_unlink("/sharedmem");
int sharedmem;
// Open the memory
if( (sharedmem = shm_open("/sharedmem", O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR)) == -1)
{
fprintf(stderr, "Error opening sharedmem in main() errno is: %s ", strerror(errno));
exit(EXIT_FAILURE);
}
// Set the size of the shared memory to the size of my structure
ftruncate(sharedmem, sizeof(sharedVariables) );
// Map the shared memory into our address space
sharedVariables *mempointer;
// Set mempointer to point at the shared memory
mempointer = mmap(NULL, sizeof(sharedVariables), PROT_READ | PROT_WRITE, MAP_SHARED, sharedmem, 0);
// Check the memory allocation went OK
if( mempointer == MAP_FAILED )
{
fprintf(stderr, "Error setting shared memory for sharedVariables in recordTotalBytes() error is %d \n ", errno);
exit(EXIT_FAILURE);
}
// Initalise the mutex
pthread_mutex_init(&(*mempointer).mutexlock, NULL);
// Set total bytes sent to 0
(*mempointer).totalbytes = 0;
// Size of the address
int addr_size = sizeof(servaddr);
// Sizes of data were sending out
int headersize;
int pagesize;
int totaldata;
// Number of child processes we have spawned
int children = 0;
// Variable to store the ID of the process we get when we spawn
pid_t pid;
// Loop infinitly serving requests
while(1)
{
// If we haven't already spawned 10 children fork
if( children <= 10)
{
pid = fork();
children++;
}
// If the pid is -1 the fork failed so handle that
if( pid == -1)
{
fprintf(stderr,"can't fork, error %d\n" , errno);
exit (1);
}
// Have the child process deal with the connection
if ( pid == 0)
{
// Have the child loop infinetly dealing with a connection then getting the next one in the queue
while(1)
{
// Accept a connection
conn_s = accept(list_s, (struct sockaddr *)&servaddr, &addr_size);
// If something went wrong with accepting the connection deal with it
if(conn_s == -1)
{
fprintf(stderr,"Error accepting connection \n");
exit (1);
}
// Get the message from the file descriptor
char * header = getMessage(conn_s);
// Parse the request
httpRequest details = parseRequest(header);
// Free header now were done with it
free(header);
// Print out the correct header
headersize = printHeader(conn_s, details.returncode);
// Print out the file they wanted
pagesize = printFile(conn_s, details.filename);
// Increment our count of total datasent by all processes and get back the new total
totaldata = recordTotalBytes(headersize+pagesize, mempointer);
// Print out which process handled the request and how much data was sent
printf("Process %d served a request of %d bytes. Total bytes sent %d \n", getpid(), headersize+pagesize, totaldata);
// Close the connection now were done
close(conn_s);
}
}
}
return EXIT_SUCCESS;
}
Pexec.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
static char* args[512];
pid_t pid;
int command_pipe[2];
#define READ 0
#define WRITE 1
static int command(int input, int first, int last)
{
int pipettes[2];
pipe( pipettes );
pid = fork();
if (pid == 0) {
if (first == 1 && last == 0 && input == 0) {
// First command
dup2( pipettes[WRITE], STDOUT_FILENO );
} else if (first == 0 && last == 0 && input != 0) {
// Middle command
dup2(input, STDIN_FILENO);
dup2(pipettes[WRITE], STDOUT_FILENO);
} else {
// Last command
dup2( input, STDIN_FILENO );
}
if (execvp( args[0], args) == -1)
_exit(EXIT_FAILURE);
}
if (input != 0)
close(input);
close(pipettes[WRITE]);
if (last == 1)
close(pipettes[READ]);
return pipettes[READ];
}
static void cleanup(int n)
{
int i;
for (i = 0; i < n; ++i)
wait(NULL);
}
static int run(char* cmd, int input, int first, int last);
static char line[1024];
static int n = 0; /* number of calls to 'command' */
int main(int argc, char *argv[])
{
while (1) {
// for(int i = 1; i < argc; i++){
// strcat(line, argv[i]);
// strcat(line, " ");
// }
/* Read a command line */
//if (!fgets(line, 1024, stdin))
//return 0;
int InputLength = atoi(getenv("INPUT_LENGTH"));
fread(line, InputLength, 1, stdin);
int input = 0;
int first = 1;
char* cmd = line;
char* next = strchr(cmd, '#'); /* Find first '|' */
while (next != NULL) {
/* 'next' points to '|' */
*next = '\0';
input = run(cmd, input, first, 0);
cmd = next + 1;
next = strchr(cmd, '#'); /* Find next '|' */
first = 0;
}
input = run(cmd, input, first, 1);
cleanup(n);
n = 0;
}
return 0;
}
static void split(char* cmd);
static int run(char* cmd, int input, int first, int last)
{
split(cmd);
if (args[0] != NULL) {
if (strcmp(args[0], "exit") == 0)
exit(0);
n += 1;
return command(input, first, last);
}
return 0;
}
static char* skipwhite(char* s)
{
while (isspace(*s)) ++s;
return s;
}
static void split(char* cmd)
{
cmd = skipwhite(cmd);
char* next = strchr(cmd, ' ');
int i = 0;
while(next != NULL) {
next[0] = '\0';
args[i] = cmd;
++i;
cmd = skipwhite(next + 1);
next = strchr(cmd, ' ');
}
if (cmd[0] != '\0') {
args[i] = cmd;
next = strchr(cmd, '\n');
next[0] = '\0';
++i;
}
args[i] = NULL;
}
input.html
<!DOCTYPE html>
<html>
<style>
input[type=text], select {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
input[type=submit] {
width: 100%;
background-color: #4CAF50;
color: white;
padding: 14px 20px;
margin: 8px 0;
border: none;
border-radius: 4px;
cursor: pointer;
}
input[type=submit]:hover {
background-color: #45a049;
}
div {
border-radius: 5px;
background-color: #f2f2f2;
padding: 20px;
}
</style>
<body>
<h3><center>The Html Page Title </center></h3>
<div>
<form method="POST" action="pexec.cgi">
<label for="cmmd">Command</label>
<input type="text" id="cmmd" name="firstname" placeholder="Enter your Command here and then hit Run! Below">
<label for="lname">Entered Command </label>
<input type="text" id="lname" name="lastname" placeholder="This is what you entered...">
<label for="lname">Standard Output </label>
<input type="text" id="lname" name="lastname" placeholder="Standard Output will be shown here...">
<label for="lname">Standard Error </label>
<input type="text" id="lname" name="lastname" placeholder="standard error will be shown here...">
<input type="submit" value="Run!">
</form>
</div>
</body>
</html>