Http GET fails at school

Not sure if this is the correct place in the forum for this issue, but we're using the WiFi Rev2, so it seems like a good place to start.

I'm a high school teacher and a couple of students are building a project that requires calling ThingSpeak to get the current temperature as reported by our weather station. (public channel 930894, field 7).

We're using WiFiNINA. Our first attempt was using the thingspeak library, but get -304 errors ("Timeout waiting for server to respond"). When we play with settings, we sometimes get -301 errors ("Failed to connect to ThingSpeak"). Then we tried a sketch including HttpClient and directly attempting to GET the data from "https://api.thingspeak.com/channels/930894/fields/7/last.txt". We get http error code -1.

There is something about the configuration that is off, because when I took the arduino home and connected it to my wifi there, it worked as expected. But, the students, myself, and our tech person cannot figure out the problem. ip address, dns server, gateway, and subnet are all correct (tried both Wifi.config and the auto default).

Our code (based on combining the WiFiNina example with the ThingSpeak read example) is below. Sorry for the mess, as it's gotten sloppy during our attempts at trouble-shooting. Any help would be greatly appreciated. Thank you.

#include <WiFiNINA.h>
#include "ThingSpeak.h" // always include thingspeak header file after other header files and custom macros

char ssid[] = "XXXXXXXXXXXX";   // your network SSID (name) 
char pass[] = "XXXXXXXXXXXX";   // your network password
int keyIndex = 0;            // your network key Index number (needed only for WEP)
WiFiClient  client;
int status = WL_IDLE_STATUS;
IPAddress local_ip = IPAddress(172, 17, 0, 90);
IPAddress dns_server = IPAddress(192, 168, 10, 3);
IPAddress gateway = IPAddress(172, 17, 0, 1);
IPAddress subnet = IPAddress(255, 255, 254, 0);


// Counting channel details
unsigned long counterChannelNumber = 930894;
const char * myCounterReadAPIKey = "XXXXXXXXXXXX";
unsigned int counterFieldNumber = 7; 

void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(9600); 

    //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }


  String fv = WiFi.firmwareVersion();
  if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
    Serial.println("Please upgrade the firmware");
  }

  // attempt to connect to WiFi network:
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to WPA SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network:
    WiFi.config(local_ip, dns_server, gateway, subnet);
    status = WiFi.begin(ssid, pass);

    // wait 10 seconds for connection:
    delay(10000);
    WiFi.setDNS(IPAddress(192,168, 10, 3));
    ThingSpeak.begin(client); //initialize thingspeak

  }

  // you're connected now, so print out the data:
  Serial.println("You're connected to the network");
  WiFi.setDNS(IPAddress(192, 168, 10, 3));
  Serial.println("DNS set");
  printCurrentNet();
  printWifiData();


}

void loop() {

 int statusCode = 0;
 
 // Connect or reconnect to WiFi
 if(WiFi.status() != WL_CONNECTED){
   Serial.print("Attempting to connect to SSID: ");
   //Serial.println(SECRET_SSID);
   while(WiFi.status() != WL_CONNECTED){
     WiFi.begin(ssid, pass); // Connect to WPA/WPA2 network. Change this line if using open or WEP network
     Serial.print(".");
     delay(10000);     
   } 
   Serial.println("\nConnected");
 }

 // Read in field 1 of the private channel which is a counter  
 float count = ThingSpeak.readFloatField(counterChannelNumber, counterFieldNumber, myCounterReadAPIKey);  
 delay(10000);
  // Check the status of the read operation to see if it was successful
 statusCode = ThingSpeak.getLastReadStatus();
 if(statusCode == 200){
   Serial.println("Temperature: " + String(count));
 }
 else{
   Serial.println("Problem reading channel. HTTP error code " + String(statusCode)); 
 }
 
 delay(15000); // No need to read the counter too often.
 
}

void printWifiData() {
  // print your board's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
  Serial.println(ip);

  // print your MAC address:
  byte mac[6];
  WiFi.macAddress(mac);
  Serial.print("MAC address: ");
  printMacAddress(mac);

  //print subnet and gateway
  IPAddress sub = WiFi.subnetMask();
  Serial.print("Subnet Mask: ");
  Serial.println(sub);
  IPAddress gtwy = WiFi.gatewayIP();
  Serial.print("Gateway: ");
  Serial.println(gtwy);
}

void printCurrentNet() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print the MAC address of the router you're attached to:
  byte bssid[6];
  WiFi.BSSID(bssid);
  Serial.print("BSSID: ");
  printMacAddress(bssid);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.println(rssi);
  
  // print the encryption type:
  byte encryption = WiFi.encryptionType();
  Serial.print("Encryption Type:");
  Serial.println(encryption, HEX);
  Serial.println();
}

void printMacAddress(byte mac[]) {
  for (int i = 5; i >= 0; i--) {
    if (mac[i] < 16) {
      Serial.print("0");
    }
    Serial.print(mac[i], HEX);
    if (i > 0) {
      Serial.print(":");
    }
  }
  Serial.println();
}

