diff --git a/influxdb-lib/ESP8266Influxdb.cpp b/influxdb-lib/ESP8266Influxdb.cpp new file mode 100644 index 0000000..caf16bc --- /dev/null +++ b/influxdb-lib/ESP8266Influxdb.cpp @@ -0,0 +1,176 @@ +#include "Arduino.h" +#include "ESP8266Influxdb.h" +#include + +#define DEBUG_PRINT // comment this line to disable debug print + +#ifndef DEBUG_PRINT +#define DEBUG_PRINT(a) +#else +#define DEBUG_PRINT(a) (Serial.println(String(F("[Debug]: "))+(a))) +#define _DEBUG +#endif + +Influxdb::Influxdb(const char *host, uint16_t port) : WiFiClient() { + _port = port; + _host = host; +} + +DB_RESPONSE Influxdb::opendb(String db, String user, String password) { + _db = "db=" + db + "&u=" + user + "&p=" + password; +} + +DB_RESPONSE Influxdb::opendb(String db) { + _db = "db=" + db; + +} + +DB_RESPONSE Influxdb::write(FIELD data) { + return write(data.postString()); +} + +DB_RESPONSE Influxdb::write(String data) { + if (!connect(_host, _port)) { + DEBUG_PRINT("connection failed"); + _response = DB_CONNECT_FAILED; + return _response; + } + String postHead = "POST /write?" + _db + " HTTP/1.1\r\n"; + postHead += "Host: " + String(_host) + ":" + String(_port) + "\r\n"; + // postHead += "Content-Type: application/x-www-form-urlencoded\r\n"; + postHead += "Content-Length: " + String(data.length()) + "\r\n\r\n"; + + DEBUG_PRINT("Writing data to " + String(_host) + ":" + String(_port)); + print(postHead + data); + DEBUG_PRINT(postHead + data); + + uint8_t t = 0; + // Check the reply whether writing is success or not + while (!available() && t < 200) { + delay(10); + t++; + } + if (t==200) {_response = DB_ERROR; return DB_ERROR; } // Return error if time out. + +#if !defined _DEBUG + if (available()) { + _response = (findUntil("204", "\r")) ? DB_SUCCESS : DB_ERROR; + return _response; + } +#else + _response=DB_ERROR; + while (available()) { + String line = readStringUntil('\n'); + if (line.substring(9,12)=="204") + _response = DB_SUCCESS; + DEBUG_PRINT("(Responsed): " + line); + } + return _response; +#endif + return DB_ERROR; +} + +DB_RESPONSE Influxdb::query(String sql) { + + if (!connect(_host, _port)) { + DEBUG_PRINT("connection failed"); + _response = DB_CONNECT_FAILED; + return _response; + } + + String url = "/query?"; +#if defined _DEBUG + url += "pretty=true&"; +#endif + url += _db; + url += "&q=" + URLEncode(sql); + DEBUG_PRINT("Requesting URL: "); + DEBUG_PRINT(url); + + // This will send the request to the server + print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + _host + + ":" + _port + "\r\n" + "Connection: close\r\n\r\n"); + + // Read all the lines of the reply from server and print them to Serial + uint8_t t = 0; + while (!available() && t < 200) { + delay(10); + t++; + } + if (t==200) {_response = DB_ERROR; return DB_ERROR; } // Return error if time out. + + DEBUG_PRINT("Receiving...."); + uint8_t i=0; + String line = readStringUntil('\n'); + DEBUG_PRINT("[HEAD] " + line); + + if (line.substring(9,12) == "200") { + while (available()) { + line = readStringUntil('\n'); + DEBUG_PRINT("(HEAD) " + line); + if (i < 6 ) i++; else return _response; + } + _response = DB_SUCCESS; + } + else{ + _response = DB_ERROR; +#if defined _DEBUG + while (available()) { + line = readStringUntil('\n'); + DEBUG_PRINT("[HEAD] " + line); + } +#endif + } + + return _response; +} + +DB_RESPONSE Influxdb::response() { + return _response; +} + +/* -----------------------------------------------*/ +// Field object +/* -----------------------------------------------*/ +FIELD::FIELD(String m) { + measurement = m; +} + +void FIELD::empty() { + _data = ""; + _tag = ""; +} + +void FIELD::addTag(String key, String value) { + _tag += "," + key + "=" + value; +} + +void FIELD::addField(String key, float value) { + _data = (_data == "") ? (" ") : (_data += ","); + _data += key + "=" + String(value); +} + +String FIELD::postString() { + // uint32_t utc = 1448114561 + millis() /1000; + return measurement + _tag + _data; +} + +// URL Encode with Arduino String object +String URLEncode(String msg) { + const char *hex = "0123456789abcdef"; + String encodedMsg = ""; + + uint16_t i; + for (i = 0; i < msg.length(); i++) { + if (('a' <= msg.charAt(i) && msg.charAt(i) <= 'z') || + ('A' <= msg.charAt(i) && msg.charAt(i) <= 'Z') || + ('0' <= msg.charAt(i) && msg.charAt(i) <= '9')) { + encodedMsg += msg.charAt(i); + } else { + encodedMsg += '%'; + encodedMsg += hex[msg.charAt(i) >> 4]; + encodedMsg += hex[msg.charAt(i) & 15]; + } + } + return encodedMsg; +} diff --git a/influxdb-lib/ESP8266Influxdb.h b/influxdb-lib/ESP8266Influxdb.h new file mode 100644 index 0000000..4b0f78e --- /dev/null +++ b/influxdb-lib/ESP8266Influxdb.h @@ -0,0 +1,72 @@ +/* Influxdb library + + MIT license + Written by HW Wong + */ + +#ifndef INFLUXDB_H +#define INFLUXDB_H +#include "Arduino.h" +#include + +enum DB_RESPONSE {DB_SUCCESS, DB_ERROR, DB_CONNECT_FAILED}; + +// Url encode function +String URLEncode(String msg); + +class FIELD +{ +public: + FIELD(String m); + + String measurement; + + void addField(String key, float value); + void addTag(String key, String value); + void empty(); + String postString(); + +private: + String _data; + String _tag; + +}; + +class Influxdb : private WiFiClient +{ +public: + Influxdb(const char* host, uint16_t port); + + DB_RESPONSE opendb(String db); + DB_RESPONSE opendb(String db, String user, String password); + DB_RESPONSE write(FIELD data); + DB_RESPONSE write(String data); + DB_RESPONSE query(String sql); + //uint8_t createDatabase(char *dbname); + DB_RESPONSE response(); + + using WiFiClient::available; + using WiFiClient::read; + using WiFiClient::flush; + using WiFiClient::find; + using WiFiClient::findUntil; + using WiFiClient::peek; + using WiFiClient::readBytes; + using WiFiClient::readBytesUntil; + using WiFiClient::readString; + using WiFiClient::readStringUntil; + using WiFiClient::parseInt; + using WiFiClient::setTimeout; + +private: + uint16_t _port; + const char* _host; + String _db; + DB_RESPONSE _response; + +}; + + + + +#endif diff --git a/influxdb-lib/README.md b/influxdb-lib/README.md new file mode 100644 index 0000000..99ad2ec --- /dev/null +++ b/influxdb-lib/README.md @@ -0,0 +1 @@ +# ESP8266Influxdb diff --git a/influxdb-lib/examples/influxdb_write/influxdb_write.ino b/influxdb-lib/examples/influxdb_write/influxdb_write.ino new file mode 100644 index 0000000..c89fc0b --- /dev/null +++ b/influxdb-lib/examples/influxdb_write/influxdb_write.ino @@ -0,0 +1,63 @@ + +#include +#include +#include +#include + +const char *INFLUXDB_HOST = "host_or_ip"; +const uint16_t INFLUXDB_PORT = 8086; + +const char *DATABASE = "dbname"; +const char *DB_USER = "dbuser"; +const char *DB_PASSWORD = "dbpassword"; + +ESP8266WiFiMulti WiFiMulti; +Influxdb influxdb(INFLUXDB_HOST, INFLUXDB_PORT); + +void setup() { + Serial.begin(115200); + WiFiMulti.addAP("SSID", "PASSWORD"); + while (WiFiMulti.run() != WL_CONNECTED) { + delay(100); + } + Serial.println("Ready"); + influxdb.opendb(DATABASE, DB_USER, DB_PASSWORD); +} + +void loop() { + // Writing data with influxdb HTTP API + // https://influxdb.com/docs/v0.9/guides/writing_data.html + Serial.println("Writing data to host " + String(INFLUXDB_HOST) + ":" + + INFLUXDB_PORT + "'s database=" + DATABASE); + String data = "analog_read,method=HTTP_API,pin=A0 value=" + String(analogRead(A0)); + influxdb.write(data); + Serial.println(influxdb.response() == DB_SUCCESS ? "HTTP write success" + : "Writing failed"); + + // Writing data using FIELD object + // Create field object with measurment name=analog_read + FIELD dataObj("analog_read"); + dataObj.addTag("method", "Field_object"); // Add method tag + dataObj.addTag("pin", "A0"); // Add pin tag + dataObj.addField("value", analogRead(A0)); // Add value field + Serial.println(influxdb.write(dataObj) == DB_SUCCESS ? "Object write success" + : "Writing failed"); + + // Empty field object. + dataObj.empty(); + + // Querying Data + // https://influxdb.com/docs/v0.9/query_language/query_syntax.html + Serial.println("Querying data ........"); + + String sql = "select * from analog_read order by time desc limit 2"; + if (influxdb.query(sql) == DB_SUCCESS) { + while (influxdb.available()) { + String line = influxdb.readStringUntil('\n'); + Serial.println(line); + } + } + else + Serial.println("Query Failed"); + delay(30000); +} diff --git a/influxdb-lib/keywords.txt b/influxdb-lib/keywords.txt new file mode 100644 index 0000000..6b493f8 --- /dev/null +++ b/influxdb-lib/keywords.txt @@ -0,0 +1,24 @@ +################################################## +# Syntax Coloring Map For ESP8266 Influxdb library +################################################## + +################################################## +# Datatypes (KEYWORD1) +################################################## + +Influxdb KEYWORD1 +FIELD KEYWORD1 +DB_RESPOND KEYWORD1 + +################################################## +# Methods and Functions (KEYWORD2) +################################################## + +addField KEYWORD2 +addTag KEYWORD2 +empty KEYWORD2 +opendb KEYWORD2 +write KEYWORD2 +query KEYWORD2 +postString KEYWORD2 +response KEYWORD2