compatibitly mit esp-idf pure

This commit is contained in:
jomjol
2020-11-20 19:34:55 +01:00
parent 1cba7d3e1d
commit 1a0feb4f19
308 changed files with 4163 additions and 4382 deletions

View File

@@ -0,0 +1,7 @@
FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*)
idf_component_register(SRCS ${app_sources}
INCLUDE_DIRS "."
REQUIRES jomjol_tfliteclass jomjol_helper jomjol_controlcamera jomjol_mqtt jomjol_fileserver_ota)

View File

@@ -0,0 +1,114 @@
#include "ClassFlow.h"
#include <fstream>
#include <string>
#include <iostream>
#include <string.h>
void ClassFlow::SetInitialParameter(void)
{
ListFlowControll = NULL;
}
std::vector<string> ClassFlow::ZerlegeZeile(std::string input)
{
std::vector<string> Output;
std::string delimiter = " =,";
input = trim(input, delimiter);
size_t pos = findDelimiterPos(input, delimiter);
std::string token;
while (pos != std::string::npos) {
token = input.substr(0, pos);
token = trim(token, delimiter);
Output.push_back(token);
input.erase(0, pos + 1);
input = trim(input, delimiter);
pos = findDelimiterPos(input, delimiter);
}
Output.push_back(input);
return Output;
}
bool ClassFlow::isNewParagraph(string input)
{
if (input[0] == '[')
return true;
return false;
}
bool ClassFlow::GetNextParagraph(FILE* pfile, string& aktparamgraph)
{
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph));
if (this->isNewParagraph(aktparamgraph))
return true;
return false;
}
ClassFlow::ClassFlow(void)
{
SetInitialParameter();
ListFlowControll = NULL;
}
ClassFlow::ClassFlow(std::vector<ClassFlow*> * lfc)
{
SetInitialParameter();
ListFlowControll = lfc;
}
bool ClassFlow::ReadParameter(FILE* pfile, string &aktparamgraph)
{
return false;
}
bool ClassFlow::doFlow(string time)
{
return false;
}
string ClassFlow::getHTMLSingleStep(string host){
return "";
}
string ClassFlow::getReadout()
{
return string();
}
bool ClassFlow::getNextLine(FILE* pfile, string *rt)
{
char zw[1024];
if (pfile == NULL)
{
*rt = "";
return false;
}
fgets(zw, 1024, pfile);
printf("%s", zw);
if ((strlen(zw) == 0) && feof(pfile))
{
*rt = "";
return false;
}
*rt = zw;
*rt = trim(*rt);
while (zw[0] == '#' || (rt->size() == 0)) // Kommentarzeilen und Leerzeilen überspringen
{
fgets(zw, 1024, pfile);
printf("%s", zw);
if (feof(pfile))
{
*rt = "";
return false;
}
*rt = zw;
*rt = trim(*rt);
}
return true;
}

View File

@@ -0,0 +1,45 @@
#pragma once
#include <fstream>
#include <string>
#include <vector>
#include "Helper.h"
#include "CFindTemplate.h"
using namespace std;
#define LOGFILE_TIME_FORMAT "%Y%m%d-%H%M%S"
#define LOGFILE_TIME_FORMAT_DATE_EXTR substr(0, 8)
#define LOGFILE_TIME_FORMAT_HOUR_EXTR substr(9, 2)
struct HTMLInfo
{
float val;
std::string filename;
};
class ClassFlow
{
protected:
std::vector<string> ZerlegeZeile(string input);
bool isNewParagraph(string input);
bool GetNextParagraph(FILE* pfile, string& aktparamgraph);
bool getNextLine(FILE* pfile, string* rt);
std::vector<ClassFlow*>* ListFlowControll;
virtual void SetInitialParameter(void);
public:
ClassFlow(void);
ClassFlow(std::vector<ClassFlow*> * lfc);
virtual bool ReadParameter(FILE* pfile, string &aktparamgraph);
virtual bool doFlow(string time);
virtual string getHTMLSingleStep(string host);
virtual string getReadout();
virtual string name(){return "ClassFlow";};
};

View File

@@ -0,0 +1,151 @@
#include "ClassFlowAlignment.h"
#include "ClassLogFile.h"
ClassFlowAlignment::ClassFlowAlignment()
{
initalrotate = 0;
anz_ref = 0;
suchex = 40;
suchey = 40;
initialmirror = false;
namerawimage = "/sdcard/img_tmp/raw.jpg";
ListFlowControll = NULL;
}
ClassFlowAlignment::ClassFlowAlignment(std::vector<ClassFlow*>* lfc)
{
initalrotate = 0;
anz_ref = 0;
suchex = 40;
suchey = 40;
initialmirror = false;
namerawimage = "/sdcard/img_tmp/raw.jpg";
ListFlowControll = lfc;
}
bool ClassFlowAlignment::ReadParameter(FILE* pfile, string& aktparamgraph)
{
std::vector<string> zerlegt;
aktparamgraph = trim(aktparamgraph);
if (aktparamgraph.size() == 0)
if (!this->GetNextParagraph(pfile, aktparamgraph))
return false;
if (aktparamgraph.compare("[Alignment]") != 0) // Paragraph passt nich zu MakeImage
return false;
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
{
zerlegt = this->ZerlegeZeile(aktparamgraph);
if ((zerlegt[0] == "InitialMirror") && (zerlegt.size() > 1))
{
if (toUpper(zerlegt[1]) == "TRUE")
initialmirror = true;
}
if (((zerlegt[0] == "InitalRotate") || (zerlegt[0] == "InitialRotate")) && (zerlegt.size() > 1))
{
this->initalrotate = std::stod(zerlegt[1]);
}
if ((zerlegt[0] == "SearchFieldX") && (zerlegt.size() > 1))
{
this->suchex = std::stod(zerlegt[1]);
}
if ((zerlegt[0] == "SearchFieldY") && (zerlegt.size() > 1))
{
this->suchey = std::stod(zerlegt[1]);
}
if ((zerlegt.size() == 3) && (anz_ref < 2))
{
this->reffilename[anz_ref] = FormatFileName("/sdcard" + zerlegt[0]);
this->ref_x[anz_ref] = std::stod(zerlegt[1]);
this->ref_y[anz_ref] = std::stod(zerlegt[2]);
anz_ref++;
}
}
return true;
}
string ClassFlowAlignment::getHTMLSingleStep(string host)
{
string result;
result = "<p>Rotated Image: </p> <p><img src=\"" + host + "/img_tmp/rot.jpg\"></p>\n";
result = result + "<p>Found Alignment: </p> <p><img src=\"" + host + "/img_tmp/rot_roi.jpg\"></p>\n";
result = result + "<p>Aligned Image: </p> <p><img src=\"" + host + "/img_tmp/alg.jpg\"></p>\n";
return result;
}
bool ClassFlowAlignment::doFlow(string time)
{
string input = namerawimage;
string output = "/sdcard/img_tmp/rot.jpg";
string output3 = "/sdcard/img_tmp/rot_roi.jpg";
string output2 = "/sdcard/img_tmp/alg.jpg";
string output4 = "/sdcard/img_tmp/alg_roi.jpg";
string output1 = "/sdcard/img_tmp/mirror.jpg";
input = FormatFileName(input);
output = FormatFileName(output);
output2 = FormatFileName(output2);
if (initialmirror){
CRotate *rt;
rt = new CRotate(input);
if (!rt->ImageOkay()){
LogFile.WriteToFile("ClassFlowAlignment::doFlow CRotate Inital Mirror raw.jpg not okay!");
delete rt;
return false;
}
printf("do mirror\n");
rt->Mirror();
rt->SaveToFile(output1);
input = output1;
delete rt;
}
if (initalrotate != 0)
{
CRotate *rt = NULL;
printf("Load rotationfile: %s\n", input.c_str());
rt = new CRotate(input);
if (!rt->ImageOkay()){
LogFile.WriteToFile("ClassFlowAlignment::doFlow CRotate raw.jpg not okay!");
delete rt;
return false;
}
rt->Rotate(this->initalrotate);
rt->SaveToFile(output);
delete rt;
}
else
{
CopyFile(input, output);
}
CAlignAndCutImage *caic;
caic = new CAlignAndCutImage(output);
caic->Align(this->reffilename[0], this->ref_x[0], this->ref_y[0], this->reffilename[1], this->ref_x[1], this->ref_y[1], suchex, suchey, output3);
caic->SaveToFile(output2);
printf("Startwriting Output4:%s\n", output4.c_str());
if (output4.length() > 0)
{
caic->drawRect(ref_x[0], ref_y[0], caic->t0_dx, caic->t0_dy, 255, 0, 0, 2);
caic->drawRect(ref_x[1], ref_y[1], caic->t1_dx, caic->t1_dy, 255, 0, 0, 2);
caic->SaveToFile(output4);
printf("Write output4: %s\n", output4.c_str());
}
delete caic;
// Align mit Templates
return true;
}

