Strange behaviour of client.readStringUntil('\r')

When I launch the function getWeather() from setup() the client.readStringUntil('\r') works, but when launched by RTCZero alarm trigger it seems to crash.

#include <SPI.h>
#include <SD.h>
#include <WiFiNINA.h>
#include <ArduinoJson.h>
#include <RTCZero.h>

char ssid[] = "xxxxxxx";                                // WiFi SSID
char pass[] = "xxxxxxx";                           // Wifi Key

WiFiClient client;
RTCZero rtc;                                            // Real Time Clock
const int GMT = 2;                                      // Change this to adapt it to your time zone
int status = WL_IDLE_STATUS;
String location = "offida,IT";                          // OpenWeatherMap location
String apiKey = "1111111111";                           // OpenWeatherMap test Key
char server[] = "api.openweathermap.org";               // OpenWeatherMap Server


void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ;
  }
  Serial.println("     *** Infosphere Microcontroller Testing Board ***");

  // Connect to Wifi network
  while (status != WL_CONNECTED) {
    Serial.print("Connecting to ");
    Serial.print(ssid);
    Serial.print("...");
    status = WiFi.begin(ssid, pass);
    // wait 1 seconds for connection:
    delay(1000);
  }
  Serial.println(" Connected.");

  rtc.begin();

  // Set Time via NTP
  Serial.println("Retriving NTP Time...");
  unsigned long epoch;
  int numberOfTries = 0, maxTries = 10;
  do {
    epoch = WiFi.getTime();
    numberOfTries++;
    delay(1000);
  }
  while ((epoch == 0) && (numberOfTries < maxTries));
  if (numberOfTries == maxTries) {
    Serial.println(" NTP unreachable");
    while (1);
  }
  else {
    rtc.setEpoch(epoch);
  }

  /*****************************************************
  ***                   Scheduler                    ***
  ******************************************************/
  Serial.println("Waiting schedule time for starting jobs...");
  rtc.setAlarmTime(13 - GMT, 19, 0);                               // Set time here
  rtc.enableAlarm(rtc.MATCH_HHMMSS);
  rtc.attachInterrupt(midnightJobs);


  Serial.println(getWeather());
}

void loop()
{ }

// 
int getWeather() {
  int rain_prob_index = 0;
  Serial.println("\nConnecting to OpenWeatherMap API...");
  if (client.connect(server, 80)) {
    Serial.println("Connected. Retriving weather forecast for the next 24 hours...");
    client.print("GET /data/2.5/forecast?");
    client.print("q=" + location);
    client.print("&appid=" + apiKey);
    client.print("&cnt=8");
    client.println("&units=metric");
    client.println("Host: api.openweathermap.org");
    client.println("Connection: close");
    client.println();
  } else {
    Serial.println("Unable to connect to OpenWeatherMap");
  }
  // read OpenWeatherMap response

  String line = "";
  while (client.connected()) {
    line = client.readStringUntil('\r');
    client.flush();
  }
  client.stop();
  Serial.println(line);
  return rain_prob_index;
}

/*****************************************************
***               Midnight Jobs                    ***
******************************************************/

void midnightJobs()
{
  Serial.println(getWeather());
}

Can you please help?

Thanks,
Dan

Please show us. I never see you use 'RTCZero'

My board is an MKR1010 (same hw as Arduino Zero). RTCZero library works perfectly, adding a real time clock without any additional hw.

Thanks for any comment,

Dan

Any ideas?

Thanks

You still have NOT

septillion:
Please show us. I never see you use 'RTCZero'

So where is you code?

The code was the first thing I posted... Anyway please find it below (again)

Thanks for your help

Dan

#include <SPI.h>
#include <SD.h>
#include <WiFiNINA.h>
#include <RTCZero.h>

char ssid[] = "xxxxxxxx";                                // WiFi SSID
char pass[] = "xxxxxxxx";                           // Wifi Key

