初始化提交
This commit is contained in:
165
arduino-cli/libraries/TinyGSM/LICENSE
Normal file
165
arduino-cli/libraries/TinyGSM/LICENSE
Normal file
@@ -0,0 +1,165 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
9
arduino-cli/libraries/TinyGSM/Makefile
Normal file
9
arduino-cli/libraries/TinyGSM/Makefile
Normal file
@@ -0,0 +1,9 @@
|
||||
.PHONY: travis-build
|
||||
|
||||
travis-build:
|
||||
ifdef PLATFORMIO_CI_ARGS
|
||||
platformio ci --lib="." $(PLATFORMIO_CI_ARGS)
|
||||
else
|
||||
platformio ci --lib="." --board=leonardo
|
||||
endif
|
||||
|
||||
193
arduino-cli/libraries/TinyGSM/README.md
Normal file
193
arduino-cli/libraries/TinyGSM/README.md
Normal file
@@ -0,0 +1,193 @@
|
||||

|
||||
|
||||
A small Arduino library for GSM modules, that just works.
|
||||
<!---
|
||||
[](https://github.com/vshymanskyy/TinyGSM/releases/latest)--->
|
||||
[](https://github.com/vshymanskyy/TinyGSM/releases/latest)
|
||||
[](https://travis-ci.org/vshymanskyy/TinyGSM)
|
||||
[](https://github.com/vshymanskyy/TinyGSM/issues)
|
||||
[](https://github.com/vshymanskyy/TinyGSM/wiki)
|
||||
[](https://github.com/vshymanskyy/TinyGSM/stargazers)
|
||||
[](https://github.com/vshymanskyy/TinyGSM/blob/master/LICENSE)
|
||||
|
||||
If you like **TinyGSM** - give it a star, or fork it and contribute!
|
||||
[](https://github.com/vshymanskyy/TinyGSM/stargazers)
|
||||
[](https://github.com/vshymanskyy/TinyGSM/network)
|
||||
|
||||
You can also join our chat:
|
||||
[](https://gitter.im/tinygsm)
|
||||
|
||||
### Arduino Client interface support
|
||||
This library is easy to integrate with lots of sketches, which use Ethernet or WiFi.
|
||||
**PubSubClient ([MQTT](http://mqtt.org/))**, **[Blynk](http://blynk.cc)**, **HTTP Client** and **File Download** examples are provided.
|
||||
|
||||

|
||||
|
||||
### TinyGSM is tiny
|
||||
The complete WebClient example for Arduino Uno (via Software Serial) takes little resources:
|
||||
```
|
||||
Sketch uses 15022 bytes (46%) of program storage space. Maximum is 32256 bytes.
|
||||
Global variables use 574 bytes (28%) of dynamic memory, leaving 1474 bytes for local variables. Maximum is 2048 bytes.
|
||||
```
|
||||
Arduino GSM library uses 15868 bytes (49%) of Flash and 1113 bytes (54%) of RAM in a similar scenario.
|
||||
TinyGSM also pulls data gently from the modem (whenever possible), so it can operate on very little RAM.
|
||||
**Now, you have more space for your experiments.**
|
||||
|
||||
## Features
|
||||
|
||||
Feature \ Modem | SIM8xx | u-Blox | A6/A7/A20 | M590 | ESP8266 | XBee
|
||||
--- | --- | --- | --- | --- | --- | ---
|
||||
**Data connections**
|
||||
TCP (HTTP, MQTT, Blynk, ...) | ✔ | ✔ | ✔ | ✔ | ✔ | ✔
|
||||
UDP | ◌ | ◌ | | | | ◌
|
||||
SSL/TLS (HTTPS) | ✔¹ | ✔ | 🅧 | 🅧 | ✔¹ | ✔¹
|
||||
**USSD**
|
||||
Sending USSD requests | ✔ | | ✔ | ✔ | 🅧 |
|
||||
Decoding 7,8,16-bit response | ✔ | | ✔ | ✔ | 🅧 |
|
||||
**SMS**
|
||||
Sending | ✔ | ✔ | ✔ | ✔ | 🅧 | ✔
|
||||
Sending Unicode | ✔ | | ◌ | 🅧 | 🅧 |
|
||||
Reading | | | | | 🅧 |
|
||||
Incoming message event | | | | ? | 🅧 |
|
||||
**Calls**
|
||||
Dial, hangup | ✔ | | ✔ | 🅧 | 🅧 | 🅧
|
||||
Receiving calls | ✔ | | ✔ | 🅧 | 🅧 | 🅧
|
||||
Incoming event (RING) | ◌ | | ◌ | 🅧 | 🅧 | 🅧
|
||||
DTMF sending | ✔ | | ✔ | 🅧 | 🅧 | 🅧
|
||||
DTMF decoding | ◌ | | 🅧 | 🅧 | 🅧 | 🅧
|
||||
**Location**
|
||||
GSM location service | ✔ | ✔ | 🅧 | 🅧 | 🅧 | ✔
|
||||
GPS/GNSS | ✔¹ | 🅧 | ◌¹ | 🅧 | 🅧 | 🅧
|
||||
|
||||
✔ - implemented ◌ - planned 🅧 - not available on this modem
|
||||
¹ - only some device models or firmware revisions have this feature (SIM8xx R14.18, A7, etc.)
|
||||
|
||||
## Supported modems
|
||||
|
||||
- SIMCom SIM800 series (SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868)
|
||||
- SIMCom SIM900 series (SIM900A, SIM900D, SIM908, SIM968)
|
||||
- AI-Thinker A6, A6C, A7, A20
|
||||
- ESP8266 (AT commands interface, similar to GSM modems)
|
||||
- Digi XBee WiFi and Cellular (using XBee command mode)
|
||||
- Neoway M590
|
||||
- u-blox Cellular Modems (LEON-G100, LISA-U2xx, SARA-G3xx, SARA-U2xx, TOBY-L2xx, LARA-R2xx, MPCI-L2xx)
|
||||
- Quectel BG96 ***(alpha)***
|
||||
|
||||
### Supported boards/modules
|
||||
- Arduino MKR GSM 1400
|
||||
- GPRSbee
|
||||
- Microduino GSM
|
||||
- Adafruit FONA (Mini Cellular GSM Breakout)
|
||||
- Adafruit FONA 800/808 Shield
|
||||
- Industruino GSM
|
||||
- RAK WisLTE ***(alpha)***
|
||||
- ... other modules, based on supported modems. Some boards require [**special configuration**](https://github.com/vshymanskyy/TinyGSM/wiki/Board-configuration).
|
||||
|
||||
More modems may be supported later:
|
||||
- [ ] Quectel M10, M35, M95, UG95, EC21
|
||||
- [ ] Sequans Monarch LTE Cat M1/NB1
|
||||
- [ ] SIMCom SIM5320, SIM5360, SIM5216, SIM7xxx
|
||||
- [ ] Telit GL865
|
||||
- [ ] ZTE MG2639
|
||||
- [ ] Hi-Link HLK-RM04
|
||||
|
||||
Watch this repo for new updates! And of course, contributions are welcome ;)
|
||||
|
||||
## Donation
|
||||
|
||||
[](https://salt.bountysource.com/checkout/amount?team=tinygsm-dev)
|
||||
[](http://tny.im/aen)
|
||||
|
||||
If you have found TinyGSM to be useful in your work, research or company, please consider making a donation to the project commensurate with your resources. Any amount helps!
|
||||
**All donations will be used strictly to fund the development of TinyGSM:**
|
||||
- Covering cellular network expences
|
||||
- Buying new hardware and modems for integration
|
||||
- Bounty Budget (to reward other developers for their contributions)
|
||||
- Implementing new features
|
||||
- Quality Assurance
|
||||
|
||||
## Getting Started
|
||||
|
||||
1. Using your phone:
|
||||
- Disable PIN code on the SIM card
|
||||
- Check your balance
|
||||
- Check that APN,User,Pass are correct and you have internet
|
||||
2. Ensure the SIM card is correctly inserted into the module
|
||||
3. Ensure that GSM antenna is firmly attached
|
||||
4. Check if serial connection is working (Hardware Serial is recommended)
|
||||
Send an ```AT``` command using [this sketch](tools/AT_Debug/AT_Debug.ino)
|
||||
|
||||
If you have any issues:
|
||||
|
||||
1. Read the whole README (you're looking at it!)
|
||||
2. Some boards require [**special configuration**](https://github.com/vshymanskyy/TinyGSM/wiki/Board-configuration).
|
||||
3. Try running the Diagnostics sketch
|
||||
4. Check for [**highlighted topics here**](https://github.com/vshymanskyy/TinyGSM/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3A%22for+reference%22+)
|
||||
5. If you have a question, please post it in our [Gitter chat](https://gitter.im/tinygsm)
|
||||
|
||||
## How does it work?
|
||||
|
||||
Many GSM modems, WiFi and radio modules can be controlled by sending AT commands over Serial.
|
||||
TinyGSM knows which commands to send, and how to handle AT responses, and wraps that into standard Arduino Client interface.
|
||||
|
||||
## API Reference
|
||||
|
||||
For GPRS data streams, this library provides the standard [Arduino Client](https://www.arduino.cc/en/Reference/ClientConstructor) interface.
|
||||
For additional functions, please refer to [this example sketch](examples/AllFunctions/AllFunctions.ino)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Diagnostics sketch
|
||||
|
||||
Use this sketch to diagnose your SIM card and GPRS connection:
|
||||
File -> Examples -> TynyGSM -> tools -> [Diagnostics](https://github.com/vshymanskyy/TinyGSM/blob/master/tools/Diagnostics/Diagnostics.ino)
|
||||
|
||||
### Ensure stable data & power connection
|
||||
|
||||
Most modules require up to 2A and specific voltage - according to the module documentation.
|
||||
So this actually solves stability problems in **many** cases:
|
||||
- Provide a good stable power supply. Read about [**powering your module**](https://github.com/vshymanskyy/TinyGSM/wiki/Powering-GSM-module).
|
||||
- Keep your wires as short as possible
|
||||
- Consider soldering them for a stable connection
|
||||
- Do not put your wires next to noisy signal sources (buck converters, antennas, oscillators etc.)
|
||||
|
||||
### SoftwareSerial problems
|
||||
|
||||
When using ```SoftwareSerial``` (on Uno, Nano, etc), the speed **115200** may not work.
|
||||
Try selecting **57600**, **38400**, or even lower - the one that works best for you.
|
||||
In some cases **9600** is unstable, but using **38400** helps, etc.
|
||||
Be sure to set correct TX/RX pins in the sketch. Please note that not every Arduino pin can serve as TX or RX pin.
|
||||
**Read more about SoftSerial options and configuration [here](https://www.pjrc.com/teensy/td_libs_AltSoftSerial.html) and [here](https://www.arduino.cc/en/Reference/SoftwareSerial).**
|
||||
|
||||
### ESP32 HardwareSerial
|
||||
|
||||
When using ESP32 `HardwareSerial`, you may need to specify additional parameters to the `.begin()` call.
|
||||
Please [refer to this comment](https://github.com/vshymanskyy/TinyGSM/issues/91#issuecomment-356024747).
|
||||
|
||||
### SAMD21
|
||||
|
||||
When using SAMD21-based boards, you may need to use a sercom uart port instead of `Serial1`.
|
||||
Please [refer to this comment](https://github.com/vshymanskyy/TinyGSM/issues/102#issuecomment-345548941).
|
||||
|
||||
### Broken initial configuration
|
||||
|
||||
Sometimes (especially if you played with AT comands), your module configuration may become invalid.
|
||||
This may result in problems such as:
|
||||
|
||||
* Can't connect to the GPRS network
|
||||
* Can't connect to the server
|
||||
* Sent/recieved data contains invalid bytes
|
||||
* etc.
|
||||
|
||||
To return module to **Factory Defaults**, use this sketch:
|
||||
File -> Examples -> TinyGSM -> tools -> [FactoryReset](https://github.com/vshymanskyy/TinyGSM/blob/master/tools/FactoryReset/FactoryReset.ino)
|
||||
|
||||
### Goouuu Tech IOT-GA6 vs AI-Thinker A6 confusion
|
||||
|
||||
It turns out that **Goouuu Tech IOT-GA6** is not the same as **AI-Thinker A6**. Unfortunately IOT-GA6 is not supported out of the box yet. There are some hints that IOT-GA6 firmware may be updated to match A6... See [this topic](https://github.com/vshymanskyy/TinyGSM/issues/164).
|
||||
|
||||
__________
|
||||
|
||||
### License
|
||||
This project is released under
|
||||
The GNU Lesser General Public License (LGPL-3.0)
|
||||
@@ -0,0 +1,202 @@
|
||||
/**************************************************************
|
||||
*
|
||||
* TinyGSM Getting Started guide:
|
||||
* https://tiny.cc/tinygsm-readme
|
||||
*
|
||||
* NOTE:
|
||||
* Some of the functions may be unavailable for your modem.
|
||||
* Just comment them out.
|
||||
*
|
||||
**************************************************************/
|
||||
|
||||
// Select your modem:
|
||||
#define TINY_GSM_MODEM_SIM800
|
||||
// #define TINY_GSM_MODEM_SIM808
|
||||
// #define TINY_GSM_MODEM_SIM900
|
||||
// #define TINY_GSM_MODEM_UBLOX
|
||||
// #define TINY_GSM_MODEM_BG96
|
||||
// #define TINY_GSM_MODEM_A6
|
||||
// #define TINY_GSM_MODEM_A7
|
||||
// #define TINY_GSM_MODEM_M590
|
||||
|
||||
// Set serial for debug console (to the Serial Monitor, speed 115200)
|
||||
#define SerialMon Serial
|
||||
|
||||
// Set serial for AT commands (to the module)
|
||||
// Use Hardware Serial on Mega, Leonardo, Micro
|
||||
#define SerialAT Serial1
|
||||
|
||||
// or Software Serial on Uno, Nano
|
||||
//#include <SoftwareSerial.h>
|
||||
//SoftwareSerial SerialAT(2, 3); // RX, TX
|
||||
|
||||
|
||||
//#define DUMP_AT_COMMANDS
|
||||
#define TINY_GSM_DEBUG SerialMon
|
||||
|
||||
// Set phone numbers, if you want to test SMS and Calls
|
||||
//#define SMS_TARGET "+380xxxxxxxxx"
|
||||
//#define CALL_TARGET "+380xxxxxxxxx"
|
||||
|
||||
// Your GPRS credentials
|
||||
// Leave empty, if missing user or pass
|
||||
const char apn[] = "YourAPN";
|
||||
const char user[] = "";
|
||||
const char pass[] = "";
|
||||
|
||||
#include <TinyGsmClient.h>
|
||||
|
||||
#ifdef DUMP_AT_COMMANDS
|
||||
#include <StreamDebugger.h>
|
||||
StreamDebugger debugger(SerialAT, SerialMon);
|
||||
TinyGsm modem(debugger);
|
||||
#else
|
||||
TinyGsm modem(SerialAT);
|
||||
#endif
|
||||
|
||||
void setup() {
|
||||
// Set console baud rate
|
||||
SerialMon.begin(115200);
|
||||
delay(10);
|
||||
|
||||
// Set your reset, enable, power pins here
|
||||
|
||||
delay(3000);
|
||||
|
||||
// Set GSM module baud rate
|
||||
TinyGsmAutoBaud(SerialAT);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
// Restart takes quite some time
|
||||
// To skip it, call init() instead of restart()
|
||||
DBG("Initializing modem...");
|
||||
if (!modem.restart()) {
|
||||
delay(10000);
|
||||
return;
|
||||
}
|
||||
|
||||
String modemInfo = modem.getModemInfo();
|
||||
DBG("Modem:", modemInfo);
|
||||
|
||||
// Unlock your SIM card with a PIN
|
||||
//modem.simUnlock("1234");
|
||||
|
||||
DBG("Waiting for network...");
|
||||
if (!modem.waitForNetwork()) {
|
||||
delay(10000);
|
||||
return;
|
||||
}
|
||||
|
||||
if (modem.isNetworkConnected()) {
|
||||
DBG("Network connected");
|
||||
}
|
||||
|
||||
DBG("Connecting to", apn);
|
||||
if (!modem.gprsConnect(apn, user, pass)) {
|
||||
delay(10000);
|
||||
return;
|
||||
}
|
||||
|
||||
bool res = modem.isGprsConnected();
|
||||
DBG("GPRS status:", res ? "connected" : "not connected");
|
||||
|
||||
String ccid = modem.getSimCCID();
|
||||
DBG("CCID:", ccid);
|
||||
|
||||
String imei = modem.getIMEI();
|
||||
DBG("IMEI:", imei);
|
||||
|
||||
String cop = modem.getOperator();
|
||||
DBG("Operator:", cop);
|
||||
|
||||
IPAddress local = modem.localIP();
|
||||
DBG("Local IP:", local);
|
||||
|
||||
int csq = modem.getSignalQuality();
|
||||
DBG("Signal quality:", csq);
|
||||
|
||||
// This is NOT supported on M590
|
||||
int battLevel = modem.getBattPercent();
|
||||
DBG("Battery lavel:", battLevel);
|
||||
|
||||
// This is only supported on SIMxxx series
|
||||
float battVoltage = modem.getBattVoltage() / 1000.0F;
|
||||
DBG("Battery voltage:", battVoltage);
|
||||
|
||||
// This is only supported on SIMxxx series
|
||||
String gsmLoc = modem.getGsmLocation();
|
||||
DBG("GSM location:", gsmLoc);
|
||||
|
||||
// This is only supported on SIMxxx series
|
||||
String gsmTime = modem.getGSMDateTime(DATE_TIME);
|
||||
DBG("GSM Time:", gsmTime);
|
||||
String gsmDate = modem.getGSMDateTime(DATE_DATE);
|
||||
DBG("GSM Date:", gsmDate);
|
||||
|
||||
String ussd_balance = modem.sendUSSD("*111#");
|
||||
DBG("Balance (USSD):", ussd_balance);
|
||||
|
||||
String ussd_phone_num = modem.sendUSSD("*161#");
|
||||
DBG("Phone number (USSD):", ussd_phone_num);
|
||||
|
||||
#if defined(TINY_GSM_MODEM_SIM808)
|
||||
modem.enableGPS();
|
||||
String gps_raw = modem.getGPSraw();
|
||||
modem.disableGPS();
|
||||
DBG("GPS raw data:", gps_raw);
|
||||
#endif
|
||||
|
||||
#if defined(SMS_TARGET)
|
||||
res = modem.sendSMS(SMS_TARGET, String("Hello from ") + imei);
|
||||
DBG("SMS:", res ? "OK" : "fail");
|
||||
|
||||
// This is only supported on SIMxxx series
|
||||
res = modem.sendSMS_UTF16(SMS_TARGET, u"Привіііт!", 9);
|
||||
DBG("UTF16 SMS:", res ? "OK" : "fail");
|
||||
#endif
|
||||
|
||||
#if defined(CALL_TARGET)
|
||||
DBG("Calling:", CALL_TARGET);
|
||||
|
||||
// This is NOT supported on M590
|
||||
res = modem.callNumber(CALL_TARGET);
|
||||
DBG("Call:", res ? "OK" : "fail");
|
||||
|
||||
if (res) {
|
||||
delay(1000L);
|
||||
|
||||
// Play DTMF A, duration 1000ms
|
||||
modem.dtmfSend('A', 1000);
|
||||
|
||||
// Play DTMF 0..4, default duration (100ms)
|
||||
for (char tone='0'; tone<='4'; tone++) {
|
||||
modem.dtmfSend(tone);
|
||||
}
|
||||
|
||||
delay(5000);
|
||||
|
||||
res = modem.callHangup();
|
||||
DBG("Hang up:", res ? "OK" : "fail");
|
||||
}
|
||||
#endif
|
||||
|
||||
modem.gprsDisconnect();
|
||||
if (!modem.isGprsConnected()) {
|
||||
DBG("GPRS disconnected");
|
||||
} else {
|
||||
DBG("GPRS disconnect: Failed.");
|
||||
}
|
||||
|
||||
// Try to power-off (modem may decide to restart automatically)
|
||||
// To turn off modem completely, please use Reset/Enable pins
|
||||
modem.poweroff();
|
||||
DBG("Poweroff.");
|
||||
|
||||
// Do nothing forevermore
|
||||
while (true) {
|
||||
modem.maintain();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/**************************************************************
|
||||
*
|
||||
* For this example, you need to install Blynk library:
|
||||
* https://github.com/blynkkk/blynk-library/releases/latest
|
||||
*
|
||||
* TinyGSM Getting Started guide:
|
||||
* https://tiny.cc/tinygsm-readme
|
||||
*
|
||||
**************************************************************
|
||||
*
|
||||
* Blynk is a platform with iOS and Android apps to control
|
||||
* Arduino, Raspberry Pi and the likes over the Internet.
|
||||
* You can easily build graphic interfaces for all your
|
||||
* projects by simply dragging and dropping widgets.
|
||||
*
|
||||
* Blynk supports many development boards with WiFi, Ethernet,
|
||||
* GSM, Bluetooth, BLE, USB/Serial connection methods.
|
||||
* See more in Blynk library examples and community forum.
|
||||
*
|
||||
* http://www.blynk.io/
|
||||
*
|
||||
* Change GPRS apm, user, pass, and Blynk auth token to run :)
|
||||
**************************************************************/
|
||||
|
||||
#define BLYNK_PRINT Serial // Comment this out to disable prints and save space
|
||||
|
||||
// Default heartbeat interval for GSM is 60
|
||||
// If you want override this value, uncomment and set this option:
|
||||
//#define BLYNK_HEARTBEAT 30
|
||||
|
||||
// Select your modem:
|
||||
#define TINY_GSM_MODEM_SIM800
|
||||
// #define TINY_GSM_MODEM_SIM808
|
||||
// #define TINY_GSM_MODEM_SIM900
|
||||
// #define TINY_GSM_MODEM_UBLOX
|
||||
// #define TINY_GSM_MODEM_BG96
|
||||
// #define TINY_GSM_MODEM_A6
|
||||
// #define TINY_GSM_MODEM_A7
|
||||
// #define TINY_GSM_MODEM_M590
|
||||
// #define TINY_GSM_MODEM_ESP8266
|
||||
// #define TINY_GSM_MODEM_XBEE
|
||||
|
||||
#include <TinyGsmClient.h>
|
||||
#include <BlynkSimpleSIM800.h>
|
||||
|
||||
// Set serial for debug console (to the Serial Monitor, default speed 115200)
|
||||
#define SerialMon Serial
|
||||
|
||||
// Hardware Serial on Mega, Leonardo, Micro
|
||||
#define SerialAT Serial1
|
||||
|
||||
// or Software Serial on Uno, Nano
|
||||
//#include <SoftwareSerial.h>
|
||||
//SoftwareSerial SerialAT(2, 3); // RX, TX
|
||||
|
||||
|
||||
// Your GPRS credentials
|
||||
// Leave empty, if missing user or pass
|
||||
const char apn[] = "YourAPN";
|
||||
const char user[] = "";
|
||||
const char pass[] = "";
|
||||
|
||||
// You should get Auth Token in the Blynk App.
|
||||
// Go to the Project Settings (nut icon).
|
||||
const char auth[] = "YourAuthToken";
|
||||
|
||||
TinyGsm modem(SerialAT);
|
||||
|
||||
void setup()
|
||||
{
|
||||
// Set console baud rate
|
||||
SerialMon.begin(115200);
|
||||
delay(10);
|
||||
|
||||
// Set GSM module baud rate
|
||||
SerialAT.begin(115200);
|
||||
delay(3000);
|
||||
|
||||
// Restart takes quite some time
|
||||
// To skip it, call init() instead of restart()
|
||||
SerialMon.println("Initializing modem...");
|
||||
modem.restart();
|
||||
|
||||
String modemInfo = modem.getModemInfo();
|
||||
SerialMon.print("Modem: ");
|
||||
SerialMon.println(modemInfo);
|
||||
|
||||
// Unlock your SIM card with a PIN
|
||||
//modem.simUnlock("1234");
|
||||
|
||||
Blynk.begin(auth, modem, apn, user, pass);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
Blynk.run();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
/**************************************************************
|
||||
*
|
||||
* For this example, you need to install CRC32 library:
|
||||
* https://github.com/bakercp/CRC32
|
||||
* or from http://librarymanager/all#CRC32+checksum
|
||||
*
|
||||
* TinyGSM Getting Started guide:
|
||||
* https://tiny.cc/tinygsm-readme
|
||||
*
|
||||
* ATTENTION! Downloading big files requires of knowledge of
|
||||
* the TinyGSM internals and some modem specifics,
|
||||
* so this is for more experienced developers.
|
||||
*
|
||||
**************************************************************/
|
||||
|
||||
// Select your modem:
|
||||
#define TINY_GSM_MODEM_SIM800
|
||||
// #define TINY_GSM_MODEM_SIM808
|
||||
// #define TINY_GSM_MODEM_SIM900
|
||||
// #define TINY_GSM_MODEM_UBLOX
|
||||
// #define TINY_GSM_MODEM_BG96
|
||||
// #define TINY_GSM_MODEM_A6
|
||||
// #define TINY_GSM_MODEM_A7
|
||||
// #define TINY_GSM_MODEM_M590
|
||||
// #define TINY_GSM_MODEM_ESP8266
|
||||
// #define TINY_GSM_MODEM_XBEE
|
||||
|
||||
// Increase RX buffer if needed
|
||||
#define TINY_GSM_RX_BUFFER 1024
|
||||
|
||||
#include <TinyGsmClient.h>
|
||||
#include <CRC32.h>
|
||||
|
||||
// Uncomment this if you want to see all AT commands
|
||||
//#define DUMP_AT_COMMANDS
|
||||
|
||||
// Set serial for debug console (to the Serial Monitor, default speed 115200)
|
||||
#define SerialMon Serial
|
||||
|
||||
// Use Hardware Serial on Mega, Leonardo, Micro
|
||||
#define SerialAT Serial1
|
||||
|
||||
// or Software Serial on Uno, Nano
|
||||
//#include <SoftwareSerial.h>
|
||||
//SoftwareSerial SerialAT(2, 3); // RX, TX
|
||||
|
||||
|
||||
// Your GPRS credentials
|
||||
// Leave empty, if missing user or pass
|
||||
const char apn[] = "YourAPN";
|
||||
const char user[] = "";
|
||||
const char pass[] = "";
|
||||
|
||||
// Server details
|
||||
const char server[] = "vsh.pp.ua";
|
||||
const int port = 80;
|
||||
|
||||
const char resource[] = "/TinyGSM/test_1k.bin";
|
||||
uint32_t knownCRC32 = 0x6f50d767;
|
||||
uint32_t knownFileSize = 1024; // In case server does not send it
|
||||
|
||||
#ifdef DUMP_AT_COMMANDS
|
||||
#include <StreamDebugger.h>
|
||||
StreamDebugger debugger(SerialAT, SerialMon);
|
||||
TinyGsm modem(debugger);
|
||||
#else
|
||||
TinyGsm modem(SerialAT);
|
||||
#endif
|
||||
|
||||
TinyGsmClient client(modem);
|
||||
|
||||
void setup() {
|
||||
// Set console baud rate
|
||||
SerialMon.begin(115200);
|
||||
delay(10);
|
||||
|
||||
// Set GSM module baud rate
|
||||
SerialAT.begin(115200);
|
||||
delay(3000);
|
||||
|
||||
// Restart takes quite some time
|
||||
// To skip it, call init() instead of restart()
|
||||
SerialMon.println(F("Initializing modem..."));
|
||||
modem.restart();
|
||||
|
||||
String modemInfo = modem.getModemInfo();
|
||||
SerialMon.print(F("Modem: "));
|
||||
SerialMon.println(modemInfo);
|
||||
|
||||
// Unlock your SIM card with a PIN
|
||||
//modem.simUnlock("1234");
|
||||
}
|
||||
|
||||
void printPercent(uint32_t readLength, uint32_t contentLength) {
|
||||
// If we know the total length
|
||||
if (contentLength != -1) {
|
||||
SerialMon.print("\r ");
|
||||
SerialMon.print((100.0 * readLength) / contentLength);
|
||||
SerialMon.print('%');
|
||||
} else {
|
||||
SerialMon.println(readLength);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
SerialMon.print(F("Waiting for network..."));
|
||||
if (!modem.waitForNetwork()) {
|
||||
SerialMon.println(" fail");
|
||||
delay(10000);
|
||||
return;
|
||||
}
|
||||
SerialMon.println(" OK");
|
||||
|
||||
SerialMon.print(F("Connecting to "));
|
||||
SerialMon.print(apn);
|
||||
if (!modem.gprsConnect(apn, user, pass)) {
|
||||
SerialMon.println(" fail");
|
||||
delay(10000);
|
||||
return;
|
||||
}
|
||||
SerialMon.println(" OK");
|
||||
|
||||
SerialMon.print(F("Connecting to "));
|
||||
SerialMon.print(server);
|
||||
if (!client.connect(server, port)) {
|
||||
SerialMon.println(" fail");
|
||||
delay(10000);
|
||||
return;
|
||||
}
|
||||
SerialMon.println(" OK");
|
||||
|
||||
// Make a HTTP GET request:
|
||||
client.print(String("GET ") + resource + " HTTP/1.0\r\n");
|
||||
client.print(String("Host: ") + server + "\r\n");
|
||||
client.print("Connection: close\r\n\r\n");
|
||||
|
||||
long timeout = millis();
|
||||
while (client.available() == 0) {
|
||||
if (millis() - timeout > 5000L) {
|
||||
SerialMon.println(F(">>> Client Timeout !"));
|
||||
client.stop();
|
||||
delay(10000L);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SerialMon.println(F("Reading response header"));
|
||||
uint32_t contentLength = knownFileSize;
|
||||
|
||||
while (client.available()) {
|
||||
String line = client.readStringUntil('\n');
|
||||
line.trim();
|
||||
//SerialMon.println(line); // Uncomment this to show response header
|
||||
line.toLowerCase();
|
||||
if (line.startsWith("content-length:")) {
|
||||
contentLength = line.substring(line.lastIndexOf(':') + 1).toInt();
|
||||
} else if (line.length() == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SerialMon.println(F("Reading response data"));
|
||||
timeout = millis();
|
||||
uint32_t readLength = 0;
|
||||
CRC32 crc;
|
||||
|
||||
unsigned long timeElapsed = millis();
|
||||
printPercent(readLength, contentLength);
|
||||
while (readLength < contentLength && client.connected() && millis() - timeout < 10000L) {
|
||||
while (client.available()) {
|
||||
uint8_t c = client.read();
|
||||
//SerialMon.print((char)c); // Uncomment this to show data
|
||||
crc.update(c);
|
||||
readLength++;
|
||||
if (readLength % (contentLength / 13) == 0) {
|
||||
printPercent(readLength, contentLength);
|
||||
}
|
||||
timeout = millis();
|
||||
}
|
||||
}
|
||||
printPercent(readLength, contentLength);
|
||||
timeElapsed = millis() - timeElapsed;
|
||||
SerialMon.println();
|
||||
|
||||
// Shutdown
|
||||
|
||||
client.stop();
|
||||
SerialMon.println(F("Server disconnected"));
|
||||
|
||||
modem.gprsDisconnect();
|
||||
SerialMon.println(F("GPRS disconnected"));
|
||||
|
||||
float duration = float(timeElapsed) / 1000;
|
||||
|
||||
SerialMon.println();
|
||||
SerialMon.print("Content-Length: "); SerialMon.println(contentLength);
|
||||
SerialMon.print("Actually read: "); SerialMon.println(readLength);
|
||||
SerialMon.print("Calc. CRC32: 0x"); SerialMon.println(crc.finalize(), HEX);
|
||||
SerialMon.print("Known CRC32: 0x"); SerialMon.println(knownCRC32, HEX);
|
||||
SerialMon.print("Duration: "); SerialMon.print(duration); SerialMon.println("s");
|
||||
|
||||
// Do nothing forevermore
|
||||
while (true) {
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
160
arduino-cli/libraries/TinyGSM/examples/HttpClient/HttpClient.ino
Normal file
160
arduino-cli/libraries/TinyGSM/examples/HttpClient/HttpClient.ino
Normal file
@@ -0,0 +1,160 @@
|
||||
/**************************************************************
|
||||
*
|
||||
* This sketch connects to a website and downloads a page.
|
||||
* It can be used to perform HTTP/RESTful API calls.
|
||||
*
|
||||
* For this example, you need to install ArduinoHttpClient library:
|
||||
* https://github.com/arduino-libraries/ArduinoHttpClient
|
||||
* or from http://librarymanager/all#ArduinoHttpClient
|
||||
*
|
||||
* TinyGSM Getting Started guide:
|
||||
* https://tiny.cc/tinygsm-readme
|
||||
*
|
||||
* For more HTTP API examples, see ArduinoHttpClient library
|
||||
*
|
||||
**************************************************************/
|
||||
|
||||
// Select your modem:
|
||||
#define TINY_GSM_MODEM_SIM800
|
||||
// #define TINY_GSM_MODEM_SIM808
|
||||
// #define TINY_GSM_MODEM_SIM900
|
||||
// #define TINY_GSM_MODEM_UBLOX
|
||||
// #define TINY_GSM_MODEM_BG96
|
||||
// #define TINY_GSM_MODEM_A6
|
||||
// #define TINY_GSM_MODEM_A7
|
||||
// #define TINY_GSM_MODEM_M590
|
||||
// #define TINY_GSM_MODEM_ESP8266
|
||||
|
||||
// Increase RX buffer if needed
|
||||
//#define TINY_GSM_RX_BUFFER 512
|
||||
|
||||
#include <TinyGsmClient.h>
|
||||
#include <ArduinoHttpClient.h>
|
||||
|
||||
// Uncomment this if you want to see all AT commands
|
||||
//#define DUMP_AT_COMMANDS
|
||||
|
||||
// Set serial for debug console (to the Serial Monitor, default speed 115200)
|
||||
#define SerialMon Serial
|
||||
|
||||
// Use Hardware Serial on Mega, Leonardo, Micro
|
||||
#define SerialAT Serial1
|
||||
|
||||
// or Software Serial on Uno, Nano
|
||||
//#include <SoftwareSerial.h>
|
||||
//SoftwareSerial SerialAT(2, 3); // RX, TX
|
||||
|
||||
|
||||
// Your GPRS credentials
|
||||
// Leave empty, if missing user or pass
|
||||
const char apn[] = "YourAPN";
|
||||
const char user[] = "";
|
||||
const char pass[] = "";
|
||||
|
||||
// Server details
|
||||
const char server[] = "vsh.pp.ua";
|
||||
const char resource[] = "/TinyGSM/logo.txt";
|
||||
const int port = 80;
|
||||
|
||||
#ifdef DUMP_AT_COMMANDS
|
||||
#include <StreamDebugger.h>
|
||||
StreamDebugger debugger(SerialAT, SerialMon);
|
||||
TinyGsm modem(debugger);
|
||||
#else
|
||||
TinyGsm modem(SerialAT);
|
||||
#endif
|
||||
|
||||
TinyGsmClient client(modem);
|
||||
HttpClient http(client, server, port);
|
||||
|
||||
void setup() {
|
||||
// Set console baud rate
|
||||
SerialMon.begin(115200);
|
||||
delay(10);
|
||||
|
||||
// Set GSM module baud rate
|
||||
SerialAT.begin(115200);
|
||||
delay(3000);
|
||||
|
||||
// Restart takes quite some time
|
||||
// To skip it, call init() instead of restart()
|
||||
SerialMon.println(F("Initializing modem..."));
|
||||
modem.restart();
|
||||
|
||||
String modemInfo = modem.getModemInfo();
|
||||
SerialMon.print(F("Modem: "));
|
||||
SerialMon.println(modemInfo);
|
||||
|
||||
// Unlock your SIM card with a PIN
|
||||
//modem.simUnlock("1234");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
SerialMon.print(F("Waiting for network..."));
|
||||
if (!modem.waitForNetwork()) {
|
||||
SerialMon.println(" fail");
|
||||
delay(10000);
|
||||
return;
|
||||
}
|
||||
SerialMon.println(" OK");
|
||||
|
||||
SerialMon.print(F("Connecting to "));
|
||||
SerialMon.print(apn);
|
||||
if (!modem.gprsConnect(apn, user, pass)) {
|
||||
SerialMon.println(" fail");
|
||||
delay(10000);
|
||||
return;
|
||||
}
|
||||
SerialMon.println(" OK");
|
||||
|
||||
SerialMon.print(F("Performing HTTP GET request... "));
|
||||
int err = http.get(resource);
|
||||
if (err != 0) {
|
||||
SerialMon.println(F("failed to connect"));
|
||||
delay(10000);
|
||||
return;
|
||||
}
|
||||
|
||||
int status = http.responseStatusCode();
|
||||
SerialMon.println(status);
|
||||
if (!status) {
|
||||
delay(10000);
|
||||
return;
|
||||
}
|
||||
|
||||
while (http.headerAvailable()) {
|
||||
String headerName = http.readHeaderName();
|
||||
String headerValue = http.readHeaderValue();
|
||||
//SerialMon.println(headerName + " : " + headerValue);
|
||||
}
|
||||
|
||||
int length = http.contentLength();
|
||||
if (length >= 0) {
|
||||
SerialMon.print(F("Content length is: "));
|
||||
SerialMon.println(length);
|
||||
}
|
||||
if (http.isResponseChunked()) {
|
||||
SerialMon.println(F("The response is chunked"));
|
||||
}
|
||||
|
||||
String body = http.responseBody();
|
||||
SerialMon.println(F("Response:"));
|
||||
SerialMon.println(body);
|
||||
|
||||
SerialMon.print(F("Body length is: "));
|
||||
SerialMon.println(body.length());
|
||||
|
||||
// Shutdown
|
||||
|
||||
http.stop();
|
||||
SerialMon.println(F("Server disconnected"));
|
||||
|
||||
modem.gprsDisconnect();
|
||||
SerialMon.println(F("GPRS disconnected"));
|
||||
|
||||
// Do nothing forevermore
|
||||
while (true) {
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
/**************************************************************
|
||||
*
|
||||
* This sketch connects to a website and downloads a page.
|
||||
* It can be used to perform HTTP/RESTful API calls.
|
||||
*
|
||||
* For this example, you need to install ArduinoHttpClient library:
|
||||
* https://github.com/arduino-libraries/ArduinoHttpClient
|
||||
* or from http://librarymanager/all#ArduinoHttpClient
|
||||
*
|
||||
* TinyGSM Getting Started guide:
|
||||
* https://tiny.cc/tinygsm-readme
|
||||
*
|
||||
* SSL/TLS is currently supported only with: SIM8xx, uBlox
|
||||
*
|
||||
* For more HTTP API examples, see ArduinoHttpClient library
|
||||
*
|
||||
**************************************************************/
|
||||
|
||||
// Select your modem:
|
||||
#define TINY_GSM_MODEM_SIM800
|
||||
// #define TINY_GSM_MODEM_SIM808
|
||||
// #define TINY_GSM_MODEM_UBLOX
|
||||
|
||||
// Increase RX buffer if needed
|
||||
//#define TINY_GSM_RX_BUFFER 512
|
||||
|
||||
#include <TinyGsmClient.h>
|
||||
#include <ArduinoHttpClient.h>
|
||||
|
||||
// Uncomment this if you want to see all AT commands
|
||||
//#define DUMP_AT_COMMANDS
|
||||
|
||||
// Set serial for debug console (to the Serial Monitor, default speed 115200)
|
||||
#define SerialMon Serial
|
||||
|
||||
// Use Hardware Serial on Mega, Leonardo, Micro
|
||||
#define SerialAT Serial1
|
||||
|
||||
// or Software Serial on Uno, Nano
|
||||
//#include <SoftwareSerial.h>
|
||||
//SoftwareSerial SerialAT(2, 3); // RX, TX
|
||||
|
||||
|
||||
// Your GPRS credentials
|
||||
// Leave empty, if missing user or pass
|
||||
const char apn[] = "YourAPN";
|
||||
const char user[] = "";
|
||||
const char pass[] = "";
|
||||
|
||||
// Server details
|
||||
const char server[] = "vsh.pp.ua";
|
||||
const char resource[] = "/TinyGSM/logo.txt";
|
||||
const int port = 443;
|
||||
|
||||
#ifdef DUMP_AT_COMMANDS
|
||||
#include <StreamDebugger.h>
|
||||
StreamDebugger debugger(SerialAT, SerialMon);
|
||||
TinyGsm modem(debugger);
|
||||
#else
|
||||
TinyGsm modem(SerialAT);
|
||||
#endif
|
||||
|
||||
TinyGsmClientSecure client(modem);
|
||||
HttpClient http(client, server, port);
|
||||
|
||||
void setup() {
|
||||
// Set console baud rate
|
||||
SerialMon.begin(115200);
|
||||
delay(10);
|
||||
|
||||
// Set GSM module baud rate
|
||||
SerialAT.begin(115200);
|
||||
delay(3000);
|
||||
|
||||
// Restart takes quite some time
|
||||
// To skip it, call init() instead of restart()
|
||||
SerialMon.println(F("Initializing modem..."));
|
||||
modem.restart();
|
||||
|
||||
String modemInfo = modem.getModemInfo();
|
||||
SerialMon.print(F("Modem: "));
|
||||
SerialMon.println(modemInfo);
|
||||
|
||||
// Unlock your SIM card with a PIN
|
||||
//modem.simUnlock("1234");
|
||||
|
||||
if (!modem.hasSSL()) {
|
||||
SerialMon.println(F("SSL is not supported by this modem"));
|
||||
while(true) { delay(1000); }
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
SerialMon.print(F("Waiting for network..."));
|
||||
if (!modem.waitForNetwork()) {
|
||||
SerialMon.println(" fail");
|
||||
delay(10000);
|
||||
return;
|
||||
}
|
||||
SerialMon.println(" OK");
|
||||
|
||||
SerialMon.print(F("Connecting to "));
|
||||
SerialMon.print(apn);
|
||||
if (!modem.gprsConnect(apn, user, pass)) {
|
||||
SerialMon.println(" fail");
|
||||
delay(10000);
|
||||
return;
|
||||
}
|
||||
SerialMon.println(" OK");
|
||||
|
||||
SerialMon.print(F("Performing HTTPS GET request... "));
|
||||
http.connectionKeepAlive(); // Currently, this is needed for HTTPS
|
||||
int err = http.get(resource);
|
||||
if (err != 0) {
|
||||
SerialMon.println(F("failed to connect"));
|
||||
delay(10000);
|
||||
return;
|
||||
}
|
||||
|
||||
int status = http.responseStatusCode();
|
||||
SerialMon.println(status);
|
||||
if (!status) {
|
||||
delay(10000);
|
||||
return;
|
||||
}
|
||||
|
||||
while (http.headerAvailable()) {
|
||||
String headerName = http.readHeaderName();
|
||||
String headerValue = http.readHeaderValue();
|
||||
//SerialMon.println(headerName + " : " + headerValue);
|
||||
}
|
||||
|
||||
int length = http.contentLength();
|
||||
if (length >= 0) {
|
||||
SerialMon.print(F("Content length is: "));
|
||||
SerialMon.println(length);
|
||||
}
|
||||
if (http.isResponseChunked()) {
|
||||
SerialMon.println(F("The response is chunked"));
|
||||
}
|
||||
|
||||
String body = http.responseBody();
|
||||
SerialMon.println(F("Response:"));
|
||||
SerialMon.println(body);
|
||||
|
||||
SerialMon.print(F("Body length is: "));
|
||||
SerialMon.println(body.length());
|
||||
|
||||
// Shutdown
|
||||
|
||||
http.stop();
|
||||
SerialMon.println(F("Server disconnected"));
|
||||
|
||||
modem.gprsDisconnect();
|
||||
SerialMon.println(F("GPRS disconnected"));
|
||||
|
||||
// Do nothing forevermore
|
||||
while (true) {
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
174
arduino-cli/libraries/TinyGSM/examples/MqttClient/MqttClient.ino
Normal file
174
arduino-cli/libraries/TinyGSM/examples/MqttClient/MqttClient.ino
Normal file
@@ -0,0 +1,174 @@
|
||||
/**************************************************************
|
||||
*
|
||||
* For this example, you need to install PubSubClient library:
|
||||
* https://github.com/knolleary/pubsubclient
|
||||
* or from http://librarymanager/all#PubSubClient
|
||||
*
|
||||
* TinyGSM Getting Started guide:
|
||||
* https://tiny.cc/tinygsm-readme
|
||||
*
|
||||
* For more MQTT examples, see PubSubClient library
|
||||
*
|
||||
**************************************************************
|
||||
* Use Mosquitto client tools to work with MQTT
|
||||
* Ubuntu/Linux: sudo apt-get install mosquitto-clients
|
||||
* Windows: https://mosquitto.org/download/
|
||||
*
|
||||
* Subscribe for messages:
|
||||
* mosquitto_sub -h test.mosquitto.org -t GsmClientTest/init -t GsmClientTest/ledStatus -q 1
|
||||
* Toggle led:
|
||||
* mosquitto_pub -h test.mosquitto.org -t GsmClientTest/led -q 1 -m "toggle"
|
||||
*
|
||||
* You can use Node-RED for wiring together MQTT-enabled devices
|
||||
* https://nodered.org/
|
||||
* Also, take a look at these additional Node-RED modules:
|
||||
* node-red-contrib-blynk-ws
|
||||
* node-red-dashboard
|
||||
*
|
||||
**************************************************************/
|
||||
|
||||
// Select your modem:
|
||||
#define TINY_GSM_MODEM_SIM800
|
||||
// #define TINY_GSM_MODEM_SIM808
|
||||
// #define TINY_GSM_MODEM_SIM900
|
||||
// #define TINY_GSM_MODEM_UBLOX
|
||||
// #define TINY_GSM_MODEM_BG96
|
||||
// #define TINY_GSM_MODEM_A6
|
||||
// #define TINY_GSM_MODEM_A7
|
||||
// #define TINY_GSM_MODEM_M590
|
||||
// #define TINY_GSM_MODEM_ESP8266
|
||||
// #define TINY_GSM_MODEM_XBEE
|
||||
|
||||
#include <TinyGsmClient.h>
|
||||
#include <PubSubClient.h>
|
||||
|
||||
// Set serial for debug console (to the Serial Monitor, default speed 115200)
|
||||
#define SerialMon Serial
|
||||
|
||||
// Use Hardware Serial on Mega, Leonardo, Micro
|
||||
#define SerialAT Serial1
|
||||
|
||||
// or Software Serial on Uno, Nano
|
||||
//#include <SoftwareSerial.h>
|
||||
//SoftwareSerial SerialAT(2, 3); // RX, TX
|
||||
|
||||
|
||||
// Your GPRS credentials
|
||||
// Leave empty, if missing user or pass
|
||||
const char apn[] = "YourAPN";
|
||||
const char user[] = "";
|
||||
const char pass[] = "";
|
||||
|
||||
// MQTT details
|
||||
const char* broker = "test.mosquitto.org";
|
||||
|
||||
const char* topicLed = "GsmClientTest/led";
|
||||
const char* topicInit = "GsmClientTest/init";
|
||||
const char* topicLedStatus = "GsmClientTest/ledStatus";
|
||||
|
||||
TinyGsm modem(SerialAT);
|
||||
TinyGsmClient client(modem);
|
||||
PubSubClient mqtt(client);
|
||||
|
||||
#define LED_PIN 13
|
||||
int ledStatus = LOW;
|
||||
|
||||
long lastReconnectAttempt = 0;
|
||||
|
||||
void setup() {
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
|
||||
// Set console baud rate
|
||||
SerialMon.begin(115200);
|
||||
delay(10);
|
||||
|
||||
// Set GSM module baud rate
|
||||
SerialAT.begin(115200);
|
||||
delay(3000);
|
||||
|
||||
// Restart takes quite some time
|
||||
// To skip it, call init() instead of restart()
|
||||
SerialMon.println("Initializing modem...");
|
||||
modem.restart();
|
||||
|
||||
String modemInfo = modem.getModemInfo();
|
||||
SerialMon.print("Modem: ");
|
||||
SerialMon.println(modemInfo);
|
||||
|
||||
// Unlock your SIM card with a PIN
|
||||
//modem.simUnlock("1234");
|
||||
|
||||
SerialMon.print("Waiting for network...");
|
||||
if (!modem.waitForNetwork()) {
|
||||
SerialMon.println(" fail");
|
||||
while (true);
|
||||
}
|
||||
SerialMon.println(" OK");
|
||||
|
||||
SerialMon.print("Connecting to ");
|
||||
SerialMon.print(apn);
|
||||
if (!modem.gprsConnect(apn, user, pass)) {
|
||||
SerialMon.println(" fail");
|
||||
while (true);
|
||||
}
|
||||
SerialMon.println(" OK");
|
||||
|
||||
// MQTT Broker setup
|
||||
mqtt.setServer(broker, 1883);
|
||||
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(" OK");
|
||||
mqtt.publish(topicInit, "GsmClientTest started");
|
||||
mqtt.subscribe(topicLed);
|
||||
return mqtt.connected();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
if (!mqtt.connected()) {
|
||||
SerialMon.println("=== MQTT NOT CONNECTED ===");
|
||||
// Reconnect every 10 seconds
|
||||
unsigned long t = millis();
|
||||
if (t - lastReconnectAttempt > 10000L) {
|
||||
lastReconnectAttempt = t;
|
||||
if (mqttConnect()) {
|
||||
lastReconnectAttempt = 0;
|
||||
}
|
||||
}
|
||||
delay(100);
|
||||
return;
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
148
arduino-cli/libraries/TinyGSM/examples/WebClient/WebClient.ino
Normal file
148
arduino-cli/libraries/TinyGSM/examples/WebClient/WebClient.ino
Normal file
@@ -0,0 +1,148 @@
|
||||
/**************************************************************
|
||||
*
|
||||
* This sketch connects to a website and downloads a page.
|
||||
* It can be used to perform HTTP/RESTful API calls.
|
||||
*
|
||||
* TinyGSM Getting Started guide:
|
||||
* https://tiny.cc/tinygsm-readme
|
||||
*
|
||||
**************************************************************/
|
||||
|
||||
// Select your modem:
|
||||
#define TINY_GSM_MODEM_SIM800
|
||||
// #define TINY_GSM_MODEM_SIM808
|
||||
// #define TINY_GSM_MODEM_SIM900
|
||||
// #define TINY_GSM_MODEM_UBLOX
|
||||
// #define TINY_GSM_MODEM_BG96
|
||||
// #define TINY_GSM_MODEM_A6
|
||||
// #define TINY_GSM_MODEM_A7
|
||||
// #define TINY_GSM_MODEM_M590
|
||||
// #define TINY_GSM_MODEM_ESP8266
|
||||
|
||||
// Increase RX buffer if needed
|
||||
//#define TINY_GSM_RX_BUFFER 512
|
||||
|
||||
#include <TinyGsmClient.h>
|
||||
|
||||
// Uncomment this if you want to see all AT commands
|
||||
//#define DUMP_AT_COMMANDS
|
||||
|
||||
// Uncomment this if you want to use SSL
|
||||
//#define USE_SSL
|
||||
|
||||
// Set serial for debug console (to the Serial Monitor, default speed 115200)
|
||||
#define SerialMon Serial
|
||||
|
||||
// Use Hardware Serial on Mega, Leonardo, Micro
|
||||
#define SerialAT Serial1
|
||||
|
||||
// or Software Serial on Uno, Nano
|
||||
//#include <SoftwareSerial.h>
|
||||
//SoftwareSerial SerialAT(2, 3); // RX, TX
|
||||
|
||||
|
||||
// Your GPRS credentials
|
||||
// Leave empty, if missing user or pass
|
||||
const char apn[] = "YourAPN";
|
||||
const char user[] = "";
|
||||
const char pass[] = "";
|
||||
|
||||
// Server details
|
||||
const char server[] = "vsh.pp.ua";
|
||||
const char resource[] = "/TinyGSM/logo.txt";
|
||||
|
||||
#ifdef DUMP_AT_COMMANDS
|
||||
#include <StreamDebugger.h>
|
||||
StreamDebugger debugger(SerialAT, SerialMon);
|
||||
TinyGsm modem(debugger);
|
||||
#else
|
||||
TinyGsm modem(SerialAT);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SSL
|
||||
TinyGsmClientSecure client(modem);
|
||||
const int port = 443;
|
||||
#else
|
||||
TinyGsmClient client(modem);
|
||||
const int port = 80;
|
||||
#endif
|
||||
|
||||
void setup() {
|
||||
// Set console baud rate
|
||||
SerialMon.begin(115200);
|
||||
delay(10);
|
||||
|
||||
// Set GSM module baud rate
|
||||
SerialAT.begin(115200);
|
||||
delay(3000);
|
||||
|
||||
// Restart takes quite some time
|
||||
// To skip it, call init() instead of restart()
|
||||
SerialMon.println(F("Initializing modem..."));
|
||||
modem.restart();
|
||||
|
||||
String modemInfo = modem.getModemInfo();
|
||||
SerialMon.print(F("Modem: "));
|
||||
SerialMon.println(modemInfo);
|
||||
|
||||
// Unlock your SIM card with a PIN
|
||||
//modem.simUnlock("1234");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
SerialMon.print(F("Waiting for network..."));
|
||||
if (!modem.waitForNetwork()) {
|
||||
SerialMon.println(" fail");
|
||||
delay(10000);
|
||||
return;
|
||||
}
|
||||
SerialMon.println(" OK");
|
||||
|
||||
SerialMon.print(F("Connecting to "));
|
||||
SerialMon.print(apn);
|
||||
if (!modem.gprsConnect(apn, user, pass)) {
|
||||
SerialMon.println(" fail");
|
||||
delay(10000);
|
||||
return;
|
||||
}
|
||||
SerialMon.println(" OK");
|
||||
|
||||
SerialMon.print(F("Connecting to "));
|
||||
SerialMon.print(server);
|
||||
if (!client.connect(server, port)) {
|
||||
SerialMon.println(" fail");
|
||||
delay(10000);
|
||||
return;
|
||||
}
|
||||
SerialMon.println(" OK");
|
||||
|
||||
// Make a HTTP GET request:
|
||||
client.print(String("GET ") + resource + " HTTP/1.0\r\n");
|
||||
client.print(String("Host: ") + server + "\r\n");
|
||||
client.print("Connection: close\r\n\r\n");
|
||||
|
||||
unsigned long timeout = millis();
|
||||
while (client.connected() && millis() - timeout < 10000L) {
|
||||
// Print available data
|
||||
while (client.available()) {
|
||||
char c = client.read();
|
||||
SerialMon.print(c);
|
||||
timeout = millis();
|
||||
}
|
||||
}
|
||||
SerialMon.println();
|
||||
|
||||
// Shutdown
|
||||
|
||||
client.stop();
|
||||
SerialMon.println(F("Server disconnected"));
|
||||
|
||||
modem.gprsDisconnect();
|
||||
SerialMon.println(F("GPRS disconnected"));
|
||||
|
||||
// Do nothing forevermore
|
||||
while (true) {
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
/**************************************************************
|
||||
*
|
||||
* This sketch connects to a website and downloads a page.
|
||||
* It can be used to perform HTTP/RESTful API calls.
|
||||
*
|
||||
* TinyGSM Getting Started guide:
|
||||
* https://tiny.cc/tinygsm-readme
|
||||
*
|
||||
**************************************************************/
|
||||
|
||||
// Hologram Dash uses UBLOX U2 modems
|
||||
#define TINY_GSM_MODEM_UBLOX
|
||||
|
||||
// Increase RX buffer if needed
|
||||
//#define TINY_GSM_RX_BUFFER 512
|
||||
|
||||
#include <TinyGsmClient.h>
|
||||
|
||||
// Uncomment this if you want to see all AT commands
|
||||
//#define DUMP_AT_COMMANDS
|
||||
|
||||
// Uncomment this if you want to use SSL
|
||||
//#define USE_SSL
|
||||
|
||||
// Set serial for debug console (to the Serial Monitor, speed 115200)
|
||||
#define SerialMon Serial
|
||||
|
||||
// We'll be using SerialSystem in Passthrough mode
|
||||
#define SerialAT SerialSystem
|
||||
|
||||
// Your GPRS credentials
|
||||
// Leave empty, if missing user or pass
|
||||
const char apn[] = "YourAPN";
|
||||
const char user[] = "";
|
||||
const char pass[] = "";
|
||||
|
||||
// Server details
|
||||
const char server[] = "vsh.pp.ua";
|
||||
const char resource[] = "/TinyGSM/logo.txt";
|
||||
|
||||
#ifdef DUMP_AT_COMMANDS
|
||||
#include <StreamDebugger.h>
|
||||
StreamDebugger debugger(SerialAT, SerialMon);
|
||||
TinyGsm mdm(debugger);
|
||||
#else
|
||||
TinyGsm mdm(SerialAT);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SSL
|
||||
TinyGsmClientSecure client(mdm);
|
||||
const int port = 443;
|
||||
#else
|
||||
TinyGsmClient client(mdm);
|
||||
const int port = 80;
|
||||
#endif
|
||||
|
||||
void setup() {
|
||||
// Set console baud rate
|
||||
SerialMon.begin(115200);
|
||||
delay(10);
|
||||
|
||||
// Set up Passthrough
|
||||
HologramCloud.enterPassthrough();
|
||||
delay(3000);
|
||||
|
||||
// Restart takes quite some time
|
||||
// To skip it, call init() instead of restart()
|
||||
SerialMon.println(F("Initializing modem..."));
|
||||
mdm.restart();
|
||||
|
||||
String modemInfo = mdm.getModemInfo();
|
||||
SerialMon.print(F("Modem: "));
|
||||
SerialMon.println(modemInfo);
|
||||
|
||||
// Unlock your SIM card with a PIN
|
||||
//mdm.simUnlock("1234");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
SerialMon.print(F("Waiting for network..."));
|
||||
if (!mdm.waitForNetwork()) {
|
||||
SerialMon.println(" fail");
|
||||
delay(10000);
|
||||
return;
|
||||
}
|
||||
SerialMon.println(" OK");
|
||||
|
||||
SerialMon.print(F("Connecting to "));
|
||||
SerialMon.print(apn);
|
||||
if (!mdm.gprsConnect(apn, user, pass)) {
|
||||
SerialMon.println(" fail");
|
||||
delay(10000);
|
||||
return;
|
||||
}
|
||||
SerialMon.println(" OK");
|
||||
|
||||
SerialMon.print(F("Connecting to "));
|
||||
SerialMon.print(server);
|
||||
if (!client.connect(server, port)) {
|
||||
SerialMon.println(" fail");
|
||||
delay(10000);
|
||||
return;
|
||||
}
|
||||
SerialMon.println(" OK");
|
||||
|
||||
// Make a HTTP GET request:
|
||||
client.print(String("GET ") + resource + " HTTP/1.0\r\n");
|
||||
client.print(String("Host: ") + server + "\r\n");
|
||||
client.print("Connection: close\r\n\r\n");
|
||||
|
||||
unsigned long timeout = millis();
|
||||
while (client.connected() && millis() - timeout < 10000L) {
|
||||
// Print available data
|
||||
while (client.available()) {
|
||||
char c = client.read();
|
||||
SerialMon.print(c);
|
||||
timeout = millis();
|
||||
}
|
||||
}
|
||||
SerialMon.println();
|
||||
|
||||
// Shutdown
|
||||
|
||||
client.stop();
|
||||
SerialMon.println(F("Server disconnected"));
|
||||
|
||||
mdm.gprsDisconnect();
|
||||
SerialMon.println(F("GPRS disconnected"));
|
||||
|
||||
// Do nothing forevermore
|
||||
while (true) {
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
/**************************************************************
|
||||
*
|
||||
* This sketch connects to a website and downloads a page.
|
||||
* It can be used to perform HTTP/RESTful API calls.
|
||||
*
|
||||
* For this example, you need to install ArduinoHttpClient library:
|
||||
* https://github.com/arduino-libraries/ArduinoHttpClient
|
||||
* or from http://librarymanager/all#ArduinoHttpClient
|
||||
*
|
||||
* TinyGSM Getting Started guide:
|
||||
* https://tiny.cc/tinygsm-readme
|
||||
*
|
||||
* For more HTTP API examples, see ArduinoHttpClient library
|
||||
*
|
||||
**************************************************************/
|
||||
|
||||
// Industruino uses SIM800H
|
||||
#define TINY_GSM_MODEM_SIM800
|
||||
|
||||
// Increase RX buffer if needed
|
||||
//#define TINY_GSM_RX_BUFFER 512
|
||||
|
||||
#include <TinyGsmClient.h>
|
||||
#include <ArduinoHttpClient.h>
|
||||
|
||||
// Uncomment this if you want to see all AT commands
|
||||
//#define DUMP_AT_COMMANDS
|
||||
|
||||
// Uncomment this if you want to use SSL
|
||||
//#define USE_SSL
|
||||
|
||||
// Set serial for debug console (to the Serial Monitor, speed 115200)
|
||||
#define SerialMon SerialUSB
|
||||
|
||||
// Select Serial1 or Serial depending on your module configuration
|
||||
#define SerialAT Serial1
|
||||
|
||||
// Your GPRS credentials
|
||||
// Leave empty, if missing user or pass
|
||||
const char apn[] = "YourAPN";
|
||||
const char user[] = "";
|
||||
const char pass[] = "";
|
||||
|
||||
// Server details
|
||||
const char server[] = "vsh.pp.ua";
|
||||
const char resource[] = "/TinyGSM/logo.txt";
|
||||
|
||||
#ifdef DUMP_AT_COMMANDS
|
||||
#include <StreamDebugger.h>
|
||||
StreamDebugger debugger(SerialAT, SerialMon);
|
||||
TinyGsm modem(debugger);
|
||||
#else
|
||||
TinyGsm modem(SerialAT);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SSL
|
||||
TinyGsmClientSecure client(modem);
|
||||
HttpClient http(client, server, 443);
|
||||
#else
|
||||
TinyGsmClient client(modem);
|
||||
HttpClient http(client, server, 80);
|
||||
#endif
|
||||
|
||||
void setup() {
|
||||
// Turn on modem with 1 second pulse on D6
|
||||
pinMode(6, OUTPUT);
|
||||
digitalWrite(6, HIGH);
|
||||
delay(1000);
|
||||
digitalWrite(6, LOW);
|
||||
|
||||
// Set console baud rate
|
||||
SerialMon.begin(115200);
|
||||
delay(10);
|
||||
|
||||
// Set GSM module baud rate
|
||||
SerialAT.begin(115200);
|
||||
delay(3000);
|
||||
|
||||
// Restart takes quite some time
|
||||
// To skip it, call init() instead of restart()
|
||||
SerialMon.println(F("Initializing modem..."));
|
||||
modem.restart();
|
||||
|
||||
String modemInfo = modem.getModemInfo();
|
||||
SerialMon.print(F("Modem: "));
|
||||
SerialMon.println(modemInfo);
|
||||
|
||||
// Unlock your SIM card with a PIN
|
||||
//modem.simUnlock("1234");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
SerialMon.print(F("Waiting for network..."));
|
||||
if (!modem.waitForNetwork()) {
|
||||
SerialMon.println(" fail");
|
||||
delay(10000);
|
||||
return;
|
||||
}
|
||||
SerialMon.println(" OK");
|
||||
|
||||
SerialMon.print(F("Connecting to "));
|
||||
SerialMon.print(apn);
|
||||
if (!modem.gprsConnect(apn, user, pass)) {
|
||||
SerialMon.println(" fail");
|
||||
delay(10000);
|
||||
return;
|
||||
}
|
||||
SerialMon.println(" OK");
|
||||
|
||||
SerialMon.print(F("Performing HTTP GET request... "));
|
||||
int err = http.get(resource);
|
||||
if (err != 0) {
|
||||
SerialMon.println(F("failed to connect"));
|
||||
delay(10000);
|
||||
return;
|
||||
}
|
||||
|
||||
int status = http.responseStatusCode();
|
||||
SerialMon.println(status);
|
||||
if (!status) {
|
||||
delay(10000);
|
||||
return;
|
||||
}
|
||||
|
||||
while (http.headerAvailable()) {
|
||||
String headerName = http.readHeaderName();
|
||||
String headerValue = http.readHeaderValue();
|
||||
//SerialMon.println(headerName + " : " + headerValue);
|
||||
}
|
||||
|
||||
int length = http.contentLength();
|
||||
if (length >= 0) {
|
||||
SerialMon.print(F("Content length is: "));
|
||||
SerialMon.println(length);
|
||||
}
|
||||
if (http.isResponseChunked()) {
|
||||
SerialMon.println(F("The response is chunked"));
|
||||
}
|
||||
|
||||
String body = http.responseBody();
|
||||
SerialMon.println(F("Response:"));
|
||||
SerialMon.println(body);
|
||||
|
||||
SerialMon.print(F("Body length is: "));
|
||||
SerialMon.println(body.length());
|
||||
|
||||
// Shutdown
|
||||
|
||||
http.stop();
|
||||
SerialMon.println(F("Server disconnected"));
|
||||
|
||||
modem.gprsDisconnect();
|
||||
SerialMon.println(F("GPRS disconnected"));
|
||||
|
||||
// Do nothing forevermore
|
||||
while (true) {
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
const char cert[] PROGMEM =
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
"MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB\n"
|
||||
"hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G\n"
|
||||
"A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV\n"
|
||||
"BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5\n"
|
||||
"MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT\n"
|
||||
"EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR\n"
|
||||
"Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh\n"
|
||||
"dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR\n"
|
||||
"6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X\n"
|
||||
"pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC\n"
|
||||
"9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV\n"
|
||||
"/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf\n"
|
||||
"Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z\n"
|
||||
"+pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w\n"
|
||||
"qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah\n"
|
||||
"SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC\n"
|
||||
"u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf\n"
|
||||
"Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq\n"
|
||||
"crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E\n"
|
||||
"FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB\n"
|
||||
"/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl\n"
|
||||
"wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM\n"
|
||||
"4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV\n"
|
||||
"2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna\n"
|
||||
"FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ\n"
|
||||
"CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK\n"
|
||||
"boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke\n"
|
||||
"jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL\n"
|
||||
"S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb\n"
|
||||
"QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl\n"
|
||||
"0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB\n"
|
||||
"NVOFBkpdn627G190\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
const char cert[] PROGMEM =
|
||||
{
|
||||
0x30, 0x82, 0x03, 0x4a, 0x30, 0x82, 0x02, 0x32, 0xa0, 0x03, 0x02, 0x01,
|
||||
0x02, 0x02, 0x10, 0x44, 0xaf, 0xb0, 0x80, 0xd6, 0xa3, 0x27, 0xba, 0x89,
|
||||
0x30, 0x39, 0x86, 0x2e, 0xf8, 0x40, 0x6b, 0x30, 0x0d, 0x06, 0x09, 0x2a,
|
||||
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3f,
|
||||
0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1b, 0x44,
|
||||
0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61,
|
||||
0x74, 0x75, 0x72, 0x65, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43,
|
||||
0x6f, 0x2e, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
|
||||
0x0e, 0x44, 0x53, 0x54, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41,
|
||||
0x20, 0x58, 0x33, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x39, 0x33,
|
||||
0x30, 0x32, 0x31, 0x31, 0x32, 0x31, 0x39, 0x5a, 0x17, 0x0d, 0x32, 0x31,
|
||||
0x30, 0x39, 0x33, 0x30, 0x31, 0x34, 0x30, 0x31, 0x31, 0x35, 0x5a, 0x30,
|
||||
0x3f, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1b,
|
||||
0x44, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x53, 0x69, 0x67, 0x6e,
|
||||
0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20,
|
||||
0x43, 0x6f, 0x2e, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03,
|
||||
0x13, 0x0e, 0x44, 0x53, 0x54, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43,
|
||||
0x41, 0x20, 0x58, 0x33, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09,
|
||||
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03,
|
||||
0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01,
|
||||
0x00, 0xdf, 0xaf, 0xe9, 0x97, 0x50, 0x08, 0x83, 0x57, 0xb4, 0xcc, 0x62,
|
||||
0x65, 0xf6, 0x90, 0x82, 0xec, 0xc7, 0xd3, 0x2c, 0x6b, 0x30, 0xca, 0x5b,
|
||||
0xec, 0xd9, 0xc3, 0x7d, 0xc7, 0x40, 0xc1, 0x18, 0x14, 0x8b, 0xe0, 0xe8,
|
||||
0x33, 0x76, 0x49, 0x2a, 0xe3, 0x3f, 0x21, 0x49, 0x93, 0xac, 0x4e, 0x0e,
|
||||
0xaf, 0x3e, 0x48, 0xcb, 0x65, 0xee, 0xfc, 0xd3, 0x21, 0x0f, 0x65, 0xd2,
|
||||
0x2a, 0xd9, 0x32, 0x8f, 0x8c, 0xe5, 0xf7, 0x77, 0xb0, 0x12, 0x7b, 0xb5,
|
||||
0x95, 0xc0, 0x89, 0xa3, 0xa9, 0xba, 0xed, 0x73, 0x2e, 0x7a, 0x0c, 0x06,
|
||||
0x32, 0x83, 0xa2, 0x7e, 0x8a, 0x14, 0x30, 0xcd, 0x11, 0xa0, 0xe1, 0x2a,
|
||||
0x38, 0xb9, 0x79, 0x0a, 0x31, 0xfd, 0x50, 0xbd, 0x80, 0x65, 0xdf, 0xb7,
|
||||
0x51, 0x63, 0x83, 0xc8, 0xe2, 0x88, 0x61, 0xea, 0x4b, 0x61, 0x81, 0xec,
|
||||
0x52, 0x6b, 0xb9, 0xa2, 0xe2, 0x4b, 0x1a, 0x28, 0x9f, 0x48, 0xa3, 0x9e,
|
||||
0x0c, 0xda, 0x09, 0x8e, 0x3e, 0x17, 0x2e, 0x1e, 0xdd, 0x20, 0xdf, 0x5b,
|
||||
0xc6, 0x2a, 0x8a, 0xab, 0x2e, 0xbd, 0x70, 0xad, 0xc5, 0x0b, 0x1a, 0x25,
|
||||
0x90, 0x74, 0x72, 0xc5, 0x7b, 0x6a, 0xab, 0x34, 0xd6, 0x30, 0x89, 0xff,
|
||||
0xe5, 0x68, 0x13, 0x7b, 0x54, 0x0b, 0xc8, 0xd6, 0xae, 0xec, 0x5a, 0x9c,
|
||||
0x92, 0x1e, 0x3d, 0x64, 0xb3, 0x8c, 0xc6, 0xdf, 0xbf, 0xc9, 0x41, 0x70,
|
||||
0xec, 0x16, 0x72, 0xd5, 0x26, 0xec, 0x38, 0x55, 0x39, 0x43, 0xd0, 0xfc,
|
||||
0xfd, 0x18, 0x5c, 0x40, 0xf1, 0x97, 0xeb, 0xd5, 0x9a, 0x9b, 0x8d, 0x1d,
|
||||
0xba, 0xda, 0x25, 0xb9, 0xc6, 0xd8, 0xdf, 0xc1, 0x15, 0x02, 0x3a, 0xab,
|
||||
0xda, 0x6e, 0xf1, 0x3e, 0x2e, 0xf5, 0x5c, 0x08, 0x9c, 0x3c, 0xd6, 0x83,
|
||||
0x69, 0xe4, 0x10, 0x9b, 0x19, 0x2a, 0xb6, 0x29, 0x57, 0xe3, 0xe5, 0x3d,
|
||||
0x9b, 0x9f, 0xf0, 0x02, 0x5d, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42,
|
||||
0x30, 0x40, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
|
||||
0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55,
|
||||
0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30,
|
||||
0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xc4, 0xa7,
|
||||
0xb1, 0xa4, 0x7b, 0x2c, 0x71, 0xfa, 0xdb, 0xe1, 0x4b, 0x90, 0x75, 0xff,
|
||||
0xc4, 0x15, 0x60, 0x85, 0x89, 0x10, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
|
||||
0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01,
|
||||
0x01, 0x00, 0xa3, 0x1a, 0x2c, 0x9b, 0x17, 0x00, 0x5c, 0xa9, 0x1e, 0xee,
|
||||
0x28, 0x66, 0x37, 0x3a, 0xbf, 0x83, 0xc7, 0x3f, 0x4b, 0xc3, 0x09, 0xa0,
|
||||
0x95, 0x20, 0x5d, 0xe3, 0xd9, 0x59, 0x44, 0xd2, 0x3e, 0x0d, 0x3e, 0xbd,
|
||||
0x8a, 0x4b, 0xa0, 0x74, 0x1f, 0xce, 0x10, 0x82, 0x9c, 0x74, 0x1a, 0x1d,
|
||||
0x7e, 0x98, 0x1a, 0xdd, 0xcb, 0x13, 0x4b, 0xb3, 0x20, 0x44, 0xe4, 0x91,
|
||||
0xe9, 0xcc, 0xfc, 0x7d, 0xa5, 0xdb, 0x6a, 0xe5, 0xfe, 0xe6, 0xfd, 0xe0,
|
||||
0x4e, 0xdd, 0xb7, 0x00, 0x3a, 0xb5, 0x70, 0x49, 0xaf, 0xf2, 0xe5, 0xeb,
|
||||
0x02, 0xf1, 0xd1, 0x02, 0x8b, 0x19, 0xcb, 0x94, 0x3a, 0x5e, 0x48, 0xc4,
|
||||
0x18, 0x1e, 0x58, 0x19, 0x5f, 0x1e, 0x02, 0x5a, 0xf0, 0x0c, 0xf1, 0xb1,
|
||||
0xad, 0xa9, 0xdc, 0x59, 0x86, 0x8b, 0x6e, 0xe9, 0x91, 0xf5, 0x86, 0xca,
|
||||
0xfa, 0xb9, 0x66, 0x33, 0xaa, 0x59, 0x5b, 0xce, 0xe2, 0xa7, 0x16, 0x73,
|
||||
0x47, 0xcb, 0x2b, 0xcc, 0x99, 0xb0, 0x37, 0x48, 0xcf, 0xe3, 0x56, 0x4b,
|
||||
0xf5, 0xcf, 0x0f, 0x0c, 0x72, 0x32, 0x87, 0xc6, 0xf0, 0x44, 0xbb, 0x53,
|
||||
0x72, 0x6d, 0x43, 0xf5, 0x26, 0x48, 0x9a, 0x52, 0x67, 0xb7, 0x58, 0xab,
|
||||
0xfe, 0x67, 0x76, 0x71, 0x78, 0xdb, 0x0d, 0xa2, 0x56, 0x14, 0x13, 0x39,
|
||||
0x24, 0x31, 0x85, 0xa2, 0xa8, 0x02, 0x5a, 0x30, 0x47, 0xe1, 0xdd, 0x50,
|
||||
0x07, 0xbc, 0x02, 0x09, 0x90, 0x00, 0xeb, 0x64, 0x63, 0x60, 0x9b, 0x16,
|
||||
0xbc, 0x88, 0xc9, 0x12, 0xe6, 0xd2, 0x7d, 0x91, 0x8b, 0xf9, 0x3d, 0x32,
|
||||
0x8d, 0x65, 0xb4, 0xe9, 0x7c, 0xb1, 0x57, 0x76, 0xea, 0xc5, 0xb6, 0x28,
|
||||
0x39, 0xbf, 0x15, 0x65, 0x1c, 0xc8, 0xf6, 0x77, 0x96, 0x6a, 0x0a, 0x8d,
|
||||
0x77, 0x0b, 0xd8, 0x91, 0x0b, 0x04, 0x8e, 0x07, 0xdb, 0x29, 0xb6, 0x0a,
|
||||
0xee, 0x9d, 0x82, 0x35, 0x35, 0x10
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
const char cert[] PROGMEM =
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
"MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/\n"
|
||||
"MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n"
|
||||
"DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow\n"
|
||||
"PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD\n"
|
||||
"Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n"
|
||||
"AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O\n"
|
||||
"rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq\n"
|
||||
"OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b\n"
|
||||
"xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw\n"
|
||||
"7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD\n"
|
||||
"aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV\n"
|
||||
"HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG\n"
|
||||
"SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69\n"
|
||||
"ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr\n"
|
||||
"AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz\n"
|
||||
"R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5\n"
|
||||
"JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo\n"
|
||||
"Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/**************************************************************
|
||||
*
|
||||
* This sketch uploads SSL certificates to the SIM8xx
|
||||
*
|
||||
* TinyGSM Getting Started guide:
|
||||
* https://tiny.cc/tinygsm-readme
|
||||
*
|
||||
**************************************************************/
|
||||
|
||||
// This example is specific to SIM8xx
|
||||
#define TINY_GSM_MODEM_SIM800
|
||||
|
||||
// Select your certificate:
|
||||
#include "DSTRootCAX3.h"
|
||||
//#include "DSTRootCAX3.der.h"
|
||||
//#include "COMODORSACertificationAuthority.h"
|
||||
|
||||
// Select the file you want to write into
|
||||
// (the file is stored on the modem)
|
||||
#define CERT_FILE "C:\\USER\\CERT.CRT"
|
||||
|
||||
#include <TinyGsmClient.h>
|
||||
|
||||
// Set serial for debug console (to the Serial Monitor, speed 115200)
|
||||
#define SerialMon Serial
|
||||
|
||||
// Use Hardware Serial for AT commands
|
||||
#define SerialAT Serial1
|
||||
|
||||
// Uncomment this if you want to see all AT commands
|
||||
//#define DUMP_AT_COMMANDS
|
||||
|
||||
|
||||
#ifdef DUMP_AT_COMMANDS
|
||||
#include <StreamDebugger.h>
|
||||
StreamDebugger debugger(SerialAT, SerialMon);
|
||||
TinyGsm modem(debugger);
|
||||
#else
|
||||
TinyGsm modem(SerialAT);
|
||||
#endif
|
||||
|
||||
void setup() {
|
||||
// Set console baud rate
|
||||
SerialMon.begin(115200);
|
||||
delay(10);
|
||||
|
||||
// Set GSM module baud rate
|
||||
SerialAT.begin(115200);
|
||||
delay(3000);
|
||||
|
||||
SerialMon.println(F("Initializing modem..."));
|
||||
modem.init();
|
||||
|
||||
modem.sendAT(GF("+FSCREATE=" CERT_FILE));
|
||||
if (modem.waitResponse() != 1) return;
|
||||
|
||||
const int cert_size = sizeof(cert);
|
||||
|
||||
modem.sendAT(GF("+FSWRITE=" CERT_FILE ",0,"), cert_size, GF(",10"));
|
||||
if (modem.waitResponse(GF(">")) != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < cert_size; i++) {
|
||||
char c = pgm_read_byte(&cert[i]);
|
||||
modem.stream.write(c);
|
||||
}
|
||||
|
||||
modem.stream.write(GSM_NL);
|
||||
modem.stream.flush();
|
||||
|
||||
if (modem.waitResponse(2000) != 1) return;
|
||||
|
||||
modem.sendAT(GF("+SSLSETCERT=\"" CERT_FILE "\""));
|
||||
if (modem.waitResponse() != 1) return;
|
||||
if (modem.waitResponse(5000L, GF(GSM_NL "+SSLSETCERT:")) != 1) return;
|
||||
const int retCode = modem.stream.readStringUntil('\n').toInt();
|
||||
|
||||
|
||||
SerialMon.println();
|
||||
SerialMon.println();
|
||||
SerialMon.println(F("****************************"));
|
||||
SerialMon.print(F("Setting Certificate: "));
|
||||
SerialMon.println((0 == retCode) ? "OK" : "FAILED");
|
||||
SerialMon.println(F("****************************"));
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (SerialAT.available()) {
|
||||
SerialMon.write(SerialAT.read());
|
||||
}
|
||||
if (SerialMon.available()) {
|
||||
SerialAT.write(SerialMon.read());
|
||||
}
|
||||
delay(0);
|
||||
}
|
||||
|
||||
29
arduino-cli/libraries/TinyGSM/keywords.txt
Normal file
29
arduino-cli/libraries/TinyGSM/keywords.txt
Normal file
@@ -0,0 +1,29 @@
|
||||
#######################################
|
||||
# Data types (KEYWORD1)
|
||||
#######################################
|
||||
TinyGsm KEYWORD1
|
||||
TinyGsmClient KEYWORD1
|
||||
TinyGsmClientSecure KEYWORD1
|
||||
|
||||
SerialAT KEYWORD1
|
||||
SerialMon KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
begin KEYWORD2
|
||||
restart KEYWORD2
|
||||
waitForNetwork KEYWORD2
|
||||
getSimStatus KEYWORD2
|
||||
gprsConnect KEYWORD2
|
||||
gprsDisconnect KEYWORD2
|
||||
isGprsConnected KEYWORD2
|
||||
isNetworkConnected KEYWORD2
|
||||
factoryReset KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Literals (LITERAL1)
|
||||
#######################################
|
||||
DATE_FULL LITERAL1
|
||||
DATE_TIME LITERAL1
|
||||
DATE_DATE LITERAL1
|
||||
24
arduino-cli/libraries/TinyGSM/library.json
Normal file
24
arduino-cli/libraries/TinyGSM/library.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "TinyGSM",
|
||||
"version": "0.3.6",
|
||||
"description": "A small Arduino library for GPRS modules, that just works. Includes examples for Blynk, MQTT, File Download, and Web Client. Supports GSM modules with AT command interface: SIM800, SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868, SIM900, SIM900A, SIM900D, SIM908, SIM968",
|
||||
"keywords": "GSM, AT commands, AT, SIM800, SIM900, A6, A7, M590, ESP8266, SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868, SIM900A, SIM900D, SIM908, SIM968",
|
||||
"authors":
|
||||
{
|
||||
"name": "Volodymyr Shymanskyy",
|
||||
"url": "https://github.com/vshymanskyy",
|
||||
"maintainer": true
|
||||
},
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/vshymanskyy/TinyGSM.git"
|
||||
},
|
||||
"homepage": "https://github.com/vshymanskyy/TinyGSM",
|
||||
"export": {
|
||||
"exclude": [ "extras/*", "tools/*" ]
|
||||
},
|
||||
"frameworks": [ "arduino", "energia", "wiringpi" ],
|
||||
"platforms": "*",
|
||||
"examples": "examples/*/*.ino"
|
||||
}
|
||||
9
arduino-cli/libraries/TinyGSM/library.properties
Normal file
9
arduino-cli/libraries/TinyGSM/library.properties
Normal file
@@ -0,0 +1,9 @@
|
||||
name=TinyGSM
|
||||
version=0.3.6
|
||||
author=Volodymyr Shymanskyy
|
||||
maintainer=Volodymyr Shymanskyy
|
||||
sentence=A small Arduino library for GPRS modules, that just works.
|
||||
paragraph=Includes examples for Blynk, MQTT, File Download, and Web Client. Supports GSM modules with AT command interface: SIM800, SIM900, A6, A7, M590, ESP8266, SIM800A, SIM800C, SIM800L, SIM800H, SIM808, SIM868, SIM900A, SIM900D, SIM908, SIM968
|
||||
category=Communication
|
||||
url=https://github.com/vshymanskyy/TinyGSM
|
||||
architectures=*
|
||||
45
arduino-cli/libraries/TinyGSM/src/ArduinoCompat/Client.h
Normal file
45
arduino-cli/libraries/TinyGSM/src/ArduinoCompat/Client.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Client.h - Base class that provides Client
|
||||
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef client_h
|
||||
#define client_h
|
||||
#include "Print.h"
|
||||
#include "Stream.h"
|
||||
#include "ArduinoCompat/IPAddress.h"
|
||||
|
||||
class Client : public Stream {
|
||||
|
||||
public:
|
||||
virtual int connect(IPAddress ip, uint16_t port) =0;
|
||||
virtual int connect(const char *host, uint16_t port) =0;
|
||||
virtual size_t write(uint8_t) =0;
|
||||
virtual size_t write(const uint8_t *buf, size_t size) =0;
|
||||
virtual int available() = 0;
|
||||
virtual int read() = 0;
|
||||
virtual int read(uint8_t *buf, size_t size) = 0;
|
||||
virtual int peek() = 0;
|
||||
virtual void flush() = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual uint8_t connected() = 0;
|
||||
virtual operator bool() = 0;
|
||||
protected:
|
||||
uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); };
|
||||
};
|
||||
|
||||
#endif
|
||||
146
arduino-cli/libraries/TinyGSM/src/ArduinoCompat/IPAddress.h
Normal file
146
arduino-cli/libraries/TinyGSM/src/ArduinoCompat/IPAddress.h
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
IPAddress.h - Base class that provides IPAddress
|
||||
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef IPAddress_h
|
||||
#define IPAddress_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include "Printable.h"
|
||||
#include "WString.h"
|
||||
|
||||
// A class to make it easier to handle and pass around IP addresses
|
||||
|
||||
class IPAddress : public Printable {
|
||||
private:
|
||||
union {
|
||||
uint8_t bytes[4]; // IPv4 address
|
||||
uint32_t dword;
|
||||
} _address;
|
||||
|
||||
// Access the raw byte array containing the address. Because this returns a pointer
|
||||
// to the internal structure rather than a copy of the address this function should only
|
||||
// be used when you know that the usage of the returned uint8_t* will be transient and not
|
||||
// stored.
|
||||
uint8_t* raw_address() { return _address.bytes; };
|
||||
|
||||
public:
|
||||
// Constructors
|
||||
IPAddress() {
|
||||
_address.dword = 0;
|
||||
}
|
||||
IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) {
|
||||
_address.bytes[0] = first_octet;
|
||||
_address.bytes[1] = second_octet;
|
||||
_address.bytes[2] = third_octet;
|
||||
_address.bytes[3] = fourth_octet;
|
||||
}
|
||||
|
||||
IPAddress(uint32_t address) {
|
||||
_address.dword = address;
|
||||
}
|
||||
IPAddress(const uint8_t *address) {
|
||||
memcpy(_address.bytes, address, sizeof(_address.bytes));
|
||||
}
|
||||
|
||||
bool fromString(const char *address) {
|
||||
uint16_t acc = 0; // Accumulator
|
||||
uint8_t dots = 0;
|
||||
|
||||
while (*address)
|
||||
{
|
||||
char c = *address++;
|
||||
if (c >= '0' && c <= '9')
|
||||
{
|
||||
acc = acc * 10 + (c - '0');
|
||||
if (acc > 255) {
|
||||
// Value out of [0..255] range
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (c == '.')
|
||||
{
|
||||
if (dots == 3) {
|
||||
// Too much dots (there must be 3 dots)
|
||||
return false;
|
||||
}
|
||||
_address.bytes[dots++] = acc;
|
||||
acc = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid char
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (dots != 3) {
|
||||
// Too few dots (there must be 3 dots)
|
||||
return false;
|
||||
}
|
||||
_address.bytes[3] = acc;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool fromString(const String &address) { return fromString(address.c_str()); }
|
||||
|
||||
// Overloaded cast operator to allow IPAddress objects to be used where a pointer
|
||||
// to a four-byte uint8_t array is expected
|
||||
operator uint32_t() const { return _address.dword; };
|
||||
bool operator==(const IPAddress& addr) const { return _address.dword == addr._address.dword; };
|
||||
bool operator==(const uint8_t* addr) const {
|
||||
return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0;
|
||||
}
|
||||
|
||||
// Overloaded index operator to allow getting and setting individual octets of the address
|
||||
uint8_t operator[](int index) const { return _address.bytes[index]; };
|
||||
uint8_t& operator[](int index) { return _address.bytes[index]; };
|
||||
|
||||
// Overloaded copy operators to allow initialisation of IPAddress objects from other types
|
||||
IPAddress& operator=(const uint8_t *address) {
|
||||
memcpy(_address.bytes, address, sizeof(_address.bytes));
|
||||
return *this;
|
||||
}
|
||||
IPAddress& operator=(uint32_t address) {
|
||||
_address.dword = address;
|
||||
return *this;
|
||||
}
|
||||
|
||||
virtual size_t printTo(Print& p) const {
|
||||
size_t n = 0;
|
||||
for (int i =0; i < 3; i++)
|
||||
{
|
||||
n += p.print(_address.bytes[i], DEC);
|
||||
n += p.print('.');
|
||||
}
|
||||
n += p.print(_address.bytes[3], DEC);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
friend class EthernetClass;
|
||||
friend class UDP;
|
||||
friend class Client;
|
||||
friend class Server;
|
||||
friend class DhcpClass;
|
||||
friend class DNSClient;
|
||||
};
|
||||
|
||||
const IPAddress INADDR_NONE(0,0,0,0);
|
||||
|
||||
#endif
|
||||
78
arduino-cli/libraries/TinyGSM/src/TinyGsmClient.h
Normal file
78
arduino-cli/libraries/TinyGSM/src/TinyGsmClient.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* @file TinyGsmClient.h
|
||||
* @author Volodymyr Shymanskyy
|
||||
* @license LGPL-3.0
|
||||
* @copyright Copyright (c) 2016 Volodymyr Shymanskyy
|
||||
* @date Nov 2016
|
||||
*/
|
||||
|
||||
#ifndef TinyGsmClient_h
|
||||
#define TinyGsmClient_h
|
||||
|
||||
#if defined(TINY_GSM_MODEM_SIM800) || defined(TINY_GSM_MODEM_SIM868) || defined(TINY_GSM_MODEM_UBLOX) || defined(TINY_GSM_MODEM_ESP8266)
|
||||
#define TINY_GSM_MODEM_HAS_SSL
|
||||
#endif
|
||||
|
||||
#if defined(TINY_GSM_MODEM_SIM808) || defined(TINY_GSM_MODEM_SIM868) || defined(TINY_GSM_MODEM_A7)
|
||||
#define TINY_GSM_MODEM_HAS_GPS
|
||||
#endif
|
||||
|
||||
#if defined(TINY_GSM_MODEM_SIM800) || defined(TINY_GSM_MODEM_SIM900)
|
||||
#define TINY_GSM_MODEM_HAS_GPRS
|
||||
#include <TinyGsmClientSIM800.h>
|
||||
typedef TinyGsmSim800 TinyGsm;
|
||||
typedef TinyGsmSim800::GsmClient TinyGsmClient;
|
||||
typedef TinyGsmSim800::GsmClientSecure TinyGsmClientSecure;
|
||||
|
||||
#elif defined(TINY_GSM_MODEM_SIM808) || defined(TINY_GSM_MODEM_SIM868)
|
||||
#define TINY_GSM_MODEM_HAS_GPRS
|
||||
#include <TinyGsmClientSIM808.h>
|
||||
typedef TinyGsmSim808 TinyGsm;
|
||||
typedef TinyGsmSim808::GsmClient TinyGsmClient;
|
||||
typedef TinyGsmSim808::GsmClientSecure TinyGsmClientSecure;
|
||||
|
||||
#elif defined(TINY_GSM_MODEM_UBLOX)
|
||||
#define TINY_GSM_MODEM_HAS_GPRS
|
||||
#include <TinyGsmClientUBLOX.h>
|
||||
typedef TinyGsmUBLOX TinyGsm;
|
||||
typedef TinyGsmUBLOX::GsmClient TinyGsmClient;
|
||||
typedef TinyGsmUBLOX::GsmClientSecure TinyGsmClientSecure;
|
||||
|
||||
#elif defined(TINY_GSM_MODEM_BG96)
|
||||
#define TINY_GSM_MODEM_HAS_GPRS
|
||||
#include <TinyGsmClientBG96.h>
|
||||
typedef TinyGsmBG96 TinyGsm;
|
||||
typedef TinyGsmBG96::GsmClient TinyGsmClient;
|
||||
|
||||
#elif defined(TINY_GSM_MODEM_A6) || defined(TINY_GSM_MODEM_A7)
|
||||
#define TINY_GSM_MODEM_HAS_GPRS
|
||||
#include <TinyGsmClientA6.h>
|
||||
typedef TinyGsmA6 TinyGsm;
|
||||
typedef TinyGsmA6::GsmClient TinyGsmClient;
|
||||
|
||||
#elif defined(TINY_GSM_MODEM_M590)
|
||||
#define TINY_GSM_MODEM_HAS_GPRS
|
||||
#include <TinyGsmClientM590.h>
|
||||
typedef TinyGsmM590 TinyGsm;
|
||||
typedef TinyGsmM590::GsmClient TinyGsmClient;
|
||||
|
||||
#elif defined(TINY_GSM_MODEM_ESP8266)
|
||||
#define TINY_GSM_MODEM_HAS_WIFI
|
||||
#include <TinyGsmClientESP8266.h>
|
||||
typedef TinyGsmESP8266 TinyGsm;
|
||||
typedef TinyGsmESP8266::GsmClient TinyGsmClient;
|
||||
typedef TinyGsmESP8266::GsmClientSecure TinyGsmClientSecure;
|
||||
|
||||
#elif defined(TINY_GSM_MODEM_XBEE)
|
||||
#define TINY_GSM_MODEM_HAS_GPRS
|
||||
#define TINY_GSM_MODEM_HAS_WIFI
|
||||
#include <TinyGsmClientXBee.h>
|
||||
typedef TinyGsmXBee TinyGsm;
|
||||
typedef TinyGsmXBee::GsmClient TinyGsmClient;
|
||||
typedef TinyGsmXBee::GsmClientSecure TinyGsmClientSecure;
|
||||
|
||||
#else
|
||||
#error "Please define GSM modem model"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
808
arduino-cli/libraries/TinyGSM/src/TinyGsmClientA6.h
Normal file
808
arduino-cli/libraries/TinyGSM/src/TinyGsmClientA6.h
Normal file
@@ -0,0 +1,808 @@
|
||||
/**
|
||||
* @file TinyGsmClientA6.h
|
||||
* @author Volodymyr Shymanskyy
|
||||
* @license LGPL-3.0
|
||||
* @copyright Copyright (c) 2016 Volodymyr Shymanskyy
|
||||
* @date Nov 2016
|
||||
*/
|
||||
|
||||
#ifndef TinyGsmClientA6_h
|
||||
#define TinyGsmClientA6_h
|
||||
|
||||
//#define TINY_GSM_DEBUG Serial
|
||||
|
||||
#if !defined(TINY_GSM_RX_BUFFER)
|
||||
#define TINY_GSM_RX_BUFFER 256
|
||||
#endif
|
||||
|
||||
#define TINY_GSM_MUX_COUNT 8
|
||||
|
||||
#include <TinyGsmCommon.h>
|
||||
|
||||
#define GSM_NL "\r\n"
|
||||
static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL;
|
||||
static const char GSM_ERROR[] TINY_GSM_PROGMEM = "ERROR" GSM_NL;
|
||||
|
||||
enum SimStatus {
|
||||
SIM_ERROR = 0,
|
||||
SIM_READY = 1,
|
||||
SIM_LOCKED = 2,
|
||||
};
|
||||
|
||||
enum RegStatus {
|
||||
REG_UNREGISTERED = 0,
|
||||
REG_SEARCHING = 2,
|
||||
REG_DENIED = 3,
|
||||
REG_OK_HOME = 1,
|
||||
REG_OK_ROAMING = 5,
|
||||
REG_UNKNOWN = 4,
|
||||
};
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// Declaration of the TinyGsmA6 Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
class TinyGsmA6
|
||||
{
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The Internal A6 Client Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
|
||||
public:
|
||||
|
||||
class GsmClient : public Client
|
||||
{
|
||||
friend class TinyGsmA6;
|
||||
typedef TinyGsmFifo<uint8_t, TINY_GSM_RX_BUFFER> RxFifo;
|
||||
|
||||
public:
|
||||
GsmClient() {}
|
||||
|
||||
GsmClient(TinyGsmA6& modem) {
|
||||
init(&modem);
|
||||
}
|
||||
|
||||
bool init(TinyGsmA6* modem) {
|
||||
this->at = modem;
|
||||
this->mux = -1;
|
||||
sock_connected = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
virtual int connect(const char *host, uint16_t port) {
|
||||
stop();
|
||||
TINY_GSM_YIELD();
|
||||
rx.clear();
|
||||
uint8_t newMux = -1;
|
||||
sock_connected = at->modemConnect(host, port, &newMux);
|
||||
if (sock_connected) {
|
||||
mux = newMux;
|
||||
at->sockets[mux] = this;
|
||||
}
|
||||
return sock_connected;
|
||||
}
|
||||
|
||||
virtual int connect(IPAddress ip, uint16_t port) {
|
||||
String host; host.reserve(16);
|
||||
host += ip[0];
|
||||
host += ".";
|
||||
host += ip[1];
|
||||
host += ".";
|
||||
host += ip[2];
|
||||
host += ".";
|
||||
host += ip[3];
|
||||
return connect(host.c_str(), port);
|
||||
}
|
||||
|
||||
virtual void stop() {
|
||||
TINY_GSM_YIELD();
|
||||
at->sendAT(GF("+CIPCLOSE="), mux);
|
||||
sock_connected = false;
|
||||
at->waitResponse();
|
||||
rx.clear();
|
||||
}
|
||||
|
||||
virtual size_t write(const uint8_t *buf, size_t size) {
|
||||
TINY_GSM_YIELD();
|
||||
//at->maintain();
|
||||
return at->modemSend(buf, size, mux);
|
||||
}
|
||||
|
||||
virtual size_t write(uint8_t c) {
|
||||
return write(&c, 1);
|
||||
}
|
||||
|
||||
virtual size_t write(const char *str) {
|
||||
if (str == NULL) return 0;
|
||||
return write((const uint8_t *)str, strlen(str));
|
||||
}
|
||||
|
||||
virtual int available() {
|
||||
TINY_GSM_YIELD();
|
||||
if (!rx.size() && sock_connected) {
|
||||
at->maintain();
|
||||
}
|
||||
return rx.size();
|
||||
}
|
||||
|
||||
virtual int read(uint8_t *buf, size_t size) {
|
||||
TINY_GSM_YIELD();
|
||||
size_t cnt = 0;
|
||||
while (cnt < size) {
|
||||
size_t chunk = TinyGsmMin(size-cnt, rx.size());
|
||||
if (chunk > 0) {
|
||||
rx.get(buf, chunk);
|
||||
buf += chunk;
|
||||
cnt += chunk;
|
||||
continue;
|
||||
}
|
||||
// TODO: Read directly into user buffer?
|
||||
if (!rx.size() && sock_connected) {
|
||||
at->maintain();
|
||||
//break;
|
||||
}
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
virtual int read() {
|
||||
uint8_t c;
|
||||
if (read(&c, 1) == 1) {
|
||||
return c;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
virtual int peek() { return -1; } //TODO
|
||||
virtual void flush() { at->stream.flush(); }
|
||||
|
||||
virtual uint8_t connected() {
|
||||
if (available()) {
|
||||
return true;
|
||||
}
|
||||
return sock_connected;
|
||||
}
|
||||
virtual operator bool() { return connected(); }
|
||||
|
||||
/*
|
||||
* Extended API
|
||||
*/
|
||||
|
||||
String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
private:
|
||||
TinyGsmA6* at;
|
||||
uint8_t mux;
|
||||
bool sock_connected;
|
||||
RxFifo rx;
|
||||
};
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The A6 does not have a secure client!
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The A6 Modem Functions
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
public:
|
||||
|
||||
#ifdef GSM_DEFAULT_STREAM
|
||||
TinyGsmA6(Stream& stream = GSM_DEFAULT_STREAM)
|
||||
#else
|
||||
TinyGsmA6(Stream& stream)
|
||||
#endif
|
||||
: stream(stream)
|
||||
{
|
||||
memset(sockets, 0, sizeof(sockets));
|
||||
}
|
||||
|
||||
/*
|
||||
* Basic functions
|
||||
*/
|
||||
bool begin() {
|
||||
return init();
|
||||
}
|
||||
|
||||
bool init() {
|
||||
if (!testAT()) {
|
||||
return false;
|
||||
}
|
||||
sendAT(GF("&FZE0")); // Factory + Reset + Echo Off
|
||||
if (waitResponse() != 1) {
|
||||
return false;
|
||||
}
|
||||
sendAT(GF("+CMEE=0"));
|
||||
waitResponse();
|
||||
|
||||
sendAT(GF("+CMER=3,0,0,2"));
|
||||
waitResponse();
|
||||
|
||||
getSimStatus();
|
||||
return true;
|
||||
}
|
||||
|
||||
void setBaud(unsigned long baud) {
|
||||
sendAT(GF("+IPR="), baud);
|
||||
}
|
||||
|
||||
bool testAT(unsigned long timeout = 10000L) {
|
||||
for (unsigned long start = millis(); millis() - start < timeout; ) {
|
||||
sendAT(GF(""));
|
||||
if (waitResponse(200) == 1) {
|
||||
delay(100);
|
||||
return true;
|
||||
}
|
||||
delay(100);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void maintain() {
|
||||
waitResponse(10, NULL, NULL);
|
||||
}
|
||||
|
||||
bool factoryDefault() {
|
||||
sendAT(GF("&FZE0&W")); // Factory + Reset + Echo Off + Write
|
||||
waitResponse();
|
||||
sendAT(GF("&W")); // Write configuration
|
||||
return waitResponse() == 1;
|
||||
}
|
||||
|
||||
String getModemInfo() {
|
||||
sendAT(GF("I"));
|
||||
String res;
|
||||
if (waitResponse(1000L, res) != 1) {
|
||||
return "";
|
||||
}
|
||||
res.replace(GSM_NL "OK" GSM_NL, "");
|
||||
res.replace(GSM_NL, " ");
|
||||
res.trim();
|
||||
return res;
|
||||
}
|
||||
|
||||
bool hasSSL() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Power functions
|
||||
*/
|
||||
|
||||
bool restart() {
|
||||
if (!testAT()) {
|
||||
return false;
|
||||
}
|
||||
sendAT(GF("+RST=1"));
|
||||
delay(3000);
|
||||
return init();
|
||||
}
|
||||
|
||||
bool poweroff() {
|
||||
sendAT(GF("+CPOF"));
|
||||
return waitResponse() == 1;
|
||||
}
|
||||
|
||||
bool radioOff() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
bool sleepEnable(bool enable = true) TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
/*
|
||||
* SIM card functions
|
||||
*/
|
||||
|
||||
bool simUnlock(const char *pin) {
|
||||
sendAT(GF("+CPIN=\""), pin, GF("\""));
|
||||
return waitResponse() == 1;
|
||||
}
|
||||
|
||||
String getSimCCID() {
|
||||
sendAT(GF("+CCID"));
|
||||
if (waitResponse(GF(GSM_NL "+SCID: SIM Card ID:")) != 1) {
|
||||
return "";
|
||||
}
|
||||
String res = stream.readStringUntil('\n');
|
||||
waitResponse();
|
||||
res.trim();
|
||||
return res;
|
||||
}
|
||||
|
||||
String getIMEI() {
|
||||
sendAT(GF("+GSN"));
|
||||
if (waitResponse(GF(GSM_NL)) != 1) {
|
||||
return "";
|
||||
}
|
||||
String res = stream.readStringUntil('\n');
|
||||
waitResponse();
|
||||
res.trim();
|
||||
return res;
|
||||
}
|
||||
|
||||
SimStatus getSimStatus(unsigned long timeout = 10000L) {
|
||||
for (unsigned long start = millis(); millis() - start < timeout; ) {
|
||||
sendAT(GF("+CPIN?"));
|
||||
if (waitResponse(GF(GSM_NL "+CPIN:")) != 1) {
|
||||
delay(1000);
|
||||
continue;
|
||||
}
|
||||
int status = waitResponse(GF("READY"), GF("SIM PIN"), GF("SIM PUK"));
|
||||
waitResponse();
|
||||
switch (status) {
|
||||
case 2:
|
||||
case 3: return SIM_LOCKED;
|
||||
case 1: return SIM_READY;
|
||||
default: return SIM_ERROR;
|
||||
}
|
||||
}
|
||||
return SIM_ERROR;
|
||||
}
|
||||
|
||||
RegStatus getRegistrationStatus() {
|
||||
sendAT(GF("+CREG?"));
|
||||
if (waitResponse(GF(GSM_NL "+CREG:")) != 1) {
|
||||
return REG_UNKNOWN;
|
||||
}
|
||||
streamSkipUntil(','); // Skip format (0)
|
||||
int status = stream.readStringUntil('\n').toInt();
|
||||
waitResponse();
|
||||
return (RegStatus)status;
|
||||
}
|
||||
|
||||
String getOperator() {
|
||||
sendAT(GF("+COPS=3,0")); // Set format
|
||||
waitResponse();
|
||||
|
||||
sendAT(GF("+COPS?"));
|
||||
if (waitResponse(GF(GSM_NL "+COPS:")) != 1) {
|
||||
return "";
|
||||
}
|
||||
streamSkipUntil('"'); // Skip mode and format
|
||||
String res = stream.readStringUntil('"');
|
||||
waitResponse();
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic network functions
|
||||
*/
|
||||
|
||||
int getSignalQuality() {
|
||||
sendAT(GF("+CSQ"));
|
||||
if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) {
|
||||
return 99;
|
||||
}
|
||||
int res = stream.readStringUntil(',').toInt();
|
||||
waitResponse();
|
||||
return res;
|
||||
}
|
||||
|
||||
bool isNetworkConnected() {
|
||||
RegStatus s = getRegistrationStatus();
|
||||
return (s == REG_OK_HOME || s == REG_OK_ROAMING);
|
||||
}
|
||||
|
||||
bool waitForNetwork(unsigned long timeout = 60000L) {
|
||||
for (unsigned long start = millis(); millis() - start < timeout; ) {
|
||||
if (isNetworkConnected()) {
|
||||
return true;
|
||||
}
|
||||
delay(250);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* WiFi functions
|
||||
*/
|
||||
|
||||
/*
|
||||
* GPRS functions
|
||||
*/
|
||||
bool gprsConnect(const char* apn, const char* user = NULL, const char* pwd = NULL) {
|
||||
gprsDisconnect();
|
||||
|
||||
sendAT(GF("+CGATT=1"));
|
||||
if (waitResponse(60000L) != 1)
|
||||
return false;
|
||||
|
||||
// TODO: wait AT+CGATT?
|
||||
|
||||
sendAT(GF("+CGDCONT=1,\"IP\",\""), apn, '"');
|
||||
waitResponse();
|
||||
|
||||
if (!user) user = "";
|
||||
if (!pwd) pwd = "";
|
||||
sendAT(GF("+CSTT=\""), apn, GF("\",\""), user, GF("\",\""), pwd, GF("\""));
|
||||
if (waitResponse(60000L) != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sendAT(GF("+CGACT=1,1"));
|
||||
waitResponse(60000L);
|
||||
|
||||
sendAT(GF("+CIPMUX=1"));
|
||||
if (waitResponse() != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool gprsDisconnect() {
|
||||
// Shut the TCP/IP connection
|
||||
sendAT(GF("+CIPSHUT"));
|
||||
if (waitResponse(60000L) != 1)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i<3; i++) {
|
||||
sendAT(GF("+CGATT=0"));
|
||||
if (waitResponse(5000L) == 1)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isGprsConnected() {
|
||||
sendAT(GF("+CGATT?"));
|
||||
if (waitResponse(GF(GSM_NL "+CGATT:")) != 1) {
|
||||
return false;
|
||||
}
|
||||
int res = stream.readStringUntil('\n').toInt();
|
||||
waitResponse();
|
||||
return (res == 1);
|
||||
}
|
||||
|
||||
String getLocalIP() {
|
||||
sendAT(GF("+CIFSR"));
|
||||
String res;
|
||||
if (waitResponse(10000L, res) != 1) {
|
||||
return "";
|
||||
}
|
||||
res.replace(GSM_NL "OK" GSM_NL, "");
|
||||
res.replace(GSM_NL, "");
|
||||
res.trim();
|
||||
return res;
|
||||
}
|
||||
|
||||
IPAddress localIP() {
|
||||
return TinyGsmIpFromString(getLocalIP());
|
||||
}
|
||||
|
||||
/*
|
||||
* Phone Call functions
|
||||
*/
|
||||
|
||||
bool setGsmBusy(bool busy = true) TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||
|
||||
bool callAnswer() {
|
||||
sendAT(GF("A"));
|
||||
return waitResponse() == 1;
|
||||
}
|
||||
|
||||
// Returns true on pick-up, false on error/busy
|
||||
bool callNumber(const String& number) {
|
||||
if (number == GF("last")) {
|
||||
sendAT(GF("DLST"));
|
||||
} else {
|
||||
sendAT(GF("D\""), number, "\";");
|
||||
}
|
||||
|
||||
if (waitResponse(5000L) != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (waitResponse(60000L,
|
||||
GF(GSM_NL "+CIEV: \"CALL\",1"),
|
||||
GF(GSM_NL "+CIEV: \"CALL\",0"),
|
||||
GFP(GSM_ERROR)) != 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int rsp = waitResponse(60000L,
|
||||
GF(GSM_NL "+CIEV: \"SOUNDER\",0"),
|
||||
GF(GSM_NL "+CIEV: \"CALL\",0"));
|
||||
|
||||
int rsp2 = waitResponse(300L, GF(GSM_NL "BUSY" GSM_NL), GF(GSM_NL "NO ANSWER" GSM_NL));
|
||||
|
||||
return rsp == 1 && rsp2 == 0;
|
||||
}
|
||||
|
||||
bool callHangup() {
|
||||
sendAT(GF("H"));
|
||||
return waitResponse() == 1;
|
||||
}
|
||||
|
||||
// 0-9,*,#,A,B,C,D
|
||||
bool dtmfSend(char cmd, unsigned duration_ms = 100) {
|
||||
duration_ms = constrain(duration_ms, 100, 1000);
|
||||
|
||||
// The duration parameter is not working, so we simulate it using delay..
|
||||
// TODO: Maybe there's another way...
|
||||
|
||||
//sendAT(GF("+VTD="), duration_ms / 100);
|
||||
//waitResponse();
|
||||
|
||||
sendAT(GF("+VTS="), cmd);
|
||||
if (waitResponse(10000L) == 1) {
|
||||
delay(duration_ms);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Audio functions
|
||||
*/
|
||||
|
||||
bool audioSetHeadphones() {
|
||||
sendAT(GF("+SNFS=0"));
|
||||
return waitResponse() == 1;
|
||||
}
|
||||
|
||||
bool audioSetSpeaker() {
|
||||
sendAT(GF("+SNFS=1"));
|
||||
return waitResponse() == 1;
|
||||
}
|
||||
|
||||
bool audioMuteMic(bool mute) {
|
||||
sendAT(GF("+CMUT="), mute);
|
||||
return waitResponse() == 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Messaging functions
|
||||
*/
|
||||
|
||||
String sendUSSD(const String& code) {
|
||||
sendAT(GF("+CMGF=1"));
|
||||
waitResponse();
|
||||
sendAT(GF("+CSCS=\"HEX\""));
|
||||
waitResponse();
|
||||
sendAT(GF("+CUSD=1,\""), code, GF("\",15"));
|
||||
if (waitResponse(10000L) != 1) {
|
||||
return "";
|
||||
}
|
||||
if (waitResponse(GF(GSM_NL "+CUSD:")) != 1) {
|
||||
return "";
|
||||
}
|
||||
stream.readStringUntil('"');
|
||||
String hex = stream.readStringUntil('"');
|
||||
stream.readStringUntil(',');
|
||||
int dcs = stream.readStringUntil('\n').toInt();
|
||||
|
||||
if (dcs == 15) {
|
||||
return TinyGsmDecodeHex7bit(hex);
|
||||
} else if (dcs == 72) {
|
||||
return TinyGsmDecodeHex16bit(hex);
|
||||
} else {
|
||||
return hex;
|
||||
}
|
||||
}
|
||||
|
||||
bool sendSMS(const String& number, const String& text) {
|
||||
sendAT(GF("+CMGF=1"));
|
||||
waitResponse();
|
||||
sendAT(GF("+CMGS=\""), number, GF("\""));
|
||||
if (waitResponse(GF(">")) != 1) {
|
||||
return false;
|
||||
}
|
||||
stream.print(text);
|
||||
stream.write((char)0x1A);
|
||||
stream.flush();
|
||||
return waitResponse(60000L) == 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Location functions
|
||||
*/
|
||||
|
||||
String getGsmLocation() TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||
|
||||
/*
|
||||
* Battery functions
|
||||
*/
|
||||
|
||||
uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||
|
||||
int getBattPercent() {
|
||||
sendAT(GF("+CBC?"));
|
||||
if (waitResponse(GF(GSM_NL "+CBC:")) != 1) {
|
||||
return false;
|
||||
}
|
||||
stream.readStringUntil(',');
|
||||
int res = stream.readStringUntil('\n').toInt();
|
||||
waitResponse();
|
||||
return res;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
bool modemConnect(const char* host, uint16_t port, uint8_t* mux) {
|
||||
sendAT(GF("+CIPSTART="), GF("\"TCP"), GF("\",\""), host, GF("\","), port);
|
||||
|
||||
if (waitResponse(75000L, GF(GSM_NL "+CIPNUM:")) != 1) {
|
||||
return false;
|
||||
}
|
||||
int newMux = stream.readStringUntil('\n').toInt();
|
||||
|
||||
int rsp = waitResponse(75000L,
|
||||
GF("CONNECT OK" GSM_NL),
|
||||
GF("CONNECT FAIL" GSM_NL),
|
||||
GF("ALREADY CONNECT" GSM_NL));
|
||||
if (waitResponse() != 1) {
|
||||
return false;
|
||||
}
|
||||
*mux = newMux;
|
||||
|
||||
return (1 == rsp);
|
||||
}
|
||||
|
||||
int modemSend(const void* buff, size_t len, uint8_t mux) {
|
||||
sendAT(GF("+CIPSEND="), mux, ',', len);
|
||||
if (waitResponse(2000L, GF(GSM_NL ">")) != 1) {
|
||||
return 0;
|
||||
}
|
||||
stream.write((uint8_t*)buff, len);
|
||||
stream.flush();
|
||||
if (waitResponse(10000L, GFP(GSM_OK), GF(GSM_NL "FAIL")) != 1) {
|
||||
return 0;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
bool modemGetConnected(uint8_t mux) {
|
||||
sendAT(GF("+CIPSTATUS")); //TODO mux?
|
||||
int res = waitResponse(GF(",\"CONNECTED\""), GF(",\"CLOSED\""), GF(",\"CLOSING\""), GF(",\"INITIAL\""));
|
||||
waitResponse();
|
||||
return 1 == res;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/* Utilities */
|
||||
|
||||
template<typename T>
|
||||
void streamWrite(T last) {
|
||||
stream.print(last);
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
void streamWrite(T head, Args... tail) {
|
||||
stream.print(head);
|
||||
streamWrite(tail...);
|
||||
}
|
||||
|
||||
bool streamSkipUntil(char c) {
|
||||
const unsigned long timeout = 1000L;
|
||||
unsigned long startMillis = millis();
|
||||
while (millis() - startMillis < timeout) {
|
||||
while (millis() - startMillis < timeout && !stream.available()) {
|
||||
TINY_GSM_YIELD();
|
||||
}
|
||||
if (stream.read() == c)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void sendAT(Args... cmd) {
|
||||
streamWrite("AT", cmd..., GSM_NL);
|
||||
stream.flush();
|
||||
TINY_GSM_YIELD();
|
||||
//DBG("### AT:", cmd...);
|
||||
}
|
||||
|
||||
// TODO: Optimize this!
|
||||
uint8_t waitResponse(uint32_t timeout, String& data,
|
||||
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
|
||||
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
|
||||
{
|
||||
/*String r1s(r1); r1s.trim();
|
||||
String r2s(r2); r2s.trim();
|
||||
String r3s(r3); r3s.trim();
|
||||
String r4s(r4); r4s.trim();
|
||||
String r5s(r5); r5s.trim();
|
||||
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
|
||||
data.reserve(64);
|
||||
int index = 0;
|
||||
unsigned long startMillis = millis();
|
||||
do {
|
||||
TINY_GSM_YIELD();
|
||||
while (stream.available() > 0) {
|
||||
int a = stream.read();
|
||||
if (a <= 0) continue; // Skip 0x00 bytes, just in case
|
||||
data += (char)a;
|
||||
if (r1 && data.endsWith(r1)) {
|
||||
index = 1;
|
||||
goto finish;
|
||||
} else if (r2 && data.endsWith(r2)) {
|
||||
index = 2;
|
||||
goto finish;
|
||||
} else if (r3 && data.endsWith(r3)) {
|
||||
index = 3;
|
||||
goto finish;
|
||||
} else if (r4 && data.endsWith(r4)) {
|
||||
index = 4;
|
||||
goto finish;
|
||||
} else if (r5 && data.endsWith(r5)) {
|
||||
index = 5;
|
||||
goto finish;
|
||||
} else if (data.endsWith(GF("+CIPRCV:"))) {
|
||||
int mux = stream.readStringUntil(',').toInt();
|
||||
int len = stream.readStringUntil(',').toInt();
|
||||
int len_orig = len;
|
||||
if (len > sockets[mux]->rx.free()) {
|
||||
DBG("### Buffer overflow: ", len, "->", sockets[mux]->rx.free());
|
||||
} else {
|
||||
DBG("### Got: ", len, "->", sockets[mux]->rx.free());
|
||||
}
|
||||
while (len--) {
|
||||
while (!stream.available()) { TINY_GSM_YIELD(); }
|
||||
sockets[mux]->rx.put(stream.read());
|
||||
}
|
||||
if (len_orig > sockets[mux]->available()) { // TODO
|
||||
DBG("### Fewer characters received than expected: ", sockets[mux]->available(), " vs ", len_orig);
|
||||
}
|
||||
data = "";
|
||||
} else if (data.endsWith(GF("+TCPCLOSED:"))) {
|
||||
int mux = stream.readStringUntil('\n').toInt();
|
||||
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT) {
|
||||
sockets[mux]->sock_connected = false;
|
||||
}
|
||||
data = "";
|
||||
DBG("### Closed: ", mux);
|
||||
}
|
||||
}
|
||||
} while (millis() - startMillis < timeout);
|
||||
finish:
|
||||
if (!index) {
|
||||
data.trim();
|
||||
if (data.length()) {
|
||||
DBG("### Unhandled:", data);
|
||||
}
|
||||
data = "";
|
||||
}
|
||||
//DBG('<', index, '>');
|
||||
return index;
|
||||
}
|
||||
|
||||
uint8_t waitResponse(uint32_t timeout,
|
||||
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
|
||||
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
|
||||
{
|
||||
String data;
|
||||
return waitResponse(timeout, data, r1, r2, r3, r4, r5);
|
||||
}
|
||||
|
||||
uint8_t waitResponse(GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
|
||||
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
|
||||
{
|
||||
return waitResponse(1000, r1, r2, r3, r4, r5);
|
||||
}
|
||||
|
||||
public:
|
||||
Stream& stream;
|
||||
|
||||
protected:
|
||||
GsmClient* sockets[TINY_GSM_MUX_COUNT];
|
||||
};
|
||||
|
||||
#endif
|
||||
813
arduino-cli/libraries/TinyGSM/src/TinyGsmClientBG96.h
Normal file
813
arduino-cli/libraries/TinyGSM/src/TinyGsmClientBG96.h
Normal file
@@ -0,0 +1,813 @@
|
||||
/**
|
||||
* @file TinyGsmClientBG96.h
|
||||
* @author Volodymyr Shymanskyy
|
||||
* @license LGPL-3.0
|
||||
* @copyright Copyright (c) 2016 Volodymyr Shymanskyy
|
||||
* @date Apr 2018
|
||||
*/
|
||||
|
||||
#ifndef TinyGsmClientBG96_h
|
||||
#define TinyGsmClientBG96_h
|
||||
|
||||
//#define TINY_GSM_DEBUG Serial
|
||||
//#define TINY_GSM_USE_HEX
|
||||
|
||||
#if !defined(TINY_GSM_RX_BUFFER)
|
||||
#define TINY_GSM_RX_BUFFER 64
|
||||
#endif
|
||||
|
||||
#define TINY_GSM_MUX_COUNT 12
|
||||
|
||||
#include <TinyGsmCommon.h>
|
||||
|
||||
#define GSM_NL "\r\n"
|
||||
static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL;
|
||||
static const char GSM_ERROR[] TINY_GSM_PROGMEM = "ERROR" GSM_NL;
|
||||
|
||||
enum SimStatus {
|
||||
SIM_ERROR = 0,
|
||||
SIM_READY = 1,
|
||||
SIM_LOCKED = 2,
|
||||
};
|
||||
|
||||
enum RegStatus {
|
||||
REG_UNREGISTERED = 0,
|
||||
REG_SEARCHING = 2,
|
||||
REG_DENIED = 3,
|
||||
REG_OK_HOME = 1,
|
||||
REG_OK_ROAMING = 5,
|
||||
REG_UNKNOWN = 4,
|
||||
};
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// Declaration of the TinyGsmBG96 Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
class TinyGsmBG96
|
||||
{
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The Internal BG96 Client Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
|
||||
public:
|
||||
|
||||
class GsmClient : public Client
|
||||
{
|
||||
friend class TinyGsmBG96;
|
||||
typedef TinyGsmFifo<uint8_t, TINY_GSM_RX_BUFFER> RxFifo;
|
||||
|
||||
public:
|
||||
GsmClient() {}
|
||||
|
||||
GsmClient(TinyGsmBG96& modem, uint8_t mux = 1) {
|
||||
init(&modem, mux);
|
||||
}
|
||||
|
||||
bool init(TinyGsmBG96* modem, uint8_t mux = 1) {
|
||||
this->at = modem;
|
||||
this->mux = mux;
|
||||
sock_available = 0;
|
||||
sock_connected = false;
|
||||
got_data = false;
|
||||
|
||||
at->sockets[mux] = this;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
virtual int connect(const char *host, uint16_t port) {
|
||||
stop();
|
||||
TINY_GSM_YIELD();
|
||||
rx.clear();
|
||||
sock_connected = at->modemConnect(host, port, mux);
|
||||
return sock_connected;
|
||||
}
|
||||
|
||||
virtual int connect(IPAddress ip, uint16_t port) {
|
||||
String host; host.reserve(16);
|
||||
host += ip[0];
|
||||
host += ".";
|
||||
host += ip[1];
|
||||
host += ".";
|
||||
host += ip[2];
|
||||
host += ".";
|
||||
host += ip[3];
|
||||
return connect(host.c_str(), port);
|
||||
}
|
||||
|
||||
virtual void stop() {
|
||||
TINY_GSM_YIELD();
|
||||
at->sendAT(GF("+QICLOSE="), mux);
|
||||
sock_connected = false;
|
||||
at->waitResponse();
|
||||
rx.clear();
|
||||
}
|
||||
|
||||
virtual size_t write(const uint8_t *buf, size_t size) {
|
||||
TINY_GSM_YIELD();
|
||||
at->maintain();
|
||||
return at->modemSend(buf, size, mux);
|
||||
}
|
||||
|
||||
virtual size_t write(uint8_t c) {
|
||||
return write(&c, 1);
|
||||
}
|
||||
|
||||
virtual size_t write(const char *str) {
|
||||
if (str == NULL) return 0;
|
||||
return write((const uint8_t *)str, strlen(str));
|
||||
}
|
||||
|
||||
virtual int available() {
|
||||
TINY_GSM_YIELD();
|
||||
if (!rx.size()) {
|
||||
at->maintain();
|
||||
}
|
||||
return rx.size() + sock_available;
|
||||
}
|
||||
|
||||
virtual int read(uint8_t *buf, size_t size) {
|
||||
TINY_GSM_YIELD();
|
||||
at->maintain();
|
||||
size_t cnt = 0;
|
||||
while (cnt < size) {
|
||||
size_t chunk = TinyGsmMin(size-cnt, rx.size());
|
||||
if (chunk > 0) {
|
||||
rx.get(buf, chunk);
|
||||
buf += chunk;
|
||||
cnt += chunk;
|
||||
continue;
|
||||
}
|
||||
// TODO: Read directly into user buffer?
|
||||
at->maintain();
|
||||
if (sock_available > 0) {
|
||||
sock_available -= at->modemRead(TinyGsmMin((uint16_t)rx.free(), sock_available), mux);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
virtual int read() {
|
||||
uint8_t c;
|
||||
if (read(&c, 1) == 1) {
|
||||
return c;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
virtual int peek() { return -1; } //TODO
|
||||
virtual void flush() { at->stream.flush(); }
|
||||
|
||||
virtual uint8_t connected() {
|
||||
if (available()) {
|
||||
return true;
|
||||
}
|
||||
return sock_connected;
|
||||
}
|
||||
virtual operator bool() { return connected(); }
|
||||
|
||||
/*
|
||||
* Extended API
|
||||
*/
|
||||
|
||||
String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
private:
|
||||
TinyGsmBG96* at;
|
||||
uint8_t mux;
|
||||
uint16_t sock_available;
|
||||
bool sock_connected;
|
||||
bool got_data;
|
||||
RxFifo rx;
|
||||
};
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The BG96 Secure Client
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
|
||||
class GsmClientSecure : public GsmClient
|
||||
{
|
||||
public:
|
||||
GsmClientSecure() {}
|
||||
|
||||
GsmClientSecure(TinyGsmBG96& modem, uint8_t mux = 1)
|
||||
: GsmClient(modem, mux)
|
||||
{}
|
||||
|
||||
public:
|
||||
virtual int connect(const char *host, uint16_t port) {
|
||||
stop();
|
||||
TINY_GSM_YIELD();
|
||||
rx.clear();
|
||||
sock_connected = at->modemConnect(host, port, mux, true);
|
||||
return sock_connected;
|
||||
}
|
||||
};
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The BG96 Modem Functions
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
public:
|
||||
|
||||
#ifdef GSM_DEFAULT_STREAM
|
||||
TinyGsmBG96(Stream& stream = GSM_DEFAULT_STREAM)
|
||||
#else
|
||||
TinyGsmBG96(Stream& stream)
|
||||
#endif
|
||||
: stream(stream)
|
||||
{
|
||||
memset(sockets, 0, sizeof(sockets));
|
||||
}
|
||||
|
||||
/*
|
||||
* Basic functions
|
||||
*/
|
||||
bool begin() {
|
||||
return init();
|
||||
}
|
||||
|
||||
bool init() {
|
||||
if (!testAT()) {
|
||||
return false;
|
||||
}
|
||||
sendAT(GF("&FZE0")); // Factory + Reset + Echo Off
|
||||
if (waitResponse() != 1) {
|
||||
return false;
|
||||
}
|
||||
getSimStatus();
|
||||
return true;
|
||||
}
|
||||
|
||||
void setBaud(unsigned long baud) {
|
||||
sendAT(GF("+IPR="), baud);
|
||||
}
|
||||
|
||||
bool testAT(unsigned long timeout = 10000L) {
|
||||
for (unsigned long start = millis(); millis() - start < timeout; ) {
|
||||
sendAT(GF(""));
|
||||
if (waitResponse(200) == 1) {
|
||||
delay(100);
|
||||
return true;
|
||||
}
|
||||
delay(100);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void maintain() {
|
||||
for (int mux = 0; mux < TINY_GSM_MUX_COUNT; mux++) {
|
||||
GsmClient* sock = sockets[mux];
|
||||
if (sock && sock->got_data) {
|
||||
sock->got_data = false;
|
||||
sock->sock_available = modemGetAvailable(mux);
|
||||
}
|
||||
}
|
||||
while (stream.available()) {
|
||||
waitResponse(10, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
bool factoryDefault() {
|
||||
sendAT(GF("&FZE0&W")); // Factory + Reset + Echo Off + Write
|
||||
waitResponse();
|
||||
sendAT(GF("+IPR=0")); // Auto-baud
|
||||
waitResponse();
|
||||
sendAT(GF("&W")); // Write configuration
|
||||
return waitResponse() == 1;
|
||||
}
|
||||
|
||||
String getModemInfo() {
|
||||
sendAT(GF("I"));
|
||||
String res;
|
||||
if (waitResponse(1000L, res) != 1) {
|
||||
return "";
|
||||
}
|
||||
res.replace(GSM_NL "OK" GSM_NL, "");
|
||||
res.replace(GSM_NL, " ");
|
||||
res.trim();
|
||||
return res;
|
||||
}
|
||||
|
||||
bool hasSSL() {
|
||||
return false; // TODO: For now
|
||||
}
|
||||
|
||||
/*
|
||||
* Power functions
|
||||
*/
|
||||
|
||||
bool restart() {
|
||||
if (!testAT()) {
|
||||
return false;
|
||||
}
|
||||
sendAT(GF("+CFUN=1,1"));
|
||||
if (waitResponse(60000L, GF("POWERED DOWN")) != 1) {
|
||||
return false;
|
||||
}
|
||||
delay(3000);
|
||||
return init();
|
||||
}
|
||||
|
||||
bool poweroff() {
|
||||
sendAT(GF("+QPOWD"));
|
||||
return waitResponse(GF("POWERED DOWN")) == 1; // TODO
|
||||
}
|
||||
|
||||
bool radioOff() {
|
||||
sendAT(GF("+CFUN=0"));
|
||||
if (waitResponse(10000L) != 1) {
|
||||
return false;
|
||||
}
|
||||
delay(3000);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* SIM card functions
|
||||
*/
|
||||
|
||||
bool simUnlock(const char *pin) {
|
||||
sendAT(GF("+CPIN=\""), pin, GF("\""));
|
||||
return waitResponse() == 1;
|
||||
}
|
||||
|
||||
String getSimCCID() {
|
||||
sendAT(GF("+ICCID"));
|
||||
if (waitResponse(GF(GSM_NL "+ICCID:")) != 1) {
|
||||
return "";
|
||||
}
|
||||
String res = stream.readStringUntil('\n');
|
||||
waitResponse();
|
||||
res.trim();
|
||||
return res;
|
||||
}
|
||||
|
||||
String getIMEI() {
|
||||
sendAT(GF("+GSN"));
|
||||
if (waitResponse(GF(GSM_NL)) != 1) {
|
||||
return "";
|
||||
}
|
||||
String res = stream.readStringUntil('\n');
|
||||
waitResponse();
|
||||
res.trim();
|
||||
return res;
|
||||
}
|
||||
|
||||
SimStatus getSimStatus(unsigned long timeout = 10000L) {
|
||||
for (unsigned long start = millis(); millis() - start < timeout; ) {
|
||||
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"));
|
||||
waitResponse();
|
||||
switch (status) {
|
||||
case 2:
|
||||
case 3: return SIM_LOCKED;
|
||||
case 1: return SIM_READY;
|
||||
default: return SIM_ERROR;
|
||||
}
|
||||
}
|
||||
return SIM_ERROR;
|
||||
}
|
||||
|
||||
RegStatus getRegistrationStatus() {
|
||||
sendAT(GF("+CREG?"));
|
||||
if (waitResponse(GF(GSM_NL "+CREG:")) != 1) {
|
||||
return REG_UNKNOWN;
|
||||
}
|
||||
streamSkipUntil(','); // Skip format (0)
|
||||
int status = stream.readStringUntil('\n').toInt();
|
||||
waitResponse();
|
||||
return (RegStatus)status;
|
||||
}
|
||||
|
||||
String getOperator() {
|
||||
sendAT(GF("+COPS?"));
|
||||
if (waitResponse(GF(GSM_NL "+COPS:")) != 1) {
|
||||
return "";
|
||||
}
|
||||
streamSkipUntil('"'); // Skip mode and format
|
||||
String res = stream.readStringUntil('"');
|
||||
waitResponse();
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic network functions
|
||||
*/
|
||||
|
||||
int getSignalQuality() {
|
||||
sendAT(GF("+CSQ"));
|
||||
if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) {
|
||||
return 99;
|
||||
}
|
||||
int res = stream.readStringUntil(',').toInt();
|
||||
waitResponse();
|
||||
return res;
|
||||
}
|
||||
|
||||
bool isNetworkConnected() {
|
||||
RegStatus s = getRegistrationStatus();
|
||||
return (s == REG_OK_HOME || s == REG_OK_ROAMING);
|
||||
}
|
||||
|
||||
bool waitForNetwork(unsigned long timeout = 60000L) {
|
||||
for (unsigned long start = millis(); millis() - start < timeout; ) {
|
||||
if (isNetworkConnected()) {
|
||||
return true;
|
||||
}
|
||||
delay(250);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* WiFi functions
|
||||
*/
|
||||
|
||||
/*
|
||||
* GPRS functions
|
||||
*/
|
||||
bool gprsConnect(const char* apn, const char* user = NULL, const char* pwd = NULL) {
|
||||
gprsDisconnect();
|
||||
|
||||
sendAT(GF("+QICSGP=1,1,\""), apn, GF("\",\""), user, GF("\",\""), pwd, GF("\""));
|
||||
if (waitResponse() != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sendAT(GF("+QIACT=1"));
|
||||
if (waitResponse(150000L) != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sendAT(GF("+CGATT=1"));
|
||||
if (waitResponse(60000L) != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool gprsDisconnect() {
|
||||
sendAT(GF("+QIDEACT=1")); // Deactivate the bearer context
|
||||
if (waitResponse(40000L) != 1)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isGprsConnected() {
|
||||
sendAT(GF("+CGATT?"));
|
||||
if (waitResponse(GF(GSM_NL "+CGATT:")) != 1) {
|
||||
return false;
|
||||
}
|
||||
int res = stream.readStringUntil('\n').toInt();
|
||||
waitResponse();
|
||||
if (res != 1)
|
||||
return false;
|
||||
|
||||
return localIP() != 0;
|
||||
}
|
||||
|
||||
String getLocalIP() {
|
||||
sendAT(GF("+CGPADDR=1"));
|
||||
if (waitResponse(10000L, GF(GSM_NL "+CGPADDR:")) != 1) {
|
||||
return "";
|
||||
}
|
||||
streamSkipUntil(',');
|
||||
String res = stream.readStringUntil('\n');
|
||||
if (waitResponse() != 1) {
|
||||
return "";
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
IPAddress localIP() {
|
||||
return TinyGsmIpFromString(getLocalIP());
|
||||
}
|
||||
|
||||
/*
|
||||
* Phone Call functions
|
||||
*/
|
||||
|
||||
bool setGsmBusy(bool busy = true) TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||
|
||||
bool callAnswer() {
|
||||
sendAT(GF("A"));
|
||||
return waitResponse() == 1;
|
||||
}
|
||||
|
||||
// Returns true on pick-up, false on error/busy
|
||||
bool callNumber(const String& number) TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
bool callHangup() {
|
||||
sendAT(GF("H"));
|
||||
return waitResponse() == 1;
|
||||
}
|
||||
|
||||
// 0-9,*,#,A,B,C,D
|
||||
bool dtmfSend(char cmd, int duration_ms = 100) { // TODO: check
|
||||
duration_ms = constrain(duration_ms, 100, 1000);
|
||||
|
||||
sendAT(GF("+VTD="), duration_ms / 100); // VTD accepts in 1/10 of a second
|
||||
waitResponse();
|
||||
|
||||
sendAT(GF("+VTS="), cmd);
|
||||
return waitResponse(10000L) == 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Messaging functions
|
||||
*/
|
||||
|
||||
String sendUSSD(const String& code) TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
bool sendSMS(const String& number, const String& text) {
|
||||
sendAT(GF("+CMGF=1"));
|
||||
waitResponse();
|
||||
//Set GSM 7 bit default alphabet (3GPP TS 23.038)
|
||||
sendAT(GF("+CSCS=\"GSM\""));
|
||||
waitResponse();
|
||||
sendAT(GF("+CMGS=\""), number, GF("\""));
|
||||
if (waitResponse(GF(">")) != 1) {
|
||||
return false;
|
||||
}
|
||||
stream.print(text);
|
||||
stream.write((char)0x1A);
|
||||
stream.flush();
|
||||
return waitResponse(60000L) == 1;
|
||||
}
|
||||
|
||||
bool sendSMS_UTF16(const String& number, const void* text, size_t len) {
|
||||
sendAT(GF("+CMGF=1"));
|
||||
waitResponse();
|
||||
sendAT(GF("+CSMP=17,167,0,8"));
|
||||
waitResponse();
|
||||
|
||||
sendAT(GF("+CMGS=\""), number, GF("\""));
|
||||
if (waitResponse(GF(">")) != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t* t = (uint16_t*)text;
|
||||
for (size_t i=0; i<len; i++) {
|
||||
uint8_t c = t[i] >> 8;
|
||||
if (c < 0x10) { stream.print('0'); }
|
||||
stream.print(c, HEX);
|
||||
c = t[i] & 0xFF;
|
||||
if (c < 0x10) { stream.print('0'); }
|
||||
stream.print(c, HEX);
|
||||
}
|
||||
stream.write((char)0x1A);
|
||||
stream.flush();
|
||||
return waitResponse(60000L) == 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Location functions
|
||||
*/
|
||||
|
||||
String getGsmLocation() TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||
|
||||
/*
|
||||
* Battery functions
|
||||
*/
|
||||
uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
int getBattPercent() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
protected:
|
||||
|
||||
bool modemConnect(const char* host, uint16_t port, uint8_t mux, bool ssl = false) {
|
||||
int rsp;
|
||||
sendAT(GF("+QIOPEN=1,"), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port, GF(",0,0"));
|
||||
rsp = waitResponse();
|
||||
|
||||
if (waitResponse(20000L, GF(GSM_NL "+QIOPEN:")) != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (stream.readStringUntil(',').toInt() != mux) {
|
||||
return false;
|
||||
}
|
||||
// Read status
|
||||
rsp = stream.readStringUntil('\n').toInt();
|
||||
|
||||
return (0 == rsp);
|
||||
}
|
||||
|
||||
int modemSend(const void* buff, size_t len, uint8_t mux) {
|
||||
sendAT(GF("+QISEND="), mux, ',', len);
|
||||
if (waitResponse(GF(">")) != 1) {
|
||||
return 0;
|
||||
}
|
||||
stream.write((uint8_t*)buff, len);
|
||||
stream.flush();
|
||||
if (waitResponse(GF(GSM_NL "SEND OK")) != 1) {
|
||||
return 0;
|
||||
}
|
||||
// TODO: Wait for ACK? AT+QISEND=id,0
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t modemRead(size_t size, uint8_t mux) {
|
||||
sendAT(GF("+QIRD="), mux, ',', size);
|
||||
if (waitResponse(GF("+QIRD:")) != 1) {
|
||||
return 0;
|
||||
}
|
||||
size_t len = stream.readStringUntil('\n').toInt();
|
||||
|
||||
for (size_t i=0; i<len; i++) {
|
||||
while (!stream.available()) { TINY_GSM_YIELD(); }
|
||||
char c = stream.read();
|
||||
sockets[mux]->rx.put(c);
|
||||
}
|
||||
waitResponse();
|
||||
DBG("### READ:", mux, ",", len);
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t modemGetAvailable(uint8_t mux) {
|
||||
sendAT(GF("+QIRD="), mux, GF(",0"));
|
||||
size_t result = 0;
|
||||
if (waitResponse(GF("+QIRD:")) == 1) {
|
||||
streamSkipUntil(','); // Skip total received
|
||||
streamSkipUntil(','); // Skip have read
|
||||
result = stream.readStringUntil('\n').toInt();
|
||||
DBG("### STILL:", mux, "has", result);
|
||||
waitResponse();
|
||||
}
|
||||
if (!result) {
|
||||
sockets[mux]->sock_connected = modemGetConnected(mux);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool modemGetConnected(uint8_t mux) {
|
||||
sendAT(GF("+QISTATE=1,"), mux);
|
||||
//+QISTATE: 0,"TCP","151.139.237.11",80,5087,4,1,0,0,"uart1"
|
||||
|
||||
if (waitResponse(GF("+QISTATE:")))
|
||||
return false;
|
||||
|
||||
streamSkipUntil(','); // Skip mux
|
||||
streamSkipUntil(','); // Skip socket type
|
||||
streamSkipUntil(','); // Skip remote ip
|
||||
streamSkipUntil(','); // Skip remote port
|
||||
streamSkipUntil(','); // Skip local port
|
||||
int res = stream.readStringUntil(',').toInt(); // socket state
|
||||
|
||||
waitResponse();
|
||||
|
||||
// 0 Initial, 1 Opening, 2 Connected, 3 Listening, 4 Closing
|
||||
return 2 == res;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/* Utilities */
|
||||
|
||||
template<typename T>
|
||||
void streamWrite(T last) {
|
||||
stream.print(last);
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
void streamWrite(T head, Args... tail) {
|
||||
stream.print(head);
|
||||
streamWrite(tail...);
|
||||
}
|
||||
|
||||
bool streamSkipUntil(char c) {
|
||||
const unsigned long timeout = 1000L;
|
||||
unsigned long startMillis = millis();
|
||||
while (millis() - startMillis < timeout) {
|
||||
while (millis() - startMillis < timeout && !stream.available()) {
|
||||
TINY_GSM_YIELD();
|
||||
}
|
||||
if (stream.read() == c)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void sendAT(Args... cmd) {
|
||||
streamWrite("AT", cmd..., GSM_NL);
|
||||
stream.flush();
|
||||
TINY_GSM_YIELD();
|
||||
//DBG("### AT:", cmd...);
|
||||
}
|
||||
|
||||
// TODO: Optimize this!
|
||||
uint8_t waitResponse(uint32_t timeout, String& data,
|
||||
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
|
||||
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
|
||||
{
|
||||
/*String r1s(r1); r1s.trim();
|
||||
String r2s(r2); r2s.trim();
|
||||
String r3s(r3); r3s.trim();
|
||||
String r4s(r4); r4s.trim();
|
||||
String r5s(r5); r5s.trim();
|
||||
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
|
||||
data.reserve(64);
|
||||
int index = 0;
|
||||
unsigned long startMillis = millis();
|
||||
do {
|
||||
TINY_GSM_YIELD();
|
||||
while (stream.available() > 0) {
|
||||
int a = stream.read();
|
||||
if (a <= 0) continue; // Skip 0x00 bytes, just in case
|
||||
data += (char)a;
|
||||
if (r1 && data.endsWith(r1)) {
|
||||
index = 1;
|
||||
goto finish;
|
||||
} else if (r2 && data.endsWith(r2)) {
|
||||
index = 2;
|
||||
goto finish;
|
||||
} else if (r3 && data.endsWith(r3)) {
|
||||
index = 3;
|
||||
goto finish;
|
||||
} else if (r4 && data.endsWith(r4)) {
|
||||
index = 4;
|
||||
goto finish;
|
||||
} else if (r5 && data.endsWith(r5)) {
|
||||
index = 5;
|
||||
goto finish;
|
||||
} else if (data.endsWith(GF(GSM_NL "+QIURC:"))) {
|
||||
stream.readStringUntil('\"');
|
||||
String urc = stream.readStringUntil('\"');
|
||||
stream.readStringUntil(',');
|
||||
if (urc == "recv") {
|
||||
int mux = stream.readStringUntil('\n').toInt();
|
||||
DBG("### URC RECV:", mux);
|
||||
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
|
||||
sockets[mux]->got_data = true;
|
||||
}
|
||||
} else if (urc == "closed") {
|
||||
int mux = stream.readStringUntil('\n').toInt();
|
||||
DBG("### URC CLOSE:", mux);
|
||||
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
|
||||
sockets[mux]->sock_connected = false;
|
||||
}
|
||||
} else {
|
||||
stream.readStringUntil('\n');
|
||||
}
|
||||
data = "";
|
||||
}
|
||||
}
|
||||
} while (millis() - startMillis < timeout);
|
||||
finish:
|
||||
if (!index) {
|
||||
data.trim();
|
||||
if (data.length()) {
|
||||
DBG("### Unhandled:", data);
|
||||
}
|
||||
data = "";
|
||||
}
|
||||
//DBG('<', index, '>');
|
||||
return index;
|
||||
}
|
||||
|
||||
uint8_t waitResponse(uint32_t timeout,
|
||||
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
|
||||
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
|
||||
{
|
||||
String data;
|
||||
return waitResponse(timeout, data, r1, r2, r3, r4, r5);
|
||||
}
|
||||
|
||||
uint8_t waitResponse(GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
|
||||
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
|
||||
{
|
||||
return waitResponse(1000, r1, r2, r3, r4, r5);
|
||||
}
|
||||
|
||||
public:
|
||||
Stream& stream;
|
||||
|
||||
protected:
|
||||
GsmClient* sockets[TINY_GSM_MUX_COUNT];
|
||||
};
|
||||
|
||||
#endif
|
||||
598
arduino-cli/libraries/TinyGSM/src/TinyGsmClientESP8266.h
Normal file
598
arduino-cli/libraries/TinyGSM/src/TinyGsmClientESP8266.h
Normal file
@@ -0,0 +1,598 @@
|
||||
/**
|
||||
* @file TinyGsmClientESP8266.h
|
||||
* @author Volodymyr Shymanskyy
|
||||
* @license LGPL-3.0
|
||||
* @copyright Copyright (c) 2016 Volodymyr Shymanskyy
|
||||
* @date Nov 2016
|
||||
*/
|
||||
|
||||
#ifndef TinyGsmClientESP8266_h
|
||||
#define TinyGsmClientESP8266_h
|
||||
|
||||
//#define TINY_GSM_DEBUG Serial
|
||||
|
||||
#if !defined(TINY_GSM_RX_BUFFER)
|
||||
#define TINY_GSM_RX_BUFFER 512
|
||||
#endif
|
||||
|
||||
#define TINY_GSM_MUX_COUNT 5
|
||||
|
||||
#include <TinyGsmCommon.h>
|
||||
|
||||
#define GSM_NL "\r\n"
|
||||
static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL;
|
||||
static const char GSM_ERROR[] TINY_GSM_PROGMEM = "ERROR" GSM_NL;
|
||||
static unsigned TINY_GSM_TCP_KEEP_ALIVE = 120;
|
||||
|
||||
// <stat> status of ESP8266 station interface
|
||||
// 2 : ESP8266 station connected to an AP and has obtained IP
|
||||
// 3 : ESP8266 station created a TCP or UDP transmission
|
||||
// 4 : the TCP or UDP transmission of ESP8266 station disconnected
|
||||
// 5 : ESP8266 station did NOT connect to an AP
|
||||
enum RegStatus {
|
||||
REG_OK_IP = 2,
|
||||
REG_OK_TCP = 3,
|
||||
REG_UNREGISTERED = 4,
|
||||
REG_DENIED = 5,
|
||||
REG_UNKNOWN = 6,
|
||||
};
|
||||
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// Declaration of the TinyGsmESP8266 Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
|
||||
class TinyGsmESP8266
|
||||
{
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The ESP8266 Internal Client Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
public:
|
||||
|
||||
class GsmClient : public Client
|
||||
{
|
||||
friend class TinyGsmESP8266;
|
||||
typedef TinyGsmFifo<uint8_t, TINY_GSM_RX_BUFFER> RxFifo;
|
||||
|
||||
public:
|
||||
GsmClient() {}
|
||||
|
||||
GsmClient(TinyGsmESP8266& modem, uint8_t mux = 1) {
|
||||
init(&modem, mux);
|
||||
}
|
||||
|
||||
bool init(TinyGsmESP8266* modem, uint8_t mux = 1) {
|
||||
this->at = modem;
|
||||
this->mux = mux;
|
||||
sock_connected = false;
|
||||
|
||||
at->sockets[mux] = this;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
virtual int connect(const char *host, uint16_t port) {
|
||||
stop();
|
||||
TINY_GSM_YIELD();
|
||||
rx.clear();
|
||||
sock_connected = at->modemConnect(host, port, mux);
|
||||
return sock_connected;
|
||||
}
|
||||
|
||||
virtual int connect(IPAddress ip, uint16_t port) {
|
||||
String host; host.reserve(16);
|
||||
host += ip[0];
|
||||
host += ".";
|
||||
host += ip[1];
|
||||
host += ".";
|
||||
host += ip[2];
|
||||
host += ".";
|
||||
host += ip[3];
|
||||
return connect(host.c_str(), port);
|
||||
}
|
||||
|
||||
virtual void stop() {
|
||||
TINY_GSM_YIELD();
|
||||
at->sendAT(GF("+CIPCLOSE="), mux);
|
||||
sock_connected = false;
|
||||
at->waitResponse();
|
||||
rx.clear();
|
||||
}
|
||||
|
||||
virtual size_t write(const uint8_t *buf, size_t size) {
|
||||
TINY_GSM_YIELD();
|
||||
//at->maintain();
|
||||
return at->modemSend(buf, size, mux);
|
||||
}
|
||||
|
||||
virtual size_t write(uint8_t c) {
|
||||
return write(&c, 1);
|
||||
}
|
||||
|
||||
virtual size_t write(const char *str) {
|
||||
if (str == NULL) return 0;
|
||||
return write((const uint8_t *)str, strlen(str));
|
||||
}
|
||||
|
||||
virtual int available() {
|
||||
TINY_GSM_YIELD();
|
||||
if (!rx.size() && sock_connected) {
|
||||
at->maintain();
|
||||
}
|
||||
return rx.size();
|
||||
}
|
||||
|
||||
virtual int read(uint8_t *buf, size_t size) {
|
||||
TINY_GSM_YIELD();
|
||||
size_t cnt = 0;
|
||||
while (cnt < size) {
|
||||
size_t chunk = TinyGsmMin(size-cnt, rx.size());
|
||||
if (chunk > 0) {
|
||||
rx.get(buf, chunk);
|
||||
buf += chunk;
|
||||
cnt += chunk;
|
||||
continue;
|
||||
}
|
||||
// TODO: Read directly into user buffer?
|
||||
if (!rx.size() && sock_connected) {
|
||||
at->maintain();
|
||||
//break;
|
||||
}
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
virtual int read() {
|
||||
uint8_t c;
|
||||
if (read(&c, 1) == 1) {
|
||||
return c;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
virtual int peek() { return -1; } //TODO
|
||||
virtual void flush() { at->stream.flush(); }
|
||||
|
||||
virtual uint8_t connected() {
|
||||
if (available()) {
|
||||
return true;
|
||||
}
|
||||
return sock_connected;
|
||||
}
|
||||
virtual operator bool() { return connected(); }
|
||||
|
||||
/*
|
||||
* Extended API
|
||||
*/
|
||||
|
||||
String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
private:
|
||||
TinyGsmESP8266* at;
|
||||
uint8_t mux;
|
||||
bool sock_connected;
|
||||
RxFifo rx;
|
||||
};
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The Secure ESP8266 Client Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
|
||||
class GsmClientSecure : public GsmClient
|
||||
{
|
||||
public:
|
||||
GsmClientSecure() {}
|
||||
|
||||
GsmClientSecure(TinyGsmESP8266& modem, uint8_t mux = 1)
|
||||
: GsmClient(modem, mux)
|
||||
{}
|
||||
|
||||
public:
|
||||
virtual int connect(const char *host, uint16_t port) {
|
||||
stop();
|
||||
TINY_GSM_YIELD();
|
||||
rx.clear();
|
||||
sock_connected = at->modemConnect(host, port, mux, true);
|
||||
return sock_connected;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The ESP8266 Modem Functions
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
public:
|
||||
|
||||
#ifdef GSM_DEFAULT_STREAM
|
||||
TinyGsmESP8266(Stream& stream = GSM_DEFAULT_STREAM)
|
||||
#else
|
||||
TinyGsmESP8266(Stream& stream)
|
||||
#endif
|
||||
: stream(stream)
|
||||
{
|
||||
memset(sockets, 0, sizeof(sockets));
|
||||
}
|
||||
|
||||
/*
|
||||
* Basic functions
|
||||
*/
|
||||
bool begin() {
|
||||
return init();
|
||||
}
|
||||
|
||||
bool init() {
|
||||
if (!testAT()) {
|
||||
return false;
|
||||
}
|
||||
sendAT(GF("E0")); // Echo Off
|
||||
if (waitResponse() != 1) {
|
||||
return false;
|
||||
}
|
||||
sendAT(GF("+CIPMUX=1")); // Enable Multiple Connections
|
||||
if (waitResponse() != 1) {
|
||||
return false;
|
||||
}
|
||||
sendAT(GF("+CWMODE_CUR=1")); // Put into "station" mode
|
||||
if (waitResponse() != 1) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void setBaud(unsigned long baud) {
|
||||
sendAT(GF("+IPR="), baud);
|
||||
}
|
||||
|
||||
bool testAT(unsigned long timeout = 10000L) {
|
||||
for (unsigned long start = millis(); millis() - start < timeout; ) {
|
||||
sendAT(GF(""));
|
||||
if (waitResponse(200) == 1) {
|
||||
delay(100);
|
||||
return true;
|
||||
}
|
||||
delay(100);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void maintain() {
|
||||
waitResponse(10, NULL, NULL);
|
||||
}
|
||||
|
||||
bool factoryDefault() {
|
||||
sendAT(GF("+RESTORE"));
|
||||
return waitResponse() == 1;
|
||||
}
|
||||
|
||||
String getModemInfo() {
|
||||
sendAT(GF("+GMR"));
|
||||
String res;
|
||||
if (waitResponse(1000L, res) != 1) {
|
||||
return "";
|
||||
}
|
||||
res.replace(GSM_NL "OK" GSM_NL, "");
|
||||
res.replace(GSM_NL, " ");
|
||||
res.trim();
|
||||
return res;
|
||||
}
|
||||
|
||||
bool hasSSL() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Power functions
|
||||
*/
|
||||
|
||||
bool restart() {
|
||||
if (!testAT()) {
|
||||
return false;
|
||||
}
|
||||
sendAT(GF("+RST"));
|
||||
if (waitResponse(10000L) != 1) {
|
||||
return false;
|
||||
}
|
||||
if (waitResponse(10000L, GF(GSM_NL "ready" GSM_NL)) != 1) {
|
||||
return false;
|
||||
}
|
||||
delay(500);
|
||||
return init();
|
||||
}
|
||||
|
||||
bool poweroff() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
bool radioOff() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
bool sleepEnable(bool enable = true) TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
/*
|
||||
* SIM card functions
|
||||
*/
|
||||
|
||||
RegStatus getRegistrationStatus() {
|
||||
sendAT(GF("+CIPSTATUS"));
|
||||
if (waitResponse(3000, GF("STATUS:")) != 1) return REG_UNKNOWN;
|
||||
int status = waitResponse(GFP(GSM_ERROR), GF("2"), GF("3"), GF("4"), GF("5"));
|
||||
waitResponse(); // Returns an OK after the status
|
||||
return (RegStatus)status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic network functions
|
||||
*/
|
||||
|
||||
int getSignalQuality() {
|
||||
sendAT(GF("+CWJAP_CUR?"));
|
||||
int res1 = waitResponse(GF("No AP"), GF("+CWJAP_CUR:"));
|
||||
if (res1 != 2) {
|
||||
waitResponse();
|
||||
return 0;
|
||||
}
|
||||
streamSkipUntil(','); // Skip SSID
|
||||
streamSkipUntil(','); // Skip BSSID/MAC address
|
||||
streamSkipUntil(','); // Skip Chanel number
|
||||
int res2 = stream.parseInt(); // Read RSSI
|
||||
waitResponse(); // Returns an OK after the value
|
||||
return res2;
|
||||
}
|
||||
|
||||
bool isNetworkConnected() {
|
||||
RegStatus s = getRegistrationStatus();
|
||||
return (s == REG_OK_IP || s == REG_OK_TCP);
|
||||
}
|
||||
|
||||
bool waitForNetwork(unsigned long timeout = 60000L) {
|
||||
for (unsigned long start = millis(); millis() - start < timeout; ) {
|
||||
sendAT(GF("+CIPSTATUS"));
|
||||
int res1 = waitResponse(3000, GF("busy p..."), GF("STATUS:"));
|
||||
if (res1 == 2) {
|
||||
int res2 = waitResponse(GFP(GSM_ERROR), GF("2"), GF("3"), GF("4"), GF("5"));
|
||||
if (res2 == 2 || res2 == 3) {
|
||||
waitResponse();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
delay(250);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* WiFi functions
|
||||
*/
|
||||
bool networkConnect(const char* ssid, const char* pwd) {
|
||||
sendAT(GF("+CWJAP_CUR=\""), ssid, GF("\",\""), pwd, GF("\""));
|
||||
if (waitResponse(30000L, GFP(GSM_OK), GF(GSM_NL "FAIL" GSM_NL)) != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool networkDisconnect() {
|
||||
sendAT(GF("+CWQAP"));
|
||||
bool retVal = waitResponse(10000L) == 1;
|
||||
waitResponse(GF("WIFI DISCONNECT"));
|
||||
return retVal;
|
||||
}
|
||||
|
||||
String getLocalIP() {
|
||||
sendAT(GF("+CIPSTA_CUR??"));
|
||||
int res1 = waitResponse(GF("ERROR"), GF("+CWJAP_CUR:"));
|
||||
if (res1 != 2) {
|
||||
return "";
|
||||
}
|
||||
String res2 = stream.readStringUntil('"');
|
||||
waitResponse();
|
||||
return res2;
|
||||
}
|
||||
|
||||
IPAddress localIP() {
|
||||
return TinyGsmIpFromString(getLocalIP());
|
||||
}
|
||||
|
||||
/*
|
||||
* GPRS functions
|
||||
*/
|
||||
|
||||
/*
|
||||
* Messaging functions
|
||||
*/
|
||||
|
||||
/*
|
||||
* Location functions
|
||||
*/
|
||||
|
||||
String getGsmLocation() TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||
|
||||
/*
|
||||
* Battery functions
|
||||
*/
|
||||
|
||||
uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||
|
||||
int getBattPercent() TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||
|
||||
protected:
|
||||
|
||||
bool modemConnect(const char* host, uint16_t port, uint8_t mux, bool ssl = false) {
|
||||
if (ssl) {
|
||||
sendAT(GF("+CIPSSLSIZE=4096"));
|
||||
waitResponse();
|
||||
}
|
||||
sendAT(GF("+CIPSTART="), mux, ',', ssl ? GF("\"SSL") : GF("\"TCP"), GF("\",\""), host, GF("\","), port, GF(","), TINY_GSM_TCP_KEEP_ALIVE);
|
||||
// TODO: Check mux
|
||||
int rsp = waitResponse(75000L,
|
||||
GFP(GSM_OK),
|
||||
GFP(GSM_ERROR),
|
||||
GF("ALREADY CONNECT"));
|
||||
// if (rsp == 3) waitResponse(); // May return "ERROR" after the "ALREADY CONNECT"
|
||||
return (1 == rsp);
|
||||
}
|
||||
|
||||
int modemSend(const void* buff, size_t len, uint8_t mux) {
|
||||
sendAT(GF("+CIPSEND="), mux, ',', len);
|
||||
if (waitResponse(GF(">")) != 1) {
|
||||
return 0;
|
||||
}
|
||||
stream.write((uint8_t*)buff, len);
|
||||
stream.flush();
|
||||
if (waitResponse(10000L, GF(GSM_NL "SEND OK" GSM_NL)) != 1) {
|
||||
return 0;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
bool modemGetConnected(uint8_t mux) {
|
||||
RegStatus s = getRegistrationStatus();
|
||||
return (s == REG_OK_IP || s == REG_OK_TCP);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/* Utilities */
|
||||
|
||||
template<typename T>
|
||||
void streamWrite(T last) {
|
||||
stream.print(last);
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
void streamWrite(T head, Args... tail) {
|
||||
stream.print(head);
|
||||
streamWrite(tail...);
|
||||
}
|
||||
|
||||
bool streamSkipUntil(char c) {
|
||||
const unsigned long timeout = 1000L;
|
||||
unsigned long startMillis = millis();
|
||||
while (millis() - startMillis < timeout) {
|
||||
while (millis() - startMillis < timeout && !stream.available()) {
|
||||
TINY_GSM_YIELD();
|
||||
}
|
||||
if (stream.read() == c)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void sendAT(Args... cmd) {
|
||||
streamWrite("AT", cmd..., GSM_NL);
|
||||
stream.flush();
|
||||
TINY_GSM_YIELD();
|
||||
//DBG("### AT:", cmd...);
|
||||
}
|
||||
|
||||
// TODO: Optimize this!
|
||||
uint8_t waitResponse(uint32_t timeout, String& data,
|
||||
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
|
||||
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
|
||||
{
|
||||
/*String r1s(r1); r1s.trim();
|
||||
String r2s(r2); r2s.trim();
|
||||
String r3s(r3); r3s.trim();
|
||||
String r4s(r4); r4s.trim();
|
||||
String r5s(r5); r5s.trim();
|
||||
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
|
||||
data.reserve(64);
|
||||
int index = 0;
|
||||
unsigned long startMillis = millis();
|
||||
do {
|
||||
TINY_GSM_YIELD();
|
||||
while (stream.available() > 0) {
|
||||
int a = stream.read();
|
||||
if (a <= 0) continue; // Skip 0x00 bytes, just in case
|
||||
data += (char)a;
|
||||
if (r1 && data.endsWith(r1)) {
|
||||
index = 1;
|
||||
goto finish;
|
||||
} else if (r2 && data.endsWith(r2)) {
|
||||
index = 2;
|
||||
goto finish;
|
||||
} else if (r3 && data.endsWith(r3)) {
|
||||
index = 3;
|
||||
goto finish;
|
||||
} else if (r4 && data.endsWith(r4)) {
|
||||
index = 4;
|
||||
goto finish;
|
||||
} else if (r5 && data.endsWith(r5)) {
|
||||
index = 5;
|
||||
goto finish;
|
||||
} else if (data.endsWith(GF(GSM_NL "+IPD,"))) {
|
||||
int mux = stream.readStringUntil(',').toInt();
|
||||
int len = stream.readStringUntil(':').toInt();
|
||||
int len_orig = len;
|
||||
if (len > sockets[mux]->rx.free()) {
|
||||
DBG("### Buffer overflow: ", len, "->", sockets[mux]->rx.free());
|
||||
} else {
|
||||
DBG("### Got: ", len, "->", sockets[mux]->rx.free());
|
||||
}
|
||||
while (len--) {
|
||||
while (!stream.available()) { TINY_GSM_YIELD(); }
|
||||
sockets[mux]->rx.put(stream.read());
|
||||
}
|
||||
if (len_orig > sockets[mux]->available()) { // TODO
|
||||
DBG("### Fewer characters received than expected: ", sockets[mux]->available(), " vs ", len_orig);
|
||||
}
|
||||
data = "";
|
||||
} else if (data.endsWith(GF("CLOSED"))) {
|
||||
int muxStart = max(0,data.lastIndexOf(GSM_NL, data.length()-8));
|
||||
int coma = data.indexOf(',', muxStart);
|
||||
int mux = data.substring(muxStart, coma).toInt();
|
||||
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
|
||||
sockets[mux]->sock_connected = false;
|
||||
}
|
||||
data = "";
|
||||
DBG("### Closed: ", mux);
|
||||
}
|
||||
}
|
||||
} while (millis() - startMillis < timeout);
|
||||
finish:
|
||||
if (!index) {
|
||||
data.trim();
|
||||
if (data.length()) {
|
||||
DBG("### Unhandled:", data);
|
||||
}
|
||||
data = "";
|
||||
}
|
||||
//DBG('<', index, '>');
|
||||
return index;
|
||||
}
|
||||
|
||||
uint8_t waitResponse(uint32_t timeout,
|
||||
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
|
||||
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
|
||||
{
|
||||
String data;
|
||||
return waitResponse(timeout, data, r1, r2, r3, r4, r5);
|
||||
}
|
||||
|
||||
uint8_t waitResponse(GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
|
||||
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
|
||||
{
|
||||
return waitResponse(1000, r1, r2, r3, r4, r5);
|
||||
}
|
||||
|
||||
public:
|
||||
Stream& stream;
|
||||
|
||||
protected:
|
||||
GsmClient* sockets[TINY_GSM_MUX_COUNT];
|
||||
};
|
||||
|
||||
#endif
|
||||
755
arduino-cli/libraries/TinyGSM/src/TinyGsmClientM590.h
Normal file
755
arduino-cli/libraries/TinyGSM/src/TinyGsmClientM590.h
Normal file
@@ -0,0 +1,755 @@
|
||||
/**
|
||||
* @file TinyGsmClientM590.h
|
||||
* @author Volodymyr Shymanskyy
|
||||
* @license LGPL-3.0
|
||||
* @copyright Copyright (c) 2016 Volodymyr Shymanskyy
|
||||
* @date Nov 2016
|
||||
*/
|
||||
|
||||
#ifndef TinyGsmClientM590_h
|
||||
#define TinyGsmClientM590_h
|
||||
|
||||
//#define TINY_GSM_DEBUG Serial
|
||||
|
||||
#if !defined(TINY_GSM_RX_BUFFER)
|
||||
#define TINY_GSM_RX_BUFFER 256
|
||||
#endif
|
||||
|
||||
#define TINY_GSM_MUX_COUNT 2
|
||||
|
||||
#include <TinyGsmCommon.h>
|
||||
|
||||
#define GSM_NL "\r\n"
|
||||
static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL;
|
||||
static const char GSM_ERROR[] TINY_GSM_PROGMEM = "ERROR" GSM_NL;
|
||||
|
||||
enum SimStatus {
|
||||
SIM_ERROR = 0,
|
||||
SIM_READY = 1,
|
||||
SIM_LOCKED = 2,
|
||||
};
|
||||
|
||||
enum RegStatus {
|
||||
REG_UNREGISTERED = 0,
|
||||
REG_SEARCHING = 3,
|
||||
REG_DENIED = 2,
|
||||
REG_OK_HOME = 1,
|
||||
REG_OK_ROAMING = 5,
|
||||
REG_UNKNOWN = 4,
|
||||
};
|
||||
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// Declaration of the TinyGsmM590 Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
class TinyGsmM590
|
||||
{
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The M590 Internal Client Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
|
||||
public:
|
||||
|
||||
class GsmClient : public Client
|
||||
{
|
||||
friend class TinyGsmM590;
|
||||
typedef TinyGsmFifo<uint8_t, TINY_GSM_RX_BUFFER> RxFifo;
|
||||
|
||||
public:
|
||||
GsmClient() {}
|
||||
|
||||
GsmClient(TinyGsmM590& modem, uint8_t mux = 1) {
|
||||
init(&modem, mux);
|
||||
}
|
||||
|
||||
bool init(TinyGsmM590* modem, uint8_t mux = 1) {
|
||||
this->at = modem;
|
||||
this->mux = mux;
|
||||
sock_connected = false;
|
||||
|
||||
at->sockets[mux] = this;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
virtual int connect(const char *host, uint16_t port) {
|
||||
stop();
|
||||
TINY_GSM_YIELD();
|
||||
rx.clear();
|
||||
sock_connected = at->modemConnect(host, port, mux);
|
||||
return sock_connected;
|
||||
}
|
||||
|
||||
virtual int connect(IPAddress ip, uint16_t port) {
|
||||
String host; host.reserve(16);
|
||||
host += ip[0];
|
||||
host += ".";
|
||||
host += ip[1];
|
||||
host += ".";
|
||||
host += ip[2];
|
||||
host += ".";
|
||||
host += ip[3];
|
||||
return connect(host.c_str(), port);
|
||||
}
|
||||
|
||||
virtual void stop() {
|
||||
TINY_GSM_YIELD();
|
||||
at->sendAT(GF("+TCPCLOSE="), mux);
|
||||
sock_connected = false;
|
||||
at->waitResponse();
|
||||
rx.clear();
|
||||
}
|
||||
|
||||
virtual size_t write(const uint8_t *buf, size_t size) {
|
||||
TINY_GSM_YIELD();
|
||||
//at->maintain();
|
||||
return at->modemSend(buf, size, mux);
|
||||
}
|
||||
|
||||
virtual size_t write(uint8_t c) {
|
||||
return write(&c, 1);
|
||||
}
|
||||
|
||||
virtual size_t write(const char *str) {
|
||||
if (str == NULL) return 0;
|
||||
return write((const uint8_t *)str, strlen(str));
|
||||
}
|
||||
|
||||
virtual int available() {
|
||||
TINY_GSM_YIELD();
|
||||
if (!rx.size() && sock_connected) {
|
||||
at->maintain();
|
||||
}
|
||||
return rx.size();
|
||||
}
|
||||
|
||||
virtual int read(uint8_t *buf, size_t size) {
|
||||
TINY_GSM_YIELD();
|
||||
size_t cnt = 0;
|
||||
while (cnt < size) {
|
||||
size_t chunk = TinyGsmMin(size-cnt, rx.size());
|
||||
if (chunk > 0) {
|
||||
rx.get(buf, chunk);
|
||||
buf += chunk;
|
||||
cnt += chunk;
|
||||
continue;
|
||||
}
|
||||
// TODO: Read directly into user buffer?
|
||||
if (!rx.size() && sock_connected) {
|
||||
at->maintain();
|
||||
//break;
|
||||
}
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
virtual int read() {
|
||||
uint8_t c;
|
||||
if (read(&c, 1) == 1) {
|
||||
return c;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
virtual int peek() { return -1; } //TODO
|
||||
virtual void flush() { at->stream.flush(); }
|
||||
|
||||
virtual uint8_t connected() {
|
||||
if (available()) {
|
||||
return true;
|
||||
}
|
||||
return sock_connected;
|
||||
}
|
||||
virtual operator bool() { return connected(); }
|
||||
|
||||
/*
|
||||
* Extended API
|
||||
*/
|
||||
|
||||
String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
private:
|
||||
TinyGsmM590* at;
|
||||
uint8_t mux;
|
||||
bool sock_connected;
|
||||
RxFifo rx;
|
||||
};
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The M590 Has no Secure client!
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The M590 Modem Functions
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
public:
|
||||
|
||||
#ifdef GSM_DEFAULT_STREAM
|
||||
TinyGsmM590(Stream& stream = GSM_DEFAULT_STREAM)
|
||||
#else
|
||||
TinyGsmM590(Stream& stream)
|
||||
#endif
|
||||
: stream(stream)
|
||||
{
|
||||
memset(sockets, 0, sizeof(sockets));
|
||||
}
|
||||
|
||||
/*
|
||||
* Basic functions
|
||||
*/
|
||||
bool begin() {
|
||||
return init();
|
||||
}
|
||||
|
||||
bool init() {
|
||||
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();
|
||||
#endif
|
||||
|
||||
getSimStatus();
|
||||
return true;
|
||||
}
|
||||
|
||||
void setBaud(unsigned long baud) {
|
||||
sendAT(GF("+IPR="), baud);
|
||||
}
|
||||
|
||||
bool testAT(unsigned long timeout = 10000L) {
|
||||
for (unsigned long start = millis(); millis() - start < timeout; ) {
|
||||
sendAT(GF(""));
|
||||
if (waitResponse(200) == 1) {
|
||||
delay(100);
|
||||
return true;
|
||||
}
|
||||
delay(100);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void maintain() {
|
||||
//while (stream.available()) {
|
||||
waitResponse(10, NULL, NULL);
|
||||
//}
|
||||
}
|
||||
|
||||
bool factoryDefault() {
|
||||
sendAT(GF("&FZE0&W")); // Factory + Reset + Echo Off + Write
|
||||
waitResponse();
|
||||
sendAT(GF("+ICF=3,1")); // 8 data 0 parity 1 stop
|
||||
waitResponse();
|
||||
sendAT(GF("+ENPWRSAVE=0")); // Disable PWR save
|
||||
waitResponse();
|
||||
sendAT(GF("+XISP=0")); // Use internal stack
|
||||
waitResponse();
|
||||
sendAT(GF("&W")); // Write configuration
|
||||
return waitResponse() == 1;
|
||||
}
|
||||
|
||||
String getModemInfo() {
|
||||
sendAT(GF("I"));
|
||||
String res;
|
||||
if (waitResponse(1000L, res) != 1) {
|
||||
return "";
|
||||
}
|
||||
res.replace(GSM_NL "OK" GSM_NL, "");
|
||||
res.replace(GSM_NL, " ");
|
||||
res.trim();
|
||||
return res;
|
||||
}
|
||||
|
||||
bool hasSSL() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Power functions
|
||||
*/
|
||||
|
||||
bool restart() {
|
||||
if (!testAT()) {
|
||||
return false;
|
||||
}
|
||||
sendAT(GF("+CFUN=15"));
|
||||
if (waitResponse(10000L) != 1) {
|
||||
return false;
|
||||
}
|
||||
//MODEM:STARTUP
|
||||
waitResponse(60000L, GF(GSM_NL "+PBREADY" GSM_NL));
|
||||
return init();
|
||||
}
|
||||
|
||||
bool poweroff() {
|
||||
sendAT(GF("+CPWROFF"));
|
||||
return waitResponse(3000L) == 1;
|
||||
}
|
||||
|
||||
bool radioOff() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
bool sleepEnable(bool enable = true) {
|
||||
sendAT(GF("+ENPWRSAVE="), enable);
|
||||
return waitResponse() == 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* SIM card functions
|
||||
*/
|
||||
|
||||
bool simUnlock(const char *pin) {
|
||||
sendAT(GF("+CPIN=\""), pin, GF("\""));
|
||||
return waitResponse() == 1;
|
||||
}
|
||||
|
||||
String getSimCCID() {
|
||||
sendAT(GF("+CCID"));
|
||||
if (waitResponse(GF(GSM_NL "+CCID:")) != 1) {
|
||||
return "";
|
||||
}
|
||||
String res = stream.readStringUntil('\n');
|
||||
waitResponse();
|
||||
res.trim();
|
||||
return res;
|
||||
}
|
||||
|
||||
String getIMEI() {
|
||||
sendAT(GF("+GSN"));
|
||||
if (waitResponse(GF(GSM_NL)) != 1) {
|
||||
return "";
|
||||
}
|
||||
String res = stream.readStringUntil('\n');
|
||||
waitResponse();
|
||||
res.trim();
|
||||
return res;
|
||||
}
|
||||
|
||||
SimStatus getSimStatus(unsigned long timeout = 10000L) {
|
||||
for (unsigned long start = millis(); millis() - start < timeout; ) {
|
||||
sendAT(GF("+CPIN?"));
|
||||
if (waitResponse(GF(GSM_NL "+CPIN:")) != 1) {
|
||||
delay(1000);
|
||||
continue;
|
||||
}
|
||||
int status = waitResponse(GF("READY"), GF("SIM PIN"), GF("SIM PUK"));
|
||||
waitResponse();
|
||||
switch (status) {
|
||||
case 2:
|
||||
case 3: return SIM_LOCKED;
|
||||
case 1: return SIM_READY;
|
||||
default: return SIM_ERROR;
|
||||
}
|
||||
}
|
||||
return SIM_ERROR;
|
||||
}
|
||||
|
||||
RegStatus getRegistrationStatus() {
|
||||
sendAT(GF("+CREG?"));
|
||||
if (waitResponse(GF(GSM_NL "+CREG:")) != 1) {
|
||||
return REG_UNKNOWN;
|
||||
}
|
||||
streamSkipUntil(','); // Skip format (0)
|
||||
int status = stream.readStringUntil('\n').toInt();
|
||||
waitResponse();
|
||||
return (RegStatus)status;
|
||||
}
|
||||
|
||||
String getOperator() {
|
||||
sendAT(GF("+COPS?"));
|
||||
if (waitResponse(GF(GSM_NL "+COPS:")) != 1) {
|
||||
return "";
|
||||
}
|
||||
streamSkipUntil('"'); // Skip mode and format
|
||||
String res = stream.readStringUntil('"');
|
||||
waitResponse();
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic network functions
|
||||
*/
|
||||
|
||||
int getSignalQuality() {
|
||||
sendAT(GF("+CSQ"));
|
||||
if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) {
|
||||
return 99;
|
||||
}
|
||||
int res = stream.readStringUntil(',').toInt();
|
||||
waitResponse();
|
||||
return res;
|
||||
}
|
||||
|
||||
bool isNetworkConnected() {
|
||||
RegStatus s = getRegistrationStatus();
|
||||
return (s == REG_OK_HOME || s == REG_OK_ROAMING);
|
||||
}
|
||||
|
||||
bool waitForNetwork(unsigned long timeout = 60000L) {
|
||||
for (unsigned long start = millis(); millis() - start < timeout; ) {
|
||||
if (isNetworkConnected()) {
|
||||
return true;
|
||||
}
|
||||
delay(250);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* WiFi functions
|
||||
*/
|
||||
|
||||
/*
|
||||
* GPRS functions
|
||||
*/
|
||||
bool gprsConnect(const char* apn, const char* user = NULL, const char* pwd = NULL) {
|
||||
gprsDisconnect();
|
||||
|
||||
sendAT(GF("+XISP=0"));
|
||||
waitResponse();
|
||||
|
||||
sendAT(GF("+CGDCONT=1,\"IP\",\""), apn, '"');
|
||||
waitResponse();
|
||||
|
||||
if (!user) user = "";
|
||||
if (!pwd) pwd = "";
|
||||
sendAT(GF("+XGAUTH=1,1,\""), user, GF("\",\""), pwd, GF("\""));
|
||||
waitResponse();
|
||||
|
||||
sendAT(GF("+XIIC=1"));
|
||||
waitResponse();
|
||||
|
||||
const unsigned long timeout = 60000L;
|
||||
for (unsigned long start = millis(); millis() - start < timeout; ) {
|
||||
if (isGprsConnected()) {
|
||||
//goto set_dns; // TODO
|
||||
return true;
|
||||
}
|
||||
delay(500);
|
||||
}
|
||||
return false;
|
||||
|
||||
// set_dns: // TODO
|
||||
// sendAT(GF("+DNSSERVER=1,8.8.8.8"));
|
||||
// waitResponse();
|
||||
//
|
||||
// sendAT(GF("+DNSSERVER=2,8.8.4.4"));
|
||||
// waitResponse();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool gprsDisconnect() {
|
||||
// TODO: There is no command in AT command set
|
||||
// XIIC=0 does not work
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isGprsConnected() {
|
||||
sendAT(GF("+XIIC?"));
|
||||
if (waitResponse(GF(GSM_NL "+XIIC:")) != 1) {
|
||||
return false;
|
||||
}
|
||||
int res = stream.readStringUntil(',').toInt();
|
||||
waitResponse();
|
||||
return res == 1;
|
||||
}
|
||||
|
||||
String getLocalIP() {
|
||||
sendAT(GF("+XIIC?"));
|
||||
if (waitResponse(GF(GSM_NL "+XIIC:")) != 1) {
|
||||
return "";
|
||||
}
|
||||
stream.readStringUntil(',');
|
||||
String res = stream.readStringUntil('\n');
|
||||
waitResponse();
|
||||
res.trim();
|
||||
return res;
|
||||
}
|
||||
|
||||
IPAddress localIP() {
|
||||
return TinyGsmIpFromString(getLocalIP());
|
||||
}
|
||||
|
||||
/*
|
||||
* Phone Call functions
|
||||
*/
|
||||
|
||||
bool setGsmBusy(bool busy = true) TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||
|
||||
bool callAnswer() TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||
|
||||
bool callNumber(const String& number) TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||
|
||||
bool callHangup() TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||
|
||||
/*
|
||||
* Messaging functions
|
||||
*/
|
||||
|
||||
String sendUSSD(const String& code) {
|
||||
sendAT(GF("+CMGF=1"));
|
||||
waitResponse();
|
||||
sendAT(GF("+CSCS=\"HEX\""));
|
||||
waitResponse();
|
||||
sendAT(GF("D"), code);
|
||||
if (waitResponse(10000L, GF(GSM_NL "+CUSD:")) != 1) {
|
||||
return "";
|
||||
}
|
||||
stream.readStringUntil('"');
|
||||
String hex = stream.readStringUntil('"');
|
||||
stream.readStringUntil(',');
|
||||
int dcs = stream.readStringUntil('\n').toInt();
|
||||
|
||||
if (waitResponse() != 1) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (dcs == 15) {
|
||||
return TinyGsmDecodeHex8bit(hex);
|
||||
} else if (dcs == 72) {
|
||||
return TinyGsmDecodeHex16bit(hex);
|
||||
} else {
|
||||
return hex;
|
||||
}
|
||||
}
|
||||
|
||||
bool sendSMS(const String& number, const String& text) {
|
||||
sendAT(GF("+CSCS=\"GSM\""));
|
||||
waitResponse();
|
||||
sendAT(GF("+CMGF=1"));
|
||||
waitResponse();
|
||||
sendAT(GF("+CMGS=\""), number, GF("\""));
|
||||
if (waitResponse(GF(">")) != 1) {
|
||||
return false;
|
||||
}
|
||||
stream.print(text);
|
||||
stream.write((char)0x1A);
|
||||
stream.flush();
|
||||
return waitResponse(60000L) == 1;
|
||||
}
|
||||
|
||||
bool sendSMS_UTF16(const String& number, const void* text, size_t len)
|
||||
TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||
|
||||
/*
|
||||
* Location functions
|
||||
*/
|
||||
|
||||
String getGsmLocation() TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||
|
||||
/*
|
||||
* Battery functions
|
||||
*/
|
||||
|
||||
uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||
|
||||
int getBattPercent() TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||
|
||||
protected:
|
||||
|
||||
bool modemConnect(const char* host, uint16_t port, uint8_t mux) {
|
||||
for (int i=0; i<3; i++) { // TODO: no need for loop?
|
||||
String ip = dnsIpQuery(host);
|
||||
|
||||
sendAT(GF("+TCPSETUP="), mux, GF(","), ip, GF(","), port);
|
||||
int rsp = waitResponse(75000L,
|
||||
GF(",OK" GSM_NL),
|
||||
GF(",FAIL" GSM_NL),
|
||||
GF("+TCPSETUP:Error" GSM_NL));
|
||||
if (1 == rsp) {
|
||||
return true;
|
||||
} else if (3 == rsp) {
|
||||
sendAT(GF("+TCPCLOSE="), mux);
|
||||
waitResponse();
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int modemSend(const void* buff, size_t len, uint8_t mux) {
|
||||
sendAT(GF("+TCPSEND="), mux, ',', len);
|
||||
if (waitResponse(GF(">")) != 1) {
|
||||
return 0;
|
||||
}
|
||||
stream.write((uint8_t*)buff, len);
|
||||
stream.write((char)0x0D);
|
||||
stream.flush();
|
||||
if (waitResponse(30000L, GF(GSM_NL "+TCPSEND:")) != 1) {
|
||||
return 0;
|
||||
}
|
||||
stream.readStringUntil('\n');
|
||||
return len;
|
||||
}
|
||||
|
||||
bool modemGetConnected(uint8_t mux) {
|
||||
sendAT(GF("+CIPSTATUS="), mux);
|
||||
int res = waitResponse(GF(",\"CONNECTED\""), GF(",\"CLOSED\""), GF(",\"CLOSING\""), GF(",\"INITIAL\""));
|
||||
waitResponse();
|
||||
return 1 == res;
|
||||
}
|
||||
|
||||
String dnsIpQuery(const char* host) {
|
||||
sendAT(GF("+DNS=\""), host, GF("\""));
|
||||
if (waitResponse(10000L, GF(GSM_NL "+DNS:")) != 1) {
|
||||
return "";
|
||||
}
|
||||
String res = stream.readStringUntil('\n');
|
||||
waitResponse(GF("+DNS:OK" GSM_NL));
|
||||
res.trim();
|
||||
return res;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/* Utilities */
|
||||
|
||||
template<typename T>
|
||||
void streamWrite(T last) {
|
||||
stream.print(last);
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
void streamWrite(T head, Args... tail) {
|
||||
stream.print(head);
|
||||
streamWrite(tail...);
|
||||
}
|
||||
|
||||
bool streamSkipUntil(char c) {
|
||||
const unsigned long timeout = 1000L;
|
||||
unsigned long startMillis = millis();
|
||||
while (millis() - startMillis < timeout) {
|
||||
while (millis() - startMillis < timeout && !stream.available()) {
|
||||
TINY_GSM_YIELD();
|
||||
}
|
||||
if (stream.read() == c)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void sendAT(Args... cmd) {
|
||||
streamWrite("AT", cmd..., GSM_NL);
|
||||
stream.flush();
|
||||
TINY_GSM_YIELD();
|
||||
//DBG("### AT:", cmd...);
|
||||
}
|
||||
|
||||
// TODO: Optimize this!
|
||||
uint8_t waitResponse(uint32_t timeout, String& data,
|
||||
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
|
||||
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
|
||||
{
|
||||
/*String r1s(r1); r1s.trim();
|
||||
String r2s(r2); r2s.trim();
|
||||
String r3s(r3); r3s.trim();
|
||||
String r4s(r4); r4s.trim();
|
||||
String r5s(r5); r5s.trim();
|
||||
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
|
||||
data.reserve(64);
|
||||
int index = 0;
|
||||
unsigned long startMillis = millis();
|
||||
do {
|
||||
TINY_GSM_YIELD();
|
||||
while (stream.available() > 0) {
|
||||
int a = stream.read();
|
||||
if (a <= 0) continue; // Skip 0x00 bytes, just in case
|
||||
data += (char)a;
|
||||
if (r1 && data.endsWith(r1)) {
|
||||
index = 1;
|
||||
goto finish;
|
||||
} else if (r2 && data.endsWith(r2)) {
|
||||
index = 2;
|
||||
goto finish;
|
||||
} else if (r3 && data.endsWith(r3)) {
|
||||
index = 3;
|
||||
goto finish;
|
||||
} else if (r4 && data.endsWith(r4)) {
|
||||
index = 4;
|
||||
goto finish;
|
||||
} else if (r5 && data.endsWith(r5)) {
|
||||
index = 5;
|
||||
goto finish;
|
||||
} else if (data.endsWith(GF("+TCPRECV:"))) {
|
||||
int mux = stream.readStringUntil(',').toInt();
|
||||
int len = stream.readStringUntil(',').toInt();
|
||||
int len_orig = len;
|
||||
if (len > sockets[mux]->rx.free()) {
|
||||
DBG("### Buffer overflow: ", len, "->", sockets[mux]->rx.free());
|
||||
} else {
|
||||
DBG("### Got: ", len, "->", sockets[mux]->rx.free());
|
||||
}
|
||||
while (len--) {
|
||||
while (!stream.available()) { TINY_GSM_YIELD(); }
|
||||
sockets[mux]->rx.put(stream.read());
|
||||
}
|
||||
if (len_orig > sockets[mux]->available()) { // TODO
|
||||
DBG("### Fewer characters received than expected: ", sockets[mux]->available(), " vs ", len_orig);
|
||||
}
|
||||
data = "";
|
||||
} else if (data.endsWith(GF("+TCPCLOSE:"))) {
|
||||
int mux = stream.readStringUntil(',').toInt();
|
||||
stream.readStringUntil('\n');
|
||||
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT) {
|
||||
sockets[mux]->sock_connected = false;
|
||||
}
|
||||
data = "";
|
||||
DBG("### Closed: ", mux);
|
||||
}
|
||||
}
|
||||
} while (millis() - startMillis < timeout);
|
||||
finish:
|
||||
if (!index) {
|
||||
data.trim();
|
||||
if (data.length()) {
|
||||
DBG("### Unhandled:", data);
|
||||
}
|
||||
data = "";
|
||||
}
|
||||
//DBG('<', index, '>');
|
||||
return index;
|
||||
}
|
||||
|
||||
uint8_t waitResponse(uint32_t timeout,
|
||||
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
|
||||
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
|
||||
{
|
||||
String data;
|
||||
return waitResponse(timeout, data, r1, r2, r3, r4, r5);
|
||||
}
|
||||
|
||||
uint8_t waitResponse(GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
|
||||
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
|
||||
{
|
||||
return waitResponse(1000, r1, r2, r3, r4, r5);
|
||||
}
|
||||
|
||||
public:
|
||||
Stream& stream;
|
||||
|
||||
protected:
|
||||
GsmClient* sockets[TINY_GSM_MUX_COUNT];
|
||||
};
|
||||
|
||||
#endif
|
||||
1011
arduino-cli/libraries/TinyGSM/src/TinyGsmClientSIM800.h
Normal file
1011
arduino-cli/libraries/TinyGSM/src/TinyGsmClientSIM800.h
Normal file
File diff suppressed because it is too large
Load Diff
155
arduino-cli/libraries/TinyGSM/src/TinyGsmClientSIM808.h
Normal file
155
arduino-cli/libraries/TinyGSM/src/TinyGsmClientSIM808.h
Normal file
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* @file TinyGsmClientSIM808.h
|
||||
* @author Volodymyr Shymanskyy
|
||||
* @license LGPL-3.0
|
||||
* @copyright Copyright (c) 2016 Volodymyr Shymanskyy
|
||||
* @date Nov 2016
|
||||
*/
|
||||
|
||||
#ifndef TinyGsmClientSIM808_h
|
||||
#define TinyGsmClientSIM808_h
|
||||
|
||||
#include <TinyGsmClientSIM800.h>
|
||||
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// Declaration and Definitio of the TinyGsmSim808 Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
class TinyGsmSim808: public TinyGsmSim800
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
TinyGsmSim808(Stream& stream)
|
||||
: TinyGsmSim800(stream)
|
||||
{}
|
||||
|
||||
/*
|
||||
* GPS location functions
|
||||
*/
|
||||
|
||||
// enable GPS
|
||||
bool enableGPS() {
|
||||
uint16_t state;
|
||||
|
||||
sendAT(GF("+CGNSPWR=1"));
|
||||
if (waitResponse() != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool disableGPS() {
|
||||
uint16_t state;
|
||||
|
||||
sendAT(GF("+CGNSPWR=0"));
|
||||
if (waitResponse() != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// get the RAW GPS output
|
||||
// works only with ans SIM808 V2
|
||||
String getGPSraw() {
|
||||
sendAT(GF("+CGNSINF"));
|
||||
if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 1) {
|
||||
return "";
|
||||
}
|
||||
String res = stream.readStringUntil('\n');
|
||||
waitResponse();
|
||||
res.trim();
|
||||
return res;
|
||||
}
|
||||
|
||||
// get GPS informations
|
||||
// works only with ans SIM808 V2
|
||||
bool getGPS(float *lat, float *lon, float *speed=0, int *alt=0, int *vsat=0, int *usat=0) {
|
||||
//String buffer = "";
|
||||
char chr_buffer[12];
|
||||
bool fix = false;
|
||||
|
||||
sendAT(GF("+CGNSINF"));
|
||||
if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
stream.readStringUntil(','); // mode
|
||||
if ( stream.readStringUntil(',').toInt() == 1 ) fix = true;
|
||||
stream.readStringUntil(','); //utctime
|
||||
*lat = stream.readStringUntil(',').toFloat(); //lat
|
||||
*lon = stream.readStringUntil(',').toFloat(); //lon
|
||||
if (alt != NULL) *alt = stream.readStringUntil(',').toFloat(); //lon
|
||||
if (speed != NULL) *speed = stream.readStringUntil(',').toFloat(); //speed
|
||||
stream.readStringUntil(',');
|
||||
stream.readStringUntil(',');
|
||||
stream.readStringUntil(',');
|
||||
stream.readStringUntil(',');
|
||||
stream.readStringUntil(',');
|
||||
stream.readStringUntil(',');
|
||||
stream.readStringUntil(',');
|
||||
if (vsat != NULL) *vsat = stream.readStringUntil(',').toInt(); //viewed satelites
|
||||
if (usat != NULL) *usat = stream.readStringUntil(',').toInt(); //used satelites
|
||||
stream.readStringUntil('\n');
|
||||
|
||||
waitResponse();
|
||||
|
||||
return fix;
|
||||
}
|
||||
|
||||
// get GPS time
|
||||
// works only with SIM808 V2
|
||||
bool getGPSTime(int *year, int *month, int *day, int *hour, int *minute, int *second) {
|
||||
bool fix = false;
|
||||
char chr_buffer[12];
|
||||
sendAT(GF("+CGNSINF"));
|
||||
if (waitResponse(GF(GSM_NL "+CGNSINF:")) != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
String buffer = stream.readStringUntil(',');
|
||||
buffer.toCharArray(chr_buffer, sizeof(chr_buffer));
|
||||
switch (i) {
|
||||
case 0:
|
||||
//mode
|
||||
break;
|
||||
case 1:
|
||||
//fixstatus
|
||||
if ( buffer.toInt() == 1 ) {
|
||||
fix = buffer.toInt();
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
*year = buffer.substring(0,4).toInt();
|
||||
*month = buffer.substring(4,6).toInt();
|
||||
*day = buffer.substring(6,8).toInt();
|
||||
*hour = buffer.substring(8,10).toInt();
|
||||
*minute = buffer.substring(10,12).toInt();
|
||||
*second = buffer.substring(12,14).toInt();
|
||||
break;
|
||||
|
||||
default:
|
||||
// if nothing else matches, do the default
|
||||
// default is optional
|
||||
break;
|
||||
}
|
||||
}
|
||||
String res = stream.readStringUntil('\n');
|
||||
waitResponse();
|
||||
|
||||
if (fix) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
807
arduino-cli/libraries/TinyGSM/src/TinyGsmClientUBLOX.h
Normal file
807
arduino-cli/libraries/TinyGSM/src/TinyGsmClientUBLOX.h
Normal file
@@ -0,0 +1,807 @@
|
||||
/**
|
||||
* @file TinyGsmClientUBLOX.h
|
||||
* @author Volodymyr Shymanskyy
|
||||
* @license LGPL-3.0
|
||||
* @copyright Copyright (c) 2016 Volodymyr Shymanskyy
|
||||
* @date Nov 2016
|
||||
*/
|
||||
|
||||
#ifndef TinyGsmClientUBLOX_h
|
||||
#define TinyGsmClientUBLOX_h
|
||||
|
||||
//#define TINY_GSM_DEBUG Serial
|
||||
|
||||
#if !defined(TINY_GSM_RX_BUFFER)
|
||||
#define TINY_GSM_RX_BUFFER 64
|
||||
#endif
|
||||
|
||||
#define TINY_GSM_MUX_COUNT 5
|
||||
|
||||
#include <TinyGsmCommon.h>
|
||||
|
||||
#define GSM_NL "\r\n"
|
||||
static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL;
|
||||
static const char GSM_ERROR[] TINY_GSM_PROGMEM = "ERROR" GSM_NL;
|
||||
static const char GSM_CME_ERROR[] TINY_GSM_PROGMEM = GSM_NL "+CME ERROR:";
|
||||
|
||||
enum SimStatus {
|
||||
SIM_ERROR = 0,
|
||||
SIM_READY = 1,
|
||||
SIM_LOCKED = 2,
|
||||
};
|
||||
|
||||
enum RegStatus {
|
||||
REG_UNREGISTERED = 0,
|
||||
REG_SEARCHING = 2,
|
||||
REG_DENIED = 3,
|
||||
REG_OK_HOME = 1,
|
||||
REG_OK_ROAMING = 5,
|
||||
REG_UNKNOWN = 4,
|
||||
};
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// Declaration of the TinyGsmUBLOX Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
class TinyGsmUBLOX
|
||||
{
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The UBLOX Internal Client Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
|
||||
public:
|
||||
|
||||
class GsmClient : public Client
|
||||
{
|
||||
friend class TinyGsmUBLOX;
|
||||
typedef TinyGsmFifo<uint8_t, TINY_GSM_RX_BUFFER> RxFifo;
|
||||
|
||||
public:
|
||||
GsmClient() {}
|
||||
|
||||
GsmClient(TinyGsmUBLOX& modem, uint8_t mux = 1) {
|
||||
init(&modem, mux);
|
||||
}
|
||||
|
||||
bool init(TinyGsmUBLOX* modem, uint8_t mux = 1) {
|
||||
this->at = modem;
|
||||
this->mux = mux;
|
||||
sock_available = 0;
|
||||
sock_connected = false;
|
||||
got_data = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
virtual int connect(const char *host, uint16_t port) {
|
||||
stop();
|
||||
TINY_GSM_YIELD();
|
||||
rx.clear();
|
||||
sock_connected = at->modemConnect(host, port, &mux);
|
||||
at->sockets[mux] = this;
|
||||
return sock_connected;
|
||||
}
|
||||
|
||||
virtual int connect(IPAddress ip, uint16_t port) {
|
||||
String host; host.reserve(16);
|
||||
host += ip[0];
|
||||
host += ".";
|
||||
host += ip[1];
|
||||
host += ".";
|
||||
host += ip[2];
|
||||
host += ".";
|
||||
host += ip[3];
|
||||
return connect(host.c_str(), port);
|
||||
}
|
||||
|
||||
virtual void stop() {
|
||||
TINY_GSM_YIELD();
|
||||
at->sendAT(GF("+USOCL="), mux);
|
||||
sock_connected = false;
|
||||
at->waitResponse();
|
||||
rx.clear();
|
||||
}
|
||||
|
||||
virtual size_t write(const uint8_t *buf, size_t size) {
|
||||
TINY_GSM_YIELD();
|
||||
at->maintain();
|
||||
return at->modemSend(buf, size, mux);
|
||||
}
|
||||
|
||||
virtual size_t write(uint8_t c) {
|
||||
return write(&c, 1);
|
||||
}
|
||||
|
||||
virtual size_t write(const char *str) {
|
||||
if (str == NULL) return 0;
|
||||
return write((const uint8_t *)str, strlen(str));
|
||||
}
|
||||
|
||||
virtual int available() {
|
||||
TINY_GSM_YIELD();
|
||||
if (!rx.size() && sock_connected) {
|
||||
at->maintain();
|
||||
}
|
||||
return rx.size() + sock_available;
|
||||
}
|
||||
|
||||
virtual int read(uint8_t *buf, size_t size) {
|
||||
TINY_GSM_YIELD();
|
||||
at->maintain();
|
||||
size_t cnt = 0;
|
||||
while (cnt < size) {
|
||||
size_t chunk = TinyGsmMin(size-cnt, rx.size());
|
||||
if (chunk > 0) {
|
||||
rx.get(buf, chunk);
|
||||
buf += chunk;
|
||||
cnt += chunk;
|
||||
continue;
|
||||
}
|
||||
// TODO: Read directly into user buffer?
|
||||
at->maintain();
|
||||
if (sock_available > 0) {
|
||||
sock_available -= at->modemRead(TinyGsmMin((uint16_t)rx.free(), sock_available), mux);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
virtual int read() {
|
||||
uint8_t c;
|
||||
if (read(&c, 1) == 1) {
|
||||
return c;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
virtual int peek() { return -1; } //TODO
|
||||
virtual void flush() { at->stream.flush(); }
|
||||
|
||||
virtual uint8_t connected() {
|
||||
if (available()) {
|
||||
return true;
|
||||
}
|
||||
return sock_connected;
|
||||
}
|
||||
virtual operator bool() { return connected(); }
|
||||
|
||||
/*
|
||||
* Extended API
|
||||
*/
|
||||
|
||||
String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
private:
|
||||
TinyGsmUBLOX* at;
|
||||
uint8_t mux;
|
||||
uint16_t sock_available;
|
||||
bool sock_connected;
|
||||
bool got_data;
|
||||
RxFifo rx;
|
||||
};
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The Secure UBLOX Client Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
|
||||
class GsmClientSecure : public GsmClient
|
||||
{
|
||||
public:
|
||||
GsmClientSecure() {}
|
||||
|
||||
GsmClientSecure(TinyGsmUBLOX& modem, uint8_t mux = 1)
|
||||
: GsmClient(modem, mux)
|
||||
{}
|
||||
|
||||
public:
|
||||
virtual int connect(const char *host, uint16_t port) {
|
||||
stop();
|
||||
TINY_GSM_YIELD();
|
||||
rx.clear();
|
||||
sock_connected = at->modemConnect(host, port, &mux, true);
|
||||
at->sockets[mux] = this;
|
||||
return sock_connected;
|
||||
}
|
||||
};
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The UBLOX Modem Functions
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
public:
|
||||
|
||||
#ifdef GSM_DEFAULT_STREAM
|
||||
TinyGsmUBLOX(Stream& stream = GSM_DEFAULT_STREAM)
|
||||
#else
|
||||
TinyGsmUBLOX(Stream& stream)
|
||||
#endif
|
||||
: stream(stream)
|
||||
{
|
||||
memset(sockets, 0, sizeof(sockets));
|
||||
}
|
||||
|
||||
/*
|
||||
* Basic functions
|
||||
*/
|
||||
bool begin(const char* pin = NULL) {
|
||||
return init(pin);
|
||||
}
|
||||
|
||||
bool init(const char* pin = NULL) {
|
||||
if (!testAT()) {
|
||||
return false;
|
||||
}
|
||||
sendAT(GF("E0")); // Echo Off
|
||||
if (waitResponse() != 1) {
|
||||
return false;
|
||||
}
|
||||
int ret = getSimStatus();
|
||||
if (ret != SIM_READY && pin != NULL && strlen(pin) > 0) {
|
||||
simUnlock(pin);
|
||||
}
|
||||
return (getSimStatus() == SIM_READY);
|
||||
}
|
||||
|
||||
void setBaud(unsigned long baud) {
|
||||
sendAT(GF("+IPR="), baud);
|
||||
}
|
||||
|
||||
bool testAT(unsigned long timeout = 10000L) {
|
||||
for (unsigned long start = millis(); millis() - start < timeout; ) {
|
||||
sendAT(GF(""));
|
||||
if (waitResponse(200) == 1) {
|
||||
delay(100);
|
||||
return true;
|
||||
}
|
||||
delay(100);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void maintain() {
|
||||
for (int mux = 0; mux < TINY_GSM_MUX_COUNT; mux++) {
|
||||
GsmClient* sock = sockets[mux];
|
||||
if (sock && sock->got_data) {
|
||||
sock->got_data = false;
|
||||
sock->sock_available = modemGetAvailable(mux);
|
||||
}
|
||||
}
|
||||
while (stream.available()) {
|
||||
waitResponse(10, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
bool factoryDefault() {
|
||||
sendAT(GF("+UFACTORY=0,1")); // Factory + Reset + Echo Off
|
||||
waitResponse();
|
||||
sendAT(GF("+CFUN=16")); // Auto-baud
|
||||
return waitResponse() == 1;
|
||||
}
|
||||
|
||||
String getModemInfo() {
|
||||
sendAT(GF("I"));
|
||||
String res;
|
||||
if (waitResponse(1000L, res) != 1) {
|
||||
return "";
|
||||
}
|
||||
res.replace(GSM_NL "OK" GSM_NL, "");
|
||||
res.replace(GSM_NL, " ");
|
||||
res.trim();
|
||||
return res;
|
||||
}
|
||||
|
||||
bool hasSSL() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Power functions
|
||||
*/
|
||||
|
||||
bool restart() {
|
||||
if (!testAT()) {
|
||||
return false;
|
||||
}
|
||||
sendAT(GF("+CFUN=16"));
|
||||
if (waitResponse(10000L) != 1) {
|
||||
return false;
|
||||
}
|
||||
delay(3000);
|
||||
return init();
|
||||
}
|
||||
|
||||
bool poweroff() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
bool radioOff() {
|
||||
sendAT(GF("+CFUN=0"));
|
||||
if (waitResponse(10000L) != 1) {
|
||||
return false;
|
||||
}
|
||||
delay(3000);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool sleepEnable(bool enable = true) TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
/*
|
||||
* SIM card functions
|
||||
*/
|
||||
|
||||
bool simUnlock(const char *pin) {
|
||||
sendAT(GF("+CPIN=\""), pin, GF("\""));
|
||||
return waitResponse() == 1;
|
||||
}
|
||||
|
||||
String getSimCCID() {
|
||||
sendAT(GF("+CCID"));
|
||||
if (waitResponse(GF(GSM_NL "+CCID:")) != 1) {
|
||||
return "";
|
||||
}
|
||||
String res = stream.readStringUntil('\n');
|
||||
waitResponse();
|
||||
res.trim();
|
||||
return res;
|
||||
}
|
||||
|
||||
String getIMEI() {
|
||||
sendAT(GF("+CGSN"));
|
||||
if (waitResponse(GF(GSM_NL)) != 1) {
|
||||
return "";
|
||||
}
|
||||
String res = stream.readStringUntil('\n');
|
||||
waitResponse();
|
||||
res.trim();
|
||||
return res;
|
||||
}
|
||||
|
||||
SimStatus getSimStatus(unsigned long timeout = 10000L) {
|
||||
for (unsigned long start = millis(); millis() - start < timeout; ) {
|
||||
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"));
|
||||
waitResponse();
|
||||
switch (status) {
|
||||
case 2:
|
||||
case 3: return SIM_LOCKED;
|
||||
case 1: return SIM_READY;
|
||||
default: return SIM_ERROR;
|
||||
}
|
||||
}
|
||||
return SIM_ERROR;
|
||||
}
|
||||
|
||||
RegStatus getRegistrationStatus() {
|
||||
sendAT(GF("+CGREG?"));
|
||||
if (waitResponse(GF(GSM_NL "+CGREG:")) != 1) {
|
||||
return REG_UNKNOWN;
|
||||
}
|
||||
streamSkipUntil(','); // Skip format (0)
|
||||
int status = stream.readStringUntil('\n').toInt();
|
||||
waitResponse();
|
||||
return (RegStatus)status;
|
||||
}
|
||||
|
||||
String getOperator() {
|
||||
sendAT(GF("+COPS?"));
|
||||
if (waitResponse(GF(GSM_NL "+COPS:")) != 1) {
|
||||
return "";
|
||||
}
|
||||
streamSkipUntil('"'); // Skip mode and format
|
||||
String res = stream.readStringUntil('"');
|
||||
waitResponse();
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic network functions
|
||||
*/
|
||||
|
||||
int getSignalQuality() {
|
||||
sendAT(GF("+CSQ"));
|
||||
if (waitResponse(GF(GSM_NL "+CSQ:")) != 1) {
|
||||
return 99;
|
||||
}
|
||||
int res = stream.readStringUntil(',').toInt();
|
||||
waitResponse();
|
||||
return res;
|
||||
}
|
||||
|
||||
bool isNetworkConnected() {
|
||||
RegStatus s = getRegistrationStatus();
|
||||
return (s == REG_OK_HOME || s == REG_OK_ROAMING);
|
||||
}
|
||||
|
||||
bool waitForNetwork(unsigned long timeout = 60000L) {
|
||||
for (unsigned long start = millis(); millis() - start < timeout; ) {
|
||||
if (isNetworkConnected()) {
|
||||
return true;
|
||||
}
|
||||
delay(250);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* WiFi functions
|
||||
*/
|
||||
|
||||
/*
|
||||
* GPRS functions
|
||||
*/
|
||||
bool gprsConnect(const char* apn, const char* user = NULL, const char* pwd = NULL) {
|
||||
gprsDisconnect();
|
||||
|
||||
sendAT(GF("+CGATT=1"));
|
||||
if (waitResponse(60000L) != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sendAT(GF("+UPSD=0,1,\""), apn, '"');
|
||||
waitResponse();
|
||||
|
||||
if (user && strlen(user) > 0) {
|
||||
sendAT(GF("+UPSD=0,2,\""), user, '"');
|
||||
waitResponse();
|
||||
}
|
||||
if (pwd && strlen(pwd) > 0) {
|
||||
sendAT(GF("+UPSD=0,3,\""), pwd, '"');
|
||||
waitResponse();
|
||||
}
|
||||
|
||||
sendAT(GF("+UPSD=0,7,\"0.0.0.0\"")); // Dynamic IP
|
||||
waitResponse();
|
||||
|
||||
sendAT(GF("+UPSDA=0,3"));
|
||||
if (waitResponse(60000L) != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Open a GPRS context
|
||||
sendAT(GF("+UPSND=0,8"));
|
||||
if (waitResponse(GF(",8,1")) != 1) {
|
||||
return false;
|
||||
}
|
||||
waitResponse();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool gprsDisconnect() {
|
||||
sendAT(GF("+UPSDA=0,4"));
|
||||
if (waitResponse(60000L) != 1)
|
||||
return false;
|
||||
|
||||
sendAT(GF("+CGATT=0"));
|
||||
if (waitResponse(60000L) != 1)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isGprsConnected() {
|
||||
sendAT(GF("+CGATT?"));
|
||||
if (waitResponse(GF(GSM_NL "+CGATT:")) != 1) {
|
||||
return false;
|
||||
}
|
||||
int res = stream.readStringUntil('\n').toInt();
|
||||
waitResponse();
|
||||
if (res != 1)
|
||||
return false;
|
||||
|
||||
return localIP() != 0;
|
||||
}
|
||||
|
||||
String getLocalIP() {
|
||||
sendAT(GF("+UPSND=0,0"));
|
||||
if (waitResponse(GF(GSM_NL "+UPSND:")) != 1) {
|
||||
return "";
|
||||
}
|
||||
streamSkipUntil(','); // Skip PSD profile
|
||||
streamSkipUntil('\"'); // Skip request type
|
||||
String res = stream.readStringUntil('\"');
|
||||
if (waitResponse() != 1) {
|
||||
return "";
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
IPAddress localIP() {
|
||||
return TinyGsmIpFromString(getLocalIP());
|
||||
}
|
||||
|
||||
/*
|
||||
* Phone Call functions
|
||||
*/
|
||||
|
||||
bool setGsmBusy(bool busy = true) TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||
|
||||
bool callAnswer() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
bool callNumber(const String& number) TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
bool callHangup() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
/*
|
||||
* Messaging functions
|
||||
*/
|
||||
|
||||
String sendUSSD(const String& code) TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
bool sendSMS(const String& number, const String& text) {
|
||||
sendAT(GF("+CSCS=\"GSM\"")); // Set GSM default alphabet
|
||||
waitResponse();
|
||||
sendAT(GF("+CMGF=1")); // Set preferred message format to text mode
|
||||
waitResponse();
|
||||
sendAT(GF("+CMGS=\""), number, GF("\"")); // set the phone number
|
||||
if (waitResponse(GF(">")) != 1) {
|
||||
return false;
|
||||
}
|
||||
stream.print(text); // Actually send the message
|
||||
stream.write((char)0x1A);
|
||||
stream.flush();
|
||||
return waitResponse(60000L) == 1;
|
||||
}
|
||||
|
||||
bool sendSMS_UTF16(const String& number, const void* text, size_t len) TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
|
||||
/*
|
||||
* Location functions
|
||||
*/
|
||||
|
||||
String getGsmLocation() {
|
||||
sendAT(GF("+ULOC=2,3,0,120,1"));
|
||||
if (waitResponse(30000L, GF(GSM_NL "+UULOC:")) != 1) {
|
||||
return "";
|
||||
}
|
||||
String res = stream.readStringUntil('\n');
|
||||
waitResponse();
|
||||
res.trim();
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Battery functions
|
||||
*/
|
||||
uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||
|
||||
int getBattPercent() {
|
||||
sendAT(GF("+CIND?"));
|
||||
if (waitResponse(GF(GSM_NL "+CIND:")) != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int res = stream.readStringUntil(',').toInt();
|
||||
waitResponse();
|
||||
return res;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
bool modemConnect(const char* host, uint16_t port, uint8_t* mux, bool ssl = false) {
|
||||
sendAT(GF("+USOCR=6"));
|
||||
if (waitResponse(GF(GSM_NL "+USOCR:")) != 1) {
|
||||
return false;
|
||||
}
|
||||
*mux = stream.readStringUntil('\n').toInt();
|
||||
waitResponse();
|
||||
|
||||
if (ssl) {
|
||||
sendAT(GF("+USOSEC="), *mux, ",1");
|
||||
waitResponse();
|
||||
}
|
||||
|
||||
// Enable NODELAY
|
||||
sendAT(GF("+USOSO="), *mux, GF(",6,1,1"));
|
||||
waitResponse();
|
||||
|
||||
// Enable KEEPALIVE, 30 sec
|
||||
//sendAT(GF("+USOSO="), *mux, GF(",6,2,30000"));
|
||||
//waitResponse();
|
||||
|
||||
sendAT(GF("+USOCO="), *mux, ",\"", host, "\",", port);
|
||||
int rsp = waitResponse(75000L);
|
||||
return (1 == rsp);
|
||||
}
|
||||
|
||||
int modemSend(const void* buff, size_t len, uint8_t mux) {
|
||||
sendAT(GF("+USOWR="), mux, ',', len);
|
||||
if (waitResponse(GF("@")) != 1) {
|
||||
return 0;
|
||||
}
|
||||
// 50ms delay, see AT manual section 25.10.4
|
||||
delay(50);
|
||||
stream.write((uint8_t*)buff, len);
|
||||
stream.flush();
|
||||
if (waitResponse(GF(GSM_NL "+USOWR:")) != 1) {
|
||||
return 0;
|
||||
}
|
||||
streamSkipUntil(','); // Skip mux
|
||||
int sent = stream.readStringUntil('\n').toInt();
|
||||
waitResponse();
|
||||
return sent;
|
||||
}
|
||||
|
||||
size_t modemRead(size_t size, uint8_t mux) {
|
||||
sendAT(GF("+USORD="), mux, ',', size);
|
||||
if (waitResponse(GF(GSM_NL "+USORD:")) != 1) {
|
||||
return 0;
|
||||
}
|
||||
streamSkipUntil(','); // Skip mux
|
||||
size_t len = stream.readStringUntil(',').toInt();
|
||||
streamSkipUntil('\"');
|
||||
|
||||
for (size_t i=0; i<len; i++) {
|
||||
while (!stream.available()) { TINY_GSM_YIELD(); }
|
||||
char c = stream.read();
|
||||
sockets[mux]->rx.put(c);
|
||||
}
|
||||
streamSkipUntil('\"');
|
||||
waitResponse();
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t modemGetAvailable(uint8_t mux) {
|
||||
sendAT(GF("+USORD="), mux, ",0");
|
||||
size_t result = 0;
|
||||
if (waitResponse(GF(GSM_NL "+USORD:")) == 1) {
|
||||
streamSkipUntil(','); // Skip mux
|
||||
result = stream.readStringUntil('\n').toInt();
|
||||
waitResponse();
|
||||
}
|
||||
if (!result) {
|
||||
sockets[mux]->sock_connected = modemGetConnected(mux);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool modemGetConnected(uint8_t mux) {
|
||||
sendAT(GF("+USOCTL="), mux, ",10");
|
||||
if (waitResponse(GF(GSM_NL "+USOCTL:")) != 1)
|
||||
return false;
|
||||
|
||||
streamSkipUntil(','); // Skip mux
|
||||
streamSkipUntil(','); // Skip type
|
||||
int result = stream.readStringUntil('\n').toInt();
|
||||
waitResponse();
|
||||
return result != 0;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/* Utilities */
|
||||
|
||||
template<typename T>
|
||||
void streamWrite(T last) {
|
||||
stream.print(last);
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
void streamWrite(T head, Args... tail) {
|
||||
stream.print(head);
|
||||
streamWrite(tail...);
|
||||
}
|
||||
|
||||
bool streamSkipUntil(char c) {
|
||||
const unsigned long timeout = 1000L;
|
||||
unsigned long startMillis = millis();
|
||||
while (millis() - startMillis < timeout) {
|
||||
while (millis() - startMillis < timeout && !stream.available()) {
|
||||
TINY_GSM_YIELD();
|
||||
}
|
||||
if (stream.read() == c)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void sendAT(Args... cmd) {
|
||||
streamWrite("AT", cmd..., GSM_NL);
|
||||
stream.flush();
|
||||
TINY_GSM_YIELD();
|
||||
//DBG("### AT:", cmd...);
|
||||
}
|
||||
|
||||
// TODO: Optimize this!
|
||||
uint8_t waitResponse(uint32_t timeout, String& data,
|
||||
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();
|
||||
String r4s(r4); r4s.trim();
|
||||
String r5s(r5); r5s.trim();
|
||||
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
|
||||
data.reserve(64);
|
||||
int index = 0;
|
||||
unsigned long startMillis = millis();
|
||||
do {
|
||||
TINY_GSM_YIELD();
|
||||
while (stream.available() > 0) {
|
||||
int a = stream.read();
|
||||
if (a < 0) continue;
|
||||
data += (char)a;
|
||||
if (r1 && data.endsWith(r1)) {
|
||||
index = 1;
|
||||
goto finish;
|
||||
} else if (r2 && data.endsWith(r2)) {
|
||||
index = 2;
|
||||
goto finish;
|
||||
} else if (r3 && data.endsWith(r3)) {
|
||||
index = 3;
|
||||
goto finish;
|
||||
} else if (r4 && data.endsWith(r4)) {
|
||||
index = 4;
|
||||
goto finish;
|
||||
} else if (r5 && data.endsWith(r5)) {
|
||||
index = 5;
|
||||
goto finish;
|
||||
} else if (data.endsWith(GF(GSM_NL "+UUSORD:"))) {
|
||||
int mux = stream.readStringUntil(',').toInt();
|
||||
streamSkipUntil('\n');
|
||||
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
|
||||
sockets[mux]->got_data = true;
|
||||
}
|
||||
data = "";
|
||||
DBG("### Got Data:", mux);
|
||||
} else if (data.endsWith(GF(GSM_NL "+UUSOCL:"))) {
|
||||
int mux = stream.readStringUntil('\n').toInt();
|
||||
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
|
||||
sockets[mux]->sock_connected = false;
|
||||
}
|
||||
data = "";
|
||||
DBG("### Closed:", mux);
|
||||
}
|
||||
}
|
||||
} while (millis() - startMillis < timeout);
|
||||
finish:
|
||||
if (!index) {
|
||||
data.trim();
|
||||
if (data.length()) {
|
||||
DBG("### Unhandled:", data);
|
||||
}
|
||||
data = "";
|
||||
}
|
||||
//DBG('<', index, '>');
|
||||
return index;
|
||||
}
|
||||
|
||||
uint8_t waitResponse(uint32_t timeout,
|
||||
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, 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)
|
||||
{
|
||||
return waitResponse(1000, r1, r2, r3, r4, r5);
|
||||
}
|
||||
|
||||
public:
|
||||
Stream& stream;
|
||||
|
||||
protected:
|
||||
GsmClient* sockets[TINY_GSM_MUX_COUNT];
|
||||
};
|
||||
|
||||
#endif
|
||||
882
arduino-cli/libraries/TinyGSM/src/TinyGsmClientXBee.h
Normal file
882
arduino-cli/libraries/TinyGSM/src/TinyGsmClientXBee.h
Normal file
@@ -0,0 +1,882 @@
|
||||
/**
|
||||
* @file TinyGsmClientXBee.h
|
||||
* @author Volodymyr Shymanskyy
|
||||
* @license LGPL-3.0
|
||||
* @copyright Copyright (c) 2016 Volodymyr Shymanskyy
|
||||
* @date Nov 2016
|
||||
*/
|
||||
|
||||
#ifndef TinyGsmClientXBee_h
|
||||
#define TinyGsmClientXBee_h
|
||||
|
||||
//#define TINY_GSM_DEBUG Serial
|
||||
|
||||
|
||||
#define TINY_GSM_MUX_COUNT 1 // Multi-plexing isn't supported using command mode
|
||||
|
||||
#include <TinyGsmCommon.h>
|
||||
|
||||
#define GSM_NL "\r"
|
||||
static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL;
|
||||
static const char GSM_ERROR[] TINY_GSM_PROGMEM = "ERROR" GSM_NL;
|
||||
|
||||
enum SimStatus {
|
||||
SIM_ERROR = 0,
|
||||
SIM_READY = 1,
|
||||
SIM_LOCKED = 2,
|
||||
};
|
||||
|
||||
enum RegStatus {
|
||||
REG_OK = 0,
|
||||
REG_UNREGISTERED = 1,
|
||||
REG_SEARCHING = 2,
|
||||
REG_DENIED = 3,
|
||||
REG_UNKNOWN = 4,
|
||||
};
|
||||
|
||||
// These are responses to the HS command to get "hardware series"
|
||||
enum XBeeType {
|
||||
XBEE_S6B_WIFI = 0x601, // Digi XBee® Wi-Fi
|
||||
XBEE_LTE1_VZN = 0xB01, // Digi XBee® Cellular LTE Cat 1
|
||||
XBEE_3G = 0xB02, // Digi XBee® Cellular 3G
|
||||
XBEE3_LTE1_ATT = 1, // Digi XBee3™ Cellular LTE CAT 1 -- HS unknown to SRGD
|
||||
XBEE3_LTEM_ATT = 2, // Digi XBee3™ Cellular LTE-M -- HS unknown to SRGD
|
||||
XBEE3_LTENB = 3, // Digi XBee3™ Cellular NB-IoT -- HS unknown to SRGD
|
||||
};
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// Declaration of the TinyGsmXBee Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
class TinyGsmXBee
|
||||
{
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The XBee Internal Client Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
|
||||
public:
|
||||
|
||||
class GsmClient : public Client
|
||||
{
|
||||
friend class TinyGsmXBee;
|
||||
|
||||
public:
|
||||
GsmClient() {}
|
||||
|
||||
GsmClient(TinyGsmXBee& modem, uint8_t mux = 0) {
|
||||
init(&modem, mux);
|
||||
}
|
||||
|
||||
bool init(TinyGsmXBee* modem, uint8_t mux = 0) {
|
||||
this->at = modem;
|
||||
this->mux = mux;
|
||||
sock_connected = false;
|
||||
|
||||
at->sockets[mux] = this;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
virtual int connect(const char *host, uint16_t port) {
|
||||
at->streamClear(); // Empty anything remaining in the buffer;
|
||||
bool sock_connected = false;
|
||||
if (at->commandMode()) { // Don't try if we didn't successfully get into command mode
|
||||
sock_connected = at->modemConnect(host, port, mux, false);
|
||||
at->writeChanges();
|
||||
at->exitCommand();
|
||||
}
|
||||
at->streamClear(); // Empty anything remaining in the buffer;
|
||||
return sock_connected;
|
||||
}
|
||||
|
||||
virtual int connect(IPAddress ip, uint16_t port) {
|
||||
at->streamClear(); // Empty anything remaining in the buffer;
|
||||
bool sock_connected = false;
|
||||
if (at->commandMode()) { // Don't try if we didn't successfully get into command mode
|
||||
sock_connected = at->modemConnect(ip, port, mux, false);
|
||||
at->writeChanges();
|
||||
at->exitCommand();
|
||||
}
|
||||
at->streamClear(); // Empty anything remaining in the buffer;
|
||||
return sock_connected;
|
||||
}
|
||||
|
||||
// This is a hack to shut the socket by setting the timeout to zero and
|
||||
// then sending an empty line to the server.
|
||||
virtual void stop() {
|
||||
at->streamClear(); // Empty anything remaining in the buffer;
|
||||
at->commandMode();
|
||||
at->sendAT(GF("TM0")); // Set socket timeout to 0;
|
||||
at->waitResponse();
|
||||
at->writeChanges();
|
||||
at->exitCommand();
|
||||
at->modemSend("", 1, mux);
|
||||
at->commandMode();
|
||||
at->sendAT(GF("TM64")); // Set socket timeout back to 10 seconds;
|
||||
at->waitResponse();
|
||||
at->writeChanges();
|
||||
at->exitCommand();
|
||||
at->streamClear(); // Empty anything remaining in the buffer;
|
||||
sock_connected = false;
|
||||
}
|
||||
|
||||
virtual size_t write(const uint8_t *buf, size_t size) {
|
||||
TINY_GSM_YIELD();
|
||||
return at->modemSend(buf, size, mux);
|
||||
}
|
||||
|
||||
virtual size_t write(uint8_t c) {
|
||||
return write(&c, 1);
|
||||
}
|
||||
|
||||
virtual size_t write(const char *str) {
|
||||
if (str == NULL) return 0;
|
||||
return write((const uint8_t *)str, strlen(str));
|
||||
}
|
||||
|
||||
virtual int available() {
|
||||
TINY_GSM_YIELD();
|
||||
return at->stream.available();
|
||||
}
|
||||
|
||||
virtual int read(uint8_t *buf, size_t size) {
|
||||
TINY_GSM_YIELD();
|
||||
return at->stream.readBytes((char*)buf, size);
|
||||
}
|
||||
|
||||
virtual int read() {
|
||||
TINY_GSM_YIELD();
|
||||
return at->stream.read();
|
||||
}
|
||||
|
||||
virtual int peek() { return at->stream.peek(); }
|
||||
virtual void flush() { at->stream.flush(); }
|
||||
|
||||
virtual uint8_t connected() {
|
||||
if (available()) {
|
||||
return true;
|
||||
}
|
||||
return sock_connected;
|
||||
}
|
||||
virtual operator bool() { return connected(); }
|
||||
|
||||
/*
|
||||
* Extended API
|
||||
*/
|
||||
|
||||
String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
private:
|
||||
TinyGsmXBee* at;
|
||||
uint8_t mux;
|
||||
bool sock_connected;
|
||||
};
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The Secure XBee Client Class
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
|
||||
class GsmClientSecure : public GsmClient
|
||||
{
|
||||
public:
|
||||
GsmClientSecure() {}
|
||||
|
||||
GsmClientSecure(TinyGsmXBee& modem, uint8_t mux = 1)
|
||||
: GsmClient(modem, mux)
|
||||
{}
|
||||
|
||||
public:
|
||||
virtual int connect(const char *host, uint16_t port) {
|
||||
at->streamClear(); // Empty anything remaining in the buffer;
|
||||
bool sock_connected = false;
|
||||
if (at->commandMode()) { // Don't try if we didn't successfully get into command mode
|
||||
sock_connected = at->modemConnect(host, port, mux, true);
|
||||
at->writeChanges();
|
||||
at->exitCommand();
|
||||
}
|
||||
at->streamClear(); // Empty anything remaining in the buffer;
|
||||
return sock_connected;
|
||||
}
|
||||
|
||||
virtual int connect(IPAddress ip, uint16_t port) {
|
||||
at->streamClear(); // Empty anything remaining in the buffer;
|
||||
bool sock_connected = false;
|
||||
if (at->commandMode()) { // Don't try if we didn't successfully get into command mode
|
||||
sock_connected = at->modemConnect(ip, port, mux, true);
|
||||
at->writeChanges();
|
||||
at->exitCommand();
|
||||
}
|
||||
at->streamClear(); // Empty anything remaining in the buffer;
|
||||
return sock_connected;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
// The XBee Modem Functions
|
||||
//============================================================================//
|
||||
//============================================================================//
|
||||
|
||||
public:
|
||||
|
||||
#ifdef GSM_DEFAULT_STREAM
|
||||
TinyGsmXBee(Stream& stream = GSM_DEFAULT_STREAM)
|
||||
#else
|
||||
TinyGsmXBee(Stream& stream)
|
||||
#endif
|
||||
: stream(stream)
|
||||
{}
|
||||
|
||||
/*
|
||||
* Basic functions
|
||||
*/
|
||||
bool begin() {
|
||||
return init();
|
||||
}
|
||||
|
||||
bool init() {
|
||||
guardTime = 1100; // Start with a default guard time of 1 second
|
||||
|
||||
if (!commandMode(10)) return false; // Try up to 10 times for the init
|
||||
|
||||
sendAT(GF("AP0")); // Put in transparent mode
|
||||
bool ret_val = waitResponse() == 1;
|
||||
ret_val &= writeChanges();
|
||||
|
||||
sendAT(GF("GT64")); // shorten the guard time to 100ms
|
||||
ret_val &= waitResponse();
|
||||
ret_val &= writeChanges();
|
||||
if (ret_val) guardTime = 125;
|
||||
|
||||
sendAT(GF("HS")); // Get the "Hardware Series";
|
||||
String res = readResponse();
|
||||
char buf[4] = {0,}; // Set up buffer for response
|
||||
res.toCharArray(buf, 4);
|
||||
int intRes = strtol(buf, 0, 16);
|
||||
beeType = (XBeeType)intRes;
|
||||
|
||||
exitCommand();
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
void setBaud(unsigned long baud) {
|
||||
if (!commandMode()) return;
|
||||
switch(baud)
|
||||
{
|
||||
case 2400: sendAT(GF("BD1")); break;
|
||||
case 4800: sendAT(GF("BD2")); break;
|
||||
case 9600: sendAT(GF("BD3")); break;
|
||||
case 19200: sendAT(GF("BD4")); break;
|
||||
case 38400: sendAT(GF("BD5")); break;
|
||||
case 57600: sendAT(GF("BD6")); break;
|
||||
case 115200: sendAT(GF("BD7")); break;
|
||||
case 230400: sendAT(GF("BD8")); break;
|
||||
case 460800: sendAT(GF("BD9")); break;
|
||||
case 921600: sendAT(GF("BDA")); break;
|
||||
default: {
|
||||
DBG(GF("Specified baud rate is unsupported! Setting to 9600 baud."));
|
||||
sendAT(GF("BD3")); // Set to default of 9600
|
||||
break;
|
||||
}
|
||||
}
|
||||
waitResponse();
|
||||
writeChanges();
|
||||
exitCommand();
|
||||
}
|
||||
|
||||
bool testAT(unsigned long timeout = 10000L) {
|
||||
for (unsigned long start = millis(); millis() - start < timeout; ) {
|
||||
if (commandMode())
|
||||
{
|
||||
sendAT();
|
||||
if (waitResponse(200) == 1) {
|
||||
return true;
|
||||
}
|
||||
exitCommand();
|
||||
}
|
||||
delay(100);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void maintain() {}
|
||||
|
||||
bool factoryDefault() {
|
||||
if (!commandMode()) return false; // Return immediately
|
||||
sendAT(GF("RE"));
|
||||
bool ret_val = waitResponse() == 1;
|
||||
ret_val &= writeChanges();
|
||||
exitCommand();
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
String getModemInfo() {
|
||||
String modemInf = "";
|
||||
if (!commandMode()) return modemInf; // Try up to 10 times for the init
|
||||
|
||||
sendAT(GF("HS")); // Get the "Hardware Series"
|
||||
modemInf += readResponse();
|
||||
|
||||
exitCommand();
|
||||
return modemInf;
|
||||
}
|
||||
|
||||
bool hasSSL() {
|
||||
if (beeType == XBEE_S6B_WIFI) return false;
|
||||
else return true;
|
||||
}
|
||||
|
||||
XBeeType getBeeType() {
|
||||
return beeType;
|
||||
}
|
||||
|
||||
String getBeeName() {
|
||||
switch (beeType){
|
||||
case XBEE_S6B_WIFI: return "Digi XBee® Wi-Fi";
|
||||
case XBEE_LTE1_VZN: return "Digi XBee® Cellular LTE Cat 1";
|
||||
case XBEE_3G: return "Digi XBee® Cellular 3G";
|
||||
case XBEE3_LTE1_ATT: return "Digi XBee3™ Cellular LTE CAT 1";
|
||||
case XBEE3_LTEM_ATT: return "Digi XBee3™ Cellular LTE-M";
|
||||
case XBEE3_LTENB: return "Digi XBee3™ Cellular NB-IoT";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Power functions
|
||||
*/
|
||||
|
||||
bool restart() {
|
||||
if (!commandMode()) return false; // Return immediately
|
||||
sendAT(GF("AM1")); // Digi suggests putting into airplane mode before restarting
|
||||
// This allows the sockets and connections to close cleanly
|
||||
writeChanges();
|
||||
if (waitResponse() != 1) goto fail;
|
||||
sendAT(GF("FR"));
|
||||
if (waitResponse() != 1) goto fail;
|
||||
|
||||
delay (2000); // Actually resets about 2 seconds later
|
||||
|
||||
// Wait until reboot complete and responds to command mode call again
|
||||
for (unsigned long start = millis(); millis() - start < 60000L; ) {
|
||||
if (commandMode(1)) {
|
||||
sendAT(GF("AM0")); // Turn off airplane mode
|
||||
writeChanges();
|
||||
exitCommand();
|
||||
delay(250); // wait a litle before trying again
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
|
||||
fail:
|
||||
exitCommand();
|
||||
return false;
|
||||
}
|
||||
|
||||
void setupPinSleep(bool maintainAssociation = false) {
|
||||
if (!commandMode()) return; // Return immediately
|
||||
sendAT(GF("SM"),1); // Pin sleep
|
||||
waitResponse();
|
||||
if (beeType == XBEE_S6B_WIFI && !maintainAssociation) {
|
||||
sendAT(GF("SO"),200); // For lowest power, dissassociated deep sleep
|
||||
waitResponse();
|
||||
}
|
||||
else if (!maintainAssociation){
|
||||
sendAT(GF("SO"),1); // For lowest power, dissassociated deep sleep
|
||||
// Not supported by all modules, will return "ERROR"
|
||||
waitResponse();
|
||||
}
|
||||
writeChanges();
|
||||
exitCommand();
|
||||
}
|
||||
|
||||
bool poweroff() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
bool radioOff() TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
bool sleepEnable(bool enable = true) TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
/*
|
||||
* SIM card functions
|
||||
*/
|
||||
|
||||
bool simUnlock(const char *pin) { // Not supported
|
||||
return false;
|
||||
}
|
||||
|
||||
String getSimCCID() {
|
||||
if (!commandMode()) return ""; // Return immediately
|
||||
sendAT(GF("S#"));
|
||||
String res = readResponse();
|
||||
exitCommand();
|
||||
return res;
|
||||
}
|
||||
|
||||
String getIMEI() {
|
||||
if (!commandMode()) return ""; // Return immediately
|
||||
sendAT(GF("IM"));
|
||||
String res = readResponse();
|
||||
exitCommand();
|
||||
return res;
|
||||
}
|
||||
|
||||
SimStatus getSimStatus(unsigned long timeout = 10000L) {
|
||||
return SIM_READY; // unsupported
|
||||
}
|
||||
|
||||
RegStatus getRegistrationStatus() {
|
||||
if (!commandMode()) return REG_UNKNOWN; // Return immediately
|
||||
|
||||
sendAT(GF("AI"));
|
||||
String res = readResponse();
|
||||
char buf[3] = {0,}; // Set up buffer for response
|
||||
res.toCharArray(buf, 3);
|
||||
int intRes = strtol(buf, 0, 16);
|
||||
RegStatus stat = REG_UNKNOWN;
|
||||
|
||||
switch (beeType){
|
||||
case XBEE_S6B_WIFI: {
|
||||
if(intRes == 0x00) // 0x00 Successfully joined an access point, established IP addresses and IP listening sockets
|
||||
stat = REG_OK;
|
||||
else if(intRes == 0x01) // 0x01 Wi-Fi transceiver initialization in progress.
|
||||
stat = REG_SEARCHING;
|
||||
else if(intRes == 0x02) // 0x02 Wi-Fi transceiver initialized, but not yet scanning for access point.
|
||||
stat = REG_SEARCHING;
|
||||
else if(intRes == 0x13) { // 0x13 Disconnecting from access point.
|
||||
restart(); // Restart the device; the S6B tends to get stuck "disconnecting"
|
||||
stat = REG_UNREGISTERED;
|
||||
}
|
||||
else if(intRes == 0x23) // 0x23 SSID not configured.
|
||||
stat = REG_UNREGISTERED;
|
||||
else if(intRes == 0x24) // 0x24 Encryption key invalid (either NULL or invalid length for WEP).
|
||||
stat = REG_DENIED;
|
||||
else if(intRes == 0x27) // 0x27 SSID was found, but join failed.
|
||||
stat = REG_DENIED;
|
||||
else if(intRes == 0x40) // 0x40 Waiting for WPA or WPA2 Authentication.
|
||||
stat = REG_SEARCHING;
|
||||
else if(intRes == 0x41) // 0x41 Device joined a network and is waiting for IP configuration to complete
|
||||
stat = REG_SEARCHING;
|
||||
else if(intRes == 0x42) // 0x42 Device is joined, IP is configured, and listening sockets are being set up.
|
||||
stat = REG_SEARCHING;
|
||||
else if(intRes == 0xFF) // 0xFF Device is currently scanning for the configured SSID.
|
||||
stat = REG_SEARCHING;
|
||||
else stat = REG_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if(intRes == 0x00) // 0x00 Connected to the Internet.
|
||||
stat = REG_OK;
|
||||
else if(intRes == 0x22) // 0x22 Registering to cellular network.
|
||||
stat = REG_SEARCHING;
|
||||
else if(intRes == 0x23) // 0x23 Connecting to the Internet.
|
||||
stat = REG_SEARCHING;
|
||||
else if(intRes == 0x24) // 0x24 The cellular component is missing, corrupt, or otherwise in error.
|
||||
stat = REG_UNKNOWN;
|
||||
else if(intRes == 0x25) // 0x25 Cellular network registration denied.
|
||||
stat = REG_DENIED;
|
||||
else if(intRes == 0x2A) { // 0x2A Airplane mode.
|
||||
sendAT(GF("AM0")); // Turn off airplane mode
|
||||
waitResponse();
|
||||
writeChanges();
|
||||
stat = REG_UNKNOWN;
|
||||
}
|
||||
else if(intRes == 0x2F) { // 0x2F Bypass mode active.
|
||||
sendAT(GF("AP0")); // Set back to transparent mode
|
||||
waitResponse();
|
||||
writeChanges();
|
||||
stat = REG_UNKNOWN;
|
||||
}
|
||||
else if(intRes == 0xFF) // 0xFF Device is currently scanning for the configured SSID.
|
||||
stat = REG_SEARCHING;
|
||||
else stat = REG_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
exitCommand();
|
||||
return stat;
|
||||
}
|
||||
|
||||
String getOperator() {
|
||||
if (!commandMode()) return ""; // Return immediately
|
||||
sendAT(GF("MN"));
|
||||
String res = readResponse();
|
||||
exitCommand();
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic network functions
|
||||
*/
|
||||
|
||||
int getSignalQuality() {
|
||||
if (!commandMode()) return 0; // Return immediately
|
||||
if (beeType == XBEE_S6B_WIFI) sendAT(GF("LM")); // ask for the "link margin" - the dB above sensitivity
|
||||
else sendAT(GF("DB")); // ask for the cell strength in dBm
|
||||
String res = readResponse(); // it works better if we read in as a string
|
||||
exitCommand();
|
||||
char buf[3] = {0,}; // Set up buffer for response
|
||||
res.toCharArray(buf, 3);
|
||||
int intRes = strtol(buf, 0, 16);
|
||||
if (beeType == XBEE_S6B_WIFI) return -93 + intRes; // the maximum sensitivity is -93dBm
|
||||
else return -1*intRes; // need to convert to negative number
|
||||
}
|
||||
|
||||
bool isNetworkConnected() {
|
||||
RegStatus s = getRegistrationStatus();
|
||||
return (s == REG_OK);
|
||||
}
|
||||
|
||||
bool waitForNetwork(unsigned long timeout = 60000L) {
|
||||
for (unsigned long start = millis(); millis() - start < timeout; ) {
|
||||
if (isNetworkConnected()) {
|
||||
return true;
|
||||
}
|
||||
// delay(250); // Enough delay going in and out of command mode
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* WiFi functions
|
||||
*/
|
||||
bool networkConnect(const char* ssid, const char* pwd) {
|
||||
|
||||
if (!commandMode()) return false; // return immediately
|
||||
|
||||
sendAT(GF("EE"), 2); // Set security to WPA2
|
||||
if (waitResponse() != 1) goto fail;
|
||||
|
||||
sendAT(GF("ID"), ssid);
|
||||
if (waitResponse() != 1) goto fail;
|
||||
|
||||
sendAT(GF("PK"), pwd);
|
||||
if (waitResponse() != 1) goto fail;
|
||||
|
||||
writeChanges();
|
||||
exitCommand();
|
||||
|
||||
return true;
|
||||
|
||||
fail:
|
||||
exitCommand();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool networkDisconnect() {
|
||||
if (!commandMode()) return false; // return immediately
|
||||
sendAT(GF("NR0")); // Do a network reset in order to disconnect
|
||||
int res = (1 == waitResponse(5000));
|
||||
writeChanges();
|
||||
exitCommand();
|
||||
return res;
|
||||
}
|
||||
|
||||
String getLocalIP() {
|
||||
if (!commandMode()) return ""; // Return immediately
|
||||
sendAT(GF("MY"));
|
||||
String IPaddr; IPaddr.reserve(16);
|
||||
// wait for the response - this response can be very slow
|
||||
IPaddr = readResponse(30000);
|
||||
exitCommand();
|
||||
IPaddr.trim();
|
||||
return IPaddr;
|
||||
}
|
||||
|
||||
IPAddress localIP() {
|
||||
return TinyGsmIpFromString(getLocalIP());
|
||||
}
|
||||
|
||||
/*
|
||||
* GPRS functions
|
||||
*/
|
||||
bool gprsConnect(const char* apn, const char* user = NULL, const char* pwd = NULL) {
|
||||
if (!commandMode()) return false; // Return immediately
|
||||
sendAT(GF("AN"), apn); // Set the APN
|
||||
waitResponse();
|
||||
writeChanges();
|
||||
exitCommand();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool gprsDisconnect() {
|
||||
if (!commandMode()) return false; // return immediately
|
||||
sendAT(GF("AM1")); // Cheating and disconnecting by turning on airplane mode
|
||||
int res = (1 == waitResponse(5000));
|
||||
writeChanges();
|
||||
sendAT(GF("AM0")); // Airplane mode off
|
||||
waitResponse(5000);
|
||||
writeChanges();
|
||||
exitCommand();
|
||||
return res;
|
||||
}
|
||||
|
||||
bool isGprsConnected() {
|
||||
return isNetworkConnected();
|
||||
}
|
||||
|
||||
/*
|
||||
* Messaging functions
|
||||
*/
|
||||
|
||||
String sendUSSD(const String& code) TINY_GSM_ATTR_NOT_IMPLEMENTED;
|
||||
|
||||
bool sendSMS(const String& number, const String& text) {
|
||||
if (!commandMode()) return false; // Return immediately
|
||||
|
||||
sendAT(GF("IP"), 2); // Put in text messaging mode
|
||||
if (waitResponse() !=1) goto fail;
|
||||
sendAT(GF("PH"), number); // Set the phone number
|
||||
if (waitResponse() !=1) goto fail;
|
||||
sendAT(GF("TDD")); // Set the text delimiter to the standard 0x0D (carriage return)
|
||||
if (waitResponse() !=1) goto fail;
|
||||
if (!writeChanges()) goto fail;
|
||||
|
||||
exitCommand();
|
||||
streamWrite(text);
|
||||
stream.write((char)0x0D); // close off with the carriage return
|
||||
return true;
|
||||
|
||||
fail:
|
||||
exitCommand();
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Location functions
|
||||
*/
|
||||
|
||||
String getGsmLocation() TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||
|
||||
/*
|
||||
* Battery functions
|
||||
*/
|
||||
|
||||
uint16_t getBattVoltage() TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||
|
||||
int getBattPercent() TINY_GSM_ATTR_NOT_AVAILABLE;
|
||||
|
||||
protected:
|
||||
|
||||
bool modemConnect(const char* host, uint16_t port, uint8_t mux = 0, bool ssl = false) {
|
||||
String strIP; strIP.reserve(16);
|
||||
unsigned long startMillis = millis();
|
||||
bool gotIP = false;
|
||||
// XBee's require a numeric IP address for connection, but do provide the
|
||||
// functionality to look up the IP address from a fully qualified domain name
|
||||
while (!gotIP && millis() - startMillis < 45000L) // the lookup can take a while
|
||||
{
|
||||
sendAT(GF("LA"), host);
|
||||
while (stream.available() < 4) {}; // wait for any response
|
||||
strIP = stream.readStringUntil('\r'); // read result
|
||||
strIP.trim();
|
||||
DBG("<<< ", strIP);
|
||||
if (!strIP.endsWith(GF("ERROR"))) gotIP = true;
|
||||
delay(100); // short wait before trying again
|
||||
}
|
||||
if (gotIP) { // No reason to continue if we don't know the IP address
|
||||
IPAddress ip = TinyGsmIpFromString(strIP);
|
||||
return modemConnect(ip, port, mux, ssl);
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
bool modemConnect(IPAddress ip, uint16_t port, uint8_t mux = 0, bool ssl = false) {
|
||||
bool success = true;
|
||||
String host; host.reserve(16);
|
||||
host += ip[0];
|
||||
host += ".";
|
||||
host += ip[1];
|
||||
host += ".";
|
||||
host += ip[2];
|
||||
host += ".";
|
||||
host += ip[3];
|
||||
if (ssl) {
|
||||
sendAT(GF("IP"), 4); // Put in SSL over TCP communication mode
|
||||
success &= (1 == waitResponse());
|
||||
} else {
|
||||
sendAT(GF("IP"), 1); // Put in TCP mode
|
||||
success &= (1 == waitResponse());
|
||||
}
|
||||
sendAT(GF("DL"), host); // Set the "Destination Address Low"
|
||||
success &= (1 == waitResponse());
|
||||
sendAT(GF("DE"), String(port, HEX)); // Set the destination port
|
||||
success &= (1 == waitResponse());
|
||||
return success;
|
||||
}
|
||||
|
||||
int modemSend(const void* buff, size_t len, uint8_t mux = 0) {
|
||||
stream.write((uint8_t*)buff, len);
|
||||
stream.flush();
|
||||
return len;
|
||||
}
|
||||
|
||||
bool modemGetConnected(uint8_t mux = 0) {
|
||||
if (!commandMode()) return false;
|
||||
sendAT(GF("AI"));
|
||||
int res = waitResponse(GF("0"));
|
||||
exitCommand();
|
||||
return 1 == res;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/* Utilities */
|
||||
|
||||
template<typename T>
|
||||
void streamWrite(T last) {
|
||||
stream.print(last);
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
void streamWrite(T head, Args... tail) {
|
||||
stream.print(head);
|
||||
streamWrite(tail...);
|
||||
}
|
||||
|
||||
void streamClear(void) {
|
||||
TINY_GSM_YIELD();
|
||||
while (stream.available()) { stream.read(); }
|
||||
}
|
||||
|
||||
bool commandMode(int retries = 2) {
|
||||
int triesMade = 0;
|
||||
bool success = false;
|
||||
streamClear(); // Empty everything in the buffer before starting
|
||||
while (!success and triesMade < retries) {
|
||||
// Cannot send anything for 1 "guard time" before entering command mode
|
||||
// Default guard time is 1s, but the init fxn decreases it to 250 ms
|
||||
delay(guardTime);
|
||||
streamWrite(GF("+++")); // enter command mode
|
||||
DBG("+++");
|
||||
success = (1 == waitResponse(guardTime*2));
|
||||
triesMade ++;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool writeChanges(void) {
|
||||
sendAT(GF("WR")); // Write changes to flash
|
||||
if (1 != waitResponse()) return false;
|
||||
sendAT(GF("AC")); // Apply changes
|
||||
if (1 != waitResponse()) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void exitCommand(void) {
|
||||
sendAT(GF("CN")); // Exit command mode
|
||||
waitResponse();
|
||||
}
|
||||
|
||||
String readResponse(uint32_t timeout = 1000) {
|
||||
TINY_GSM_YIELD();
|
||||
unsigned long startMillis = millis();
|
||||
while (!stream.available() && millis() - startMillis < timeout) {};
|
||||
String res = stream.readStringUntil('\r'); // lines end with carriage returns
|
||||
res.trim();
|
||||
DBG("<<< ", res);
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void sendAT(Args... cmd) {
|
||||
streamWrite("AT", cmd..., GSM_NL);
|
||||
stream.flush();
|
||||
TINY_GSM_YIELD();
|
||||
//DBG("### AT:", cmd...);
|
||||
}
|
||||
|
||||
// TODO: Optimize this!
|
||||
uint8_t waitResponse(uint32_t timeout, String& data,
|
||||
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
|
||||
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
|
||||
{
|
||||
/*String r1s(r1); r1s.trim();
|
||||
String r2s(r2); r2s.trim();
|
||||
String r3s(r3); r3s.trim();
|
||||
String r4s(r4); r4s.trim();
|
||||
String r5s(r5); r5s.trim();
|
||||
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s);*/
|
||||
data.reserve(16); // Should never be getting much here for the XBee
|
||||
int index = 0;
|
||||
unsigned long startMillis = millis();
|
||||
do {
|
||||
TINY_GSM_YIELD();
|
||||
while (stream.available() > 0) {
|
||||
int a = stream.read();
|
||||
if (a <= 0) continue; // Skip 0x00 bytes, just in case
|
||||
data += (char)a;
|
||||
if (r1 && data.endsWith(r1)) {
|
||||
index = 1;
|
||||
goto finish;
|
||||
} else if (r2 && data.endsWith(r2)) {
|
||||
index = 2;
|
||||
goto finish;
|
||||
} else if (r3 && data.endsWith(r3)) {
|
||||
index = 3;
|
||||
goto finish;
|
||||
} else if (r4 && data.endsWith(r4)) {
|
||||
index = 4;
|
||||
goto finish;
|
||||
} else if (r5 && data.endsWith(r5)) {
|
||||
index = 5;
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
} while (millis() - startMillis < timeout);
|
||||
finish:
|
||||
if (!index) {
|
||||
data.trim();
|
||||
data.replace(GSM_NL GSM_NL, GSM_NL);
|
||||
data.replace(GSM_NL, "\r\n ");
|
||||
if (data.length()) {
|
||||
DBG("### Unhandled:", data, "\r\n");
|
||||
} else {
|
||||
DBG("### NO RESPONSE!\r\n");
|
||||
}
|
||||
} else {
|
||||
data.trim();
|
||||
data.replace(GSM_NL GSM_NL, GSM_NL);
|
||||
data.replace(GSM_NL, "\r\n ");
|
||||
if (data.length()) {
|
||||
// DBG("<<< ", data);
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
uint8_t waitResponse(uint32_t timeout,
|
||||
GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
|
||||
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
|
||||
{
|
||||
String data;
|
||||
return waitResponse(timeout, data, r1, r2, r3, r4, r5);
|
||||
}
|
||||
|
||||
uint8_t waitResponse(GsmConstStr r1=GFP(GSM_OK), GsmConstStr r2=GFP(GSM_ERROR),
|
||||
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL)
|
||||
{
|
||||
return waitResponse(1000, r1, r2, r3, r4, r5);
|
||||
}
|
||||
|
||||
public:
|
||||
Stream& stream;
|
||||
|
||||
protected:
|
||||
int guardTime;
|
||||
XBeeType beeType;
|
||||
GsmClient* sockets[TINY_GSM_MUX_COUNT];
|
||||
};
|
||||
|
||||
#endif
|
||||
197
arduino-cli/libraries/TinyGSM/src/TinyGsmCommon.h
Normal file
197
arduino-cli/libraries/TinyGSM/src/TinyGsmCommon.h
Normal file
@@ -0,0 +1,197 @@
|
||||
/**
|
||||
* @file TinyGsmCommon.h
|
||||
* @author Volodymyr Shymanskyy
|
||||
* @license LGPL-3.0
|
||||
* @copyright Copyright (c) 2016 Volodymyr Shymanskyy
|
||||
* @date Nov 2016
|
||||
*/
|
||||
|
||||
#ifndef TinyGsmCommon_h
|
||||
#define TinyGsmCommon_h
|
||||
|
||||
#if defined(SPARK) || defined(PARTICLE)
|
||||
#include "Particle.h"
|
||||
#elif defined(ARDUINO)
|
||||
#if ARDUINO >= 100
|
||||
#include "Arduino.h"
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO_DASH)
|
||||
#include <ArduinoCompat/Client.h>
|
||||
#else
|
||||
#include <Client.h>
|
||||
#endif
|
||||
|
||||
#include <TinyGsmFifo.h>
|
||||
|
||||
#ifndef TINY_GSM_YIELD
|
||||
#define TINY_GSM_YIELD() { delay(0); }
|
||||
#endif
|
||||
|
||||
#define TINY_GSM_ATTR_NOT_AVAILABLE __attribute__((error("Not available on this modem type")))
|
||||
#define TINY_GSM_ATTR_NOT_IMPLEMENTED __attribute__((error("Not implemented")))
|
||||
|
||||
#if defined(__AVR__)
|
||||
#define TINY_GSM_PROGMEM PROGMEM
|
||||
typedef const __FlashStringHelper* GsmConstStr;
|
||||
#define GFP(x) (reinterpret_cast<GsmConstStr>(x))
|
||||
#define GF(x) F(x)
|
||||
#else
|
||||
#define TINY_GSM_PROGMEM
|
||||
typedef const char* GsmConstStr;
|
||||
#define GFP(x) x
|
||||
#define GF(x) x
|
||||
#endif
|
||||
|
||||
#ifdef TINY_GSM_DEBUG
|
||||
namespace {
|
||||
template<typename T>
|
||||
static void DBG_PLAIN(T last) {
|
||||
TINY_GSM_DEBUG.println(last);
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
static void DBG_PLAIN(T head, Args... tail) {
|
||||
TINY_GSM_DEBUG.print(head);
|
||||
TINY_GSM_DEBUG.print(' ');
|
||||
DBG_PLAIN(tail...);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
static void DBG(Args... args) {
|
||||
TINY_GSM_DEBUG.print(GF("["));
|
||||
TINY_GSM_DEBUG.print(millis());
|
||||
TINY_GSM_DEBUG.print(GF("] "));
|
||||
DBG_PLAIN(args...);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define DBG(...)
|
||||
#endif
|
||||
|
||||
template<class T>
|
||||
const T& TinyGsmMin(const T& a, const T& b)
|
||||
{
|
||||
return (b < a) ? b : a;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
const T& TinyGsmMax(const T& a, const T& b)
|
||||
{
|
||||
return (b < a) ? a : b;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
uint32_t TinyGsmAutoBaud(T& SerialAT, uint32_t minimum = 9600, uint32_t maximum = 115200)
|
||||
{
|
||||
static uint32_t rates[] = { 115200, 57600, 38400, 19200, 9600, 74400, 74880, 230400, 460800, 2400, 4800, 14400, 28800 };
|
||||
|
||||
for (unsigned i = 0; i < sizeof(rates)/sizeof(rates[0]); i++) {
|
||||
uint32_t rate = rates[i];
|
||||
if (rate < minimum || rate > maximum) continue;
|
||||
|
||||
DBG("Trying baud rate", rate, "...");
|
||||
SerialAT.begin(rate);
|
||||
delay(10);
|
||||
for (int i=0; i<3; i++) {
|
||||
SerialAT.print("AT\r\n");
|
||||
String input = SerialAT.readString();
|
||||
if (input.indexOf("OK") >= 0) {
|
||||
DBG("Modem responded at rate", rate);
|
||||
return rate;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
IPAddress TinyGsmIpFromString(const String& strIP) {
|
||||
int Parts[4] = {0, };
|
||||
int Part = 0;
|
||||
for (uint8_t i=0; i<strIP.length(); i++) {
|
||||
char c = strIP[i];
|
||||
if (c == '.') {
|
||||
Part++;
|
||||
if (Part > 3) {
|
||||
return IPAddress(0,0,0,0);
|
||||
}
|
||||
continue;
|
||||
} else if (c >= '0' && c <= '9') {
|
||||
Parts[Part] *= 10;
|
||||
Parts[Part] += c - '0';
|
||||
} else {
|
||||
if (Part == 3) break;
|
||||
}
|
||||
}
|
||||
return IPAddress(Parts[0], Parts[1], Parts[2], Parts[3]);
|
||||
}
|
||||
|
||||
static inline
|
||||
String TinyGsmDecodeHex7bit(String &instr) {
|
||||
String result;
|
||||
byte reminder = 0;
|
||||
int bitstate = 7;
|
||||
for (unsigned i=0; i<instr.length(); i+=2) {
|
||||
char buf[4] = { 0, };
|
||||
buf[0] = instr[i];
|
||||
buf[1] = instr[i+1];
|
||||
byte b = strtol(buf, NULL, 16);
|
||||
|
||||
byte bb = b << (7 - bitstate);
|
||||
char c = (bb + reminder) & 0x7F;
|
||||
result += c;
|
||||
reminder = b >> bitstate;
|
||||
bitstate--;
|
||||
if (bitstate == 0) {
|
||||
char c = reminder;
|
||||
result += c;
|
||||
reminder = 0;
|
||||
bitstate = 7;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline
|
||||
String TinyGsmDecodeHex8bit(String &instr) {
|
||||
String result;
|
||||
for (unsigned i=0; i<instr.length(); i+=2) {
|
||||
char buf[4] = { 0, };
|
||||
buf[0] = instr[i];
|
||||
buf[1] = instr[i+1];
|
||||
char b = strtol(buf, NULL, 16);
|
||||
result += b;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline
|
||||
String TinyGsmDecodeHex16bit(String &instr) {
|
||||
String result;
|
||||
for (unsigned i=0; i<instr.length(); i+=4) {
|
||||
char buf[4] = { 0, };
|
||||
buf[0] = instr[i];
|
||||
buf[1] = instr[i+1];
|
||||
char b = strtol(buf, NULL, 16);
|
||||
if (b) { // If high byte is non-zero, we can't handle it ;(
|
||||
#if defined(TINY_GSM_UNICODE_TO_HEX)
|
||||
result += "\\x";
|
||||
result += instr.substring(i, i+4);
|
||||
#else
|
||||
result += "?";
|
||||
#endif
|
||||
} else {
|
||||
buf[0] = instr[i+2];
|
||||
buf[1] = instr[i+3];
|
||||
b = strtol(buf, NULL, 16);
|
||||
result += b;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
136
arduino-cli/libraries/TinyGSM/src/TinyGsmFifo.h
Normal file
136
arduino-cli/libraries/TinyGSM/src/TinyGsmFifo.h
Normal file
@@ -0,0 +1,136 @@
|
||||
#ifndef TinyGsmFifo_h
|
||||
#define TinyGsmFifo_h
|
||||
|
||||
template <class T, unsigned N>
|
||||
class TinyGsmFifo
|
||||
{
|
||||
public:
|
||||
TinyGsmFifo()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
_r = 0;
|
||||
_w = 0;
|
||||
}
|
||||
|
||||
// writing thread/context API
|
||||
//-------------------------------------------------------------
|
||||
|
||||
bool writeable(void)
|
||||
{
|
||||
return free() > 0;
|
||||
}
|
||||
|
||||
int free(void)
|
||||
{
|
||||
int s = _r - _w;
|
||||
if (s <= 0)
|
||||
s += N;
|
||||
return s - 1;
|
||||
}
|
||||
|
||||
bool put(const T& c)
|
||||
{
|
||||
int i = _w;
|
||||
int j = i;
|
||||
i = _inc(i);
|
||||
if (i == _r) // !writeable()
|
||||
return false;
|
||||
_b[j] = c;
|
||||
_w = i;
|
||||
return true;
|
||||
}
|
||||
|
||||
int put(const T* p, int n, bool t = false)
|
||||
{
|
||||
int c = n;
|
||||
while (c)
|
||||
{
|
||||
int f;
|
||||
while ((f = free()) == 0) // wait for space
|
||||
{
|
||||
if (!t) return n - c; // no more space and not blocking
|
||||
/* nothing / just wait */;
|
||||
}
|
||||
// check free space
|
||||
if (c < f) f = c;
|
||||
int w = _w;
|
||||
int m = N - w;
|
||||
// check wrap
|
||||
if (f > m) f = m;
|
||||
memcpy(&_b[w], p, f);
|
||||
_w = _inc(w, f);
|
||||
c -= f;
|
||||
p += f;
|
||||
}
|
||||
return n - c;
|
||||
}
|
||||
|
||||
// reading thread/context API
|
||||
// --------------------------------------------------------
|
||||
|
||||
bool readable(void)
|
||||
{
|
||||
return (_r != _w);
|
||||
}
|
||||
|
||||
size_t size(void)
|
||||
{
|
||||
int s = _w - _r;
|
||||
if (s < 0)
|
||||
s += N;
|
||||
return s;
|
||||
}
|
||||
|
||||
bool get(T* p)
|
||||
{
|
||||
int r = _r;
|
||||
if (r == _w) // !readable()
|
||||
return false;
|
||||
*p = _b[r];
|
||||
_r = _inc(r);
|
||||
return true;
|
||||
}
|
||||
|
||||
int get(T* p, int n, bool t = false)
|
||||
{
|
||||
int c = n;
|
||||
while (c)
|
||||
{
|
||||
int f;
|
||||
for (;;) // wait for data
|
||||
{
|
||||
f = size();
|
||||
if (f) break; // free space
|
||||
if (!t) return n - c; // no space and not blocking
|
||||
/* nothing / just wait */;
|
||||
}
|
||||
// check available data
|
||||
if (c < f) f = c;
|
||||
int r = _r;
|
||||
int m = N - r;
|
||||
// check wrap
|
||||
if (f > m) f = m;
|
||||
memcpy(p, &_b[r], f);
|
||||
_r = _inc(r, f);
|
||||
c -= f;
|
||||
p += f;
|
||||
}
|
||||
return n - c;
|
||||
}
|
||||
|
||||
private:
|
||||
int _inc(int i, int n = 1)
|
||||
{
|
||||
return (i + n) % N;
|
||||
}
|
||||
|
||||
T _b[N];
|
||||
int _w;
|
||||
int _r;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user