View File

@@ -0,0 +1,30 @@
#pragma once
#include "ClassFlow.h"
#include "Helper.h"
#include <string>
using namespace std;
class ClassFlowAlignment :
public ClassFlow
{
protected:
float initalrotate;
bool initialmirror;
string reffilename[2];
int ref_x[2], ref_y[2];
int anz_ref;
int suchex, suchey;
string namerawimage;
public:
ClassFlowAlignment();
ClassFlowAlignment(std::vector<ClassFlow*>* lfc);
bool ReadParameter(FILE* pfile, string& aktparamgraph);
bool doFlow(string time);
string getHTMLSingleStep(string host);
string name(){return "ClassFlowAlignment";};
};

View File

@@ -0,0 +1,308 @@
#include "ClassFlowAnalog.h"
#include <math.h>
#include <iomanip>
#include <sys/types.h>
// #define OHNETFLITE
#ifndef OHNETFLITE
#include "CTfLiteClass.h"
#endif
#include "ClassLogFile.h"
static const char* TAG = "flow_analog";
bool debugdetailanalog = false;
ClassFlowAnalog::ClassFlowAnalog() : ClassFlowImage(TAG)
{
string cnnmodelfile = "";
modelxsize = 1;
modelysize = 1;
ListFlowControll = NULL;
}
ClassFlowAnalog::ClassFlowAnalog(std::vector<ClassFlow*>* lfc) : ClassFlowImage(lfc, TAG)
{
string cnnmodelfile = "";
modelxsize = 1;
modelysize = 1;
}
string ClassFlowAnalog::getReadout()
{
int prev = -1;
string result = "";
for (int i = ROI.size() - 1; i >= 0; --i)
{
prev = ZeigerEval(ROI[i]->result, prev);
result = std::to_string(prev) + result;
}
return result;
}
int ClassFlowAnalog::ZeigerEval(float zahl, int ziffer_vorgaenger)
{
int ergebnis_nachkomma = ((int) floor(zahl * 10)) % 10;
int ergebnis_vorkomma = ((int) floor(zahl)) % 10;
int ergebnis, ergebnis_rating;
if (ziffer_vorgaenger == -1)
return ergebnis_vorkomma % 10;
ergebnis_rating = ergebnis_nachkomma - ziffer_vorgaenger;
if (ergebnis_nachkomma >= 5)
ergebnis_rating-=5;
else
ergebnis_rating+=5;
ergebnis = (int) round(zahl);
if (ergebnis_rating < 0)
ergebnis-=1;
if (ergebnis == -1)
ergebnis+=10;
ergebnis = ergebnis % 10;
return ergebnis;
}
bool ClassFlowAnalog::ReadParameter(FILE* pfile, string& aktparamgraph)
{
std::vector<string> zerlegt;
aktparamgraph = trim(aktparamgraph);
if (aktparamgraph.size() == 0)
if (!this->GetNextParagraph(pfile, aktparamgraph))
return false;
if (aktparamgraph.compare("[Analog]") != 0) // Paragraph passt nich zu MakeImage
return false;
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
{
zerlegt = this->ZerlegeZeile(aktparamgraph);
if ((zerlegt[0] == "LogImageLocation") && (zerlegt.size() > 1))
{
this->LogImageLocation = "/sdcard" + zerlegt[1];
this->isLogImage = true;
}
if ((toUpper(zerlegt[0]) == "LOGFILERETENTIONINDAYS") && (zerlegt.size() > 1))
{
this->logfileRetentionInDays = std::stoi(zerlegt[1]);
}
if ((zerlegt[0] == "Model") && (zerlegt.size() > 1))
{
this->cnnmodelfile = zerlegt[1];
}
if ((zerlegt[0] == "ModelInputSize") && (zerlegt.size() > 2))
{
this->modelxsize = std::stoi(zerlegt[1]);
this->modelysize = std::stoi(zerlegt[2]);
}
if (zerlegt.size() >= 5)
{
roianalog* neuroi = new roianalog;
neuroi->name = zerlegt[0];
neuroi->posx = std::stoi(zerlegt[1]);
neuroi->posy = std::stoi(zerlegt[2]);
neuroi->deltax = std::stoi(zerlegt[3]);
neuroi->deltay = std::stoi(zerlegt[4]);
neuroi->result = -1;
ROI.push_back(neuroi);
}
}
return true;
}
string ClassFlowAnalog::getHTMLSingleStep(string host)
{
string result, zw;
std::vector<HTMLInfo*> htmlinfo;
result = "<p>Found ROIs: </p> <p><img src=\"" + host + "/img_tmp/alg_roi.jpg\"></p>\n";
result = result + "Analog Pointers: <p> ";
htmlinfo = GetHTMLInfo();
for (int i = 0; i < htmlinfo.size(); ++i)
{
std::stringstream stream;
stream << std::fixed << std::setprecision(1) << htmlinfo[i]->val;
zw = stream.str();
result = result + "<img src=\"" + host + "/img_tmp/" + htmlinfo[i]->filename + "\"> " + zw;
delete htmlinfo[i];
}
htmlinfo.clear();
return result;
}
bool ClassFlowAnalog::doFlow(string time)
{
if (!doAlignAndCut(time)){
return false;
};
if (debugdetailanalog) LogFile.WriteToFile("ClassFlowAnalog::doFlow nach Alignment");
doNeuralNetwork(time);
RemoveOldLogs();
return true;
}
bool ClassFlowAnalog::doAlignAndCut(string time)
{
string input = "/sdcard/img_tmp/alg.jpg";
string input_roi = "/sdcard/img_tmp/alg_roi.jpg";
string ioresize = "/sdcard/img_tmp/resize.bmp";
string output;
string nm;
input = FormatFileName(input);
input_roi = FormatFileName(input_roi);
CResizeImage *rs;
CImageBasis *img_roi = NULL;
CAlignAndCutImage *caic = new CAlignAndCutImage(input);
if (!caic->ImageOkay()){
if (debugdetailanalog) LogFile.WriteToFile("ClassFlowAnalog::doAlignAndCut not okay!");
delete caic;
return false;
}
if (input_roi.length() > 0){
img_roi = new CImageBasis(input_roi);
if (!img_roi->ImageOkay()){
if (debugdetailanalog) LogFile.WriteToFile("ClassFlowAnalog::doAlignAndCut ImageRoi not okay!");
delete caic;
delete img_roi;
return false;
}
}
for (int i = 0; i < ROI.size(); ++i)
{
printf("Analog %d - Align&Cut\n", i);
output = "/sdcard/img_tmp/" + ROI[i]->name + ".jpg";
output = FormatFileName(output);
caic->CutAndSave(output, ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay);
rs = new CResizeImage(output);
if (!rs->ImageOkay()){
if (debugdetailanalog) LogFile.WriteToFile("ClassFlowAnalog::doAlignAndCut CResizeImage(output);!");
delete caic;
delete rs;
return false;
}
rs->Resize(modelxsize, modelysize);
ioresize = "/sdcard/img_tmp/ra" + std::to_string(i) + ".bmp";
ioresize = FormatFileName(ioresize);
rs->SaveToFile(ioresize);
delete rs;
if (img_roi)
{
int r = 0;
int g = 255;
int b = 0;
img_roi->drawRect(ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay, r, g, b, 1);
img_roi->drawCircle((int) (ROI[i]->posx + ROI[i]->deltax/2), (int) (ROI[i]->posy + ROI[i]->deltay/2), (int) (ROI[i]->deltax/2), r, g, b, 2);
img_roi->drawLine((int) (ROI[i]->posx + ROI[i]->deltax/2), (int) ROI[i]->posy, (int) (ROI[i]->posx + ROI[i]->deltax/2), (int) (ROI[i]->posy + ROI[i]->deltay), r, g, b, 2);
img_roi->drawLine((int) ROI[i]->posx, (int) (ROI[i]->posy + ROI[i]->deltay/2), (int) ROI[i]->posx + ROI[i]->deltax, (int) (ROI[i]->posy + ROI[i]->deltay/2), r, g, b, 2);
}
}
delete caic;
if (img_roi)
{
img_roi->SaveToFile(input_roi);
delete img_roi;
}
return true;
}
bool ClassFlowAnalog::doNeuralNetwork(string time)
{
string logPath = CreateLogFolder(time);
string input = "/sdcard/img_tmp/alg.jpg";
string ioresize = "/sdcard/img_tmp/resize.bmp";
string output;
input = FormatFileName(input);
#ifndef OHNETFLITE
CTfLiteClass *tflite = new CTfLiteClass;
string zwcnn = "/sdcard" + cnnmodelfile;
zwcnn = FormatFileName(zwcnn);
printf(zwcnn.c_str());printf("\n");
tflite->LoadModel(zwcnn);
tflite->MakeAllocate();
#endif
for (int i = 0; i < ROI.size(); ++i)
{
printf("Analog %d - TfLite\n", i);
ioresize = "/sdcard/img_tmp/ra" + std::to_string(i) + ".bmp";
ioresize = FormatFileName(ioresize);
float f1, f2;
f1 = 0; f2 = 0;
#ifndef OHNETFLITE
// LogFile.WriteToFile("ClassFlowAnalog::doNeuralNetwork vor CNN tflite->LoadInputImage(ioresize)");
tflite->LoadInputImage(ioresize);
tflite->Invoke();
if (debugdetailanalog) LogFile.WriteToFile("Nach Invoke");
f1 = tflite->GetOutputValue(0);
f2 = tflite->GetOutputValue(1);
#endif
float result = fmod(atan2(f1, f2) / (M_PI * 2) + 2, 1);
// printf("Result sin, cos, ziffer: %f, %f, %f\n", f1, f2, result);
ROI[i]->result = result * 10;
printf("Result Analog%i: %f\n", i, ROI[i]->result);
LogImage(logPath, ROI[i]->name, &ROI[i]->result, NULL, time);
}
#ifndef OHNETFLITE
delete tflite;
#endif
return true;
}
std::vector<HTMLInfo*> ClassFlowAnalog::GetHTMLInfo()
{
std::vector<HTMLInfo*> result;
for (int i = 0; i < ROI.size(); ++i)
{
HTMLInfo *zw = new HTMLInfo;
zw->filename = ROI[i]->name + ".jpg";
zw->val = ROI[i]->result;
result.push_back(zw);
}
return result;
}

