Notification Email Alerts
Below you will find the C++ code that I formulated using ChatGPT. I had to go through several iterations of the code because it did not work on the first attempt. Once I confirmed the Arduino successfully sent emails based on a defined pressure threshold, I had to refine it further because the backup battery was being drained. The email content is either "Pressure is Good, x kpascals" when it is above the threshold and "Pressure is Low, x kpascals" when it is below the threshold. The Arduino will only send one email per passage of the pressure threshold. It will not send another until the threshold has been passed again to prevent spamming recipients. In order to keep from draining the battery, the Arduino takes a reading of the pressure in the tank every 15 minutes.
Arduino Code for Pressure Sensor
Standalone w/ memory pressure low pressure high 15min sleep with blinking light when it wakes.
#include <WiFiNINA.h>
#include <ArduinoHttpClient.h>
#include <WiFiSSLClient.h>
#include <Preferences.h>
#include <ArduinoLowPower.h>
const char* ssid = "PRDE_TECH";
const char* password = "@PRDETech1";
const char* host = "script.google.com";
const int httpsPort = 443;
const String scriptPath = "/macros/s/AKfycby4TUs8PcFDI9egS0HYF4VkyMAwhx2boiElSkUUWEinydspDBEDP8RMpZn01w-Kthwi/exec";
const int sensorPin = A0;
const int ledPin = LED_BUILTIN;
WiFiSSLClient wifiClient;
HttpClient client = HttpClient(wifiClient, host, httpsPort);
Preferences prefs;
void blinkLED(int times, int delayMs = 500) {
for (int i = 0; i < times; i++) {
digitalWrite(ledPin, HIGH);
delay(delayMs);
digitalWrite(ledPin, LOW);
delay(delayMs);
}
}
bool connectWiFi() {
WiFi.begin(ssid, password);
unsigned long startAttempt = millis();
while (WiFi.status() != WL_CONNECTED && millis() - startAttempt < 15000) {
delay(500);
}
if (WiFi.status() != WL_CONNECTED) {
blinkLED(5, 300); // Fail to connect WiFi
return false;
}
return true;
}
bool sendEmailAlert(const String &message) {
// Encode message for URL
String encodedMessage = "";
for (unsigned int i = 0; i < message.length(); i++) {
char c = message.charAt(i);
if (isalnum(c)) {
encodedMessage += c;
} else {
char code0 = ((c >> 4) & 0xF) + '0';
if (((c >> 4) & 0xF) > 9) code0 = ((c >> 4) & 0xF) - 10 + 'A';
char code1 = (c & 0xF) + '0';
if ((c & 0xF) > 9) code1 = (c & 0xF) - 10 + 'A';
encodedMessage += '%';
encodedMessage += code0;
encodedMessage += code1;
}
}
String url = scriptPath + "?message=" + encodedMessage;
client.get(url);
int status = client.responseStatusCode();
if (status != 200) {
blinkLED(5, 300); // Failed to send email
return false;
}
return true;
}
float readPressure() {
int rawValue = analogRead(sensorPin);
float voltage = rawValue * (3.3 / 1023.0);
float pressure = (voltage - 0.2) / 0.018; // kPa
return pressure;
}
void setup() {
pinMode(ledPin, OUTPUT);
prefs.begin("alerts", false); // namespace "alerts", RW mode
}
void loop() {
float pressure = readPressure();
bool alertSent = prefs.getBool("alertSent", false);
bool wifiOK = connectWiFi();
if (pressure < 1.0) {
blinkLED(4, 500); // below threshold
if (!alertSent && wifiOK) {
String msg = "Alert: Pressure is Low (" + String(pressure, 2) + " kPa)";
if (sendEmailAlert(msg)) {
prefs.putBool("alertSent", true);
}
}
}
else if (pressure > 5.0) {
blinkLED(2, 500); // above threshold
if (!alertSent && wifiOK) {
String msg = "Alert: Pressure is Up (" + String(pressure, 2) + " kPa)";
if (sendEmailAlert(msg)) {
prefs.putBool("alertSent", true);
}
}
}
else {
// Reset alert state when back to normal range
prefs.putBool("alertSent", false);
}
WiFi.disconnect();
LowPower.sleep(15 * 60 * 1000); // Sleep for 15 minutes
}