Browse Source

Merge pull request #84 from EnviroDIY/master

Re-creation of XBee pull request
v_master
Volodymyr Shymanskyy 7 years ago
committed by GitHub
parent
commit
8372f26135
24 changed files with 890 additions and 71 deletions
  1. +6
    -0
      .gitignore
  2. +14
    -2
      .travis.yml
  3. +21
    -20
      README.md
  4. +5
    -1
      TinyGsmClient.h
  5. +30
    -4
      TinyGsmClientA6.h
  6. +84
    -6
      TinyGsmClientESP8266.h
  7. +30
    -4
      TinyGsmClientM590.h
  8. +28
    -6
      TinyGsmClientSIM800.h
  9. +633
    -0
      TinyGsmClientXBee.h
  10. +1
    -0
      TinyGsmCommon.h
  11. BIN
      doc/Digi XBee LTEC1 Users Guide - 90001525.pdf
  12. BIN
      doc/Digi XBee S6B Users Guide - 90002180.pdf
  13. BIN
      doc/ESP8266 - AT Instruction Set.pdf
  14. BIN
      doc/ESP8266 - Datasheet v4.3.pdf
  15. BIN
      doc/ESP8266 - Low Power Solutions.pdf
  16. BIN
      doc/SIM800 AT Commands v1.11.pdf
  17. +1
    -1
      examples/BlynkClient/BlynkClient.ino
  18. +1
    -1
      examples/FileDownload/FileDownload.ino
  19. +1
    -1
      examples/MqttClient/MqttClient.ino
  20. +0
    -1
      examples/WebClient/WebClient.ino
  21. +4
    -1
      tools/AT_Debug/AT_Debug.ino
  22. +2
    -1
      tools/Diagnostics/Diagnostics.ino
  23. +2
    -0
      tools/FactoryReset/FactoryReset.ino
  24. +27
    -22
      tools/test_build/test_build.ino

+ 6
- 0
.gitignore View File

