@ -12,49 +12,17 @@
/ / # define TINY_GSM_DEBUG Serial
/ / # define TINY_GSM_DEBUG Serial
/ / # define TINY_GSM_USE_HEX
/ / # define TINY_GSM_USE_HEX
# define TINY_GSM_MUX_COUNT 2
# define TINY_GSM_MUX_COUNT 8
# define TINY_GSM_BUFFER_READ_AND_CHECK_SIZE
# define TINY_GSM_BUFFER_READ_AND_CHECK_SIZE
# include "TinyGsmBattery.tpp"
# include "TinyGsmGPRS.tpp"
# include "TinyGsmGPS.tpp"
# include "TinyGsmModem.tpp"
# include "TinyGsmSMS.tpp"
# include "TinyGsmClientSIM70xx.h"
# include "TinyGsmTCP.tpp"
# include "TinyGsmTCP.tpp"
# include "TinyGsmTime.tpp"
# define GSM_NL "\r\n"
static const char GSM_OK [ ] TINY_GSM_PROGMEM = " OK " GSM_NL ;
static const char GSM_ERROR [ ] TINY_GSM_PROGMEM = " ERROR " GSM_NL ;
# if defined TINY_GSM_DEBUG
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: " ;
# endif
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 TinyGsmSim7000 : public TinyGsmModem < TinyGsmSim7000 > ,
public TinyGsmGPRS < TinyGsmSim7000 > ,
public TinyGsmTCP < TinyGsmSim7000 , TINY_GSM_MUX_COUNT > ,
public TinyGsmSMS < TinyGsmSim7000 > ,
public TinyGsmGPS < TinyGsmSim7000 > ,
public TinyGsmTime < TinyGsmSim7000 > ,
public TinyGsmBattery < TinyGsmSim7000 > {
friend class TinyGsmModem < TinyGsmSim7000 > ;
friend class TinyGsmGPRS < TinyGsmSim7000 > ;
class TinyGsmSim7000 : public TinyGsmSim70xx < TinyGsmSim7000 > ,
public TinyGsmTCP < TinyGsmSim7000 , TINY_GSM_MUX_COUNT > {
friend class TinyGsmSim70xx < TinyGsmSim7000 > ;
friend class TinyGsmTCP < TinyGsmSim7000 , TINY_GSM_MUX_COUNT > ;
friend class TinyGsmTCP < TinyGsmSim7000 , TINY_GSM_MUX_COUNT > ;
friend class TinyGsmSMS < TinyGsmSim7000 > ;
friend class TinyGsmGPS < TinyGsmSim7000 > ;
friend class TinyGsmTime < TinyGsmSim7000 > ;
friend class TinyGsmBattery < TinyGsmSim7000 > ;
/*
/*
* Inner Client
* Inner Client
@ -99,7 +67,7 @@ class TinyGsmSim7000 : public TinyGsmModem<TinyGsmSim7000>,
void stop ( uint32_t maxWaitMs ) {
void stop ( uint32_t maxWaitMs ) {
dumpModemBuffer ( maxWaitMs ) ;
dumpModemBuffer ( maxWaitMs ) ;
at - > sendAT ( GF ( " +CA CLOSE= " ) , mux ) ;
at - > sendAT ( GF ( " +CIP CLOSE= " ) , mux ) ;
sock_connected = false ;
sock_connected = false ;
at - > waitResponse ( 3000 ) ;
at - > waitResponse ( 3000 ) ;
}
}
@ -117,79 +85,14 @@ class TinyGsmSim7000 : public TinyGsmModem<TinyGsmSim7000>,
/*
/*
* Inner Secure Client
* Inner Secure Client
*/
*/
class GsmClientSecureSIM7000 : public GsmClientSim7000 {
public :
GsmClientSecureSIM7000 ( ) { }
GsmClientSecureSIM7000 ( TinyGsmSim7000 & modem , uint8_t mux = 0 )
: GsmClientSim7000 ( modem , mux ) { }
public :
bool setCertificate ( const String & certificateName ) {
return at - > setCertificate ( certificateName , mux ) ;
}
int connect ( const char * host , uint16_t port , int timeout_s ) override {
stop ( ) ;
TINY_GSM_YIELD ( ) ;
rx . clear ( ) ;
sock_connected = at - > modemConnect ( host , port , mux , true , timeout_s ) ;
return sock_connected ;
}
TINY_GSM_CLIENT_CONNECT_OVERRIDES
} ;
public :
boolean isValidNumber ( String str ) {
if ( ! ( str . charAt ( 0 ) = = ' + ' | | str . charAt ( 0 ) = = ' - ' | |
isDigit ( str . charAt ( 0 ) ) ) )
return false ;
for ( byte i = 1 ; i < str . length ( ) ; i + + ) {
if ( ! ( isDigit ( str . charAt ( i ) ) | | str . charAt ( i ) = = ' . ' ) ) { return false ; }
}
return true ;
}
String ShowNTPError ( byte error ) {
switch ( error ) {
case 1 : return " Network time synchronization is successful " ;
case 61 : return " Network error " ;
case 62 : return " DNS resolution error " ;
case 63 : return " Connection error " ;
case 64 : return " Service response error " ;
case 65 : return " Service response timeout " ;
default : return " Unknown error: " + String ( error ) ;
}
}
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 ;
}
/ / NOTE : Use modem TINYGSMSIM7000SSL for a secure client !
/*
/*
* Constructor
* Constructor
*/
*/
public :
public :
explicit TinyGsmSim7000 ( Stream & stream ) : stream ( stream ) , certificates ( ) {
explicit TinyGsmSim7000 ( Stream & stream )
: TinyGsmSim70xx < TinyGsmSim7000 > ( stream ) {
memset ( sockets , 0 , sizeof ( sockets ) ) ;
memset ( sockets , 0 , sizeof ( sockets ) ) ;
}
}
@ -235,165 +138,23 @@ class TinyGsmSim7000 : public TinyGsmModem<TinyGsmSim7000>,
}
}
}
}
String getModemNameImpl ( ) {
String name = " SIMCom SIM7000 " ;
sendAT ( GF ( " +GMM " ) ) ;
String res2 ;
if ( waitResponse ( 1000L , res2 ) ! = 1 ) { return name ; }
res2 . replace ( GSM_NL " OK " GSM_NL , " " ) ;
res2 . replace ( " _ " , " " ) ;
res2 . trim ( ) ;
name = res2 ;
return name ;
}
bool factoryDefaultImpl ( ) { / / these commands aren ' t supported
sendAT ( GF ( " &FZE0&W " ) ) ; / / Factory + Reset + Echo Off + Write
waitResponse ( ) ;
sendAT ( GF ( " +IPR=0 " ) ) ; / / Auto - baud
waitResponse ( ) ;
sendAT ( GF ( " +IFC=0,0 " ) ) ; / / No Flow Control
waitResponse ( ) ;
sendAT ( GF ( " +ICF=3,3 " ) ) ; / / 8 data 0 parity 1 stop
waitResponse ( ) ;
sendAT ( GF ( " +CSCLK=0 " ) ) ; / / Disable Slow Clock
waitResponse ( ) ;
sendAT ( GF ( " &W " ) ) ; / / Write configuration
return waitResponse ( ) = = 1 ;
}
/*
/*
* Power functions
* Power functions
*/
*/
protected :
protected :
bool restartImpl ( const char * pin = NULL ) {
if ( ! setPhoneFunctionality ( 0 ) ) { return false ; }
if ( ! setPhoneFunctionality ( 1 , true ) ) { return false ; }
waitResponse ( 10000L , GF ( " SMS Ready " ) , GF ( " RDY " ) ) ;
return init ( pin ) ;
}
bool powerOffImpl ( ) {
sendAT ( GF ( " +CPOWD=1 " ) ) ;
return waitResponse ( GF ( " NORMAL POWER DOWN " ) ) = = 1 ;
}
/ / During sleep , the SIM7000 module has its serial communication disabled .
/ / In order to reestablish communication pull the DRT - pin of the SIM7000
/ / module LOW for at least 50 ms . Then use this function to disable sleep mode .
/ / The DTR - pin can then be released again .
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 ;
}
/ / Follows the SIM70xx template
/*
/*
* Generic network functions
* Generic network functions
*/
*/
public :
RegStatus getRegistrationStatus ( ) {
RegStatus epsStatus = ( RegStatus ) getRegistrationStatusXREG ( " CEREG " ) ;
/ / If we ' re connected on EPS , great !
if ( epsStatus = = REG_OK_HOME | | epsStatus = = REG_OK_ROAMING ) {
return epsStatus ;
} else {
/ / Otherwise , check GPRS network status
/ / We could be using GPRS fall - back or the board could be being moody
return ( RegStatus ) getRegistrationStatusXREG ( " CGREG " ) ;
}
}
protected :
protected :
bool setCertificate ( const String & certificateName , const uint8_t mux = 0 ) {
if ( mux > = TINY_GSM_MUX_COUNT ) return false ;
certificates [ mux ] = certificateName ;
return true ;
}
bool isNetworkConnectedImpl ( ) {
RegStatus s = getRegistrationStatus ( ) ;
return ( s = = REG_OK_HOME | | s = = REG_OK_ROAMING ) ;
}
public :
String getNetworkModes ( ) {
/ / Get the help string , not the setting value
sendAT ( GF ( " +CNMP=? " ) ) ;
if ( waitResponse ( GF ( GSM_NL " +CNMP: " ) ) ! = 1 ) { return " " ; }
String res = stream . readStringUntil ( ' \n ' ) ;
waitResponse ( ) ;
return res ;
}
bool getNetworkMode ( int16_t & mode ) {
sendAT ( GF ( " +CNMP? " ) ) ;
if ( waitResponse ( GF ( GSM_NL " +CNMP: " ) ) ! = 1 ) { return false ; }
mode = streamGetIntBefore ( ' \n ' ) ;
waitResponse ( ) ;
return true ;
}
String setNetworkMode ( uint8_t mode ) {
sendAT ( GF ( " +CNMP= " ) , mode ) ;
if ( waitResponse ( ) ! = 1 ) return " " ;
return " OK " ;
}
String getPreferredModes ( ) {
/ / Get the help string , not the setting value
sendAT ( GF ( " +CMNB=? " ) ) ;
if ( waitResponse ( GF ( GSM_NL " +CMNB: " ) ) ! = 1 ) { return " " ; }
String res = stream . readStringUntil ( ' \n ' ) ;
waitResponse ( ) ;
return res ;
}
bool getPreferredMode ( int16_t & mode ) {
sendAT ( GF ( " +CMNB? " ) ) ;
if ( waitResponse ( GF ( GSM_NL " +CMNB: " ) ) ! = 1 ) { return false ; }
mode = streamGetIntBefore ( ' \n ' ) ;
waitResponse ( ) ;
return true ;
}
String setPreferredMode ( uint8_t mode ) {
sendAT ( GF ( " +CMNB= " ) , mode ) ;
if ( waitResponse ( ) ! = 1 ) return " " ;
return " OK " ;
}
bool getNetworkSystemMode ( bool & n , int16_t & stat ) {
/ / n : whether to automatically report the system mode info
/ / stat : the current service . 0 if it not connected
sendAT ( GF ( " +CNSMOD? " ) ) ;
if ( waitResponse ( GF ( GSM_NL " +CNSMOD: " ) ) ! = 1 ) { return false ; }
n = streamGetIntBefore ( ' , ' ) ! = 0 ;
stat = streamGetIntBefore ( ' \n ' ) ;
waitResponse ( ) ;
return true ;
}
String setNetworkSystemMode ( bool n ) {
/ / n : whether to automatically report the system mode info
sendAT ( GF ( " +CNSMOD= " ) , int8_t ( n ) ) ;
if ( waitResponse ( ) ! = 1 ) return " " ;
return " OK " ;
}
String getLocalIPImpl ( ) {
String getLocalIPImpl ( ) {
sendAT ( GF ( " +CNACT? " ) ) ;
if ( waitResponse ( GF ( GSM_NL " +CNACT: " ) ) ! = 1 ) { return " " ; }
streamSkipUntil ( ' \" ' ) ;
String res = stream . readStringUntil ( ' \" ' ) ;
waitResponse ( ) ;
sendAT ( GF ( " +CIFSR;E0 " ) ) ;
String res ;
if ( waitResponse ( 10000L , res ) ! = 1 ) { return " " ; }
res . replace ( GSM_NL " OK " GSM_NL , " " ) ;
res . replace ( GSM_NL , " " ) ;
res . trim ( ) ;
return res ;
return res ;
}
}
@ -405,24 +166,23 @@ class TinyGsmSim7000 : public TinyGsmModem<TinyGsmSim7000>,
const char * pwd = NULL ) {
const char * pwd = NULL ) {
gprsDisconnect ( ) ;
gprsDisconnect ( ) ;
/ / Open data connection
sendAT ( GF ( " +CNACT=1, \" " ) , apn , GF ( " \" " ) ) ;
if ( waitResponse ( 60000L ) ! = 1 ) { return false ; }
/ / Set the Bearer for the IP
sendAT ( GF (
" +SAPBR=3,1, \" Contype \" , \" GPRS \" " ) ) ; / / Set the connection type to GPRS
/ / Bearer settings for applications based on IP
/ / Set the connection type to GPRS
sendAT ( GF ( " +SAPBR=3,1, \" Contype \" , \" GPRS \" " ) ) ;
waitResponse ( ) ;
waitResponse ( ) ;
sendAT ( GF ( " +SAPBR=3,1, \" APN \" , \" " ) , apn , ' " ' ) ; / / Set the APN
/ / Set the APN
sendAT ( GF ( " +SAPBR=3,1, \" APN \" , \" " ) , apn , ' " ' ) ;
waitResponse ( ) ;
waitResponse ( ) ;
/ / Set the user name
if ( user & & strlen ( user ) > 0 ) {
if ( user & & strlen ( user ) > 0 ) {
sendAT ( GF ( " +SAPBR=3,1, \" USER \" , \" " ) , user , ' " ' ) ; / / Set the user name
sendAT ( GF ( " +SAPBR=3,1, \" USER \" , \" " ) , user , ' " ' ) ;
waitResponse ( ) ;
waitResponse ( ) ;
}
}
/ / Set the password
if ( pwd & & strlen ( pwd ) > 0 ) {
if ( pwd & & strlen ( pwd ) > 0 ) {
sendAT ( GF ( " +SAPBR=3,1, \" PWD \" , \" " ) , pwd , ' " ' ) ; / / Set the password
sendAT ( GF ( " +SAPBR=3,1, \" PWD \" , \" " ) , pwd , ' " ' ) ;
waitResponse ( ) ;
waitResponse ( ) ;
}
}
@ -430,6 +190,10 @@ class TinyGsmSim7000 : public TinyGsmModem<TinyGsmSim7000>,
sendAT ( GF ( " +CGDCONT=1, \" IP \" , \" " ) , apn , ' " ' ) ;
sendAT ( GF ( " +CGDCONT=1, \" IP \" , \" " ) , apn , ' " ' ) ;
waitResponse ( ) ;
waitResponse ( ) ;
/ / Attach to GPRS
sendAT ( GF ( " +CGATT=1 " ) ) ;
if ( waitResponse ( 60000L ) ! = 1 ) { return false ; }
/ / Activate the PDP context
/ / Activate the PDP context
sendAT ( GF ( " +CGACT=1,1 " ) ) ;
sendAT ( GF ( " +CGACT=1,1 " ) ) ;
waitResponse ( 60000L ) ;
waitResponse ( 60000L ) ;
@ -441,24 +205,39 @@ class TinyGsmSim7000 : public TinyGsmModem<TinyGsmSim7000>,
sendAT ( GF ( " +SAPBR=2,1 " ) ) ;
sendAT ( GF ( " +SAPBR=2,1 " ) ) ;
if ( waitResponse ( 30000L ) ! = 1 ) { return false ; }
if ( waitResponse ( 30000L ) ! = 1 ) { return false ; }
/ / Attach to GPRS
sendAT ( GF ( " +CGATT=1 " ) ) ;
/ / Set the TCP application toolkit to multi - IP
sendAT ( GF ( " +CIPMUX=1 " ) ) ;
if ( waitResponse ( ) ! = 1 ) { return false ; }
/ / Put the TCP application toolkit in " quick send " mode
/ / ( thus no extra " Send OK " )
sendAT ( GF ( " +CIPQSEND=1 " ) ) ;
if ( waitResponse ( ) ! = 1 ) { return false ; }
/ / Set the TCP application toolkit to get data manually
sendAT ( GF ( " +CIPRXGET=1 " ) ) ;
if ( waitResponse ( ) ! = 1 ) { return false ; }
/ / Start the TCP application toolkit task and set APN , USER NAME , PASSWORD
sendAT ( GF ( " +CSTT= \" " ) , apn , GF ( " \" , \" " ) , user , GF ( " \" , \" " ) , pwd , GF ( " \" " ) ) ;
if ( waitResponse ( 60000L ) ! = 1 ) { return false ; }
if ( waitResponse ( 60000L ) ! = 1 ) { return false ; }
/ / Check data connection
/ / Bring up the TCP application toolkit wireless connection with GPRS or CSD
sendAT ( GF ( " +CIICR " ) ) ;
if ( waitResponse ( 60000L ) ! = 1 ) { return false ; }
sendAT ( GF ( " +CNACT? " ) ) ;
if ( waitResponse ( GF ( GSM_NL " +CNACT: " ) ) ! = 1 ) { return false ; }
int res = streamGetIntBefore ( ' , ' ) ;
waitResponse ( ) ;
/ / Get local IP address for the TCP application toolkit
/ / only assigned after connection
sendAT ( GF ( " +CIFSR;E0 " ) ) ;
if ( waitResponse ( 10000L ) ! = 1 ) { return false ; }
return res = = 1 ;
return t ru e;
}
}
bool gprsDisconnectImpl ( ) {
bool gprsDisconnectImpl ( ) {
/ / Shut the TCP / IP connection
/ / CNAC T will close * all * open connections
sendAT ( GF ( " +CNACT=0 " ) ) ;
/ / Shut the TCP application toolkit connection
/ / CIPSHU T will close * all * open TCP application toolkit connections
sendAT ( GF ( " +CIPSHUT " ) ) ;
if ( waitResponse ( 60000L ) ! = 1 ) { return false ; }
if ( waitResponse ( 60000L ) ! = 1 ) { return false ; }
sendAT ( GF ( " +CGATT=0 " ) ) ; / / Deactivate the bearer context
sendAT ( GF ( " +CGATT=0 " ) ) ; / / Deactivate the bearer context
@ -471,15 +250,7 @@ class TinyGsmSim7000 : public TinyGsmModem<TinyGsmSim7000>,
* SIM card functions
* SIM card functions
*/
*/
protected :
protected :
/ / Doesn ' t return the " +CCID " before the number
String getSimCCIDImpl ( ) {
sendAT ( GF ( " +CCID " ) ) ;
if ( waitResponse ( GF ( GSM_NL ) ) ! = 1 ) { return " " ; }
String res = stream . readStringUntil ( ' \n ' ) ;
waitResponse ( ) ;
res . trim ( ) ;
return res ;
}
/ / Follows the SIM70xx template
/*
/*
* Messaging functions
* Messaging functions
@ -491,113 +262,18 @@ class TinyGsmSim7000 : public TinyGsmModem<TinyGsmSim7000>,
* GPS / GNSS / GLONASS location functions
* GPS / GNSS / GLONASS location functions
*/
*/
protected :
protected :
/ / enable GPS
bool enableGPSImpl ( ) {
sendAT ( GF ( " +CGNSPWR=1 " ) ) ;
if ( waitResponse ( ) ! = 1 ) { return false ; }
return true ;
}
bool disableGPSImpl ( ) {
sendAT ( GF ( " +CGNSPWR=0 " ) ) ;
if ( waitResponse ( ) ! = 1 ) { return false ; }
return true ;
}
/ / get the RAW GPS output
String getGPSrawImpl ( ) {
sendAT ( GF ( " +CGNSINF " ) ) ;
if ( waitResponse ( 10000L , GF ( GSM_NL " +CGNSINF: " ) ) ! = 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 ( " +CGNSINF " ) ) ;
if ( waitResponse ( 10000L , GF ( GSM_NL " +CGNSINF: " ) ) ! = 1 ) { return false ; }
streamSkipUntil ( ' , ' ) ; / / GNSS run status
if ( streamGetIntBefore ( ' , ' ) = = 1 ) { / / fix status
/ / init variables
float ilat = 0 ;
float ilon = 0 ;
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 ;
/ / UTC date & Time
iyear = streamGetIntLength ( 4 ) ; / / Four digit year
imonth = streamGetIntLength ( 2 ) ; / / Two digit month
iday = streamGetIntLength ( 2 ) ; / / Two digit day
ihour = streamGetIntLength ( 2 ) ; / / Two digit hour
imin = streamGetIntLength ( 2 ) ; / / Two digit minute
secondWithSS =
streamGetFloatBefore ( ' , ' ) ; / / 6 digit second with subseconds
ilat = streamGetFloatBefore ( ' , ' ) ; / / Latitude
ilon = streamGetFloatBefore ( ' , ' ) ; / / Longitude
ialt = streamGetFloatBefore ( ' , ' ) ; / / MSL Altitude . Unit is meters
ispeed = streamGetFloatBefore ( ' , ' ) ; / / Speed Over Ground . Unit is knots .
streamSkipUntil ( ' , ' ) ; / / Course Over Ground . Degrees .
streamSkipUntil ( ' , ' ) ; / / Fix Mode
streamSkipUntil ( ' , ' ) ; / / Reserved1
iaccuracy =
streamGetFloatBefore ( ' , ' ) ; / / Horizontal Dilution Of Precision
streamSkipUntil ( ' , ' ) ; / / Position Dilution Of Precision
streamSkipUntil ( ' , ' ) ; / / Vertical Dilution Of Precision
streamSkipUntil ( ' , ' ) ; / / Reserved2
ivsat = streamGetIntBefore ( ' , ' ) ; / / GNSS Satellites in View
iusat = streamGetIntBefore ( ' , ' ) ; / / GNSS Satellites Used
streamSkipUntil ( ' , ' ) ; / / GLONASS Satellites Used
streamSkipUntil ( ' , ' ) ; / / Reserved3
streamSkipUntil ( ' , ' ) ; / / C / N0 max
streamSkipUntil ( ' , ' ) ; / / HPA
streamSkipUntil ( ' \n ' ) ; / / VPA
/ / Set pointers
if ( lat ! = NULL ) * lat = ilat ;
if ( lon ! = NULL ) * lon = ilon ;
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 ) ;
waitResponse ( ) ;
return true ;
}
streamSkipUntil ( ' \n ' ) ; / / toss the row of commas
waitResponse ( ) ;
return false ;
}
/ / Follows the SIM70xx template
/*
/*
* Time functions
* Time functions
*/
*/
/ / Can follow CCLK as per template
/ / Can follow CCLK as per template
/*
* NTP server functions
*/
/ / Can sync with server using CNTP as per template
/*
/*
* Battery functions
* Battery functions
*/
*/
@ -610,161 +286,106 @@ class TinyGsmSim7000 : public TinyGsmModem<TinyGsmSim7000>,
protected :
protected :
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 , int timeout_s = 75 ) {
bool ssl = false , int timeout_s = 75 ) {
if ( ssl ) { DBG ( " SSL only supported using application on SIM7000! " ) ; }
uint32_t timeout_ms = ( ( uint32_t ) timeout_s ) * 1000 ;
uint32_t timeout_ms = ( ( uint32_t ) timeout_s ) * 1000 ;
sendAT ( GF ( " +CACID= " ) , mux ) ;
if ( waitResponse ( timeout_ms ) ! = 1 ) return false ;
if ( ssl ) {
sendAT ( GF ( " +CSSLCFG= \" sslversion \" ,0,3 " ) ) ; / / TLS 1.2
if ( waitResponse ( ) ! = 1 ) return false ;
sendAT ( GF ( " +CSSLCFG= \" ctxindex \" ,0 " ) ) ;
if ( waitResponse ( ) ! = 1 ) return false ;
if ( certificates [ mux ] ! = " " ) {
sendAT ( GF ( " +CASSLCFG= " ) , mux , " ,CACERT, \" " , certificates [ mux ] . c_str ( ) ,
" \" " ) ;
if ( waitResponse ( ) ! = 1 ) return false ;
}
}
sendAT ( GF ( " +CASSLCFG= " ) , mux , ' , ' , GF ( " ssl, " ) , ssl ) ;
waitResponse ( ) ;
sendAT ( GF ( " +CASSLCFG= " ) , mux , ' , ' , GF ( " protocol,0 " ) ) ;
waitResponse ( ) ;
sendAT ( GF ( " +CSSLCFG= \" sni \" , " ) , mux , ' , ' , GF ( " \" " ) , host , GF ( " \" " ) ) ;
waitResponse ( ) ;
sendAT ( GF ( " +CAOPEN= " ) , mux , ' , ' , GF ( " \" " ) , host , GF ( " \" , " ) , port ) ;
if ( waitResponse ( timeout_ms , GF ( GSM_NL " +CAOPEN: " ) ) ! = 1 ) { return 0 ; }
streamSkipUntil ( ' , ' ) ; / / Skip mux
int8_t res = streamGetIntBefore ( ' \n ' ) ;
waitResponse ( ) ;
return 0 = = res ;
/ / when not using SSL , the TCP application toolkit is more stable
sendAT ( GF ( " +CIPSTART= " ) , mux , ' , ' , GF ( " \" TCP " ) , GF ( " \" , \" " ) , host ,
GF ( " \" , " ) , port ) ;
return ( 1 = =
waitResponse ( timeout_ms , GF ( " CONNECT OK " GSM_NL ) ,
GF ( " CONNECT FAIL " GSM_NL ) ,
GF ( " ALREADY CONNECT " GSM_NL ) , GF ( " ERROR " GSM_NL ) ,
GF ( " CLOSE OK " GSM_NL ) ) ) ;
}
}
int16_t modemSend ( const void * buff , size_t len , uint8_t mux ) {
int16_t modemSend ( const void * buff , size_t len , uint8_t mux ) {
sendAT ( GF ( " +CA SEND= " ) , mux , ' , ' , ( uint16_t ) len ) ;
sendAT ( GF ( " +CIPSEND= " ) , mux , ' , ' , ( uint16_t ) len ) ;
if ( waitResponse ( GF ( " > " ) ) ! = 1 ) { return 0 ; }
if ( waitResponse ( GF ( " > " ) ) ! = 1 ) { return 0 ; }
stream . write ( reinterpret_cast < const uint8_t * > ( buff ) , len ) ;
stream . write ( reinterpret_cast < const uint8_t * > ( buff ) , len ) ;
stream . flush ( ) ;
stream . flush ( ) ;
if ( waitResponse ( GF ( GSM_NL " +CASEND: " ) ) ! = 1 ) { return 0 ; }
streamSkipUntil ( ' , ' ) ; / / Skip mux
if ( streamGetIntBefore ( ' , ' ) ! = 0 ) { return 0 ; } / / If result ! = success
if ( waitResponse ( GF ( GSM_NL " DATA ACCEPT: " ) ) ! = 1 ) { return 0 ; }
streamSkipUntil ( ' , ' ) ; / / Skip mux
return streamGetIntBefore ( ' \n ' ) ;
return streamGetIntBefore ( ' \n ' ) ;
}
}
size_t modemRead ( size_t size , uint8_t mux ) {
size_t modemRead ( size_t size , uint8_t mux ) {
if ( ! sockets [ mux ] ) return 0 ;
if ( ! sockets [ mux ] ) return 0 ;
sendAT ( GF ( " +CARECV= " ) , mux , ' , ' , ( uint16_t ) size ) ;
if ( waitResponse ( GF ( " +CARECV: " ) ) ! = 1 ) {
sockets [ mux ] - > sock_available = 0 ;
return 0 ;
}
stream . read ( ) ;
if ( stream . peek ( ) = = ' 0 ' ) {
waitResponse ( ) ;
sockets [ mux ] - > sock_available = 0 ;
return 0 ;
}
const int16_t len_confirmed = streamGetIntBefore ( ' , ' ) ;
if ( len_confirmed < = 0 ) {
sockets [ mux ] - > sock_available = 0 ;
waitResponse ( ) ;
return 0 ;
}
for ( int i = 0 ; i < len_confirmed ; i + + ) {
# ifdef TINY_GSM_USE_HEX
sendAT ( GF ( " +CIPRXGET=3, " ) , mux , ' , ' , ( uint16_t ) size ) ;
if ( waitResponse ( GF ( " +CIPRXGET: " ) ) ! = 1 ) { return 0 ; }
# else
sendAT ( GF ( " +CIPRXGET=2, " ) , mux , ' , ' , ( uint16_t ) size ) ;
if ( waitResponse ( GF ( " +CIPRXGET: " ) ) ! = 1 ) { return 0 ; }
# endif
streamSkipUntil ( ' , ' ) ; / / Skip Rx mode 2 / normal or 3 / HEX
streamSkipUntil ( ' , ' ) ; / / Skip mux
int16_t len_requested = streamGetIntBefore ( ' , ' ) ;
/ / ^ ^ Requested number of data bytes ( 1 - 1460 bytes ) to be read
int16_t len_confirmed = streamGetIntBefore ( ' \n ' ) ;
/ / ^ ^ Confirmed number of data bytes to be read , which may be less than
/ / requested . 0 indicates that no data can be read .
/ / SRGD NOTE : Contrary to above ( which is copied from AT command manual )
/ / this is actually be the number of bytes that will be remaining in the
/ / buffer after the read .
for ( int i = 0 ; i < len_requested ; i + + ) {
uint32_t startMillis = millis ( ) ;
uint32_t startMillis = millis ( ) ;
# ifdef TINY_GSM_USE_HEX
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 ) ;
# else
while ( ! stream . available ( ) & &
while ( ! stream . available ( ) & &
( millis ( ) - startMillis < sockets [ mux ] - > _timeout ) ) {
( millis ( ) - startMillis < sockets [ mux ] - > _timeout ) ) {
TINY_GSM_YIELD ( ) ;
TINY_GSM_YIELD ( ) ;
}
}
char c = stream . read ( ) ;
char c = stream . read ( ) ;
# endif
sockets [ mux ] - > rx . put ( c ) ;
sockets [ mux ] - > rx . put ( c ) ;
}
}
/ / DBG ( " ### READ: " , len_requested , " from " , mux ) ;
/ / DBG ( " ### READ: " , len_requested , " from " , mux ) ;
/ / sockets [ mux ] - > sock_available = modemGetAvailable ( mux ) ;
/ / sockets [ mux ] - > sock_available = modemGetAvailable ( mux ) ;
auto diff = int64_t ( size ) - int64_t ( len_confirmed ) ;
if ( diff < 0 ) diff = 0 ;
sockets [ mux ] - > sock_available = diff ;
sockets [ mux ] - > sock_available = len_confirmed ;
waitResponse ( ) ;
waitResponse ( ) ;
return len_confirm ed ;
return len_requested ;
}
}
size_t modemGetAvailable ( uint8_t mux ) {
size_t modemGetAvailable ( uint8_t mux ) {
if ( ! sockets [ mux ] ) return 0 ;
if ( ! sockets [ mux ] ) return 0 ;
if ( ! sockets [ mux ] - > sock_connected ) {
sockets [ mux ] - > sock_connected = modemGetConnected ( mux ) ;
}
if ( ! sockets [ mux ] - > sock_connected ) return 0 ;
sendAT ( GF ( " +CARECV? " ) ) ;
int8_t readMux = - 1 ;
size_t result = 0 ;
while ( readMux ! = mux ) {
if ( waitResponse ( GF ( " +CARECV: " ) ) ! = 1 ) {
sockets [ mux ] - > sock_connected = modemGetConnected ( mux ) ;
return 0 ;
} ;
readMux = streamGetIntBefore ( ' , ' ) ;
result = streamGetIntBefore ( ' \n ' ) ;
sendAT ( GF ( " +CIPRXGET=4, " ) , mux ) ;
size_t result = 0 ;
if ( waitResponse ( GF ( " +CIPRXGET: " ) ) = = 1 ) {
streamSkipUntil ( ' , ' ) ; / / Skip mode 4
streamSkipUntil ( ' , ' ) ; / / Skip mux
result = streamGetIntBefore ( ' \n ' ) ;
waitResponse ( ) ;
}
}
waitResponse ( ) ;
/ / DBG ( " ### Available: " , result , " on " , mux ) ;
if ( ! result ) { sockets [ mux ] - > sock_connected = modemGetConnected ( mux ) ; }
return result ;
return result ;
}
}
bool modemGetConnected ( uint8_t mux ) {
bool modemGetConnected ( uint8_t mux ) {
sendAT ( GF ( " +CASTATE? " ) ) ;
int8_t readMux = - 1 ;
while ( readMux ! = mux ) {
if ( waitResponse ( 3000 , GF ( " +CASTATE: " ) , GFP ( GSM_OK ) ) ! = 1 ) { return 0 ; }
readMux = streamGetIntBefore ( ' , ' ) ;
}
int8_t res = streamGetIntBefore ( ' \n ' ) ;
sendAT ( GF ( " +CIPSTATUS= " ) , mux ) ;
waitResponse ( GF ( " +CIPSTATUS " ) ) ;
int8_t res = waitResponse ( GF ( " , \" CONNECTED \" " ) , GF ( " , \" CLOSED \" " ) ,
GF ( " , \" CLOSING \" " ) , GF ( " , \" REMOTE CLOSING \" " ) ,
GF ( " , \" INITIAL \" " ) ) ;
waitResponse ( ) ;
waitResponse ( ) ;
return 1 = = res ;
return 1 = = res ;
}
}
public :
bool modemGetConnected ( const char * host , uint16_t port , uint8_t mux ) {
sendAT ( GF ( " +CAOPEN? " ) ) ;
int8_t readMux = - 1 ;
while ( readMux ! = mux ) {
if ( waitResponse ( GF ( " +CAOPEN: " ) ) ! = 1 ) return 0 ;
readMux = streamGetIntBefore ( ' , ' ) ;
}
streamSkipUntil ( ' \" ' ) ;
size_t hostLen = strlen ( host ) ;
char buffer [ hostLen ] ;
stream . readBytesUntil ( ' \" ' , buffer , hostLen ) ;
streamSkipUntil ( ' , ' ) ;
uint16_t connectedPort = streamGetIntBefore ( ' \n ' ) ;
waitResponse ( ) ;
bool samePort = connectedPort = = port ;
bool sameHost = memcmp ( buffer , host , hostLen ) = = 0 ;
sockets [ mux ] - > sock_connected = sameHost & & samePort ;
return sockets [ mux ] - > sock_connected ;
}
/*
/*
* Utilities
* Utilities
*/
*/
@ -828,30 +449,6 @@ class TinyGsmSim7000 : public TinyGsmModem<TinyGsmSim7000>,
} else {
} else {
data + = mode ;
data + = mode ;
}
}
} else if ( data . endsWith ( GF ( GSM_NL " +CARECV: " ) ) ) {
int8_t mux = streamGetIntBefore ( ' , ' ) ;
if ( mux > = 0 & & mux < TINY_GSM_MUX_COUNT & & sockets [ mux ] ) {
sockets [ mux ] - > got_data = true ;
}
data = " " ;
/ / DBG ( " ### Got Data: " , mux ) ;
} else if ( data . endsWith ( GF ( GSM_NL " +CADATAIND: " ) ) ) {
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 if ( data . endsWith ( GF ( GSM_NL " +CASTATE: " ) ) ) {
int8_t mux = streamGetIntBefore ( ' , ' ) ;
int8_t state = streamGetIntBefore ( ' \n ' ) ;
if ( mux > = 0 & & mux < TINY_GSM_MUX_COUNT & & sockets [ mux ] ) {
if ( state ! = 1 ) {
sockets [ mux ] - > sock_connected = false ;
DBG ( " ### Closed: " , mux ) ;
}
}
data = " " ;
} else if ( data . endsWith ( GF ( GSM_NL " +RECEIVE: " ) ) ) {
} else if ( data . endsWith ( GF ( GSM_NL " +RECEIVE: " ) ) ) {
int8_t mux = streamGetIntBefore ( ' , ' ) ;
int8_t mux = streamGetIntBefore ( ' , ' ) ;
int16_t len = streamGetIntBefore ( ' \n ' ) ;
int16_t len = streamGetIntBefore ( ' \n ' ) ;
@ -887,6 +484,10 @@ class TinyGsmSim7000 : public TinyGsmModem<TinyGsmSim7000>,
' \n ' ) ; / / Refresh Network Daylight Saving Time by network
' \n ' ) ; / / Refresh Network Daylight Saving Time by network
data = " " ;
data = " " ;
DBG ( " ### Daylight savings time state updated. " ) ;
DBG ( " ### Daylight savings time state updated. " ) ;
} else if ( data . endsWith ( GF ( GSM_NL " SMS Ready " GSM_NL ) ) ) {
data = " " ;
DBG ( " ### Unexpected module reset! " ) ;
init ( ) ;
}
}
}
}
} while ( millis ( ) - startMillis < timeout_ms ) ;
} while ( millis ( ) - startMillis < timeout_ms ) ;
@ -926,13 +527,8 @@ class TinyGsmSim7000 : public TinyGsmModem<TinyGsmSim7000>,
return waitResponse ( 1000 , r1 , r2 , r3 , r4 , r5 ) ;
return waitResponse ( 1000 , r1 , r2 , r3 , r4 , r5 ) ;
}
}
public :
Stream & stream ;
protected :
protected :
GsmClientSim7000 * sockets [ TINY_GSM_MUX_COUNT ] ;
GsmClientSim7000 * sockets [ TINY_GSM_MUX_COUNT ] ;
String certificates [ TINY_GSM_MUX_COUNT ] ;
const char * gsmNL = GSM_NL ;
} ;
} ;
# endif / / SRC_TINYGSMCLIENTSIM7000_H_
# endif / / SRC_TINYGSMCLIENTSIM7000_H_