Browse Source

Merge pull request #327 from EnviroDIY/master

Updates
v_master
Sara Damiano 5 years ago
committed by GitHub
parent
commit
c652760e55
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 1149 additions and 462 deletions
  1. +2
    -0
      .gitattributes
  2. +1
    -1
      .github/ISSUE_TEMPLATE.md
  3. +7
    -0
      .gitignore
  4. +2
    -2
      README.md
  5. +28
    -3
      examples/AllFunctions/AllFunctions.ino
  6. +2
    -3
      examples/BlynkClient/BlynkClient.ino
  7. +40
    -5
      examples/FileDownload/FileDownload.ino
  8. +33
    -6
      examples/HttpClient/HttpClient.ino
  9. +34
    -7
      examples/HttpsClient/HttpsClient.ino
  10. +69
    -45
      examples/MqttClient/MqttClient.ino
  11. +28
    -5
      examples/WebClient/WebClient.ino
  12. +1
    -1
      library.json
  13. +1
    -1
      library.properties
  14. +24
    -5
      src/TinyGsmClientA6.h
  15. +29
    -12
      src/TinyGsmClientBG96.h
  16. +59
    -26
      src/TinyGsmClientESP8266.h
  17. +21
    -5
      src/TinyGsmClientM590.h
  18. +128
    -63
      src/TinyGsmClientM95.h
  19. +80
    -45
      src/TinyGsmClientMC60.h
  20. +28
    -10
      src/TinyGsmClientSIM5360.h
  21. +37
    -22
      src/TinyGsmClientSIM7000.h
  22. +54
    -43
      src/TinyGsmClientSIM7600.h
  23. +19
    -8
      src/TinyGsmClientSIM800.h
  24. +88
    -57
      src/TinyGsmClientSaraR4.h
  25. +20
    -6
      src/TinyGsmClientSequansMonarch.h
  26. +8
    -4
      src/TinyGsmClientUBLOX.h
  27. +271
    -68
      src/TinyGsmClientXBee.h
  28. +7
    -4
      src/TinyGsmCommon.h
  29. +28
    -5
      tools/Diagnostics/Diagnostics.ino

+ 2
- 0
.gitattributes View File

@ -2,3 +2,5 @@
/.gitattributes export-ignore
/.gitignore export-ignore
/.travis.yml export-ignore
*.ino filter=updateUsersAndPasses

+ 1
- 1
.github/ISSUE_TEMPLATE.md View File

@ -23,7 +23,7 @@ with your board before submitting any issues.
Main processor board: <!-- Uno, Zero, ESP32, Particle, etc -->
Modem: <!-- Brand, model, variant, firmware version -->
TinyGSM version: <!-- always try to use the latest (0.9.7) -->
TinyGSM version: <!-- always try to use the latest (0.9.17) -->
Code: <!-- Example name or paste in your code -->
### Scenario, steps to reproduce


+ 7
- 0
.gitignore View File