@ -21,3 +21,9 @@
# Extras
extras/docs/*
.pioenvs
.piolibdeps
.clang_complete
.gcc-flags.json
platformio.ini
lib/readme.txt

+ 14
- 2
.travis.yml View File

@ -18,16 +18,26 @@ env:
- PLATFORMIO_CI_SRC=tools/FactoryReset
# Arduino test
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=esp01 --board=nodemcuv2 --board=esp32dev --board=uno_pic32"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SIM800' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev --board=mayfly"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_A6' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev --board=mayfly"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_M590' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev --board=mayfly"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_ESP8266' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev --board=mayfly"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_XBEE' --project-option='framework=arduino' --board=uno --board=leonardo --board=yun --board=megaatmega2560 --board=genuino101 --board=mkr1000USB --board=zero --board=teensy31 --board=bluepill_f103c8 --board=uno_pic32 --board=esp01 --board=nodemcuv2 --board=esp32dev --board=mayfly"
# Energia test
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='framework=energia' --board=lplm4f120h5qr"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_SIM800' --project-option='framework=energia' --board=lplm4f120h5qr"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_A6' --project-option='framework=energia' --board=lplm4f120h5qr"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_M590' --project-option='framework=energia' --board=lplm4f120h5qr"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_ESP8266' --project-option='framework=energia' --board=lplm4f120h5qr"
- PLATFORMIO_CI_SRC=tools/test_build PLATFORMIO_CI_ARGS="--project-option='build_flags=-D TINY_GSM_MODEM_XBEE' --project-option='framework=energia' --board=lplm4f120h5qr"
install:
# ChipKIT issue: install 32-bit support for GCC PIC32
- sudo apt-get install libc6-i386
- pip install -U https://github.com/platformio/platformio/archive/develop.zip
- platformio upgrade
- platformio update
#
# Libraries from PlatformIO Library Registry:
@ -38,5 +48,7 @@ install:
# http://platformio.org/lib/show/1286/StreamDebugger
- platformio lib -g install 89 415 1202 1286
- platformio lib -g update
- platformio lib update
script: make travis-build

+ 21
- 20
README.md View File

@ -10,8 +10,8 @@ A small Arduino library for GSM modules, that just works.
[![GitHub stars](https://img.shields.io/github/stars/vshymanskyy/TinyGSM.svg)](https://github.com/vshymanskyy/TinyGSM/stargazers)
[![License](https://img.shields.io/badge/license-LGPL3-blue.svg)](https://github.com/vshymanskyy/TinyGSM/blob/master/LICENSE)
If you like **TinyGSM** - give it a star, or fork it and contribute!
[![GitHub stars](https://img.shields.io/github/stars/vshymanskyy/TinyGSM.svg?style=social&label=Star)](https://github.com/vshymanskyy/TinyGSM/stargazers)
If you like **TinyGSM** - give it a star, or fork it and contribute!
[![GitHub stars](https://img.shields.io/github/stars/vshymanskyy/TinyGSM.svg?style=social&label=Star)](https://github.com/vshymanskyy/TinyGSM/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/vshymanskyy/TinyGSM.svg?style=social&label=Fork)](https://github.com/vshymanskyy/TinyGSM/network)
You can also join our chat:
@ -35,29 +35,29 @@ TinyGSM also pulls data gently from the modem (whenever possible), so it can ope
## Features
Feature \ Modem | SIM800 | SIM8x8 | A6/A7/A20 | M590 | ESP8266
--- | --- | --- | --- | --- | ---
Feature \ Modem | SIM800 | SIM8x8 | A6/A7/A20 | M590 | ESP8266 | XBee
--- | --- | --- | --- | --- | --- |
**Data connections**
TCP (HTTP, MQTT, Blynk, ...) | ✔ | ✔ | ✔ | ✔ | ✔
UDP | | | | |
SSL/TLS (HTTPS) | ✔¹ | ✔¹ | 🅧 | 🅧 | ◌
TCP (HTTP, MQTT, Blynk, ...) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔
UDP | | | | | | ◌
SSL/TLS (HTTPS) | ✔¹ | ✔¹ | 🅧 | 🅧 | ◌ |
**USSD**
Sending USSD requests | ✔ | ✔ | ✔ | ✔ |
Decoding 7,8,16-bit response | ✔ | ✔ | ✔ | ✔ |
Sending USSD requests | ✔ | ✔ | ✔ | ✔ | |
Decoding 7,8,16-bit response | ✔ | ✔ | ✔ | ✔ | |
**SMS**
Sending | ✔ | ✔ | ✔ | ✔ |
Sending Unicode | ✔ | ✔ | ◌ | 🅧 |
Reading | | | | |
Incoming message event | | | | ? |
Sending | ✔ | ✔ | ✔ | ✔ | | ✔
Sending Unicode | ✔ | ✔ | ◌ | 🅧 | |
Reading | | | | | |
Incoming message event | | | | ? | |
**Calls**
Dial, hangup | ✔ | ✔ | ✔ | 🅧 |
Receiving calls | ✔ | ✔ | ✔ | 🅧 |
Incoming event (RING) | ◌ | ◌ | ◌ | 🅧 |
DTMF sending | ◌ | ◌ | ◌ | 🅧 |
DTMF decoding | ◌ | ◌ | 🅧 | 🅧 |
Dial, hangup | ✔ | ✔ | ✔ | 🅧 | | 🅧
Receiving calls | ✔ | ✔ | ✔ | 🅧 | | 🅧
Incoming event (RING) | ◌ | ◌ | ◌ | 🅧 | | 🅧
DTMF sending | ◌ | ◌ | ◌ | 🅧 | | 🅧
DTMF decoding | ◌ | ◌ | 🅧 | 🅧 | | 🅧
**Location**
GSM location service | ✔ | ✔ | 🅧 | 🅧 |
GPS/GNSS | 🅧 | ✔² | ◌¹ | 🅧 |
GSM location service | ✔ | ✔ | 🅧 | 🅧 | | 🅧
GPS/GNSS | 🅧 | ✔² | ◌¹ | 🅧 | | 🅧
✔ - implemented  ◌ - planned  🅧 - not available for this modem
¹ - only some device models or firmware revisions have this feature
@ -70,6 +70,7 @@ GPS/GNSS | 🅧 | ✔² | ◌¹ | 🅧 |
- [x] AI-Thinker A6, A6C, A7
- [x] Neoway M590
- [x] ESP8266 (AT commands interface, similar to GSM modems)
- [x] Digi XBee WiFi and Cellular (using XBee command mode)
### Supported modules
- [x] GPRSbee


+ 5
- 1
TinyGsmClient.h View File

@ -9,7 +9,7 @@
#ifndef TinyGsmClient_h
#define TinyGsmClient_h
#if defined(TINY_GSM_MODEM_SIM800) || defined(TINY_GSM_MODEM_SIM900)
#if defined(TINY_GSM_MODEM_SIM800) || defined(TINY_GSM_MODEM_SIM900)
#include <TinyGsmClientSIM800.h>
typedef TinyGsmSim800 TinyGsm;
typedef TinyGsmSim800::GsmClient TinyGsmClient;
@ -33,6 +33,10 @@
#include <TinyGsmClientESP8266.h>
typedef TinyGsm::GsmClient TinyGsmClient;
#elif defined(TINY_GSM_MODEM_XBEE)
#include <TinyGsmClientXBee.h>
typedef TinyGsm::GsmClient TinyGsmClient;
#else
#error "Please define GSM modem model"
#endif


+ 30
- 4
TinyGsmClientA6.h View File

@ -348,6 +348,17 @@ public:
return false;
}
/*
* WiFi functions
*/
bool networkConnect(const char* ssid, const char* pwd) {
return false;
}
bool networkDisconnect() {
return false;
}
/*
* GPRS functions
*/
@ -397,8 +408,19 @@ public:
}
IPAddress localIP() {
IPAddress res;
res.fromString(getLocalIP());
String strIP = getLocalIP();
int Parts[4] = {0,0,0,0};
int Part = 0;
for (uint8_t i=0; i<strIP.length(); i++) {
char c = strIP[i];
if (c == '.') {
Part++;
continue;
}
Parts[Part] *= 10;
Parts[Part] += c - '0';
}
IPAddress res(Parts[0], Parts[1], Parts[2], Parts[3]);
return res;
}
@ -623,7 +645,7 @@ public:
streamWrite("AT", cmd..., GSM_NL);
stream.flush();
TINY_GSM_YIELD();
//DBG("### AT:", cmd...);
// DBG("### AT:", cmd...);
}
// TODO: Optimize this!
@ -664,6 +686,7 @@ public:
} else if (data.endsWith(GF("+CIPRCV:"))) {
int mux = stream.readStringUntil(',').toInt();
int len = stream.readStringUntil(',').toInt();
int len_orig = len;
if (len > sockets[mux]->rx.free()) {
DBG("### Buffer overflow: ", len, "->", sockets[mux]->rx.free());
} else {
@ -673,6 +696,9 @@ public:
while (!stream.available()) { TINY_GSM_YIELD(); }
sockets[mux]->rx.put(stream.read());
}
if (len_orig > sockets[mux]->available()) {
DBG(GSM_NL, "### Fewer characters received than expected: ", sockets[mux]->available(), " vs ", len_orig);
}
data = "";
} else if (data.endsWith(GF("+TCPCLOSED:"))) {
int mux = stream.readStringUntil('\n').toInt();
@ -684,7 +710,7 @@ public:
}
}
} while (millis() - startMillis < timeout);
finish:
finish:
if (!index) {
data.trim();
if (data.length()) {


+ 84
- 6
TinyGsmClientESP8266.h View File

@ -212,8 +212,46 @@ public:
return autoBaud();
}
/*
* SIM card functions
*/
/*
* Generic network functions
*/
int getSignalQuality() {
sendAT(GF("+CWJAP_CUR?"));
int res1 = waitResponse(GF("No AP"), GF("+CWJAP_CUR:"));
if (res1 != 2) {
waitResponse();
return 0;
}
streamSkipUntil(','); // Skip SSID
streamSkipUntil(','); // Skip BSSID/MAC address
streamSkipUntil(','); // Skip Chanel number
int res2 = stream.parseInt(); // Read RSSI
DBG(res2);
waitResponse();
return res2;
}
bool waitForNetwork(unsigned long timeout = 60000L) {
return true;
for (unsigned long start = millis(); millis() - start < timeout; ) {
sendAT(GF("+CIPSTATUS"));
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) return true;
}
// <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
delay(1000);
}
return false;
}
/*
@ -244,9 +282,45 @@ public:
return waitResponse(10000L) == 1;
}
String getLocalIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
String getLocalIP() {
sendAT(GF("+CIPSTA_CUR??"));
int res1 = waitResponse(GF("ERROR"), GF("+CWJAP_CUR:"));
if (res1 != 2) {
return "";
}
String res2 = stream.readStringUntil('"');
DBG(res2);
waitResponse();
return res2;
}
IPAddress localIP() {
String strIP = getLocalIP();
int Parts[4] = {0,0,0,0};
int Part = 0;
for (uint8_t i=0; i<strIP.length(); i++) {
char c = strIP[i];
if (c == '.') {
Part++;
continue;
}
Parts[Part] *= 10;
Parts[Part] += c - '0';
}
IPAddress res(Parts[0], Parts[1], Parts[2], Parts[3]);
return res;
}
/*
* GPRS functions
*/
bool gprsConnect(const char* apn, const char* user, const char* pwd) {
return false;
}
IPAddress localIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
bool gprsDisconnect() {
return false;
}
private:
@ -256,6 +330,7 @@ private:
GFP(GSM_OK),
GFP(GSM_ERROR),
GF(GSM_NL "ALREADY CONNECT" GSM_NL));
waitResponse(100, GF("1,CONNECT"));
return (1 == rsp);
}
@ -308,7 +383,7 @@ public:
streamWrite("AT", cmd..., GSM_NL);
stream.flush();
TINY_GSM_YIELD();
//DBG("### AT:", cmd...);
// DBG("### AT:", cmd...);
}
// TODO: Optimize this!
@ -349,6 +424,7 @@ public:
} else if (data.endsWith(GF(GSM_NL "+IPD,"))) {
int mux = stream.readStringUntil(',').toInt();
int len = stream.readStringUntil(':').toInt();
int len_orig = len;
if (len > sockets[mux]->rx.free()) {
DBG("### Buffer overflow: ", len, "->", sockets[mux]->rx.free());
} else {
@ -358,15 +434,17 @@ public:
while (!stream.available()) { TINY_GSM_YIELD(); }
sockets[mux]->rx.put(stream.read());
}
if (len_orig > sockets[mux]->available()) {
DBG(GSM_NL, "### Fewer characters received than expected: ", sockets[mux]->available(), " vs ", len_orig);
}
data = "";
return index;
} else if (data.endsWith(GF(GSM_NL "1,CLOSED" GSM_NL))) { //TODO: use mux
sockets[1]->sock_connected = false;
data = "";
}
}
} while (millis() - startMillis < timeout);
finish:
finish:
if (!index) {
data.trim();
if (data.length()) {


+ 30
- 4
TinyGsmClientM590.h View File

@ -357,6 +357,17 @@ public:
return false;
}
/*
* WiFi functions
*/
bool networkConnect(const char* ssid, const char* pwd) {
return false;
}
bool networkDisconnect() {
return false;
}
/*
* GPRS functions
*/
@ -413,8 +424,19 @@ public:
}
IPAddress localIP() {
IPAddress res;
res.fromString(getLocalIP());
String strIP = getLocalIP();
int Parts[4] = {0,0,0,0};
int Part = 0;
for (uint8_t i=0; i<strIP.length(); i++) {
char c = strIP[i];
if (c == '.') {
Part++;
continue;
}
Parts[Part] *= 10;
Parts[Part] += c - '0';
}
IPAddress res(Parts[0], Parts[1], Parts[2], Parts[3]);
return res;
}
@ -610,7 +632,7 @@ public:
streamWrite("AT", cmd..., GSM_NL);
stream.flush();
TINY_GSM_YIELD();
//DBG("### AT:", cmd...);
// DBG("### AT:", cmd...);
}
// TODO: Optimize this!
@ -651,6 +673,7 @@ public:
} else if (data.endsWith(GF("+TCPRECV:"))) {
int mux = stream.readStringUntil(',').toInt();
int len = stream.readStringUntil(',').toInt();
int len_orig = len;
if (len > sockets[mux]->rx.free()) {
DBG("### Buffer overflow: ", len, "->", sockets[mux]->rx.free());
} else {
@ -660,6 +683,9 @@ public:
while (!stream.available()) { TINY_GSM_YIELD(); }
sockets[mux]->rx.put(stream.read());
}
if (len_orig > sockets[mux]->available()) {
DBG(GSM_NL, "### Fewer characters received than expected: ", sockets[mux]->available(), " vs ", len_orig);
}
data = "";
} else if (data.endsWith(GF("+TCPCLOSE:"))) {
int mux = stream.readStringUntil(',').toInt();
@ -672,7 +698,7 @@ public:
}
}
} while (millis() - startMillis < timeout);
finish:
finish:
if (!index) {
data.trim();
if (data.length()) {


+ 28
- 6
TinyGsmClientSIM800.h View File

@ -9,8 +9,8 @@
#ifndef TinyGsmClientSIM800_h
#define TinyGsmClientSIM800_h
//#define TINY_GSM_DEBUG Serial
//#define TINY_GSM_USE_HEX
// #define TINY_GSM_DEBUG Serial
// #define TINY_GSM_USE_HEX
#if !defined(TINY_GSM_RX_BUFFER)
#define TINY_GSM_RX_BUFFER 64
@ -426,6 +426,17 @@ public:
return false;
}
/*
* WiFi functions
*/
bool networkConnect(const char* ssid, const char* pwd) {
return false;
}
bool networkDisconnect() {
return false;
}
/*
* GPRS functions
*/
@ -545,8 +556,19 @@ public:
}
IPAddress localIP() {
IPAddress res;
res.fromString(getLocalIP());
String strIP = getLocalIP();
int Parts[4] = {0,0,0,0};
int Part = 0;
for (uint8_t i=0; i<strIP.length(); i++) {
char c = strIP[i];
if (c == '.') {
Part++;
continue;
}
Parts[Part] *= 10;
Parts[Part] += c - '0';
}
IPAddress res(Parts[0], Parts[1], Parts[2], Parts[3]);
return res;
}
@ -846,7 +868,7 @@ public:
streamWrite("AT", cmd..., GSM_NL);
stream.flush();
TINY_GSM_YIELD();
//DBG("### AT:", cmd...);
DBG("### AT:", cmd...);
}
// TODO: Optimize this!
@ -907,7 +929,7 @@ public:
}
}
} while (millis() - startMillis < timeout);
finish:
finish:
if (!index) {
data.trim();
if (data.length()) {


+ 633
- 0
TinyGsmClientXBee.h View File

@ -0,0 +1,633 @@
/**
* @file TinyWiFiClientESP8266.h
* @author Volodymyr Shymanskyy
* @license LGPL-3.0
* @copyright Copyright (c) 2016 Volodymyr Shymanskyy
* @date Nov 2016
*/
#ifndef TinyGsmClientXBee_h
#define TinyGsmClientXBee_h
// #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
#include <TinyGsmCommon.h>
#define GSM_NL "\r"
static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL;
static const char GSM_ERROR[] TINY_GSM_PROGMEM = "ERROR" GSM_NL;
enum SimStatus {
SIM_ERROR = 0,
SIM_READY = 1,
SIM_LOCKED = 2,
};
enum XBeeType {
S6B = 0,
LTEC1 = 1,
};
enum RegStatus {
REG_UNREGISTERED = 0,
REG_SEARCHING = 2,
REG_DENIED = 3,
REG_OK_HOME = 1,
REG_OK_ROAMING = 5,
REG_UNKNOWN = 4,
};
class TinyGsm
{
public:
TinyGsm(Stream& stream)
: stream(stream)
{}
public:
class GsmClient : public Client
{
friend class TinyGsm;
public:
GsmClient() {}
GsmClient(TinyGsm& modem, uint8_t mux = 0) {
init(&modem, mux);
}
bool init(TinyGsm* modem, uint8_t mux = 0) {
this->at = modem;
this->mux = mux;
sock_connected = false;
at->sockets[mux] = this;
return true;
}
public:
virtual int connect(const char *host, uint16_t port) {
at->streamClear(); // Empty anything remaining in the buffer;
at->commandMode();
sock_connected = at->modemConnect(host, port, mux);
at->writeChanges();
at->exitCommand();
return sock_connected;
}
virtual int connect(IPAddress ip, uint16_t port) {
at->streamClear(); // Empty anything remaining in the buffer;
at->commandMode();
sock_connected = at->modemConnect(ip, port, mux);
at->writeChanges();
at->exitCommand();
return sock_connected;
}
// This is a hack to shut the socket by setting the timeout to zero and
// then sending an empty line to the server.
virtual void stop() {
at->commandMode();
at->sendAT(GF("TM0")); // Set socket timeout to 0;
at->waitResponse();
at->writeChanges();
at->exitCommand();
at->modemSend("", 1, mux);
at->streamClear(); // Empty anything remaining in the buffer;
at->commandMode();
at->sendAT(GF("TM64")); // Set socket timeout back to 10seconds;
at->waitResponse();
at->writeChanges();
at->exitCommand();
at->streamClear(); // Empty anything remaining in the buffer;
sock_connected = false;
}
virtual size_t write(const uint8_t *buf, size_t size) {
return at->modemSend(buf, size, mux);
}
virtual size_t write(uint8_t c) {
return write(&c, 1);
}
virtual int available() {
return at->stream.available();
}
virtual int read(uint8_t *buf, size_t size) {
return available();
}
virtual int read() {
TINY_GSM_YIELD();
return at->stream.read();
}
virtual int peek() { return at->stream.peek(); }
virtual void flush() { at->stream.flush(); }
virtual uint8_t connected() {
if (available()) {
return true;
}
return sock_connected;
}
virtual operator bool() { return connected(); }
private:
TinyGsm* at;
uint8_t mux;
bool sock_connected;
};
public:
/*
* Basic functions
*/
bool begin() {
return init();
}
bool init() {
guardTime = 1100;
commandMode();
sendAT(GF("AP0")); // Put in transparent mode
waitResponse();
sendAT(GF("GT64")); // shorten the guard time to 100ms
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 autoBaud(unsigned long timeout = 10000L) { // not supported
return false;
}
void maintain() {}
bool factoryDefault() {
commandMode();
sendAT(GF("RE"));
bool ret_val = waitResponse() == 1;
writeChanges();
exitCommand();
return ret_val;
}
/*
* Power functions
*/
bool restart() {
commandMode();
sendAT(GF("FR"));
if (waitResponse() != 1) {
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);
waitResponse();
sendAT(GF("SO"),200);
waitResponse();
writeChanges();
exitCommand();
}
/*
* SIM card functions
*/
bool simUnlock(const char *pin) { // Not supported
return false;
}
String getSimCCID() {
commandMode();
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
exitCommand();
return res;
}
String getIMEI() {
commandMode();
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
exitCommand();
return res;
}
SimStatus getSimStatus(unsigned long timeout = 10000L) {
return SIM_READY; // unsupported
}
RegStatus getRegistrationStatus() {
commandMode();
if (beeType == S6B) sendAT(GF("AI"));
else sendAT(GF("CI"));
// 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"))
return REG_DENIED;
else return REG_UNKNOWN;
}
String getOperator() {
commandMode();
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
exitCommand();
return res;
}
/*
* Generic network functions
*/
int getSignalQuality() {
commandMode();
if (beeType == S6B) sendAT(GF("LM")); // ask for the "link margin" - the dB above sensitivity
else sendAT(GF("DB")); // ask for the cell strenght 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");
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
}
bool waitForNetwork(unsigned long timeout = 60000L) {
for (unsigned long start = millis(); millis() - start < timeout; ) {
commandMode();
if (beeType == S6B) sendAT(GF("AI"));
else sendAT(GF("CI"));
// 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 true;
}
delay(1000);
}
return false;
}
/*
* WiFi functions
*/
bool networkConnect(const char* ssid, const char* pwd) {
commandMode();
sendAT(GF("EE"), 2); // Set security to WPA2
waitResponse();
sendAT(GF("ID"), ssid);
if (waitResponse() != 1) {
goto fail;
}
sendAT(GF("PK"), pwd);
if (waitResponse() != 1) {
goto fail;
}
writeChanges();
exitCommand();
return true;
fail:
exitCommand();
return false;
}
bool networkDisconnect() {
return false; // Doesn't support disconnecting
}
String getLocalIP() {
commandMode();
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
return IPaddr;
}
IPAddress localIP() {
String strIP = getLocalIP();
int Parts[4] = {0,0,0,0};
int Part = 0;
for (uint8_t i=0; i<strIP.length(); i++) {
char c = strIP[i];
if (c == '.') {
Part++;
continue;
}
Parts[Part] *= 10;
Parts[Part] += c - '0';
}
IPAddress res(Parts[0], Parts[1], Parts[2], Parts[3]);
return res;
}
/*
* GPRS functions
*/
bool gprsConnect(const char* apn, const char* user = "", const char* pw = "") {
commandMode();
sendAT(GF("AN"), apn); // Set the APN
waitResponse();
writeChanges();
exitCommand();
return true;
}
bool gprsDisconnect() { // TODO
return false;
}
/*
* Messaging functions
*/
void sendUSSD() {
}
void sendSMS() {
}
bool sendSMS(const String& number, const String& text) {
commandMode();
sendAT(GF("IP"), 2); // Put in text messaging mode
waitResponse();
sendAT(GF("PH"), number); // Set the phone number
waitResponse();
sendAT(GF("TDD")); // Set the text delimiter to the standard 0x0D (carriabe return)
waitResponse();
writeChanges();
exitCommand();
stream.print(text);
stream.write((char)0x0D); // close off with the carriage return
return true;
}
private:
int modemConnect(const char* host, uint16_t port, uint8_t mux = 0) {
sendAT(GF("LA"), host);
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
int Parts[4] = {0,0,0,0};
int Part = 0;
for (uint8_t i=0; i<strIP.length(); i++) {
char c = strIP[i];
if (c == '.') {
Part++;
continue;
}
Parts[Part] *= 10;
Parts[Part] += c - '0';
}
IPAddress res(Parts[0], Parts[1], Parts[2], Parts[3]);
return modemConnect(res, port);
}
int modemConnect(IPAddress ip, uint16_t port, uint8_t mux = 0) {
String host; host.reserve(16);
host += ip[0];
host += ".";
host += ip[1];
host += ".";
host += ip[2];
host += ".";
host += ip[3];
sendAT(GF("IP"), 1); // Put in TCP mode
waitResponse();
sendAT(GF("DL"), host); // Set the "Destination Address Low"
waitResponse();
sendAT(GF("DE"), String(port, HEX)); // Set the destination port
int rsp = waitResponse();
return rsp;
}
int modemSend(const void* buff, size_t len, uint8_t mux = 0) {
stream.write((uint8_t*)buff, len);
stream.flush();
return len;
}
bool modemGetConnected(uint8_t mux = 0) {
commandMode();
if (beeType == S6B) sendAT(GF("AI"));
else sendAT(GF("CI"));
int res = waitResponse(GF("0"));
exitCommand();
return 1 == res;
}
/* Private Utilities */
template<typename T>
void streamWrite(T last) {
stream.print(last);
}
template<typename T, typename... Args>
void streamWrite(T head, Args... tail) {
stream.print(head);
streamWrite(tail...);
}
int streamRead() { return stream.read(); }
String streamReadUntil(char c) {
TINY_GSM_YIELD();
String return_string = stream.readStringUntil(c);
return_string.trim();
if (String(c) == GSM_NL) {
DBG(return_string, "\r\n");
} else DBG(return_string, c);
return return_string;
}
void streamClear(void) {
while (stream.available())
{streamRead();}
}
bool commandMode(void) {
delay(guardTime); // cannot send anything for 1 second before entering command mode
streamWrite(GF("+++")); // enter command mode
DBG("\r\n+++\r\n");
return 1 == waitResponse(guardTime*2);
}
void writeChanges(void) {
sendAT(GF("WR")); // Write changes to flash
waitResponse();
sendAT(GF("AC")); // Apply changes
waitResponse();
}
void exitCommand(void) {
sendAT(GF("CN")); // Exit command mode
waitResponse();
}
template<typename... Args>
void sendAT(Args... cmd) {
streamWrite("AT", cmd..., GSM_NL);
stream.flush();
TINY_GSM_YIELD();
DBG(">>> AT ", cmd..., "\r\n");
}
// TODO: Optimize this!
uint8_t waitResponse(uint32_t timeout, String& data,
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
{
/*String r1s(r1); r1s.trim();
String r2s(r2); r2s.trim();
String r3s(r3); r3s.trim();
String r4s(r4); r4s.trim();
String r5s(r5); r5s.trim();
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
data.reserve(64);
int index = 0;
unsigned long startMillis = millis();
do {
TINY_GSM_YIELD();
while (stream.available() > 0) {
int a = streamRead();
if (a <= 0) continue; // Skip 0x00 bytes, just in case
data += (char)a;
if (r1 && data.endsWith(r1)) {
index = 1;
goto finish;
} else if (r2 && data.endsWith(r2)) {
index = 2;
goto finish;
} else if (r3 && data.endsWith(r3)) {
index = 3;
goto finish;
} else if (r4 && data.endsWith(r4)) {
index = 4;
goto finish;
} else if (r5 && data.endsWith(r5)) {
index = 5;
goto finish;
}
}
} while (millis() - startMillis < timeout);
finish:
if (!index) {
data.trim();
data.replace(GSM_NL GSM_NL, GSM_NL);
data.replace(GSM_NL, "\r\n" " ");
if (data.length()) {
DBG("### Unhandled:", data, "\r\n");
} else DBG("### NO RESPONSE!\r\n");
}
else {
data.trim();
data.replace(GSM_NL GSM_NL, GSM_NL);
data.replace(GSM_NL, "\r\n ");
if (data.length()) {
DBG("<<< ", data, "\r\n");
}
}
return index;
}
uint8_t waitResponse(uint32_t timeout,
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
{
String data;
return waitResponse(timeout, data, r1, r2, r3, r4, r5);
}
uint8_t waitResponse(GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
{
return waitResponse(1000, r1, r2, r3, r4, r5);
}
private:
int guardTime;
XBeeType beeType;
Stream& stream;
GsmClient* sockets[TINY_GSM_MUX_COUNT];
};
#endif

+ 1
- 0
TinyGsmCommon.h View File

@ -46,6 +46,7 @@ namespace {
template<typename T>
static void DBG(T last) {
TINY_GSM_DEBUG.println(last);
// TINY_GSM_DEBUG.print(last);
}
template<typename T, typename... Args>


BIN
doc/Digi XBee LTEC1 Users Guide - 90001525.pdf View File


BIN
doc/Digi XBee S6B Users Guide - 90002180.pdf View File


BIN
doc/ESP8266 - AT Instruction Set.pdf View File


BIN
doc/ESP8266 - Datasheet v4.3.pdf View File


BIN
doc/ESP8266 - Low Power Solutions.pdf View File


BIN
doc/SIM800 AT Commands v1.11.pdf View File


+ 1
- 1
examples/BlynkClient/BlynkClient.ino View File

@ -36,6 +36,7 @@
// #define TINY_GSM_MODEM_A7
// #define TINY_GSM_MODEM_M590
// #define TINY_GSM_MODEM_ESP8266
// #define TINY_GSM_MODEM_XBEE
#include <TinyGsmClient.h>
#include <BlynkSimpleSIM800.h>
@ -88,4 +89,3 @@ void loop()
{
Blynk.run();
}

+ 1
- 1
examples/FileDownload/FileDownload.ino View File

@ -20,6 +20,7 @@
// #define TINY_GSM_MODEM_A7
// #define TINY_GSM_MODEM_M590
// #define TINY_GSM_MODEM_ESP8266
// #define TINY_GSM_MODEM_XBEE
// Increase RX buffer
#define TINY_GSM_RX_BUFFER 1030
@ -193,4 +194,3 @@ void loop() {
delay(1000);
}
}

+ 1
- 1
examples/MqttClient/MqttClient.ino View File

@ -33,6 +33,7 @@
// #define TINY_GSM_MODEM_A7
// #define TINY_GSM_MODEM_M590
// #define TINY_GSM_MODEM_ESP8266
// #define TINY_GSM_MODEM_XBEE
#include <TinyGsmClient.h>
#include <PubSubClient.h>
@ -152,4 +153,3 @@ void mqttCallback(char* topic, byte* payload, unsigned int len) {
mqtt.publish(topicLedStatus, ledStatus ? "1" : "0");
}
}

+ 0
- 1
examples/WebClient/WebClient.ino View File

@ -116,4 +116,3 @@ void loop() {
delay(1000);
}
}

+ 4
- 1
tools/AT_Debug/AT_Debug.ino View File

@ -10,11 +10,15 @@
// Select your modem:
#define TINY_GSM_MODEM_SIM800
// #define TINY_GSM_MODEM_SIM808
// #define TINY_GSM_MODEM_SIM900
// #define TINY_GSM_MODEM_A6
// #define TINY_GSM_MODEM_A7
// #define TINY_GSM_MODEM_M590
// #define TINY_GSM_MODEM_ESP8266
// #define TINY_GSM_MODEM_XBEE
#include <TinyGsmClient.h>
// Set serial for debug console (to the Serial Monitor, speed 115200)
#define SerialMon Serial
@ -75,4 +79,3 @@ void loop() {
delay(0);
}
}

+ 2
- 1
tools/Diagnostics/Diagnostics.ino View File

@ -11,11 +11,13 @@
// Select your modem:
#define TINY_GSM_MODEM_SIM800
// #define TINY_GSM_MODEM_SIM808
// #define TINY_GSM_MODEM_SIM900
// #define TINY_GSM_MODEM_A6
// #define TINY_GSM_MODEM_A7
// #define TINY_GSM_MODEM_M590
// #define TINY_GSM_MODEM_ESP8266
// #define TINY_GSM_MODEM_XBEE
// Increase the buffer
#define TINY_GSM_RX_BUFFER 512
@ -153,4 +155,3 @@ void loop() {
delay(1000);
}
}

+ 2
- 0
tools/FactoryReset/FactoryReset.ino View File

@ -11,11 +11,13 @@
// Select your modem:
#define TINY_GSM_MODEM_SIM800
// #define TINY_GSM_MODEM_SIM808
// #define TINY_GSM_MODEM_SIM900
// #define TINY_GSM_MODEM_A6
// #define TINY_GSM_MODEM_A7
// #define TINY_GSM_MODEM_M590
// #define TINY_GSM_MODEM_ESP8266
// #define TINY_GSM_MODEM_XBEE
#include <TinyGsmClient.h>


+ 27
- 22
tools/test_build/test_build.ino View File

@ -4,8 +4,6 @@
*
**************************************************************/
#define TINY_GSM_MODEM_SIM800
#include <TinyGsmClient.h>
TinyGsm modem(Serial);
@ -21,26 +19,36 @@ void setup() {
}
void loop() {
modem.restart();
// Test the start/restart functions
modem.restart();
modem.begin();
modem.autoBaud();
modem.factoryDefault();
modem.getOperator();
// Test the SIM card functions
#if defined(TINY_GSM_MODEM_SIM800) || defined(TINY_GSM_MODEM_A6) || defined(TINY_GSM_MODEM_M590) || defined(TINY_GSM_MODEM_XBEE)
modem.getSimCCID();
modem.getIMEI();
modem.getSimStatus();
modem.getRegistrationStatus();
modem.getOperator();
#endif
// Test the Networking functions
modem.getSignalQuality();
#if defined(TINY_GSM_MODEM_SIM800) || defined(TINY_GSM_MODEM_A6) || defined(TINY_GSM_MODEM_M590)
modem.waitForNetwork();
modem.gprsConnect("YourAPN", "", "");
#else
modem.networkConnect("YourSSID", "YourPWD");
modem.waitForNetwork();
#endif
if (!modem.gprsConnect("YourAPN", "", "")) {
delay(10000);
return;
}
if (!client.connect(server, 80)) {
delay(10000);
return;
}
client.connect(server, 80);
// Make a HTTP GET request:
client.print(String("GET ") + resource + " HTTP/1.0\r\n");
@ -49,20 +57,17 @@ void loop() {
unsigned long timeout = millis();
while (client.connected() && millis() - timeout < 10000L) {
// Print available data
while (client.available()) {
char c = client.read();
client.read();
timeout = millis();
}
}
client.stop();
#if defined(TINY_GSM_MODEM_SIM800) || defined(TINY_GSM_MODEM_A6) || defined(TINY_GSM_MODEM_M590)
modem.gprsDisconnect();
// Do nothing forevermore
while (true) {
delay(1000);
}
#else
modem.networkDisconnect();
#endif
}

Loading…
Cancel
Save