I have a datalogger sketch that uploads to a Google sheet using this basic technique:
http://lethanhtrieu.likesyou.org/2017/11/07/how-to-send-data-from-esp8266-to-google-drive/?i=2
I've noticed that it sometimes fails to connect depending on the IP address that comes back for script.google.com. Some work fine, some get nothing.
With a static IP, it works everytime using 3 IP addresses. But half a dozen others (that also resolve from script.google.com) fail every time. But if I use hostByName, it works for a few cycles and then fails.
I'm wondering if there might be different SSL certificates some of the servers?
I uploaded the google.com:443 certificate via the Arduino IDE. Should I add the other IP addresses directly? Am I on the wrong track? Any other thoughts on this?
Running on a Mega2560 with an Adafruit ATWINC1500 WiFi.
/***************************************************************************
***************************************************************************/
// Libraries
#include "Arduino.h"
#include "WifiLogin.h"
#include <SPI.h>
#include <Wire.h>
#include <WiFi101.h>
#include <TimeLib.h>
// Function Declarations
void echoData(String s);
String IpAddress2String(const IPAddress& ipAddress);
bool sendData();
bool ConnectWiFi();
#define baudRate 9600
// LED Alarm Pins
#define faultAlarmPin 9 // Red LED indicating fatal fault, or setup()
#define wifiAlarmPin 10 // Yellow LED functioning wifi connection
#define dsAlarmPin 11 // Green LED indicating successful data server update
#define timeAlarmPin 12 // Blue LED indicating time sync
#define statusPin 13 // White LED Heartbeat indicator
bool alarmStatus = false;
bool firstRun = true;
bool wifiStatus = false;
const unsigned long logTimerDelay = 60000; // 1 minute delay for data logging functions
unsigned long logTimerStart = 0;
unsigned long sysTime;
String logData;
// Google Data Script
int dsIndex = 0;
const int httpsPort = 443;
const char* dsHostName = "script.google.com";
WiFiClient client;
void setup() {
// Setup Alarm pins
pinMode(faultAlarmPin, OUTPUT); digitalWrite(faultAlarmPin, HIGH); // Initial alarm to indicate setup()
pinMode(wifiAlarmPin, OUTPUT); digitalWrite(wifiAlarmPin, LOW);
pinMode(dsAlarmPin, OUTPUT); digitalWrite(dsAlarmPin, LOW);
pinMode(timeAlarmPin, OUTPUT); digitalWrite(timeAlarmPin, LOW);
// Setup SPI pins
pinMode(46, OUTPUT);
pinMode(48, OUTPUT);
pinMode(49, OUTPUT);
pinMode(50, OUTPUT);
pinMode(51, OUTPUT);
pinMode(52, OUTPUT);
pinMode(53, OUTPUT);
// Setup Status Light
pinMode(statusPin, OUTPUT); digitalWrite(statusPin, LOW);
alarmStatus = false;
// Reserve SRAM memory for data string
logData.reserve(150);
// Open serial communications and wait for port to open:
Serial.begin(baudRate);
logData = F("\r\n-----------Starting Grow Tent Logger-----------"); echoData(logData);
WiFi.setPins(46, 48, 49); //WiFi.setPins(42, 44, 46);
wifiStatus = ConnectWiFi();
// Clear alarm status
alarmStatus = false;
digitalWrite(faultAlarmPin, LOW);
logData = F("-----------Begin Data Logging-----------"); echoData(logData);
} // End of setup()---------------------------------------------------------
void loop() {
// Get time variables for current loop
sysTime = now();
unsigned long sysTime_millis = millis();
// Begin data logging cycle
if (sysTime_millis - logTimerStart >= logTimerDelay) {
// Save the current cycle time
logTimerStart = sysTime_millis;
sendData();
logData = F("-----------End of Cycle-----------"); echoData(logData);
}
if(WiFi.status() != WL_CONNECTED){
digitalWrite(wifiAlarmPin, HIGH);
WiFi.end();
wifiStatus = ConnectWiFi();
}
digitalWrite(statusPin, !digitalRead(statusPin)); // Toggle led as proof of life
} // End of loop()---------------------------------------------------------------------
// Simplify code by sending string to Serial and SD Card
void echoData(String s){
if (Serial){
Serial.println(s);
Serial.flush();
}
}
// Format IPAddress for more reliable printing
String IpAddress2String(const IPAddress& ip){
return String(ip[0]) + String(".") +\
String(ip[1]) + String(".") +\
String(ip[2]) + String(".") +\
String(ip[3]) ;
}
// Send data to Google Sheet via GET request to Sheet Script
bool sendData(){
String GAS_ID = F("XXXXXX"); // New Google Script Service ID
alarmStatus = false;
int dsCount = 2;
IPAddress IP;
IPAddress dataServerIP[10] = {
IPAddress(172,217,14,174), //OK
IPAddress(172,217,9,174), //OK
IPAddress(216,58,201,206), //OK
// IPAddress(216,58,217,206), //fail
// IPAddress(216,58,219,14), //fail
// IPAddress(216,58,193,206), //fail
// IPAddress(216,58,219,14), //fail
// IPAddress(216,58,219,14), //fail
// IPAddress(216,58,217,206), //fail
};
/* ----------ConnectSSL via static IP works fine with some IP addresses----------
if(!client.connectSSL(dataServerIP[dsIndex], httpsPort)){
----------------------------------------*/
// ----------But ConnectSSL via hostByName fails----------
WiFi.hostByName(dsHostName, IP);
echoData(IpAddress2String(IP));
if(!client.connectSSL(IP, httpsPort)){
//----------------------------------------
/* ----------And ConnectSSL via HostName fails----------
if(!client.connectSSL(dsHostName, httpsPort)){
----------------------------------------*/
logData = F("Failed to connect to:"); logData += IpAddress2String(dataServerIP[dsIndex]);
logData += F(" Client Status:"); logData += client.status();
logData += F(", WiFi Status: "); logData += WiFi.status();
logData += F(", DSIndex: "); logData += dsIndex; echoData(logData);
echoData(F("Data Server connection failed."));
if(dsIndex++ >= dsCount) dsIndex = 0; // Get the next data server IP address
digitalWrite(dsAlarmPin, HIGH);
return false;
}
if(dsIndex++ >= dsCount) dsIndex = 0; // Get the next data server IP address
logData = F("Script Server: "); logData += dsHostName;
logData += F(" ("); logData += IpAddress2String(client.remoteIP());
logData += F(")"); echoData(logData);
String url = F("B="); url += 0;
url += F("&C="); url += 0;
url += F("&D="); url += 0;
url += F("&E="); url += 0;
url += F("&F="); url += 0;
url += F("&G="); url += 0;
url += F("&H="); url += 0;
url += F("&I="); url += firstRun;
url += F("&J="); url += 0;
url += F("&K="); url += 0;
url += F("&L="); url += WiFi.RSSI();
url += F("&M="); url += 0;
logData = F("Sending Data: "); logData += url; echoData(logData);
client.print(String("GET ") + "/macros/s/" + GAS_ID + "/exec?"
+ url + " HTTP/1.1\r\n" + "Host: " + dsHostName + "\r\n"
+ "User-Agent: ArduinoGTLogger1.0\r\n"
+ "Connection: close\r\n\r\n");
logData = F("Data Sent; Closing Connection"); echoData(logData);
client.stop();
if(firstRun == true) firstRun = false;
alarmStatus = false;
digitalWrite(dsAlarmPin, LOW);
return true;
}
// Wifi Connect function to facilitate online reconnects
bool ConnectWiFi(){
const char ssid[] = SECRET_SSID; // your network SSID (name)
const char pass[] = SECRET_PASS; // your network password
if (WiFi.status() == WL_NO_SHIELD) {
logData = F("WiFi shield not present; WiFi not available"); echoData(logData);
alarmStatus = true;
digitalWrite(wifiAlarmPin, HIGH);
return false;
}
// Attempting to connect to WiFi network. Only attempt once so the rest of the sketch is not neglected
if(WiFi.status() != WL_CONNECTED) {
logData = F("Attempting to connect to WPA SSID: "); logData += ssid; echoData(logData);
WiFi.begin(ssid, pass); // Connect to WPA/WPA2 network
delay(5000); // wait 10 seconds for connection:
}
// If you're connected now, print out the status:
if(WiFi.status() == WL_CONNECTED) {
logData = F("SSID: "); logData += WiFi.SSID(); echoData(logData);
logData = F("IP Address: "); logData += IpAddress2String(WiFi.localIP()); echoData(logData);
logData = F("Signal Strength (RSSI): "); logData += WiFi.RSSI(); echoData(logData);
alarmStatus = false;
digitalWrite(wifiAlarmPin, LOW);
return true;
}
logData = F("WiFi could not connect; WiFi not available"); echoData(logData);
alarmStatus = true;
digitalWrite(wifiAlarmPin, HIGH);
return false;
}