Json parsing not working with JsonObject using ArduinoJson library - json

I am using the following code to store Config.json file to ESP32 flash memory using SPIFFS
#include <ArduinoJson.h>
#include <FS.h>
#include<SPIFFS.h>
bool loadConfig() {
File configFile = SPIFFS.open("/Config.json", "r");
if (!configFile) {
Serial.println("Failed to open config file");
return false;
}
size_t size = configFile.size();
if (size > 1024) {
Serial.println("Config file size is too large");
return false;
}
// Allocate a buffer to store contents of the file.
std::unique_ptr<char[]> buf(new char[size]);
// We don't use String here because ArduinoJson library requires the input
// buffer to be mutable. If you don't use ArduinoJson, you may as well
// use configFile.readString instead.
configFile.readBytes(buf.get(), size);
Serial.println(buf.get());
StaticJsonBuffer<1024> jsonBuffer;
JsonObject& json = jsonBuffer.parseObject(buf.get());
if (!json.success()) {
Serial.println("Failed to parse config file");
return false;
}
const char* ssid = json["ssid"];
const char* password = json["password"];
// Real world application would store these values in some variables for
// later use.
Serial.print("Loaded ssid: ");
Serial.println(ssid);
Serial.print("Loaded password: ");
Serial.println(password);
return true;
}
void setup() {
Serial.begin(115200);
Serial.println("");
delay(1000);
Serial.println("Mounting FS...");
if (!SPIFFS.begin()) {
Serial.println("Failed to mount file system");
return;
}
if (!loadConfig()) {
Serial.println("Failed to load config");
}
else {
Serial.println("Config loaded");
}
}
void loop() {
yield();
}
However the parsing fails, and I get the following message on the serial monitor:
Mounting FS...
⸮xV⸮⸮⸮⸮⸮
Failed to parse config file
Failed to load config
My Arduino IDE version: 1.8.13 (Windows)
Config file has 2 objects:
{
"ssid": "ESP32",
"password": "Softronics"
}
Thank you in advance

There's no need to pre-allocate a buffer to store the file for ArduinoJSON. ArduinoJSON is quite capable of reading the file itself and avoiding the need to manage a buffer for the file.
This code is unnecessary. You should not allocate a buffer.
std::unique_ptr<char[]> buf(new char[size]);
// We don't use String here because ArduinoJson library requires the input
// buffer to be mutable. If you don't use ArduinoJson, you may as well
// use configFile.readString instead.
configFile.readBytes(buf.get(), size);
Serial.println(buf.get());
StaticJsonBuffer<1024> jsonBuffer;
JsonObject& json = jsonBuffer.parseObject(buf.get());
if (!json.success()) {
Serial.println("Failed to parse config file");
return false;
}
Here's a complete program which works correctly for me:
#include <ArduinoJson.h>
#include <FS.h>
#include<SPIFFS.h>
bool loadConfig() {
File configFile = SPIFFS.open("/Config.json", "r");
if (!configFile) {
Serial.println("Failed to open config file");
return false;
}
size_t size = configFile.size();
if (size > 1024) {
Serial.println("Config file size is too large");
return false;
}
StaticJsonDocument<1024> doc;
DeserializationError error = deserializeJson(doc, configFile);
if(error) {
Serial.println("Failed to parse config file");
return false;
}
const char* ssid = doc["ssid"];
const char* password = doc["password"];
// Real world application would store these values in some variables for
// later use.
Serial.print("Loaded ssid: ");
Serial.println(ssid);
Serial.print("Loaded password: ");
Serial.println(password);
return true;
}
void setup() {
Serial.begin(115200);
Serial.println("");
delay(1000);
Serial.println("Mounting FS...");
if (!SPIFFS.begin()) {
Serial.println("Failed to mount file system");
return;
}
if (!loadConfig()) {
Serial.println("Failed to load config");
}
else {
Serial.println("Config loaded");
}
}
void loop() {
yield();
}
The code you posted was for ArduinoJSON version 5, which is obsolete. This uses ArduinoJSON version 6. You should upgrade your library to use it.
The ArduinoJSON documentation and examples are quite helpful when writing code that uses the library.
Also, please try indenting your code, at least as a courtesy to others if not to do yourself a favor. Proper indentation makes code much more readable.