@ -22,6 +22,9 @@
platformio.ini
lib/readme.txt
include/readme.txt
.atomrc.cson
# VSCode
.vscode/*
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
@ -36,3 +39,7 @@ extras/Module Datasheets/*
extras/Older Command Manuals/*
extras/Older Command Manuals/*
extras/At Command Manuals - Unsupported/*
# Filters
.gitconfig
filters/*

+ 2
- 2
README.md View File

@ -79,9 +79,9 @@ Watch this repo for new updates! And of course, contributions are welcome ;)
- UDP
- Not yet supported on any module, though it may be some day
- SSL/TLS (HTTPS)
- Supported on¹:
- Supported on:
- SIM800, u-Blox, XBee _cellular_, ESP8266, and Sequans Monarch
¹ - only some device models or firmware revisions have this feature (SIM8xx R14.18, A7, etc.)
- Note: only some device models or firmware revisions have this feature (SIM8xx R14.18, A7, etc.)
- Not yet supported on:
- Quectel modems, SIM7000, SIM5360/5320/7100/7500/7600
- Not possible on:


+ 28
- 3
examples/AllFunctions/AllFunctions.ino View File

@ -60,6 +60,7 @@
#define TINY_GSM_TEST_SMS true
#define TINY_GSM_TEST_USSD true
#define TINY_GSM_TEST_BATTERY true
#define TINY_GSM_TEST_GPS false
// powerdown modem after tests
#define TINY_GSM_POWERDOWN false
@ -70,16 +71,40 @@
//#define SMS_TARGET "+380xxxxxxxxx"
//#define CALL_TARGET "+380xxxxxxxxx"
// Your GPRS credentials
// Leave empty, if missing user or pass
// Your GPRS credentials, if any
const char apn[] = "YourAPN";
const char gprsUser[] = "";
const char gprsPass[] = "";
// Your WiFi connection credentials, if applicable
const char wifiSSID[] = "YourSSID";
const char wifiPass[] = "YourWiFiPass";
#include <TinyGsmClient.h>
#if TINY_GSM_TEST_GPRS && not defined TINY_GSM_MODEM_HAS_GPRS
#undef TINY_GSM_TEST_GPRS
#undef TINY_GSM_TEST_CALL
#undef TINY_GSM_TEST_SMS
#undef TINY_GSM_TEST_USSD
#undef TINY_GSM_TEST_WIFI
#define TINY_GSM_TEST_GPRS false
#define TINY_GSM_TEST_CALL false
#define TINY_GSM_TEST_SMS false
#define TINY_GSM_TEST_USSD false
#define TINY_GSM_TEST_WIFI true
#endif
#if TINY_GSM_TEST_WIFI && not defined TINY_GSM_MODEM_HAS_WIFI
#undef TINY_GSM_USE_GPRS
#undef TINY_GSM_USE_WIFI
#define TINY_GSM_USE_GPRS true
#define TINY_GSM_USE_WIFI false
#endif
#if TINY_GSM_TEST_GPS && not defined TINY_GSM_MODEM_HAS_GPS
#undef TINY_GSM_TEST_GPS
#define TINY_GSM_TEST_GPS false
#endif
#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
@ -202,7 +227,7 @@ void loop() {
DBG("Phone number (USSD):", ussd_phone_num);
#endif
#if defined(TINY_GSM_MODEM_HAS_GPS)
#if TINY_GSM_TEST_GPS
modem.enableGPS();
String gps_raw = modem.getGPSraw();
modem.disableGPS();


+ 2
- 3
examples/BlynkClient/BlynkClient.ino View File

@ -63,8 +63,7 @@
//SoftwareSerial SerialAT(2, 3); // RX, TX
// Your GPRS credentials
// Leave empty, if missing user or pass
// Your GPRS credentials, if any
const char apn[] = "YourAPN";
const char user[] = "";
const char pass[] = "";
@ -91,7 +90,7 @@ void setup()
modem.restart();
String modemInfo = modem.getModemInfo();
SerialMon.print("Modem: ");
SerialMon.print("Modem Info: ");
SerialMon.println(modemInfo);
// Unlock your SIM card with a PIN


+ 40
- 5
examples/FileDownload/FileDownload.ino View File

@ -61,17 +61,19 @@
// Add a reception delay - may be needed for a fast processor at a slow baud rate
//#define TINY_GSM_YIELD() { delay(2); }
// Define how you're planning to connect to the internet
#define TINY_GSM_USE_GPRS true
#define TINY_GSM_USE_WIFI false
// set GSM PIN, if any
#define GSM_PIN ""
// Your GPRS credentials
// Leave empty, if missing user or pass
// Your GPRS credentials, if any
const char apn[] = "YourAPN";
const char gprsUser[] = "";
const char gprsPass[] = "";
// Your WiFi connection credentials, if applicable
const char wifiSSID[] = "YourSSID";
const char wifiPass[] = "YourWiFiPass";
@ -82,6 +84,20 @@ const int port = 80;
#include <TinyGsmClient.h>
#include <CRC32.h>
// Just in case someone defined the wrong thing..
#if TINY_GSM_USE_GPRS && not defined TINY_GSM_MODEM_HAS_GPRS
#undef TINY_GSM_USE_GPRS
#undef TINY_GSM_USE_WIFI
#define TINY_GSM_USE_GPRS false
#define TINY_GSM_USE_WIFI true
#endif
#if TINY_GSM_USE_WIFI && not defined TINY_GSM_MODEM_HAS_WIFI
#undef TINY_GSM_USE_GPRS
#undef TINY_GSM_USE_WIFI
#define TINY_GSM_USE_GPRS true
#define TINY_GSM_USE_WIFI false
#endif
const char resource[] = "/TinyGSM/test_1k.bin";
uint32_t knownCRC32 = 0x6f50d767;
uint32_t knownFileSize = 1024; // In case server does not send it
@ -101,6 +117,12 @@ void setup() {
SerialMon.begin(115200);
delay(10);
// !!!!!!!!!!!
// Set your reset, enable, power pins here
// !!!!!!!!!!!
SerialMon.println("Wait...");
// Set GSM module baud rate
SerialAT.begin(115200);
delay(3000);
@ -109,9 +131,10 @@ void setup() {
// To skip it, call init() instead of restart()
SerialMon.println("Initializing modem...");
modem.restart();
// modem.init();
String modemInfo = modem.getModemInfo();
SerialMon.print("Modem: ");
SerialMon.print("Modem Info: ");
SerialMon.println(modemInfo);
#if TINY_GSM_USE_GPRS
@ -135,7 +158,8 @@ void printPercent(uint32_t readLength, uint32_t contentLength) {
void loop() {
#if defined TINY_GSM_USE_WIFI && defined TINY_GSM_MODEM_HAS_WIFI
#if TINY_GSM_USE_WIFI
// Wifi connection parameters must be set before waiting for the network
SerialMon.print(F("Setting SSID/password..."));
if (!modem.networkConnect(wifiSSID, wifiPass)) {
SerialMon.println(" fail");
@ -162,7 +186,8 @@ void loop() {
SerialMon.println("Network connected");
}
#if TINY_GSM_USE_GPRS && defined TINY_GSM_MODEM_HAS_GPRS
#if TINY_GSM_USE_GPRS
// GPRS connection parameters are usually set after network registration
SerialMon.print(F("Connecting to "));
SerialMon.print(apn);
if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
@ -171,6 +196,10 @@ void loop() {
return;
}
SerialMon.println(" success");
if (modem.isGprsConnected()) {
SerialMon.println("GPRS connected");
}
#endif
SerialMon.print(F("Connecting to "));
@ -292,8 +321,14 @@ void loop() {
client.stop();
SerialMon.println(F("Server disconnected"));
#if TINY_GSM_USE_WIFI
modem.networkDisconnect();
SerialMon.println(F("WiFi disconnected"));
#endif
#if TINY_GSM_USE_GPRS
modem.gprsDisconnect();
SerialMon.println(F("GPRS disconnected"));
#endif
float duration = float(timeElapsed) / 1000;


+ 33
- 6
examples/HttpClient/HttpClient.ino View File

@ -63,20 +63,26 @@
#define TINY_GSM_DEBUG SerialMon
//#define LOGGING // <- Logging is for the HTTP library
// Range to attempt to autobaud
#define GSM_AUTOBAUD_MIN 9600
#define GSM_AUTOBAUD_MAX 115200
// Add a reception delay - may be needed for a fast processor at a slow baud rate
//#define TINY_GSM_YIELD() { delay(2); }
// Define how you're planning to connect to the internet
#define TINY_GSM_USE_GPRS true
#define TINY_GSM_USE_WIFI false
// set GSM PIN, if any
#define GSM_PIN ""
// Your GPRS credentials
// Leave empty, if missing user or pass
// Your GPRS credentials, if any
const char apn[] = "YourAPN";
const char gprsUser[] = "";
const char gprsPass[] = "";
// Your WiFi connection credentials, if applicable
const char wifiSSID[] = "YourSSID";
const char wifiPass[] = "YourWiFiPass";
@ -88,6 +94,20 @@ const int port = 80;
#include <TinyGsmClient.h>
#include <ArduinoHttpClient.h>
// Just in case someone defined the wrong thing..
#if TINY_GSM_USE_GPRS && not defined TINY_GSM_MODEM_HAS_GPRS
#undef TINY_GSM_USE_GPRS
#undef TINY_GSM_USE_WIFI
#define TINY_GSM_USE_GPRS false
#define TINY_GSM_USE_WIFI true
#endif
#if TINY_GSM_USE_WIFI && not defined TINY_GSM_MODEM_HAS_WIFI
#undef TINY_GSM_USE_GPRS
#undef TINY_GSM_USE_WIFI
#define TINY_GSM_USE_GPRS true
#define TINY_GSM_USE_WIFI false
#endif
#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
@ -111,7 +131,8 @@ void setup() {
SerialMon.println("Wait...");
// Set GSM module baud rate
SerialAT.begin(115200);
// TinyGsmAutoBaud(SerialAT,GSM_AUTOBAUD_MIN,GSM_AUTOBAUD_MAX);
SerialAT.begin(9600);
delay(3000);
// Restart takes quite some time
@ -121,7 +142,7 @@ void setup() {
// modem.init();
String modemInfo = modem.getModemInfo();
SerialMon.print("Modem: ");
SerialMon.print("Modem Info: ");
SerialMon.println(modemInfo);
#if TINY_GSM_USE_GPRS
@ -134,7 +155,8 @@ void setup() {
void loop() {
#if defined TINY_GSM_USE_WIFI && defined TINY_GSM_MODEM_HAS_WIFI
#if TINY_GSM_USE_WIFI
// Wifi connection parameters must be set before waiting for the network
SerialMon.print(F("Setting SSID/password..."));
if (!modem.networkConnect(wifiSSID, wifiPass)) {
SerialMon.println(" fail");
@ -161,7 +183,8 @@ void loop() {
SerialMon.println("Network connected");
}
#if TINY_GSM_USE_GPRS && defined TINY_GSM_MODEM_HAS_GPRS
#if TINY_GSM_USE_GPRS
// GPRS connection parameters are usually set after network registration
SerialMon.print(F("Connecting to "));
SerialMon.print(apn);
if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
@ -170,6 +193,10 @@ void loop() {
return;
}
SerialMon.println(" success");
if (modem.isGprsConnected()) {
SerialMon.println("GPRS connected");
}
#endif
SerialMon.print(F("Performing HTTP GET request... "));


+ 34
- 7
examples/HttpsClient/HttpsClient.ino View File

@ -55,20 +55,26 @@
#define TINY_GSM_DEBUG SerialMon
//#define LOGGING // <- Logging is for the HTTP library
// Range to attempt to autobaud
#define GSM_AUTOBAUD_MIN 9600
#define GSM_AUTOBAUD_MAX 115200
// Add a reception delay - may be needed for a fast processor at a slow baud rate
//#define TINY_GSM_YIELD() { delay(2); }
// Define how you're planning to connect to the internet
#define TINY_GSM_USE_GPRS true
#define TINY_GSM_USE_WIFI false
// set GSM PIN, if any
#define GSM_PIN ""
// Your GPRS credentials
// Leave empty, if missing user or pass
// Your GPRS credentials, if any
const char apn[] = "YourAPN";
const char gprsUser[] = "";
const char gprsPass[] = "";
// Your WiFi connection credentials, if applicable
const char wifiSSID[] = "YourSSID";
const char wifiPass[] = "YourWiFiPass";
@ -80,6 +86,20 @@ const int port = 443;
#include <TinyGsmClient.h>
#include <ArduinoHttpClient.h>
// Just in case someone defined the wrong thing..
#if TINY_GSM_USE_GPRS && not defined TINY_GSM_MODEM_HAS_GPRS
#undef TINY_GSM_USE_GPRS
#undef TINY_GSM_USE_WIFI
#define TINY_GSM_USE_GPRS false
#define TINY_GSM_USE_WIFI true
#endif
#if TINY_GSM_USE_WIFI && not defined TINY_GSM_MODEM_HAS_WIFI
#undef TINY_GSM_USE_GPRS
#undef TINY_GSM_USE_WIFI
#define TINY_GSM_USE_GPRS true
#define TINY_GSM_USE_WIFI false
#endif
#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
@ -103,7 +123,8 @@ void setup() {
SerialMon.println("Wait...");
// Set GSM module baud rate
SerialAT.begin(115200);
// TinyGsmAutoBaud(SerialAT,GSM_AUTOBAUD_MIN,GSM_AUTOBAUD_MAX);
SerialAT.begin(9600);
delay(3000);
// Restart takes quite some time
@ -113,7 +134,7 @@ void setup() {
// modem.init();
String modemInfo = modem.getModemInfo();
SerialMon.print("Modem: ");
SerialMon.print("Modem Info: ");
SerialMon.println(modemInfo);
#if TINY_GSM_USE_GPRS
@ -131,7 +152,8 @@ void setup() {
void loop() {
#if defined TINY_GSM_USE_WIFI && defined TINY_GSM_MODEM_HAS_WIFI
#if TINY_GSM_USE_WIFI
// Wifi connection parameters must be set before waiting for the network
SerialMon.print(F("Setting SSID/password..."));
if (!modem.networkConnect(wifiSSID, wifiPass)) {
SerialMon.println(" fail");
@ -158,7 +180,8 @@ void loop() {
SerialMon.println("Network connected");
}
#if TINY_GSM_USE_GPRS && defined TINY_GSM_MODEM_HAS_GPRS
#if TINY_GSM_USE_GPRS
// GPRS connection parameters are usually set after network registration
SerialMon.print(F("Connecting to "));
SerialMon.print(apn);
if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
@ -167,10 +190,14 @@ void loop() {
return;
}
SerialMon.println(" success");
if (modem.isGprsConnected()) {
SerialMon.println("GPRS connected");
}
#endif
SerialMon.print(F("Performing HTTPS GET request... "));
http.connectionKeepAlive(); // Currently, this is needed for HTTPS
http.connectionKeepAlive(); // Currently, this is needed for HTTPS
int err = http.get(resource);
if (err != 0) {
SerialMon.println(F("failed to connect"));


+ 69
- 45
examples/MqttClient/MqttClient.ino View File

@ -67,27 +67,29 @@
// Range to attempt to autobaud
#define GSM_AUTOBAUD_MIN 9600
#define GSM_AUTOBAUD_MAX 38400
#define GSM_AUTOBAUD_MAX 115200
// Add a reception delay - may be needed for a fast processor at a slow baud rate
//#define TINY_GSM_YIELD() { delay(2); }
// Define how you're planning to connect to the internet
#define TINY_GSM_USE_GPRS true
#define TINY_GSM_USE_WIFI false
// set GSM PIN, if any
#define GSM_PIN ""
// Your GPRS credentials
// Leave empty, if missing user or pass
const char apn[] = "YourAPN";
// Your GPRS credentials, if any
const char apn[] = "YourAPN";
const char gprsUser[] = "";
const char gprsPass[] = "";
const char wifiSSID[] = "YourSSID";
// Your WiFi connection credentials, if applicable
const char wifiSSID[] = "YourSSID";
const char wifiPass[] = "YourWiFiPass";
// MQTT details
const char* broker = "test.mosquitto.org";
const char* broker = "broker.hivemq.com";
const char* topicLed = "GsmClientTest/led";
const char* topicInit = "GsmClientTest/init";
@ -96,6 +98,20 @@ const char* topicLedStatus = "GsmClientTest/ledStatus";
#include <TinyGsmClient.h>
#include <PubSubClient.h>
// Just in case someone defined the wrong thing..
#if TINY_GSM_USE_GPRS && not defined TINY_GSM_MODEM_HAS_GPRS
#undef TINY_GSM_USE_GPRS
#undef TINY_GSM_USE_WIFI
#define TINY_GSM_USE_GPRS false
#define TINY_GSM_USE_WIFI true
#endif
#if TINY_GSM_USE_WIFI && not defined TINY_GSM_MODEM_HAS_WIFI
#undef TINY_GSM_USE_GPRS
#undef TINY_GSM_USE_WIFI
#define TINY_GSM_USE_GPRS true
#define TINY_GSM_USE_WIFI false
#endif
#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
@ -111,6 +127,42 @@ int ledStatus = LOW;
long lastReconnectAttempt = 0;
void mqttCallback(char* topic, byte* payload, unsigned int len) {
SerialMon.print("Message arrived [");
SerialMon.print(topic);
SerialMon.print("]: ");
SerialMon.write(payload, len);
SerialMon.println();
// Only proceed if incoming message's topic matches
if (String(topic) == topicLed) {
ledStatus = !ledStatus;
digitalWrite(LED_PIN, ledStatus);
mqtt.publish(topicLedStatus, ledStatus ? "1" : "0");
}
}
boolean mqttConnect() {
SerialMon.print("Connecting to ");
SerialMon.print(broker);
// Connect to MQTT Broker
boolean status = mqtt.connect("GsmClientTest");
// Or, if you want to authenticate MQTT:
//boolean status = mqtt.connect("GsmClientName", "mqtt_user", "mqtt_pass");
if (status == false) {
SerialMon.println(" fail");
return false;
}
SerialMon.println(" success");
mqtt.publish(topicInit, "GsmClientTest started");
mqtt.subscribe(topicLed);
return mqtt.connected();
}
void setup() {
// Set console baud rate
SerialMon.begin(115200);
@ -125,7 +177,8 @@ void setup() {
SerialMon.println("Wait...");
// Set GSM module baud rate
SerialAT.begin(115200);
// TinyGsmAutoBaud(SerialAT,GSM_AUTOBAUD_MIN,GSM_AUTOBAUD_MAX);
SerialAT.begin(9600);
delay(3000);
// Restart takes quite some time
@ -135,7 +188,7 @@ void setup() {
// modem.init();
String modemInfo = modem.getModemInfo();
SerialMon.print("Modem: ");
SerialMon.print("Modem Info: ");
SerialMon.println(modemInfo);
#if TINY_GSM_USE_GPRS
@ -145,7 +198,8 @@ void setup() {
}
#endif
#if defined TINY_GSM_USE_WIFI && defined TINY_GSM_MODEM_HAS_WIFI
#if TINY_GSM_USE_WIFI
// Wifi connection parameters must be set before waiting for the network
SerialMon.print(F("Setting SSID/password..."));
if (!modem.networkConnect(wifiSSID, wifiPass)) {
SerialMon.println(" fail");
@ -172,7 +226,8 @@ void setup() {
SerialMon.println("Network connected");
}
#if TINY_GSM_USE_GPRS && defined TINY_GSM_MODEM_HAS_GPRS
#if TINY_GSM_USE_GPRS
// GPRS connection parameters are usually set after network registration
SerialMon.print(F("Connecting to "));
SerialMon.print(apn);
if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
@ -181,6 +236,10 @@ void setup() {
return;
}
SerialMon.println(" success");
if (modem.isGprsConnected()) {
SerialMon.println("GPRS connected");
}
#endif
// MQTT Broker setup
@ -188,26 +247,6 @@ void setup() {
mqtt.setCallback(mqttCallback);
}
boolean mqttConnect() {
SerialMon.print("Connecting to ");
SerialMon.print(broker);
// Connect to MQTT Broker
boolean status = mqtt.connect("GsmClientTest");
// Or, if you want to authenticate MQTT:
//boolean status = mqtt.connect("GsmClientName", "mqtt_user", "mqtt_pass");
if (status == false) {
SerialMon.println(" fail");
return false;
}
SerialMon.println(" success");
mqtt.publish(topicInit, "GsmClientTest started");
mqtt.subscribe(topicLed);
return mqtt.connected();
}
void loop() {
if (!mqtt.connected()) {
@ -226,18 +265,3 @@ void loop() {
mqtt.loop();
}
void mqttCallback(char* topic, byte* payload, unsigned int len) {
SerialMon.print("Message arrived [");
SerialMon.print(topic);
SerialMon.print("]: ");
SerialMon.write(payload, len);
SerialMon.println();
// Only proceed if incoming message's topic matches
if (String(topic) == topicLed) {
ledStatus = !ledStatus;
digitalWrite(LED_PIN, ledStatus);
mqtt.publish(topicLedStatus, ledStatus ? "1" : "0");
}
}

+ 28
- 5
examples/WebClient/WebClient.ino View File

@ -62,17 +62,20 @@
// Uncomment this if you want to use SSL
//#define USE_SSL
// Define how you're planning to connect to the internet
#define TINY_GSM_USE_GPRS true
#define TINY_GSM_USE_WIFI false
// set GSM PIN, if any
#define GSM_PIN ""
// Your GPRS credentials
// Leave empty, if missing user or pass
// Your GPRS credentials, if any
const char apn[] = "YourAPN";
const char gprsUser[] = "";
const char gprsPass[] = "";
// Your WiFi connection credentials, if applicable
const char wifiSSID[] = "YourSSID";
const char wifiPass[] = "YourWiFiPass";
// Server details
@ -81,6 +84,20 @@ const char resource[] = "/TinyGSM/logo.txt";
#include <TinyGsmClient.h>
// Just in case someone defined the wrong thing..
#if TINY_GSM_USE_GPRS && not defined TINY_GSM_MODEM_HAS_GPRS
#undef TINY_GSM_USE_GPRS
#undef TINY_GSM_USE_WIFI
#define TINY_GSM_USE_GPRS false
#define TINY_GSM_USE_WIFI true
#endif
#if TINY_GSM_USE_WIFI && not defined TINY_GSM_MODEM_HAS_WIFI
#undef TINY_GSM_USE_GPRS
#undef TINY_GSM_USE_WIFI
#define TINY_GSM_USE_GPRS true
#define TINY_GSM_USE_WIFI false
#endif
#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
@ -120,7 +137,7 @@ void setup() {
// modem.init();
String modemInfo = modem.getModemInfo();
SerialMon.print("Modem: ");
SerialMon.print("Modem Info: ");
SerialMon.println(modemInfo);
#if TINY_GSM_USE_GPRS
@ -133,7 +150,8 @@ void setup() {
void loop() {
#if defined TINY_GSM_USE_WIFI && defined TINY_GSM_MODEM_HAS_WIFI
#if TINY_GSM_USE_WIFI
// Wifi connection parameters must be set before waiting for the network
SerialMon.print(F("Setting SSID/password..."));
if (!modem.networkConnect(wifiSSID, wifiPass)) {
SerialMon.println(" fail");
@ -160,7 +178,8 @@ void loop() {
SerialMon.println("Network connected");
}
#if TINY_GSM_USE_GPRS && defined TINY_GSM_MODEM_HAS_GPRS
#if TINY_GSM_USE_GPRS
// GPRS connection parameters are usually set after network registration
SerialMon.print(F("Connecting to "));
SerialMon.print(apn);
if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
@ -169,6 +188,10 @@ void loop() {
return;
}
SerialMon.println(" success");
if (modem.isGprsConnected()) {
SerialMon.println("GPRS connected");
}
#endif
SerialMon.print("Connecting to ");


+ 1
- 1
library.json View File

@ -1,6 +1,6 @@
{
"name": "TinyGSM",
"version": "0.9.7",
"version": "0.9.17",
"description": "A small Arduino library for GPRS modules, that just works. Includes examples for Blynk, MQTT, File Download, and Web Client. Supports many GSM, LTE, and WiFi modules with AT command interfaces.",
"keywords": "GSM, AT commands, AT, SIM800, SIM900, A6, A7, M590, ESP8266, SIM7000, SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868, SIM900A, SIM900D, SIM908, SIM968, M95, MC60, MC60E, BG96, ublox, Quectel, SIMCOM, AI Thinker, LTE, LTE-M",
"authors":


+ 1
- 1
library.properties View File

@ -1,5 +1,5 @@
name=TinyGSM
version=0.9.7
version=0.9.17
author=Volodymyr Shymanskyy
maintainer=Volodymyr Shymanskyy
sentence=A small Arduino library for GPRS modules, that just works.


+ 24
- 5
src/TinyGsmClientA6.h View File

@ -122,7 +122,7 @@ public:
{
memset(sockets, 0, sizeof(sockets));
}
virtual ~TinyGsmA6() {}
/*
@ -135,20 +135,38 @@ public:
bool init(const char* pin = NULL) {
DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION);
if (!testAT()) {
return false;
}
sendAT(GF("&FZE0")); // Factory + Reset + Echo Off
if (waitResponse() != 1) {
return false;
}
sendAT(GF("+CMEE=0")); // Turn off verbose errors
#ifdef TINY_GSM_DEBUG
sendAT(GF("+CMEE=2")); // turn on verbose error codes
#else
sendAT(GF("+CMEE=0")); // turn off error codes
#endif
waitResponse();
sendAT(GF("+CMER=3,0,0,2")); // Set unsolicited result code output destination
waitResponse();
DBG(GF("### Modem:"), getModemName());
getSimStatus();
return true;
int ret = getSimStatus();
// if the sim isn't ready and a pin has been provided, try to unlock the sim
if (ret != SIM_READY && pin != NULL && strlen(pin) > 0) {
simUnlock(pin);
return (getSimStatus() == SIM_READY);
}
// if the sim is ready, or it's locked but no pin has been provided, return
// true
else {
return (ret == SIM_READY || ret == SIM_LOCKED);
}
}
String getModemName() {
@ -525,6 +543,7 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK()
}
chargeState = stream.readStringUntil(',').toInt();
percent = stream.readStringUntil('\n').toInt();
milliVolts = 0;
// Wait for final OK
waitResponse();
return true;
@ -562,7 +581,7 @@ protected:
}
int16_t modemSend(const void* buff, size_t len, uint8_t mux) {
sendAT(GF("+CIPSEND="), mux, ',', len);
sendAT(GF("+CIPSEND="), mux, ',', (uint16_t)len);
if (waitResponse(2000L, GF(GSM_NL ">")) != 1) {
return 0;
}


+ 29
- 12
src/TinyGsmClientBG96.h View File

@ -158,16 +158,29 @@ public:
bool init(const char* pin = NULL) {
DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION);
if (!testAT()) {
return false;
}
sendAT(GF("&FZE0")); // Factory + Reset + Echo Off
if (waitResponse() != 1) {
return false;
}
DBG(GF("### Modem:"), getModemName());
getSimStatus();
return true;
int ret = getSimStatus();
// if the sim isn't ready and a pin has been provided, try to unlock the sim
if (ret != SIM_READY && pin != NULL && strlen(pin) > 0) {
simUnlock(pin);
return (getSimStatus() == SIM_READY);
}
// if the sim is ready, or it's locked but no pin has been provided, return
// true
else {
return (ret == SIM_READY || ret == SIM_LOCKED);
}
}
String getModemName() {
@ -496,11 +509,13 @@ TINY_GSM_MODEM_GET_GPRS_IP_CONNECTED()
protected:
bool modemConnect(const char* host, uint16_t port, uint8_t mux,
bool ssl = false, int timeout_s = 20)
{
int rsp;
uint32_t timeout_ms = ((uint32_t)timeout_s)*1000;
bool modemConnect(const char* host, uint16_t port, uint8_t mux,
bool ssl = false, int timeout_s = 20) {
if (ssl) {
DBG("SSL not yet supported on this module!");
}
int rsp;
uint32_t timeout_ms = ((uint32_t)timeout_s) * 1000;
// <PDPcontextID>(1-16), <connectID>(0-11),"TCP/UDP/TCP LISTENER/UDP SERVICE",
// "<IP_address>/<domain_name>",<remote_port>,<local_port>,<access_mode>(0-2 0=buffer)
@ -521,7 +536,7 @@ protected:
}
int16_t modemSend(const void* buff, size_t len, uint8_t mux) {
sendAT(GF("+QISEND="), mux, ',', len);
sendAT(GF("+QISEND="), mux, ',', (uint16_t)len);
if (waitResponse(GF(">")) != 1) {
return 0;
}
@ -535,13 +550,13 @@ protected:
}
size_t modemRead(size_t size, uint8_t mux) {
sendAT(GF("+QIRD="), mux, ',', size);
sendAT(GF("+QIRD="), mux, ',', (uint16_t)size);
if (waitResponse(GF("+QIRD:")) != 1) {
return 0;
}
size_t len = stream.readStringUntil('\n').toInt();
int len = stream.readStringUntil('\n').toInt();
for (size_t i=0; i<len; i++) {
for (int i=0; i<len; i++) {
TINY_GSM_MODEM_STREAM_TO_MUX_FIFO_WITH_DOUBLE_TIMEOUT
}
waitResponse();
@ -557,7 +572,9 @@ protected:
streamSkipUntil(','); // Skip total received
streamSkipUntil(','); // Skip have read
result = stream.readStringUntil('\n').toInt();
if (result) DBG("### DATA AVAILABLE:", result, "on", mux);
if (result) {
DBG("### DATA AVAILABLE:", result, "on", mux);
}
waitResponse();
}
if (!result) {


+ 59
- 26
src/TinyGsmClientESP8266.h View File

@ -31,15 +31,14 @@ static unsigned TINY_GSM_TCP_KEEP_ALIVE = 120;
// 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,
REG_OK_IP = 2,
REG_OK_TCP = 3,
REG_OK_NO_TCP = 4,
REG_DENIED = 5,
REG_UNKNOWN = 6,
};
class TinyGsmESP8266
{
@ -157,6 +156,9 @@ public:
if (!testAT()) {
return false;
}
if (pin && strlen(pin) > 0) {
DBG("ESP8266 modules do not use an unlock pin!");
}
sendAT(GF("E0")); // Echo Off
if (waitResponse() != 1) {
return false;
@ -249,7 +251,8 @@ TINY_GSM_MODEM_MAINTAIN_LISTEN()
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"));
int status =
waitResponse(GFP(GSM_ERROR), GF("2"), GF("3"), GF("4"), GF("5"));
waitResponse(); // Returns an OK after the status
return (RegStatus)status;
}
@ -275,25 +278,26 @@ TINY_GSM_MODEM_MAINTAIN_LISTEN()
bool isNetworkConnected() {
RegStatus s = getRegistrationStatus();
return (s == REG_OK_IP || s == REG_OK_TCP);
}
bool waitForNetwork(unsigned long timeout_ms = 60000L) {
for (unsigned long start = millis(); millis() - start < timeout_ms; ) {
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) {
waitResponse();
return true;
}
}
delay(250);
if (s == REG_OK_IP || s == REG_OK_TCP) {
// with these, we're definitely connected
return true;
}
else if (s == REG_OK_NO_TCP) {
// with this, we may or may not be connected
if (getLocalIP() == "") {
return false;
}
else {
return true;
}
}
else {
return false;
}
return false;
}
TINY_GSM_MODEM_WAIT_FOR_NETWORK()
/*
* WiFi functions
*/
@ -370,7 +374,7 @@ protected:
}
int16_t modemSend(const void* buff, size_t len, uint8_t mux) {
sendAT(GF("+CIPSEND="), mux, ',', len);
sendAT(GF("+CIPSEND="), mux, ',', (uint16_t)len);
if (waitResponse(GF(">")) != 1) {
return 0;
}
@ -383,8 +387,37 @@ protected:
}
bool modemGetConnected(uint8_t mux) {
RegStatus s = getRegistrationStatus();
return (s == REG_OK_IP || s == REG_OK_TCP);
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"));
if (status != 3) {
// if the status is anything but 3, there are no connections open
waitResponse(); // Returns an OK after the status
for (int muxNo = 0; muxNo < TINY_GSM_MUX_COUNT; muxNo++) {
sockets[muxNo]->sock_connected = false;
}
return false;
}
bool verified_connections[TINY_GSM_MUX_COUNT] = {0, 0, 0, 0, 0};
for (int muxNo = 0; muxNo < TINY_GSM_MUX_COUNT; muxNo++) {
uint8_t has_status = waitResponse(GF("+CIPSTATUS:"), GFP(GSM_OK), GFP(GSM_ERROR));
if (has_status == 1) {
int returned_mux = stream.readStringUntil(',').toInt();
streamSkipUntil(','); // Skip mux
streamSkipUntil(','); // Skip type
streamSkipUntil(','); // Skip remote IP
streamSkipUntil(','); // Skip remote port
streamSkipUntil(','); // Skip local port
streamSkipUntil('\n'); // Skip client/server type
verified_connections[returned_mux] = 1;
}
if (has_status == 2) break; // once we get to the ok, stop
}
for (int muxNo = 0; muxNo < TINY_GSM_MUX_COUNT; muxNo++) {
sockets[muxNo]->sock_connected = verified_connections[muxNo];
}
return verified_connections[mux];
}
public:


