From e8c5ad145c0372183835ee196aef0c8124f8a1c9 Mon Sep 17 00:00:00 2001 From: rahehl Date: Tue, 6 Aug 2024 22:30:36 +0200 Subject: [PATCH 01/17] WIP add Webhook --- .../jomjol_flowcontroll/CMakeLists.txt | 2 +- .../jomjol_flowcontroll/ClassFlowControll.cpp | 13 ++ .../jomjol_flowcontroll/ClassFlowControll.h | 3 + .../jomjol_flowcontroll/ClassFlowWebhook.cpp | 204 ++++++++++++++++++ .../jomjol_flowcontroll/ClassFlowWebhook.h | 40 ++++ code/components/jomjol_webhook/CMakeLists.txt | 7 + .../jomjol_webhook/interface_webhook.cpp | 110 ++++++++++ .../jomjol_webhook/interface_webhook.h | 15 ++ code/platformio.ini | 9 +- sd-card/config/config.ini | 4 + sd-card/html/edit_config_template.html | 40 ++++ sd-card/html/readconfigparam.js | 8 + 12 files changed, 451 insertions(+), 4 deletions(-) create mode 100644 code/components/jomjol_flowcontroll/ClassFlowWebhook.cpp create mode 100644 code/components/jomjol_flowcontroll/ClassFlowWebhook.h create mode 100644 code/components/jomjol_webhook/CMakeLists.txt create mode 100644 code/components/jomjol_webhook/interface_webhook.cpp create mode 100644 code/components/jomjol_webhook/interface_webhook.h diff --git a/code/components/jomjol_flowcontroll/CMakeLists.txt b/code/components/jomjol_flowcontroll/CMakeLists.txt index 4ad9f317f..2df515fc7 100644 --- a/code/components/jomjol_flowcontroll/CMakeLists.txt +++ b/code/components/jomjol_flowcontroll/CMakeLists.txt @@ -2,6 +2,6 @@ FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*) idf_component_register(SRCS ${app_sources} INCLUDE_DIRS "." - REQUIRES esp_timer esp_wifi jomjol_tfliteclass jomjol_helper jomjol_controlcamera jomjol_mqtt jomjol_influxdb jomjol_fileserver_ota jomjol_image_proc jomjol_wlan openmetrics) + REQUIRES esp_timer esp_wifi jomjol_tfliteclass jomjol_helper jomjol_controlcamera jomjol_mqtt jomjol_influxdb jomjol_webhook jomjol_fileserver_ota jomjol_image_proc jomjol_wlan openmetrics) diff --git a/code/components/jomjol_flowcontroll/ClassFlowControll.cpp b/code/components/jomjol_flowcontroll/ClassFlowControll.cpp index 1e2cd7512..f347f6bad 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowControll.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowControll.cpp @@ -65,6 +65,11 @@ std::string ClassFlowControll::doSingleStep(std::string _stepname, std::string _ _classname = "ClassFlowInfluxDBv2"; } #endif //ENABLE_INFLUXDB + #ifdef ENABLE_WEBHOOK + if ((_stepname.compare("[Webhook]") == 0) || (_stepname.compare(";[Webhook]") == 0)){ + _classname = "ClassFlowWebhook"; + } + #endif //ENABLE_WEBHOOK for (int i = 0; i < FlowControll.size(); ++i) if (FlowControll[i]->name().compare(_classname) == 0){ @@ -97,6 +102,10 @@ std::string ClassFlowControll::TranslateAktstatus(std::string _input) if (_input.compare("ClassFlowInfluxDBv2") == 0) return ("Sending InfluxDBv2"); #endif //ENABLE_INFLUXDB + #ifdef ENABLE_WEBHOOK + if (_input.compare("ClassFlowWebhook") == 0) + return ("Sending Webhook"); + #endif //ENABLE_WEBHOOK if (_input.compare("ClassFlowPostProcessing") == 0) return ("Post-Processing"); @@ -238,6 +247,10 @@ ClassFlow* ClassFlowControll::CreateClassFlow(std::string _type) if (toUpper(_type).compare("[INFLUXDBV2]") == 0) cfc = new ClassFlowInfluxDBv2(&FlowControll); #endif //ENABLE_INFLUXDB + #ifdef ENABLE_WEBHOOK + if (toUpper(_type).compare("[WEBHOOK]") == 0) + cfc = new ClassFlowWebhook(&FlowControll); + #endif //ENABLE_WEBHOOK if (toUpper(_type).compare("[POSTPROCESSING]") == 0) { diff --git a/code/components/jomjol_flowcontroll/ClassFlowControll.h b/code/components/jomjol_flowcontroll/ClassFlowControll.h index 3021338ba..4e8e2f167 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowControll.h +++ b/code/components/jomjol_flowcontroll/ClassFlowControll.h @@ -17,6 +17,9 @@ #include "ClassFlowInfluxDB.h" #include "ClassFlowInfluxDBv2.h" #endif //ENABLE_INFLUXDB +#ifdef ENABLE_WEBHOOK + #include "ClassFlowWebhook.h" +#endif //ENABLE_WEBHOOK #include "ClassFlowCNNGeneral.h" class ClassFlowControll : diff --git a/code/components/jomjol_flowcontroll/ClassFlowWebhook.cpp b/code/components/jomjol_flowcontroll/ClassFlowWebhook.cpp new file mode 100644 index 000000000..6aa55a79e --- /dev/null +++ b/code/components/jomjol_flowcontroll/ClassFlowWebhook.cpp @@ -0,0 +1,204 @@ +#ifdef ENABLE_WEBHOOK +#include +#include "ClassFlowWebhook.h" +#include "Helper.h" +#include "connect_wlan.h" + +#include "time_sntp.h" +#include "interface_webhook.h" + +#include "ClassFlowPostProcessing.h" +#include "esp_log.h" +#include "../../include/defines.h" + +#include "ClassLogFile.h" + +#include + +static const char* TAG = "WEBHOOK"; + +void ClassFlowWebhook::SetInitialParameter(void) +{ + uri = ""; + OldValue = ""; + flowpostprocessing = NULL; + previousElement = NULL; + ListFlowControll = NULL; + disabled = false; + WebhookEnable = false; +} + +ClassFlowWebhook::ClassFlowWebhook() +{ + SetInitialParameter(); +} + +ClassFlowWebhook::ClassFlowWebhook(std::vector* lfc) +{ + SetInitialParameter(); + + ListFlowControll = lfc; + for (int i = 0; i < ListFlowControll->size(); ++i) + { + if (((*ListFlowControll)[i])->name().compare("ClassFlowPostProcessing") == 0) + { + flowpostprocessing = (ClassFlowPostProcessing*) (*ListFlowControll)[i]; + } + } +} + +ClassFlowWebhook::ClassFlowWebhook(std::vector* 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 ClassFlowWebhook::ReadParameter(FILE* pfile, string& aktparamgraph) +{ + std::vector 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("[WEBHOOK]") != 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) == "URI") && (splitted.size() > 1)) + { + this->uri = splitted[1]; + } + if (((toUpper(_param) == "FIELD")) && (splitted.size() > 1)) + { + handleFieldname(splitted[0], splitted[1]); + } + if (((toUpper(_param) == "MEASUREMENT")) && (splitted.size() > 1)) + { + handleMeasurement(splitted[0], splitted[1]); + } + } + + printf("uri: %s\n", uri.c_str()); + return true; +} + +void ClassFlowWebhook::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]->FieldV2 = _value; + } + if (flowpostprocessing->NUMBERS[j]->name == _digit) + { + flowpostprocessing->NUMBERS[j]->FieldV2 = _value; + } + } +} + +void ClassFlowWebhook::handleMeasurement(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]->MeasurementV2 = _value; + } + if (flowpostprocessing->NUMBERS[j]->name == _digit) + { + flowpostprocessing->NUMBERS[j]->MeasurementV2 = _value; + } + } +} + + +bool ClassFlowWebhook::doFlow(string zwtime) +{ + if (!WebhookEnable) + return true; + + std::string result; + std::string resulterror = ""; + std::string resultraw = ""; + std::string resultrate = ""; + std::string resulttimestamp = ""; + long int resulttimeutc = 0; + string zw = ""; + string namenumber = ""; + + + if (flowpostprocessing) + { + std::vector* 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; + resulttimeutc = (*NUMBERS)[i]->timeStampTimeUTC; + + + if ((*NUMBERS)[i]->FieldV2.length() > 0) + { + namenumber = (*NUMBERS)[i]->FieldV2; + } + else + { + namenumber = (*NUMBERS)[i]->name; + if (namenumber == "default") + namenumber = "value"; + else + namenumber = namenumber + "/value"; + } + + printf("vor sende WebHook - namenumber. %s, result: %s, timestampt: %s", namenumber.c_str(), result.c_str(), resulttimestamp.c_str()); + + if (result.length() > 0) + WebhookPublish(namenumber, result, resulttimeutc); + } + } + + OldValue = result; + + return true; +} + +#endif //ENABLE_WEBHOOK \ No newline at end of file diff --git a/code/components/jomjol_flowcontroll/ClassFlowWebhook.h b/code/components/jomjol_flowcontroll/ClassFlowWebhook.h new file mode 100644 index 000000000..337949793 --- /dev/null +++ b/code/components/jomjol_flowcontroll/ClassFlowWebhook.h @@ -0,0 +1,40 @@ +#ifdef ENABLE_WEBHOOK + +#pragma once + +#ifndef CLASSFWEBHOOK_H +#define CLASSFWEBHOOK_H + +#include "ClassFlow.h" + +#include "ClassFlowPostProcessing.h" + +#include + +class ClassFlowWebhook : + public ClassFlow +{ +protected: + std::string uri, apikey; + std::string OldValue; + ClassFlowPostProcessing* flowpostprocessing; + bool WebhookEnable; + + void SetInitialParameter(void); + + void handleFieldname(string _decsep, string _value); + void handleMeasurement(string _decsep, string _value); + + +public: + ClassFlowWebhook(); + ClassFlowWebhook(std::vector* lfc); + ClassFlowWebhook(std::vector* lfc, ClassFlow *_prev); + + bool ReadParameter(FILE* pfile, string& aktparamgraph); + bool doFlow(string time); + string name(){return "ClassFlowWebhook";}; +}; + +#endif //CLASSFWEBHOOK_H +#endif //ENABLE_WEBHOOK \ No newline at end of file diff --git a/code/components/jomjol_webhook/CMakeLists.txt b/code/components/jomjol_webhook/CMakeLists.txt new file mode 100644 index 000000000..545134087 --- /dev/null +++ b/code/components/jomjol_webhook/CMakeLists.txt @@ -0,0 +1,7 @@ +FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*) + +idf_component_register(SRCS ${app_sources} + INCLUDE_DIRS "." + REQUIRES esp_http_client jomjol_logfile) + + diff --git a/code/components/jomjol_webhook/interface_webhook.cpp b/code/components/jomjol_webhook/interface_webhook.cpp new file mode 100644 index 000000000..46674e492 --- /dev/null +++ b/code/components/jomjol_webhook/interface_webhook.cpp @@ -0,0 +1,110 @@ +#ifdef ENABLE_WEBHOOK +#include "interface_webhook.h" + +#include "esp_log.h" +#include +#include "ClassLogFile.h" +#include "esp_http_client.h" +#include "time_sntp.h" +#include "../../include/defines.h" + + +static const char *TAG = "WEBHOOK"; + +std::string _webhookURI; +std::string _webhookApiKey; + +static esp_err_t http_event_handler(esp_http_client_event_t *evt); + +void WebhookInit(std::string _uri, std::string _apiKey) +{ + _webhookURI = _uri; + _webhookApiKey = _apiKey; +} + +void WebhookPublish(std::string _key, std::string _content, long int _timeUTC) +{ + 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, "Webhook_Publish - Key: " + _key + ", Content: " + _content + ", timeUTC: " + std::to_string(_timeUTC)); + + std::string payload; + char nowTimestamp[21]; + + payload = _content; + payload.shrink_to_fit(); + + LogFile.WriteToFile(ESP_LOG_INFO, TAG, "sending line to webhook uri:" + payload); + + std::string apiURI = _webhookURI; + 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"); + + esp_http_client_set_header(http_client, "APIKEY", _webhookApiKey.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) +{ + switch(evt->event_id) + { + case HTTP_EVENT_ERROR: + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "HTTP Client Error encountered"); + break; + case HTTP_EVENT_ON_CONNECTED: + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "HTTP Client connected"); + ESP_LOGI(TAG, "HTTP Client Connected"); + break; + case HTTP_EVENT_HEADERS_SENT: + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "HTTP Client sent all request headers"); + break; + case HTTP_EVENT_ON_HEADER: + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Header: key=" + std::string(evt->header_key) + ", value=" + std::string(evt->header_value)); + break; + case HTTP_EVENT_ON_DATA: + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "HTTP Client data recevied: len=" + std::to_string(evt->data_len)); + break; + case HTTP_EVENT_ON_FINISH: + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "HTTP Client finished"); + break; + case HTTP_EVENT_DISCONNECTED: + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "HTTP Client Disconnected"); + break; + case HTTP_EVENT_REDIRECT: + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "HTTP Redirect"); + break; + } + return ESP_OK; +} + +#endif //ENABLE_WEBHOOK \ No newline at end of file diff --git a/code/components/jomjol_webhook/interface_webhook.h b/code/components/jomjol_webhook/interface_webhook.h new file mode 100644 index 000000000..d6a5443ec --- /dev/null +++ b/code/components/jomjol_webhook/interface_webhook.h @@ -0,0 +1,15 @@ +#ifdef ENABLE_WEBHOOK + +#pragma once +#ifndef INTERFACE_WEBHOOK_H +#define INTERFACE_WEBHOOK_H + +#include +#include +#include + +void WebhookInit(std::string _webhookURI, std::string _apiKey); +void WebhookPublish(std::string _key, std::string _content, long int _timeUTC); + +#endif //INTERFACE_WEBHOOK_H +#endif //ENABLE_WEBHOOK \ No newline at end of file diff --git a/code/platformio.ini b/code/platformio.ini index c174baa25..3c86e4a6d 100644 --- a/code/platformio.ini +++ b/code/platformio.ini @@ -58,7 +58,8 @@ build_flags = ${flags:runtime.build_flags} ; ### Sofware options : (can be set in defines.h) -D ENABLE_MQTT - -D ENABLE_INFLUXDB + -D ENABLE_INFLUXDB + -D ENABLE_WEBHOOK -D ENABLE_SOFTAP board_build.partitions = partitions.csv monitor_speed = 115200 @@ -79,7 +80,8 @@ build_flags = ${flags:clangtidy.build_flags} ; ### Sofware options : (can be set in defines.h) -D ENABLE_MQTT - -D ENABLE_INFLUXDB + -D ENABLE_INFLUXDB + -D ENABLE_WEBHOOK ;-D ENABLE_SOFTAP ; ### Debug options : ;-D DEBUG_DETAIL_ON @@ -211,5 +213,6 @@ build_flags = ${flags:clangtidy.build_flags} ; ### Sofware options : -D ENABLE_MQTT - -D ENABLE_INFLUXDB + -D ENABLE_INFLUXDB + -D ENABLE_WEBHOOK ;-D ENABLE_SOFTAP ; disabled diff --git a/sd-card/config/config.ini b/sd-card/config/config.ini index 2b133857f..8f40444e5 100644 --- a/sd-card/config/config.ini +++ b/sd-card/config/config.ini @@ -103,6 +103,10 @@ HomeassistantDiscovery = false ;Token = undefined ;main.Fieldname = undefined +;[Webhook] +;Uri = undefined +;ApiKey = undefined + ;[GPIO] ;MainTopicMQTT = wasserzaehler/GPIO ;IO0 = input disabled 10 false false diff --git a/sd-card/html/edit_config_template.html b/sd-card/html/edit_config_template.html index 68b9cd134..4f7f3ea83 100644 --- a/sd-card/html/edit_config_template.html +++ b/sd-card/html/edit_config_template.html @@ -1324,6 +1324,37 @@

