Browse Source

add SIM800L library

develop
Dslak 4 years ago
parent
commit
89e32f159b
  1. BIN
      libraries/Arduino-SIM800L-driver-master.zip
  2. 38
      libraries/SIM800L/.gitignore
  3. 21
      libraries/SIM800L/LICENSE
  4. 147
      libraries/SIM800L/README.md
  5. 99
      libraries/SIM800L/examples/BasicTest_HardwareSerial/BasicTest_HardwareSerial.ino
  6. 104
      libraries/SIM800L/examples/BasicTest_SoftSerial/BasicTest_SoftSerial.ino
  7. 7
      libraries/SIM800L/examples/BasicTest_SoftSerial/sketch.json
  8. 153
      libraries/SIM800L/examples/HTTPS_GET_HardwareSerial/HTTPS_GET_HardwareSerial.ino
  9. 158
      libraries/SIM800L/examples/HTTPS_GET_SoftSerial/HTTPS_GET_SoftSerial.ino
  10. 155
      libraries/SIM800L/examples/HTTPS_POST_HardwareSerial/HTTPS_POST_HardwareSerial.ino
  11. 160
      libraries/SIM800L/examples/HTTPS_POST_SoftSerial/HTTPS_POST_SoftSerial.ino
  12. BIN
      libraries/SIM800L/extras/SIM800 Series_AT Command Manual_V1.09.pdf
  13. BIN
      libraries/SIM800L/extras/SIM800 Series_IP_Application Note_V1.02.pdf
  14. BIN
      libraries/SIM800L/extras/SIM800 Series_SSL_Application Note_V1.00.pdf
  15. 12
      libraries/SIM800L/keywords.txt
  16. 11
      libraries/SIM800L/library.properties
  17. 935
      libraries/SIM800L/src/SIM800L.cpp
  18. 138
      libraries/SIM800L/src/SIM800L.h

BIN
libraries/Arduino-SIM800L-driver-master.zip

Binary file not shown.

38
libraries/SIM800L/.gitignore

@ -0,0 +1,38 @@
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
# Compiled arduino
*.eep
*.elf
*.hex
*.bin

21
libraries/SIM800L/LICENSE

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Olivier Staquet
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

147
libraries/SIM800L/README.md