Related

ESP32 board_POST_Error_[E][WiFiClient.cpp:258] connect(): socket error on fd 56, errno: 113, "Software caused connection abort"

I need to send HTTP POST request using ESP32 module, to my REST API server which coded using python. But when running following code, an error comes. Running on Windows 10 OS. WiFi is connecting with the module. here I need to send "A" to the REST API server.
Code - Running on VSCode PlatformIO IDE.
#include <Arduino.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <Arduino_JSON.h>
const char *ssid = "***need to fill***";
const char *password = "***need to fill***";
const char *serverName = "***need to fill***";
String sensorReadings;
String httpGETRequest(const char *serverName);
void setup()
{
Serial.begin(115200);
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi ..");
while (WiFi.status() != WL_CONNECTED)
{
Serial.print('.');
delay(1000);
}
Serial.println(WiFi.localIP());
}
void loop()
{
//Check WiFi connection status
if (WiFi.status() == WL_CONNECTED)
{
sensorReadings = httpGETRequest(serverName);
Serial.println(sensorReadings);
JSONVar myObject = JSON.parse(sensorReadings);
// JSON.typeof(jsonVar) can be used to get the type of the var
if (JSON.typeof(myObject) == "undefined")
{
Serial.println("Parsing input failed!");
return;
}
Serial.print("JSON object = ");
Serial.println(myObject);
// myObject.keys() can be used to get an array of all the keys in the object
JSONVar keys = myObject.keys();
for (int i = 0; i < keys.length(); i++)
{
JSONVar value = myObject[keys[i]];
Serial.print(keys[i]);
Serial.print(" = ");
Serial.println(value);
}
}
else
{
Serial.println("WiFi Disconnected");
}
delay(2000);
}
String httpGETRequest(const char *serverName)
{
WiFiClient client;
HTTPClient http;
// Your Domain name with URL path or IP address with path
http.begin(client, serverName);
http.addHeader("Content-Type", "application/json");
// Reading one byte from serial buffer
uint8_t buffer;
Serial.readBytes(&buffer, 1);
// Dummy data to check
// this is the hex value for
// 'A' = 0x41
buffer = 0x41;
// creating payload buff
char buff[100];
sprintf(buff, "{\"Serial_Data\": \"%c\"}", buffer);
// Send HTTP POST request
int httpResponseCode = http.POST(buff);
String payload = "{}";
if (httpResponseCode > 0)
{
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
payload = http.getString();
}
else
{
Serial.print("Error code: ");
Serial.println(httpResponseCode);
}
// Free resources
http.end();
return payload;
}
Error comes as below,
[E][WiFiClient.cpp:258] connect(): socket error on fd 54, errno: 113, "Software caused
connection abort"
Error code: -1
{}
JSON object = {}
Though this is very late I have an answer that could help any that will run into this problem. Follow the steps.
Make sure you are running your service on a WiFi IP that your PC and the ESP-32 are connected to. In my case, my Pc is connected to the WiFi with the IP 192.168.43.178 and I am using FastAPI, so I have the following line of code in my run.py
import unicorn
if __name__ == "__main__":
uvicorn.run("app.main:app", host="192.168.43.178", port=8080, reload=True)
Increase the delay. When the dataset is huge, the ESP-32 needs more time to send it, therefore it is necessary to increase the delay to suit your needs of the data sending.

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 to fix no matching function for call in Arduino IDE?

