mirror of
https://github.com/jomjol/AI-on-the-edge-device.git
synced 2025-12-14 15:36:56 +03:00
compatibitly mit esp-idf pure
This commit is contained in:
7
code/components/jomjol_flowcontroll/CMakeLists.txt
Normal file
7
code/components/jomjol_flowcontroll/CMakeLists.txt
Normal 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)
|
||||
|
||||
|
||||
114
code/components/jomjol_flowcontroll/ClassFlow.cpp
Normal file
114
code/components/jomjol_flowcontroll/ClassFlow.cpp
Normal 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;
|
||||
}
|
||||
45
code/components/jomjol_flowcontroll/ClassFlow.h
Normal file
45
code/components/jomjol_flowcontroll/ClassFlow.h
Normal 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";};
|
||||
|
||||
};
|
||||
|
||||
151
code/components/jomjol_flowcontroll/ClassFlowAlignment.cpp
Normal file
151
code/components/jomjol_flowcontroll/ClassFlowAlignment.cpp
Normal 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;
|
||||
}
|
||||
|
||||
30
code/components/jomjol_flowcontroll/ClassFlowAlignment.h
Normal file
30
code/components/jomjol_flowcontroll/ClassFlowAlignment.h
Normal 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";};
|
||||
};
|
||||
|
||||
308
code/components/jomjol_flowcontroll/ClassFlowAnalog.cpp
Normal file
308
code/components/jomjol_flowcontroll/ClassFlowAnalog.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
36
code/components/jomjol_flowcontroll/ClassFlowAnalog.h
Normal file
36
code/components/jomjol_flowcontroll/ClassFlowAnalog.h
Normal 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";};
|
||||
};
|
||||
|
||||
326
code/components/jomjol_flowcontroll/ClassFlowControll.cpp
Normal file
326
code/components/jomjol_flowcontroll/ClassFlowControll.cpp
Normal 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;
|
||||
}
|
||||
49
code/components/jomjol_flowcontroll/ClassFlowControll.h
Normal file
49
code/components/jomjol_flowcontroll/ClassFlowControll.h
Normal 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";};
|
||||
};
|
||||
|
||||
250
code/components/jomjol_flowcontroll/ClassFlowDigit.cpp
Normal file
250
code/components/jomjol_flowcontroll/ClassFlowDigit.cpp
Normal 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;
|
||||
}
|
||||
36
code/components/jomjol_flowcontroll/ClassFlowDigit.h
Normal file
36
code/components/jomjol_flowcontroll/ClassFlowDigit.h
Normal 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";};
|
||||
};
|
||||
|
||||
101
code/components/jomjol_flowcontroll/ClassFlowImage.cpp
Normal file
101
code/components/jomjol_flowcontroll/ClassFlowImage.cpp
Normal 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);
|
||||
}
|
||||
|
||||
22
code/components/jomjol_flowcontroll/ClassFlowImage.h
Normal file
22
code/components/jomjol_flowcontroll/ClassFlowImage.h
Normal 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();
|
||||
};
|
||||
120
code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp
Normal file
120
code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp
Normal 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;
|
||||
}
|
||||
25
code/components/jomjol_flowcontroll/ClassFlowMQTT.h
Normal file
25
code/components/jomjol_flowcontroll/ClassFlowMQTT.h
Normal 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";};
|
||||
};
|
||||
|
||||
110
code/components/jomjol_flowcontroll/ClassFlowMakeImage.cpp
Normal file
110
code/components/jomjol_flowcontroll/ClassFlowMakeImage.cpp
Normal 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;
|
||||
}
|
||||
38
code/components/jomjol_flowcontroll/ClassFlowMakeImage.h
Normal file
38
code/components/jomjol_flowcontroll/ClassFlowMakeImage.h
Normal 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";};
|
||||
};
|
||||
|
||||
462
code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp
Normal file
462
code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp
Normal 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;
|
||||
}
|
||||
@@ -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";};
|
||||
};
|
||||
|
||||
101
code/components/jomjol_flowcontroll/camera_define.h
Normal file
101
code/components/jomjol_flowcontroll/camera_define.h
Normal 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
|
||||
Reference in New Issue
Block a user