@ -0,0 +1,147 @@
# Arduino SIM800L HTTP connector
Arduino driver for GSM/GPRS module SIMCom SIM800L to make HTTP/S connections with GET and POST methods
[![GitHub](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/ostaquet/Arduino-SIM800L-driver/blob/master/LICENSE)
[![GitHub release](https://img.shields.io/github/release/ostaquet/Arduino-SIM800L-driver.svg)](#releases)
[![GitHub issues](https://img.shields.io/github/issues/ostaquet/Arduino-SIM800L-driver.svg)](https://github.com/ostaquet/Arduino-SIM800L-driver/issues)
This is a comprehensive Arduino library to make HTTP or HTTPS communication through the SIMCom SIM800L module. The library has been designed to **limit the memory usage** by working with the same shared buffer all the time.
The [SIM800L](https://simcom.ee/modules/gsm-gprs/sim800/) is a GSM/GPRS module built by SIMCom. The communication with the SIM800L module relies on AT commands. The available AT commands are described in the [SIM800 series AT Command Manual](extras/SIM800%20Series_AT%20Command%20Manual_V1.09.pdf).
Supported features in this library:
* Power management of the SIM800L module
* Network registration and signal strengh measurement
* GPRS connectivity and setup
* HTTP and HTTPS (SSL based on in-built IP stack)
* GET and POST methods
* SoftwareSerial and HardwareSerial links
* Configurable debug serial
* Limited memory usage
## To know before starting...
* The original module is working with an input voltage of 3.7V to 4.2V. So, __don't connect the naked module directly on the Arduino__. I personally use a module with voltage convertors from/to 5V like [this one](https://www.amazon.fr/dp/B073TF2QKL).
* As the chipset can draw 2A maximum, it is better to use an external power source. __Using the USB power through the computer is not enough while HTTP communication__.
* There are different firmware version of the SIM800L on the market. **The HTTPS connectivity is available only for R14 and above.** (You can check your version with the examples [BasicTest_HardwareSerial](https://github.com/ostaquet/Arduino-SIM800L-driver/blob/master/examples/BasicTest_HardwareSerial/BasicTest_HardwareSerial.ino) or [BasicTest_SoftSerial](https://github.com/ostaquet/Arduino-SIM800L-driver/blob/master/examples/BasicTest_SoftSerial/BasicTest_SoftSerial.ino))
* The firmware of the SIM800L is quite old and **doesn't support the latest cryptographic protocols** which could lead to some issues while connecting backends (typically errors `605` and `606`). [Read also the section below about security concerns](https://github.com/ostaquet/Arduino-SIM800L-driver#security-concerns).
## How to install the library?
The easiest way to install the library is to go to the Library manager of the Arduino IDE and install the library.
1. In the Arduino IDE, go into menu _Tools_ -> _Manage Libraries..._
2. Search for _SIM800L_
3. Install _SIM800L HTTP connector by Olivier Staquet_
## Examples
You will find [examples in the repository](https://github.com/ostaquet/Arduino-SIM800L-driver/tree/master/examples) to make HTTPS GET and HTTPS POST.
We are using the [Postman Echo service](https://docs.postman-echo.com) to illustrate the communication with an external API. By the way, if you need a pretty cool tool to test and validate API, I recommend [Postman](https://www.getpostman.com). They make really API devlopment simple.
## Usage
### Initiate the driver and the module
First, you have to initiate the driver by telling him the serial link and the RESET pin. The next two parameters defined the size of the internal buffer and the size of the reception buffer.
The size of the reception buffer is depending on the data you will receive from the web service/API. If the buffer is too small, you will receive only the first 512 bytes in the examples below. The driver has a buffer overflow protection.
To initiate with a SoftwareSerial link (on pin TX_PIN and RX_PIN):
```
SoftwareSerial* serial = new SoftwareSerial(TX_PIN, RX_PIN);
serial->begin(9600);
SIM800L* sim800l = new SIM800L((Stream *)serial, SIM800_RST_PIN, 200, 512);
```
To initiate with a hardware serial link (Serial1):
```
Serial1.begin(9600);
SIM800L* sim800l = new SIM800L((Stream *)&Serial1, SIM800_RST_PIN, 200, 512);
```
### Setup and check all aspects for the connectivity
Then, you have to initiate the basis for a GPRS connectivity.
The module has to be initalized and accept AT commands. You can test it and wait the module to be ready.
```
sim800l->isReady();
```
The GSM signal should be up. You can test the signed strenght and wait for a signal greater than 0.
```
sim800l->getSignal();
```
The module has to be registered on the network. You can obtain the registration status through a specific command and wait for a REGISTERED_HOME or REGISTERED_ROAMING depending on your operator and location.
```
sim800l->getRegistrationStatus();
```
Finally, you have to setup the APN for the GPRS connectivity. By example: *Internet.be* for Orange Belgium who is providing [SIM cards dedicated for IoT](https://orange-iotshop.allthingstalk.com).
```
sim800l->setupGPRS("Internet.be");
```
### Connecting GPRS
Before making any connection, you have to open the GPRS connection. It can be done easily. When the GPRS connectivity is UP, the LED is blinking fast on the SIM800L module.
```
sim800l->connectGPRS();
```
### HTTP communication GET
In order to make an HTTP GET connection to a server or the [Postman Echo service](https://docs.postman-echo.com), you just have to define the URL and the timeout in milli-seconds. The HTTP or the HTTPS protocol is set automatically depending on the URL. The URL should always start with *http://* or *https://*.
```
sim800l->doGet("https://postman-echo.com/get?foo1=bar1&foo2=bar2", 10000);
```
or
```
sim800l->doGet("https://postman-echo.com/get?foo1=bar1&foo2=bar2", "Header-1:value1\\r\\nHeader-2:value2", 10000);
```
If the method returns 200 (HTTP status code for OK), you can obtain the size of the data received.
```
sim800l->getDataSizeReceived();
```
And you can obtain the data received through a char array.
```
sim800l->getDataReceived();
```
### HTTP communication POST
In order to make an HTTP POST connection to a server or the [Postman Echo service](https://docs.postman-echo.com), you have to define a bit more information than the GET. Again, the HTTP or the HTTPS protocol is set automatically depending on the URL. The URL should always start with *http://* or *https://*.
The arguments of the method are:
* The URL (*https://postman-echo.com/post*)
* *(optional)* Headers *("Header-1:value1\\r\\nHeader-2:value2")*
* The content type (*application/json*)
* The content to POST (*{"name": "morpheus", "job": "leader"}*)
* The write timeout while writing data to the server (*10000* ms)
* The read timeout while reading data from the server (*10000* ms)
```
sim800l->doPost("https://postman-echo.com/post", "application/json", "{\"name\": \"morpheus\", \"job\": \"leader\"}", 10000, 10000);
```
or with headers
```
sim800l->doPost("https://postman-echo.com/post", "Header-1:value1\\r\\nHeader-2:value2", "application/json", "{\"name\": \"morpheus\", \"job\": \"leader\"}", 10000, 10000);
```
If the method returns 200 (HTTP status code for OK), you can obtain the size of the data received.
```
sim800l->getDataSizeReceived();
```
And you can obtain the data recieved through a char array.
```
sim800l->getDataReceived();
```
### Disconnecting GPRS
At the end of the connection, don't forget to disconnect the GPRS to save power.
```
sim800l->disconnectGPRS();
```
## Security concerns
The SIM800L latest firmware update was in January 2016. It means that using the IP stack embedded on the SIM800L is convenient but not secure. **The embedded IP stack should not be used for the transfer of critical data.**
The embedded IP stack of the SIM800L only supports SSL2, SSL3 and TLS 1.0. These cryptographic protocols are considered deprecated for most of web browsers and the connection will be denied by modern backend (i.e. AWS). This will typically lead to an error `605` or `606` when you establish an HTTPS connection.
In order to secure your connectivity to the backend, we strongly recommend using an up-to-date SSL library like [WolfSSL](https://www.wolfssl.com).
## Links
* [SIM800 series AT Command Manual](extras/SIM800%20Series_AT%20Command%20Manual_V1.09.pdf)
* [SIM800 series IP Application Note](extras/SIM800%20Series_IP_Application%20Note_V1.02.pdf)
* [SIM800 series SSL Application Note](extras/SIM800%20Series_SSL_Application%20Note_V1.00.pdf)

99
libraries/SIM800L/examples/BasicTest_HardwareSerial/BasicTest_HardwareSerial.ino

@ -0,0 +1,99 @@
/********************************************************************************
* Execute sanity check on the module and output version (hardware serial) *
* *
* Author: Olivier Staquet *
* Last version available on https://github.com/ostaquet/Arduino-SIM800L-driver *
********************************************************************************
* MIT License
*
* Copyright (c) 2019 Olivier Staquet
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*******************************************************************************/
#include "SIM800L.h"
#define SIM800_RST_PIN 6
SIM800L* sim800l;
void setup() {
// Initialize Serial Monitor for debugging
Serial.begin(115200);
while(!Serial);
// Initialize the hardware Serial1
Serial1.begin(9600);
delay(1000);
// Initialize SIM800L driver with an internal buffer of 200 bytes and a reception buffer of 512 bytes, debug disabled
sim800l = new SIM800L((Stream *)&Serial1, SIM800_RST_PIN, 200, 512);
// Equivalent line with the debug enabled on the Serial
//sim800l = new SIM800L((Stream *)&Serial1, SIM800_RST_PIN, 200, 512, (Stream *)&Serial);
Serial.println("Start of test protocol");
// Wait until the module is ready to accept AT commands
while(!sim800l->isReady()) {
Serial.println(F("Problem to initialize AT command, retry in 1 sec"));
delay(1000);
}
Serial.println("Module ready");
// Print version
Serial.print("Module ");
Serial.println(sim800l->getVersion());
Serial.print("Firmware ");
Serial.println(sim800l->getFirmware());
// Print SIM card number
Serial.print("SIM card number ");
Serial.println(sim800l->getSimCardNumber());
// Wait for the GSM signal
uint8_t signal = sim800l->getSignal();
while(signal <= 0) {
delay(1000);
signal = sim800l->getSignal();
}
if(signal > 5) {
Serial.print(F("Signal OK (strenght: "));
} else {
Serial.print(F("Signal low (strenght: "));
}
Serial.print(signal);
Serial.println(F(")"));
delay(1000);
// Wait for operator network registration (national or roaming network)
NetworkRegistration network = sim800l->getRegistrationStatus();
while(network != REGISTERED_HOME && network != REGISTERED_ROAMING) {
delay(1000);
network = sim800l->getRegistrationStatus();
}
Serial.println(F("Network registration OK"));
Serial.println("End of test protocol");
}
void loop() {
}

104
libraries/SIM800L/examples/BasicTest_SoftSerial/BasicTest_SoftSerial.ino

@ -0,0 +1,104 @@
/********************************************************************************
* Execute sanity check on the module and output version (software serial) *
* *
* Author: Olivier Staquet *
* Last version available on https://github.com/ostaquet/Arduino-SIM800L-driver *
********************************************************************************
* MIT License
*
* Copyright (c) 2019 Olivier Staquet
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*******************************************************************************/
#include <SoftwareSerial.h>
#include "SIM800L.h"
#define SIM800_RX_PIN 10
#define SIM800_TX_PIN 11
#define SIM800_RST_PIN 6
SIM800L* sim800l;
void setup() {
// Initialize Serial Monitor for debugging
Serial.begin(115200);
while(!Serial);
// Initialize a SoftwareSerial
SoftwareSerial* serial = new SoftwareSerial(SIM800_RX_PIN, SIM800_TX_PIN);
serial->begin(9600);
delay(1000);
// Initialize SIM800L driver with an internal buffer of 200 bytes and a reception buffer of 512 bytes, debug disabled
sim800l = new SIM800L((Stream *)serial, SIM800_RST_PIN, 200, 512);
// Equivalent line with the debug enabled on the Serial
//sim800l = new SIM800L((Stream *)serial, SIM800_RST_PIN, 200, 512, (Stream *)&Serial);
Serial.println("Start of test protocol");
// Wait until the module is ready to accept AT commands
while(!sim800l->isReady()) {
Serial.println(F("Problem to initialize AT command, retry in 1 sec"));
delay(1000);
}
Serial.println("Module ready");
// Print version
Serial.print("Module ");
Serial.println(sim800l->getVersion());
Serial.print("Firmware ");
Serial.println(sim800l->getFirmware());
// Print SIM card number
Serial.print("SIM card number ");
Serial.println(sim800l->getSimCardNumber());
// Wait for the GSM signal
uint8_t signal = sim800l->getSignal();
while(signal <= 0) {
delay(1000);
signal = sim800l->getSignal();
}
if(signal > 5) {
Serial.print(F("Signal OK (strenght: "));
} else {
Serial.print(F("Signal low (strenght: "));
}
Serial.print(signal);
Serial.println(F(")"));
delay(1000);
// Wait for operator network registration (national or roaming network)
NetworkRegistration network = sim800l->getRegistrationStatus();
while(network != REGISTERED_HOME && network != REGISTERED_ROAMING) {
delay(1000);
network = sim800l->getRegistrationStatus();
}
Serial.println(F("Network registration OK"));
Serial.println("End of test protocol");
}
void loop() {
}

7
libraries/SIM800L/examples/BasicTest_SoftSerial/sketch.json

@ -0,0 +1,7 @@
{
"cpu": {
"fqbn": "arduino:avr:uno",
"name": "Arduino Uno",
"port": "serial:///dev/cu.usbmodem14301"
}
}

153
libraries/SIM800L/examples/HTTPS_GET_HardwareSerial/HTTPS_GET_HardwareSerial.ino

@ -0,0 +1,153 @@
/********************************************************************************
* Example of HTTPS GET with Serial1 (Mega2560) and Arduino-SIM800L-driver *
* *
* Author: Olivier Staquet *
* Last version available on https://github.com/ostaquet/Arduino-SIM800L-driver *
********************************************************************************
* MIT License
*
* Copyright (c) 2019 Olivier Staquet
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*******************************************************************************/
#include "SIM800L.h"
#define SIM800_RST_PIN 6
const char APN[] = "Internet.be";
const char URL[] = "https://postman-echo.com/get?foo1=bar1&foo2=bar2";
SIM800L* sim800l;
void setup() {
// Initialize Serial Monitor for debugging
Serial.begin(115200);
while(!Serial);
// Initialize the hardware Serial1
Serial1.begin(9600);
delay(1000);
// Initialize SIM800L driver with an internal buffer of 200 bytes and a reception buffer of 512 bytes, debug disabled
sim800l = new SIM800L((Stream *)&Serial1, SIM800_RST_PIN, 200, 512);
// Equivalent line with the debug enabled on the Serial
// sim800l = new SIM800L((Stream *)&Serial1, SIM800_RST_PIN, 200, 512, (Stream *)&Serial);
// Setup module for GPRS communication
setupModule();
}
void loop() {
// Establish GPRS connectivity (5 trials)
bool connected = false;
for(uint8_t i = 0; i < 5 && !connected; i++) {
delay(1000);
connected = sim800l->connectGPRS();
}
// Check if connected, if not reset the module and setup the config again
if(connected) {
Serial.println(F("GPRS connected !"));
} else {
Serial.println(F("GPRS not connected !"));
Serial.println(F("Reset the module."));
sim800l->reset();
setupModule();
return;
}
Serial.println(F("Start HTTP GET..."));
// Do HTTP GET communication with 10s for the timeout (read)
uint16_t rc = sim800l->doGet(URL, 10000);
if(rc == 200) {
// Success, output the data received on the serial
Serial.print(F("HTTP GET successful ("));
Serial.print(sim800l->getDataSizeReceived());
Serial.println(F(" bytes)"));
Serial.print(F("Received : "));
Serial.println(sim800l->getDataReceived());
} else {
// Failed...
Serial.print(F("HTTP GET error "));
Serial.println(rc);
}
// Close GPRS connectivity (5 trials)
bool disconnected = sim800l->disconnectGPRS();
for(uint8_t i = 0; i < 5 && !connected; i++) {
delay(1000);
disconnected = sim800l->disconnectGPRS();
}
if(disconnected) {
Serial.println(F("GPRS disconnected !"));
} else {
Serial.println(F("GPRS still connected !"));
}
// Go into low power mode
bool lowPowerMode = sim800l->setPowerMode(MINIMUM);
if(lowPowerMode) {
Serial.println(F("Module in low power mode"));
} else {
Serial.println(F("Failed to switch module to low power mode"));
}
// End of program... wait...
while(1);
}
void setupModule() {
// Wait until the module is ready to accept AT commands
while(!sim800l->isReady()) {
Serial.println(F("Problem to initialize AT command, retry in 1 sec"));
delay(1000);
}
Serial.println(F("Setup Complete!"));
// Wait for the GSM signal
uint8_t signal = sim800l->getSignal();
while(signal <= 0) {
delay(1000);
signal = sim800l->getSignal();
}
Serial.print(F("Signal OK (strenght: "));
Serial.print(signal);
Serial.println(F(")"));
delay(1000);
// Wait for operator network registration (national or roaming network)
NetworkRegistration network = sim800l->getRegistrationStatus();
while(network != REGISTERED_HOME && network != REGISTERED_ROAMING) {
delay(1000);
network = sim800l->getRegistrationStatus();
}
Serial.println(F("Network registration OK"));
delay(1000);
// Setup APN for GPRS configuration
bool success = sim800l->setupGPRS(APN);
while(!success) {
success = sim800l->setupGPRS(APN);
delay(5000);
}
Serial.println(F("GPRS config OK"));
}

158
libraries/SIM800L/examples/HTTPS_GET_SoftSerial/HTTPS_GET_SoftSerial.ino

@ -0,0 +1,158 @@
/********************************************************************************
* Example of HTTPS GET with SoftwareSerial and Arduino-SIM800L-driver *
* *
* Author: Olivier Staquet *
* Last version available on https://github.com/ostaquet/Arduino-SIM800L-driver *
********************************************************************************
* MIT License
*
* Copyright (c) 2019 Olivier Staquet
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*******************************************************************************/
#include <SoftwareSerial.h>
#include "SIM800L.h"
#define SIM800_RX_PIN 10
#define SIM800_TX_PIN 11
#define SIM800_RST_PIN 6
const char APN[] = "Internet.be";
const char URL[] = "https://postman-echo.com/get?foo1=bar1&foo2=bar2";
SIM800L* sim800l;
void setup() {
// Initialize Serial Monitor for debugging
Serial.begin(115200);
while(!Serial);
// Initialize a SoftwareSerial
SoftwareSerial* serial = new SoftwareSerial(SIM800_RX_PIN, SIM800_TX_PIN);
serial->begin(9600);
delay(1000);
// Initialize SIM800L driver with an internal buffer of 200 bytes and a reception buffer of 512 bytes, debug disabled
sim800l = new SIM800L((Stream *)serial, SIM800_RST_PIN, 200, 512);
// Equivalent line with the debug enabled on the Serial
//sim800l = new SIM800L((Stream *)serial, SIM800_RST_PIN, 200, 512, (Stream *)&Serial);
// Setup module for GPRS communication
setupModule();
}
void loop() {
// Establish GPRS connectivity (5 trials)
bool connected = false;
for(uint8_t i = 0; i < 5 && !connected; i++) {
delay(1000);
connected = sim800l->connectGPRS();
}
// Check if connected, if not reset the module and setup the config again
if(connected) {
Serial.println(F("GPRS connected !"));
} else {
Serial.println(F("GPRS not connected !"));
Serial.println(F("Reset the module."));
sim800l->reset();
setupModule();
return;
}
Serial.println(F("Start HTTP GET..."));
// Do HTTP GET communication with 10s for the timeout (read)
uint16_t rc = sim800l->doGet(URL, 10000);
if(rc == 200) {
// Success, output the data received on the serial
Serial.print(F("HTTP GET successful ("));
Serial.print(sim800l->getDataSizeReceived());
Serial.println(F(" bytes)"));
Serial.print(F("Received : "));
Serial.println(sim800l->getDataReceived());
} else {
// Failed...
Serial.print(F("HTTP GET error "));
Serial.println(rc);
}
// Close GPRS connectivity (5 trials)
bool disconnected = sim800l->disconnectGPRS();
for(uint8_t i = 0; i < 5 && !connected; i++) {
delay(1000);
disconnected = sim800l->disconnectGPRS();
}
if(disconnected) {
Serial.println(F("GPRS disconnected !"));
} else {
Serial.println(F("GPRS still connected !"));
}
// Go into low power mode
bool lowPowerMode = sim800l->setPowerMode(MINIMUM);
if(lowPowerMode) {
Serial.println(F("Module in low power mode"));
} else {
Serial.println(F("Failed to switch module to low power mode"));
}
// End of program... wait...
while(1);
}
void setupModule() {
// Wait until the module is ready to accept AT commands
while(!sim800l->isReady()) {
Serial.println(F("Problem to initialize AT command, retry in 1 sec"));
delay(1000);
}
Serial.println(F("Setup Complete!"));
// Wait for the GSM signal
uint8_t signal = sim800l->getSignal();
while(signal <= 0) {
delay(1000);
signal = sim800l->getSignal();
}
Serial.print(F("Signal OK (strenght: "));
Serial.print(signal);
Serial.println(F(")"));
delay(1000);
// Wait for operator network registration (national or roaming network)
NetworkRegistration network = sim800l->getRegistrationStatus();
while(network != REGISTERED_HOME && network != REGISTERED_ROAMING) {
delay(1000);
network = sim800l->getRegistrationStatus();
}
Serial.println(F("Network registration OK"));
delay(1000);
// Setup APN for GPRS configuration
bool success = sim800l->setupGPRS(APN);
while(!success) {
success = sim800l->setupGPRS(APN);
delay(5000);
}
Serial.println(F("GPRS config OK"));
}

155
libraries/SIM800L/examples/HTTPS_POST_HardwareSerial/HTTPS_POST_HardwareSerial.ino

@ -0,0 +1,155 @@
/********************************************************************************
* Example of HTTPS POST with Serial1 (Mega2560) and Arduino-SIM800L-driver *
* *
* Author: Olivier Staquet *
* Last version available on https://github.com/ostaquet/Arduino-SIM800L-driver *
********************************************************************************
* MIT License
*
* Copyright (c) 2019 Olivier Staquet
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*******************************************************************************/
#include "SIM800L.h"
#define SIM800_RST_PIN 6
const char APN[] = "Internet.be";
const char URL[] = "https://postman-echo.com/post";
const char CONTENT_TYPE[] = "application/json";
const char PAYLOAD[] = "{\"name\": \"morpheus\", \"job\": \"leader\"}";
SIM800L* sim800l;
void setup() {
// Initialize Serial Monitor for debugging
Serial.begin(115200);
while(!Serial);
// Initialize the hardware Serial1
Serial1.begin(9600);
delay(1000);
// Initialize SIM800L driver with an internal buffer of 200 bytes and a reception buffer of 512 bytes, debug disabled
sim800l = new SIM800L((Stream *)&Serial1, SIM800_RST_PIN, 200, 512);
// Equivalent line with the debug enabled on the Serial
// sim800l = new SIM800L((Stream *)&Serial1, SIM800_RST_PIN, 200, 512, (Stream *)&Serial);
// Setup module for GPRS communication
setupModule();
}
void loop() {
// Establish GPRS connectivity (5 trials)
bool connected = false;
for(uint8_t i = 0; i < 5 && !connected; i++) {
delay(1000);
connected = sim800l->connectGPRS();
}
// Check if connected, if not reset the module and setup the config again
if(connected) {
Serial.println(F("GPRS connected !"));
} else {
Serial.println(F("GPRS not connected !"));
Serial.println(F("Reset the module."));
sim800l->reset();
setupModule();
return;
}
Serial.println(F("Start HTTP POST..."));
// Do HTTP POST communication with 10s for the timeout (read and write)
uint16_t rc = sim800l->doPost(URL, CONTENT_TYPE, PAYLOAD, 10000, 10000);
if(rc == 200) {
// Success, output the data received on the serial
Serial.print(F("HTTP POST successful ("));
Serial.print(sim800l->getDataSizeReceived());
Serial.println(F(" bytes)"));
Serial.print(F("Received : "));
Serial.println(sim800l->getDataReceived());
} else {
// Failed...
Serial.print(F("HTTP POST error "));
Serial.println(rc);
}
// Close GPRS connectivity (5 trials)
bool disconnected = sim800l->disconnectGPRS();
for(uint8_t i = 0; i < 5 && !connected; i++) {
delay(1000);
disconnected = sim800l->disconnectGPRS();
}
if(disconnected) {
Serial.println(F("GPRS disconnected !"));
} else {
Serial.println(F("GPRS still connected !"));
}
// Go into low power mode
bool lowPowerMode = sim800l->setPowerMode(MINIMUM);
if(lowPowerMode) {
Serial.println(F("Module in low power mode"));
} else {
Serial.println(F("Failed to switch module to low power mode"));
}
// End of program... wait...
while(1);
}
void setupModule() {
// Wait until the module is ready to accept AT commands
while(!sim800l->isReady()) {
Serial.println(F("Problem to initialize AT command, retry in 1 sec"));
delay(1000);
}
Serial.println(F("Setup Complete!"));
// Wait for the GSM signal
uint8_t signal = sim800l->getSignal();
while(signal <= 0) {
delay(1000);
signal = sim800l->getSignal();
}
Serial.print(F("Signal OK (strenght: "));
Serial.print(signal);
Serial.println(F(")"));
delay(1000);
// Wait for operator network registration (national or roaming network)
NetworkRegistration network = sim800l->getRegistrationStatus();
while(network != REGISTERED_HOME && network != REGISTERED_ROAMING) {
delay(1000);
network = sim800l->getRegistrationStatus();
}
Serial.println(F("Network registration OK"));
delay(1000);
// Setup APN for GPRS configuration
bool success = sim800l->setupGPRS(APN);
while(!success) {
success = sim800l->setupGPRS(APN);
delay(5000);
}
Serial.println(F("GPRS config OK"));
}

160
libraries/SIM800L/examples/HTTPS_POST_SoftSerial/HTTPS_POST_SoftSerial.ino

@ -0,0 +1,160 @@
/********************************************************************************
* Example of HTTPS POST with SoftwareSerial and Arduino-SIM800L-driver *
* *
* Author: Olivier Staquet *
* Last version available on https://github.com/ostaquet/Arduino-SIM800L-driver *
********************************************************************************
* MIT License
*
* Copyright (c) 2019 Olivier Staquet
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*******************************************************************************/
#include <SoftwareSerial.h>
#include "SIM800L.h"
#define SIM800_RX_PIN 10
#define SIM800_TX_PIN 11
#define SIM800_RST_PIN 6
const char APN[] = "Internet.be";
const char URL[] = "https://postman-echo.com/post";
const char CONTENT_TYPE[] = "application/json";
const char PAYLOAD[] = "{\"name\": \"morpheus\", \"job\": \"leader\"}";
SIM800L* sim800l;
void setup() {
// Initialize Serial Monitor for debugging
Serial.begin(115200);
while(!Serial);
// Initialize a SoftwareSerial
SoftwareSerial* serial = new SoftwareSerial(SIM800_RX_PIN, SIM800_TX_PIN);
serial->begin(9600);
delay(1000);
// Initialize SIM800L driver with an internal buffer of 200 bytes and a reception buffer of 512 bytes, debug disabled
sim800l = new SIM800L((Stream *)serial, SIM800_RST_PIN, 200, 512);
// Equivalent line with the debug enabled on the Serial
// sim800l = new SIM800L((Stream *)&Serial1, SIM800_RST_PIN, 200, 512, (Stream *)&Serial);
// Setup module for GPRS communication
setupModule();
}
void loop() {
// Establish GPRS connectivity (5 trials)
bool connected = false;
for(uint8_t i = 0; i < 5 && !connected; i++) {
delay(1000);
connected = sim800l->connectGPRS();
}
// Check if connected, if not reset the module and setup the config again
if(connected) {
Serial.println(F("GPRS connected !"));
} else {
Serial.println(F("GPRS not connected !"));
Serial.println(F("Reset the module."));
sim800l->reset();
setupModule();
return;
}
Serial.println(F("Start HTTP POST..."));
// Do HTTP POST communication with 10s for the timeout (read and write)
uint16_t rc = sim800l->doPost(URL, CONTENT_TYPE, PAYLOAD, 10000, 10000);
if(rc == 200) {
// Success, output the data received on the serial
Serial.print(F("HTTP POST successful ("));
Serial.print(sim800l->getDataSizeReceived());
Serial.println(F(" bytes)"));
Serial.print(F("Received : "));
Serial.println(sim800l->getDataReceived());
} else {
// Failed...
Serial.print(F("HTTP POST error "));
Serial.println(rc);
}
// Close GPRS connectivity (5 trials)
bool disconnected = sim800l->disconnectGPRS();
for(uint8_t i = 0; i < 5 && !connected; i++) {
delay(1000);
disconnected = sim800l->disconnectGPRS();
}
if(disconnected) {
Serial.println(F("GPRS disconnected !"));
} else {
Serial.println(F("GPRS still connected !"));
}
// Go into low power mode
bool lowPowerMode = sim800l->setPowerMode(MINIMUM);
if(lowPowerMode) {
Serial.println(F("Module in low power mode"));
} else {
Serial.println(F("Failed to switch module to low power mode"));
}
// End of program... wait...
while(1);
}
void setupModule() {
// Wait until the module is ready to accept AT commands
while(!sim800l->isReady()) {
Serial.println(F("Problem to initialize AT command, retry in 1 sec"));
delay(1000);
}
Serial.println(F("Setup Complete!"));
// Wait for the GSM signal
uint8_t signal = sim800l->getSignal();
while(signal <= 0) {
delay(1000);
signal = sim800l->getSignal();
}
Serial.print(F("Signal OK (strenght: "));
Serial.print(signal);
Serial.println(F(")"));
delay(1000);
// Wait for operator network registration (national or roaming network)
NetworkRegistration network = sim800l->getRegistrationStatus();
while(network != REGISTERED_HOME && network != REGISTERED_ROAMING) {
delay(1000);
network = sim800l->getRegistrationStatus();
}
Serial.println(F("Network registration OK"));
delay(1000);
// Setup APN for GPRS configuration
bool success = sim800l->setupGPRS(APN);
while(!success) {
success = sim800l->setupGPRS(APN);
delay(5000);
}
Serial.println(F("GPRS config OK"));
}

BIN
libraries/SIM800L/extras/SIM800 Series_AT Command Manual_V1.09.pdf

Binary file not shown.

BIN
libraries/SIM800L/extras/SIM800 Series_IP_Application Note_V1.02.pdf

Binary file not shown.

BIN
libraries/SIM800L/extras/SIM800 Series_SSL_Application Note_V1.00.pdf

Binary file not shown.

12
libraries/SIM800L/keywords.txt

@ -0,0 +1,12 @@
# Syntax Coloring Map For Arduino-SIM800L-driver
# Datatypes (KEYWORD1)
SIM800L KEYWORD3
# Methods and Functions (KEYWORD2)
doGet KEYWORD2
doPost KEYWORD2
# Instances (KEYWORD2)
# Constants (LITERAL1)

11
libraries/SIM800L/library.properties

@ -0,0 +1,11 @@
name=SIM800L HTTP connector
version=1.13.2
author=Olivier Staquet
maintainer=Olivier Staquet
sentence=Library for GSM/GPRS module SIMCom SIM800L to make HTTP/S connections with GET and POST methods.
paragraph=This library supports power management, network registration, signal check, GPRS connectivity, HTTP/HTTPS protocols, GET/POST methods and software/hardware serials.
category=Communication
url=https://github.com/ostaquet/Arduino-SIM800L-driver
architectures=*
repository=https://github.com/ostaquet/Arduino-SIM800L-driver
license=MIT

935
libraries/SIM800L/src/SIM800L.cpp

@ -0,0 +1,935 @@
/********************************************************************************
* Arduino-SIM800L-driver *
* ---------------------- *
* Arduino driver for GSM/GPRS module SIMCom SIM800L to make HTTP/S connections *
* with GET and POST methods *
* Author: Olivier Staquet *
* Last version available on https://github.com/ostaquet/Arduino-SIM800L-driver *
********************************************************************************
* MIT License
*
* Copyright (c) 2019 Olivier Staquet
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*******************************************************************************/
#include "SIM800L.h"
/**
* AT commands required (const char in PROGMEM to save memory usage)
*/
const char AT_CMD_BASE[] PROGMEM = "AT"; // Basic AT command to check the link
const char AT_CMD_CSQ[] PROGMEM = "AT+CSQ"; // Check the signal strengh
const char AT_CMD_ATI[] PROGMEM = "ATI"; // Output version of the module
const char AT_CMD_GMR[] PROGMEM = "AT+GMR"; // Output version of the firmware
const char AT_CMD_SIM_CARD[] PROGMEM = "AT+CCID"; // Get Sim Card version
const char AT_CMD_CFUN_TEST[] PROGMEM = "AT+CFUN?"; // Check the current power mode
const char AT_CMD_CFUN0[] PROGMEM = "AT+CFUN=0"; // Switch minimum power mode
const char AT_CMD_CFUN1[] PROGMEM = "AT+CFUN=1"; // Switch normal power mode
const char AT_CMD_CFUN4[] PROGMEM = "AT+CFUN=4"; // Switch sleep power mode
const char AT_CMD_CREG_TEST[] PROGMEM = "AT+CREG?"; // Check the network registration status
const char AT_CMD_SAPBR_GPRS[] PROGMEM = "AT+SAPBR=3,1,\"Contype\",\"GPRS\""; // Configure the GPRS bearer
const char AT_CMD_SAPBR_APN[] PROGMEM = "AT+SAPBR=3,1,\"APN\","; // Configure the APN for the GPRS
const char AT_CMD_SAPBR1[] PROGMEM = "AT+SAPBR=1,1"; // Connect GPRS
const char AT_CMD_SAPBR0[] PROGMEM = "AT+SAPBR=0,1"; // Disconnect GPRS
const char AT_CMD_HTTPINIT[] PROGMEM = "AT+HTTPINIT"; // Init HTTP connection
const char AT_CMD_HTTPPARA_CID[] PROGMEM = "AT+HTTPPARA=\"CID\",1"; // Connect HTTP through GPRS bearer
const char AT_CMD_HTTPPARA_URL[] PROGMEM = "AT+HTTPPARA=\"URL\","; // Define the URL to connect in HTTP
const char AT_CMD_HTTPPARA_USERDATA[] PROGMEM = "AT+HTTPPARA=\"USERDATA\","; // Define the header(s)
const char AT_CMD_HTTPPARA_CONTENT[] PROGMEM = "AT+HTTPPARA=\"CONTENT\","; // Define the content type for the HTTP POST
const char AT_CMD_HTTPSSL_Y[] PROGMEM = "AT+HTTPSSL=1"; // Enable SSL for HTTP connection
const char AT_CMD_HTTPSSL_N[] PROGMEM = "AT+HTTPSSL=0"; // Disable SSL for HTTP connection
const char AT_CMD_HTTPACTION0[] PROGMEM = "AT+HTTPACTION=0"; // Launch HTTP GET action
const char AT_CMD_HTTPACTION1[] PROGMEM = "AT+HTTPACTION=1"; // Launch HTTP POST action
const char AT_CMD_HTTPREAD[] PROGMEM = "AT+HTTPREAD"; // Start reading HTTP return data
const char AT_CMD_HTTPTERM[] PROGMEM = "AT+HTTPTERM"; // Terminate HTTP connection
const char AT_RSP_OK[] PROGMEM = "OK"; // Expected answer OK
const char AT_RSP_DOWNLOAD[] PROGMEM = "DOWNLOAD"; // Expected answer DOWNLOAD
const char AT_RSP_HTTPREAD[] PROGMEM = "+HTTPREAD: "; // Expected answer HTTPREAD
/**
* Constructor; Init the driver, communication with the module and shared
* buffer used by the driver (to avoid multiples allocation)
*/
SIM800L::SIM800L(Stream* _stream, uint8_t _pinRst, uint16_t _internalBufferSize, uint16_t _recvBufferSize, Stream* _debugStream) {
// Store local variables
stream = _stream;
enableDebug = _debugStream != NULL;
debugStream = _debugStream;
pinReset = _pinRst;
if(pinReset != RESET_PIN_NOT_USED) {
// Setup the reset pin and force a reset of the module
pinMode(pinReset, OUTPUT);
reset();
}
// Prepare internal buffers
if(enableDebug) {
debugStream->print(F("SIM800L : Prepare internal buffer of "));
debugStream->print(_internalBufferSize);
debugStream->println(F(" bytes"));
}
internalBufferSize = _internalBufferSize;
internalBuffer = (char*) malloc(internalBufferSize);
if(enableDebug) {
debugStream->print(F("SIM800L : Prepare reception buffer of "));
debugStream->print(_recvBufferSize);
debugStream->println(F(" bytes"));
}
recvBufferSize = _recvBufferSize;
recvBuffer = (char *) malloc(recvBufferSize);
}
/**
* Destructor; cleanup the memory allocated by the driver
*/
SIM800L::~SIM800L() {
free(internalBuffer);
free(recvBuffer);
}
/**
* Do HTTP/S POST to a specific URL
*/
uint16_t SIM800L::doPost(const char* url, const char* contentType, const char* payload, uint16_t clientWriteTimeoutMs, uint16_t serverReadTimeoutMs) {
return doPost(url, NULL, contentType, payload, clientWriteTimeoutMs , serverReadTimeoutMs);
}
/**
* Do HTTP/S POST to a specific URL with headers
*/
uint16_t SIM800L::doPost(const char* url, const char* headers, const char* contentType, const char* payload, uint16_t clientWriteTimeoutMs, uint16_t serverReadTimeoutMs) {
// Cleanup the receive buffer
initRecvBuffer();
dataSize = 0;
// Initiate HTTP/S session with the module
uint16_t initRC = initiateHTTP(url, headers);
if(initRC > 0) {
return initRC;
}
// Define the content type
sendCommand_P(AT_CMD_HTTPPARA_CONTENT, contentType);
if(!readResponseCheckAnswer_P(DEFAULT_TIMEOUT, AT_RSP_OK)) {
if(enableDebug) debugStream->println(F("SIM800L : doPost() - Unable to define the content type"));
return 702;
}
// Prepare to send the payload
char* tmpBuf = (char*)malloc(30);
sprintf(tmpBuf, "AT+HTTPDATA=%d,%d", strlen(payload), clientWriteTimeoutMs);
sendCommand(tmpBuf);
free(tmpBuf);
if(!readResponseCheckAnswer_P(DEFAULT_TIMEOUT, AT_RSP_DOWNLOAD)) {
if(enableDebug) debugStream->println(F("SIM800L : doPost() - Unable to send payload to module"));
return 707;
}
// Write the payload on the module
if(enableDebug) {
debugStream->print(F("SIM800L : doPost() - Payload to send : "));
debugStream->println(payload);
}
purgeSerial();
stream->write(payload);
stream->flush();
delay(500);
// Start HTTP POST action
sendCommand_P(AT_CMD_HTTPACTION1);
if(!readResponseCheckAnswer_P(DEFAULT_TIMEOUT, AT_RSP_OK)) {
if(enableDebug) debugStream->println(F("SIM800L : doPost() - Unable to initiate POST action"));
return 703;
}
// Wait answer from the server
if(!readResponse(serverReadTimeoutMs)) {
if(enableDebug) debugStream->println(F("SIM800L : doPost() - Server timeout"));
return 408;
}
// Extract status information
int16_t idxBase = strIndex(internalBuffer, "+HTTPACTION: 1,");
if(idxBase < 0) {
if(enableDebug) debugStream->println(F("SIM800L : doPost() - Invalid answer on HTTP POST"));
return 703;
}
// Get the HTTP return code
uint16_t httpRC = 0;
httpRC += (internalBuffer[idxBase + 15] - '0') * 100;
httpRC += (internalBuffer[idxBase + 16] - '0') * 10;
httpRC += (internalBuffer[idxBase + 17] - '0') * 1;
if(enableDebug) {
debugStream->print(F("SIM800L : doPost() - HTTP status "));
debugStream->println(httpRC);
}
if(httpRC == 200) {
// Get the size of the data to receive
dataSize = 0;
for(uint16_t i = 0; (internalBuffer[idxBase + 19 + i] - '0') >= 0 && (internalBuffer[idxBase + 19 + i] - '0') <= 9; i++) {
if(i != 0) {
dataSize = dataSize * 10;
}
dataSize += (internalBuffer[idxBase + 19 + i] - '0');
}
if(enableDebug) {
debugStream->print(F("SIM800L : doPost() - Data size received of "));
debugStream->print(dataSize);
debugStream->println(F(" bytes"));
}
// Ask for reading and detect the start of the reading...
sendCommand_P(AT_CMD_HTTPREAD);
if(!readResponseCheckAnswer_P(DEFAULT_TIMEOUT, AT_RSP_HTTPREAD, 2)) {
return 705;
}
// Read number of bytes defined in the dataSize
for(uint16_t i = 0; i < dataSize && i < recvBufferSize; i++) {
while(!stream->available());
if(stream->available()) {
// Load the next char
recvBuffer[i] = stream->read();
// If the character is CR or LF, ignore it (it's probably part of the module communication schema)
if((recvBuffer[i] == '\r') || (recvBuffer[i] == '\n')) {
i--;
}
}
}
if(recvBufferSize < dataSize) {
dataSize = recvBufferSize;
if(enableDebug) {
debugStream->println(F("SIM800L : doPost() - Buffer overflow while loading data from HTTP. Keep only first bytes..."));
}
}
// We are expecting a final OK
if(!readResponseCheckAnswer_P(DEFAULT_TIMEOUT, AT_RSP_OK)) {
if(enableDebug) debugStream->println(F("SIM800L : doPost() - Invalid end of data while reading HTTP result from the module"));
return 705;
}
if(enableDebug) {
debugStream->print(F("SIM800L : doPost() - Received from HTTP POST : "));
debugStream->println(recvBuffer);
}
}
// Terminate HTTP/S session
uint16_t termRC = terminateHTTP();
if(termRC > 0) {
return termRC;
}
return httpRC;
}
/**
* Do HTTP/S GET on a specific URL
*/
uint16_t SIM800L::doGet(const char* url, uint16_t serverReadTimeoutMs) {
return doGet(url, NULL, serverReadTimeoutMs);
}
/**
* Do HTTP/S GET on a specific URL with headers
*/
uint16_t SIM800L::doGet(const char* url, const char* headers, uint16_t serverReadTimeoutMs) {
// Cleanup the receive buffer
initRecvBuffer();
dataSize = 0;
// Initiate HTTP/S session
uint16_t initRC = initiateHTTP(url, headers);
if(initRC > 0) {
return initRC;
}
// Start HTTP GET action
sendCommand_P(AT_CMD_HTTPACTION0);
if(!readResponseCheckAnswer_P(DEFAULT_TIMEOUT, AT_RSP_OK)) {
if(enableDebug) debugStream->println(F("SIM800L : doGet() - Unable to initiate GET action"));
return 703;
}
// Wait answer from the server
if(!readResponse(serverReadTimeoutMs)) {
if(enableDebug) debugStream->println(F("SIM800L : doGet() - Server timeout"));
return 408;
}
// Extract status information
int16_t idxBase = strIndex(internalBuffer, "+HTTPACTION: 0,");
if(idxBase < 0) {
if(enableDebug) debugStream->println(F("SIM800L : doGet() - Invalid answer on HTTP GET"));
return 703;
}
// Get the HTTP return code
uint16_t httpRC = 0;
httpRC += (internalBuffer[idxBase + 15] - '0') * 100;
httpRC += (internalBuffer[idxBase + 16] - '0') * 10;
httpRC += (internalBuffer[idxBase + 17] - '0') * 1;
if(enableDebug) {
debugStream->print(F("SIM800L : doGet() - HTTP status "));
debugStream->println(httpRC);
}
if(httpRC == 200) {
// Get the size of the data to receive
dataSize = 0;
for(uint16_t i = 0; (internalBuffer[idxBase + 19 + i] - '0') >= 0 && (internalBuffer[idxBase + 19 + i] - '0') <= 9; i++) {
if(i != 0) {
dataSize = dataSize * 10;
}
dataSize += (internalBuffer[idxBase + 19 + i] - '0');
}
if(enableDebug) {
debugStream->print(F("SIM800L : doGet() - Data size received of "));
debugStream->print(dataSize);
debugStream->println(F(" bytes"));
}
// Ask for reading and detect the start of the reading...
sendCommand_P(AT_CMD_HTTPREAD);
if(!readResponseCheckAnswer_P(DEFAULT_TIMEOUT, AT_RSP_HTTPREAD, 2)) {
return 705;
}
// Read number of bytes defined in the dataSize
for(uint16_t i = 0; i < dataSize && i < recvBufferSize; i++) {
while(!stream->available());
if(stream->available()) {
// Load the next char
recvBuffer[i] = stream->read();
// If the character is CR or LF, ignore it (it's probably part of the module communication schema)
if((recvBuffer[i] == '\r') || (recvBuffer[i] == '\n')) {
i--;
}
}
}
if(recvBufferSize < dataSize) {
dataSize = recvBufferSize;
if(enableDebug) {
debugStream->println(F("SIM800L : doGet() - Buffer overflow while loading data from HTTP. Keep only first bytes..."));
}
}
// We are expecting a final OK
if(!readResponseCheckAnswer_P(DEFAULT_TIMEOUT, AT_RSP_OK)) {
if(enableDebug) debugStream->println(F("SIM800L : doGet() - Invalid end of data while reading HTTP result from the module"));
return 705;
}
if(enableDebug) {
debugStream->print(F("SIM800L : doGet() - Received from HTTP GET : "));
debugStream->println(recvBuffer);
}
}
// Terminate HTTP/S session
uint16_t termRC = terminateHTTP();
if(termRC > 0) {
return termRC;
}
return httpRC;
}
/**
* Meta method to initiate the HTTP/S session on the module
*/
uint16_t SIM800L::initiateHTTP(const char* url, const char* headers) {
// Init HTTP connection
sendCommand_P(AT_CMD_HTTPINIT);
if(!readResponseCheckAnswer_P(DEFAULT_TIMEOUT, AT_RSP_OK)) {
if(enableDebug) debugStream->println(F("SIM800L : initiateHTTP() - Unable to init HTTP"));
return 701;
}
// Use the GPRS bearer
sendCommand_P(AT_CMD_HTTPPARA_CID);
if(!readResponseCheckAnswer_P(DEFAULT_TIMEOUT, AT_RSP_OK)) {
if(enableDebug) debugStream->println(F("SIM800L : initiateHTTP() - Unable to define bearer"));
return 702;
}
// Define URL to look for
sendCommand_P(AT_CMD_HTTPPARA_URL, url);
if(!readResponseCheckAnswer_P(DEFAULT_TIMEOUT, AT_RSP_OK)) {
if(enableDebug) debugStream->println(F("SIM800L : initiateHTTP() - Unable to define the URL"));
return 702;
}
// Set Headers
if (headers != NULL) {
sendCommand_P(AT_CMD_HTTPPARA_USERDATA, headers);
if(!readResponseCheckAnswer_P(DEFAULT_TIMEOUT, AT_RSP_OK)) {
if(enableDebug) debugStream->println(F("SIM800L : initiateHTTP() - Unable to define Headers"));
return 702;
}
}
// Check if the firmware support HTTPSSL command
bool isSupportSSL = false;
char* version = getVersion();
int16_t rIdx = strIndex(version, "R");
if(rIdx > 0) {
uint8_t releaseInt = (version[rIdx + 1] - '0') * 10 + (version[rIdx + 2] - '0');
// The release should be greater or equals to 14 to support SSL stack
if(releaseInt >= 14) {
isSupportSSL = true;
if(enableDebug) debugStream->println(F("SIM800L : initiateHTTP() - Support of SSL enabled"));
} else {
isSupportSSL = false;
if(enableDebug) debugStream->println(F("SIM800L : initiateHTTP() - Support of SSL disabled (SIM800L firware below R14)"));
}
}
// Send HTTPSSL command only if the version is greater or equals to 14
if(isSupportSSL) {
// HTTP or HTTPS
if(strIndex(url, "https://") == 0) {
sendCommand_P(AT_CMD_HTTPSSL_Y);
if(!readResponseCheckAnswer_P(DEFAULT_TIMEOUT, AT_RSP_OK)) {
if(enableDebug) debugStream->println(F("SIM800L : initiateHTTP() - Unable to switch to HTTPS"));
return 702;
}
} else {
sendCommand_P(AT_CMD_HTTPSSL_N);
if(!readResponseCheckAnswer_P(DEFAULT_TIMEOUT, AT_RSP_OK)) {
if(enableDebug) debugStream->println(F("SIM800L : initiateHTTP() - Unable to switch to HTTP"));
return 702;
}
}
}
return 0;
}
/**
* Meta method to terminate the HTTP/S session on the module
*/
uint16_t SIM800L::terminateHTTP() {
// Close HTTP connection
sendCommand_P(AT_CMD_HTTPTERM);
if(!readResponseCheckAnswer_P(DEFAULT_TIMEOUT, AT_RSP_OK)) {
if(enableDebug) debugStream->println(F("SIM800L : terminateHTTP() - Unable to close HTTP session"));
return 706;
}
return 0;
}
/**
* Force a reset of the module
*/
void SIM800L::reset() {
if(pinReset != RESET_PIN_NOT_USED)
{
// Some logging
if(enableDebug) debugStream->println(F("SIM800L : Reset"));
// Reset the device
digitalWrite(pinReset, HIGH);
delay(500);
digitalWrite(pinReset, LOW);
delay(500);
digitalWrite(pinReset, HIGH);
delay(1000);
} else {
// Some logging
if(enableDebug) debugStream->println(F("SIM800L : Reset requested but reset pin undefined"));
if(enableDebug) debugStream->println(F("SIM800L : No reset"));
}
// Purge the serial
stream->flush();
while (stream->available()) {
stream->read();
}
}
/**
* Return the size of data received after the last successful HTTP connection
*/
uint16_t SIM800L::getDataSizeReceived() {
return dataSize;
}
/**
* Return the buffer of data received after the last successful HTTP connection
*/
char* SIM800L::getDataReceived() {
return recvBuffer;
}
/**
* Status function: Check if AT command works
*/
bool SIM800L::isReady() {
sendCommand_P(AT_CMD_BASE);
return readResponseCheckAnswer_P(DEFAULT_TIMEOUT, AT_RSP_OK);
}
/**
* Status function: Check the power mode
*/
PowerMode SIM800L::getPowerMode() {
sendCommand_P(AT_CMD_CFUN_TEST);
if(readResponse(DEFAULT_TIMEOUT)) {
// Check if there is an error
int16_t errIdx = strIndex(internalBuffer, "ERROR");
if(errIdx > 0) {
return POW_ERROR;
}
// Extract the value
int16_t idx = strIndex(internalBuffer, "+CFUN: ");
char value = internalBuffer[idx + 7];
// Prepare the clear output
switch(value) {
case '0' : return MINIMUM;
case '1' : return NORMAL;
case '4' : return SLEEP;
default : return POW_UNKNOWN;
}
}
return POW_ERROR;
}
/**
* Status function: Get version of the module
*/
char* SIM800L::getVersion() {
sendCommand_P(AT_CMD_ATI);
if(readResponse(DEFAULT_TIMEOUT)) {
// Extract the value
int16_t idx = strIndex(internalBuffer, "SIM");
int16_t idxEnd = strIndex(internalBuffer, "\r", idx+1);
// Store it on the recv buffer (not used at the moment)
initRecvBuffer();
for(uint16_t i = 0; i < idxEnd - idx; i++) {
recvBuffer[i] = internalBuffer[idx + i];
}
return getDataReceived();
} else {
return NULL;
}
}
/**
* Status function: Get firmware version
*/
char* SIM800L::getFirmware() {
sendCommand_P(AT_CMD_GMR);
if(readResponse(DEFAULT_TIMEOUT)) {
// Extract the value
int16_t idx = strIndex(internalBuffer, "AT+GMR") + 9;
int16_t idxEnd = strIndex(internalBuffer, "\r", idx+1);
// Store it on the recv buffer (not used at the moment)
initRecvBuffer();
for(uint16_t i = 0; i < idxEnd - idx; i++) {
recvBuffer[i] = internalBuffer[idx + i];
}
return getDataReceived();
} else {
return NULL;
}
}
/**
* Status function: Requests the simcard number
*/
char* SIM800L::getSimCardNumber() {
sendCommand_P(AT_CMD_SIM_CARD);
if(readResponse(DEFAULT_TIMEOUT)) {
int16_t idx = strIndex(internalBuffer, "AT+CCID") + 10;
int16_t idxEnd = strIndex(internalBuffer, "\r", idx+1);
// Store it on the recv buffer (not used at the moment)
initRecvBuffer();
for(uint16_t i = 0; i < idxEnd - idx; i++) {
recvBuffer[i] = internalBuffer[idx + i];
}
return getDataReceived();
} else {
return NULL;
}
}
/**
* Status function: Check if the module is registered on the network
*/
NetworkRegistration SIM800L::getRegistrationStatus() {
sendCommand_P(AT_CMD_CREG_TEST);
if(readResponse(DEFAULT_TIMEOUT)) {
// Check if there is an error
int16_t errIdx = strIndex(internalBuffer, "ERROR");
if(errIdx > 0) {
return NET_ERROR;
}
// Extract the value
int16_t idx = strIndex(internalBuffer, "+CREG: ");
char value = internalBuffer[idx + 9];
// Prepare the clear output
switch(value) {
case '0' : return NOT_REGISTERED;
case '1' : return REGISTERED_HOME;
case '2' : return SEARCHING;
case '3' : return DENIED;
case '5' : return REGISTERED_ROAMING;
default : return NET_UNKNOWN;
}
}
return NET_ERROR;
}
/**
* Setup the GPRS connectivity
* As input, give the APN string of the operator
*/
bool SIM800L::setupGPRS(const char* apn) {
// Prepare the GPRS connection as the bearer
sendCommand_P(AT_CMD_SAPBR_GPRS);
if(!readResponseCheckAnswer_P(20000, AT_RSP_OK)) {
return false;
}
// Set the config of the bearer with the APN
sendCommand_P(AT_CMD_SAPBR_APN, apn);
return readResponseCheckAnswer_P(20000, AT_RSP_OK);
}
/**
* Open the GPRS connectivity
*/
bool SIM800L::connectGPRS() {
sendCommand_P(AT_CMD_SAPBR1);
// Timout is max 85 seconds according to SIM800 specifications
// We will wait for 65s to be within uint16_t
return readResponseCheckAnswer_P(65000, AT_RSP_OK);
}
/**
* Close the GPRS connectivity
*/
bool SIM800L::disconnectGPRS() {
sendCommand_P(AT_CMD_SAPBR0);
// Timout is max 65 seconds according to SIM800 specifications
return readResponseCheckAnswer_P(65000, AT_RSP_OK);
}
/**
* Define the power mode
* Available : MINIMUM, NORMAL, SLEEP
* Return true is the mode is correctly switched
*/
bool SIM800L::setPowerMode(PowerMode powerMode) {
// Check if the power mode requested is not ERROR or UNKNOWN
if(powerMode == POW_ERROR || powerMode == POW_UNKNOWN) {
return false;
}
// Check the current power mode
PowerMode currentPowerMode = getPowerMode();
// If the current power mode is undefined, abord
if(currentPowerMode == POW_ERROR || currentPowerMode == POW_UNKNOWN) {
return false;
}
// If the current power mode is the same that the requested power mode, say it's OK
if(currentPowerMode == powerMode) {
return true;
}
// If SLEEP or MINIMUM, only NORMAL is allowed
if((currentPowerMode == SLEEP || currentPowerMode == MINIMUM) && (powerMode != NORMAL)) {
return false;
}
// Send the command
char value;
switch(powerMode) {
case MINIMUM :
sendCommand_P(AT_CMD_CFUN0);
break;
case SLEEP :
sendCommand_P(AT_CMD_CFUN4);
break;
case NORMAL :
default :
sendCommand_P(AT_CMD_CFUN1);
}
// Read but don't care about the result
purgeSerial();
// Check the current power mode
currentPowerMode = getPowerMode();
// If the current power mode is the same that the requested power mode, say it's OK
return currentPowerMode == powerMode;
}
/**
* Status function: Check the strengh of the signal
*/
uint8_t SIM800L::getSignal() {
sendCommand_P(AT_CMD_CSQ);
if(readResponse(DEFAULT_TIMEOUT)) {
int16_t idxBase = strIndex(internalBuffer, "AT+CSQ");
if(idxBase != 0) {
return 0;
}
int16_t idxEnd = strIndex(internalBuffer, ",", idxBase);
uint8_t value = internalBuffer[idxEnd - 1] - '0';
if(internalBuffer[idxEnd - 2] != ' ') {
value += (internalBuffer[idxEnd - 2] - '0') * 10;
}
if(value > 31) {
return 0;
}
return value;
}
return 0;
}
/*****************************************************************************************
* HELPERS
*****************************************************************************************/
/**
* Find string "findStr" in another string "str"
* Returns true if found, false elsewhere
*/
int16_t SIM800L::strIndex(const char* str, const char* findStr, uint16_t startIdx) {
int16_t firstIndex = -1;
int16_t sizeMatch = 0;
for(int16_t i = startIdx; i < strlen(str); i++) {
if(sizeMatch >= strlen(findStr)) {
break;
}
if(str[i] == findStr[sizeMatch]) {
if(firstIndex < 0) {
firstIndex = i;
}
sizeMatch++;
} else {
firstIndex = -1;
sizeMatch = 0;
}
}
if(sizeMatch >= strlen(findStr)) {
return firstIndex;
} else {
return -1;
}
}
/**
* Init internal buffer
*/
void SIM800L::initInternalBuffer() {
for(uint16_t i = 0; i < internalBufferSize; i++) {
internalBuffer[i] = '\0';
}
}
/**
* Init recv buffer
*/
void SIM800L::initRecvBuffer() {
// Cleanup the receive buffer
for(uint16_t i = 0; i < recvBufferSize; i++) {
recvBuffer[i] = 0;
}
}
/*****************************************************************************************
* LOW LEVEL FUNCTIONS TO COMMUNICATE WITH THE SIM800L MODULE
*****************************************************************************************/
/**
* Send AT command to the module
*/
void SIM800L::sendCommand(const char* command) {
if(enableDebug) {
debugStream->print(F("SIM800L : Send \""));
debugStream->print(command);
debugStream->println(F("\""));
}
purgeSerial();
stream->write(command);
stream->write("\r\n");
purgeSerial();
}
/**
* Send AT command coming from the PROGMEM
*/
void SIM800L::sendCommand_P(const char* command) {
char cmdBuff[32];
strcpy_P(cmdBuff, command);
sendCommand(cmdBuff);
}
/**
* Send AT command to the module with a parameter
*/
void SIM800L::sendCommand(const char* command, const char* parameter) {
if(enableDebug) {
debugStream->print(F("SIM800L : Send \""));
debugStream->print(command);
debugStream->print(F("\""));
debugStream->print(parameter);
debugStream->print(F("\""));
debugStream->println(F("\""));
}
purgeSerial();
stream->write(command);
stream->write("\"");
stream->write(parameter);
stream->write("\"");
stream->write("\r\n");
purgeSerial();
}
/**
* Send AT command coming from the PROGMEM with a parameter
*/
void SIM800L::sendCommand_P(const char* command, const char* parameter) {
char cmdBuff[32];
strcpy_P(cmdBuff, command);
sendCommand(cmdBuff, parameter);
}
/**
* Purge the serial data
*/
void SIM800L::purgeSerial() {
stream->flush();
while (stream->available()) {
stream->read();
}
stream->flush();
}
/**
* Read from module and expect a specific answer (timeout in millisec)
*/
bool SIM800L::readResponseCheckAnswer_P(uint16_t timeout, const char* expectedAnswer, uint8_t crlfToWait) {
if(readResponse(timeout, crlfToWait)) {
// Prepare the local expected answer
char rspBuff[16];
strcpy_P(rspBuff, expectedAnswer);
// Check if it's the expected answer
int16_t idx = strIndex(internalBuffer, rspBuff);
if(idx > 0) {
return true;
}
}
return false;
}
/**
* Read from the module for a specific number of CRLF
* True if we have some data
*/
bool SIM800L::readResponse(uint16_t timeout, uint8_t crlfToWait) {
uint16_t currentSizeResponse = 0;
bool seenCR = false;
uint8_t countCRLF = 0;
// First of all, cleanup the buffer
initInternalBuffer();
uint32_t timerStart = millis();
while(1) {
// While there is data available on the buffer, read it until the max size of the response
if(stream->available()) {
// Load the next char
internalBuffer[currentSizeResponse] = stream->read();
// Detect end of transmission (CRLF)
if(internalBuffer[currentSizeResponse] == '\r') {
seenCR = true;
} else if (internalBuffer[currentSizeResponse] == '\n' && seenCR) {
countCRLF++;
if(countCRLF == crlfToWait) {
if(enableDebug) debugStream->println(F("SIM800L : End of transmission"));
break;
}
} else {
seenCR = false;
}
// Prepare for next read
currentSizeResponse++;
// Avoid buffer overflow
if(currentSizeResponse == internalBufferSize) {
if(enableDebug) debugStream->println(F("SIM800L : Received maximum buffer size"));
break;
}
}
// If timeout, abord the reading
if(millis() - timerStart > timeout) {
if(enableDebug) debugStream->println(F("SIM800L : Receive timeout"));
// Timeout, return false to parent function
return false;
}
}
if(enableDebug) {
debugStream->print(F("SIM800L : Receive \""));
debugStream->print(internalBuffer);
debugStream->println(F("\""));
}
// If we are here, it's OK ;-)
return true;
}

138
libraries/SIM800L/src/SIM800L.h

@ -0,0 +1,138 @@
/********************************************************************************
* Arduino-SIM800L-driver *
* ---------------------- *
* Arduino driver for GSM/GPRS module SIMCom SIM800L to make HTTP/S connections *
* with GET and POST methods *
* Author: Olivier Staquet *
* Last version available on https://github.com/ostaquet/Arduino-SIM800L-driver *
********************************************************************************
* MIT License
*
* Copyright (c) 2019 Olivier Staquet
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*******************************************************************************/
#ifndef _SIM800L_H_
#define _SIM800L_H_
#include <Arduino.h>
#define DEFAULT_TIMEOUT 5000
#define RESET_PIN_NOT_USED -1
enum PowerMode {MINIMUM, NORMAL, POW_UNKNOWN, SLEEP, POW_ERROR};
enum NetworkRegistration {NOT_REGISTERED, REGISTERED_HOME, SEARCHING, DENIED, NET_UNKNOWN, REGISTERED_ROAMING, NET_ERROR};
class SIM800L {
public:
// Initialize the driver
// Parameters:
// _stream : Stream opened to the SIM800L module (Software or Hardware, usually 9600 bps)
// _pinRst (optional) : pin to the reset of the SIM800L module
// _internalBufferSize (optional): size in bytes of the internal buffer to handle general IO with the module
// (including URL and maximum payload to send through POST method)
// _recvBufferSize (optional) : size in bytes of the reception buffer (max data to receive from GET or POST)
// _debugStream (optional) : Stream opened to the debug console (Software of Hardware)
SIM800L(Stream* _stream, uint8_t _pinRst = RESET_PIN_NOT_USED, uint16_t _internalBufferSize = 128, uint16_t _recvBufferSize = 256, Stream* _debugStream = NULL);
~SIM800L();
// Force a reset of the module
void reset();
// Status functions
bool isReady();
uint8_t getSignal();
PowerMode getPowerMode();
NetworkRegistration getRegistrationStatus();
char* getVersion();
char* getFirmware();
char* getSimCardNumber();
// Define the power mode (for parameter: see PowerMode enum)
bool setPowerMode(PowerMode powerMode);
// Enable/disable GPRS
bool setupGPRS(const char *apn);
bool connectGPRS();
bool disconnectGPRS();
// HTTP methods
uint16_t doGet(const char* url, uint16_t serverReadTimeoutMs);
uint16_t doGet(const char* url, const char* headers, uint16_t serverReadTimeoutMs);
uint16_t doPost(const char* url, const char* contentType, const char* payload, uint16_t clientWriteTimeoutMs, uint16_t serverReadTimeoutMs);
uint16_t doPost(const char* url, const char* headers, const char* contentType, const char* payload, uint16_t clientWriteTimeoutMs, uint16_t serverReadTimeoutMs);
// Obtain results after HTTP successful connections (size and buffer)
uint16_t getDataSizeReceived();
char* getDataReceived();
protected:
// Send command
void sendCommand(const char* command);
// Send comment from PROGMEM
void sendCommand_P(const char* command);
// Send command with parameter within quotes (template : command"parameter")
void sendCommand(const char* command, const char* parameter);
// Send command with parameter within quotes from PROGMEM (template : command"parameter")
void sendCommand_P(const char* command, const char* parameter);
// Read from module (timeout in millisec)
bool readResponse(uint16_t timeout, uint8_t crlfToWait = 2);
// Read from module and expect a specific answer defined in PROGMEM (timeout in millisec)
bool readResponseCheckAnswer_P(uint16_t timeout, const char* expectedAnswer, uint8_t crlfToWait = 2);
// Purge the serial
void purgeSerial();
// Find string in another string
int16_t strIndex(const char* str, const char* findStr, uint16_t startIdx = 0);
// Manage internal buffer
void initInternalBuffer();
void initRecvBuffer();
// Initiate HTTP/S connection
uint16_t initiateHTTP(const char* url, const char* headers);
uint16_t terminateHTTP();
private:
// Serial line with SIM800L
Stream* stream = NULL;
// Serial console for the debug
Stream* debugStream = NULL;
// Details about the circuit: pins
uint8_t pinReset = 0;
// Internal memory for the shared buffer
// Used for all reception of message from the module
char *internalBuffer;
uint16_t internalBufferSize = 0;
// Reception buffer
char *recvBuffer;
uint16_t recvBufferSize = 0;
uint16_t dataSize = 0;
// Enable debug mode
bool enableDebug = false;
};
#endif // _SIM800L_H_
Loading…
Cancel
Save