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

Set prevalue using MQTT + set prevalue to RAW value (REST+MQTT) #2252

Merged
merged 4 commits into from
Mar 28, 2023
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
43 changes: 23 additions & 20 deletions code/components/jomjol_flowcontroll/ClassFlowControll.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -470,10 +470,10 @@ string ClassFlowControll::getReadoutAll(int _type)
}


string ClassFlowControll::getReadout(bool _rawvalue = false, bool _noerror = false)
string ClassFlowControll::getReadout(bool _rawvalue = false, bool _noerror = false, int _number = 0)
{
if (flowpostprocessing)
return flowpostprocessing->getReadoutParam(_rawvalue, _noerror);
return flowpostprocessing->getReadoutParam(_rawvalue, _noerror, _number);

string zw = "";
string result = "";
Expand Down Expand Up @@ -501,37 +501,40 @@ string ClassFlowControll::GetPrevalue(std::string _number)
return flowpostprocessing->GetPreValue(_number);
}


return std::string("");
}


std::string ClassFlowControll::UpdatePrevalue(std::string _newvalue, std::string _numbers, bool _extern)
bool ClassFlowControll::UpdatePrevalue(std::string _newvalue, std::string _numbers, bool _extern)
{
float zw;
double newvalueAsDouble;
char* p;

_newvalue = trim(_newvalue);
// ESP_LOGD(TAG, "Input UpdatePreValue: %s", _newvalue.c_str());
//ESP_LOGD(TAG, "Input UpdatePreValue: %s", _newvalue.c_str());

if (_newvalue.compare("0.0") == 0)
{
zw = 0;
if (_newvalue.substr(0,8).compare("0.000000") == 0 || _newvalue.compare("0.0") == 0 || _newvalue.compare("0") == 0) {
newvalueAsDouble = 0; // preset to value = 0
}
else
{
zw = strtof(_newvalue.c_str(), &p);
if (zw == 0)
return "- Error in String to Value Conversion!!! Must be of format value=123.456";
else {
newvalueAsDouble = strtod(_newvalue.c_str(), &p);
if (newvalueAsDouble == 0) {
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "UpdatePrevalue: No valid value for processing: " + _newvalue);
return false;
}
}


if (flowpostprocessing)
{
flowpostprocessing->SetPreValue(zw, _numbers, _extern);
return _newvalue;
if (flowpostprocessing) {
if (flowpostprocessing->SetPreValue(newvalueAsDouble, _numbers, _extern))
return true;
else
return false;
}
else {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "UpdatePrevalue: ERROR - Class Post-Processing not initialized");
return false;
}

return std::string();
}


Expand Down
4 changes: 2 additions & 2 deletions code/components/jomjol_flowcontroll/ClassFlowControll.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ class ClassFlowControll :
bool doFlow(string time);
void doFlowTakeImageOnly(string time);
bool getStatusSetupModus(){return SetupModeActive;};
string getReadout(bool _rawvalue, bool _noerror);
string getReadout(bool _rawvalue, bool _noerror, int _number);
string getReadoutAll(int _type);
string UpdatePrevalue(std::string _newvalue, std::string _numbers, bool _extern);
bool UpdatePrevalue(std::string _newvalue, std::string _numbers, bool _extern);
string GetPrevalue(std::string _number = "");
bool ReadParameter(FILE* pfile, string& aktparamgraph);
string getJSON();
Expand Down
46 changes: 34 additions & 12 deletions code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,27 +96,49 @@ string ClassFlowPostProcessing::GetPreValue(std::string _number)
return result;
}

void ClassFlowPostProcessing::SetPreValue(double zw, string _numbers, bool _extern)