Can you hit that api URL with a browser from the school?

Oops, I forgot to include that, sorry.

Yes, I can visit "https://api.thingspeak.com/channels/930894/fields/7/last.txt" from any browser on every device except the arduino. From my laptop's command line I can curl that website and get the data also.

I'm fairly sure that either a) there's something in the arduino setup that I'm not familiar with and am not configuring properly or b) there's something in the building's pipeline (server, fortigate, access points) that isn't recognizing the arduino quite right and we don't know what that setting is.

can you check that joining the school wifi does actually work and you get proper routing to the internet and not just the local network? Many schools have tight policies when it comes to internet access or even joining the WiFi network ...

the laptop you use might have been properly registered and signed in into the WiFi network and blessed for internet access.

try putting your smartphone in internet sharing mode and join that network from the Arduino and check if that works. That would be an indication the the school network does not grant internet access.

1 Like

Nice suggestion. I did that and kept getting the -304 (timed out errors), but noticed that we got one response. I let it run and we are now getting one response every 15 minutes (on average). Still not sure what's causing that.

Looks like there may be two problems. The first is that something is set wrong and preventing the arduino from accessing the wifi correctly. Not sure what setting that could be, however. The second is that we are only getting a response once every 15 minutes (I could understand 15 seconds because of the post limit, but minutes?). Could it be that the function needs more time to complete? If so, how would I make that adjustment?

Thank you for your help.

it seems you are providing private network information, the DNS is not in the same local network

IPAddress local_ip = IPAddress(172, 17, 0, 90);
IPAddress dns_server = IPAddress(192, 168, 10, 3);
IPAddress gateway = IPAddress(172, 17, 0, 1);

try with a very basic code where you don't set anything (get a dynamic IP address and let the gateway, DNS etc be provided by the infrastructure)

The config command that sets those values is currently commented out, just before the WiFi.begin(). It was something we were using earlier to make sure all of those values were getting set properly when done automatically. I could (and probably should) have deleted those lines before posting that code.

after this loop

while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to WPA SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network:
    WiFi.config(local_ip, dns_server, gateway, subnet);
    status = WiFi.begin(ssid, pass);

    // wait 10 seconds for connection:
    delay(10000);
    WiFi.setDNS(IPAddress(192,168, 10, 3));
    ThingSpeak.begin(client); //initialize thingspeak
  }

you print a message

  Serial.println("You're connected to the network");

do you see it ?

if you take a very basic example, do you connect ?

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

char ssid[] = "";     // your network SSID (name)
char pass[] = "";     // your network password 

void setup() {
  Serial.begin(115200);
  while (!Serial) yield();

  int status = WL_IDLE_STATUS;
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to WPA SSID: "); Serial.println(ssid);
    status = WiFi.begin(ssid, pass);
    delay(3000);
  }

  Serial.print("You're connected to the network");

  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
}

void loop() {}

Yes. It says I'm connected. When I add the code to print out the details (IP, gateway, etc), their numbers all seem correct. When I put the calls to ThingSpeak back into the code, I get the -304 error ( Timeout waiting for server to respond).

I would think that most schools would be very wary of allowing random devices to connect to wifi and use the internet. Wifi is hard to lock down because students will always find out what the wifi password is, so I'll guess that the server has some kind of whitelist or other mechanism to restrict external access.

You might try one of the IDE examples that hit google (or whatever) to see if the Arduino can get out at all.

You can edit ThingSpeak.h and uncomment this line to get info in the Arduino IDE console about what's going on:

// #define PRINT_DEBUG_MESSAGES

Thank you. The debug messages provided some more info. It looks like the GET request is connecting, but being dropped.

               Connect to default ThingSpeak: api.thingspeak.com:443...Success.
               GET "/channels/930894/fields/7/last"
disconnected.
Problem reading channel. HTTP error code -304

I added a WiFi.setTimeOut for 5 seconds, because (as I understand it) that will make the request wait for a full five seconds before disconnecting. Either because that's how it works or other reasons, I'm now getting data more often than not.

Is my thinking correct on that? If I set it for a little longer, would that help make it more consistent? Or is something else going on and setTimeOut() not doing anything?

               GET "/channels/930894/fields/7/last"
Read: "53.55955976136029"
disconnected.

if ThingSpeak is slow answering or you have a slow network, yes that will help. (just to be sure - the value is in ms so use 5000 for 5 seconds not 5)

Error 304 is "Not modified". Thingspeak is telling you that the data on your channel hasn't changed since your last visit. Apparently the library is using an If-Modified-Since attribute in the http request. Which means that you need to keep the temperature once you do get it.

For such a small data item, it seems like a pointless thing to do - the Thingspeak server has to do the same amount of work and it's confusing to the user.

The fifteen minute thing is odd too. I'll guess that Thingspeak has some kind of timeout or count of requests from you that it 304'd and at that point it's all "ok, ok here it is - stop asking!".

Edit: It may be instead that the data is updated every 15 minutes and if it has changed, Thingspeak will give it to you.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.