WiFiClient client;
RTCZero rtc;                                            // Real Time Clock
const int GMT = 2;                                      // Change this to adapt it to your time zone
int status = WL_IDLE_STATUS;
String location = "offida,IT";                          // OpenWeatherMap location
String apiKey = "1111111111";                           // OpenWeatherMap test Key
char server[] = "api.openweathermap.org";               // OpenWeatherMap Server

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ;
  }

  // Connect to Wifi network
  while (status != WL_CONNECTED) {
    Serial.print("Connecting to ");
    Serial.print(ssid);
    Serial.print("...");
    status = WiFi.begin(ssid, pass);
    // wait 1 seconds for connection:
    delay(1000);
  }
  Serial.println(" Connected.");

  rtc.begin();

  // Set Time via NTP
  Serial.println("Retriving NTP Time...");
  unsigned long epoch;
  int numberOfTries = 0, maxTries = 10;
  do {
    epoch = WiFi.getTime();
    numberOfTries++;
    delay(1000);
  }
  while ((epoch == 0) && (numberOfTries < maxTries));
  if (numberOfTries == maxTries) {
    Serial.println(" NTP unreachable");
    while (1);
  }
  else {
    rtc.setEpoch(epoch);
  }

  /*****************************************************
  ***                   RTC Alarm                    ***
  ******************************************************/
  Serial.println("Waiting schedule time for starting jobs...");
  rtc.setAlarmTime(22 - GMT, 18, 0);                               // Set time here
  rtc.enableAlarm(rtc.MATCH_HHMMSS);
  rtc.attachInterrupt(alarm1);

  getWeather();                                          // *** Here working! ***
}

void loop()
{

}

//
void getWeather() {
  int rain_prob_index = 0;
  Serial.println("\nConnecting to OpenWeatherMap API...");
  if (client.connect(server, 80)) {
    Serial.println("Connected. Retriving weather forecast for the next 24 hours...");
    client.print("GET /data/2.5/forecast?");
    client.print("q=" + location);
    client.print("&appid=" + apiKey);
    client.print("&cnt=8");
    client.println("&units=metric");
    client.println("Host: api.openweathermap.org");
    client.println("Connection: close");
    client.println();
  } else {
    Serial.println("Unable to connect to OpenWeatherMap");
  }
  // read OpenWeatherMap response

  int timeout = millis() + 5000;
  while (client.available() == 0) {
    if (timeout - millis() < 0) {
      Serial.println("Client Timeout!");
      client.stop();
      return;
    }
  }
  while(client.available()) {
    String line = client.readStringUntil('\r');
      Serial.println(line);
  }

  Serial.println("Success!");
}

/*****************************************************
***               Midnight Jobs                    ***
******************************************************/

void alarm1()
{
  getWeather();                                             // *** Here Error!!! ***
}

Looks like you are doing a lot if I/O from an interrupt service routine. I suspect that will cause problems because interrupts will be disabled.

Create a global volatile flag:

volatile boolean DoMidnightThings = false;

In loop() check the flag:

  if (DoMidnightThings)
  {
    DoMidnightThings = false;
    Serial.print(getWeather());
  }

Change your ISR to set the flag:

void alarm1()
{
  DoMidnightThings = true;
}

Yes! Now the ISR works. Thanks!

Can't figure out why the ISR is generating such amount of I/O... Do you thing that could be due to a bug in RTCZero library or something related to the MKR1010 interrupt mechanism itself?

Thanks again,

Dan

Celofan:
Can't figure out why the ISR is generating such amount of I/O... Do you thing that could be due to a bug in RTCZero library or something related to the MKR1010 interrupt mechanism itself?

It's because the ISR calls getWeather() and that function does Serial and network I/O, neither of which should be done inside an ISR. If your ISR triggers something that doesn't need sub-microsecond timing, just set a flag and have loop() handle it.

Clear! Thanks so much for your tips,

Dan