From 87af409c4debbc868c829feae3ea82a81e22b90d Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Tue, 12 Sep 2017 12:46:05 +0300 Subject: [PATCH] SSL/TLS support. Added GsmClientSecure. Fix #29 --- TinyGsmClientSIM800.h | 42 +++++++- examples/HttpsClient/HttpsClient.ino | 154 +++++++++++++++++++++++++++ keywords.txt | 1 + 3 files changed, 192 insertions(+), 5 deletions(-) create mode 100644 examples/HttpsClient/HttpsClient.ino diff --git a/TinyGsmClientSIM800.h b/TinyGsmClientSIM800.h index 6b50293..72a5b78 100644 --- a/TinyGsmClientSIM800.h +++ b/TinyGsmClientSIM800.h @@ -180,6 +180,24 @@ private: RxFifo rx; }; +class GsmClientSecure : public GsmClient +{ +public: + GsmClientSecure() {} + + GsmClientSecure(TinyGsm& modem, uint8_t mux = 1) + : GsmClient(modem, mux) + {} + +public: + virtual int connect(const char *host, uint16_t port) { + TINY_GSM_YIELD(); + rx.clear(); + sock_connected = at->modemConnect(host, port, mux, true); + return sock_connected; + } +}; + public: TinyGsm(Stream& stream) @@ -262,6 +280,14 @@ public: return res; } + bool hasSSL() { + sendAT(GF("+CIPSSL=?")); + if (waitResponse(GF(GSM_NL "+CIPSSL:")) != 1) { + return false; + } + return waitResponse() == 1; + } + /* * Power functions */ @@ -648,12 +674,17 @@ public: private: - bool modemConnect(const char* host, uint16_t port, uint8_t mux) { + bool modemConnect(const char* host, uint16_t port, uint8_t mux, bool ssl = false) { + sendAT(GF("+CIPSSL="), ssl); + int rsp = waitResponse(); + if (ssl && rsp != 1) { + return false; + } sendAT(GF("+CIPSTART="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port); - int rsp = waitResponse(75000L, - GF("CONNECT OK" GSM_NL), - GF("CONNECT FAIL" GSM_NL), - GF("ALREADY CONNECT" GSM_NL)); + rsp = waitResponse(75000L, + GF("CONNECT OK" GSM_NL), + GF("CONNECT FAIL" GSM_NL), + GF("ALREADY CONNECT" GSM_NL)); return (1 == rsp); } @@ -879,5 +910,6 @@ private: }; typedef TinyGsm::GsmClient TinyGsmClient; +typedef TinyGsm::GsmClientSecure TinyGsmClientSecure; #endif diff --git a/examples/HttpsClient/HttpsClient.ino b/examples/HttpsClient/HttpsClient.ino new file mode 100644 index 0000000..f91928d --- /dev/null +++ b/examples/HttpsClient/HttpsClient.ino @@ -0,0 +1,154 @@ +/************************************************************** + * + * This sketch connects to a website and downloads a page. + * It can be used to perform HTTP/RESTful API calls. + * + * For this example, you need to install ArduinoHttpClient library: + * https://github.com/arduino-libraries/ArduinoHttpClient + * or from http://librarymanager/all#ArduinoHttpClient + * + * TinyGSM Getting Started guide: + * http://tiny.cc/tiny-gsm-readme + * + **************************************************************/ + +// Select your modem +// SSL/TLS is currently supported only with SIM800 series +#define TINY_GSM_MODEM_SIM800 + +// Increase RX buffer +#define TINY_GSM_RX_BUFFER 64 + +// Use Hardware Serial on Mega, Leonardo, Micro +#define SerialAT Serial1 + +// or Software Serial on Uno, Nano +//#include +//SoftwareSerial SerialAT(2, 3); // RX, TX + +//#define DUMP_AT_COMMANDS +//#define TINY_GSM_DEBUG Serial + + +// Your GPRS credentials +// Leave empty, if missing user or pass +const char apn[] = "YourAPN"; +const char user[] = ""; +const char pass[] = ""; + +// Name of the server we want to connect to +const char server[] = "cdn.rawgit.com"; +const int port = 443; +// Path to download (this is the bit after the hostname in the URL) +const char resource[] = "/vshymanskyy/tinygsm/master/extras/logo.txt"; + +#include +#include + +#ifdef DUMP_AT_COMMANDS + #include + StreamDebugger debugger(SerialAT, Serial); + TinyGsm modem(debugger); +#else + TinyGsm modem(SerialAT); +#endif + +TinyGsmClientSecure client(modem); +HttpClient http(client, server, port); + +void setup() { + // Set console baud rate + Serial.begin(115200); + delay(10); + + // Set GSM module baud rate + SerialAT.begin(115200); + delay(3000); + + // Restart takes quite some time + // To skip it, call init() instead of restart() + Serial.println("Initializing modem..."); + modem.restart(); + + String modemInfo = modem.getModemInfo(); + Serial.print("Modem: "); + Serial.println(modemInfo); + + // Unlock your SIM card with a PIN + //modem.simUnlock("1234"); +} + +void loop() { + if (!modem.hasSSL()) { + Serial.print("SSL is not supported by this modem"); + delay(10000); + return; + } + + Serial.print(F("Waiting for network...")); + if (!modem.waitForNetwork()) { + Serial.println(" fail"); + delay(10000); + return; + } + Serial.println(" OK"); + + Serial.print(F("Connecting to ")); + Serial.print(apn); + if (!modem.gprsConnect(apn, user, pass)) { + Serial.println(" fail"); + delay(10000); + return; + } + Serial.println(" OK"); + + + Serial.print(F("Performing HTTP GET request... ")); + http.connectionKeepAlive(); // Currently, this is needed for HTTPS + int err = http.get(resource); + if (err != 0) { + Serial.println("failed to connect"); + delay(10000); + return; + } + + int status = http.responseStatusCode(); + Serial.println(status); + if (!status) { + delay(10000); + return; + } + + while (http.headerAvailable()) { + String headerName = http.readHeaderName(); + String headerValue = http.readHeaderValue(); + //Serial.println(headerName + " : " + headerValue); + } + + int length = http.contentLength(); + if (length >= 0) { + Serial.println(String("Content length is: ") + length); + } + if (http.isResponseChunked()) { + Serial.println("This response is chunked"); + } + + String body = http.responseBody(); + Serial.println("Response:"); + Serial.println(body); + + Serial.println(String("Body length is: ") + body.length()); + + // Shutdown + + http.stop(); + + modem.gprsDisconnect(); + Serial.println("GPRS disconnected"); + + // Do nothing forevermore + while (true) { + delay(1000); + } +} + diff --git a/keywords.txt b/keywords.txt index 5c6cd82..fa2df44 100644 --- a/keywords.txt +++ b/keywords.txt @@ -3,6 +3,7 @@ ####################################### TinyGsm KEYWORD1 TinyGsmClient KEYWORD1 +TinyGsmClientSecure KEYWORD1 SerialAT KEYWORD1 SerialMon KEYWORD1