Open biswaKL opened 3 years ago
Not at present.
Here is support for HTTPS
See below code.
/* @file TinyGsmClientSIM7600.h @author Volodymyr Shymanskyy @license LGPL-3.0 @copyright Copyright (c) 2016 Volodymyr Shymanskyy @date Nov 2016 /
// #define TINY_GSM_DEBUG Serial // #define TINY_GSM_USE_HEX
static const char GSM_OK[] TINY_GSM_PROGMEM = "OK" GSM_NL; static const char GSM_ERROR[] TINY_GSM_PROGMEM = "ERROR" GSM_NL;
static const char GSM_CME_ERROR[] TINY_GSM_PROGMEM = GSM_NL "+CME ERROR:"; static const char GSM_CMS_ERROR[] TINY_GSM_PROGMEM = GSM_NL "+CMS ERROR:";
enum RegStatus { REG_NO_RESULT = -1, REG_UNREGISTERED = 0, REG_SEARCHING = 2, REG_DENIED = 3, REG_OK_HOME = 1, REG_OK_ROAMING = 5, REG_UNKNOWN = 4, };
class TinyGsmSim7600 : public TinyGsmModem
/*
Inner Client
*/
public: class GsmClientSim7600 : public GsmClient { friend class TinyGsmSim7600;
public:
GsmClientSim7600() {}
explicit GsmClientSim7600(TinyGsmSim7600& modem, uint8_t mux = 0) {
init(&modem, mux);
}
bool init(TinyGsmSim7600* modem, uint8_t mux = 0) {
this->at = modem;
sock_available = 0;
prev_check = 0;
sock_connected = false;
got_data = false;
if (mux < TINY_GSM_MUX_COUNT) {
this->mux = mux;
} else {
this->mux = (mux % TINY_GSM_MUX_COUNT);
}
at->sockets[this->mux] = this;
return true;
}
public:
virtual int connect(const char* host, uint16_t port, int timeout_s) {
DBG("connect called");
stop();
TINY_GSM_YIELD();
rx.clear();
sock_connected = at->modemConnect(host, port, mux, false, timeout_s);
return sock_connected;
}
TINY_GSM_CLIENT_CONNECT_OVERRIDES
void stop(uint32_t maxWaitMs) {
DBG("stop called");
dumpModemBuffer(maxWaitMs);
// at->sendAT(GF("+CIPCLOSE="), mux);
at->sendAT(GF("+CCHCLOSE=0"));//todo
// at->sendAT(GF("+CCHSTOP=0"));//todo
sock_connected = false;
DBG("stop waitResponse called");
at->waitResponse();
}
void stop() override {
stop(15000L);
}
/*
Extended API
*/
String remoteIP() TINY_GSM_ATTR_NOT_IMPLEMENTED;
};
public: explicit TinyGsmSim7600(Stream& stream) : stream(stream) { memset(sockets, 0, sizeof(sockets)); }
/*
Basic functions
*/
protected: bool initImpl(const char* pin = NULL) { DBG(GF("### TinyGSM Version:"), TINYGSM_VERSION); DBG(GF("### TinyGSM Compiled Module: TinyGsmClientSIM7600"));
if (!testAT()) {
return false;
}
sendAT(GF("E0")); // Echo Off
if (waitResponse() != 1) {
return false;
}
sendAT(GF("+CMEE=2")); // turn on verbose error codes
sendAT(GF("+CMEE=0")); // turn off error codes
waitResponse();
DBG(GF("### Modem:"), getModemName());
// Disable time and time zone URC's
sendAT(GF("+CTZR=0"));
if (waitResponse(10000L) != 1) {
return false;
}
// Enable automatic time zome update
sendAT(GF("+CTZU=1"));
if (waitResponse(10000L) != 1) {
return false;
}
SimStatus ret = getSimStatus();
// if the sim isn't ready and a pin has been provided, try to unlock the sim
if (ret != SIM_READY && pin != NULL && strlen(pin) > 0) {
simUnlock(pin);
return (getSimStatus() == SIM_READY);
} else {
// if the sim is ready, or it's locked but no pin has been provided,
// return true
return (ret == SIM_READY || ret == SIM_LOCKED);
}
}
String getModemNameImpl() {
String name = "SIMCom SIM7600";
sendAT(GF("+CGMM"));
String res2;
if (waitResponse(1000L, res2) != 1) {
return name;
}
res2.replace(GSM_NL "OK" GSM_NL, "");
res2.replace("_", " ");
res2.trim();
name = res2;
DBG("### Modem:", name);
return name;
}
bool factoryDefaultImpl() { // these commands aren't supported
return false;
}
/*
Power functions
*/
protected: bool restartImpl(const char* pin = NULL) { if (!testAT()) { return false; } sendAT(GF("+CRESET")); if (waitResponse(10000L) != 1) { return false; } delay(5000L); // TODO(?): Test this delay! return init(pin); }
bool powerOffImpl() {
sendAT(GF("+CPOF"));
return waitResponse() == 1;
}
bool radioOffImpl() {
if (!setPhoneFunctionality(4)) {
return false;
}
delay(5000L);
return true;
}
bool sleepEnableImpl(bool enable = true) {
sendAT(GF("+CSCLK="), enable);
return waitResponse() == 1;
}
bool setPhoneFunctionalityImpl(uint8_t fun, bool reset = false) {
sendAT(GF("+CFUN="), fun, reset ? ",1" : "");
return waitResponse(10000L) == 1;
}
/*
Generic network functions
*/
public: RegStatus getRegistrationStatus() { return (RegStatus)getRegistrationStatusXREG("CGREG"); }
protected: bool isNetworkConnectedImpl() { RegStatus s = getRegistrationStatus(); return (s == REG_OK_HOME || s == REG_OK_ROAMING); }
public: String getNetworkModes() { sendAT(GF("+CNMP=?")); if (waitResponse(GF(GSM_NL "+CNMP:")) != 1) { return ""; } String res = stream.readStringUntil('\n'); waitResponse(); return res; }
String setNetworkMode(uint8_t mode) {
sendAT(GF("+CNMP="), mode);
if (waitResponse(GF(GSM_NL "+CNMP:")) != 1) {
return "OK";
}
String res = stream.readStringUntil('\n');
waitResponse();
return res;
}
String getLocalIPImpl() {
sendAT(GF("+IPADDR")); // Inquire Socket PDP address
// sendAT(GF("+CGPADDR=1")); // Show PDP address
String res;
if (waitResponse(10000L, res) != 1) {
return "";
}
res.replace(GSM_NL "OK" GSM_NL, "");
res.replace(GSM_NL, "");
res.trim();
return res;
}
/*
GPRS functions
*/
protected: bool gprsConnectImpl(const char apn, const char user = NULL, const char* pwd = NULL) { gprsDisconnect(); // Make sure we're not connected first
sendAT(GF("+CGDCONT=1,\"IP\",\""), apn, '"');
waitResponse();
sendAT(GF("+CGPADDR"));
waitResponse();
sendAT(GF("+CIPMODE=0"));
waitResponse();
sendAT(GF("+CIPSENDMODE=0"));
waitResponse();
sendAT(GF("+CIPCCFG=10,0,0,0,1,0,30000"));
waitResponse();
sendAT(GF("+CIPTIMEOUT="), 30000, ',', 30000, ',', 30000);
waitResponse();
sendAT(GF("+NETOPEN"));
if (waitResponse(75000L,GF(GSM_NL "+NETOPEN: 0")) != 1)
{
DBG("+NETOPEN: 0 not found");
sendAT(GF("+NETOPEN"));
if (waitResponse(75000L,GF("+IP ERROR: Network is already opened")) != 1)
{
DBG("+IP ERROR: Network is already opened not found");
sendAT(GF(GSM_NL "+NETOPEN"));
if (waitResponse(75000L,GF("+IP ERROR: 4")) == 1)
{
DBG("+IP ERROR: 4 not found");
DBG("NET DEACTIVATED");
return false;
}
}
}
DBG("NET ACTIVATED");
delay(1000);
/*sendAT(GF("+IPADDR")); // Inquire Socket PDP address
if (waitResponse(120000L,GF(GSM_NL "+IP ERROR:")) == 1) {
DBG("IPADDRESS NOT FOUND");
return false;
}
DBG("IPADDRESS FOUND"); */
return true;
}
bool isGprsConnectedImpl() {
//AT+NETOPEN?
sendAT(GF("+NETOPEN?"));
if (waitResponse((GSM_NL "+NETOPEN: 1")) != 1) {
DBG("CHECK NET FAIL");
return false;
}
DBG("CHECK NET SUCCESS");
return true;
}
bool gprsDisconnectImpl() {
sendAT(GF("+NETCLOSE"));
if (waitResponse(GF(GSM_NL "+NETCLOSE: 0")) != 1) {
DBG("GPRS CLOSED");
return false;
}
DBG("GPRS OPENED");
return true;
}
/*
SIM card functions
*/
protected: // Gets the CCID of a sim card via AT+CCID String getSimCCIDImpl() { sendAT(GF("+CICCID")); if (waitResponse(GF(GSM_NL "+ICCID:")) != 1) { return ""; } String res = stream.readStringUntil('\n'); waitResponse(); res.trim(); return res; }
/*
Phone Call functions
*/
protected: bool callAnswerImpl() TINY_GSM_ATTR_NOT_IMPLEMENTED; bool callNumberImpl(const String& number) TINY_GSM_ATTR_NOT_IMPLEMENTED; bool callHangupImpl() TINY_GSM_ATTR_NOT_IMPLEMENTED; bool dtmfSendImpl(char cmd, int duration_ms = 100) TINY_GSM_ATTR_NOT_IMPLEMENTED;
/*
Messaging functions
*/
protected: // Follows all messaging functions per template
/*
GSM Location functions
*/
protected: // Can return a GSM-based location from CLBS as per the template
/*
GPS/GNSS/GLONASS location functions
*/
protected: // enable GPS bool enableGPSImpl() { sendAT(GF("+CGPS=1")); if (waitResponse() != 1) { return false; } return true; }
bool disableGPSImpl() {
sendAT(GF("+CGPS=0"));
if (waitResponse() != 1) {
return false;
}
return true;
}
// get the RAW GPS output
String getGPSrawImpl() {
sendAT(GF("+CGNSSINFO"));
if (waitResponse(GF(GSM_NL "+CGNSSINFO:")) != 1) {
return "";
}
String res = stream.readStringUntil('\n');
waitResponse();
res.trim();
return res;
}
// get GPS informations
bool getGPSImpl(float* lat, float* lon, float* speed = 0, float* alt = 0,
int* vsat = 0, int* usat = 0, float* accuracy = 0,
int* year = 0, int* month = 0, int* day = 0, int* hour = 0,
int* minute = 0, int* second = 0) {
sendAT(GF("+CGNSSINFO"));
if (waitResponse(GF(GSM_NL "+CGNSSINFO:")) != 1) {
return false;
}
uint8_t fixMode = streamGetIntBefore(','); // mode 2=2D Fix or 3=3DFix
// TODO(?) Can 1 be returned
if (fixMode == 1 || fixMode == 2 || fixMode == 3) {
// init variables
float ilat = 0;
char north;
float ilon = 0;
char east;
float ispeed = 0;
float ialt = 0;
int ivsat = 0;
int iusat = 0;
float iaccuracy = 0;
int iyear = 0;
int imonth = 0;
int iday = 0;
int ihour = 0;
int imin = 0;
float secondWithSS = 0;
streamSkipUntil(','); // GPS satellite valid numbers
streamSkipUntil(','); // GLONASS satellite valid numbers
streamSkipUntil(','); // BEIDOU satellite valid numbers
ilat = streamGetFloatBefore(','); // Latitude in ddmm.mmmmmm
north = stream.read(); // N/S Indicator, N=north or S=south
streamSkipUntil(',');
ilon = streamGetFloatBefore(','); // Longitude in ddmm.mmmmmm
east = stream.read(); // E/W Indicator, E=east or W=west
streamSkipUntil(',');
// Date. Output format is ddmmyy
iday = streamGetIntLength(2); // Two digit day
imonth = streamGetIntLength(2); // Two digit month
iyear = streamGetIntBefore(','); // Two digit year
// UTC Time. Output format is hhmmss.s
ihour = streamGetIntLength(2); // Two digit hour
imin = streamGetIntLength(2); // Two digit minute
secondWithSS =
streamGetFloatBefore(','); // 4 digit second with subseconds
ialt = streamGetFloatBefore(','); // MSL Altitude. Unit is meters
ispeed = streamGetFloatBefore(','); // Speed Over Ground. Unit is knots.
streamSkipUntil(','); // Course Over Ground. Degrees.
streamSkipUntil(','); // After set, will report GPS every x seconds
iaccuracy = streamGetFloatBefore(','); // Position Dilution Of Precision
streamSkipUntil(','); // Horizontal Dilution Of Precision
streamSkipUntil(','); // Vertical Dilution Of Precision
streamSkipUntil('\n'); // TODO(?) is one more field reported??
// Set pointers
if (lat != NULL)
*lat = (floor(ilat / 100) + fmod(ilat, 100.) / 60) *
(north == 'N' ? 1 : -1);
if (lon != NULL)
*lon = (floor(ilon / 100) + fmod(ilon, 100.) / 60) *
(east == 'E' ? 1 : -1);
if (speed != NULL) *speed = ispeed;
if (alt != NULL) *alt = ialt;
if (vsat != NULL) *vsat = ivsat;
if (usat != NULL) *usat = iusat;
if (accuracy != NULL) *accuracy = iaccuracy;
if (iyear < 2000) iyear += 2000;
if (year != NULL) *year = iyear;
if (month != NULL) *month = imonth;
if (day != NULL) *day = iday;
if (hour != NULL) *hour = ihour;
if (minute != NULL) *minute = imin;
if (second != NULL) *second = static_cast<int>(secondWithSS);
DBG("getGPSImpl waitResponse called true"); waitResponse(); return true; } DBG("getGPSImpl waitResponse called false"); waitResponse(); return false; }
/**
CGNSSMODE: <gnss_mode>,<dpo_mode>
This command is used to configure GPS, GLONASS, BEIDOU and QZSS support
mode. 0 : GLONASS 1 : BEIDOU 2 : GALILEO 3 : QZSS dpo_mode: 1 enable , 0
disable
*/
String setGNSSModeImpl(uint8_t mode, bool dpo) {
String res;
sendAT(GF("+CGNSSMODE="), mode, ",", dpo);
if (waitResponse(10000L, res) != 1) {
return "";
}
res.replace(GSM_NL, "");
res.trim();
return res;
}
uint8_t getGNSSModeImpl() {
sendAT(GF("+CGNSSMODE?"));
if (waitResponse(GF(GSM_NL "+CGNSSMODE:")) != 1) {
return 0;
}
return stream.readStringUntil(',').toInt();
}
/*
Time functions
*/
protected: // Can follow the standard CCLK function in the template
/*
Battery functions
*/
protected: // returns volts, multiply by 1000 to get mV uint16_t getBattVoltageImpl() { sendAT(GF("+CBC")); if (waitResponse(GF(GSM_NL "+CBC:")) != 1) { return 0; }
// get voltage in VOLTS
float voltage = streamGetFloatBefore('\n');
// Wait for final OK
waitResponse();
// Return millivolts
uint16_t res = voltage * 1000;
return res;
}
int8_t getBattPercentImpl() TINY_GSM_ATTR_NOT_AVAILABLE;
uint8_t getBattChargeStateImpl() TINY_GSM_ATTR_NOT_AVAILABLE;
bool getBattStatsImpl(uint8_t& chargeState, int8_t& percent,
uint16_t& milliVolts) {
chargeState = 0;
percent = 0;
milliVolts = getBattVoltage();
return true;
}
/*
Temperature functions
*/
protected: // get temperature in degree celsius uint16_t getTemperatureImpl() { sendAT(GF("+CPMUTEMP")); if (waitResponse(GF(GSM_NL "+CPMUTEMP:")) != 1) { return 0; } // return temperature in C uint16_t res = streamGetIntBefore('\n'); // Wait for final OK waitResponse(); return res; }
/*
Client related functions
*/
/* byte NTPServerSync(String server = "pool.ntp.org", byte TimeZone = 3) {
// Set GPRS bearer profile to associate with NTP sync
// sendAT(GF("+CNTPCID=1"));
// if (waitResponse(10000L) != 1) { return -1; }
// Set NTP server and timezone
sendAT(GF("+CNTP="), server, ',', String(TimeZone));
if (waitResponse(10000L) != 1) { return -1; }
// Request network synchronization
sendAT(GF("+CNTP"));
if (waitResponse(10000L, GF(GSM_NL "+CNTP:"))) {
String result = stream.readStringUntil('\n');
result.trim();
if (isValidNumber(result)) { return result.toInt(); }
} else {
return -1;
}
return -1;
} */
protected: bool _ssl = true; bool modemConnect(const char* host, uint16_t port, uint8_t mux, bool ssl = true, int timeout_s = 15) {
if (_ssl) {
sendAT(GF("+CSSLCFG=\"sslversion\",0,4"));
waitResponse();
sendAT(GF("+CSSLCFG=\"authmode\",0,2"));
waitResponse();
sendAT(GF("+CSSLCFG=\"ignorelocaltime\",0,1"));
waitResponse();
sendAT(GF("+CSSLCFG=\"negotiatetime\",0,25"));
waitResponse();
sendAT(GF("+CSSLCFG=\"cacert\",0,\"ca_cert.pem\""));
waitResponse();
sendAT(GF("+CSSLCFG=\"clientcert\",0,\"cert.pem\""));
waitResponse();
sendAT(GF("+CSSLCFG=\"clientkey\",0,\"key_cert.pem\""));
waitResponse();
sendAT(GF("+CCHSET=1,1"));
waitResponse();
sendAT(GF("+CCHSTART"));
waitResponse();
sendAT(GF("+CCHSSLCFG=0,0"));
waitResponse();
}
// Make sure we'll be getting data manually on this connection
// waitResponse();
// Establish a connection in multi-socket mode
uint32_t timeout_ms = ((uint32_t)timeout_s) * 1000;
if (!_ssl) {
sendAT(GF("+CIPRXGET=1"));
if (waitResponse() != 1) { return false; }
sendAT(GF("+CIPOPEN="), mux, ',', GF("\"TCP"), GF("\",\""), host, GF("\","), port);
}
else {
sendAT(GF("+CCHOPEN=0,"), GF("\""), host, GF("\","), port, GF(",2"));
}
// The reply is OK followed by +CIPOPEN: <link_num>,<err> where <link_num>
// is the mux number and <err> should be 0 if there's no error
if (!_ssl) {
if (waitResponse(timeout_ms, GF(GSM_NL "+CIPOPEN:")) != 1) {
return false;
}
}
else {
if (waitResponse(timeout_ms,GF(GSM_NL "+CCHOPEN: 0,0")) != 1) {
return false;
}
else{
return true;
}
}
/* uint8_t opened_mux = streamGetIntBefore(',');
uint8_t opened_result = streamGetIntBefore('\n');
if (opened_mux != mux || opened_result != 0)
{
DBG("return false;");
return false;
}
else
{
DBG("return TRUE;");
return true;
} */
}
int16_t modemSend(const void* buff, size_t len, uint8_t mux) {
DBG("modemSend called ");
if (!_ssl) {
sendAT(GF("+CIPSEND="), mux, ',', (uint16_t)len);
}
else {
sendAT(GF("+CCHSEND="), mux, ',', (uint16_t)len);
}
DBG("modemSend waitResponse> called "); if (waitResponse(GF(">")) != 1) { return 0; } SerialMon.print((const int )buff); stream.write(reinterpret_cast<const uint8_t*>(buff), len); stream.flush(); if (!_ssl) { if (waitResponse(GF(GSM_NL "+CIPSEND:")) != 1) { return 0; } } else { DBG("modemSend waitResponse CCHSEND called "); if (waitResponse(GF(GSM_NL "+CCHSEND:")) != 1) { return 0; } }
streamSkipUntil(','); // Skip mux
streamSkipUntil(','); // Skip requested bytes to send
// TODO(?): make sure requested and confirmed bytes match
return streamGetIntBefore('\n');
}
size_t modemRead(size_t size, uint8_t mux) {
DBG("modemRead called ");
int16_t len_requested = 0;
int16_t len_confirmed = 0;
if (!sockets[mux]) return 0;
if (!_ssl)
{
sendAT(GF("+CIPRXGET=3,"), mux, ',', (uint16_t)size);
if (waitResponse(GF("+CIPRXGET:")) != 1) {
return 0;
}
sendAT(GF("+CIPRXGET=2,"), mux, ',', (uint16_t)size);
if (waitResponse(GF("+CIPRXGET:")) != 1) {
return 0;
}
//+CIPRXGET: 2,1,5,11
streamSkipUntil(','); // Skip Rx mode 2/normal or 3/HEX 2,
streamSkipUntil(','); // Skip mux/cid (1,)
len_requested = streamGetIntBefore(',');//5,
// ^^ Requested number of data bytes (1-1460 bytes)to be read
len_confirmed = streamGetIntBefore('\n');//,11
}
else {
sendAT(GF("+CCHRECV="), mux, ',', (uint16_t)size);
DBG("modemRead CCHRECV called ");
if (waitResponse(GF("+CCHRECV:")) != 1) {
return 0;
}
// DATA,0,4
streamSkipUntil(','); //DATA,
streamSkipUntil(','); // Skip mux/cid (0,)
len_requested = streamGetIntBefore('\n');
// DBG("###len_requested", len_requested);
len_confirmed = len_requested;
}
// ^^ The data length which not read in the buffer
for (int i = 0; i < len_requested; i++) {
uint32_t startMillis = millis();
while (stream.available() < 2 &&
(millis() - startMillis < sockets[mux]->_timeout)) {
TINY_GSM_YIELD();
}
char buf[4] = {
0,
};
buf[0] = stream.read();
buf[1] = stream.read();
char c = strtol(buf, NULL, 16);
while (!stream.available() &&
(millis() - startMillis < sockets[mux]->_timeout)) {
TINY_GSM_YIELD();
}
char c = stream.read();
SerialMon.print(c);
sockets[mux]->rx.put(c);
}
// DBG("### READ:", len_requested, "from", mux);
sockets[mux]->sock_available = modemGetAvailable(mux);
// sockets[mux]->sock_available = len_confirmed;
if (!_ssl)
{
waitResponse();
}
return len_requested;
}
size_t modemGetAvailable(uint8_t mux) {
DBG("modemGetAvailable called ");
if (!sockets[mux]) return 0;
size_t result = 0;
if (!_ssl)
{
sendAT(GF("+CIPRXGET=4,"), mux);
if (waitResponse(GF("+CIPRXGET:")) == 1) {
streamSkipUntil(','); // Skip mode 4
streamSkipUntil(','); // Skip mux
result = streamGetIntBefore('\n');
waitResponse();
}
}
else
{
// AT+CCHRECV? +CCHRECV: LEN,<cache_len_0>,<cache_len_1>
sendAT(GF("+CCHRECV?"));
DBG("modemGetAvailable +CCHRECV? called ");
if (waitResponse(GF("+CCHRECV:")) == 1) {
streamSkipUntil(','); // Skip mode 4
result = streamGetIntBefore(',');
DBG("modemGetAvailable +CCHRECV?2 called ");
waitResponse();
}
}
DBG("### Available:", result, "on", mux);
if (!result) {
sockets[mux]->sock_connected = modemGetConnected(mux);
}
return result;
}
bool modemGetConnected(uint8_t mux) {
DBG("modemGetConnected called ");
// Read the status of all sockets at once
if (!_ssl)
{
sendAT(GF("+CIPCLOSE?"));
if (waitResponse(GF("+CIPCLOSE:")) != 1) {
return false; // TODO: Why does this not read correctly?
}
for (int muxNo = 0; muxNo < TINY_GSM_MUX_COUNT; muxNo++) {
// +CIPCLOSE:<link0_state>,<link1_state>,...,<link9_state>
bool muxState = stream.parseInt();
if (sockets[muxNo]) {
sockets[muxNo]->sock_connected = muxState;
}
}
waitResponse(); // Should be an OK at the end
if (!sockets[mux])
return false;
return sockets[mux]->sock_connected;
}
else {
sendAT(GF("+CCHOPEN?"));
DBG("modemGetConnected +CCHOPEN? waitResponsecalled ");
if (waitResponse(GF("+CCHOPEN:")) != 1) {
DBG("Modem not connectedXXXXXXXXXXXXXXXXX CCHOPEN Not Found");
return false;
}
//+CCHOPEN: 0,"",,,
streamSkipUntil(',');
String res = stream.readStringUntil(',');
if (res == "\"\"")
{
DBG("Modem not connectedXXXXXXXXXXXXXXXXX empty +CCHOPEN: 0,"",,, Found");
return false;
}
else {
DBG("************Modem is connected Found in sim7600 Library****************");
DBG("Dats is",res);
sockets[mux]->sock_connected = true;
waitResponse(); // Should be an OK at the end
sockets[mux]->sock_connected;
return true;
}
}
return false;
}
/*
Utilities
*/
public: // TODO(vshymanskyy): Optimize this! int8_t waitResponse(uint32_t timeout_ms, String& data, GsmConstStr r1 = GFP(GSM_OK), GsmConstStr r2 = GFP(GSM_ERROR),
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
GsmConstStr r5 = NULL) {
/* String r1s(r1); r1s.trim();
String r2s(r2); r2s.trim();
String r3s(r3); r3s.trim();
String r4s(r4); r4s.trim();
String r5s(r5); r5s.trim();
DBG("### ..:", r1s, ",", r2s, ",", r3s, ",", r4s, ",", r5s); */
data.reserve(64);
uint8_t index = 0;
uint32_t startMillis = millis();
do {
TINY_GSM_YIELD();
while (stream.available() > 0) {
TINY_GSM_YIELD();
int8_t a = stream.read();
if (a <= 0) continue; // Skip 0x00 bytes, just in case
data += static_cast<char>(a);
if (r1 && data.endsWith(r1)) {
index = 1;
goto finish;
} else if (r2 && data.endsWith(r2)) {
index = 2;
goto finish;
} else if (r3 && data.endsWith(r3)) {
if (r3 == GFP(GSM_CME_ERROR)) {
streamSkipUntil('\n'); // Read out the error
}
index = 3;
goto finish;
} else if (r4 && data.endsWith(r4)) {
index = 4;
goto finish;
} else if (r5 && data.endsWith(r5)) {
index = 5;
goto finish;
} else if (data.endsWith(GF(GSM_NL "+CIPRXGET:"))) {
int8_t mode = streamGetIntBefore(',');
if (mode == 1) {
int8_t mux = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
}
data = "";
// DBG("### Got Data:", mux);
} else {
// DBG("data += mode");
data += mode;
}
} else if (data.endsWith(GF(GSM_NL "+RECEIVE:"))) {
int8_t mux = streamGetIntBefore(',');
int16_t len = streamGetIntBefore('\n');
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->got_data = true;
if (len >= 0 && len <= 1024) {
sockets[mux]->sock_available = len;
}
}
data = "";
// DBG("### Got Data:", len, "on", mux);
}
else if (data.endsWith(GF(GSM_NL "+CCHRECV:"))) //+CCHRECV: DATA,0,4
{
DBG("*************data start**************");
//+CCHRECV: DATA, <session_id>,<len>
streamSkipUntil(','); // Skip DATA,
int8_t mux = streamGetIntBefore(',');//Skip 0,
int16_t len = streamGetIntBefore('\n');//Skip ,4
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
DBG("### Got_data = true");
sockets[mux]->got_data = true;
if (len >= 0 && len <= 1024) {
sockets[mux]->sock_available = len;
}
}
data = "";
DBG("### Got Data:", len, "on", mux);
DBG("**************data end*************");
}
else if (data.endsWith(GF("+IPCLOSE:"))) {
int8_t mux = streamGetIntBefore(',');
streamSkipUntil('\n'); // Skip the reason code
if (mux >= 0 && mux < TINY_GSM_MUX_COUNT && sockets[mux]) {
sockets[mux]->sock_connected = false;
}
data = "";
// DBG("### Closed: ", mux);
} else if (data.endsWith(GF("+CIPEVENT:"))) {
// Need to close all open sockets and release the network library.
// User will then need to reconnect.
// DBG("### Network error!");
if (!isGprsConnected()) {
gprsDisconnect();
}
data = "";
}
}
} while (millis() - startMillis < timeout_ms);
finish: if (!index) { data.trim(); if (data.length()) { DBG("*Unhandled**"); DBG(data); DBG("*Unhandled end**"); } } // DBG("###############data start2#################"); ////data.replace(GSM_NL, "/"); // DBG('<', index, '>', data); // data = ""; // DBG("##############data end2####################"); return index; }
int8_t waitResponse(uint32_t timeout_ms, GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
GsmConstStr r5 = NULL) {
String data;
return waitResponse(timeout_ms, data, r1, r2, r3, r4, r5);
}
int8_t waitResponse(GsmConstStr r1 = GFP(GSM_OK),
GsmConstStr r2 = GFP(GSM_ERROR),
GsmConstStr r3 = GFP(GSM_CME_ERROR),
GsmConstStr r4 = GFP(GSM_CMS_ERROR),
GsmConstStr r3 = NULL, GsmConstStr r4 = NULL,
GsmConstStr r5 = NULL) {
return waitResponse(1000, r1, r2, r3, r4, r5);
}
public: Stream& stream;
protected: GsmClientSim7600 sockets[TINY_GSM_MUX_COUNT]; const char gsmNL = GSM_NL; };
I got success in sending data to both aws and azure TLS 1.2...its going good.
Hello @ashwanisihag,
Would you accept to provide your TinyGsmClientSIM7600.h in raw format ? I'm trying to find something to support HTTPS on SIM7600, and I have difficulties to work with your file.
Do you implement the class TinyGsmClientSecure ?
Thanks
hi @ashwanisihag I'm trying to use your code but I can't make it work, could you please provide your raw file?
@ashwanisihag @erlo I made a fork of tinygsm and modified two files: TinyGsmClientSIM7600.h and TinyGsmClient.h, please check it out. I looked through code above and I got it working, so thank you a lot @ashwanisihag !! I'm using the sim7600 module to connect to a mosquitto broker using the secure port 8883. I tested it and it's working correctly, the esp32 connects to mosquitto broker successfully. In my case I do not use certificates on the esp32 so I commented the lines in the code. In the arduino script I declare the client as TinyGsmClientSecure client(modem);
I am glad that it worked.:-)
I found a relative easy way to make it support HTTPS. Check out this tutorial!
Hi @EmanueleFeola , i have the same problem you had with the same mqtt server configuration, i download from your repository the two files modified by you but when i compile i get exit status 1 error if i revert to the original files and set TinyGsmClient client(modem) i'm able to compile....i don't know what could be. please let me know
i activated the verbose level and it says: \Documents\Arduino\libraries\TinyGSM\src/TinyGsmClient.h:46:25: error: 'GsmClientSecureSIM7600' in 'class TinyGsmSim7600' does not name a type typedef TinyGsmSim7600::GsmClientSecureSIM7600 TinyGsmClientSecure;
ok found where is the problem: there is a SerialMon.print(c); left in the TinyGsmClientSIM7600.h downloaded from @EmanueleFeola tinygsm fork
@tradexsrl ok, so is the code working or you need some help?
At least I was able to compile the program , in the comeing days I'll test the program on lilygo board with MQTT on port 8883 If I have problems I will post a comment here Thanks
Hi @EmanueleFeola and @ashwanisihag Thank you for this patch - it works nicely on an ESP32 :) but I have a question: When making an HTTPS GET request, the request reliably works, but there is a strange delay.
Please see the output below:
Performing HTTPS GET request... [1063451] modemSend called
[1063462] modemSend waitResponse> called
[1063477] modemSend waitResponse CCHSEND called
[1065489] modemSend called
[1065490] modemSend waitResponse> called
[1065498] modemSend waitResponse CCHSEND called
[1067507] modemSend called
[1067508] modemSend waitResponse> called
[1067522] modemSend waitResponse CCHSEND called
[1069534] modemSend called
[1069535] modemSend waitResponse> called
[1069549] modemSend waitResponse CCHSEND called
[1071562] modemSend called
[1071563] modemSend waitResponse> called
[1071574] modemSend waitResponse CCHSEND called
[1073583] modemSend called
[1073584] modemSend waitResponse> called
[1073594] modemSend waitResponse CCHSEND called
[1075603] modemSend called
[1075604] modemSend waitResponse> called
[1075619] modemSend waitResponse CCHSEND called
[1077633] modemSend called
[1077634] modemSend waitResponse> called
[1077645] modemSend waitResponse CCHSEND called
[1079656] modemSend called
[1079657] modemSend waitResponse> called
[1079670] modemSend waitResponse CCHSEND called
[1081682] modemSend called
[1081683] modemSend waitResponse> called
[1081697] modemSend waitResponse CCHSEND called
[1083707] modemSend called
[1083708] modemSend waitResponse> called
[1083722] modemSend waitResponse CCHSEND called
[1085735] modemSend called
[1085736] modemSend waitResponse> called
[1085749] modemSend waitResponse CCHSEND called
[1087761] modemSend called
[1087762] modemSend waitResponse> called
[1087773] modemSend waitResponse CCHSEND called
[1089783] modemSend called
[1089784] modemSend waitResponse> called
[1089796] modemSend waitResponse CCHSEND called
[1091808] modemSend called
[1091809] modemSend waitResponse> called
[1091822] modemSend waitResponse CCHSEND called
[1092129] modemGetAvailable called
[1092130] modemGetAvailable +CCHRECV? called
[1092142] modemGetAvailable +CCHRECV?2 called
[1092142] ### Available: 340 on 0
[1092142] modemRead called
[1092144] modemRead CCHRECV called
HTTP/1.1 200 OK
Server: nginx
Date: Tue, 20 Jun 2023 22:42:08 GMT
Content-Type: application/json
Transfer-Encoding: chunked
Connection: keep-alive
X-Powered-By: PHP/7.4.33
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type
X-Powered-By: PleskLin
30
{"status":200,"status_message":"OK","data":null}
0
[1092186] modemGetAvailable called
[1092198] modemGetAvailable +CCHRECV? called
[1092208] modemGetAvailable +CCHRECV?2 called
[1092210] ### Available: 4294957297 on 0
Response status code: 200
Response Headers:
Server : nginx
Date : Tue, 20 Jun 2023 22:42:08 GMT
Content-Type : application/json
Transfer-Encoding : chunked
Connection : keep-alive
X-Powered-By : PHP/7.4.33
Access-Control-Allow-Origin : *
Access-Control-Allow-Headers : Content-Type
X-Powered-By : PleskLin
The response is chunked
[1092248] modemRead called
[1092250] modemRead CCHRECV called
[1092259] modemRead called
[1092260] modemRead CCHRECV called
[1092273] modemRead called
[1092275] modemRead CCHRECV called
[1092287] modemRead called
[1092289] modemRead CCHRECV called
[1092301] modemRead called
[1092303] modemRead CCHRECV called
[1092313] modemRead called
[1092315] modemRead CCHRECV called
[1092325] modemRead called
[1092327] modemRead CCHRECV called
[1092337] modemRead called
[1092338] modemRead CCHRECV called
[1092347] modemRead called
[1092349] modemRead CCHRECV called
[1092360] modemRead called
[1092362] modemRead CCHRECV called
[1092372] modemRead called
[1092374] modemRead CCHRECV called
[1092384] modemRead called
[1092385] modemRead CCHRECV called
[1092395] modemRead called
[1092396] modemRead CCHRECV called
[1092407] modemRead called
[1092408] modemRead CCHRECV called
[1092418] modemRead called
[1092420] modemRead CCHRECV called
[1092433] modemRead called
[1092434] modemRead CCHRECV called
[1092448] modemRead called
[1092450] modemRead CCHRECV called
[1092464] modemRead called
[1092465] modemRead CCHRECV called
[1092479] modemRead called
[1092481] modemRead CCHRECV called
[1092495] modemRead called
[1092496] modemRead CCHRECV called
[1092508] modemRead called
[1092510] modemRead CCHRECV called
[1092522] modemRead called
[1092524] modemRead CCHRECV called
[1092538] modemRead called
[1092539] modemRead CCHRECV called
[1092553] modemRead called
[1092555] modemRead CCHRECV called
[1092567] modemRead called
[1092568] modemRead CCHRECV called
[1092580] modemRead called
[1092582] modemRead CCHRECV called
[1092596] modemRead called
[1092598] modemRead CCHRECV called
[1092610] modemRead called
[1092611] modemRead CCHRECV called
[1092623] modemRead called
[1092625] modemRead CCHRECV called
[1092637] modemGetAvailable called
[1092638] modemGetAvailable +CCHRECV? called
[1092652] modemGetAvailable +CCHRECV?2 called
[1092652] ### Available: 0 on 0
[1092653] modemGetConnected called
[1092654] modemGetConnected +CCHOPEN? waitResponsecalled
[1092671] ************Modem is connected Found in sim7600 Library****************
[1092671] Dats is "api.mywebsite.com"
[1093138] modemGetAvailable called
[1093139] modemGetAvailable +CCHRECV? called
[1093154] modemGetAvailable +CCHRECV?2 called
[1093154] ### Available: 0 on 0
[1093154] modemGetConnected called
[1093156] modemGetConnected +CCHOPEN? waitResponsecalled
[1093172] ************Modem is connected Found in sim7600 Library****************
[1093173] Dats is "api.mywebsite.com"
Response:
{"status":200,"status_message":"OK","data":null}
Body length is: 48
The library appears to be filling up the buffer (CCHSEND
) with only a handful of bytes, every 2 secs and it takes approx 30 secs to finish filling the buffer.
Here is the recorded TX RX UART data, showing 30 seconds of CCHSEND
:
Then it reads the buffer back(CCHRECV
) all in one go, fine.
But then sends the following command 30 times, all receiving the same ERROR response from the SIM7600:
AT+CCHRECV=0,649\r\n
ERROR\r\n
...executed 30 times in quick succession and then finishes with...
AT+CCHRECV?\r\n
+CCHRECV: LEN,0,0\r\n\r\nOK\r\n
Why? It means that a simple HTTPS GET request is unnecessarily long. Any insight would be much appreciated.
Any support for SIM7600 HTTPS?