bool ClassFlowPostProcessing::SetPreValue(double _newvalue, string _numbers, bool _extern)
{
ESP_LOGD(TAG, "SetPrevalue: %f, %s", zw, _numbers.c_str());
for (int j = 0; j < NUMBERS.size(); ++j)
{
// ESP_LOGD(TAG, "Number %d, %s", j, NUMBERS[j]->name.c_str());
if (NUMBERS[j]->name == _numbers)
{
NUMBERS[j]->PreValue = zw;
NUMBERS[j]->ReturnPreValue = std::to_string(zw);
//ESP_LOGD(TAG, "SetPrevalue: %f, %s", zw, _numbers.c_str());

for (int j = 0; j < NUMBERS.size(); ++j) {
//ESP_LOGD(TAG, "Number %d, %s", j, NUMBERS[j]->name.c_str());
if (NUMBERS[j]->name == _numbers) {
if (_newvalue >= 0) { // if new value posivive, use provided value to preset PreValue
NUMBERS[j]->PreValue = _newvalue;
}
else { // if new value negative, use last raw value to preset PreValue
char* p;
double ReturnRawValueAsDouble = strtod(NUMBERS[j]->ReturnRawValue.c_str(), &p);
if (ReturnRawValueAsDouble == 0) {
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "SetPreValue: RawValue not a valid value for further processing: "
+ NUMBERS[j]->ReturnRawValue);
return false;
}
NUMBERS[j]->PreValue = ReturnRawValueAsDouble;
}

NUMBERS[j]->ReturnPreValue = std::to_string(NUMBERS[j]->PreValue);
NUMBERS[j]->PreValueOkay = true;

if (_extern)
{
time(&(NUMBERS[j]->lastvalue));
localtime(&(NUMBERS[j]->lastvalue));
}
// ESP_LOGD(TAG, "Found %d! - set to %f", j, NUMBERS[j]->PreValue);
//ESP_LOGD(TAG, "Found %d! - set to %.8f", j, NUMBERS[j]->PreValue);

UpdatePreValueINI = true; // Only update prevalue file if a new value is set
SavePreValue();

LogFile.WriteToFile(ESP_LOG_INFO, TAG, "SetPreValue: PreValue for " + NUMBERS[j]->name + " set to " +
std::to_string(NUMBERS[j]->PreValue));
return true;
}
}
UpdatePreValueINI = true;
SavePreValue();

LogFile.WriteToFile(ESP_LOG_WARN, TAG, "SetPreValue: Numbersname not found or not valid");
return false; // No new value was set (e.g. wrong numbersname, no numbers at all)
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class ClassFlowPostProcessing :
void SavePreValue();
string getJsonFromNumber(int i, std::string _lineend);
string GetPreValue(std::string _number = "");
void SetPreValue(double zw, string _numbers, bool _extern = false);
bool SetPreValue(double zw, string _numbers, bool _extern = false);

std::string GetJSON(std::string _lineend = "\n");
std::string getNumbersName();
Expand Down
2 changes: 1 addition & 1 deletion code/components/jomjol_mqtt/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*)

idf_component_register(SRCS ${app_sources}
INCLUDE_DIRS "."
REQUIRES tflite-lib mqtt jomjol_tfliteclass jomjol_helper jomjol_mqtt jomjol_wlan)
REQUIRES tflite-lib mqtt jomjol_tfliteclass jomjol_helper jomjol_mqtt jomjol_wlan json)
51 changes: 47 additions & 4 deletions code/components/jomjol_mqtt/interface_mqtt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "mqtt_client.h"
#include "ClassLogFile.h"
#include "server_tflite.h"
#include "cJSON.h"
#include "../../include/defines.h"

static const char *TAG = "MQTT IF";
Expand Down Expand Up @@ -336,17 +337,54 @@ bool getMQTTisConnected() {
}


bool mqtt_handler_flow_start(std::string _topic, char* _data, int _data_len) {
bool mqtt_handler_flow_start(std::string _topic, char* _data, int _data_len)
{
ESP_LOGD(TAG, "Handler called: topic %s, data %.*s", _topic.c_str(), _data_len, _data);

if (_data_len > 0) {
MQTTCtrlFlowStart(_topic);
}
else {
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "handler_flow_start: handler called, but no data");
}

return ESP_OK;
}


