Home › Forums › Mayfly Data Logger › Connecting SIM7080 to New Thingspeak › Reply To: Connecting SIM7080 to New Thingspeak
2022-01-07 at 5:11 PM
#16245
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
/** * @file ThingSpeakPublisher.cpp * @copyright 2020 Stroud Water Research Center * Part of the EnviroDIY ModularSensors library for Arduino * @author Sara Geleskie Damiano <sdamiano@stroudcenter.org> * * @brief Implements the ThingSpeakPublisher class. */ #include "ThingSpeakPublisher.h" // ============================================================================ // Functions for the EnviroDIY data portal receivers. // ============================================================================ // Constant values for MQTT publish // I want to refer to these more than once while ensuring there is only one copy // in memory const char* ThingSpeakPublisher::mqttServer = "mqtt3.thingspeak.com"; const int ThingSpeakPublisher::mqttPort = 1883; const char* ThingSpeakPublisher::mqttClientID = THING_SPEAK_CLIENT_ID; const char* ThingSpeakPublisher::mqttUser = THING_SPEAK_USER_NAME; const char* ThingSpeakPublisher::mqttPass = THING_SPEAK_PASS_WORD; // Constructors ThingSpeakPublisher::ThingSpeakPublisher() : dataPublisher() { // MS_DBG(F("ThingSpeakPublisher object created")); _thingSpeakChannelID = NULL; _thingSpeakUsername = NULL; _thingSpeakPassword = NULL; _thingSpeakClientID = NULL; } ThingSpeakPublisher::ThingSpeakPublisher(Logger& baseLogger, uint8_t sendEveryX, uint8_t sendOffset) : dataPublisher(baseLogger, sendEveryX, sendOffset) { // MS_DBG(F("ThingSpeakPublisher object created")); _thingSpeakChannelID = NULL; _thingSpeakUsername = NULL; _thingSpeakPassword = NULL; _thingSpeakClientID = NULL; } ThingSpeakPublisher::ThingSpeakPublisher(Logger& baseLogger, Client* inClient, uint8_t sendEveryX, uint8_t sendOffset) : dataPublisher(baseLogger, inClient, sendEveryX, sendOffset) { // MS_DBG(F("ThingSpeakPublisher object created")); _thingSpeakChannelID = NULL; _thingSpeakUsername = NULL; _thingSpeakPassword = NULL; _thingSpeakClientID = NULL; } ThingSpeakPublisher::ThingSpeakPublisher(Logger& baseLogger, const char* thingSpeakChannelID, const char* thingSpeakUsername, const char* thingSpeakPassword, const char* thingSpeakClientID, uint8_t sendEveryX, uint8_t sendOffset) : dataPublisher(baseLogger, sendEveryX, sendOffset) { setChannelID(thingSpeakChannelID); setUsername(thingSpeakUsername); setPassword(thingSpeakPassword); setClientID(thingSpeakClientID); // MS_DBG(F("ThingSpeakPublisher object created")); } ThingSpeakPublisher::ThingSpeakPublisher(Logger& baseLogger, Client* inClient, const char* thingSpeakChannelID, const char* thingSpeakUsername, const char* thingSpeakPassword, const char* thingSpeakClientID, uint8_t sendEveryX, uint8_t sendOffset) : dataPublisher(baseLogger, inClient, sendEveryX, sendOffset) { setChannelID(thingSpeakChannelID); setUsername(thingSpeakUsername); setPassword(thingSpeakPassword); setClientID(thingSpeakClientID); // MS_DBG(F("ThingSpeakPublisher object created")); } // Destructor ThingSpeakPublisher::~ThingSpeakPublisher() {} void ThingSpeakPublisher::setChannelID(const char* thingSpeakChannelID) { _thingSpeakChannelID = thingSpeakChannelID; // MS_DBG(F("Channel ID set!")); } void ThingSpeakPublisher::setUsername(const char* thingSpeakUsername) { _thingSpeakUsername = thingSpeakUsername; // MS_DBG(F("Username set!")); } void ThingSpeakPublisher::setPassword(const char* thingSpeakPassword) { _thingSpeakPassword = thingSpeakPassword; // MS_DBG(F("Password set!")); } void ThingSpeakPublisher::setClientID(const char* thingSpeakClientID) { _thingSpeakClientID = thingSpeakClientID; // MS_DBG(F("Client ID set!")); } // Sets all 3 ThingSpeak parameters void ThingSpeakPublisher::setThingSpeakParams(const char* channelID, const char* Username, const char* Password, const char* ClientID) { setChannelID(channelID); setUsername(Username); setPassword(Password); setClientID(ClientID); } // A way to begin with everything already set void ThingSpeakPublisher::begin(Logger& baseLogger, Client* inClient, const char* thingSpeakChannelID, const char* thingSpeakUsername, const char* thingSpeakPassword, const char* thingSpeakClientID ) { setChannelID(thingSpeakChannelID); setUsername(thingSpeakUsername); setPassword(thingSpeakPassword); setClientID(thingSpeakClientID); dataPublisher::begin(baseLogger, inClient); } void ThingSpeakPublisher::begin(Logger& baseLogger, const char* thingSpeakChannelID, const char* thingSpeakUsername, const char* thingSpeakPassword, const char* thingSpeakClientID ) { setChannelID(thingSpeakChannelID); setUsername(thingSpeakUsername); setPassword(thingSpeakPassword); setClientID(thingSpeakClientID); dataPublisher::begin(baseLogger); } // This sends the data to ThingSpeak // bool ThingSpeakPublisher::mqttThingSpeak(void) int16_t ThingSpeakPublisher::publishData(Client* outClient) { bool retVal = false; // Make sure we don't have too many fields // A channel can have a max of 8 fields if (_baseLogger->getArrayVarCount() > 8) { MS_DBG(F("No more than 8 fields of data can be sent to a single " "ThingSpeak channel!")); MS_DBG(F("Only the first 8 fields worth of data will be sent.")); } uint8_t numChannels = min(_baseLogger->getArrayVarCount(), 8); MS_DBG(numChannels, F("fields will be sent to ThingSpeak")); // Create a buffer for the portions of the request and response char tempBuffer[26] = ""; char topicBuffer[25] = "channels/"; //was 42 strcat(topicBuffer, _thingSpeakChannelID); strcat(topicBuffer, "/publish"); //MS_DBG(F("Topic ["), strlen(topicBuffer), F("]:"), String(topicBuffer)); emptyTxBuffer(); _baseLogger->formatDateTime_ISO8601(Logger::markedEpochTime) .toCharArray(tempBuffer, 26); strcat(txBuffer, "#P"); strcat(txBuffer, "created_at="); strcat(txBuffer, tempBuffer); txBuffer[strlen(txBuffer)] = '&'; for (uint8_t i = 0; i < numChannels; i++) { strcat(txBuffer, "field"); itoa(i + 1, tempBuffer, 10); // BASE 10 strcat(txBuffer, tempBuffer); txBuffer[strlen(txBuffer)] = '='; _baseLogger->getValueStringAtI(i).toCharArray(tempBuffer, 26); strcat(txBuffer, tempBuffer); if (i + 1 != numChannels) { txBuffer[strlen(txBuffer)] = '&'; } } //strcat(txBuffer, "&status=MQTTPUBLISH"); MS_DBG(F("Message ["), strlen(txBuffer), F("]:"), String(txBuffer)); // Set the client connection parameters _mqttClient.setClient(*outClient); _mqttClient.setServer(mqttServer, mqttPort); // Make sure any previous TCP connections are closed // NOTE: The PubSubClient library used for MQTT connect assumes that as // long as the client is connected, it must be connected to the right place. // Closing any stray client sockets here ensures that a new client socket // is opened to the right place. // client is connected when a different socket is open if (outClient->connected()) { outClient->stop(); } // Make the MQTT connection // Note: the client id and the user name do not mean anything for // ThingSpeak MS_DBG(F("Opening MQTT Connection")); MS_START_DEBUG_TIMER; if (_mqttClient.connect(_thingSpeakClientID, _thingSpeakUsername, _thingSpeakPassword)) { MS_DBG(F("MQTT connected after"), MS_PRINT_DEBUG_TIMER, F("ms")); if (_mqttClient.publish(topicBuffer, txBuffer)) { PRINTOUT(F("ThingSpeak topic published! Current state:"), parseMQTTState(_mqttClient.state())); retVal = true; } else { PRINTOUT(F("MQTT publish failed with state:"), parseMQTTState(_mqttClient.state())); retVal = false; } } else { PRINTOUT(F("MQTT connection failed with state:"), parseMQTTState(_mqttClient.state())); delay(1000); retVal = false; } // Disconnect from MQTT MS_DBG(F("Disconnecting from MQTT")); MS_RESET_DEBUG_TIMER _mqttClient.disconnect(); MS_DBG(F("Disconnected after"), MS_PRINT_DEBUG_TIMER, F("ms")); return retVal; } |
^^ Here’s the edited cpp for the publisher
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
/** * @file ThingSpeakPublisher.h * @copyright 2020 Stroud Water Research Center * Part of the EnviroDIY ModularSensors library for Arduino * @author Sara Geleskie Damiano <sdamiano@stroudcenter.org> * * @brief Contains the ThingSpeakPublisher subclass of dataPublisher for * publishing data to ThingSpeak using the MQTT protocol. */ // Header Guards #ifndef SRC_PUBLISHERS_THINGSPEAKPUBLISHER_H_ #define SRC_PUBLISHERS_THINGSPEAKPUBLISHER_H_ // Debugging Statement // #define MS_THINGSPEAKPUBLISHER_DEBUG #ifdef MS_THINGSPEAKPUBLISHER_DEBUG #define MS_DEBUGGING_STD "ThingSpeakPublisher" #endif /** * @brief The MQTT User Name * * @note The user name doesn't actually mean anything for ThingSpeak */ //edited, defines username, password, and client ID #define THING_SPEAK_USER_NAME "" #define THING_SPEAK_PASS_WORD "" #define THING_SPEAK_CLIENT_ID "" //edited for mqtt3 //#define USESECUREMQTT // Included Dependencies #include "ModSensorDebugger.h" #undef MS_DEBUGGING_STD #include "dataPublisherBase.h" #include <PubSubClient.h> // ============================================================================ // Functions for the EnviroDIY data portal receivers. // ============================================================================ /** * @brief The ThingSpeakPublisher subclass of dataPublisher for publishing data * to ThingSpeak using the MQTT protocol. * * When sending data to ThingSpeak the order of the variables in the variable * array attached to your logger is __crucial__. The results from the variables * in the VariableArray will be sent to ThingSpeak in the order they are in the * array; that is, the first variable in the array will be sent as Field1, the * second as Field2, etc. Any UUID's or custom variable codes are ignored for * ThingSpeak. They will only appear in the header of your file on the SD card. * Giving a variable a custom variable code like "Field3" will **NOT** make that * variable field 3 on ThingSpeak. The third variable in the array will always * be "Field3". Any text names you have given to your fields in ThingSpeak are * also irrelevant. * * @ingroup the_publishers */ class ThingSpeakPublisher : public dataPublisher { public: // Constructors /** * @brief Construct a new ThingSpeak Publisher object with no members * initialized. */ ThingSpeakPublisher(); /** * @brief Construct a new ThingSpeak Publisher object * * @note If a client is never specified, the publisher will attempt to * create and use a client on a LoggerModem instance tied to the attached * 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 * * @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, uint8_t sendEveryX = 1, uint8_t sendOffset = 0); /** * @brief Construct a new ThingSpeak Publisher object * * @param baseLogger The logger supplying the data to be published * @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 * * @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, uint8_t sendEveryX = 1, uint8_t sendOffset = 0); /** * @brief Construct a new ThingSpeak Publisher object * * @param baseLogger The logger supplying the data to be published * @param thingSpeakChannelID The numeric channel id 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 */ ThingSpeakPublisher(Logger& baseLogger, const char* thingSpeakChannelID, const char* thingSpeakUsername, const char* thingSpeakPassword, const char* thingSpeakClientID, uint8_t sendEveryX = 1, uint8_t sendOffset = 0); /** * @brief Construct a new ThingSpeak Publisher object * * @param baseLogger The logger supplying the data to be published * @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 thingSpeakChannelID The numeric channel id 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 */ ThingSpeakPublisher(Logger& baseLogger, Client* inClient, const char* thingSpeakChannelID, const char* thingSpeakUsername, const char* thingSpeakPassword, const char* thingSpeakClientID, uint8_t sendEveryX = 1, uint8_t sendOffset = 0); /** * @brief Destroy the ThingSpeak Publisher object */ virtual ~ThingSpeakPublisher(); // Returns the data destination String getEndpoint(void) override { return String(mqttServer); } /** * @brief Set the ThingSpeak channel ID * * @param thingSpeakChannelID The numeric channel id for your channel */ void setChannelID(const char* thingSpeakChannelID); //edited void setUsername(const char* thingSpeakUsername); void setPassword(const char* thingSpeakPassword); void setClientID(const char* thingSpeakClientID); void setThingSpeakParams(const char* channelID, const char* Username, const char* Password, const char* ClientID); // A way to begin with everything already set /** * @copydoc dataPublisher::begin(Logger& baseLogger, Client* inClient) * @param thingSpeakChannelID The numeric channel id for your channel */ void begin(Logger& baseLogger, Client* inClient, const char* thingSpeakChannelID, const char* thingSpeakUsername, const char* thingSpeakPassword, const char* thingSpeakClientID); /** * @copydoc dataPublisher::begin(Logger& baseLogger) * @param thingSpeakChannelID The numeric channel id for your channel */ void begin(Logger& baseLogger, const char* thingSpeakChannelID, const char* thingSpeakUsername, const char* thingSpeakPassword, const char* thingSpeakClientID); // This sends the data to ThingSpeak // bool mqttThingSpeak(void); int16_t publishData(Client* outClient) override; protected: /** * @anchor ts_mqqt_vars * @name Portions of the MQTT data publication * * @{ */ static const char* mqttServer; ///< The MQTT server static const int mqttPort; ///< The MQTT port static const char* mqttClientName; ///< The MQTT client name static const char* mqttChannelID; ///< The MQTT channel ID static const char* mqttUser; ///< The MQTT user name static const char* mqttPass; ///< The MQTT password static const char* mqttClientID; /**@}*/ private: // Keys for ThingSpeak const char* _thingSpeakChannelID; const char* _thingSpeakUsername; const char* _thingSpeakPassword; const char* _thingSpeakClientID; PubSubClient _mqttClient; }; #endif // SRC_PUBLISHERS_THINGSPEAKPUBLISHER_H_ |
^^ Here’s the edited code for the header file.