$TOOLTIP_InfluxDBv2_NUMBER.Field + + + +

+ +

+ + + + + + + + + + + + $TOOLTIP_Webhook_Uri + + + + + + + + + + + $TOOLTIP_Webhook_ApiKey + + @@ -2169,6 +2200,9 @@

Date: Wed, 7 Aug 2024 10:41:03 +0200 Subject: [PATCH 03/17] webhook: fix not enabling webhook --- .../jomjol_flowcontroll/ClassFlowWebhook.cpp | 37 +++++-------------- 1 file changed, 9 insertions(+), 28 deletions(-) diff --git a/code/components/jomjol_flowcontroll/ClassFlowWebhook.cpp b/code/components/jomjol_flowcontroll/ClassFlowWebhook.cpp index 6aa55a79e..c97083c0d 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowWebhook.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowWebhook.cpp @@ -78,9 +78,11 @@ bool ClassFlowWebhook::ReadParameter(FILE* pfile, string& aktparamgraph) if (toUpper(aktparamgraph).compare("[WEBHOOK]") != 0) return false; + + while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph)) { -// ESP_LOGD(TAG, "while loop reading line: %s", aktparamgraph.c_str()); + ESP_LOGD(TAG, "while loop reading line: %s", aktparamgraph.c_str()); splitted = ZerlegeZeile(aktparamgraph); std::string _param = GetParameterName(splitted[0]); @@ -88,41 +90,20 @@ bool ClassFlowWebhook::ReadParameter(FILE* pfile, string& aktparamgraph) { this->uri = splitted[1]; } - if (((toUpper(_param) == "FIELD")) && (splitted.size() > 1)) - { - handleFieldname(splitted[0], splitted[1]); - } - if (((toUpper(_param) == "MEASUREMENT")) && (splitted.size() > 1)) + if (((toUpper(_param) == "APIKEY")) && (splitted.size() > 1)) { - handleMeasurement(splitted[0], splitted[1]); + this->apikey = splitted[1]; } } + + WebhookInit(uri,apikey); + WebhookEnable = true; + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Webhook Enabled for Uri " + uri); printf("uri: %s\n", uri.c_str()); return true; } -void ClassFlowWebhook::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]->FieldV2 = _value; - } - if (flowpostprocessing->NUMBERS[j]->name == _digit) - { - flowpostprocessing->NUMBERS[j]->FieldV2 = _value; - } - } -} void ClassFlowWebhook::handleMeasurement(string _decsep, string _value) { From a9d5f089fbf0f79955ac8236a9758ee48e174c81 Mon Sep 17 00:00:00 2001 From: rahehl Date: Wed, 7 Aug 2024 12:00:12 +0200 Subject: [PATCH 04/17] send webhook as json --- .../jomjol_flowcontroll/ClassFlowWebhook.cpp | 29 ++------ .../jomjol_flowcontroll/ClassFlowWebhook.h | 1 - code/components/jomjol_webhook/CMakeLists.txt | 2 +- .../jomjol_webhook/interface_webhook.cpp | 66 +++++++++---------- .../jomjol_webhook/interface_webhook.h | 2 +- 5 files changed, 38 insertions(+), 62 deletions(-) diff --git a/code/components/jomjol_flowcontroll/ClassFlowWebhook.cpp b/code/components/jomjol_flowcontroll/ClassFlowWebhook.cpp index c97083c0d..1af17c060 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowWebhook.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowWebhook.cpp @@ -20,7 +20,6 @@ static const char* TAG = "WEBHOOK"; void ClassFlowWebhook::SetInitialParameter(void) { uri = ""; - OldValue = ""; flowpostprocessing = NULL; previousElement = NULL; ListFlowControll = NULL; @@ -133,7 +132,7 @@ bool ClassFlowWebhook::doFlow(string zwtime) if (!WebhookEnable) return true; - std::string result; + std::string resultValue; std::string resulterror = ""; std::string resultraw = ""; std::string resultrate = ""; @@ -149,36 +148,18 @@ bool ClassFlowWebhook::doFlow(string zwtime) for (int i = 0; i < (*NUMBERS).size(); ++i) { - result = (*NUMBERS)[i]->ReturnValue; + resultValue = (*NUMBERS)[i]->ReturnValue; resultraw = (*NUMBERS)[i]->ReturnRawValue; resulterror = (*NUMBERS)[i]->ErrorMessageText; resultrate = (*NUMBERS)[i]->ReturnRateValue; resulttimestamp = (*NUMBERS)[i]->timeStamp; resulttimeutc = (*NUMBERS)[i]->timeStampTimeUTC; - - - if ((*NUMBERS)[i]->FieldV2.length() > 0) - { - namenumber = (*NUMBERS)[i]->FieldV2; - } - else - { - namenumber = (*NUMBERS)[i]->name; - if (namenumber == "default") - namenumber = "value"; - else - namenumber = namenumber + "/value"; - } - printf("vor sende WebHook - namenumber. %s, result: %s, timestampt: %s", namenumber.c_str(), result.c_str(), resulttimestamp.c_str()); - - if (result.length() > 0) - WebhookPublish(namenumber, result, resulttimeutc); + printf("vor sende WebHook - result: %s, timestampt: %s", resultValue.c_str(), resulttimestamp.c_str()); + WebhookPublish(resultValue, resultraw, resulterror, resultrate, resulttimestamp, resulttimeutc); } } - - OldValue = result; - + return true; } diff --git a/code/components/jomjol_flowcontroll/ClassFlowWebhook.h b/code/components/jomjol_flowcontroll/ClassFlowWebhook.h index 337949793..3900fc092 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowWebhook.h +++ b/code/components/jomjol_flowcontroll/ClassFlowWebhook.h @@ -16,7 +16,6 @@ class ClassFlowWebhook : { protected: std::string uri, apikey; - std::string OldValue; ClassFlowPostProcessing* flowpostprocessing; bool WebhookEnable; diff --git a/code/components/jomjol_webhook/CMakeLists.txt b/code/components/jomjol_webhook/CMakeLists.txt index 545134087..bcc7dc4c8 100644 --- a/code/components/jomjol_webhook/CMakeLists.txt +++ b/code/components/jomjol_webhook/CMakeLists.txt @@ -2,6 +2,6 @@ FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*) idf_component_register(SRCS ${app_sources} INCLUDE_DIRS "." - REQUIRES esp_http_client jomjol_logfile) + REQUIRES esp_http_client jomjol_logfile json) diff --git a/code/components/jomjol_webhook/interface_webhook.cpp b/code/components/jomjol_webhook/interface_webhook.cpp index 46674e492..fef61dfb6 100644 --- a/code/components/jomjol_webhook/interface_webhook.cpp +++ b/code/components/jomjol_webhook/interface_webhook.cpp @@ -7,6 +7,7 @@ #include "esp_http_client.h" #include "time_sntp.h" #include "../../include/defines.h" +#include static const char *TAG = "WEBHOOK"; @@ -22,56 +23,51 @@ void WebhookInit(std::string _uri, std::string _apiKey) _webhookApiKey = _apiKey; } -void WebhookPublish(std::string _key, std::string _content, long int _timeUTC) +void WebhookPublish(std::string _value,std::string _valueraw,std::string _error,std::string _rate,std::string _timestamp, long int _timeUTC) { - 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, "Webhook_Publish - Key: " + _key + ", Content: " + _content + ", timeUTC: " + std::to_string(_timeUTC)); - - std::string payload; - char nowTimestamp[21]; - - payload = _content; - payload.shrink_to_fit(); + cJSON *json = cJSON_CreateObject(); + cJSON_AddStringToObject(json, "value", _value.c_str()); + cJSON_AddStringToObject(json, "valueraw", _valueraw.c_str()); + cJSON_AddStringToObject(json, "error", _error.c_str()); + cJSON_AddStringToObject(json, "rate", _rate.c_str()); + cJSON_AddStringToObject(json, "timestamp", _timestamp.c_str()); + cJSON_AddNumberToObject(json, "timeUTC", _timeUTC); - LogFile.WriteToFile(ESP_LOG_INFO, TAG, "sending line to webhook uri:" + payload); + char *jsonString = cJSON_PrintUnformatted(json); - std::string apiURI = _webhookURI; - 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, "sending webhook"); + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "sending JSON: " + std::string(jsonString)); - LogFile.WriteToFile(ESP_LOG_INFO, TAG, "API URI: " + apiURI); + char response_buffer[MAX_HTTP_OUTPUT_BUFFER] = {0}; + esp_http_client_config_t http_config = { + .url = _webhookURI.c_str(), + .user_agent = "ESP32 Meter reader", + .method = HTTP_METHOD_POST, + .event_handler = http_event_handler, + .buffer_size = MAX_HTTP_OUTPUT_BUFFER, + .user_data = response_buffer + }; 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"); + esp_http_client_set_header(http_client, "Content-Type", "application/json"); esp_http_client_set_header(http_client, "APIKEY", _webhookApiKey.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_ERROR_CHECK(esp_http_client_set_post_field(http_client, jsonString, strlen(jsonString))); 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)); + 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"); + LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "HTTP request failed"); } + esp_http_client_cleanup(http_client); + cJSON_Delete(json); + free(jsonString); } static esp_err_t http_event_handler(esp_http_client_event_t *evt) diff --git a/code/components/jomjol_webhook/interface_webhook.h b/code/components/jomjol_webhook/interface_webhook.h index d6a5443ec..c3cfa5346 100644 --- a/code/components/jomjol_webhook/interface_webhook.h +++ b/code/components/jomjol_webhook/interface_webhook.h @@ -9,7 +9,7 @@ #include void WebhookInit(std::string _webhookURI, std::string _apiKey); -void WebhookPublish(std::string _key, std::string _content, long int _timeUTC); +void WebhookPublish(std::string _value,std::string _valueraw,std::string _error,std::string _rate,std::string _timestamp, long int _timeUTC); #endif //INTERFACE_WEBHOOK_H #endif //ENABLE_WEBHOOK \ No newline at end of file From e642b0a99f4f56774dde8778082b72c1f5242f31 Mon Sep 17 00:00:00 2001 From: CaCO3 Date: Fri, 9 Aug 2024 00:59:11 +0200 Subject: [PATCH 05/17] Update ApiKey.md --- param-docs/parameter-pages/Webhook/ApiKey.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/param-docs/parameter-pages/Webhook/ApiKey.md b/param-docs/parameter-pages/Webhook/ApiKey.md index 7b7aa955e..79cf21615 100644 --- a/param-docs/parameter-pages/Webhook/ApiKey.md +++ b/param-docs/parameter-pages/Webhook/ApiKey.md @@ -1,4 +1,4 @@ # Parameter `ApiKey` Default Value: `undefined` -ApiKey send as Header +ApiKey sent as Header From e38c9eaaa51acfd08091471d018ef59b1207c43b Mon Sep 17 00:00:00 2001 From: rahehl Date: Fri, 9 Aug 2024 10:50:28 +0200 Subject: [PATCH 06/17] webhook: fix only sending last "Number" --- .../jomjol_flowcontroll/ClassFlowWebhook.cpp | 27 ++-------------- code/components/jomjol_webhook/CMakeLists.txt | 2 +- .../jomjol_webhook/interface_webhook.cpp | 32 +++++++++++++------ .../jomjol_webhook/interface_webhook.h | 3 +- 4 files changed, 27 insertions(+), 37 deletions(-) diff --git a/code/components/jomjol_flowcontroll/ClassFlowWebhook.cpp b/code/components/jomjol_flowcontroll/ClassFlowWebhook.cpp index 1af17c060..a60919bda 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowWebhook.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowWebhook.cpp @@ -132,35 +132,12 @@ bool ClassFlowWebhook::doFlow(string zwtime) if (!WebhookEnable) return true; - std::string resultValue; - std::string resulterror = ""; - std::string resultraw = ""; - std::string resultrate = ""; - std::string resulttimestamp = ""; - long int resulttimeutc = 0; - string zw = ""; - string namenumber = ""; - - if (flowpostprocessing) { - std::vector* NUMBERS = flowpostprocessing->GetNumbers(); - - for (int i = 0; i < (*NUMBERS).size(); ++i) - { - resultValue = (*NUMBERS)[i]->ReturnValue; - resultraw = (*NUMBERS)[i]->ReturnRawValue; - resulterror = (*NUMBERS)[i]->ErrorMessageText; - resultrate = (*NUMBERS)[i]->ReturnRateValue; - resulttimestamp = (*NUMBERS)[i]->timeStamp; - resulttimeutc = (*NUMBERS)[i]->timeStampTimeUTC; - - printf("vor sende WebHook - result: %s, timestampt: %s", resultValue.c_str(), resulttimestamp.c_str()); - WebhookPublish(resultValue, resultraw, resulterror, resultrate, resulttimestamp, resulttimeutc); - } + printf("vor sende WebHook"); + WebhookPublish(flowpostprocessing->GetNumbers()); } return true; } - #endif //ENABLE_WEBHOOK \ No newline at end of file diff --git a/code/components/jomjol_webhook/CMakeLists.txt b/code/components/jomjol_webhook/CMakeLists.txt index bcc7dc4c8..10271c118 100644 --- a/code/components/jomjol_webhook/CMakeLists.txt +++ b/code/components/jomjol_webhook/CMakeLists.txt @@ -2,6 +2,6 @@ FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*) idf_component_register(SRCS ${app_sources} INCLUDE_DIRS "." - REQUIRES esp_http_client jomjol_logfile json) + REQUIRES esp_http_client jomjol_logfile jomjol_flowcontroll json) diff --git a/code/components/jomjol_webhook/interface_webhook.cpp b/code/components/jomjol_webhook/interface_webhook.cpp index fef61dfb6..a77d13992 100644 --- a/code/components/jomjol_webhook/interface_webhook.cpp +++ b/code/components/jomjol_webhook/interface_webhook.cpp @@ -8,6 +8,7 @@ #include "time_sntp.h" #include "../../include/defines.h" #include +#include static const char *TAG = "WEBHOOK"; @@ -23,17 +24,26 @@ void WebhookInit(std::string _uri, std::string _apiKey) _webhookApiKey = _apiKey; } -void WebhookPublish(std::string _value,std::string _valueraw,std::string _error,std::string _rate,std::string _timestamp, long int _timeUTC) +void WebhookPublish(std::vector* numbers) { - cJSON *json = cJSON_CreateObject(); - cJSON_AddStringToObject(json, "value", _value.c_str()); - cJSON_AddStringToObject(json, "valueraw", _valueraw.c_str()); - cJSON_AddStringToObject(json, "error", _error.c_str()); - cJSON_AddStringToObject(json, "rate", _rate.c_str()); - cJSON_AddStringToObject(json, "timestamp", _timestamp.c_str()); - cJSON_AddNumberToObject(json, "timeUTC", _timeUTC); - char *jsonString = cJSON_PrintUnformatted(json); + cJSON *jsonArray = cJSON_CreateArray(); + + for (int i = 0; i < (*numbers).size(); ++i) + { + cJSON *json = cJSON_CreateObject(); + cJSON_AddStringToObject(json, "name", (*numbers)[i]->name.c_str()); + cJSON_AddStringToObject(json, "value", (*numbers)[i]->ReturnValue.c_str()); + cJSON_AddStringToObject(json, "valueraw", (*numbers)[i]->ReturnRawValue.c_str()); + cJSON_AddStringToObject(json, "error", (*numbers)[i]->ErrorMessageText.c_str()); + cJSON_AddStringToObject(json, "rate", (*numbers)[i]->ReturnRateValue.c_str()); + cJSON_AddStringToObject(json, "timestamp", (*numbers)[i]->timeStamp.c_str()); + cJSON_AddNumberToObject(json, "timeUTC", (*numbers)[i]->timeStampTimeUTC); + + cJSON_AddItemToArray(jsonArray, json); + } + + char *jsonString = cJSON_PrintUnformatted(jsonArray); LogFile.WriteToFile(ESP_LOG_INFO, TAG, "sending webhook"); LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "sending JSON: " + std::string(jsonString)); @@ -65,8 +75,10 @@ void WebhookPublish(std::string _value,std::string _valueraw,std::string _error, LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "HTTP request failed"); } + + esp_http_client_cleanup(http_client); - cJSON_Delete(json); + cJSON_Delete(jsonArray); free(jsonString); } diff --git a/code/components/jomjol_webhook/interface_webhook.h b/code/components/jomjol_webhook/interface_webhook.h index c3cfa5346..0d1cb0dd1 100644 --- a/code/components/jomjol_webhook/interface_webhook.h +++ b/code/components/jomjol_webhook/interface_webhook.h @@ -7,9 +7,10 @@ #include #include #include +#include void WebhookInit(std::string _webhookURI, std::string _apiKey); -void WebhookPublish(std::string _value,std::string _valueraw,std::string _error,std::string _rate,std::string _timestamp, long int _timeUTC); +void WebhookPublish(std::vector* numbers); #endif //INTERFACE_WEBHOOK_H #endif //ENABLE_WEBHOOK \ No newline at end of file From 6529252a96e4920a306aed05cd457fc24dda90d5 Mon Sep 17 00:00:00 2001 From: rahehl Date: Fri, 9 Aug 2024 11:23:41 +0200 Subject: [PATCH 07/17] webhook JSON is now closer to the data log in CSV format --- .../jomjol_webhook/interface_webhook.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/code/components/jomjol_webhook/interface_webhook.cpp b/code/components/jomjol_webhook/interface_webhook.cpp index a77d13992..678bac548 100644 --- a/code/components/jomjol_webhook/interface_webhook.cpp +++ b/code/components/jomjol_webhook/interface_webhook.cpp @@ -27,19 +27,23 @@ void WebhookInit(std::string _uri, std::string _apiKey) void WebhookPublish(std::vector* numbers) { + + cJSON *jsonArray = cJSON_CreateArray(); for (int i = 0; i < (*numbers).size(); ++i) { cJSON *json = cJSON_CreateObject(); + cJSON_AddNumberToObject(json, "timeUTC", (*numbers)[i]->timeStampTimeUTC); + cJSON_AddStringToObject(json, "timestamp", (*numbers)[i]->timeStamp.c_str()); cJSON_AddStringToObject(json, "name", (*numbers)[i]->name.c_str()); + cJSON_AddStringToObject(json, "rawValue", (*numbers)[i]->ReturnRawValue.c_str()); cJSON_AddStringToObject(json, "value", (*numbers)[i]->ReturnValue.c_str()); - cJSON_AddStringToObject(json, "valueraw", (*numbers)[i]->ReturnRawValue.c_str()); - cJSON_AddStringToObject(json, "error", (*numbers)[i]->ErrorMessageText.c_str()); + cJSON_AddStringToObject(json, "preValue", (*numbers)[i]->ReturnPreValue.c_str()); cJSON_AddStringToObject(json, "rate", (*numbers)[i]->ReturnRateValue.c_str()); - cJSON_AddStringToObject(json, "timestamp", (*numbers)[i]->timeStamp.c_str()); - cJSON_AddNumberToObject(json, "timeUTC", (*numbers)[i]->timeStampTimeUTC); - + cJSON_AddStringToObject(json, "changeAbsolute", (*numbers)[i]->ReturnChangeAbsolute.c_str()); + cJSON_AddStringToObject(json, "error", (*numbers)[i]->ErrorMessageText.c_str()); + cJSON_AddItemToArray(jsonArray, json); } From c335d0df9fa16dc6bf4b35e2222df645762642e5 Mon Sep 17 00:00:00 2001 From: rahehl Date: Fri, 9 Aug 2024 13:59:55 +0200 Subject: [PATCH 08/17] webhook: add img upload --- .../jomjol_flowcontroll/ClassFlowWebhook.cpp | 22 +++++++- .../jomjol_flowcontroll/ClassFlowWebhook.h | 6 ++- .../jomjol_webhook/interface_webhook.cpp | 54 ++++++++++++++++--- .../jomjol_webhook/interface_webhook.h | 3 +- 4 files changed, 73 insertions(+), 12 deletions(-) diff --git a/code/components/jomjol_flowcontroll/ClassFlowWebhook.cpp b/code/components/jomjol_flowcontroll/ClassFlowWebhook.cpp index a60919bda..fd9971ad2 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowWebhook.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowWebhook.cpp @@ -8,6 +8,7 @@ #include "interface_webhook.h" #include "ClassFlowPostProcessing.h" +#include "ClassFlowAlignment.h" #include "esp_log.h" #include "../../include/defines.h" @@ -20,11 +21,13 @@ static const char* TAG = "WEBHOOK"; void ClassFlowWebhook::SetInitialParameter(void) { uri = ""; - flowpostprocessing = NULL; + flowpostprocessing = NULL; + flowAlignment = NULL; previousElement = NULL; ListFlowControll = NULL; disabled = false; WebhookEnable = false; + WebhookUploadImg = 1; //todo read from param } ClassFlowWebhook::ClassFlowWebhook() @@ -43,6 +46,11 @@ ClassFlowWebhook::ClassFlowWebhook(std::vector* lfc) { flowpostprocessing = (ClassFlowPostProcessing*) (*ListFlowControll)[i]; } + if (((*ListFlowControll)[i])->name().compare("ClassFlowAlignment") == 0) + { + flowAlignment = (ClassFlowAlignment*) (*ListFlowControll)[i]; + } + } } @@ -59,6 +67,10 @@ ClassFlowWebhook::ClassFlowWebhook(std::vector* lfc, ClassFlow *_pre { flowpostprocessing = (ClassFlowPostProcessing*) (*ListFlowControll)[i]; } + if (((*ListFlowControll)[i])->name().compare("ClassFlowAlignment") == 0) + { + flowAlignment = (ClassFlowAlignment*) (*ListFlowControll)[i]; + } } } @@ -135,7 +147,13 @@ bool ClassFlowWebhook::doFlow(string zwtime) if (flowpostprocessing) { printf("vor sende WebHook"); - WebhookPublish(flowpostprocessing->GetNumbers()); + bool numbersWithError = WebhookPublish(flowpostprocessing->GetNumbers()); + + #ifdef ALGROI_LOAD_FROM_MEM_AS_JPG + if ((WebhookUploadImg == 1 || (WebhookUploadImg != 0 && numbersWithError)) && flowAlignment && flowAlignment->AlgROI) { + WebhookUploadPic(flowAlignment->AlgROI); + } + #endif } return true; diff --git a/code/components/jomjol_flowcontroll/ClassFlowWebhook.h b/code/components/jomjol_flowcontroll/ClassFlowWebhook.h index 3900fc092..8f679d42f 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowWebhook.h +++ b/code/components/jomjol_flowcontroll/ClassFlowWebhook.h @@ -8,6 +8,7 @@ #include "ClassFlow.h" #include "ClassFlowPostProcessing.h" +#include "ClassFlowAlignment.h" #include @@ -16,8 +17,11 @@ class ClassFlowWebhook : { protected: std::string uri, apikey; - ClassFlowPostProcessing* flowpostprocessing; + ClassFlowPostProcessing* flowpostprocessing; + ClassFlowAlignment* flowAlignment; + bool WebhookEnable; + int WebhookUploadImg; void SetInitialParameter(void); diff --git a/code/components/jomjol_webhook/interface_webhook.cpp b/code/components/jomjol_webhook/interface_webhook.cpp index 678bac548..0e8576e2d 100644 --- a/code/components/jomjol_webhook/interface_webhook.cpp +++ b/code/components/jomjol_webhook/interface_webhook.cpp @@ -24,11 +24,9 @@ void WebhookInit(std::string _uri, std::string _apiKey) _webhookApiKey = _apiKey; } -void WebhookPublish(std::vector* numbers) +bool WebhookPublish(std::vector* numbers) { - - - + bool numbersWithError = false; cJSON *jsonArray = cJSON_CreateArray(); for (int i = 0; i < (*numbers).size(); ++i) @@ -45,6 +43,10 @@ void WebhookPublish(std::vector* numbers) cJSON_AddStringToObject(json, "error", (*numbers)[i]->ErrorMessageText.c_str()); cJSON_AddItemToArray(jsonArray, json); + + if ((*numbers)[i]->ErrorMessage) { + numbersWithError = true; + } } char *jsonString = cJSON_PrintUnformatted(jsonArray); @@ -77,15 +79,51 @@ void WebhookPublish(std::vector* numbers) LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "HTTP status code: " + std::to_string(status_code)); } else { LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "HTTP request failed"); - } - - + } - esp_http_client_cleanup(http_client); cJSON_Delete(jsonArray); free(jsonString); + esp_http_client_cleanup(http_client); + + return numbersWithError; +} + +void WebhookUploadPic(ImageData *Img) { + LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Starting WebhookUploadPic"); + + char response_buffer[MAX_HTTP_OUTPUT_BUFFER] = {0}; + esp_http_client_config_t http_config = { + .url = _webhookURI.c_str(), + .user_agent = "ESP32 Meter reader", + .method = HTTP_METHOD_PUT, + .event_handler = http_event_handler, + .buffer_size = MAX_HTTP_OUTPUT_BUFFER, + .user_data = response_buffer + }; + + esp_http_client_handle_t http_client = esp_http_client_init(&http_config); + + esp_http_client_set_header(http_client, "Content-Type", "image/jpeg"); + esp_http_client_set_header(http_client, "APIKEY", _webhookApiKey.c_str()); + + esp_err_t err = ESP_ERROR_CHECK_WITHOUT_ABORT(esp_http_client_set_post_field(http_client, (const char *)Img->data, Img->size)); + + err = ESP_ERROR_CHECK_WITHOUT_ABORT(esp_http_client_perform(http_client)); + + if (err == ESP_OK) { + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "HTTP PUT request was performed successfully"); + 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_ERROR, TAG, "HTTP PUT request failed"); + } + + esp_http_client_cleanup(http_client); + + LogFile.WriteToFile(ESP_LOG_INFO, TAG, "WebhookUploadPic finished"); } + static esp_err_t http_event_handler(esp_http_client_event_t *evt) { switch(evt->event_id) diff --git a/code/components/jomjol_webhook/interface_webhook.h b/code/components/jomjol_webhook/interface_webhook.h index 0d1cb0dd1..d7033be09 100644 --- a/code/components/jomjol_webhook/interface_webhook.h +++ b/code/components/jomjol_webhook/interface_webhook.h @@ -10,7 +10,8 @@ #include void WebhookInit(std::string _webhookURI, std::string _apiKey); -void WebhookPublish(std::vector* numbers); +bool WebhookPublish(std::vector* numbers); +void WebhookUploadPic(ImageData *Img); #endif //INTERFACE_WEBHOOK_H #endif //ENABLE_WEBHOOK \ No newline at end of file From 67ab7fc24f6cd0f37b260a22700558f64a35c17c Mon Sep 17 00:00:00 2001 From: rahehl Date: Fri, 9 Aug 2024 15:06:52 +0200 Subject: [PATCH 09/17] webhoop added config for imgupload --- .../jomjol_flowcontroll/ClassFlowWebhook.cpp | 12 +++++++++++- param-docs/parameter-pages/Webhook/UploadImg.md | 8 ++++++++ sd-card/config/config.ini | 1 + sd-card/html/edit_config_template.html | 16 ++++++++++++++++ sd-card/html/readconfigparam.js | 1 + 5 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 param-docs/parameter-pages/Webhook/UploadImg.md diff --git a/code/components/jomjol_flowcontroll/ClassFlowWebhook.cpp b/code/components/jomjol_flowcontroll/ClassFlowWebhook.cpp index fd9971ad2..5194c82b4 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowWebhook.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowWebhook.cpp @@ -27,7 +27,7 @@ void ClassFlowWebhook::SetInitialParameter(void) ListFlowControll = NULL; disabled = false; WebhookEnable = false; - WebhookUploadImg = 1; //todo read from param + WebhookUploadImg = 0; } ClassFlowWebhook::ClassFlowWebhook() @@ -105,6 +105,16 @@ bool ClassFlowWebhook::ReadParameter(FILE* pfile, string& aktparamgraph) { this->apikey = splitted[1]; } + if (((toUpper(_param) == "UPLOADIMG")) && (splitted.size() > 1)) + { + if (toUpper(splitted[1]) == "1") + { + this->WebhookUploadImg = 1; + } else if (toUpper(splitted[1]) == "2") + { + this->WebhookUploadImg = 2; + } + } } WebhookInit(uri,apikey); diff --git a/param-docs/parameter-pages/Webhook/UploadImg.md b/param-docs/parameter-pages/Webhook/UploadImg.md new file mode 100644 index 000000000..fb375642f --- /dev/null +++ b/param-docs/parameter-pages/Webhook/UploadImg.md @@ -0,0 +1,8 @@ +# Parameter `UploadImg` +Default Value: `0` (`NEVER`) + +Available options: + +- `0`: `NEVER` +- `1`: `ALWAYS` +- `2`: `ON_ERROR` \ No newline at end of file diff --git a/sd-card/config/config.ini b/sd-card/config/config.ini index 8f40444e5..0efa3d322 100644 --- a/sd-card/config/config.ini +++ b/sd-card/config/config.ini @@ -106,6 +106,7 @@ HomeassistantDiscovery = false ;[Webhook] ;Uri = undefined ;ApiKey = undefined +;UploadImg = 0 ;[GPIO] ;MainTopicMQTT = wasserzaehler/GPIO diff --git a/sd-card/html/edit_config_template.html b/sd-card/html/edit_config_template.html index 713834095..9da39373b 100644 --- a/sd-card/html/edit_config_template.html +++ b/sd-card/html/edit_config_template.html @@ -1355,6 +1355,20 @@

$TOOLTIP_Webhook_ApiKey + + + Upload Image + + + + + $TOOLTIP_Webhook_UploadImg + + @@ -2283,6 +2297,7 @@

Date: Fri, 9 Aug 2024 20:55:51 +0200 Subject: [PATCH 10/17] webhook html fixes --- sd-card/html/edit_config_template.html | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sd-card/html/edit_config_template.html b/sd-card/html/edit_config_template.html index 9da39373b..3459f60c2 100644 --- a/sd-card/html/edit_config_template.html +++ b/sd-card/html/edit_config_template.html @@ -1329,7 +1329,8 @@

-

+ +

@@ -1357,7 +1358,7 @@

- Upload Image + From 086e1ddfaa67dd6c6c5865d7c709cfe5056e6047 Mon Sep 17 00:00:00 2001 From: CaCO3 Date: Sun, 25 Aug 2024 19:39:16 +0200 Subject: [PATCH 13/17] Update sd-card/html/edit_config_template.html --- sd-card/html/edit_config_template.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sd-card/html/edit_config_template.html b/sd-card/html/edit_config_template.html index 8a8fd6ff3..4e1df32b0 100644 --- a/sd-card/html/edit_config_template.html +++ b/sd-card/html/edit_config_template.html @@ -2298,7 +2298,7 @@

- + + From 6b88121227fbc82b04aaee87c6ee0bda75d5b5e7 Mon Sep 17 00:00:00 2001 From: rahehl Date: Fri, 30 Aug 2024 22:24:41 +0200 Subject: [PATCH 17/17] added a long timestamp to both webhook requests --- code/components/jomjol_webhook/interface_webhook.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/code/components/jomjol_webhook/interface_webhook.cpp b/code/components/jomjol_webhook/interface_webhook.cpp index 0973d6083..54d4c48ed 100644 --- a/code/components/jomjol_webhook/interface_webhook.cpp +++ b/code/components/jomjol_webhook/interface_webhook.cpp @@ -15,6 +15,7 @@ static const char *TAG = "WEBHOOK"; std::string _webhookURI; std::string _webhookApiKey; +long _lastTimestamp; static esp_err_t http_event_handler(esp_http_client_event_t *evt); @@ -22,6 +23,7 @@ void WebhookInit(std::string _uri, std::string _apiKey) { _webhookURI = _uri; _webhookApiKey = _apiKey; + _lastTimestamp = 0L; } bool WebhookPublish(std::vector* numbers) @@ -33,12 +35,15 @@ bool WebhookPublish(std::vector* numbers) { string timezw = ""; char buffer[80]; - struct tm* timeinfo = localtime(&(*numbers)[i]->timeStampLastPreValue); + time_t &lastPreValue = (*numbers)[i]->timeStampLastPreValue; + struct tm* timeinfo = localtime(&lastPreValue); + _lastTimestamp = static_cast(lastPreValue); strftime(buffer, 80, PREVALUE_TIME_FORMAT_OUTPUT, timeinfo); timezw = std::string(buffer); cJSON *json = cJSON_CreateObject(); cJSON_AddStringToObject(json, "timestamp", timezw.c_str()); + cJSON_AddStringToObject(json, "timestampLong", std::to_string(_lastTimestamp).c_str()); cJSON_AddStringToObject(json, "name", (*numbers)[i]->name.c_str()); cJSON_AddStringToObject(json, "rawValue", (*numbers)[i]->ReturnRawValue.c_str()); cJSON_AddStringToObject(json, "value", (*numbers)[i]->ReturnValue.c_str()); @@ -95,9 +100,10 @@ bool WebhookPublish(std::vector* numbers) void WebhookUploadPic(ImageData *Img) { LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Starting WebhookUploadPic"); + std::string fullURI = _webhookURI + "?timestamp=" + std::to_string(_lastTimestamp); char response_buffer[MAX_HTTP_OUTPUT_BUFFER] = {0}; esp_http_client_config_t http_config = { - .url = _webhookURI.c_str(), + .url = fullURI.c_str(), .user_agent = "ESP32 Meter reader", .method = HTTP_METHOD_PUT, .event_handler = http_event_handler,