Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add Webhook #3148 #3163

Merged
merged 10 commits into from
Aug 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion code/components/jomjol_flowcontroll/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)


15 changes: 14 additions & 1 deletion code/components/jomjol_flowcontroll/ClassFlowControll.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,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){
Expand Down Expand Up @@ -109,7 +114,11 @@ std::string ClassFlowControll::TranslateAktstatus(std::string _input)
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");
}
Expand Down Expand Up @@ -251,6 +260,10 @@ ClassFlow* ClassFlowControll::CreateClassFlow(std::string _type)
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) {
cfc = new ClassFlowPostProcessing(&FlowControll, flowanalog, flowdigit);
Expand Down
3 changes: 3 additions & 0 deletions code/components/jomjol_flowcontroll/ClassFlowControll.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 :
Expand Down
143 changes: 143 additions & 0 deletions code/components/jomjol_flowcontroll/ClassFlowWebhook.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
#ifdef ENABLE_WEBHOOK
#include <sstream>
#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 <time.h>

static const char* TAG = "WEBHOOK";

void ClassFlowWebhook::SetInitialParameter(void)
{
uri = "";
flowpostprocessing = NULL;
previousElement = NULL;
ListFlowControll = NULL;
disabled = false;
WebhookEnable = false;
}

ClassFlowWebhook::ClassFlowWebhook()
{
SetInitialParameter();
}

ClassFlowWebhook::ClassFlowWebhook(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];
}
}
}

ClassFlowWebhook::ClassFlowWebhook(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 ClassFlowWebhook::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("[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) == "APIKEY")) && (splitted.size() > 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::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;

if (flowpostprocessing)
{
printf("vor sende WebHook");
WebhookPublish(flowpostprocessing->GetNumbers());
}

return true;
}
#endif //ENABLE_WEBHOOK
39 changes: 39 additions & 0 deletions code/components/jomjol_flowcontroll/ClassFlowWebhook.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#ifdef ENABLE_WEBHOOK

#pragma once

#ifndef CLASSFWEBHOOK_H
#define CLASSFWEBHOOK_H

#include "ClassFlow.h"

#include "ClassFlowPostProcessing.h"

#include <string>

class ClassFlowWebhook :
public ClassFlow
{
protected:
std::string uri, apikey;
ClassFlowPostProcessing* flowpostprocessing;
bool WebhookEnable;

void SetInitialParameter(void);

void handleFieldname(string _decsep, string _value);
void handleMeasurement(string _decsep, string _value);


public:
ClassFlowWebhook();
ClassFlowWebhook(std::vector<ClassFlow*>* lfc);
ClassFlowWebhook(std::vector<ClassFlow*>* lfc, ClassFlow *_prev);

bool ReadParameter(FILE* pfile, string& aktparamgraph);
bool doFlow(string time);
string name(){return "ClassFlowWebhook";};
};

#endif //CLASSFWEBHOOK_H
#endif //ENABLE_WEBHOOK
7 changes: 7 additions & 0 deletions code/components/jomjol_webhook/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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 jomjol_flowcontroll json)


128 changes: 128 additions & 0 deletions code/components/jomjol_webhook/interface_webhook.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#ifdef ENABLE_WEBHOOK
#include "interface_webhook.h"

#include "esp_log.h"
#include <time.h>
#include "ClassLogFile.h"
#include "esp_http_client.h"
#include "time_sntp.h"
#include "../../include/defines.h"
#include <cJSON.h>
#include <ClassFlowDefineTypes.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::vector<NumberPost*>* numbers)
{




cJSON *jsonArray = cJSON_CreateArray();

for (int i = 0; i < (*numbers).size(); ++i)
{
string timezw = "";
char buffer[80];
struct tm* timeinfo = localtime(&(*numbers)[i]->lastvalue);
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, "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, "preValue", (*numbers)[i]->ReturnPreValue.c_str());
cJSON_AddStringToObject(json, "rate", (*numbers)[i]->ReturnRateValue.c_str());
cJSON_AddStringToObject(json, "changeAbsolute", (*numbers)[i]->ReturnChangeAbsolute.c_str());
cJSON_AddStringToObject(json, "error", (*numbers)[i]->ErrorMessageText.c_str());

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));

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);

esp_http_client_set_header(http_client, "Content-Type", "application/json");
esp_http_client_set_header(http_client, "APIKEY", _webhookApiKey.c_str());

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));
} else {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "HTTP request failed");
}



esp_http_client_cleanup(http_client);
cJSON_Delete(jsonArray);
free(jsonString);
}

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
16 changes: 16 additions & 0 deletions code/components/jomjol_webhook/interface_webhook.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#ifdef ENABLE_WEBHOOK

#pragma once
#ifndef INTERFACE_WEBHOOK_H
#define INTERFACE_WEBHOOK_H

#include <string>
#include <map>
#include <functional>
#include <ClassFlowDefineTypes.h>

void WebhookInit(std::string _webhookURI, std::string _apiKey);
void WebhookPublish(std::vector<NumberPost*>* numbers);

#endif //INTERFACE_WEBHOOK_H
#endif //ENABLE_WEBHOOK
Loading