Merge pull request #354 from GertSanders/development
Adding SMS Gateway node example and supporting library.
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
language: c
|
||||
sudo: false
|
||||
before_install:
|
||||
- source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/install.sh)
|
||||
script:
|
||||
- build_main_platforms
|
||||
notifications:
|
||||
email:
|
||||
on_success: change
|
||||
on_failure: change
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,257 @@
|
||||
/***************************************************
|
||||
This is a library for our Adafruit FONA Cellular Module
|
||||
|
||||
Designed specifically to work with the Adafruit FONA
|
||||
----> http://www.adafruit.com/products/1946
|
||||
----> http://www.adafruit.com/products/1963
|
||||
|
||||
These displays use TTL Serial to communicate, 2 pins are required to
|
||||
interface
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, all text above must be included in any redistribution
|
||||
****************************************************/
|
||||
#ifndef ADAFRUIT_FONA_H
|
||||
#define ADAFRUIT_FONA_H
|
||||
|
||||
#if (ARDUINO >= 100)
|
||||
#include "Arduino.h"
|
||||
#ifndef __SAM3X8E__ // Arduino Due doesn't support SoftwareSerial
|
||||
#include <SoftwareSerial.h>
|
||||
#endif
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#include <NewSoftSerial.h>
|
||||
#endif
|
||||
|
||||
#define ADAFRUIT_FONA_DEBUG
|
||||
|
||||
#define FONA800L 1
|
||||
#define FONA800H 6
|
||||
|
||||
#define FONA808_V1 2
|
||||
#define FONA808_V2 3
|
||||
|
||||
#define FONA3G_A 4
|
||||
#define FONA3G_E 5
|
||||
|
||||
|
||||
#define FONA_HEADSETAUDIO 0
|
||||
#define FONA_EXTAUDIO 1
|
||||
|
||||
#define FONA_STTONE_DIALTONE 1
|
||||
#define FONA_STTONE_BUSY 2
|
||||
#define FONA_STTONE_CONGESTION 3
|
||||
#define FONA_STTONE_PATHACK 4
|
||||
#define FONA_STTONE_DROPPED 5
|
||||
#define FONA_STTONE_ERROR 6
|
||||
#define FONA_STTONE_CALLWAIT 7
|
||||
#define FONA_STTONE_RINGING 8
|
||||
#define FONA_STTONE_BEEP 16
|
||||
#define FONA_STTONE_POSTONE 17
|
||||
#define FONA_STTONE_ERRTONE 18
|
||||
#define FONA_STTONE_INDIANDIALTONE 19
|
||||
#define FONA_STTONE_USADIALTONE 20
|
||||
|
||||
#define FONA_DEFAULT_TIMEOUT_MS 500
|
||||
|
||||
#define FONA_HTTP_GET 0
|
||||
#define FONA_HTTP_POST 1
|
||||
#define FONA_HTTP_HEAD 2
|
||||
|
||||
class Adafruit_FONA : public Stream {
|
||||
public:
|
||||
Adafruit_FONA(int8_t r);
|
||||
boolean begin(Stream &port);
|
||||
uint8_t type();
|
||||
|
||||
// Stream
|
||||
int available(void);
|
||||
size_t write(uint8_t x);
|
||||
int read(void);
|
||||
int peek(void);
|
||||
void flush();
|
||||
|
||||
// FONA 3G requirements
|
||||
boolean setBaudrate(uint16_t baud);
|
||||
|
||||
// RTC
|
||||
boolean enableRTC(uint8_t i);
|
||||
boolean readRTC(uint8_t *year, uint8_t *month, uint8_t *date, uint8_t *hr, uint8_t *min, uint8_t *sec);
|
||||
|
||||
// Battery and ADC
|
||||
boolean getADCVoltage(uint16_t *v);
|
||||
boolean getBattPercent(uint16_t *p);
|
||||
boolean getBattVoltage(uint16_t *v);
|
||||
|
||||
// SIM query
|
||||
uint8_t unlockSIM(char *pin);
|
||||
uint8_t getSIMCCID(char *ccid);
|
||||
uint8_t getNetworkStatus(void);
|
||||
uint8_t getRSSI(void);
|
||||
|
||||
// IMEI
|
||||
uint8_t getIMEI(char *imei);
|
||||
|
||||
// set Audio output
|
||||
boolean setAudio(uint8_t a);
|
||||
boolean setVolume(uint8_t i);
|
||||
uint8_t getVolume(void);
|
||||
boolean playToolkitTone(uint8_t t, uint16_t len);
|
||||
boolean setMicVolume(uint8_t a, uint8_t level);
|
||||
boolean playDTMF(char tone);
|
||||
|
||||
// FM radio functions.
|
||||
boolean tuneFMradio(uint16_t station);
|
||||
boolean FMradio(boolean onoff, uint8_t a = FONA_HEADSETAUDIO);
|
||||
boolean setFMVolume(uint8_t i);
|
||||
int8_t getFMVolume();
|
||||
int8_t getFMSignalLevel(uint16_t station);
|
||||
|
||||
// SMS handling
|
||||
boolean setSMSInterrupt(uint8_t i);
|
||||
uint8_t getSMSInterrupt(void);
|
||||
int8_t getNumSMS(void);
|
||||
boolean readSMS(uint8_t i, char *smsbuff, uint16_t max, uint16_t *readsize);
|
||||
boolean sendSMS(char *smsaddr, char *smsmsg);
|
||||
boolean deleteSMS(uint8_t i);
|
||||
boolean getSMSSender(uint8_t i, char *sender, int senderlen);
|
||||
|
||||
// Time
|
||||
boolean enableNetworkTimeSync(boolean onoff);
|
||||
boolean enableNTPTimeSync(boolean onoff, const __FlashStringHelper *ntpserver=0);
|
||||
boolean getTime(char *buff, uint16_t maxlen);
|
||||
|
||||
// GPRS handling
|
||||
boolean enableGPRS(boolean onoff);
|
||||
uint8_t GPRSstate(void);
|
||||
boolean getGSMLoc(uint16_t *replycode, char *buff, uint16_t maxlen);
|
||||
boolean getGSMLoc(float *lat, float *lon);
|
||||
void setGPRSNetworkSettings(const __FlashStringHelper *apn, const __FlashStringHelper *username=0, const __FlashStringHelper *password=0);
|
||||
|
||||
// GPS handling
|
||||
boolean enableGPS(boolean onoff);
|
||||
int8_t GPSstatus(void);
|
||||
uint8_t getGPS(uint8_t arg, char *buffer, uint8_t maxbuff);
|
||||
boolean getGPS(float *lat, float *lon, float *speed_kph=0, float *heading=0, float *altitude=0);
|
||||
boolean enableGPSNMEA(uint8_t nmea);
|
||||
|
||||
// TCP raw connections
|
||||
boolean TCPconnect(char *server, uint16_t port);
|
||||
boolean TCPclose(void);
|
||||
boolean TCPconnected(void);
|
||||
boolean TCPsend(char *packet, uint8_t len);
|
||||
uint16_t TCPavailable(void);
|
||||
uint16_t TCPread(uint8_t *buff, uint8_t len);
|
||||
|
||||
// HTTP low level interface (maps directly to SIM800 commands).
|
||||
boolean HTTP_init();
|
||||
boolean HTTP_term();
|
||||
void HTTP_para_start(const __FlashStringHelper *parameter, boolean quoted = true);
|
||||
boolean HTTP_para_end(boolean quoted = true);
|
||||
boolean HTTP_para(const __FlashStringHelper *parameter, const char *value);
|
||||
boolean HTTP_para(const __FlashStringHelper *parameter, const __FlashStringHelper *value);
|
||||
boolean HTTP_para(const __FlashStringHelper *parameter, int32_t value);
|
||||
boolean HTTP_data(uint32_t size, uint32_t maxTime=10000);
|
||||
boolean HTTP_action(uint8_t method, uint16_t *status, uint16_t *datalen, int32_t timeout = 10000);
|
||||
boolean HTTP_readall(uint16_t *datalen);
|
||||
boolean HTTP_ssl(boolean onoff);
|
||||
|
||||
// HTTP high level interface (easier to use, less flexible).
|
||||
boolean HTTP_GET_start(char *url, uint16_t *status, uint16_t *datalen);
|
||||
void HTTP_GET_end(void);
|
||||
boolean HTTP_POST_start(char *url, const __FlashStringHelper *contenttype, const uint8_t *postdata, uint16_t postdatalen, uint16_t *status, uint16_t *datalen);
|
||||
void HTTP_POST_end(void);
|
||||
void setUserAgent(const __FlashStringHelper *useragent);
|
||||
|
||||
// HTTPS
|
||||
void setHTTPSRedirect(boolean onoff);
|
||||
|
||||
// PWM (buzzer)
|
||||
boolean setPWM(uint16_t period, uint8_t duty = 50);
|
||||
|
||||
// Phone calls
|
||||
boolean callPhone(char *phonenum);
|
||||
boolean hangUp(void);
|
||||
boolean pickUp(void);
|
||||
boolean callerIdNotification(boolean enable, uint8_t interrupt = 0);
|
||||
boolean incomingCallNumber(char* phonenum);
|
||||
|
||||
// Helper functions to verify responses.
|
||||
boolean expectReply(const __FlashStringHelper *reply, uint16_t timeout = 10000);
|
||||
boolean sendCheckReply(char *send, char *reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
|
||||
boolean sendCheckReply(const __FlashStringHelper *send, const __FlashStringHelper *reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
|
||||
|
||||
|
||||
protected:
|
||||
int8_t _rstpin;
|
||||
uint8_t _type;
|
||||
|
||||
char replybuffer[255];
|
||||
const __FlashStringHelper *apn;
|
||||
const __FlashStringHelper *apnusername;
|
||||
const __FlashStringHelper *apnpassword;
|
||||
boolean httpsredirect;
|
||||
const __FlashStringHelper *useragent;
|
||||
|
||||
// HTTP helpers
|
||||
boolean HTTP_setup(char *url);
|
||||
|
||||
void flushInput();
|
||||
uint16_t readRaw(uint16_t b);
|
||||
uint8_t readline(uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS, boolean multiline = false);
|
||||
uint8_t getReply(char *send, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
|
||||
uint8_t getReply(const __FlashStringHelper *send, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
|
||||
uint8_t getReply(const __FlashStringHelper *prefix, char *suffix, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
|
||||
uint8_t getReply(const __FlashStringHelper *prefix, int32_t suffix, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
|
||||
uint8_t getReply(const __FlashStringHelper *prefix, int32_t suffix1, int32_t suffix2, uint16_t timeout); // Don't set default value or else function call is ambiguous.
|
||||
uint8_t getReplyQuoted(const __FlashStringHelper *prefix, const __FlashStringHelper *suffix, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
|
||||
|
||||
boolean sendCheckReply(const __FlashStringHelper *prefix, char *suffix, const __FlashStringHelper *reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
|
||||
boolean sendCheckReply(const __FlashStringHelper *prefix, int32_t suffix, const __FlashStringHelper *reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
|
||||
boolean sendCheckReply(const __FlashStringHelper *prefix, int32_t suffix, int32_t suffix2, const __FlashStringHelper *reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
|
||||
boolean sendCheckReplyQuoted(const __FlashStringHelper *prefix, const __FlashStringHelper *suffix, const __FlashStringHelper *reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
|
||||
|
||||
|
||||
boolean parseReply(const __FlashStringHelper *toreply,
|
||||
uint16_t *v, char divider = ',', uint8_t index=0);
|
||||
boolean parseReply(const __FlashStringHelper *toreply,
|
||||
char *v, char divider = ',', uint8_t index=0);
|
||||
boolean parseReplyQuoted(const __FlashStringHelper *toreply,
|
||||
char *v, int maxlen, char divider, uint8_t index);
|
||||
|
||||
boolean sendParseReply(const __FlashStringHelper *tosend,
|
||||
const __FlashStringHelper *toreply,
|
||||
uint16_t *v, char divider = ',', uint8_t index=0);
|
||||
|
||||
static boolean _incomingCall;
|
||||
static void onIncomingCall();
|
||||
|
||||
Stream *mySerial;
|
||||
};
|
||||
|
||||
class Adafruit_FONA_3G : public Adafruit_FONA {
|
||||
|
||||
public:
|
||||
Adafruit_FONA_3G (int8_t r) : Adafruit_FONA(r) { _type = FONA3G_A; }
|
||||
|
||||
boolean getBattVoltage(uint16_t *v);
|
||||
boolean playToolkitTone(uint8_t t, uint16_t len);
|
||||
boolean hangUp(void);
|
||||
boolean pickUp(void);
|
||||
boolean enableGPRS(boolean onoff);
|
||||
boolean enableGPS(boolean onoff);
|
||||
|
||||
protected:
|
||||
boolean parseReply(const __FlashStringHelper *toreply,
|
||||
float *f, char divider, uint8_t index);
|
||||
|
||||
boolean sendParseReply(const __FlashStringHelper *tosend,
|
||||
const __FlashStringHelper *toreply,
|
||||
float *f, char divider = ',', uint8_t index=0);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,29 @@
|
||||
# Adafruit FONA Library [](https://travis-ci.org/adafruit/Adafruit_FONA_Library)
|
||||
|
||||
**This library requires Arduino v1.0.6 or higher**
|
||||
|
||||
This is a library for the Adafruit FONA Cellular GSM Breakouts etc
|
||||
|
||||
Designed specifically to work with the Adafruit FONA Breakout
|
||||
* https://www.adafruit.com/products/1946
|
||||
* https://www.adafruit.com/products/1963
|
||||
* http://www.adafruit.com/products/2468
|
||||
* http://www.adafruit.com/products/2542
|
||||
|
||||
These modules use TTL Serial to communicate, 2 pins are required to interface
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Check out the links above for our tutorials and wiring diagrams
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, all text above must be included in any redistribution
|
||||
With updates from Samy Kamkar
|
||||
|
||||
To download. click the DOWNLOADS button in the top right corner, rename the uncompressed folder Adafruit_FONA
|
||||
Check that the Adafruit_FONA folder contains Adafruit_FONA.cpp and Adafruit_FONA.h
|
||||
|
||||
Place the Adafruit_FONA library folder your *arduinosketchfolder*/libraries/ folder.
|
||||
You may need to create the libraries subfolder if its your first library. Restart the IDE.
|
||||
@@ -0,0 +1,77 @@
|
||||
/***************************************************
|
||||
This is an example for our Adafruit FONA Cellular Module
|
||||
since the FONA 3G does not do auto-baud very well, this demo
|
||||
fixes the baud rate to 4800 from the default 115200
|
||||
|
||||
Designed specifically to work with the Adafruit FONA 3G
|
||||
----> http://www.adafruit.com/products/2691
|
||||
----> http://www.adafruit.com/products/2687
|
||||
|
||||
These cellular modules use TTL Serial to communicate, 2 pins are
|
||||
required to interface
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, all text above must be included in any redistribution
|
||||
****************************************************/
|
||||
|
||||
#include "Adafruit_FONA.h"
|
||||
|
||||
#define FONA_RX 2
|
||||
#define FONA_TX 3
|
||||
#define FONA_RST 4
|
||||
|
||||
// this is a large buffer for replies
|
||||
char replybuffer[255];
|
||||
|
||||
// We default to using software serial. If you want to use hardware serial
|
||||
// (because softserial isnt supported) comment out the following three lines
|
||||
// and uncomment the HardwareSerial line
|
||||
#include <SoftwareSerial.h>
|
||||
SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX);
|
||||
SoftwareSerial *fonaSerial = &fonaSS;
|
||||
|
||||
// Hardware serial is also possible!
|
||||
// HardwareSerial *fonaSerial = &Serial1;
|
||||
|
||||
Adafruit_FONA fona = Adafruit_FONA(FONA_RST);
|
||||
|
||||
uint8_t readline(char *buff, uint8_t maxbuff, uint16_t timeout = 0);
|
||||
|
||||
void setup() {
|
||||
while (!Serial);
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println(F("FONA set baudrate"));
|
||||
|
||||
Serial.println(F("First trying 115200 baud"));
|
||||
// start at 115200 baud
|
||||
fonaSerial->begin(115200);
|
||||
fona.begin(*fonaSerial);
|
||||
|
||||
// send the command to reset the baud rate to 4800
|
||||
fona.setBaudrate(4800);
|
||||
|
||||
// restart with 4800 baud
|
||||
fonaSerial->begin(4800);
|
||||
Serial.println(F("Initializing @ 4800 baud..."));
|
||||
|
||||
if (! fona.begin(*fonaSerial)) {
|
||||
Serial.println(F("Couldn't find FONA"));
|
||||
while(1);
|
||||
}
|
||||
Serial.println(F("FONA is OK"));
|
||||
|
||||
// Print module IMEI number.
|
||||
char imei[15] = {0}; // MUST use a 16 character buffer for IMEI!
|
||||
uint8_t imeiLen = fona.getIMEI(imei);
|
||||
if (imeiLen > 0) {
|
||||
Serial.print("Module IMEI: "); Serial.println(imei);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/***************************************************
|
||||
This is an example for our Adafruit FONA Cellular Module
|
||||
|
||||
Designed specifically to work with the Adafruit FONA
|
||||
----> http://www.adafruit.com/products/1946
|
||||
----> http://www.adafruit.com/products/1963
|
||||
----> http://www.adafruit.com/products/2468
|
||||
----> http://www.adafruit.com/products/2542
|
||||
|
||||
These cellular modules use TTL Serial to communicate, 2 pins are
|
||||
required to interface
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, all text above must be included in any redistribution
|
||||
****************************************************/
|
||||
|
||||
/*
|
||||
THIS CODE IS STILL IN PROGRESS!
|
||||
|
||||
Open up the serial console on the Arduino at 115200 baud to interact with FONA
|
||||
|
||||
|
||||
This code will receive an SMS, identify the sender's phone number, and automatically send a response
|
||||
|
||||
*/
|
||||
|
||||
#include "Adafruit_FONA.h"
|
||||
|
||||
#define FONA_RX 2
|
||||
#define FONA_TX 3
|
||||
#define FONA_RST 4
|
||||
|
||||
// this is a large buffer for replies
|
||||
char replybuffer[255];
|
||||
|
||||
// We default to using software serial. If you want to use hardware serial
|
||||
// (because softserial isnt supported) comment out the following three lines
|
||||
// and uncomment the HardwareSerial line
|
||||
#include <SoftwareSerial.h>
|
||||
SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX);
|
||||
SoftwareSerial *fonaSerial = &fonaSS;
|
||||
|
||||
// Hardware serial is also possible!
|
||||
// HardwareSerial *fonaSerial = &Serial1;
|
||||
|
||||
Adafruit_FONA fona = Adafruit_FONA(FONA_RST);
|
||||
|
||||
uint8_t readline(char *buff, uint8_t maxbuff, uint16_t timeout = 0);
|
||||
|
||||
void setup() {
|
||||
while (!Serial);
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println(F("FONA SMS caller ID test"));
|
||||
Serial.println(F("Initializing....(May take 3 seconds)"));
|
||||
|
||||
// make it slow so its easy to read!
|
||||
fonaSerial->begin(4800);
|
||||
if (! fona.begin(*fonaSerial)) {
|
||||
Serial.println(F("Couldn't find FONA"));
|
||||
while(1);
|
||||
}
|
||||
Serial.println(F("FONA is OK"));
|
||||
|
||||
// Print SIM card IMEI number.
|
||||
char imei[15] = {0}; // MUST use a 16 character buffer for IMEI!
|
||||
uint8_t imeiLen = fona.getIMEI(imei);
|
||||
if (imeiLen > 0) {
|
||||
Serial.print("SIM card IMEI: "); Serial.println(imei);
|
||||
}
|
||||
|
||||
Serial.println("FONA Ready");
|
||||
}
|
||||
|
||||
|
||||
char fonaInBuffer[64]; //for notifications from the FONA
|
||||
|
||||
void loop() {
|
||||
|
||||
char* bufPtr = fonaInBuffer; //handy buffer pointer
|
||||
|
||||
if (fona.available()) //any data available from the FONA?
|
||||
{
|
||||
int slot = 0; //this will be the slot number of the SMS
|
||||
int charCount = 0;
|
||||
//Read the notification into fonaInBuffer
|
||||
do {
|
||||
*bufPtr = fona.read();
|
||||
Serial.write(*bufPtr);
|
||||
delay(1);
|
||||
} while ((*bufPtr++ != '\n') && (fona.available()) && (++charCount < (sizeof(fonaInBuffer)-1)));
|
||||
|
||||
//Add a terminal NULL to the notification string
|
||||
*bufPtr = 0;
|
||||
|
||||
//Scan the notification string for an SMS received notification.
|
||||
// If it's an SMS message, we'll get the slot number in 'slot'
|
||||
if (1 == sscanf(fonaInBuffer, "+CMTI: \"SM\",%d", &slot)) {
|
||||
Serial.print("slot: "); Serial.println(slot);
|
||||
|
||||
char callerIDbuffer[32]; //we'll store the SMS sender number in here
|
||||
|
||||
// Retrieve SMS sender address/phone number.
|
||||
if (! fona.getSMSSender(slot, callerIDbuffer, 31)) {
|
||||
Serial.println("Didn't find SMS message in slot!");
|
||||
}
|
||||
Serial.print(F("FROM: ")); Serial.println(callerIDbuffer);
|
||||
|
||||
//Send back an automatic response
|
||||
Serial.println("Sending reponse...");
|
||||
if (!fona.sendSMS(callerIDbuffer, "Hey, I got your text!")) {
|
||||
Serial.println(F("Failed"));
|
||||
} else {
|
||||
Serial.println(F("Sent!"));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,851 @@
|
||||
/***************************************************
|
||||
This is an example for our Adafruit FONA Cellular Module
|
||||
|
||||
Designed specifically to work with the Adafruit FONA
|
||||
----> http://www.adafruit.com/products/1946
|
||||
----> http://www.adafruit.com/products/1963
|
||||
----> http://www.adafruit.com/products/2468
|
||||
----> http://www.adafruit.com/products/2542
|
||||
|
||||
These cellular modules use TTL Serial to communicate, 2 pins are
|
||||
required to interface
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
BSD license, all text above must be included in any redistribution
|
||||
****************************************************/
|
||||
|
||||
/*
|
||||
THIS CODE IS STILL IN PROGRESS!
|
||||
|
||||
Open up the serial console on the Arduino at 115200 baud to interact with FONA
|
||||
|
||||
Note that if you need to set a GPRS APN, username, and password scroll down to
|
||||
the commented section below at the end of the setup() function.
|
||||
*/
|
||||
#include "Adafruit_FONA.h"
|
||||
|
||||
#define FONA_RX 2
|
||||
#define FONA_TX 3
|
||||
#define FONA_RST 4
|
||||
|
||||
// this is a large buffer for replies
|
||||
char replybuffer[255];
|
||||
|
||||
// We default to using software serial. If you want to use hardware serial
|
||||
// (because softserial isnt supported) comment out the following three lines
|
||||
// and uncomment the HardwareSerial line
|
||||
#include <SoftwareSerial.h>
|
||||
SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX);
|
||||
SoftwareSerial *fonaSerial = &fonaSS;
|
||||
|
||||
// Hardware serial is also possible!
|
||||
// HardwareSerial *fonaSerial = &Serial1;
|
||||
|
||||
// Use this for FONA 800 and 808s
|
||||
Adafruit_FONA fona = Adafruit_FONA(FONA_RST);
|
||||
// Use this one for FONA 3G
|
||||
//Adafruit_FONA_3G fona = Adafruit_FONA_3G(FONA_RST);
|
||||
|
||||
uint8_t readline(char *buff, uint8_t maxbuff, uint16_t timeout = 0);
|
||||
|
||||
uint8_t type;
|
||||
|
||||
void setup() {
|
||||
while (!Serial);
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println(F("FONA basic test"));
|
||||
Serial.println(F("Initializing....(May take 3 seconds)"));
|
||||
|
||||
fonaSerial->begin(4800);
|
||||
if (! fona.begin(*fonaSerial)) {
|
||||
Serial.println(F("Couldn't find FONA"));
|
||||
while (1);
|
||||
}
|
||||
type = fona.type();
|
||||
Serial.println(F("FONA is OK"));
|
||||
Serial.print(F("Found "));
|
||||
switch (type) {
|
||||
case FONA800L:
|
||||
Serial.println(F("FONA 800L")); break;
|
||||
case FONA800H:
|
||||
Serial.println(F("FONA 800H")); break;
|
||||
case FONA808_V1:
|
||||
Serial.println(F("FONA 808 (v1)")); break;
|
||||
case FONA808_V2:
|
||||
Serial.println(F("FONA 808 (v2)")); break;
|
||||
case FONA3G_A:
|
||||
Serial.println(F("FONA 3G (American)")); break;
|
||||
case FONA3G_E:
|
||||
Serial.println(F("FONA 3G (European)")); break;
|
||||
default:
|
||||
Serial.println(F("???")); break;
|
||||
}
|
||||
|
||||
// Print module IMEI number.
|
||||
char imei[15] = {0}; // MUST use a 16 character buffer for IMEI!
|
||||
uint8_t imeiLen = fona.getIMEI(imei);
|
||||
if (imeiLen > 0) {
|
||||
Serial.print("Module IMEI: "); Serial.println(imei);
|
||||
}
|
||||
|
||||
// Optionally configure a GPRS APN, username, and password.
|
||||
// You might need to do this to access your network's GPRS/data
|
||||
// network. Contact your provider for the exact APN, username,
|
||||
// and password values. Username and password are optional and
|
||||
// can be removed, but APN is required.
|
||||
//fona.setGPRSNetworkSettings(F("your APN"), F("your username"), F("your password"));
|
||||
|
||||
// Optionally configure HTTP gets to follow redirects over SSL.
|
||||
// Default is not to follow SSL redirects, however if you uncomment
|
||||
// the following line then redirects over SSL will be followed.
|
||||
//fona.setHTTPSRedirect(true);
|
||||
|
||||
printMenu();
|
||||
}
|
||||
|
||||
void printMenu(void) {
|
||||
Serial.println(F("-------------------------------------"));
|
||||
Serial.println(F("[?] Print this menu"));
|
||||
Serial.println(F("[a] read the ADC 2.8V max (FONA800 & 808)"));
|
||||
Serial.println(F("[b] read the Battery V and % charged"));
|
||||
Serial.println(F("[C] read the SIM CCID"));
|
||||
Serial.println(F("[U] Unlock SIM with PIN code"));
|
||||
Serial.println(F("[i] read RSSI"));
|
||||
Serial.println(F("[n] get Network status"));
|
||||
Serial.println(F("[v] set audio Volume"));
|
||||
Serial.println(F("[V] get Volume"));
|
||||
Serial.println(F("[H] set Headphone audio (FONA800 & 808)"));
|
||||
Serial.println(F("[e] set External audio (FONA800 & 808)"));
|
||||
Serial.println(F("[T] play audio Tone"));
|
||||
Serial.println(F("[P] PWM/Buzzer out (FONA800 & 808)"));
|
||||
|
||||
// FM (SIM800 only!)
|
||||
Serial.println(F("[f] tune FM radio (FONA800)"));
|
||||
Serial.println(F("[F] turn off FM (FONA800)"));
|
||||
Serial.println(F("[m] set FM volume (FONA800)"));
|
||||
Serial.println(F("[M] get FM volume (FONA800)"));
|
||||
Serial.println(F("[q] get FM station signal level (FONA800)"));
|
||||
|
||||
// Phone
|
||||
Serial.println(F("[c] make phone Call"));
|
||||
Serial.println(F("[h] Hang up phone"));
|
||||
Serial.println(F("[p] Pick up phone"));
|
||||
|
||||
// SMS
|
||||
Serial.println(F("[N] Number of SMSs"));
|
||||
Serial.println(F("[r] Read SMS #"));
|
||||
Serial.println(F("[R] Read All SMS"));
|
||||
Serial.println(F("[d] Delete SMS #"));
|
||||
Serial.println(F("[s] Send SMS"));
|
||||
|
||||
// Time
|
||||
Serial.println(F("[y] Enable network time sync (FONA 800 & 808)"));
|
||||
Serial.println(F("[Y] Enable NTP time sync (GPRS FONA 800 & 808)"));
|
||||
Serial.println(F("[t] Get network time"));
|
||||
|
||||
// GPRS
|
||||
Serial.println(F("[G] Enable GPRS"));
|
||||
Serial.println(F("[g] Disable GPRS"));
|
||||
Serial.println(F("[l] Query GSMLOC (GPRS)"));
|
||||
Serial.println(F("[w] Read webpage (GPRS)"));
|
||||
Serial.println(F("[W] Post to website (GPRS)"));
|
||||
|
||||
// GPS
|
||||
if ((type == FONA3G_A) || (type == FONA3G_E) || (type == FONA808_V1) || (type == FONA808_V2)) {
|
||||
Serial.println(F("[O] Turn GPS on (FONA 808 & 3G)"));
|
||||
Serial.println(F("[o] Turn GPS off (FONA 808 & 3G)"));
|
||||
Serial.println(F("[L] Query GPS location (FONA 808 & 3G)"));
|
||||
if (type == FONA808_V1) {
|
||||
Serial.println(F("[x] GPS fix status (FONA808 v1 only)"));
|
||||
}
|
||||
Serial.println(F("[E] Raw NMEA out (FONA808)"));
|
||||
}
|
||||
|
||||
Serial.println(F("[S] create Serial passthru tunnel"));
|
||||
Serial.println(F("-------------------------------------"));
|
||||
Serial.println(F(""));
|
||||
|
||||
}
|
||||
void loop() {
|
||||
Serial.print(F("FONA> "));
|
||||
while (! Serial.available() ) {
|
||||
if (fona.available()) {
|
||||
Serial.write(fona.read());
|
||||
}
|
||||
}
|
||||
|
||||
char command = Serial.read();
|
||||
Serial.println(command);
|
||||
|
||||
|
||||
switch (command) {
|
||||
case '?': {
|
||||
printMenu();
|
||||
break;
|
||||
}
|
||||
|
||||
case 'a': {
|
||||
// read the ADC
|
||||
uint16_t adc;
|
||||
if (! fona.getADCVoltage(&adc)) {
|
||||
Serial.println(F("Failed to read ADC"));
|
||||
} else {
|
||||
Serial.print(F("ADC = ")); Serial.print(adc); Serial.println(F(" mV"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'b': {
|
||||
// read the battery voltage and percentage
|
||||
uint16_t vbat;
|
||||
if (! fona.getBattVoltage(&vbat)) {
|
||||
Serial.println(F("Failed to read Batt"));
|
||||
} else {
|
||||
Serial.print(F("VBat = ")); Serial.print(vbat); Serial.println(F(" mV"));
|
||||
}
|
||||
|
||||
|
||||
if (! fona.getBattPercent(&vbat)) {
|
||||
Serial.println(F("Failed to read Batt"));
|
||||
} else {
|
||||
Serial.print(F("VPct = ")); Serial.print(vbat); Serial.println(F("%"));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'U': {
|
||||
// Unlock the SIM with a PIN code
|
||||
char PIN[5];
|
||||
flushSerial();
|
||||
Serial.println(F("Enter 4-digit PIN"));
|
||||
readline(PIN, 3);
|
||||
Serial.println(PIN);
|
||||
Serial.print(F("Unlocking SIM card: "));
|
||||
if (! fona.unlockSIM(PIN)) {
|
||||
Serial.println(F("Failed"));
|
||||
} else {
|
||||
Serial.println(F("OK!"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'C': {
|
||||
// read the CCID
|
||||
fona.getSIMCCID(replybuffer); // make sure replybuffer is at least 21 bytes!
|
||||
Serial.print(F("SIM CCID = ")); Serial.println(replybuffer);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'i': {
|
||||
// read the RSSI
|
||||
uint8_t n = fona.getRSSI();
|
||||
int8_t r;
|
||||
|
||||
Serial.print(F("RSSI = ")); Serial.print(n); Serial.print(": ");
|
||||
if (n == 0) r = -115;
|
||||
if (n == 1) r = -111;
|
||||
if (n == 31) r = -52;
|
||||
if ((n >= 2) && (n <= 30)) {
|
||||
r = map(n, 2, 30, -110, -54);
|
||||
}
|
||||
Serial.print(r); Serial.println(F(" dBm"));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'n': {
|
||||
// read the network/cellular status
|
||||
uint8_t n = fona.getNetworkStatus();
|
||||
Serial.print(F("Network status "));
|
||||
Serial.print(n);
|
||||
Serial.print(F(": "));
|
||||
if (n == 0) Serial.println(F("Not registered"));
|
||||
if (n == 1) Serial.println(F("Registered (home)"));
|
||||
if (n == 2) Serial.println(F("Not registered (searching)"));
|
||||
if (n == 3) Serial.println(F("Denied"));
|
||||
if (n == 4) Serial.println(F("Unknown"));
|
||||
if (n == 5) Serial.println(F("Registered roaming"));
|
||||
break;
|
||||
}
|
||||
|
||||
/*** Audio ***/
|
||||
case 'v': {
|
||||
// set volume
|
||||
flushSerial();
|
||||
if ( (type == FONA3G_A) || (type == FONA3G_E) ) {
|
||||
Serial.print(F("Set Vol [0-8] "));
|
||||
} else {
|
||||
Serial.print(F("Set Vol % [0-100] "));
|
||||
}
|
||||
uint8_t vol = readnumber();
|
||||
Serial.println();
|
||||
if (! fona.setVolume(vol)) {
|
||||
Serial.println(F("Failed"));
|
||||
} else {
|
||||
Serial.println(F("OK!"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'V': {
|
||||
uint8_t v = fona.getVolume();
|
||||
Serial.print(v);
|
||||
if ( (type == FONA3G_A) || (type == FONA3G_E) ) {
|
||||
Serial.println(" / 8");
|
||||
} else {
|
||||
Serial.println("%");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'H': {
|
||||
// Set Headphone output
|
||||
if (! fona.setAudio(FONA_HEADSETAUDIO)) {
|
||||
Serial.println(F("Failed"));
|
||||
} else {
|
||||
Serial.println(F("OK!"));
|
||||
}
|
||||
fona.setMicVolume(FONA_HEADSETAUDIO, 15);
|
||||
break;
|
||||
}
|
||||
case 'e': {
|
||||
// Set External output
|
||||
if (! fona.setAudio(FONA_EXTAUDIO)) {
|
||||
Serial.println(F("Failed"));
|
||||
} else {
|
||||
Serial.println(F("OK!"));
|
||||
}
|
||||
|
||||
fona.setMicVolume(FONA_EXTAUDIO, 10);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'T': {
|
||||
// play tone
|
||||
flushSerial();
|
||||
Serial.print(F("Play tone #"));
|
||||
uint8_t kittone = readnumber();
|
||||
Serial.println();
|
||||
// play for 1 second (1000 ms)
|
||||
if (! fona.playToolkitTone(kittone, 1000)) {
|
||||
Serial.println(F("Failed"));
|
||||
} else {
|
||||
Serial.println(F("OK!"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*** FM Radio ***/
|
||||
|
||||
case 'f': {
|
||||
// get freq
|
||||
flushSerial();
|
||||
Serial.print(F("FM Freq (eg 1011 == 101.1 MHz): "));
|
||||
uint16_t station = readnumber();
|
||||
Serial.println();
|
||||
// FM radio ON using headset
|
||||
if (fona.FMradio(true, FONA_HEADSETAUDIO)) {
|
||||
Serial.println(F("Opened"));
|
||||
}
|
||||
if (! fona.tuneFMradio(station)) {
|
||||
Serial.println(F("Failed"));
|
||||
} else {
|
||||
Serial.println(F("Tuned"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'F': {
|
||||
// FM radio off
|
||||
if (! fona.FMradio(false)) {
|
||||
Serial.println(F("Failed"));
|
||||
} else {
|
||||
Serial.println(F("OK!"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'm': {
|
||||
// Set FM volume.
|
||||
flushSerial();
|
||||
Serial.print(F("Set FM Vol [0-6]:"));
|
||||
uint8_t vol = readnumber();
|
||||
Serial.println();
|
||||
if (!fona.setFMVolume(vol)) {
|
||||
Serial.println(F("Failed"));
|
||||
} else {
|
||||
Serial.println(F("OK!"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'M': {
|
||||
// Get FM volume.
|
||||
uint8_t fmvol = fona.getFMVolume();
|
||||
if (fmvol < 0) {
|
||||
Serial.println(F("Failed"));
|
||||
} else {
|
||||
Serial.print(F("FM volume: "));
|
||||
Serial.println(fmvol, DEC);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'q': {
|
||||
// Get FM station signal level (in decibels).
|
||||
flushSerial();
|
||||
Serial.print(F("FM Freq (eg 1011 == 101.1 MHz): "));
|
||||
uint16_t station = readnumber();
|
||||
Serial.println();
|
||||
int8_t level = fona.getFMSignalLevel(station);
|
||||
if (level < 0) {
|
||||
Serial.println(F("Failed! Make sure FM radio is on (tuned to station)."));
|
||||
} else {
|
||||
Serial.print(F("Signal level (dB): "));
|
||||
Serial.println(level, DEC);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*** PWM ***/
|
||||
|
||||
case 'P': {
|
||||
// PWM Buzzer output @ 2KHz max
|
||||
flushSerial();
|
||||
Serial.print(F("PWM Freq, 0 = Off, (1-2000): "));
|
||||
uint16_t freq = readnumber();
|
||||
Serial.println();
|
||||
if (! fona.setPWM(freq)) {
|
||||
Serial.println(F("Failed"));
|
||||
} else {
|
||||
Serial.println(F("OK!"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*** Call ***/
|
||||
case 'c': {
|
||||
// call a phone!
|
||||
char number[30];
|
||||
flushSerial();
|
||||
Serial.print(F("Call #"));
|
||||
readline(number, 30);
|
||||
Serial.println();
|
||||
Serial.print(F("Calling ")); Serial.println(number);
|
||||
if (!fona.callPhone(number)) {
|
||||
Serial.println(F("Failed"));
|
||||
} else {
|
||||
Serial.println(F("Sent!"));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 'h': {
|
||||
// hang up!
|
||||
if (! fona.hangUp()) {
|
||||
Serial.println(F("Failed"));
|
||||
} else {
|
||||
Serial.println(F("OK!"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'p': {
|
||||
// pick up!
|
||||
if (! fona.pickUp()) {
|
||||
Serial.println(F("Failed"));
|
||||
} else {
|
||||
Serial.println(F("OK!"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*** SMS ***/
|
||||
|
||||
case 'N': {
|
||||
// read the number of SMS's!
|
||||
int8_t smsnum = fona.getNumSMS();
|
||||
if (smsnum < 0) {
|
||||
Serial.println(F("Could not read # SMS"));
|
||||
} else {
|
||||
Serial.print(smsnum);
|
||||
Serial.println(F(" SMS's on SIM card!"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'r': {
|
||||
// read an SMS
|
||||
flushSerial();
|
||||
Serial.print(F("Read #"));
|
||||
uint8_t smsn = readnumber();
|
||||
Serial.print(F("\n\rReading SMS #")); Serial.println(smsn);
|
||||
|
||||
// Retrieve SMS sender address/phone number.
|
||||
if (! fona.getSMSSender(smsn, replybuffer, 250)) {
|
||||
Serial.println("Failed!");
|
||||
break;
|
||||
}
|
||||
Serial.print(F("FROM: ")); Serial.println(replybuffer);
|
||||
|
||||
// Retrieve SMS value.
|
||||
uint16_t smslen;
|
||||
if (! fona.readSMS(smsn, replybuffer, 250, &smslen)) { // pass in buffer and max len!
|
||||
Serial.println("Failed!");
|
||||
break;
|
||||
}
|
||||
Serial.print(F("***** SMS #")); Serial.print(smsn);
|
||||
Serial.print(" ("); Serial.print(smslen); Serial.println(F(") bytes *****"));
|
||||
Serial.println(replybuffer);
|
||||
Serial.println(F("*****"));
|
||||
|
||||
break;
|
||||
}
|
||||
case 'R': {
|
||||
// read all SMS
|
||||
int8_t smsnum = fona.getNumSMS();
|
||||
uint16_t smslen;
|
||||
int8_t smsn;
|
||||
|
||||
if ( (type == FONA3G_A) || (type == FONA3G_E) ) {
|
||||
smsn = 0; // zero indexed
|
||||
smsnum--;
|
||||
} else {
|
||||
smsn = 1; // 1 indexed
|
||||
}
|
||||
|
||||
for ( ; smsn <= smsnum; smsn++) {
|
||||
Serial.print(F("\n\rReading SMS #")); Serial.println(smsn);
|
||||
if (!fona.readSMS(smsn, replybuffer, 250, &smslen)) { // pass in buffer and max len!
|
||||
Serial.println(F("Failed!"));
|
||||
break;
|
||||
}
|
||||
// if the length is zero, its a special case where the index number is higher
|
||||
// so increase the max we'll look at!
|
||||
if (smslen == 0) {
|
||||
Serial.println(F("[empty slot]"));
|
||||
smsnum++;
|
||||
continue;
|
||||
}
|
||||
|
||||
Serial.print(F("***** SMS #")); Serial.print(smsn);
|
||||
Serial.print(" ("); Serial.print(smslen); Serial.println(F(") bytes *****"));
|
||||
Serial.println(replybuffer);
|
||||
Serial.println(F("*****"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'd': {
|
||||
// delete an SMS
|
||||
flushSerial();
|
||||
Serial.print(F("Delete #"));
|
||||
uint8_t smsn = readnumber();
|
||||
|
||||
Serial.print(F("\n\rDeleting SMS #")); Serial.println(smsn);
|
||||
if (fona.deleteSMS(smsn)) {
|
||||
Serial.println(F("OK!"));
|
||||
} else {
|
||||
Serial.println(F("Couldn't delete"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 's': {
|
||||
// send an SMS!
|
||||
char sendto[21], message[141];
|
||||
flushSerial();
|
||||
Serial.print(F("Send to #"));
|
||||
readline(sendto, 20);
|
||||
Serial.println(sendto);
|
||||
Serial.print(F("Type out one-line message (140 char): "));
|
||||
readline(message, 140);
|
||||
Serial.println(message);
|
||||
if (!fona.sendSMS(sendto, message)) {
|
||||
Serial.println(F("Failed"));
|
||||
} else {
|
||||
Serial.println(F("Sent!"));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/*** Time ***/
|
||||
|
||||
case 'y': {
|
||||
// enable network time sync
|
||||
if (!fona.enableNetworkTimeSync(true))
|
||||
Serial.println(F("Failed to enable"));
|
||||
break;
|
||||
}
|
||||
|
||||
case 'Y': {
|
||||
// enable NTP time sync
|
||||
if (!fona.enableNTPTimeSync(true, F("pool.ntp.org")))
|
||||
Serial.println(F("Failed to enable"));
|
||||
break;
|
||||
}
|
||||
|
||||
case 't': {
|
||||
// read the time
|
||||
char buffer[23];
|
||||
|
||||
fona.getTime(buffer, 23); // make sure replybuffer is at least 23 bytes!
|
||||
Serial.print(F("Time = ")); Serial.println(buffer);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/*********************************** GPS (SIM808 only) */
|
||||
|
||||
case 'o': {
|
||||
// turn GPS off
|
||||
if (!fona.enableGPS(false))
|
||||
Serial.println(F("Failed to turn off"));
|
||||
break;
|
||||
}
|
||||
case 'O': {
|
||||
// turn GPS on
|
||||
if (!fona.enableGPS(true))
|
||||
Serial.println(F("Failed to turn on"));
|
||||
break;
|
||||
}
|
||||
case 'x': {
|
||||
int8_t stat;
|
||||
// check GPS fix
|
||||
stat = fona.GPSstatus();
|
||||
if (stat < 0)
|
||||
Serial.println(F("Failed to query"));
|
||||
if (stat == 0) Serial.println(F("GPS off"));
|
||||
if (stat == 1) Serial.println(F("No fix"));
|
||||
if (stat == 2) Serial.println(F("2D fix"));
|
||||
if (stat == 3) Serial.println(F("3D fix"));
|
||||
break;
|
||||
}
|
||||
|
||||
case 'L': {
|
||||
// check for GPS location
|
||||
char gpsdata[120];
|
||||
fona.getGPS(0, gpsdata, 120);
|
||||
if (type == FONA808_V1)
|
||||
Serial.println(F("Reply in format: mode,longitude,latitude,altitude,utctime(yyyymmddHHMMSS),ttff,satellites,speed,course"));
|
||||
else
|
||||
Serial.println(F("Reply in format: mode,fixstatus,utctime(yyyymmddHHMMSS),latitude,longitude,altitude,speed,course,fixmode,reserved1,HDOP,PDOP,VDOP,reserved2,view_satellites,used_satellites,reserved3,C/N0max,HPA,VPA"));
|
||||
Serial.println(gpsdata);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'E': {
|
||||
flushSerial();
|
||||
if (type == FONA808_V1) {
|
||||
Serial.print(F("GPS NMEA output sentences (0 = off, 34 = RMC+GGA, 255 = all)"));
|
||||
} else {
|
||||
Serial.print(F("On (1) or Off (0)? "));
|
||||
}
|
||||
uint8_t nmeaout = readnumber();
|
||||
|
||||
// turn on NMEA output
|
||||
fona.enableGPSNMEA(nmeaout);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/*********************************** GPRS */
|
||||
|
||||
case 'g': {
|
||||
// turn GPRS off
|
||||
if (!fona.enableGPRS(false))
|
||||
Serial.println(F("Failed to turn off"));
|
||||
break;
|
||||
}
|
||||
case 'G': {
|
||||
// turn GPRS on
|
||||
if (!fona.enableGPRS(true))
|
||||
Serial.println(F("Failed to turn on"));
|
||||
break;
|
||||
}
|
||||
case 'l': {
|
||||
// check for GSMLOC (requires GPRS)
|
||||
uint16_t returncode;
|
||||
|
||||
if (!fona.getGSMLoc(&returncode, replybuffer, 250))
|
||||
Serial.println(F("Failed!"));
|
||||
if (returncode == 0) {
|
||||
Serial.println(replybuffer);
|
||||
} else {
|
||||
Serial.print(F("Fail code #")); Serial.println(returncode);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 'w': {
|
||||
// read website URL
|
||||
uint16_t statuscode;
|
||||
int16_t length;
|
||||
char url[80];
|
||||
|
||||
flushSerial();
|
||||
Serial.println(F("NOTE: in beta! Use small webpages to read!"));
|
||||
Serial.println(F("URL to read (e.g. www.adafruit.com/testwifi/index.html):"));
|
||||
Serial.print(F("http://")); readline(url, 79);
|
||||
Serial.println(url);
|
||||
|
||||
Serial.println(F("****"));
|
||||
if (!fona.HTTP_GET_start(url, &statuscode, (uint16_t *)&length)) {
|
||||
Serial.println("Failed!");
|
||||
break;
|
||||
}
|
||||
while (length > 0) {
|
||||
while (fona.available()) {
|
||||
char c = fona.read();
|
||||
|
||||
// Serial.write is too slow, we'll write directly to Serial register!
|
||||
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
|
||||
loop_until_bit_is_set(UCSR0A, UDRE0); /* Wait until data register empty. */
|
||||
UDR0 = c;
|
||||
#else
|
||||
Serial.write(c);
|
||||
#endif
|
||||
length--;
|
||||
if (! length) break;
|
||||
}
|
||||
}
|
||||
Serial.println(F("\n****"));
|
||||
fona.HTTP_GET_end();
|
||||
break;
|
||||
}
|
||||
|
||||
case 'W': {
|
||||
// Post data to website
|
||||
uint16_t statuscode;
|
||||
int16_t length;
|
||||
char url[80];
|
||||
char data[80];
|
||||
|
||||
flushSerial();
|
||||
Serial.println(F("NOTE: in beta! Use simple websites to post!"));
|
||||
Serial.println(F("URL to post (e.g. httpbin.org/post):"));
|
||||
Serial.print(F("http://")); readline(url, 79);
|
||||
Serial.println(url);
|
||||
Serial.println(F("Data to post (e.g. \"foo\" or \"{\"simple\":\"json\"}\"):"));
|
||||
readline(data, 79);
|
||||
Serial.println(data);
|
||||
|
||||
Serial.println(F("****"));
|
||||
if (!fona.HTTP_POST_start(url, F("text/plain"), (uint8_t *) data, strlen(data), &statuscode, (uint16_t *)&length)) {
|
||||
Serial.println("Failed!");
|
||||
break;
|
||||
}
|
||||
while (length > 0) {
|
||||
while (fona.available()) {
|
||||
char c = fona.read();
|
||||
|
||||
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
|
||||
loop_until_bit_is_set(UCSR0A, UDRE0); /* Wait until data register empty. */
|
||||
UDR0 = c;
|
||||
#else
|
||||
Serial.write(c);
|
||||
#endif
|
||||
|
||||
length--;
|
||||
if (! length) break;
|
||||
}
|
||||
}
|
||||
Serial.println(F("\n****"));
|
||||
fona.HTTP_POST_end();
|
||||
break;
|
||||
}
|
||||
/*****************************************/
|
||||
|
||||
case 'S': {
|
||||
Serial.println(F("Creating SERIAL TUBE"));
|
||||
while (1) {
|
||||
while (Serial.available()) {
|
||||
delay(1);
|
||||
fona.write(Serial.read());
|
||||
}
|
||||
if (fona.available()) {
|
||||
Serial.write(fona.read());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
Serial.println(F("Unknown command"));
|
||||
printMenu();
|
||||
break;
|
||||
}
|
||||
}
|
||||
// flush input
|
||||
flushSerial();
|
||||
while (fona.available()) {
|
||||
Serial.write(fona.read());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void flushSerial() {
|
||||
while (Serial.available())
|
||||
Serial.read();
|
||||
}
|
||||
|
||||
char readBlocking() {
|
||||
while (!Serial.available());
|
||||
return Serial.read();
|
||||
}
|
||||
uint16_t readnumber() {
|
||||
uint16_t x = 0;
|
||||
char c;
|
||||
while (! isdigit(c = readBlocking())) {
|
||||
//Serial.print(c);
|
||||
}
|
||||
Serial.print(c);
|
||||
x = c - '0';
|
||||
while (isdigit(c = readBlocking())) {
|
||||
Serial.print(c);
|
||||
x *= 10;
|
||||
x += c - '0';
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
uint8_t readline(char *buff, uint8_t maxbuff, uint16_t timeout) {
|
||||
uint16_t buffidx = 0;
|
||||
boolean timeoutvalid = true;
|
||||
if (timeout == 0) timeoutvalid = false;
|
||||
|
||||
while (true) {
|
||||
if (buffidx > maxbuff) {
|
||||
//Serial.println(F("SPACE"));
|
||||
break;
|
||||
}
|
||||
|
||||
while (Serial.available()) {
|
||||
char c = Serial.read();
|
||||
|
||||
//Serial.print(c, HEX); Serial.print("#"); Serial.println(c);
|
||||
|
||||
if (c == '\r') continue;
|
||||
if (c == 0xA) {
|
||||
if (buffidx == 0) // the first 0x0A is ignored
|
||||
continue;
|
||||
|
||||
timeout = 0; // the second 0x0A is the end of the line
|
||||
timeoutvalid = true;
|
||||
break;
|
||||
}
|
||||
buff[buffidx] = c;
|
||||
buffidx++;
|
||||
}
|
||||
|
||||
if (timeoutvalid && timeout == 0) {
|
||||
//Serial.println(F("TIMEOUT"));
|
||||
break;
|
||||
}
|
||||
delay(1);
|
||||
}
|
||||
buff[buffidx] = 0; // null term
|
||||
return buffidx;
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* ___ ___ _ _ _ ___ __ ___ ___ ___ ___
|
||||
* | __/ _ \| \| | /_\ ( _ )/ \( _ ) / __| _ \/ __|
|
||||
* | _| (_) | .` |/ _ \ / _ \ () / _ \ | (_ | _/\__ \
|
||||
* |_| \___/|_|\_/_/ \_\ \___/\__/\___/ \___|_| |___/
|
||||
*
|
||||
* This example is meant to work with the Adafruit
|
||||
* FONA 808 or 3G Shield or Breakout
|
||||
*
|
||||
* Copyright: 2015 Adafruit
|
||||
* Author: Todd Treece
|
||||
* Licence: MIT
|
||||
*
|
||||
*/
|
||||
#include "Adafruit_FONA.h"
|
||||
|
||||
// standard pins for the shield, adjust as necessary
|
||||
#define FONA_RX 2
|
||||
#define FONA_TX 3
|
||||
#define FONA_RST 4
|
||||
|
||||
// We default to using software serial. If you want to use hardware serial
|
||||
// (because softserial isnt supported) comment out the following three lines
|
||||
// and uncomment the HardwareSerial line
|
||||
#include <SoftwareSerial.h>
|
||||
SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX);
|
||||
SoftwareSerial *fonaSerial = &fonaSS;
|
||||
|
||||
// Hardware serial is also possible!
|
||||
// HardwareSerial *fonaSerial = &Serial1;
|
||||
|
||||
Adafruit_FONA fona = Adafruit_FONA(FONA_RST);
|
||||
|
||||
// Have a FONA 3G? use this object type instead
|
||||
//Adafruit_FONA_3G fona = Adafruit_FONA_3G(FONA_RST);
|
||||
|
||||
|
||||
void setup() {
|
||||
|
||||
while (! Serial);
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println(F("Adafruit FONA 808 & 3G GPS demo"));
|
||||
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);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
delay(2000);
|
||||
|
||||
float latitude, longitude, speed_kph, heading, speed_mph, altitude;
|
||||
|
||||
// if you ask for an altitude reading, getGPS will return false if there isn't a 3D fix
|
||||
boolean gps_success = fona.getGPS(&latitude, &longitude, &speed_kph, &heading, &altitude);
|
||||
|
||||
if (gps_success) {
|
||||
|
||||
Serial.print("GPS lat:");
|
||||
Serial.println(latitude, 6);
|
||||
Serial.print("GPS long:");
|
||||
Serial.println(longitude, 6);
|
||||
Serial.print("GPS speed KPH:");
|
||||
Serial.println(speed_kph);
|
||||
Serial.print("GPS speed MPH:");
|
||||
speed_mph = speed_kph * 0.621371192;
|
||||
Serial.println(speed_mph);
|
||||
Serial.print("GPS heading:");
|
||||
Serial.println(heading);
|
||||
Serial.print("GPS altitude:");
|
||||
Serial.println(altitude);
|
||||
|
||||
} else {
|
||||
Serial.println("Waiting for FONA GPS 3D fix...");
|
||||
}
|
||||
|
||||
// Fona 3G doesnt have GPRSlocation :/
|
||||
if ((fona.type() == FONA3G_A) || (fona.type() == FONA3G_E))
|
||||
return;
|
||||
// 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
|
||||
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);
|
||||
} 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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
// FONA Incoming Call Number Example
|
||||
// Listens for a call and displays the phone number of the caller (if available).
|
||||
// Use this example to add phone call detection to your own FONA sketch.
|
||||
#include "Adafruit_FONA.h"
|
||||
|
||||
// Pins which are connected to the FONA.
|
||||
// Note that this is different from FONAtest!
|
||||
#define FONA_RX 3
|
||||
#define FONA_TX 4
|
||||
#define FONA_RST 5
|
||||
|
||||
// Note you need to map interrupt number to pin number
|
||||
// for your board. On an Uno & Mega interrupt 0 is
|
||||
// digital pin 2, and on a Leonardo interrupt 0 is
|
||||
// digital pin 3. See this page for a complete table:
|
||||
// http://arduino.cc/en/Reference/attachInterrupt
|
||||
// Make sure this interrupt pin is connected to FONA RI!
|
||||
#define FONA_RI_INTERRUPT 0
|
||||
|
||||
// We default to using software serial. If you want to use hardware serial
|
||||
// (because softserial isnt supported) comment out the following three lines
|
||||
// and uncomment the HardwareSerial line
|
||||
#include <SoftwareSerial.h>
|
||||
SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX);
|
||||
SoftwareSerial *fonaSerial = &fonaSS;
|
||||
|
||||
// Hardware serial is also possible!
|
||||
// HardwareSerial *fonaSerial = &Serial1;
|
||||
|
||||
Adafruit_FONA fona = Adafruit_FONA(FONA_RST);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println(F("FONA incoming call example"));
|
||||
Serial.println(F("Initializing....(May take 3 seconds)"));
|
||||
|
||||
fonaSerial->begin(4800);
|
||||
if (! fona.begin(*fonaSerial)) {
|
||||
Serial.println(F("Couldn't find FONA"));
|
||||
while(1);
|
||||
}
|
||||
Serial.println(F("FONA is OK"));
|
||||
|
||||
// Enable incoming call notification.
|
||||
if(fona.callerIdNotification(true, FONA_RI_INTERRUPT)) {
|
||||
Serial.println(F("Caller id notification enabled."));
|
||||
}
|
||||
else {
|
||||
Serial.println(F("Caller id notification disabled"));
|
||||
}
|
||||
}
|
||||
|
||||
void loop(){
|
||||
// Create a small string buffer to hold incoming call number.
|
||||
char phone[32] = {0};
|
||||
// Check for an incoming call. Will return true if a call is incoming.
|
||||
if(fona.incomingCallNumber(phone)){
|
||||
Serial.println(F("RING!"));
|
||||
Serial.print(F("Phone Number: "));
|
||||
Serial.println(phone);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
name=Adafruit FONA Library
|
||||
version=1.3.0
|
||||
author=Adafruit
|
||||
maintainer=Adafruit <info@adafruit.com>
|
||||
sentence=Arduino library for the Adafruit FONA
|
||||
paragraph=Arduino library for the Adafruit FONA
|
||||
category=Communication
|
||||
url=https://github.com/adafruit/Adafruit_FONA_Library
|
||||
architectures=*
|
||||
@@ -0,0 +1,646 @@
|
||||
/*
|
||||
SMS Gateway
|
||||
|
||||
This node works as a SMS gateway, receiving and sending SMS messages at the request of other nodes
|
||||
It needs to have a fixed ID to be able to be addessed within a MySensors network.
|
||||
As it is easy to remember I chose the ID 123.
|
||||
|
||||
Once the node is sent an initiating SMS, it will respond to the received calling number as it's "owner". This way you do not
|
||||
need to hardcode your number in the sketch. But to make it operational, you will need to send at least 1 SMS to it
|
||||
with the prededfined text MYPASSWORD (see below in the definitions, you set your own string).
|
||||
The node should respond with CONFIRMOWNER, you can set this string in de definitions below.
|
||||
The allow another phone to control the node and receive messages, the "owner" needs to release the node by sending a SMS with
|
||||
the text MYRELEASEWORD. Again you can set this string in the definitions below.
|
||||
The node will then again become ownerless and ignore all messages and SMS's.
|
||||
|
||||
If the node has an owner and another phone sends a message to the node, it will inform the owner of a "take over attempt".
|
||||
|
||||
You can sent V_TEXT to other nodes in your network by using the following format:
|
||||
|
||||
"N021:xxx.any.25.characters.xxx"
|
||||
|
||||
Anything sent after the "N021:" will be sent to the node with address 021. A V_TEXT has a maximum length of 25 charters. Adding the node address make the SMS length 30 charters.
|
||||
The SMS buffer is 31 characters long.
|
||||
|
||||
A node address can have a value 000 (the controller) and any value between 001 and 254. Values higher then 254 are ignored and nothing will be done with the
|
||||
received SMS, apart from informing the controller that this SMS was received.
|
||||
|
||||
Sending a SMS to the SMS Gateway with the address of the SMS Gateway itself will result in the SMS Gateway sending the same SMS back.
|
||||
So if you send the following SMS to your SMS Gateway:
|
||||
"N123:Are you there ?"
|
||||
You will receive a SMS with the content ""N123:Are you there ?"
|
||||
|
||||
What is happening ?
|
||||
|
||||
The SMS Gateway receives a SMS adressed to the node 123, the SMS Gateway sends a copy of the received SMS to the controller and sends a message with content "Are you there ?"
|
||||
to the node 123. Since node 123 is the SMS Gateway receiving a message, it will pass on this message as a SMS to the owner in the format specified earlier.
|
||||
So a text SMS is sent with content "N123:Are you there?"
|
||||
|
||||
If a node sends a V_TEXT "Garagedoor is opened" to the SMS Gateway, the SMS gateway will pass this on to the owner's GSM in the format below:
|
||||
"N011:Garagedoor is opened"
|
||||
Address from the node sending the text is sent first (in this case "N011:"), and then the contents of the V_TEXT itself is appended ("Garagedoor is opened").
|
||||
|
||||
You need a SIM800L module hooked to an atmega328 based MySensor node via softserial port. This sketch was made for my AC capable
|
||||
board wich allows use of a SIM800L module. More on that board on the forum at this location:
|
||||
http://forum.mysensors.org/topic/2374/50mm-x-50mm-board-with-different-powering-options/10
|
||||
or
|
||||
https://www.openhardware.io/view/11/ACDCBatteries-capable-atmega328p-board
|
||||
|
||||
Nodes that want to inform an GSM owner via the SMS Gateway need to have the capacity to send a V_TEXT.
|
||||
Even nodes that sleep most of the time can send messages to any other node. You just need to define a V_TEXT message type.
|
||||
|
||||
Nodes that need to react to SMS messages with instructions, need to be able to receive V_TEXT and need to be reachable (always on).
|
||||
So battery based nodes will not be the best candidates as actuators based on SMS.
|
||||
|
||||
This example code is in the public domain.
|
||||
|
||||
modified 10 oktober 2015 version 1.0
|
||||
modified 6 january 2016 version 1.1
|
||||
modified 15 january 2016 version 1.2
|
||||
|
||||
by GertSanders on the MySensors forum
|
||||
|
||||
Uses the Adafruit FONA library to drive the SIM800L, this need to be included in your library to compile this sketch.
|
||||
|
||||
|
||||
To do: create a buffer structure to handle several incoming messages from nodes or phone.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#define SKETCHNAME "SMSGatewayNode"
|
||||
#define SKETCHVERSION "1.2"
|
||||
|
||||
|
||||
// Enable debug prints to serial monitor
|
||||
|
||||
//#define MY_DEBUG
|
||||
//#define MY_DEBUG_VERBOSE
|
||||
|
||||
//#define MY_BAUD_RATE 57600
|
||||
|
||||
#define MY_NODE_ID 123
|
||||
#define GATEWAY_ID 0
|
||||
|
||||
// Enable and select radio type attached
|
||||
#define MY_RADIO_NRF24
|
||||
//#define MY_RADIO_RFM69
|
||||
|
||||
// defines for sensors
|
||||
//#define BATTERYLEVEL 0
|
||||
#define SMSTEXT 1
|
||||
|
||||
|
||||
// Enable repeater functionality for this node
|
||||
//#define MY_REPEATER_FEATURE
|
||||
|
||||
|
||||
// All includes
|
||||
#include <SPI.h>
|
||||
#include <SoftwareSerial.h>
|
||||
#include <Adafruit_FONA.h>
|
||||
#include <MySensor.h>
|
||||
|
||||
// Pin definitions and other defines
|
||||
#define FONA_RX 2
|
||||
#define FONA_TX 3
|
||||
#define FONA_RST 4
|
||||
|
||||
#define defaultledpin 8 // usually this is pin 13, but better to use another digital pin
|
||||
|
||||
// constants
|
||||
|
||||
#define MAXSMSLENGTH 30 // No need for longer messages from GSM's as V_TEXT is limiting what can be sent to the other nodes. Node addresses are maximum 000 -> 255
|
||||
#define MAXMSGLENGTH 25 // limiting factor is the payload of V_TEXT, which is 25 chars. Nodes will never send you more then this in 1 message.
|
||||
#define MAXNUMBERLENGTH 12 // based on "plus" sign, a country prefix and national number. Example in Belgium: +32 123 45 67
|
||||
#define MAXNODEID 254 // highest value a node ID can have
|
||||
|
||||
// following strings need to be set by you, maximum length is 30 CHARS.
|
||||
#define MYPASSWORD "Password" // replace this with your preferred passphrase to gain ownership
|
||||
#define CONFIRMOWNER "I am yours" // replace this string if your partner is of the untrusting type ;-)
|
||||
#define MYRELEASEWORD "I release you" // replace this with your preferred release confirmation
|
||||
|
||||
// variables
|
||||
|
||||
boolean KnowMyOwner = false;
|
||||
boolean MsgReceived = false;
|
||||
uint16_t smslen = 0;
|
||||
int8_t smsnum = 0;
|
||||
int bufferindex = 0;
|
||||
|
||||
char smsbuffer[MAXSMSLENGTH + 1] = "";
|
||||
char msgbuffer[MAXMSGLENGTH + 1] = "";
|
||||
char nodemsgbuffer[MAXMSGLENGTH + 1] = "";
|
||||
char nodeaddress[5];
|
||||
char Numbers[11] = "0123456789";
|
||||
|
||||
char myOwnersNumber[MAXNUMBERLENGTH + 1] = "";
|
||||
char ReceivedNumber[MAXNUMBERLENGTH + 1] = "";
|
||||
|
||||
// Instantiate objects
|
||||
MyMessage SMSMsg(SMSTEXT, V_TEXT);
|
||||
Adafruit_FONA fona = Adafruit_FONA(FONA_RST);
|
||||
SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX);
|
||||
SoftwareSerial *fonaSerial = &fonaSS;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// supporting functions.
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
void blipled()
|
||||
{
|
||||
digitalWrite(defaultledpin, HIGH); // turn the LED on (HIGH is the voltage level)
|
||||
wait(3); // wait for a second
|
||||
digitalWrite(defaultledpin, LOW); // turn the LED off by making the voltage HIGH
|
||||
wait(100); // wait for a second
|
||||
digitalWrite(defaultledpin, HIGH); // turn the LED on (HIGH is the voltage level)
|
||||
wait(3); // wait for a second
|
||||
digitalWrite(defaultledpin, LOW); // turn the LED off by making the voltage HIGH
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
int GetNodeID()
|
||||
{
|
||||
int TheAddress = -1;
|
||||
TheAddress = ((smsbuffer[1] - 48) * 100) + ((smsbuffer[2] - 48) * 10) + (smsbuffer[3] - 48);
|
||||
return TheAddress;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
bool IsAddressingNode()
|
||||
{
|
||||
if (strlen(smsbuffer) > 5)
|
||||
{ // at least something to check
|
||||
if ((smsbuffer[0] == 'N') && (smsbuffer[4] == ':') && (strchr(Numbers, smsbuffer[1]) != NULL) && (strchr(Numbers, smsbuffer[2]) != NULL) && (strchr(Numbers, smsbuffer[3]) != NULL))
|
||||
{
|
||||
#ifdef MY_DEBUG
|
||||
Serial.print("Message addressed to: ");
|
||||
Serial.println(GetNodeID());
|
||||
#endif
|
||||
if (GetNodeID() <= MAXNODEID)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
char* GetMessageContent(char incomingsmsbuffer[MAXSMSLENGTH])
|
||||
{
|
||||
strcpy(nodemsgbuffer, "");
|
||||
for (int i = 5; i < MAXSMSLENGTH; i++)
|
||||
{
|
||||
nodemsgbuffer[i - 5] = incomingsmsbuffer[i];
|
||||
}
|
||||
return nodemsgbuffer;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
void presentation()
|
||||
{
|
||||
// Send the sketch version information to the gateway and Controller
|
||||
sendSketchInfo(SKETCHNAME, SKETCHVERSION);
|
||||
wait(500);
|
||||
// node ID is 123
|
||||
present(SMSTEXT, S_INFO);
|
||||
wait(500);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
void receive(const MyMessage & message)
|
||||
{
|
||||
#ifdef MY_DEBUG
|
||||
Serial.print(F("Incoming from sensor: "));
|
||||
Serial.print(message.sensor);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
if ((message.type == V_TEXT) and (!MsgReceived))
|
||||
{
|
||||
sprintf(smsbuffer, "N%d:", message.sender);
|
||||
strcat(smsbuffer, message.getString());
|
||||
strcpy(msgbuffer, message.getString());
|
||||
MsgReceived = true;
|
||||
|
||||
#ifdef MY_DEBUG
|
||||
Serial.print(F(", New text: "));
|
||||
Serial.print(message.getString());
|
||||
#endif
|
||||
// send a copy of the received message to the controller
|
||||
}
|
||||
|
||||
#ifdef MY_DEBUG
|
||||
Serial.println();
|
||||
#endif
|
||||
|
||||
} // end: void receive()
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
void clearSMSmemory()
|
||||
{
|
||||
int8_t smsnum = fona.getNumSMS();
|
||||
while (smsnum > 0)
|
||||
{
|
||||
fona.deleteSMS(smsnum);
|
||||
smsnum--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// the setup function runs once when you press reset or power the board
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
void setup()
|
||||
{
|
||||
KnowMyOwner = false;
|
||||
MsgReceived = false;
|
||||
SMSMsg.setDestination(GATEWAY_ID);
|
||||
|
||||
// initialize digital LEDpin as an output.
|
||||
pinMode(defaultledpin, OUTPUT);
|
||||
digitalWrite(defaultledpin, HIGH); // turn the LED on by making the voltage HIGH
|
||||
|
||||
#ifdef MY_DEBUG
|
||||
|
||||
Serial.println(F("SIM800L basic test"));
|
||||
Serial.println(F("Initializing....(May take 3 seconds)"));
|
||||
Serial.println(F("starting SIM800L"));
|
||||
|
||||
#endif
|
||||
|
||||
fonaSerial->begin(4800);
|
||||
if (! fona.begin(*fonaSerial))
|
||||
{
|
||||
#ifdef MY_DEBUG
|
||||
Serial.println(F("Couldn't find SIM800L"));
|
||||
#endif
|
||||
while (1);
|
||||
}
|
||||
|
||||
#ifdef MY_DEBUG
|
||||
Serial.println(F("SIM800L is OK"));
|
||||
#endif
|
||||
|
||||
digitalWrite(defaultledpin, LOW); // turn the LED off by making the voltage LOW
|
||||
wait(250); // wait for a bit
|
||||
digitalWrite(defaultledpin, HIGH); // turn the LED on by making the voltage HIGH
|
||||
|
||||
#ifdef MY_DEBUG
|
||||
// Print SIM card IMEI number.
|
||||
char imei[15] = {0}; // MUST use a 16 character buffer for IMEI!
|
||||
uint8_t imeiLen = fona.getIMEI(imei);
|
||||
if (imeiLen > 0) {
|
||||
Serial.print(F("SIM card IMEI: ")); Serial.println(imei);
|
||||
}
|
||||
#endif
|
||||
|
||||
smsnum = fona.getNumSMS();
|
||||
|
||||
if (smsnum < 0)
|
||||
{
|
||||
#ifdef MY_DEBUG
|
||||
Serial.println(F("Could not read # SMS"));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef MY_DEBUG
|
||||
Serial.print(smsnum);
|
||||
Serial.println(F(" SMS's on SIM card!"));
|
||||
#endif
|
||||
}
|
||||
|
||||
clearSMSmemory();
|
||||
|
||||
smsnum = fona.getNumSMS();
|
||||
|
||||
if (smsnum == 0)
|
||||
{
|
||||
#ifdef MY_DEBUG
|
||||
Serial.println(F("SMS Memory cleared"));
|
||||
#endif
|
||||
}
|
||||
|
||||
digitalWrite(defaultledpin, LOW); // turn the LED off by making the voltage LOW
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// the loop function runs over and over again forever
|
||||
///////////////////////////////////////////////////////
|
||||
void loop()
|
||||
{
|
||||
blipled();
|
||||
// sensor.request(SMSTEXT, V_TEXT, 0);
|
||||
|
||||
wait(500); // wait for a second and proces messages
|
||||
|
||||
#ifdef MY_DEBUG
|
||||
Serial.print(F("Owner's number: "));
|
||||
Serial.println(myOwnersNumber);
|
||||
Serial.print(F("Last received number: "));
|
||||
Serial.println(ReceivedNumber);
|
||||
#endif
|
||||
|
||||
smsnum = fona.getNumSMS();
|
||||
|
||||
if (smsnum < 0)
|
||||
{
|
||||
#ifdef MY_DEBUG
|
||||
Serial.println(F("Could not read # SMS"));
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MY_DEBUG
|
||||
Serial.println(F("Process incoming messages"));
|
||||
#endif
|
||||
|
||||
if (MsgReceived && KnowMyOwner)
|
||||
{
|
||||
// a node sent us V_TEXT and we know the owner, so we can send an SMS
|
||||
|
||||
SMSMsg.setDestination(GATEWAY_ID);
|
||||
send(SMSMsg.set(smsbuffer));
|
||||
|
||||
if (fona.sendSMS(myOwnersNumber, smsbuffer))
|
||||
{
|
||||
// SMS was sent to owner
|
||||
MsgReceived = false;
|
||||
strcpy(smsbuffer, "");
|
||||
strcpy(msgbuffer, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
// We do not know the owner, then ignore this message, we know the owner but no message was received, so just to be safe:
|
||||
MsgReceived = false;
|
||||
strcpy(msgbuffer, "");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (smsnum > 0)
|
||||
{ // we received an SMS and now need to check it
|
||||
|
||||
#ifdef MY_DEBUG
|
||||
Serial.print(smsnum);
|
||||
Serial.println(F(" SMS received"));
|
||||
#endif
|
||||
|
||||
if (! fona.readSMS(smsnum, smsbuffer, MAXSMSLENGTH, &smslen))
|
||||
{ // could not read SMS
|
||||
|
||||
#ifdef MY_DEBUG
|
||||
Serial.println(F("Failed to get SMS!"));
|
||||
#endif
|
||||
|
||||
}
|
||||
else
|
||||
{ // We could read the SMS, now retreive sms to smsbuffer and number of origin
|
||||
fona.getSMSSender(smsnum, ReceivedNumber, MAXNUMBERLENGTH);
|
||||
|
||||
#ifdef MY_DEBUG
|
||||
Serial.print(F("***** SMS #")); Serial.print(smsnum);
|
||||
Serial.print(F(" (")); Serial.print(smslen); Serial.println(F(") bytes *****"));
|
||||
Serial.println(smsbuffer);
|
||||
Serial.print(F("from: "));
|
||||
Serial.println(ReceivedNumber);
|
||||
Serial.println(F("***************************"));
|
||||
Serial.print(F("Owner is known: "));
|
||||
if (KnowMyOwner)
|
||||
Serial.println(F("yes"));
|
||||
else
|
||||
Serial.println(F("no"));
|
||||
Serial.println();
|
||||
#endif
|
||||
|
||||
if (!KnowMyOwner)
|
||||
{ // no owner, so check request for ownership
|
||||
if (strcmp(smsbuffer, MYPASSWORD) == 0)
|
||||
{ // valid question for ownership
|
||||
strcpy(smsbuffer, "OwnReq by: ");
|
||||
strcat(smsbuffer, ReceivedNumber);
|
||||
send(SMSMsg.set(smsbuffer));
|
||||
KnowMyOwner = true;
|
||||
strcpy(myOwnersNumber, ReceivedNumber);
|
||||
// from now on we can respond to owner
|
||||
|
||||
#ifdef MY_DEBUG
|
||||
Serial.print(F("Request for ownership by "));
|
||||
Serial.println(myOwnersNumber);
|
||||
#endif
|
||||
|
||||
strcpy(smsbuffer, CONFIRMOWNER);
|
||||
if (fona.sendSMS(myOwnersNumber, smsbuffer))
|
||||
{ // send confirmation to new owner
|
||||
strcpy(smsbuffer, "Owner is informed.");
|
||||
SMSMsg.setDestination(GATEWAY_ID);
|
||||
send(SMSMsg.set(smsbuffer));
|
||||
|
||||
#ifdef MY_DEBUG
|
||||
Serial.print(smsbuffer);
|
||||
Serial.print(": ");
|
||||
Serial.println(myOwnersNumber);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{ // could not send confirmation to new owner
|
||||
|
||||
strcpy(smsbuffer, "Owner is not informed.");
|
||||
SMSMsg.setDestination(GATEWAY_ID);
|
||||
send(SMSMsg.set(smsbuffer));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
strcpy(smsbuffer, "");
|
||||
}
|
||||
else
|
||||
{ // no owner and no valid request, so ignore and log in controller
|
||||
strcpy(smsbuffer, "Attempt by: ");
|
||||
strcat(smsbuffer, ReceivedNumber);
|
||||
SMSMsg.setDestination(GATEWAY_ID);
|
||||
send(SMSMsg.set(smsbuffer));
|
||||
strcpy(smsbuffer, "");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (KnowMyOwner)
|
||||
{ // now we can accept SMS messages but we need to check the origin of the SMS
|
||||
|
||||
if (strcmp(myOwnersNumber, ReceivedNumber) == 0)
|
||||
{ // this is the owner talking, so handle his SMS
|
||||
|
||||
#ifdef MY_DEBUG
|
||||
Serial.println();
|
||||
Serial.print(F("Owner is talking: "));
|
||||
Serial.println(smsbuffer);
|
||||
Serial.println();
|
||||
#endif
|
||||
|
||||
if (strcmp(smsbuffer, MYRELEASEWORD) == 0)
|
||||
{
|
||||
|
||||
strcpy(smsbuffer, "Released by ");
|
||||
strcat(smsbuffer, ReceivedNumber);
|
||||
SMSMsg.setDestination(GATEWAY_ID);
|
||||
send(SMSMsg.set(smsbuffer));
|
||||
|
||||
strcpy(smsbuffer, "I am released.");
|
||||
if (fona.sendSMS(myOwnersNumber, smsbuffer))
|
||||
{
|
||||
strcpy(smsbuffer, "Owner is informed.");
|
||||
SMSMsg.setDestination(GATEWAY_ID);
|
||||
send(SMSMsg.set(smsbuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(smsbuffer, "Owner is not informed.");
|
||||
SMSMsg.setDestination(GATEWAY_ID);
|
||||
send(SMSMsg.set(smsbuffer));
|
||||
}
|
||||
|
||||
// clean up buffers, we are done and need to get ready for new owner request, ignore further messages
|
||||
KnowMyOwner = false;
|
||||
MsgReceived = false;
|
||||
strcpy(myOwnersNumber, "");
|
||||
strcpy(ReceivedNumber, "");
|
||||
strcpy(smsbuffer, "");
|
||||
strcpy(msgbuffer, "");
|
||||
}
|
||||
|
||||
|
||||
if (strcmp(smsbuffer, "Blip") == 0)
|
||||
{ // handle the command to light the defaultled. This could be anything else of course
|
||||
|
||||
digitalWrite(defaultledpin, HIGH); // turn the LED on (HIGH is the voltage level)
|
||||
wait(2000); // wait for two seconds
|
||||
digitalWrite(defaultledpin, LOW); // turn the LED off by making the voltage LOW
|
||||
|
||||
strcpy(smsbuffer, "R: Blip");
|
||||
SMSMsg.setDestination(GATEWAY_ID);
|
||||
send(SMSMsg.set(smsbuffer));
|
||||
strcpy(smsbuffer, "");
|
||||
}
|
||||
|
||||
|
||||
// and here we put the code to pass the message on to another node
|
||||
// smsbuffer contains the first 30 characters of the SMS received.
|
||||
// if a message starts with Nxxx:1234567890123456789012345 then you need to pass on the content to node Nxxx
|
||||
// the node needs to be able to handle the incoming V_TEXT message
|
||||
|
||||
if (IsAddressingNode()) // check if sms is in Node addressing format
|
||||
{
|
||||
int NodeID = GetNodeID();
|
||||
|
||||
#ifdef MY_DEBUG
|
||||
|
||||
Serial.println();
|
||||
Serial.print("Message for node ");
|
||||
Serial.print(NodeID);
|
||||
Serial.print(" is treated: ");
|
||||
Serial.println(GetMessageContent(smsbuffer));
|
||||
Serial.println();
|
||||
|
||||
#endif
|
||||
|
||||
// send a copy of the incoming message to the controller
|
||||
SMSMsg.setDestination(GATEWAY_ID);
|
||||
send(SMSMsg.set(smsbuffer));
|
||||
// send the stripped message to the addressed node
|
||||
SMSMsg.setDestination(NodeID);
|
||||
SMSMsg.set(GetMessageContent(smsbuffer));
|
||||
send(SMSMsg);
|
||||
|
||||
strcpy(smsbuffer, "");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// finally we mention to the controller all the SMS messages we received and did not treat.
|
||||
|
||||
if (strcmp(smsbuffer, "") != 0)
|
||||
{ // so we still got something to do
|
||||
#ifdef MY_DEBUG
|
||||
Serial.println(smsbuffer);
|
||||
Serial.println();
|
||||
#endif
|
||||
//strcpy(smsbuffer, "Received crap from owner.");
|
||||
SMSMsg.setDestination(GATEWAY_ID);
|
||||
send(SMSMsg.set(smsbuffer));
|
||||
strcpy(smsbuffer, "");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{ // not the owner trying to get access
|
||||
strcpy(smsbuffer, "Hack by:");
|
||||
strcat(smsbuffer, ReceivedNumber);
|
||||
SMSMsg.setDestination(GATEWAY_ID);
|
||||
send(SMSMsg.set(smsbuffer));
|
||||
#ifdef MY_DEBUG
|
||||
Serial.print(F("Hijack attempt by: "));
|
||||
Serial.println(ReceivedNumber);
|
||||
#else
|
||||
if (fona.sendSMS(myOwnersNumber, smsbuffer))
|
||||
{
|
||||
strcpy(smsbuffer, "Owner is informed.");
|
||||
SMSMsg.setDestination(GATEWAY_ID);
|
||||
send(SMSMsg.set(smsbuffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(smsbuffer, "Owner could not be informed.");
|
||||
SMSMsg.setDestination(GATEWAY_ID);
|
||||
send(SMSMsg.set(smsbuffer));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
clearSMSmemory();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user