This is my first time using Arduino IDE, and after replacing the jsonBuffer with jsonDOcument, as jsonBuffer was an older version, instructed by the jsonarduino website, and i have received the error message, "no matching function for call to 'ArduinoJson6171_91::BasicJsonDocument<ArduinoJson6171_91::DefaultAllocator>::BasicJsonDocument()'"
What should I do?
This is my code:
#include <FS.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <RCSwitch.h>
#include <WiFiUdp.h>
#include <WiFiManager.h>
#include <ArduinoJson.h>
#include
#ifndef CALLBACKFUNCTION_H //this is the beginning of the callbackfunction script
#define CALLBACKFUNCTION_H
#include <Arduino.h>
typedef void (*CallbackFunction) ();
#endif //this is the end of the callbackfunction script
#ifndef SWITCH_H //this is the beginning of the switch script
#define SWITCH_H
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <WiFiUDP.h>
#include "CallbackFunction.h"
class Switch {
private:
ESP8266WebServer *server = NULL;
WiFiUDP UDP;
String serial;
String persistent_uuid;
String device_name;
unsigned int localPort;
CallbackFunction onCallback;
CallbackFunction offCallback;
void startWebServer();
void handleEventservice();
void handleUpnpControl();
void handleRoot();
void handleSetupXml();
public:
Switch();
Switch(String alexaInvokeName, unsigned int port, CallbackFunction onCallback, CallbackFunction offCallback);
~Switch();
String getAlexaInvokeName();
void serverLoop();
void respondToSearch(IPAddress& senderIP, unsigned int senderPort);
};
#endif //this is the end of the switch script
#include "switch.h"
#include "UpnpBroadcastResponder.h"
#include "CallbackFunction.h"
UpnpBroadcastResponder upnpBroadcastResponder;
Switch *alexa_switch1 = NULL;
Switch *alexa_switch2 = NULL;
Switch *alexa_switch3 = NULL;
Switch *alexa_switch4 = NULL;
Switch *alexa_switch5 = NULL;
// Callback prototypes
void alexa_switch1On();
void alexa_switch1Off();
void alexa_switch2On();
void alexa_switch2Off();
void alexa_switch3On();
void alexa_switch3Off();
void alexa_switch4On();
void alexa_switch4Off();
void alexa_switch5On();
void alexa_switch5Off();
// Set Relay Pins
int relayOne = 12;
int relayTwo = 13;
int relayThree = 14;
int relayFour = 16;
// Names each relay/outlet/device is known by -- these are set during config
char alexa_name1[100] = "1";
char alexa_name2[100] = "2";
char alexa_name3[100] = "3";
char alexa_name4[100] = "4";
char alexa_name5[100] = "5";
const char* AP_Name = "EchoBase1";
char saved_ssid[100] = "";
char saved_psk[100] = "";
// Flag for saving config data
bool shouldSaveConfig = false;
bool forceConfigPortal = false;
WiFiManager wifiManager;
// RF Tooling - https://codebender.cc/sketch:80290#RCSwitch%20-%20Transmit%20(Etekcity%20Power%20Outlets).ino
RCSwitch RFSwitch = RCSwitch();
int RF_PULSE_LENGTH = 179; // Pulse length to use for RF transmitter
int RF_TX_PIN = 0; // Digital pin connected to RF transmitter
int RF_BIT_LENGTH = 24;
// RF Signals (varies per remote controlled plugin set)
unsigned long rc_codes[5][2] = {
// ON //OFF
{5313843, 5313852}, /* Outlet 1 /
{5313987, 5313996}, / Outlet 2 /
{5314307, 5314316}, / Outlet 3 /
{335107, 335116}, / Outlet 4 /
{341251, 341260}, / Outlet 5 */
};
// Callback notifying us of the need to save config
void saveConfigCallback () {
Serial.println("Should save config");
shouldSaveConfig = true;
}
void setup()
{
Serial.begin(115200);
// -- WifiManager handling
// 5-second delay in case you wish to observe boot-up
for(int i=0; i < 5; i++) {
Serial.print(".");
delay(1000);
}
Serial.println("Booting");
// Clean FS, for testing... consider enabling if jumper is in flash mode, etc.
// SPIFFS.format();
// Set the flash/boot pin for input so we can read if the jumper is present
pinMode(0, INPUT);
// If the jumper is in "flash" mode (i.e., pin 0 is grounded), we will be enabling the config portal
forceConfigPortal = (digitalRead(0) == 0);
if(forceConfigPortal) {
Serial.println("Jumper set for flash - will trigger config portal");
} else {
Serial.println("Jumper set for boot - will attempt autoconnect, else config portal");
}
// Read configuration from FS json
Serial.println("Mounting ESP8266 integrated filesystem...");
if (SPIFFS.begin()) {
Serial.println("Mounted file system");
if (SPIFFS.exists("/config.json")) {
Serial.println("Found existing config; reading file");
File configFile = SPIFFS.open("/config.json", "r");
if (configFile) {
Serial.println("Opened config file for reading");
size_t size = configFile.size();
Serial.print("File size (bytes) = ");
Serial.println(size);
// Allocate a buffer to store contents of the file.
std::unique_ptr<char[]> buf(new char[size]);
configFile.readBytes(buf.get(), size);
DynamicJsonDocument jsonDocument;
JsonObject& json = jsonDocument.parseObject(buf.get());
Serial.println("Parsed JSON content:");
json.printTo(Serial);
Serial.println();
if (json.success()) {
strcpy(alexa_name1, json["alexa_name1"]);
strcpy(alexa_name2, json["alexa_name2"]);
strcpy(alexa_name3, json["alexa_name3"]);
strcpy(alexa_name4, json["alexa_name4"]);
strcpy(alexa_name5, json["alexa_name5"]);
Serial.println("Parsed Alexa relay name #1: " + String(alexa_name1));
Serial.println("Parsed Alexa relay name #2: " + String(alexa_name2));
Serial.println("Parsed Alexa relay name CharlesJGantt#3: " + String(alexa_name3));
Serial.println("Parsed Alexa relay name CharlesJGantt#4: " + String(alexa_name4));
Serial.println("Parsed Alexa relay name CharlesJGantt#5: " + String(alexa_name5));
} else {
Serial.println("** ERROR ** Failed to load/parse JSON config");
}
} else {
Serial.println("No JSON file found in filesystem");
}
}
} else {
Serial.println("** ERROR ** Failed to mount ESP8266's integrated filesyste,m");
}
// The extra parameters to be configured (can be either global or just in the setup)
// After connecting, parameter.getValue() will get you the configured value
// id/name placeholder/prompt default length
WiFiManagerParameter custom_alexa_name1("alexa_name1", "Device #1 name", alexa_name1, 100);
WiFiManagerParameter custom_alexa_name2("alexa_name2", "Device #2 name", alexa_name2, 100);
WiFiManagerParameter custom_alexa_name3("alexa_name3", "Device CharlesJGantt#3 name", alexa_name3, 100);
WiFiManagerParameter custom_alexa_name4("alexa_name4", "Device CharlesJGantt#4 name", alexa_name4, 100);
WiFiManagerParameter custom_alexa_name5("alexa_name5", "Device CharlesJGantt#5 name", alexa_name5, 100);
// Set the function that will be called to save the custom parameter after config
wifiManager.setSaveConfigCallback(saveConfigCallback);
// Hand the parameter defintions to the WifiManager for use during config
wifiManager.addParameter(&custom_alexa_name1);
wifiManager.addParameter(&custom_alexa_name2);
wifiManager.addParameter(&custom_alexa_name3);
wifiManager.addParameter(&custom_alexa_name4);
wifiManager.addParameter(&custom_alexa_name5);
//reset settings - for testing
//wifiManager.resetSettings();
//set minimu quality of signal so it ignores AP's under that quality
//defaults to 8%
//wifiManager.setMinimumSignalQuality();
//sets timeout until configuration portal gets turned off
//useful to make it all retry or go to sleep
//in seconds
//wifiManager.setTimeout(120);
if(forceConfigPortal) {
wifiManager.setSTAStaticIPConfig(IPAddress(10,0,1,99), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
// Force config portal while jumper is set for flashing
if (!wifiManager.startConfigPortal(AP_Name)) {
Serial.println("** ERROR ** Failed to connect with new config / possibly hit config portal timeout; Resetting in 3sec...");
delay(3000);
//reset and try again, or maybe put it to deep sleep
ESP.reset();
delay(5000);
}
} else {
// Autoconnect if we can
// Fetches ssid and pass and tries to connect; if it does not connect it starts an access point with the specified name
// and goes into a blocking loop awaiting configuration
if (!wifiManager.autoConnect(AP_Name)) {
Serial.println("** ERROR ** Failed to connect with new config / possibly hit timeout; Resetting in 3sec...");
delay(3000);
//reset and try again, or maybe put it to deep sleep
ESP.reset();
delay(5000);
}
}
// --- If you get here you have connected to the WiFi ---
Serial.println("Connected to wifi");
// Save the connect info in case we need to reconnect
WiFi.SSID().toCharArray(saved_ssid, 100);
WiFi.psk().toCharArray(saved_psk, 100);
// Read updated parameters
strcpy(alexa_name1, custom_alexa_name1.getValue());
strcpy(alexa_name2, custom_alexa_name2.getValue());
strcpy(alexa_name3, custom_alexa_name3.getValue());
strcpy(alexa_name4, custom_alexa_name4.getValue());
strcpy(alexa_name5, custom_alexa_name5.getValue());
Serial.println("Read configured Alexa relay name #1: " + String(alexa_name1));
Serial.println("Read configured Alexa relay name #2: " + String(alexa_name2));
Serial.println("Read configured Alexa relay name CharlesJGantt#3: " + String(alexa_name3));
Serial.println("Read configured Alexa relay name CharlesJGantt#4: " + String(alexa_name4));
Serial.println("Read configured Alexa relay name CharlesJGantt#5: " + String(alexa_name5));
// Save the custom parameters to the ESP8266 filesystem if changed
if (shouldSaveConfig) {
Serial.println("Saving config to ESP8266 filesystem");
DynamicJsonDocument jsonDocument;
JsonObject& json = jsonDocument.createObject();
json["alexa_name1"] = alexa_name1;
json["alexa_name2"] = alexa_name2;
json["alexa_name3"] = alexa_name3;
json["alexa_name4"] = alexa_name4;
json["alexa_name5"] = alexa_name5;
Serial.println("Attempting to open config JSON file for writing");
File configFile = SPIFFS.open("/config.json", "w");
if (!configFile) {
Serial.println("** ERROR ** Failed to open JSON config file for writing");
} else {
json.printTo(Serial);
Serial.println();
json.printTo(configFile);
configFile.close();
Serial.println("File write complete");
}
}
Serial.print("SSID: " );
Serial.println(WiFi.SSID());
Serial.print("Local IP: ");
Serial.println(WiFi.localIP());
// -- ALEXA setup/handling --
upnpBroadcastResponder.beginUdpMulticast();
// Define your switches here. Max 14
// Format: Alexa invocation name, local port no, on callback, off callback
alexa_switch1 = new Switch(alexa_name1, 80, alexa_switch1On, alexa_switch1Off);
alexa_switch2 = new Switch(alexa_name2, 81, alexa_switch2On, alexa_switch2Off);
alexa_switch3 = new Switch(alexa_name3, 82, alexa_switch3On, alexa_switch3Off);
alexa_switch4 = new Switch(alexa_name4, 83, alexa_switch4On, alexa_switch4Off);
alexa_switch5 = new Switch(alexa_name5, 85, alexa_switch5On, alexa_switch5Off);
Serial.println("Adding switches upnp broadcast responder");
upnpBroadcastResponder.addDevice(*alexa_switch1);
upnpBroadcastResponder.addDevice(*alexa_switch2);
upnpBroadcastResponder.addDevice(*alexa_switch3);
upnpBroadcastResponder.addDevice(*alexa_switch4);
upnpBroadcastResponder.addDevice(*alexa_switch5);
// Setup RF Transmitter
RFSwitch.enableTransmit(RF_TX_PIN);
RFSwitch.setPulseLength(RF_PULSE_LENGTH);
}
/* If disconnected from Wifi, enter a blocking loop that periodically attempts reconnection */
void reconnectIfNecessary() {
while(WiFi.status() != WL_CONNECTED) {
Serial.println("Disconnected; Attempting reconnect to " + String(saved_ssid) + "...");
WiFi.disconnect();
WiFi.mode(WIFI_AP_STA);
WiFi.begin(saved_ssid, saved_psk);
// Output reconnection status info every second over the next 10 sec
for( int i = 0; i < 10 ; i++ ) {
delay(1000);
Serial.print("WiFi status = ");
if( WiFi.status() == WL_CONNECTED ) {
Serial.println("Connected");
break;
} else {
Serial.println("Disconnected");
}
}
if(WiFi.status() != WL_CONNECTED) {
Serial.println("Failure to establish connection after 10 sec. Will reattempt connection in 2 sec");
delay(2000);
}
}
}
void loop()
{
// Ensure wifi is connected (won't return until it has connected)
reconnectIfNecessary();
// Respond to any Alexa/discovery requests
upnpBroadcastResponder.serverLoop();
// Respond to any UPnP control requests
alexa_switch1->serverLoop();
alexa_switch2->serverLoop();
alexa_switch3->serverLoop();
alexa_switch4->serverLoop();
alexa_switch5->serverLoop();
}
void alexa_switch1On() {
Serial.println("Switch 1 turn on ...");
enableOutlet(1, true);
}
void alexa_switch1Off() {
Serial.println("Switch 1 turn off ...");
enableOutlet(1, false);
}
void alexa_switch2On() {
Serial.println("Switch 2 turn on ...");
enableOutlet(2, true);
}
void alexa_switch2Off() {
Serial.println("Switch 2 turn off ...");
enableOutlet(2, false);
}
void alexa_switch3On() {
Serial.println("Switch 3 turn on ...");
enableOutlet(3, true);
}
void alexa_switch3Off() {
Serial.println("Switch 3 turn off ...");
enableOutlet(3, false);
}
void alexa_switch4On() {
Serial.println("Switch 4 turn on ...");
enableOutlet(4, true);
}
void alexa_switch4Off() {
Serial.println("Switch 4 turn off ...");
enableOutlet(4, false);
}
void alexa_switch5On() {
Serial.println("Switch 5 turn on ...");
enableOutlet(5, true);
}
void alexa_switch5Off() {
Serial.println("Switch 5 turn off ...");
enableOutlet(5, false);
}
void enableOutlet(int outletNumber, bool onOrOff)
{
if (outletNumber < 1 || outletNumber > 5) {
Serial.println("Invalid outlet number");
return;
}
unsigned long *onOffCodes = rc_codes[outletNumber - 1];
unsigned long codeToSend = onOffCodes[onOrOff ? 0 : 1];
RFSwitch.send(codeToSend, RF_BIT_LENGTH);
char outletNumberString[1];
int retVal = snprintf(outletNumberString, 1, "%d", outletNumber);
if (retVal < 0) {
Serial.println("Log encoding error");
return;
}
Serial.print("Switch " + String(outletNumber) + " turned ");
if (onOrOff) {
Serial.println("on");
} else {
Serial.println("off");
}
}

Parsing data from incoming HTTP Post request on ESP8266/Wemos

I'm sending an HTTP Post request on my Android App to my Wemos D1 mini pro and want to parse the incoming data (which is a json). My current code just prints out the whole POST request and I need to trim it so I only get the needed data. There are several examples out there but nothing matched my needs or worked at all.
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ArduinoJson.h>
const char* ssid = "myssid";
const char* password = "mypassword";
char c;
String readString = String(100);
WiFiServer wifiServer(80);
void setup() {
Serial.begin(9600);
delay(1000);
WiFi.begin(ssid, password);
WiFi.mode(WIFI_STA);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting..");
}
Serial.print("Connected to WiFi. IP:");
Serial.println(WiFi.localIP());
wifiServer.begin();
}
//for parsing the actual JSON later
//you can ignore this at this moment because I don't even get the needed string to parse it from JSON
void handleReceivedMessage(String message){
StaticJsonBuffer<500> JSONBuffer; //Memory pool
JsonObject& parsed = JSONBuffer.parseObject(message); //Parse message
if (!parsed.success()) { //Check for errors in parsing
Serial.println("Parsing failed");
return;
}
const char * name3 = parsed["name"]; //Get name from HTTP
Serial.println("name3");
}
void loop() {
WiFiClient client = wifiServer.available();
if (client) {
Serial.println("Client connected");
while (client.connected()) {
while (client.available()>0) {
//instream from mobile device
char c = client.read();
if (readString.length() < 100) {
//store characters to string
readString.concat(c);
//Serial.print(c);
}
Serial.print(c);
//if HTTP request has ended
if (c == '\n') {
//Serial.println(readString);
delay(50);
//handleReceivedMessage(readString);
readString = "";
client.stop();
}
}}}}
Well first of all you seem to be using ArduinoJson lib version 5, now I could share the code I worked with and never failed me with version 5. But i'm going to encourage you to update the library to version 6 and share with you my piece of code.
I use this normally when I need to get information out of API's
DynamicJsonDocument doc(1024);
char* payload1 = (char*)malloc(http.getSize() + 1);
http.getString().toCharArray(payload1, http.getSize() + 1);
Serial.println(payload1);
http.end();
auto error = deserializeJson(doc, payload1);
free(payload1);
if (error) {
Serial.print(F("deserializeJson() failed with code "));
Serial.println(error.c_str());
return;
}
serializeJsonPretty(doc, Serial);
now as you can see, I'm using a getString method from httpClient lib in order to fill my char array and than parse it into json object (pretty much the same thing you was attempting, only difference is the memory pointers and Memory allocations.
Hopefully this will work with you.

