2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -2,3 +2,5 @@
|
||||
/.gitattributes export-ignore
|
||||
/.gitignore export-ignore
|
||||
/.travis.yml export-ignore
|
||||
|
||||
*.ino filter=updateUsersAndPasses
|
2
.github/ISSUE_TEMPLATE.md
vendored
2
.github/ISSUE_TEMPLATE.md
vendored
@@ -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
.gitignore
vendored
7
.gitignore
vendored
@@ -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/*
|
||||
|
@@ -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:
|
||||
|
@@ -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();
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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... "));
|
||||
|
@@ -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"));
|
||||
|
@@ -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");
|
||||
}
|
||||
}
|
||||
|
@@ -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,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,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.
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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) {
|
||||
|
@@ -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,24 +278,25 @@ TINY_GSM_MODEM_MAINTAIN_LISTEN()
|
||||
|
||||
bool isNetworkConnected() {
|
||||
RegStatus s = getRegistrationStatus();
|
||||
return (s == REG_OK_IP || s == REG_OK_TCP);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
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:
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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,6 +338,18 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK()
|
||||
return false;
|
||||
}
|
||||
|
||||
// Select TCP/IP transfer mode - NOT transparent mode
|
||||
sendAT(GF("+QIMODE=0"));
|
||||
if (waitResponse() != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enable multiple TCP/IP connections
|
||||
sendAT(GF("+QIMUX=1"));
|
||||
if (waitResponse() != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Start TCPIP Task and Set APN, User Name and Password
|
||||
sendAT("+QIREGAPP=\"", apn, "\",\"", user, "\",\"", pwd, "\"" );
|
||||
if (waitResponse() != 1) {
|
||||
@@ -332,28 +358,51 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK()
|
||||
|
||||
//Activate GPRS/CSD Context
|
||||
sendAT(GF("+QIACT"));
|
||||
if (waitResponse(10000) != 1) {
|
||||
if (waitResponse(60000L) != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Enable multiple TCP/IP connections
|
||||
sendAT(GF("+QIMUX=1"));
|
||||
if (waitResponse() != 1) {
|
||||
// Check that we have a local IP address
|
||||
if (localIP() == IPAddress(0,0,0,0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Request an IP header for received data ("IPD(data length):")
|
||||
sendAT(GF("+QIHEAD=1"));
|
||||
if (waitResponse() != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Set Method to Handle Received TCP/IP Data - Retrieve Data by Command
|
||||
// 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;
|
||||
// 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;
|
||||
}
|
||||
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
|
||||
}
|
||||
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);
|
||||
|
@@ -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,6 +350,18 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK()
|
||||
sendAT(GF("+CGACT=1,1"));
|
||||
waitResponse(60000L);
|
||||
|
||||
// Select TCP/IP transfer mode - NOT transparent mode
|
||||
sendAT(GF("+QIMODE=0"));
|
||||
if (waitResponse() != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enable multiple TCP/IP connections
|
||||
sendAT(GF("+QIMUX=1"));
|
||||
if (waitResponse() != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Start TCPIP Task and Set APN, User Name and Password
|
||||
sendAT("+QIREGAPP=\"", apn, "\",\"", user, "\",\"", pwd, "\"" );
|
||||
if (waitResponse() != 1) {
|
||||
@@ -350,30 +374,20 @@ TINY_GSM_MODEM_WAIT_FOR_NETWORK()
|
||||
return false;
|
||||
}
|
||||
|
||||
//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"));
|
||||
if (waitResponse() != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Set Method to Handle Received TCP/IP Data - Retrieve Data by Command
|
||||
sendAT(GF("+QINDI=1"));
|
||||
if (waitResponse() != 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;
|
||||
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;
|
||||
}
|
||||
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
|
||||
}
|
||||
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);
|
||||
|
@@ -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(); }
|
||||
|
@@ -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(); }
|
||||
|
@@ -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;
|
||||
}
|
||||
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
|
||||
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;
|
||||
// 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(); }
|
||||
|
@@ -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(); }
|
||||
|
@@ -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
|
||||
|
@@ -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(); \
|
||||
|
@@ -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('\"');
|
||||
|
@@ -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];
|
||||
|
@@ -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; \
|
||||
}
|
||||
|
||||
|
||||
|
@@ -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("************************"));
|
||||
|
Reference in New Issue
Block a user