View File

@@ -0,0 +1,36 @@
#pragma once
#include "ClassFlowImage.h"
// #include "CTfLiteClass.h"
struct roianalog {
int posx, posy, deltax, deltay;
float result;
string name;
};
class ClassFlowAnalog :
public ClassFlowImage
{
protected:
std::vector<roianalog*> ROI;
string cnnmodelfile;
int modelxsize, modelysize;
int ZeigerEval(float zahl, int ziffer_vorgaenger);
public:
ClassFlowAnalog();
ClassFlowAnalog(std::vector<ClassFlow*>* lfc);
bool ReadParameter(FILE* pfile, string& aktparamgraph);
bool doFlow(string time);
string getHTMLSingleStep(string host);
string getReadout();
bool doNeuralNetwork(string time);
bool doAlignAndCut(string time);
std::vector<HTMLInfo*> GetHTMLInfo();
int AnzahlROIs(){return ROI.size();};
string name(){return "ClassFlowAnalog";};
};

View File

@@ -0,0 +1,326 @@
#include "ClassFlowControll.h"
#include <sys/stat.h>
#include <dirent.h>
#include "ClassLogFile.h"
#include "time_sntp.h"
#include "Helper.h"
#include "server_ota.h"
static const char* TAG = "flow_controll";
std::string ClassFlowControll::doSingleStep(std::string _stepname, std::string _host){
std::string _classname = "";
std::string result = "";
if (_stepname.compare("[MakeImage]") == 0){
_classname = "ClassFlowMakeImage";
}
if (_stepname.compare("[Alignment]") == 0){
_classname = "ClassFlowAlignment";
}
if (_stepname.compare("[Digits]") == 0){
_classname = "ClassFlowDigit";
}
if (_stepname.compare("[Analog]") == 0){
_classname = "ClassFlowAnalog";
}
if (_stepname.compare("[MQTT]") == 0){
_classname = "ClassFlowMQTT";
}
// std::string zw = "Classname: " + _classname + "\n";
// printf(zw.c_str());
for (int i = 0; i < FlowControll.size(); ++i)
if (FlowControll[i]->name().compare(_classname) == 0){
// printf(FlowControll[i]->name().c_str()); printf("\n");
FlowControll[i]->doFlow("");
result = FlowControll[i]->getHTMLSingleStep(_host);
}
return result;
}
std::vector<HTMLInfo*> ClassFlowControll::GetAllDigital()
{
for (int i = 0; i < FlowControll.size(); ++i)
if (FlowControll[i]->name().compare("ClassFlowDigit") == 0)
return ((ClassFlowDigit*) (FlowControll[i]))->GetHTMLInfo();
std::vector<HTMLInfo*> empty;
return empty;
}
std::vector<HTMLInfo*> ClassFlowControll::GetAllAnalog()
{
for (int i = 0; i < FlowControll.size(); ++i)
if (FlowControll[i]->name().compare("ClassFlowAnalog") == 0)
return ((ClassFlowAnalog*) (FlowControll[i]))->GetHTMLInfo();
std::vector<HTMLInfo*> empty;
return empty;
}
void ClassFlowControll::SetInitialParameter(void)
{
AutoStart = false;
AutoIntervall = 10;
}
bool ClassFlowControll::isAutoStart(long &_intervall)
{
_intervall = AutoIntervall * 60 * 1000; // AutoIntervall: Minuten -> ms
return AutoStart;
}
ClassFlow* ClassFlowControll::CreateClassFlow(std::string _type)
{
ClassFlow* cfc = NULL;
_type = trim(_type);
if (toUpper(_type).compare("[MAKEIMAGE]") == 0)
cfc = new ClassFlowMakeImage(&FlowControll);
if (toUpper(_type).compare("[ALIGNMENT]") == 0)
cfc = new ClassFlowAlignment(&FlowControll);
if (toUpper(_type).compare("[ANALOG]") == 0)
cfc = new ClassFlowAnalog(&FlowControll);
if (toUpper(_type).compare("[DIGITS]") == 0)
cfc = new ClassFlowDigit(&FlowControll);
if (toUpper(_type).compare("[MQTT]") == 0)
cfc = new ClassFlowMQTT(&FlowControll);
if (toUpper(_type).compare("[POSTPROCESSING]") == 0)
{
cfc = new ClassFlowPostProcessing(&FlowControll);
flowpostprocessing = (ClassFlowPostProcessing*) cfc;
}
if (cfc) // Wird nur angehangen, falls es nicht [AutoTimer] ist, denn dieses ist für FlowControll
FlowControll.push_back(cfc);
if (toUpper(_type).compare("[AUTOTIMER]") == 0)
cfc = this;
if (toUpper(_type).compare("[DEBUG]") == 0)
cfc = this;
return cfc;
}
void ClassFlowControll::InitFlow(std::string config)
{
string line;
flowpostprocessing = NULL;
ClassFlow* cfc;
FILE* pFile;
config = FormatFileName(config);
pFile = fopen(config.c_str(), "r");
line = "";
char zw[1024];
if (pFile != NULL)
{
fgets(zw, 1024, pFile);
printf("%s", zw);
line = std::string(zw);
}
while ((line.size() > 0) && !(feof(pFile)))
{
cfc = CreateClassFlow(line);
if (cfc)
{
cfc->ReadParameter(pFile, line);
}
else
{
fgets(zw, 1024, pFile);
printf("%s", zw);
line = std::string(zw);
}
}
fclose(pFile);
}
std::string ClassFlowControll::getActStatus(){
return aktstatus;
}
bool ClassFlowControll::doFlow(string time)
{
// CleanTempFolder(); // dazu muss man noch eine Rolling einführen
bool result = true;
std::string zw_time;
int repeat = 0;
for (int i = 0; i < FlowControll.size(); ++i)
{
zw_time = gettimestring("%Y%m%d-%H%M%S");
aktstatus = zw_time + ": " + FlowControll[i]->name();
string zw = "FlowControll.doFlow - " + FlowControll[i]->name();
LogFile.WriteToFile(zw);
if (!FlowControll[i]->doFlow(time)){
repeat++;
LogFile.WriteToFile("Fehler im vorheriger Schritt - wird zum " + to_string(repeat) + ". Mal wiederholt");
i = -1; // vorheriger Schritt muss wiederholt werden (vermutlich Bilder aufnehmen)
result = false;
if (repeat > 5) {
LogFile.WriteToFile("Wiederholung 5x nicht erfolgreich --> reboot");
doReboot();
// Schritt wurde 5x wiederholt --> reboot
}
}
else
{
result = true;
}
}
zw_time = gettimestring("%Y%m%d-%H%M%S");
aktstatus = zw_time + ": Flow is done";
return result;
}
string ClassFlowControll::getReadout(bool _rawvalue = false, bool _noerror = false)
{
if (flowpostprocessing)
return flowpostprocessing->getReadoutParam(_rawvalue, _noerror);
string zw = "";
string result = "";
for (int i = 0; i < FlowControll.size(); ++i)
{
zw = FlowControll[i]->getReadout();
if (zw.length() > 0)
{
if (result.length() == 0)
result = zw;
else
result = result + "\t" + zw;
}
}
return result;
}
string ClassFlowControll::GetPrevalue()
{
if (flowpostprocessing)
{
return flowpostprocessing->GetPreValue();
}
return std::string();
}
std::string ClassFlowControll::UpdatePrevalue(std::string _newvalue)
{
float zw;
char* p;
_newvalue = trim(_newvalue);
// printf("Input UpdatePreValue: %s\n", _newvalue.c_str());
if (_newvalue.compare("0.0") == 0)
{
zw = 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";
}
if (flowpostprocessing)
{
flowpostprocessing->SavePreValue(zw);
return _newvalue;
}
return std::string();
}
bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph)
{
std::vector<string> zerlegt;
aktparamgraph = trim(aktparamgraph);
if (aktparamgraph.size() == 0)
if (!this->GetNextParagraph(pfile, aktparamgraph))
return false;
if ((toUpper(aktparamgraph).compare("[AUTOTIMER]") != 0) && (toUpper(aktparamgraph).compare("[DEBUG]") != 0)) // Paragraph passt nicht zu MakeImage
return false;
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
{
zerlegt = this->ZerlegeZeile(aktparamgraph);
if ((toUpper(zerlegt[0]) == "AUTOSTART") && (zerlegt.size() > 1))
{
if (toUpper(zerlegt[1]) == "TRUE")
{
AutoStart = true;
}
}
if ((toUpper(zerlegt[0]) == "INTERVALL") && (zerlegt.size() > 1))
{
AutoIntervall = std::stof(zerlegt[1]);
}
if ((toUpper(zerlegt[0]) == "LOGFILE") && (zerlegt.size() > 1))
{
if (toUpper(zerlegt[1]) == "TRUE")
{
LogFile.SwitchOnOff(true);
}
if (toUpper(zerlegt[1]) == "FALSE")
{
LogFile.SwitchOnOff(false);
}
}
if ((toUpper(zerlegt[0]) == "LOGFILERETENTIONINDAYS") && (zerlegt.size() > 1))
{
LogFile.SetRetention(std::stoi(zerlegt[1]));
}
}
return true;
}
int ClassFlowControll::CleanTempFolder() {
const char* folderPath = "/sdcard/img_tmp";
ESP_LOGI(TAG, "Clean up temporary folder to avoid damage of sdcard sectors : %s", folderPath);
DIR *dir = opendir(folderPath);
if (!dir) {
ESP_LOGE(TAG, "Failed to stat dir : %s", folderPath);
return -1;
}
struct dirent *entry;
int deleted = 0;
while ((entry = readdir(dir)) != NULL) {
std::string path = string(folderPath) + "/" + entry->d_name;
if (entry->d_type == DT_REG) {
if (unlink(path.c_str()) == 0) {
deleted ++;
} else {
ESP_LOGE(TAG, "can't delete file : %s", path.c_str());
}
} else if (entry->d_type == DT_DIR) {
deleted += removeFolder(path.c_str(), TAG);
}
}
closedir(dir);
ESP_LOGI(TAG, "%d files deleted", deleted);
return 0;
}

