@ -11,9 +11,6 @@
/ / # define TINY_GSM_DEBUG Serial
# if !defined(TINY_GSM_RX_BUFFER)
# define TINY_GSM_RX_BUFFER 256
# endif
# define TINY_GSM_MUX_COUNT 1 / / Multi-plexing isn't supported using command mode
@ -29,38 +26,54 @@ enum SimStatus {
SIM_LOCKED = 2 ,
} ;
enum XBeeType {
S6B = 0 ,
LTEC1 = 1 ,
} ;
enum RegStatus {
REG_UNREGISTERED = 0 ,
REG_OK = 0 ,
REG_UNREGISTERED = 1 ,
REG_SEARCHING = 2 ,
REG_DENIED = 3 ,
REG_OK_HOME = 1 ,
REG_OK_ROAMING = 5 ,
REG_UNKNOWN = 4 ,
} ;
/ / These are responses to the HS command to get " hardware series "
enum XBeeType {
XBEE_S6B_WIFI = 0x601 , / / Digi XBee ® Wi - Fi
XBEE_LTE1_VZN = 0xB01 , / / Digi XBee ® Cellular LTE Cat 1
XBEE_3G = 0xB02 , / / Digi XBee ® Cellular 3 G
XBEE3_LTE1_ATT = 1 , / / Digi XBee3 ™ Cellular LTE CAT 1 - - HS unknown to SRGD
XBEE3_LTEM_ATT = 2 , / / Digi XBee3 ™ Cellular LTE - M - - HS unknown to SRGD
XBEE3_LTENB = 3 , / / Digi XBee3 ™ Cellular NB - IoT - - HS unknown to SRGD
} ;
/ / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = / /
/ / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = / /
/ / Declaration of the TinyGsmXBee Class
/ / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = / /
/ / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = / /
class TinyGsm
class TinyGsmXBee
{
/ / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = / /
/ / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = / /
/ / The XBee Internal Client Class
/ / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = / /
/ / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = / /
public :
class GsmClient : public Client
{
friend class TinyGsm ;
friend class TinyGsmXBee ;
public :
GsmClient ( ) { }
GsmClient ( TinyGsm & modem , uint8_t mux = 0 ) {
GsmClient ( TinyGsmXBee & modem , uint8_t mux = 0 ) {
init ( & modem , mux ) ;
}
bool init ( TinyGsm * modem , uint8_t mux = 0 ) {
bool init ( TinyGsmXBee * modem , uint8_t mux = 0 ) {
this - > at = modem ;
this - > mux = mux ;
sock_connected = false ;
@ -73,19 +86,25 @@ public:
public :
virtual int connect ( const char * host , uint16_t port ) {
at - > streamClear ( ) ; / / Empty anything remaining in the buffer ;
at - > commandMode ( ) ;
sock_connected = at - > modemConnect ( host , port , mux , false ) ;
at - > writeChanges ( ) ;
at - > exitCommand ( ) ;
bool sock_connected = false ;
if ( at - > commandMode ( ) ) { / / Don ' t try if we didn ' t successfully get into command mode
sock_connected = at - > modemConnect ( host , port , mux , false ) ;
at - > writeChanges ( ) ;
at - > exitCommand ( ) ;
}
at - > streamClear ( ) ; / / Empty anything remaining in the buffer ;
return sock_connected ;
}
virtual int connect ( IPAddress ip , uint16_t port ) {
at - > streamClear ( ) ; / / Empty anything remaining in the buffer ;
at - > commandMode ( ) ;
sock_connected = at - > modemConnect ( ip , port , mux , false ) ;
at - > writeChanges ( ) ;
at - > exitCommand ( ) ;
bool sock_connected = false ;
if ( at - > commandMode ( ) ) { / / Don ' t try if we didn ' t successfully get into command mode
sock_connected = at - > modemConnect ( ip , port , mux , false ) ;
at - > writeChanges ( ) ;
at - > exitCommand ( ) ;
}
at - > streamClear ( ) ; / / Empty anything remaining in the buffer ;
return sock_connected ;
}
@ -100,7 +119,7 @@ public:
at - > exitCommand ( ) ;
at - > modemSend ( " " , 1 , mux ) ;
at - > commandMode ( ) ;
at - > sendAT ( GF ( " TM64 " ) ) ; / / Set socket timeout back to 10 seconds ;
at - > sendAT ( GF ( " TM64 " ) ) ; / / Set socket timeout back to 10 seconds ;
at - > waitResponse ( ) ;
at - > writeChanges ( ) ;
at - > exitCommand ( ) ;
@ -110,7 +129,6 @@ public:
virtual size_t write ( const uint8_t * buf , size_t size ) {
TINY_GSM_YIELD ( ) ;
/ / at - > maintain ( ) ;
return at - > modemSend ( buf , size , mux ) ;
}
@ -125,7 +143,7 @@ public:
virtual int read ( uint8_t * buf , size_t size ) {
TINY_GSM_YIELD ( ) ;
return at - > stream . readBytes ( buf , size ) ;
return at - > stream . readBytes ( ( char * ) buf , size ) ;
}
virtual int read ( ) {
@ -151,47 +169,69 @@ public:
String remoteIP ( ) TINY_GSM_ATTR_NOT_IMPLEMENTED ;
private :
TinyGsm * at ;
TinyGsmXBee * at ;
uint8_t mux ;
bool sock_connected ;
} ;
/ / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = / /
/ / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = / /
/ / The Secure XBee Client Class
/ / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = / /
/ / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = / /
class GsmClientSecure : public GsmClient
{
public :
GsmClientSecure ( ) { }
GsmClientSecure ( TinyGsm & modem , uint8_t mux = 1 )
GsmClientSecure ( TinyGsmXBee & modem , uint8_t mux = 1 )
: GsmClient ( modem , mux )
{ }
public :
virtual int connect ( const char * host , uint16_t port ) {
at - > streamClear ( ) ; / / Empty anything remaining in the buffer ;
at - > commandMode ( ) ;
sock_connected = at - > modemConnect ( host , port , mux , true ) ;
at - > writeChanges ( ) ;
at - > exitCommand ( ) ;
bool sock_connected = false ;
if ( at - > commandMode ( ) ) { / / Don ' t try if we didn ' t successfully get into command mode
sock_connected = at - > modemConnect ( host , port , mux , true ) ;
at - > writeChanges ( ) ;
at - > exitCommand ( ) ;
}
at - > streamClear ( ) ; / / Empty anything remaining in the buffer ;
return sock_connected ;
}
virtual int connect ( IPAddress ip , uint16_t port ) {
at - > streamClear ( ) ; / / Empty anything remaining in the buffer ;
at - > commandMode ( ) ;
sock_connected = at - > modemConnect ( ip , port , mux , true ) ;
at - > writeChanges ( ) ;
at - > exitCommand ( ) ;
bool sock_connected = false ;
if ( at - > commandMode ( ) ) { / / Don ' t try if we didn ' t successfully get into command mode
sock_connected = at - > modemConnect ( ip , port , mux , true ) ;
at - > writeChanges ( ) ;
at - > exitCommand ( ) ;
}
at - > streamClear ( ) ; / / Empty anything remaining in the buffer ;
return sock_connected ;
}
} ;
/ / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = / /
/ / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = / /
/ / The XBee Modem Functions
/ / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = / /
/ / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = / /
public :
TinyGsm ( Stream & stream )
# ifdef GSM_DEFAULT_STREAM
TinyGsmXBee ( Stream & stream = GSM_DEFAULT_STREAM )
# else
TinyGsmXBee ( Stream & stream )
# endif
: stream ( stream )
{
memset ( sockets , 0 , sizeof ( sockets ) ) ;
}
{ }
/*
* Basic functions
@ -201,23 +241,53 @@ public:
}
bool init ( ) {
guardTime = 1100 ;
commandMode ( ) ;
guardTime = 1100 ; / / Start with a default guard time of 1 second
if ( ! commandMode ( 10 ) ) return false ; / / Try up to 10 times for the init
sendAT ( GF ( " AP0 " ) ) ; / / Put in transparent mode
waitResponse ( ) ;
bool ret_val = waitResponse ( ) = = 1 ;
ret_val & = writeChanges ( ) ;
sendAT ( GF ( " GT64 " ) ) ; / / shorten the guard time to 100 ms
ret_val & = waitResponse ( ) ;
ret_val & = writeChanges ( ) ;
if ( ret_val ) guardTime = 125 ;
sendAT ( GF ( " HS " ) ) ; / / Get the " Hardware Series " ;
String res = readResponse ( ) ;
char buf [ 4 ] = { 0 , } ; / / Set up buffer for response
res . toCharArray ( buf , 4 ) ;
int intRes = strtol ( buf , 0 , 16 ) ;
beeType = ( XBeeType ) intRes ;
exitCommand ( ) ;
return ret_val ;
}
void setBaud ( unsigned long baud ) {
if ( ! commandMode ( ) ) return ;
switch ( baud )
{
case 2400 : sendAT ( GF ( " BD1 " ) ) ; break ;
case 4800 : sendAT ( GF ( " BD2 " ) ) ; break ;
case 9600 : sendAT ( GF ( " BD3 " ) ) ; break ;
case 19200 : sendAT ( GF ( " BD4 " ) ) ; break ;
case 38400 : sendAT ( GF ( " BD5 " ) ) ; break ;
case 57600 : sendAT ( GF ( " BD6 " ) ) ; break ;
case 115200 : sendAT ( GF ( " BD7 " ) ) ; break ;
case 230400 : sendAT ( GF ( " BD8 " ) ) ; break ;
case 460800 : sendAT ( GF ( " BD9 " ) ) ; break ;
case 921600 : sendAT ( GF ( " BDA " ) ) ; break ;
default : {
DBG ( GF ( " Specified baud rate is unsupported! Setting to 9600 baud. " ) ) ;
sendAT ( GF ( " BD3 " ) ) ; / / Set to default of 9600
break ;
}
}
waitResponse ( ) ;
writeChanges ( ) ;
sendAT ( GF ( " HS " ) ) ; / / Get the " Hardware Series " ; 0x601 for S6B ( Wifi )
/ / wait for the response
unsigned long startMillis = millis ( ) ;
while ( ! stream . available ( ) & & millis ( ) - startMillis < 1000 ) { } ;
String res = streamReadUntil ( ' \r ' ) ; / / Does not send an OK , just the result
exitCommand ( ) ;
if ( res = = " 601 " ) beeType = S6B ;
else beeType = LTEC1 ;
guardTime = 125 ;
return true ;
}
bool testAT ( unsigned long timeout = 10000L ) {
@ -238,52 +308,100 @@ public:
void maintain ( ) { }
bool factoryDefault ( ) {
commandMode ( ) ;
if ( ! commandMode ( ) ) return false ; / / Return immediately
sendAT ( GF ( " RE " ) ) ;
bool ret_val = waitResponse ( ) = = 1 ;
writeChanges ( ) ;
ret_val & = writeChanges ( ) ;
exitCommand ( ) ;
return ret_val ;
}
String getModemInfo ( ) {
String modemInf = " " ;
if ( ! commandMode ( ) ) return modemInf ; / / Try up to 10 times for the init
sendAT ( GF ( " HS " ) ) ; / / Get the " Hardware Series "
modemInf + = readResponse ( ) ;
exitCommand ( ) ;
return modemInf ;
}
bool hasSSL ( ) {
if ( beeType = = S6B ) return false ;
if ( beeType = = XBEE_ S6B_WIFI ) return false ;
else return true ;
}
XBeeType getBeeType ( ) {
return beeType ;
}
String getBeeName ( ) {
switch ( beeType ) {
case XBEE_S6B_WIFI : return " Digi XBee® Wi-Fi " ;
case XBEE_LTE1_VZN : return " Digi XBee® Cellular LTE Cat 1 " ;
case XBEE_3G : return " Digi XBee® Cellular 3G " ;
case XBEE3_LTE1_ATT : return " Digi XBee3™ Cellular LTE CAT 1 " ;
case XBEE3_LTEM_ATT : return " Digi XBee3™ Cellular LTE-M " ;
case XBEE3_LTENB : return " Digi XBee3™ Cellular NB-IoT " ;
}
}
/*
* Power functions
*/
bool restart ( ) {
commandMode ( ) ;
if ( ! commandMode ( ) ) return false ; / / Return immediately
sendAT ( GF ( " AM1 " ) ) ; / / Digi suggests putting into airplane mode before restarting
/ / This allows the sockets and connections to close cleanly
writeChanges ( ) ;
if ( waitResponse ( ) ! = 1 ) goto fail ;
sendAT ( GF ( " FR " ) ) ;
if ( waitResponse ( ) ! = 1 ) {
return false ;
}
if ( waitResponse ( ) ! = 1 ) goto fail ;
delay ( 2000 ) ; / / Actually resets about 2 seconds later
/ / Wait until reboot complete and responds to command mode call again
for ( unsigned long start = millis ( ) ; millis ( ) - start < 60000L ; ) {
if ( commandMode ( ) ) {
if ( commandMode ( 1 ) ) {
sendAT ( GF ( " AM0 " ) ) ; / / Turn off airplane mode
writeChanges ( ) ;
exitCommand ( ) ;
return true ;
delay ( 250 ) ; / / wait a litle before trying again
}
}
exitCommand ( ) ;
return false ; ;
return true ;
fail :
exitCommand ( ) ;
return false ;
}
void setupPinSleep ( ) {
commandMode ( ) ;
sendAT ( GF ( " SM " ) , 1 ) ;
void setupPinSleep ( bool maintainAssociation = false ) {
if ( ! commandMode ( ) ) return ; / / Return immediately
sendAT ( GF ( " SM " ) , 1 ) ; / / Pin sleep
waitResponse ( ) ;
if ( beeType = = S6B ) {
sendAT ( GF ( " SO " ) , 200 ) ;
if ( beeType = = XBEE_S6B_WIFI & & ! maintainAssociation ) {
sendAT ( GF ( " SO " ) , 200 ) ; / / For lowest power , dissassociated deep sleep
waitResponse ( ) ;
}
else if ( ! maintainAssociation ) {
sendAT ( GF ( " SO " ) , 1 ) ; / / For lowest power , dissassociated deep sleep
/ / Not supported by all modules , will return " ERROR "
waitResponse ( ) ;
}
writeChanges ( ) ;
exitCommand ( ) ;
}
bool poweroff ( ) TINY_GSM_ATTR_NOT_IMPLEMENTED ;
bool radioOff ( ) TINY_GSM_ATTR_NOT_IMPLEMENTED ;
bool sleepEnable ( bool enable = true ) TINY_GSM_ATTR_NOT_IMPLEMENTED ;
/*
* SIM card functions
*/
@ -293,23 +411,17 @@ public:
}
String getSimCCID ( ) {
commandMode ( ) ;
if ( ! commandMode ( ) ) return "" ; / / Return immediately
sendAT ( GF ( " S# " ) ) ;
/ / wait for the response
unsigned long startMillis = millis ( ) ;
while ( ! stream . available ( ) & & millis ( ) - startMillis < 1000 ) { } ;
String res = streamReadUntil ( ' \r ' ) ; / / Does not send an OK , just the result
String res = readResponse ( ) ;
exitCommand ( ) ;
return res ;
}
String getIMEI ( ) {
commandMode ( ) ;
if ( ! commandMode ( ) ) return "" ; / / Return immediately
sendAT ( GF ( " IM " ) ) ;
/ / wait for the response
unsigned long startMillis = millis ( ) ;
while ( ! stream . available ( ) & & millis ( ) - startMillis < 1000 ) { } ;
String res = streamReadUntil ( ' \r ' ) ; / / Does not send an OK , just the result
String res = readResponse ( ) ;
exitCommand ( ) ;
return res ;
}
@ -319,37 +431,82 @@ public:
}
RegStatus getRegistrationStatus ( ) {
commandMode ( ) ;
sendAT ( GF ( " AI " ) ) ;
/ / wait for the response
unsigned long startMillis = millis ( ) ;
while ( ! stream . available ( ) & & millis ( ) - startMillis < 1000 ) { } ;
String res = streamReadUntil ( ' \r ' ) ; / / Does not send an OK , just the result
exitCommand ( ) ;
if ( res = = GF ( " 0 " ) )
return REG_OK_HOME ;
if ( ! commandMode ( ) ) return REG_UNKNOWN ; / / Return immediately
else if ( res = = GF ( " 13 " ) | | res = = GF ( " 2A " ) )
return REG_UNREGISTERED ;
else if ( res = = GF ( " FF " ) | | res = = GF ( " 22 " ) | | res = = GF ( " 23 " ) | |
res = = GF ( " 40 " ) | | res = = GF ( " 41 " ) | | res = = GF ( " 42 " ) )
return REG_SEARCHING ;
else if ( res = = GF ( " 24 " ) | | res = = GF ( " 25 " ) | | res = = GF ( " 27 " ) )
return REG_DENIED ;
sendAT ( GF ( " AI " ) ) ;
String res = readResponse ( ) ;
char buf [ 3 ] = { 0 , } ; / / Set up buffer for response
res . toCharArray ( buf , 3 ) ;
int intRes = strtol ( buf , 0 , 16 ) ;
RegStatus stat = REG_UNKNOWN ;
switch ( beeType ) {
case XBEE_S6B_WIFI : {
if ( intRes = = 0x00 ) / / 0x00 Successfully joined an access point , established IP addresses and IP listening sockets
stat = REG_OK ;
else if ( intRes = = 0x01 ) / / 0x01 Wi - Fi transceiver initialization in progress .
stat = REG_SEARCHING ;
else if ( intRes = = 0x02 ) / / 0x02 Wi - Fi transceiver initialized , but not yet scanning for access point .
stat = REG_SEARCHING ;
else if ( intRes = = 0x13 ) { / / 0x13 Disconnecting from access point .
restart ( ) ; / / Restart the device ; the S6B tends to get stuck " disconnecting "
stat = REG_UNREGISTERED ;
}
else if ( intRes = = 0x23 ) / / 0x23 SSID not configured .
stat = REG_UNREGISTERED ;
else if ( intRes = = 0x24 ) / / 0x24 Encryption key invalid ( either NULL or invalid length for WEP ) .
stat = REG_DENIED ;
else if ( intRes = = 0x27 ) / / 0x27 SSID was found , but join failed .
stat = REG_DENIED ;
else if ( intRes = = 0x40 ) / / 0x40 Waiting for WPA or WPA2 Authentication .
stat = REG_SEARCHING ;
else if ( intRes = = 0x41 ) / / 0x41 Device joined a network and is waiting for IP configuration to complete
stat = REG_SEARCHING ;
else if ( intRes = = 0x42 ) / / 0x42 Device is joined , IP is configured , and listening sockets are being set up .
stat = REG_SEARCHING ;
else if ( intRes = = 0xFF ) / / 0xFF Device is currently scanning for the configured SSID .
stat = REG_SEARCHING ;
else stat = REG_UNKNOWN ;
break ;
}
default : {
if ( intRes = = 0x00 ) / / 0x00 Connected to the Internet .
stat = REG_OK ;
else if ( intRes = = 0x22 ) / / 0x22 Registering to cellular network .
stat = REG_SEARCHING ;
else if ( intRes = = 0x23 ) / / 0x23 Connecting to the Internet .
stat = REG_SEARCHING ;
else if ( intRes = = 0x24 ) / / 0x24 The cellular component is missing , corrupt , or otherwise in error .
stat = REG_UNKNOWN ;
else if ( intRes = = 0x25 ) / / 0x25 Cellular network registration denied .
stat = REG_DENIED ;
else if ( intRes = = 0x2A ) { / / 0x2A Airplane mode .
sendAT ( GF ( " AM0 " ) ) ; / / Turn off airplane mode
waitResponse ( ) ;
writeChanges ( ) ;
stat = REG_UNKNOWN ;
}
else if ( intRes = = 0x2F ) { / / 0x2F Bypass mode active .
sendAT ( GF ( " AP0 " ) ) ; / / Set back to transparent mode
waitResponse ( ) ;
writeChanges ( ) ;
stat = REG_UNKNOWN ;
}
else if ( intRes = = 0xFF ) / / 0xFF Device is currently scanning for the configured SSID .
stat = REG_SEARCHING ;
else stat = REG_UNKNOWN ;
break ;
}
}
else return REG_UNKNOWN ;
exitCommand ( ) ;
return stat ;
}
String getOperator ( ) {
commandMode ( ) ;
if ( ! commandMode ( ) ) return "" ; / / Return immediately
sendAT ( GF ( " MN " ) ) ;
/ / wait for the response
unsigned long startMillis = millis ( ) ;
while ( ! stream . available ( ) & & millis ( ) - startMillis < 1000 ) { } ;
String res = streamReadUntil ( ' \r ' ) ; / / Does not send an OK , just the result
String res = readResponse ( ) ;
exitCommand ( ) ;
return res ;
}
@ -359,25 +516,21 @@ public:
*/
int getSignalQuality ( ) {
commandMode ( ) ;
if ( beeType = = S6B ) sendAT ( GF ( " LM " ) ) ; / / ask for the " link margin " - the dB above sensitivity
if ( ! commandMode ( ) ) return 0 ; / / Return immediately
if ( beeType = = XBEE_ S6B_WIFI ) sendAT ( GF ( " LM " ) ) ; / / ask for the " link margin " - the dB above sensitivity
else sendAT ( GF ( " DB " ) ) ; / / ask for the cell strength in dBm
/ / wait for the response
unsigned long startMillis = millis ( ) ;
while ( ! stream . available ( ) & & millis ( ) - startMillis < 1000 ) { } ;
char buf [ 2 ] = { 0 } ; / / Set up buffer for response
buf [ 0 ] = streamRead ( ) ;
buf [ 1 ] = streamRead ( ) ;
/ / DBG ( buf [ 0 ] , buf [ 1 ] , " \n " ) ;
String res = readResponse ( ) ; / / it works better if we read in as a string
exitCommand ( ) ;
int intr = strtol ( buf , 0 , 16 ) ;
if ( beeType = = S6B ) return - 93 + intr ; / / the maximum sensitivity is - 93 dBm
else return - 1 * intr ; / / need to convert to negative number
char buf [ 3 ] = { 0 , } ; / / Set up buffer for response
res . toCharArray ( buf , 3 ) ;
int intRes = strtol ( buf , 0 , 16 ) ;
if ( beeType = = XBEE_S6B_WIFI ) return - 93 + intRes ; / / the maximum sensitivity is - 93 dBm
else return - 1 * intRes ; / / need to convert to negative number
}
bool isNetworkConnected ( ) {
RegStatus s = getRegistrationStatus ( ) ;
return ( s = = REG_OK_HOME | | s = = REG_OK_ROAMING ) ;
return ( s = = REG_OK ) ;
}
bool waitForNetwork ( unsigned long timeout = 60000L ) {
@ -385,7 +538,7 @@ public:
if ( isNetworkConnected ( ) ) {
return true ;
}
delay ( 250 ) ;
/ / delay ( 250 ) ; / / Enough delay going in and out of command mode
}
return false ;
}
@ -395,20 +548,16 @@ public:
*/
bool networkConnect ( const char * ssid , const char * pwd ) {
commandMode ( ) ;
if ( ! commandMode ( ) ) return false ; / / return immediately
sendAT ( GF ( " EE " ) , 2 ) ; / / Set security to WPA2
waitResponse ( ) ;
if ( waitResponse ( ) ! = 1 ) goto fail ;
sendAT ( GF ( " ID " ) , ssid ) ;
if ( waitResponse ( ) ! = 1 ) {
goto fail ;
}
if ( waitResponse ( ) ! = 1 ) goto fail ;
sendAT ( GF ( " PK " ) , pwd ) ;
if ( waitResponse ( ) ! = 1 ) {
goto fail ;
}
if ( waitResponse ( ) ! = 1 ) goto fail ;
writeChanges ( ) ;
exitCommand ( ) ;
@ -421,17 +570,22 @@ fail:
}
bool networkDisconnect ( ) {
return false ; / / Doesn ' t support disconnecting
if ( ! commandMode ( ) ) return false ; / / return immediately
sendAT ( GF ( " NR0 " ) ) ; / / Do a network reset in order to disconnect
int res = ( 1 = = waitResponse ( 5000 ) ) ;
writeChanges ( ) ;
exitCommand ( ) ;
return res ;
}
String getLocalIP ( ) {
commandMode ( ) ;
if ( ! commandMode ( ) ) return "" ; / / Return immediately
sendAT ( GF ( " MY " ) ) ;
String IPaddr ; IPaddr . reserve ( 16 ) ;
/ / wait for the response
unsigned long startMillis = millis ( ) ;
while ( stream . available ( ) < 8 & & millis ( ) - startMillis < 30000 ) { } ;
IPaddr = streamReadUntil ( ' \r ' ) ; / / read result
/ / wait for the response - this response can be very slow
IPaddr = readResponse ( 30000 ) ;
exitCommand ( ) ;
IPaddr . trim ( ) ;
return IPaddr ;
}
@ -443,7 +597,7 @@ fail:
* GPRS functions
*/
bool gprsConnect ( const char * apn , const char * user = NULL , const char * pwd = NULL ) {
commandMode ( ) ;
if ( ! commandMode ( ) ) return false ; / / Return immediately
sendAT ( GF ( " AN " ) , apn ) ; / / Set the APN
waitResponse ( ) ;
writeChanges ( ) ;
@ -451,8 +605,20 @@ fail:
return true ;
}
bool gprsDisconnect ( ) { / / TODO
return false ;
bool gprsDisconnect ( ) {
if ( ! commandMode ( ) ) return false ; / / return immediately
sendAT ( GF ( " AM1 " ) ) ; / / Cheating and disconnecting by turning on airplane mode
int res = ( 1 = = waitResponse ( 5000 ) ) ;
writeChanges ( ) ;
sendAT ( GF ( " AM0 " ) ) ; / / Airplane mode off
waitResponse ( 5000 ) ;
writeChanges ( ) ;
exitCommand ( ) ;
return res ;
}
bool isGprsConnected ( ) {
return isNetworkConnected ( ) ;
}
/*
@ -462,35 +628,67 @@ fail:
String sendUSSD ( const String & code ) TINY_GSM_ATTR_NOT_IMPLEMENTED ;
bool sendSMS ( const String & number , const String & text ) {
commandMode ( ) ;
if ( ! commandMode ( ) ) return false ; / / Return immediately
sendAT ( GF ( " IP " ) , 2 ) ; / / Put in text messaging mode
waitResponse ( ) ;
if ( waitResponse ( ) ! = 1 ) goto fail ;
sendAT ( GF ( " PH " ) , number ) ; / / Set the phone number
waitResponse ( ) ;
sendAT ( GF ( " TDD " ) ) ; / / Set the text delimiter to the standard 0x0D ( carriabe return )
waitResponse ( ) ;
writeChanges ( ) ;
if ( waitResponse ( ) ! = 1 ) goto fail ;
sendAT ( GF ( " TDD " ) ) ; / / Set the text delimiter to the standard 0x0D ( carriage return )
if ( waitResponse ( ) ! = 1 ) goto fail ;
if ( ! writeChanges ( ) ) goto fail ;
exitCommand ( ) ;
stream . print ( text ) ;
streamWrite ( text ) ;
stream . write ( ( char ) 0x0D ) ; / / close off with the carriage return
return true ;
fail :
exitCommand ( ) ;
return false ;
}
/*
* Location functions
*/
private :
String getGsmLocation ( ) TINY_GSM_ATTR_NOT_AVAILABLE ;
int modemConnect ( const char * host , uint16_t port , uint8_t mux = 0 , bool ssl = false ) {
sendAT ( GF ( " LA " ) , host ) ;
/*
* Battery functions
*/
uint16_t getBattVoltage ( ) TINY_GSM_ATTR_NOT_AVAILABLE ;
int getBattPercent ( ) TINY_GSM_ATTR_NOT_AVAILABLE ;
protected :
bool modemConnect ( const char * host , uint16_t port , uint8_t mux = 0 , bool ssl = false ) {
String strIP ; strIP . reserve ( 16 ) ;
/ / wait for the response
unsigned long startMillis = millis ( ) ;
while ( stream . available ( ) < 8 & & millis ( ) - startMillis < 30000 ) { } ;
strIP = streamReadUntil ( ' \r ' ) ; / / read result
IPAddress ip = TinyGsmIpFromString ( strIP ) ;
return modemConnect ( ip , port , mux , ssl ) ;
bool gotIP = false ;
/ / XBee ' s require a numeric IP address for connection , but do provide the
/ / functionality to look up the IP address from a fully qualified domain name
while ( ! gotIP & & millis ( ) - startMillis < 45000L ) / / the lookup can take a while
{
sendAT ( GF ( " LA " ) , host ) ;
while ( stream . available ( ) < 4 ) { } ; / / wait for any response
strIP = stream . readStringUntil ( ' \r ' ) ; / / read result
strIP . trim ( ) ;
DBG ( " <<< " , strIP ) ;
if ( ! strIP . endsWith ( GF ( " ERROR " ) ) ) gotIP = true ;
delay ( 100 ) ; / / short wait before trying again
}
if ( gotIP ) { / / No reason to continue if we don ' t know the IP address
IPAddress ip = TinyGsmIpFromString ( strIP ) ;
return modemConnect ( ip , port , mux , ssl ) ;
}
else return false ;
}
int modemConnect ( IPAddress ip , uint16_t port , uint8_t mux = 0 , bool ssl = false ) {
bool modemConnect ( IPAddress ip , uint16_t port , uint8_t mux = 0 , bool ssl = false ) {
bool success = true ;
String host ; host . reserve ( 16 ) ;
host + = ip [ 0 ] ;
host + = " . " ;
@ -500,17 +698,17 @@ private:
host + = " . " ;
host + = ip [ 3 ] ;
if ( ssl ) {
sendAT ( GF ( " IP " ) , 4 ) ; / / Put in TCP mode
waitResponse ( ) ;
sendAT ( GF ( " IP " ) , 4 ) ; / / Put in SSL over TCP communication mode
success & = ( 1 = = waitResponse ( ) ) ;
} else {
sendAT ( GF ( " IP " ) , 1 ) ; / / Put in TCP mode
waitResponse ( ) ;
success & = ( 1 = = waitResponse ( ) ) ;
}
sendAT ( GF ( " DL " ) , host ) ; / / Set the " Destination Address Low "
waitResponse ( ) ;
success & = ( 1 = = waitResponse ( ) ) ;
sendAT ( GF ( " DE " ) , String ( port , HEX ) ) ; / / Set the destination port
int rsp = waitResponse ( ) ;
return rsp ;
success & = ( 1 = = waitResponse ( ) ) ;
return success ;
}
int modemSend ( const void * buff , size_t len , uint8_t mux = 0 ) {
@ -520,7 +718,7 @@ private:
}
bool modemGetConnected ( uint8_t mux = 0 ) {
commandMode ( ) ;
if ( ! commandMode ( ) ) return false ;
sendAT ( GF ( " AI " ) ) ;
int res = waitResponse ( GF ( " 0 " ) ) ;
exitCommand ( ) ;
@ -542,32 +740,33 @@ public:
streamWrite ( tail . . . ) ;
}
int streamRead ( ) { return stream . read ( ) ; }
String streamReadUntil ( char c ) {
TINY_GSM_YIELD ( ) ;
String return_string = stream . readStringUntil ( c ) ;
return_string . trim ( ) ;
/ / DBG ( return_string , c ) ;
return return_string ;
}
void streamClear ( void ) {
while ( stream . available ( ) ) { streamRead ( ) ; }
}
bool commandMode ( void ) {
delay ( guardTime ) ; / / cannot send anything for 1 second before entering command mode
streamWrite ( GF ( " +++ " ) ) ; / / enter command mode
/ / DBG ( " \r \n +++ \r \n " ) ;
return 1 = = waitResponse ( guardTime * 2 ) ;
TINY_GSM_YIELD ( ) ;
while ( stream . available ( ) ) { stream . read ( ) ; }
}
bool commandMode ( int retries = 2 ) {
int triesMade = 0 ;
bool success = false ;
streamClear ( ) ; / / Empty everything in the buffer before starting
while ( ! success and triesMade < retries ) {
/ / Cannot send anything for 1 " guard time " before entering command mode
/ / Default guard time is 1 s , but the init fxn decreases it to 250 ms
delay ( guardTime ) ;
streamWrite ( GF ( " +++ " ) ) ; / / enter command mode
DBG ( " +++ " ) ;
success = ( 1 = = waitResponse ( guardTime * 2 ) ) ;
triesMade + + ;
}
return success ;
}
void writeChanges ( void ) {
bool writeChanges ( void ) {
sendAT ( GF ( " WR " ) ) ; / / Write changes to flash
waitResponse ( ) ;
if ( 1 ! = waitResponse ( ) ) return false ;
sendAT ( GF ( " AC " ) ) ; / / Apply changes
waitResponse ( ) ;
if ( 1 ! = waitResponse ( ) ) return false ;
return true ;
}
void exitCommand ( void ) {
@ -575,6 +774,16 @@ public:
waitResponse ( ) ;
}
String readResponse ( uint32_t timeout = 1000 ) {
TINY_GSM_YIELD ( ) ;
unsigned long startMillis = millis ( ) ;
while ( ! stream . available ( ) & & millis ( ) - startMillis < timeout ) { } ;
String res = stream . readStringUntil ( ' \r ' ) ; / / lines end with carriage returns
res . trim ( ) ;
DBG ( " <<< " , res ) ;
return res ;
}
template < typename . . . Args >
void sendAT ( Args . . . cmd ) {
streamWrite ( " AT " , cmd . . . , GSM_NL ) ;
@ -594,13 +803,13 @@ public:
String r4s ( r4 ) ; r4s . trim ( ) ;
String r5s ( r5 ) ; r5s . trim ( ) ;
DBG ( " ### ..: " , r1s , " , " , r2s , " , " , r3s , " , " , r4s , " , " , r5s ) ; */
data . reserve ( 64 ) ;
data . reserve ( 1 6) ; / / Should never be getting much here for the XBee
int index = 0 ;
unsigned long startMillis = millis ( ) ;
do {
TINY_GSM_YIELD ( ) ;
while ( stream . available ( ) > 0 ) {
int a = streamR ead ( ) ;
int a = stream . r ead( ) ;
if ( a < = 0 ) continue ; / / Skip 0x00 bytes , just in case
data + = ( char ) a ;
if ( r1 & & data . endsWith ( r1 ) ) {
@ -625,7 +834,7 @@ finish:
if ( ! index ) {
data . trim ( ) ;
data . replace ( GSM_NL GSM_NL , GSM_NL ) ;
data . replace ( GSM_NL , " \r \n " " " ) ;
data . replace ( GSM_NL , " \r \n " ) ;
if ( data . length ( ) ) {
DBG ( " ### Unhandled: " , data , " \r \n " ) ;
} else {