Merge branch 'master' of https://github.com/vshymanskyy/TinyGSM
This commit is contained in:
10
README.md
10
README.md
@@ -35,7 +35,7 @@ TinyGSM also pulls data gently from the modem (whenever possible), so it can ope
|
||||
|
||||
## Features
|
||||
|
||||
Feature \ Modem | SIM8xx | U2 | A6/A7/A20 | M590 | ESP8266 | XBee
|
||||
Feature \ Modem | SIM8xx | u-Blox | A6/A7/A20 | M590 | ESP8266 | XBee
|
||||
--- | --- | --- | --- | --- | --- | ---
|
||||
**Data connections**
|
||||
TCP (HTTP, MQTT, Blynk, ...) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔
|
||||
@@ -45,7 +45,7 @@ SSL/TLS (HTTPS) | ✔¹ | ✔ | 🅧 | 🅧 |
|
||||
Sending USSD requests | ✔ | | ✔ | ✔ | 🅧 |
|
||||
Decoding 7,8,16-bit response | ✔ | | ✔ | ✔ | 🅧 |
|
||||
**SMS**
|
||||
Sending | ✔ | | ✔ | ✔ | 🅧 | ✔
|
||||
Sending | ✔ | ✔ | ✔ | ✔ | 🅧 | ✔
|
||||
Sending Unicode | ✔ | | ◌ | 🅧 | 🅧 |
|
||||
Reading | | | | | 🅧 |
|
||||
Incoming message event | | | | ? | 🅧 |
|
||||
@@ -70,7 +70,7 @@ GPS/GNSS | ✔¹ | 🅧 | ◌¹ | 🅧 |
|
||||
- ESP8266 (AT commands interface, similar to GSM modems)
|
||||
- Digi XBee WiFi and Cellular (using XBee command mode)
|
||||
- Neoway M590
|
||||
- U-blox SARA U2
|
||||
- u-blox Cellular Modems (LEON-G100, LISA-U2xx, SARA-G3xx, SARA-U2xx, TOBY-L2xx, LARA-R2xx, MPCI-L2xx)
|
||||
- Quectel BG96 ***(alpha)***
|
||||
|
||||
### Supported boards/modules
|
||||
@@ -180,11 +180,11 @@ This may result in problems such as:
|
||||
* etc.
|
||||
|
||||
To return module to **Factory Defaults**, use this sketch:
|
||||
File -> Examples -> TynyGSM -> tools -> [FactoryReset](https://github.com/vshymanskyy/TinyGSM/blob/master/tools/FactoryReset/FactoryReset.ino)
|
||||
File -> Examples -> TinyGSM -> tools -> [FactoryReset](https://github.com/vshymanskyy/TinyGSM/blob/master/tools/FactoryReset/FactoryReset.ino)
|
||||
|
||||
### Goouuu Tech IOT-GA6 vs AI-Thinker A6 confusion
|
||||
|
||||
It turns out that **Goouuu Tech IOT-GA6** is not the same as **AI-Thinker A6**. Unfortunately IOT-GA6 is not supported out of the box yet. There are some hints that IOT-GA6 firmware may be updated to match A6... But no one confirmed that up to my knowledge.
|
||||
It turns out that **Goouuu Tech IOT-GA6** is not the same as **AI-Thinker A6**. Unfortunately IOT-GA6 is not supported out of the box yet. There are some hints that IOT-GA6 firmware may be updated to match A6... See [this topic](https://github.com/vshymanskyy/TinyGSM/issues/164).
|
||||
|
||||
__________
|
||||
|
||||
|
@@ -34,9 +34,9 @@
|
||||
#elif defined(TINY_GSM_MODEM_UBLOX)
|
||||
#define TINY_GSM_MODEM_HAS_GPRS
|
||||
#include <TinyGsmClientUBLOX.h>
|
||||
typedef TinyGsmU201 TinyGsm;
|
||||
typedef TinyGsmU201::GsmClient TinyGsmClient;
|
||||
typedef TinyGsmU201::GsmClientSecure TinyGsmClientSecure;
|
||||
typedef TinyGsmUBLOX TinyGsm;
|
||||
typedef TinyGsmUBLOX::GsmClient TinyGsmClient;
|
||||
typedef TinyGsmUBLOX::GsmClientSecure TinyGsmClientSecure;
|
||||
|
||||
#elif defined(TINY_GSM_MODEM_BG96)
|
||||
#define TINY_GSM_MODEM_HAS_GPRS
|
||||
@@ -47,24 +47,29 @@
|
||||
#elif defined(TINY_GSM_MODEM_A6) || defined(TINY_GSM_MODEM_A7)
|
||||
#define TINY_GSM_MODEM_HAS_GPRS
|
||||
#include <TinyGsmClientA6.h>
|
||||
typedef TinyGsm::GsmClient TinyGsmClient;
|
||||
typedef TinyGsmA6 TinyGsm;
|
||||
typedef TinyGsmA6::GsmClient TinyGsmClient;
|
||||
|
||||
#elif defined(TINY_GSM_MODEM_M590)
|
||||
#define TINY_GSM_MODEM_HAS_GPRS
|
||||
#include <TinyGsmClientM590.h>
|
||||
typedef TinyGsm::GsmClient TinyGsmClient;
|
||||
typedef TinyGsmM590 TinyGsm;
|
||||
typedef TinyGsmM590::GsmClient TinyGsmClient;
|
||||
|
||||
#elif defined(TINY_GSM_MODEM_ESP8266)
|
||||
#define TINY_GSM_MODEM_HAS_WIFI
|
||||
#include <TinyGsmClientESP8266.h>
|
||||
typedef TinyGsm::GsmClient TinyGsmClient;
|
||||
typedef TinyGsm::GsmClientSecure TinyGsmClientSecure;
|
||||
typedef TinyGsmESP8266 TinyGsm;
|
||||
typedef TinyGsmESP8266::GsmClient TinyGsmClient;
|
||||
typedef TinyGsmESP8266::GsmClientSecure TinyGsmClientSecure;
|
||||
|
||||
#elif defined(TINY_GSM_MODEM_XBEE)
|
||||
#define TINY_GSM_MODEM_HAS_GPRS
|
||||
#define TINY_GSM_MODEM_HAS_WIFI
|
||||
#include <TinyGsmClientXBee.h>
|
||||
typedef TinyGsm::GsmClient TinyGsmClient;
|
||||
typedef TinyGsmXBee TinyGsm;
|
||||
typedef TinyGsmXBee::GsmClient TinyGsmClient;
|
||||
typedef TinyGsmXBee::GsmClientSecure TinyGsmClientSecure;
|
||||
|
||||
#else
|
||||
#error "Please define GSM modem model"
|
||||
|
@@ -38,25 +38,37 @@ enum RegStatus {
|
||||
REG_UNKNOWN = 4,
|
||||
};
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// Declaration of the TinyGsmA6 Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
class TinyGsm
|
||||
class TinyGsmA6
|
||||
{
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The Internal A6 Client Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
|
||||
public:
|
||||
|
||||
class GsmClient : public Client
|
||||
{
|
||||
friend class TinyGsm;
|
||||
friend class TinyGsmA6;
|
||||
typedef TinyGsmFifo<uint8_t, TINY_GSM_RX_BUFFER> RxFifo;
|
||||
|
||||
public:
|
||||
GsmClient() {}
|
||||
|
||||
GsmClient(TinyGsm& modem) {
|
||||
GsmClient(TinyGsmA6& modem) {
|
||||
init(&modem);
|
||||
}
|
||||
|
||||
bool init(TinyGsm* modem) {
|
||||
bool init(TinyGsmA6* modem) {
|
||||
this->at = modem;
|
||||
this->mux = -1;
|
||||
sock_connected = false;
|
||||
@@ -167,15 +179,33 @@ public:
|
||||
String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
private:
|
||||
TinyGsm* at;
|
||||
TinyGsmA6* at;
|
||||
uint8_t mux;
|
||||
bool sock_connected;
|
||||
RxFifo rx;
|
||||
};
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The A6 does not have a secure client!
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The A6 Modem Functions
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
public:
|
||||
|
||||
TinyGsm(Stream& stream)
|
||||
#ifdef GSM_DEFAULT_STREAM
|
||||
TinyGsmA6(Stream& stream = GSM_DEFAULT_STREAM)
|
||||
#else
|
||||
TinyGsmA6(Stream& stream)
|
||||
#endif
|
||||
: stream(stream)
|
||||
{
|
||||
memset(sockets, 0, sizeof(sockets));
|
||||
@@ -375,6 +405,10 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* WiFi functions
|
||||
*/
|
||||
|
||||
/*
|
||||
* GPRS functions
|
||||
*/
|
||||
@@ -655,9 +689,13 @@ public:
|
||||
streamWrite(tail...);
|
||||
}
|
||||
|
||||
bool streamSkipUntil(char c) { //TODO: timeout
|
||||
while (true) {
|
||||
while (!stream.available()) { TINY_GSM_YIELD(); }
|
||||
bool streamSkipUntil(char c) {
|
||||
const unsigned long timeout = 1000L;
|
||||
unsigned long startMillis = millis();
|
||||
while (millis() - startMillis < timeout) {
|
||||
while (millis() - startMillis < timeout && !stream.available()) {
|
||||
TINY_GSM_YIELD();
|
||||
}
|
||||
if (stream.read() == c)
|
||||
return true;
|
||||
}
|
||||
@@ -742,6 +780,7 @@ finish:
|
||||
}
|
||||
data = "";
|
||||
}
|
||||
//DBG('<', index, '>');
|
||||
return index;
|
||||
}
|
||||
|
||||
|
@@ -16,7 +16,7 @@
|
||||
#define TINY_GSM_RX_BUFFER 64
|
||||
#endif
|
||||
|
||||
#define TINY_GSM_MUX_COUNT 5
|
||||
#define TINY_GSM_MUX_COUNT 12
|
||||
|
||||
#include <TinyGsmCommon.h>
|
||||
|
||||
@@ -39,10 +39,22 @@ enum RegStatus {
|
||||
REG_UNKNOWN = 4,
|
||||
};
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// Declaration of the TinyGsmBG96 Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
class TinyGsmBG96
|
||||
{
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The Internal BG96 Client Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
|
||||
public:
|
||||
|
||||
class GsmClient : public Client
|
||||
@@ -178,6 +190,13 @@ private:
|
||||
RxFifo rx;
|
||||
};
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The BG96 Secure Client
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
|
||||
class GsmClientSecure : public GsmClient
|
||||
{
|
||||
public:
|
||||
@@ -197,9 +216,19 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The BG96 Modem Functions
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
public:
|
||||
|
||||
#ifdef GSM_DEFAULT_STREAM
|
||||
TinyGsmBG96(Stream& stream = GSM_DEFAULT_STREAM)
|
||||
#else
|
||||
TinyGsmBG96(Stream& stream)
|
||||
#endif
|
||||
: stream(stream)
|
||||
{
|
||||
memset(sockets, 0, sizeof(sockets));
|
||||
@@ -409,6 +438,10 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* WiFi functions
|
||||
*/
|
||||
|
||||
/*
|
||||
* GPRS functions
|
||||
*/
|
||||
@@ -665,9 +698,13 @@ public:
|
||||
streamWrite(tail...);
|
||||
}
|
||||
|
||||
bool streamSkipUntil(char c) { //TODO: timeout
|
||||
while (true) {
|
||||
while (!stream.available()) { TINY_GSM_YIELD(); }
|
||||
bool streamSkipUntil(char c) {
|
||||
const unsigned long timeout = 1000L;
|
||||
unsigned long startMillis = millis();
|
||||
while (millis() - startMillis < timeout) {
|
||||
while (millis() - startMillis < timeout && !stream.available()) {
|
||||
TINY_GSM_YIELD();
|
||||
}
|
||||
if (stream.read() == c)
|
||||
return true;
|
||||
}
|
||||
@@ -748,6 +785,7 @@ finish:
|
||||
}
|
||||
data = "";
|
||||
}
|
||||
//DBG('<', index, '>');
|
||||
return index;
|
||||
}
|
||||
|
||||
|
@@ -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 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 Internal Client Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
public:
|
||||
|
||||
class GsmClient : public Client
|
||||
{
|
||||
friend class TinyGsm;
|
||||
friend class TinyGsmESP8266;
|
||||
typedef TinyGsmFifo<uint8_t, TINY_GSM_RX_BUFFER> RxFifo;
|
||||
|
||||
public:
|
||||
GsmClient() {}
|
||||
|
||||
GsmClient(TinyGsm& modem, uint8_t mux = 1) {
|
||||
GsmClient(TinyGsmESP8266& modem, uint8_t mux = 1) {
|
||||
init(&modem, mux);
|
||||
}
|
||||
|
||||
bool init(TinyGsm* modem, uint8_t mux = 1) {
|
||||
bool init(TinyGsmESP8266* modem, uint8_t mux = 1) {
|
||||
this->at = modem;
|
||||
this->mux = mux;
|
||||
sock_connected = false;
|
||||
@@ -149,18 +176,25 @@ public:
|
||||
String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
private:
|
||||
TinyGsm* at;
|
||||
TinyGsmESP8266* at;
|
||||
uint8_t mux;
|
||||
bool sock_connected;
|
||||
RxFifo rx;
|
||||
};
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The Secure ESP8266 Client Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
|
||||
class GsmClientSecure : public GsmClient
|
||||
{
|
||||
public:
|
||||
GsmClientSecure() {}
|
||||
|
||||
GsmClientSecure(TinyGsm& modem, uint8_t mux = 1)
|
||||
GsmClientSecure(TinyGsmESP8266& modem, uint8_t mux = 1)
|
||||
: GsmClient(modem, mux)
|
||||
{}
|
||||
|
||||
@@ -174,9 +208,20 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The ESP8266 Modem Functions
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
public:
|
||||
|
||||
TinyGsm(Stream& stream)
|
||||
#ifdef GSM_DEFAULT_STREAM
|
||||
TinyGsmESP8266(Stream& stream = GSM_DEFAULT_STREAM)
|
||||
#else
|
||||
TinyGsmESP8266(Stream& stream)
|
||||
#endif
|
||||
: stream(stream)
|
||||
{
|
||||
memset(sockets, 0, sizeof(sockets));
|
||||
@@ -197,6 +242,14 @@ public:
|
||||
if (waitResponse() != 1) {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -260,6 +313,23 @@ public:
|
||||
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
|
||||
*/
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic network functions
|
||||
@@ -281,20 +351,8 @@ public:
|
||||
}
|
||||
|
||||
bool isNetworkConnected() {
|
||||
sendAT(GF("+CIPSTATUS"));
|
||||
int res1 = waitResponse(3000, GF("STATUS:"));
|
||||
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;
|
||||
RegStatus s = getRegistrationStatus();
|
||||
return (s == REG_OK_IP || s == REG_OK_TCP);
|
||||
}
|
||||
|
||||
bool waitForNetwork(unsigned long timeout = 60000L) {
|
||||
@@ -303,7 +361,7 @@ public:
|
||||
int res1 = waitResponse(3000, GF("busy p..."), GF("STATUS:"));
|
||||
if (res1 == 2) {
|
||||
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();
|
||||
return true;
|
||||
}
|
||||
@@ -317,17 +375,6 @@ public:
|
||||
* 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;
|
||||
@@ -358,6 +405,28 @@ public:
|
||||
return TinyGsmIpFromString(getLocalIP());
|
||||
}
|
||||
|
||||
/*
|
||||
* 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:
|
||||
|
||||
bool modemConnect(const char* host, uint16_t port, uint8_t mux, bool ssl = false) {
|
||||
@@ -389,21 +458,8 @@ protected:
|
||||
}
|
||||
|
||||
bool modemGetConnected(uint8_t mux) {
|
||||
// TODO: re-check this
|
||||
sendAT(GF("+CIPSTATUS="), mux);
|
||||
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;
|
||||
RegStatus s = getRegistrationStatus();
|
||||
return (s == REG_OK_IP || s == REG_OK_TCP);
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -421,9 +477,13 @@ public:
|
||||
streamWrite(tail...);
|
||||
}
|
||||
|
||||
bool streamSkipUntil(char c) { //TODO: timeout
|
||||
while (true) {
|
||||
while (!stream.available()) { TINY_GSM_YIELD(); }
|
||||
bool streamSkipUntil(char c) {
|
||||
const unsigned long timeout = 1000L;
|
||||
unsigned long startMillis = millis();
|
||||
while (millis() - startMillis < timeout) {
|
||||
while (millis() - startMillis < timeout && !stream.available()) {
|
||||
TINY_GSM_YIELD();
|
||||
}
|
||||
if (stream.read() == c)
|
||||
return true;
|
||||
}
|
||||
@@ -510,6 +570,7 @@ finish:
|
||||
}
|
||||
data = "";
|
||||
}
|
||||
//DBG('<', index, '>');
|
||||
return index;
|
||||
}
|
||||
|
||||
|
@@ -39,24 +39,37 @@ enum RegStatus {
|
||||
};
|
||||
|
||||
|
||||
class TinyGsm
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// Declaration of the TinyGsmM590 Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
class TinyGsmM590
|
||||
{
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The M590 Internal Client Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
|
||||
public:
|
||||
|
||||
class GsmClient : public Client
|
||||
{
|
||||
friend class TinyGsm;
|
||||
friend class TinyGsmM590;
|
||||
typedef TinyGsmFifo<uint8_t, TINY_GSM_RX_BUFFER> RxFifo;
|
||||
|
||||
public:
|
||||
GsmClient() {}
|
||||
|
||||
GsmClient(TinyGsm& modem, uint8_t mux = 1) {
|
||||
GsmClient(TinyGsmM590& modem, uint8_t mux = 1) {
|
||||
init(&modem, mux);
|
||||
}
|
||||
|
||||
bool init(TinyGsm* modem, uint8_t mux = 1) {
|
||||
bool init(TinyGsmM590* modem, uint8_t mux = 1) {
|
||||
this->at = modem;
|
||||
this->mux = mux;
|
||||
sock_connected = false;
|
||||
@@ -164,15 +177,33 @@ public:
|
||||
String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
private:
|
||||
TinyGsm* at;
|
||||
TinyGsmM590* at;
|
||||
uint8_t mux;
|
||||
bool sock_connected;
|
||||
RxFifo rx;
|
||||
};
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The M590 Has no Secure client!
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The M590 Modem Functions
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
public:
|
||||
|
||||
TinyGsm(Stream& stream)
|
||||
#ifdef GSM_DEFAULT_STREAM
|
||||
TinyGsmM590(Stream& stream = GSM_DEFAULT_STREAM)
|
||||
#else
|
||||
TinyGsmM590(Stream& stream)
|
||||
#endif
|
||||
: stream(stream)
|
||||
{
|
||||
memset(sockets, 0, sizeof(sockets));
|
||||
@@ -383,6 +414,10 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* WiFi functions
|
||||
*/
|
||||
|
||||
/*
|
||||
* GPRS functions
|
||||
*/
|
||||
@@ -413,12 +448,12 @@ public:
|
||||
}
|
||||
return false;
|
||||
|
||||
set_dns:
|
||||
sendAT(GF("+DNSSERVER=1,8.8.8.8"));
|
||||
waitResponse();
|
||||
|
||||
sendAT(GF("+DNSSERVER=2,8.8.4.4"));
|
||||
waitResponse();
|
||||
// set_dns: // TODO
|
||||
// sendAT(GF("+DNSSERVER=1,8.8.8.8"));
|
||||
// waitResponse();
|
||||
//
|
||||
// sendAT(GF("+DNSSERVER=2,8.8.4.4"));
|
||||
// waitResponse();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -600,9 +635,13 @@ public:
|
||||
streamWrite(tail...);
|
||||
}
|
||||
|
||||
bool streamSkipUntil(char c) { //TODO: timeout
|
||||
while (true) {
|
||||
while (!stream.available()) { TINY_GSM_YIELD(); }
|
||||
bool streamSkipUntil(char c) {
|
||||
const unsigned long timeout = 1000L;
|
||||
unsigned long startMillis = millis();
|
||||
while (millis() - startMillis < timeout) {
|
||||
while (millis() - startMillis < timeout && !stream.available()) {
|
||||
TINY_GSM_YIELD();
|
||||
}
|
||||
if (stream.read() == c)
|
||||
return true;
|
||||
}
|
||||
@@ -688,6 +727,7 @@ finish:
|
||||
}
|
||||
data = "";
|
||||
}
|
||||
//DBG('<', index, '>');
|
||||
return index;
|
||||
}
|
||||
|
||||
|
@@ -39,15 +39,28 @@ enum RegStatus {
|
||||
REG_UNKNOWN = 4,
|
||||
};
|
||||
|
||||
enum DateTime {
|
||||
enum TinyGSMDateTimeFormat {
|
||||
DATE_FULL = 0,
|
||||
DATE_TIME = 1,
|
||||
DATE_DATE = 2
|
||||
};
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// Declaration of the TinyGsmSim800 Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
class TinyGsmSim800
|
||||
{
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The Sim800 Internal Client Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
|
||||
public:
|
||||
|
||||
class GsmClient : public Client
|
||||
@@ -192,6 +205,13 @@ private:
|
||||
RxFifo rx;
|
||||
};
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The SIM800 Secure Client
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
|
||||
class GsmClientSecure : public GsmClient
|
||||
{
|
||||
public:
|
||||
@@ -211,9 +231,19 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The SIM800 Modem Functions
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
public:
|
||||
|
||||
#ifdef GSM_DEFAULT_STREAM
|
||||
TinyGsmSim800(Stream& stream = GSM_DEFAULT_STREAM)
|
||||
#else
|
||||
TinyGsmSim800(Stream& stream)
|
||||
#endif
|
||||
: stream(stream)
|
||||
{
|
||||
memset(sockets, 0, sizeof(sockets));
|
||||
@@ -462,6 +492,10 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* WiFi functions
|
||||
*/
|
||||
|
||||
/*
|
||||
* GPRS functions
|
||||
*/
|
||||
@@ -740,7 +774,7 @@ public:
|
||||
/*
|
||||
* Time functions
|
||||
*/
|
||||
String getGSMDateTime(DateTime format) {
|
||||
String getGSMDateTime(TinyGSMDateTimeFormat format) {
|
||||
sendAT(GF("+CCLK?"));
|
||||
if (waitResponse(2000L, GF(GSM_NL "+CCLK: \"")) != 1) {
|
||||
return "";
|
||||
@@ -898,9 +932,13 @@ public:
|
||||
streamWrite(tail...);
|
||||
}
|
||||
|
||||
bool streamSkipUntil(char c) { //TODO: timeout
|
||||
while (true) {
|
||||
while (!stream.available()) { TINY_GSM_YIELD(); }
|
||||
bool streamSkipUntil(char c) {
|
||||
const unsigned long timeout = 1000L;
|
||||
unsigned long startMillis = millis();
|
||||
while (millis() - startMillis < timeout) {
|
||||
while (millis() - startMillis < timeout && !stream.available()) {
|
||||
TINY_GSM_YIELD();
|
||||
}
|
||||
if (stream.read() == c)
|
||||
return true;
|
||||
}
|
||||
@@ -981,6 +1019,7 @@ finish:
|
||||
}
|
||||
data = "";
|
||||
}
|
||||
//DBG('<', index, '>');
|
||||
return index;
|
||||
}
|
||||
|
||||
|
@@ -11,6 +11,13 @@
|
||||
|
||||
#include <TinyGsmClientSIM800.h>
|
||||
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// Declaration and Definitio of the TinyGsmSim808 Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
class TinyGsmSim808: public TinyGsmSim800
|
||||
{
|
||||
|
||||
|
@@ -1,13 +1,13 @@
|
||||
/**
|
||||
* @file TinyGsmClientU201.h
|
||||
* @file TinyGsmClientUBLOX.h
|
||||
* @author Volodymyr Shymanskyy
|
||||
* @license LGPL-3.0
|
||||
* @copyright Copyright (c) 2016 Volodymyr Shymanskyy
|
||||
* @date Nov 2016
|
||||
*/
|
||||
|
||||
#ifndef TinyGsmClientU201_h
|
||||
#define TinyGsmClientU201_h
|
||||
#ifndef TinyGsmClientUBLOX_h
|
||||
#define TinyGsmClientUBLOX_h
|
||||
|
||||
//#define TINY_GSM_DEBUG Serial
|
||||
|
||||
@@ -39,31 +39,42 @@ enum RegStatus {
|
||||
REG_UNKNOWN = 4,
|
||||
};
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// Declaration of the TinyGsmUBLOX Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
class TinyGsmU201
|
||||
class TinyGsmUBLOX
|
||||
{
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The UBLOX Internal Client Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
|
||||
public:
|
||||
|
||||
class GsmClient : public Client
|
||||
{
|
||||
friend class TinyGsmU201;
|
||||
friend class TinyGsmUBLOX;
|
||||
typedef TinyGsmFifo<uint8_t, TINY_GSM_RX_BUFFER> RxFifo;
|
||||
|
||||
public:
|
||||
GsmClient() {}
|
||||
|
||||
GsmClient(TinyGsmU201& modem, uint8_t mux = 1) {
|
||||
GsmClient(TinyGsmUBLOX& modem, uint8_t mux = 1) {
|
||||
init(&modem, mux);
|
||||
}
|
||||
|
||||
bool init(TinyGsmU201* modem, uint8_t mux = 1) {
|
||||
bool init(TinyGsmUBLOX* modem, uint8_t mux = 1) {
|
||||
this->at = modem;
|
||||
this->mux = mux;
|
||||
sock_available = 0;
|
||||
sock_connected = false;
|
||||
got_data = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -114,7 +125,7 @@ public:
|
||||
|
||||
virtual int available() {
|
||||
TINY_GSM_YIELD();
|
||||
if (!rx.size()) {
|
||||
if (!rx.size() && sock_connected) {
|
||||
at->maintain();
|
||||
}
|
||||
return rx.size() + sock_available;
|
||||
@@ -169,7 +180,7 @@ public:
|
||||
String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
private:
|
||||
TinyGsmU201* at;
|
||||
TinyGsmUBLOX* at;
|
||||
uint8_t mux;
|
||||
uint16_t sock_available;
|
||||
bool sock_connected;
|
||||
@@ -177,12 +188,19 @@ private:
|
||||
RxFifo rx;
|
||||
};
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The Secure UBLOX Client Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
|
||||
class GsmClientSecure : public GsmClient
|
||||
{
|
||||
public:
|
||||
GsmClientSecure() {}
|
||||
|
||||
GsmClientSecure(TinyGsmU201& modem, uint8_t mux = 1)
|
||||
GsmClientSecure(TinyGsmUBLOX& modem, uint8_t mux = 1)
|
||||
: GsmClient(modem, mux)
|
||||
{}
|
||||
|
||||
@@ -197,12 +215,18 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The UBLOX Modem Functions
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
public:
|
||||
|
||||
#ifdef GSM_DEFAULT_STREAM
|
||||
TinyGsmU201(Stream& stream = GSM_DEFAULT_STREAM)
|
||||
TinyGsmUBLOX(Stream& stream = GSM_DEFAULT_STREAM)
|
||||
#else
|
||||
TinyGsmU201(Stream& stream)
|
||||
TinyGsmUBLOX(Stream& stream)
|
||||
#endif
|
||||
: stream(stream)
|
||||
{
|
||||
@@ -310,6 +334,8 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sleepEnable(bool enable = true) TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
/*
|
||||
* SIM card functions
|
||||
*/
|
||||
@@ -411,6 +437,10 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* WiFi functions
|
||||
*/
|
||||
|
||||
/*
|
||||
* GPRS functions
|
||||
*/
|
||||
@@ -512,7 +542,20 @@ public:
|
||||
|
||||
String sendUSSD(const String& code) TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
bool sendSMS(const String& number, const String& text) TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
bool sendSMS(const String& number, const String& text) {
|
||||
sendAT(GF("+CSCS=\"GSM\"")); // Set GSM default alphabet
|
||||
waitResponse();
|
||||
sendAT(GF("+CMGF=1")); // Set preferred message format to text mode
|
||||
waitResponse();
|
||||
sendAT(GF("+CMGS=\""), number, GF("\"")); // set the phone number
|
||||
if (waitResponse(GF(">")) != 1) {
|
||||
return false;
|
||||
}
|
||||
stream.print(text); // Actually send the message
|
||||
stream.write((char)0x1A);
|
||||
stream.flush();
|
||||
return waitResponse(60000L) == 1;
|
||||
}
|
||||
|
||||
bool sendSMS_UTF16(const String& number, const void* text, size_t len) TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
@@ -654,9 +697,13 @@ public:
|
||||
streamWrite(tail...);
|
||||
}
|
||||
|
||||
bool streamSkipUntil(char c) { //TODO: timeout
|
||||
while (true) {
|
||||
while (!stream.available()) { TINY_GSM_YIELD(); }
|
||||
bool streamSkipUntil(char c) {
|
||||
const unsigned long timeout = 1000L;
|
||||
unsigned long startMillis = millis();
|
||||
while (millis() - startMillis < timeout) {
|
||||
while (millis() - startMillis < timeout && !stream.available()) {
|
||||
TINY_GSM_YIELD();
|
||||
}
|
||||
if (stream.read() == c)
|
||||
return true;
|
||||
}
|
||||
@@ -732,6 +779,7 @@ finish:
|
||||
}
|
||||
data = "";
|
||||
}
|
||||
//DBG('<', index, '>');
|
||||
return index;
|
||||
}
|
||||
|
||||
|
@@ -11,9 +11,6 @@
|
||||
|
||||
//#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
|
||||
|
||||
@@ -29,38 +26,54 @@ enum SimStatus {
|
||||
SIM_LOCKED = 2,
|
||||
};
|
||||
|
||||
enum XBeeType {
|
||||
S6B = 0,
|
||||
LTEC1 = 1,
|
||||
};
|
||||
|
||||
enum RegStatus {
|
||||
REG_UNREGISTERED = 0,
|
||||
REG_OK = 0,
|
||||
REG_UNREGISTERED = 1,
|
||||
REG_SEARCHING = 2,
|
||||
REG_DENIED = 3,
|
||||
REG_OK_HOME = 1,
|
||||
REG_OK_ROAMING = 5,
|
||||
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 Internal Client Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
|
||||
public:
|
||||
|
||||
class GsmClient : public Client
|
||||
{
|
||||
friend class TinyGsm;
|
||||
friend class TinyGsmXBee;
|
||||
|
||||
public:
|
||||
GsmClient() {}
|
||||
|
||||
GsmClient(TinyGsm& modem, uint8_t mux = 0) {
|
||||
GsmClient(TinyGsmXBee& modem, uint8_t mux = 0) {
|
||||
init(&modem, mux);
|
||||
}
|
||||
|
||||
bool init(TinyGsm* modem, uint8_t mux = 0) {
|
||||
bool init(TinyGsmXBee* modem, uint8_t mux = 0) {
|
||||
this->at = modem;
|
||||
this->mux = mux;
|
||||
sock_connected = false;
|
||||
@@ -73,19 +86,25 @@ public:
|
||||
public:
|
||||
virtual int connect(const char *host, uint16_t port) {
|
||||
at->streamClear(); // Empty anything remaining in the buffer;
|
||||
at->commandMode();
|
||||
bool sock_connected = false;
|
||||
if (at->commandMode()) { // Don't try if we didn't successfully get into command mode
|
||||
sock_connected = at->modemConnect(host, port, mux, false);
|
||||
at->writeChanges();
|
||||
at->exitCommand();
|
||||
}
|
||||
at->streamClear(); // Empty anything remaining in the buffer;
|
||||
return sock_connected;
|
||||
}
|
||||
|
||||
virtual int connect(IPAddress ip, uint16_t port) {
|
||||
at->streamClear(); // Empty anything remaining in the buffer;
|
||||
at->commandMode();
|
||||
bool sock_connected = false;
|
||||
if (at->commandMode()) { // Don't try if we didn't successfully get into command mode
|
||||
sock_connected = at->modemConnect(ip, port, mux, false);
|
||||
at->writeChanges();
|
||||
at->exitCommand();
|
||||
}
|
||||
at->streamClear(); // Empty anything remaining in the buffer;
|
||||
return sock_connected;
|
||||
}
|
||||
|
||||
@@ -110,7 +129,6 @@ public:
|
||||
|
||||
virtual size_t write(const uint8_t *buf, size_t size) {
|
||||
TINY_GSM_YIELD();
|
||||
//at->maintain();
|
||||
return at->modemSend(buf, size, mux);
|
||||
}
|
||||
|
||||
@@ -130,7 +148,7 @@ public:
|
||||
|
||||
virtual int read(uint8_t *buf, size_t size) {
|
||||
TINY_GSM_YIELD();
|
||||
return at->stream.readBytes(buf, size);
|
||||
return at->stream.readBytes((char*)buf, size);
|
||||
}
|
||||
|
||||
virtual int read() {
|
||||
@@ -156,47 +174,69 @@ public:
|
||||
String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
private:
|
||||
TinyGsm* at;
|
||||
TinyGsmXBee* at;
|
||||
uint8_t mux;
|
||||
bool sock_connected;
|
||||
};
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The Secure XBee Client Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
|
||||
class GsmClientSecure : public GsmClient
|
||||
{
|
||||
public:
|
||||
GsmClientSecure() {}
|
||||
|
||||
GsmClientSecure(TinyGsm& modem, uint8_t mux = 1)
|
||||
GsmClientSecure(TinyGsmXBee& modem, uint8_t mux = 1)
|
||||
: GsmClient(modem, mux)
|
||||
{}
|
||||
|
||||
public:
|
||||
virtual int connect(const char *host, uint16_t port) {
|
||||
at->streamClear(); // Empty anything remaining in the buffer;
|
||||
at->commandMode();
|
||||
bool sock_connected = false;
|
||||
if (at->commandMode()) { // Don't try if we didn't successfully get into command mode
|
||||
sock_connected = at->modemConnect(host, port, mux, true);
|
||||
at->writeChanges();
|
||||
at->exitCommand();
|
||||
}
|
||||
at->streamClear(); // Empty anything remaining in the buffer;
|
||||
return sock_connected;
|
||||
}
|
||||
|
||||
virtual int connect(IPAddress ip, uint16_t port) {
|
||||
at->streamClear(); // Empty anything remaining in the buffer;
|
||||
at->commandMode();
|
||||
bool sock_connected = false;
|
||||
if (at->commandMode()) { // Don't try if we didn't successfully get into command mode
|
||||
sock_connected = at->modemConnect(ip, port, mux, true);
|
||||
at->writeChanges();
|
||||
at->exitCommand();
|
||||
}
|
||||
at->streamClear(); // Empty anything remaining in the buffer;
|
||||
return sock_connected;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The XBee Modem Functions
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
public:
|
||||
|
||||
TinyGsm(Stream& stream)
|
||||
#ifdef GSM_DEFAULT_STREAM
|
||||
TinyGsmXBee(Stream& stream = GSM_DEFAULT_STREAM)
|
||||
#else
|
||||
TinyGsmXBee(Stream& stream)
|
||||
#endif
|
||||
: stream(stream)
|
||||
{
|
||||
memset(sockets, 0, sizeof(sockets));
|
||||
}
|
||||
{}
|
||||
|
||||
/*
|
||||
* Basic functions
|
||||
@@ -206,23 +246,53 @@ public:
|
||||
}
|
||||
|
||||
bool init() {
|
||||
guardTime = 1100;
|
||||
commandMode();
|
||||
guardTime = 1100; // Start with a default guard time of 1 second
|
||||
|
||||
if (!commandMode(10)) return false; // Try up to 10 times for the init
|
||||
|
||||
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
|
||||
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();
|
||||
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();
|
||||
if (res == "601") beeType = S6B;
|
||||
else beeType = LTEC1;
|
||||
guardTime = 125;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool testAT(unsigned long timeout = 10000L) {
|
||||
@@ -243,52 +313,100 @@ public:
|
||||
void maintain() {}
|
||||
|
||||
bool factoryDefault() {
|
||||
commandMode();
|
||||
if (!commandMode()) return false; // Return immediately
|
||||
sendAT(GF("RE"));
|
||||
bool ret_val = waitResponse() == 1;
|
||||
writeChanges();
|
||||
ret_val &= writeChanges();
|
||||
exitCommand();
|
||||
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() {
|
||||
if (beeType == S6B) return false;
|
||||
if (beeType == XBEE_S6B_WIFI) return false;
|
||||
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
|
||||
*/
|
||||
|
||||
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"));
|
||||
if (waitResponse() != 1) {
|
||||
if (waitResponse() != 1) goto fail;
|
||||
|
||||
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; ) {
|
||||
if (commandMode(1)) {
|
||||
sendAT(GF("AM0")); // Turn off airplane mode
|
||||
writeChanges();
|
||||
exitCommand();
|
||||
delay(250); // wait a litle before trying again
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
|
||||
fail:
|
||||
exitCommand();
|
||||
return false;
|
||||
}
|
||||
delay (2000); // Actually resets about 2 seconds later
|
||||
for (unsigned long start = millis(); millis() - start < 60000L; ) {
|
||||
if (commandMode()) {
|
||||
exitCommand();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
exitCommand();
|
||||
return false;;
|
||||
}
|
||||
|
||||
void setupPinSleep() {
|
||||
commandMode();
|
||||
sendAT(GF("SM"),1);
|
||||
void setupPinSleep(bool maintainAssociation = false) {
|
||||
if (!commandMode()) return; // Return immediately
|
||||
sendAT(GF("SM"),1); // Pin sleep
|
||||
waitResponse();
|
||||
if (beeType == S6B) {
|
||||
sendAT(GF("SO"),200);
|
||||
if (beeType == XBEE_S6B_WIFI && !maintainAssociation) {
|
||||
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();
|
||||
}
|
||||
writeChanges();
|
||||
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
|
||||
*/
|
||||
@@ -298,23 +416,17 @@ public:
|
||||
}
|
||||
|
||||
String getSimCCID() {
|
||||
commandMode();
|
||||
if (!commandMode()) return ""; // Return immediately
|
||||
sendAT(GF("S#"));
|
||||
// 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
|
||||
String res = readResponse();
|
||||
exitCommand();
|
||||
return res;
|
||||
}
|
||||
|
||||
String getIMEI() {
|
||||
commandMode();
|
||||
if (!commandMode()) return ""; // Return immediately
|
||||
sendAT(GF("IM"));
|
||||
// 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
|
||||
String res = readResponse();
|
||||
exitCommand();
|
||||
return res;
|
||||
}
|
||||
@@ -324,37 +436,82 @@ public:
|
||||
}
|
||||
|
||||
RegStatus getRegistrationStatus() {
|
||||
commandMode();
|
||||
if (!commandMode()) return REG_UNKNOWN; // Return immediately
|
||||
|
||||
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
|
||||
String res = readResponse();
|
||||
char buf[3] = {0,}; // Set up buffer for response
|
||||
res.toCharArray(buf, 3);
|
||||
int intRes = strtol(buf, 0, 16);
|
||||
RegStatus stat = REG_UNKNOWN;
|
||||
|
||||
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();
|
||||
|
||||
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;
|
||||
return stat;
|
||||
}
|
||||
|
||||
String getOperator() {
|
||||
commandMode();
|
||||
if (!commandMode()) return ""; // Return immediately
|
||||
sendAT(GF("MN"));
|
||||
// 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
|
||||
String res = readResponse();
|
||||
exitCommand();
|
||||
return res;
|
||||
}
|
||||
@@ -364,25 +521,21 @@ public:
|
||||
*/
|
||||
|
||||
int getSignalQuality() {
|
||||
commandMode();
|
||||
if (beeType == S6B) sendAT(GF("LM")); // ask for the "link margin" - the dB above sensitivity
|
||||
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
|
||||
// wait for the response
|
||||
unsigned long startMillis = millis();
|
||||
while (!stream.available() && millis() - startMillis < 1000) {};
|
||||
char buf[2] = {0}; // Set up buffer for response
|
||||
buf[0] = streamRead();
|
||||
buf[1] = streamRead();
|
||||
// DBG(buf[0], buf[1], "\n");
|
||||
String res = readResponse(); // it works better if we read in as a string
|
||||
exitCommand();
|
||||
int intr = strtol(buf, 0, 16);
|
||||
if (beeType == S6B) return -93 + intr; // the maximum sensitivity is -93dBm
|
||||
else return -1*intr; // need to convert to negative number
|
||||
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() {
|
||||
RegStatus s = getRegistrationStatus();
|
||||
return (s == REG_OK_HOME || s == REG_OK_ROAMING);
|
||||
return (s == REG_OK);
|
||||
}
|
||||
|
||||
bool waitForNetwork(unsigned long timeout = 60000L) {
|
||||
@@ -390,7 +543,7 @@ public:
|
||||
if (isNetworkConnected()) {
|
||||
return true;
|
||||
}
|
||||
delay(250);
|
||||
// delay(250); // Enough delay going in and out of command mode
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -400,20 +553,16 @@ public:
|
||||
*/
|
||||
bool networkConnect(const char* ssid, const char* pwd) {
|
||||
|
||||
commandMode();
|
||||
if (!commandMode()) return false; // return immediately
|
||||
|
||||
sendAT(GF("EE"), 2); // Set security to WPA2
|
||||
waitResponse();
|
||||
if (waitResponse() != 1) goto fail;
|
||||
|
||||
sendAT(GF("ID"), ssid);
|
||||
if (waitResponse() != 1) {
|
||||
goto fail;
|
||||
}
|
||||
if (waitResponse() != 1) goto fail;
|
||||
|
||||
sendAT(GF("PK"), pwd);
|
||||
if (waitResponse() != 1) {
|
||||
goto fail;
|
||||
}
|
||||
if (waitResponse() != 1) goto fail;
|
||||
|
||||
writeChanges();
|
||||
exitCommand();
|
||||
@@ -426,17 +575,22 @@ fail:
|
||||
}
|
||||
|
||||
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));
|
||||
writeChanges();
|
||||
exitCommand();
|
||||
return res;
|
||||
}
|
||||
|
||||
String getLocalIP() {
|
||||
commandMode();
|
||||
if (!commandMode()) return ""; // Return immediately
|
||||
sendAT(GF("MY"));
|
||||
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
|
||||
// wait for the response - this response can be very slow
|
||||
IPaddr = readResponse(30000);
|
||||
exitCommand();
|
||||
IPaddr.trim();
|
||||
return IPaddr;
|
||||
}
|
||||
|
||||
@@ -448,7 +602,7 @@ fail:
|
||||
* GPRS functions
|
||||
*/
|
||||
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
|
||||
waitResponse();
|
||||
writeChanges();
|
||||
@@ -456,8 +610,20 @@ fail:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool gprsDisconnect() { // TODO
|
||||
return false;
|
||||
bool gprsDisconnect() {
|
||||
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();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -467,35 +633,67 @@ fail:
|
||||
String sendUSSD(const String& code) TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
bool sendSMS(const String& number, const String& text) {
|
||||
commandMode();
|
||||
if (!commandMode()) return false; // Return immediately
|
||||
|
||||
sendAT(GF("IP"), 2); // Put in text messaging mode
|
||||
waitResponse();
|
||||
if (waitResponse() !=1) goto fail;
|
||||
sendAT(GF("PH"), number); // Set the phone number
|
||||
waitResponse();
|
||||
sendAT(GF("TDD")); // Set the text delimiter to the standard 0x0D (carriabe return)
|
||||
waitResponse();
|
||||
writeChanges();
|
||||
if (waitResponse() !=1) goto fail;
|
||||
sendAT(GF("TDD")); // Set the text delimiter to the standard 0x0D (carriage return)
|
||||
if (waitResponse() !=1) goto fail;
|
||||
if (!writeChanges()) goto fail;
|
||||
|
||||
exitCommand();
|
||||
stream.print(text);
|
||||
streamWrite(text);
|
||||
stream.write((char)0x0D); // close off with the carriage return
|
||||
return true;
|
||||
|
||||
fail:
|
||||
exitCommand();
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Location functions
|
||||
*/
|
||||
|
||||
private:
|
||||
String getGsmLocation() TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||
|
||||
int modemConnect(const char* host, uint16_t port, uint8_t mux = 0, bool ssl = false) {
|
||||
sendAT(GF("LA"), host);
|
||||
/*
|
||||
* Battery functions
|
||||
*/
|
||||
|
||||
uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||
|
||||
int getBattPercent() TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||
|
||||
protected:
|
||||
|
||||
bool modemConnect(const char* host, uint16_t port, uint8_t mux = 0, bool ssl = false) {
|
||||
String strIP; strIP.reserve(16);
|
||||
// wait for the response
|
||||
unsigned long startMillis = millis();
|
||||
while (stream.available() < 8 && millis() - startMillis < 30000) {};
|
||||
strIP = streamReadUntil('\r'); // read result
|
||||
bool gotIP = false;
|
||||
// XBee's require a numeric IP address for connection, but do provide the
|
||||
// functionality to look up the IP address from a fully qualified domain name
|
||||
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);
|
||||
host += ip[0];
|
||||
host += ".";
|
||||
@@ -505,17 +703,17 @@ private:
|
||||
host += ".";
|
||||
host += ip[3];
|
||||
if (ssl) {
|
||||
sendAT(GF("IP"), 4); // Put in TCP mode
|
||||
waitResponse();
|
||||
sendAT(GF("IP"), 4); // Put in SSL over TCP communication mode
|
||||
success &= (1 == waitResponse());
|
||||
} else {
|
||||
sendAT(GF("IP"), 1); // Put in TCP mode
|
||||
waitResponse();
|
||||
success &= (1 == waitResponse());
|
||||
}
|
||||
sendAT(GF("DL"), host); // Set the "Destination Address Low"
|
||||
waitResponse();
|
||||
success &= (1 == waitResponse());
|
||||
sendAT(GF("DE"), String(port, HEX)); // Set the destination port
|
||||
int rsp = waitResponse();
|
||||
return rsp;
|
||||
success &= (1 == waitResponse());
|
||||
return success;
|
||||
}
|
||||
|
||||
int modemSend(const void* buff, size_t len, uint8_t mux = 0) {
|
||||
@@ -525,7 +723,7 @@ private:
|
||||
}
|
||||
|
||||
bool modemGetConnected(uint8_t mux = 0) {
|
||||
commandMode();
|
||||
if (!commandMode()) return false;
|
||||
sendAT(GF("AI"));
|
||||
int res = waitResponse(GF("0"));
|
||||
exitCommand();
|
||||
@@ -547,32 +745,33 @@ public:
|
||||
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) {
|
||||
while (stream.available()) { streamRead(); }
|
||||
TINY_GSM_YIELD();
|
||||
while (stream.available()) { stream.read(); }
|
||||
}
|
||||
|
||||
bool commandMode(void) {
|
||||
delay(guardTime); // cannot send anything for 1 second before entering command mode
|
||||
bool commandMode(int retries = 2) {
|
||||
int triesMade = 0;
|
||||
bool success = false;
|
||||
streamClear(); // Empty everything in the buffer before starting
|
||||
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+++\r\n");
|
||||
return 1 == waitResponse(guardTime*2);
|
||||
DBG("+++");
|
||||
success = (1 == waitResponse(guardTime*2));
|
||||
triesMade ++;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void writeChanges(void) {
|
||||
bool writeChanges(void) {
|
||||
sendAT(GF("WR")); // Write changes to flash
|
||||
waitResponse();
|
||||
if (1 != waitResponse()) return false;
|
||||
sendAT(GF("AC")); // Apply changes
|
||||
waitResponse();
|
||||
if (1 != waitResponse()) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void exitCommand(void) {
|
||||
@@ -580,6 +779,16 @@ public:
|
||||
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>
|
||||
void sendAT(Args... cmd) {
|
||||
streamWrite("AT", cmd..., GSM_NL);
|
||||
@@ -599,13 +808,13 @@ public:
|
||||
String r4s(r4); r4s.trim();
|
||||
String r5s(r5); r5s.trim();
|
||||
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
|
||||
data.reserve(64);
|
||||
data.reserve(16); // Should never be getting much here for the XBee
|
||||
int index = 0;
|
||||
unsigned long startMillis = millis();
|
||||
do {
|
||||
TINY_GSM_YIELD();
|
||||
while (stream.available() > 0) {
|
||||
int a = streamRead();
|
||||
int a = stream.read();
|
||||
if (a <= 0) continue; // Skip 0x00 bytes, just in case
|
||||
data += (char)a;
|
||||
if (r1 && data.endsWith(r1)) {
|
||||
@@ -630,7 +839,7 @@ finish:
|
||||
if (!index) {
|
||||
data.trim();
|
||||
data.replace(GSM_NL GSM_NL, GSM_NL);
|
||||
data.replace(GSM_NL, "\r\n" " ");
|
||||
data.replace(GSM_NL, "\r\n ");
|
||||
if (data.length()) {
|
||||
DBG("### Unhandled:", data, "\r\n");
|
||||
} else {
|
||||
|
Reference in New Issue
Block a user