Merge branch 'master' into master
This commit is contained in:
BIN
extras/doc/Digi XBee 3G Global Users Guide - 90001541.pdf
Normal file
BIN
extras/doc/Digi XBee 3G Global Users Guide - 90001541.pdf
Normal file
Binary file not shown.
BIN
extras/doc/Digi XBee3 LTEC1 Users Guide - 90002253.pdf
Normal file
BIN
extras/doc/Digi XBee3 LTEC1 Users Guide - 90002253.pdf
Normal file
Binary file not shown.
BIN
extras/doc/ESP8266 - AT Command Examples 1.3.pdf
Normal file
BIN
extras/doc/ESP8266 - AT Command Examples 1.3.pdf
Normal file
Binary file not shown.
BIN
extras/doc/ESP8266 - AT Instruction Set v2.0.0.pdf
Normal file
BIN
extras/doc/ESP8266 - AT Instruction Set v2.0.0.pdf
Normal file
Binary file not shown.
BIN
extras/doc/Gemalto ELS31 AT Commands.pdf
Normal file
BIN
extras/doc/Gemalto ELS31 AT Commands.pdf
Normal file
Binary file not shown.
BIN
extras/doc/SIM800 Series AT Command Manual V1.09.pdf
Normal file
BIN
extras/doc/SIM800 Series AT Command Manual V1.09.pdf
Normal file
Binary file not shown.
BIN
extras/doc/SIM800 Series AT Command Manual V1.10.pdf
Normal file
BIN
extras/doc/SIM800 Series AT Command Manual V1.10.pdf
Normal file
Binary file not shown.
Binary file not shown.
BIN
extras/doc/SIM800+Series Bluetooth Application Note V1.04.pdf
Normal file
BIN
extras/doc/SIM800+Series Bluetooth Application Note V1.04.pdf
Normal file
Binary file not shown.
BIN
extras/doc/SIM800+Series Email Application Note V1.00.pdf
Normal file
BIN
extras/doc/SIM800+Series Email Application Note V1.00.pdf
Normal file
Binary file not shown.
BIN
extras/doc/Sequans Monarch AT Commands.pdf
Normal file
BIN
extras/doc/Sequans Monarch AT Commands.pdf
Normal file
Binary file not shown.
Binary file not shown.
BIN
extras/doc/Telit CE910 AT Commands Reference Guide r5.pdf
Normal file
BIN
extras/doc/Telit CE910 AT Commands Reference Guide r5.pdf
Normal file
Binary file not shown.
BIN
extras/doc/Telit HE910 AT Command Reference Guide r0.pdf
Normal file
BIN
extras/doc/Telit HE910 AT Command Reference Guide r0.pdf
Normal file
Binary file not shown.
BIN
extras/doc/Telit LE910 AT Commands Reference Guide r14.1.pdf
Normal file
BIN
extras/doc/Telit LE910 AT Commands Reference Guide r14.1.pdf
Normal file
Binary file not shown.
BIN
extras/doc/Telit ME910C1 AT Commands Reference Guide r2.pdf
Normal file
BIN
extras/doc/Telit ME910C1 AT Commands Reference Guide r2.pdf
Normal file
Binary file not shown.
BIN
extras/doc/Telit Modules Software User Guide 2G3G4G r20.pdf
Normal file
BIN
extras/doc/Telit Modules Software User Guide 2G3G4G r20.pdf
Normal file
Binary file not shown.
21
library.json
21
library.json
@@ -1,18 +1,25 @@
|
|||||||
{
|
{
|
||||||
"name": "TinyGSM",
|
"name": "TinyGSM",
|
||||||
"version": "0.3.3",
|
"version": "0.3.30",
|
||||||
"description": "A small Arduino library for GPRS modules, that just works. Includes examples for Blynk, MQTT, File Download, and Web Client. Supports GSM modules with AT command interface: SIM800, SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868, SIM900, SIM900A, SIM900D, SIM908, SIM968",
|
"description": "A small Arduino library for GPRS modules, that just works. Includes examples for Blynk, MQTT, File Download, and Web Client. Supports GSM modules with AT command interface: SIM800, SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868, SIM900, SIM900A, SIM900D, SIM908, SIM968",
|
||||||
"keywords": "GSM, AT commands, AT, SIM800, SIM900, A6, A7, M590, ESP8266, SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868, SIM900A, SIM900D, SIM908, SIM968",
|
"keywords": "GSM, AT commands, AT, SIM800, SIM900, A6, A7, M590, ESP8266, SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868, SIM900A, SIM900D, SIM908, SIM968",
|
||||||
"authors":
|
"authors":
|
||||||
{
|
[
|
||||||
"name": "Volodymyr Shymanskyy",
|
{
|
||||||
"url": "https://github.com/vshymanskyy",
|
"name": "Sara Damiano",
|
||||||
"maintainer": true
|
"email": "sdamiano@stroudcenter.org",
|
||||||
},
|
"url": "https://envirodiy.org/",
|
||||||
|
"maintainer": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Volodymyr Shymanskyy",
|
||||||
|
"url": "https://github.com/vshymanskyy"
|
||||||
|
}
|
||||||
|
],
|
||||||
"repository":
|
"repository":
|
||||||
{
|
{
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/vshymanskyy/TinyGSM.git"
|
"url": "https://github.com/EnviroDIY/TinyGSM.git"
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/vshymanskyy/TinyGSM",
|
"homepage": "https://github.com/vshymanskyy/TinyGSM",
|
||||||
"export": {
|
"export": {
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
name=TinyGSM
|
name=TinyGSM
|
||||||
version=0.3.3
|
version=0.3.30
|
||||||
author=Volodymyr Shymanskyy
|
author=Volodymyr Shymanskyy
|
||||||
maintainer=Volodymyr Shymanskyy
|
maintainer=Volodymyr Shymanskyy
|
||||||
sentence=A small Arduino library for GPRS modules, that just works.
|
sentence=A small Arduino library for GPRS modules, that just works.
|
||||||
|
@@ -34,11 +34,13 @@
|
|||||||
#elif defined(TINY_GSM_MODEM_A6) || defined(TINY_GSM_MODEM_A7)
|
#elif defined(TINY_GSM_MODEM_A6) || defined(TINY_GSM_MODEM_A7)
|
||||||
#define TINY_GSM_MODEM_HAS_GPRS
|
#define TINY_GSM_MODEM_HAS_GPRS
|
||||||
#include <TinyGsmClientA6.h>
|
#include <TinyGsmClientA6.h>
|
||||||
|
typedef TinyGsmA6 TinyGsm;
|
||||||
typedef TinyGsm::GsmClient TinyGsmClient;
|
typedef TinyGsm::GsmClient TinyGsmClient;
|
||||||
|
|
||||||
#elif defined(TINY_GSM_MODEM_M590)
|
#elif defined(TINY_GSM_MODEM_M590)
|
||||||
#define TINY_GSM_MODEM_HAS_GPRS
|
#define TINY_GSM_MODEM_HAS_GPRS
|
||||||
#include <TinyGsmClientM590.h>
|
#include <TinyGsmClientM590.h>
|
||||||
|
typedef TinyGsmM590 TinyGsm;
|
||||||
typedef TinyGsm::GsmClient TinyGsmClient;
|
typedef TinyGsm::GsmClient TinyGsmClient;
|
||||||
|
|
||||||
#elif defined(TINY_GSM_MODEM_U201)
|
#elif defined(TINY_GSM_MODEM_U201)
|
||||||
@@ -51,6 +53,7 @@
|
|||||||
#elif defined(TINY_GSM_MODEM_ESP8266)
|
#elif defined(TINY_GSM_MODEM_ESP8266)
|
||||||
#define TINY_GSM_MODEM_HAS_WIFI
|
#define TINY_GSM_MODEM_HAS_WIFI
|
||||||
#include <TinyGsmClientESP8266.h>
|
#include <TinyGsmClientESP8266.h>
|
||||||
|
typedef TinyGsmESP8266 TinyGsm;
|
||||||
typedef TinyGsm::GsmClient TinyGsmClient;
|
typedef TinyGsm::GsmClient TinyGsmClient;
|
||||||
typedef TinyGsm::GsmClientSecure TinyGsmClientSecure;
|
typedef TinyGsm::GsmClientSecure TinyGsmClientSecure;
|
||||||
|
|
||||||
@@ -58,7 +61,9 @@
|
|||||||
#define TINY_GSM_MODEM_HAS_GPRS
|
#define TINY_GSM_MODEM_HAS_GPRS
|
||||||
#define TINY_GSM_MODEM_HAS_WIFI
|
#define TINY_GSM_MODEM_HAS_WIFI
|
||||||
#include <TinyGsmClientXBee.h>
|
#include <TinyGsmClientXBee.h>
|
||||||
typedef TinyGsm::GsmClient TinyGsmClient;
|
typedef TinyGsmXBee TinyGsm;
|
||||||
|
typedef TinyGsmXBee::GsmClient TinyGsmClient;
|
||||||
|
typedef TinyGsmXBee::GsmClientSecure TinyGsmClientSecure;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#error "Please define GSM modem model"
|
#error "Please define GSM modem model"
|
||||||
|
@@ -39,24 +39,40 @@ enum RegStatus {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class TinyGsm
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
// Declaration of the TinyGsmA6 Class
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class TinyGsmA6
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
// The A6 Client Class
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
|
||||||
|
|
||||||
class GsmClient : public Client
|
class GsmClient : public Client
|
||||||
{
|
{
|
||||||
friend class TinyGsm;
|
friend class TinyGsmA6;
|
||||||
typedef TinyGsmFifo<uint8_t, TINY_GSM_RX_BUFFER> RxFifo;
|
typedef TinyGsmFifo<uint8_t, TINY_GSM_RX_BUFFER> RxFifo;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GsmClient() {}
|
GsmClient() {}
|
||||||
|
|
||||||
GsmClient(TinyGsm& modem) {
|
GsmClient(TinyGsmA6& modem) {
|
||||||
init(&modem);
|
init(&modem);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool init(TinyGsm* modem) {
|
bool init(TinyGsmA6* modem) {
|
||||||
this->at = modem;
|
this->at = modem;
|
||||||
this->mux = -1;
|
this->mux = -1;
|
||||||
sock_connected = false;
|
sock_connected = false;
|
||||||
@@ -119,7 +135,8 @@ public:
|
|||||||
virtual int read(uint8_t *buf, size_t size) {
|
virtual int read(uint8_t *buf, size_t size) {
|
||||||
TINY_GSM_YIELD();
|
TINY_GSM_YIELD();
|
||||||
size_t cnt = 0;
|
size_t cnt = 0;
|
||||||
while (cnt < size) {
|
uint32_t _startMillis = millis();
|
||||||
|
while (cnt < size && millis() - _startMillis < _timeout) {
|
||||||
size_t chunk = TinyGsmMin(size-cnt, rx.size());
|
size_t chunk = TinyGsmMin(size-cnt, rx.size());
|
||||||
if (chunk > 0) {
|
if (chunk > 0) {
|
||||||
rx.get(buf, chunk);
|
rx.get(buf, chunk);
|
||||||
@@ -162,15 +179,34 @@ public:
|
|||||||
String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TinyGsm* at;
|
TinyGsmA6* at;
|
||||||
uint8_t mux;
|
uint8_t mux;
|
||||||
bool sock_connected;
|
bool sock_connected;
|
||||||
RxFifo rx;
|
RxFifo rx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
// The A6 Does not have a secure client!
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
// The A6 Modem Functions
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
TinyGsm(Stream& stream)
|
#ifdef GSM_DEFAULT_STREAM
|
||||||
|
TinyGsmA6(Stream& stream = GSM_DEFAULT_STREAM)
|
||||||
|
#else
|
||||||
|
TinyGsmA6(Stream& stream)
|
||||||
|
#endif
|
||||||
: stream(stream)
|
: stream(stream)
|
||||||
{
|
{
|
||||||
memset(sockets, 0, sizeof(sockets));
|
memset(sockets, 0, sizeof(sockets));
|
||||||
@@ -316,17 +352,6 @@ public:
|
|||||||
return SIM_ERROR;
|
return SIM_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
RegStatus getRegistrationStatus() {
|
|
||||||
sendAT(GF("+CREG?"));
|
|
||||||
if (waitResponse(GF(GSM_NL "+CREG:")) != 1) {
|
|
||||||
return REG_UNKNOWN;
|
|
||||||
}
|
|
||||||
streamSkipUntil(','); // Skip format (0)
|
|
||||||
int status = stream.readStringUntil('\n').toInt();
|
|
||||||
waitResponse();
|
|
||||||
return (RegStatus)status;
|
|
||||||
}
|
|
||||||
|
|
||||||
String getOperator() {
|
String getOperator() {
|
||||||
sendAT(GF("+COPS=3,0")); // Set format
|
sendAT(GF("+COPS=3,0")); // Set format
|
||||||
waitResponse();
|
waitResponse();
|
||||||
@@ -345,6 +370,17 @@ public:
|
|||||||
* Generic network functions
|
* Generic network functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
RegStatus getRegistrationStatus() {
|
||||||
|
sendAT(GF("+CREG?"));
|
||||||
|
if (waitResponse(GF(GSM_NL "+CREG:")) != 1) {
|
||||||
|
return REG_UNKNOWN;
|
||||||
|
}
|
||||||
|
streamSkipUntil(','); // Skip format (0)
|
||||||
|
int status = stream.readStringUntil('\n').toInt();
|
||||||
|
waitResponse();
|
||||||
|
return (RegStatus)status;
|
||||||
|
}
|
||||||
|
|
||||||
int getSignalQuality() {
|
int getSignalQuality() {
|
||||||
sendAT(GF("+CSQ"));
|
sendAT(GF("+CSQ"));
|
||||||
if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) {
|
if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) {
|
||||||
@@ -370,6 +406,26 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getLocalIP() {
|
||||||
|
sendAT(GF("+CIFSR"));
|
||||||
|
String res;
|
||||||
|
if (waitResponse(10000L, res) != 1) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
res.replace(GSM_NL "OK" GSM_NL, "");
|
||||||
|
res.replace(GSM_NL, "");
|
||||||
|
res.trim();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress localIP() {
|
||||||
|
return TinyGsmIpFromString(getLocalIP());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* WiFi functions
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GPRS functions
|
* GPRS functions
|
||||||
*/
|
*/
|
||||||
@@ -428,104 +484,6 @@ public:
|
|||||||
return (res == 1);
|
return (res == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
String getLocalIP() {
|
|
||||||
sendAT(GF("+CIFSR"));
|
|
||||||
String res;
|
|
||||||
if (waitResponse(10000L, res) != 1) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
res.replace(GSM_NL "OK" GSM_NL, "");
|
|
||||||
res.replace(GSM_NL, "");
|
|
||||||
res.trim();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
IPAddress localIP() {
|
|
||||||
return TinyGsmIpFromString(getLocalIP());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Phone Call functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool setGsmBusy(bool busy = true) TINY_GSM_ATTR_NOT_AVAILABLE;
|
|
||||||
|
|
||||||
bool callAnswer() {
|
|
||||||
sendAT(GF("A"));
|
|
||||||
return waitResponse() == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns true on pick-up, false on error/busy
|
|
||||||
bool callNumber(const String& number) {
|
|
||||||
if (number == GF("last")) {
|
|
||||||
sendAT(GF("DLST"));
|
|
||||||
} else {
|
|
||||||
sendAT(GF("D\""), number, "\";");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (waitResponse(5000L) != 1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (waitResponse(60000L,
|
|
||||||
GF(GSM_NL "+CIEV: \"CALL\",1"),
|
|
||||||
GF(GSM_NL "+CIEV: \"CALL\",0"),
|
|
||||||
GFP(GSM_ERROR)) != 1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int rsp = waitResponse(60000L,
|
|
||||||
GF(GSM_NL "+CIEV: \"SOUNDER\",0"),
|
|
||||||
GF(GSM_NL "+CIEV: \"CALL\",0"));
|
|
||||||
|
|
||||||
int rsp2 = waitResponse(300L, GF(GSM_NL "BUSY" GSM_NL), GF(GSM_NL "NO ANSWER" GSM_NL));
|
|
||||||
|
|
||||||
return rsp == 1 && rsp2 == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool callHangup() {
|
|
||||||
sendAT(GF("H"));
|
|
||||||
return waitResponse() == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 0-9,*,#,A,B,C,D
|
|
||||||
bool dtmfSend(char cmd, unsigned duration_ms = 100) {
|
|
||||||
duration_ms = constrain(duration_ms, 100, 1000);
|
|
||||||
|
|
||||||
// The duration parameter is not working, so we simulate it using delay..
|
|
||||||
// TODO: Maybe there's another way...
|
|
||||||
|
|
||||||
//sendAT(GF("+VTD="), duration_ms / 100);
|
|
||||||
//waitResponse();
|
|
||||||
|
|
||||||
sendAT(GF("+VTS="), cmd);
|
|
||||||
if (waitResponse(10000L) == 1) {
|
|
||||||
delay(duration_ms);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Audio functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool audioSetHeadphones() {
|
|
||||||
sendAT(GF("+SNFS=0"));
|
|
||||||
return waitResponse() == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool audioSetSpeaker() {
|
|
||||||
sendAT(GF("+SNFS=1"));
|
|
||||||
return waitResponse() == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool audioMuteMic(bool mute) {
|
|
||||||
sendAT(GF("+CMUT="), mute);
|
|
||||||
return waitResponse() == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Messaging functions
|
* Messaging functions
|
||||||
*/
|
*/
|
||||||
@@ -650,9 +608,13 @@ public:
|
|||||||
streamWrite(tail...);
|
streamWrite(tail...);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool streamSkipUntil(char c) { //TODO: timeout
|
bool streamSkipUntil(char c) {
|
||||||
while (true) {
|
const unsigned long timeout = 1000L;
|
||||||
while (!stream.available()) { TINY_GSM_YIELD(); }
|
unsigned long startMillis = millis();
|
||||||
|
while (millis() - startMillis < timeout) {
|
||||||
|
while (millis() - startMillis < timeout && !stream.available()) {
|
||||||
|
TINY_GSM_YIELD();
|
||||||
|
}
|
||||||
if (stream.read() == c)
|
if (stream.read() == c)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -664,7 +626,7 @@ public:
|
|||||||
streamWrite("AT", cmd..., GSM_NL);
|
streamWrite("AT", cmd..., GSM_NL);
|
||||||
stream.flush();
|
stream.flush();
|
||||||
TINY_GSM_YIELD();
|
TINY_GSM_YIELD();
|
||||||
//DBG("### AT:", cmd...);
|
DBG("### AT:", cmd...);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Optimize this!
|
// TODO: Optimize this!
|
||||||
@@ -672,12 +634,12 @@ public:
|
|||||||
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
|
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
|
||||||
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
|
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
|
||||||
{
|
{
|
||||||
/*String r1s(r1); r1s.trim();
|
String r1s(r1); r1s.trim();
|
||||||
String r2s(r2); r2s.trim();
|
String r2s(r2); r2s.trim();
|
||||||
String r3s(r3); r3s.trim();
|
String r3s(r3); r3s.trim();
|
||||||
String r4s(r4); r4s.trim();
|
String r4s(r4); r4s.trim();
|
||||||
String r5s(r5); r5s.trim();
|
String r5s(r5); r5s.trim();
|
||||||
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
|
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);
|
||||||
data.reserve(64);
|
data.reserve(64);
|
||||||
int index = 0;
|
int index = 0;
|
||||||
unsigned long startMillis = millis();
|
unsigned long startMillis = millis();
|
||||||
@@ -737,6 +699,7 @@ finish:
|
|||||||
}
|
}
|
||||||
data = "";
|
data = "";
|
||||||
}
|
}
|
||||||
|
DBG('<', index, '>');
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
#ifndef TinyGsmClientESP8266_h
|
#ifndef TinyGsmClientESP8266_h
|
||||||
#define TinyGsmClientESP8266_h
|
#define TinyGsmClientESP8266_h
|
||||||
|
|
||||||
//#define TINY_GSM_DEBUG Serial
|
// #define TINY_GSM_DEBUG Serial
|
||||||
|
|
||||||
#if !defined(TINY_GSM_RX_BUFFER)
|
#if !defined(TINY_GSM_RX_BUFFER)
|
||||||
#define TINY_GSM_RX_BUFFER 512
|
#define TINY_GSM_RX_BUFFER 512
|
||||||
@@ -24,24 +24,51 @@ static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL;
|
|||||||
static const char GSM_ERROR[] TINY_GSM_PROGMEM = "ERROR" GSM_NL;
|
static const char GSM_ERROR[] TINY_GSM_PROGMEM = "ERROR" GSM_NL;
|
||||||
static unsigned TINY_GSM_TCP_KEEP_ALIVE = 120;
|
static unsigned TINY_GSM_TCP_KEEP_ALIVE = 120;
|
||||||
|
|
||||||
class TinyGsm
|
// <stat> status of ESP8266 station interface
|
||||||
|
// 2 : ESP8266 station connected to an AP and has obtained IP
|
||||||
|
// 3 : ESP8266 station created a TCP or UDP transmission
|
||||||
|
// 4 : the TCP or UDP transmission of ESP8266 station disconnected
|
||||||
|
// 5 : ESP8266 station did NOT connect to an AP
|
||||||
|
enum RegStatus {
|
||||||
|
REG_OK_IP = 2,
|
||||||
|
REG_OK_TCP = 3,
|
||||||
|
REG_UNREGISTERED = 4,
|
||||||
|
REG_DENIED = 5,
|
||||||
|
REG_UNKNOWN = 6,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
// Declaration of the TinyGsmESP8266 Class
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
|
||||||
|
|
||||||
|
class TinyGsmESP8266
|
||||||
{
|
{
|
||||||
|
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
// The ESP8266 Client Class
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
class GsmClient : public Client
|
class GsmClient : public Client
|
||||||
{
|
{
|
||||||
friend class TinyGsm;
|
friend class TinyGsmESP8266;
|
||||||
typedef TinyGsmFifo<uint8_t, TINY_GSM_RX_BUFFER> RxFifo;
|
typedef TinyGsmFifo<uint8_t, TINY_GSM_RX_BUFFER> RxFifo;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GsmClient() {}
|
GsmClient() {}
|
||||||
|
|
||||||
GsmClient(TinyGsm& modem, uint8_t mux = 1) {
|
GsmClient(TinyGsmESP8266& modem, uint8_t mux = 1) {
|
||||||
init(&modem, mux);
|
init(&modem, mux);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool init(TinyGsm* modem, uint8_t mux = 1) {
|
bool init(TinyGsmESP8266* modem, uint8_t mux = 1) {
|
||||||
this->at = modem;
|
this->at = modem;
|
||||||
this->mux = mux;
|
this->mux = mux;
|
||||||
sock_connected = false;
|
sock_connected = false;
|
||||||
@@ -101,7 +128,8 @@ public:
|
|||||||
virtual int read(uint8_t *buf, size_t size) {
|
virtual int read(uint8_t *buf, size_t size) {
|
||||||
TINY_GSM_YIELD();
|
TINY_GSM_YIELD();
|
||||||
size_t cnt = 0;
|
size_t cnt = 0;
|
||||||
while (cnt < size) {
|
uint32_t _startMillis = millis();
|
||||||
|
while (cnt < size && millis() - _startMillis < _timeout) {
|
||||||
size_t chunk = TinyGsmMin(size-cnt, rx.size());
|
size_t chunk = TinyGsmMin(size-cnt, rx.size());
|
||||||
if (chunk > 0) {
|
if (chunk > 0) {
|
||||||
rx.get(buf, chunk);
|
rx.get(buf, chunk);
|
||||||
@@ -144,18 +172,25 @@ public:
|
|||||||
String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TinyGsm* at;
|
TinyGsmESP8266* at;
|
||||||
uint8_t mux;
|
uint8_t mux;
|
||||||
bool sock_connected;
|
bool sock_connected;
|
||||||
RxFifo rx;
|
RxFifo rx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
// The Secure ESP8266 Client Class
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
|
||||||
|
|
||||||
class GsmClientSecure : public GsmClient
|
class GsmClientSecure : public GsmClient
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GsmClientSecure() {}
|
GsmClientSecure() {}
|
||||||
|
|
||||||
GsmClientSecure(TinyGsm& modem, uint8_t mux = 1)
|
GsmClientSecure(TinyGsmESP8266& modem, uint8_t mux = 1)
|
||||||
: GsmClient(modem, mux)
|
: GsmClient(modem, mux)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -169,9 +204,20 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
// The ESP8266 Modem Functions
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
TinyGsm(Stream& stream)
|
#ifdef GSM_DEFAULT_STREAM
|
||||||
|
TinyGsmESP8266(Stream& stream = GSM_DEFAULT_STREAM)
|
||||||
|
#else
|
||||||
|
TinyGsmESP8266(Stream& stream)
|
||||||
|
#endif
|
||||||
: stream(stream)
|
: stream(stream)
|
||||||
{
|
{
|
||||||
memset(sockets, 0, sizeof(sockets));
|
memset(sockets, 0, sizeof(sockets));
|
||||||
@@ -192,6 +238,14 @@ public:
|
|||||||
if (waitResponse() != 1) {
|
if (waitResponse() != 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
sendAT(GF("+CIPMUX=1")); // Enable Multiple Connections
|
||||||
|
if (waitResponse() != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
sendAT(GF("+CWMODE_CUR=1")); // Put into "station" mode
|
||||||
|
if (waitResponse() != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,9 +286,7 @@ public:
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasSSL() {
|
bool hasSSL() { return true; }
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Power functions
|
* Power functions
|
||||||
@@ -255,11 +307,30 @@ public:
|
|||||||
return init();
|
return init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool poweroff() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
|
bool radioOff() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
|
bool sleepEnable(bool enable = true) TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SIM card functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generic network functions
|
* Generic network functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
RegStatus getRegistrationStatus() {
|
||||||
|
sendAT(GF("+CIPSTATUS"));
|
||||||
|
if (waitResponse(3000, GF("STATUS:")) != 1) return REG_UNKNOWN;
|
||||||
|
int status = waitResponse(GFP(GSM_ERROR), GF("2"), GF("3"), GF("4"), GF("5"));
|
||||||
|
waitResponse(); // Returns an OK after the status
|
||||||
|
return (RegStatus)status;
|
||||||
|
}
|
||||||
|
|
||||||
int getSignalQuality() {
|
int getSignalQuality() {
|
||||||
sendAT(GF("+CWJAP_CUR?"));
|
sendAT(GF("+CWJAP_CUR?"));
|
||||||
int res1 = waitResponse(GF("No AP"), GF("+CWJAP_CUR:"));
|
int res1 = waitResponse(GF("No AP"), GF("+CWJAP_CUR:"));
|
||||||
@@ -275,21 +346,9 @@ public:
|
|||||||
return res2;
|
return res2;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNetworkConnected() {
|
bool isNetworkConnected() {
|
||||||
sendAT(GF("+CIPSTATUS"));
|
RegStatus s = getRegistrationStatus();
|
||||||
int res1 = waitResponse(3000, GF("STATUS:"));
|
return (s == REG_OK_IP || s == REG_OK_TCP);
|
||||||
int res2 = 0;
|
|
||||||
if (res1 == 1) {
|
|
||||||
res2 = waitResponse(GFP(GSM_ERROR), GF("2"), GF("3"), GF("4"), GF("5"));
|
|
||||||
}
|
|
||||||
// <stat> status of ESP8266 station interface
|
|
||||||
// 2 : ESP8266 station connected to an AP and has obtained IP
|
|
||||||
// 3 : ESP8266 station created a TCP or UDP transmission
|
|
||||||
// 4 : the TCP or UDP transmission of ESP8266 station disconnected (but AP is connected)
|
|
||||||
// 5 : ESP8266 station did NOT connect to an AP
|
|
||||||
waitResponse(); // Returns an OK after the status
|
|
||||||
if (res2 == 2 || res2 == 3 || res2 == 4) return true;
|
|
||||||
else return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool waitForNetwork(unsigned long timeout = 60000L) {
|
bool waitForNetwork(unsigned long timeout = 60000L) {
|
||||||
@@ -298,7 +357,7 @@ public:
|
|||||||
int res1 = waitResponse(3000, GF("busy p..."), GF("STATUS:"));
|
int res1 = waitResponse(3000, GF("busy p..."), GF("STATUS:"));
|
||||||
if (res1 == 2) {
|
if (res1 == 2) {
|
||||||
int res2 = waitResponse(GFP(GSM_ERROR), GF("2"), GF("3"), GF("4"), GF("5"));
|
int res2 = waitResponse(GFP(GSM_ERROR), GF("2"), GF("3"), GF("4"), GF("5"));
|
||||||
if (res2 == 2 || res2 == 3 || res2 == 4) {
|
if (res2 == 2 || res2 == 3) {
|
||||||
waitResponse();
|
waitResponse();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -308,36 +367,6 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* WiFi functions
|
|
||||||
*/
|
|
||||||
bool networkConnect(const char* ssid, const char* pwd) {
|
|
||||||
|
|
||||||
sendAT(GF("+CIPMUX=1"));
|
|
||||||
if (waitResponse() != 1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
sendAT(GF("+CWMODE_CUR=1"));
|
|
||||||
if (waitResponse() != 1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
sendAT(GF("+CWJAP_CUR=\""), ssid, GF("\",\""), pwd, GF("\""));
|
|
||||||
if (waitResponse(30000L, GFP(GSM_OK), GF(GSM_NL "FAIL" GSM_NL)) != 1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool networkDisconnect() {
|
|
||||||
sendAT(GF("+CWQAP"));
|
|
||||||
bool retVal = waitResponse(10000L) == 1;
|
|
||||||
waitResponse(GF("WIFI DISCONNECT"));
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
String getLocalIP() {
|
String getLocalIP() {
|
||||||
sendAT(GF("+CIPSTA_CUR??"));
|
sendAT(GF("+CIPSTA_CUR??"));
|
||||||
int res1 = waitResponse(GF("ERROR"), GF("+CWJAP_CUR:"));
|
int res1 = waitResponse(GF("ERROR"), GF("+CWJAP_CUR:"));
|
||||||
@@ -353,6 +382,46 @@ public:
|
|||||||
return TinyGsmIpFromString(getLocalIP());
|
return TinyGsmIpFromString(getLocalIP());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* WiFi functions
|
||||||
|
*/
|
||||||
|
bool networkConnect(const char* ssid, const char* pwd) {
|
||||||
|
sendAT(GF("+CWJAP_CUR=\""), ssid, GF("\",\""), pwd, GF("\""));
|
||||||
|
if (waitResponse(30000L, GFP(GSM_OK), GF(GSM_NL "FAIL" GSM_NL)) != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool networkDisconnect() {
|
||||||
|
sendAT(GF("+CWQAP"));
|
||||||
|
bool retVal = waitResponse(10000L) == 1;
|
||||||
|
waitResponse(GF("WIFI DISCONNECT"));
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GPRS functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Messaging functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Location functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
String getGsmLocation() TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Battery functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||||
|
|
||||||
|
int getBattPercent() TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
bool modemConnect(const char* host, uint16_t port, uint8_t mux, bool ssl = false) {
|
bool modemConnect(const char* host, uint16_t port, uint8_t mux, bool ssl = false) {
|
||||||
@@ -384,21 +453,8 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool modemGetConnected(uint8_t mux) {
|
bool modemGetConnected(uint8_t mux) {
|
||||||
// TODO: re-check this
|
RegStatus s = getRegistrationStatus();
|
||||||
sendAT(GF("+CIPSTATUS="), mux);
|
return (s == REG_OK_IP || s == REG_OK_TCP);
|
||||||
int res1 = waitResponse(3000, GF("STATUS:"));
|
|
||||||
int res2;
|
|
||||||
if (res1 == 1) {
|
|
||||||
res2 = waitResponse(GFP(GSM_ERROR), GF("2"), GF("3"), GF("4"), GF("5"));
|
|
||||||
}
|
|
||||||
// <stat> status of ESP8266 station interface
|
|
||||||
// 2 : ESP8266 station connected to an AP and has obtained IP
|
|
||||||
// 3 : ESP8266 station created a TCP or UDP transmission
|
|
||||||
// 4 : the TCP or UDP transmission of ESP8266 station disconnected (but AP is connected)
|
|
||||||
// 5 : ESP8266 station did NOT connect to an AP
|
|
||||||
waitResponse(); // Returns an OK after the status
|
|
||||||
if (res2 == 2 || res2 == 3 || res2 == 4) return true;
|
|
||||||
else return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -416,9 +472,13 @@ public:
|
|||||||
streamWrite(tail...);
|
streamWrite(tail...);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool streamSkipUntil(char c) { //TODO: timeout
|
bool streamSkipUntil(char c) {
|
||||||
while (true) {
|
const unsigned long timeout = 1000L;
|
||||||
while (!stream.available()) { TINY_GSM_YIELD(); }
|
unsigned long startMillis = millis();
|
||||||
|
while (millis() - startMillis < timeout) {
|
||||||
|
while (millis() - startMillis < timeout && !stream.available()) {
|
||||||
|
TINY_GSM_YIELD();
|
||||||
|
}
|
||||||
if (stream.read() == c)
|
if (stream.read() == c)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -430,7 +490,7 @@ public:
|
|||||||
streamWrite("AT", cmd..., GSM_NL);
|
streamWrite("AT", cmd..., GSM_NL);
|
||||||
stream.flush();
|
stream.flush();
|
||||||
TINY_GSM_YIELD();
|
TINY_GSM_YIELD();
|
||||||
//DBG("### AT:", cmd...);
|
DBG("### AT:", cmd...);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Optimize this!
|
// TODO: Optimize this!
|
||||||
@@ -438,12 +498,12 @@ public:
|
|||||||
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
|
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
|
||||||
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
|
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
|
||||||
{
|
{
|
||||||
/*String r1s(r1); r1s.trim();
|
String r1s(r1); r1s.trim();
|
||||||
String r2s(r2); r2s.trim();
|
String r2s(r2); r2s.trim();
|
||||||
String r3s(r3); r3s.trim();
|
String r3s(r3); r3s.trim();
|
||||||
String r4s(r4); r4s.trim();
|
String r4s(r4); r4s.trim();
|
||||||
String r5s(r5); r5s.trim();
|
String r5s(r5); r5s.trim();
|
||||||
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
|
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);
|
||||||
data.reserve(64);
|
data.reserve(64);
|
||||||
int index = 0;
|
int index = 0;
|
||||||
unsigned long startMillis = millis();
|
unsigned long startMillis = millis();
|
||||||
@@ -505,6 +565,7 @@ finish:
|
|||||||
}
|
}
|
||||||
data = "";
|
data = "";
|
||||||
}
|
}
|
||||||
|
DBG('<', index, '>');
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
#ifndef TinyGsmClientM590_h
|
#ifndef TinyGsmClientM590_h
|
||||||
#define TinyGsmClientM590_h
|
#define TinyGsmClientM590_h
|
||||||
|
|
||||||
//#define TINY_GSM_DEBUG Serial
|
// #define TINY_GSM_DEBUG Serial
|
||||||
|
|
||||||
#if !defined(TINY_GSM_RX_BUFFER)
|
#if !defined(TINY_GSM_RX_BUFFER)
|
||||||
#define TINY_GSM_RX_BUFFER 256
|
#define TINY_GSM_RX_BUFFER 256
|
||||||
@@ -39,24 +39,36 @@ enum RegStatus {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class TinyGsm
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
// Declaration of the TinyGsmM590 Class
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
|
||||||
|
class TinyGsmM590
|
||||||
{
|
{
|
||||||
|
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
// The M590 Client Class
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
class GsmClient : public Client
|
class GsmClient : public Client
|
||||||
{
|
{
|
||||||
friend class TinyGsm;
|
friend class TinyGsmM590;
|
||||||
typedef TinyGsmFifo<uint8_t, TINY_GSM_RX_BUFFER> RxFifo;
|
typedef TinyGsmFifo<uint8_t, TINY_GSM_RX_BUFFER> RxFifo;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GsmClient() {}
|
GsmClient() {}
|
||||||
|
|
||||||
GsmClient(TinyGsm& modem, uint8_t mux = 1) {
|
GsmClient(TinyGsmM590& modem, uint8_t mux = 1) {
|
||||||
init(&modem, mux);
|
init(&modem, mux);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool init(TinyGsm* modem, uint8_t mux = 1) {
|
bool init(TinyGsmM590* modem, uint8_t mux = 1) {
|
||||||
this->at = modem;
|
this->at = modem;
|
||||||
this->mux = mux;
|
this->mux = mux;
|
||||||
sock_connected = false;
|
sock_connected = false;
|
||||||
@@ -116,7 +128,8 @@ public:
|
|||||||
virtual int read(uint8_t *buf, size_t size) {
|
virtual int read(uint8_t *buf, size_t size) {
|
||||||
TINY_GSM_YIELD();
|
TINY_GSM_YIELD();
|
||||||
size_t cnt = 0;
|
size_t cnt = 0;
|
||||||
while (cnt < size) {
|
uint32_t _startMillis = millis();
|
||||||
|
while (cnt < size && millis() - _startMillis < _timeout) {
|
||||||
size_t chunk = TinyGsmMin(size-cnt, rx.size());
|
size_t chunk = TinyGsmMin(size-cnt, rx.size());
|
||||||
if (chunk > 0) {
|
if (chunk > 0) {
|
||||||
rx.get(buf, chunk);
|
rx.get(buf, chunk);
|
||||||
@@ -159,15 +172,33 @@ public:
|
|||||||
String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TinyGsm* at;
|
TinyGsmM590* at;
|
||||||
uint8_t mux;
|
uint8_t mux;
|
||||||
bool sock_connected;
|
bool sock_connected;
|
||||||
RxFifo rx;
|
RxFifo rx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
// The M590 Has no Secure client!
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
// The M590 Modem Functions
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
TinyGsm(Stream& stream)
|
#ifdef GSM_DEFAULT_STREAM
|
||||||
|
TinyGsmM590(Stream& stream = GSM_DEFAULT_STREAM)
|
||||||
|
#else
|
||||||
|
TinyGsmM590(Stream& stream)
|
||||||
|
#endif
|
||||||
: stream(stream)
|
: stream(stream)
|
||||||
{
|
{
|
||||||
memset(sockets, 0, sizeof(sockets));
|
memset(sockets, 0, sizeof(sockets));
|
||||||
@@ -327,17 +358,6 @@ public:
|
|||||||
return SIM_ERROR;
|
return SIM_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
RegStatus getRegistrationStatus() {
|
|
||||||
sendAT(GF("+CREG?"));
|
|
||||||
if (waitResponse(GF(GSM_NL "+CREG:")) != 1) {
|
|
||||||
return REG_UNKNOWN;
|
|
||||||
}
|
|
||||||
streamSkipUntil(','); // Skip format (0)
|
|
||||||
int status = stream.readStringUntil('\n').toInt();
|
|
||||||
waitResponse();
|
|
||||||
return (RegStatus)status;
|
|
||||||
}
|
|
||||||
|
|
||||||
String getOperator() {
|
String getOperator() {
|
||||||
sendAT(GF("+COPS?"));
|
sendAT(GF("+COPS?"));
|
||||||
if (waitResponse(GF(GSM_NL "+COPS:")) != 1) {
|
if (waitResponse(GF(GSM_NL "+COPS:")) != 1) {
|
||||||
@@ -353,6 +373,17 @@ public:
|
|||||||
* Generic network functions
|
* Generic network functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
RegStatus getRegistrationStatus() {
|
||||||
|
sendAT(GF("+CREG?"));
|
||||||
|
if (waitResponse(GF(GSM_NL "+CREG:")) != 1) {
|
||||||
|
return REG_UNKNOWN;
|
||||||
|
}
|
||||||
|
streamSkipUntil(','); // Skip format (0)
|
||||||
|
int status = stream.readStringUntil('\n').toInt();
|
||||||
|
waitResponse();
|
||||||
|
return (RegStatus)status;
|
||||||
|
}
|
||||||
|
|
||||||
int getSignalQuality() {
|
int getSignalQuality() {
|
||||||
sendAT(GF("+CSQ"));
|
sendAT(GF("+CSQ"));
|
||||||
if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) {
|
if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) {
|
||||||
@@ -378,6 +409,26 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getLocalIP() {
|
||||||
|
sendAT(GF("+XIIC?"));
|
||||||
|
if (waitResponse(GF(GSM_NL "+XIIC:")) != 1) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
stream.readStringUntil(',');
|
||||||
|
String res = stream.readStringUntil('\n');
|
||||||
|
waitResponse();
|
||||||
|
res.trim();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress localIP() {
|
||||||
|
return TinyGsmIpFromString(getLocalIP());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* WiFi functions
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GPRS functions
|
* GPRS functions
|
||||||
*/
|
*/
|
||||||
@@ -408,12 +459,12 @@ public:
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
set_dns:
|
// set_dns: // TODO
|
||||||
sendAT(GF("+DNSSERVER=1,8.8.8.8"));
|
// sendAT(GF("+DNSSERVER=1,8.8.8.8"));
|
||||||
waitResponse();
|
// waitResponse();
|
||||||
|
//
|
||||||
sendAT(GF("+DNSSERVER=2,8.8.4.4"));
|
// sendAT(GF("+DNSSERVER=2,8.8.4.4"));
|
||||||
waitResponse();
|
// waitResponse();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -434,34 +485,6 @@ set_dns:
|
|||||||
return res == 1;
|
return res == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getLocalIP() {
|
|
||||||
sendAT(GF("+XIIC?"));
|
|
||||||
if (waitResponse(GF(GSM_NL "+XIIC:")) != 1) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
stream.readStringUntil(',');
|
|
||||||
String res = stream.readStringUntil('\n');
|
|
||||||
waitResponse();
|
|
||||||
res.trim();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
IPAddress localIP() {
|
|
||||||
return TinyGsmIpFromString(getLocalIP());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Phone Call functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool setGsmBusy(bool busy = true) TINY_GSM_ATTR_NOT_AVAILABLE;
|
|
||||||
|
|
||||||
bool callAnswer() TINY_GSM_ATTR_NOT_AVAILABLE;
|
|
||||||
|
|
||||||
bool callNumber(const String& number) TINY_GSM_ATTR_NOT_AVAILABLE;
|
|
||||||
|
|
||||||
bool callHangup() TINY_GSM_ATTR_NOT_AVAILABLE;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Messaging functions
|
* Messaging functions
|
||||||
*/
|
*/
|
||||||
@@ -595,9 +618,13 @@ public:
|
|||||||
streamWrite(tail...);
|
streamWrite(tail...);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool streamSkipUntil(char c) { //TODO: timeout
|
bool streamSkipUntil(char c) {
|
||||||
while (true) {
|
const unsigned long timeout = 1000L;
|
||||||
while (!stream.available()) { TINY_GSM_YIELD(); }
|
unsigned long startMillis = millis();
|
||||||
|
while (millis() - startMillis < timeout) {
|
||||||
|
while (millis() - startMillis < timeout && !stream.available()) {
|
||||||
|
TINY_GSM_YIELD();
|
||||||
|
}
|
||||||
if (stream.read() == c)
|
if (stream.read() == c)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -609,7 +636,7 @@ public:
|
|||||||
streamWrite("AT", cmd..., GSM_NL);
|
streamWrite("AT", cmd..., GSM_NL);
|
||||||
stream.flush();
|
stream.flush();
|
||||||
TINY_GSM_YIELD();
|
TINY_GSM_YIELD();
|
||||||
//DBG("### AT:", cmd...);
|
DBG("### AT:", cmd...);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Optimize this!
|
// TODO: Optimize this!
|
||||||
@@ -617,12 +644,12 @@ public:
|
|||||||
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
|
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
|
||||||
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
|
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
|
||||||
{
|
{
|
||||||
/*String r1s(r1); r1s.trim();
|
String r1s(r1); r1s.trim();
|
||||||
String r2s(r2); r2s.trim();
|
String r2s(r2); r2s.trim();
|
||||||
String r3s(r3); r3s.trim();
|
String r3s(r3); r3s.trim();
|
||||||
String r4s(r4); r4s.trim();
|
String r4s(r4); r4s.trim();
|
||||||
String r5s(r5); r5s.trim();
|
String r5s(r5); r5s.trim();
|
||||||
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
|
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);
|
||||||
data.reserve(64);
|
data.reserve(64);
|
||||||
int index = 0;
|
int index = 0;
|
||||||
unsigned long startMillis = millis();
|
unsigned long startMillis = millis();
|
||||||
@@ -683,6 +710,7 @@ finish:
|
|||||||
}
|
}
|
||||||
data = "";
|
data = "";
|
||||||
}
|
}
|
||||||
|
DBG('<', index, '>');
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -9,8 +9,8 @@
|
|||||||
#ifndef TinyGsmClientSIM800_h
|
#ifndef TinyGsmClientSIM800_h
|
||||||
#define TinyGsmClientSIM800_h
|
#define TinyGsmClientSIM800_h
|
||||||
|
|
||||||
//#define TINY_GSM_DEBUG Serial
|
// #define TINY_GSM_DEBUG Serial
|
||||||
//#define TINY_GSM_USE_HEX
|
// #define TINY_GSM_USE_HEX
|
||||||
|
|
||||||
#if !defined(TINY_GSM_RX_BUFFER)
|
#if !defined(TINY_GSM_RX_BUFFER)
|
||||||
#define TINY_GSM_RX_BUFFER 64
|
#define TINY_GSM_RX_BUFFER 64
|
||||||
@@ -40,9 +40,22 @@ enum RegStatus {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
// Declaration of the TinyGsmSim800 Class
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
|
||||||
class TinyGsmSim800
|
class TinyGsmSim800
|
||||||
{
|
{
|
||||||
|
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
// The Sim800 Client Class
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
class GsmClient : public Client
|
class GsmClient : public Client
|
||||||
@@ -173,15 +186,22 @@ public:
|
|||||||
String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TinyGsmSim800* at;
|
TinyGsmSim800* at;
|
||||||
uint8_t mux;
|
uint8_t mux;
|
||||||
uint16_t sock_available;
|
uint16_t sock_available;
|
||||||
uint32_t prev_check;
|
uint32_t prev_check;
|
||||||
bool sock_connected;
|
bool sock_connected;
|
||||||
bool got_data;
|
bool got_data;
|
||||||
RxFifo rx;
|
RxFifo rx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
// The SIM800 Secure Client
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
|
||||||
|
|
||||||
class GsmClientSecure : public GsmClient
|
class GsmClientSecure : public GsmClient
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -201,9 +221,19 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
// The SIM800 Modem Functions
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
#ifdef GSM_DEFAULT_STREAM
|
||||||
|
TinyGsmSim800(Stream& stream = GSM_DEFAULT_STREAM)
|
||||||
|
#else
|
||||||
TinyGsmSim800(Stream& stream)
|
TinyGsmSim800(Stream& stream)
|
||||||
|
#endif
|
||||||
: stream(stream)
|
: stream(stream)
|
||||||
{
|
{
|
||||||
memset(sockets, 0, sizeof(sockets));
|
memset(sockets, 0, sizeof(sockets));
|
||||||
@@ -226,6 +256,11 @@ public:
|
|||||||
if (waitResponse() != 1) {
|
if (waitResponse() != 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PREFERRED SMS STORAGE
|
||||||
|
sendAT(GF("+CPMS="), GF("\"SM\""), GF(","), GF("\"SM\""), GF(","), GF("\"SM\""));
|
||||||
|
waitResponse();
|
||||||
|
|
||||||
getSimStatus();
|
getSimStatus();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -393,17 +428,6 @@ public:
|
|||||||
return SIM_ERROR;
|
return SIM_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
RegStatus getRegistrationStatus() {
|
|
||||||
sendAT(GF("+CREG?"));
|
|
||||||
if (waitResponse(GF(GSM_NL "+CREG:")) != 1) {
|
|
||||||
return REG_UNKNOWN;
|
|
||||||
}
|
|
||||||
streamSkipUntil(','); // Skip format (0)
|
|
||||||
int status = stream.readStringUntil('\n').toInt();
|
|
||||||
waitResponse();
|
|
||||||
return (RegStatus)status;
|
|
||||||
}
|
|
||||||
|
|
||||||
String getOperator() {
|
String getOperator() {
|
||||||
sendAT(GF("+COPS?"));
|
sendAT(GF("+COPS?"));
|
||||||
if (waitResponse(GF(GSM_NL "+COPS:")) != 1) {
|
if (waitResponse(GF(GSM_NL "+COPS:")) != 1) {
|
||||||
@@ -419,6 +443,17 @@ public:
|
|||||||
* Generic network functions
|
* Generic network functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
RegStatus getRegistrationStatus() {
|
||||||
|
sendAT(GF("+CREG?"));
|
||||||
|
if (waitResponse(GF(GSM_NL "+CREG:")) != 1) {
|
||||||
|
return REG_UNKNOWN;
|
||||||
|
}
|
||||||
|
streamSkipUntil(','); // Skip format (0)
|
||||||
|
int status = stream.readStringUntil('\n').toInt();
|
||||||
|
waitResponse();
|
||||||
|
return (RegStatus)status;
|
||||||
|
}
|
||||||
|
|
||||||
int getSignalQuality() {
|
int getSignalQuality() {
|
||||||
sendAT(GF("+CSQ"));
|
sendAT(GF("+CSQ"));
|
||||||
if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) {
|
if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) {
|
||||||
@@ -444,6 +479,26 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getLocalIP() {
|
||||||
|
sendAT(GF("+CIFSR;E0"));
|
||||||
|
String res;
|
||||||
|
if (waitResponse(10000L, res) != 1) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
res.replace(GSM_NL "OK" GSM_NL, "");
|
||||||
|
res.replace(GSM_NL, "");
|
||||||
|
res.trim();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress localIP() {
|
||||||
|
return TinyGsmIpFromString(getLocalIP());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* WiFi functions
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GPRS functions
|
* GPRS functions
|
||||||
*/
|
*/
|
||||||
@@ -564,72 +619,6 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getLocalIP() {
|
|
||||||
sendAT(GF("+CIFSR;E0"));
|
|
||||||
String res;
|
|
||||||
if (waitResponse(10000L, res) != 1) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
res.replace(GSM_NL "OK" GSM_NL, "");
|
|
||||||
res.replace(GSM_NL, "");
|
|
||||||
res.trim();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
IPAddress localIP() {
|
|
||||||
return TinyGsmIpFromString(getLocalIP());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Phone Call functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool setGsmBusy(bool busy = true) {
|
|
||||||
sendAT(GF("+GSMBUSY="), busy ? 1 : 0);
|
|
||||||
return waitResponse() == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool callAnswer() {
|
|
||||||
sendAT(GF("A"));
|
|
||||||
return waitResponse() == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns true on pick-up, false on error/busy
|
|
||||||
bool callNumber(const String& number) {
|
|
||||||
if (number == GF("last")) {
|
|
||||||
sendAT(GF("DL"));
|
|
||||||
} else {
|
|
||||||
sendAT(GF("D"), number, ";");
|
|
||||||
}
|
|
||||||
int status = waitResponse(60000L,
|
|
||||||
GFP(GSM_OK),
|
|
||||||
GF("BUSY" GSM_NL),
|
|
||||||
GF("NO ANSWER" GSM_NL),
|
|
||||||
GF("NO CARRIER" GSM_NL));
|
|
||||||
switch (status) {
|
|
||||||
case 1: return true;
|
|
||||||
case 2:
|
|
||||||
case 3: return false;
|
|
||||||
default: return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool callHangup() {
|
|
||||||
sendAT(GF("H"));
|
|
||||||
return waitResponse() == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 0-9,*,#,A,B,C,D
|
|
||||||
bool dtmfSend(char cmd, int duration_ms = 100) {
|
|
||||||
duration_ms = constrain(duration_ms, 100, 1000);
|
|
||||||
|
|
||||||
sendAT(GF("+VTD="), duration_ms / 100); // VTD accepts in 1/10 of a second
|
|
||||||
waitResponse();
|
|
||||||
|
|
||||||
sendAT(GF("+VTS="), cmd);
|
|
||||||
return waitResponse(10000L) == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Messaging functions
|
* Messaging functions
|
||||||
*/
|
*/
|
||||||
@@ -722,6 +711,7 @@ public:
|
|||||||
/*
|
/*
|
||||||
* Battery functions
|
* Battery functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Use: float vBatt = modem.getBattVoltage() / 1000.0;
|
// Use: float vBatt = modem.getBattVoltage() / 1000.0;
|
||||||
uint16_t getBattVoltage() {
|
uint16_t getBattVoltage() {
|
||||||
sendAT(GF("+CBC"));
|
sendAT(GF("+CBC"));
|
||||||
@@ -854,9 +844,13 @@ public:
|
|||||||
streamWrite(tail...);
|
streamWrite(tail...);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool streamSkipUntil(char c) { //TODO: timeout
|
bool streamSkipUntil(char c) {
|
||||||
while (true) {
|
const unsigned long timeout = 1000L;
|
||||||
while (!stream.available()) { TINY_GSM_YIELD(); }
|
unsigned long startMillis = millis();
|
||||||
|
while (millis() - startMillis < timeout) {
|
||||||
|
while (millis() - startMillis < timeout && !stream.available()) {
|
||||||
|
TINY_GSM_YIELD();
|
||||||
|
}
|
||||||
if (stream.read() == c)
|
if (stream.read() == c)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -868,7 +862,7 @@ public:
|
|||||||
streamWrite("AT", cmd..., GSM_NL);
|
streamWrite("AT", cmd..., GSM_NL);
|
||||||
stream.flush();
|
stream.flush();
|
||||||
TINY_GSM_YIELD();
|
TINY_GSM_YIELD();
|
||||||
//DBG("### AT:", cmd...);
|
DBG("### AT:", cmd...);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Optimize this!
|
// TODO: Optimize this!
|
||||||
@@ -876,12 +870,12 @@ public:
|
|||||||
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
|
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
|
||||||
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
|
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
|
||||||
{
|
{
|
||||||
/*String r1s(r1); r1s.trim();
|
String r1s(r1); r1s.trim();
|
||||||
String r2s(r2); r2s.trim();
|
String r2s(r2); r2s.trim();
|
||||||
String r3s(r3); r3s.trim();
|
String r3s(r3); r3s.trim();
|
||||||
String r4s(r4); r4s.trim();
|
String r4s(r4); r4s.trim();
|
||||||
String r5s(r5); r5s.trim();
|
String r5s(r5); r5s.trim();
|
||||||
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
|
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);
|
||||||
data.reserve(64);
|
data.reserve(64);
|
||||||
int index = 0;
|
int index = 0;
|
||||||
unsigned long startMillis = millis();
|
unsigned long startMillis = millis();
|
||||||
@@ -937,6 +931,7 @@ finish:
|
|||||||
}
|
}
|
||||||
data = "";
|
data = "";
|
||||||
}
|
}
|
||||||
|
DBG('<', index, '>');
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -11,6 +11,13 @@
|
|||||||
|
|
||||||
#include <TinyGsmClientSIM800.h>
|
#include <TinyGsmClientSIM800.h>
|
||||||
|
|
||||||
|
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
// Declaration and Definitio of the TinyGsmSim808 Class
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
|
||||||
class TinyGsmSim808: public TinyGsmSim800
|
class TinyGsmSim808: public TinyGsmSim800
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
#ifndef TinyGsmClientU201_h
|
#ifndef TinyGsmClientU201_h
|
||||||
#define TinyGsmClientU201_h
|
#define TinyGsmClientU201_h
|
||||||
|
|
||||||
//#define TINY_GSM_DEBUG Serial
|
// #define TINY_GSM_DEBUG Serial
|
||||||
|
|
||||||
#if !defined(TINY_GSM_RX_BUFFER)
|
#if !defined(TINY_GSM_RX_BUFFER)
|
||||||
#define TINY_GSM_RX_BUFFER 64
|
#define TINY_GSM_RX_BUFFER 64
|
||||||
@@ -39,9 +39,22 @@ enum RegStatus {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
// Declaration of the TinyGsmU201 Class
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
|
||||||
class TinyGsmU201
|
class TinyGsmU201
|
||||||
{
|
{
|
||||||
|
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
// The U201 Client Class
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
class GsmClient : public Client
|
class GsmClient : public Client
|
||||||
@@ -171,6 +184,13 @@ private:
|
|||||||
RxFifo rx;
|
RxFifo rx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
// The Secure U201 Client Class
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
|
||||||
|
|
||||||
class GsmClientSecure : public GsmClient
|
class GsmClientSecure : public GsmClient
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -191,6 +211,13 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
// The U201 Modem Functions
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
#ifdef GSM_DEFAULT_STREAM
|
#ifdef GSM_DEFAULT_STREAM
|
||||||
@@ -285,6 +312,10 @@ public:
|
|||||||
|
|
||||||
bool poweroff() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
bool poweroff() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
|
bool radioOff() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
|
bool sleepEnable(bool enable = true) TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SIM card functions
|
* SIM card functions
|
||||||
*/
|
*/
|
||||||
@@ -335,17 +366,6 @@ public:
|
|||||||
return SIM_ERROR;
|
return SIM_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
RegStatus getRegistrationStatus() {
|
|
||||||
sendAT(GF("+CGREG?"));
|
|
||||||
if (waitResponse(GF(GSM_NL "+CGREG:")) != 1) {
|
|
||||||
return REG_UNKNOWN;
|
|
||||||
}
|
|
||||||
streamSkipUntil(','); // Skip format (0)
|
|
||||||
int status = stream.readStringUntil('\n').toInt();
|
|
||||||
waitResponse();
|
|
||||||
return (RegStatus)status;
|
|
||||||
}
|
|
||||||
|
|
||||||
String getOperator() {
|
String getOperator() {
|
||||||
sendAT(GF("+COPS?"));
|
sendAT(GF("+COPS?"));
|
||||||
if (waitResponse(GF(GSM_NL "+COPS:")) != 1) {
|
if (waitResponse(GF(GSM_NL "+COPS:")) != 1) {
|
||||||
@@ -361,6 +381,17 @@ public:
|
|||||||
* Generic network functions
|
* Generic network functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
RegStatus getRegistrationStatus() {
|
||||||
|
sendAT(GF("+CGREG?"));
|
||||||
|
if (waitResponse(GF(GSM_NL "+CGREG:")) != 1) {
|
||||||
|
return REG_UNKNOWN;
|
||||||
|
}
|
||||||
|
streamSkipUntil(','); // Skip format (0)
|
||||||
|
int status = stream.readStringUntil('\n').toInt();
|
||||||
|
waitResponse();
|
||||||
|
return (RegStatus)status;
|
||||||
|
}
|
||||||
|
|
||||||
int getSignalQuality() {
|
int getSignalQuality() {
|
||||||
sendAT(GF("+CSQ"));
|
sendAT(GF("+CSQ"));
|
||||||
if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) {
|
if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) {
|
||||||
@@ -386,6 +417,24 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getLocalIP() {
|
||||||
|
sendAT(GF("+CIFSR;E0"));
|
||||||
|
String res;
|
||||||
|
if (waitResponse(10000L, res) != 1) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
res.trim();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress localIP() {
|
||||||
|
return TinyGsmIpFromString(getLocalIP());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* WiFi functions
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GPRS functions
|
* GPRS functions
|
||||||
*/
|
*/
|
||||||
@@ -450,32 +499,6 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getLocalIP() {
|
|
||||||
sendAT(GF("+CIFSR;E0"));
|
|
||||||
String res;
|
|
||||||
if (waitResponse(10000L, res) != 1) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
res.trim();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
IPAddress localIP() {
|
|
||||||
return TinyGsmIpFromString(getLocalIP());
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Phone Call functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool setGsmBusy(bool busy = true) TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
|
||||||
|
|
||||||
bool callAnswer() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
|
||||||
|
|
||||||
bool callNumber(const String& number) TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
|
||||||
|
|
||||||
bool callHangup() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Messaging functions
|
* Messaging functions
|
||||||
*/
|
*/
|
||||||
@@ -505,6 +528,7 @@ public:
|
|||||||
/*
|
/*
|
||||||
* Battery functions
|
* Battery functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Use: float vBatt = modem.getBattVoltage() / 1000.0;
|
// Use: float vBatt = modem.getBattVoltage() / 1000.0;
|
||||||
uint16_t getBattVoltage() {
|
uint16_t getBattVoltage() {
|
||||||
sendAT(GF("+CIND"));
|
sendAT(GF("+CIND"));
|
||||||
@@ -615,9 +639,13 @@ public:
|
|||||||
streamWrite(tail...);
|
streamWrite(tail...);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool streamSkipUntil(char c) { //TODO: timeout
|
bool streamSkipUntil(char c) {
|
||||||
while (true) {
|
const unsigned long timeout = 1000L;
|
||||||
while (!stream.available()) { TINY_GSM_YIELD(); }
|
unsigned long startMillis = millis();
|
||||||
|
while (millis() - startMillis < timeout) {
|
||||||
|
while (millis() - startMillis < timeout && !stream.available()) {
|
||||||
|
TINY_GSM_YIELD();
|
||||||
|
}
|
||||||
if (stream.read() == c)
|
if (stream.read() == c)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -629,7 +657,7 @@ public:
|
|||||||
streamWrite("AT", cmd..., GSM_NL);
|
streamWrite("AT", cmd..., GSM_NL);
|
||||||
stream.flush();
|
stream.flush();
|
||||||
TINY_GSM_YIELD();
|
TINY_GSM_YIELD();
|
||||||
//DBG("### AT:", cmd...);
|
DBG("### AT:", cmd...);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Optimize this!
|
// TODO: Optimize this!
|
||||||
@@ -637,12 +665,12 @@ public:
|
|||||||
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
|
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
|
||||||
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
|
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
|
||||||
{
|
{
|
||||||
/*String r1s(r1); r1s.trim();
|
String r1s(r1); r1s.trim();
|
||||||
String r2s(r2); r2s.trim();
|
String r2s(r2); r2s.trim();
|
||||||
String r3s(r3); r3s.trim();
|
String r3s(r3); r3s.trim();
|
||||||
String r4s(r4); r4s.trim();
|
String r4s(r4); r4s.trim();
|
||||||
String r5s(r5); r5s.trim();
|
String r5s(r5); r5s.trim();
|
||||||
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
|
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);
|
||||||
data.reserve(64);
|
data.reserve(64);
|
||||||
int index = 0;
|
int index = 0;
|
||||||
unsigned long startMillis = millis();
|
unsigned long startMillis = millis();
|
||||||
@@ -650,7 +678,7 @@ public:
|
|||||||
TINY_GSM_YIELD();
|
TINY_GSM_YIELD();
|
||||||
while (stream.available() > 0) {
|
while (stream.available() > 0) {
|
||||||
int a = stream.read();
|
int a = stream.read();
|
||||||
if (a < 0) continue;
|
if (a <= 0) continue; // Skip 0x00 bytes, just in case
|
||||||
data += (char)a;
|
data += (char)a;
|
||||||
if (r1 && data.endsWith(r1)) {
|
if (r1 && data.endsWith(r1)) {
|
||||||
index = 1;
|
index = 1;
|
||||||
@@ -691,6 +719,7 @@ finish:
|
|||||||
}
|
}
|
||||||
data = "";
|
data = "";
|
||||||
}
|
}
|
||||||
|
DBG('<', index, '>');
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -11,9 +11,6 @@
|
|||||||
|
|
||||||
//#define TINY_GSM_DEBUG Serial
|
//#define TINY_GSM_DEBUG Serial
|
||||||
|
|
||||||
#if !defined(TINY_GSM_RX_BUFFER)
|
|
||||||
#define TINY_GSM_RX_BUFFER 256
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define TINY_GSM_MUX_COUNT 1 // Multi-plexing isn't supported using command mode
|
#define TINY_GSM_MUX_COUNT 1 // Multi-plexing isn't supported using command mode
|
||||||
|
|
||||||
@@ -29,38 +26,55 @@ enum SimStatus {
|
|||||||
SIM_LOCKED = 2,
|
SIM_LOCKED = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum XBeeType {
|
|
||||||
S6B = 0,
|
|
||||||
LTEC1 = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum RegStatus {
|
enum RegStatus {
|
||||||
REG_UNREGISTERED = 0,
|
REG_OK = 0,
|
||||||
|
REG_UNREGISTERED = 1,
|
||||||
REG_SEARCHING = 2,
|
REG_SEARCHING = 2,
|
||||||
REG_DENIED = 3,
|
REG_DENIED = 3,
|
||||||
REG_OK_HOME = 1,
|
|
||||||
REG_OK_ROAMING = 5,
|
|
||||||
REG_UNKNOWN = 4,
|
REG_UNKNOWN = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// These are responses to the HS command to get "hardware series"
|
||||||
|
enum XBeeType {
|
||||||
|
XBEE_S6B_WIFI = 0x601, // Digi XBee® Wi-Fi
|
||||||
|
XBEE_LTE1_VZN = 0xB01, // Digi XBee® Cellular LTE Cat 1
|
||||||
|
XBEE_3G = 0xB02, // Digi XBee® Cellular 3G
|
||||||
|
XBEE3_LTE1_ATT = 1, // Digi XBee3™ Cellular LTE CAT 1 -- HS unknown to SRGD
|
||||||
|
XBEE3_LTEM_ATT = 2, // Digi XBee3™ Cellular LTE-M -- HS unknown to SRGD
|
||||||
|
XBEE3_LTENB = 3, // Digi XBee3™ Cellular NB-IoT -- HS unknown to SRGD
|
||||||
|
};
|
||||||
|
|
||||||
class TinyGsm
|
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
// Declaration of the TinyGsmXBee Class
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
|
||||||
|
class TinyGsmXBee
|
||||||
{
|
{
|
||||||
|
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
// The XBee Client Class
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
class GsmClient : public Client
|
class GsmClient : public Client
|
||||||
{
|
{
|
||||||
friend class TinyGsm;
|
friend class TinyGsmXBee;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GsmClient() {}
|
GsmClient() {}
|
||||||
|
|
||||||
GsmClient(TinyGsm& modem, uint8_t mux = 0) {
|
GsmClient(TinyGsmXBee& modem, uint8_t mux = 0) {
|
||||||
init(&modem, mux);
|
init(&modem, mux);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool init(TinyGsm* modem, uint8_t mux = 0) {
|
bool init(TinyGsmXBee* modem, uint8_t mux = 0) {
|
||||||
this->at = modem;
|
this->at = modem;
|
||||||
this->mux = mux;
|
this->mux = mux;
|
||||||
sock_connected = false;
|
sock_connected = false;
|
||||||
@@ -73,19 +87,25 @@ public:
|
|||||||
public:
|
public:
|
||||||
virtual int connect(const char *host, uint16_t port) {
|
virtual int connect(const char *host, uint16_t port) {
|
||||||
at->streamClear(); // Empty anything remaining in the buffer;
|
at->streamClear(); // Empty anything remaining in the buffer;
|
||||||
at->commandMode();
|
bool sock_connected = false;
|
||||||
sock_connected = at->modemConnect(host, port, mux, false);
|
if (at->commandMode()) { // Don't try if we didn't successfully get into command mode
|
||||||
at->writeChanges();
|
sock_connected = at->modemConnect(host, port, mux, false);
|
||||||
at->exitCommand();
|
at->writeChanges();
|
||||||
|
at->exitCommand();
|
||||||
|
}
|
||||||
|
at->streamClear(); // Empty anything remaining in the buffer;
|
||||||
return sock_connected;
|
return sock_connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int connect(IPAddress ip, uint16_t port) {
|
virtual int connect(IPAddress ip, uint16_t port) {
|
||||||
at->streamClear(); // Empty anything remaining in the buffer;
|
at->streamClear(); // Empty anything remaining in the buffer;
|
||||||
at->commandMode();
|
bool sock_connected = false;
|
||||||
sock_connected = at->modemConnect(ip, port, mux, false);
|
if (at->commandMode()) { // Don't try if we didn't successfully get into command mode
|
||||||
at->writeChanges();
|
sock_connected = at->modemConnect(ip, port, mux, false);
|
||||||
at->exitCommand();
|
at->writeChanges();
|
||||||
|
at->exitCommand();
|
||||||
|
}
|
||||||
|
at->streamClear(); // Empty anything remaining in the buffer;
|
||||||
return sock_connected;
|
return sock_connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +120,7 @@ public:
|
|||||||
at->exitCommand();
|
at->exitCommand();
|
||||||
at->modemSend("", 1, mux);
|
at->modemSend("", 1, mux);
|
||||||
at->commandMode();
|
at->commandMode();
|
||||||
at->sendAT(GF("TM64")); // Set socket timeout back to 10seconds;
|
at->sendAT(GF("TM64")); // Set socket timeout back to 10 seconds;
|
||||||
at->waitResponse();
|
at->waitResponse();
|
||||||
at->writeChanges();
|
at->writeChanges();
|
||||||
at->exitCommand();
|
at->exitCommand();
|
||||||
@@ -110,7 +130,6 @@ public:
|
|||||||
|
|
||||||
virtual size_t write(const uint8_t *buf, size_t size) {
|
virtual size_t write(const uint8_t *buf, size_t size) {
|
||||||
TINY_GSM_YIELD();
|
TINY_GSM_YIELD();
|
||||||
//at->maintain();
|
|
||||||
return at->modemSend(buf, size, mux);
|
return at->modemSend(buf, size, mux);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +144,7 @@ public:
|
|||||||
|
|
||||||
virtual int read(uint8_t *buf, size_t size) {
|
virtual int read(uint8_t *buf, size_t size) {
|
||||||
TINY_GSM_YIELD();
|
TINY_GSM_YIELD();
|
||||||
return at->stream.readBytes(buf, size);
|
return at->stream.readBytes((char*)buf, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int read() {
|
virtual int read() {
|
||||||
@@ -151,47 +170,69 @@ public:
|
|||||||
String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TinyGsm* at;
|
TinyGsmXBee* at;
|
||||||
uint8_t mux;
|
uint8_t mux;
|
||||||
bool sock_connected;
|
bool sock_connected;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
// The Secure XBee Client Class
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
|
||||||
|
|
||||||
class GsmClientSecure : public GsmClient
|
class GsmClientSecure : public GsmClient
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GsmClientSecure() {}
|
GsmClientSecure() {}
|
||||||
|
|
||||||
GsmClientSecure(TinyGsm& modem, uint8_t mux = 1)
|
GsmClientSecure(TinyGsmXBee& modem, uint8_t mux = 1)
|
||||||
: GsmClient(modem, mux)
|
: GsmClient(modem, mux)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual int connect(const char *host, uint16_t port) {
|
virtual int connect(const char *host, uint16_t port) {
|
||||||
at->streamClear(); // Empty anything remaining in the buffer;
|
at->streamClear(); // Empty anything remaining in the buffer;
|
||||||
at->commandMode();
|
bool sock_connected = false;
|
||||||
sock_connected = at->modemConnect(host, port, mux, true);
|
if (at->commandMode()) { // Don't try if we didn't successfully get into command mode
|
||||||
at->writeChanges();
|
sock_connected = at->modemConnect(host, port, mux, true);
|
||||||
at->exitCommand();
|
at->writeChanges();
|
||||||
|
at->exitCommand();
|
||||||
|
}
|
||||||
|
at->streamClear(); // Empty anything remaining in the buffer;
|
||||||
return sock_connected;
|
return sock_connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int connect(IPAddress ip, uint16_t port) {
|
virtual int connect(IPAddress ip, uint16_t port) {
|
||||||
at->streamClear(); // Empty anything remaining in the buffer;
|
at->streamClear(); // Empty anything remaining in the buffer;
|
||||||
at->commandMode();
|
bool sock_connected = false;
|
||||||
sock_connected = at->modemConnect(ip, port, mux, true);
|
if (at->commandMode()) { // Don't try if we didn't successfully get into command mode
|
||||||
at->writeChanges();
|
sock_connected = at->modemConnect(ip, port, mux, true);
|
||||||
at->exitCommand();
|
at->writeChanges();
|
||||||
|
at->exitCommand();
|
||||||
|
}
|
||||||
|
at->streamClear(); // Empty anything remaining in the buffer;
|
||||||
return sock_connected;
|
return sock_connected;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
// The XBee Modem Functions
|
||||||
|
//============================================================================//
|
||||||
|
//============================================================================//
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
TinyGsm(Stream& stream)
|
#ifdef GSM_DEFAULT_STREAM
|
||||||
|
TinyGsmXBee(Stream& stream = GSM_DEFAULT_STREAM)
|
||||||
|
#else
|
||||||
|
TinyGsmXBee(Stream& stream)
|
||||||
|
#endif
|
||||||
: stream(stream)
|
: stream(stream)
|
||||||
{
|
{}
|
||||||
memset(sockets, 0, sizeof(sockets));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Basic functions
|
* Basic functions
|
||||||
@@ -201,23 +242,53 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool init() {
|
bool init() {
|
||||||
guardTime = 1100;
|
guardTime = 1100; // Start with a default guard time of 1 second
|
||||||
commandMode();
|
|
||||||
|
if (!commandMode(10)) return false; // Try up to 10 times for the init
|
||||||
|
|
||||||
sendAT(GF("AP0")); // Put in transparent mode
|
sendAT(GF("AP0")); // Put in transparent mode
|
||||||
waitResponse();
|
bool ret_val = waitResponse() == 1;
|
||||||
|
ret_val &= writeChanges();
|
||||||
|
|
||||||
sendAT(GF("GT64")); // shorten the guard time to 100ms
|
sendAT(GF("GT64")); // shorten the guard time to 100ms
|
||||||
|
ret_val &= waitResponse();
|
||||||
|
ret_val &= writeChanges();
|
||||||
|
if (ret_val) guardTime = 125;
|
||||||
|
|
||||||
|
sendAT(GF("HS")); // Get the "Hardware Series";
|
||||||
|
String res = readResponse();
|
||||||
|
char buf[4] = {0,}; // Set up buffer for response
|
||||||
|
res.toCharArray(buf, 4);
|
||||||
|
int intRes = strtol(buf, 0, 16);
|
||||||
|
beeType = (XBeeType)intRes;
|
||||||
|
|
||||||
|
exitCommand();
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setBaud(unsigned long baud) {
|
||||||
|
if (!commandMode()) return;
|
||||||
|
switch(baud)
|
||||||
|
{
|
||||||
|
case 2400: sendAT(GF("BD1")); break;
|
||||||
|
case 4800: sendAT(GF("BD2")); break;
|
||||||
|
case 9600: sendAT(GF("BD3")); break;
|
||||||
|
case 19200: sendAT(GF("BD4")); break;
|
||||||
|
case 38400: sendAT(GF("BD5")); break;
|
||||||
|
case 57600: sendAT(GF("BD6")); break;
|
||||||
|
case 115200: sendAT(GF("BD7")); break;
|
||||||
|
case 230400: sendAT(GF("BD8")); break;
|
||||||
|
case 460800: sendAT(GF("BD9")); break;
|
||||||
|
case 921600: sendAT(GF("BDA")); break;
|
||||||
|
default: {
|
||||||
|
DBG(GF("Specified baud rate is unsupported! Setting to 9600 baud."));
|
||||||
|
sendAT(GF("BD3")); // Set to default of 9600
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
waitResponse();
|
waitResponse();
|
||||||
writeChanges();
|
writeChanges();
|
||||||
sendAT(GF("HS")); // Get the "Hardware Series"; 0x601 for S6B (Wifi)
|
|
||||||
// wait for the response
|
|
||||||
unsigned long startMillis = millis();
|
|
||||||
while (!stream.available() && millis() - startMillis < 1000) {};
|
|
||||||
String res = streamReadUntil('\r'); // Does not send an OK, just the result
|
|
||||||
exitCommand();
|
exitCommand();
|
||||||
if (res == "601") beeType = S6B;
|
|
||||||
else beeType = LTEC1;
|
|
||||||
guardTime = 125;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool testAT(unsigned long timeout = 10000L) {
|
bool testAT(unsigned long timeout = 10000L) {
|
||||||
@@ -238,52 +309,100 @@ public:
|
|||||||
void maintain() {}
|
void maintain() {}
|
||||||
|
|
||||||
bool factoryDefault() {
|
bool factoryDefault() {
|
||||||
commandMode();
|
if (!commandMode()) return false; // Return immediately
|
||||||
sendAT(GF("RE"));
|
sendAT(GF("RE"));
|
||||||
bool ret_val = waitResponse() == 1;
|
bool ret_val = waitResponse() == 1;
|
||||||
writeChanges();
|
ret_val &= writeChanges();
|
||||||
exitCommand();
|
exitCommand();
|
||||||
return ret_val;
|
return ret_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getModemInfo() {
|
||||||
|
String modemInf = "";
|
||||||
|
if (!commandMode()) return modemInf; // Try up to 10 times for the init
|
||||||
|
|
||||||
|
sendAT(GF("HS")); // Get the "Hardware Series"
|
||||||
|
modemInf += readResponse();
|
||||||
|
|
||||||
|
exitCommand();
|
||||||
|
return modemInf;
|
||||||
|
}
|
||||||
|
|
||||||
bool hasSSL() {
|
bool hasSSL() {
|
||||||
if (beeType == S6B) return false;
|
if (beeType == XBEE_S6B_WIFI) return false;
|
||||||
else return true;
|
else return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XBeeType getBeeType() {
|
||||||
|
return beeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getBeeName() {
|
||||||
|
switch (beeType){
|
||||||
|
case XBEE_S6B_WIFI: return "Digi XBee® Wi-Fi";
|
||||||
|
case XBEE_LTE1_VZN: return "Digi XBee® Cellular LTE Cat 1";
|
||||||
|
case XBEE_3G: return "Digi XBee® Cellular 3G";
|
||||||
|
case XBEE3_LTE1_ATT: return "Digi XBee3™ Cellular LTE CAT 1";
|
||||||
|
case XBEE3_LTEM_ATT: return "Digi XBee3™ Cellular LTE-M";
|
||||||
|
case XBEE3_LTENB: return "Digi XBee3™ Cellular NB-IoT";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Power functions
|
* Power functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool restart() {
|
bool restart() {
|
||||||
commandMode();
|
if (!commandMode()) return false; // Return immediately
|
||||||
|
sendAT(GF("AM1")); // Digi suggests putting into airplane mode before restarting
|
||||||
|
// This allows the sockets and connections to close cleanly
|
||||||
|
writeChanges();
|
||||||
|
if (waitResponse() != 1) goto fail;
|
||||||
sendAT(GF("FR"));
|
sendAT(GF("FR"));
|
||||||
if (waitResponse() != 1) {
|
if (waitResponse() != 1) goto fail;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
delay (2000); // Actually resets about 2 seconds later
|
delay (2000); // Actually resets about 2 seconds later
|
||||||
|
|
||||||
|
// Wait until reboot complete and responds to command mode call again
|
||||||
for (unsigned long start = millis(); millis() - start < 60000L; ) {
|
for (unsigned long start = millis(); millis() - start < 60000L; ) {
|
||||||
if (commandMode()) {
|
if (commandMode(1)) {
|
||||||
|
sendAT(GF("AM0")); // Turn off airplane mode
|
||||||
|
writeChanges();
|
||||||
exitCommand();
|
exitCommand();
|
||||||
return true;
|
delay(250); // wait a litle before trying again
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exitCommand();
|
return true;
|
||||||
return false;;
|
|
||||||
|
|
||||||
|
fail:
|
||||||
|
exitCommand();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupPinSleep() {
|
void setupPinSleep(bool maintainAssociation = false) {
|
||||||
commandMode();
|
if (!commandMode()) return; // Return immediately
|
||||||
sendAT(GF("SM"),1);
|
sendAT(GF("SM"),1); // Pin sleep
|
||||||
waitResponse();
|
waitResponse();
|
||||||
if (beeType == S6B) {
|
if (beeType == XBEE_S6B_WIFI && !maintainAssociation) {
|
||||||
sendAT(GF("SO"),200);
|
sendAT(GF("SO"),200); // For lowest power, dissassociated deep sleep
|
||||||
|
waitResponse();
|
||||||
|
}
|
||||||
|
else if (!maintainAssociation){
|
||||||
|
sendAT(GF("SO"),1); // For lowest power, dissassociated deep sleep
|
||||||
|
// Not supported by all modules, will return "ERROR"
|
||||||
waitResponse();
|
waitResponse();
|
||||||
}
|
}
|
||||||
writeChanges();
|
writeChanges();
|
||||||
exitCommand();
|
exitCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool poweroff() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
|
bool radioOff() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
|
bool sleepEnable(bool enable = true) TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SIM card functions
|
* SIM card functions
|
||||||
*/
|
*/
|
||||||
@@ -293,23 +412,17 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
String getSimCCID() {
|
String getSimCCID() {
|
||||||
commandMode();
|
if (!commandMode()) return ""; // Return immediately
|
||||||
sendAT(GF("S#"));
|
sendAT(GF("S#"));
|
||||||
// wait for the response
|
String res = readResponse();
|
||||||
unsigned long startMillis = millis();
|
|
||||||
while (!stream.available() && millis() - startMillis < 1000) {};
|
|
||||||
String res = streamReadUntil('\r'); // Does not send an OK, just the result
|
|
||||||
exitCommand();
|
exitCommand();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getIMEI() {
|
String getIMEI() {
|
||||||
commandMode();
|
if (!commandMode()) return ""; // Return immediately
|
||||||
sendAT(GF("IM"));
|
sendAT(GF("IM"));
|
||||||
// wait for the response
|
String res = readResponse();
|
||||||
unsigned long startMillis = millis();
|
|
||||||
while (!stream.available() && millis() - startMillis < 1000) {};
|
|
||||||
String res = streamReadUntil('\r'); // Does not send an OK, just the result
|
|
||||||
exitCommand();
|
exitCommand();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -318,38 +431,10 @@ public:
|
|||||||
return SIM_READY; // unsupported
|
return SIM_READY; // unsupported
|
||||||
}
|
}
|
||||||
|
|
||||||
RegStatus getRegistrationStatus() {
|
|
||||||
commandMode();
|
|
||||||
sendAT(GF("AI"));
|
|
||||||
// wait for the response
|
|
||||||
unsigned long startMillis = millis();
|
|
||||||
while (!stream.available() && millis() - startMillis < 1000) {};
|
|
||||||
String res = streamReadUntil('\r'); // Does not send an OK, just the result
|
|
||||||
exitCommand();
|
|
||||||
|
|
||||||
if(res == GF("0"))
|
|
||||||
return REG_OK_HOME;
|
|
||||||
|
|
||||||
else if(res == GF("13") || res == GF("2A"))
|
|
||||||
return REG_UNREGISTERED;
|
|
||||||
|
|
||||||
else if(res == GF("FF") || res == GF("22") || res == GF("23") ||
|
|
||||||
res == GF("40") || res == GF("41") || res == GF("42"))
|
|
||||||
return REG_SEARCHING;
|
|
||||||
|
|
||||||
else if(res == GF("24") || res == GF("25") || res == GF("27"))
|
|
||||||
return REG_DENIED;
|
|
||||||
|
|
||||||
else return REG_UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
String getOperator() {
|
String getOperator() {
|
||||||
commandMode();
|
if (!commandMode()) return ""; // Return immediately
|
||||||
sendAT(GF("MN"));
|
sendAT(GF("MN"));
|
||||||
// wait for the response
|
String res = readResponse();
|
||||||
unsigned long startMillis = millis();
|
|
||||||
while (!stream.available() && millis() - startMillis < 1000) {};
|
|
||||||
String res = streamReadUntil('\r'); // Does not send an OK, just the result
|
|
||||||
exitCommand();
|
exitCommand();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -358,26 +443,95 @@ public:
|
|||||||
* Generic network functions
|
* Generic network functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int getSignalQuality() {
|
RegStatus getRegistrationStatus() {
|
||||||
commandMode();
|
if (!commandMode()) return REG_UNKNOWN; // Return immediately
|
||||||
if (beeType == S6B) sendAT(GF("LM")); // ask for the "link margin" - the dB above sensitivity
|
|
||||||
else sendAT(GF("DB")); // ask for the cell strength in dBm
|
sendAT(GF("AI"));
|
||||||
// wait for the response
|
String res = readResponse();
|
||||||
unsigned long startMillis = millis();
|
char buf[3] = {0,}; // Set up buffer for response
|
||||||
while (!stream.available() && millis() - startMillis < 1000) {};
|
res.toCharArray(buf, 3);
|
||||||
char buf[2] = {0}; // Set up buffer for response
|
int intRes = strtol(buf, 0, 16);
|
||||||
buf[0] = streamRead();
|
RegStatus stat = REG_UNKNOWN;
|
||||||
buf[1] = streamRead();
|
|
||||||
// DBG(buf[0], buf[1], "\n");
|
switch (beeType){
|
||||||
|
case XBEE_S6B_WIFI: {
|
||||||
|
if(intRes == 0x00) // 0x00 Successfully joined an access point, established IP addresses and IP listening sockets
|
||||||
|
stat = REG_OK;
|
||||||
|
else if(intRes == 0x01) // 0x01 Wi-Fi transceiver initialization in progress.
|
||||||
|
stat = REG_SEARCHING;
|
||||||
|
else if(intRes == 0x02) // 0x02 Wi-Fi transceiver initialized, but not yet scanning for access point.
|
||||||
|
stat = REG_SEARCHING;
|
||||||
|
else if(intRes == 0x13) { // 0x13 Disconnecting from access point.
|
||||||
|
restart(); // Restart the device; the S6B tends to get stuck "disconnecting"
|
||||||
|
stat = REG_UNREGISTERED;
|
||||||
|
}
|
||||||
|
else if(intRes == 0x23) // 0x23 SSID not configured.
|
||||||
|
stat = REG_UNREGISTERED;
|
||||||
|
else if(intRes == 0x24) // 0x24 Encryption key invalid (either NULL or invalid length for WEP).
|
||||||
|
stat = REG_DENIED;
|
||||||
|
else if(intRes == 0x27) // 0x27 SSID was found, but join failed.
|
||||||
|
stat = REG_DENIED;
|
||||||
|
else if(intRes == 0x40) // 0x40 Waiting for WPA or WPA2 Authentication.
|
||||||
|
stat = REG_SEARCHING;
|
||||||
|
else if(intRes == 0x41) // 0x41 Device joined a network and is waiting for IP configuration to complete
|
||||||
|
stat = REG_SEARCHING;
|
||||||
|
else if(intRes == 0x42) // 0x42 Device is joined, IP is configured, and listening sockets are being set up.
|
||||||
|
stat = REG_SEARCHING;
|
||||||
|
else if(intRes == 0xFF) // 0xFF Device is currently scanning for the configured SSID.
|
||||||
|
stat = REG_SEARCHING;
|
||||||
|
else stat = REG_UNKNOWN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
if(intRes == 0x00) // 0x00 Connected to the Internet.
|
||||||
|
stat = REG_OK;
|
||||||
|
else if(intRes == 0x22) // 0x22 Registering to cellular network.
|
||||||
|
stat = REG_SEARCHING;
|
||||||
|
else if(intRes == 0x23) // 0x23 Connecting to the Internet.
|
||||||
|
stat = REG_SEARCHING;
|
||||||
|
else if(intRes == 0x24) // 0x24 The cellular component is missing, corrupt, or otherwise in error.
|
||||||
|
stat = REG_UNKNOWN;
|
||||||
|
else if(intRes == 0x25) // 0x25 Cellular network registration denied.
|
||||||
|
stat = REG_DENIED;
|
||||||
|
else if(intRes == 0x2A) { // 0x2A Airplane mode.
|
||||||
|
sendAT(GF("AM0")); // Turn off airplane mode
|
||||||
|
waitResponse();
|
||||||
|
writeChanges();
|
||||||
|
stat = REG_UNKNOWN;
|
||||||
|
}
|
||||||
|
else if(intRes == 0x2F) { // 0x2F Bypass mode active.
|
||||||
|
sendAT(GF("AP0")); // Set back to transparent mode
|
||||||
|
waitResponse();
|
||||||
|
writeChanges();
|
||||||
|
stat = REG_UNKNOWN;
|
||||||
|
}
|
||||||
|
else if(intRes == 0xFF) // 0xFF Device is currently scanning for the configured SSID.
|
||||||
|
stat = REG_SEARCHING;
|
||||||
|
else stat = REG_UNKNOWN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
exitCommand();
|
exitCommand();
|
||||||
int intr = strtol(buf, 0, 16);
|
return stat;
|
||||||
if (beeType == S6B) return -93 + intr; // the maximum sensitivity is -93dBm
|
}
|
||||||
else return -1*intr; // need to convert to negative number
|
|
||||||
|
int getSignalQuality() {
|
||||||
|
if (!commandMode()) return 0; // Return immediately
|
||||||
|
if (beeType == XBEE_S6B_WIFI) sendAT(GF("LM")); // ask for the "link margin" - the dB above sensitivity
|
||||||
|
else sendAT(GF("DB")); // ask for the cell strength in dBm
|
||||||
|
String res = readResponse(); // it works better if we read in as a string
|
||||||
|
exitCommand();
|
||||||
|
char buf[3] = {0,}; // Set up buffer for response
|
||||||
|
res.toCharArray(buf, 3);
|
||||||
|
int intRes = strtol(buf, 0, 16);
|
||||||
|
if (beeType == XBEE_S6B_WIFI) return -93 + intRes; // the maximum sensitivity is -93dBm
|
||||||
|
else return -1*intRes; // need to convert to negative number
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNetworkConnected() {
|
bool isNetworkConnected() {
|
||||||
RegStatus s = getRegistrationStatus();
|
RegStatus s = getRegistrationStatus();
|
||||||
return (s == REG_OK_HOME || s == REG_OK_ROAMING);
|
return (s == REG_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool waitForNetwork(unsigned long timeout = 60000L) {
|
bool waitForNetwork(unsigned long timeout = 60000L) {
|
||||||
@@ -385,30 +539,41 @@ public:
|
|||||||
if (isNetworkConnected()) {
|
if (isNetworkConnected()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
delay(250);
|
// delay(250); // Enough delay going in and out of command mode
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getLocalIP() {
|
||||||
|
if (!commandMode()) return ""; // Return immediately
|
||||||
|
sendAT(GF("MY"));
|
||||||
|
String IPaddr; IPaddr.reserve(16);
|
||||||
|
// wait for the response - this response can be very slow
|
||||||
|
IPaddr = readResponse(30000);
|
||||||
|
exitCommand();
|
||||||
|
IPaddr.trim();
|
||||||
|
return IPaddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress localIP() {
|
||||||
|
return TinyGsmIpFromString(getLocalIP());
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* WiFi functions
|
* WiFi functions
|
||||||
*/
|
*/
|
||||||
bool networkConnect(const char* ssid, const char* pwd) {
|
bool networkConnect(const char* ssid, const char* pwd) {
|
||||||
|
|
||||||
commandMode();
|
if (!commandMode()) return false; // return immediately
|
||||||
|
|
||||||
sendAT(GF("EE"), 2); // Set security to WPA2
|
sendAT(GF("EE"), 2); // Set security to WPA2
|
||||||
waitResponse();
|
if (waitResponse() != 1) goto fail;
|
||||||
|
|
||||||
sendAT(GF("ID"), ssid);
|
sendAT(GF("ID"), ssid);
|
||||||
if (waitResponse() != 1) {
|
if (waitResponse() != 1) goto fail;
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
sendAT(GF("PK"), pwd);
|
sendAT(GF("PK"), pwd);
|
||||||
if (waitResponse() != 1) {
|
if (waitResponse() != 1) goto fail;
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
writeChanges();
|
writeChanges();
|
||||||
exitCommand();
|
exitCommand();
|
||||||
@@ -421,29 +586,19 @@ fail:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool networkDisconnect() {
|
bool networkDisconnect() {
|
||||||
return false; // Doesn't support disconnecting
|
if (!commandMode()) return false; // return immediately
|
||||||
}
|
sendAT(GF("NR0")); // Do a network reset in order to disconnect
|
||||||
|
int res = (1 == waitResponse(5000));
|
||||||
String getLocalIP() {
|
writeChanges();
|
||||||
commandMode();
|
exitCommand();
|
||||||
sendAT(GF("MY"));
|
return res;
|
||||||
String IPaddr; IPaddr.reserve(16);
|
|
||||||
// wait for the response
|
|
||||||
unsigned long startMillis = millis();
|
|
||||||
while (stream.available() < 8 && millis() - startMillis < 30000) {};
|
|
||||||
IPaddr = streamReadUntil('\r'); // read result
|
|
||||||
return IPaddr;
|
|
||||||
}
|
|
||||||
|
|
||||||
IPAddress localIP() {
|
|
||||||
return TinyGsmIpFromString(getLocalIP());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GPRS functions
|
* GPRS functions
|
||||||
*/
|
*/
|
||||||
bool gprsConnect(const char* apn, const char* user = NULL, const char* pwd = NULL) {
|
bool gprsConnect(const char* apn, const char* user = NULL, const char* pwd = NULL) {
|
||||||
commandMode();
|
if (!commandMode()) return false; // Return immediately
|
||||||
sendAT(GF("AN"), apn); // Set the APN
|
sendAT(GF("AN"), apn); // Set the APN
|
||||||
waitResponse();
|
waitResponse();
|
||||||
writeChanges();
|
writeChanges();
|
||||||
@@ -451,8 +606,20 @@ fail:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool gprsDisconnect() { // TODO
|
bool gprsDisconnect() {
|
||||||
return false;
|
if (!commandMode()) return false; // return immediately
|
||||||
|
sendAT(GF("AM1")); // Cheating and disconnecting by turning on airplane mode
|
||||||
|
int res = (1 == waitResponse(5000));
|
||||||
|
writeChanges();
|
||||||
|
sendAT(GF("AM0")); // Airplane mode off
|
||||||
|
waitResponse(5000);
|
||||||
|
writeChanges();
|
||||||
|
exitCommand();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isGprsConnected() {
|
||||||
|
return isNetworkConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -462,35 +629,69 @@ fail:
|
|||||||
String sendUSSD(const String& code) TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
String sendUSSD(const String& code) TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
bool sendSMS(const String& number, const String& text) {
|
bool sendSMS(const String& number, const String& text) {
|
||||||
commandMode();
|
if (!commandMode()) return false; // Return immediately
|
||||||
|
|
||||||
sendAT(GF("IP"), 2); // Put in text messaging mode
|
sendAT(GF("IP"), 2); // Put in text messaging mode
|
||||||
waitResponse();
|
if (waitResponse() !=1) goto fail;
|
||||||
sendAT(GF("PH"), number); // Set the phone number
|
sendAT(GF("PH"), number); // Set the phone number
|
||||||
waitResponse();
|
if (waitResponse() !=1) goto fail;
|
||||||
sendAT(GF("TDD")); // Set the text delimiter to the standard 0x0D (carriabe return)
|
sendAT(GF("TDD")); // Set the text delimiter to the standard 0x0D (carriage return)
|
||||||
waitResponse();
|
if (waitResponse() !=1) goto fail;
|
||||||
writeChanges();
|
if (!writeChanges()) goto fail;
|
||||||
|
|
||||||
exitCommand();
|
exitCommand();
|
||||||
stream.print(text);
|
streamWrite(text);
|
||||||
stream.write((char)0x0D); // close off with the carriage return
|
stream.write((char)0x0D); // close off with the carriage return
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
exitCommand();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Location functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
String getGsmLocation() TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Battery functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||||
|
|
||||||
|
int getBattPercent() TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
int modemConnect(const char* host, uint16_t port, uint8_t mux = 0, bool ssl = false) {
|
bool modemConnect(const char* host, uint16_t port, uint8_t mux = 0, bool ssl = false) {
|
||||||
sendAT(GF("LA"), host);
|
|
||||||
String strIP; strIP.reserve(16);
|
String strIP; strIP.reserve(16);
|
||||||
// wait for the response
|
|
||||||
unsigned long startMillis = millis();
|
unsigned long startMillis = millis();
|
||||||
while (stream.available() < 8 && millis() - startMillis < 30000) {};
|
bool gotIP = false;
|
||||||
strIP = streamReadUntil('\r'); // read result
|
// XBee's require a numeric IP address for connection, but do provide the
|
||||||
IPAddress ip = TinyGsmIpFromString(strIP);
|
// functionality to look up the IP address from a fully qualified domain name
|
||||||
return modemConnect(ip, port, mux, ssl);
|
while (!gotIP && millis() - startMillis < 45000L) // the lookup can take a while
|
||||||
|
{
|
||||||
|
sendAT(GF("LA"), host);
|
||||||
|
while (stream.available() < 4) {}; // wait for any response
|
||||||
|
strIP = stream.readStringUntil('\r'); // read result
|
||||||
|
strIP.trim();
|
||||||
|
DBG("<<< ", strIP);
|
||||||
|
if (!strIP.endsWith(GF("ERROR"))) gotIP = true;
|
||||||
|
delay(100); // short wait before trying again
|
||||||
|
}
|
||||||
|
if (gotIP) { // No reason to continue if we don't know the IP address
|
||||||
|
IPAddress ip = TinyGsmIpFromString(strIP);
|
||||||
|
return modemConnect(ip, port, mux, ssl);
|
||||||
|
}
|
||||||
|
else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int modemConnect(IPAddress ip, uint16_t port, uint8_t mux = 0, bool ssl = false) {
|
bool modemConnect(IPAddress ip, uint16_t port, uint8_t mux = 0, bool ssl = false) {
|
||||||
|
bool success = true;
|
||||||
String host; host.reserve(16);
|
String host; host.reserve(16);
|
||||||
host += ip[0];
|
host += ip[0];
|
||||||
host += ".";
|
host += ".";
|
||||||
@@ -500,17 +701,17 @@ private:
|
|||||||
host += ".";
|
host += ".";
|
||||||
host += ip[3];
|
host += ip[3];
|
||||||
if (ssl) {
|
if (ssl) {
|
||||||
sendAT(GF("IP"), 4); // Put in TCP mode
|
sendAT(GF("IP"), 4); // Put in SSL over TCP communication mode
|
||||||
waitResponse();
|
success &= (1 == waitResponse());
|
||||||
} else {
|
} else {
|
||||||
sendAT(GF("IP"), 1); // Put in TCP mode
|
sendAT(GF("IP"), 1); // Put in TCP mode
|
||||||
waitResponse();
|
success &= (1 == waitResponse());
|
||||||
}
|
}
|
||||||
sendAT(GF("DL"), host); // Set the "Destination Address Low"
|
sendAT(GF("DL"), host); // Set the "Destination Address Low"
|
||||||
waitResponse();
|
success &= (1 == waitResponse());
|
||||||
sendAT(GF("DE"), String(port, HEX)); // Set the destination port
|
sendAT(GF("DE"), String(port, HEX)); // Set the destination port
|
||||||
int rsp = waitResponse();
|
success &= (1 == waitResponse());
|
||||||
return rsp;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
int modemSend(const void* buff, size_t len, uint8_t mux = 0) {
|
int modemSend(const void* buff, size_t len, uint8_t mux = 0) {
|
||||||
@@ -520,7 +721,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool modemGetConnected(uint8_t mux = 0) {
|
bool modemGetConnected(uint8_t mux = 0) {
|
||||||
commandMode();
|
if (!commandMode()) return false;
|
||||||
sendAT(GF("AI"));
|
sendAT(GF("AI"));
|
||||||
int res = waitResponse(GF("0"));
|
int res = waitResponse(GF("0"));
|
||||||
exitCommand();
|
exitCommand();
|
||||||
@@ -542,32 +743,33 @@ public:
|
|||||||
streamWrite(tail...);
|
streamWrite(tail...);
|
||||||
}
|
}
|
||||||
|
|
||||||
int streamRead() { return stream.read(); }
|
|
||||||
|
|
||||||
String streamReadUntil(char c) {
|
|
||||||
TINY_GSM_YIELD();
|
|
||||||
String return_string = stream.readStringUntil(c);
|
|
||||||
return_string.trim();
|
|
||||||
// DBG(return_string, c);
|
|
||||||
return return_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
void streamClear(void) {
|
void streamClear(void) {
|
||||||
while (stream.available()) { streamRead(); }
|
TINY_GSM_YIELD();
|
||||||
|
while (stream.available()) { stream.read(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
bool commandMode(void) {
|
bool commandMode(int retries = 2) {
|
||||||
delay(guardTime); // cannot send anything for 1 second before entering command mode
|
int triesMade = 0;
|
||||||
streamWrite(GF("+++")); // enter command mode
|
bool success = false;
|
||||||
// DBG("\r\n+++\r\n");
|
streamClear(); // Empty everything in the buffer before starting
|
||||||
return 1 == waitResponse(guardTime*2);
|
while (!success and triesMade < retries) {
|
||||||
|
// Cannot send anything for 1 "guard time" before entering command mode
|
||||||
|
// Default guard time is 1s, but the init fxn decreases it to 250 ms
|
||||||
|
delay(guardTime);
|
||||||
|
streamWrite(GF("+++")); // enter command mode
|
||||||
|
DBG("\r\n+++");
|
||||||
|
success = (1 == waitResponse(guardTime*2));
|
||||||
|
triesMade ++;
|
||||||
|
}
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeChanges(void) {
|
bool writeChanges(void) {
|
||||||
sendAT(GF("WR")); // Write changes to flash
|
sendAT(GF("WR")); // Write changes to flash
|
||||||
waitResponse();
|
if (1 != waitResponse()) return false;
|
||||||
sendAT(GF("AC")); // Apply changes
|
sendAT(GF("AC")); // Apply changes
|
||||||
waitResponse();
|
if (1 != waitResponse()) return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void exitCommand(void) {
|
void exitCommand(void) {
|
||||||
@@ -575,12 +777,22 @@ public:
|
|||||||
waitResponse();
|
waitResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String readResponse(uint32_t timeout = 1000) {
|
||||||
|
TINY_GSM_YIELD();
|
||||||
|
unsigned long startMillis = millis();
|
||||||
|
while (!stream.available() && millis() - startMillis < timeout) {};
|
||||||
|
String res = stream.readStringUntil('\r'); // lines end with carriage returns
|
||||||
|
res.trim();
|
||||||
|
DBG("<<< ", res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void sendAT(Args... cmd) {
|
void sendAT(Args... cmd) {
|
||||||
streamWrite("AT", cmd..., GSM_NL);
|
streamWrite("AT", cmd..., GSM_NL);
|
||||||
stream.flush();
|
stream.flush();
|
||||||
TINY_GSM_YIELD();
|
TINY_GSM_YIELD();
|
||||||
//DBG("### AT:", cmd...);
|
DBG("### AT:", cmd...);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Optimize this!
|
// TODO: Optimize this!
|
||||||
@@ -588,19 +800,19 @@ public:
|
|||||||
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
|
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
|
||||||
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
|
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
|
||||||
{
|
{
|
||||||
/*String r1s(r1); r1s.trim();
|
String r1s(r1); r1s.trim();
|
||||||
String r2s(r2); r2s.trim();
|
String r2s(r2); r2s.trim();
|
||||||
String r3s(r3); r3s.trim();
|
String r3s(r3); r3s.trim();
|
||||||
String r4s(r4); r4s.trim();
|
String r4s(r4); r4s.trim();
|
||||||
String r5s(r5); r5s.trim();
|
String r5s(r5); r5s.trim();
|
||||||
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
|
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);
|
||||||
data.reserve(64);
|
data.reserve(16); // Should never be getting much here for the XBee
|
||||||
int index = 0;
|
int index = 0;
|
||||||
unsigned long startMillis = millis();
|
unsigned long startMillis = millis();
|
||||||
do {
|
do {
|
||||||
TINY_GSM_YIELD();
|
TINY_GSM_YIELD();
|
||||||
while (stream.available() > 0) {
|
while (stream.available() > 0) {
|
||||||
int a = streamRead();
|
int a = stream.read();
|
||||||
if (a <= 0) continue; // Skip 0x00 bytes, just in case
|
if (a <= 0) continue; // Skip 0x00 bytes, just in case
|
||||||
data += (char)a;
|
data += (char)a;
|
||||||
if (r1 && data.endsWith(r1)) {
|
if (r1 && data.endsWith(r1)) {
|
||||||
@@ -625,7 +837,7 @@ finish:
|
|||||||
if (!index) {
|
if (!index) {
|
||||||
data.trim();
|
data.trim();
|
||||||
data.replace(GSM_NL GSM_NL, GSM_NL);
|
data.replace(GSM_NL GSM_NL, GSM_NL);
|
||||||
data.replace(GSM_NL, "\r\n" " ");
|
data.replace(GSM_NL, "\r\n ");
|
||||||
if (data.length()) {
|
if (data.length()) {
|
||||||
DBG("### Unhandled:", data, "\r\n");
|
DBG("### Unhandled:", data, "\r\n");
|
||||||
} else {
|
} else {
|
||||||
@@ -636,7 +848,7 @@ finish:
|
|||||||
data.replace(GSM_NL GSM_NL, GSM_NL);
|
data.replace(GSM_NL GSM_NL, GSM_NL);
|
||||||
data.replace(GSM_NL, "\r\n ");
|
data.replace(GSM_NL, "\r\n ");
|
||||||
if (data.length()) {
|
if (data.length()) {
|
||||||
// DBG("<<< ", data);
|
DBG("<<< ", data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return index;
|
return index;
|
||||||
|
Reference in New Issue
Block a user