Reconnect

ubi, code follows. I get a connection to the IOT cloud when starting with attempted = true which prevents the call to isRainForecast() and all is fine.

As soon as calling isRainForecast(), which instantiates a new client connection with the connection to IOT cloud drops. I was trying to work round this by checking status and then calling a reconnect (where my original question came from). I use the existing WiFi connection.

Thank you for looking at this.

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

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
  -----------------------------------------
*/

//weather
String apiKeyOWM = "8ddbf758ac17a2039eeec55db60d56bd";  //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 = true;


void setup() {
  // Initialize serial and wait for port to open:
  Serial.begin(9600);
  unsigned long serialBeginTime = millis();
  while (!Serial && (millis() - serialBeginTime > 5000));

  // 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 = false; //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() {

  
  // Your code here
  
  ArduinoCloud.update();
  
 //  Serial.println(WiFi.status());
  //Serial.println(ArduinoCloud.connected());
 
  if (ArduinoCloud.connected() == 0) {
    //Serial.println("Not connected to Arduino Cloud.");
    //ArduinoCloud.reconnect(&ArduinoIoTPreferredConnection);
  } else {
    //we are connected
    Serial.println("Connected.");
    //ArduinoCloud.update();
    //Serial.println(ArduinoCloud.connected());
  }
  //Serial.println(ArduinoCloud.connected()) 

  if (WiFi.status() == WL_CONNECTED) {

    if (!attempted) {
      
      rainIsImminent = isRainForecast();
      if (rainIsImminent) {
        Serial.println("Rain is forecast.");
      } else {
        Serial.println("Rain is not forecast.");
      }
      
      
      attempted = true;
    }

  }
  
}

void onMinutesRemainingValve1Change() {
  // the minutes remaining has been changed in the web interface

}

bool isRainForecast() {
  //check whether rain is forecast from Open Weather Map
  
  
  WiFiClient webclient;
  String webServerResponse = "";

  //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");
    
    // construct a HTTP request:
    webclient.print("GET /data/2.5/forecast?");
    webclient.print("id=" + weatherLocation);
    webclient.print("&appid=" + apiKeyOWM);
    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);  //this needs to change to a timer
  
  
  while (webclient.connected()) {
    // grab the data coming back from the server
    webServerResponse = webclient.readStringUntil('\n');
  }
  
  if (webServerResponse.indexOf("rain") > -1) {  //does the forecast data contain the word rain?
      return true;
  } else {
      Serial.println("Rain not forecast.");
      return false;
  }
  
}