From fd02919205a4a91d6643fd3efa41381ea7c2a868 Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Thu, 16 Mar 2023 14:38:20 -0500 Subject: [PATCH 01/11] run clang-format on *.cpp and *.h --- src/VariableBase.cpp | 3 ++- src/sensors/YosemitechY700.h | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/VariableBase.cpp b/src/VariableBase.cpp index f330bf234..a557c267f 100644 --- a/src/VariableBase.cpp +++ b/src/VariableBase.cpp @@ -228,7 +228,8 @@ bool Variable::checkUUIDFormat(void) { int first_invalid = strspn(_uuid, acceptableChars); if (first_invalid != 36) { MS_DBG(F("UUID for"), getVarCode(), '(', _uuid, ')', - F("has a bad character"), _uuid[first_invalid], F("at"), first_invalid); + F("has a bad character"), _uuid[first_invalid], F("at"), + first_invalid); return false; } return true; diff --git a/src/sensors/YosemitechY700.h b/src/sensors/YosemitechY700.h index 6a146bac6..7db473937 100644 --- a/src/sensors/YosemitechY700.h +++ b/src/sensors/YosemitechY700.h @@ -70,11 +70,11 @@ /// 1000 ms. #define Y700_WARM_UP_TIME_MS 1000 /// @brief Sensor::_stabilizationTime_ms; time between "StartMeasurement" -/// command and stable reading - Y700 takes 4 s to get stability <1 mm, +/// command and stable reading - Y700 takes 4 s to get stability <1 mm, /// but 12 s for <0.1 mm. If highest precision is required, increase to 12000. #define Y700_STABILIZATION_TIME_MS 4000 /// @brief Sensor::_measurementTime_ms; the Y700 takes <1 s for new values. -/// but >1 s for values that don't seem autocorrelated. +/// but >1 s for values that don't seem autocorrelated. #define Y700_MEASUREMENT_TIME_MS 1000 /**@}*/ @@ -211,9 +211,9 @@ class YosemitechY700_Pressure : public Variable { * @param varCode A short code to help identify the variable in files; * optional with a default value of "Y700Pres". */ - explicit YosemitechY700_Pressure(YosemitechY700* parentSense, - const char* uuid = "", - const char* varCode = Y700_PRES_DEFAULT_CODE) + explicit YosemitechY700_Pressure( + YosemitechY700* parentSense, const char* uuid = "", + const char* varCode = Y700_PRES_DEFAULT_CODE) : Variable(parentSense, (const uint8_t)Y700_PRES_VAR_NUM, (uint8_t)Y700_PRES_RESOLUTION, Y700_PRES_VAR_NAME, Y700_PRES_UNIT_NAME, varCode, uuid) {} From 55973fa77162409c65afe792b84404d33e9dd9f5 Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Thu, 16 Mar 2023 14:24:40 -0500 Subject: [PATCH 02/11] publishers: fix undefined behavior in response code processing Correctly initialize response code variable terminator. --- src/publishers/DreamHostPublisher.cpp | 1 + src/publishers/EnviroDIYPublisher.cpp | 1 + src/publishers/UbidotsPublisher.cpp | 1 + 3 files changed, 3 insertions(+) diff --git a/src/publishers/DreamHostPublisher.cpp b/src/publishers/DreamHostPublisher.cpp index fbfa07e7d..f3ae302f7 100644 --- a/src/publishers/DreamHostPublisher.cpp +++ b/src/publishers/DreamHostPublisher.cpp @@ -189,6 +189,7 @@ int16_t DreamHostPublisher::publishData(Client* outClient) { int16_t responseCode = 0; if (did_respond > 0) { char responseCode_char[4]; + responseCode_char[3] = 0; for (uint8_t i = 0; i < 3; i++) { responseCode_char[i] = tempBuffer[i + 9]; } diff --git a/src/publishers/EnviroDIYPublisher.cpp b/src/publishers/EnviroDIYPublisher.cpp index 5d017ea99..28ead3f78 100644 --- a/src/publishers/EnviroDIYPublisher.cpp +++ b/src/publishers/EnviroDIYPublisher.cpp @@ -260,6 +260,7 @@ int16_t EnviroDIYPublisher::publishData(Client* outClient) { int16_t responseCode = 0; if (did_respond > 0) { char responseCode_char[4]; + responseCode_char[3] = 0; for (uint8_t i = 0; i < 3; i++) { responseCode_char[i] = tempBuffer[i + 9]; } diff --git a/src/publishers/UbidotsPublisher.cpp b/src/publishers/UbidotsPublisher.cpp index c840cdfcf..afd20a1e7 100644 --- a/src/publishers/UbidotsPublisher.cpp +++ b/src/publishers/UbidotsPublisher.cpp @@ -279,6 +279,7 @@ int16_t UbidotsPublisher::publishData(Client* outClient) { int16_t responseCode = 0; if (did_respond > 0) { char responseCode_char[4]; + responseCode_char[3] = 0; for (uint8_t i = 0; i < 3; i++) { responseCode_char[i] = tempBuffer[i + 9]; } From 507b3174929834e182b3dae43ed173351b789138 Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Thu, 16 Mar 2023 14:24:40 -0500 Subject: [PATCH 03/11] dataPublisherBase: remove redundant zero init of TX buffer Saves 750 bytes of flash as the buffer can be placed in .bss to be zero-initialized instead of .data. --- src/dataPublisherBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dataPublisherBase.cpp b/src/dataPublisherBase.cpp index 76e298b6c..e21c08285 100644 --- a/src/dataPublisherBase.cpp +++ b/src/dataPublisherBase.cpp @@ -10,7 +10,7 @@ */ #include "dataPublisherBase.h" -char dataPublisher::txBuffer[MS_SEND_BUFFER_SIZE] = {'\0'}; +char dataPublisher::txBuffer[MS_SEND_BUFFER_SIZE]; // Basic chunks of HTTP const char* dataPublisher::getHeader = "GET "; From 83b27ead472932b3ed8af229998c7eeca616ab76 Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Thu, 16 Mar 2023 14:24:40 -0500 Subject: [PATCH 04/11] LoggerBase: optimize setFileTimestamp Saves ~110 bytes of flash and substantial stack --- src/LoggerBase.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/LoggerBase.cpp b/src/LoggerBase.cpp index c125f0180..6386c0380 100644 --- a/src/LoggerBase.cpp +++ b/src/LoggerBase.cpp @@ -1053,12 +1053,10 @@ bool Logger::initializeSDCard(void) { // Protected helper function - This sets a timestamp on a file void Logger::setFileTimestamp(File fileToStamp, uint8_t stampFlag) { - fileToStamp.timestamp(stampFlag, dtFromEpoch(getNowLocalEpoch()).year(), - dtFromEpoch(getNowLocalEpoch()).month(), - dtFromEpoch(getNowLocalEpoch()).date(), - dtFromEpoch(getNowLocalEpoch()).hour(), - dtFromEpoch(getNowLocalEpoch()).minute(), - dtFromEpoch(getNowLocalEpoch()).second()); + DateTime dt = dtFromEpoch(getNowLocalEpoch()); + + fileToStamp.timestamp(stampFlag, dt.year(), dt.month(), dt.date(), + dt.hour(), dt.minute(), dt.second()); } From f0d26374ec0f15f385b8ce4c1cfc8a8a4e57a35d Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Thu, 16 Mar 2023 14:24:40 -0500 Subject: [PATCH 05/11] LoggerModem: optimize CSQ conversion functions Saves ~200 bytes of RAM and ~360 bytes of flash. The equations reproduce the tables previously found in the source code exactly. The reason for the values in the original tables is unknown. --- src/LoggerModem.cpp | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/src/LoggerModem.cpp b/src/LoggerModem.cpp index b44fa8159..15ca08ba4 100644 --- a/src/LoggerModem.cpp +++ b/src/LoggerModem.cpp @@ -394,31 +394,16 @@ float loggerModem::getModemTemperature() { // Helper to get approximate RSSI from CSQ (assuming no noise) int16_t loggerModem::getRSSIFromCSQ(int16_t csq) { - int16_t CSQs[33] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 99}; - int16_t RSSIs[33] = {-113, -111, -109, -107, -105, -103, -101, -99, -97, - -95, -93, -91, -89, -87, -85, -83, -81, -79, - -77, -75, -73, -71, -69, -67, -65, -63, -61, - -59, -57, -55, -53, -51, 0}; - for (uint8_t i = 0; i < 33; i++) { - if (CSQs[i] == csq) return RSSIs[i]; - } - return 0; + if ((csq < 0) || (csq > 31)) return 0; + // equation matches previous table. not sure the original motivation. + return ((csq * 2) - 113); } // Helper to get signal percent from CSQ int16_t loggerModem::getPctFromCSQ(int16_t csq) { - int16_t CSQs[33] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 99}; - int16_t PCTs[33] = {0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, - 36, 39, 42, 45, 48, 52, 55, 58, 61, 65, 68, - 71, 74, 78, 81, 84, 87, 90, 94, 97, 100, 0}; - for (uint8_t i = 0; i < 33; i++) { - if (CSQs[i] == csq) return PCTs[i]; - } - return 0; + if ((csq < 0) || (csq > 31)) return 0; + // equation matches previous table. not sure the original motivation. + return (csq * 827 + 127) >> 8; } // Helper to get signal percent from RSSI From 2692821e7faf30e6c904f44b174419bce6ceee9f Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Thu, 16 Mar 2023 14:24:40 -0500 Subject: [PATCH 06/11] LoggerBase: always power down modem after RTC sync The test for "15 seconds before the next logging interval" has been wrong for years, possibly since this code was written, with no apparent consequence. The behavior is additionally confusing to users deploying the devices and causes problems with logging as the modem won't get turned off for a long time. Remove it completely to solve the problems. --- src/LoggerBase.cpp | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/src/LoggerBase.cpp b/src/LoggerBase.cpp index 6386c0380..0070e379b 100644 --- a/src/LoggerBase.cpp +++ b/src/LoggerBase.cpp @@ -305,25 +305,11 @@ bool Logger::syncRTC() { PRINTOUT(F("Could not wake modem for clock sync.")); } watchDogTimer.resetWatchDog(); - // Power down the modem - but only if there will be more than 15 seconds - // before the NEXT logging interval - it can take the modem that long to - // shut down - - uint32_t setupFinishTime = getNowLocalEpoch(); - if (setupFinishTime % (_loggingIntervalMinutes * 60) > 15) { - MS_DBG(F("At"), formatDateTime_ISO8601(setupFinishTime), F("with"), - setupFinishTime % (_loggingIntervalMinutes * 60), - F("seconds until next logging interval, putting modem to " - "sleep")); - _logModem->disconnectInternet(); - _logModem->modemSleepPowerDown(); - } else { - MS_DBG(F("At"), formatDateTime_ISO8601(setupFinishTime), - F("there are only"), - setupFinishTime % (_loggingIntervalMinutes * 60), - F("seconds until next logging interval; leaving modem on " - "and connected to the internet.")); - } + + // Power down the modem now that we are done with it + MS_DBG(F("Powering down modem after clock sync.")); + _logModem->disconnectInternet(); + _logModem->modemSleepPowerDown(); } watchDogTimer.resetWatchDog(); return success; From 389c16293a10237741db17d5aeeca77272fa89a3 Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Thu, 16 Mar 2023 14:24:40 -0500 Subject: [PATCH 07/11] publishers: remove unused functions --- src/publishers/DreamHostPublisher.cpp | 35 ----------------------- src/publishers/DreamHostPublisher.h | 21 -------------- src/publishers/EnviroDIYPublisher.cpp | 40 --------------------------- src/publishers/EnviroDIYPublisher.h | 34 +++-------------------- src/publishers/UbidotsPublisher.cpp | 40 --------------------------- src/publishers/UbidotsPublisher.h | 34 +++-------------------- 6 files changed, 8 insertions(+), 196 deletions(-) diff --git a/src/publishers/DreamHostPublisher.cpp b/src/publishers/DreamHostPublisher.cpp index f3ae302f7..b65c6caed 100644 --- a/src/publishers/DreamHostPublisher.cpp +++ b/src/publishers/DreamHostPublisher.cpp @@ -52,41 +52,6 @@ void DreamHostPublisher::setDreamHostPortalRX(const char* dhUrl) { } -// This prints the URL out to an Arduino stream -void DreamHostPublisher::printSensorDataDreamHost(Stream* stream) { - stream->print(_DreamHostPortalRX); - stream->print(loggerTag); - stream->print(_baseLogger->getLoggerID()); - stream->print(timestampTagDH); - stream->print(String(Logger::markedLocalEpochTime - - 946684800)); // Correct time from epoch to y2k - - for (uint8_t i = 0; i < _baseLogger->getArrayVarCount(); i++) { - stream->print('&'); - stream->print(_baseLogger->getVarCodeAtI(i)); - stream->print('='); - stream->print(_baseLogger->getValueStringAtI(i)); - } -} - - -// This prints a fully structured GET request for DreamHost to the -// specified stream -void DreamHostPublisher::printDreamHostRequest(Stream* stream) { - // Start the request - stream->print(getHeader); - - // Stream the full URL with parameters - printSensorDataDreamHost(stream); - - // Send the rest of the HTTP header - stream->print(HTTPtag); - stream->print(hostHeader); - stream->print(dreamhostHost); - stream->print(F("\r\n\r\n")); -} - - // A way to begin with everything already set void DreamHostPublisher::begin(Logger& baseLogger, Client* inClient, const char* dhUrl) { diff --git a/src/publishers/DreamHostPublisher.h b/src/publishers/DreamHostPublisher.h index 6a7fe1a46..584be2142 100644 --- a/src/publishers/DreamHostPublisher.h +++ b/src/publishers/DreamHostPublisher.h @@ -133,26 +133,6 @@ class DreamHostPublisher : public dataPublisher { */ void setDreamHostPortalRX(const char* dhUrl); - /** - * @brief This creates all of the URL parameter tags and values and writes - * the result to an Arduino stream. - * - * HTML headers are not included. - * - * @param stream The Arduino stream to write out the URL and parameters to. - */ - void printSensorDataDreamHost(Stream* stream); - - /** - * @brief This prints a fully structured GET request for DreamHost to the - * specified stream. - * - * This includes the HTML headers. - * - * @param stream The Arduino stream to write out the URL and parameters to. - */ - void printDreamHostRequest(Stream* stream); - // A way to begin with everything already set /** * @copydoc dataPublisher::begin(Logger& baseLogger, Client* inClient) @@ -165,7 +145,6 @@ class DreamHostPublisher : public dataPublisher { */ void begin(Logger& baseLogger, const char* dhUrl); - // int16_t postDataDreamHost(void); /** * @brief Utilizes an attached modem to make a TCP connection to the * DreamHost URL and then stream out a get request over that connection. diff --git a/src/publishers/EnviroDIYPublisher.cpp b/src/publishers/EnviroDIYPublisher.cpp index 28ead3f78..b27516106 100644 --- a/src/publishers/EnviroDIYPublisher.cpp +++ b/src/publishers/EnviroDIYPublisher.cpp @@ -83,45 +83,6 @@ uint16_t EnviroDIYPublisher::calculateJsonSize() { return jsonLength; } -// This prints a properly formatted JSON for EnviroDIY to an Arduino stream -void EnviroDIYPublisher::printSensorDataJSON(Stream* stream) { - stream->print(samplingFeatureTag); - stream->print(_baseLogger->getSamplingFeatureUUID()); - stream->print(timestampTag); - stream->print(Logger::formatDateTime_ISO8601(Logger::markedLocalEpochTime)); - stream->print(F("\",")); - - for (uint8_t i = 0; i < _baseLogger->getArrayVarCount(); i++) { - stream->print('"'); - stream->print(_baseLogger->getVarUUIDAtI(i)); - stream->print(F("\":")); - stream->print(_baseLogger->getValueStringAtI(i)); - if (i + 1 != _baseLogger->getArrayVarCount()) { stream->print(','); } - } - - stream->print('}'); -} - - -// This prints a fully structured post request for EnviroDIY to the -// specified stream. -void EnviroDIYPublisher::printEnviroDIYRequest(Stream* stream) { - // Stream the HTTP headers for the post request - stream->print(postHeader); - stream->print(postEndpoint); - stream->print(HTTPtag); - stream->print(hostHeader); - stream->print(enviroDIYHost); - stream->print(tokenHeader); - stream->print(_registrationToken); - stream->print(contentLengthHeader); - stream->print(calculateJsonSize()); - stream->print(contentTypeHeader); - - // Stream the JSON itself - printSensorDataJSON(stream); -} - // A way to begin with everything already set void EnviroDIYPublisher::begin(Logger& baseLogger, Client* inClient, @@ -144,7 +105,6 @@ void EnviroDIYPublisher::begin(Logger& baseLogger, // EnviroDIY/ODM2DataSharingPortal and then streams out a post request // over that connection. // The return is the http status code of the response. -// int16_t EnviroDIYPublisher::postDataEnviroDIY(void) int16_t EnviroDIYPublisher::publishData(Client* outClient) { // Create a buffer for the portions of the request and response char tempBuffer[37] = ""; diff --git a/src/publishers/EnviroDIYPublisher.h b/src/publishers/EnviroDIYPublisher.h index 8a728dd1d..145860908 100644 --- a/src/publishers/EnviroDIYPublisher.h +++ b/src/publishers/EnviroDIYPublisher.h @@ -149,30 +149,7 @@ class EnviroDIYPublisher : public dataPublisher { * @return uint16_t The number of characters in the JSON object. */ uint16_t calculateJsonSize(); - // /** - // * @brief Calculates how long the full post request will be, including - // * headers - // * - // * @return uint16_t The length of the full request including HTTP - // headers. - // */ - // uint16_t calculatePostSize(); - /** - * @brief This generates a properly formatted JSON for EnviroDIY and prints - * it to the input Arduino stream object. - * - * @param stream The Arduino stream to write out the JSON to. - */ - void printSensorDataJSON(Stream* stream); - - /** - * @brief This prints a fully structured post request for Monitor My - * Watershed/EnviroDIY to the specified stream. - * - * @param stream The Arduino stream to write out the request to. - */ - void printEnviroDIYRequest(Stream* stream); // A way to begin with everything already set /** @@ -194,7 +171,6 @@ class EnviroDIYPublisher : public dataPublisher { void begin(Logger& baseLogger, const char* registrationToken, const char* samplingFeatureUUID); - // int16_t postDataEnviroDIY(void); /** * @brief Utilize an attached modem to open a a TCP connection to the * EnviroDIY/ODM2DataSharingPortal and then stream out a post request over @@ -217,12 +193,10 @@ class EnviroDIYPublisher : public dataPublisher { * * @{ */ - static const char* postEndpoint; ///< The endpoint - static const char* enviroDIYHost; ///< The host name - static const int enviroDIYPort; ///< The host port - static const char* tokenHeader; ///< The token header text - // static const char *cacheHeader; ///< The cache header text - // static const char *connectionHeader; ///< The keep alive header text + static const char* postEndpoint; ///< The endpoint + static const char* enviroDIYHost; ///< The host name + static const int enviroDIYPort; ///< The host port + static const char* tokenHeader; ///< The token header text static const char* contentLengthHeader; ///< The content length header text static const char* contentTypeHeader; ///< The content type header text /**@}*/ diff --git a/src/publishers/UbidotsPublisher.cpp b/src/publishers/UbidotsPublisher.cpp index afd20a1e7..55f4f5227 100644 --- a/src/publishers/UbidotsPublisher.cpp +++ b/src/publishers/UbidotsPublisher.cpp @@ -93,46 +93,6 @@ uint16_t UbidotsPublisher::calculateJsonSize() { } -// This prints a properly formatted JSON for EnviroDIY to an Arduino stream -void UbidotsPublisher::printSensorDataJSON(Stream* stream) { - stream->print(payload); - - for (uint8_t i = 0; i < _baseLogger->getArrayVarCount(); i++) { - stream->print('"'); - stream->print(_baseLogger->getVarUUIDAtI(i)); - stream->print(F("\":{'value':")); - stream->print(_baseLogger->getValueStringAtI(i)); - stream->print(",'timestamp':"); - stream->print(Logger::markedUTCEpochTime); - stream->print( - F("000}")); // Convert microseconds to milliseconds for ubidots - if (i + 1 != _baseLogger->getArrayVarCount()) { stream->print(','); } - } - - stream->print(F("}}")); -} - - -// This prints a fully structured post request for Ubidots to the -// specified stream. -void UbidotsPublisher::printUbidotsRequest(Stream* stream) { - // Stream the HTTP headers for the post request - stream->print(postHeader); - stream->print(postEndpoint); - stream->print(HTTPtag); - stream->print(hostHeader); - stream->print(ubidotsHost); - stream->print(tokenHeader); - stream->print(_authentificationToken); - stream->print(contentLengthHeader); - stream->print(calculateJsonSize()); - stream->print(contentTypeHeader); - - // Stream the JSON itself - printSensorDataJSON(stream); -} - - // A way to begin with everything already set void UbidotsPublisher::begin(Logger& baseLogger, Client* inClient, const char* authentificationToken, diff --git a/src/publishers/UbidotsPublisher.h b/src/publishers/UbidotsPublisher.h index adb47f9e2..1562890c6 100644 --- a/src/publishers/UbidotsPublisher.h +++ b/src/publishers/UbidotsPublisher.h @@ -153,30 +153,6 @@ class UbidotsPublisher : public dataPublisher { * @return uint16_t The number of characters in the JSON object. */ uint16_t calculateJsonSize(); - // /** - // * @brief Calculates how long the full post request will be, including - // * headers - // * - // * @return uint16_t The length of the full request including HTTP - // headers. - // */ - // uint16_t calculatePostSize(); - - /** - * @brief This generates a properly formatted JSON for Ubidots and prints - * it to the input Arduino stream object. - * - * @param stream The Arduino stream to write out the JSON to. - */ - void printSensorDataJSON(Stream* stream); - - /** - * @brief This prints a fully structured post request for the Ubidots API - * to the specified stream. - * - * @param stream The Arduino stream to write out the request to. - */ - void printUbidotsRequest(Stream* stream); // A way to begin with everything already set /** @@ -225,12 +201,10 @@ class UbidotsPublisher : public dataPublisher { * * @{ */ - static const char* postEndpoint; ///< The endpoint - static const char* ubidotsHost; ///< The host name - static const int ubidotsPort; ///< The host port - static const char* tokenHeader; ///< The token header text - // static const char *cacheHeader; ///< The cache header text - // static const char *connectionHeader; ///< The keep alive header text + static const char* postEndpoint; ///< The endpoint + static const char* ubidotsHost; ///< The host name + static const int ubidotsPort; ///< The host port + static const char* tokenHeader; ///< The token header text static const char* contentLengthHeader; ///< The content length header text static const char* contentTypeHeader; ///< The content type header text /**@}*/ From 493215d0693daec6e634daf8643b28d2dbe8ffa9 Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Thu, 16 Mar 2023 14:24:40 -0500 Subject: [PATCH 08/11] publishers: refactor transmit buffer usage Use cleaner interface and common functions that avoid repeated snprintf and strlen usage to save ~2.5KB of flash and dozens of lines of code. Removes extra \r\n from HTTP requests as a side effect, which were against spec and caused spurious 400 Bad Request status messages from servers. --- src/dataPublisherBase.cpp | 52 +++++++++----- src/dataPublisherBase.h | 54 +++++++++----- src/publishers/DreamHostPublisher.cpp | 64 ++++++----------- src/publishers/EnviroDIYPublisher.cpp | 94 ++++++++---------------- src/publishers/ThingSpeakPublisher.cpp | 26 +++---- src/publishers/UbidotsPublisher.cpp | 99 +++++++------------------- 6 files changed, 159 insertions(+), 230 deletions(-) diff --git a/src/dataPublisherBase.cpp b/src/dataPublisherBase.cpp index e21c08285..6075d9bae 100644 --- a/src/dataPublisherBase.cpp +++ b/src/dataPublisherBase.cpp @@ -10,7 +10,9 @@ */ #include "dataPublisherBase.h" -char dataPublisher::txBuffer[MS_SEND_BUFFER_SIZE]; +char dataPublisher::txBuffer[MS_SEND_BUFFER_SIZE]; +Client* dataPublisher::txBufferOutClient = nullptr; +size_t dataPublisher::txBufferLen; // Basic chunks of HTTP const char* dataPublisher::getHeader = "GET "; @@ -71,34 +73,46 @@ void dataPublisher::begin(Logger& baseLogger) { } -// Empties the outgoing buffer -void dataPublisher::emptyTxBuffer(void) { - MS_DBG(F("Dumping the TX Buffer")); - for (int i = 0; i < MS_SEND_BUFFER_SIZE; i++) { txBuffer[i] = '\0'; } +void dataPublisher::txBufferInit(Client* outClient) { + // remember client we are sending to + txBufferOutClient = outClient; + + // reset buffer length to be empty + txBufferLen = 0; } +void dataPublisher::txBufferAppend(const char* data, size_t length) { + while (length > 0) { + size_t remaining = MS_SEND_BUFFER_SIZE - txBufferLen; + size_t amount = remaining < length ? remaining : length; + + memcpy(&txBuffer[txBufferLen], data, amount); + length -= amount; + data += amount; + txBufferLen += amount; + + if (txBufferLen == MS_SEND_BUFFER_SIZE) { txBufferFlush(); } + } +} -// Returns how much space is left in the buffer -int dataPublisher::bufferFree(void) { - MS_DBG(F("Current TX Buffer Size:"), strlen(txBuffer)); - return MS_SEND_BUFFER_SIZE - strlen(txBuffer); +void dataPublisher::txBufferAppend(const char* s) { + txBufferAppend(s, strlen(s)); } +void dataPublisher::txBufferAppend(char c) { + txBufferAppend(&c, 1); +} -// Sends the tx buffer to a stream and then clears it -void dataPublisher::printTxBuffer(Stream* stream, bool addNewLine) { -// Send the out buffer so far to the serial for debugging +void dataPublisher::txBufferFlush() { #if defined(STANDARD_SERIAL_OUTPUT) - STANDARD_SERIAL_OUTPUT.write(txBuffer, strlen(txBuffer)); - if (addNewLine) { PRINTOUT('\n'); } + // send to debugging stream + STANDARD_SERIAL_OUTPUT.write((const uint8_t*)txBuffer, txBufferLen); STANDARD_SERIAL_OUTPUT.flush(); #endif - stream->write(txBuffer, strlen(txBuffer)); - if (addNewLine) { stream->print("\r\n"); } - stream->flush(); + txBufferOutClient->write((const uint8_t*)txBuffer, txBufferLen); + txBufferOutClient->flush(); - // empty the buffer after printing it - emptyTxBuffer(); + txBufferLen = 0; } diff --git a/src/dataPublisherBase.h b/src/dataPublisherBase.h index d43ba5dde..91b4f9060 100644 --- a/src/dataPublisherBase.h +++ b/src/dataPublisherBase.h @@ -32,11 +32,10 @@ * @def MS_SEND_BUFFER_SIZE * @brief Send Buffer * - * This determines how many characters to set out at once over the TCP/UDP - * connection. Increasing this may decrease data use by a loger, while - * decreasing it will save memory. Do not make it smaller than 47 (to keep all - * variable values with their UUID's) or bigger than 1500 (a typical TCP/UDP - * Maximum Transmission Unit). + * This determines how many characters to set out at once over the TCP + * connection. Increasing this may decrease data use by a logger, while + * decreasing it will save memory. Do not make it smaller than 32 or bigger + * than 1500 (a typical TCP Maximum Transmission Unit). * * This can be changed by setting the build flag MS_SEND_BUFFER_SIZE when * compiling. @@ -280,29 +279,48 @@ class dataPublisher { Client* _inClient = nullptr; /** - * @brief A buffer for outgoing data. + * @brief The buffer for outgoing data. */ static char txBuffer[MS_SEND_BUFFER_SIZE]; /** - * @brief Get the number of empty spots in the buffer. + * @brief The pointer to the client instance the TX buffer is writing to. + */ + static Client* txBufferOutClient; + /** + * @brief The number of used characters in the TX buffer. + */ + static size_t txBufferLen; + /** + * @brief Initialize the TX buffer to be empty and start writing to the + * given client. + * + * @param client The client to transmit to. + */ + static void txBufferInit(Client* outClient); + /** + * @brief Append the given data to the TX buffer, flushing if necessary. * - * @return **int** The number of available characters in the buffer + * @param data The data start pointer. + * @param length The number of bytes to add. */ - static int bufferFree(void); + static void txBufferAppend(const char* data, size_t length); /** - * @brief Fill the TX buffer with nulls ('\0'). + * @brief Append the given string to the TX buffer, flushing if necessary. + * + * @param s The null-terminated string to append. */ - static void emptyTxBuffer(void); + static void txBufferAppend(const char* s); /** - * @brief Write the TX buffer to a stream and also to the debugging - * port. + * @brief Append the given char to the TX buffer, flushing if necessary. * - * @param stream A pointer to an Arduino Stream instance to use to print - * data - * @param addNewLine True to add a new line character ("\n") at the end of - * the print + * @param c The char to append. + */ + static void txBufferAppend(char c); + /** + * @brief Write the TX buffer contents to the initialized stream and also to + * the debugging port. */ - static void printTxBuffer(Stream* stream, bool addNewLine = false); + static void txBufferFlush(); /** * @brief Unimplemented; intended for future use to enable caching and bulk diff --git a/src/publishers/DreamHostPublisher.cpp b/src/publishers/DreamHostPublisher.cpp index b65c6caed..5c3db12f6 100644 --- a/src/publishers/DreamHostPublisher.cpp +++ b/src/publishers/DreamHostPublisher.cpp @@ -76,59 +76,41 @@ int16_t DreamHostPublisher::publishData(Client* outClient) { MS_START_DEBUG_TIMER; if (outClient->connect(dreamhostHost, dreamhostPort)) { MS_DBG(F("Client connected after"), MS_PRINT_DEBUG_TIMER, F("ms\n")); + txBufferInit(outClient); // copy the initial post header into the tx buffer - snprintf(txBuffer, sizeof(txBuffer), "%s", getHeader); + txBufferAppend(getHeader); // add in the dreamhost receiver URL - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", _DreamHostPortalRX); + txBufferAppend(_DreamHostPortalRX); // start the URL parameters - if (bufferFree() < 16) printTxBuffer(outClient); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", loggerTag); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", - _baseLogger->getLoggerID()); - - if (bufferFree() < 22) printTxBuffer(outClient); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", timestampTagDH); + txBufferAppend(loggerTag); + txBufferAppend(_baseLogger->getLoggerID()); + + txBufferAppend(timestampTagDH); ltoa((Logger::markedLocalEpochTime - 946684800), tempBuffer, 10); // BASE 10 - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tempBuffer); + txBufferAppend(tempBuffer); for (uint8_t i = 0; i < _baseLogger->getArrayVarCount(); i++) { - // Once the buffer fills, send it out - if (bufferFree() < 47) printTxBuffer(outClient); - - txBuffer[strlen(txBuffer)] = '&'; - _baseLogger->getVarCodeAtI(i).toCharArray(tempBuffer, 37); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tempBuffer); - txBuffer[strlen(txBuffer)] = '='; - _baseLogger->getValueStringAtI(i).toCharArray(tempBuffer, 37); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tempBuffer); + txBufferAppend('&'); + txBufferAppend(_baseLogger->getVarCodeAtI(i).c_str()); + txBufferAppend('='); + txBufferAppend(_baseLogger->getValueStringAtI(i).c_str()); } // add the rest of the HTTP GET headers to the outgoing buffer - if (bufferFree() < 52) printTxBuffer(outClient); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", HTTPtag); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", hostHeader); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", dreamhostHost); - txBuffer[strlen(txBuffer)] = '\r'; - txBuffer[strlen(txBuffer)] = '\n'; - txBuffer[strlen(txBuffer)] = '\r'; - txBuffer[strlen(txBuffer)] = '\n'; - - // Send out the finished request (or the last unsent section of it) - printTxBuffer(outClient); + txBufferAppend(HTTPtag); + txBufferAppend(hostHeader); + txBufferAppend(dreamhostHost); + txBufferAppend('\r'); + txBufferAppend('\n'); + txBufferAppend('\r'); + txBufferAppend('\n'); + + // Flush the complete request + txBufferFlush(); // Wait 10 seconds for a response from the server uint32_t start = millis(); @@ -163,7 +145,7 @@ int16_t DreamHostPublisher::publishData(Client* outClient) { responseCode = 504; } - PRINTOUT(F("-- Response Code --")); + PRINTOUT(F("\n-- Response Code --")); PRINTOUT(responseCode); return responseCode; diff --git a/src/publishers/EnviroDIYPublisher.cpp b/src/publishers/EnviroDIYPublisher.cpp index b27516106..4c8b7455a 100644 --- a/src/publishers/EnviroDIYPublisher.cpp +++ b/src/publishers/EnviroDIYPublisher.cpp @@ -117,83 +117,51 @@ int16_t EnviroDIYPublisher::publishData(Client* outClient) { MS_START_DEBUG_TIMER; if (outClient->connect(enviroDIYHost, enviroDIYPort)) { MS_DBG(F("Client connected after"), MS_PRINT_DEBUG_TIMER, F("ms\n")); + txBufferInit(outClient); // copy the initial post header into the tx buffer - snprintf(txBuffer, sizeof(txBuffer), "%s", postHeader); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", postEndpoint); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", HTTPtag); + txBufferAppend(postHeader); + txBufferAppend(postEndpoint); + txBufferAppend(HTTPtag); // add the rest of the HTTP POST headers to the outgoing buffer - // before adding each line/chunk to the outgoing buffer, we make sure - // there is space for that line, sending out buffer if not - if (bufferFree() < 28) printTxBuffer(outClient); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", hostHeader); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", enviroDIYHost); - - if (bufferFree() < 47) printTxBuffer(outClient); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tokenHeader); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", _registrationToken); - - if (bufferFree() < 26) printTxBuffer(outClient); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", - contentLengthHeader); + txBufferAppend(hostHeader); + txBufferAppend(enviroDIYHost); + txBufferAppend(tokenHeader); + txBufferAppend(_registrationToken); + + txBufferAppend(contentLengthHeader); itoa(calculateJsonSize(), tempBuffer, 10); // BASE 10 - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tempBuffer); + txBufferAppend(tempBuffer); - if (bufferFree() < 42) printTxBuffer(outClient); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", contentTypeHeader); + txBufferAppend(contentTypeHeader); // put the start of the JSON into the outgoing response_buffer - if (bufferFree() < 21) printTxBuffer(outClient); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", samplingFeatureTag); - - if (bufferFree() < 36) printTxBuffer(outClient); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", - _baseLogger->getSamplingFeatureUUID()); - - if (bufferFree() < 42) printTxBuffer(outClient); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", timestampTag); - Logger::formatDateTime_ISO8601(Logger::markedLocalEpochTime) - .toCharArray(tempBuffer, 37); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tempBuffer); - txBuffer[strlen(txBuffer)] = '"'; - txBuffer[strlen(txBuffer)] = ','; + txBufferAppend(samplingFeatureTag); + txBufferAppend(_baseLogger->getSamplingFeatureUUID()); + + txBufferAppend(timestampTag); + txBufferAppend( + Logger::formatDateTime_ISO8601(Logger::markedLocalEpochTime) + .c_str()); + txBufferAppend('"'); + txBufferAppend(','); for (uint8_t i = 0; i < _baseLogger->getArrayVarCount(); i++) { - // Once the buffer fills, send it out - if (bufferFree() < 47) printTxBuffer(outClient); - - txBuffer[strlen(txBuffer)] = '"'; - _baseLogger->getVarUUIDAtI(i).toCharArray(tempBuffer, 37); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tempBuffer); - txBuffer[strlen(txBuffer)] = '"'; - txBuffer[strlen(txBuffer)] = ':'; - _baseLogger->getValueStringAtI(i).toCharArray(tempBuffer, 37); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tempBuffer); + txBufferAppend('"'); + txBufferAppend(_baseLogger->getVarUUIDAtI(i).c_str()); + txBufferAppend('"'); + txBufferAppend(':'); + txBufferAppend(_baseLogger->getValueStringAtI(i).c_str()); if (i + 1 != _baseLogger->getArrayVarCount()) { - txBuffer[strlen(txBuffer)] = ','; + txBufferAppend(','); } else { - txBuffer[strlen(txBuffer)] = '}'; + txBufferAppend('}'); } } - // Send out the finished request (or the last unsent section of it) - printTxBuffer(outClient, true); + // Flush the complete request + txBufferFlush(); // Wait 10 seconds for a response from the server uint32_t start = millis(); @@ -229,7 +197,7 @@ int16_t EnviroDIYPublisher::publishData(Client* outClient) { responseCode = 504; } - PRINTOUT(F("-- Response Code --")); + PRINTOUT(F("\n-- Response Code --")); PRINTOUT(responseCode); return responseCode; diff --git a/src/publishers/ThingSpeakPublisher.cpp b/src/publishers/ThingSpeakPublisher.cpp index e1b0e3a7f..f65d8e23f 100644 --- a/src/publishers/ThingSpeakPublisher.cpp +++ b/src/publishers/ThingSpeakPublisher.cpp @@ -129,27 +129,19 @@ int16_t ThingSpeakPublisher::publishData(Client* outClient) { _thingSpeakChannelKey); MS_DBG(F("Topic ["), strlen(topicBuffer), F("]:"), String(topicBuffer)); - emptyTxBuffer(); + // buffer is used only locally, it does not transmit + txBufferInit(nullptr); - Logger::formatDateTime_ISO8601(Logger::markedLocalEpochTime) - .toCharArray(tempBuffer, 26); - snprintf(txBuffer + strlen(txBuffer), sizeof(txBuffer) - strlen(txBuffer), - "%s", "created_at="); - snprintf(txBuffer + strlen(txBuffer), sizeof(txBuffer) - strlen(txBuffer), - "%s", tempBuffer); - txBuffer[strlen(txBuffer)] = '&'; + txBufferAppend("created_at="); + txBufferAppend( + Logger::formatDateTime_ISO8601(Logger::markedLocalEpochTime).c_str()); for (uint8_t i = 0; i < numChannels; i++) { - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", "field"); + txBufferAppend("&field"); itoa(i + 1, tempBuffer, 10); // BASE 10 - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tempBuffer); - txBuffer[strlen(txBuffer)] = '='; - _baseLogger->getValueStringAtI(i).toCharArray(tempBuffer, 26); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tempBuffer); - if (i + 1 != numChannels) { txBuffer[strlen(txBuffer)] = '&'; } + txBufferAppend(tempBuffer); + txBufferAppend('='); + txBufferAppend(_baseLogger->getValueStringAtI(i).c_str()); } MS_DBG(F("Message ["), strlen(txBuffer), F("]:"), String(txBuffer)); diff --git a/src/publishers/UbidotsPublisher.cpp b/src/publishers/UbidotsPublisher.cpp index 55f4f5227..c1e781d62 100644 --- a/src/publishers/UbidotsPublisher.cpp +++ b/src/publishers/UbidotsPublisher.cpp @@ -127,93 +127,48 @@ int16_t UbidotsPublisher::publishData(Client* outClient) { MS_START_DEBUG_TIMER; if (outClient->connect(ubidotsHost, ubidotsPort)) { MS_DBG(F("Client connected after"), MS_PRINT_DEBUG_TIMER, F("ms\n")); + txBufferInit(outClient); // copy the initial post header into the tx buffer - snprintf(txBuffer, sizeof(txBuffer), "%s", postHeader); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", postEndpoint); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", - _baseLogger->getSamplingFeatureUUID()); - txBuffer[strlen(txBuffer)] = '/'; - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", HTTPtag); + txBufferAppend(postHeader); + txBufferAppend(postEndpoint); + txBufferAppend(_baseLogger->getSamplingFeatureUUID()); + txBufferAppend('/'); + txBufferAppend(HTTPtag); // add the rest of the HTTP POST headers to the outgoing buffer - // before adding each line/chunk to the outgoing buffer, we make sure - // there is space for that line, sending out buffer if not - if (bufferFree() < 28) printTxBuffer(outClient); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", hostHeader); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", ubidotsHost); - - if (bufferFree() < 47) printTxBuffer(outClient); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tokenHeader); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", - _authentificationToken); - - if (bufferFree() < 26) printTxBuffer(outClient); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", - contentLengthHeader); + txBufferAppend(hostHeader); + txBufferAppend(ubidotsHost); + txBufferAppend(tokenHeader); + txBufferAppend(_authentificationToken); + + txBufferAppend(contentLengthHeader); itoa(calculateJsonSize(), tempBuffer, 10); // BASE 10 - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tempBuffer); + txBufferAppend(tempBuffer); - if (bufferFree() < 42) printTxBuffer(outClient); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", contentTypeHeader); + txBufferAppend(contentTypeHeader); // put the start of the JSON into the outgoing response_buffer - if (bufferFree() < 21) printTxBuffer(outClient); - - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", payload); + txBufferAppend(payload); for (uint8_t i = 0; i < _baseLogger->getArrayVarCount(); i++) { - // Once the buffer fills, send it out - if (bufferFree() < 47) printTxBuffer(outClient); - - txBuffer[strlen(txBuffer)] = '"'; - _baseLogger->getVarUUIDAtI(i).toCharArray(tempBuffer, 37); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tempBuffer); - txBuffer[strlen(txBuffer)] = '"'; - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", ":{"); - txBuffer[strlen(txBuffer)] = '"'; - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", "value"); - txBuffer[strlen(txBuffer)] = '"'; - txBuffer[strlen(txBuffer)] = ':'; - _baseLogger->getValueStringAtI(i).toCharArray(tempBuffer, 37); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tempBuffer); - txBuffer[strlen(txBuffer)] = ','; - txBuffer[strlen(txBuffer)] = '"'; - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", "timestamp"); - txBuffer[strlen(txBuffer)] = '"'; - txBuffer[strlen(txBuffer)] = ':'; + txBufferAppend('"'); + txBufferAppend(_baseLogger->getVarUUIDAtI(i).c_str()); + txBufferAppend("\":{\"value\":"); + txBufferAppend(_baseLogger->getValueStringAtI(i).c_str()); + txBufferAppend(",\"timestamp\":"); ltoa(Logger::markedUTCEpochTime, tempBuffer, 10); // BASE 10 - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tempBuffer); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", "000"); + txBufferAppend(tempBuffer); + txBufferAppend("000}"); if (i + 1 != _baseLogger->getArrayVarCount()) { - txBuffer[strlen(txBuffer)] = '}'; - txBuffer[strlen(txBuffer)] = ','; + txBufferAppend(','); } else { - txBuffer[strlen(txBuffer)] = '}'; - txBuffer[strlen(txBuffer)] = '}'; + txBufferAppend('}'); } } - // Send out the finished request (or the last unsent section of it) - printTxBuffer(outClient, true); + // Flush the complete request + txBufferFlush(); // Wait 10 seconds for a response from the server uint32_t start = millis(); @@ -248,7 +203,7 @@ int16_t UbidotsPublisher::publishData(Client* outClient) { responseCode = 504; } - PRINTOUT(F("-- Response Code --")); + PRINTOUT(F("\n-- Response Code --")); PRINTOUT(responseCode); return responseCode; From 2c87ff0e68fac51d231e0c0f658d0ff958fd9967 Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Thu, 16 Mar 2023 14:24:40 -0500 Subject: [PATCH 09/11] dataPublisherBase: widen sendEveryX and ditch sendOffset sendEveryX will be used in the future for data buffering functionality. Increase its width to an int to allow larger buffers when desired. Delete sendOffset completely as there is little reason for that particular functionality. The offset will be in effect set randomly using the time the datalogger initially powers on. --- src/dataPublisherBase.cpp | 18 ++++------ src/dataPublisherBase.h | 46 ++++++++------------------ src/publishers/DreamHostPublisher.cpp | 18 +++++----- src/publishers/DreamHostPublisher.h | 37 +++++++-------------- src/publishers/EnviroDIYPublisher.cpp | 17 +++++----- src/publishers/EnviroDIYPublisher.h | 39 +++++++--------------- src/publishers/ThingSpeakPublisher.cpp | 17 +++++----- src/publishers/ThingSpeakPublisher.h | 38 +++++++-------------- src/publishers/UbidotsPublisher.cpp | 19 +++++------ src/publishers/UbidotsPublisher.h | 39 +++++++--------------- 10 files changed, 101 insertions(+), 187 deletions(-) diff --git a/src/dataPublisherBase.cpp b/src/dataPublisherBase.cpp index 6075d9bae..1f4ab0a51 100644 --- a/src/dataPublisherBase.cpp +++ b/src/dataPublisherBase.cpp @@ -23,19 +23,16 @@ const char* dataPublisher::hostHeader = "\r\nHost: "; // Constructors dataPublisher::dataPublisher() {} -dataPublisher::dataPublisher(Logger& baseLogger, uint8_t sendEveryX, - uint8_t sendOffset) +dataPublisher::dataPublisher(Logger& baseLogger, int sendEveryX) : _baseLogger(&baseLogger), - _sendEveryX(sendEveryX), - _sendOffset(sendOffset) { + _sendEveryX(sendEveryX) { _baseLogger->registerDataPublisher(this); // register self with logger } dataPublisher::dataPublisher(Logger& baseLogger, Client* inClient, - uint8_t sendEveryX, uint8_t sendOffset) + int sendEveryX) : _baseLogger(&baseLogger), _inClient(inClient), - _sendEveryX(sendEveryX), - _sendOffset(sendOffset) { + _sendEveryX(sendEveryX) { _baseLogger->registerDataPublisher(this); // register self with logger } // Destructor @@ -55,11 +52,10 @@ void dataPublisher::attachToLogger(Logger& baseLogger) { } -// Sets the parameters for frequency of sending and any offset, if needed -// NOTE: These parameters are not currently used!! -void dataPublisher::setSendFrequency(uint8_t sendEveryX, uint8_t sendOffset) { +// Sets the interval (in units of the logging interval) between attempted +// data transmissions +void dataPublisher::setSendInterval(int sendEveryX) { _sendEveryX = sendEveryX; - _sendOffset = sendOffset; } diff --git a/src/dataPublisherBase.h b/src/dataPublisherBase.h index 91b4f9060..1f24430f9 100644 --- a/src/dataPublisherBase.h +++ b/src/dataPublisherBase.h @@ -85,11 +85,8 @@ class dataPublisher { * logger. * * @param baseLogger The logger supplying the data to be published - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. Not respected by all publishers. * * @note It is possible (though very unlikey) that using this constructor * could cause errors if the compiler attempts to initialize the publisher @@ -97,8 +94,7 @@ class dataPublisher { * issue, use the null constructor and a populated begin(...) within your * set-up function. */ - explicit dataPublisher(Logger& baseLogger, uint8_t sendEveryX = 1, - uint8_t sendOffset = 0); + explicit dataPublisher(Logger& baseLogger, int sendEveryX = 1); /** * @brief Construct a new data Publisher object. * @@ -106,11 +102,8 @@ class dataPublisher { * @param inClient An Arduino client instance to use to print data to. * Allows the use of any type of client and multiple clients tied to a * single TinyGSM modem instance - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. Not respected by all publishers. * * @note It is possible (though very unlikey) that using this constructor * could cause errors if the compiler attempts to initialize the publisher @@ -118,8 +111,7 @@ class dataPublisher { * issue, use the null constructor and a populated begin(...) within your * set-up function. */ - dataPublisher(Logger& baseLogger, Client* inClient, uint8_t sendEveryX = 1, - uint8_t sendOffset = 0); + dataPublisher(Logger& baseLogger, Client* inClient, int sendEveryX = 1); /** * @brief Destroy the data Publisher object - no action is taken. */ @@ -144,18 +136,13 @@ class dataPublisher { */ void attachToLogger(Logger& baseLogger); /** - * @brief Set the parameters for frequency of sending and any offset, if - * needed. + * @brief Sets the interval (in units of the logging interval) between + * attempted data transmissions * - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected - * - * @note These parameters are not currently used! + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. Not respected by all publishers. */ - void setSendFrequency(uint8_t sendEveryX, uint8_t sendOffset); + void setSendInterval(int sendEveryX); /** * @brief Begin the publisher - linking it to the client and logger. @@ -323,15 +310,10 @@ class dataPublisher { static void txBufferFlush(); /** - * @brief Unimplemented; intended for future use to enable caching and bulk - * publishing. - */ - uint8_t _sendEveryX = 1; - /** - * @brief Unimplemented; intended for future use to enable publishing data - * at a time slightly delayed from when it is collected. + * @brief Interval (in units of the logging interval) between + * attempted data transmissions. Not respected by all publishers. */ - uint8_t _sendOffset = 0; + int _sendEveryX = 1; // Basic chunks of HTTP /** diff --git a/src/publishers/DreamHostPublisher.cpp b/src/publishers/DreamHostPublisher.cpp index 5c3db12f6..74412523e 100644 --- a/src/publishers/DreamHostPublisher.cpp +++ b/src/publishers/DreamHostPublisher.cpp @@ -23,23 +23,21 @@ const char* DreamHostPublisher::timestampTagDH = "&Loggertime="; // Constructors DreamHostPublisher::DreamHostPublisher() : dataPublisher() {} -DreamHostPublisher::DreamHostPublisher(Logger& baseLogger, uint8_t sendEveryX, - uint8_t sendOffset) - : dataPublisher(baseLogger, sendEveryX, sendOffset) {} +DreamHostPublisher::DreamHostPublisher(Logger& baseLogger, int sendEveryX) + : dataPublisher(baseLogger, sendEveryX) {} DreamHostPublisher::DreamHostPublisher(Logger& baseLogger, Client* inClient, - uint8_t sendEveryX, uint8_t sendOffset) - : dataPublisher(baseLogger, inClient, sendEveryX, sendOffset) {} + int sendEveryX) + : dataPublisher(baseLogger, inClient, sendEveryX) {} DreamHostPublisher::DreamHostPublisher(Logger& baseLogger, const char* dhUrl, - uint8_t sendEveryX, uint8_t sendOffset) - : dataPublisher(baseLogger, sendEveryX, sendOffset) { + int sendEveryX) + : dataPublisher(baseLogger, sendEveryX) { setDreamHostPortalRX(dhUrl); } DreamHostPublisher::DreamHostPublisher(Logger& baseLogger, Client* inClient, - const char* dhUrl, uint8_t sendEveryX, - uint8_t sendOffset) - : dataPublisher(baseLogger, inClient, sendEveryX, sendOffset) { + const char* dhUrl, int sendEveryX) + : dataPublisher(baseLogger, inClient, sendEveryX) { setDreamHostPortalRX(dhUrl); } // Destructor diff --git a/src/publishers/DreamHostPublisher.h b/src/publishers/DreamHostPublisher.h index 584be2142..e7a8a6fb6 100644 --- a/src/publishers/DreamHostPublisher.h +++ b/src/publishers/DreamHostPublisher.h @@ -51,11 +51,8 @@ class DreamHostPublisher : public dataPublisher { * logger. * * @param baseLogger The logger supplying the data to be published - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! * * @note It is possible (though very unlikey) that using this constructor * could cause errors if the compiler attempts to initialize the publisher @@ -63,8 +60,7 @@ class DreamHostPublisher : public dataPublisher { * issue, use the null constructor and a populated begin(...) within your * set-up function. */ - explicit DreamHostPublisher(Logger& baseLogger, uint8_t sendEveryX = 1, - uint8_t sendOffset = 0); + explicit DreamHostPublisher(Logger& baseLogger, int sendEveryX = 1); /** * @brief Construct a new DreamHost Publisher object * @@ -72,11 +68,8 @@ class DreamHostPublisher : public dataPublisher { * @param inClient An Arduino client instance to use to print data to. * Allows the use of any type of client and multiple clients tied to a * single TinyGSM modem instance - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! * * @note It is possible (though very unlikey) that using this constructor * could cause errors if the compiler attempts to initialize the publisher @@ -85,20 +78,17 @@ class DreamHostPublisher : public dataPublisher { * set-up function. */ DreamHostPublisher(Logger& baseLogger, Client* inClient, - uint8_t sendEveryX = 1, uint8_t sendOffset = 0); + int sendEveryX = 1); /** * @brief Construct a new DreamHost Publisher object * * @param baseLogger The logger supplying the data to be published * @param dhUrl The URL for sending data to DreamHost - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! */ DreamHostPublisher(Logger& baseLogger, const char* dhUrl, - uint8_t sendEveryX = 1, uint8_t sendOffset = 0); + int sendEveryX = 1); /** * @brief Construct a new DreamHost Publisher object * @@ -107,14 +97,11 @@ class DreamHostPublisher : public dataPublisher { * Allows the use of any type of client and multiple clients tied to a * single TinyGSM modem instance * @param dhUrl The URL for sending data to DreamHost - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! */ DreamHostPublisher(Logger& baseLogger, Client* inClient, const char* dhUrl, - uint8_t sendEveryX = 1, uint8_t sendOffset = 0); + int sendEveryX = 1); /** * @brief Destroy the DreamHost Publisher object */ diff --git a/src/publishers/EnviroDIYPublisher.cpp b/src/publishers/EnviroDIYPublisher.cpp index 4c8b7455a..ec65e0f48 100644 --- a/src/publishers/EnviroDIYPublisher.cpp +++ b/src/publishers/EnviroDIYPublisher.cpp @@ -31,25 +31,24 @@ const char* EnviroDIYPublisher::timestampTag = "\",\"timestamp\":\""; // Constructors EnviroDIYPublisher::EnviroDIYPublisher() : dataPublisher() {} -EnviroDIYPublisher::EnviroDIYPublisher(Logger& baseLogger, uint8_t sendEveryX, - uint8_t sendOffset) - : dataPublisher(baseLogger, sendEveryX, sendOffset) {} +EnviroDIYPublisher::EnviroDIYPublisher(Logger& baseLogger, int sendEveryX) + : dataPublisher(baseLogger, sendEveryX) {} EnviroDIYPublisher::EnviroDIYPublisher(Logger& baseLogger, Client* inClient, - uint8_t sendEveryX, uint8_t sendOffset) - : dataPublisher(baseLogger, inClient, sendEveryX, sendOffset) {} + int sendEveryX) + : dataPublisher(baseLogger, inClient, sendEveryX) {} EnviroDIYPublisher::EnviroDIYPublisher(Logger& baseLogger, const char* registrationToken, const char* samplingFeatureUUID, - uint8_t sendEveryX, uint8_t sendOffset) - : dataPublisher(baseLogger, sendEveryX, sendOffset) { + int sendEveryX) + : dataPublisher(baseLogger, sendEveryX) { setToken(registrationToken); _baseLogger->setSamplingFeatureUUID(samplingFeatureUUID); } EnviroDIYPublisher::EnviroDIYPublisher(Logger& baseLogger, Client* inClient, const char* registrationToken, const char* samplingFeatureUUID, - uint8_t sendEveryX, uint8_t sendOffset) - : dataPublisher(baseLogger, inClient, sendEveryX, sendOffset) { + int sendEveryX) + : dataPublisher(baseLogger, inClient, sendEveryX) { setToken(registrationToken); _baseLogger->setSamplingFeatureUUID(samplingFeatureUUID); } diff --git a/src/publishers/EnviroDIYPublisher.h b/src/publishers/EnviroDIYPublisher.h index 145860908..9a37df180 100644 --- a/src/publishers/EnviroDIYPublisher.h +++ b/src/publishers/EnviroDIYPublisher.h @@ -51,11 +51,8 @@ class EnviroDIYPublisher : public dataPublisher { * logger. * * @param baseLogger The logger supplying the data to be published - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! * * @note It is possible (though very unlikey) that using this constructor * could cause errors if the compiler attempts to initialize the publisher @@ -63,8 +60,7 @@ class EnviroDIYPublisher : public dataPublisher { * issue, use the null constructor and a populated begin(...) within your * set-up function. */ - explicit EnviroDIYPublisher(Logger& baseLogger, uint8_t sendEveryX = 1, - uint8_t sendOffset = 0); + explicit EnviroDIYPublisher(Logger& baseLogger, int sendEveryX = 1); /** * @brief Construct a new EnviroDIY Publisher object * @@ -72,11 +68,8 @@ class EnviroDIYPublisher : public dataPublisher { * @param inClient An Arduino client instance to use to print data to. * Allows the use of any type of client and multiple clients tied to a * single TinyGSM modem instance - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! * * @note It is possible (though very unlikey) that using this constructor * could cause errors if the compiler attempts to initialize the publisher @@ -85,7 +78,7 @@ class EnviroDIYPublisher : public dataPublisher { * set-up function. */ EnviroDIYPublisher(Logger& baseLogger, Client* inClient, - uint8_t sendEveryX = 1, uint8_t sendOffset = 0); + int sendEveryX = 1); /** * @brief Construct a new EnviroDIY Publisher object * @@ -94,15 +87,11 @@ class EnviroDIYPublisher : public dataPublisher { * Monitor My Watershed data portal. * @param samplingFeatureUUID The sampling feature UUID for the site on the * Monitor My Watershed data portal. - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! */ EnviroDIYPublisher(Logger& baseLogger, const char* registrationToken, - const char* samplingFeatureUUID, uint8_t sendEveryX = 1, - uint8_t sendOffset = 0); + const char* samplingFeatureUUID, int sendEveryX = 1); /** * @brief Construct a new EnviroDIY Publisher object * @@ -114,16 +103,12 @@ class EnviroDIYPublisher : public dataPublisher { * Monitor My Watershed data portal. * @param samplingFeatureUUID The sampling feature UUID for the site on the * Monitor My Watershed data portal. - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! */ EnviroDIYPublisher(Logger& baseLogger, Client* inClient, const char* registrationToken, - const char* samplingFeatureUUID, uint8_t sendEveryX = 1, - uint8_t sendOffset = 0); + const char* samplingFeatureUUID, int sendEveryX = 1); /** * @brief Destroy the EnviroDIY Publisher object */ diff --git a/src/publishers/ThingSpeakPublisher.cpp b/src/publishers/ThingSpeakPublisher.cpp index f65d8e23f..b3c9fb706 100644 --- a/src/publishers/ThingSpeakPublisher.cpp +++ b/src/publishers/ThingSpeakPublisher.cpp @@ -25,18 +25,17 @@ const char* ThingSpeakPublisher::mqttUser = THING_SPEAK_USER_NAME; // Constructors ThingSpeakPublisher::ThingSpeakPublisher() : dataPublisher() {} -ThingSpeakPublisher::ThingSpeakPublisher(Logger& baseLogger, uint8_t sendEveryX, - uint8_t sendOffset) - : dataPublisher(baseLogger, sendEveryX, sendOffset) {} +ThingSpeakPublisher::ThingSpeakPublisher(Logger& baseLogger, int sendEveryX) + : dataPublisher(baseLogger, sendEveryX) {} ThingSpeakPublisher::ThingSpeakPublisher(Logger& baseLogger, Client* inClient, - uint8_t sendEveryX, uint8_t sendOffset) - : dataPublisher(baseLogger, inClient, sendEveryX, sendOffset) {} + int sendEveryX) + : dataPublisher(baseLogger, inClient, sendEveryX) {} ThingSpeakPublisher::ThingSpeakPublisher(Logger& baseLogger, const char* thingSpeakMQTTKey, const char* thingSpeakChannelID, const char* thingSpeakChannelKey, - uint8_t sendEveryX, uint8_t sendOffset) - : dataPublisher(baseLogger, sendEveryX, sendOffset) { + int sendEveryX) + : dataPublisher(baseLogger, sendEveryX) { setMQTTKey(thingSpeakMQTTKey); setChannelID(thingSpeakChannelID); setChannelKey(thingSpeakChannelKey); @@ -45,8 +44,8 @@ ThingSpeakPublisher::ThingSpeakPublisher(Logger& baseLogger, Client* inClient, const char* thingSpeakMQTTKey, const char* thingSpeakChannelID, const char* thingSpeakChannelKey, - uint8_t sendEveryX, uint8_t sendOffset) - : dataPublisher(baseLogger, inClient, sendEveryX, sendOffset) { + int sendEveryX) + : dataPublisher(baseLogger, inClient, sendEveryX) { setMQTTKey(thingSpeakMQTTKey); setChannelID(thingSpeakChannelID); setChannelKey(thingSpeakChannelKey); diff --git a/src/publishers/ThingSpeakPublisher.h b/src/publishers/ThingSpeakPublisher.h index 2b0bbe89d..857efa42b 100644 --- a/src/publishers/ThingSpeakPublisher.h +++ b/src/publishers/ThingSpeakPublisher.h @@ -76,11 +76,8 @@ class ThingSpeakPublisher : public dataPublisher { * logger. * * @param baseLogger The logger supplying the data to be published - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! * * @note It is possible (though very unlikey) that using this constructor * could cause errors if the compiler attempts to initialize the publisher @@ -88,8 +85,7 @@ class ThingSpeakPublisher : public dataPublisher { * issue, use the null constructor and a populated begin(...) within your * set-up function. */ - explicit ThingSpeakPublisher(Logger& baseLogger, uint8_t sendEveryX = 1, - uint8_t sendOffset = 0); + explicit ThingSpeakPublisher(Logger& baseLogger, int sendEveryX = 1); /** * @brief Construct a new ThingSpeak Publisher object * @@ -97,11 +93,8 @@ class ThingSpeakPublisher : public dataPublisher { * @param inClient An Arduino client instance to use to print data to. * Allows the use of any type of client and multiple clients tied to a * single TinyGSM modem instance - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! * * @note It is possible (though very unlikey) that using this constructor * could cause errors if the compiler attempts to initialize the publisher @@ -110,7 +103,7 @@ class ThingSpeakPublisher : public dataPublisher { * set-up function. */ ThingSpeakPublisher(Logger& baseLogger, Client* inClient, - uint8_t sendEveryX = 1, uint8_t sendOffset = 0); + int sendEveryX = 1); /** * @brief Construct a new ThingSpeak Publisher object * @@ -118,15 +111,12 @@ class ThingSpeakPublisher : public dataPublisher { * @param thingSpeakMQTTKey Your MQTT API Key from Account > MyProfile. * @param thingSpeakChannelID The numeric channel id for your channel * @param thingSpeakChannelKey The write API key for your channel - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! */ ThingSpeakPublisher(Logger& baseLogger, const char* thingSpeakMQTTKey, const char* thingSpeakChannelID, - const char* thingSpeakChannelKey, - uint8_t sendEveryX = 1, uint8_t sendOffset = 0); + const char* thingSpeakChannelKey, int sendEveryX = 1); /** * @brief Construct a new ThingSpeak Publisher object * @@ -137,17 +127,13 @@ class ThingSpeakPublisher : public dataPublisher { * @param thingSpeakMQTTKey Your MQTT API Key from Account > MyProfile. * @param thingSpeakChannelID The numeric channel id for your channel * @param thingSpeakChannelKey The write API key for your channel - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! */ ThingSpeakPublisher(Logger& baseLogger, Client* inClient, const char* thingSpeakMQTTKey, const char* thingSpeakChannelID, - const char* thingSpeakChannelKey, - uint8_t sendEveryX = 1, uint8_t sendOffset = 0); + const char* thingSpeakChannelKey, int sendEveryX = 1); /** * @brief Destroy the ThingSpeak Publisher object */ diff --git a/src/publishers/UbidotsPublisher.cpp b/src/publishers/UbidotsPublisher.cpp index c1e781d62..5477345a4 100644 --- a/src/publishers/UbidotsPublisher.cpp +++ b/src/publishers/UbidotsPublisher.cpp @@ -34,26 +34,23 @@ const char* UbidotsPublisher::payload = "{"; // Constructors UbidotsPublisher::UbidotsPublisher() : dataPublisher() {} -UbidotsPublisher::UbidotsPublisher(Logger& baseLogger, uint8_t sendEveryX, - uint8_t sendOffset) - : dataPublisher(baseLogger, sendEveryX, sendOffset) {} +UbidotsPublisher::UbidotsPublisher(Logger& baseLogger, int sendEveryX) + : dataPublisher(baseLogger, sendEveryX) {} UbidotsPublisher::UbidotsPublisher(Logger& baseLogger, Client* inClient, - uint8_t sendEveryX, uint8_t sendOffset) - : dataPublisher(baseLogger, inClient, sendEveryX, sendOffset) {} + int sendEveryX) + : dataPublisher(baseLogger, inClient, sendEveryX) {} UbidotsPublisher::UbidotsPublisher(Logger& baseLogger, const char* authentificationToken, - const char* deviceID, uint8_t sendEveryX, - uint8_t sendOffset) - : dataPublisher(baseLogger, sendEveryX, sendOffset) { + const char* deviceID, int sendEveryX) + : dataPublisher(baseLogger, sendEveryX) { setToken(authentificationToken); _baseLogger->setSamplingFeatureUUID(deviceID); MS_DBG(F("dataPublisher object created")); } UbidotsPublisher::UbidotsPublisher(Logger& baseLogger, Client* inClient, const char* authentificationToken, - const char* deviceID, uint8_t sendEveryX, - uint8_t sendOffset) - : dataPublisher(baseLogger, inClient, sendEveryX, sendOffset) { + const char* deviceID, int sendEveryX) + : dataPublisher(baseLogger, inClient, sendEveryX) { setToken(authentificationToken); _baseLogger->setSamplingFeatureUUID(deviceID); MS_DBG(F("dataPublisher object created")); diff --git a/src/publishers/UbidotsPublisher.h b/src/publishers/UbidotsPublisher.h index 1562890c6..94853c79a 100644 --- a/src/publishers/UbidotsPublisher.h +++ b/src/publishers/UbidotsPublisher.h @@ -50,11 +50,8 @@ class UbidotsPublisher : public dataPublisher { * logger. * * @param baseLogger The logger supplying the data to be published - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! * * @note It is possible (though very unlikey) that using this constructor * could cause errors if the compiler attempts to initialize the publisher @@ -62,8 +59,7 @@ class UbidotsPublisher : public dataPublisher { * issue, use the null constructor and a populated begin(...) within your * set-up function. */ - explicit UbidotsPublisher(Logger& baseLogger, uint8_t sendEveryX = 1, - uint8_t sendOffset = 0); + explicit UbidotsPublisher(Logger& baseLogger, int sendEveryX = 1); /** * @brief Construct a new Ubidots Publisher object * @@ -71,11 +67,8 @@ class UbidotsPublisher : public dataPublisher { * @param inClient An Arduino client instance to use to print data to. * Allows the use of any type of client and multiple clients tied to a * single TinyGSM modem instance - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! * * @note It is possible (though very unlikey) that using this constructor * could cause errors if the compiler attempts to initialize the publisher @@ -83,8 +76,7 @@ class UbidotsPublisher : public dataPublisher { * issue, use the null constructor and a populated begin(...) within your * set-up function. */ - UbidotsPublisher(Logger& baseLogger, Client* inClient, - uint8_t sendEveryX = 1, uint8_t sendOffset = 0); + UbidotsPublisher(Logger& baseLogger, Client* inClient, int sendEveryX = 1); /** * @brief Construct a new Ubidots Publisher object * @@ -95,15 +87,11 @@ class UbidotsPublisher : public dataPublisher { * specific device's setup panel). * @param deviceID The device API Label from Ubidots, derived from the * user-specified device name. - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! */ UbidotsPublisher(Logger& baseLogger, const char* authentificationToken, - const char* deviceID, uint8_t sendEveryX = 1, - uint8_t sendOffset = 0); + const char* deviceID, int sendEveryX = 1); /** * @brief Construct a new Ubidots Publisher object * @@ -117,15 +105,12 @@ class UbidotsPublisher : public dataPublisher { * specific device's setup panel). * @param deviceID The device API Label from Ubidots, derived from the * user-specified device name. - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! */ UbidotsPublisher(Logger& baseLogger, Client* inClient, const char* authentificationToken, const char* deviceID, - uint8_t sendEveryX = 1, uint8_t sendOffset = 0); + int sendEveryX = 1); /** * @brief Destroy the EnviroDIY Publisher object */ From f83a96f1318e86c3f6dd507f627df8c905c42cb5 Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Thu, 16 Mar 2023 14:24:40 -0500 Subject: [PATCH 10/11] publishers: remove hearsay about logger construction order The C++ standard specifies that all objects in the same translation unit (i.e. source file) are constructed in order of declaration. Since this is the most common case when using Modular Sensors, the described case cannot occur. --- src/dataPublisherBase.h | 28 ++-------------------------- src/publishers/DreamHostPublisher.h | 12 ------------ src/publishers/EnviroDIYPublisher.h | 12 ------------ src/publishers/ThingSpeakPublisher.h | 12 ------------ src/publishers/UbidotsPublisher.h | 12 ------------ 5 files changed, 2 insertions(+), 74 deletions(-) diff --git a/src/dataPublisherBase.h b/src/dataPublisherBase.h index 1f24430f9..bedaa1cf7 100644 --- a/src/dataPublisherBase.h +++ b/src/dataPublisherBase.h @@ -87,12 +87,6 @@ class dataPublisher { * @param baseLogger The logger supplying the data to be published * @param sendEveryX Interval (in units of the logging interval) between * attempted data transmissions. Not respected by all publishers. - * - * @note It is possible (though very unlikey) that using this constructor - * could cause errors if the compiler attempts to initialize the publisher - * instance before the logger instance. If you suspect you are seeing that - * issue, use the null constructor and a populated begin(...) within your - * set-up function. */ explicit dataPublisher(Logger& baseLogger, int sendEveryX = 1); /** @@ -104,12 +98,6 @@ class dataPublisher { * single TinyGSM modem instance * @param sendEveryX Interval (in units of the logging interval) between * attempted data transmissions. Not respected by all publishers. - * - * @note It is possible (though very unlikey) that using this constructor - * could cause errors if the compiler attempts to initialize the publisher - * instance before the logger instance. If you suspect you are seeing that - * issue, use the null constructor and a populated begin(...) within your - * set-up function. */ dataPublisher(Logger& baseLogger, Client* inClient, int sendEveryX = 1); /** @@ -148,13 +136,7 @@ class dataPublisher { * @brief Begin the publisher - linking it to the client and logger. * * This can be used as an alternative to adding the logger and client in the - * constructor. This is slightly "safer" because we expect the publishers - * to be created in the "global scope" and we cannot control the order in - * which objects in that global scope will be created. That is, we cannot - * guarantee that the logger will actually be created before the publisher - * that wants to attach to it unless we wait to attach the publisher until - * in the setup or loop function of the main program. In reality, it is - * very unlikely that this is necessary. + * constructor. * * @param baseLogger The logger supplying the data to be published * @param inClient An Arduino client instance to use to print data to. @@ -172,13 +154,7 @@ class dataPublisher { * logger. * * This can be used as an alternative to adding the logger and client in the - * constructor. This is slightly "safer" because we expect the publishers - * to be created in the "global scope" and we cannot control the order in - * which objects in that global scope will be created. That is, we cannot - * guarantee that the logger will actually be created before the publisher - * that wants to attach to it unless we wait to attach the publisher until - * in the setup or loop function of the main program. In reality, it is - * very unlikely that this is necessary. + * constructor. * * @param baseLogger The logger supplying the data to be published */ diff --git a/src/publishers/DreamHostPublisher.h b/src/publishers/DreamHostPublisher.h index e7a8a6fb6..64a465be6 100644 --- a/src/publishers/DreamHostPublisher.h +++ b/src/publishers/DreamHostPublisher.h @@ -53,12 +53,6 @@ class DreamHostPublisher : public dataPublisher { * @param baseLogger The logger supplying the data to be published * @param sendEveryX Interval (in units of the logging interval) between * attempted data transmissions. NOTE: not implemented by this publisher! - * - * @note It is possible (though very unlikey) that using this constructor - * could cause errors if the compiler attempts to initialize the publisher - * instance before the logger instance. If you suspect you are seeing that - * issue, use the null constructor and a populated begin(...) within your - * set-up function. */ explicit DreamHostPublisher(Logger& baseLogger, int sendEveryX = 1); /** @@ -70,12 +64,6 @@ class DreamHostPublisher : public dataPublisher { * single TinyGSM modem instance * @param sendEveryX Interval (in units of the logging interval) between * attempted data transmissions. NOTE: not implemented by this publisher! - * - * @note It is possible (though very unlikey) that using this constructor - * could cause errors if the compiler attempts to initialize the publisher - * instance before the logger instance. If you suspect you are seeing that - * issue, use the null constructor and a populated begin(...) within your - * set-up function. */ DreamHostPublisher(Logger& baseLogger, Client* inClient, int sendEveryX = 1); diff --git a/src/publishers/EnviroDIYPublisher.h b/src/publishers/EnviroDIYPublisher.h index 9a37df180..742681dc6 100644 --- a/src/publishers/EnviroDIYPublisher.h +++ b/src/publishers/EnviroDIYPublisher.h @@ -53,12 +53,6 @@ class EnviroDIYPublisher : public dataPublisher { * @param baseLogger The logger supplying the data to be published * @param sendEveryX Interval (in units of the logging interval) between * attempted data transmissions. NOTE: not implemented by this publisher! - * - * @note It is possible (though very unlikey) that using this constructor - * could cause errors if the compiler attempts to initialize the publisher - * instance before the logger instance. If you suspect you are seeing that - * issue, use the null constructor and a populated begin(...) within your - * set-up function. */ explicit EnviroDIYPublisher(Logger& baseLogger, int sendEveryX = 1); /** @@ -70,12 +64,6 @@ class EnviroDIYPublisher : public dataPublisher { * single TinyGSM modem instance * @param sendEveryX Interval (in units of the logging interval) between * attempted data transmissions. NOTE: not implemented by this publisher! - * - * @note It is possible (though very unlikey) that using this constructor - * could cause errors if the compiler attempts to initialize the publisher - * instance before the logger instance. If you suspect you are seeing that - * issue, use the null constructor and a populated begin(...) within your - * set-up function. */ EnviroDIYPublisher(Logger& baseLogger, Client* inClient, int sendEveryX = 1); diff --git a/src/publishers/ThingSpeakPublisher.h b/src/publishers/ThingSpeakPublisher.h index 857efa42b..b0dec9cf1 100644 --- a/src/publishers/ThingSpeakPublisher.h +++ b/src/publishers/ThingSpeakPublisher.h @@ -78,12 +78,6 @@ class ThingSpeakPublisher : public dataPublisher { * @param baseLogger The logger supplying the data to be published * @param sendEveryX Interval (in units of the logging interval) between * attempted data transmissions. NOTE: not implemented by this publisher! - * - * @note It is possible (though very unlikey) that using this constructor - * could cause errors if the compiler attempts to initialize the publisher - * instance before the logger instance. If you suspect you are seeing that - * issue, use the null constructor and a populated begin(...) within your - * set-up function. */ explicit ThingSpeakPublisher(Logger& baseLogger, int sendEveryX = 1); /** @@ -95,12 +89,6 @@ class ThingSpeakPublisher : public dataPublisher { * single TinyGSM modem instance * @param sendEveryX Interval (in units of the logging interval) between * attempted data transmissions. NOTE: not implemented by this publisher! - * - * @note It is possible (though very unlikey) that using this constructor - * could cause errors if the compiler attempts to initialize the publisher - * instance before the logger instance. If you suspect you are seeing that - * issue, use the null constructor and a populated begin(...) within your - * set-up function. */ ThingSpeakPublisher(Logger& baseLogger, Client* inClient, int sendEveryX = 1); diff --git a/src/publishers/UbidotsPublisher.h b/src/publishers/UbidotsPublisher.h index 94853c79a..6f4a7f328 100644 --- a/src/publishers/UbidotsPublisher.h +++ b/src/publishers/UbidotsPublisher.h @@ -52,12 +52,6 @@ class UbidotsPublisher : public dataPublisher { * @param baseLogger The logger supplying the data to be published * @param sendEveryX Interval (in units of the logging interval) between * attempted data transmissions. NOTE: not implemented by this publisher! - * - * @note It is possible (though very unlikey) that using this constructor - * could cause errors if the compiler attempts to initialize the publisher - * instance before the logger instance. If you suspect you are seeing that - * issue, use the null constructor and a populated begin(...) within your - * set-up function. */ explicit UbidotsPublisher(Logger& baseLogger, int sendEveryX = 1); /** @@ -69,12 +63,6 @@ class UbidotsPublisher : public dataPublisher { * single TinyGSM modem instance * @param sendEveryX Interval (in units of the logging interval) between * attempted data transmissions. NOTE: not implemented by this publisher! - * - * @note It is possible (though very unlikey) that using this constructor - * could cause errors if the compiler attempts to initialize the publisher - * instance before the logger instance. If you suspect you are seeing that - * issue, use the null constructor and a populated begin(...) within your - * set-up function. */ UbidotsPublisher(Logger& baseLogger, Client* inClient, int sendEveryX = 1); /** From d82635ec4e78dbe0281cb3252b4c5cfe6f0a17f1 Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Thu, 16 Mar 2023 15:13:09 -0500 Subject: [PATCH 11/11] update changelog --- ChangeLog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog.md b/ChangeLog.md index f59567474..310041eaf 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Changed +- **BREAKING** Refactored how the publisher transmit buffer works. This will require adjustment to custom data publishers. ### Added