I am trying to fix an issue with the IOT cloud where it disconnects, i Reconnect and each time I do available memory is lost until eventually the Nano 33 IOT crashes. I use the , false parameter in begin to prevent reboots but that results in out of memory crashes. Generally every time I reconnect to the cloud I lose 3.2k of memory. Maybe they're not closing a socket and hanging up the memory.
Here's some serial out from the sequence that shows losing memory on reconnect:
21:36:06.245 -> top of disco at minute:3
21:36:06.245 -> >>>> DISCONNECTED from network
21:36:06.245 -> Netstate = 0 FailState=1
21:36:08.629 -> Reconnect Retries=3
21:36:08.629 -> Now Free RAM = 10671
21:36:08.629 -> in disco at minute:3
21:36:16.495 -> Now Free RAM = 10671
21:36:16.495 -> top of disco at minute:3
21:36:16.495 -> >>>> DISCONNECTED from network
21:36:16.495 -> Netstate = 0 FailState=1
21:36:18.948 -> Reconnect Retries=4
21:36:18.948 -> Now Free RAM = 9555
21:36:18.948 -> in disco at minute:3
21:36:19.728 -> Connected to Arduino IoT Cloud
21:36:19.728 -> onNetworkConnect Connected
21:36:19.728 -> in reconn logText4=xxCommsFailp1xx
21:36:19.728 -> text msg=ALERT Reconnected to Cloud and logtxt=ALERT Reconnected to Cloud
21:36:19.728 ->
21:36:19.728 -> Starting connection to server...
21:36:21.539 -> connected to server
21:36:21.539 -> From=%2B14084098202&To=%2B14083983519&Body=ALERT Reconnected to Cloud
21:36:24.081 -> New DST:1
21:36:35.027 -> New Flow Set at minute:4
21:36:35.027 -> Got new Gpm1=0
21:36:35.027 -> Got new Gpm2=0
21:36:35.027 -> Got new Gpm3=0
21:36:35.027 -> before acloud update
21:36:35.027 -> Netstate = 1
21:36:36.031 -> * UPDATED
21:36:36.031 -> LOC : 21:35:39 Thu 23 Jun 2022
21:36:36.031 -> Now Free RAM = 6299
21:36:36.031 -> at minute:4
Here's my code that does this:
//String Version = "SysLogTextAlertsFlowsv8Test 6/15/2022";
/*
Sketch generated by the Arduino IoT Cloud Thing
https://create.arduino.cc/cloud/things/ea8db7ae-93d0-4290-99a4-a026ac6aaccc
Arduino IoT Cloud Variables description
The following variables are automatically generated and updated when changes are made to the Thing
String logText;
2/20/2022
20220329 -- Use Serial1 on pins Tx,Rx tofr XBee
20220407 -- incorporated text alerts from the BTC
20220407 -- incorporated flow collection,time and dst flag and cloud update
20220423 -- Changed i'm alive to 24 hrs
20220517 -- added alert for reboots
20220606 -- added alerts for tank1 valve on/off
20220609 -- added ability to override T1Valve On/Off from webconsole
20220609 -- parameterized Twilio phone numbers
and added testsd flag = 1 if testing
20220613 -- removed v1open control and messages due to cloud instability
20220615 -- cleaned up messages to clarify connect vs reconnect
20220623 -- trying to fix reboot failure
*/
#include "thingProperties.h"
#include <WiFiNINA.h>
#include <Arduino.h>
#include "wiring_private.h"
#include <pgmspace.h>
#include <SPI.h>
#include <Base64.h>
#include <NTPClient_Generic.h>
#include <NTPClient_Generic_Impl.h>
// GitHub - khoih-prog/NTPClient_Generic: Library for NTPClient to connect to an NTP time-server. Get time from a NTP time-server and keep it in sync. For ESP8266/ESP32, nRF52, SAMD21/SAMD51, STM32F/L/H/G/WB/MP1, Teensy, etc. besides AVR, using ESP WiFi, WiFiNINA, Ethernet W5x00, ENC28J60, LAN8742A, ESP8266/ESP32 AT-command WiFi.
#include <MemoryFree.h>;
#include <pgmStrToRAM.h>;
String Version = "SysLogTextAlertsFlowsv8Test 6/15/2022";
// test flags -- reset in prod
bool testsd = 1;
byte txtboth = 0; // flag to send texts to Colby and me or just me
byte status = WL_IDLE_STATUS;
volatile bool netstate = 0;
int retries = 0;
volatile int netFailState = 1;
byte t1empty = 0; // flag for tank state
byte pnum = 1;
String pnum1 = "4083983519";
String pnum2 = "5104147332";
String pnumtosendto = "4083983519"; // init to SD pnum
String TwilioNumRBC = "8059247990";
String TwilioNumSD = "4084098202";
String TwilioNum = "4084098202";
long ttime = 0;
const long TxtTimeDelay = 10000;
byte txtwait = 0;
int myfirst = 0;
bool NewT1V = 0;
bool OldT1Vopen = 0;
bool vfirst = 1;
bool reconn = 0;
String newlogtext;
bool newtext = 0;
bool txtfirst = 0;
bool cfirst = 1;
bool slrebooted = 0;
bool syncDone;
byte txt1 = 1;
byte txt2 = 2;
String Account_SID = SECRET_Acct_SID; // live acct
char toencode[] = SECRET_User_Auth; //live acct
int toencodeLength = 0;
int xencodedLength = 0; //Base64.encodedLength(toencodeLength);
//char encodedString[xencodedLength];
//Base64.encode(encodedString, toencode, toencodeLength - 1);
String astring = "Authorization: Basic ";
String authstring; // = astring + encodedString;
char server[] = "api.twilio.com"; // name address for twilio api (using DNS) https://api.twilio.com/2010-04-01
// Initialize the WiFiNINA client library
WiFiSSLClient txtclient;
WiFiServer myserver(80); // set up a server added
String ackstring = "xxackslogxxx";
/-----( Declare Constants and Pin Numbers )-----/
// "RXD" Nano Pin Rx on XBee pin 2 Tx
// "TXD" Nano Pin Tx on XBee pin 3 Rx
const int XRDelay = 3000; //time to wait after sending command to read
const int ReadDelay = 400; // time to wait to read buffer
String input = "";
String newmsg = "";
String CkInput = "";
int GotAck = 0;
int Tries = 0;
int maxtries = 10;
byte CkCommsOK = 1; // gets checked when transmitting commands
// I'm Alive timer sends a log message and text every alivetime
long atime = 0;
const long AliveTimeDelay = 86400000; // use 1 hour 3600000 in prod
byte alivewait = 0;
// flow collection
unsigned long Timer = 0;
unsigned long StartTime = 0;
unsigned long Interval = 60000; // 60 second interval to calc flow
int MinCnt=0;
volatile int Gpm1;
volatile int Gpm2;
volatile int Gpm3;
const int CountPin1 = 2; // the interrupt pin for count
const int CountPin2 = 3; // the interrupt pin for count
const int CountPin3 = 9; // the interrupt pin for count
IPAddress poolServerIP(129, 6, 15, 28); // time.nist.gov NTP server
// A UDP instance to let us send and receive packets over UDP
WiFiUDP Udp;
NTPClient timeClient(Udp);
void setup()
{
Serial.begin(9600);
delay(3000);
Serial.println(Version);
// temp stuff to measure mem usage
Serial.print("Free RAM = ");
Serial.println(freeMemory());
// Serial.println();
pinMode(CountPin1,INPUT_PULLUP);
attachInterrupt (digitalPinToInterrupt(CountPin1), Counter1, FALLING) ; // start with int on pin 2 enabled and attached
pinMode(CountPin2,INPUT_PULLUP);
attachInterrupt (digitalPinToInterrupt(CountPin2), Counter2, FALLING) ; // start with int on pin 3 enabled and attached
pinMode(CountPin3,INPUT_PULLUP);
attachInterrupt (digitalPinToInterrupt(CountPin3), Counter3, FALLING) ; // start with int on pin 9 enabled and attached
//**************************************************
initProperties();
// String Account_SID = SECRET_Acct_SID; // live acct
// char toencode[] = SECRET_User_Auth; //live acct
toencodeLength = sizeof(toencode);
xencodedLength = Base64.encodedLength(toencodeLength);
char encodedString[xencodedLength];
Base64.encode(encodedString, toencode, toencodeLength - 1);
// String astring = "Authorization: Basic ";
authstring = astring + encodedString;
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while (true);
}
Serial.println("Connecting to: " + String(SSID));
WiFi.begin(SSID, PASS); delay(1000);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
WiFi.begin(SSID, PASS);
}
printWifiStatus();
// Connect to Arduino IoT Cloud
ArduinoCloud.addCallback(ArduinoIoTCloudEvent::CONNECT, onNetworkConnect);
ArduinoCloud.addCallback(ArduinoIoTCloudEvent::DISCONNECT, onNetworkDisconnect);
// ArduinoCloud.addCallback(ArduinoIoTCloudEvent::SYNC, onIoTSync);
ArduinoCloud.begin(ArduinoIoTPreferredConnection, false);
// false disables the cloud timeout and reboot
// ArduinoCloud.begin(ArduinoIoTPreferredConnection);
setDebugMessageLevel(DBG_INFO);
ArduinoCloud.printDebugInfo();
// ArduinoCloud.update();
if(netstate == 0) Serial.println("Netstate = 0");
if(netstate == 1) Serial.println("Netstate = 1");
timeClient.begin();
timeClient.setTimeOffset(-28800);
if(dST) timeClient.setTimeOffset(-25200);
Serial.println("Using NTP Server " + timeClient.getPoolServerName());
// Get XBee going
TwilioNum = TwilioNumRBC;
if(testsd == 1) TwilioNum = TwilioNumSD;
Serial1.begin(9600);
delay(XRDelay);
Serial1.print("Serial1 says hello!");
newmsg = "ALERT SysLog Restarting";
Serial.println("text msg=" + newmsg);
Sendtxt(txt1);
if (txtboth == 1 ) Sendtxt(txt2);
// t1Vopen = 0; // test var
} // ****************** end setup **********************************
void loop() {
ArduinoCloud.update();
// attempt to stay connected to WiFi
if (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("lost wifi connection");
WiFi.begin(SSID, PASS);
if (WiFi.status() == WL_CONNECTED) {
Serial.println("Connected to wifi");
printWifiStatus();
}
}
// Check for radio traffic
if ( Serial1.available() > 0 ){
delay(ReadDelay); // delay to get all of string
CkInput = Serial1.readString(); //Read from XBee
Serial.println( "in asynch logText1=" + logText );
logText = CkInput;
Serial.println( "in asynch logText2=" + logText );
// look for alert to send text
if (CkInput.indexOf("CommsFail") > 0 ) {
Serial1.flush();
Serial1.print("xxackxx");// send xxackxx
// delay(XRDelay);
// Serial1.print("xxackxx");
newmsg = "ALERT Comms Failure " +
CkInput.substring(CkInput.indexOf("CommsFail") + 9, CkInput.indexOf("CommsFail") + 11);
Serial.println("text msg=" + newmsg);
Sendtxt(txt1);
if (txtboth == 1 )Sendtxt(txt2);
}
if ((CkInput.indexOf("fvalveon") > 0 ) && txtwait == 0 ) {
CkInput = CkInput.substring(CkInput.indexOf("fvalveon") + 8);
//Serial.println("CkInput after strip leading xx="+CkInput);
if (CkInput.indexOf("x") >= 0) CkInput = CkInput.substring(0, CkInput.indexOf("x"));
//Serial.println("CkInput after strip trailing junk="+CkInput);
newmsg = "ALERT Watering on for Valve " + CkInput;
Serial.println("text msg=" + newmsg);
Sendtxt(txt1);
if (txtboth == 1 )Sendtxt(txt2);
txtwait = 1;
}
if ((CkInput.indexOf("fvalveoff") > 0 ) && txtwait == 0) {
CkInput = CkInput.substring(CkInput.indexOf("fvalveoff") + 9);
//Serial.println("CkInput after strip leading xx="+CkInput);
if (CkInput.indexOf("x") >= 0) CkInput = CkInput.substring(0, CkInput.indexOf("x"));
newmsg = "ALERT Watering off for Valve " + CkInput;
Serial.println("text msg=" + newmsg);
Sendtxt(txt1);
if (txtboth == 1 ) Sendtxt(txt2);
txtwait = 1;
}
input = "";
if ((CkInput.indexOf("t1empalert") > 0 )) {
Serial1.print("xxackxx");
t1empty = 1;
newmsg = "ALERT Tank1 Empty";
Serial.println("text msg=" + newmsg);
Sendtxt(txt1);
if (txtboth == 1 )Sendtxt(txt2);
txtwait = 1;
}
if ((CkInput.indexOf("t1fullalert") > 0 ) ) {
Serial1.print("xxackxx");
t1empty = 0;
newmsg = "ALERT Tank1 Full";
Serial.println("text msg=" + newmsg);
Sendtxt(txt1);
if (txtboth == 1 )Sendtxt(txt2);
txtwait = 1;
}
if ((CkInput.indexOf("BTfull") > 0 ) && txtwait == 0 ) {
Serial1.print("xxackxx");
if(t1empty == 0) newmsg = "ALERT Blending Tank Full - Pumps Off";
else newmsg = "ALERT Blending Tank Full - P3 Off P1 On";
Serial.println("text msg=" + newmsg);
Sendtxt(txt1);
if (txtboth == 1 )Sendtxt(txt2);
txtwait = 1;
}
if ((CkInput.indexOf("BTempty") > 0 ) && txtwait == 0 ) {
Serial1.print("xxackxx");
newmsg = "ALERT Blending Tank Empty, Pumps On";
Serial.println("text msg=" + newmsg);
Sendtxt(txt1);
if (txtboth == 1 )Sendtxt(txt2);
txtwait = 1;
}
if ((CkInput.indexOf("tvalveoff1") > 0 ) && txtwait == 0 ) {
Serial1.print("xxackxx");
newmsg = "ALERT Tank1 Valve OFF";
Serial.println("text msg=" + newmsg);
Sendtxt(txt1);
if (txtboth == 1 )Sendtxt(txt2);
txtwait = 1;
t1Vopen = 0;
}
if ((CkInput.indexOf("tvalveon1") > 0 ) && txtwait == 0 ) {
Serial1.print("xxackxx");
newmsg = "ALERT Tank1 Valve ON";
Serial.println("text msg=" + newmsg);
Sendtxt(txt1);
if (txtboth == 1 )Sendtxt(txt2);
txtwait = 1;
t1Vopen = 1;
}
if ((CkInput.indexOf("watpoff1") > 0 ) && txtwait == 0 ) {
Serial1.print("xxackxx");
newmsg = "ALERT Pump1 Off";
Serial.println("text msg=" + newmsg);
Sendtxt(txt1);
if (txtboth == 1 )Sendtxt(txt2);
txtwait = 1;
}
if (CkInput.indexOf("reboot") > 0 ) {
Serial1.flush();
Serial1.print("xxackxx");// send xxackxx
delay(XRDelay);
// Serial1.print("xxackxx");
newmsg = "ALERT Rebooted " +
CkInput.substring(CkInput.indexOf("reboot") + 6, CkInput.indexOf("reboot") + 8);
Serial.println("text msg=" + newmsg);
Sendtxt(txt1);
if (txtboth == 1 )Sendtxt(txt2);
}
CkInput = "";
} // end serial available check for radio traffic
if (reconn == 1){
reconn = 0;
// newlogtext = "onNetworkConnect Connected";
// logText = newlogtext;
t1Vopen = 1; // test var
Serial.println( "in reconn logText4=" + logText );
// ArduinoCloud.update();
if( cfirst == 1){
cfirst =0;
newmsg = "ALERT Connected to Cloud " ;
newlogtext = newmsg;
logText = newlogtext;
Serial.println("text msg=" + newmsg + " and logtxt=" + logText);
Sendtxt(txt1);
if (txtboth == 1 )Sendtxt(txt2);
}
else {
newmsg = "ALERT Reconnected to Cloud " ;
newlogtext = newmsg;
logText = newlogtext;
//Serial.println("text msg=" + newmsg);
Serial.println("text msg=" + newmsg + " and logtxt=" + logText);
Sendtxt(txt1);
if (txtboth == 1 )Sendtxt(txt2);
}}
/* check for new T1VOpen signal and send alert and command
if(NewT1V == 1 ){
NewT1V=0;
if (vfirst == 1 || reconn == 1){
vfirst = 0; reconn = 0;
newmsg = "ALERT Reconnected to Cloud " ;
Serial.println("text msg=" + newmsg);
Sendtxt(txt1);
if (txtboth == 1 )Sendtxt(txt2);
}
else{
if(OldT1Vopen != t1Vopen){
if (t1Vopen == 1){
GotAck = 0; Tries = 0; input = ""; //setup for next xmit
while (GotAck==0 && Tries < maxtries) { // send redundant stop signal
Serial1.print("xxT1ValveOVONxx");
Serial.println("xxT1ValveOVONxx");
delay(XRDelay) ; // delay to allow time to respond was 2000
GetAck();
if(GotAck == 1 ){
newmsg = "ALERT Overriding Tank1 Valve ON";
Serial.println("text msg=" + newmsg);
Sendtxt(txt1);
if (txtboth == 1 )Sendtxt(txt2);
txtwait = 1;
OldT1Vopen = 1;
logText= "xxT1ValveOVONxx";
}
else {
Serial.print("No ack in tries=");
Serial.println(Tries);
if (Tries==maxtries){
Serial1.print("syCommsFailIC"); // Send out failure notice
Serial.println("IC Com Fail"); // Send out failure notice
}
}
}
}
else {
GotAck = 0; Tries = 0; input = ""; //setup for next xmit
while (GotAck==0 && Tries < maxtries) { // send redundant stop signal
Serial1.print("xxT1ValveOVOFFxx");
Serial.println("xxT1ValveOVOFFxx");
delay(XRDelay) ; // delay to allow time to respond was 2000
GetAck();
if(GotAck == 1 ){
newmsg = "ALERT Overriding Tank1 Valve OFF";
Serial.println("text msg=" + newmsg);
Sendtxt(txt1);
if (txtboth == 1 )Sendtxt(txt2);
txtwait = 1;
OldT1Vopen = 0;
logText= "xxT1ValveOVOFFxx";
}
else {
Serial.print("No ack in tries=");
Serial.println(Tries);
if (Tries==maxtries){
Serial1.print("syCommsFailIC"); // Send out failure notice
Serial.println("IC Com Fail"); // Send out failure notice
}
}
}
}
}
}
}
*/
Timer = millis();
if (Timer - StartTime >= Interval) {
StartTime = millis(); // reset Start to now for next get request
MinCnt += 1; //count minutes since starting
myMinute=MinCnt;
Serial.println("New Flow Set at minute:" + String(MinCnt));
galPerMin1 = Gpm1;
Serial.println("Got new Gpm1="+String(galPerMin1));
galPerMin2 = Gpm2;
Serial.println("Got new Gpm2="+String(galPerMin2));
galPerMin3 = Gpm3;
Serial.println("Got new Gpm3="+String(galPerMin3));
Gpm1=0;
Gpm2=0;
Gpm3=0;
Serial.println("before acloud update");
if(netstate == 0) Serial.println("Netstate = 0");
if(netstate == 1) Serial.println("Netstate = 1");
delay(1000);
timeClient.update();
if (timeClient.updated())
Serial.println("* UPDATED");
else
Serial.println("* NOT UPDATED");
Serial.println("LOC : " + timeClient.getFormattedDateTime());
timeDate = timeClient.getFormattedDateTime();
// show mem every interval
Serial.print("Now Free RAM = ");
Serial.println(freeMemory());
Serial.println("at minute:" + String(myMinute));
}
// ArduinoCloud.update();
if(netstate ==0){
Serial.print(F("Now Free RAM = "));
Serial.println(freeMemory());
Serial.print(F("top of disco at minute:"));
Serial.println (String(myMinute));
Serial.println(F(">>>> DISCONNECTED from network"));
Serial.println("Netstate = 0 FailState="+String(netFailState));
// Connect to Arduino IoT Cloud
ArduinoCloud.begin(ArduinoIoTPreferredConnection);
// false disables the cloud timeout and reboot
// ArduinoCloud.update(); // try to reconnect
delay(2000);
retries += 1;
Serial.print(F("Reconnect Retries="));
Serial.println ( String(retries));
Serial.print(F("Now Free RAM = "));
Serial.println(freeMemory());
Serial.print(F("in disco at minute:"));
Serial.println( String(myMinute));
if(retries == 10 && netstate ==0)reboot();
if(freeMemory()< 4000) reboot();
// delay(1000);
}
// Delay TxtTimeDelay after sending text alerts to prevent multiples
if (txtwait == 1) // this section waits for a while then reenables on/off
{
if ( ttime == 0 ) ttime = millis();
if ( millis() - ttime < 0 ) ttime = 0 ; // make sure you aren't waiting over a millis
// reached max reset which should be exceedingly rare but possible
if ( millis() - ttime > TxtTimeDelay )
{
ttime = 0 ;
txtwait = 0 ;
}
}
if (slrebooted == 1 ) {
newmsg = "Notice - SysLog Rebooted";
logText = newmsg;
Serial.println("text msg=" + newmsg);
Sendtxt(txt1);
if (txtboth == 1 )Sendtxt(txt2);
slrebooted = 0;
}
// Delay AliveTimeDelay after sending alive alerts
// this section waits for a while then reenables alive messages
if (alivewait == 1)
{
if ( atime == 0 ) atime = millis();
if ( millis() - atime < 0 ) atime = 0 ; // make sure you aren't waiting over a millis
// reached max reset which should be exceedingly rare but possible
if ( millis() - atime > AliveTimeDelay )
{
atime = 0 ;
alivewait = 0 ;
}
}
if (myfirst == 0 ) {
Serial.println(F("Waiting for TXT Server Response"));
Serial.print(F("status = "));
Serial.println(txtclient.status());
}
myfirst = 1;
while (txtclient.available()) {
char c = txtclient.read();
// Serial.write(c); // write twilio response if needed otherwise just empty buffer
}
txtclient.flush();
txtclient.stop();
// get actual changed text and send it
if(newtext == 1 ) {
newtext = 0;
if (txtfirst == 1){
txtfirst = 0;
}
else {Serial.println("Got new text="+newlogtext);
newmsg = "ALERT Got new text="+newlogtext;
Serial1.print("Got new text="+newlogtext);
Sendtxt(txt1);
if (txtboth == 1 )Sendtxt(txt2);
txtwait = 1;
newlogtext="";
}}
} // end loop *************
void reboot() {
Serial.println("Rebooting...");
NVIC_SystemReset();
slrebooted = 1;
}
void onLogTextChange() {
newtext = 1;
newlogtext = logText;
logText = "got input message=" + newlogtext; // Add your code here to act upon LogText change
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your board's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
void onNetworkConnect() {
Serial.println("onNetworkConnect Connected");
// logText = "onNetworkConnect Connected";
netstate = 1;
reconn = 1; txtfirst = 1; retries = 0;
}
void onNetworkDisconnect() {
netstate = 0;
Serial.println("onNetworkDisconnect Disconnected");
}
//void onIoTSync() {
// syncDone = 1;
// logText = newlogtext;
// Serial.println("Arduino synced to IoT Cloud");
//}
// RBC P# 8059247990 SD P# 4084098202
void Sendtxt(byte &pnum) {
if (pnum == 1) pnumtosendto = pnum1;
if (pnum == 2) pnumtosendto = pnum2;
/* String Account_SID = SECRET_Acct_SID; // live acct
char toencode[] = SECRET_User_Auth; //live acct
int toencodeLength = sizeof(toencode);
int xencodedLength = Base64.encodedLength(toencodeLength);
char encodedString[xencodedLength];
Base64.encode(encodedString, toencode, toencodeLength - 1);
String astring = "Authorization: Basic ";
String authstring = astring + encodedString; */
String body = "From=%2B1" + TwilioNum + "&To=%2B1" + pnumtosendto + "&Body=" + newmsg; // added
int bodylen = body.length();
Serial.println("\nStarting connection to server...");
if (txtclient.connectSSL(server, 443)) {
Serial.println("connected to server");
// Make a Twilio api request
String(TWPOST) = "POST /2010-04-01/Accounts/" + Account_SID + "/Messages HTTP/1.1\r\n"
+ authstring + "\r\n"
+ "Host: api.twilio.com\r\n"
+ "Cache-control: no-cache\r\n"
+ "User-Agent: Arduino/1.0\r\n"
+ "Content-Type: application/x-www-form-urlencoded\r\n"
+ "Content-Length: " + bodylen + "\r\n"
+ "Connection: close\r\n"
+ "\r\n"
+ body
+ "\r\n";
// txtclient.println(TWPOST); //temporarily don't post
// Serial.println(TWPOST); // full post for inspection temporarily
Serial.println(body);
}
else {
Serial.println("twilio connection failed");
}
txtclient.flush();
txtclient.stop();
}
void Counter1() // counts pulses from flow meter 1
{
Gpm1 += 1;
// Serial.println("got interrupt1");
}
void Counter2() // counts pulses from flow meter 2
{
Gpm2 += 1;
//Serial.println("got interrupt2");
}
void Counter3() // counts pulses from flow meter 3
{
Gpm3 += 1;
// Serial.println("got interrupt3");
}
void onTimeDateChange() {
// Add your code here to act upon TimeDate change
}
void onDSTChange() {
Serial.println("New DST:" + String(dST));
timeClient.setTimeOffset(-28800);
if(dST) timeClient.setTimeOffset(-25200);
}
//void onT1VopenChange() {
// Serial.println("New T1Vopen:" + String(t1Vopen));
// OldT1Vopen = !t1Vopen;
// NewT1V=1;
//}
void GetAck(){
if(Serial1.available() > 1 && Tries < maxtries) { //Read from XBee
delay(ReadDelay); // delay 0.1 sec to get all of string
String input = Serial1.readString(); //Read from XBee
if (input.indexOf("relay") >= 0 ) {
GotAck = 1; //received ack
CkCommsOK = 1;
CkInput = input;
Serial.print("Got ack in tries=");
Serial.println(String(Tries) + " CkInput=" + CkInput);
}}
else {
Serial.print("No ack in tries=");
Serial.println(Tries);
if (Tries == maxtries-1){
Serial.println("Com Fail"); // Send out failure notice
CkCommsOK = 0;
}
}
++Tries;
input="";
}
I suspect that someone knows this which is why they have the watchdog timer in the first place. Would be nice if this was fixed.