Implement InfluxDB v2 (#2004)

* Implement InfluxDBv2 Innitial

* Update incl. UI

* Correct UI

* Update UI - Indiv. Param.

* Update edit_config_param.html

* Correct Timeshift

* Update Fieldname
This commit is contained in:
jomjol
2023-02-09 20:13:08 +01:00
committed by GitHub
parent 795bcd0d21
commit 1acd72d33e
13 changed files with 578 additions and 40 deletions

View File

@@ -60,6 +60,9 @@ std::string ClassFlowControll::doSingleStep(std::string _stepname, std::string _
if ((_stepname.compare("[InfluxDB]") == 0) || (_stepname.compare(";[InfluxDB]") == 0)){ if ((_stepname.compare("[InfluxDB]") == 0) || (_stepname.compare(";[InfluxDB]") == 0)){
_classname = "ClassFlowInfluxDB"; _classname = "ClassFlowInfluxDB";
} }
if ((_stepname.compare("[InfluxDBv2]") == 0) || (_stepname.compare(";[InfluxDBv2]") == 0)){
_classname = "ClassFlowInfluxDBv2";
}
#endif //ENABLE_INFLUXDB #endif //ENABLE_INFLUXDB
for (int i = 0; i < FlowControll.size(); ++i) for (int i = 0; i < FlowControll.size(); ++i)
@@ -90,6 +93,8 @@ std::string ClassFlowControll::TranslateAktstatus(std::string _input)
#ifdef ENABLE_INFLUXDB #ifdef ENABLE_INFLUXDB
if (_input.compare("ClassFlowInfluxDB") == 0) if (_input.compare("ClassFlowInfluxDB") == 0)
return ("Sending InfluxDB"); return ("Sending InfluxDB");
if (_input.compare("ClassFlowInfluxDBv2") == 0)
return ("Sending InfluxDBv2");
#endif //ENABLE_INFLUXDB #endif //ENABLE_INFLUXDB
if (_input.compare("ClassFlowPostProcessing") == 0) if (_input.compare("ClassFlowPostProcessing") == 0)
return ("Post-Processing"); return ("Post-Processing");
@@ -233,6 +238,8 @@ ClassFlow* ClassFlowControll::CreateClassFlow(std::string _type)
#ifdef ENABLE_INFLUXDB #ifdef ENABLE_INFLUXDB
if (toUpper(_type).compare("[INFLUXDB]") == 0) if (toUpper(_type).compare("[INFLUXDB]") == 0)
cfc = new ClassFlowInfluxDB(&FlowControll); cfc = new ClassFlowInfluxDB(&FlowControll);
if (toUpper(_type).compare("[INFLUXDBV2]") == 0)
cfc = new ClassFlowInfluxDBv2(&FlowControll);
#endif //ENABLE_INFLUXDB #endif //ENABLE_INFLUXDB
if (toUpper(_type).compare("[WRITELIST]") == 0) if (toUpper(_type).compare("[WRITELIST]") == 0)
cfc = new ClassFlowWriteList(&FlowControll); cfc = new ClassFlowWriteList(&FlowControll);
@@ -290,6 +297,7 @@ void ClassFlowControll::InitFlow(std::string config)
while ((line.size() > 0) && !(feof(pFile))) while ((line.size() > 0) && !(feof(pFile)))
{ {
cfc = CreateClassFlow(line); cfc = CreateClassFlow(line);
// printf("Name: %s\n", cfc->name().c_str());
if (cfc) if (cfc)
{ {
ESP_LOGD(TAG, "Start ReadParameter (%s)", line.c_str()); ESP_LOGD(TAG, "Start ReadParameter (%s)", line.c_str());

View File

@@ -15,6 +15,7 @@
#endif //ENABLE_MQTT #endif //ENABLE_MQTT
#ifdef ENABLE_INFLUXDB #ifdef ENABLE_INFLUXDB
#include "ClassFlowInfluxDB.h" #include "ClassFlowInfluxDB.h"
#include "ClassFlowInfluxDBv2.h"
#endif //ENABLE_INFLUXDB #endif //ENABLE_INFLUXDB
#include "ClassFlowCNNGeneral.h" #include "ClassFlowCNNGeneral.h"
#include "ClassFlowWriteList.h" #include "ClassFlowWriteList.h"

View File

@@ -50,6 +50,7 @@ struct NumberPost {
int DecimalShiftInitial; int DecimalShiftInitial;
float AnalogDigitalTransitionStart; // When is the digit > x.1, i.e. when does it start to tilt? float AnalogDigitalTransitionStart; // When is the digit > x.1, i.e. when does it start to tilt?
int Nachkomma; int Nachkomma;
string Fieldname; // Fieldname in InfluxDB2
bool isExtendedResolution; bool isExtendedResolution;

View File

@@ -0,0 +1,219 @@
#ifdef ENABLE_INFLUXDB
#include <sstream>
#include "ClassFlowInfluxDBv2.h"
#include "Helper.h"
#include "connect_wlan.h"
#include "time_sntp.h"
#include "interface_influxdb.h"
#include "ClassFlowPostProcessing.h"
#include "esp_log.h"
#include "../../include/defines.h"
#include "ClassLogFile.h"
#include <time.h>
static const char* TAG = "class_flow_influxDbv2";
void ClassFlowInfluxDBv2::SetInitialParameter(void)
{
uri = "";
database = "";
measurement = "";
dborg = "";
dbtoken = "";
// dbfield = "";
OldValue = "";
flowpostprocessing = NULL;
previousElement = NULL;
ListFlowControll = NULL;
disabled = false;
InfluxDBenable = false;
}
ClassFlowInfluxDBv2::ClassFlowInfluxDBv2()
{
SetInitialParameter();
}
ClassFlowInfluxDBv2::ClassFlowInfluxDBv2(std::vector<ClassFlow*>* lfc)
{
SetInitialParameter();
ListFlowControll = lfc;
for (int i = 0; i < ListFlowControll->size(); ++i)
{
if (((*ListFlowControll)[i])->name().compare("ClassFlowPostProcessing") == 0)
{
flowpostprocessing = (ClassFlowPostProcessing*) (*ListFlowControll)[i];
}
}
}
ClassFlowInfluxDBv2::ClassFlowInfluxDBv2(std::vector<ClassFlow*>* lfc, ClassFlow *_prev)
{
SetInitialParameter();
previousElement = _prev;
ListFlowControll = lfc;
for (int i = 0; i < ListFlowControll->size(); ++i)
{
if (((*ListFlowControll)[i])->name().compare("ClassFlowPostProcessing") == 0)
{
flowpostprocessing = (ClassFlowPostProcessing*) (*ListFlowControll)[i];
}
}
}
bool ClassFlowInfluxDBv2::ReadParameter(FILE* pfile, string& aktparamgraph)
{
std::vector<string> splitted;
aktparamgraph = trim(aktparamgraph);
printf("akt param: %s\n", aktparamgraph.c_str());
if (aktparamgraph.size() == 0)
if (!this->GetNextParagraph(pfile, aktparamgraph))
return false;
if (toUpper(aktparamgraph).compare("[INFLUXDBV2]") != 0)
return false;
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
{
// ESP_LOGD(TAG, "while loop reading line: %s", aktparamgraph.c_str());
splitted = ZerlegeZeile(aktparamgraph);
std::string _param = GetParameterName(splitted[0]);
if ((toUpper(_param) == "ORG") && (splitted.size() > 1))
{
this->dborg = splitted[1];
}
if ((toUpper(_param) == "TOKEN") && (splitted.size() > 1))
{
this->dbtoken = splitted[1];
}
if ((toUpper(_param) == "URI") && (splitted.size() > 1))
{
this->uri = splitted[1];
}
if (((toUpper(_param) == "MEASUREMENT")) && (splitted.size() > 1))
{
this->measurement = splitted[1];
}
if (((toUpper(_param) == "FIELDNAME")) && (splitted.size() > 1))
{
handleFieldname(splitted[0], splitted[1]);
}
if (((toUpper(splitted[0]) == "DATABASE")) && (splitted.size() > 1))
{
this->database = splitted[1];
}
}
printf("uri: %s\n", uri.c_str());
printf("measurement: %s\n", measurement.c_str());
printf("org: %s\n", dborg.c_str());
printf("token: %s\n", dbtoken.c_str());
if ((uri.length() > 0) && (database.length() > 0) && (measurement.length() > 0) && (dbtoken.length() > 0) && (dborg.length() > 0))
{
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Init InfluxDB with uri: " + uri + ", measurement: " + measurement + ", org: " + dborg + ", token: *****");
// printf("vor V2 Init\n");
InfluxDB_V2_Init(uri, database, measurement, dborg, dbtoken);
// printf("nach V2 Init\n");
InfluxDBenable = true;
} else {
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "InfluxDBv2 (Verion2 !!!) init skipped as we are missing some parameters");
}
return true;
}
string ClassFlowInfluxDBv2::GetInfluxDBMeasurement()
{
return measurement;
}
void ClassFlowInfluxDBv2::handleFieldname(string _decsep, string _value)
{
string _digit, _decpos;
int _pospunkt = _decsep.find_first_of(".");
// ESP_LOGD(TAG, "Name: %s, Pospunkt: %d", _decsep.c_str(), _pospunkt);
if (_pospunkt > -1)
_digit = _decsep.substr(0, _pospunkt);
else
_digit = "default";
for (int j = 0; j < flowpostprocessing->NUMBERS.size(); ++j)
{
if (_digit == "default") // Set to default first (if nothing else is set)
{
flowpostprocessing->NUMBERS[j]->Fieldname = _value;
}
if (flowpostprocessing->NUMBERS[j]->name == _digit)
{
flowpostprocessing->NUMBERS[j]->Fieldname = _value;
}
}
}
bool ClassFlowInfluxDBv2::doFlow(string zwtime)
{
if (!InfluxDBenable)
return true;
std::string result;
std::string resulterror = "";
std::string resultraw = "";
std::string resultrate = "";
std::string resulttimestamp = "";
string zw = "";
string namenumber = "";
if (flowpostprocessing)
{
std::vector<NumberPost*>* NUMBERS = flowpostprocessing->GetNumbers();
for (int i = 0; i < (*NUMBERS).size(); ++i)
{
result = (*NUMBERS)[i]->ReturnValue;
resultraw = (*NUMBERS)[i]->ReturnRawValue;
resulterror = (*NUMBERS)[i]->ErrorMessageText;
resultrate = (*NUMBERS)[i]->ReturnRateValue;
resulttimestamp = (*NUMBERS)[i]->timeStamp;
if ((*NUMBERS)[i]->Fieldname.length() > 0)
{
namenumber = (*NUMBERS)[i]->Fieldname;
}
else
{
namenumber = (*NUMBERS)[i]->name;
if (namenumber == "default")
namenumber = "value";
else
namenumber = namenumber + "/value";
}
printf("vor sende Influx_DB_V2 - namenumber. %s, result: %s, timestampt: %s", namenumber.c_str(), result.c_str(), resulttimestamp.c_str());
if (result.length() > 0)
InfluxDB_V2_Publish(namenumber, result, resulttimestamp);
// InfluxDB_V2_Publish(namenumber, result, resulttimestamp);
}
}
OldValue = result;
return true;
}
#endif //ENABLE_INFLUXDB

View File

@@ -0,0 +1,41 @@
#ifdef ENABLE_INFLUXDB
#pragma once
#ifndef CLASSFINFLUXDBv2_H
#define CLASSFINFLUXDBv2_H
#include "ClassFlow.h"
#include "ClassFlowPostProcessing.h"
#include <string>
class ClassFlowInfluxDBv2 :
public ClassFlow
{
protected:
std::string uri, database, measurement;
std::string dborg, dbtoken, dbfield;
std::string OldValue;
ClassFlowPostProcessing* flowpostprocessing;
bool InfluxDBenable;
void SetInitialParameter(void);
void handleFieldname(string _decsep, string _value);
public:
ClassFlowInfluxDBv2();
ClassFlowInfluxDBv2(std::vector<ClassFlow*>* lfc);
ClassFlowInfluxDBv2(std::vector<ClassFlow*>* lfc, ClassFlow *_prev);
string GetInfluxDBMeasurement();
bool ReadParameter(FILE* pfile, string& aktparamgraph);
bool doFlow(string time);
string name(){return "ClassFlowInfluxDBv2";};
};
#endif //CLASSFINFLUXDBv2_H
#endif //ENABLE_INFLUXDB

View File

@@ -15,7 +15,6 @@ class ClassFlowPostProcessing :
public ClassFlow public ClassFlow
{ {
protected: protected:
std::vector<NumberPost*> NUMBERS;
bool UpdatePreValueINI; bool UpdatePreValueINI;
int PreValueAgeStartup; int PreValueAgeStartup;
@@ -54,6 +53,8 @@ protected:
public: public:
bool PreValueUse; bool PreValueUse;
std::vector<NumberPost*> NUMBERS;
ClassFlowPostProcessing(std::vector<ClassFlow*>* lfc, ClassFlowCNNGeneral *_analog, ClassFlowCNNGeneral *_digit); ClassFlowPostProcessing(std::vector<ClassFlow*>* lfc, ClassFlowCNNGeneral *_analog, ClassFlowCNNGeneral *_digit);
virtual ~ClassFlowPostProcessing(){}; virtual ~ClassFlowPostProcessing(){};

View File

@@ -576,9 +576,6 @@ std::vector<string> HelperZerlegeZeile(std::string input, std::string _delimiter
std::vector<string> ZerlegeZeile(std::string input, std::string delimiter) std::vector<string> ZerlegeZeile(std::string input, std::string delimiter)
{ {
std::vector<string> Output; std::vector<string> Output;
input = trim(input, delimiter);
/* The input can have multiple formats: /* The input can have multiple formats:
* - key = value * - key = value
* - key = value1 value2 value3 ... * - key = value1 value2 value3 ...
@@ -593,12 +590,13 @@ std::vector<string> ZerlegeZeile(std::string input, std::string delimiter)
* As a workaround and to not break any legacy usage, we enforce to only use the * As a workaround and to not break any legacy usage, we enforce to only use the
* equal sign, if the key is "password" * equal sign, if the key is "password"
*/ */
if (input.find("password") != string::npos) { // Line contains a password, use the equal sign as the only delimiter and only split on first occurrence if ((input.find("password") != string::npos) || (input.find("Token") != string::npos)) { // Line contains a password, use the equal sign as the only delimiter and only split on first occurrence
size_t pos = input.find("="); size_t pos = input.find("=");
Output.push_back(trim(input.substr(0, pos), "")); Output.push_back(trim(input.substr(0, pos), ""));
Output.push_back(trim(input.substr(pos +1, string::npos), "")); Output.push_back(trim(input.substr(pos +1, string::npos), ""));
} }
else { // Legacy Mode else { // Legacy Mode
input = trim(input, delimiter); // sonst werden delimiter am Ende (z.B. == im Token) gelöscht)
size_t pos = findDelimiterPos(input, delimiter); size_t pos = findDelimiterPos(input, delimiter);
std::string token; std::string token;
while (pos != std::string::npos) { while (pos != std::string::npos) {

View File

@@ -16,6 +16,101 @@ std::string _influxDBMeasurement;
std::string _influxDBUser; std::string _influxDBUser;
std::string _influxDBPassword; std::string _influxDBPassword;
std::string _influxDB_V2_URI;
std::string _influxDB_V2_Database;
std::string _influxDB_V2_Measurement;
std::string _influxDB_V2_Token;
std::string _influxDB_V2_Org;
static esp_err_t http_event_handler(esp_http_client_event_t *evt);
void InfluxDB_V2_Init(std::string _uri, std::string _database, std::string _measurement, std::string _org, std::string _token)
{
_influxDB_V2_URI = _uri;
_influxDB_V2_Database = _database;
_influxDB_V2_Measurement = _measurement;
_influxDB_V2_Org = _org;
_influxDB_V2_Token = _token;
}
void InfluxDB_V2_Publish(std::string _key, std::string _content, std::string _timestamp)
{
char response_buffer[MAX_HTTP_OUTPUT_BUFFER] = {0};
esp_http_client_config_t http_config = {
.user_agent = "ESP32 Meter reader",
.method = HTTP_METHOD_POST,
.event_handler = http_event_handler,
.buffer_size = MAX_HTTP_OUTPUT_BUFFER,
.user_data = response_buffer
};
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "InfluxDB_V2_Publish - Key: " + _key + ", Content: " + _content + ", Timestamp: " + _timestamp);
// Format: #define PREVALUE_TIME_FORMAT_OUTPUT "%Y-%m-%dT%H:%M:%S%z"
char nowTimestamp[21];
std::string payload;
if (_timestamp.length() > 0)
{
struct tm tm;
strptime(_timestamp.c_str(), PREVALUE_TIME_FORMAT_OUTPUT, &tm);
time_t t = mktime(&tm); // Time in Localtime (looks like timezone is not used by strptime)
struct tm * ptm;
ptm = gmtime ( &t );
time_t utc = mktime(ptm);
utc = 2*t - utc; // Take care of timezone (looks difficult, but is easy: t = t + (t - utc), weil t-utc = timezone)
sprintf(nowTimestamp,"%ld000000000", (long) utc); // UTC
payload = _influxDB_V2_Measurement + " " + _key + "=" + _content + " " + nowTimestamp;
// payload = _influxDB_V2_Measurement + " " + _key + "=774 " + nowTimestamp;
}
else
{
payload = _influxDB_V2_Measurement + " " + _key + "=" + _content;
// payload = _influxDB_V2_Measurement + " " + _key + "=774";
}
payload.shrink_to_fit();
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "sending line to influxdb:" + payload);
std::string apiURI = _influxDB_V2_URI + "/api/v2/write?org=" + _influxDB_V2_Org + "&bucket=" + _influxDB_V2_Database;
apiURI.shrink_to_fit();
http_config.url = apiURI.c_str();
ESP_LOGI(TAG, "http_config: %s", http_config.url); // Add mark on log to see when it restarted
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "API URI: " + apiURI);
esp_http_client_handle_t http_client = esp_http_client_init(&http_config);
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "client is initialized");
esp_http_client_set_header(http_client, "Content-Type", "text/plain");
std::string _zw = "Token " + _influxDB_V2_Token;
// LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Tokenheader: %s\n", _zw.c_str());
esp_http_client_set_header(http_client, "Authorization", _zw.c_str());
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "header is set");
ESP_ERROR_CHECK(esp_http_client_set_post_field(http_client, payload.c_str(), payload.length()));
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "post payload is set");
esp_err_t err = ESP_ERROR_CHECK_WITHOUT_ABORT(esp_http_client_perform(http_client));
if( err == ESP_OK ) {
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "HTTP request was performed");
int status_code = esp_http_client_get_status_code(http_client);
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "HTTP status code" + std::to_string(status_code));
} else {
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "HTTP request failed");
}
esp_http_client_cleanup(http_client);
}
static esp_err_t http_event_handler(esp_http_client_event_t *evt) static esp_err_t http_event_handler(esp_http_client_event_t *evt)
{ {
switch(evt->event_id) switch(evt->event_id)
@@ -64,26 +159,30 @@ void InfluxDBPublish(std::string _key, std::string _content, std::string _timest
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "InfluxDBPublish - Key: " + _key + ", Content: " + _content + ", Timestamp: " + _timestamp); LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "InfluxDBPublish - Key: " + _key + ", Content: " + _content + ", Timestamp: " + _timestamp);
// Format: #define PREVALUE_TIME_FORMAT_OUTPUT "%Y-%m-%dT%H:%M:%S%z"
struct tm tm;
strptime(_timestamp.c_str(), PREVALUE_TIME_FORMAT_OUTPUT, &tm);
time_t t = mktime(&tm); // Time in Localtime (looks like timezone is not used by strptime)
struct tm * ptm;
ptm = gmtime ( &t );
time_t utc = mktime(ptm);
utc = 2*t - utc;
char nowTimestamp[21]; char nowTimestamp[21];
std::string payload;
sprintf(nowTimestamp,"%ld000000000", (long) utc); // UTC if (_timestamp.length() > 0)
{
struct tm tm;
strptime(_timestamp.c_str(), PREVALUE_TIME_FORMAT_OUTPUT, &tm);
time_t t = mktime(&tm); // Time in Localtime (looks like timezone is not used by strptime)
struct tm * ptm;
ptm = gmtime ( &t );
time_t utc = mktime(ptm);
utc = 2*t - utc; // Take care of timezone (looks difficult, but is easy: t = t + (t - utc), weil t-utc = timezone)
// LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Test Time Conversion - t: " + std::to_string(t) + ", utc: " + std::to_string(utc) + ", now: " + std::to_string(now) + ", utc_local: " + std::to_string(utc_local)); sprintf(nowTimestamp,"%ld000000000", (long) utc); // UTC
payload = _influxDB_V2_Measurement + " " + _key + "=" + _content + " " + nowTimestamp;
// payload = _influxDB_V2_Measurement + " " + _key + "=774 " + nowTimestamp;
}
else
{
payload = _influxDBMeasurement + " " + _key + "=" + _content;
}
std::string payload = _influxDBMeasurement + " " + _key + "=" + _content + " " + nowTimestamp;
payload.shrink_to_fit(); payload.shrink_to_fit();
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "sending line to influxdb:" + payload); LogFile.WriteToFile(ESP_LOG_INFO, TAG, "sending line to influxdb:" + payload);

View File

@@ -8,10 +8,17 @@
#include <map> #include <map>
#include <functional> #include <functional>
// Interface to InfluxDB v1.x
void InfluxDBInit(std::string _influxDBURI, std::string _database, std::string _measurement, std::string _user, std::string _password); void InfluxDBInit(std::string _influxDBURI, std::string _database, std::string _measurement, std::string _user, std::string _password);
void InfluxDBdestroy();
void InfluxDBPublish(std::string _key, std::string _content, std::string _timestamp); void InfluxDBPublish(std::string _key, std::string _content, std::string _timestamp);
// Interface to InfluxDB v2.x
void InfluxDB_V2_Init(std::string _uri, std::string _database, std::string _measurement, std::string _org, std::string _token);
void InfluxDB_V2_Publish(std::string _key, std::string _content, std::string _timestamp);
void InfluxDBdestroy();
#endif //INTERFACE_INFLUXDB_H #endif //INTERFACE_INFLUXDB_H
#endif //ENABLE_INFLUXDB #endif //ENABLE_INFLUXDB

View File

@@ -456,7 +456,7 @@ textarea {
</td> </td>
</tr> </tr>
<tr> <tr>
<td class="indent1"> <td class="indent1" style="padding-left: 75px;">
<input type="checkbox" id="PostProcessing_AllowNegativeRates_enabled" value="1" onclick = 'InvertEnableItem("PostProcessing", "AllowNegativeRates")' unchecked > <input type="checkbox" id="PostProcessing_AllowNegativeRates_enabled" value="1" onclick = 'InvertEnableItem("PostProcessing", "AllowNegativeRates")' unchecked >
<label for=PostProcessing_AllowNegativeRates_enabled><class id="PostProcessing_AllowNegativeRates_text" style="color:black;">AllowNegativeRates</class></label> <label for=PostProcessing_AllowNegativeRates_enabled><class id="PostProcessing_AllowNegativeRates_text" style="color:black;">AllowNegativeRates</class></label>
</td> </td>
@@ -471,7 +471,7 @@ textarea {
</td> </td>
</tr> </tr>
<tr> <tr>
<td class="indent1"> <td class="indent1" style="padding-left: 75px;">
<input type="checkbox" id="PostProcessing_DecimalShift_enabled" value="1" onclick = 'InvertEnableItem("PostProcessing", "DecimalShift")' unchecked > <input type="checkbox" id="PostProcessing_DecimalShift_enabled" value="1" onclick = 'InvertEnableItem("PostProcessing", "DecimalShift")' unchecked >
<label for=PostProcessing_DecimalShift_enabled><class id="PostProcessing_DecimalShift_text" style="color:black;">DecimalShift</class></label> <label for=PostProcessing_DecimalShift_enabled><class id="PostProcessing_DecimalShift_text" style="color:black;">DecimalShift</class></label>
</td> </td>
@@ -484,7 +484,7 @@ textarea {
</td> </td>
</tr> </tr>
<tr> <tr>
<td class="indent1"> <td class="indent1" style="padding-left: 75px;">
<input type="checkbox" id="PostProcessing_AnalogDigitalTransitionStart_enabled" value="1" onclick = 'InvertEnableItem("PostProcessing", "AnalogDigitalTransitionStart")' unchecked > <input type="checkbox" id="PostProcessing_AnalogDigitalTransitionStart_enabled" value="1" onclick = 'InvertEnableItem("PostProcessing", "AnalogDigitalTransitionStart")' unchecked >
<label for=PostProcessing_AnalogDigitalTransitionStart_enabled><class id="PostProcessing_AnalogDigitalTransitionStart_text" style="color:black;">AnalogDigitalTransitionStart</class></label> <label for=PostProcessing_AnalogDigitalTransitionStart_enabled><class id="PostProcessing_AnalogDigitalTransitionStart_text" style="color:black;">AnalogDigitalTransitionStart</class></label>
</td> </td>
@@ -498,7 +498,7 @@ textarea {
</tr> </tr>
<tr> <tr>
<td class="indent1"> <td class="indent1" style="padding-left: 75px;">
<input type="checkbox" id="PostProcessing_MaxRateValue_enabled" value="1" onclick = 'InvertEnableItem("PostProcessing", "MaxRateValue")' unchecked > <input type="checkbox" id="PostProcessing_MaxRateValue_enabled" value="1" onclick = 'InvertEnableItem("PostProcessing", "MaxRateValue")' unchecked >
<label for=PostProcessing_MaxRateValue_enabled><class id="PostProcessing_MaxRateValue_text" style="color:black;">MaxRateValue</class></label> <label for=PostProcessing_MaxRateValue_enabled><class id="PostProcessing_MaxRateValue_text" style="color:black;">MaxRateValue</class></label>
</td> </td>
@@ -510,7 +510,7 @@ textarea {
</td> </td>
</tr> </tr>
<tr> <tr>
<td class="indent1"> <td class="indent1" style="padding-left: 75px;">
<input type="checkbox" id="PostProcessing_MaxRateType_enabled" value="1" onclick = 'InvertEnableItem("PostProcessing", "MaxRateType")' unchecked > <input type="checkbox" id="PostProcessing_MaxRateType_enabled" value="1" onclick = 'InvertEnableItem("PostProcessing", "MaxRateType")' unchecked >
<label for=PostProcessing_MaxRateType_enabled><class id="PostProcessing_MaxRateType_text" style="color:black;">MaxRateType</class></label> <label for=PostProcessing_MaxRateType_enabled><class id="PostProcessing_MaxRateType_text" style="color:black;">MaxRateType</class></label>
</td> </td>
@@ -525,7 +525,7 @@ textarea {
</td> </td>
</tr> </tr>
<tr> <tr>
<td class="indent1"> <td class="indent1" style="padding-left: 75px;">
<input type="checkbox" id="PostProcessing_ExtendedResolution_enabled" value="1" onclick = 'InvertEnableItem("PostProcessing", "ExtendedResolution")' unchecked > <input type="checkbox" id="PostProcessing_ExtendedResolution_enabled" value="1" onclick = 'InvertEnableItem("PostProcessing", "ExtendedResolution")' unchecked >
<label for=PostProcessing_ExtendedResolution_enabled><class id="PostProcessing_ExtendedResolution_text" style="color:black;">ExtendedResolution</class></label> <label for=PostProcessing_ExtendedResolution_enabled><class id="PostProcessing_ExtendedResolution_text" style="color:black;">ExtendedResolution</class></label>
</td> </td>
@@ -541,7 +541,7 @@ textarea {
</tr> </tr>
<tr> <tr>
<td id="ex121" class="indent1"> <td id="ex121" class="indent1" style="padding-left: 75px;">
<input type="checkbox" id="PostProcessing_IgnoreLeadingNaN_enabled" value="1" onclick = 'InvertEnableItem("PostProcessing", "IgnoreLeadingNaN")' unchecked > <input type="checkbox" id="PostProcessing_IgnoreLeadingNaN_enabled" value="1" onclick = 'InvertEnableItem("PostProcessing", "IgnoreLeadingNaN")' unchecked >
<label for=PostProcessing_IgnoreLeadingNaN_enabled><class id="PostProcessing_IgnoreLeadingNaN_text" style="color:black;">IgnoreLeadingNaN</class></label> <label for=PostProcessing_IgnoreLeadingNaN_enabled><class id="PostProcessing_IgnoreLeadingNaN_text" style="color:black;">IgnoreLeadingNaN</class></label>
</td> </td>
@@ -701,7 +701,7 @@ textarea {
<td colspan="3" style="padding-left: 20px;"> <td colspan="3" style="padding-left: 20px;">
<h4> <h4>
<input type="checkbox" id="Category_InfluxDB_enabled" value="1" onclick = 'UpdateAfterCategoryCheck()' unchecked > <input type="checkbox" id="Category_InfluxDB_enabled" value="1" onclick = 'UpdateAfterCategoryCheck()' unchecked >
<label for=Category_InfluxDB_enabled>InfluxDB</h4><h5>Only InfluxDB v1.x is supported, v2.x has a changed interface</h5></label> <label for=Category_InfluxDB_enabled>InfluxDB</h4><h5>Only InfluxDB v1.x is configured here - v2.x see below [InfluxDBv2]</h5></label>
</td> </td>
</tr> </tr>
<tr> <tr>
@@ -765,6 +765,109 @@ textarea {
</td> </td>
</tr> </tr>
<tr>
<td colspan="3" style="padding-left: 20px;">
<h4>
<input type="checkbox" id="Category_InfluxDBv2_enabled" value="1" onclick = 'UpdateAfterCategoryCheck()' unchecked >
<label for=Category_InfluxDBv2_enabled>InfluxDBv2</h4><h5>Only InfluxDB v2.x is configured here, v1.x see above [InfluxDB]</h5></label>
</td>
</tr>
<tr>
<td class="indent1">
<input type="checkbox" id="InfluxDBv2_Uri_enabled" value="1" onclick = 'InvertEnableItem("InfluxDBv2", "Uri")' unchecked >
<label for=InfluxDBv2_Uri_enabled><class id="InfluxDBv2_Uri_text" style="color:black;">Uri</class></label>
</td>
<td>
<input type="text" id="InfluxDBv2_Uri_value1">
</td>
<td style="font-size: 80%;">
URI of the HTTP interface to InfluxDB (Version2), without traililing slash, e.g. http://IP-Address:Port
</td>
</tr>
<tr>
<td class="indent1">
<input type="checkbox" id="InfluxDBv2_Database_enabled" value="1" onclick = 'InvertEnableItem("InfluxDBv2", "Database")' unchecked >
<label for=InfluxDBv2_Database_enabled><class id="InfluxDBv2_Database_text" style="color:black;">Database</class></label>
</td>
<td>
<input type="text" id="InfluxDBv2_Database_value1">
</td>
<td style="font-size: 80%;">
Database name in which to publish the read value.
</td>
</tr>
<tr>
<td class="indent1">
<input type="checkbox" id="InfluxDBv2_Measurement_enabled" value="1" onclick = 'InvertEnableItem("InfluxDBv2", "Measurement")' unchecked >
<label for=InfluxDBv2_Measurement_enabled><class id="InfluxDBv2_Measurement_text" style="color:black;">Measurement</class></label>
</td>
<td>
<input type="text" id="InfluxDBv2_Measurement_value1">
</td>
<td style="font-size: 80%;">
Measurement name to use to publish the read value.
</td>
</tr>
<tr>
<td class="indent1">
<input type="checkbox" id="InfluxDBv2_Org_enabled" value="1" onclick = 'InvertEnableItem("InfluxDBv2", "Org")' unchecked >
<label for=InfluxDBv2_Org_enabled><class id="InfluxDBv2_Org_text" style="color:black;">Org</class></label>
</td>
<td>
<input type="text" id="InfluxDBv2_Org_value1">
</td>
<td style="font-size: 80%;">
Organisation (Org) for InfluxDBv2 authentication
</td>
</tr>
<tr>
<td class="indent1">
<input type="checkbox" id="InfluxDBv2_Token_enabled" value="1" onclick = 'InvertEnableItem("InfluxDBv2", "Token")' unchecked >
<label for=InfluxDBv2_Token_enabled><class id="InfluxDBv2_Token_text" style="color:black;">Token</class></label>
</td>
<td>
<input type="text" id="InfluxDBv2_Token_value1">
</td>
<td style="font-size: 80%;">
Token for InfluxDB authentication
</td>
</tr>
<tr>
<td class="indent1" colspan="3">
<br>
<b>Postprocessing Individual Parameters:
<select id="NumbersInfluxDB_value1" onchange="numberInfluxDBChanged()">
<option value="0" selected>default</option>
<option value="1" >NT</option>
<option value="2" >HT</option>
</select></b>
</td>
</tr>
<tr>
<td class="indent1" style="padding-left: 75px;">
<input type="checkbox" id="InfluxDBv2_Fieldname_enabled" value="1" onclick = 'InvertEnableItem("InfluxDBv2", "Fieldname")' unchecked >
<label for=InfluxDBv2_Fieldname_enabled><class id="InfluxDBv2_Fieldname_text" style="color:black;">Fieldname</class></label>
</td>
<td>
<input type="text" id="InfluxDBv2_Fieldname_value1">
</td>
<td style="font-size: 80%;">
Fieldname to use for saving.
</td>
</tr>
<tr> <tr>
<td colspan="3" style="padding-left: 20px;"> <td colspan="3" style="padding-left: 20px;">
<h4><input type="checkbox" id="Category_GPIO_enabled" value="1" onclick='UpdateAfterCategoryCheck()' unchecked > <h4><input type="checkbox" id="Category_GPIO_enabled" value="1" onclick='UpdateAfterCategoryCheck()' unchecked >
@@ -1464,7 +1567,8 @@ function LoadConfigNeu() {
InitIndivParameter(); InitIndivParameter();
UpdateInput(); UpdateInput();
UpdateInputIndividual(); var sel = document.getElementById("Numbers_value1");
UpdateInputIndividual(sel);
UpdateExpertModus(); UpdateExpertModus();
document.getElementById("divall").style.display = ''; document.getElementById("divall").style.display = '';
} }
@@ -1476,14 +1580,23 @@ function InitIndivParameter()
var _index = document.getElementById("Numbers_value1"); var _index = document.getElementById("Numbers_value1");
while (_index.length) while (_index.length)
_index.remove(0); _index.remove(0);
var _indexInflux = document.getElementById("NumbersInfluxDB_value1");
while (_indexInflux.length)
_indexInflux.remove(0);
for (var i = 0; i < NUMBERS.length; ++i){ for (var i = 0; i < NUMBERS.length; ++i){
var option = document.createElement("option"); var option = document.createElement("option");
option.text = NUMBERS[i]["name"]; option.text = NUMBERS[i]["name"];
option.value = i; option.value = i;
_index.add(option); _index.add(option);
var optionInflux = document.createElement("option");
optionInflux.text = NUMBERS[i]["name"];
optionInflux.value = i;
_indexInflux.add(optionInflux);
} }
_index.selectedIndex = 0; _index.selectedIndex = 0;
_indexInflux.selectedIndex = 0;
} }
@@ -1768,7 +1881,7 @@ function ReadParameter(_param, _cat, _name, _optional, _number = -1){
} }
} }
function UpdateInputIndividual() function UpdateInputIndividual(sel)
{ {
if (NUNBERSAkt != -1) if (NUNBERSAkt != -1)
{ {
@@ -1779,9 +1892,10 @@ function UpdateInputIndividual()
ReadParameter(param, "PostProcessing", "ExtendedResolution", true, NUNBERSAkt) ReadParameter(param, "PostProcessing", "ExtendedResolution", true, NUNBERSAkt)
ReadParameter(param, "PostProcessing", "IgnoreLeadingNaN", true, NUNBERSAkt) ReadParameter(param, "PostProcessing", "IgnoreLeadingNaN", true, NUNBERSAkt)
ReadParameter(param, "PostProcessing", "AllowNegativeRates", true, NUNBERSAkt) ReadParameter(param, "PostProcessing", "AllowNegativeRates", true, NUNBERSAkt)
ReadParameter(param, "InfluxDBv2", "Fieldname", true, NUNBERSAkt)
} }
var sel = document.getElementById("Numbers_value1"); // var sel = document.getElementById("Numbers_value1");
NUNBERSAkt = sel.selectedIndex; NUNBERSAkt = sel.selectedIndex;
WriteParameter(param, category, "PostProcessing", "DecimalShift", true, NUNBERSAkt); WriteParameter(param, category, "PostProcessing", "DecimalShift", true, NUNBERSAkt);
WriteParameter(param, category, "PostProcessing", "AnalogDigitalTransitionStart", true, NUNBERSAkt); WriteParameter(param, category, "PostProcessing", "AnalogDigitalTransitionStart", true, NUNBERSAkt);
@@ -1790,6 +1904,7 @@ function UpdateInputIndividual()
WriteParameter(param, category, "PostProcessing", "ExtendedResolution", true, NUNBERSAkt); WriteParameter(param, category, "PostProcessing", "ExtendedResolution", true, NUNBERSAkt);
WriteParameter(param, category, "PostProcessing", "IgnoreLeadingNaN", true, NUNBERSAkt); WriteParameter(param, category, "PostProcessing", "IgnoreLeadingNaN", true, NUNBERSAkt);
WriteParameter(param, category, "PostProcessing", "AllowNegativeRates", true, NUNBERSAkt); WriteParameter(param, category, "PostProcessing", "AllowNegativeRates", true, NUNBERSAkt);
WriteParameter(param, category, "InfluxDBv2", "Fieldname", true, NUNBERSAkt);
} }
function UpdateInput() { function UpdateInput() {
@@ -1798,6 +1913,7 @@ function UpdateInput() {
document.getElementById("Category_MQTT_enabled").checked = category["MQTT"]["enabled"]; document.getElementById("Category_MQTT_enabled").checked = category["MQTT"]["enabled"];
document.getElementById("Category_GPIO_enabled").checked = category["GPIO"]["enabled"]; document.getElementById("Category_GPIO_enabled").checked = category["GPIO"]["enabled"];
document.getElementById("Category_InfluxDB_enabled").checked = category["InfluxDB"]["enabled"]; document.getElementById("Category_InfluxDB_enabled").checked = category["InfluxDB"]["enabled"];
document.getElementById("Category_InfluxDBv2_enabled").checked = category["InfluxDBv2"]["enabled"];
setVisible("GPIO_item", category["GPIO"]["enabled"]); setVisible("GPIO_item", category["GPIO"]["enabled"]);
WriteParameter(param, category, "MakeImage", "LogImageLocation", true); WriteParameter(param, category, "MakeImage", "LogImageLocation", true);
@@ -1844,6 +1960,13 @@ function UpdateInput() {
WriteParameter(param, category, "InfluxDB", "user", true); WriteParameter(param, category, "InfluxDB", "user", true);
WriteParameter(param, category, "InfluxDB", "password", true); WriteParameter(param, category, "InfluxDB", "password", true);
WriteParameter(param, category, "InfluxDBv2", "Uri", true);
WriteParameter(param, category, "InfluxDBv2", "Database", true);
WriteParameter(param, category, "InfluxDBv2", "Measurement", true);
WriteParameter(param, category, "InfluxDBv2", "Org", true);
WriteParameter(param, category, "InfluxDBv2", "Token", true);
WriteParameter(param, category, "InfluxDBv2", "Fieldname", true);
WriteParameter(param, category, "GPIO", "IO0", true); WriteParameter(param, category, "GPIO", "IO0", true);
WriteParameter(param, category, "GPIO", "IO1", true); WriteParameter(param, category, "GPIO", "IO1", true);
WriteParameter(param, category, "GPIO", "IO3", true); WriteParameter(param, category, "GPIO", "IO3", true);
@@ -1919,6 +2042,7 @@ function ReadParameterAll()
category["Digits"]["enabled"] = document.getElementById("Category_Digits_enabled").checked; category["Digits"]["enabled"] = document.getElementById("Category_Digits_enabled").checked;
category["MQTT"]["enabled"] = document.getElementById("Category_MQTT_enabled").checked; category["MQTT"]["enabled"] = document.getElementById("Category_MQTT_enabled").checked;
category["InfluxDB"]["enabled"] = document.getElementById("Category_InfluxDB_enabled").checked; category["InfluxDB"]["enabled"] = document.getElementById("Category_InfluxDB_enabled").checked;
category["InfluxDBv2"]["enabled"] = document.getElementById("Category_InfluxDBv2_enabled").checked;
category["GPIO"]["enabled"] = document.getElementById("Category_GPIO_enabled").checked; category["GPIO"]["enabled"] = document.getElementById("Category_GPIO_enabled").checked;
ReadParameter(param, "MakeImage", "LogImageLocation", true); ReadParameter(param, "MakeImage", "LogImageLocation", true);
@@ -1948,7 +2072,6 @@ function ReadParameterAll()
ReadParameter(param, "PostProcessing", "PreValueUse", true); ReadParameter(param, "PostProcessing", "PreValueUse", true);
ReadParameter(param, "PostProcessing", "PreValueAgeStartup", true); ReadParameter(param, "PostProcessing", "PreValueAgeStartup", true);
// ReadParameter(param, "PostProcessing", "AllowNegativeRates", true);
ReadParameter(param, "PostProcessing", "ErrorMessage", true); ReadParameter(param, "PostProcessing", "ErrorMessage", true);
ReadParameter(param, "PostProcessing", "CheckDigitIncreaseConsistency", true); ReadParameter(param, "PostProcessing", "CheckDigitIncreaseConsistency", true);
@@ -1967,6 +2090,13 @@ function ReadParameterAll()
ReadParameter(param, "InfluxDB", "user", true); ReadParameter(param, "InfluxDB", "user", true);
ReadParameter(param, "InfluxDB", "password", true); ReadParameter(param, "InfluxDB", "password", true);
ReadParameter(param, "InfluxDBv2", "Uri", true);
ReadParameter(param, "InfluxDBv2", "Database", true);
ReadParameter(param, "InfluxDBv2", "Measurement", true);
ReadParameter(param, "InfluxDBv2", "Org", true);
ReadParameter(param, "InfluxDBv2", "Token", true);
// ReadParameter(param, "InfluxDB", "Fieldname", true);
ReadParameter(param, "GPIO", "IO0", true); ReadParameter(param, "GPIO", "IO0", true);
ReadParameter(param, "GPIO", "IO1", true); ReadParameter(param, "GPIO", "IO1", true);
ReadParameter(param, "GPIO", "IO3", true); ReadParameter(param, "GPIO", "IO3", true);
@@ -1998,7 +2128,8 @@ function ReadParameterAll()
ReadParameter(param, "System", "TimeServer", true); ReadParameter(param, "System", "TimeServer", true);
ReadParameter(param, "System", "RSSIThreashold", true); ReadParameter(param, "System", "RSSIThreashold", true);
UpdateInputIndividual(); var sel = document.getElementById("Numbers_value1");
UpdateInputIndividual(sel);
// FormatDecimalValue(param, "PostProcessing", "MaxRateValue"); // FormatDecimalValue(param, "PostProcessing", "MaxRateValue");
} }
@@ -2018,10 +2149,12 @@ function UpdateAfterCategoryCheck() {
category["Digits"]["enabled"] = document.getElementById("Category_Digits_enabled").checked; category["Digits"]["enabled"] = document.getElementById("Category_Digits_enabled").checked;
category["MQTT"]["enabled"] = document.getElementById("Category_MQTT_enabled").checked; category["MQTT"]["enabled"] = document.getElementById("Category_MQTT_enabled").checked;
category["InfluxDB"]["enabled"] = document.getElementById("Category_InfluxDB_enabled").checked; category["InfluxDB"]["enabled"] = document.getElementById("Category_InfluxDB_enabled").checked;
category["InfluxDBv2"]["enabled"] = document.getElementById("Category_InfluxDBv2_enabled").checked;
category["GPIO"]["enabled"] = document.getElementById("Category_GPIO_enabled").checked; category["GPIO"]["enabled"] = document.getElementById("Category_GPIO_enabled").checked;
UpdateInput(); UpdateInput();
UpdateInputIndividual(); var sel = document.getElementById("Numbers_value1");
UpdateInputIndividual(sel);
} }
function UpdateExpertModus() function UpdateExpertModus()
@@ -2098,7 +2231,24 @@ function editConfigDirect() {
function numberChanged() function numberChanged()
{ {
UpdateInputIndividual(); var sel = document.getElementById("Numbers_value1");
_neu = sel.selectedIndex;
UpdateInputIndividual(sel);
var _selInflux = document.getElementById("NumbersInfluxDB_value1");
if (_selInflux.selectedIndex != _neu)
_selInflux.selectedIndex = _neu
}
function numberInfluxDBChanged()
{
var sel = document.getElementById("NumbersInfluxDB_value1");
_neu = sel.selectedIndex;
UpdateInputIndividual(sel);
var _sel2 = document.getElementById("Numbers_value1");
if (_sel2.selectedIndex != _neu)
_sel2.selectedIndex = _neu
} }
LoadConfigNeu(); LoadConfigNeu();

View File

@@ -13,7 +13,7 @@ function getbasepath(){
{ {
// host = "http://192.168.2.219"; // jomjol interner test // host = "http://192.168.2.219"; // jomjol interner test
// host = "http://192.168.178.46"; // jomjol interner test // host = "http://192.168.178.46"; // jomjol interner test
host = "http://192.168.178.62"; // jomjol interner Real host = "http://192.168.178.44"; // jomjol interner Real
// host = "http://192.168.43.191"; // host = "http://192.168.43.191";
// host = "."; // jomjol interner localhost // host = "."; // jomjol interner localhost

View File

@@ -45,7 +45,6 @@ function ZerlegeZeile(input, delimiter = " =\t\r")
var Output = Array(0); var Output = Array(0);
// delimiter = " =,\t"; // delimiter = " =,\t";
input = trim(input, delimiter);
/* The input can have multiple formats: /* The input can have multiple formats:
* - key = value * - key = value
@@ -61,12 +60,14 @@ function ZerlegeZeile(input, delimiter = " =\t\r")
* As a workaround and to not break any legacy usage, we enforce to only use the * As a workaround and to not break any legacy usage, we enforce to only use the
* equal sign, if the key is "password" * equal sign, if the key is "password"
*/ */
if (input.includes("password")) { // Line contains a password, use the equal sign as the only delimiter and only split on first occurrence if (input.includes("password") || input.includes("Token")) { // Line contains a password, use the equal sign as the only delimiter and only split on first occurrence
var pos = input.indexOf("="); var pos = input.indexOf("=");
delimiter = " \t\r"
Output.push(trim(input.substr(0, pos), delimiter)); Output.push(trim(input.substr(0, pos), delimiter));
Output.push(trim(input.substr(pos +1, input.length), delimiter)); Output.push(trim(input.substr(pos +1, input.length), delimiter));
} }
else { // Legacy Mode else { // Legacy Mode
input = trim(input, delimiter);
var pos = findDelimiterPos(input, delimiter); var pos = findDelimiterPos(input, delimiter);
var token; var token;
while (pos > -1) { while (pos > -1) {

View File

@@ -196,6 +196,18 @@ function ParseConfig() {
ParamAddValue(param, catname, "user"); ParamAddValue(param, catname, "user");
ParamAddValue(param, catname, "password"); ParamAddValue(param, catname, "password");
var catname = "InfluxDBv2";
category[catname] = new Object();
category[catname]["enabled"] = false;
category[catname]["found"] = false;
param[catname] = new Object();
ParamAddValue(param, catname, "Uri");
ParamAddValue(param, catname, "Database");
ParamAddValue(param, catname, "Measurement");
ParamAddValue(param, catname, "Org");
ParamAddValue(param, catname, "Token");
ParamAddValue(param, catname, "Fieldname", 1, true);
var catname = "GPIO"; var catname = "GPIO";
category[catname] = new Object(); category[catname] = new Object();
category[catname]["enabled"] = false; category[catname]["enabled"] = false;