Cocos2dx Web services Json - json

I am new in cocos2dx .. I have some doubts in json parsing . I have got messages from server .But I cant post messages to the server . here i paste the code of getmessages. Plz hel me to post messages.Thanks in Advance.
void ChatRoom::function()
{
std::vector<std::string> headers;
headers.push_back("Content-Type: application/json; charset=utf-8");
cocos2d::extension::CCHttpRequest * request = new cocos2d::extension::CCHttpRequest();
request->setUrl("url here");
const char* postData ="chatManagerRequestType=GET_MESSAGES_AFTER_CHAT_ENABLED";
request->setRequestType(cocos2d::extension::CCHttpRequest::kHttpGet);
request->setResponseCallback(this, httpresponse_selector(ChatRoom::onHttpRequestCompleted));
request->setRequestData(postData, strlen(postData));
request->setHeaders(headers);
cocos2d::extension::CCHttpClient::getInstance()->send(request);
request->release();
}
void ChatRoom::onHttpRequestCompleted(cocos2d::CCNode *sender, void *data)
{
cocos2d::extension::CCHttpResponse * response = (cocos2d::extension::CCHttpResponse *)data;
if (!response)
{
return;
} std::string command;
if (0 != strlen(response->getHttpRequest()->getTag()))
{
command = response->getHttpRequest()->getTag();
CCLog("%s completed", response->getHttpRequest()->getTag());
}
int statusCode = response->getResponseCode();
char statusString[64] = {};
sprintf(statusString, "HTTP Status Code: %d, tag = %s", statusCode, response->getHttpRequest()->getTag());
CCLog("response code: %d", statusCode);
if (!response->isSucceed())
{
CCLog("response failed");
CCLog("error buffer: %s", response->getErrorBuffer());
return;
}
std::vector<char> * buffer = response->getResponseData();
char * concatenated = (char *) malloc(buffer->size() + 1);
std::string s2(buffer->begin(), buffer->end());
strcpy(concatenated, s2.c_str());
CCLOG("%s",s2.c_str());
CCArray *arry=new CCArray();
printf("Http Test, dump data: ");
std::string tstr;
for (unsigned int i = 0; i < buffer->size(); i++)
{
char s[10];
sprintf(s, "%c",(*buffer)[i]);
tstr += (*buffer)[i];
arry->addObject((CCObject*)s);
}
for (int i=0; i<9; i++) {
cocos2d::extension::Json * jsondd = cocos2d::extension::Json_create(concatenated);
cocos2d::extension::Json *json1 = cocos2d::extension::Json_getItem(jsondd, "chatValueList");
cocos2d::extension::Json *json2 = cocos2d::extension::Json_getItemAt (json1, 0);
cocos2d::extension::Json *json3 = cocos2d::extension::Json_getItem(json2,"message");
cocos2d::extension::Json *json31 = cocos2d::extension::Json_getItem(json2,"chatId");
cocos2d::extension::Json *json4= cocos2d::extension::Json_getItem(json2,"userValue");
cocos2d::extension::Json *json5= cocos2d::extension::Json_getItem(json4,"userName");
cocos2d::extension::Json *json6= cocos2d::extension::Json_getItem(json4,"emailId");
val1 = json5->valuestring;
val2 = json3->valuestring;
val3 = json31->valueint;
CCLOG("value:%s %s %d",val1.getCString(),val2.getCString(),val3);
}
}

First of all, to post data using http you have to use kHttpPost not kHttpGet. So if you just set the request type to CCHttpRequest::kHttpPost you will be able to send your post data to server.
Second, if you are not having trouble with json then don't mention it in the question title. It misleads the users.

Related

trying to deserialize JSON unsuccesfully

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);
}

C- HTTP web server: how to cache

