From 99bc551078ba3b9243e40968b5a8d11f01a1d51a Mon Sep 17 00:00:00 2001 From: neilh20 Date: Mon, 3 Jul 2023 16:45:07 -0700 Subject: [PATCH] a/tu_xx01 works. Merged most xbee_fixes #21 --- a/logging_to_MMW/src/logging_to_MMW.cpp | 1 + a/tu_xx01/src/tu_xx01.cpp | 11 -- src/LoggerModem.cpp | 113 +++++++++----- src/LoggerModem.h | 159 +++++++++++++------- src/modems/DigiXBeeWifi.cpp | 191 +++++++++++++++--------- src/modems/DigiXBeeWifi.h | 23 ++- 6 files changed, 314 insertions(+), 184 deletions(-) diff --git a/a/logging_to_MMW/src/logging_to_MMW.cpp b/a/logging_to_MMW/src/logging_to_MMW.cpp index f4b4001e1..87b572aac 100644 --- a/a/logging_to_MMW/src/logging_to_MMW.cpp +++ b/a/logging_to_MMW/src/logging_to_MMW.cpp @@ -156,6 +156,7 @@ const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem #define USE_WIFI_DIGI_S6B 3 #define USE_WIFI_ENVIRODIY_ESP32 4 +//#define USE_MODEM USE_WIFI_DIGI_S6B #define USE_MODEM USE_WIFI_ENVIRODIY_ESP32 #if USE_MODEM == USE_CELL_DIGI_LTE_XBM3 diff --git a/a/tu_xx01/src/tu_xx01.cpp b/a/tu_xx01/src/tu_xx01.cpp index 682a33c88..969738ce4 100644 --- a/a/tu_xx01/src/tu_xx01.cpp +++ b/a/tu_xx01/src/tu_xx01.cpp @@ -1592,17 +1592,6 @@ void setup() { loggerModemPhyInst->modemHardReset(); //Ensure in known state ~ 5mS // loggerModemPhyInst->setModemLED(modemLEDPin); //Used in UI_status subsystem -#if defined Modem_SignalPercent_UUID || defined DIGI_RSSI_UUID || \ - defined DIGI_VCC_UID -#define POLL_MODEM_REQ \ - (loggerModem::PollModemMetaData_t)( \ - loggerModem::POLL_MODEM_META_DATA_RSSI | \ - loggerModem::POLL_MODEM_META_DATA_VCC) - loggerModemPhyInst->pollModemMetadata(loggerModem::POLL_MODEM_META_DATA_RSSI ); - #else - //Ensure its all turned OFF. - loggerModemPhyInst->pollModemMetadata(loggerModem::POLL_MODEM_META_DATA_OFF); -#endif #endif // UseModem_Module // Begin the logger diff --git a/src/LoggerModem.cpp b/src/LoggerModem.cpp index ee018cad9..12d6c7d3c 100644 --- a/src/LoggerModem.cpp +++ b/src/LoggerModem.cpp @@ -10,9 +10,6 @@ #include "LoggerModem.h" // Initialize the static members -loggerModem::PollModemMetaData_t loggerModem::_pollModemMetaData = - POLL_MODEM_META_DATA_DEF; - int16_t loggerModem::_priorRSSI = SENSOR_DEFAULT_I; int16_t loggerModem::_priorSignalPercent = SENSOR_DEFAULT_I; float loggerModem::_priorModemTemp = SENSOR_DEFAULT_F; @@ -67,6 +64,11 @@ String loggerModem::getModemName(void) { return _modemName; } +String loggerModem::getModemDevId(void) { + return _modemName + F(" Sn ") + _modemSerialNumber + F(" HwVer ") + + _modemHwVersion + F(" FwVer ") + _modemFwVersion; +} + void loggerModem::modemPowerUp(void) { if (_powerPin >= 0) { if (_modemSleepRqPin >= 0) { @@ -306,6 +308,18 @@ void loggerModem::setModemPinModes(void) { } _pinModesSet = true; } +} + + +void loggerModem::enableMetadataPolling(uint8_t pollingBitmask) { + _pollModemMetaData |= pollingBitmask; +} +void loggerModem::disableMetadataPolling(uint8_t pollingBitmask) { + _pollModemMetaData |= ~pollingBitmask; +} +void loggerModem::setMetadataPolling(uint8_t pollingBitmask) { + _pollModemMetaData = pollingBitmask; +} // Turn off pins connected to modem #if defined POWERPIN_ALLPINS_OFF @@ -319,12 +333,7 @@ void loggerModem::setModemPinModes(void) { digitalWrite(MODEMPHY_TX_PIN, LOW); digitalWrite(MODEMPHY_RX_PIN, LOW); #endif // POWERPIN_ALLPINS_OFF -} - -void loggerModem::pollModemMetadata(PollModemMetaData_t status) { - _pollModemMetaData = status; -} bool loggerModem::updateModemMetadata(void) { bool success = true; @@ -343,40 +352,64 @@ bool loggerModem::updateModemMetadata(void) { int8_t bpercent = -99; uint16_t volt = 9999; - // Try for up to 15 seconds to get a valid signal quality - uint32_t startMillis = millis(); - do { - success &= getModemSignalQuality(rssi, percent); + MS_DBG(F("Modem polling settings:"), String(_pollModemMetaData, BIN)); + + if ((_pollModemMetaData & MODEM_RSSI_ENABLE_BITMASK) == + MODEM_RSSI_ENABLE_BITMASK || + (_pollModemMetaData & MODEM_PERCENT_SIGNAL_ENABLE_BITMASK) == + MODEM_PERCENT_SIGNAL_ENABLE_BITMASK) { + // Try for up to 15 seconds to get a valid signal quality + uint32_t startMillis = millis(); + do { + success &= getModemSignalQuality(rssi, percent); + loggerModem::_priorRSSI = rssi; + loggerModem::_priorSignalPercent = percent; + if (rssi != 0 && rssi != -9999) break; + delay(250); + } while ((rssi == 0 || rssi == -9999) && + millis() - startMillis < 15000L && success); MS_DBG(F("CURRENT RSSI:"), rssi); MS_DBG(F("CURRENT Percent signal strength:"), percent); - loggerModem::_priorRSSI = rssi; - loggerModem::_priorSignalPercent = percent; - if (rssi != 0 && rssi != -9999) break; - delay(250); - } while ((rssi == 0 || rssi == -9999) && millis() - startMillis < 15000L && - success); - - success &= getModemBatteryStats(state, bpercent, volt); - MS_DBG(F("CURRENT Modem Battery Charge State:"), state); - MS_DBG(F("CURRENT Modem Battery Charge Percentage:"), bpercent); - MS_DBG(F("CURRENT Modem Battery Voltage:"), volt); - if (state != 99) - loggerModem::_priorBatteryState = static_cast(state); - else - loggerModem::_priorBatteryState = static_cast(-9999); - - if (bpercent != -99) - loggerModem::_priorBatteryPercent = static_cast(bpercent); - else - loggerModem::_priorBatteryPercent = static_cast(-9999); - - if (volt != 9999) - loggerModem::_priorBatteryVoltage = static_cast(volt); - else - loggerModem::_priorBatteryVoltage = static_cast(-9999); - - loggerModem::_priorModemTemp = getModemChipTemperature(); - MS_DBG(F("CURRENT Modem Chip Temperature:"), loggerModem::_priorModemTemp); + } else { + MS_DBG(F("Polling for both RSSI and signal strength is disabled")); + } + + if ((_pollModemMetaData & MODEM_BATTERY_STATE_ENABLE_BITMASK) == + MODEM_BATTERY_STATE_ENABLE_BITMASK || + (_pollModemMetaData & MODEM_BATTERY_PERCENT_ENABLE_BITMASK) == + MODEM_BATTERY_PERCENT_ENABLE_BITMASK || + (_pollModemMetaData & MODEM_BATTERY_VOLTAGE_ENABLE_BITMASK) == + MODEM_BATTERY_VOLTAGE_ENABLE_BITMASK) { + success &= getModemBatteryStats(state, bpercent, volt); + MS_DBG(F("CURRENT Modem Battery Charge State:"), state); + MS_DBG(F("CURRENT Modem Battery Charge Percentage:"), bpercent); + MS_DBG(F("CURRENT Modem Battery Voltage:"), volt); + if (state != 99) + loggerModem::_priorBatteryState = static_cast(state); + else + loggerModem::_priorBatteryState = static_cast(-9999); + + if (bpercent != -99) + loggerModem::_priorBatteryPercent = static_cast(bpercent); + else + loggerModem::_priorBatteryPercent = static_cast(-9999); + + if (volt != 9999) + loggerModem::_priorBatteryVoltage = static_cast(volt); + else + loggerModem::_priorBatteryVoltage = static_cast(-9999); + } else { + MS_DBG(F("Polling for all modem battery parameters is disabled")); + } + + if ((_pollModemMetaData & MODEM_TEMPERATURE_ENABLE_BITMASK) == + MODEM_TEMPERATURE_ENABLE_BITMASK) { + loggerModem::_priorModemTemp = getModemChipTemperature(); + MS_DBG(F("CURRENT Modem Chip Temperature:"), + loggerModem::_priorModemTemp); + } else { + MS_DBG(F("Polling for modem chip temperature is disabled")); + } return success; } diff --git a/src/LoggerModem.h b/src/LoggerModem.h index 3e8e114f5..a45e8d36d 100644 --- a/src/LoggerModem.h +++ b/src/LoggerModem.h @@ -68,6 +68,8 @@ * RSSI is a rough calculation, so it has 0 decimal place resolution */ #define MODEM_RSSI_RESOLUTION 0 +/// @brief The bit mask for #_pollModemMetaData to enable RSSI polling. +#define MODEM_RSSI_ENABLE_BITMASK 0b00000001 /// @brief Variable name in /// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/variablename/); /// "RSSI" @@ -94,6 +96,9 @@ * Percent signal is a rough calculation, so it has 0 decimal place resolution */ #define MODEM_PERCENT_SIGNAL_RESOLUTION 0 +/// @brief The bit mask for #_pollModemMetaData to enable percent signal +/// polling. +#define MODEM_PERCENT_SIGNAL_ENABLE_BITMASK 0b00000010 /// @brief Variable name in /// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/variablename/); /// "signalPercent" @@ -124,6 +129,9 @@ * Battery state is a code value; it has 0 decimal place resolution */ #define MODEM_BATTERY_STATE_RESOLUTION 0 +/// @brief The bit mask for #_pollModemMetaData to enable modem battery charging +/// state polling. +#define MODEM_BATTERY_STATE_ENABLE_BITMASK 0b00000100 /// @brief Variable name in /// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/variablename/); /// "batteryChargeState" @@ -151,6 +159,9 @@ /// @brief Decimals places in string representation; battery charge percent /// should have 0. #define MODEM_BATTERY_PERCENT_RESOLUTION 0 +/// @brief The bit mask for #_pollModemMetaData to enable modem battery percent +/// polling. +#define MODEM_BATTERY_PERCENT_ENABLE_BITMASK 0b00001000 /// @brief Variable name in /// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/variablename/); /// "batteryVoltage" @@ -181,6 +192,9 @@ * No supported module has higher than 1mV resolution in battery reading. */ #define MODEM_BATTERY_VOLTAGE_RESOLUTION 0 +/// @brief The bit mask for #_pollModemMetaData to enable modem battery voltage +/// polling. +#define MODEM_BATTERY_VOLTAGE_ENABLE_BITMASK 0b00010000 /// @brief Variable name in /// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/variablename/); /// "batteryVoltage" @@ -210,6 +224,9 @@ * Most modules that can measure temperature measure to 0.1°C */ #define MODEM_TEMPERATURE_RESOLUTION 1 +/// @brief The bit mask for #_pollModemMetaData to enable modem temperature +/// polling. +#define MODEM_TEMPERATURE_ENABLE_BITMASK 0b00100000 /// @brief Variable name in /// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/variablename/); /// "temperature" @@ -236,6 +253,9 @@ /// @brief Decimals places in string representation; total active time should /// have 3. #define MODEM_ACTIVATION_RESOLUTION 3 +/// @brief The bit mask for #_pollModemMetaData to enable modem activation time +/// polling. +#define MODEM_ACTIVATION_ENABLE_BITMASK 0b01000000 /// @brief Variable name in /// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/variablename/); /// "timeElapsed" @@ -260,6 +280,9 @@ /// @brief Decimals places in string representation; total powered time should /// have 3. #define MODEM_POWERED_RESOLUTION 3 +/// @brief The bit mask for #_pollModemMetaData to enable modem power time +/// polling +#define MODEM_POWERED_ENABLE_BITMASK 0b10000000 /// @brief Variable name in /// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/variablename/); /// "timeElapsed" @@ -340,6 +363,16 @@ class loggerModem { */ String getModemName(void); + /** + * @brief Get a detailed printable description of the modem. + * + * @note These values are polled for and cached in memory till needed + * + * @return **String** The concatenated name, hardware version, firmware + * version, and serial number fo the modem.. + */ + String getModemDevId(void); + /** * @brief Set up the modem before first use. * @@ -535,6 +568,7 @@ class loggerModem { * called after the modem is connected to the internet. */ /**@{*/ + /** * @brief Query the modem for the current signal quality and write the * results to the supplied non-constant references. @@ -572,13 +606,45 @@ class loggerModem { */ virtual float getModemChipTemperature(void) = 0; + + /** + * @brief Enables metadata polling for one or more modem measured + * variables. Setting this to 0b11111111 will enable polling for all modem + * measured variables. + * + * @note This will **not** disable polling for any unset bits in the + * provided bitmask. It will only enable those bits that are set. + */ + void enableMetadataPolling(uint8_t pollingBitmask); + + /** + * @brief Disables metadata polling for one or more modem measured + * variables. Setting this to 0b11111111 will disable polling for all modem + * measured variables. + * + * @note This will **not** enable polling for any unset bits in the + * provided bitmask. It will only disable polling for those bits that are + * set. + */ + void disableMetadataPolling(uint8_t pollingBitmask); + + /** + * @brief Sets the bitmask for modem metadata polling. + * + * This will enable polling for 1 bits and disable polling for 0 bits. + * Setting this to 0 (0b00000000) will disable polling for all metadata + * parameters. Setting it to 256 (0b11111111) will enable polling for all + * parameters. + */ + void setMetadataPolling(uint8_t pollingBitmask); + /** * @brief Query the modem for signal quality, battery, and temperature * information and store the values to the static internal variables. * - * @return **bool** True indicates that the communication with the modem was - * successful and the values of the internal static variables should be - * valid. + * @return **bool** True indicates that the communication with the modem + * was successful and the values of the internal static variables should + * be valid. */ virtual bool updateModemMetadata(void); /**@}*/ @@ -990,53 +1056,32 @@ class loggerModem { // modemType gsmModem; // modemClientType gsmClient; - /** - * @brief The retreived modem paramters + /** + * @brief The modem hardware version. * + * Set in #modemSetup(). + * Returned as a portion of the #getModemDevId(). */ String _modemHwVersion; - String _modemSerialNumber; - String _modemFwVersion; - - public: - /** - * @brief Get a printable description of the modem. - * - * - * @note These values are polled for and cached in memory till needed - * - * @return *string discritption of modem. - */ - String getModemDevId(void) - {return _modemName+F(" Sn ")+_modemSerialNumber+F(" HwVer " )+_modemHwVersion+F(" FwVer ")+_modemFwVersion;} - /** - * @brief modem management data setup - * - * Set in setup() + * @brief The modem firmware version. * - * @param status type of default polling + * Set in #modemSetup(). + * Returned as a portion of the #getModemDevId(). */ -#if !defined POLL_MODEM_META_DATA_ON -#define POLL_MODEM_META_DATA_ALL 0xFF -#endif // POLL_MODEM_META_DATA_ON - typedef enum { - POLL_MODEM_META_DATA_OFF = 0x0, - POLL_MODEM_META_DATA_RSSI = 0x01, - POLL_MODEM_META_DATA_VCC = 0x02, - POLL_MODEM_META_DATA_TEMP = 0x04, - POLL_MODEM_META_DATA_PARM4 = 0x08, - POLL_MODEM_META_DATA_PARM5 = 0x010, - POLL_MODEM_META_DATA_DEF = POLL_MODEM_META_DATA_ALL, - } PollModemMetaData_t; + String _modemFwVersion; /** - * @brief poll modem meta data + * @brief The modem serial number. * - * Set polling status. - * Default won't poll + * Set in #modemSetup(). + * Returned as a portion of the #getModemDevId(). */ - void pollModemMetadata(PollModemMetaData_t status = POLL_MODEM_META_DATA_DEF); + String _modemSerialNumber; + /** + * @brief An 8-bit code for the enabled modem polling variables + */ + uint8_t _pollModemMetaData = 0; #if not defined SENSOR_DEFAULT_I #define SENSOR_DEFAULT_I -1 @@ -1065,14 +1110,6 @@ class loggerModem { */ inline int8_t getPowerPin() {return _powerPin;} - protected: - /** - * @brief poll the modem management data - * - * Set in the init() portion of the #modemSetup(). - */ - PollModemMetaData_t static _pollModemMetaData; - }; /* atl_extension */ @@ -1115,7 +1152,9 @@ class Modem_RSSI : public Variable { const char* varCode = MODEM_RSSI_DEFAULT_CODE) : Variable(&parentModem->getModemRSSI, (uint8_t)MODEM_RSSI_RESOLUTION, &*MODEM_RSSI_VAR_NAME, &*MODEM_RSSI_UNIT_NAME, varCode, - uuid) {} + uuid) { + parentModem->enableMetadataPolling(MODEM_RSSI_ENABLE_BITMASK); + } /** * @brief Destroy the Modem_RSSI object - no action needed. */ @@ -1148,7 +1187,9 @@ class Modem_SignalPercent : public Variable { : Variable(&parentModem->getModemSignalPercent, (uint8_t)MODEM_PERCENT_SIGNAL_RESOLUTION, &*MODEM_PERCENT_SIGNAL_VAR_NAME, - &*MODEM_PERCENT_SIGNAL_UNIT_NAME, varCode, uuid) {} + &*MODEM_PERCENT_SIGNAL_UNIT_NAME, varCode, uuid) { + parentModem->enableMetadataPolling(MODEM_PERCENT_SIGNAL_ENABLE_BITMASK); + } /** * @brief Destroy the Modem_SignalPercent object - no action needed. */ @@ -1184,7 +1225,9 @@ class Modem_BatteryState : public Variable { : Variable(&parentModem->getModemBatteryChargeState, (uint8_t)MODEM_BATTERY_STATE_RESOLUTION, &*MODEM_BATTERY_STATE_VAR_NAME, - &*MODEM_BATTERY_STATE_UNIT_NAME, varCode, uuid) {} + &*MODEM_BATTERY_STATE_UNIT_NAME, varCode, uuid) { + parentModem->enableMetadataPolling(MODEM_BATTERY_STATE_ENABLE_BITMASK); + } /** * @brief Destroy the Modem_BatteryState object - no action needed. */ @@ -1220,7 +1263,10 @@ class Modem_BatteryPercent : public Variable { : Variable(&parentModem->getModemBatteryChargePercent, (uint8_t)MODEM_BATTERY_PERCENT_RESOLUTION, &*MODEM_BATTERY_PERCENT_VAR_NAME, - &*MODEM_BATTERY_PERCENT_UNIT_NAME, varCode, uuid) {} + &*MODEM_BATTERY_PERCENT_UNIT_NAME, varCode, uuid) { + parentModem->enableMetadataPolling( + MODEM_BATTERY_PERCENT_ENABLE_BITMASK); + } /** * @brief Destroy the Modem_BatteryPercent object - no action needed. */ @@ -1256,7 +1302,10 @@ class Modem_BatteryVoltage : public Variable { : Variable(&parentModem->getModemBatteryVoltage, (uint8_t)MODEM_BATTERY_VOLTAGE_RESOLUTION, &*MODEM_BATTERY_VOLTAGE_VAR_NAME, - &*MODEM_BATTERY_VOLTAGE_UNIT_NAME, varCode, uuid) {} + &*MODEM_BATTERY_VOLTAGE_UNIT_NAME, varCode, uuid) { + parentModem->enableMetadataPolling( + MODEM_BATTERY_VOLTAGE_ENABLE_BITMASK); + } /** * @brief Destroy the Modem_BatteryVoltage object - no action needed. */ @@ -1291,7 +1340,9 @@ class Modem_Temp : public Variable { : Variable(&parentModem->getModemTemperature, (uint8_t)MODEM_TEMPERATURE_RESOLUTION, &*MODEM_TEMPERATURE_VAR_NAME, &*MODEM_TEMPERATURE_UNIT_NAME, - varCode, uuid) {} + varCode, uuid) { + parentModem->enableMetadataPolling(MODEM_TEMPERATURE_ENABLE_BITMASK); + } /** * @brief Destroy the Modem_Temp object - no action needed. */ diff --git a/src/modems/DigiXBeeWifi.cpp b/src/modems/DigiXBeeWifi.cpp index eaed88857..a9542d5be 100644 --- a/src/modems/DigiXBeeWifi.cpp +++ b/src/modems/DigiXBeeWifi.cpp @@ -10,19 +10,13 @@ // Included Dependencies #include "DigiXBeeWifi.h" #include "LoggerModemMacros.h" -//#define USE_NTP 1 -#if defined USE_NTP -#include "NTPClientTinyGsm.h" -// WiFiUDP ntpUDP; -// NTPClient timeClient(ntpUDP); -NTPClient timeClient(); -#endif // USE_NTP // Constructor/Destructor DigiXBeeWifi::DigiXBeeWifi(Stream* modemStream, int8_t powerPin, int8_t statusPin, bool useCTSStatus, int8_t modemResetPin, int8_t modemSleepRqPin, - const char* ssid, const char* pwd) + const char* ssid, const char* pwd, + bool maintainAssociation) : DigiXBee(powerPin, statusPin, useCTSStatus, modemResetPin, modemSleepRqPin), #ifdef MS_DIGIXBEEWIFI_DEBUG_DEEP @@ -33,7 +27,8 @@ DigiXBeeWifi::DigiXBeeWifi(Stream* modemStream, int8_t powerPin, #endif gsmClient(gsmModem), _ssid(ssid), - _pwd(pwd) { + _pwd(pwd), + _maintainAssociation(maintainAssociation) { } DigiXBeeWifi::DigiXBeeWifi(Stream* modemStream, int8_t powerPin, @@ -57,20 +52,52 @@ DigiXBeeWifi::~DigiXBeeWifi() {} MS_IS_MODEM_AWAKE(DigiXBeeWifi); MS_MODEM_WAKE(DigiXBeeWifi); -// MS_MODEM_CONNECT_INTERNET(DigiXBeeWifi); has instability -// See https://github.com/neilh10/ModularSensors/issues/125 -bool DigiXBeeWifi::connectInternet(uint32_t maxConnectionTime) { - MS_START_DEBUG_TIMER - MS_DBG(F("\nDigiXbee Attempting to connect to WiFi network...")); - if (!(gsmModem.isNetworkConnected())) { - if (!gsmModem.waitForNetwork(maxConnectionTime)) { - PRINTOUT(F("... WiFi connection failed")); - return false; - } - } - MS_DBG(F("... WiFi connected after"), MS_PRINT_DEBUG_TIMER, - F("milliseconds!")); - return true; + +// This is different MS_MODEM_CONNECT_INTERNET in that it doesn't attempt to +// resend credentials +bool DigiXBeeWifi::connectInternet(uint32_t maxConnectionTime) { + bool success = true; + + /** Power up, if necessary */ + bool wasPowered = true; + if (_millisPowerOn == 0) { + modemPowerUp(); + wasPowered = false; + } + + /** Check if the modem was awake, wake it if not */ + bool wasAwake = isModemAwake(); + if (!wasAwake) { + MS_DBG(F("Waiting for modem to boot after power on ...")); + while (millis() - _millisPowerOn < _wakeDelayTime_ms) { /** wait */ + } + MS_DBG(F("Waking up the modem to connect to the internet ...")); + success &= modemWake(); + } else { + MS_DBG(F("Modem was already awake and should be ready.")); + } + + if (success) { + MS_START_DEBUG_TIMER + MS_DBG(F("\nAttempting to connect to WiFi without sending new " + "credentials...")); + if (!(gsmModem.isNetworkConnected())) { + if (!gsmModem.waitForNetwork(maxConnectionTime)) { + PRINTOUT(F("... WiFi connection failed")); + success = false; + } + } + MS_DBG(F("... WiFi connected after"), MS_PRINT_DEBUG_TIMER, + F("milliseconds!")); + } + if (!wasPowered) { + MS_DBG(F("Modem was powered to connect to the internet! " + "Remember to turn it off when you're done.")); + } else if (!wasAwake) { + MS_DBG(F("Modem was woken up to connect to the internet! " + "Remember to put it to sleep when you're done.")); + } + return success; } MS_MODEM_IS_INTERNET_AVAILABLE(DigiXBeeWifi); @@ -87,7 +114,8 @@ bool DigiXBeeWifi::extraModemSetup(void) { _modemName = gsmModem.getModemName(); /** Then enter command mode to set pin outputs. */ if (gsmModem.commandMode()) { - String xbeeSnLow,xbeeSnHigh;//XbeeDevHwVer,XbeeFwVer; + String xbeeSnLow; + String xbeeSnHigh; gsmModem.getSeries(); _modemName = gsmModem.getModemName(); gsmModem.sendAT(F("SL")); // Request Module MAC/Serial Number Low @@ -167,12 +195,28 @@ bool DigiXBeeWifi::extraModemSetup(void) { if (!success) { MS_DBG(F("Fail IP "), success); } /** Put the XBee in pin sleep mode in conjuction with D8=1 */ + // From the S6B User Guide: + // 0 - Normal. In this mode the device never sleeps. + // 1 - Pin Sleep. In this mode the device honors the SLEEP_RQ pin. + // Set D8 (DIO8 Configuration) to the sleep request function: 1. + // 4 - Cyclic Sleep. In this mode the device repeatedly sleeps for the + // value specified by SP and spends ST time awake. + // 5 - Cyclic Sleep with Pin Wake. In this mode the device acts as in + // Cyclic Sleep but does not sleep if the SLEEP_RQ pin is inactive, + // allowing the device to be kept awake or woken by the connected + // system. MS_DBG(F("Setting Sleep Options...")); gsmModem.sendAT(GF("SM"), XBEE_SLEEP_SETTING); success &= gsmModem.waitResponse(TGWRIDW+0x09) == 1; - // Disassociate from network for lowest power deep sleep - // 40 - Aay associated with AP during sleep - draws more current - // (+10mA?) 100 -Cyclic sleep ST specifies time before reutnring to + // Disassociate from the network for the lowest power deep sleep. + // From S6B User Guide: + // 0x40 - Stay associated with AP during sleep. Draw more current + // (+10mA?) during sleep with this option enabled, but also avoid data + // loss. [0x40 = 64] + // 0x100 - For cyclic sleep, ST specifies the time before returning + // to sleep. With this bit set, new receptions from either the serial or + // the RF port do not restart the ST timer. Current implementation does + // not support this bit being turned off. [0x100 = 256] // sleep 200 - SRGD magic number gsmModem.sendAT(GF("SO"), XBEE_SLEEP_ASSOCIATE); success &= gsmModem.waitResponse(TGWRIDW+0x0a) == 1; @@ -194,7 +238,7 @@ bool DigiXBeeWifi::extraModemSetup(void) { if (success) { - MS_DBG(F("Setup Wifi Network "), _ssid); + MS_DBG(F("Successfully setup Wifi Network"), _ssid); } else { MS_DBG(F("Failed Setting WiFi"), _ssid); } @@ -319,14 +363,13 @@ bool DigiXBeeWifi::extraModemSetup(void) { void DigiXBeeWifi::disconnectInternet(void) { - // Ensure Wifi XBee IP socket torn down by forcing connection to localhost IP - // For A XBee S6B bug, then force restart - // Note: TinyGsmClientXbee.h:modemStop() had a hack for closing socket with Timeout=0 "TM0" for S6B disabled + // Ensure Wifi XBee IP socket torn down by forcing connection to + // localhost IP For A XBee S6B bug, then force restart. String oldRemoteIp = gsmClient.remoteIP(); IPAddress newHostIp = IPAddress(127, 0, 0, 1); // localhost gsmClient.connect(newHostIp, 80); - MS_DBG(gsmModem.getBeeName(), oldRemoteIp, F(" disconnectInternet set to "), + MS_DBG(gsmModem.getBeeName(), oldRemoteIp, F("disconnectInternet set to"), gsmClient.remoteIP()); gsmModem.restart(); @@ -347,8 +390,7 @@ uint32_t DigiXBeeWifi::getNISTTime(void) { #if !defined NIST_SERVER_RETRYS #define NIST_SERVER_RETRYS 4 #endif // NIST_SERVER_RETRYS - String nistIpStr; - __attribute__((unused)) uint8_t index = 0; + for (uint8_t i = 0; i < NIST_SERVER_RETRYS; i++) { // Must ensure that we do not ping the daylight servers more than once // every 4 seconds. NIST clearly specifies here that this is a @@ -367,7 +409,7 @@ uint32_t DigiXBeeWifi::getNISTTime(void) { MS_DBG(F("\nConnecting to NIST daytime Server")); bool connectionMade = false; - // This is the IP address of time-e-wwv.nist.gov + // These are is the IP address of time-[a,b,c,d]-wwv.nist.gov // XBee's address lookup falters on time.nist.gov #define TIME_PROTOCOL_PORT 37 @@ -378,27 +420,12 @@ uint32_t DigiXBeeWifi::getNISTTime(void) { {"132, 163, 97, 3"}, {"132, 163, 97, 4"}}; IPAddress ip1(132, 163, 97, 1); // Initialize -#if 0 - gsmModem.sendAT(F("time-e-wwv.nist.gov")); - index = gsmModem.waitResponse(TGWRIDW+0x00,4000, nistIpStr); - nistIpStr.trim(); - uint16_t nistIp_len = nistIpStr.length(); - if ((nistIp_len < 7) || (nistIp_len > 20)) - { - ip1.fromString(ipAddr[i]); - MS_DBG(F("Bad lookup"), nistIpStr, "'=", nistIp_len, F(" Using "), - ipAddr[i]); - } else { - ip1.fromString(nistIpStr); - PRINTOUT(F("Good lookup mdmIP["), i, "/", NIST_SERVER_RETRYS, - F("] '"), nistIpStr, "'=", nistIp_len); - } -#else ip1.fromString(ipAddr[i]); PRINTOUT(F("NIST lookup mdmIP["), i, "/", NIST_SERVER_RETRYS, - F("] with "), ip1); -// F("] with "), ipAddr[i]); -#endif + F("] with "), ip1); + + // NOTE: This "connect" only sets up the connection parameters, the TCP + // socket isn't actually opened until we first send data (the '!' below) connectionMade = gsmClient.connect(ip1, TIME_PROTOCOL_PORT); // Need to send something before connection is made gsmClient.println('!'); @@ -433,9 +460,9 @@ bool DigiXBeeWifi::getModemSignalQuality(int16_t& rssi, int16_t& percent) { bool success = true; // Initialize float variable - int16_t signalQual = -9999; - percent = -9999; - rssi = -9999; + int16_t signalQual = SENSOR_DEFAULT_I; + percent = SENSOR_DEFAULT_I; + rssi = SENSOR_DEFAULT_I; // Assume measurement from previous connection @@ -478,27 +505,35 @@ bool DigiXBeeWifi::updateModemMetadata(void) { #define XBEE_V_KEY 9999 uint16_t volt_mV = XBEE_V_KEY; + MS_DBG(F("Modem polling settings:"), String(_pollModemMetaData, BIN)); + // if not enabled don't collect data - if (0 == loggerModem::_pollModemMetaData) { - MS_DBG(F("updateModemMetadata None to update")); + if (_pollModemMetaData == 0) { + MS_DBG(F("No modem metadata to update")); return false; } - // Enter command mode only once for temp and battery - MS_DBG(F("updateModemMetadata Entering Command Mode:")); + + // Enter command mode only once + MS_DBG(F("Entering Command Mode to update modem metadata:")); success &= gsmModem.commandMode(); - if (POLL_MODEM_META_DATA_RSSI & loggerModem::_pollModemMetaData) { + + if ((_pollModemMetaData & MODEM_RSSI_ENABLE_BITMASK) == + MODEM_RSSI_ENABLE_BITMASK || + (_pollModemMetaData & MODEM_PERCENT_SIGNAL_ENABLE_BITMASK) == + MODEM_PERCENT_SIGNAL_ENABLE_BITMASK) { // Assume a signal has already been established. // Try to get a valid signal quality // NOTE: We can't actually distinguish between a bad modem response, no // modem response, and a real response from the modem of no // service/signal. The TinyGSM getSignalQuality function returns the - // same "no signal" value (99 CSQ or 0 RSSI) in all 3 cases. Try up to 5 - // times to get a signal quality - that is, ping NIST 5 times and see if - // the value updates + // same "no signal" value (99 CSQ or 0 RSSI) in all 3 cases. + + // Try up to 5 times to get a signal quality int8_t num_trys_remaining = 5; do { rssi = gsmModem.getSignalQuality(); - MS_DBG(F("Raw signal quality("), num_trys_remaining, F("):"), rssi); + MS_DBG(F("Raw signal quality ("), num_trys_remaining, F("):"), + rssi); if (rssi != 0 && rssi != SENSOR_DEFAULT_I) break; num_trys_remaining--; } while ((rssi == 0 || rssi == SENSOR_DEFAULT_I) && num_trys_remaining); @@ -510,9 +545,14 @@ bool DigiXBeeWifi::updateModemMetadata(void) { loggerModem::_priorRSSI = rssi; MS_DBG(F("CURRENT RSSI:"), rssi); + } else { + MS_DBG(F("Polling for both RSSI and signal strength is disabled")); } - if (POLL_MODEM_META_DATA_VCC & loggerModem::_pollModemMetaData) { - // MS_DBG(F("Getting input voltage:")); + + + if ((_pollModemMetaData & MODEM_BATTERY_VOLTAGE_ENABLE_BITMASK) == + MODEM_BATTERY_VOLTAGE_ENABLE_BITMASK) { + MS_DBG(F("Getting input voltage:")); volt_mV = gsmModem.getBattVoltage(); MS_DBG(F("CURRENT Modem battery (mV):"), volt_mV); if (volt_mV != XBEE_V_KEY) { @@ -522,15 +562,22 @@ bool DigiXBeeWifi::updateModemMetadata(void) { loggerModem::_priorBatteryVoltage = static_cast(SENSOR_DEFAULT_I); } + } else { + MS_DBG(F("Polling for modem battery voltage is disabled")); } - if (POLL_MODEM_META_DATA_TEMP & loggerModem::_pollModemMetaData) { - // MS_DBG(F("Getting chip temperature:")); + + if ((_pollModemMetaData & MODEM_TEMPERATURE_ENABLE_BITMASK) == + MODEM_TEMPERATURE_ENABLE_BITMASK) { + MS_DBG(F("Getting chip temperature:")); loggerModem::_priorModemTemp = getModemChipTemperature(); MS_DBG(F("CURRENT Modem temperature(C):"), loggerModem::_priorModemTemp); + } else { + MS_DBG(F("Polling for modem chip temperature is disabled")); } - // Exit command modem - MS_DBG(F("updateModemMetadata Leaving Command Mode:")); + + // Exit command mode + MS_DBG(F("Leaving Command Mode after updating modem metadata:")); gsmModem.exitCommand(); ++updateModemMetadata_cnt; diff --git a/src/modems/DigiXBeeWifi.h b/src/modems/DigiXBeeWifi.h index 6daaf2b46..4f414f509 100644 --- a/src/modems/DigiXBeeWifi.h +++ b/src/modems/DigiXBeeWifi.h @@ -50,6 +50,10 @@ #define MS_DEBUGGING_STD "DigiXBeeWifi" #endif +#ifdef MS_DIGIXBEEWIFI_DEBUG_DEEP +#define MS_DEBUGGING_DEEP "DigiXBeeWifi" +#endif + /** @ingroup modem_digi_wifi */ /**@{*/ @@ -105,13 +109,18 @@ class DigiXBeeWifi : public DigiXBee { * reference. * @param ssid The wifi network ID. * @param pwd The wifi network password, assuming WPA2. + * @param maintainAssociation Whether to maintain association with the + * access point during sleep. Maitaining the association during sleep draws + * more current (+10mA?), but also allows a faster reconnection on the next + * wake. */ DigiXBeeWifi(Stream* modemStream, int8_t powerPin, int8_t statusPin, bool useCTSStatus, int8_t modemResetPin, - int8_t modemSleepRqPin, const char* ssid, const char* pwd); - DigiXBeeWifi(Stream* modemStream, int8_t powerPin, - int8_t statusPin, bool useCTSStatus, - int8_t modemResetPin, int8_t modemSleepRqPin); + int8_t modemSleepRqPin, const char* ssid, const char* pwd, + bool maintainAssociation = false); + DigiXBeeWifi(Stream* modemStream, int8_t powerPin, int8_t statusPin, + bool useCTSStatus, int8_t modemResetPin, + int8_t modemSleepRqPin); /** * @brief Destroy the Digi XBee Wifi object - no action taken */ @@ -136,7 +145,7 @@ class DigiXBeeWifi : public DigiXBee { void setWiFiPwd(const char* WiFiPwd, bool copyId = false); String getWiFiId(void); String getWiFiPwd(void); - + #ifdef MS_DIGIXBEEWIFI_DEBUG_DEEP StreamDebugger _modemATDebugger; #endif @@ -167,15 +176,15 @@ class DigiXBeeWifi : public DigiXBee { private: const char* _ssid; const char* _pwd; + bool _maintainAssociation; // Access Management char* _ssid_buf = NULL; char* _pwd_buf = NULL; uint16_t updateModemMetadata_cnt = 0; - //This causes the Xbee to reset afte this number of transmission attempts + // This causes the Xbee to reset after this number of transmission attempts #define XBEE_RESET_THRESHOLD 4 - }; /**@}*/ #endif // SRC_MODEMS_DIGIXBEEWIFI_H_