View File

@@ -0,0 +1,49 @@
#pragma once
#include <string>
#include "ClassFlow.h"
#include "ClassFlowMakeImage.h"
#include "ClassFlowAlignment.h"
#include "ClassFlowDigit.h"
#include "ClassFlowAnalog.h"
#include "ClassFlowPostProcessing.h"
#include "ClassFlowMQTT.h"
class ClassFlowControll :
public ClassFlow
{
protected:
std::vector<ClassFlow*> FlowControll;
ClassFlowPostProcessing* flowpostprocessing;
ClassFlow* CreateClassFlow(std::string _type);
bool AutoStart;
float AutoIntervall;
void SetInitialParameter(void);
std::string aktstatus;
public:
void InitFlow(std::string config);
bool doFlow(string time);
string getReadout(bool _rawvalue, bool _noerror);
string UpdatePrevalue(std::string _newvalue);
string GetPrevalue();
bool ReadParameter(FILE* pfile, string& aktparamgraph);
std::string doSingleStep(std::string _stepname, std::string _host);
bool isAutoStart(long &_intervall);
std::string getActStatus();
std::vector<HTMLInfo*> GetAllDigital();
std::vector<HTMLInfo*> GetAllAnalog();
int CleanTempFolder();
string name(){return "ClassFlowControll";};
};

View File

@@ -0,0 +1,250 @@
#include "ClassFlowDigit.h"
//#include "CFindTemplate.h"
//#include "CTfLiteClass.h"
// #define OHNETFLITE
#ifndef OHNETFLITE
#include "CTfLiteClass.h"
#endif
// #include "bitmap_image.hpp"
#include "ClassLogFile.h"
static const char* TAG = "flow_digital";
ClassFlowDigit::ClassFlowDigit() : ClassFlowImage(TAG)
{
string cnnmodelfile = "";
modelxsize = 1;
modelysize = 1;
ListFlowControll = NULL;
}
ClassFlowDigit::ClassFlowDigit(std::vector<ClassFlow*>* lfc) : ClassFlowImage(lfc, TAG)
{
string cnnmodelfile = "";
modelxsize = 1;
modelysize = 1;
}
string ClassFlowDigit::getReadout()
{
string rst = "";
for (int i = 0; i < ROI.size(); ++i)
{
if (ROI[i]->resultklasse == 10)
rst = rst + "N";
else
rst = rst + std::to_string(ROI[i]->resultklasse);
}
return rst;
}
bool ClassFlowDigit::ReadParameter(FILE* pfile, string& aktparamgraph)
{
std::vector<string> zerlegt;
aktparamgraph = trim(aktparamgraph);
if (aktparamgraph.size() == 0)
if (!this->GetNextParagraph(pfile, aktparamgraph))
return false;
if (aktparamgraph.compare("[Digits]") != 0) // Paragraph passt nich zu MakeImage
return false;
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
{
zerlegt = this->ZerlegeZeile(aktparamgraph);
if ((zerlegt[0] == "LogImageLocation") && (zerlegt.size() > 1))
{
LogImageLocation = "/sdcard" + zerlegt[1];
isLogImage = true;
}
if ((zerlegt[0] == "Model") && (zerlegt.size() > 1))
{
cnnmodelfile = zerlegt[1];
}
if ((zerlegt[0] == "ModelInputSize") && (zerlegt.size() > 2))
{
modelxsize = std::stoi(zerlegt[1]);
modelysize = std::stoi(zerlegt[2]);
}
if (zerlegt.size() >= 5)
{
roi* neuroi = new roi;
neuroi->name = zerlegt[0];
neuroi->posx = std::stoi(zerlegt[1]);
neuroi->posy = std::stoi(zerlegt[2]);
neuroi->deltax = std::stoi(zerlegt[3]);
neuroi->deltay = std::stoi(zerlegt[4]);
neuroi->resultklasse = -1;
ROI.push_back(neuroi);
}
}
return true;
}
string ClassFlowDigit::getHTMLSingleStep(string host)
{
string result, zw;
std::vector<HTMLInfo*> htmlinfo;
result = "<p>Found ROIs: </p> <p><img src=\"" + host + "/img_tmp/alg_roi.jpg\"></p>\n";
result = result + "Digital Counter: <p> ";
htmlinfo = GetHTMLInfo();
for (int i = 0; i < htmlinfo.size(); ++i)
{
if (htmlinfo[i]->val == 10)
zw = "NaN";
else
{
zw = to_string((int) htmlinfo[i]->val);
}
result = result + "<img src=\"" + host + "/img_tmp/" + htmlinfo[i]->filename + "\"> " + zw;
delete htmlinfo[i];
}
htmlinfo.clear();
return result;
}
bool ClassFlowDigit::doFlow(string time)
{
if (!doAlignAndCut(time)){
return false;
};
doNeuralNetwork(time);
RemoveOldLogs();
return true;
}
bool ClassFlowDigit::doAlignAndCut(string time)
{
string input = "/sdcard/img_tmp/alg.jpg";
string input_roi = "/sdcard/img_tmp/alg_roi.jpg";
string ioresize = "/sdcard/img_tmp/resize.bmp";
string output;
string nm;
input = FormatFileName(input);
input_roi = FormatFileName(input_roi);
CResizeImage *rs;
CImageBasis *img_roi = NULL;
CAlignAndCutImage *caic = new CAlignAndCutImage(input);
if (!caic->ImageOkay()){
LogFile.WriteToFile("ClassFlowDigit::doAlignAndCut not okay!");
delete caic;
return false;
}
if (input_roi.length() > 0){
img_roi = new CImageBasis(input_roi);
if (!img_roi->ImageOkay()){
LogFile.WriteToFile("ClassFlowDigit::doAlignAndCut ImageRoi not okay!");
delete caic;
delete img_roi;
return false;
}
}
for (int i = 0; i < ROI.size(); ++i)
{
printf("DigitalDigit %d - Align&Cut\n", i);
output = "/sdcard/img_tmp/" + ROI[i]->name + ".jpg";
output = FormatFileName(output);
caic->CutAndSave(output, ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay);
rs = new CResizeImage(output);
rs->Resize(modelxsize, modelysize);
ioresize = "/sdcard/img_tmp/rd" + std::to_string(i) + ".bmp";
ioresize = FormatFileName(ioresize);
rs->SaveToFile(ioresize);
delete rs;
if (img_roi)
{
img_roi->drawRect(ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay, 0, 0, 255, 2);
}
}
delete caic;
if (img_roi)
{
img_roi->SaveToFile(input_roi);
delete img_roi;
}
return true;
}
bool ClassFlowDigit::doNeuralNetwork(string time)
{
string logPath = CreateLogFolder(time);
string input = "/sdcard/img_tmp/alg.jpg";
string ioresize = "/sdcard/img_tmp/resize.bmp";
string output;
string nm;
input = FormatFileName(input);
#ifndef OHNETFLITE
CTfLiteClass *tflite = new CTfLiteClass;
string zwcnn = "/sdcard" + cnnmodelfile;
zwcnn = FormatFileName(zwcnn);
printf(zwcnn.c_str());printf("\n");
tflite->LoadModel(zwcnn);
tflite->MakeAllocate();
#endif
for (int i = 0; i < ROI.size(); ++i)
{
printf("DigitalDigit %d - TfLite\n", i);
ioresize = "/sdcard/img_tmp/rd" + std::to_string(i) + ".bmp";
ioresize = FormatFileName(ioresize);
// printf("output: %s, ioresize: %s\n", output.c_str(), ioresize.c_str());
ROI[i]->resultklasse = 0;
#ifndef OHNETFLITE
ROI[i]->resultklasse = tflite->GetClassFromImage(ioresize);
#endif
printf("Result Digit%i: %d\n", i, ROI[i]->resultklasse);
LogImage(logPath, ROI[i]->name, NULL, &ROI[i]->resultklasse, time);
}
#ifndef OHNETFLITE
delete tflite;
#endif
return true;
}
std::vector<HTMLInfo*> ClassFlowDigit::GetHTMLInfo()
{
std::vector<HTMLInfo*> result;
for (int i = 0; i < ROI.size(); ++i)
{
HTMLInfo *zw = new HTMLInfo;
zw->filename = ROI[i]->name + ".jpg";
zw->val = ROI[i]->resultklasse;
result.push_back(zw);
}
return result;
}

