Hi all,
In case anyone is wondering, the twilio.h library works fine with the Nano ESP32. Just created a little one-room motion alarm that sends me an SMS. Very simple indeed. Create a free account on Twilio.com which will give you login credentials.
Just in case you need it, here's my code (and of course I have replaced all credentials with "XXXX"...). Reasonable well commented, I think. Have fun!
Cheers,
Michael
/*
Intruder Alarm with text messaging
By: Michael Willems - michael@willems.ca
Needs:
-Arduino Nano ESP32
-WiFi connectivity (2.4 GHz)
-Twilio account
-twilio-esp32-client library (from Arduino IDE)
-PIR sensor
-Five LEDs, 100R resistors, SPDT switch.
Version 0.2 - 7 Aug 2023
Alarm is activated with switch (flashing yellow); 60 seconds later it's active (solid yellow)
Sends SMS to phone upon alarm, bootup, and arm/disarm.
*/
//-------------------------------------------------------------------------------------------
// INCLUDES, DECLARATIONS:
//-------------------------------------------------------------------------------------------
#include "WiFi.h"
#include "twilio.hpp"
// define WiFi and SMS credentials:
const char* ssid = "XXXX";
const char* password = "XXXX";
Twilio *twilio;
// Values from Twilio (from the dashboard):
static const char *account_sid = "XXXX";
static const char *auth_token = "XXXX";
static const char *from_number = "XXXX";
static const char *to_number = "XXXX";
static const char *messageStart = "I2000 Home Startup";
static const char *messageAlert = "I2000 Home MOTION DETECTED";
static const char *messageArmed = "I2000 Home Armed";
static const char *messageDisarmed = "I2000 Home Disarmed";
String response;
// define misc pins:
int PIRpin = 2;
int Switch = 10;
int PushButton = 11;
// on-board LEDs:
int activeled = 13;
int blueled = 16;
// External LEDs:
int OkLed = 3; // WiFi and SMS OK
int WiFiErrLed = 4; // WiFi Error
int SmsErrLed = 5; // SMS Error
int ArmLed = 6; // Armed
int TrigLed = 7; // Motion seen!
// Counters etc:
unsigned long oneseccounter;
unsigned long quartersecondcounter;
unsigned long prearmtimer;
unsigned long prearmdelay = 60000;
boolean ArmedStat = false; // are we armed?
boolean PreArmInhibit = false; // are we stil in pre-arm time, so no alarms yet please?
boolean TriggeredStat = false; // is the alarm triggered?
//-------------------------------------------------------------------------------------------
// THE SETUP (RUNS ONCE):
//-------------------------------------------------------------------------------------------
void setup() {
pinMode(PIRpin, INPUT);
pinMode(Switch, INPUT_PULLUP);
pinMode(PushButton, INPUT_PULLUP);
pinMode(activeled, OUTPUT);
pinMode(blueled, OUTPUT);
pinMode(OkLed, OUTPUT);
pinMode(WiFiErrLed, OUTPUT);
pinMode(SmsErrLed, OUTPUT);
pinMode (ArmLed, OUTPUT);
pinMode(TrigLed, OUTPUT);
// Set inital LED status:
digitalWrite (OkLed, LOW);
digitalWrite (WiFiErrLed, HIGH);
digitalWrite (SmsErrLed, HIGH);
digitalWrite (ArmLed, LOW);
digitalWrite (TrigLed, LOW);
// Now connect to WiFi and wait until connected:
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
digitalWrite (activeled, LOW);
analogWrite (blueled, LOW);
delay(500);
}
// We are connected, so indicate this:
analogWrite (blueled, HIGH);
digitalWrite (activeled, HIGH);
digitalWrite (WiFiErrLed, LOW);
delay(500);
// start Twilio instance:
twilio = new Twilio(account_sid, auth_token);
// Now send SMS:
String response;
bool success = twilio->send_message(to_number, from_number, messageStart, response);
if (success) {
digitalWrite(SmsErrLed, LOW);
digitalWrite (OkLed, HIGH); // because of SMS was sent, WiFi must also be OK
} else {
digitalWrite(SmsErrLed, HIGH);
Serial.println(response);
}
// set the timers to start:
oneseccounter = millis();
quartersecondcounter = millis();
}
//-------------------------------------------------------------------------------------------
// THE LOOP (RUNS CONTINUOUSLY):
//-------------------------------------------------------------------------------------------
void loop() {
// now do the "once every second" things:
if ((millis() - oneseccounter) > 1000) {
//Toggle the on-board active LED:
digitalWrite (activeled, !digitalRead(activeled));
// is WiFi connected? If not, turn off the blue and OK LED, and turn on WiFi Error LED:
if (WiFi.status() != WL_CONNECTED) {
analogWrite (blueled, LOW);
analogWrite (WiFiErrLed, HIGH);
digitalWrite (OkLed, LOW);
}
else {
// wifi is OK, so turn the on-board blue LED on, and turn WiFi error light off:
analogWrite (blueled, HIGH);
analogWrite (WiFiErrLed, LOW);
digitalWrite (OkLed, HIGH);
}
// Now reset counter so we can start counting another second:
oneseccounter = millis();
}
// End of "once a second" things.
// The "every quarter second" thing - for flashing the light while armed+inhibited:
if ((millis() - quartersecondcounter) > 250) {
if ((ArmedStat == true) && (PreArmInhibit == true)) {
digitalWrite (ArmLed, !digitalRead(ArmLed));
}
quartersecondcounter = millis();
}
// End of the "every quarter second" thing.
// Now the "always do this" things:
// Arm/Disarm routines:
// -------------------
if (digitalRead(Switch) == LOW){ //switch is turned on (up)
if ((millis() - prearmtimer) > prearmdelay) {
PreArmInhibit = false;
digitalWrite (ArmLed, HIGH); // turn on "Armed" light just in case it's not on yet
}
if (ArmedStat == false) { // i.e. it was just now turned to ARM...
ArmedStat = true; // so next loop it knows it's not only just been armed, so not another SMS
digitalWrite (ArmLed, HIGH); // turn on "Armed" light just in case it's not on yet
// Send "Armed" SMS:
bool success = twilio->send_message(to_number, from_number, messageArmed, response);
if (success) {
digitalWrite(SmsErrLed, LOW);
digitalWrite (OkLed, HIGH); // because of SMS was sent, WiFi must also be OK
} else {
digitalWrite(SmsErrLed, HIGH);
}
// Start Inhibit timer (minute to get out of the room):
PreArmInhibit = true;
prearmtimer = millis();
}
} else { // Switch is turned down (off)
digitalWrite (ArmLed, LOW); // so turn off Armed LED
if (ArmedStat == true) { // i.e. it was just turned to DISARM...
// Send "Disarmed" SMS:
bool success = twilio->send_message(to_number, from_number, messageDisarmed, response);
if (success) {
digitalWrite(SmsErrLed, LOW);
digitalWrite (OkLed, HIGH); // We can do this because if SMS was sent, WiFi must also be OK
} else {
digitalWrite(SmsErrLed, HIGH);
}
ArmedStat = false; // so next loop it knows it's not only just been disarmed, so not another SMS
}
}
// Trigger Event Routines:
// -----------------------
if (digitalRead(PIRpin) == HIGH) { // The PIR is giving an trigger indication...
digitalWrite (TrigLed, HIGH); // ..so, turn on the Trigger LED just in case it's not on yet.
if ((ArmedStat == true) && (PreArmInhibit == false)) { // we are armed and we are not inhibited
if (TriggeredStat == false) { //we were not triggered, but now we are.
// So, send an SMS: we had a motion alert.
bool success = twilio->send_message(to_number, from_number, messageAlert, response);
if (success) {
digitalWrite(SmsErrLed, LOW);
digitalWrite (OkLed, HIGH);
} else {
digitalWrite(SmsErrLed, HIGH);
Serial.println(response);
}
TriggeredStat = true; // Trigger status ON (so we won't send another SMS, for a start!)
}
}
}
else { // the PIR is not giving an trigger indication
if ((ArmedStat == false) || (PreArmInhibit == true )) {
digitalWrite (TrigLed, LOW); // ...we are not [yet] armed, so turn off Trigger LED when PIR stops activating
TriggeredStat = false; // also, since we are not armed and not triggered, turn off triggered status
}
}
//--end of loop code here--
//
}
//-------------------------------------------------------------------------------------------
// THE FUNCTIONS (CALLED AS NEEDED):
//-------------------------------------------------------------------------------------------
// tbd