bblanchon / ArduinoJson

📟 JSON library for Arduino and embedded C++. Simple and efficient.
https://arduinojson.org
MIT License
6.69k stars 1.12k forks source link

Fail to send data to TD using MessagePack, all records turn to NULL #843

Closed nakajimajunko closed 5 years ago

nakajimajunko commented 5 years ago

Hi,

I tried to send data from arduino to TD using ArduinoJson v.6.5.0 to use MsgPack.

#include <ArduinoHttpClient.h>
#include <ArduinoJson.h>
#include <ArduinoJson.hpp>

const char DEVICEID[] = "Arduino_MKR_WIFI_1010";
int tempPin = A1; //the analog pin the sensor's Vout (sense) pin is connected to

float get_temperature(){
  int reading = analogRead(tempPin);
  float voltage = reading * 3.3;
  voltage /= 1024.0;
  // Print tempeature in Celsius
  float temperatureC = (1.8 - voltage) * 100 ; //Change here to adjust to your sensor
  return temperatureC;
}

const char server[] = "in.treasuredata.com";
const char database[] = "iot_test/arduino"; // destination database
String path = "/postback/v3/event/"+String(database)+"?td_write_key="+String(SECRET_TD_API_KEY);

WiFiClient client;
HttpClient http = HttpClient(client, server);
int statusCode = 0;

//Message Pack generator
StaticJsonDocument<200> doc;
JsonObject root = doc.to<JsonObject>();
char output[200];

void loop() {
  // Build MessagePack data
  root["deviceid"] = DEVICEID;
  root["temp"] = get_temperature();
  serializeJson(root, output);

  // Do the HTTP POST 
  http.post(path, "application/x-msgpack", output);

  // Get status code
  statusCode = http.responseStatusCode();
  http.responseBody(); // flush response body

  Serial.print("Status code: ");
  Serial.println(statusCode);

  http.stop();

  delay(10000);
}

Status code 200 was returned, but records other than time in TD turned NULL. How should I fix my code?

Thanks, Junko

bblanchon commented 5 years ago

Hi @nakajimajunko,

You forgot to replace serializeJson() with serializeMsgPack().

Regards, Benoit

nakajimajunko commented 5 years ago

Hi @bblanchon ,

Sorry for pasting wrong code. My code is:

#include <ArduinoHttpClient.h>
#include <ArduinoJson.h>
#include <ArduinoJson.hpp>

const char DEVICEID[] = "Arduino_MKR_WIFI_1010";
int tempPin = A1; //the analog pin the sensor's Vout (sense) pin is connected to

float get_temperature(){
  int reading = analogRead(tempPin);
  float voltage = reading * 3.3;
  voltage /= 1024.0;
  // Print tempeature in Celsius
  float temperatureC = (1.8 - voltage) * 100 ; //Change here to adjust to your sensor
  return temperatureC;
}

const char server[] = "in.treasuredata.com";
const char database[] = "iot_test/arduino"; // destination database
String path = "/postback/v3/event/"+String(database)+"?td_write_key="+String(SECRET_TD_API_KEY);

WiFiClient client;
HttpClient http = HttpClient(client, server);
int statusCode = 0;

//Message Pack generator
StaticJsonDocument<200> doc;
JsonObject root = doc.to<JsonObject>();
char output[200];

void loop() {
  // Build MessagePack data
  root["deviceid"] = DEVICEID;
  root["temp"] = get_temperature();
  serializeMsgPack(root, output);

  // Do the HTTP POST 
  http.post(path, "application/x-msgpack", output);

  // Get status code
  statusCode = http.responseStatusCode();
  http.responseBody(); // flush response body

  Serial.print("Status code: ");
  Serial.println(statusCode);

  http.stop();

  delay(10000);
}

This code returned status code 200, but records in TD are all NULL. I'd like to know how to fix it.

Thanks, Junko

bblanchon commented 5 years ago

Hi Junko,

You forgot to specify the content length. You need to save the result from serializeMsgPack(); it's the number of bytes written in output. Then you need to pass this value to post().

I think it's something like that:

size_t contentLength = serializeMsgPack(root, output);
http.post(path, "application/x-msgpack", contentLength, output);

If it's still not working, here is what you should do to diagnose the problem.

First, use cURL on your computer to send the POST request to Treasure Data. You can use an online service to generate the MessagePack payload. If you cannot send the data with cURL, then it's no use trying with your microcontroller. I cannot help you in this step since I never used Treasure Data.

After you found the right recipe with cURL, you can reproduce the query with your microcontroller. If it doesn't work, see how the query differs from the one sent by cURL. Is the payload properly encoded by ArduinoJson? Are the same header sent? Etc.

Regards, Benoit

nakajimajunko commented 5 years ago

Hi @bblanchon Thank you for kind and detailed help. I found that curl also doesn't work, thus asked TD support and got an answer that they don't support msgpack. I really appreciate your help! Thank you, Junko

bblanchon commented 5 years ago

You're welcome Junko. Thanks for using ArduinoJson. Don't hesitate to cast a star if you like this project 😉