View File

@@ -0,0 +1,36 @@
#pragma once
#include "ClassFlowImage.h"
#include "Helper.h"
#include <string>
struct roi {
int posx, posy, deltax, deltay;
int resultklasse;
string name;
roi* next;
};
class ClassFlowDigit :
public ClassFlowImage
{
protected:
std::vector<roi*> ROI;
string cnnmodelfile;
int modelxsize, modelysize;
bool doNeuralNetwork(string time);
bool doAlignAndCut(string time);
public:
ClassFlowDigit();
ClassFlowDigit(std::vector<ClassFlow*>* lfc);
bool ReadParameter(FILE* pfile, string& aktparamgraph);
bool doFlow(string time);
string getHTMLSingleStep(string host);
string getReadout();
std::vector<HTMLInfo*> GetHTMLInfo();
string name(){return "ClassFlowDigit";};
};

View File

@@ -0,0 +1,101 @@
#include "ClassFlowImage.h"
#include <string>
#include <string.h>
#include <sys/stat.h>
#include <dirent.h>
#include "time_sntp.h"
#include "ClassLogFile.h"
ClassFlowImage::ClassFlowImage(const char* logTag)
{
this->logTag = logTag;
isLogImage = false;
}
ClassFlowImage::ClassFlowImage(std::vector<ClassFlow*> * lfc, const char* logTag) : ClassFlow((std::vector<ClassFlow*>*)lfc)
{
this->logTag = logTag;
isLogImage = false;
}
string ClassFlowImage::CreateLogFolder(string time) {
if (!isLogImage)
return "";
string logPath = LogImageLocation + "/" + time.LOGFILE_TIME_FORMAT_DATE_EXTR + "/" + time.LOGFILE_TIME_FORMAT_HOUR_EXTR;
isLogImage = mkdir_r(logPath.c_str(), S_IRWXU) == 0;
if (!isLogImage) {
ESP_LOGW(logTag, "Can't create log foolder for analog images. Path %s", logPath.c_str());
LogFile.WriteToFile("Can't create log foolder for analog images. Path " + logPath);
}
return logPath;
}
void ClassFlowImage::LogImage(string logPath, string name, float *resultFloat, int *resultInt, string time) {
if (!isLogImage)
return;
char buf[10];
if (resultFloat != NULL) {
sprintf(buf, "%.1f_", *resultFloat);
} else if (resultInt != NULL) {
sprintf(buf, "%d_", *resultInt);
} else {
buf[0] = '\0';
}
string nm = logPath + "/" + buf + name + "_" + time + ".jpg";
nm = FormatFileName(nm);
string output = "/sdcard/img_tmp/" + name + ".jpg";
output = FormatFileName(output);
printf("save to file: %s\n", nm.c_str());
CopyFile(output, nm);
}
void ClassFlowImage::RemoveOldLogs()
{
if (!isLogImage)
return;
ESP_LOGI(logTag, "remove old log images");
if (logfileRetentionInDays == 0) {
return;
}
time_t rawtime;
struct tm* timeinfo;
char cmpfilename[30];
time(&rawtime);
rawtime = addDays(rawtime, -logfileRetentionInDays);
timeinfo = localtime(&rawtime);
strftime(cmpfilename, 30, LOGFILE_TIME_FORMAT, timeinfo);
//ESP_LOGE(TAG, "log file name to compare: %s", cmpfilename);
string folderName = string(cmpfilename).LOGFILE_TIME_FORMAT_DATE_EXTR;
DIR *dir = opendir(LogImageLocation.c_str());
if (!dir) {
ESP_LOGI(logTag, "Failed to stat dir : %s", LogImageLocation.c_str());
return;
}
struct dirent *entry;
int deleted = 0;
int notDeleted = 0;
while ((entry = readdir(dir)) != NULL) {
string folderPath = LogImageLocation + "/" + entry->d_name;
if (entry->d_type == DT_DIR) {
//ESP_LOGI(logTag, "Compare %s %s", entry->d_name, folderName.c_str());
if ((strlen(entry->d_name) == folderName.length()) && (strcmp(entry->d_name, folderName.c_str()) < 0)) {
deleted += removeFolder(folderPath.c_str(), logTag);
} else {
notDeleted ++;
}
}
}
ESP_LOGI(logTag, "%d older log files deleted. %d current log files not deleted.", deleted, notDeleted);
closedir(dir);
}

View File

@@ -0,0 +1,22 @@
#pragma once
#include "ClassFlow.h"
using namespace std;
class ClassFlowImage : public ClassFlow
{
protected:
string LogImageLocation;
bool isLogImage;
unsigned short logfileRetentionInDays;
const char* logTag;
string CreateLogFolder(string time);
void LogImage(string logPath, string name, float *resultFloat, int *resultInt, string time);
public:
ClassFlowImage(const char* logTag);
ClassFlowImage(std::vector<ClassFlow*> * lfc, const char* logTag);
void RemoveOldLogs();
};

View File

