Hi,
Some puzzling behaviour I'm struggling to decipher and would welcome any pointers.
Code snippet:
while (webclient.connected()) {
webServerResponse = webclient.readStringUntil('\n');
Serial.println(webServerResponse);
}
Serial.println("Got string, parse json");
DeserializationError err = deserializeJson(weatherJson, webServerResponse);
if (err) {
Serial.print(F("deserializeJson() failed with code "));
Serial.println(err.c_str());
}
If I comment out from DeserializationError.... through to the last closing } displayed above, when the sketch runs I can see the full web server response in the serial monitor. When I run the code as above, it appears to connect, then hang, I don't even the the message Got String, parse json.
I'm trying to check for rain in the next 3 hours so I could work round this by quickly searching the webServerResponse string for the word 'rain' but I'd much prefer to check the json properly.
Thoughts would be welcome, full sketch reproduced below. All I'm trying to achieve in the code below is to open web connection to the api at open weather map, once and parse the json - it's part of a larger project.
Many thanks
Sketch:
/*
Sketch generated by the Arduino IoT Cloud Thing "SmartIrrigator"
https://create.arduino.cc/cloud/things/2cc1911c-c24b-49a4-a04c-d2d596ba89aa
Arduino IoT Cloud Properties description
The following variables are automatically generated and updated when changes are made to the Thing properties
bool soilNeedsWatering;
bool valve1isOpen;
int minutesRemainValve1;
float ambientHumidity;
float soilMoisturePC;
float ambientTemperature;
bool rainIsImminent;
int minutesToSunset;
Properties which are marked as READ/WRITE in the Cloud Thing will also have functions
which are called when their values are changed from the Dashboard.
These functions are generated with the Thing and added at the end of this sketch.
*/
#include "thingProperties.h"
#include "SPI.h"
#include "ArduinoJson.h"
const int rainLookForwardHours = 3; //how many hours do we want to check for rain for? 3h feels about right, too far it'll dry out
/*
globals
-----------------------------------------
*/
WiFiClient webclient;
//weather
String apiKeyOWM = "*****API KEY HERE"; //your personal API key from https://openweathermap.org/appid
char weatherServer[] = "api.openweathermap.org";
String weatherLocation = "2640908"; //city id for weather location from https://openweathermap.org/current
//temp
bool attempted = false;
void setup() {
// Initialize serial and wait for port to open:
Serial.begin(9600);
// This delay gives the chance to wait for a Serial Monitor without blocking if none is found
delay(1500);
// Defined in thingProperties.h
initProperties();
// Connect to Arduino IoT Cloud
ArduinoCloud.begin(ArduinoIoTPreferredConnection);
/*
The following function allows you to obtain more information
related to the state of network and IoT Cloud connection and errors
the higher number the more granular information you’ll get.
The default is 0 (only errors).
Maximum is 4
*/
setDebugMessageLevel(2);
ArduinoCloud.printDebugInfo();
/*
initialise application variables
-------------------------------------
*/
//calculated
soilNeedsWatering = false; //result of a calculation
valve1isOpen = true; //state of the first valve
minutesRemainValve1 = 0; //0 to 30
minutesToSunset = 0; //0 to 1500;
rainIsImminent = false; //is it going to rain within the next forecast period defined by rainLookForwardHours
//sensor readings
ambientHumidity = 0; //percentage
ambientTemperature = 0; //-30 to 50
soilMoisturePC = 0; //0 to 100, 0 is bone dry, 100 is water
}
void loop() {
ArduinoCloud.update();
// Your code here
// Serial.println(WiFi.status());
if (WiFi.status() == WL_CONNECTED) {
if (!attempted) {
Serial.println("Connected to Wifi");
getWeather();
attempted = true;
}
}
}
void onMinutesRemainingValve1Change() {
// the minutes remaining has been changed in the web interface
}
void getWeather() {
String webServerResponse = "";
StaticJsonDocument<5000> weatherJson;
Serial.println("\nStarting connection to server...");
// if you get a connection, report back via serial:
if (webclient.connect(weatherServer, 80)) {
Serial.println("connected to server");
// Make a HTTP request:
webclient.print("GET /data/2.5/forecast?");
//webclient.print("q=" + location);
webclient.print("id=" + weatherLocation);
webclient.print("&appid=" + apiKeyOWM);
//webclient.print("&appid= " + apiKeyOpenWeatherMap);
webclient.print("&cnt=3");
webclient.println("&units=metric");
webclient.println("Host: api.openweathermap.org");
webclient.println("Connection: close");
webclient.println();
} else {
Serial.println("unable to connect");
}
delay(1000);
while (webclient.connected()) {
webServerResponse = webclient.readStringUntil('\n');
Serial.println(webServerResponse);
}
Serial.println("Got string, parse json");
DeserializationError err = deserializeJson(weatherJson, webServerResponse);
if (err) {
Serial.print(F("deserializeJson() failed with code "));
Serial.println(err.c_str());
}
}
thingProperties.h
#include <ArduinoIoTCloud.h>
#include <WiFiConnectionManager.h>
const char THING_ID[] = "*************************";
const char SSID[] = SECRET_SSID; // Network SSID (name)
const char PASS[] = SECRET_PASS; // Network password (use for WPA, or use as key for WEP)
void onMinutesRemainingValve1Change();
bool soilNeedsWatering;
bool valve1isOpen;
int minutesRemainValve1;
float ambientHumidity;
float soilMoisturePC;
float ambientTemperature;
bool rainIsImminent;
int minutesToSunset;
void initProperties(){
ArduinoCloud.setThingId(THING_ID);
ArduinoCloud.addProperty(soilNeedsWatering, READ, ON_CHANGE, NULL);
ArduinoCloud.addProperty(valve1isOpen, READ, ON_CHANGE, NULL);
ArduinoCloud.addProperty(minutesRemainValve1, READWRITE, ON_CHANGE, onMinutesRemainingValve1Change);
ArduinoCloud.addProperty(ambientHumidity, READ, ON_CHANGE, NULL);
ArduinoCloud.addProperty(soilMoisturePC, READ, ON_CHANGE, NULL);
ArduinoCloud.addProperty(ambientTemperature, READ, ON_CHANGE, NULL);
ArduinoCloud.addProperty(rainIsImminent, READ, ON_CHANGE, NULL);
ArduinoCloud.addProperty(minutesToSunset, READ, ON_CHANGE, NULL);
}
ConnectionManager *ArduinoIoTPreferredConnection = new WiFiConnectionManager(SSID, PASS);