bool mqtt_handler_set_prevalue(std::string _topic, char* _data, int _data_len)
{
//ESP_LOGD(TAG, "Handler called: topic %s, data %.*s", _topic.c_str(), _data_len, _data);
//example: {"numbersname": "main", "value": 12345.1234567}

if (_data_len > 0) { // Check if data length > 0
cJSON *jsonData = cJSON_Parse(_data);
cJSON *numbersname = cJSON_GetObjectItemCaseSensitive(jsonData, "numbersname");
cJSON *value = cJSON_GetObjectItemCaseSensitive(jsonData, "value");

if (cJSON_IsString(numbersname) && (numbersname->valuestring != NULL)) { // Check if numbersname is valid
if (cJSON_IsNumber(value)) { // Check if value is a number
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "handler_set_prevalue called: numbersname: " + std::string(numbersname->valuestring) +
", value: " + std::to_string(value->valuedouble));
if (tfliteflow.UpdatePrevalue(std::to_string(value->valuedouble), std::string(numbersname->valuestring), true))
return ESP_OK;
}
else {
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "handler_set_prevalue: value not a valid number (\"value\": 12345.12345)");
}
}
else {
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "handler_set_prevalue: numbersname not a valid string (\"numbersname\": \"main\")");
}
}
else {
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "handler_set_prevalue: handler called, but no data received");
}

return ESP_FAIL;
}