@@ -0,0 +1,120 @@
#include "ClassFlowMQTT.h"
#include "Helper.h"
#include "interface_mqtt.h"
#include "ClassFlowPostProcessing.h"
#include <time.h>
ClassFlowMQTT::ClassFlowMQTT()
{
uri = "";
topic = "";
clientname = "watermeter";
OldValue = "";
flowpostprocessing = NULL;
user = "";
password = "";
}
ClassFlowMQTT::ClassFlowMQTT(std::vector<ClassFlow*>* lfc)
{
uri = "";
topic = "";
clientname = "watermeter";
OldValue = "";
flowpostprocessing = NULL;
user = "";
password = "";
ListFlowControll = lfc;
for (int i = 0; i < ListFlowControll->size(); ++i)
{
if (((*ListFlowControll)[i])->name().compare("ClassFlowPostProcessing") == 0)
{
flowpostprocessing = (ClassFlowPostProcessing*) (*ListFlowControll)[i];
}
}
}
bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
{
std::vector<string> zerlegt;
aktparamgraph = trim(aktparamgraph);
if (aktparamgraph.size() == 0)
if (!this->GetNextParagraph(pfile, aktparamgraph))
return false;
if (toUpper(aktparamgraph).compare("[MQTT]") != 0) // Paragraph passt nich zu MakeImage
return false;
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
{
zerlegt = this->ZerlegeZeile(aktparamgraph);
if ((toUpper(zerlegt[0]) == "USER") && (zerlegt.size() > 1))
{
this->user = zerlegt[1];
}
if ((toUpper(zerlegt[0]) == "PASSWORD") && (zerlegt.size() > 1))
{
this->password = zerlegt[1];
}
if ((toUpper(zerlegt[0]) == "URI") && (zerlegt.size() > 1))
{
this->uri = zerlegt[1];
}
if ((toUpper(zerlegt[0]) == "TOPIC") && (zerlegt.size() > 1))
{
this->topic = zerlegt[1];
}
if ((toUpper(zerlegt[0]) == "CLIENTID") && (zerlegt.size() > 1))
{
this->clientname = zerlegt[1];
}
}
if ((uri.length() > 0) && (topic.length() > 0))
{
MQTTInit(uri, clientname, user, password);
}
return true;
}
bool ClassFlowMQTT::doFlow(string zwtime)
{
std::string result;
string zw = "";
if (flowpostprocessing)
{
result = flowpostprocessing->getReadoutParam(false, true);
}
else
{
for (int i = 0; i < ListFlowControll->size(); ++i)
{
zw = (*ListFlowControll)[i]->getReadout();
if (zw.length() > 0)
{
if (result.length() == 0)
result = zw;
else
result = result + "\t" + zw;
}
}
}
MQTTPublish(topic, result);
OldValue = result;
return true;
}

View File

@@ -0,0 +1,25 @@
#pragma once
#include "ClassFlow.h"
#include "ClassFlowPostProcessing.h"
#include <string>
class ClassFlowMQTT :
public ClassFlow
{
protected:
std::string uri, topic, clientname;
std::string OldValue;
ClassFlowPostProcessing* flowpostprocessing;
std::string user, password;
public:
ClassFlowMQTT();
ClassFlowMQTT(std::vector<ClassFlow*>* lfc);
bool ReadParameter(FILE* pfile, string& aktparamgraph);
bool doFlow(string time);
string name(){return "ClassFlowMQTT";};
};

View File

@@ -0,0 +1,110 @@
#include "ClassFlowMakeImage.h"
#include "Helper.h"
#include "CFindTemplate.h"
#include "ClassControllCamera.h"
#include <time.h>
static const char* TAG = "flow_make_image";
esp_err_t ClassFlowMakeImage::camera_capture(){
string nm = namerawimage;
Camera.CaptureToFile(nm);
return ESP_OK;
}
void ClassFlowMakeImage::takePictureWithFlash(int flashdauer)
{
string nm = namerawimage;
if (isImageSize && (ImageQuality > 0))
Camera.SetQualitySize(ImageQuality, ImageSize);
printf("Start CaptureFile\n");
Camera.CaptureToFile(nm, flashdauer);
}
ClassFlowMakeImage::ClassFlowMakeImage() : ClassFlowImage(TAG)
{
waitbeforepicture = 5;
isImageSize = false;
ImageQuality = -1;
TimeImageTaken = 0;
namerawimage = "/sdcard/img_tmp/raw.jpg";
}
ClassFlowMakeImage::ClassFlowMakeImage(std::vector<ClassFlow*>* lfc) : ClassFlowImage(lfc, TAG)
{
waitbeforepicture = 5;
isImageSize = false;
ImageQuality = -1;
TimeImageTaken = 0;
namerawimage = "/sdcard/img_tmp/raw.jpg";
}
bool ClassFlowMakeImage::ReadParameter(FILE* pfile, string& aktparamgraph)
{
std::vector<string> zerlegt;
aktparamgraph = trim(aktparamgraph);
if (aktparamgraph.size() == 0)
if (!this->GetNextParagraph(pfile, aktparamgraph))
return false;
if (aktparamgraph.compare("[MakeImage]") != 0) // Paragraph passt nich zu MakeImage
return false;
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
{
zerlegt = this->ZerlegeZeile(aktparamgraph);
if ((zerlegt[0] == "LogImageLocation") && (zerlegt.size() > 1))
{
LogImageLocation = "/sdcard" + zerlegt[1];
isLogImage = true;
}
if ((zerlegt[0] == "ImageQuality") && (zerlegt.size() > 1))
this->ImageQuality = std::stod(zerlegt[1]);
if ((zerlegt[0] == "ImageSize") && (zerlegt.size() > 1))
{
ImageSize = Camera.TextToFramesize(zerlegt[1].c_str());
isImageSize = true;
}
}
return true;
}
string ClassFlowMakeImage::getHTMLSingleStep(string host)
{
string result;
result = "Raw Image: <br>\n<img src=\"" + host + "/img_tmp/raw.jpg\">\n";
return result;
}
bool ClassFlowMakeImage::doFlow(string zwtime)
{
////////////////////////////////////////////////////////////////////
// TakeImage and Store into /image_tmp/raw.jpg TO BE DONE
////////////////////////////////////////////////////////////////////
string logPath = CreateLogFolder(zwtime);
int flashdauer = (int) waitbeforepicture * 1000;
takePictureWithFlash(flashdauer);
time(&TimeImageTaken);
localtime(&TimeImageTaken);
LogImage(logPath, "raw", NULL, NULL, zwtime);
RemoveOldLogs();
return true;
}
time_t ClassFlowMakeImage::getTimeImageTaken()
{
return TimeImageTaken;
}

View File

@@ -0,0 +1,38 @@
#pragma once
#include "ClassFlowImage.h"
#include "ClassControllCamera.h"
#include <string>
#define BLINK_GPIO GPIO_NUM_4
#define CAMERA_MODEL_AI_THINKER
class ClassFlowMakeImage :
public ClassFlowImage
{
protected:
float waitbeforepicture;
framesize_t ImageSize;
bool isImageSize;
int ImageQuality;
time_t TimeImageTaken;
string namerawimage;
void CopyFile(string input, string output);
esp_err_t camera_capture();
void takePictureWithFlash(int flashdauer);
public:
ClassFlowMakeImage();
ClassFlowMakeImage(std::vector<ClassFlow*>* lfc);
bool ReadParameter(FILE* pfile, string& aktparamgraph);
bool doFlow(string time);
string getHTMLSingleStep(string host);
time_t getTimeImageTaken();
string name(){return "ClassFlowMakeImage";};
};

View File