+ 21
- 5
src/TinyGsmClientM590.h View File

@ -133,20 +133,36 @@ public:
bool init(const char* pin = NULL) {
DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION);
if (!testAT()) {
return false;
}
sendAT(GF("&FZE0")); // Factory + Reset + Echo Off
if (waitResponse() != 1) {
return false;
}
#ifdef TINY_GSM_DEBUG
sendAT(GF("+CMEE=2"));
waitResponse();
sendAT(GF("+CMEE=2")); // turn on verbose error codes
#else
sendAT(GF("+CMEE=0")); // turn off error codes
#endif
waitResponse();
DBG(GF("### Modem:"), getModemName());
getSimStatus();
return true;
int ret = getSimStatus();
// if the sim isn't ready and a pin has been provided, try to unlock the sim
if (ret != SIM_READY && pin != NULL && strlen(pin) > 0) {
simUnlock(pin);
return (getSimStatus() == SIM_READY);
}
// if the sim is ready, or it's locked but no pin has been provided, return
// true
else {
return (ret == SIM_READY || ret == SIM_LOCKED);
}
}
String getModemName() {
@ -443,7 +459,7 @@ protected:
}
int16_t modemSend(const void* buff, size_t len, uint8_t mux) {
sendAT(GF("+TCPSEND="), mux, ',', len);
sendAT(GF("+TCPSEND="), mux, ',', (uint16_t)len);
if (waitResponse(GF(">")) != 1) {
return 0;
}


+ 128
- 63
src/TinyGsmClientM95.h View File

@ -64,7 +64,6 @@ public:
this->mux = mux;
sock_available = 0;
sock_connected = false;
got_data = false;
at->sockets[mux] = this;
@ -110,7 +109,6 @@ private:
uint8_t mux;
uint16_t sock_available;
bool sock_connected;
bool got_data;
RxFifo rx;
};
@ -157,20 +155,36 @@ public:
bool init(const char* pin = NULL) {
DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION);
if (!testAT()) {
return false;
}
sendAT(GF("&FZE0")); // Factory + Reset + Echo Off
if (waitResponse() != 1) {
return false;
}
#ifdef TINY_GSM_DEBUG
sendAT(GF("+CMEE=2"));
waitResponse();
sendAT(GF("+CMEE=2")); // turn on verbose error codes
#else
sendAT(GF("+CMEE=0")); // turn off error codes
#endif
waitResponse();
DBG(GF("### Modem:"), getModemName());
getSimStatus();
return true;
int ret = getSimStatus();
// if the sim isn't ready and a pin has been provided, try to unlock the sim
if (ret != SIM_READY && pin != NULL && strlen(pin) > 0) {
simUnlock(pin);
return (getSimStatus() == SIM_READY);
}
// if the sim is ready, or it's locked but no pin has been provided, return
// true
else {
return (ret == SIM_READY || ret == SIM_LOCKED);
}
}
String getModemName() {
@ -324,36 +338,71 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK()
return false;
}
//Start TCPIP Task and Set APN, User Name and Password
sendAT("+QIREGAPP=\"", apn, "\",\"", user, "\",\"", pwd, "\"" );
// Select TCP/IP transfer mode - NOT transparent mode
sendAT(GF("+QIMODE=0"));
if (waitResponse() != 1) {
return false;
}
//Activate GPRS/CSD Context
sendAT(GF("+QIACT"));
if (waitResponse(10000) != 1) {
// Enable multiple TCP/IP connections
sendAT(GF("+QIMUX=1"));
if (waitResponse() != 1) {
return false;
}
//Enable multiple TCP/IP connections
sendAT(GF("+QIMUX=1"));
//Start TCPIP Task and Set APN, User Name and Password
sendAT("+QIREGAPP=\"", apn, "\",\"", user, "\",\"", pwd, "\"" );
if (waitResponse() != 1) {
return false;
}
//Request an IP header for received data ("IPD(data length):")
sendAT(GF("+QIHEAD=1"));
if (waitResponse() != 1) {
//Activate GPRS/CSD Context
sendAT(GF("+QIACT"));
if (waitResponse(60000L) != 1) {
return false;
}
//Set Method to Handle Received TCP/IP Data - Retrieve Data by Command
// Check that we have a local IP address
if (localIP() == IPAddress(0,0,0,0)) {
return false;
}
// Set Method to Handle Received TCP/IP Data
// Mode = 1 - Output a notification when data is received
// +QIRDI: <id>,<sc>,<sid>
sendAT(GF("+QINDI=1"));
if (waitResponse() != 1) {
return false;
}
// // Request an IP header for received data
// // "IPD(data length):"
// sendAT(GF("+QIHEAD=1"));
// if (waitResponse() != 1) {
// return false;
// }
//
// // Do NOT show the IP address of the sender when receiving data
// // The format to show the address is: RECV FROM: <IP ADDRESS>:<PORT>
// sendAT(GF("+QISHOWRA=0"));
// if (waitResponse() != 1) {
// return false;
// }
//
// // Do NOT show the protocol type at the end of the header for received data
// // IPD(data length)(TCP/UDP):
// sendAT(GF("+QISHOWPT=0"));
// if (waitResponse() != 1) {
// return false;
// }
//
// // Do NOT show the destination address before receiving data
// // The format to show the address is: TO:<IP ADDRESS>
// sendAT(GF("+QISHOWLA=0"));
// if (waitResponse() != 1) {
// return false;
// }
return true;
}
@ -556,20 +605,22 @@ TINY_GSM_MODEM_GET_GPRS_IP_CONNECTED()
protected:
bool modemConnect(const char* host, uint16_t port, uint8_t mux,
bool ssl = false, int timeout_s = 75)
{
uint32_t timeout_ms = ((uint32_t)timeout_s)*1000;
sendAT(GF("+QIOPEN="), mux, GF("\"TCP"), GF("\",\""), host, GF("\","), port);
bool modemConnect(const char* host, uint16_t port, uint8_t mux,
bool ssl = false, int timeout_s = 75) {
if (ssl) {
DBG("SSL not yet supported on this module!");
}
uint32_t timeout_ms = ((uint32_t)timeout_s) * 1000;
sendAT(GF("+QIOPEN="), mux, GF(",\""), GF("TCP"), GF("\",\""), host, GF("\","), port);
int rsp = waitResponse(timeout_ms,
GF("CONNECT OK" GSM_NL),
GF("CONNECT FAIL" GSM_NL),
GF("ALREADY CONNECT" GSM_NL));
return (1 == rsp);
return (1 == rsp);
}
int16_t modemSend(const void* buff, size_t len, uint8_t mux) {
sendAT(GF("+QISEND="), mux, ',', len);
sendAT(GF("+QISEND="), mux, ',', (uint16_t)len);
if (waitResponse(GF(">")) != 1) {
return 0;
}
@ -579,51 +630,62 @@ protected:
return 0;
}
bool allAcknowledged = false;
// bool failed = false;
while ( !allAcknowledged ) {
sendAT( GF("+QISACK"));
if (waitResponse(5000L, GF(GSM_NL "+QISACK:")) != 1) {
return -1;
} else {
streamSkipUntil(','); /** Skip total */
streamSkipUntil(','); /** Skip acknowledged data size */
if ( stream.readStringUntil('\n').toInt() == 0 ) {
allAcknowledged = true;
}
}
}
waitResponse(5000L);
// bool allAcknowledged = false;
// // bool failed = false;
// while ( !allAcknowledged ) {
// sendAT( GF("+QISACK"));
// if (waitResponse(5000L, GF(GSM_NL "+QISACK:")) != 1) {
// return -1;
// } else {
// streamSkipUntil(','); // Skip total length sent on connection
// streamSkipUntil(','); // Skip length already acknowledged by remote
// // Make sure the total length un-acknowledged is 0
// if ( stream.readStringUntil('\n').toInt() == 0 ) {
// allAcknowledged = true;
// }
// }
// }
// waitResponse(5000L);
// streamSkipUntil(','); // Skip mux
// return stream.readStringUntil('\n').toInt();
return len; // TODO
}
size_t modemRead(size_t size, uint8_t mux) {
// TODO: Does this work????
// AT+QIRD=<id>,<sc>,<sid>,<len>
// id = GPRS context number - 0, set in GPRS connect
// sc = roll in connection - 1, client of connection
// sid = index of connection - mux
// len = maximum length of data to send
sendAT(GF("+QIRD=0,1,"), mux, ',', size);
// sendAT(GF("+QIRD="), mux, ',', size);
if (waitResponse(GF("+QIRD:")) != 1) {
return 0;
}
streamSkipUntil(':'); // skip IP address
streamSkipUntil(','); // skip port
streamSkipUntil(','); // skip connection type (TCP/UDP)
size_t len = stream.readStringUntil('\n').toInt(); // read length
for (size_t i=0; i<len; i++) {
TINY_GSM_MODEM_STREAM_TO_MUX_FIFO_WITH_DOUBLE_TIMEOUT
sockets[mux]->sock_available--;
// ^^ One less character available after moving from modem's FIFO to our FIFO
// id = GPRS context number = 0, set in GPRS connect
// sc = role in connection = 1, client of connection
// sid = index of connection = mux
// len = maximum length of data to retrieve
sendAT(GF("+QIRD=0,1,"), mux, ',', (uint16_t)size);
// If it replies only OK for the write command, it means there is no
// received data in the buffer of the connection.
int res = waitResponse(GF("+QIRD:"), GFP(GSM_OK), GFP(GSM_ERROR));
if (res == 1) {
streamSkipUntil(':'); // skip IP address
streamSkipUntil(','); // skip port
streamSkipUntil(','); // skip connection type (TCP/UDP)
// read the real length of the retrieved data
uint16_t len = stream.readStringUntil('\n').toInt();
// We have no way of knowing in advance how much data will be in the buffer
// so when data is received we always assume the buffer is completely full.
// Chances are, this is not true and there's really not that much there.
// In that case, make sure we make sure we re-set the amount of data available.
if (len < size) {
sockets[mux]->sock_available = len;
}
for (uint16_t i=0; i<len; i++) {
TINY_GSM_MODEM_STREAM_TO_MUX_FIFO_WITH_DOUBLE_TIMEOUT
sockets[mux]->sock_available--;
// ^^ One less character available after moving from modem's FIFO to our FIFO
}
waitResponse(); // ends with an OK
DBG("### READ:", len, "from", mux);
return len;
} else {
sockets[mux]->sock_available = 0;
return 0;
}
waitResponse(); // ends with an OK
DBG("### READ:", len, "from", mux);
return len;
}
bool modemGetConnected(uint8_t mux) {
@ -690,14 +752,17 @@ TINY_GSM_MODEM_STREAM_UTILITIES()
} else if (r5 && data.endsWith(r5)) {
index = 5;
goto finish;
} else if (data.endsWith(GF(GSM_NL "+QIRD:"))) { // TODO: QIRD? or QIRDI?
} else if (data.endsWith(GF(GSM_NL "+QIRDI:"))) {
streamSkipUntil(','); // Skip the context
streamSkipUntil(','); // Skip the role
int mux = stream.readStringUntil('\n').toInt();
DBG("### Got Data:", mux);
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
// We have no way of knowing how much data actually came in, so
// we set the value to 1500, the maximum possible size.
sockets[mux]->sock_available = 1500;
}
data = "";
} else if (data.endsWith(GF("CLOSED" GSM_NL))) {
int nl = data.lastIndexOf(GSM_NL, data.length()-8);
int coma = data.indexOf(',', nl+2);


+ 80
- 45
src/TinyGsmClientMC60.h View File

@ -68,7 +68,6 @@ public:
this->mux = mux;
sock_available = 0;
sock_connected = false;
got_data = false;
at->sockets[mux] = this;
@ -114,7 +113,6 @@ private:
uint8_t mux;
uint16_t sock_available;
bool sock_connected;
bool got_data;
RxFifo rx;
};
@ -161,18 +159,32 @@ public:
bool init(const char* pin = NULL) {
DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION);
if (!testAT()) {
return false;
}
sendAT(GF("&FZ")); // Factory + Reset
waitResponse();
sendAT(GF("E0")); // Echo Off
if (waitResponse() != 1) {
return false;
}
DBG(GF("### Modem:"), getModemName());
getSimStatus();
return true;
int ret = getSimStatus();
// if the sim isn't ready and a pin has been provided, try to unlock the sim
if (ret != SIM_READY && pin != NULL && strlen(pin) > 0) {
simUnlock(pin);
return (getSimStatus() == SIM_READY);
}
// if the sim is ready, or it's locked but no pin has been provided, return
// true
else {
return (ret == SIM_READY || ret == SIM_LOCKED);
}
}
String getModemName() {
@ -338,42 +350,44 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK()
sendAT(GF("+CGACT=1,1"));
waitResponse(60000L);
//Start TCPIP Task and Set APN, User Name and Password
sendAT("+QIREGAPP=\"", apn, "\",\"", user, "\",\"", pwd, "\"" );
// Select TCP/IP transfer mode - NOT transparent mode
sendAT(GF("+QIMODE=0"));
if (waitResponse() != 1) {
return false;
}
//Activate GPRS/CSD Context
sendAT(GF("+QIACT"));
if (waitResponse(60000L) != 1) {
return false;
}
//Enable multiple TCP/IP connections
// Enable multiple TCP/IP connections
sendAT(GF("+QIMUX=1"));
if (waitResponse() != 1) {
return false;
}
//Request an IP header for received data ("IPD(data length):")
sendAT(GF("+QIHEAD=1"));
//Start TCPIP Task and Set APN, User Name and Password
sendAT("+QIREGAPP=\"", apn, "\",\"", user, "\",\"", pwd, "\"" );
if (waitResponse() != 1) {
return false;
}
//Set Method to Handle Received TCP/IP Data - Retrieve Data by Command
sendAT(GF("+QINDI=1"));
if (waitResponse() != 1) {
//Activate GPRS/CSD Context
sendAT(GF("+QIACT"));
if (waitResponse(60000L) != 1) {
return false;
}
// Check that we have a local IP address
if (localIP() != IPAddress(0,0,0,0)) {
return true;
if (localIP() == IPAddress(0,0,0,0)) {
return false;
}
return false;
//Set Method to Handle Received TCP/IP Data
// Mode=2 - Output a notification statement:
// +QIRDI: <id>,<sc>,<sid>,<num>,<len>,< tlen>
sendAT(GF("+QINDI=2"));
if (waitResponse() != 1) {
return false;
}
return true;
}
bool gprsDisconnect() {
@ -563,10 +577,12 @@ TINY_GSM_MODEM_GET_GPRS_IP_CONNECTED()
protected:
bool modemConnect(const char* host, uint16_t port, uint8_t mux,
bool ssl = false, int timeout_s = 75)
{
uint32_t timeout_ms = ((uint32_t)timeout_s)*1000;
sendAT(GF("+QIOPEN="), mux, GF("\"TCP"), GF("\",\""), host, GF("\","), port);
bool ssl = false, int timeout_s = 75) {
if (ssl) {
DBG("SSL not yet supported on this module!");
}
uint32_t timeout_ms = ((uint32_t)timeout_s) * 1000;
sendAT(GF("+QIOPEN="), mux, GF(",\""), GF("TCP"), GF("\",\""), host, GF("\","), port);
int rsp = waitResponse(timeout_ms,
GF("CONNECT OK" GSM_NL),
GF("CONNECT FAIL" GSM_NL),
@ -575,7 +591,7 @@ protected:
}
int16_t modemSend(const void* buff, size_t len, uint8_t mux) {
sendAT(GF("+QISEND="), mux, ',', len);
sendAT(GF("+QISEND="), mux, ',', (uint16_t)len);
if (waitResponse(GF(">")) != 1) {
return 0;
}
@ -614,23 +630,35 @@ protected:
// sc = roll in connection - 1, client of connection
// sid = index of connection - mux
// len = maximum length of data to send
sendAT(GF("+QIRD=0,1,"), mux, ',', size);
// sendAT(GF("+QIRD="), mux, ',', size);
if (waitResponse(GF("+QIRD:")) != 1) {
return 0;
}
streamSkipUntil(':'); // skip IP address
streamSkipUntil(','); // skip port
streamSkipUntil(','); // skip connection type (TCP/UDP)
size_t len = stream.readStringUntil('\n').toInt(); // read length
for (size_t i=0; i<len; i++) {
TINY_GSM_MODEM_STREAM_TO_MUX_FIFO_WITH_DOUBLE_TIMEOUT
sockets[mux]->sock_available--;
// ^^ One less character available after moving from modem's FIFO to our FIFO
sendAT(GF("+QIRD=0,1,"), mux, ',', (uint16_t)size);
// If it replies only OK for the write command, it means there is no
// received data in the buffer of the connection.
int res = waitResponse(GF("+QIRD:"), GFP(GSM_OK), GFP(GSM_ERROR));
if (res == 1) {
streamSkipUntil(':'); // skip IP address
streamSkipUntil(','); // skip port
streamSkipUntil(','); // skip connection type (TCP/UDP)
// read the real length of the retrieved data
uint16_t len = stream.readStringUntil('\n').toInt();
// It's possible that the real length available is less than expected
// This is quite likely if the buffer is broken into packets - which may
// be different sizes.
// If so, make sure we make sure we re-set the amount of data available.
if (len < size) {
sockets[mux]->sock_available = len;
}
for (uint16_t i=0; i<len; i++) {
TINY_GSM_MODEM_STREAM_TO_MUX_FIFO_WITH_DOUBLE_TIMEOUT
sockets[mux]->sock_available--;
// ^^ One less character available after moving from modem's FIFO to our FIFO
}
waitResponse();
DBG("### READ:", len, "from", mux);
return len;
} else {
sockets[mux]->sock_available = 0;
return 0;
}
waitResponse();
DBG("### READ:", len, "from", mux);
return len;
}
bool modemGetConnected(uint8_t mux) {
@ -702,13 +730,20 @@ TINY_GSM_MODEM_STREAM_UTILITIES()
index = 6;
goto finish;
} else if (data.endsWith(GF(GSM_NL "+QIRD:"))) { // TODO: QIRD? or QIRDI?
// +QIRDI: <id>,<sc>,<sid>,<num>,<len>,< tlen>
streamSkipUntil(','); // Skip the context
streamSkipUntil(','); // Skip the role
int mux = stream.readStringUntil('\n').toInt();
DBG("### Got Data:", mux);
// read the connection id
int mux = stream.readStringUntil(',').toInt();
// read the number of packets in the buffer
int num_packets = stream.readStringUntil(',').toInt();
// read the length of the current packet
int len_packet = stream.readStringUntil('\n').toInt();
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
sockets[mux]->sock_available = len_packet*num_packets;
}
data = "";
DBG("### Got Data:", len, "on", mux);
} else if (data.endsWith(GF("CLOSED" GSM_NL))) {
int nl = data.lastIndexOf(GSM_NL, data.length()-8);
int coma = data.indexOf(',', nl+2);


+ 28
- 10
src/TinyGsmClientSIM5360.h View File

@ -142,16 +142,29 @@ public:
bool init(const char* pin = NULL) {
DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION);
if (!testAT()) {
return false;
}
sendAT(GF("E0")); // Echo Off
if (waitResponse() != 1) {
return false;
}
DBG(GF("### Modem:"), getModemName());
getSimStatus();
return true;
int ret = getSimStatus();
// if the sim isn't ready and a pin has been provided, try to unlock the sim
if (ret != SIM_READY && pin != NULL && strlen(pin) > 0) {
simUnlock(pin);
return (getSimStatus() == SIM_READY);
}
// if the sim is ready, or it's locked but no pin has been provided, return
// true
else {
return (ret == SIM_READY || ret == SIM_LOCKED);
}
}
String getModemName() {
@ -640,24 +653,29 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK()
protected:
bool modemConnect(const char* host, uint16_t port, uint8_t mux,
bool ssl = false, int timeout_s = 75) {
bool ssl = false, int timeout_s = 15) {
// Make sure we'll be getting data manually on this connection
sendAT(GF("+CIPRXGET=1"));
if (waitResponse() != 1) {
return false;
}
if (ssl) {
DBG("SSL not yet supported on this module!");
}
// Establish a connection in multi-socket mode
uint32_t timeout_ms = ((uint32_t)timeout_s) * 1000;
sendAT(GF("+CIPOPEN="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port);
// The reply is +CIPOPEN: ## of socket created
if (waitResponse(15000L, GF(GSM_NL "+CIPOPEN:")) != 1) {
if (waitResponse(timeout_ms, GF(GSM_NL "+CIPOPEN:")) != 1) {
return false;
}
return true;
}
int16_t modemSend(const void* buff, size_t len, uint8_t mux) {
sendAT(GF("+CIPSEND="), mux, ',', len);
sendAT(GF("+CIPSEND="), mux, ',', (uint16_t)len);
if (waitResponse(GF(">")) != 1) {
return 0;
}
@ -674,23 +692,23 @@ protected:
size_t modemRead(size_t size, uint8_t mux) {
#ifdef TINY_GSM_USE_HEX
sendAT(GF("+CIPRXGET=3,"), mux, ',', size);
sendAT(GF("+CIPRXGET=3,"), mux, ',', (uint16_t)size);
if (waitResponse(GF("+CIPRXGET:")) != 1) {
return 0;
}
#else
sendAT(GF("+CIPRXGET=2,"), mux, ',', size);
sendAT(GF("+CIPRXGET=2,"), mux, ',', (uint16_t)size);
if (waitResponse(GF("+CIPRXGET:")) != 1) {
return 0;
}
#endif
streamSkipUntil(','); // Skip Rx mode 2/normal or 3/HEX
streamSkipUntil(','); // Skip mux/cid (connecion id)
size_t len_requested = stream.readStringUntil(',').toInt();
int len_requested = stream.readStringUntil(',').toInt();
// ^^ Requested number of data bytes (1-1460 bytes)to be read
size_t len_confirmed = stream.readStringUntil('\n').toInt();
int len_confirmed = stream.readStringUntil('\n').toInt();
// ^^ The data length which not read in the buffer
for (size_t i=0; i<len_requested; i++) {
for (int i=0; i<len_requested; i++) {
uint32_t startMillis = millis();
#ifdef TINY_GSM_USE_HEX
while (stream.available() < 2 && (millis() - startMillis < sockets[mux]->_timeout)) { TINY_GSM_YIELD(); }


+ 37
- 22
src/TinyGsmClientSIM7000.h View File

@ -166,16 +166,29 @@ public:
bool init(const char* pin = NULL) {
DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION);
if (!testAT()) {
return false;
}
sendAT(GF("E0")); // Echo Off
if (waitResponse() != 1) {
return false;
}
DBG(GF("### Modem:"), getModemName());
getSimStatus();
return true;
int ret = getSimStatus();
// if the sim isn't ready and a pin has been provided, try to unlock the sim
if (ret != SIM_READY && pin != NULL && strlen(pin) > 0) {
simUnlock(pin);
return (getSimStatus() == SIM_READY);
}
// if the sim is ready, or it's locked but no pin has been provided, return
// true
else {
return (ret == SIM_READY || ret == SIM_LOCKED);
}
}
String getModemName() {
@ -800,24 +813,26 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK()
protected:
bool modemConnect(const char* host, uint16_t port, uint8_t mux,
bool ssl = false, int timeout_s = 75)
{
int rsp;
uint32_t timeout_ms = ((uint32_t)timeout_s)*1000;
sendAT(GF("+CIPSTART="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port);
rsp = waitResponse(timeout_ms,
GF("CONNECT OK" GSM_NL),
GF("CONNECT FAIL" GSM_NL),
GF("ALREADY CONNECT" GSM_NL),
GF("ERROR" GSM_NL),
GF("CLOSE OK" GSM_NL) // Happens when HTTPS handshake fails
);
return (1 == rsp);
bool modemConnect(const char* host, uint16_t port, uint8_t mux,
bool ssl = false, int timeout_s = 75) {
if (ssl) {
DBG("SSL not yet supported on this module!");
}
int rsp;
uint32_t timeout_ms = ((uint32_t)timeout_s) * 1000;
sendAT(GF("+CIPSTART="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","),
port);
rsp = waitResponse(
timeout_ms, GF("CONNECT OK" GSM_NL), GF("CONNECT FAIL" GSM_NL),
GF("ALREADY CONNECT" GSM_NL), GF("ERROR" GSM_NL),
GF("CLOSE OK" GSM_NL) // Happens when HTTPS handshake fails
);
return (1 == rsp);
}
int16_t modemSend(const void* buff, size_t len, uint8_t mux) {
sendAT(GF("+CIPSEND="), mux, ',', len);
sendAT(GF("+CIPSEND="), mux, ',', (uint16_t)len);
if (waitResponse(GF(">")) != 1) {
return 0;
}
@ -832,25 +847,25 @@ protected:
size_t modemRead(size_t size, uint8_t mux) {
#ifdef TINY_GSM_USE_HEX
sendAT(GF("+CIPRXGET=3,"), mux, ',', size);
sendAT(GF("+CIPRXGET=3,"), mux, ',', (uint16_t)size);
if (waitResponse(GF("+CIPRXGET:")) != 1) {
return 0;
}
#else
sendAT(GF("+CIPRXGET=2,"), mux, ',', size);
sendAT(GF("+CIPRXGET=2,"), mux, ',', (uint16_t)size);
if (waitResponse(GF("+CIPRXGET:")) != 1) {
return 0;
}
#endif
streamSkipUntil(','); // Skip Rx mode 2/normal or 3/HEX
streamSkipUntil(','); // Skip mux
size_t len_requested = stream.readStringUntil(',').toInt();
int len_requested = stream.readStringUntil(',').toInt();
// ^^ Requested number of data bytes (1-1460 bytes)to be read
size_t len_confirmed = stream.readStringUntil('\n').toInt();
int len_confirmed = stream.readStringUntil('\n').toInt();
// ^^ Confirmed number of data bytes to be read, which may be less than requested.
// 0 indicates that no data can be read.
// This is actually be the number of bytes that will be remaining after the read
for (size_t i=0; i<len_requested; i++) {
for (int i=0; i<len_requested; i++) {
uint32_t startMillis = millis();
#ifdef TINY_GSM_USE_HEX
while (stream.available() < 2 && (millis() - startMillis < sockets[mux]->_timeout)) { TINY_GSM_YIELD(); }


+ 54
- 43
src/TinyGsmClientSIM7600.h View File

@ -142,16 +142,29 @@ public:
bool init(const char* pin = NULL) {
DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION);
if (!testAT()) {
return false;
}
sendAT(GF("E0")); // Echo Off
if (waitResponse() != 1) {
return false;
}
DBG(GF("### Modem:"), getModemName());
getSimStatus();
return true;
int ret = getSimStatus();
// if the sim isn't ready and a pin has been provided, try to unlock the sim
if (ret != SIM_READY && pin != NULL && strlen(pin) > 0) {
simUnlock(pin);
return (getSimStatus() == SIM_READY);
}
// if the sim is ready, or it's locked but no pin has been provided, return
// true
else {
return (ret == SIM_READY || ret == SIM_LOCKED);
}
}
String getModemName() {
@ -555,7 +568,7 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK()
}
// get GPS informations
bool getGPS(float *lat, float *lon, float *speed=0, int *alt=0, int *vsat=0, int *usat=0) {
bool getGPS(float *lat, float *lon, float *speed=0, int *alt=0) {
//String buffer = "";
bool fix = false;
@ -567,14 +580,14 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK()
//stream.readStringUntil(','); // mode
if ( stream.readStringUntil(',').toInt() == 1 ) fix = true;
stream.readStringUntil(','); //gps
stream.readStringUntil(','); // glonass
stream.readStringUntil(','); // beidu
stream.readStringUntil(','); // glonass
stream.readStringUntil(','); // beidu
*lat = stream.readStringUntil(',').toFloat(); //lat
stream.readStringUntil(','); // N/S
stream.readStringUntil(','); // N/S
*lon = stream.readStringUntil(',').toFloat(); //lon
stream.readStringUntil(','); // E/W
stream.readStringUntil(','); // date
stream.readStringUntil(','); // UTC time
stream.readStringUntil(','); // E/W
stream.readStringUntil(','); // date
stream.readStringUntil(','); // UTC time
if (alt != NULL) *alt = stream.readStringUntil(',').toFloat(); //alt
if (speed != NULL) *speed = stream.readStringUntil(',').toFloat(); //speed
stream.readStringUntil(','); //course
@ -582,8 +595,6 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK()
stream.readStringUntil(',');//PDOP
stream.readStringUntil(',');//HDOP
stream.readStringUntil(',');//VDOP
//if (vsat != NULL) *vsat = stream.readStringUntil(',').toInt(); //viewed satelites
//if (usat != NULL) *usat = stream.readStringUntil(',').toInt(); //used satelites
stream.readStringUntil('\n');
waitResponse();
@ -610,7 +621,7 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK()
// Wait for final OK
waitResponse();
// Return millivolts
uint16_t res = voltage*1000;
uint16_t res = voltage*1000;
return res;
}
@ -618,16 +629,11 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK()
uint8_t getBattChargeState() TINY_GSM_ATTR_NOT_AVAILABLE;
bool getBattStats(uint8_t &chargeState, int8_t &percent, uint16_t &milliVolts) {
sendAT(GF("+CBC?"));
if (waitResponse(GF(GSM_NL "+CBC:")) != 1) {
return false;
}
// get voltage in VOLTS
float voltage = stream.readStringUntil('\n').toFloat();
milliVolts = voltage*1000;
// Wait for final OK
waitResponse();
bool getBattStats(uint8_t& chargeState, int8_t& percent,
uint16_t& milliVolts) {
chargeState = 0;
percent = 0;
milliVolts = getBattVoltage();
return true;
}
@ -650,25 +656,30 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK()
protected:
bool modemConnect(const char* host, uint16_t port, uint8_t mux,
bool ssl = false, int timeout_s = 75) {
// Make sure we'll be getting data manually on this connection
sendAT(GF("+CIPRXGET=1"));
if (waitResponse() != 1) {
return false;
}
// Establish a connection in multi-socket mode
sendAT(GF("+CIPOPEN="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port);
// The reply is +CIPOPEN: ## of socket created
if (waitResponse(15000L, GF(GSM_NL "+CIPOPEN:")) != 1) {
return false;
}
return true;
bool modemConnect(const char* host, uint16_t port, uint8_t mux,
bool ssl = false, int timeout_s = 15) {
if (ssl) {
DBG("SSL not yet supported on this module!");
}
// Make sure we'll be getting data manually on this connection
sendAT(GF("+CIPRXGET=1"));
if (waitResponse() != 1) {
return false;
}
// Establish a connection in multi-socket mode
uint32_t timeout_ms = ((uint32_t)timeout_s) * 1000;
sendAT(GF("+CIPOPEN="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","),
port);
// The reply is +CIPOPEN: ## of socket created
if (waitResponse(timeout_ms, GF(GSM_NL "+CIPOPEN:")) != 1) {
return false;
}
return true;
}
int16_t modemSend(const void* buff, size_t len, uint8_t mux) {
sendAT(GF("+CIPSEND="), mux, ',', len);
sendAT(GF("+CIPSEND="), mux, ',', (uint16_t)len);
if (waitResponse(GF(">")) != 1) {
return 0;
}
@ -685,23 +696,23 @@ protected:
size_t modemRead(size_t size, uint8_t mux) {
#ifdef TINY_GSM_USE_HEX
sendAT(GF("+CIPRXGET=3,"), mux, ',', size);
sendAT(GF("+CIPRXGET=3,"), mux, ',', (uint16_t)size);
if (waitResponse(GF("+CIPRXGET:")) != 1) {
return 0;
}
#else
sendAT(GF("+CIPRXGET=2,"), mux, ',', size);
sendAT(GF("+CIPRXGET=2,"), mux, ',', (uint16_t)size);
if (waitResponse(GF("+CIPRXGET:")) != 1) {
return 0;
}
#endif
streamSkipUntil(','); // Skip Rx mode 2/normal or 3/HEX
streamSkipUntil(','); // Skip mux/cid (connecion id)
size_t len_requested = stream.readStringUntil(',').toInt();
int len_requested = stream.readStringUntil(',').toInt();
// ^^ Requested number of data bytes (1-1460 bytes)to be read
size_t len_confirmed = stream.readStringUntil('\n').toInt();
int len_confirmed = stream.readStringUntil('\n').toInt();
// ^^ The data length which not read in the buffer
for (size_t i=0; i<len_requested; i++) {
for (int i=0; i<len_requested; i++) {
uint32_t startMillis = millis();
#ifdef TINY_GSM_USE_HEX
while (stream.available() < 2 && (millis() - startMillis < sockets[mux]->_timeout)) { TINY_GSM_YIELD(); }


+ 19
- 8
src/TinyGsmClientSIM800.h View File

@ -165,6 +165,7 @@ public:
bool init(const char* pin = NULL) {
DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION);
if (!testAT()) {
return false;
}
@ -174,9 +175,19 @@ public:
if (waitResponse() != 1) {
return false;
}
DBG(GF("### Modem:"), getModemName());
getSimStatus();
return true;
int ret = getSimStatus();
// if the sim isn't ready and a pin has been provided, try to unlock the sim
if (ret != SIM_READY && pin != NULL && strlen(pin) > 0) {
simUnlock(pin);
return (getSimStatus() == SIM_READY);
}
// if the sim is ready, or it's locked but no pin has been provided, return true
else {
return (ret == SIM_READY || ret == SIM_LOCKED);
}
}
String getModemName() {
@ -801,7 +812,7 @@ protected:
}
int16_t modemSend(const void* buff, size_t len, uint8_t mux) {
sendAT(GF("+CIPSEND="), mux, ',', len);
sendAT(GF("+CIPSEND="), mux, ',', (uint16_t)len);
if (waitResponse(GF(">")) != 1) {
return 0;
}
@ -816,25 +827,25 @@ protected:
size_t modemRead(size_t size, uint8_t mux) {
#ifdef TINY_GSM_USE_HEX
sendAT(GF("+CIPRXGET=3,"), mux, ',', size);
sendAT(GF("+CIPRXGET=3,"), mux, ',', (uint16_t)size);
if (waitResponse(GF("+CIPRXGET:")) != 1) {
return 0;
}
#else
sendAT(GF("+CIPRXGET=2,"), mux, ',', size);
sendAT(GF("+CIPRXGET=2,"), mux, ',', (uint16_t)size);
if (waitResponse(GF("+CIPRXGET:")) != 1) {
return 0;
}
#endif
streamSkipUntil(','); // Skip Rx mode 2/normal or 3/HEX
streamSkipUntil(','); // Skip mux
size_t len_requested = stream.readStringUntil(',').toInt();
int len_requested = stream.readStringUntil(',').toInt();
// ^^ Requested number of data bytes (1-1460 bytes)to be read
size_t len_confirmed = stream.readStringUntil('\n').toInt();
int len_confirmed = stream.readStringUntil('\n').toInt();
// ^^ Confirmed number of data bytes to be read, which may be less than requested.
// 0 indicates that no data can be read.
// This is actually be the number of bytes that will be remaining after the read
for (size_t i=0; i<len_requested; i++) {
for (int i=0; i<len_requested; i++) {
uint32_t startMillis = millis();
#ifdef TINY_GSM_USE_HEX
while (stream.available() < 2 && (millis() - startMillis < sockets[mux]->_timeout)) { TINY_GSM_YIELD(); }


+ 88
- 57
src/TinyGsmClientSaraR4.h View File

@ -54,9 +54,7 @@ class GsmClient : public Client
public:
GsmClient() {}
GsmClient(TinyGsmSaraR4& modem, uint8_t mux = 0) {
init(&modem, mux);
}
GsmClient(TinyGsmSaraR4& modem, uint8_t mux = 0) { init(&modem, mux); }
virtual ~GsmClient(){}
@ -95,8 +93,18 @@ TINY_GSM_CLIENT_CONNECT_OVERLOADS()
virtual void stop(uint32_t maxWaitMs) {
TINY_GSM_CLIENT_DUMP_MODEM_BUFFER()
at->sendAT(GF("+USOCL="), mux);
at->waitResponse((maxWaitMs - (millis() - startMillis))); // NOTE: can take up to 120s to get a response
// // synchronous close
// at->sendAT(GF("+USOCL="), mux);
// // NOTE: can take up to 120s to get a response
// at->waitResponse((maxWaitMs - (millis() - startMillis)));
// sock_connected = false;
// faster asynchronous close
// NOT supported on SARA-R404M / SARA-R410M-01B
at->sendAT(GF("+USOCL="), mux, GF(",1"));
// NOTE: can take up to 120s to get a response
at->waitResponse((maxWaitMs - (millis() - startMillis)));
sock_connected = false;
}
@ -170,16 +178,16 @@ public:
* Basic functions
*/
bool begin(const char* pin = NULL) {
return init(pin);
}
bool begin(const char* pin = NULL) { return init(pin); }
bool init(const char* pin = NULL) {
DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION);
if (!testAT()) {
return false;
}
sendAT(GF("E0")); // Echo Off
sendAT(GF("E0")); // Echo Off
if (waitResponse() != 1) {
return false;
}
@ -191,7 +199,7 @@ public:
#endif
waitResponse();
getModemName();
DBG(GF("### Modem:"), getModemName());
int ret = getSimStatus();
// if the sim isn't ready and a pin has been provided, try to unlock the sim
@ -199,7 +207,8 @@ public:
simUnlock(pin);
return (getSimStatus() == SIM_READY);
}
// if the sim is ready, or it's locked but no pin has been provided, return true
// if the sim is ready, or it's locked but no pin has been provided,return
// return true
else {
return (ret == SIM_READY || ret == SIM_LOCKED);
}
@ -224,7 +233,8 @@ public:
String name = res1 + String(' ') + res2;
DBG("### Modem:", name);
if (!name.startsWith("u-blox SARA-R4") && !name.startsWith("u-blox SARA-N4")) {
if (!name.startsWith("u-blox SARA-R4") &&
!name.startsWith("u-blox SARA-N4")) {
DBG("### WARNING: You are using the wrong TinyGSM modem!");
}
@ -308,13 +318,14 @@ TINY_GSM_MODEM_GET_SIMCCID_CCID()
}
SimStatus getSimStatus(unsigned long timeout_ms = 10000L) {
for (unsigned long start = millis(); millis() - start < timeout_ms; ) {
for (unsigned long start = millis(); millis() - start < timeout_ms;) {
sendAT(GF("+CPIN?"));
if (waitResponse(GF(GSM_NL "+CPIN:")) != 1) {
delay(1000);
continue;
}
int status = waitResponse(GF("READY"), GF("SIM PIN"), GF("SIM PUK"), GF("NOT INSERTED"));
int status = waitResponse(GF("READY"), GF("SIM PIN"), GF("SIM PUK"),
GF("NOT INSERTED"));
waitResponse();
switch (status) {
case 2:
@ -347,10 +358,10 @@ TINY_GSM_MODEM_GET_CSQ()
TINY_GSM_MODEM_WAIT_FOR_NETWORK()
bool setURAT( uint8_t urat ) {
bool setURAT(uint8_t urat) {
// AT+URAT=<SelectedAcT>[,<PreferredAct>[,<2ndPreferredAct>]]
sendAT(GF("+COPS=2")); // Deregister from network
sendAT(GF("+COPS=2")); // Deregister from network
if (waitResponse() != 1) {
return false;
}
@ -358,7 +369,7 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK()
if (waitResponse() != 1) {
return false;
}
sendAT(GF("+COPS=0")); // Auto-register to the network
sendAT(GF("+COPS=0")); // Auto-register to the network
if (waitResponse() != 1) {
return false;
}
@ -370,7 +381,7 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK()
*/
bool gprsConnect(const char* apn, const char* user = NULL, const char* pwd = NULL) {
gprsDisconnect();
// gprsDisconnect();
sendAT(GF("+CGATT=1")); // attach to GPRS
if (waitResponse(360000L) != 1) {
@ -382,8 +393,9 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK()
// serial interface. This is the only command set supported by the LTE-M
// and LTE NB-IoT modules (SARA-R4xx, SARA-N4xx)
// Set the authentication
if (user && strlen(user) > 0) {
sendAT(GF("+CGAUTH=1,0,\""), user, GF("\",\""), pwd, '"'); // Set the authentication
sendAT(GF("+CGAUTH=1,0,\""), user, GF("\",\""), pwd, '"');
waitResponse();
}
@ -399,9 +411,10 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK()
}
bool gprsDisconnect() {
sendAT(GF("+CGACT=1,0")); // Deactivate PDP context 1
// sendAT(GF("+CGACT=0,1")); // Deactivate PDP context 1
sendAT(GF("+CGACT=0")); // Deactivate all contexts
if (waitResponse(40000L) != 1) {
return false;
// return false;
}
sendAT(GF("+CGATT=0")); // detach from GPRS
@ -509,6 +522,8 @@ TINY_GSM_MODEM_GET_GPRS_IP_CONNECTED()
bool getBattStats(uint8_t &chargeState, int8_t &percent, uint16_t &milliVolts) {
percent = getBattPercent();
chargeState = 0;
milliVolts = 0;
return true;
}
@ -522,10 +537,9 @@ TINY_GSM_MODEM_GET_GPRS_IP_CONNECTED()
if (waitResponse(GF(GSM_NL "+UTEMP:")) != 1) {
return (float)-9999;
}
streamSkipUntil(','); // Skip units (C/F)
int16_t res = stream.readStringUntil('\n').toInt();
float temp = -9999;
if (res != 65535) {
if (res != -1) {
temp = ((float)res)/10;
}
return temp;
@ -538,11 +552,12 @@ TINY_GSM_MODEM_GET_GPRS_IP_CONNECTED()
protected:
bool modemConnect(const char* host, uint16_t port, uint8_t* mux,
bool ssl = false, int timeout_s = 120)
{
bool ssl = false, int timeout_s = 120) {
uint32_t timeout_ms = ((uint32_t)timeout_s)*1000;
sendAT(GF("+USOCR=6")); // create a socket
if (waitResponse(GF(GSM_NL "+USOCR:")) != 1) { // reply is +USOCR: ## of socket created
// create a socket
sendAT(GF("+USOCR=6"));
// reply is +USOCR: ## of socket created
if (waitResponse(GF(GSM_NL "+USOCR:")) != 1) {
return false;
}
*mux = stream.readStringUntil('\n').toInt();
@ -558,17 +573,31 @@ protected:
waitResponse();
// Enable KEEPALIVE, 30 sec
//sendAT(GF("+USOSO="), *mux, GF(",6,2,30000"));
//waitResponse();
// sendAT(GF("+USOSO="), *mux, GF(",6,2,30000"));
// waitResponse();
// connect on the allocated socket
sendAT(GF("+USOCO="), *mux, ",\"", host, "\",", port);
int rsp = waitResponse(timeout_ms);
return (1 == rsp);
// Use an asynchronous open to reduce the number of terminal freeze-ups
// This is still blocking until the URC arrives
// The SARA-R410M-02B with firmware revisions prior to L0.0.00.00.05.08
// has a nasty habit of locking up when opening a socket, especially if
// the cellular service is poor.
// NOT supported on SARA-R404M / SARA-R410M-01B
sendAT(GF("+USOCO="), *mux, ",\"", host, "\",", port, ",1");
waitResponse(timeout_ms, GF(GSM_NL "+UUSOCO: "));
stream.readStringUntil(',').toInt(); // skip repeated mux
int connection_status = stream.readStringUntil('\n').toInt();
return (0 == connection_status);
// use synchronous open
// sendAT(GF("+USOCO="), *mux, ",\"", host, "\",", port, ",0");
// int rsp = waitResponse(timeout_ms);
// return (1 == rsp);
}
int16_t modemSend(const void* buff, size_t len, uint8_t mux) {
sendAT(GF("+USOWR="), mux, ',', len);
sendAT(GF("+USOWR="), mux, ',', (uint16_t)len);
if (waitResponse(GF("@")) != 1) {
return 0;
}
@ -579,22 +608,22 @@ protected:
if (waitResponse(GF(GSM_NL "+USOWR:")) != 1) {
return 0;
}
streamSkipUntil(','); // Skip mux
streamSkipUntil(','); // Skip mux
int sent = stream.readStringUntil('\n').toInt();
waitResponse(); // sends back OK after the confirmation of number sent
return sent;
}
size_t modemRead(size_t size, uint8_t mux) {
sendAT(GF("+USORD="), mux, ',', size);
sendAT(GF("+USORD="), mux, ',', (uint16_t)size);
if (waitResponse(GF(GSM_NL "+USORD:")) != 1) {
return 0;
}
streamSkipUntil(','); // Skip mux
size_t len = stream.readStringUntil(',').toInt();
streamSkipUntil(','); // Skip mux
int len = stream.readStringUntil(',').toInt();
streamSkipUntil('\"');
for (size_t i=0; i<len; i++) {
for (int i=0; i<len; i++) {
TINY_GSM_MODEM_STREAM_TO_MUX_FIFO_WITH_DOUBLE_TIMEOUT
}
streamSkipUntil('\"');
@ -612,7 +641,7 @@ protected:
// Will give error "operation not allowed" when attempting to read a socket
// that you have already told to close
if (res == 1) {
streamSkipUntil(','); // Skip mux
streamSkipUntil(','); // Skip mux
result = stream.readStringUntil('\n').toInt();
// if (result) DBG("### DATA AVAILABLE:", result, "on", mux);
waitResponse();
@ -628,11 +657,10 @@ protected:
// NOTE: Querying a closed socket gives an error "operation not allowed"
sendAT(GF("+USOCTL="), mux, ",10");
uint8_t res = waitResponse(GF(GSM_NL "+USOCTL:"));
if (res != 1)
return false;
if (res != 1) return false;
streamSkipUntil(','); // Skip mux
streamSkipUntil(','); // Skip type
streamSkipUntil(','); // Skip mux
streamSkipUntil(','); // Skip type
int result = stream.readStringUntil('\n').toInt();
// 0: the socket is in INACTIVE status (it corresponds to CLOSED status
// defined in RFC793 "TCP Protocol Specification" [112])
@ -660,9 +688,10 @@ TINY_GSM_MODEM_STREAM_UTILITIES()
// TODO: Optimize this!
uint8_t waitResponse(uint32_t timeout_ms, String& data,
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
GsmConstStr r3=GFP(GSM_CME_ERROR), GsmConstStr r4=NULL, GsmConstStr r5=NULL)
{
GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = NULL, GsmConstStr r5 = NULL) {
/*String r1s(r1); r1s.trim();
String r2s(r2); r2s.trim();
String r3s(r3); r3s.trim();
@ -677,7 +706,7 @@ TINY_GSM_MODEM_STREAM_UTILITIES()
while (stream.available() > 0) {
TINY_GSM_YIELD();
int a = stream.read();
if (a <= 0) continue; // Skip 0x00 bytes, just in case
if (a <= 0) continue; // Skip 0x00 bytes, just in case
data += (char)a;
if (r1 && data.endsWith(r1)) {
index = 1;
@ -724,30 +753,32 @@ finish:
}
data = "";
}
//data.replace(GSM_NL, "/");
//DBG('<', index, '>', data);
// data.replace(GSM_NL, "/");
// DBG('<', index, '>', data);
return index;
}
uint8_t waitResponse(uint32_t timeout_ms,
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
GsmConstStr r3=GFP(GSM_CME_ERROR), GsmConstStr r4=NULL, GsmConstStr r5=NULL)
{
GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = NULL, GsmConstStr r5 = NULL) {
String data;
return waitResponse(timeout_ms, data, r1, r2, r3, r4, r5);
}
uint8_t waitResponse(GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
GsmConstStr r3=GFP(GSM_CME_ERROR), GsmConstStr r4=NULL, GsmConstStr r5=NULL)
{
uint8_t waitResponse(GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = NULL, GsmConstStr r5 = NULL) {
return waitResponse(1000, r1, r2, r3, r4, r5);
}
public:
Stream& stream;
Stream& stream;
protected:
GsmClient* sockets[TINY_GSM_MUX_COUNT];
GsmClient* sockets[TINY_GSM_MUX_COUNT];
};
#endif

+ 20
- 6
src/TinyGsmClientSequansMonarch.h View File

@ -195,15 +195,29 @@ public:
bool init(const char* pin = NULL) {
DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION);
if (!testAT()) {
return false;
}
sendAT(GF("E0")); // Echo Off
if (waitResponse() != 1) {
return false;
}
getSimStatus();
return true;
DBG(GF("### Modem:"), getModemName());
int ret = getSimStatus();
// if the sim isn't ready and a pin has been provided, try to unlock the sim
if (ret != SIM_READY && pin != NULL && strlen(pin) > 0) {
simUnlock(pin);
return (getSimStatus() == SIM_READY);
}
// if the sim is ready, or it's locked but no pin has been provided, return
// true
else {
return (ret == SIM_READY || ret == SIM_LOCKED);
}
}
String getModemName() {
@ -570,7 +584,7 @@ protected:
return 0;
}
sendAT(GF("+SQNSSENDEXT="), mux, ',', len);
sendAT(GF("+SQNSSENDEXT="), mux, ',', (uint16_t)len);
waitResponse(10000L, GF(GSM_NL "> "));
stream.write((uint8_t*)buff, len);
stream.flush();
@ -605,13 +619,13 @@ protected:
size_t modemRead(size_t size, uint8_t mux) {
sendAT(GF("+SQNSRECV="), mux, ',', size);
sendAT(GF("+SQNSRECV="), mux, ',', (uint16_t)size);
if (waitResponse(GF("+SQNSRECV: ")) != 1) {
return 0;
}
streamSkipUntil(','); // Skip mux
size_t len = stream.readStringUntil('\n').toInt();
for (size_t i=0; i<len; i++) {
int len = stream.readStringUntil('\n').toInt();
for (int i=0; i<len; i++) {
uint32_t startMillis = millis(); \
while (!stream.available() && ((millis() - startMillis) < sockets[mux % TINY_GSM_MUX_COUNT]->_timeout)) { TINY_GSM_YIELD(); } \
char c = stream.read(); \


+ 8
- 4
src/TinyGsmClientUBLOX.h View File

@ -176,9 +176,11 @@ public:
bool init(const char* pin = NULL) {
DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION);
if (!testAT()) {
return false;
}
sendAT(GF("E0")); // Echo Off
if (waitResponse() != 1) {
return false;
@ -535,7 +537,9 @@ TINY_GSM_MODEM_GET_GPRS_IP_CONNECTED()
uint8_t getBattChargeState() TINY_GSM_ATTR_NOT_AVAILABLE;
bool getBattStats(uint8_t &chargeState, int8_t &percent, uint16_t &milliVolts) {
chargeState = 0;
percent = getBattPercent();
milliVolts = 0;
return true;
}
@ -579,7 +583,7 @@ protected:
}
int16_t modemSend(const void* buff, size_t len, uint8_t mux) {
sendAT(GF("+USOWR="), mux, ',', len);
sendAT(GF("+USOWR="), mux, ',', (uint16_t)len);
if (waitResponse(GF("@")) != 1) {
return 0;
}
@ -597,15 +601,15 @@ protected:
}
size_t modemRead(size_t size, uint8_t mux) {
sendAT(GF("+USORD="), mux, ',', size);
sendAT(GF("+USORD="), mux, ',', (uint16_t)size);
if (waitResponse(GF(GSM_NL "+USORD:")) != 1) {
return 0;
}
streamSkipUntil(','); // Skip mux
size_t len = stream.readStringUntil(',').toInt();
int len = stream.readStringUntil(',').toInt();
streamSkipUntil('\"');
for (size_t i=0; i<len; i++) {
for (int i=0; i<len; i++) {
TINY_GSM_MODEM_STREAM_TO_MUX_FIFO_WITH_DOUBLE_TIMEOUT
}
streamSkipUntil('\"');


+ 271
- 68
src/TinyGsmClientXBee.h View File

@ -109,34 +109,25 @@ public:
}
virtual int connect(IPAddress ip, uint16_t port, int timeout_s) {
if (timeout_s != 0) {
DBG("Timeout [", timeout_s, "] doesn't apply here.");
}
// NOTE: Not caling stop() or yeild() here
at->streamClear(); // Empty anything in the buffer before starting
sock_connected = at->modemConnect(ip, port, mux, false, timeout_s);
sock_connected = at->modemConnect(ip, port, mux, false);
return sock_connected;
}
virtual int connect(IPAddress ip, uint16_t port) {
return connect(ip, port, 75);
return connect(ip, port, 0);
}
virtual void stop(uint32_t maxWaitMs) {
at->streamClear(); // Empty anything in the buffer
at->commandMode();
// For WiFi models, there's no direct way to close the socket. This is a
// hack to shut the socket by setting the timeout to zero.
if (at->beeType == XBEE_S6B_WIFI) {
at->sendAT(GF("TM0")); // Set socket timeout (using Digi default of 10 seconds)
at->waitResponse(maxWaitMs); // This response can be slow
at->writeChanges();
}
// For cellular models, per documentation: If you change the TM (socket
// timeout) value while in Transparent Mode, the current connection is
// immediately closed.
at->sendAT(GF("TM64")); // Set socket timeout (using Digi default of 10 seconds)
at->waitResponse(maxWaitMs); // This response can be slow
at->writeChanges();
at->exitCommand();
at->streamClear(); // Empty anything remaining in the buffer
// empty the saved currently-in-use destination address
at->modemStop(maxWaitMs);
at->streamClear(); // Empty anything in the buffer
sock_connected = false;
// Note: because settings are saved in flash, the XBEE will attempt to
// reconnect to the previous socket if it receives any outgoing data.
// Setting sock_connected to false after the stop ensures that connected()
@ -214,6 +205,10 @@ public:
return true;
}
return sock_connected;
// NOTE: We dont't check or return
// modemGetConnected() because we don't
// want to go into command mode.
// return at->modemGetConnected();
}
virtual operator bool() { return connected(); }
@ -251,9 +246,12 @@ public:
}
virtual int connect(IPAddress ip, uint16_t port, int timeout_s) {
if (timeout_s != 0) {
DBG("Timeout [", timeout_s, "] doesn't apply here.");
}
// NOTE: Not caling stop() or yeild() here
at->streamClear(); // Empty anything in the buffer before starting
sock_connected = at->modemConnect(ip, port, mux, true, timeout_s);
sock_connected = at->modemConnect(ip, port, mux, true);
return sock_connected;
}
};
@ -305,6 +303,10 @@ public:
digitalWrite(resetPin, HIGH);
}
if (pin && strlen(pin) > 0) {
DBG("XBee's do not support SIMs that require an unlock pin!");
}
XBEE_COMMAND_START_DECORATOR(10, false)
sendAT(GF("AP0")); // Put in transparent mode
@ -511,8 +513,15 @@ public:
XBEE_COMMAND_END_DECORATOR
}
bool poweroff() { // Not supported
return false;
bool poweroff() { // NOTE: Not supported for WiFi or older cellular firmware
XBEE_COMMAND_START_DECORATOR(5, false)
sendAT(GF("SD"));
bool ret_val = waitResponse(120000L) == 1;
if (ret_val) {
ret_val &= (sendATGetString(GF("AI")) == "2D");
}
XBEE_COMMAND_END_DECORATOR
return ret_val;
}
bool radioOff() TINY_GSM_ATTR_NOT_IMPLEMENTED;
@ -524,6 +533,9 @@ public:
*/
bool simUnlock(const char *pin) { // Not supported
if (pin && strlen(pin) > 0) {
DBG("XBee's do not support SIMs that require an unlock pin!");
}
return false;
}
@ -535,7 +547,7 @@ public:
return sendATGetString(GF("IM"));
}
SimStatus getSimStatus(unsigned long timeout_ms = 10000L) {
SimStatus getSimStatus() {
return SIM_READY; // unsupported
}
@ -680,7 +692,7 @@ public:
//nh For no pwd don't set setscurity or pwd
if (ssid == NULL) retVal = false;;
if (pwd != NULL)
if (pwd && strlen(pwd) > 0)
{
sendAT(GF("EE"), 2); // Set security to WPA2
if (waitResponse() != 1) retVal = false;
@ -734,10 +746,19 @@ public:
* GPRS functions
*/
bool gprsConnect(const char* apn, const char* user = NULL, const char* pwd = NULL) {
bool gprsConnect(const char* apn, const char* user = NULL,
const char* pwd = NULL) {
if (user && strlen(user) > 0) {
DBG("XBee's do not support SIMs that a user name/password!");
}
if (pwd && strlen(pwd) > 0) {
DBG("XBee's do not support SIMs that a user name/password!");
}
XBEE_COMMAND_START_DECORATOR(5, false)
sendAT(GF("AN"), apn); // Set the APN
bool success = waitResponse() == 1;
sendAT(GF("AM0")); // Airplane mode off
waitResponse(5000);
writeChanges();
XBEE_COMMAND_END_DECORATOR
return success;
@ -748,9 +769,9 @@ public:
sendAT(GF("AM1")); // Cheating and disconnecting by turning on airplane mode
int8_t res = (1 == waitResponse(5000));
writeChanges();
sendAT(GF("AM0")); // Airplane mode off
waitResponse(5000);
writeChanges();
// sendAT(GF("AM0")); // Airplane mode off
// waitResponse(5000);
// writeChanges();
XBEE_COMMAND_END_DECORATOR
return res;
}
@ -796,12 +817,30 @@ public:
*/
// Use: float vBatt = modem.getBattVoltage() / 1000.0;
uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_AVAILABLE;
uint16_t getBattVoltage() {
int16_t intRes = 0;
XBEE_COMMAND_START_DECORATOR(5, false)
if (beeType == XBEE_UNKNOWN) getSeries();
if (beeType == XBEE_S6B_WIFI) {
sendAT(GF("%V"));
intRes = readResponseInt();
}
XBEE_COMMAND_END_DECORATOR
return intRes;
}
int8_t getBattPercent() TINY_GSM_ATTR_NOT_AVAILABLE;
uint8_t getBattChargeState() TINY_GSM_ATTR_NOT_AVAILABLE;
bool getBattStats(uint8_t &chargeState, int8_t &percent, uint16_t &milliVolts) TINY_GSM_ATTR_NOT_AVAILABLE;
bool getBattStats(uint8_t &chargeState, int8_t &percent, uint16_t &milliVolts) {
chargeState = 0;
percent = 0;
milliVolts = getBattVoltage();
return true;
}
float getTemperature() {
XBEE_COMMAND_START_DECORATOR(5, (float)-9999)
String res = sendATGetString(GF("TP"));
if (res == "") {
return (float)-9999;
@ -809,6 +848,7 @@ public:
char buf[5] = {0,};
res.toCharArray(buf, 5);
int8_t intRes = (int8_t)strtol(buf, 0, 16); // degrees Celsius displayed in 8-bit two's complement format.
XBEE_COMMAND_END_DECORATOR
return (float)intRes;
}
@ -816,10 +856,35 @@ public:
* Client related functions
*/
protected:
protected:
IPAddress getHostIP(const char* host, int timeout_s = 45) {
String strIP; strIP.reserve(16);
int16_t getConnectionIndicator() {
XBEE_COMMAND_START_DECORATOR(5, false)
sendAT(GF("CI"));
int16_t intRes = readResponseInt();
XBEE_COMMAND_END_DECORATOR
return intRes;
}
IPAddress getOperatingIP() {
String strIP;
strIP.reserve(16);
XBEE_COMMAND_START_DECORATOR(5, IPAddress(0, 0, 0, 0))
sendAT(GF("OD"));
strIP = stream.readStringUntil('\r'); // read result
strIP.trim();
XBEE_COMMAND_END_DECORATOR
if (strIP != "" && strIP != GF("ERROR")) {
return TinyGsmIpFromString(strIP);
} else
return IPAddress(0, 0, 0, 0);
}
IPAddress lookupHostIP(const char* host, int timeout_s = 45) {
String strIP;
strIP.reserve(16);
unsigned long startMillis = millis();
uint32_t timeout_ms = ((uint32_t)timeout_s)*1000;
bool gotIP = false;
@ -850,10 +915,8 @@ protected:
bool modemConnect(const char* host, uint16_t port, uint8_t mux = 0,
bool ssl = false, int timeout_s = 75)
{
unsigned long startMillis = millis();
uint32_t timeout_ms = ((uint32_t)timeout_s)*1000;
bool retVal = false;
XBEE_COMMAND_START_DECORATOR(5, false)
XBEE_COMMAND_START_DECORATOR(5, false)
// If this is a new host name, replace the saved host and wipe out the saved host IP
if (this->savedHost != String(host)) {
@ -863,12 +926,12 @@ protected:
// If we don't have a good IP for the host, we need to do a DNS search
if (savedHostIP == IPAddress(0,0,0,0)) {
savedHostIP = getHostIP(host, timeout_s); // This will return 0.0.0.0 if lookup fails
savedHostIP = lookupHostIP(host, timeout_s); // This will return 0.0.0.0 if lookup fails
}
// If we now have a valid IP address, use it to connect
if (savedHostIP != IPAddress(0,0,0,0)) { // Only re-set connection information if we have an IP address
retVal = modemConnect(savedHostIP, port, mux, ssl, timeout_ms - (millis() - startMillis));
retVal = modemConnect(savedHostIP, port, mux, ssl);
}
XBEE_COMMAND_END_DECORATOR
@ -876,13 +939,21 @@ protected:
return retVal;
}
bool modemConnect(IPAddress ip, uint16_t port, uint8_t mux = 0, bool ssl = false, int timeout_s = 75) {
bool modemConnect(IPAddress ip, uint16_t port, uint8_t mux = 0,
bool ssl = false) {
bool success = true;
uint32_t timeout_ms = ((uint32_t)timeout_s)*1000;
if (mux != 0) {
DBG("XBee only supports 1 IP channel in transparent mode!");
}
// empty the saved currelty-in-use destination address
savedOperatingIP = IPAddress(0, 0, 0, 0);
XBEE_COMMAND_START_DECORATOR(5, false)
if (ip != savedIP) { // Can skip almost everything if there's no change in the IP address
if (ip != savedIP) { // Can skip almost everything if there's no
// change in the IP address
savedIP = ip; // Set the newly requested IP address
String host; host.reserve(16);
host += ip[0];
@ -909,11 +980,14 @@ protected:
success &= writeChanges();
}
for (unsigned long start = millis(); millis() - start < timeout_ms; ) {
if (modemGetConnected()) {
sockets[mux]->sock_connected = true;
break;
}
// we'll accept either unknown or connected
if (beeType != XBEE_S6B_WIFI) {
uint16_t ci = getConnectionIndicator();
success &= (ci == 0x00 || ci == 0xFF || ci == 0x28);
}
if (success) {
sockets[mux]->sock_connected = true;
}
XBEE_COMMAND_END_DECORATOR
@ -921,9 +995,55 @@ protected:
return success;
}
bool modemStop(uint32_t maxWaitMs) {
streamClear(); // Empty anything in the buffer
// empty the saved currently-in-use destination address
savedOperatingIP = IPAddress(0, 0, 0, 0);
XBEE_COMMAND_START_DECORATOR(5, false)
// Get the current socket timeout
sendAT(GF("TM"));
String timeoutUsed = readResponseString(5000L);
// For WiFi models, there's no direct way to close the socket. This is a
// hack to shut the socket by setting the timeout to zero.
if (beeType == XBEE_S6B_WIFI) {
sendAT(GF("TM0")); // Set socket timeout to 0
waitResponse(maxWaitMs); // This response can be slow
writeChanges();
}
// For cellular models, per documentation: If you write the TM (socket
// timeout) value while in Transparent Mode, the current connection is
// immediately closed - this works even if the TM values is unchanged
sendAT(GF("TM"), timeoutUsed); // Re-set socket timeout
waitResponse(maxWaitMs); // This response can be slow
writeChanges();
XBEE_COMMAND_END_DECORATOR
return true;
}
int16_t modemSend(const void* buff, size_t len, uint8_t mux = 0) {
if (mux != 0) {
DBG("XBee only supports 1 IP channel in transparent mode!");
}
stream.write((uint8_t*)buff, len);
stream.flush();
if (beeType != XBEE_S6B_WIFI) {
// After a send, verify the outgoing ip if it isn't set
if (savedOperatingIP == IPAddress(0, 0, 0, 0)) {
modemGetConnected();
}
// After sending several characters, also re-check
// NOTE: I'm intentionally not checking after every single character!
else if (len > 5) {
modemGetConnected();
}
}
return len;
}
@ -937,17 +1057,11 @@ protected:
XBEE_COMMAND_START_DECORATOR(5, false)
// Verify that we're connected to the *right* IP address
// We might be connected - but to the wrong thing
// NOTE: In transparent mode, there is only one connection possible - no multiplex
// String strIP; strIP.reserve(16);
// sendAT(GF("DL"));
// strIP = stream.readStringUntil('\r'); // read result
// if (TinyGsmIpFromString(strIP) != savedIP) return exitAndFail();
if (beeType == XBEE_UNKNOWN) getSeries(); // Need to know the bee type to interpret response
switch (beeType){ // The wifi be can only say if it's connected to the netowrk
switch (beeType){
// The wifi be can only say if it's connected to the netowrk
case XBEE_S6B_WIFI: {
RegStatus s = getRegistrationStatus();
XBEE_COMMAND_END_DECORATOR
@ -956,22 +1070,110 @@ protected:
}
return (s == REG_OK); // if it's connected, we hope the sockets are too
}
default: { // Cellular XBee's
sendAT(GF("CI"));
int16_t intRes = readResponseInt();
// Cellular XBee's
default: {
int16_t ci = getConnectionIndicator();
// Get the operating destination address
IPAddress od = getOperatingIP();
XBEE_COMMAND_END_DECORATOR
switch(intRes) {
case 0x00: // 0x00 = The socket is definitely open
case 0x28: // 0x28 = "Unknown."
case 0xFF: // 0xFF = No known status - this is always returned prior to sending data
switch(ci) {
// 0x00 = The socket is definitely open
case 0x00: {
savedOperatingIP = od;
// but it's possible the socket is set to the wrong place
if (od != IPAddress(0, 0, 0, 0) && od != savedIP) {
sockets[0]->stop();
return false;
}
return true;
case 0x02: // 0x02 = Invalid parameters (bad IP/host)
case 0x12: // 0x12 = DNS query lookup failure
case 0x25: // 0x25 = Unknown server - DNS lookup failed (0x22 for UDP socket!)
savedIP = IPAddress(0,0,0,0); // force a lookup next time!
default: // If it's anything else (inc 0x02, 0x12, and 0x25)...
sockets[0]->sock_connected = false; // ...it's definitely NOT connected
}
// 0x28 = "Unknown."
// 0xFF = No known status - always returned prior to sending data
case 0x28:
case 0xFF: {
// If we previously had an operating destination and we no longer do,
// the socket must have closed
if (od == IPAddress(0, 0, 0, 0) && savedOperatingIP != IPAddress(0, 0, 0, 0)) {
savedOperatingIP = od;
sockets[0]->sock_connected = false;
return false;
}
// else if the operating destination exists, but is wrong
// we need to close and re-open
else if (od != IPAddress(0, 0, 0, 0) && od != savedIP) {
sockets[0]->stop();
return false;
}
// else if the operating destination exists and matches, we're
// good to go
else if (od != IPAddress(0, 0, 0, 0) && od == savedIP) {
savedOperatingIP = od;
return true;
}
// If we never had an operating destination, then sock may be open
// but data never sent - this is the dreaded "we don't know"
else {
savedOperatingIP = od;
return true;
}
// // Ask for information about any open sockets
// sendAT(GF("SI"));
// String open_socks = stream.readStringUntil('\r');
// open_socks.replace(GSM_NL, "");
// open_socks.trim();
// if (open_socks != "") {
// // In transparent mode, only socket 0 should be possible
// sendAT(GF("SI0"));
// // read socket it
// String sock_id = stream.readStringUntil('\r');
// // read socket state
// String sock_state = stream.readStringUntil('\r');
// // read socket protocol (TCP/UDP)
// String sock_protocol = stream.readStringUntil('\r');
// // read local port number
// String local_port = stream.readStringUntil('\r');
// // read remote port number
// String remote_port = stream.readStringUntil('\r');
// // read remote ip address
// String remoted_address =
// stream.readStringUntil('\r'); // read result
// stream.readStringUntil('\r'); // final carriage return
// }
}
// 0x21 = User closed
// 0x27 = Connection lost
// If the connection is lost or timed out on our side,
// we force close so it can reopen
case 0x21 :
case 0x27 : {
sendAT(GF("TM")); // Get socket timeout
String timeoutUsed = readResponseString(5000L);
sendAT(GF("TM"), timeoutUsed); // Re-set socket timeout
waitResponse(5000L); // This response can be slow
}
// 0x02 = Invalid parameters (bad IP/host)
// 0x12 = DNS query lookup failure
// 0x25 = Unknown server - DNS lookup failed (0x22 for UDP socket!)
case 0x02:
case 0x12:
case 0x25: {
savedIP = IPAddress(0, 0, 0, 0); // force a lookup next time!
}
// If it's anything else (inc 0x02, 0x12, and 0x25)...
// it's definitely NOT connected
default: {
sockets[0]->sock_connected = false;
savedOperatingIP = od;
return false;
}
}
}
}
@ -1175,6 +1377,7 @@ protected:
IPAddress savedIP;
String savedHost;
IPAddress savedHostIP;
IPAddress savedOperatingIP;
bool inCommandMode;
uint32_t lastCommandModeMillis;
GsmClient* sockets[TINY_GSM_MUX_COUNT];


+ 7
- 4
src/TinyGsmCommon.h View File

@ -10,7 +10,7 @@
#define TinyGsmCommon_h
// The current library version number
#define TINYGSM_VERSION "0.9.7"
#define TINYGSM_VERSION "0.9.17"
#if defined(SPARK) || defined(PARTICLE)
#include "Particle.h"
@ -490,9 +490,12 @@ String TinyGsmDecodeHex16bit(String &instr) {
// Unlocks a sim via the 3GPP TS command AT+CPIN
#define TINY_GSM_MODEM_SIM_UNLOCK_CPIN() \
bool simUnlock(const char *pin) { \
sendAT(GF("+CPIN=\""), pin, GF("\"")); \
return waitResponse() == 1; \
bool simUnlock(const char *pin) { \
if (pin && strlen(pin) > 0) { \
sendAT(GF("+CPIN=\""), pin, GF("\"")); \
return waitResponse() == 1; \
} \
return true; \
}


+ 28
- 5
tools/Diagnostics/Diagnostics.ino View File

@ -69,11 +69,12 @@
// set GSM PIN, if any
#define GSM_PIN ""
// Your GPRS credentials
// Leave empty, if missing user or pass
// Your GPRS credentials, if any
const char apn[] = "YourAPN";
const char gprsUser[] = "";
const char gprsPass[] = "";
// Your WiFi connection credentials, if applicable
const char wifiSSID[] = "YourSSID";
const char wifiPass[] = "YourWiFiPass";
@ -83,6 +84,20 @@ const char resource[] = "/TinyGSM/logo.txt";
#include <TinyGsmClient.h>
// Just in case someone defined the wrong thing..
#if TINY_GSM_USE_GPRS && not defined TINY_GSM_MODEM_HAS_GPRS
#undef TINY_GSM_USE_GPRS
#undef TINY_GSM_USE_WIFI
#define TINY_GSM_USE_GPRS false
#define TINY_GSM_USE_WIFI true
#endif
#if TINY_GSM_USE_WIFI && not defined TINY_GSM_MODEM_HAS_WIFI
#undef TINY_GSM_USE_GPRS
#undef TINY_GSM_USE_WIFI
#define TINY_GSM_USE_GPRS true
#define TINY_GSM_USE_WIFI false
#endif
#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, SerialMon);
@ -111,8 +126,8 @@ void setup() {
SerialMon.println("Wait...");
// Set GSM module baud rate
TinyGsmAutoBaud(SerialAT,GSM_AUTOBAUD_MIN,GSM_AUTOBAUD_MAX);
// SerialAT.begin(115200);
// TinyGsmAutoBaud(SerialAT,GSM_AUTOBAUD_MIN,GSM_AUTOBAUD_MAX);
SerialAT.begin(115200);
delay(3000);
}
@ -147,6 +162,7 @@ void loop() {
#endif
#if TINY_GSM_USE_WIFI
// Wifi connection parameters must be set before waiting for the network
SerialMon.print(F("Setting SSID/password..."));
if (!modem.networkConnect(wifiSSID, wifiPass)) {
SerialMon.println(" fail");
@ -175,7 +191,8 @@ void loop() {
}
SerialMon.println(F(" [OK]"));
#if TINY_GSM_USE_GPRS && defined TINY_GSM_MODEM_HAS_GPRS
#if TINY_GSM_USE_GPRS
// GPRS connection parameters are usually set after network registration
SerialMon.print("Connecting to ");
SerialMon.print(apn);
if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
@ -233,8 +250,14 @@ void loop() {
client.stop();
SerialMon.println(F("Server disconnected"));
#if TINY_GSM_USE_WIFI
modem.networkDisconnect();
SerialMon.println(F("WiFi disconnected"));
#endif
#if TINY_GSM_USE_GPRS
modem.gprsDisconnect();
SerialMon.println(F("GPRS disconnected"));
#endif
SerialMon.println();
SerialMon.println(F("************************"));


Loading…
Cancel
Save