|
|
@ -329,25 +329,43 @@ class TinyGsmXBee : public TinyGsmModem<TinyGsmXBee>, |
|
|
|
digitalWrite(resetPin, HIGH); |
|
|
|
} |
|
|
|
|
|
|
|
if (pin && strlen(pin) > 0) { |
|
|
|
DBG("XBee's do not support SIMs that require an unlock pin!"); |
|
|
|
} |
|
|
|
|
|
|
|
XBEE_COMMAND_START_DECORATOR(10, false) |
|
|
|
|
|
|
|
sendAT(GF("AP0")); // Put in transparent mode |
|
|
|
bool ret_val = waitResponse() == 1; |
|
|
|
bool changesMade = false; |
|
|
|
bool ret_val = true; |
|
|
|
|
|
|
|
sendAT(GF("GT64")); // shorten the guard time to 100ms |
|
|
|
ret_val &= waitResponse() == 1; |
|
|
|
if (ret_val) guardTime = 110; |
|
|
|
// if there's a pin, we need to re-write to flash each time |
|
|
|
if (pin && strlen(pin) > 0) { |
|
|
|
sendAT(GF("PN"), pin); |
|
|
|
if (waitResponse() != 1) { |
|
|
|
ret_val = false; |
|
|
|
} else { |
|
|
|
changesMade = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Put in transparent mode, if it isn't already |
|
|
|
changesMade |= changeSettingIfNeeded(GF("AP"), 0); |
|
|
|
|
|
|
|
// shorten the guard time to 100ms, if it was anything else |
|
|
|
sendAT(GF("GT")); |
|
|
|
if (readResponseInt() != 64) { |
|
|
|
sendAT(GF("GT"), 64); |
|
|
|
ret_val &= waitResponse() == 1; |
|
|
|
if (ret_val) { |
|
|
|
guardTime = 110; |
|
|
|
changesMade = true; |
|
|
|
} |
|
|
|
} else { |
|
|
|
guardTime = 110; |
|
|
|
} |
|
|
|
|
|
|
|
// Make sure the command mode drop-out time is long enough that we won't |
|
|
|
// fall out of command mode without intentionally leaving it. This is the |
|
|
|
// default drop out time of 0x64 x 100ms (10 seconds) |
|
|
|
sendAT(GF("CT64")); |
|
|
|
ret_val &= waitResponse() == 1; |
|
|
|
ret_val &= writeChanges(); |
|
|
|
changesMade |= changeSettingIfNeeded(GF("CT"), 64); |
|
|
|
|
|
|
|
if (changesMade) { ret_val &= writeChanges(); } |
|
|
|
|
|
|
|
getSeries(); // Get the "Hardware Series"; |
|
|
|
|
|
|
@ -362,25 +380,28 @@ class TinyGsmXBee : public TinyGsmModem<TinyGsmXBee>, |
|
|
|
|
|
|
|
void setBaudImpl(uint32_t baud) { |
|
|
|
XBEE_COMMAND_START_DECORATOR(5, ) |
|
|
|
bool changesMade = false; |
|
|
|
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; |
|
|
|
case 2400: changesMade |= changeSettingIfNeeded(GF("BD"), 1); break; |
|
|
|
case 4800: changesMade |= changeSettingIfNeeded(GF("BD"), 2); break; |
|
|
|
case 9600: changesMade |= changeSettingIfNeeded(GF("BD"), 3); break; |
|
|
|
case 19200: changesMade |= changeSettingIfNeeded(GF("BD"), 4); break; |
|
|
|
case 38400: changesMade |= changeSettingIfNeeded(GF("BD"), 5); break; |
|
|
|
case 57600: changesMade |= changeSettingIfNeeded(GF("BD"), 6); break; |
|
|
|
case 115200: changesMade |= changeSettingIfNeeded(GF("BD"), 7); break; |
|
|
|
case 230400: changesMade |= changeSettingIfNeeded(GF("BD"), 8); break; |
|
|
|
case 460800: changesMade |= changeSettingIfNeeded(GF("BD"), 9); break; |
|
|
|
case 921600: |
|
|
|
changesMade |= changeSettingIfNeeded(GF("BD"), String("A")); |
|
|
|
break; |
|
|
|
default: { |
|
|
|
DBG(GF("Specified baud rate is unsupported! Setting to 9600 baud.")); |
|
|
|
sendAT(GF("BD3")); // Set to default of 9600 |
|
|
|
changesMade |= changeSettingIfNeeded(GF("BD"), |
|
|
|
3); // Set to default of 9600 |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
waitResponse(); |
|
|
|
writeChanges(); |
|
|
|
if (changesMade) { writeChanges(); } |
|
|
|
XBEE_COMMAND_END_DECORATOR |
|
|
|
} |
|
|
|
|
|
|
@ -533,20 +554,21 @@ class TinyGsmXBee : public TinyGsmModem<TinyGsmXBee>, |
|
|
|
|
|
|
|
if (beeType == XBEE_UNKNOWN) getSeries(); // Command depends on series |
|
|
|
|
|
|
|
sendAT(GF("SM"), 1); // Pin sleep |
|
|
|
waitResponse(); |
|
|
|
bool changesMade = false; |
|
|
|
|
|
|
|
// Pin sleep |
|
|
|
changesMade |= changeSettingIfNeeded(GF("SM"), 1); |
|
|
|
|
|
|
|
if (beeType == XBEE_S6B_WIFI && !maintainAssociation) { |
|
|
|
sendAT(GF("SO"), 200); // For lowest power, dissassociated deep sleep |
|
|
|
waitResponse(); |
|
|
|
// For lowest power, dissassociated deep sleep |
|
|
|
changesMade |= changeSettingIfNeeded(GF("SO"), 200); |
|
|
|
} else if (!maintainAssociation) { |
|
|
|
sendAT(GF("SO"), |
|
|
|
1); // For supported cellular modules, maintain association |
|
|
|
// Not supported by all modules, will return "ERROR" |
|
|
|
waitResponse(); |
|
|
|
// For supported cellular modules, maintain association |
|
|
|
// Not supported by all modules, will return "ERROR" |
|
|
|
changesMade |= changeSettingIfNeeded(GF("SO"), 1); |
|
|
|
} |
|
|
|
|
|
|
|
writeChanges(); |
|
|
|
if (changesMade) { writeChanges(); } |
|
|
|
XBEE_COMMAND_END_DECORATOR |
|
|
|
} |
|
|
|
|
|
|
@ -555,6 +577,7 @@ class TinyGsmXBee : public TinyGsmModem<TinyGsmXBee>, |
|
|
|
XBEE_COMMAND_START_DECORATOR(5, false) |
|
|
|
sendAT(GF("SD")); |
|
|
|
bool ret_val = waitResponse(120000L) == 1; |
|
|
|
// make sure we're really shut down |
|
|
|
if (ret_val) { ret_val &= (sendATGetString(GF("AI")) == "2D"); } |
|
|
|
XBEE_COMMAND_END_DECORATOR |
|
|
|
return ret_val; |
|
|
@ -562,12 +585,13 @@ class TinyGsmXBee : public TinyGsmModem<TinyGsmXBee>, |
|
|
|
|
|
|
|
// Enable airplane mode |
|
|
|
bool radioOffImpl() { |
|
|
|
bool success = true; |
|
|
|
bool changesMade = false; |
|
|
|
XBEE_COMMAND_START_DECORATOR(5, false) |
|
|
|
sendAT(GF("AM1")); |
|
|
|
int8_t res = (1 == waitResponse(5000)); |
|
|
|
writeChanges(); |
|
|
|
changesMade = changeSettingIfNeeded(GF("AM"), 1, 5000L); |
|
|
|
if (changesMade) { success = writeChanges(); } |
|
|
|
XBEE_COMMAND_END_DECORATOR |
|
|
|
return res; |
|
|
|
return success; |
|
|
|
} |
|
|
|
|
|
|
|
bool sleepEnableImpl(bool enable = true) TINY_GSM_ATTR_NOT_IMPLEMENTED; |
|
|
@ -742,25 +766,33 @@ class TinyGsmXBee : public TinyGsmModem<TinyGsmXBee>, |
|
|
|
*/ |
|
|
|
protected: |
|
|
|
bool networkConnectImpl(const char* ssid, const char* pwd) { |
|
|
|
bool retVal = true; |
|
|
|
bool changesMade = false; |
|
|
|
bool retVal = true; |
|
|
|
|
|
|
|
XBEE_COMMAND_START_DECORATOR(5, false) |
|
|
|
|
|
|
|
// nh For no pwd don't set set security or pwd |
|
|
|
if (ssid == NULL) retVal = false; |
|
|
|
|
|
|
|
changesMade |= changeSettingIfNeeded(GF("ID"), ssid); |
|
|
|
|
|
|
|
if (pwd && strlen(pwd) > 0) { |
|
|
|
sendAT(GF("EE"), 2); // Set security to WPA2 |
|
|
|
if (waitResponse() != 1) retVal = false; |
|
|
|
// Set security to WPA2 |
|
|
|
changesMade |= changeSettingIfNeeded(GF("EE"), 2); |
|
|
|
// set the password |
|
|
|
// the wifi bee will NOT return the previously set password, |
|
|
|
// so we have no way of knowing if the passwords has changed |
|
|
|
// and must re-write to flash each time |
|
|
|
sendAT(GF("PK"), pwd); |
|
|
|
if (waitResponse() != 1) { |
|
|
|
retVal = false; |
|
|
|
} else { |
|
|
|
changesMade = true; |
|
|
|
} |
|
|
|
} else { |
|
|
|
sendAT(GF("EE"), 0); // Set No security |
|
|
|
changesMade |= changeSettingIfNeeded(GF("EE"), 0); // Set No security |
|
|
|
} |
|
|
|
if (waitResponse() != 1) retVal = false; |
|
|
|
|
|
|
|
sendAT(GF("ID"), ssid); |
|
|
|
if (waitResponse() != 1) retVal = false; |
|
|
|
|
|
|
|
if (!writeChanges()) retVal = false; |
|
|
|
if (changesMade) { retVal &= writeChanges(); } |
|
|
|
|
|
|
|
XBEE_COMMAND_END_DECORATOR |
|
|
|
|
|
|
@ -784,36 +816,48 @@ class TinyGsmXBee : public TinyGsmModem<TinyGsmXBee>, |
|
|
|
protected: |
|
|
|
bool gprsConnectImpl(const char* apn, const char* user = NULL, |
|
|
|
const char* pwd = NULL) { |
|
|
|
bool success = true; |
|
|
|
bool success = true; |
|
|
|
bool changesMade = false; |
|
|
|
XBEE_COMMAND_START_DECORATOR(5, false) |
|
|
|
|
|
|
|
// the cellular bees will NOT return the previously set username or |
|
|
|
// password, so we have no way of knowing if they have changed |
|
|
|
// and must re-write to flash each time |
|
|
|
if (user && strlen(user) > 0) { |
|
|
|
sendAT(GF("CU"), user); // Set the user for the APN |
|
|
|
success &= waitResponse() == 1; |
|
|
|
if (waitResponse() != 1) { |
|
|
|
success = false; |
|
|
|
} else { |
|
|
|
changesMade = true; |
|
|
|
} |
|
|
|
} |
|
|
|
if (pwd && strlen(pwd) > 0) { |
|
|
|
sendAT(GF("CW"), pwd); // Set the password for the APN |
|
|
|
success &= waitResponse() == 1; |
|
|
|
if (waitResponse() != 1) { |
|
|
|
success = false; |
|
|
|
} else { |
|
|
|
changesMade = true; |
|
|
|
} |
|
|
|
} |
|
|
|
XBEE_COMMAND_START_DECORATOR(5, false) |
|
|
|
sendAT(GF("AN"), apn); // Set the APN |
|
|
|
success &= waitResponse() == 1; |
|
|
|
sendAT(GF("AM0")); // Airplane mode off |
|
|
|
waitResponse(5000); |
|
|
|
writeChanges(); |
|
|
|
changesMade |= changeSettingIfNeeded(GF("AN"), String(apn)); // Set the APN |
|
|
|
|
|
|
|
changesMade |= changeSettingIfNeeded(GF("AM"), 0, |
|
|
|
5000L); // Airplane mode off |
|
|
|
|
|
|
|
if (changesMade) { success = writeChanges(); } |
|
|
|
XBEE_COMMAND_END_DECORATOR |
|
|
|
return success; |
|
|
|
} |
|
|
|
|
|
|
|
bool gprsDisconnectImpl() { |
|
|
|
bool success = true; |
|
|
|
XBEE_COMMAND_START_DECORATOR(5, false) |
|
|
|
sendAT( |
|
|
|
GF("AM1")); // Cheating and disconnecting by turning on airplane mode |
|
|
|
int8_t res = (1 == waitResponse(5000)); |
|
|
|
writeChanges(); |
|
|
|
// sendAT(GF("AM0")); // Airplane mode off |
|
|
|
// waitResponse(5000); |
|
|
|
// writeChanges(); |
|
|
|
// Cheating and disconnecting by turning on airplane mode |
|
|
|
bool changesMade = changeSettingIfNeeded(GF("AM"), 1, 5000L); |
|
|
|
|
|
|
|
if (changesMade) { success = writeChanges(); } |
|
|
|
XBEE_COMMAND_END_DECORATOR |
|
|
|
return res; |
|
|
|
return success; |
|
|
|
} |
|
|
|
|
|
|
|
bool isGprsConnectedImpl() { |
|
|
@ -828,7 +872,7 @@ class TinyGsmXBee : public TinyGsmModem<TinyGsmXBee>, |
|
|
|
* SIM card functions |
|
|
|
*/ |
|
|
|
protected: |
|
|
|
bool simUnlockImpl(const char* pin) { // Not supported |
|
|
|
bool simUnlockImpl(const char* pin) { |
|
|
|
if (pin && strlen(pin) > 0) { |
|
|
|
sendAT(GF("PN"), pin); |
|
|
|
return waitResponse() == 1; |
|
|
@ -859,17 +903,44 @@ class TinyGsmXBee : public TinyGsmModem<TinyGsmXBee>, |
|
|
|
String sendUSSDImpl(const String& code) TINY_GSM_ATTR_NOT_AVAILABLE; |
|
|
|
|
|
|
|
bool sendSMSImpl(const String& number, const String& text) { |
|
|
|
bool ret_val = true; |
|
|
|
bool changesMade = false; |
|
|
|
if (!commandMode()) { return false; } // Return immediately |
|
|
|
|
|
|
|
sendAT(GF("IP"), 2); // Put in text messaging mode |
|
|
|
if (waitResponse() != 1) return exitAndFail(); |
|
|
|
sendAT(GF("PH"), number); // Set the phone number |
|
|
|
if (waitResponse() != 1) return exitAndFail(); |
|
|
|
sendAT(GF("TDD")); // Set the text delimiter to the standard 0x0D (carriage |
|
|
|
// return) |
|
|
|
if (waitResponse() != 1) return exitAndFail(); |
|
|
|
sendAT(GF("IP")); // check mode |
|
|
|
if (readResponseInt() != 2) { |
|
|
|
sendAT(GF("IP"), 2); // Put in text messaging mode |
|
|
|
if (waitResponse() != 1) { |
|
|
|
return exitAndFail(); |
|
|
|
} else { |
|
|
|
changesMade = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
sendAT(GF("PH")); // check last number |
|
|
|
if (readResponseString() != String(number)) { |
|
|
|
sendAT(GF("PH"), number); // Set the phone number |
|
|
|
if (waitResponse() != 1) { |
|
|
|
return exitAndFail(); |
|
|
|
} else { |
|
|
|
changesMade = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
sendAT(GF("TD")); // check the text delimiter |
|
|
|
if (readResponseString() != String("D")) { |
|
|
|
sendAT(GF("TDD")); // Set the text delimiter to the standard 0x0D |
|
|
|
//(carriage return) |
|
|
|
if (waitResponse() != 1) { |
|
|
|
return exitAndFail(); |
|
|
|
} else { |
|
|
|
changesMade = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (!writeChanges()) return exitAndFail(); |
|
|
|
if (changesMade) { |
|
|
|
if (!writeChanges()) return exitAndFail(); |
|
|
|
} |
|
|
|
// Get out of command mode to actually send the text |
|
|
|
exitCommand(); |
|
|
|
|
|
|
@ -1021,13 +1092,14 @@ class TinyGsmXBee : public TinyGsmModem<TinyGsmXBee>, |
|
|
|
|
|
|
|
bool modemConnect(IPAddress ip, uint16_t port, uint8_t mux = 0, |
|
|
|
bool ssl = false) { |
|
|
|
bool success = true; |
|
|
|
bool success = true; |
|
|
|
bool changesMade = false; |
|
|
|
|
|
|
|
if (mux != 0) { |
|
|
|
DBG("XBee only supports 1 IP channel in transparent mode!"); |
|
|
|
} |
|
|
|
|
|
|
|
// empty the saved currelty-in-use destination address |
|
|
|
// empty the saved currenty-in-use destination address |
|
|
|
savedOperatingIP = IPAddress(0, 0, 0, 0); |
|
|
|
|
|
|
|
XBEE_COMMAND_START_DECORATOR(5, false) |
|
|
@ -1046,19 +1118,19 @@ class TinyGsmXBee : public TinyGsmModem<TinyGsmXBee>, |
|
|
|
host += ip[3]; |
|
|
|
|
|
|
|
if (ssl) { |
|
|
|
sendAT(GF("IP"), 4); // Put in SSL over TCP communication mode |
|
|
|
success &= (1 == waitResponse()); |
|
|
|
// Put in SSL over TCP communication mode |
|
|
|
changesMade |= changeSettingIfNeeded(GF("IP"), 4); |
|
|
|
} else { |
|
|
|
sendAT(GF("IP"), 1); // Put in TCP mode |
|
|
|
success &= (1 == waitResponse()); |
|
|
|
// Put in TCP mode |
|
|
|
changesMade |= changeSettingIfNeeded(GF("IP"), 1); |
|
|
|
} |
|
|
|
|
|
|
|
sendAT(GF("DL"), host); // Set the "Destination Address Low" |
|
|
|
success &= (1 == waitResponse()); |
|
|
|
sendAT(GF("DE"), String(port, HEX)); // Set the destination port |
|
|
|
success &= (1 == waitResponse()); |
|
|
|
changesMade |= changeSettingIfNeeded( |
|
|
|
GF("DL"), host); // Set the "Destination Address Low" |
|
|
|
changesMade |= changeSettingIfNeeded( |
|
|
|
GF("DE"), String(port, HEX)); // Set the destination port |
|
|
|
|
|
|
|
success &= writeChanges(); |
|
|
|
if (changesMade) { success &= writeChanges(); } |
|
|
|
} |
|
|
|
|
|
|
|
// we'll accept either unknown or connected |
|
|
@ -1114,11 +1186,11 @@ class TinyGsmXBee : public TinyGsmModem<TinyGsmXBee>, |
|
|
|
if (beeType != XBEE_S6B_WIFI) { |
|
|
|
// After a send, verify the outgoing ip if it isn't set |
|
|
|
if (savedOperatingIP == IPAddress(0, 0, 0, 0)) { |
|
|
|
modemGetConnected(); |
|
|
|
modemGetConnected(0); |
|
|
|
} else if (len > 5) { |
|
|
|
// After sending several characters, also re-check |
|
|
|
// NOTE: I'm intentionally not checking after every single character! |
|
|
|
modemGetConnected(); |
|
|
|
modemGetConnected(0); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -1436,6 +1508,34 @@ class TinyGsmXBee : public TinyGsmModem<TinyGsmXBee>, |
|
|
|
return res; |
|
|
|
} |
|
|
|
|
|
|
|
bool changeSettingIfNeeded(GsmConstStr cmd, uint16_t newValue, |
|
|
|
uint32_t timeout_ms = 1000L) { |
|
|
|
sendAT(cmd); |
|
|
|
if (readResponseInt() != newValue) { |
|
|
|
sendAT(cmd, newValue); |
|
|
|
// return false if we attempted to change but failed |
|
|
|
if (waitResponse(timeout_ms) != 1) { return false; } |
|
|
|
// return true if we succeeded in staging a change |
|
|
|
return true; |
|
|
|
} |
|
|
|
// return false if no change is needed |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
bool changeSettingIfNeeded(GsmConstStr cmd, String newValue, |
|
|
|
uint32_t timeout_ms = 1000L) { |
|
|
|
sendAT(cmd); |
|
|
|
if (readResponseString() != newValue) { |
|
|
|
sendAT(cmd, newValue); |
|
|
|
// return false if we attempted to change but failed |
|
|
|
if (waitResponse(timeout_ms) != 1) { return false; } |
|
|
|
// return true if we succeeded in staging a change |
|
|
|
return true; |
|
|
|
} |
|
|
|
// return false if no change is needed |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
bool gotIPforSavedHost() { |
|
|
|
if (savedHost != "" && savedHostIP != IPAddress(0, 0, 0, 0)) |
|
|
|
return true; |
|
|
|