Let GPRS connected && Include SIM800L library (because of local edits)
Signed-off-by: Martin Kolací <martin.kolaci@lmc.eu>
This commit is contained in:
@@ -112,13 +112,13 @@ void BoardInterface::loadSettings() {
|
||||
liveData->settings.sdcardEnabled = 0;
|
||||
liveData->settings.sdcardAutstartLog = 1;
|
||||
liveData->settings.gprsEnabled = 0;
|
||||
tmpStr = "internet.t-mobile.cz";
|
||||
tmpStr = "not_set";
|
||||
tmpStr.toCharArray(liveData->settings.gprsApn, tmpStr.length() + 1);
|
||||
// Remote upload
|
||||
liveData->settings.remoteUploadEnabled = 0;
|
||||
tmpStr = "http://api.example.com";
|
||||
tmpStr = "not_set";
|
||||
tmpStr.toCharArray(liveData->settings.remoteApiUrl, tmpStr.length() + 1);
|
||||
tmpStr = "example";
|
||||
tmpStr = "not_set";
|
||||
tmpStr.toCharArray(liveData->settings.remoteApiKey, tmpStr.length() + 1);
|
||||
liveData->settings.headlightsReminder = 0;
|
||||
|
||||
|
||||
945
SIM800L.cpp
Normal file
945
SIM800L.cpp
Normal file
@@ -0,0 +1,945 @@
|
||||
/********************************************************************************
|
||||
* 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_SAPBR2[] PROGMEM = "AT+SAPBR=2,1";
|
||||
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
|
||||
const char AT_RSP_SAPBR[] PROGMEM = "+SAPBR: 1,1,"; // Expected answer SAPBR:1,1
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if GPRS is connected
|
||||
*/
|
||||
bool SIM800L::isConnectedGPRS() {
|
||||
sendCommand_P(AT_CMD_SAPBR2);
|
||||
return readResponseCheckAnswer_P(65000, AT_RSP_SAPBR);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
139
SIM800L.h
Normal file
139
SIM800L.h
Normal file
@@ -0,0 +1,139 @@
|
||||
/********************************************************************************
|
||||
* 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 isConnectedGPRS();
|
||||
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_
|
||||
22
evDash.ino
22
evDash.ino
@@ -420,6 +420,9 @@ bool sim800lSetup() {
|
||||
serial->begin(9600);
|
||||
sim800l = new SIM800L((Stream *)serial, SIM800L_RST, 512 , 512);
|
||||
|
||||
// SIM800L DebugMode:
|
||||
//sim800l = new SIM800L((Stream *)serial, SIM800L_RST, 512 , 512, (Stream *)&Serial);
|
||||
|
||||
bool sim800l_ready = sim800l->isReady();
|
||||
for (uint8_t i = 0; i < 5 && !sim800l_ready; i++) {
|
||||
Serial.println("Problem to initialize SIM800L module, retry in 1 sec");
|
||||
@@ -437,16 +440,16 @@ bool sim800lSetup() {
|
||||
|
||||
bool sim800l_gprs = sim800l->setupGPRS(liveData->settings.gprsApn);
|
||||
for (uint8_t i = 0; i < 5 && !sim800l_gprs; i++) {
|
||||
Serial.println("Problem to set GPRS connection, retry in 1 sec");
|
||||
Serial.println("Problem to set GPRS APN, retry in 1 sec");
|
||||
delay(1000);
|
||||
sim800l_gprs = sim800l->setupGPRS(liveData->settings.gprsApn);
|
||||
}
|
||||
|
||||
if (sim800l_gprs) {
|
||||
liveData->params.sim800l_enabled = true;
|
||||
Serial.println("GPRS OK");
|
||||
Serial.println("GPRS APN set OK");
|
||||
} else {
|
||||
Serial.println("Problem to set GPRS");
|
||||
Serial.println("Problem to set GPRS APN");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -458,23 +461,28 @@ bool sendDataViaGPRS() {
|
||||
|
||||
NetworkRegistration network = sim800l->getRegistrationStatus();
|
||||
if (network != REGISTERED_HOME && network != REGISTERED_ROAMING) {
|
||||
Serial.println("SIM800L module not connected to network!");
|
||||
Serial.println("SIM800L module not connected to network, skipping data send");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!sim800l->isConnectedGPRS()) {
|
||||
Serial.println("GPRS not connected... Connecting");
|
||||
bool connected = sim800l->connectGPRS();
|
||||
for (uint8_t i = 0; i < 5 && !connected; i++) {
|
||||
Serial.println("Problem to connect GPRS, retry in 1 sec");
|
||||
delay(1000);
|
||||
connected = sim800l->connectGPRS();
|
||||
}
|
||||
|
||||
if (!connected) {
|
||||
if(connected) {
|
||||
Serial.println("GPRS connected!");
|
||||
} else {
|
||||
Serial.println("GPRS not connected! Reseting SIM800L module!");
|
||||
sim800l->reset();
|
||||
sim800lSetup();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Serial.println("Start HTTP POST...");
|
||||
|
||||
@@ -513,8 +521,6 @@ bool sendDataViaGPRS() {
|
||||
Serial.println(rc);
|
||||
}
|
||||
|
||||
sim800l->disconnectGPRS();
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif //SIM800L_ENABLED
|
||||
|
||||
Reference in New Issue
Block a user