@@ -0,0 +1,462 @@
#include "ClassFlowPostProcessing.h"
#include "Helper.h"
#include "ClassFlowAnalog.h"
#include "ClassFlowDigit.h"
#include "ClassFlowMakeImage.h"
#include <iomanip>
#include <sstream>
#include <time.h>
string ClassFlowPostProcessing::GetPreValue()
{
std::string result;
result = to_string(PreValue);
for (int i = 0; i < ListFlowControll->size(); ++i)
{
if (((*ListFlowControll)[i])->name().compare("ClassFlowAnalog") == 0)
{
int AnzahlAnalog = ((ClassFlowAnalog*)(*ListFlowControll)[i])->AnzahlROIs();
result = RundeOutput(PreValue, AnzahlAnalog - DecimalShift);
}
}
return result;
}
bool ClassFlowPostProcessing::LoadPreValue(void)
{
FILE* pFile;
char zw[1024];
string zwtime, zwvalue;
pFile = fopen(FilePreValue.c_str(), "r");
if (pFile == NULL)
return false;
fgets(zw, 1024, pFile);
printf("%s", zw);
zwtime = trim(std::string(zw));
fgets(zw, 1024, pFile);
printf("%s", zw);
zwvalue = trim(std::string(zw));
PreValue = stof(zwvalue.c_str());
time_t tStart;
int yy, month, dd, hh, mm, ss;
struct tm whenStart;
sscanf(zwtime.c_str(), "%d-%d-%d_%d-%d-%d", &yy, &month, &dd, &hh, &mm, &ss);
whenStart.tm_year = yy - 1900;
whenStart.tm_mon = month - 1;
whenStart.tm_mday = dd;
whenStart.tm_hour = hh;
whenStart.tm_min = mm;
whenStart.tm_sec = ss;
whenStart.tm_isdst = -1;
tStart = mktime(&whenStart);
time_t now;
time(&now);
localtime(&now);
double difference = difftime(now, tStart);
difference /= 60;
if (difference > PreValueAgeStartup)
return false;
Value = PreValue;
ReturnValue = to_string(Value);
ReturnValueNoError = ReturnValue;
// falls es Analog gibt, dann die Anzahl der Nachkommastellen feststellen und entsprechend runden:
for (int i = 0; i < ListFlowControll->size(); ++i)
{
if (((*ListFlowControll)[i])->name().compare("ClassFlowAnalog") == 0)
{
int AnzahlAnalog = ((ClassFlowAnalog*)(*ListFlowControll)[i])->AnzahlROIs();
ReturnValue = RundeOutput(Value, AnzahlAnalog - DecimalShift);
ReturnValueNoError = ReturnValue;
}
}
return true;
}
void ClassFlowPostProcessing::SavePreValue(float value, string zwtime)
{
FILE* pFile;
pFile = fopen(FilePreValue.c_str(), "w");
if (strlen(zwtime.c_str()) == 0)
{
time_t rawtime;
struct tm* timeinfo;
char buffer[80];
time(&rawtime);
timeinfo = localtime(&rawtime);
strftime(buffer, 80, "%Y-%m-%d_%H-%M-%S", timeinfo);
zwtime = std::string(buffer);
}
fputs(zwtime.c_str(), pFile);
fputs("\n", pFile);
fputs(to_string(value).c_str(), pFile);
fputs("\n", pFile);
fclose(pFile);
}
ClassFlowPostProcessing::ClassFlowPostProcessing()
{
PreValueUse = false;
PreValueAgeStartup = 30;
AllowNegativeRates = false;
MaxRateValue = 0.1;
ErrorMessage = false;
ListFlowControll = NULL;
PreValueOkay = false;
useMaxRateValue = false;
checkDigitIncreaseConsistency = false;
DecimalShift = 0;
FilePreValue = FormatFileName("/sdcard/config/prevalue.ini");
}
ClassFlowPostProcessing::ClassFlowPostProcessing(std::vector<ClassFlow*>* lfc)
{
PreValueUse = false;
PreValueAgeStartup = 30;
AllowNegativeRates = false;
MaxRateValue = 0.1;
ErrorMessage = false;
ListFlowControll = NULL;
PreValueOkay = false;
useMaxRateValue = false;
checkDigitIncreaseConsistency = false;
DecimalShift = 0;
FilePreValue = FormatFileName("/sdcard/config/prevalue.ini");
ListFlowControll = lfc;
}
bool ClassFlowPostProcessing::ReadParameter(FILE* pfile, string& aktparamgraph)
{
std::vector<string> zerlegt;
aktparamgraph = trim(aktparamgraph);
if (aktparamgraph.size() == 0)
if (!this->GetNextParagraph(pfile, aktparamgraph))
return false;
if (aktparamgraph.compare("[PostProcessing]") != 0) // Paragraph passt nich zu MakeImage
return false;
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
{
zerlegt = this->ZerlegeZeile(aktparamgraph);
if ((toUpper(zerlegt[0]) == "DECIMALSHIFT") && (zerlegt.size() > 1))
{
DecimalShift = stoi(zerlegt[1]);
}
if ((toUpper(zerlegt[0]) == "PREVALUEUSE") && (zerlegt.size() > 1))
{
if (toUpper(zerlegt[1]) == "TRUE")
{
PreValueUse = true;
}
}
if ((toUpper(zerlegt[0]) == "CHECKDIGITINCREASECONSISTENCY") && (zerlegt.size() > 1))
{
if (toUpper(zerlegt[1]) == "TRUE")
checkDigitIncreaseConsistency = true;
}
if ((toUpper(zerlegt[0]) == "ALLOWNEGATIVERATES") && (zerlegt.size() > 1))
{
if (toUpper(zerlegt[1]) == "TRUE")
AllowNegativeRates = true;
}
if ((toUpper(zerlegt[0]) == "ERRORMESSAGE") && (zerlegt.size() > 1))
{
if (toUpper(zerlegt[1]) == "TRUE")
ErrorMessage = true;
}
if ((toUpper(zerlegt[0]) == "PREVALUEAGESTARTUP") && (zerlegt.size() > 1))
{
PreValueAgeStartup = std::stoi(zerlegt[1]);
}
if ((toUpper(zerlegt[0]) == "MAXRATEVALUE") && (zerlegt.size() > 1))
{
useMaxRateValue = true;
MaxRateValue = std::stof(zerlegt[1]);
}
}
if (PreValueUse) {
PreValueOkay = LoadPreValue();
}
return true;
}
string ClassFlowPostProcessing::ShiftDecimal(string in, int _decShift){
if (_decShift == 0){
return in;
}
int _pos_dec_org, _pos_dec_neu;
_pos_dec_org = findDelimiterPos(in, ".");
if (_pos_dec_org == std::string::npos) {
_pos_dec_org = in.length();
}
else
{
in = in.erase(_pos_dec_org, 1);
}
_pos_dec_neu = _pos_dec_org + _decShift;
if (_pos_dec_neu <= 0) { // Komma ist vor der ersten Ziffer
for (int i = 0; i > _pos_dec_neu; --i){
in = in.insert(0, "0");
}
in = "0." + in;
return in;
}
if (_pos_dec_neu > in.length()){ // Komma soll hinter String (123 --> 1230)
for (int i = in.length(); i < _pos_dec_neu; ++i){
in = in.insert(in.length(), "0");
}
return in;
}
string zw;
zw = in.substr(0, _pos_dec_neu);
zw = zw + ".";
zw = zw + in.substr(_pos_dec_neu, in.length() - _pos_dec_neu);
return zw;
}
bool ClassFlowPostProcessing::doFlow(string zwtime)
{
string result = "";
string digit = "";
string analog = "";
string zwvalue;
bool isdigit = false;
bool isanalog = false;
int AnzahlAnalog = 0;
string zw;
string error = "";
time_t imagetime = 0;
for (int i = 0; i < ListFlowControll->size(); ++i)
{
if (((*ListFlowControll)[i])->name().compare("ClassFlowMakeImage") == 0)
{
imagetime = ((ClassFlowMakeImage*)(*ListFlowControll)[i])->getTimeImageTaken();
}
if (((*ListFlowControll)[i])->name().compare("ClassFlowDigit") == 0)
{
isdigit = true;
digit = (*ListFlowControll)[i]->getReadout();
}
if (((*ListFlowControll)[i])->name().compare("ClassFlowAnalog") == 0)
{
isanalog = true;
analog = (*ListFlowControll)[i]->getReadout();
AnzahlAnalog = ((ClassFlowAnalog*)(*ListFlowControll)[i])->AnzahlROIs();
}
}
if (imagetime == 0)
time(&imagetime);
struct tm* timeinfo;
timeinfo = localtime(&imagetime);
char strftime_buf[64];
strftime(strftime_buf, sizeof(strftime_buf), "%Y-%m-%d_%H-%M-%S", timeinfo);
zwtime = std::string(strftime_buf);
// // TESTING ONLY////////////////////
// isdigit = true; digit = "12N";
// isanalog = true; analog = "456";
if (isdigit)
ReturnRawValue = digit;
if (isdigit && isanalog)
ReturnRawValue = ReturnRawValue + ".";
if (isanalog)
ReturnRawValue = ReturnRawValue + analog;
ReturnRawValue = ShiftDecimal(ReturnRawValue, DecimalShift);
if (!PreValueUse || !PreValueOkay)
{
ReturnValue = ReturnRawValue;
ReturnValueNoError = ReturnRawValue;
if ((findDelimiterPos(ReturnValue, "N") == std::string::npos) && (ReturnValue.length() > 0))
{
while ((ReturnValue.length() > 1) && (ReturnValue[0] == '0'))
{
ReturnValue.erase(0, 1);
}
Value = std::stof(ReturnValue);
ReturnValueNoError = ReturnValue;
PreValueOkay = true;
PreValue = Value;
SavePreValue(Value, zwtime);
}
return true;
}
zw = ErsetzteN(ReturnRawValue);
Value = std::stof(zw);
if (checkDigitIncreaseConsistency)
{
Value = checkDigitConsistency(Value, DecimalShift, isanalog);
}
zwvalue = RundeOutput(Value, AnzahlAnalog - DecimalShift);
if ((!AllowNegativeRates) && (Value < PreValue))
{
error = error + "Negative Rate - Returned old value - read value: " + zwvalue + " ";
Value = PreValue;
zwvalue = RundeOutput(Value, AnzahlAnalog - DecimalShift);
}
if (useMaxRateValue && (abs(Value - PreValue) > MaxRateValue))
{
error = error + "Rate too high - Returned old value - read value: " + zwvalue + " ";
Value = PreValue;
zwvalue = RundeOutput(Value, AnzahlAnalog - DecimalShift);
}
ReturnValueNoError = zwvalue;
ReturnValue = zwvalue;
if (ErrorMessage && (error.length() > 0))
ReturnValue = ReturnValue + "\t" + error;
if (error.length() == 0)
{
PreValue = Value;
SavePreValue(Value, zwtime);
}
return true;
}
string ClassFlowPostProcessing::getReadout()
{
return ReturnValue;
}
string ClassFlowPostProcessing::getReadoutParam(bool _rawValue, bool _noerror)
{
if (_rawValue)
return ReturnRawValue;
if (_noerror)
return ReturnValueNoError;
return ReturnValue;
}
string ClassFlowPostProcessing::RundeOutput(float _in, int _anzNachkomma){
std::stringstream stream;
stream << std::fixed << std::setprecision(_anzNachkomma) << _in;
return stream.str();
}
string ClassFlowPostProcessing::ErsetzteN(string input)
{
int posN, posPunkt;
int pot, ziffer;
float zw;
posN = findDelimiterPos(input, "N");
posPunkt = findDelimiterPos(input, ".");
if (posPunkt == std::string::npos){
posPunkt = input.length();
}
while (posN != std::string::npos)
{
if (posN < posPunkt) {
pot = posPunkt - posN - 1;
}
else {
pot = posPunkt - posN;
}
zw = PreValue / pow(10, pot);
ziffer = ((int) zw) % 10;
input[posN] = ziffer + 48;
posN = findDelimiterPos(input, "N");
}
return input;
}
float ClassFlowPostProcessing::checkDigitConsistency(float input, int _decilamshift, bool _isanalog){
int aktdigit, olddigit;
int aktdigit_before, olddigit_before;
int pot, pot_max;
float zw;
pot = _decilamshift;
if (!_isanalog) // falls es keine analogwerte gibt, kann die letzte nicht bewertet werden
{
pot++;
}
pot_max = ((int) log10(input)) + 1;
while (pot <= pot_max)
{
zw = input / pow(10, pot-1);
aktdigit_before = ((int) zw) % 10;
zw = PreValue / pow(10, pot-1);
olddigit_before = ((int) zw) % 10;
zw = input / pow(10, pot);
aktdigit = ((int) zw) % 10;
zw = PreValue / pow(10, pot);
olddigit = ((int) zw) % 10;
if (aktdigit != olddigit) {
if (olddigit_before <= aktdigit_before) // stelle vorher hat noch keinen Nulldurchgang --> nachfolgestelle sollte sich nicht verändern
{
input = input + ((float) (olddigit - aktdigit)) * pow(10, pot); // Neue Digit wird durch alte Digit ersetzt;
}
}
pot++;
}
return input;
}