arduino json parser failing to parse a uri

HI I am trying to use the Json Library by Benoit Blanchon 2014-2016 from this URL https://github.com/bblanchon/ArduinoJson
I struggled at first as I had the second generation ethernet shield. Got it going once I realised I needed the second ethernet library.
However I get the error message unable to parse json and I am unsure why, and how debug.
// Sample Arduino Json Web Client
// Downloads and parse http://api.sunrise-sunset.org/json?lat=53.440&lng=0.200&date=today
//
// Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!
#include <ArduinoJson.h>
#include <SPI.h>
#include <Ethernet.h>
EthernetClient client;
const char* server = "api.sunrise-sunset.org"; // server's address
const char* resource = "/json?lat=53.440&lng=0.200&date=today"; // http resource
const unsigned long BAUD_RATE = 9600; // serial connection speed
const unsigned long HTTP_TIMEOUT = 10000; // max respone time from server
const size_t MAX_CONTENT_SIZE = 512; // max size of the HTTP response
// The type of data that we want to extract from the page
struct UserData {
char sunrise[32];
char sunset[32];
};
// ARDUINO entry point #1: runs once when you press reset or power the board
void setup() {
// initSerial();
// initEthernet();
Serial.begin(9600);
Serial.println("Serial ready");
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
byte ip[] = { 192,168,0,202 };
Ethernet.begin(mac, ip);
Serial.println("Ethernet ready");
delay(1000);
}
// ARDUINO entry point #2: runs over and over again forever
void loop() {
if (connect(server)) {
if (sendRequest(server, resource) && skipResponseHeaders()) {
char response[MAX_CONTENT_SIZE];
readReponseContent(response, sizeof(response));
UserData userData;
if (parseUserData(response, &userData)) {
printUserData(&userData);
}
}
disconnect();
}
wait();
}
// Initialize Serial port
void initSerial() {
Serial.begin(BAUD_RATE);
while (!Serial) {
; // wait for serial port to initialize
}
Serial.println("Serial ready");
}
// Initialize Ethernet library
void initEthernet() {
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
if (!Ethernet.begin(mac)) {
Serial.println("Failed to configure Ethernet");
return;
}
Serial.println("Ethernet ready");
delay(1000);
}
// Open connection to the HTTP server
bool connect(const char* hostName) {
Serial.print("Connect to ");
Serial.println(hostName);
bool ok = client.connect(hostName, 80);
Serial.println(ok ? "Connected" : "Connection Failed!");
return ok;
}
// Send the HTTP GET request to the server
bool sendRequest(const char* host, const char* resource) {
Serial.print("GET ");
Serial.println(resource);
client.print("GET ");
client.print(resource);
client.println(" HTTP/1.1");
client.print("Host: ");
client.println(server);
client.println("Connection: close");
client.println();
return true;
}
// Skip HTTP headers so that we are at the beginning of the response's body
bool skipResponseHeaders() {
// HTTP headers end with an empty line
char endOfHeaders[] = "\r\n\r\n";
client.setTimeout(HTTP_TIMEOUT);
bool ok = client.find(endOfHeaders);
if (!ok) {
Serial.println("No response or invalid response!");
}
return ok;
}
// Read the body of the response from the HTTP server
void readReponseContent(char* content, size_t maxSize) {
size_t length = client.readBytes(content, maxSize);
content[length] = 0;
Serial.println(content);
}
// Parse the JSON from the input string and extract the interesting values
// Here is the JSON we need to parse
//{
// "results":{
// "sunrise":"5:45:00 AM",
// "sunset":"5:58:51 PM",
// "solar_noon":"11:51:55 AM",
// "day_length":"12:13:51",
// "civil_twilight_begin":"5:10:15 AM",
// "civil_twilight_end":"6:33:36 PM",
// "nautical_twilight_begin":"4:28:54 AM",
// "nautical_twilight_end":"7:14:57 PM",
// "astronomical_twilight_begin":"3:45:29 AM",
// "astronomical_twilight_end":"7:58:22 PM"
// },
// "status":"OK"
//}
bool parseUserData(char* content, struct UserData* userData) {
// Compute optimal size of the JSON buffer according to what we need to parse.
// This is only required if you use StaticJsonBuffer.
const size_t BUFFER_SIZE =
JSON_OBJECT_SIZE(2) // the root object has 2 elements
+ JSON_OBJECT_SIZE(10); // the "result" object has 10 elements
// Allocate a temporary memory pool on the stack
StaticJsonBuffer<BUFFER_SIZE> jsonBuffer;
// If the memory pool is too big for the stack, use this instead:
// DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.parseObject(content);
if (!root.success()) {
Serial.println("JSON parsing failed!");
return false;
}
// Here were copy the strings we're interested in
strcpy(userData->sunrise, root["results"]["sunrise"]);
strcpy(userData->sunset, root["results"]["sunset"]);
// It's not mandatory to make a copy, you could just use the pointers
// Since, they are pointing inside the "content" buffer, so you need to make
// sure it's still in memory when you read the string
return true;
}
// Print the data extracted from the JSON
void printUserData(const struct UserData* userData) {
Serial.print("Name = ");
Serial.println(userData->sunrise);
Serial.print("Company = ");
Serial.println(userData->sunset);
}
// Close the connection with the HTTP server
void disconnect() {
Serial.println("Disconnect");
client.stop();
}
// Pause for a 1 minute
void wait() {
Serial.println("Wait 60 seconds");
delay(60000);
}
There is a 161 before the JSON string because the server is using Chunked transfer encoding.
It is a feature of the HTTP 1.1 specification and the only way to disable it is to use HTTP 1.0 in the request.
See:
New JsonHttpClient.ino, which uses HTTP 1.0 and doesn't require the response buffer.
FAQ: Why parsing fails?