@ -0,0 +1,438 @@ | |||||
/** | |||||
* @file TinyGsmClient.h | |||||
* @author Volodymyr Shymanskyy | |||||
* @license LGPL-3.0 | |||||
* @copyright Copyright (c) 2016 Volodymyr Shymanskyy | |||||
* @date Nov 2016 | |||||
*/ | |||||
#ifndef TinyGsmClient_h | |||||
#define TinyGsmClient_h | |||||
#if defined(SPARK) || defined(PARTICLE) | |||||
#include "Particle.h" | |||||
#elif defined(ARDUINO) | |||||
#if ARDUINO >= 100 | |||||
#include "Arduino.h" | |||||
#else | |||||
#include "WProgram.h" | |||||
#endif | |||||
#endif | |||||
#include <Client.h> | |||||
#include <TinyGsmFifo.h> | |||||
#if defined(__AVR__) | |||||
#define GSM_PROGMEM PROGMEM | |||||
typedef const __FlashStringHelper* GsmConstStr; | |||||
#define FP(x) (reinterpret_cast<GsmConstStr>(x)) | |||||
#else | |||||
#define GSM_PROGMEM | |||||
typedef const char* GsmConstStr; | |||||
#define FP(x) x | |||||
#undef F | |||||
#define F(x) x | |||||
#endif | |||||
//#define GSM_USE_HEX | |||||
#define GSM_RX_BUFFER 64 | |||||
#define GSM_NL "\r\n" | |||||
static constexpr char GSM_OK[] GSM_PROGMEM = "OK" GSM_NL; | |||||
static constexpr char GSM_ERROR[] GSM_PROGMEM = "ERROR" GSM_NL; | |||||
class TinyGsmClient | |||||
: public Client | |||||
{ | |||||
typedef TinyGsmFifo<uint8_t, GSM_RX_BUFFER> RxFifo; | |||||
#ifdef GSM_DEBUG | |||||
template<typename T> | |||||
void DBG(T last) { | |||||
GSM_DEBUG.println(last); | |||||
} | |||||
template<typename T, typename... Args> | |||||
void DBG(T head, Args... tail) { | |||||
GSM_DEBUG.print(head); | |||||
GSM_DEBUG.print(' '); | |||||
DBG(tail...); | |||||
} | |||||
#else | |||||
#define DBG(...) | |||||
#endif | |||||
public: | |||||
TinyGsmClient(Stream& stream, uint8_t mux = 1) | |||||
: stream(stream) | |||||
, mux(mux) | |||||
, sock_available(0) | |||||
, sock_connected(false) | |||||
{} | |||||
public: | |||||
virtual int connect(const char *host, uint16_t port) { | |||||
return modemConnect(host, port); | |||||
} | |||||
virtual int connect(IPAddress ip, uint16_t port) { | |||||
String host; host.reserve(16); | |||||
host += ip[0]; | |||||
host += "."; | |||||
host += ip[1]; | |||||
host += "."; | |||||
host += ip[2]; | |||||
host += "."; | |||||
host += ip[3]; | |||||
return modemConnect(host.c_str(), port); | |||||
} | |||||
virtual void stop() { | |||||
sendAT(F("+CIPCLOSE="), mux); | |||||
sock_connected = false; | |||||
waitResponse(); | |||||
} | |||||
virtual size_t write(const uint8_t *buf, size_t size) { | |||||
maintain(); | |||||
return modemSend(buf, size); | |||||
} | |||||
virtual size_t write(uint8_t c) { | |||||
return write(&c, 1); | |||||
} | |||||
virtual int available() { | |||||
maintain(); | |||||
size_t res = rx.size(); | |||||
if (res > 0) { | |||||
return res; | |||||
} | |||||
return sock_available; | |||||
} | |||||
virtual int read(uint8_t *buf, size_t size) { | |||||
maintain(); | |||||
size_t cnt = 0; | |||||
while (cnt < size) { | |||||
size_t chunk = min(size-cnt, rx.size()); | |||||
if (chunk > 0) { | |||||
rx.get(buf, chunk); | |||||
buf += chunk; | |||||
cnt += chunk; | |||||
} else { | |||||
modemRead(rx.free()); //TODO: min(rx.free(), sock_available) | |||||
} | |||||
} | |||||
return cnt; | |||||
} | |||||
virtual int read() { | |||||
uint8_t c; | |||||
if (read(&c, 1) == 1) { | |||||
return c; | |||||
} | |||||
return -1; | |||||
} | |||||
virtual int peek() { return -1; } //TODO | |||||
virtual void flush() { stream.flush(); } | |||||
virtual uint8_t connected() { | |||||
maintain(); | |||||
return sock_connected; | |||||
} | |||||
virtual operator bool() { return connected(); } | |||||
public: | |||||
bool factoryDefault() { | |||||
if (!autoBaud()) { | |||||
return false; | |||||
} | |||||
sendAT(F("&FZE0&W")); // Factory + Reset + Echo Off + Write | |||||
waitResponse(); | |||||
sendAT(F("+IPR=0")); // Auto-baud | |||||
waitResponse(); | |||||
sendAT(F("+IFC=0,0")); // No Flow Control | |||||
waitResponse(); | |||||
sendAT(F("+ICF=3,3")); // 8 data 0 parity 1 stop | |||||
waitResponse(); | |||||
sendAT(F("+CSCLK=0")); // Disable Slow Clock | |||||
waitResponse(); | |||||
sendAT(F("&W")); // Write configuration | |||||
return waitResponse() == 1; | |||||
} | |||||
bool restart() { | |||||
autoBaud(); | |||||
sendAT(F("+CFUN=0")); | |||||
if (waitResponse(10000L) != 1) { | |||||
return false; | |||||
} | |||||
sendAT(F("+CFUN=1,1")); | |||||
if (waitResponse(10000L) != 1) { | |||||
return false; | |||||
} | |||||
delay(3000); | |||||
autoBaud(); | |||||
sendAT(F("E0")); | |||||
if (waitResponse() != 1) { | |||||
return false; | |||||
} | |||||
return 1 == waitResponse(60000, F("Ready")); | |||||
} | |||||
bool networkConnect(const char* apn, const char* user, const char* pwd) { | |||||
autoBaud(); | |||||
// AT+CPIN=pin-code | |||||
// AT+CREG? | |||||
networkDisconnect(); | |||||
// AT+CGATT? | |||||
// AT+CGATT=1 | |||||
sendAT(F("+CIPMUX=1")); | |||||
if (waitResponse() != 1) { | |||||
return false; | |||||
} | |||||
sendAT(F("+CIPQSEND=1")); | |||||
if (waitResponse() != 1) { | |||||
return false; | |||||
} | |||||
sendAT(F("+CIPRXGET=1")); | |||||
if (waitResponse() != 1) { | |||||
return false; | |||||
} | |||||
sendAT(F("+CSTT=\""), apn, F("\",\""), user, F("\",\""), pwd, F("\"")); | |||||
if (waitResponse(60000L) != 1) { | |||||
return false; | |||||
} | |||||
sendAT(F("+CIICR")); | |||||
if (waitResponse(60000L) != 1) { | |||||
return false; | |||||
} | |||||
sendAT(F("+CIFSR;E0")); | |||||
String data; | |||||
if (waitResponse(10000L, data) != 1) { | |||||
data.replace(GSM_NL, ""); | |||||
return false; | |||||
} | |||||
sendAT(F("+CDNSCFG=\"8.8.8.8\",\"8.8.4.4\"")); | |||||
if (waitResponse() != 1) { | |||||
return false; | |||||
} | |||||
// AT+CIPSTATUS | |||||
return true; | |||||
} | |||||
bool networkDisconnect() { | |||||
sendAT(F("+CIPSHUT")); | |||||
return waitResponse(60000L) == 1; | |||||
} | |||||
bool autoBaud(unsigned long timeout = 10000L) { | |||||
for (unsigned long start = millis(); millis() - start < timeout; ) { | |||||
sendAT(""); | |||||
if (waitResponse() == 1) { | |||||
delay(100); | |||||
return true; | |||||
} | |||||
delay(100); | |||||
} | |||||
return false; | |||||
} | |||||
void maintain() { | |||||
while (stream.available()) { | |||||
waitResponse(10); | |||||
} | |||||
} | |||||
private: | |||||
int modemConnect(const char* host, uint16_t port) { | |||||
sendAT(F("+CIPSTART="), mux, ',', F("\"TCP"), F("\",\""), host, F("\","), port); | |||||
sock_connected = (1 == waitResponse(75000L, F("CONNECT OK" GSM_NL), F("CONNECT FAIL" GSM_NL), F("ALREADY CONNECT" GSM_NL))); | |||||
return sock_connected; | |||||
} | |||||
int modemSend(const void* buff, size_t len) { | |||||
sendAT(F("+CIPSEND="), mux, ',', len); | |||||
if (waitResponse(F(">")) != 1) { | |||||
return -1; | |||||
} | |||||
stream.write((uint8_t*)buff, len); | |||||
if (waitResponse(F(GSM_NL "DATA ACCEPT:")) != 1) { | |||||
return -1; | |||||
} | |||||
stream.readStringUntil(','); | |||||
String data = stream.readStringUntil('\n'); | |||||
return data.toInt(); | |||||
} | |||||
size_t modemRead(size_t size) { | |||||
#ifdef GSM_USE_HEX | |||||
sendAT(F("+CIPRXGET=3,"), mux, ',', size); | |||||
if (waitResponse(F("+CIPRXGET: 3,")) != 1) { | |||||
return 0; | |||||
} | |||||
#else | |||||
sendAT(F("+CIPRXGET=2,"), mux, ',', size); | |||||
if (waitResponse(F("+CIPRXGET: 2,")) != 1) { | |||||
return 0; | |||||
} | |||||
#endif | |||||
stream.readStringUntil(','); // Skip mux | |||||
size_t len = stream.readStringUntil(',').toInt(); | |||||
sock_available = stream.readStringUntil('\n').toInt(); | |||||
for (size_t i=0; i<len; i++) { | |||||
#ifdef GSM_USE_HEX | |||||
while (stream.available() < 2) { delay(1); } | |||||
char buf[4] = { 0, }; | |||||
buf[0] = stream.read(); | |||||
buf[1] = stream.read(); | |||||
char c = strtol(buf, NULL, 16); | |||||
#else | |||||
while (stream.available() < 1) { delay(1); } | |||||
char c = stream.read(); | |||||
#endif | |||||
rx.put(c); | |||||
} | |||||
waitResponse(); | |||||
return len; | |||||
} | |||||
size_t modemGetAvailable() { | |||||
sendAT(F("+CIPRXGET=4,"), mux); | |||||
size_t result = 0; | |||||
for (byte i = 0; i < 2; i++) { | |||||
int res = waitResponse(F("+CIPRXGET: 4"), FP(GSM_OK), FP(GSM_ERROR)); | |||||
if (res == 1) { | |||||
stream.readStringUntil(','); | |||||
stream.readStringUntil(','); | |||||
result = stream.readStringUntil('\n').toInt(); | |||||
} else if (res == 2) { | |||||
} else { | |||||
return result; | |||||
} | |||||
} | |||||
if (!result) { | |||||
sock_connected = modemGetConnected(); | |||||
} | |||||
return result; | |||||
} | |||||
bool modemGetConnected() { | |||||
sendAT(F("+CIPSTATUS="), mux); | |||||
int res = waitResponse(F(",\"CONNECTED\""), F(",\"CLOSED\""), F(",\"CLOSING\""), F(",\"INITIAL\"")); | |||||
waitResponse(); | |||||
return 1 == res; | |||||
} | |||||
/* Utilities */ | |||||
template<typename T> | |||||
void streamWrite(T last) { | |||||
stream.print(last); | |||||
} | |||||
template<typename T, typename... Args> | |||||
void streamWrite(T head, Args... tail) { | |||||
stream.print(head); | |||||
streamWrite(tail...); | |||||
} | |||||
int streamRead() { return stream.read(); } | |||||
void streamReadAll() { while(stream.available()) { stream.read(); } } | |||||
template<typename... Args> | |||||
void sendAT(Args... cmd) { | |||||
streamWrite("AT", cmd..., GSM_NL); | |||||
} | |||||
// TODO: Optimize this! | |||||
uint8_t waitResponse(uint32_t timeout, String& data, | |||||
GsmConstStr r1=FP(GSM_OK), GsmConstStr r2=FP(GSM_ERROR), | |||||
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) | |||||
{ | |||||
data.reserve(64); | |||||
bool gotNewData = false; | |||||
int index = 0; | |||||
for (unsigned long start = millis(); millis() - start < timeout; ) { | |||||
while (stream.available() > 0) { | |||||
int a = streamRead(); | |||||
if (a < 0) continue; //? | |||||
data += (char)a; | |||||
if (data.indexOf(r1) >= 0) { | |||||
index = 1; | |||||
goto finish; | |||||
} else if (r2 && data.indexOf(r2) >= 0) { | |||||
index = 2; | |||||
goto finish; | |||||
} else if (r3 && data.indexOf(r3) >= 0) { | |||||
index = 3; | |||||
goto finish; | |||||
} else if (r4 && data.indexOf(r4) >= 0) { | |||||
index = 4; | |||||
goto finish; | |||||
} else if (r5 && data.indexOf(r5) >= 0) { | |||||
index = 5; | |||||
goto finish; | |||||
} else if (data.indexOf(F(GSM_NL "+CIPRXGET: 1,1" GSM_NL)) >= 0) { //TODO: use mux | |||||
gotNewData = true; | |||||
data = ""; | |||||
} else if (data.indexOf(F(GSM_NL "1, CLOSED" GSM_NL)) >= 0) { //TODO: use mux | |||||
sock_connected = false; | |||||
data = ""; | |||||
} | |||||
} | |||||
} | |||||
finish: | |||||
if (!index) { | |||||
if (data.length()) { | |||||
DBG("### Unhandled:", data); | |||||
} | |||||
data = ""; | |||||
} | |||||
if (gotNewData) { | |||||
sock_available = modemGetAvailable(); | |||||
} | |||||
return index; | |||||
} | |||||
uint8_t waitResponse(uint32_t timeout, | |||||
GsmConstStr r1=FP(GSM_OK), GsmConstStr r2=FP(GSM_ERROR), | |||||
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) | |||||
{ | |||||
String data; | |||||
return waitResponse(timeout, data, r1, r2, r3, r4, r5); | |||||
} | |||||
uint8_t waitResponse(GsmConstStr r1=FP(GSM_OK), GsmConstStr r2=FP(GSM_ERROR), | |||||
GsmConstStr r3=NULL, GsmConstStr r4=NULL, GsmConstStr r5=NULL) | |||||
{ | |||||
return waitResponse(1000, r1, r2, r3, r4, r5); | |||||
} | |||||
private: | |||||
Stream& stream; | |||||
const uint8_t mux; | |||||
RxFifo rx; | |||||
uint16_t sock_available; | |||||
bool sock_connected; | |||||
}; | |||||
#endif |
@ -0,0 +1,136 @@ | |||||
#ifndef TinyGsmFifo_h | |||||
#define TinyGsmFifo_h | |||||
template <class T, unsigned N> | |||||
class TinyGsmFifo | |||||
{ | |||||
public: | |||||
TinyGsmFifo() | |||||
{ | |||||
clear(); | |||||
} | |||||
void clear() | |||||
{ | |||||
_r = 0; | |||||
_w = 0; | |||||
} | |||||
// writing thread/context API | |||||
//------------------------------------------------------------- | |||||
bool writeable(void) | |||||
{ | |||||
return free() > 0; | |||||
} | |||||
int free(void) | |||||
{ | |||||
int s = _r - _w; | |||||
if (s <= 0) | |||||
s += N; | |||||
return s - 1; | |||||
} | |||||
T put(const T& c) | |||||
{ | |||||
int i = _w; | |||||
int j = i; | |||||
i = _inc(i); | |||||
while (i == _r) // = !writeable() | |||||
/* nothing / just wait */; | |||||
_b[j] = c; | |||||
_w = i; | |||||
return c; | |||||
} | |||||
int put(const T* p, int n, bool t = false) | |||||
{ | |||||
int c = n; | |||||
while (c) | |||||
{ | |||||
int f; | |||||
while ((f = free()) == 0) // wait for space | |||||
{ | |||||
if (!t) return n - c; // no more space and not blocking | |||||
/* nothing / just wait */; | |||||
} | |||||
// check free space | |||||
if (c < f) f = c; | |||||
int w = _w; | |||||
int m = N - w; | |||||
// check wrap | |||||
if (f > m) f = m; | |||||
memcpy(&_b[w], p, f); | |||||
_w = _inc(w, f); | |||||
c -= f; | |||||
p += f; | |||||
} | |||||
return n - c; | |||||
} | |||||
// reading thread/context API | |||||
// -------------------------------------------------------- | |||||
bool readable(void) | |||||
{ | |||||
return (_r != _w); | |||||
} | |||||
size_t size(void) | |||||
{ | |||||
int s = _w - _r; | |||||
if (s < 0) | |||||
s += N; | |||||
return s; | |||||
} | |||||
T get(void) | |||||
{ | |||||
int r = _r; | |||||
while (r == _w) // = !readable() | |||||
/* nothing / just wait */; | |||||
T t = _b[r]; | |||||
_r = _inc(r); | |||||
return t; | |||||
} | |||||
int get(T* p, int n, bool t = false) | |||||
{ | |||||
int c = n; | |||||
while (c) | |||||
{ | |||||
int f; | |||||
for (;;) // wait for data | |||||
{ | |||||
f = size(); | |||||
if (f) break; // free space | |||||
if (!t) return n - c; // no space and not blocking | |||||
/* nothing / just wait */; | |||||
} | |||||
// check available data | |||||
if (c < f) f = c; | |||||
int r = _r; | |||||
int m = N - r; | |||||
// check wrap | |||||
if (f > m) f = m; | |||||
memcpy(p, &_b[r], f); | |||||
_r = _inc(r, f); | |||||
c -= f; | |||||
p += f; | |||||
} | |||||
return n - c; | |||||
} | |||||
private: | |||||
int _inc(int i, int n = 1) | |||||
{ | |||||
return (i + n) % N; | |||||
} | |||||
T _b[N]; | |||||
int _w; | |||||
int _r; | |||||
}; | |||||
#endif |
@ -0,0 +1,75 @@ | |||||
/************************************************************** | |||||
* | |||||
* For this example, you need to install Blynk library: | |||||
* https://github.com/blynkkk/blynk-library/releases/latest | |||||
* | |||||
* TinyGSM Getting Started guide: | |||||
* http://tiny.cc/tiny-gsm-readme | |||||
* | |||||
************************************************************** | |||||
* | |||||
* Blynk is a platform with iOS and Android apps to control | |||||
* Arduino, Raspberry Pi and the likes over the Internet. | |||||
* You can easily build graphic interfaces for all your | |||||
* projects by simply dragging and dropping widgets. | |||||
* | |||||
* Blynk supports many development boards with WiFi, Ethernet, | |||||
* GSM, Bluetooth, BLE, USB/Serial connection methods. | |||||
* See more in Blynk library examples and community forum. | |||||
* | |||||
* http://www.blynk.io/ | |||||
* | |||||
* Change GPRS apm, user, pass, and Blynk auth token to run :) | |||||
**************************************************************/ | |||||
#define BLYNK_PRINT Serial // Comment this out to disable prints and save space | |||||
// Default heartbeat interval for GSM is 60 | |||||
// If you want override this value, uncomment and set this option: | |||||
//#define BLYNK_HEARTBEAT 30 | |||||
#include <TinyGsmClient.h> | |||||
#include <BlynkSimpleSIM800.h> | |||||
// You should get Auth Token in the Blynk App. | |||||
// Go to the Project Settings (nut icon). | |||||
char auth[] = "YourAuthToken"; | |||||
// Your GPRS credentials | |||||
// Leave empty, if missing user or pass | |||||
char apn[] = "YourAPN"; | |||||
char user[] = ""; | |||||
char pass[] = ""; | |||||
// Hardware Serial on Mega, Leonardo, Micro | |||||
#define GsmSerial Serial1 | |||||
// or Software Serial on Uno, Nano | |||||
//#include <SoftwareSerial.h> | |||||
//SoftwareSerial GsmSerial(2, 3); // RX, TX | |||||
TinyGsmClient gsm(GsmSerial); | |||||
void setup() | |||||
{ | |||||
// Set console baud rate | |||||
Serial.begin(115200); | |||||
delay(10); | |||||
// Set GSM module baud rate | |||||
GsmSerial.begin(115200); | |||||
delay(3000); | |||||
// Restart takes quite some time | |||||
// You can skip it in many cases | |||||
Serial.println("Restarting modem..."); | |||||
gsm.restart(); | |||||
Blynk.begin(auth, gsm, apn, user, pass); | |||||
} | |||||
void loop() | |||||
{ | |||||
Blynk.run(); | |||||
} | |||||
@ -0,0 +1,153 @@ | |||||
/************************************************************** | |||||
* | |||||
* For this example, you need to install CRC32 library: | |||||
* https://github.com/vshymanskyy/CRC32.git | |||||
* | |||||
* TinyGSM Getting Started guide: | |||||
* http://tiny.cc/tiny-gsm-readme | |||||
* | |||||
**************************************************************/ | |||||
#include <TinyGsmClient.h> | |||||
#include <CRC32.h> | |||||
// Your GPRS credentials | |||||
// Leave empty, if missing user or pass | |||||
char apn[] = "YourAPN"; | |||||
char user[] = ""; | |||||
char pass[] = ""; | |||||
// Use Hardware Serial on Mega, Leonardo, Micro | |||||
#define GsmSerial Serial1 | |||||
// or Software Serial on Uno, Nano | |||||
//#include <SoftwareSerial.h> | |||||
//SoftwareSerial GsmSerial(2, 3); // RX, TX | |||||
TinyGsmClient client(GsmSerial); | |||||
char server[] = "cdn.rawgit.com"; | |||||
char resource[] = "/vshymanskyy/tinygsm/master/extras/test_10k.hex"; | |||||
uint32_t knownCRC32 = 0x54b3dcbf; | |||||
uint32_t knownFileSize = 10240; // In case server does not send it | |||||
void setup() { | |||||
// Set console baud rate | |||||
Serial.begin(115200); | |||||
delay(10); | |||||
// Set GSM module baud rate | |||||
GsmSerial.begin(115200); | |||||
delay(3000); | |||||
// Restart takes quite some time | |||||
// You can skip it in many cases | |||||
Serial.println("Restarting modem..."); | |||||
client.restart(); | |||||
} | |||||
void printPercent(uint32_t readLength, uint32_t contentLength) { | |||||
// If we know the total length | |||||
if (contentLength != -1) { | |||||
Serial.print(String("\r ") + ((100.0 * readLength) / contentLength) + "%"); | |||||
} else { | |||||
Serial.println(readLength); | |||||
} | |||||
} | |||||
void loop() { | |||||
Serial.print("Connecting to "); | |||||
Serial.print(apn); | |||||
if (!client.networkConnect(apn, user, pass)) { | |||||
Serial.println(" failed"); | |||||
delay(10000); | |||||
return; | |||||
} | |||||
Serial.println(" OK"); | |||||
Serial.print("Connecting to "); | |||||
Serial.print(server); | |||||
// if you get a connection, report back via serial: | |||||
if (!client.connect(server, 80)) { | |||||
Serial.println(" failed"); | |||||
delay(10000); | |||||
return; | |||||
} | |||||
Serial.println(" OK"); | |||||
// Make a HTTP request: | |||||
client.print(String("GET ") + resource + " HTTP/1.0\r\n"); | |||||
client.print(String("Host: ") + server + "\r\n"); | |||||
client.print("Connection: close\r\n\r\n"); | |||||
long timeout = millis(); | |||||
while (client.available() == 0) { | |||||
if (millis() - timeout > 5000L) { | |||||
Serial.println(">>> Client Timeout !"); | |||||
client.stop(); | |||||
delay(10000L); | |||||
return; | |||||
} | |||||
} | |||||
Serial.println("Reading response header"); | |||||
uint32_t contentLength = knownFileSize; | |||||
while (client.available()) { | |||||
String line = client.readStringUntil('\n'); | |||||
line.trim(); | |||||
//Serial.println(line); // Uncomment this to show response header | |||||
line.toLowerCase(); | |||||
if (line.startsWith("content-length:")) { | |||||
contentLength = line.substring(line.lastIndexOf(':') + 1).toInt(); | |||||
} else if (line.length() == 0) { | |||||
break; | |||||
} | |||||
} | |||||
Serial.println("Reading response data"); | |||||
timeout = millis(); | |||||
uint32_t readLength = 0; | |||||
CRC32 crc; | |||||
unsigned long timeElapsed = millis(); | |||||
printPercent(readLength, contentLength); | |||||
while (readLength < contentLength && client.connected() && millis() - timeout < 10000L) { | |||||
while (client.available()) { | |||||
uint8_t c = client.read(); | |||||
//Serial.print((char)c); // Uncomment this to show data | |||||
crc.update(c); | |||||
readLength++; | |||||
if (readLength % (contentLength / 13) == 0) { | |||||
printPercent(readLength, contentLength); | |||||
} | |||||
timeout = millis(); | |||||
} | |||||
} | |||||
printPercent(readLength, contentLength); | |||||
timeElapsed = millis() - timeElapsed; | |||||
Serial.println(); | |||||
client.stop(); | |||||
Serial.println("Server disconnected"); | |||||
client.networkDisconnect(); | |||||
Serial.println("GPRS disconnected"); | |||||
Serial.println(); | |||||
float timeSpent = float(timeElapsed) / 1000; | |||||
float theorLimit = ((8.0 * readLength) / 85.6) / 1000; | |||||
Serial.print("Content-Length: "); Serial.println(contentLength); | |||||
Serial.print("Actually read: "); Serial.println(readLength); | |||||
Serial.print("Calc. CRC32: 0x"); Serial.println(crc.finalize(), HEX); | |||||
Serial.print("Known CRC32: 0x"); Serial.println(knownCRC32, HEX); | |||||
Serial.print("Time spent: "); Serial.print(timeSpent); Serial.println("s"); | |||||
Serial.print("85.6kBps limit: "); Serial.print(theorLimit); Serial.println("s"); | |||||
// Do nothing forevermore | |||||
while (true) { | |||||
delay(1000); | |||||
} | |||||
} | |||||
@ -0,0 +1,130 @@ | |||||
/************************************************************** | |||||
* | |||||
* For this example, you need to install PubSubClient library: | |||||
* https://github.com/knolleary/pubsubclient/releases/latest | |||||
* | |||||
* TinyGSM Getting Started guide: | |||||
* http://tiny.cc/tiny-gsm-readme | |||||
* | |||||
************************************************************** | |||||
* Use Mosquitto client tools to work with MQTT | |||||
* Ubuntu/Linux: sudo apt-get install mosquitto-clients | |||||
* Windows: https://mosquitto.org/download/ | |||||
* | |||||
* Subscribe for messages: | |||||
* mosquitto_sub -h test.mosquitto.org -t GsmClientTest/init -t GsmClientTest/ledStatus -q 1 | |||||
* Toggle led: | |||||
* mosquitto_pub -h test.mosquitto.org -t GsmClientTest/led -q 1 -m "toggle" | |||||
* | |||||
* You can use Node-RED for wiring together MQTT-enabled devices | |||||
* https://nodered.org/ | |||||
* Also, take a look at these additional Node-RED modules: | |||||
* node-red-contrib-blynk-websockets | |||||
* node-red-dashboard | |||||
* | |||||
**************************************************************/ | |||||
#include <TinyGsmClient.h> | |||||
#include <PubSubClient.h> | |||||
// Your GPRS credentials | |||||
// Leave empty, if missing user or pass | |||||
char apn[] = "YourAPN"; | |||||
char user[] = ""; | |||||
char pass[] = ""; | |||||
// Use Hardware Serial on Mega, Leonardo, Micro | |||||
#define GsmSerial Serial1 | |||||
// or Software Serial on Uno, Nano | |||||
//#include <SoftwareSerial.h> | |||||
//SoftwareSerial GsmSerial(2, 3); // RX, TX | |||||
TinyGsmClient gsm(GsmSerial); | |||||
PubSubClient mqtt(gsm); | |||||
const char* broker = "test.mosquitto.org"; | |||||
const char* topicLed = "GsmClientTest/led"; | |||||
const char* topicInit = "GsmClientTest/init"; | |||||
const char* topicLedStatus = "GsmClientTest/ledStatus"; | |||||
#define LED_PIN 13 | |||||
int ledStatus = LOW; | |||||
long lastReconnectAttempt = 0; | |||||
void setup() { | |||||
pinMode(LED_PIN, OUTPUT); | |||||
// Set console baud rate | |||||
Serial.begin(115200); | |||||
delay(10); | |||||
// Set GSM module baud rate | |||||
GsmSerial.begin(115200); | |||||
delay(3000); | |||||
// Restart takes quite some time | |||||
// You can skip it in many cases | |||||
Serial.println("Restarting modem..."); | |||||
gsm.restart(); | |||||
Serial.print("Connecting to "); | |||||
Serial.print(apn); | |||||
if (!gsm.networkConnect(apn, user, pass)) { | |||||
Serial.println(" failed"); | |||||
while (true); | |||||
} | |||||
Serial.println(" OK"); | |||||
// MQTT Broker setup | |||||
mqtt.setServer(broker, 1883); | |||||
mqtt.setCallback(mqttCallback); | |||||
} | |||||
boolean mqttConnect() { | |||||
Serial.print("Connecting to "); | |||||
Serial.print(broker); | |||||
if (!mqtt.connect("GsmClientTest")) { | |||||
Serial.println(" failed"); | |||||
return false; | |||||
} | |||||
Serial.println(" OK"); | |||||
mqtt.publish(topicInit, "GsmClientTest started"); | |||||
mqtt.subscribe(topicLed); | |||||
return mqtt.connected(); | |||||
} | |||||
void loop() { | |||||
if (mqtt.connected()) { | |||||
mqtt.loop(); | |||||
} else { | |||||
// Reconnect every 10 seconds | |||||
unsigned long t = millis(); | |||||
if (t - lastReconnectAttempt > 10000L) { | |||||
lastReconnectAttempt = t; | |||||
if (mqttConnect()) { | |||||
lastReconnectAttempt = 0; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
void mqttCallback(char* topic, byte* payload, unsigned int len) { | |||||
Serial.print("Message arrived ["); | |||||
Serial.print(topic); | |||||
Serial.print("]: "); | |||||
Serial.write(payload, len); | |||||
Serial.println(); | |||||
// Only proceed if incoming message's topic matches | |||||
if (String(topic) == topicLed) { | |||||
ledStatus = !ledStatus; | |||||
digitalWrite(LED_PIN, ledStatus); | |||||
mqtt.publish(topicLedStatus, ledStatus ? "1" : "0"); | |||||
} | |||||
} | |||||
@ -0,0 +1,92 @@ | |||||
/************************************************************** | |||||
* | |||||
* This sketch connects to a website and downloads a page. | |||||
* It can be used to perform HTTP/RESTful API calls. | |||||
* | |||||
* TinyGSM Getting Started guide: | |||||
* http://tiny.cc/tiny-gsm-readme | |||||
* | |||||
**************************************************************/ | |||||
#include <TinyGsmClient.h> | |||||
// Your GPRS credentials | |||||
// Leave empty, if missing user or pass | |||||
char apn[] = "YourAPN"; | |||||
char user[] = ""; | |||||
char pass[] = ""; | |||||
// Use Hardware Serial on Mega, Leonardo, Micro | |||||
#define GsmSerial Serial1 | |||||
// or Software Serial on Uno, Nano | |||||
//#include <SoftwareSerial.h> | |||||
//SoftwareSerial GsmSerial(2, 3); // RX, TX | |||||
TinyGsmClient client(GsmSerial); | |||||
char server[] = "cdn.rawgit.com"; | |||||
char resource[] = "/vshymanskyy/tinygsm/master/extras/logo.txt"; | |||||
void setup() { | |||||
// Set console baud rate | |||||
Serial.begin(115200); | |||||
delay(10); | |||||
// Set GSM module baud rate | |||||
GsmSerial.begin(115200); | |||||
delay(3000); | |||||
// Restart takes quite some time | |||||
// You can skip it in many cases | |||||
Serial.println("Restarting modem..."); | |||||
client.restart(); | |||||
} | |||||
void loop() { | |||||
Serial.print("Connecting to "); | |||||
Serial.print(apn); | |||||
if (!client.networkConnect(apn, user, pass)) { | |||||
Serial.println(" failed"); | |||||
delay(10000); | |||||
return; | |||||
} | |||||
Serial.println(" OK"); | |||||
Serial.print("Connecting to "); | |||||
Serial.print(server); | |||||
if (!client.connect(server, 80)) { | |||||
Serial.println(" failed"); | |||||
delay(10000); | |||||
return; | |||||
} | |||||
Serial.println(" OK"); | |||||
// Make a HTTP GET request: | |||||
client.print(String("GET ") + resource + " HTTP/1.0\r\n"); | |||||
client.print(String("Host: ") + server + "\r\n"); | |||||
client.print("Connection: close\r\n\r\n"); | |||||
unsigned long timeout = millis(); | |||||
while (client.connected() && millis() - timeout < 10000L) { | |||||
// Print available data | |||||
while (client.available()) { | |||||
char c = client.read(); | |||||
Serial.print(c); | |||||
timeout = millis(); | |||||
} | |||||
} | |||||
Serial.println(); | |||||
client.stop(); | |||||
Serial.println("Server disconnected"); | |||||
client.networkDisconnect(); | |||||
Serial.println("GPRS disconnected"); | |||||
// Do nothing forevermore | |||||
while (true) { | |||||
delay(1000); | |||||
} | |||||
} | |||||