mirror of
https://github.com/KevinMidboe/TinyGSM.git
synced 2026-07-24 02:32:01 +00:00
Merge branch 'master' into master
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+14
-7
@@ -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
-1
@@ -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.
|
||||||
|
|||||||
+6
-1
@@ -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"
|
||||||
|
|||||||
+88
-125
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+143
-82
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+87
-59
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+87
-92
@@ -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
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
+74
-45
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+411
-199
@@ -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