ESP32 / ESP8266 & BME280 / SHT2x sensor with InfluxDB support
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SimpleInflux.cpp 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /*
  2. * SimpleInflux.cpp
  3. *
  4. * ESP8266 / ESP32 Environmental Sensor
  5. *
  6. * ----------------------------------------------------------------------------
  7. * "THE BEER-WARE LICENSE" (Revision 42):
  8. * <xythobuz@xythobuz.de> wrote this file. As long as you retain this notice
  9. * you can do whatever you want with this stuff. If we meet some day, and you
  10. * think this stuff is worth it, you can buy me a beer in return. Thomas Buck
  11. * ----------------------------------------------------------------------------
  12. */
  13. #include <Arduino.h>
  14. #include "config.h"
  15. #include "DebugLog.h"
  16. #include "SimpleInflux.h"
  17. #ifdef DENABLE_SIMPLE_INFLUX
  18. #if defined(ARDUINO_ARCH_AVR)
  19. #include <WiFiLink.h>
  20. WiFiClient client;
  21. #elif defined(ARDUINO_ARCH_ESP8266)
  22. #include <ESP8266WiFi.h>
  23. #include <ESP8266HTTPClient.h>
  24. #include <WiFiClient.h>
  25. #endif
  26. void InfluxData::addTag(const char *name, const char *value) {
  27. if (tag_count < SIMPLE_INFLUX_MAX_ELEMENTS) {
  28. tag_name[tag_count] = name;
  29. tag_value[tag_count] = value;
  30. tag_count++;
  31. }
  32. }
  33. void InfluxData::addValue(const char *name, double value) {
  34. if (value_count < SIMPLE_INFLUX_MAX_ELEMENTS) {
  35. value_name[value_count] = name;
  36. value_value[value_count] = value;
  37. value_count++;
  38. }
  39. }
  40. // https://docs.influxdata.com/influxdb/v1.8/guides/write_data/
  41. boolean Influxdb::write(InfluxData &data) {
  42. //debug.print(F("Writing "));
  43. //debug.println(data.dataName());
  44. #if defined(ARDUINO_ARCH_AVR)
  45. client.stop();
  46. if (client.connect(db_host, db_port)) {
  47. client.print(F("POST /write?db="));
  48. client.print(db_name);
  49. client.println(F(" HTTP/1.1"));
  50. client.print(F("Host: "));
  51. client.print(db_host);
  52. client.print(F(":"));
  53. client.println(String(db_port));
  54. client.println(F("Connection: close"));
  55. int len = strlen(data.dataName()) + 1;
  56. for (int i = 0; i < data.tagCount(); i++) {
  57. len += strlen(data.tagName(i)) + strlen(data.tagValue(i)) + 2;
  58. }
  59. for (int i = 0; i < data.valueCount(); i++) {
  60. len += strlen(data.valueName(i)) + String(data.valueValue(i)).length() + 1;
  61. if (i > 0) {
  62. len += 1;
  63. }
  64. }
  65. client.print(F("Content-Length: "));
  66. client.println(String(len));
  67. client.println();
  68. client.print(data.dataName());
  69. for (int i = 0; i < data.tagCount(); i++) {
  70. client.print(F(","));
  71. client.print(data.tagName(i));
  72. client.print(F("="));
  73. //client.print(F("\""));
  74. client.print(data.tagValue(i));
  75. //client.print(F("\""));
  76. }
  77. client.print(F(" "));
  78. for (int i = 0; i < data.valueCount(); i++) {
  79. if (i > 0) {
  80. client.print(F(","));
  81. }
  82. client.print(data.valueName(i));
  83. client.print(F("="));
  84. client.print(data.valueValue(i));
  85. }
  86. // we're leaving out the timestamp, it's optional
  87. boolean currentLineIsBlank = true, contains_error = false;
  88. int compare_off = 0;
  89. String compare_to(F("X-Influxdb-Error"));
  90. while (client.connected()) {
  91. if (client.available()) {
  92. char c = client.read();
  93. if (c != '\r') {
  94. debug.write(c);
  95. }
  96. if (compare_off == compare_to.length()) {
  97. contains_error = true;
  98. } else if ((compare_off < compare_to.length()) && (c == compare_to[compare_off])) {
  99. if ((compare_off > 0) || currentLineIsBlank) {
  100. compare_off++;
  101. }
  102. } else {
  103. compare_off = 0;
  104. }
  105. if ((c == '\n') && currentLineIsBlank) {
  106. // http headers ended
  107. break;
  108. }
  109. if (c == '\n') {
  110. // you're starting a new line
  111. currentLineIsBlank = true;
  112. } else if (c != '\r') {
  113. // you've gotten a character on the current line
  114. currentLineIsBlank = false;
  115. }
  116. }
  117. }
  118. client.stop();
  119. debug.println(contains_error ? F("Request failed") : F("Request Done"));
  120. return !contains_error;
  121. } else {
  122. debug.println(F("Error connecting"));
  123. return false; // failed
  124. }
  125. #elif defined(ARDUINO_ARCH_ESP8266)
  126. String content = data.dataName();
  127. for (int i = 0; i < data.tagCount(); i++) {
  128. content += F(",");
  129. content += data.tagName(i);
  130. content += F("=");
  131. //content += F("\"");
  132. content += data.tagValue(i);
  133. //content += F("\"");
  134. }
  135. content += F(" ");
  136. for (int i = 0; i < data.valueCount(); i++) {
  137. if (i > 0) {
  138. content += F(",");
  139. }
  140. content += data.valueName(i);
  141. content += F("=");
  142. content += data.valueValue(i);
  143. }
  144. // we're leaving out the timestamp, it's optional
  145. WiFiClient client;
  146. HTTPClient http;
  147. http.setReuse(false);
  148. http.setTimeout(1500); // ms
  149. String uri("/write?db=");
  150. uri += db_name;
  151. http.begin(client, db_host, db_port, uri, false);
  152. //debug.print(F("Sending to Influx: "));
  153. //debug.println(content);
  154. int httpResponseCode = http.POST(content);
  155. String payload = http.getString();
  156. String compare_to(F("X-Influxdb-Error"));
  157. bool result = false; // error
  158. if ((httpResponseCode >= 200) && (httpResponseCode <= 299)
  159. && (payload.indexOf(compare_to) < 0)) {
  160. result = true; // success
  161. } else {
  162. debug.print(F("Got "));
  163. debug.print(httpResponseCode);
  164. debug.print(F(" response from Influx: "));
  165. debug.println(payload);
  166. }
  167. http.end();
  168. return result;
  169. #elif defined(ARDUINO_ARCH_ESP32)
  170. #error Not implemented for ESP32 yet
  171. #else
  172. return true; // success
  173. #endif
  174. }
  175. #endif