Skip to content

Commit

Permalink
Set prevalue using MQTT + set prevalue to RAW value (REST+MQTT) (#2252)
Browse files Browse the repository at this point in the history
* Use double instead of float

* Error handling + set to RAW if newvalue < 0

* REST SetPrevalue: Set to RAW if newvalue < 0

* set prevalue with MQTT
  • Loading branch information
Slider0007 authored Mar 28, 2023
1 parent f79e03f commit b6bfeea
Show file tree
Hide file tree
Showing 7 changed files with 169 additions and 70 deletions.
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

0 comments on commit b6bfeea

Please sign in to comment.