View File

@@ -0,0 +1,47 @@
#pragma once
#include "ClassFlow.h"
#include <string>
class ClassFlowPostProcessing :
public ClassFlow
{
protected:
bool PreValueUse;
int PreValueAgeStartup;
bool AllowNegativeRates;
float MaxRateValue;
bool useMaxRateValue;
bool ErrorMessage;
bool PreValueOkay;
bool checkDigitIncreaseConsistency;
int DecimalShift;
string FilePreValue;
float PreValue; // letzter Wert, der gut ausgelesen wurde
float Value; // letzer ausgelesener Wert, inkl. Korrekturen
string ReturnRawValue; // Rohwert (mit N & führenden 0)
string ReturnValue; // korrigierter Rückgabewert, ggf. mit Fehlermeldung
string ReturnValueNoError; // korrigierter Rückgabewert ohne Fehlermeldung
bool LoadPreValue(void);
string ShiftDecimal(string in, int _decShift);
string ErsetzteN(string);
float checkDigitConsistency(float input, int _decilamshift, bool _isanalog);
string RundeOutput(float _in, int _anzNachkomma);
public:
ClassFlowPostProcessing();
ClassFlowPostProcessing(std::vector<ClassFlow*>* lfc);
bool ReadParameter(FILE* pfile, string& aktparamgraph);
bool doFlow(string time);
string getReadout();
string getReadoutParam(bool _rawValue, bool _noerror);
void SavePreValue(float value, string time = "");
string GetPreValue();
string name(){return "ClassFlowPostProcessing";};
};

View File

@@ -0,0 +1,101 @@
#ifndef CAMERADEFINED
#define CAMERADEFINED
#if defined(CAMERA_MODEL_WROVER_KIT)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 21
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 19
#define Y4_GPIO_NUM 18
#define Y3_GPIO_NUM 5
#define Y2_GPIO_NUM 4
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM 15
#define XCLK_GPIO_NUM 27
#define SIOD_GPIO_NUM 25
#define SIOC_GPIO_NUM 23
#define Y9_GPIO_NUM 19
#define Y8_GPIO_NUM 36
#define Y7_GPIO_NUM 18
#define Y6_GPIO_NUM 39
#define Y5_GPIO_NUM 5
#define Y4_GPIO_NUM 34
#define Y3_GPIO_NUM 35
#define Y2_GPIO_NUM 32
#define VSYNC_GPIO_NUM 22
#define HREF_GPIO_NUM 26
#define PCLK_GPIO_NUM 21
#elif defined(CAMERA_MODEL_AI_THINKER)
#define PWDN_GPIO_NUM GPIO_NUM_32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM GPIO_NUM_0
#define SIOD_GPIO_NUM GPIO_NUM_26
#define SIOC_GPIO_NUM GPIO_NUM_27
#define Y9_GPIO_NUM GPIO_NUM_35
#define Y8_GPIO_NUM GPIO_NUM_34
#define Y7_GPIO_NUM GPIO_NUM_39
#define Y6_GPIO_NUM GPIO_NUM_36
#define Y5_GPIO_NUM GPIO_NUM_21
#define Y4_GPIO_NUM GPIO_NUM_19
#define Y3_GPIO_NUM GPIO_NUM_18
#define Y2_GPIO_NUM GPIO_NUM_5
#define VSYNC_GPIO_NUM GPIO_NUM_25
#define HREF_GPIO_NUM GPIO_NUM_23
#define PCLK_GPIO_NUM GPIO_NUM_22
#else
#error "Camera model not selected"
#endif
static camera_config_t camera_config = {
.pin_pwdn = PWDN_GPIO_NUM,
.pin_reset = RESET_GPIO_NUM,
.pin_xclk = XCLK_GPIO_NUM,
.pin_sscb_sda = SIOD_GPIO_NUM,
.pin_sscb_scl = SIOC_GPIO_NUM,
.pin_d7 = Y9_GPIO_NUM,
.pin_d6 = Y8_GPIO_NUM,
.pin_d5 = Y7_GPIO_NUM,
.pin_d4 = Y6_GPIO_NUM,
.pin_d3 = Y5_GPIO_NUM,
.pin_d2 = Y4_GPIO_NUM,
.pin_d1 = Y3_GPIO_NUM,
.pin_d0 = Y2_GPIO_NUM,
.pin_vsync = VSYNC_GPIO_NUM,
.pin_href = HREF_GPIO_NUM,
.pin_pclk = PCLK_GPIO_NUM,
//XCLK 20MHz or 10MHz for OV2640 double FPS (Experimental)
.xclk_freq_hz = 20000000,
.ledc_timer = LEDC_TIMER_0,
.ledc_channel = LEDC_CHANNEL_0,
.pixel_format = PIXFORMAT_JPEG,//YUV422,GRAYSCALE,RGB565,JPEG
// .pixel_format = PIXFORMAT_RGB888,//YUV422,GRAYSCALE,RGB565,JPEG
// .frame_size = FRAMESIZE_QVGA,//QQVGA-QXGA Do not use sizes above QVGA when not JPEG
.frame_size = FRAMESIZE_SVGA,//QQVGA-QXGA Do not use sizes above QVGA when not JPEG
.jpeg_quality = 12, //0-63 lower number means higher quality
.fb_count = 1 //if more than one, i2s runs in continuous mode. Use only with JPEG
};
#endif