Auto-Texting Code-
Code: Select all
/*
* Panic Button!
* A way to silently alert authorities or someone who can help with your GPS location.
Created 20-11-2017
By Deon P.
The tutorial can be found at:
http://www.sensingthecity.com
*/
#include "Adafruit_FONA.h"
#include <SoftwareSerial.h>
#define FONA_RX 2
#define FONA_TX 3
#define FONA_RST 4
#include <SoftwareSerial.h>
SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX);
SoftwareSerial *fonaSerial = &fonaSS;
// Use this for FONA 800 and 808s
Adafruit_FONA fona = Adafruit_FONA(FONA_RST);
//for replies later
char replybuffer[255];
uint8_t readline(char *buff, uint8_t maxbuff, uint16_t timeout = 0);
uint8_t type;
const int buttonPin = 8; // pushbutton pin
//RGB pins
const int RED_PIN = 9;
const int GREEN_PIN = 10;
const int BLUE_PIN = 11;
void setup() {
while (! Serial);
Serial.begin(115200);
Serial.println(F("Initializing FONA... (May take a few seconds)"));
fonaSerial->begin(4800);
if (! fona.begin(*fonaSerial)) {
Serial.println(F("Couldn't find FONA"));
while(1);
}
Serial.println(F("FONA is OK"));
// Try to enable GPRS
Serial.println(F("Enabling GPS..."));
fona.enableGPS(true);
delay(4000);
pinMode(RED_PIN, OUTPUT);
pinMode(GREEN_PIN, OUTPUT);
pinMode(BLUE_PIN, OUTPUT);
}
void loop() {
//BLINK RED LED TO SIGNIFY PRE-SMS-SEND (NORMAL) STATUS
digitalWrite(RED_PIN, HIGH);
delay(1000);
digitalWrite(RED_PIN, LOW);
delay(1000);
int buttonState;
buttonState = digitalRead(buttonPin);
//if holding down button (i.e. panic)
if (buttonState == LOW) {
//get gps location
float latitude, longitude;//variables to hold initial GPS readings
boolean gps_success = fona.getGPS(&latitude, &longitude);
if (gps_success) {
Serial.print("GPS lat:");
Serial.println(latitude, 6);
Serial.print("GPS long:");
Serial.println(longitude, 6);
//send sms
char message[141];
char LAT1[10];//string of lat and long unparsed & overflowing bound
char LAT[10];
char LONG[10];
dtostrf(latitude, 10, 7, LAT1); //gathering GPS data in a format that can be sent
dtostrf(longitude, 10, 7, LONG);
//initialize desired array from unparsed array
for(int i = 0; i < 9; i++) {
LAT[i] = LAT1[i];
}
LAT[9] = '\0';//truncate array at last desired value
sprintf(message, "I JUST PUSHED MY PANIC BUTTON! I NEED HELP NOW! https://www.google.com/maps?q=%s,%s", LAT, LONG);
Serial.println(LAT);Serial.println(LAT1);Serial.println(LONG);
Serial.println(message) ; //prints the message in the serial monitor before sending
char sendto[13] = "6317087748"; //put the desired destination phone number for sms here
fona.sendSMS(sendto, message) ; //sends the message via SMS}
//BLINK BLUE LED FOR 30 SECONDS TO NOTIFY THAT TEXT SENT
for (int i = 0; i < 30; i++){
digitalWrite(BLUE_PIN, HIGH);//keep blinking light red
delay(1000);
digitalWrite(BLUE_PIN, LOW);//keep blinking light red
delay(1000);
}
} else {
Serial.println("Waiting for FONA GPS 3D fix...");
}
// Check for network, then GPRS
Serial.println(F("Checking for Cell network..."));
if (fona.getNetworkStatus() == 1) {
// network & GPRS? Great! Print out the GSM location to compare
float latitude, longitude;
boolean gsmloc_success = fona.getGSMLoc(&latitude, &longitude);
if (gsmloc_success) {
Serial.print("GSMLoc lat:");
Serial.println(latitude, 6);
Serial.print("GSMLoc long:");
Serial.println(longitude, 6);
//send sms
char message[141];
char LAT1[10];//string of lat and long unparsed & overflowing bound
char LAT[10];
char LONG[10];
dtostrf(latitude, 10, 7, LAT1); //gathering GPS data in a format that can be sent
dtostrf(longitude, 10, 7, LONG);
//initialize desired array from unparsed array
for(int i = 0; i < 9; i++) {
LAT[i] = LAT1[i];
}
LAT[9] = '\0';//truncate array at last desired value
sprintf(message, "I JUST PUSHED MY PANIC BUTTON! I NEED HELP NOW! https://www.google.com/maps?q=%s,%s", LAT, LONG);
Serial.println(LAT);Serial.println(LAT1);Serial.println(LONG);
Serial.println(message) ; //prints the message in the serial monitor before sending
char sendto[13] = "6317087748"; //put the desired destination phone number for sms here
fona.sendSMS(sendto, message) ; //sends the message via SMS}
//BLINK BLUE LED FOR 30 SECONDS TO NOTIFY THAT TEXT SENT
for (int i = 0; i < 30; i++){
digitalWrite(BLUE_PIN, HIGH);//keep blinking light BLUE
delay(1000);
digitalWrite(BLUE_PIN, LOW);//keep blinking light BLUE
delay(1000);
}
} else {
Serial.println("GSM location failed...");
Serial.println(F("Disabling GPRS"));
fona.enableGPRS(false);
Serial.println(F("Enabling GPRS"));
if (!fona.enableGPRS(true)) {
Serial.println(F("Failed to turn GPRS on"));
}
}
}
}
}
Adafruit Code-
Code: Select all
// Geo Fencing project with Adafruit IO
// Author: Marco Schwartz
//
// Inspired by the code from Tony DiCola
//
// Released under a MIT license:
// https://opensource.org/licenses/MIT
// Libraries
#include <Adafruit_SleepyDog.h>
#include <SoftwareSerial.h>
#include "Adafruit_FONA.h"
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_FONA.h"
// Alarm pins
const int ledPin = 6;
// Size of the geo fence (in meters)
const float maxDistance = 100;
// Latitude & longitude for distance measurement
float initialLatitude;
float initialLongitude;
float latitude, longitude, speed_kph, heading, altitude;
// FONA pins configuration
#define FONA_RX 2 // FONA serial RX pin (pin 2 for shield).
#define FONA_TX 3 // FONA serial TX pin (pin 3 for shield).
#define FONA_RST 4 // FONA reset pin (pin 4 for shield)
// FONA GPRS configuration
#define FONA_APN "internet" // APN used by cell data service (leave blank if unused)
#define FONA_USERNAME "" // Username used by cell data service (leave blank if unused).
#define FONA_PASSWORD "" // Password used by cell data service (leave blank if unused).
// Adafruit IO configuration
#define AIO_SERVER "io.adafruit.com" // Adafruit IO server name.
#define AIO_SERVERPORT 1883 // Adafruit IO port.
#define AIO_USERNAME "your-adafruit-io-name" // Adafruit IO username (see http://accounts.adafruit.com/).
#define AIO_KEY "your-adafruit-io-key" // Adafruit IO key (see settings page at: https://io.adafruit.com/settings).
// Feeds
#define LOCATION_FEED_NAME "location" // Name of the AIO feed to log regular location updates.
#define MAX_TX_FAILURES 3 // Maximum number of publish failures in a row before resetting the whole sketch.
// FONA instance & configuration
SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX); // FONA software serial connection.
Adafruit_FONA fona = Adafruit_FONA(FONA_RST); // FONA library connection.
const char MQTT_SERVER[] PROGMEM = AIO_SERVER;
const char MQTT_USERNAME[] PROGMEM = AIO_USERNAME;
const char MQTT_PASSWORD[] PROGMEM = AIO_KEY;
// Setup the FONA MQTT class by passing in the FONA class and MQTT server and login details.
Adafruit_MQTT_FONA mqtt(&fona, MQTT_SERVER, AIO_SERVERPORT, MQTT_USERNAME, MQTT_PASSWORD);
uint8_t txFailures = 0; // Count of how many publish failures have occured in a row.
// Feeds configuration
const char LOCATION_FEED[] PROGMEM = AIO_USERNAME "/feeds/" LOCATION_FEED_NAME "/csv";
Adafruit_MQTT_Publish location_feed = Adafruit_MQTT_Publish(&mqtt, LOCATION_FEED);
const char BATTERY_FEED[] PROGMEM = AIO_USERNAME "/feeds/battery";
Adafruit_MQTT_Publish battery_feed = Adafruit_MQTT_Publish(&mqtt, BATTERY_FEED);
const char ALERTS_FEED[] PROGMEM = AIO_USERNAME "/feeds/alerts";
Adafruit_MQTT_Publish alerts_feed = Adafruit_MQTT_Publish(&mqtt, ALERTS_FEED);
void setup() {
// Initialize serial output.
Serial.begin(115200);
Serial.println(F("Geofencing with Adafruit IO & FONA808"));
// Set alarm components
pinMode(ledPin, OUTPUT);
// Initialize the FONA module
Serial.println(F("Initializing FONA....(may take 10 seconds)"));
fonaSS.begin(4800);
if (!fona.begin(fonaSS)) {
halt(F("Couldn't find FONA"));
}
fonaSS.println("AT+CMEE=2");
Serial.println(F("FONA is OK"));
// Use the watchdog to simplify retry logic and make things more robust.
// Enable this after FONA is intialized because FONA init takes about 8-9 seconds.
Watchdog.enable(8000);
Watchdog.reset();
// Wait for FONA to connect to cell network (up to 8 seconds, then watchdog reset).
Serial.println(F("Checking for network..."));
while (fona.getNetworkStatus() != 1) {
delay(500);
}
// Enable GPS.
fona.enableGPS(true);
// Start the GPRS data connection.
Watchdog.reset();
fona.setGPRSNetworkSettings(F(FONA_APN));
//fona.setGPRSNetworkSettings(F(FONA_APN), F(FONA_USERNAME), F(FONA_PASSWORD));
delay(2000);
Watchdog.reset();
Serial.println(F("Disabling GPRS"));
fona.enableGPRS(false);
delay(2000);
Watchdog.reset();
Serial.println(F("Enabling GPRS"));
if (!fona.enableGPRS(true)) {
halt(F("Failed to turn GPRS on, resetting..."));
}
Serial.println(F("Connected to Cellular!"));
// Wait a little bit to stabilize the connection.
Watchdog.reset();
delay(3000);
// Now make the MQTT connection.
int8_t ret = mqtt.connect();
if (ret != 0) {
Serial.println(mqtt.connectErrorString(ret));
halt(F("MQTT connection failed, resetting..."));
}
Serial.println(F("MQTT Connected!"));
// Initial GPS read
bool gpsFix = fona.getGPS(&latitude, &longitude, &speed_kph, &heading, &altitude);
initialLatitude = latitude;
initialLongitude = longitude;
// Set alert to 0
logAlert(0, alerts_feed);
}
void loop() {
// Watchdog reset at start of loop--make sure everything below takes less than 8 seconds in normal operation!
Watchdog.reset();
// Reset everything if disconnected or too many transmit failures occured in a row.
if (!fona.TCPconnected() || (txFailures >= MAX_TX_FAILURES)) {
halt(F("Connection lost, resetting..."));
}
// Grab a GPS reading.
float latitude, longitude, speed_kph, heading, altitude;
bool gpsFix = fona.getGPS(&latitude, &longitude, &speed_kph, &heading, &altitude);
Serial.print("Latitude: ");
printFloat(latitude, 5);
Serial.println("");
Serial.print("Longitude: ");
printFloat(longitude, 5);
Serial.println("");
// Calculate distance between new & old coordinates
float distance = distanceCoordinates(latitude, longitude, initialLatitude, initialLongitude);
Serial.print("Distance: ");
printFloat(distance, 5);
Serial.println("");
// Set alarm on?
if (distance > maxDistance) {
logAlert(1, alerts_feed);
}
// Grab battery reading
uint16_t vbat;
fona.getBattPercent(&vbat);
// Log the current location to the path feed, then reset the counter.
logLocation(latitude, longitude, altitude, location_feed);
logBatteryPercent(vbat, battery_feed);
// Wait 5 seconds
delay(5000);
}
// Log alerts
void logAlert(uint32_t alert, Adafruit_MQTT_Publish& publishFeed) {
// Publish
Serial.print(F("Publishing alert: "));
Serial.println(alert);
if (!publishFeed.publish(alert)) {
Serial.println(F("Publish failed!"));
txFailures++;
}
else {
Serial.println(F("Publish succeeded!"));
txFailures = 0;
}
}
// Log battery
void logBatteryPercent(uint32_t indicator, Adafruit_MQTT_Publish& publishFeed) {
// Publish
Serial.print(F("Publishing battery percentage: "));
Serial.println(indicator);
if (!publishFeed.publish(indicator)) {
Serial.println(F("Publish failed!"));
txFailures++;
}
else {
Serial.println(F("Publish succeeded!"));
txFailures = 0;
}
}
// Serialize the lat, long, altitude to a CSV string that can be published to the specified feed.
void logLocation(float latitude, float longitude, float altitude, Adafruit_MQTT_Publish& publishFeed) {
// Initialize a string buffer to hold the data that will be published.
char sendBuffer[120];
memset(sendBuffer, 0, sizeof(sendBuffer));
int index = 0;
// Start with '0,' to set the feed value. The value isn't really used so 0 is used as a placeholder.
sendBuffer[index++] = '0';
sendBuffer[index++] = ',';
// Now set latitude, longitude, altitude separated by commas.
dtostrf(latitude, 2, 6, &sendBuffer[index]);
index += strlen(&sendBuffer[index]);
sendBuffer[index++] = ',';
dtostrf(longitude, 3, 6, &sendBuffer[index]);
index += strlen(&sendBuffer[index]);
sendBuffer[index++] = ',';
dtostrf(altitude, 2, 6, &sendBuffer[index]);
// Finally publish the string to the feed.
Serial.print(F("Publishing location: "));
Serial.println(sendBuffer);
if (!publishFeed.publish(sendBuffer)) {
Serial.println(F("Publish failed!"));
txFailures++;
}
else {
Serial.println(F("Publish succeeded!"));
txFailures = 0;
}
}
// Halt function called when an error occurs. Will print an error and stop execution while
// doing a fast blink of the LED. If the watchdog is enabled it will reset after 8 seconds.
void halt(const __FlashStringHelper *error) {
Serial.println(error);
while (1) {
digitalWrite(ledPin, LOW);
delay(100);
digitalWrite(ledPin, HIGH);
delay(100);
}
}
// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
void MQTT_connect() {
int8_t ret;
// Stop if already connected.
if (mqtt.connected()) {
return;
}
Serial.print("Connecting to MQTT... ");
while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
Serial.println(mqtt.connectErrorString(ret));
Serial.println("Retrying MQTT connection in 5 seconds...");
mqtt.disconnect();
delay(5000); // wait 5 seconds
}
Serial.println("MQTT Connected!");
}
void printFloat(float value, int places) {
// this is used to cast digits
int digit;
float tens = 0.1;
int tenscount = 0;
int i;
float tempfloat = value;
// make sure we round properly. this could use pow from <math.h>, but doesn't seem worth the import
// if this rounding step isn't here, the value 54.321 prints as 54.3209
// calculate rounding term d: 0.5/pow(10,places)
float d = 0.5;
if (value < 0)
d *= -1.0;
// divide by ten for each decimal place
for (i = 0; i < places; i++)
d/= 10.0;
// this small addition, combined with truncation will round our values properly
tempfloat += d;
// first get value tens to be the large power of ten less than value
// tenscount isn't necessary but it would be useful if you wanted to know after this how many chars the number will take
if (value < 0)
tempfloat *= -1.0;
while ((tens * 10.0) <= tempfloat) {
tens *= 10.0;
tenscount += 1;
}
// write out the negative if needed
if (value < 0)
Serial.print('-');
if (tenscount == 0)
Serial.print(0, DEC);
for (i=0; i< tenscount; i++) {
digit = (int) (tempfloat/tens);
Serial.print(digit, DEC);
tempfloat = tempfloat - ((float)digit * tens);
tens /= 10.0;
}
// if no places after decimal, stop now and return
if (places <= 0)
return;
// otherwise, write the point and continue on
Serial.print('.');
// now write out each decimal place by shifting digits one by one into the ones place and writing the truncated value
for (i = 0; i < places; i++) {
tempfloat *= 10.0;
digit = (int) tempfloat;
Serial.print(digit,DEC);
// once written, subtract off that digit
tempfloat = tempfloat - (float) digit;
}
}
// Calculate distance between two points
float distanceCoordinates(float flat1, float flon1, float flat2, float flon2) {
// Variables
float dist_calc=0;
float dist_calc2=0;
float diflat=0;
float diflon=0;
// Calculations
diflat = radians(flat2-flat1);
flat1 = radians(flat1);
flat2 = radians(flat2);
diflon = radians((flon2)-(flon1));
dist_calc = (sin(diflat/2.0)*sin(diflat/2.0));
dist_calc2 = cos(flat1);
dist_calc2*=cos(flat2);
dist_calc2*=sin(diflon/2.0);
dist_calc2*=sin(diflon/2.0);
dist_calc +=dist_calc2;
dist_calc=(2*atan2(sqrt(dist_calc),sqrt(1.0-dist_calc)));
dist_calc*=6371000.0; //Converting to meters
return dist_calc;
}