/ Open_Sesame_SMS_Lock / OpenSesame / OpenSesame.ino
OpenSesame.ino
  1  // SPDX-FileCopyrightText: 2019 Anne Barela for Adafruit Industries
  2  //
  3  // SPDX-License-Identifier: MIT
  4  
  5  #include <SoftwareSerial.h>
  6  #include "Adafruit_FONA.h"
  7  
  8  #define FONA_TX 3
  9  #define FONA_RX 4
 10  #define FONA_RST 5
 11  #define FONA_RI 2
 12  
 13  #define MOTOR_PWM A1
 14  #define MOTOR_1 A2
 15  #define MOTOR_2 A3
 16  
 17  #define LED 13
 18  
 19  #define OPEN true
 20  #define CLOSE false
 21  
 22  #define BUSYWAIT 5000  // milliseconds
 23  
 24  // this is a large buffer for replies
 25  char replybuffer[255];
 26  
 27  // or comment this out & use a hardware serial port like Serial1 (see below)
 28  SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX);
 29  
 30  Adafruit_FONA fona = Adafruit_FONA(FONA_RST);
 31  
 32  uint8_t readline(char *buff, uint8_t maxbuff, uint16_t timeout = 0);
 33  
 34  boolean fonainit(void) {
 35    Serial.println(F("Initializing....(May take 3 seconds)"));
 36  
 37    digitalWrite(LED, HIGH);
 38    delay(100);
 39    digitalWrite(LED, LOW);
 40    delay(100);
 41    digitalWrite(LED, HIGH);
 42    delay(100);
 43    digitalWrite(LED, LOW);
 44    delay(100);
 45     
 46    // make it slow so its easy to read!
 47    fonaSS.begin(4800); // if you're using software serial
 48    //Serial1.begin(4800); // if you're using hardware serial
 49  
 50    // See if the FONA is responding
 51    if (! fona.begin(fonaSS)) {           // can also try fona.begin(Serial1) 
 52      Serial.println(F("Couldn't find FONA"));
 53      return false;
 54    }
 55    Serial.println(F("FONA is OK"));
 56    return true;
 57    
 58  }
 59  
 60  void setup() {
 61    while (!Serial);  // useful for Leonardo/Micro, remove in production!
 62  
 63    // set LED output for debugging
 64    pinMode(LED, OUTPUT);
 65    
 66    // set up motor pins, but turn them off
 67    pinMode(MOTOR_1, OUTPUT);
 68    digitalWrite(MOTOR_1, LOW);
 69    pinMode(MOTOR_2, OUTPUT);
 70    digitalWrite(MOTOR_2, LOW);  
 71    pinMode(MOTOR_PWM, OUTPUT);
 72    digitalWrite(MOTOR_PWM, LOW);  
 73    
 74    Serial.begin(115200);
 75    Serial.println(F("FONA basic test"));
 76  
 77    while (! fonainit()) {
 78      delay(5000);
 79    }
 80    
 81    // Print SIM card IMEI number.
 82    char imei[15] = {0}; // MUST use a 16 character buffer for IMEI!
 83    uint8_t imeiLen = fona.getIMEI(imei);
 84    if (imeiLen > 0) {
 85      Serial.print("SIM card IMEI: "); Serial.println(imei);
 86    }
 87    
 88    pinMode(FONA_RI, INPUT);
 89    digitalWrite(FONA_RI, HIGH); // turn on pullup on RI
 90    // turn on RI pin change on incoming SMS!
 91    fona.sendCheckReply(F("AT+CFGRI=1"), F("OK"));
 92  }
 93  
 94  int8_t lastsmsnum = 0;
 95  
 96  void loop() {
 97     digitalWrite(LED, HIGH);
 98     delay(100);
 99     digitalWrite(LED, LOW);
100         
101    while (fona.getNetworkStatus() != 1) {
102      Serial.println("Waiting for cell connection");
103      delay(2000);
104    }
105    
106    // this is a 'busy wait' loop, we check if the interrupt
107    // pin went low, and after BUSYWAIT milliseconds break out to check
108    // manually for SMS's and connection status
109    // This would be a good place to 'sleep'
110    for (uint16_t i=0; i<BUSYWAIT; i++) {
111       if (! digitalRead(FONA_RI)) {
112          // RI pin went low, SMS received?
113          Serial.println(F("RI went low"));
114          break;
115       } 
116       delay(1);
117    }
118    
119    int8_t smsnum = fona.getNumSMS();
120    if (smsnum < 0) {
121      Serial.println(F("Could not read # SMS"));
122      return;
123    } else {
124      Serial.print(smsnum); 
125      Serial.println(F(" SMS's on SIM card!"));
126    }
127    
128    if (smsnum == 0) return;
129  
130    // there's an SMS!
131    uint8_t n = 1; 
132    while (true) {
133       uint16_t smslen;
134       char sender[25];
135       
136       Serial.print(F("\n\rReading SMS #")); Serial.println(n);
137       uint8_t len = fona.readSMS(n, replybuffer, 250, &smslen); // pass in buffer and max len!
138       // if the length is zero, its a special case where the index number is higher
139       // so increase the max we'll look at!
140       if (len == 0) {
141          Serial.println(F("[empty slot]"));
142          n++;
143          continue;
144       }
145       if (! fona.getSMSSender(n, sender, sizeof(sender))) {
146         // failed to get the sender?
147         sender[0] = 0;
148       }
149       
150       Serial.print(F("***** SMS #")); Serial.print(n);
151       Serial.print(" ("); Serial.print(len); Serial.println(F(") bytes *****"));
152       Serial.println(replybuffer);
153       Serial.print(F("From: ")); Serial.println(sender);
154       Serial.println(F("*****"));
155       
156       if (strcasecmp(replybuffer, "open sesame") == 0) {
157         // open the door!
158         digitalWrite(LED, HIGH);
159         moveMotor(OPEN, 800);
160         digitalWrite(LED, LOW);
161       }
162       if (strcasecmp(replybuffer, "close cadabra") == 0) {
163         // close the door!
164         digitalWrite(LED, HIGH);
165         moveMotor(CLOSE, 800);
166         digitalWrite(LED, LOW);
167       }
168       
169       delay(3000);
170       break;
171    }  
172    fona.deleteSMS(n);
173   
174    delay(1000); 
175  }
176  
177  
178  void moveMotor(boolean direction, uint16_t t) {
179    digitalWrite(MOTOR_PWM, HIGH);   // enable motor
180    if (direction) {
181      digitalWrite(MOTOR_1, HIGH);
182      digitalWrite(MOTOR_2, LOW);
183    } else {
184      digitalWrite(MOTOR_2, HIGH);
185      digitalWrite(MOTOR_1, LOW);  
186    }
187    delay(t);
188    digitalWrite(MOTOR_1, LOW);
189    digitalWrite(MOTOR_2, LOW);
190  
191    digitalWrite(MOTOR_PWM, LOW);    // disable motor
192  }