I know that by using wget INSIDE my c program for the server, this is possible. For example, we have to wget facebook.com. Then a file called index.html will be downloaded to my laptop. After that, we have to call in /facebook.com/index.html to the web server through the web browser once more. Any idea on how to do this? I tried to do this but this is wrong.
int connection(int fd, int portnum) {
char request[500], resource[500], answer, *ptr;
int fd1, length,c1,c2;
if (recv_new(fd, request) == 0) {
printf("Receive Failed\n");
}
printf("%s\n", request);
// Check for a valid browser request
ptr = strstr(request, " HTTP/");
if (ptr == NULL) {
printf("NOT HTTP !\n");
} else {
*ptr = 0;
ptr = NULL;
if (strncmp(request, "GET ", 4) == 0) {
ptr = request + 4;
}
if (ptr == NULL) {
printf("Unknown Request ! \n");
} else {
if (ptr[strlen(ptr) - 1] == '/') {
strcat(ptr, "test.html");
}
char s1[100] = "facebook.com";
char s2[100] = "twitter.com";
c1 = strncmp(s1,ptr,100);
c2 = strncmp(s2,ptr,100);
if((c1==0)||(c2==0))
{
printf("ACCESS DENIED\n");
}
//how to compare strings
strcpy(resource, webroot());
strcat(resource, ptr);
char* s = strchr(ptr, '.');
int i;
for (i = 0; extensions[i].ext != NULL; i++) {
if (strcmp(s + 1, extensions[i].ext) == 0) {
fd1 = open(resource, O_RDONLY, 0);
printf("Opening \"%s\"\n", resource);
system("wget -E -H -k -K -p localhost:8888"); //lets assume that this is the default port number
printf("Do you want to reload your recent website?\n");
scanf(" %c", &answer);
if(answer=='Y'||answer=='y')
{
fd1 = open(resource, O_RDONLY, 0);
printf("Opening \"%s\"\n", resource);
}
Have a look at the curl library. It allows you to do what you need and much more..
https://curl.haxx.se/

How to get all html file with a HTTP GET request using c++?

I need to create a c++ console application that query a site in turn to get the html page.
The site is static because when I queried it in the url I see the html file, so I use this code:
send(Socket, "GET /it/ricette/q-torte_forno_statico.html HTTP/1.1\r\nHost: worldrecipes.expo2015.org/\r\nConnection: close\r\n\r\n", strlen("GET /it/ricette/q-torte_forno_statico.html HTTP/1.1\r\nHost: worldrecipes.expo2015.org\r\nConnection: close\r\n\r\n"), 0);
char buffer[1000000];
int nDataLength;
while ((nDataLength = recv(Socket, buffer, 1000000, 0)) > 0) {
int i = 0;
while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r') {
cout << buffer[i];
i += 1;
}
}
It doesn't give me any errors but don't show me the whole html page and every time that I call send the request I get different answers ... why?
This code below seems to only work on the index page worldrecipes.expo2015.org and not the sub pages. You might want to look at more advanced webbrowser controls for visual studio for parsing and processing HTML.
Like here : http://www.codeproject.com/Articles/3365/Embed-an-HTML-control-in-your-own-window-using-pla
here : https://msdn.microsoft.com/en-us/library/aa752046(v=vs.85).aspx
and here : http://www.codeproject.com/Articles/3919/Using-the-WebBrowser-control-simplified
Example code:
#include <windows.h>
#include <string>
#include <stdio.h>
using std::string;
#pragma comment(lib,"ws2_32.lib")
HINSTANCE hInst;
WSADATA wsaData;
void mParseUrl(char *mUrl, string &serverName, string &filepath, string &filename);
SOCKET connectToServer(char *szServerName, WORD portNum);
int getHeaderLength(char *content);
char *readUrl2(char *szUrl, long &bytesReturnedOut, char **headerOut);
int main()
{
const int bufLen = 1024;
char *szUrl = "http://worldrecipes.expo2015.org/it/ricette/q-torte_forno_statico.html";
long fileSize;
char *memBuffer, *headerBuffer;
FILE *fp;
memBuffer = headerBuffer = NULL;
if ( WSAStartup(0x101, &wsaData) != 0)
return -1;
memBuffer = readUrl2(szUrl, fileSize, &headerBuffer);
printf("returned from readUrl\n");
printf("data returned:\n%s", memBuffer);
if (fileSize != 0)
{
printf("Got some data\n");
fp = fopen("downloaded.file", "wb");
fwrite(memBuffer, 1, fileSize, fp);
fclose(fp);
// SetDlgItemText(hwndDlg, IDC_EDIT4, headerBuffer);
// SetDlgItemText(hwndDlg, IDC_EDIT5, memBuffer);
delete(memBuffer);
delete(headerBuffer);
}
WSACleanup();
return 0;
}
void mParseUrl(char *mUrl, string &serverName, string &filepath, string &filename)
{
string::size_type n;
string url = mUrl;
if (url.substr(0,7) == "http://")
url.erase(0,7);
if (url.substr(0,8) == "https://")
url.erase(0,8);
n = url.find('/');
if (n != string::npos)
{
serverName = url.substr(0,n);
filepath = url.substr(n);
n = filepath.rfind('/');
filename = filepath.substr(n+1);
}
else
{
serverName = url;
filepath = "/";
filename = "";
}
}
SOCKET connectToServer(char *szServerName, WORD portNum)
{
struct hostent *hp;
unsigned int addr;
struct sockaddr_in server;
SOCKET conn;
conn = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (conn == INVALID_SOCKET)
return NULL;
if(inet_addr(szServerName)==INADDR_NONE)
{
hp=gethostbyname(szServerName);
}
else
{
addr=inet_addr(szServerName);
hp=gethostbyaddr((char*)&addr,sizeof(addr),AF_INET);
}
if(hp==NULL)
{
closesocket(conn);
return NULL;
}
server.sin_addr.s_addr=*((unsigned long*)hp->h_addr);
server.sin_family=AF_INET;
server.sin_port=htons(portNum);
if(connect(conn,(struct sockaddr*)&server,sizeof(server)))
{
closesocket(conn);
return NULL;
}
return conn;
}
int getHeaderLength(char *content)
{
const char *srchStr1 = "\r\n\r\n", *srchStr2 = "\n\r\n\r";
char *findPos;
int ofset = -1;
findPos = strstr(content, srchStr1);
if (findPos != NULL)
{
ofset = findPos - content;
ofset += strlen(srchStr1);
}
else
{
findPos = strstr(content, srchStr2);
if (findPos != NULL)
{
ofset = findPos - content;
ofset += strlen(srchStr2);
}
}
return ofset;
}
char *readUrl2(char *szUrl, long &bytesReturnedOut, char **headerOut)
{
const int bufSize = 512;
char readBuffer[bufSize], sendBuffer[bufSize], tmpBuffer[bufSize];
char *tmpResult=NULL, *result;
SOCKET conn;
string server, filepath, filename;
long totalBytesRead, thisReadSize, headerLen;
mParseUrl(szUrl, server, filepath, filename);
///////////// step 1, connect //////////////////////
conn = connectToServer((char*)server.c_str(), 80);
///////////// step 2, send GET request /////////////
sprintf(tmpBuffer, "GET %s HTTP/1.0", filepath.c_str());
strcpy(sendBuffer, tmpBuffer);
strcat(sendBuffer, "\r\n");
sprintf(tmpBuffer, "Host: %s", server.c_str());
strcat(sendBuffer, tmpBuffer);
strcat(sendBuffer, "\r\n");
strcat(sendBuffer, "\r\n");
send(conn, sendBuffer, strlen(sendBuffer), 0);
// SetWindowText(edit3Hwnd, sendBuffer);
printf("Buffer being sent:\n%s", sendBuffer);
///////////// step 3 - get received bytes ////////////////
// Receive until the peer closes the connection
totalBytesRead = 0;
while(1)
{
memset(readBuffer, 0, bufSize);
thisReadSize = recv (conn, readBuffer, bufSize, 0);
if ( thisReadSize <= 0 )
break;
tmpResult = (char*)realloc(tmpResult, thisReadSize+totalBytesRead);
memcpy(tmpResult+totalBytesRead, readBuffer, thisReadSize);
totalBytesRead += thisReadSize;
}
headerLen = getHeaderLength(tmpResult);
long contenLen = totalBytesRead-headerLen;
result = new char[contenLen+1];
memcpy(result, tmpResult+headerLen, contenLen);
result[contenLen] = 0x0;
char *myTmp;
myTmp = new char[headerLen+1];
strncpy(myTmp, tmpResult, headerLen);
myTmp[headerLen] = NULL;
delete(tmpResult);
*headerOut = myTmp;
bytesReturnedOut = contenLen;
closesocket(conn);
return(result);
}

Converting a MySQL result into a JSON string in C

How do I convert a result from a MySQL query to a JSON string in C?
Of course I know how to do it, I just wondered if there's already a solution to copy-paste, realizing I don't want to write boiler-plate code.
And how do I Google for this question? Google just disregard the c and shows results for PHP etc.
The C file I made to do this is four times faster than the corresponding PHP file, using ab to measure performance:
ab -k -c 300 -n 10000 localhost/tiny.php
Time per request: 393.072 [ms] (mean)
With C:
ab -k -c 300 -n 10000 localhost/cgi/tiny.fcgi
Time per request: 98.237 [ms] (mean)
This is assuming Apache spawns 10 processes of tiny.fcgi, and PHP does not use FastCGI.
FastCgiServer /var/www/cgi/tiny.fcgi -processes 10
This is the PHP code, which connects to MySQL, fetch a query result and echo the JSON representation:
<?php
$mysqli = mysqli_connect("localhost", "user", "password", "db");
mysqli_set_charset($mysqli, "utf8");
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
$result = mysqli_query($mysqli, "SELECT * FROM table");
$rows = array();
while ($row = mysqli_fetch_assoc($result)) {
$rows[] = $row;
}
echo json_encode($rows);
Let's step through the C code. I will use the PHP internal struct smart_str to handle strings (this is what PHP use in the json_encode function). Using the naive char* for strings will be catastrophical, because the number of malloc and free will be huge due to string append usage.
We want to use FastCGI:
#include "fcgi_stdio.h"
int main(void)
{
while(FCGI_Accept() >= 0)
{
}
FCGI_Finish();
return 0;
}
Analysing this with valgrind gives 768 bytes still reachable at end, which we will ignore (bug in FastCGI probably).
Next comes MySQL connection and query:
MYSQL* connection = NULL;
MYSQL_RES* result = NULL;
connection = mysql_init(NULL);
if (connection == NULL)
{
(void) FCGI_fprintf(FCGI_stderr, "Could not connect to MySQL: %s\n", mysql_error(connection));
continue;
}
// Connect to database
if (mysql_real_connect(connection, "localhost", "user", "password", "db", 0, NULL, 0) == NULL)
{
close_mysql_with_error(connection);
continue;
}
// Select from pages
if (mysql_query(connection, "SELECT * FROM table") != 0)
{
close_mysql_with_error(connection);
continue;
}
// Get result
result = mysql_store_result(connection);
// Abort if no result
if (result == NULL)
{
close_mysql_with_error(connection);
continue;
}
(I use continue instead of exit or return, because this code is within the while loop seen above.)
Nothing strange here, right?
The next part will create our smart_str JSON variable, pass it to function result_to_json and then echo the result.
smart_str json = {0, 0, 0};
result_to_json(result, &json);
if (json.c != NULL)
(void) FCGI_printf("json = %s\n", json.c);
smart_str_free(&json);
The result_to_json is just a loop over the rows in the MySQL result:
static void result_to_json(MYSQL_RES *result, smart_str* json)
{
MYSQL_ROW row;
int i;
int num_fields = (int) mysql_num_fields(result);
smart_str** fields = get_field_names(result, num_fields);
if (fields == NULL)
{
return;
}
smart_str_appendc(json, '[');
while ((row = mysql_fetch_row(result, num_fields)))
{
smart_str_appendl(json, "{", 1);
for (i = 0; i < num_fields; i++)
{
// key
smart_str_appendl(json, "\"", 1);
smart_str_appendl(json, fields[i]->c, fields[i]->len);
smart_str_appendl(json, "\": ", 3);
if (row[i] == NULL)
{
smart_str_appendl(json, "null", 4);
smart_str_appendl(json, ", ", 2);
}
else
{
smart_str_appendl(json, "\"", 1);
smart_str_appendl(json, row[i], strlen(row[i]));
smart_str_appendl(json, "\", ", 3);
}
}
if (json == NULL) {
free_field_names(fields, num_fields);
return;
}
// Strip last ','
json->len--;
json->len--;
smart_str_appendl(json, "}, ", 3);
}
if (json == NULL)
{
free_field_names(fields, num_fields);
return;
}
// Strip last ','
json->len--;
json->len--;
smart_str_appendl(json, "]", 1);
smart_str_0(json);
free_field_names(fields, num_fields);
return;
}
Finally, get_field_names and free_field_names:
static smart_str** get_field_names(MYSQL_RES *my_result, int num_fields)
{
smart_str** fields; // Array of pointers
MYSQL_FIELD *field = NULL;
int i;
// Allocate size of array
fields = malloc(num_fields * sizeof(smart_str*));
if (fields == NULL)
{
return NULL;
}
for (i = 0; i < num_fields; i++)
{
field = mysql_fetch_field(my_result);
if (field == NULL) {
// TODO: Free fields[]
free(fields);
return NULL;
}
fields[i] = malloc(sizeof(smart_str));
if (fields[i] == NULL) {
// TODO: Free fields[]
free(fields);
return NULL;
}
else
{
fields[i]->c = NULL;
smart_str_appendl(fields[i], field->name, strlen(field->name));
}
return fields;
}
static void free_field_names(smart_str** strings, int size)
{
int i;
for (i = 0; i < size; i++)
{
smart_str_free(strings[i]);
free(strings[i]);
}
free(strings);
}
There you go! What's left to do is to measure against FastCGI enabled PHP, to see how much the PHP performance improves.

Sending Data to WEB server: Data is being sent, but only once

This code sends data to my server, where it is being get with php and sent to mysql.
The main problem is, that I use cycle void loop(), but it does its task only once. If I will reset the Arduino, then it sends data twice and so on.. I have tried to to send multiple data with delays without a cycle, but it repeatedly sends data, that was send first.. Help :)
#include <SPI.h>
#include <Ethernet.h>
#include <stdlib.h> //Including libraries
int moi_int = 12;
int temp_int = 13; //doing some convertion
int moi_int1 = moi_int %10;
int moi_int2 = moi_int - moi_int1;
int moi_int3 = moi_int2/10;
char moi1 = (char)(((int)'0')+moi_int1);
char moi2 = (char)(((int)'0')+moi_int3);
int temp_int1 = temp_int %10;
int temp_int2 = temp_int - temp_int1;
int temp_int3 = temp_int2/10;
char temp1 = (char)(((int)'0')+temp_int1); //convertion
char temp2 = (char)(((int)'0')+temp_int3);
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte server[] = { my server };
IPAddress ip(my ip);
EthernetClient client;
void setup() {
Serial.begin(9600);
}
void SendInfo() //Info
{
char string[29]; //Here is displayed by char some adress (data) I need to send
string[0] = 'G'; string[1] = 'E'; string[2] = 'T'; string[3] = ' '; string[4] = '/'; string[5] = 'a'; string[6] = 'd'; string[7] = 'd';
string[8] = '.'; string[9] = 'p'; string[10] = 'h'; string[11] = 'p'; string[12] = '?'; string[13] = 't'; string[14] = 'e'; string[15] = 'm';
string[16] = 'p'; string[17] = '1'; string[18] = '='; string[19] = temp2; string[20] = temp1; string[21] = '&'; string[22] = '&';
string[23] = 'm'; string[24] = 'o'; string[25] = 'i'; string[26] = '1'; string[27] = '='; string[28] = moi2; string[29] = moi1;
String adresas(string);
client.println(adresas); // Sending Data
client.print(" HTTP/1.1");
client.println( "Host: my server" );
client.println("Connection: close");
client.println();
}
void Connect() //Connecting
{
Ethernet.begin(mac, ip);
delay(1000);
if (client.connect(server, 80)) {
delay(1000);
SendInfo();
delay(1000);
}
else Serial.println("connection failed");
}
void loop() //Main Loop
{
Connect();
}
You should call begin() only once in the setup:
void setup() {
...
Ethernet.begin()
You call
client.connect(server, 80)
but never a matching disconnect. You need to add one of these to cleanup the connection:
if (client.connect(server, 80)) {
...
client.stop();
}
An alternate approach is to re-user the previously opened connection on each loop.
// open the connection if needed
if(!client.connected()) {
client.connect(server, 80);
}
// ensure connection is available before trying to write
if(client.connected()) {
// do something with connection
}
If you are going to be transmitting very frequent small data, then this second approach is better because less time is wasted to the open/close of the connection.