void MQTTconnected(){
if (mqtt_connected) {
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Connected to broker");
Expand All @@ -358,9 +396,14 @@ void MQTTconnected(){
}
}

/* Subcribe to topics */
std::function<bool(std::string topic, char* data, int data_len)> subHandler = mqtt_handler_flow_start;
MQTTregisterSubscribeFunction(maintopic + "/ctrl/flow_start", subHandler); // subcribe to maintopic/ctrl/flow_start
// Subcribe to topics
// Note: Further subsriptions are handled in GPIO class
//*****************************************
std::function<bool(std::string topic, char* data, int data_len)> subHandler1 = mqtt_handler_flow_start;
MQTTregisterSubscribeFunction(maintopic + "/ctrl/flow_start", subHandler1); // subcribe to maintopic/ctrl/flow_start

std::function<bool(std::string topic, char* data, int data_len)> subHandler2 = mqtt_handler_set_prevalue;
MQTTregisterSubscribeFunction(maintopic + "/ctrl/set_prevalue", subHandler2); // subcribe to maintopic/ctrl/set_prevalue

if (subscribeFunktionMap != NULL) {
for(std::map<std::string, std::function<bool(std::string, char*, int)>>::iterator it = subscribeFunktionMap->begin(); it != subscribeFunktionMap->end(); ++it) {
Expand Down
91 changes: 61 additions & 30 deletions code/components/jomjol_tfliteclass/server_tflite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req)
}


zw = tfliteflow.getReadout(_rawValue, _noerror);
zw = tfliteflow.getReadout(_rawValue, _noerror, 0);
if (zw.length() > 0)
httpd_resp_sendstr_chunk(req, zw.c_str());

Expand Down Expand Up @@ -706,7 +706,7 @@ esp_err_t handler_editflow(httpd_req_t *req)
esp_err_t handler_statusflow(httpd_req_t *req)
{
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_prevalue - Start");
LogFile.WriteHeapInfo("handler_statusflow - Start");
#endif

const char* resp_str;
Expand All @@ -715,7 +715,7 @@ esp_err_t handler_statusflow(httpd_req_t *req)
if (bTaskAutoFlowCreated)
{
#ifdef DEBUG_DETAIL_ON
ESP_LOGD(TAG, "handler_prevalue: %s", req->uri);
ESP_LOGD(TAG, "handler_statusflow: %s", req->uri);
#endif

string* zw = tfliteflow.getActStatusWithTime();
Expand All @@ -730,7 +730,7 @@ esp_err_t handler_statusflow(httpd_req_t *req)
}

#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_prevalue - Done");
LogFile.WriteHeapInfo("handler_statusflow - Done");
#endif

return ESP_OK;
Expand Down Expand Up @@ -802,50 +802,81 @@ esp_err_t handler_uptime(httpd_req_t *req)
esp_err_t handler_prevalue(httpd_req_t *req)
{
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_prevalue - Start");
LogFile.WriteHeapInfo("handler_prevalue - Start");
ESP_LOGD(TAG, "handler_prevalue: %s", req->uri);
#endif

const char* resp_str;
string zw;
// Default usage message when handler gets called without any parameter
const std::string RESTUsageInfo =
"00: Handler usage:<br>"
"- To retrieve actual PreValue, please provide only a numbersname, e.g. /setPreValue?numbers=main<br>"
"- To set PreValue to a new value, please provide a numbersname and a value, e.g. /setPreValue?numbers=main&value=1234.5678<br>"
"NOTE:<br>"
"value >= 0.0: Set PreValue to provided value<br>"
"value < 0.0: Set PreValue to actual RAW value (as long RAW value is a valid number, without N)";

#ifdef DEBUG_DETAIL_ON
ESP_LOGD(TAG, "handler_prevalue: %s", req->uri);
#endif
// Default return error message when no return is programmed
std::string sReturnMessage = "E90: Uninitialized";

char _query[100];
char _size[10] = "";
char _numbers[50] = "default";
char _numbersname[50] = "default";
char _value[20] = "";

if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK)
{
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");

if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK) {
#ifdef DEBUG_DETAIL_ON
ESP_LOGD(TAG, "Query: %s", _query);
#endif

if (httpd_query_key_value(_query, "value", _size, 10) == ESP_OK)
{
if (httpd_query_key_value(_query, "numbers", _numbersname, 50) != ESP_OK) { // If request is incomplete
sReturnMessage = "E91: Query parameter incomplete or not valid!<br> "
"Call /setPreValue to show REST API usage info and/or check documentation";
httpd_resp_send(req, sReturnMessage.c_str(), sReturnMessage.length());
return ESP_FAIL;
}

if (httpd_query_key_value(_query, "value", _value, 20) == ESP_OK) {
#ifdef DEBUG_DETAIL_ON
ESP_LOGD(TAG, "Value: %s", _size);
#endif
}
}
else { // if no parameter is provided, print handler usage
httpd_resp_send(req, RESTUsageInfo.c_str(), RESTUsageInfo.length());
return ESP_OK;
}

if (strlen(_value) == 0) { // If no value is povided --> return actual PreValue
sReturnMessage = tfliteflow.GetPrevalue(std::string(_numbersname));

if (sReturnMessage.empty()) {
sReturnMessage = "E92: Numbers name not found";
httpd_resp_send(req, sReturnMessage.c_str(), sReturnMessage.length());
return ESP_FAIL;
}
}
else {
// New value is positive: Set PreValue to provided value and return value
// New value is negative and actual RAW value is a valid number: Set PreValue to RAW value and return value
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "REST API handler_prevalue called: numbersname: " + std::string(_numbersname) +
", value: " + std::string(_value));
if (!tfliteflow.UpdatePrevalue(_value, _numbersname, true)) {
sReturnMessage = "E93: Update request rejected. Please check device logs for more details";
httpd_resp_send(req, sReturnMessage.c_str(), sReturnMessage.length());
return ESP_FAIL;
}

httpd_query_key_value(_query, "numbers", _numbers, 50);
}
sReturnMessage = tfliteflow.GetPrevalue(std::string(_numbersname));

if (strlen(_size) == 0)
{
zw = tfliteflow.GetPrevalue(std::string(_numbers));
}
else
{
zw = "SetPrevalue to " + tfliteflow.UpdatePrevalue(_size, _numbers, true);
if (sReturnMessage.empty()) {
sReturnMessage = "E94: Numbers name not found";
httpd_resp_send(req, sReturnMessage.c_str(), sReturnMessage.length());
return ESP_FAIL;
}
}

resp_str = zw.c_str();

httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");

httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN);
httpd_resp_send(req, sReturnMessage.c_str(), sReturnMessage.length());

#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_prevalue - End");
Expand Down