interface_influxdb.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. #include "defines.h"
  2. #include "interface_influxdb.h"
  3. #include "esp_log.h"
  4. #include <time.h>
  5. #include "ClassLogFile.h"
  6. #include "esp_http_client.h"
  7. #include "time_sntp.h"
  8. static const char *TAG = "INFLUXDB";
  9. /**
  10. * @brief Buffer to store the HTTP response.
  11. *
  12. * This character array is used to store the output of an HTTP response.
  13. * The size of the buffer is defined by the constant MAX_HTTP_OUTPUT_BUFFER.
  14. */
  15. char response_buffer[MAX_HTTP_OUTPUT_BUFFER] = {0};
  16. /**
  17. * @brief HTTP event handler callback function.
  18. *
  19. * This function handles various HTTP client events and logs appropriate messages.
  20. *
  21. * @param evt Pointer to the HTTP client event structure.
  22. * @return esp_err_t ESP_OK on success.
  23. *
  24. * Event types handled:
  25. * - HTTP_EVENT_ERROR: Logs an error message when an HTTP error is encountered.
  26. * - HTTP_EVENT_ON_CONNECTED: Logs a message when the HTTP client successfully connects.
  27. * - HTTP_EVENT_HEADERS_SENT: Logs a message when all request headers are sent.
  28. * - HTTP_EVENT_ON_HEADER: Logs the received header key and value.
  29. * - HTTP_EVENT_ON_DATA: Logs the length of the received data.
  30. * - HTTP_EVENT_ON_FINISH: Logs a message when the HTTP client finishes the request.
  31. * - HTTP_EVENT_DISCONNECTED: Logs a message when the HTTP client disconnects.
  32. * - HTTP_EVENT_REDIRECT: Logs a message when an HTTP redirect occurs.
  33. */
  34. static esp_err_t http_event_handler(esp_http_client_event_t *evt)
  35. {
  36. switch (evt->event_id)
  37. {
  38. case HTTP_EVENT_ERROR:
  39. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "HTTP Client Error encountered");
  40. break;
  41. case HTTP_EVENT_ON_CONNECTED:
  42. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "HTTP Client connected");
  43. ESP_LOGI(TAG, "HTTP Client Connected");
  44. break;
  45. case HTTP_EVENT_HEADERS_SENT:
  46. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "HTTP Client sent all request headers");
  47. break;
  48. case HTTP_EVENT_ON_HEADER:
  49. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Header: key=" + std::string(evt->header_key) + ", value=" + std::string(evt->header_value));
  50. break;
  51. case HTTP_EVENT_ON_DATA:
  52. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "HTTP Client data recevied: len=" + std::to_string(evt->data_len));
  53. break;
  54. case HTTP_EVENT_ON_FINISH:
  55. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "HTTP Client finished");
  56. break;
  57. case HTTP_EVENT_DISCONNECTED:
  58. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "HTTP Client Disconnected");
  59. break;
  60. case HTTP_EVENT_REDIRECT:
  61. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "HTTP Redirect");
  62. break;
  63. }
  64. return ESP_OK;
  65. }
  66. /**
  67. * @brief Initializes the InfluxDB connection with version 1 settings.
  68. *
  69. * This function sets up the connection parameters for InfluxDB version 1.
  70. *
  71. * @param _influxDBURI The URI of the InfluxDB server.
  72. * @param _database The name of the database to connect to.
  73. * @param _user The username for authentication.
  74. * @param _password The password for authentication.
  75. */
  76. void InfluxDB::InfluxDBInitV1(std::string _influxDBURI, std::string _database, std::string _user, std::string _password)
  77. {
  78. version = INFLUXDB_V1;
  79. influxDBURI = _influxDBURI;
  80. database = _database;
  81. user = _user;
  82. password = _password;
  83. }
  84. /**
  85. * @brief Initializes the InfluxDB client with version 2 settings.
  86. *
  87. * This function sets up the InfluxDB client to use InfluxDB version 2 by
  88. * configuring the URI, bucket, organization, and token.
  89. *
  90. * @param _influxDBURI The URI of the InfluxDB server.
  91. * @param _bucket The bucket name to store data in.
  92. * @param _org The organization name associated with the bucket.
  93. * @param _token The authentication token for accessing the InfluxDB server.
  94. */
  95. void InfluxDB::InfluxDBInitV2(std::string _influxDBURI, std::string _bucket, std::string _org, std::string _token)
  96. {
  97. version = INFLUXDB_V2;
  98. influxDBURI = _influxDBURI;
  99. bucket = _bucket;
  100. org = _org;
  101. token = _token;
  102. }
  103. /**
  104. * @brief Establishes an HTTP connection to the InfluxDB server.
  105. *
  106. * This function configures and initializes an HTTP client to connect to the InfluxDB server.
  107. * It sets up the necessary parameters such as the URL, event handler, buffer size, and user data.
  108. * Depending on the InfluxDB version, it also configures the authentication type and credentials.
  109. *
  110. * @note This function destroys any existing HTTP client before initializing a new one.
  111. *
  112. * @param None
  113. * @return None
  114. */
  115. void InfluxDB::connectHTTP()
  116. {
  117. esp_http_client_config_t config = {};
  118. config.url = influxDBURI.c_str();
  119. config.event_handler = http_event_handler;
  120. config.buffer_size = MAX_HTTP_OUTPUT_BUFFER;
  121. config.user_data = response_buffer;
  122. switch (version)
  123. {
  124. case INFLUXDB_V1:
  125. config.auth_type = HTTP_AUTH_TYPE_BASIC;
  126. config.username = user.c_str();
  127. config.password = password.c_str();
  128. break;
  129. case INFLUXDB_V2:
  130. break;
  131. }
  132. InfluxDBdestroy();
  133. httpClient = esp_http_client_init(&config);
  134. if (!httpClient)
  135. {
  136. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to initialize HTTP client");
  137. }
  138. else
  139. {
  140. LogFile.WriteToFile(ESP_LOG_INFO, TAG, "HTTP client initialized successfully");
  141. }
  142. }
  143. /**
  144. * @brief Destroys the InfluxDB instance by cleaning up the HTTP client.
  145. *
  146. * This function checks if the HTTP client is initialized. If it is, it cleans up the HTTP client
  147. * and logs the cleanup action. The HTTP client pointer is then set to NULL.
  148. */
  149. void InfluxDB::InfluxDBdestroy()
  150. {
  151. if (httpClient)
  152. {
  153. esp_http_client_cleanup(httpClient);
  154. LogFile.WriteToFile(ESP_LOG_INFO, TAG, "HTTP client cleaned up");
  155. httpClient = NULL;
  156. }
  157. }
  158. /**
  159. * @brief Publishes data to an InfluxDB instance.
  160. *
  161. * This function sends a measurement, key, and content to an InfluxDB server.
  162. * It supports both InfluxDB v1 and v2 APIs.
  163. *
  164. * @param _measurement The measurement name to publish.
  165. * @param _key The key associated with the measurement.
  166. * @param _content The content or value to publish.
  167. * @param _timeUTC The timestamp in UTC. If greater than 0, it will be included in the payload.
  168. *
  169. * The function logs the process and handles HTTP communication with the InfluxDB server.
  170. * It constructs the appropriate API URI based on the InfluxDB version and sends the data
  171. * using an HTTP POST request.
  172. */
  173. void InfluxDB::InfluxDBPublish(std::string _measurement, std::string _key, std::string _content, long int _timeUTC)
  174. {
  175. std::string apiURI;
  176. std::string payload;
  177. char nowTimestamp[21];
  178. connectHTTP();
  179. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "InfluxDBPublish - Key: " + _key + ", Content: " + _content + ", timeUTC: " + std::to_string(_timeUTC));
  180. if (_timeUTC > 0)
  181. {
  182. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Timestamp (UTC): " + std::to_string(_timeUTC));
  183. sprintf(nowTimestamp, "%ld000000000", _timeUTC); // UTC
  184. payload = _measurement + " " + _key + "=" + _content + " " + nowTimestamp;
  185. }
  186. else
  187. {
  188. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "no timestamp given");
  189. payload = _measurement + " " + _key + "=" + _content;
  190. }
  191. payload.shrink_to_fit();
  192. LogFile.WriteToFile(ESP_LOG_INFO, TAG, "sending line to influxdb:" + payload);
  193. esp_err_t err;
  194. switch (version)
  195. {
  196. case INFLUXDB_V1:
  197. apiURI = influxDBURI + "/write?db=" + database;
  198. apiURI.shrink_to_fit();
  199. esp_http_client_set_url(httpClient, apiURI.c_str());
  200. esp_http_client_set_method(httpClient, HTTP_METHOD_POST);
  201. esp_http_client_set_header(httpClient, "Content-Type", "text/plain");
  202. esp_http_client_set_post_field(httpClient, payload.c_str(), payload.length());
  203. err = esp_http_client_perform(httpClient);
  204. if (err == ESP_OK)
  205. {
  206. LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Data published successfully: " + payload);
  207. }
  208. else
  209. {
  210. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to publish data: " + std::string(esp_err_to_name(err)));
  211. }
  212. break;
  213. case INFLUXDB_V2:
  214. apiURI = influxDBURI + "/api/v2/write?org=" + org + "&bucket=" + bucket;
  215. apiURI.shrink_to_fit();
  216. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "apiURI: " + apiURI);
  217. esp_http_client_set_url(httpClient, apiURI.c_str());
  218. esp_http_client_set_method(httpClient, HTTP_METHOD_POST);
  219. esp_http_client_set_header(httpClient, "Content-Type", "text/plain");
  220. std::string _zw = "Token " + token;
  221. esp_http_client_set_header(httpClient, "Authorization", _zw.c_str());
  222. esp_http_client_set_post_field(httpClient, payload.c_str(), payload.length());
  223. err = ESP_ERROR_CHECK_WITHOUT_ABORT(esp_http_client_perform(httpClient));
  224. if (err == ESP_OK)
  225. {
  226. LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Data published successfully: " + payload);
  227. }
  228. else
  229. {
  230. LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Failed to publish data: " + std::string(esp_err_to_name(err)));
  231. }
  232. break;
  233. }
  234. }