diff --git a/FeatureRequest.md b/FeatureRequest.md index 5521641e..c28745b5 100644 --- a/FeatureRequest.md +++ b/FeatureRequest.md @@ -11,6 +11,22 @@ ____ +#### #8 MQTT configurable readout intervall + +Make the readout intervall configurable via MQTT. + +* Change the mqtt part to receive and process input and not only sending + +#### #7 Extended Error Handling + +Check different types of error (e.g. tflite not availabe) and generate an error on the html page. + +To do: + +* Make a list of "important" errors +* Implement a checking algo +* Extend the firmware and html page for the error handling + #### #6 Check for double ROI names Check during configuration, that ROI names are unique. diff --git a/README.md b/README.md index e8d0e833..953c3279 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,8 @@ respectively ESP32-Cam housing only: https://www.thingiverse.com/thing:4571627 + + @@ -45,15 +47,55 @@ In other cases you can contact the developer via email: + +* MQTT: standardization of the naming - only the main topic needs to be specified. The subtopics will be named automatically. This is necessary to handle the multi number option. + **ATTENTION**: the parameter `maintopic` needs to be set + +* Remark: + + * This is an early stage - do only use it on a test system and make a backup of your configuration. + * The documentation is not updated yet. + +* **ATTENTION: the configuration and prevalue files are modified automatically and will not be backward compatible!** + + + +Rolling - (2021-06-17) + +* bug fix setting hostname, Flash-LED not off during reboot + +Rolling - (2021-06-11) + +* Restructuring for multi number counters + * Major internal and html changes + (html and firmware) +* **ATTENTION: the configuration and prevalue files are modified automatically and will not be backward compatible!** + + + +##### 7.1.2 MQTT-Update - (2021-06-17) + +* NEW: 7.1.2: bug fix setting hostname, Flash-LED not off during rebootNEW: 7.1.1: bug fix wlan password with "=" (again) * MQTT error message: changes "no error", send retain flag * Update wlan handling to esp-idf 4.1 * Upgrade digital CNN to v8.7.0 (added new images) * Bug fix: MQTT, WLAN, LED-Controll, GPIO usage, fixed IP, calculation flow rate + ##### 7.0.1 MQTT-Update - (2021-05-13) diff --git a/code/components/connect_wlan.zip b/code/components/connect_wlan.zip deleted file mode 100644 index 31ab9b29..00000000 Binary files a/code/components/connect_wlan.zip and /dev/null differ diff --git a/code/components/jomjol_controlcamera/ClassControllCamera.cpp b/code/components/jomjol_controlcamera/ClassControllCamera.cpp index d4bd9224..b7f80d38 100644 --- a/code/components/jomjol_controlcamera/ClassControllCamera.cpp +++ b/code/components/jomjol_controlcamera/ClassControllCamera.cpp @@ -230,6 +230,8 @@ void CCamera::EnableAutoExposure(int flashdauer) camera_fb_t * fb = esp_camera_fb_get(); if (!fb) { ESP_LOGE(TAGCAMERACLASS, "Camera Capture Failed"); + LEDOnOff(false); + LightOnOff(false); doReboot(); } esp_camera_fb_return(fb); @@ -275,6 +277,7 @@ esp_err_t CCamera::CaptureToBasisImage(CImageBasis *_Image, int delay) if (!fb) { ESP_LOGE(TAGCAMERACLASS, "Camera Capture Failed"); LEDOnOff(false); + LightOnOff(false); doReboot(); return ESP_FAIL; @@ -453,6 +456,7 @@ esp_err_t CCamera::CaptureToHTTP(httpd_req_t *req, int delay) fb = esp_camera_fb_get(); if (!fb) { ESP_LOGE(TAGCAMERACLASS, "Camera capture failed"); + LEDOnOff(false); LightOnOff(false); httpd_resp_send_500(req); // doReboot(); diff --git a/code/components/jomjol_flowcontroll/ClassFlow.cpp b/code/components/jomjol_flowcontroll/ClassFlow.cpp index 3ee76cfb..97d77dfb 100644 --- a/code/components/jomjol_flowcontroll/ClassFlow.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlow.cpp @@ -94,6 +94,23 @@ string ClassFlow::getReadout() return string(); } +std::string ClassFlow::GetParameterName(std::string _input) +{ + string _param; + int _pospunkt = _input.find_first_of("."); + if (_pospunkt > -1) + { + _param = _input.substr(_pospunkt+1, _input.length() - _pospunkt - 1); + } + else + { + _param = _input; + } +// printf("Parameter: %s, Pospunkt: %d\n", _param.c_str(), _pospunkt); + return _param; +} + + bool ClassFlow::getNextLine(FILE* pfile, string *rt) { char zw[1024]; @@ -102,13 +119,13 @@ bool ClassFlow::getNextLine(FILE* pfile, string *rt) *rt = ""; return false; } - fgets(zw, 1024, pfile); - printf("%s", zw); - if ((strlen(zw) == 0) && feof(pfile)) + if (!fgets(zw, 1024, pfile)) { *rt = ""; + printf("END OF FILE\n"); return false; } + printf("%s", zw); *rt = zw; *rt = trim(*rt); while ((zw[0] == ';' || zw[0] == '#' || (rt->size() == 0)) && !(zw[1] == '[')) // Kommentarzeilen (; oder #) und Leerzeilen überspringen, es sei denn es ist ein neuer auskommentierter Paragraph diff --git a/code/components/jomjol_flowcontroll/ClassFlow.h b/code/components/jomjol_flowcontroll/ClassFlow.h index bcad7b4f..4df4777c 100644 --- a/code/components/jomjol_flowcontroll/ClassFlow.h +++ b/code/components/jomjol_flowcontroll/ClassFlow.h @@ -37,6 +37,8 @@ protected: virtual void SetInitialParameter(void); + std::string GetParameterName(std::string _input); + bool disabled; public: diff --git a/code/components/jomjol_flowcontroll/ClassFlowAnalog._c_p_p_ b/code/components/jomjol_flowcontroll/ClassFlowAnalog._c_p_p_ new file mode 100644 index 00000000..3f9cce45 --- /dev/null +++ b/code/components/jomjol_flowcontroll/ClassFlowAnalog._c_p_p_ @@ -0,0 +1,350 @@ +#include "ClassFlowAnalog.h" + +#include +#include +#include +#include // std::stringstream + + +// #define OHNETFLITE + +#ifndef OHNETFLITE +#include "CTfLiteClass.h" +#endif + +#include "ClassLogFile.h" + +static const char* TAG = "flow_analog"; + +bool debugdetailanalog = false; + +void ClassFlowAnalog::SetInitialParameter(void) +{ + string cnnmodelfile = ""; + modelxsize = 1; + modelysize = 1; + ListFlowControll = NULL; + previousElement = NULL; + SaveAllFiles = false; + disabled = false; + extendedResolution = false; +} + +ClassFlowAnalog::ClassFlowAnalog(std::vector* lfc) : ClassFlowImage(lfc, TAG) +{ + SetInitialParameter(); + ListFlowControll = lfc; + + for (int i = 0; i < ListFlowControll->size(); ++i) + { + if (((*ListFlowControll)[i])->name().compare("ClassFlowAlignment") == 0) + { + flowpostalignment = (ClassFlowAlignment*) (*ListFlowControll)[i]; + } + } + +} + + +int ClassFlowAnalog::AnzahlROIs() +{ + int zw = ROI.size(); + if (extendedResolution) + zw++; + + return zw; +} + + +string ClassFlowAnalog::getReadout() +{ + string result = ""; + if (ROI.size() == 0) + return result; + + + float zahl = ROI[ROI.size() - 1]->result; + int ergebnis_nachkomma = ((int) floor(zahl * 10)) % 10; + + int prev = -1; + + prev = ZeigerEval(ROI[ROI.size() - 1]->result, prev); + result = std::to_string(prev); + + if (extendedResolution) + result = result + std::to_string(ergebnis_nachkomma); + + for (int i = ROI.size() - 2; 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 zerlegt; + + aktparamgraph = trim(aktparamgraph); + + if (aktparamgraph.size() == 0) + if (!this->GetNextParagraph(pfile, aktparamgraph)) + return false; + + + if ((aktparamgraph.compare("[Analog]") != 0) && (aktparamgraph.compare(";[Analog]") != 0)) // Paragraph passt nich zu MakeImage + return false; + + if (aktparamgraph[0] == ';') + { + disabled = true; + while (getNextLine(pfile, &aktparamgraph) && !isNewParagraph(aktparamgraph)); + printf("[Analog] is disabled !!!\n"); + return true; + } + + + 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; + neuroi->image = NULL; + neuroi->image_org = NULL; + ROI.push_back(neuroi); + } + + if ((toUpper(zerlegt[0]) == "SAVEALLFILES") && (zerlegt.size() > 1)) + { + if (toUpper(zerlegt[1]) == "TRUE") + SaveAllFiles = true; + } + + if ((toUpper(zerlegt[0]) == "EXTENDEDRESOLUTION") && (zerlegt.size() > 1)) + { + if (toUpper(zerlegt[1]) == "TRUE") + extendedResolution = true; + } + } + + for (int i = 0; i < ROI.size(); ++i) + { + ROI[i]->image = new CImageBasis(modelxsize, modelysize, 3); + ROI[i]->image_org = new CImageBasis(ROI[i]->deltax, ROI[i]->deltay, 3); + } + + return true; +} + + +string ClassFlowAnalog::getHTMLSingleStep(string host) +{ + string result, zw; + std::vector htmlinfo; + + result = "

Found ROIs:

\n"; + result = result + "Analog Pointers:

"; + + 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 + "filename + "\"> " + zw; + delete htmlinfo[i]; + } + htmlinfo.clear(); + + return result; +} + + + +bool ClassFlowAnalog::doFlow(string time) +{ + if (disabled) + return true; + + if (!doAlignAndCut(time)){ + return false; + }; + + if (debugdetailanalog) LogFile.WriteToFile("ClassFlowAnalog::doFlow nach Alignment"); + + doNeuralNetwork(time); + + RemoveOldLogs(); + + return true; +} + +bool ClassFlowAnalog::doAlignAndCut(string time) +{ + if (disabled) + return true; + + CAlignAndCutImage *caic = flowpostalignment->GetAlignAndCutImage(); + + for (int i = 0; i < ROI.size(); ++i) + { + printf("Analog %d - Align&Cut\n", i); + + caic->CutAndSave(ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay, ROI[i]->image_org); + if (SaveAllFiles) ROI[i]->image_org->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ROI[i]->name + ".jpg")); + + ROI[i]->image_org->Resize(modelxsize, modelysize, ROI[i]->image); + if (SaveAllFiles) ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ROI[i]->name + ".bmp")); + } + + return true; +} + +void ClassFlowAnalog::DrawROI(CImageBasis *_zw) +{ + int r = 0; + int g = 255; + int b = 0; + + for (int i = 0; i < ROI.size(); ++i) + { + _zw->drawRect(ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay, r, g, b, 1); + _zw->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); + _zw->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); + _zw->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); + } +} + +bool ClassFlowAnalog::doNeuralNetwork(string time) +{ + if (disabled) + return true; + + 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->LoadInputImageBasis(ROI[i]->image); + 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); + + if (isLogImage) + { + LogImage(logPath, ROI[i]->name, &ROI[i]->result, NULL, time, ROI[i]->image_org); + } + } +#ifndef OHNETFLITE + delete tflite; +#endif + + return true; +} + + +std::vector ClassFlowAnalog::GetHTMLInfo() +{ + std::vector result; + + for (int i = 0; i < ROI.size(); ++i) + { + HTMLInfo *zw = new HTMLInfo; + zw->filename = ROI[i]->name + ".bmp"; + zw->filename_org = ROI[i]->name + ".jpg"; + zw->val = ROI[i]->result; + zw->image = ROI[i]->image; + zw->image_org = ROI[i]->image_org; + result.push_back(zw); + } + + return result; +} + + diff --git a/code/components/jomjol_flowcontroll/ClassFlowAnalog._h_ b/code/components/jomjol_flowcontroll/ClassFlowAnalog._h_ new file mode 100644 index 00000000..08a29be7 --- /dev/null +++ b/code/components/jomjol_flowcontroll/ClassFlowAnalog._h_ @@ -0,0 +1,48 @@ +#pragma once +#include "ClassFlowImage.h" +#include "ClassFlowAlignment.h" +// #include "CTfLiteClass.h" + +struct roianalog { + int posx, posy, deltax, deltay; + float result; + CImageBasis *image, *image_org; + string name; +}; + + +class ClassFlowAnalog : + public ClassFlowImage +{ +protected: + std::vector ROI; + string cnnmodelfile; + int modelxsize, modelysize; + int ZeigerEval(float zahl, int ziffer_vorgaenger); + bool SaveAllFiles; + + + ClassFlowAlignment* flowpostalignment; + + void SetInitialParameter(void); + +public: + bool extendedResolution; + + ClassFlowAnalog(std::vector* lfc); + + bool ReadParameter(FILE* pfile, string& aktparamgraph); + bool doFlow(string time); + string getHTMLSingleStep(string host); + string getReadout(); + + void DrawROI(CImageBasis *_zw); + + bool doNeuralNetwork(string time); + bool doAlignAndCut(string time); + std::vector GetHTMLInfo(); + int AnzahlROIs(); + + string name(){return "ClassFlowAnalog";}; +}; + diff --git a/code/components/jomjol_flowcontroll/ClassFlowAnalog.cpp b/code/components/jomjol_flowcontroll/ClassFlowAnalog.cpp index a23d8b42..c38d15b5 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowAnalog.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowAnalog.cpp @@ -1,7 +1,7 @@ #include "ClassFlowAnalog.h" #include -#include +#include #include #include // std::stringstream @@ -46,9 +46,9 @@ ClassFlowAnalog::ClassFlowAnalog(std::vector* lfc) : ClassFlowImage( } -int ClassFlowAnalog::AnzahlROIs() +int ClassFlowAnalog::AnzahlROIs(int _analog = 0) { - int zw = ROI.size(); + int zw = ANALOG[_analog]->ROI.size(); if (extendedResolution) zw++; @@ -56,27 +56,27 @@ int ClassFlowAnalog::AnzahlROIs() } -string ClassFlowAnalog::getReadout() +string ClassFlowAnalog::getReadout(int _analog = 0) { string result = ""; - if (ROI.size() == 0) + if (ANALOG[_analog]->ROI.size() == 0) return result; - float zahl = ROI[ROI.size() - 1]->result; + float zahl = ANALOG[_analog]->ROI[ANALOG[_analog]->ROI.size() - 1]->result; int ergebnis_nachkomma = ((int) floor(zahl * 10)) % 10; int prev = -1; - prev = ZeigerEval(ROI[ROI.size() - 1]->result, prev); + prev = ZeigerEval(ANALOG[_analog]->ROI[ANALOG[_analog]->ROI.size() - 1]->result, prev); result = std::to_string(prev); if (extendedResolution) result = result + std::to_string(ergebnis_nachkomma); - for (int i = ROI.size() - 2; i >= 0; --i) + for (int i = ANALOG[_analog]->ROI.size() - 2; i >= 0; --i) { - prev = ZeigerEval(ROI[i]->result, prev); + prev = ZeigerEval(ANALOG[_analog]->ROI[i]->result, prev); result = std::to_string(prev) + result; } @@ -153,8 +153,8 @@ bool ClassFlowAnalog::ReadParameter(FILE* pfile, string& aktparamgraph) } if (zerlegt.size() >= 5) { - roianalog* neuroi = new roianalog; - neuroi->name = zerlegt[0]; + analog* _analog = GetANALOG(zerlegt[0], true); + roianalog* neuroi = _analog->ROI[_analog->ROI.size()-1]; neuroi->posx = std::stoi(zerlegt[1]); neuroi->posy = std::stoi(zerlegt[2]); neuroi->deltax = std::stoi(zerlegt[3]); @@ -162,7 +162,7 @@ bool ClassFlowAnalog::ReadParameter(FILE* pfile, string& aktparamgraph) neuroi->result = -1; neuroi->image = NULL; neuroi->image_org = NULL; - ROI.push_back(neuroi); +// ROI.push_back(neuroi); } if ((toUpper(zerlegt[0]) == "SAVEALLFILES") && (zerlegt.size() > 1)) @@ -178,15 +178,76 @@ bool ClassFlowAnalog::ReadParameter(FILE* pfile, string& aktparamgraph) } } - for (int i = 0; i < ROI.size(); ++i) - { - ROI[i]->image = new CImageBasis(modelxsize, modelysize, 3); - ROI[i]->image_org = new CImageBasis(ROI[i]->deltax, ROI[i]->deltay, 3); - } + for (int _ana = 0; _ana < ANALOG.size(); ++_ana) + for (int i = 0; i < ANALOG[_ana]->ROI.size(); ++i) + { + ANALOG[_ana]->ROI[i]->image = new CImageBasis(modelxsize, modelysize, 3); + ANALOG[_ana]->ROI[i]->image_org = new CImageBasis(ANALOG[_ana]->ROI[i]->deltax, ANALOG[_ana]->ROI[i]->deltay, 3); + } return true; } +analog* ClassFlowAnalog::FindANALOG(string _name_number) +{ + analog *_ret = NULL; + + for (int i = 0; i < ANALOG.size(); ++i) + { + if (ANALOG[i]->name == _name_number) + return ANALOG[i]; + } + + return NULL; +} + + + +analog* ClassFlowAnalog::GetANALOG(string _name, bool _create = true) +{ + string _analog, _roi; + int _pospunkt = _name.find_first_of("."); +// printf("Name: %s, Pospunkt: %d\n", _name.c_str(), _pospunkt); + if (_pospunkt > -1) + { + _analog = _name.substr(0, _pospunkt); + _roi = _name.substr(_pospunkt+1, _name.length() - _pospunkt - 1); + } + else + { + _analog = "default"; + _roi = _name; + } + + analog *_ret = NULL; + + for (int i = 0; i < ANALOG.size(); ++i) + { + if (ANALOG[i]->name == _analog) + _ret = ANALOG[i]; + } + + if (!_create) // nicht gefunden und soll auch nicht erzeugt werden + return _ret; + + + if (_ret == NULL) + { + _ret = new analog; + _ret->name = _analog; + ANALOG.push_back(_ret); + } + + roianalog* neuroi = new roianalog; + neuroi->name = _roi; + _ret->ROI.push_back(neuroi); + + printf("GetANALOG - ANALOG %s - roi %s\n", _analog.c_str(), _roi.c_str()); + + return _ret; +} + + string ClassFlowAnalog::getHTMLSingleStep(string host) { @@ -238,16 +299,29 @@ bool ClassFlowAnalog::doAlignAndCut(string time) CAlignAndCutImage *caic = flowpostalignment->GetAlignAndCutImage(); - for (int i = 0; i < ROI.size(); ++i) - { - printf("Analog %d - Align&Cut\n", i); - - caic->CutAndSave(ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay, ROI[i]->image_org); - if (SaveAllFiles) ROI[i]->image_org->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ROI[i]->name + ".jpg")); + for (int _ana = 0; _ana < ANALOG.size(); ++_ana) + for (int i = 0; i < ANALOG[_ana]->ROI.size(); ++i) + { + printf("Analog %d - Align&Cut\n", i); + + caic->CutAndSave(ANALOG[_ana]->ROI[i]->posx, ANALOG[_ana]->ROI[i]->posy, ANALOG[_ana]->ROI[i]->deltax, ANALOG[_ana]->ROI[i]->deltay, ANALOG[_ana]->ROI[i]->image_org); + if (SaveAllFiles) + { + if (ANALOG[_ana]->name == "default") + ANALOG[_ana]->ROI[i]->image_org->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ANALOG[_ana]->ROI[i]->name + ".jpg")); + else + ANALOG[_ana]->ROI[i]->image_org->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ANALOG[_ana]->name + "_" + ANALOG[_ana]->ROI[i]->name + ".jpg")); + } - ROI[i]->image_org->Resize(modelxsize, modelysize, ROI[i]->image); - if (SaveAllFiles) ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ROI[i]->name + ".bmp")); - } + ANALOG[_ana]->ROI[i]->image_org->Resize(modelxsize, modelysize, ANALOG[_ana]->ROI[i]->image); + if (SaveAllFiles) + { + if (ANALOG[_ana]->name == "default") + ANALOG[_ana]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ANALOG[_ana]->ROI[i]->name + ".bmp")); + else + ANALOG[_ana]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ANALOG[_ana]->name + "_" + ANALOG[_ana]->ROI[i]->name + ".bmp")); + } + } return true; } @@ -258,13 +332,14 @@ void ClassFlowAnalog::DrawROI(CImageBasis *_zw) int g = 255; int b = 0; - for (int i = 0; i < ROI.size(); ++i) - { - _zw->drawRect(ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay, r, g, b, 1); - _zw->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); - _zw->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); - _zw->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); - } + for (int _ana = 0; _ana < ANALOG.size(); ++_ana) + for (int i = 0; i < ANALOG[_ana]->ROI.size(); ++i) + { + _zw->drawRect(ANALOG[_ana]->ROI[i]->posx, ANALOG[_ana]->ROI[i]->posy, ANALOG[_ana]->ROI[i]->deltax, ANALOG[_ana]->ROI[i]->deltay, r, g, b, 1); + _zw->drawCircle((int) (ANALOG[_ana]->ROI[i]->posx + ANALOG[_ana]->ROI[i]->deltax/2), (int) (ANALOG[_ana]->ROI[i]->posy + ANALOG[_ana]->ROI[i]->deltay/2), (int) (ANALOG[_ana]->ROI[i]->deltax/2), r, g, b, 2); + _zw->drawLine((int) (ANALOG[_ana]->ROI[i]->posx + ANALOG[_ana]->ROI[i]->deltax/2), (int) ANALOG[_ana]->ROI[i]->posy, (int) (ANALOG[_ana]->ROI[i]->posx + ANALOG[_ana]->ROI[i]->deltax/2), (int) (ANALOG[_ana]->ROI[i]->posy + ANALOG[_ana]->ROI[i]->deltay), r, g, b, 2); + _zw->drawLine((int) ANALOG[_ana]->ROI[i]->posx, (int) (ANALOG[_ana]->ROI[i]->posy + ANALOG[_ana]->ROI[i]->deltay/2), (int) ANALOG[_ana]->ROI[i]->posx + ANALOG[_ana]->ROI[i]->deltax, (int) (ANALOG[_ana]->ROI[i]->posy + ANALOG[_ana]->ROI[i]->deltay/2), r, g, b, 2); + } } bool ClassFlowAnalog::doNeuralNetwork(string time) @@ -288,39 +363,38 @@ bool ClassFlowAnalog::doNeuralNetwork(string time) tflite->MakeAllocate(); #endif - for (int i = 0; i < ROI.size(); ++i) + for (int _ana = 0; _ana < ANALOG.size(); ++_ana) { - 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->LoadInputImageBasis(ROI[i]->image); - 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); - - if (isLogImage) + for (int i = 0; i < ANALOG[_ana]->ROI.size(); ++i) { - LogImage(logPath, ROI[i]->name, &ROI[i]->result, NULL, time, ROI[i]->image_org); + printf("Analog %d - TfLite\n", i); + + float f1, f2; + f1 = 0; f2 = 0; + + #ifndef OHNETFLITE + tflite->LoadInputImageBasis(ANALOG[_ana]->ROI[i]->image); + 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); + ANALOG[_ana]->ROI[i]->result = result * 10; + + printf("Result Analog%i: %f\n", i, ANALOG[_ana]->ROI[i]->result); + + if (isLogImage) + { + LogImage(logPath, ANALOG[_ana]->ROI[i]->name, &ANALOG[_ana]->ROI[i]->result, NULL, time, ANALOG[_ana]->ROI[i]->image_org); + } } } + #ifndef OHNETFLITE delete tflite; #endif @@ -333,18 +407,78 @@ std::vector ClassFlowAnalog::GetHTMLInfo() { std::vector result; - for (int i = 0; i < ROI.size(); ++i) - { - HTMLInfo *zw = new HTMLInfo; - zw->filename = ROI[i]->name + ".bmp"; - zw->filename_org = ROI[i]->name + ".jpg"; - zw->val = ROI[i]->result; - zw->image = ROI[i]->image; - zw->image_org = ROI[i]->image_org; - result.push_back(zw); - } + for (int _ana = 0; _ana < ANALOG.size(); ++_ana) + for (int i = 0; i < ANALOG[_ana]->ROI.size(); ++i) + { + if (ANALOG[_ana]->name == "default") + ANALOG[_ana]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ANALOG[_ana]->ROI[i]->name + ".bmp")); + else + ANALOG[_ana]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ANALOG[_ana]->name + "_" + ANALOG[_ana]->ROI[i]->name + ".bmp")); + + + HTMLInfo *zw = new HTMLInfo; + if (ANALOG[_ana]->name == "default") + { + zw->filename = ANALOG[_ana]->ROI[i]->name + ".bmp"; + zw->filename_org = ANALOG[_ana]->ROI[i]->name + ".jpg"; + } + else + { + zw->filename = ANALOG[_ana]->name + "_" + ANALOG[_ana]->ROI[i]->name + ".bmp"; + zw->filename_org = ANALOG[_ana]->name + "_" + ANALOG[_ana]->ROI[i]->name + ".jpg"; + } + + zw->val = ANALOG[_ana]->ROI[i]->result; + zw->image = ANALOG[_ana]->ROI[i]->image; + zw->image_org = ANALOG[_ana]->ROI[i]->image_org; + + result.push_back(zw); + } return result; } + +int ClassFlowAnalog::getAnzahlANALOG() +{ + return ANALOG.size(); +} + +string ClassFlowAnalog::getNameANALOG(int _analog) +{ + if (_analog < ANALOG.size()) + return ANALOG[_analog]->name; + + return "ANALOG DOES NOT EXIST"; +} + +analog* ClassFlowAnalog::GetANALOG(int _analog) +{ + if (_analog < ANALOG.size()) + return ANALOG[_analog]; + + return NULL; +} + + + +void ClassFlowAnalog::UpdateNameNumbers(std::vector *_name_numbers) +{ + for (int _dig = 0; _dig < ANALOG.size(); _dig++) + { + std::string _name = ANALOG[_dig]->name; + bool found = false; + for (int i = 0; i < (*_name_numbers).size(); ++i) + { + if ((*_name_numbers)[i] == _name) + found = true; + } + if (!found) + (*_name_numbers).push_back(_name); + } +} + + + + diff --git a/code/components/jomjol_flowcontroll/ClassFlowAnalog.h b/code/components/jomjol_flowcontroll/ClassFlowAnalog.h index 08a29be7..bd9af089 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowAnalog.h +++ b/code/components/jomjol_flowcontroll/ClassFlowAnalog.h @@ -10,12 +10,19 @@ struct roianalog { string name; }; +struct analog { + string name; + std::vector ROI; +}; + class ClassFlowAnalog : public ClassFlowImage { protected: - std::vector ROI; +// std::vector ROI; + std::vector ANALOG; + string cnnmodelfile; int modelxsize, modelysize; int ZeigerEval(float zahl, int ziffer_vorgaenger); @@ -24,7 +31,8 @@ protected: ClassFlowAlignment* flowpostalignment; - void SetInitialParameter(void); + void SetInitialParameter(void); + public: bool extendedResolution; @@ -34,14 +42,23 @@ public: bool ReadParameter(FILE* pfile, string& aktparamgraph); bool doFlow(string time); string getHTMLSingleStep(string host); - string getReadout(); + string getReadout(int _analog); void DrawROI(CImageBasis *_zw); bool doNeuralNetwork(string time); bool doAlignAndCut(string time); std::vector GetHTMLInfo(); - int AnzahlROIs(); + int AnzahlROIs(int _analog); + + int getAnzahlANALOG(); + analog* GetANALOG(int _analog); + analog* GetANALOG(string _name, bool _create); + analog* FindANALOG(string _name_number); + string getNameANALOG(int _analog); + + void UpdateNameNumbers(std::vector *_name_numbers); + string name(){return "ClassFlowAnalog";}; }; diff --git a/code/components/jomjol_flowcontroll/ClassFlowControll.cpp b/code/components/jomjol_flowcontroll/ClassFlowControll.cpp index 7399aa23..10013455 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowControll.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowControll.cpp @@ -120,6 +120,7 @@ ClassFlow* ClassFlowControll::CreateClassFlow(std::string _type) } if (toUpper(_type).compare("[MQTT]") == 0) cfc = new ClassFlowMQTT(&FlowControll); + if (toUpper(_type).compare("[POSTPROCESSING]") == 0) { cfc = new ClassFlowPostProcessing(&FlowControll); @@ -262,6 +263,38 @@ void ClassFlowControll::UpdateAktStatus(std::string _flow) } +string ClassFlowControll::getReadoutAll(int _type) +{ + std::vector numbers = flowpostprocessing->GetNumbers(); + std::string out = ""; + + for (int i = 0; i < numbers.size(); ++i) + { + out = out + numbers[i]->name + "\t"; + switch (_type) { + case READOUT_TYPE_VALUE: + out = out + numbers[i]->ReturnValue; + break; + case READOUT_TYPE_PREVALUE: + out = out + numbers[i]->ReturnPreValue; + break; + case READOUT_TYPE_RAWVALUE: + out = out + numbers[i]->ReturnRawValue; + break; + case READOUT_TYPE_ERROR: + out = out + numbers[i]->ErrorMessageText; + break; + } + if (i < numbers.size()-1) + out = out + "\r\n"; + } + +// printf("OUT: %s", out.c_str()); + + return out; +} + + string ClassFlowControll::getReadout(bool _rawvalue = false, bool _noerror = false) { if (flowpostprocessing) @@ -285,17 +318,17 @@ string ClassFlowControll::getReadout(bool _rawvalue = false, bool _noerror = fal return result; } -string ClassFlowControll::GetPrevalue() +string ClassFlowControll::GetPrevalue(std::string _number) { if (flowpostprocessing) { - return flowpostprocessing->GetPreValue(); + return flowpostprocessing->GetPreValue(_number); } return std::string(); } -std::string ClassFlowControll::UpdatePrevalue(std::string _newvalue) +std::string ClassFlowControll::UpdatePrevalue(std::string _newvalue, std::string _numbers) { float zw; char* p; @@ -317,7 +350,7 @@ std::string ClassFlowControll::UpdatePrevalue(std::string _newvalue) if (flowpostprocessing) { - flowpostprocessing->SavePreValue(zw); + flowpostprocessing->SetPreValue(zw, _numbers); return _newvalue; } diff --git a/code/components/jomjol_flowcontroll/ClassFlowControll.h b/code/components/jomjol_flowcontroll/ClassFlowControll.h index 6ef26a2c..7a21406b 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowControll.h +++ b/code/components/jomjol_flowcontroll/ClassFlowControll.h @@ -11,6 +11,12 @@ #include "ClassFlowMQTT.h" +#define READOUT_TYPE_VALUE 0 +#define READOUT_TYPE_PREVALUE 1 +#define READOUT_TYPE_RAWVALUE 2 +#define READOUT_TYPE_ERROR 3 + + class ClassFlowControll : public ClassFlow { @@ -38,8 +44,9 @@ public: void doFlowMakeImageOnly(string time); bool getStatusSetupModus(){return SetupModeActive;}; string getReadout(bool _rawvalue, bool _noerror); - string UpdatePrevalue(std::string _newvalue); - string GetPrevalue(); + string getReadoutAll(int _type); + string UpdatePrevalue(std::string _newvalue, std::string _numbers); + string GetPrevalue(std::string _number = ""); bool ReadParameter(FILE* pfile, string& aktparamgraph); esp_err_t GetJPGStream(std::string _fn, httpd_req_t *req); diff --git a/code/components/jomjol_flowcontroll/ClassFlowDigit.cpp b/code/components/jomjol_flowcontroll/ClassFlowDigit.cpp index 6e37cc0b..dad5fcfe 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowDigit.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowDigit.cpp @@ -64,16 +64,16 @@ ClassFlowDigit::ClassFlowDigit(std::vector* lfc, ClassFlow *_prev) : } } -string ClassFlowDigit::getReadout() +string ClassFlowDigit::getReadout(int _digit = 0) { string rst = ""; - for (int i = 0; i < ROI.size(); ++i) + for (int i = 0; i < DIGIT[_digit]->ROI.size(); ++i) { - if (ROI[i]->resultklasse == 10) + if (DIGIT[_digit]->ROI[i]->resultklasse == 10) rst = rst + "N"; else - rst = rst + std::to_string(ROI[i]->resultklasse); + rst = rst + std::to_string(DIGIT[_digit]->ROI[i]->resultklasse); } return rst; @@ -91,18 +91,11 @@ bool ClassFlowDigit::ReadParameter(FILE* pfile, string& aktparamgraph) printf("aktparamgraph: %s\n", aktparamgraph.c_str()); - -/* - if ((aktparamgraph.compare("[Digits]") != 0) && (aktparamgraph.compare(";[Digits]") != 0)) // Paragraph passt nich zu MakeImage - return false; -*/ - if ((aktparamgraph.compare(0, 7, "[Digits") != 0) && (aktparamgraph.compare(0, 8, ";[Digits") != 0)) // Paragraph passt nich zu MakeImage return false; int _pospkt = aktparamgraph.find_first_of("."); int _posklammerzu = aktparamgraph.find_first_of("]"); -// printf("Pos: %d, %d\n", _pospkt, _posklammerzu); if (_pospkt > -1) NameDigit = aktparamgraph.substr(_pospkt+1, _posklammerzu - _pospkt-1); else @@ -137,8 +130,8 @@ bool ClassFlowDigit::ReadParameter(FILE* pfile, string& aktparamgraph) } if (zerlegt.size() >= 5) { - roi* neuroi = new roi; - neuroi->name = zerlegt[0]; + digit* _digit = GetDIGIT(zerlegt[0], true); + roi* neuroi = _digit->ROI[_digit->ROI.size()-1]; neuroi->posx = std::stoi(zerlegt[1]); neuroi->posy = std::stoi(zerlegt[2]); neuroi->deltax = std::stoi(zerlegt[3]); @@ -146,7 +139,6 @@ bool ClassFlowDigit::ReadParameter(FILE* pfile, string& aktparamgraph) neuroi->resultklasse = -1; neuroi->image = NULL; neuroi->image_org = NULL; - ROI.push_back(neuroi); } if ((toUpper(zerlegt[0]) == "SAVEALLFILES") && (zerlegt.size() > 1)) @@ -157,15 +149,74 @@ bool ClassFlowDigit::ReadParameter(FILE* pfile, string& aktparamgraph) } - for (int i = 0; i < ROI.size(); ++i) - { - ROI[i]->image = new CImageBasis(modelxsize, modelysize, 3); - ROI[i]->image_org = new CImageBasis(ROI[i]->deltax, ROI[i]->deltay, 3); - } + for (int _dig = 0; _dig < DIGIT.size(); ++_dig) + for (int i = 0; i < DIGIT[_dig]->ROI.size(); ++i) + { + DIGIT[_dig]->ROI[i]->image = new CImageBasis(modelxsize, modelysize, 3); + DIGIT[_dig]->ROI[i]->image_org = new CImageBasis(DIGIT[_dig]->ROI[i]->deltax, DIGIT[_dig]->ROI[i]->deltay, 3); + } return true; } +digit* ClassFlowDigit::FindDIGIT(string _name_number) +{ + digit *_ret = NULL; + + for (int i = 0; i < DIGIT.size(); ++i) + { + if (DIGIT[i]->name == _name_number) + return DIGIT[i]; + } + + return NULL; +} + + +digit* ClassFlowDigit::GetDIGIT(string _name, bool _create = true) +{ + string _digit, _roi; + int _pospunkt = _name.find_first_of("."); +// printf("Name: %s, Pospunkt: %d\n", _name.c_str(), _pospunkt); + if (_pospunkt > -1) + { + _digit = _name.substr(0, _pospunkt); + _roi = _name.substr(_pospunkt+1, _name.length() - _pospunkt - 1); + } + else + { + _digit = "default"; + _roi = _name; + } + + digit *_ret = NULL; + + for (int i = 0; i < DIGIT.size(); ++i) + { + if (DIGIT[i]->name == _digit) + _ret = DIGIT[i]; + } + + if (!_create) // nicht gefunden und soll auch nicht erzeugt werden, ggf. geht eine NULL zurück + return _ret; + + if (_ret == NULL) + { + _ret = new digit; + _ret->name = _digit; + DIGIT.push_back(_ret); + } + + roi* neuroi = new roi; + neuroi->name = _roi; + _ret->ROI.push_back(neuroi); + + printf("GetDIGIT - digit %s - roi %s\n", _digit.c_str(), _roi.c_str()); + + return _ret; +} + + string ClassFlowDigit::getHTMLSingleStep(string host) { @@ -216,17 +267,32 @@ bool ClassFlowDigit::doAlignAndCut(string time) CAlignAndCutImage *caic = flowpostalignment->GetAlignAndCutImage(); - for (int i = 0; i < ROI.size(); ++i) + for (int _dig = 0; _dig < DIGIT.size(); ++_dig) { - printf("DigitalDigit %d - Align&Cut\n", i); - - caic->CutAndSave(ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay, ROI[i]->image_org); - if (SaveAllFiles) ROI[i]->image_org->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ROI[i]->name + ".jpg")); + printf("DIGIT[_dig]->ROI.size() %d\n", DIGIT[_dig]->ROI.size()); + for (int i = 0; i < DIGIT[_dig]->ROI.size(); ++i) + { + printf("DigitalDigit %d - Align&Cut\n", i); + + caic->CutAndSave(DIGIT[_dig]->ROI[i]->posx, DIGIT[_dig]->ROI[i]->posy, DIGIT[_dig]->ROI[i]->deltax, DIGIT[_dig]->ROI[i]->deltay, DIGIT[_dig]->ROI[i]->image_org); + if (SaveAllFiles) + { + if (DIGIT[_dig]->name == "default") + DIGIT[_dig]->ROI[i]->image_org->SaveToFile(FormatFileName("/sdcard/img_tmp/" + DIGIT[_dig]->ROI[i]->name + ".jpg")); + else + DIGIT[_dig]->ROI[i]->image_org->SaveToFile(FormatFileName("/sdcard/img_tmp/" + DIGIT[_dig]->name + "_" + DIGIT[_dig]->ROI[i]->name + ".jpg")); + } - ROI[i]->image_org->Resize(modelxsize, modelysize, ROI[i]->image); - if (SaveAllFiles) ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ROI[i]->name + ".bmp")); + DIGIT[_dig]->ROI[i]->image_org->Resize(modelxsize, modelysize, DIGIT[_dig]->ROI[i]->image); + if (SaveAllFiles) + { + if (DIGIT[_dig]->name == "default") + DIGIT[_dig]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + DIGIT[_dig]->ROI[i]->name + ".bmp")); + else + DIGIT[_dig]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + DIGIT[_dig]->name + "_" + DIGIT[_dig]->ROI[i]->name + ".bmp")); + } + } } - return true; } @@ -245,22 +311,23 @@ bool ClassFlowDigit::doNeuralNetwork(string time) tflite->MakeAllocate(); #endif - for (int i = 0; i < ROI.size(); ++i) - { - printf("DigitalDigit %d - TfLite\n", i); - - ROI[i]->resultklasse = 0; -#ifndef OHNETFLITE - ROI[i]->resultklasse = tflite->GetClassFromImageBasis(ROI[i]->image); - -#endif - printf("Result Digit%i: %d\n", i, ROI[i]->resultklasse); - - if (isLogImage) + for (int _dig = 0; _dig < DIGIT.size(); ++_dig) + for (int i = 0; i < DIGIT[_dig]->ROI.size(); ++i) { - LogImage(logPath, ROI[i]->name, NULL, &ROI[i]->resultklasse, time, ROI[i]->image_org); + printf("DigitalDigit %d - TfLite\n", i); + + DIGIT[_dig]->ROI[i]->resultklasse = 0; + #ifndef OHNETFLITE + DIGIT[_dig]->ROI[i]->resultklasse = tflite->GetClassFromImageBasis(DIGIT[_dig]->ROI[i]->image); + + #endif + printf("Result Digit%i: %d\n", i, DIGIT[_dig]->ROI[i]->resultklasse); + + if (isLogImage) + { + LogImage(logPath, DIGIT[_dig]->ROI[i]->name, NULL, &DIGIT[_dig]->ROI[i]->resultklasse, time, DIGIT[_dig]->ROI[i]->image_org); + } } - } #ifndef OHNETFLITE delete tflite; #endif @@ -269,25 +336,82 @@ bool ClassFlowDigit::doNeuralNetwork(string time) void ClassFlowDigit::DrawROI(CImageBasis *_zw) { - for (int i = 0; i < ROI.size(); ++i) - _zw->drawRect(ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay, 0, 0, 255, 2); + for (int _dig = 0; _dig < DIGIT.size(); ++_dig) + for (int i = 0; i < DIGIT[_dig]->ROI.size(); ++i) + _zw->drawRect(DIGIT[_dig]->ROI[i]->posx, DIGIT[_dig]->ROI[i]->posy, DIGIT[_dig]->ROI[i]->deltax, DIGIT[_dig]->ROI[i]->deltay, 0, 0, (255 - _dig*100), 2); } std::vector ClassFlowDigit::GetHTMLInfo() { std::vector result; - for (int i = 0; i < ROI.size(); ++i) - { - HTMLInfo *zw = new HTMLInfo; - zw->filename = ROI[i]->name + ".bmp"; - zw->filename_org = ROI[i]->name + ".jpg"; - zw->val = ROI[i]->resultklasse; - zw->image = ROI[i]->image; - zw->image_org = ROI[i]->image_org; - result.push_back(zw); - } + for (int _dig = 0; _dig < DIGIT.size(); ++_dig) + for (int i = 0; i < DIGIT[_dig]->ROI.size(); ++i) + { + if (DIGIT[_dig]->name == "default") + DIGIT[_dig]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + DIGIT[_dig]->ROI[i]->name + ".bmp")); + else + DIGIT[_dig]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + DIGIT[_dig]->name + "_" + DIGIT[_dig]->ROI[i]->name + ".bmp")); + + + HTMLInfo *zw = new HTMLInfo; + if (DIGIT[_dig]->name == "default") + { + zw->filename = DIGIT[_dig]->ROI[i]->name + ".bmp"; + zw->filename_org = DIGIT[_dig]->ROI[i]->name + ".jpg"; + } + else + { + zw->filename = DIGIT[_dig]->name + "_" + DIGIT[_dig]->ROI[i]->name + ".bmp"; + zw->filename_org = DIGIT[_dig]->name + "_" + DIGIT[_dig]->ROI[i]->name + ".jpg"; + } + + zw->val = DIGIT[_dig]->ROI[i]->resultklasse; + zw->image = DIGIT[_dig]->ROI[i]->image; + zw->image_org = DIGIT[_dig]->ROI[i]->image_org; + result.push_back(zw); + } return result; } +int ClassFlowDigit::getAnzahlDIGIT() +{ + return DIGIT.size(); +} + +string ClassFlowDigit::getNameDIGIT(int _digit) +{ + if (_digit < DIGIT.size()) + return DIGIT[_digit]->name; + + return "DIGIT DOES NOT EXIST"; +} + +digit* ClassFlowDigit::GetDIGIT(int _digit) +{ + if (_digit < DIGIT.size()) + return DIGIT[_digit]; + + return NULL; +} + +void ClassFlowDigit::UpdateNameNumbers(std::vector *_name_numbers) +{ + for (int _dig = 0; _dig < DIGIT.size(); _dig++) + { + std::string _name = DIGIT[_dig]->name; + bool found = false; + for (int i = 0; i < (*_name_numbers).size(); ++i) + { + if ((*_name_numbers)[i] == _name) + found = true; + } + if (!found) + (*_name_numbers).push_back(_name); + } +} + + + + diff --git a/code/components/jomjol_flowcontroll/ClassFlowDigit.h b/code/components/jomjol_flowcontroll/ClassFlowDigit.h index 3af92f85..f6d98616 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowDigit.h +++ b/code/components/jomjol_flowcontroll/ClassFlowDigit.h @@ -5,6 +5,8 @@ #include + + struct roi { int posx, posy, deltax, deltay; int resultklasse; @@ -13,11 +15,17 @@ struct roi { roi* next; }; +struct digit { + string name; + std::vector ROI; +}; + class ClassFlowDigit : public ClassFlowImage { protected: - std::vector ROI; +// std::vector ROI; + std::vector DIGIT; string cnnmodelfile; int modelxsize, modelysize; bool SaveAllFiles; @@ -31,6 +39,7 @@ protected: bool doNeuralNetwork(string time); bool doAlignAndCut(string time); + void SetInitialParameter(void); public: @@ -40,9 +49,18 @@ public: bool ReadParameter(FILE* pfile, string& aktparamgraph); bool doFlow(string time); string getHTMLSingleStep(string host); - string getReadout(); + string getReadout(int _digit); std::vector GetHTMLInfo(); + int getAnzahlDIGIT(); + digit* GetDIGIT(int _digit); + digit* GetDIGIT(string _name, bool _create); + digit* FindDIGIT(string _name_number); + + string getNameDIGIT(int _digit); + + void UpdateNameNumbers(std::vector *_name_numbers); + void DrawROI(CImageBasis *_zw); string name(){return "ClassFlowDigit";}; diff --git a/code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp b/code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp index 1d0e4c1b..b540e83f 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp @@ -13,6 +13,9 @@ void ClassFlowMQTT::SetInitialParameter(void) topicError = ""; topicRate = ""; topicTimeStamp = ""; + maintopic = ""; + mainerrortopic = ""; + clientname = "watermeter"; OldValue = ""; flowpostprocessing = NULL; @@ -21,6 +24,9 @@ void ClassFlowMQTT::SetInitialParameter(void) previousElement = NULL; ListFlowControll = NULL; disabled = false; + MQTTenable = false; + + } @@ -88,33 +94,24 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph) { this->uri = zerlegt[1]; } - if ((toUpper(zerlegt[0]) == "TOPIC") && (zerlegt.size() > 1)) - { - this->topic = zerlegt[1]; - } - if ((toUpper(zerlegt[0]) == "TOPICERROR") && (zerlegt.size() > 1)) - { - this->topicError = zerlegt[1]; - } - if ((toUpper(zerlegt[0]) == "TOPICRATE") && (zerlegt.size() > 1)) - { - this->topicRate = zerlegt[1]; - } - if ((toUpper(zerlegt[0]) == "TOPICTIMESTAMP") && (zerlegt.size() > 1)) - { - this->topicTimeStamp = zerlegt[1]; - } if ((toUpper(zerlegt[0]) == "CLIENTID") && (zerlegt.size() > 1)) { this->clientname = zerlegt[1]; } + if (((toUpper(zerlegt[0]) == "TOPIC") || (toUpper(zerlegt[0]) == "MAINTOPIC")) && (zerlegt.size() > 1)) + { + maintopic = zerlegt[1]; + } } - if ((uri.length() > 0) && (topic.length() > 0)) + if ((uri.length() > 0) && (maintopic.length() > 0)) { - MQTTInit(uri, clientname, user, password, topicError, 60); + mainerrortopic = maintopic + "/connection"; + MQTTInit(uri, clientname, user, password, mainerrortopic, 60); + MQTTPublish(mainerrortopic, "connected"); + MQTTenable = true; } return true; @@ -123,18 +120,47 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph) bool ClassFlowMQTT::doFlow(string zwtime) { + if (!MQTTenable) + return true; + std::string result; std::string resulterror = ""; std::string resultrate = ""; std::string resulttimestamp = ""; string zw = ""; + string namenumber = ""; + + MQTTPublish(mainerrortopic, "connected"); if (flowpostprocessing) { - result = flowpostprocessing->getReadoutParam(false, true); - resulterror = flowpostprocessing->getReadoutError(); - resultrate = flowpostprocessing->getReadoutRate(); - resulttimestamp = flowpostprocessing->getReadoutTimeStamp(); + std::vector NUMBERS = flowpostprocessing->GetNumbers(); + + for (int i = 0; i < NUMBERS.size(); ++i) + { + result = NUMBERS[i]->ReturnValueNoError; + resulterror = NUMBERS[i]->ErrorMessageText; + resultrate = std::to_string(NUMBERS[i]->FlowRateAct); + resulttimestamp = NUMBERS[i]->timeStamp; + + namenumber = NUMBERS[i]->name; + if (namenumber == "default") + namenumber = maintopic + "/"; + else + namenumber = maintopic + "/" + namenumber + "/"; + + zw = namenumber + "value"; + MQTTPublish(zw, result); + + zw = namenumber + "error"; + MQTTPublish(zw, resulterror, 1); + + zw = namenumber + "rate"; + MQTTPublish(zw, resultrate); + + zw = namenumber + "timestamp"; + MQTTPublish(zw, resulttimestamp); + } } else { @@ -149,25 +175,9 @@ bool ClassFlowMQTT::doFlow(string zwtime) result = result + "\t" + zw; } } + MQTTPublish(topic, result); } - MQTTPublish(topic, result); - - if (topicError.length() > 0) { - if (resulterror.length() == 0) - { - resulterror = " "; - } - MQTTPublish(topicError, resulterror, 1); - } - - if (topicRate.length() > 0) { - MQTTPublish(topicRate, resultrate); - } - - if (topicTimeStamp.length() > 0) { - MQTTPublish(topicTimeStamp, resulttimestamp); - } OldValue = result; diff --git a/code/components/jomjol_flowcontroll/ClassFlowMQTT.h b/code/components/jomjol_flowcontroll/ClassFlowMQTT.h index 99035659..71ff8455 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowMQTT.h +++ b/code/components/jomjol_flowcontroll/ClassFlowMQTT.h @@ -12,7 +12,10 @@ protected: std::string uri, topic, topicError, clientname, topicRate, topicTimeStamp; std::string OldValue; ClassFlowPostProcessing* flowpostprocessing; - std::string user, password; + std::string user, password; + bool MQTTenable; + + std::string maintopic, mainerrortopic; void SetInitialParameter(void); public: diff --git a/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp b/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp index e9d54cb0..8f6258f5 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp @@ -1,8 +1,6 @@ #include "ClassFlowPostProcessing.h" #include "Helper.h" -#include "ClassFlowAnalog.h" -#include "ClassFlowDigit.h" #include "ClassFlowMakeImage.h" #include "ClassLogFile.h" @@ -18,130 +16,205 @@ #define PREVALUE_TIME_FORMAT_INPUT "%d-%d-%dT%d:%d:%d" -string ClassFlowPostProcessing::GetPreValue() +string ClassFlowPostProcessing::GetPreValue(std::string _number) { std::string result; - bool isAnalog = false; - bool isDigit = false; + int index = -1; - int AnzahlAnalog = 0; - result = RundeOutput(PreValue, -DecimalShift); + if (_number == "") + _number = "default"; - for (int i = 0; i < ListFlowControll->size(); ++i) - { - if (((*ListFlowControll)[i])->name().compare("ClassFlowAnalog") == 0) - { - isAnalog = true; - AnzahlAnalog = ((ClassFlowAnalog*)(*ListFlowControll)[i])->AnzahlROIs(); - } - if (((*ListFlowControll)[i])->name().compare("ClassFlowDigit") == 0) - { - isDigit = true; - } - } + for (int i = 0; i < NUMBERS.size(); ++i) + if (NUMBERS[i]->name == _number) + index = i; - if (isDigit && isAnalog) - result = RundeOutput(PreValue, AnzahlAnalog - DecimalShift); +// result = RundeOutput(NUMBERS[index]->PreValue, -NUMBERS[index]->DecimalShift); + result = RundeOutput(NUMBERS[index]->PreValue, NUMBERS[index]->Nachkomma); + +// if (NUMBERS[index]->digit_roi && NUMBERS[index]->analog_roi) +// result = RundeOutput(NUMBERS[index]->PreValue, NUMBERS[index]->AnzahlAnalog - NUMBERS[index]->DecimalShift); return result; } +void ClassFlowPostProcessing::SetPreValue(float zw, string _numbers) +{ + for (int j = 0; j < NUMBERS.size(); ++j) + { + if (NUMBERS[j]->name == _numbers) + NUMBERS[j]->PreValue = zw; + } + UpdatePreValueINI = true; + SavePreValue(); +} + + bool ClassFlowPostProcessing::LoadPreValue(void) { + std::vector zerlegt; FILE* pFile; char zw[1024]; - string zwtime, zwvalue; + string zwtime, zwvalue, name; + bool _done = false; + + UpdatePreValueINI = false; // Konvertierung ins neue Format + pFile = fopen(FilePreValue.c_str(), "r"); if (pFile == NULL) return false; fgets(zw, 1024, pFile); - printf("%s", zw); + printf("Read Zeile Prevalue.ini: %s", zw); zwtime = trim(std::string(zw)); - - fgets(zw, 1024, pFile); - fclose(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(), PREVALUE_TIME_FORMAT_INPUT, &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; - - lastvalue = mktime(&whenStart); - - time(&tStart); - localtime(&tStart); - double difference = difftime(tStart, lastvalue); - difference /= 60; - if (difference > PreValueAgeStartup) + if (zwtime.length() == 0) return false; - Value = PreValue; - ReturnValue = to_string(Value); - ReturnValueNoError = ReturnValue; - - bool isAnalog = false; - bool isDigit = false; - int AnzahlAnalog = 0; - - for (int i = 0; i < ListFlowControll->size(); ++i) + zerlegt = HelperZerlegeZeile(zwtime, "\t"); + if (zerlegt.size() > 1) // neues Format { - if (((*ListFlowControll)[i])->name().compare("ClassFlowAnalog") == 0) - isAnalog = true; - if (((*ListFlowControll)[i])->name().compare("ClassFlowDigit") == 0) - isDigit = true; - } + while ((zerlegt.size() > 1) && !_done) + { + name = trim(zerlegt[0]); + zwtime = trim(zerlegt[1]); + zwvalue = trim(zerlegt[2]); - if (isDigit || isAnalog) + for (int j = 0; j < NUMBERS.size(); ++j) + { + if (NUMBERS[j]->name == name) + { + NUMBERS[j]->PreValue = stof(zwvalue.c_str()); + NUMBERS[j]->ReturnPreValue = RundeOutput(NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma); + + time_t tStart; + int yy, month, dd, hh, mm, ss; + struct tm whenStart; + + sscanf(zwtime.c_str(), PREVALUE_TIME_FORMAT_INPUT, &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; + + NUMBERS[j]->lastvalue = mktime(&whenStart); + + time(&tStart); + localtime(&tStart); + double difference = difftime(tStart, NUMBERS[j]->lastvalue); + difference /= 60; + if (difference > PreValueAgeStartup) + { + NUMBERS[j]->PreValueOkay = false; + } + else + { + NUMBERS[j]->PreValueOkay = true; + NUMBERS[j]->Value = NUMBERS[j]->PreValue; + NUMBERS[j]->ReturnValue = to_string(NUMBERS[j]->Value); + NUMBERS[j]->ReturnValueNoError = NUMBERS[j]->ReturnValue; + + if (NUMBERS[j]->digit_roi || NUMBERS[j]->analog_roi) + { + NUMBERS[j]->ReturnValue = RundeOutput(NUMBERS[j]->Value, NUMBERS[j]->AnzahlAnalog - NUMBERS[j]->DecimalShift); + NUMBERS[j]->ReturnValueNoError = NUMBERS[j]->ReturnValue; + } + } + + } + } + + if (!fgets(zw, 1024, pFile)) + _done = true; + else + { + printf("Read Zeile Prevalue.ini: %s", zw); + zerlegt = HelperZerlegeZeile(trim(std::string(zw)), "\t"); + if (zerlegt.size() > 1) + { + name = trim(zerlegt[0]); + zwtime = trim(zerlegt[1]); + zwvalue = trim(zerlegt[2]); + } + } + } + fclose(pFile); + } + else // altes Format { - ReturnValue = RundeOutput(Value, AnzahlAnalog - DecimalShift); - ReturnValueNoError = ReturnValue; - } - + fgets(zw, 1024, pFile); + fclose(pFile); + printf("%s", zw); + zwvalue = trim(std::string(zw)); + NUMBERS[0]->PreValue = stof(zwvalue.c_str()); + + time_t tStart; + int yy, month, dd, hh, mm, ss; + struct tm whenStart; + + sscanf(zwtime.c_str(), PREVALUE_TIME_FORMAT_INPUT, &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; + + printf("TIME: %d, %d, %d, %d, %d, %d\n", whenStart.tm_year, whenStart.tm_mon, whenStart.tm_wday, whenStart.tm_hour, whenStart.tm_min, whenStart.tm_sec); + + NUMBERS[0]->lastvalue = mktime(&whenStart); + + time(&tStart); + localtime(&tStart); + double difference = difftime(tStart, NUMBERS[0]->lastvalue); + difference /= 60; + if (difference > PreValueAgeStartup) + return false; + + NUMBERS[0]->Value = NUMBERS[0]->PreValue; + NUMBERS[0]->ReturnValue = to_string(NUMBERS[0]->Value); + NUMBERS[0]->ReturnValueNoError = NUMBERS[0]->ReturnValue; + + if (NUMBERS[0]->digit_roi || NUMBERS[0]->analog_roi) + { + NUMBERS[0]->ReturnValue = RundeOutput(NUMBERS[0]->Value, NUMBERS[0]->AnzahlAnalog - NUMBERS[0]->DecimalShift); + NUMBERS[0]->ReturnValueNoError = NUMBERS[0]->ReturnValue; + } + + UpdatePreValueINI = true; // Konvertierung ins neue Format + SavePreValue(); + } + return true; } -void ClassFlowPostProcessing::SavePreValue(float value, string zwtime) +void ClassFlowPostProcessing::SavePreValue() { FILE* pFile; + string _zw; + + if (!UpdatePreValueINI) // PreValues unverändert --> File muss nicht neu geschrieben werden + return; pFile = fopen(FilePreValue.c_str(), "w"); - if (strlen(zwtime.c_str()) == 0) + for (int j = 0; j < NUMBERS.size(); ++j) { - time_t rawtime; - struct tm* timeinfo; char buffer[80]; - - time(&rawtime); - timeinfo = localtime(&rawtime); - + struct tm* timeinfo = localtime(&NUMBERS[j]->lastvalue); strftime(buffer, 80, PREVALUE_TIME_FORMAT_OUTPUT, timeinfo); - timeStamp = std::string(buffer); - } - else - { - timeStamp = zwtime; + NUMBERS[j]->timeStamp = std::string(buffer); + + _zw = NUMBERS[j]->name + "\t" + NUMBERS[j]->timeStamp + "\t" + to_string(NUMBERS[j]->PreValue) + "\n"; + printf("Write PreValue Zeile: %s\n", _zw.c_str()); + + fputs(_zw.c_str(), pFile); } - PreValue = value; - - fputs(timeStamp.c_str(), pFile); - fputs("\n", pFile); - fputs(to_string(value).c_str(), pFile); - fputs("\n", pFile); + UpdatePreValueINI = false; fclose(pFile); } @@ -149,22 +222,19 @@ void ClassFlowPostProcessing::SavePreValue(float value, string zwtime) ClassFlowPostProcessing::ClassFlowPostProcessing(std::vector* lfc) { - FlowRateAct = 0; +// FlowRateAct = 0; PreValueUse = false; PreValueAgeStartup = 30; - AllowNegativeRates = false; - MaxRateValue = 0.1; ErrorMessage = false; ListFlowControll = NULL; - PreValueOkay = false; - useMaxRateValue = false; - checkDigitIncreaseConsistency = false; - DecimalShift = 0; - ErrorMessageText = ""; - timeStamp = ""; +// PreValueOkay = false; +// DecimalShift = 0; +// ErrorMessageText = ""; +// timeStamp = ""; FilePreValue = FormatFileName("/sdcard/config/prevalue.ini"); ListFlowControll = lfc; flowMakeImage = NULL; + UpdatePreValueINI = false; for (int i = 0; i < ListFlowControll->size(); ++i) { @@ -175,10 +245,59 @@ ClassFlowPostProcessing::ClassFlowPostProcessing(std::vector* lfc) } } +void ClassFlowPostProcessing::handleDecimalSeparator(string _decsep, string _value) +{ + string _digit, _decpos; + int _pospunkt = _decsep.find_first_of("."); +// printf("Name: %s, Pospunkt: %d\n", _decsep.c_str(), _pospunkt); + if (_pospunkt > -1) + _digit = _decsep.substr(0, _pospunkt); + else + _digit = "default"; + + for (int j = 0; j < NUMBERS.size(); ++j) + { + if (_digit == "default") // erstmal auf default setzen (falls sonst nichts gesetzt) + NUMBERS[j]->DecimalShift = stoi(_value); + + if (NUMBERS[j]->name == _digit) + NUMBERS[j]->DecimalShift = stoi(_value); + + NUMBERS[j]->Nachkomma = NUMBERS[j]->AnzahlAnalog - NUMBERS[j]->DecimalShift; + } +} + +void ClassFlowPostProcessing::handleMaxRateValue(string _decsep, string _value) +{ + string _digit, _decpos; + int _pospunkt = _decsep.find_first_of("."); +// printf("Name: %s, Pospunkt: %d\n", _decsep.c_str(), _pospunkt); + if (_pospunkt > -1) + _digit = _decsep.substr(0, _pospunkt); + else + _digit = "default"; + + for (int j = 0; j < NUMBERS.size(); ++j) + { + if (_digit == "default") // erstmal auf default setzen (falls sonst nichts gesetzt) + { + NUMBERS[j]->useMaxRateValue = true; + NUMBERS[j]->MaxRateValue = stof(_value); + } + + if (NUMBERS[j]->name == _digit) + { + NUMBERS[j]->useMaxRateValue = true; + NUMBERS[j]->MaxRateValue = stof(_value); + } + } +} + bool ClassFlowPostProcessing::ReadParameter(FILE* pfile, string& aktparamgraph) { std::vector zerlegt; + int _n; aktparamgraph = trim(aktparamgraph); @@ -190,53 +309,148 @@ bool ClassFlowPostProcessing::ReadParameter(FILE* pfile, string& aktparamgraph) if (aktparamgraph.compare("[PostProcessing]") != 0) // Paragraph passt nich zu MakeImage return false; + InitNUMBERS(); + + while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph)) { zerlegt = this->ZerlegeZeile(aktparamgraph); - if ((toUpper(zerlegt[0]) == "DECIMALSHIFT") && (zerlegt.size() > 1)) + std::string _param = GetParameterName(zerlegt[0]); + + if ((toUpper(_param) == "DECIMALSHIFT") && (zerlegt.size() > 1)) { - DecimalShift = stoi(zerlegt[1]); + handleDecimalSeparator(zerlegt[0], zerlegt[1]); + } + if ((toUpper(_param) == "MAXRATEVALUE") && (zerlegt.size() > 1)) + { + handleMaxRateValue(zerlegt[0], zerlegt[1]); } - if ((toUpper(zerlegt[0]) == "PREVALUEUSE") && (zerlegt.size() > 1)) + if ((toUpper(_param) == "PREVALUEUSE") && (zerlegt.size() > 1)) { if (toUpper(zerlegt[1]) == "TRUE") { PreValueUse = true; } } - if ((toUpper(zerlegt[0]) == "CHECKDIGITINCREASECONSISTENCY") && (zerlegt.size() > 1)) + if ((toUpper(_param) == "CHECKDIGITINCREASECONSISTENCY") && (zerlegt.size() > 1)) { if (toUpper(zerlegt[1]) == "TRUE") - checkDigitIncreaseConsistency = true; + for (_n = 0; _n < NUMBERS.size(); ++_n) + NUMBERS[_n]->checkDigitIncreaseConsistency = true; } - if ((toUpper(zerlegt[0]) == "ALLOWNEGATIVERATES") && (zerlegt.size() > 1)) + if ((toUpper(_param) == "ALLOWNEGATIVERATES") && (zerlegt.size() > 1)) { if (toUpper(zerlegt[1]) == "TRUE") - AllowNegativeRates = true; + for (_n = 0; _n < NUMBERS.size(); ++_n) + NUMBERS[_n]->AllowNegativeRates = true; } - if ((toUpper(zerlegt[0]) == "ERRORMESSAGE") && (zerlegt.size() > 1)) + if ((toUpper(_param) == "ERRORMESSAGE") && (zerlegt.size() > 1)) { if (toUpper(zerlegt[1]) == "TRUE") ErrorMessage = true; } - if ((toUpper(zerlegt[0]) == "PREVALUEAGESTARTUP") && (zerlegt.size() > 1)) + if ((toUpper(_param) == "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(); + LoadPreValue(); } + return true; } +void ClassFlowPostProcessing::InitNUMBERS() +{ +// ClassFlowDigit* _cdigit = NULL; +// ClassFlowAnalog* _canalog = NULL; + int anzDIGIT = 0; + int anzANALOG = 0; + std::vector name_numbers; + + flowAnalog = NULL; + flowDigit = NULL; + + for (int i = 0; i < ListFlowControll->size(); ++i) + { + if (((*ListFlowControll)[i])->name().compare("ClassFlowDigit") == 0) + { + flowDigit = (ClassFlowDigit*) (*ListFlowControll)[i]; + anzDIGIT = flowDigit->getAnzahlDIGIT(); + } + if (((*ListFlowControll)[i])->name().compare("ClassFlowAnalog") == 0) + { + flowAnalog = (ClassFlowAnalog*)(*ListFlowControll)[i]; + anzANALOG = flowAnalog->getAnzahlANALOG(); + } + } + + if (flowDigit) + flowDigit->UpdateNameNumbers(&name_numbers); + if (flowAnalog) + flowAnalog->UpdateNameNumbers(&name_numbers); + + printf("Anzahl NUMBERS: %d - DIGITS: %d, ANALOG: %d\n", name_numbers.size(), anzDIGIT, anzANALOG); + + for (int _num = 0; _num < name_numbers.size(); ++_num) + { + NumberPost *_number = new NumberPost; + + _number->name = name_numbers[_num]; + + _number->digit_roi = NULL; + if (flowDigit) + _number->digit_roi = flowDigit->FindDIGIT(name_numbers[_num]); + + if (_number->digit_roi) + _number->AnzahlDigital = _number->digit_roi->ROI.size(); + else + _number->AnzahlDigital = 0; + + _number->analog_roi = NULL; + if (flowAnalog) + _number->analog_roi = flowAnalog->FindANALOG(name_numbers[_num]); + + + if (_number->analog_roi) + _number->AnzahlAnalog = _number->analog_roi->ROI.size(); + else + _number->AnzahlAnalog = 0; + + _number->ReturnRawValue = ""; // Rohwert (mit N & führenden 0) + _number->ReturnValue = ""; // korrigierter Rückgabewert, ggf. mit Fehlermeldung + _number->ReturnValueNoError = ""; // korrigierter Rückgabewert ohne Fehlermeldung + _number->ErrorMessageText = ""; // Fehlermeldung bei Consistency Check + _number->ReturnPreValue = ""; + _number->PreValueOkay = false; + _number->AllowNegativeRates = false; + _number->MaxRateValue = 0.1; + _number->useMaxRateValue = false; + _number->checkDigitIncreaseConsistency = false; + _number->PreValueOkay = false; + _number->useMaxRateValue = false; + _number->DecimalShift = 0; + + _number->FlowRateAct = 0; // m3 / min + _number->PreValue = 0; // letzter Wert, der gut ausgelesen wurde + _number->Value = 0; // letzer ausgelesener Wert, inkl. Korrekturen + _number->ReturnRawValue = ""; // Rohwert (mit N & führenden 0) + _number->ReturnValue = ""; // korrigierter Rückgabewert, ggf. mit Fehlermeldung + _number->ReturnValueNoError = ""; // korrigierter Rückgabewert ohne Fehlermeldung + _number->ErrorMessageText = ""; // Fehlermeldung bei Consistency Check + + _number->Nachkomma = _number->AnzahlAnalog; + + NUMBERS.push_back(_number); + } + + for (int i = 0; i < NUMBERS.size(); ++i) + printf("Number %s, Anz DIG: %d, Anz ANA %d\n", NUMBERS[i]->name.c_str(), NUMBERS[i]->AnzahlDigital, NUMBERS[i]->AnzahlAnalog); +} + string ClassFlowPostProcessing::ShiftDecimal(string in, int _decShift){ if (_decShift == 0){ @@ -285,173 +499,127 @@ bool ClassFlowPostProcessing::doFlow(string zwtime) string digit = ""; string analog = ""; string zwvalue; - bool isdigit = false; - bool isanalog = false; - int AnzahlAnalog = 0; string zw; time_t imagetime = 0; string rohwert; - ErrorMessageText = ""; - - - 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(); - } - } +// ErrorMessageText = ""; + imagetime = flowMakeImage->getTimeImageTaken(); if (imagetime == 0) time(&imagetime); struct tm* timeinfo; timeinfo = localtime(&imagetime); - char strftime_buf[64]; strftime(strftime_buf, sizeof(strftime_buf), "%Y-%m-%dT%H:%M:%S", timeinfo); zwtime = std::string(strftime_buf); + printf("Anzahl NUMBERS: %d\n", NUMBERS.size()); - // // TESTING ONLY//////////////////// - // isdigit = true; digit = "12N"; - // isanalog = true; analog = "456"; - - ReturnRawValue = ""; - - if (isdigit) - ReturnRawValue = digit; - if (isdigit && isanalog) - ReturnRawValue = ReturnRawValue + "."; - if (isanalog) - ReturnRawValue = ReturnRawValue + analog; - - - if (!isdigit) + for (int j = 0; j < NUMBERS.size(); ++j) { - AnzahlAnalog = 0; - } + NUMBERS[j]->ReturnRawValue = ""; + NUMBERS[j]->ErrorMessageText = ""; - ReturnRawValue = ShiftDecimal(ReturnRawValue, DecimalShift); + if (NUMBERS[j]->digit_roi) + NUMBERS[j]->ReturnRawValue = flowDigit->getReadout(j); + if (NUMBERS[j]->digit_roi && NUMBERS[j]->analog_roi) + NUMBERS[j]->ReturnRawValue = NUMBERS[j]->ReturnRawValue + "."; + if (NUMBERS[j]->analog_roi) + NUMBERS[j]->ReturnRawValue = NUMBERS[j]->ReturnRawValue + flowAnalog->getReadout(j); - rohwert = ReturnRawValue; + NUMBERS[j]->ReturnRawValue = ShiftDecimal(NUMBERS[j]->ReturnRawValue, NUMBERS[j]->DecimalShift); - if (!PreValueUse || !PreValueOkay) - { - ReturnValue = ReturnRawValue; - ReturnValueNoError = ReturnRawValue; + rohwert = NUMBERS[j]->ReturnRawValue; - if ((findDelimiterPos(ReturnValue, "N") == std::string::npos) && (ReturnValue.length() > 0)) + if (!PreValueUse || !NUMBERS[j]->PreValueOkay) { - while ((ReturnValue.length() > 1) && (ReturnValue[0] == '0')) - { - ReturnValue.erase(0, 1); - } - Value = std::stof(ReturnValue); - ReturnValueNoError = ReturnValue; + NUMBERS[j]->ReturnValue = NUMBERS[j]->ReturnRawValue; + NUMBERS[j]->ReturnValueNoError = NUMBERS[j]->ReturnRawValue; - PreValueOkay = true; - PreValue = Value; - if (flowMakeImage) + if ((findDelimiterPos(NUMBERS[j]->ReturnValue, "N") == std::string::npos) && (NUMBERS[j]->ReturnValue.length() > 0)) { - lastvalue = flowMakeImage->getTimeImageTaken(); - zwtime = ConvertTimeToString(lastvalue, PREVALUE_TIME_FORMAT_OUTPUT); - } - else - { - time(&lastvalue); - localtime(&lastvalue); - } + while ((NUMBERS[j]->ReturnValue.length() > 1) && (NUMBERS[j]->ReturnValue[0] == '0')) + { + NUMBERS[j]->ReturnValue.erase(0, 1); + } + NUMBERS[j]->Value = std::stof(NUMBERS[j]->ReturnValue); + NUMBERS[j]->ReturnValueNoError = NUMBERS[j]->ReturnValue; - SavePreValue(Value, zwtime); + NUMBERS[j]->PreValueOkay = true; + NUMBERS[j]->PreValue = NUMBERS[j]->Value; + NUMBERS[j]->ReturnPreValue = RundeOutput(NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma); + NUMBERS[j]->lastvalue = flowMakeImage->getTimeImageTaken(); + zwtime = ConvertTimeToString(NUMBERS[j]->lastvalue, PREVALUE_TIME_FORMAT_OUTPUT); + + UpdatePreValueINI = true; + SavePreValue(); + } + } + else + { + zw = ErsetzteN(NUMBERS[j]->ReturnRawValue, NUMBERS[j]->PreValue); + + NUMBERS[j]->Value = std::stof(zw); + if (NUMBERS[j]->checkDigitIncreaseConsistency) + { + NUMBERS[j]->Value = checkDigitConsistency(NUMBERS[j]->Value, NUMBERS[j]->DecimalShift, NUMBERS[j]->analog_roi != NULL, NUMBERS[j]->PreValue); + } + + zwvalue = RundeOutput(NUMBERS[j]->Value, NUMBERS[j]->AnzahlAnalog - NUMBERS[j]->DecimalShift); + + if ((!NUMBERS[j]->AllowNegativeRates) && (NUMBERS[j]->Value < NUMBERS[j]->PreValue)) + { + NUMBERS[j]->ErrorMessageText = NUMBERS[j]->ErrorMessageText + "Neg. Rate - Read: " + zwvalue + " - Raw: " + NUMBERS[j]->ReturnRawValue + " - Pre: " + std::to_string(NUMBERS[j]->Value) + " "; + NUMBERS[j]->Value = NUMBERS[j]->PreValue; + zwvalue = RundeOutput(NUMBERS[j]->Value, NUMBERS[j]->AnzahlAnalog - NUMBERS[j]->DecimalShift); + } + + if (NUMBERS[j]->useMaxRateValue && (abs(NUMBERS[j]->Value - NUMBERS[j]->PreValue) > NUMBERS[j]->MaxRateValue)) + { + NUMBERS[j]->ErrorMessageText = NUMBERS[j]->ErrorMessageText + "Rate too high - Read: " + RundeOutput(NUMBERS[j]->Value, NUMBERS[j]->Nachkomma) + " - Pre: " + RundeOutput(NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma) + " "; + NUMBERS[j]->Value = NUMBERS[j]->PreValue; + zwvalue = RundeOutput(NUMBERS[j]->Value, NUMBERS[j]->Nachkomma); + } + + NUMBERS[j]->ReturnValueNoError = zwvalue; + NUMBERS[j]->ReturnValue = zwvalue; + if (NUMBERS[j]->ErrorMessage && (NUMBERS[j]->ErrorMessageText.length() > 0)) + NUMBERS[j]->ReturnValue = NUMBERS[j]->ReturnValue + "\t" + NUMBERS[j]->ErrorMessageText; + + + double difference = difftime(imagetime, NUMBERS[j]->lastvalue); // in Sekunden + difference /= 60; // in Minuten + NUMBERS[j]->FlowRateAct = (NUMBERS[j]->Value - NUMBERS[j]->PreValue) / difference; + NUMBERS[j]->lastvalue = imagetime; + + if (NUMBERS[j]->ErrorMessageText.length() == 0) + { + NUMBERS[j]->PreValue = NUMBERS[j]->Value; + NUMBERS[j]->ReturnPreValue = RundeOutput(NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma); + NUMBERS[j]->ErrorMessageText = "no error"; + UpdatePreValueINI = true; + } } - 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)) - { - ErrorMessageText = ErrorMessageText + "Negative Rate - Returned old value - read value: " + zwvalue + " - raw value: " + ReturnRawValue + " - checked value: " + std::to_string(Value) + " "; - Value = PreValue; - zwvalue = RundeOutput(Value, AnzahlAnalog - DecimalShift); - } - - if (useMaxRateValue && (abs(Value - PreValue) > MaxRateValue)) - { - ErrorMessageText = ErrorMessageText + "Rate too high - Returned old value - read value: " + zwvalue + " - checked value: " + RundeOutput(Value, AnzahlAnalog - DecimalShift) + " "; - Value = PreValue; - zwvalue = RundeOutput(Value, AnzahlAnalog - DecimalShift); - } - - - ReturnValueNoError = zwvalue; - ReturnValue = zwvalue; - if (ErrorMessage && (ErrorMessageText.length() > 0)) - ReturnValue = ReturnValue + "\t" + ErrorMessageText; - - time_t currenttime; - if (flowMakeImage) - { - currenttime = flowMakeImage->getTimeImageTaken(); - zwtime = ConvertTimeToString(currenttime, PREVALUE_TIME_FORMAT_OUTPUT); - } - else - { - time(¤ttime); - localtime(¤ttime); - } - - double difference = difftime(currenttime, lastvalue); // in Sekunden - difference /= 60; // in Minuten - FlowRateAct = (Value - PreValue) / difference; - lastvalue = currenttime; -// std::string _zw = "CalcRate: " + std::to_string(FlowRateAct) + " TimeDifference[min]: " + std::to_string(difference); -// _zw = _zw + " Value: " + std::to_string(Value) + " PreValue: " + std::to_string(PreValue); -// LogFile.WriteToFile(_zw); - - if (ErrorMessageText.length() == 0) - { - PreValue = Value; - ErrorMessageText = "no error"; - SavePreValue(Value, zwtime); - } + SavePreValue(); return true; } -string ClassFlowPostProcessing::getReadout() +string ClassFlowPostProcessing::getReadout(int _number) { - return ReturnValue; + return NUMBERS[_number]->ReturnValue; } -string ClassFlowPostProcessing::getReadoutParam(bool _rawValue, bool _noerror) +string ClassFlowPostProcessing::getReadoutParam(bool _rawValue, bool _noerror, int _number) { if (_rawValue) - return ReturnRawValue; + return NUMBERS[_number]->ReturnRawValue; if (_noerror) - return ReturnValueNoError; - return ReturnValue; + return NUMBERS[_number]->ReturnValueNoError; + return NUMBERS[_number]->ReturnValue; } string ClassFlowPostProcessing::RundeOutput(float _in, int _anzNachkomma){ @@ -478,7 +646,7 @@ string ClassFlowPostProcessing::RundeOutput(float _in, int _anzNachkomma){ } -string ClassFlowPostProcessing::ErsetzteN(string input) +string ClassFlowPostProcessing::ErsetzteN(string input, float _prevalue) { int posN, posPunkt; int pot, ziffer; @@ -499,7 +667,7 @@ string ClassFlowPostProcessing::ErsetzteN(string input) pot = posPunkt - posN; } - zw = PreValue / pow(10, pot); + zw =_prevalue / pow(10, pot); ziffer = ((int) zw) % 10; input[posN] = ziffer + 48; @@ -509,7 +677,7 @@ string ClassFlowPostProcessing::ErsetzteN(string input) return input; } -float ClassFlowPostProcessing::checkDigitConsistency(float input, int _decilamshift, bool _isanalog){ +float ClassFlowPostProcessing::checkDigitConsistency(float input, int _decilamshift, bool _isanalog, float _preValue){ int aktdigit, olddigit; int aktdigit_before, olddigit_before; int pot, pot_max; @@ -527,12 +695,12 @@ float ClassFlowPostProcessing::checkDigitConsistency(float input, int _decilamsh { zw = input / pow(10, pot-1); aktdigit_before = ((int) zw) % 10; - zw = PreValue / pow(10, pot-1); + 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); + zw = _preValue / pow(10, pot); olddigit = ((int) zw) % 10; no_nulldurchgang = (olddigit_before <= aktdigit_before); @@ -558,18 +726,18 @@ float ClassFlowPostProcessing::checkDigitConsistency(float input, int _decilamsh return input; } -string ClassFlowPostProcessing::getReadoutRate() +string ClassFlowPostProcessing::getReadoutRate(int _number) { - return std::to_string(FlowRateAct); + return std::to_string(NUMBERS[_number]->FlowRateAct); } -string ClassFlowPostProcessing::getReadoutTimeStamp() +string ClassFlowPostProcessing::getReadoutTimeStamp(int _number) { - return timeStamp; + return NUMBERS[_number]->timeStamp; } -string ClassFlowPostProcessing::getReadoutError() +string ClassFlowPostProcessing::getReadoutError(int _number) { - return ErrorMessageText; + return NUMBERS[_number]->ErrorMessageText; } diff --git a/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.h b/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.h index 8a115705..48a5510e 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.h +++ b/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.h @@ -1,58 +1,94 @@ #pragma once #include "ClassFlow.h" #include "ClassFlowMakeImage.h" +#include "ClassFlowAnalog.h" +#include "ClassFlowDigit.h" + #include +struct NumberPost { +// int PreValueAgeStartup; + float MaxRateValue; + bool useMaxRateValue; + bool ErrorMessage; + bool PreValueOkay; + bool AllowNegativeRates; + bool checkDigitIncreaseConsistency; + time_t lastvalue; + string timeStamp; + float FlowRateAct; // m3 / min + 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 ReturnPreValue; // korrigierter Rückgabewert ohne Fehlermeldung + string ReturnValueNoError; + string ErrorMessageText; // Fehlermeldung bei Consistency Check + int AnzahlAnalog; + int AnzahlDigital; + int DecimalShift; + int Nachkomma; +// ClassFlowAnalog* ANALOG; +// ClassFlowDigit* DIGIT; + + digit *digit_roi; + analog *analog_roi; + + + + string name; +}; + + class ClassFlowPostProcessing : public ClassFlow { protected: + std::vector NUMBERS; + bool UpdatePreValueINI; + bool PreValueUse; int PreValueAgeStartup; - bool AllowNegativeRates; - float MaxRateValue; - bool useMaxRateValue; bool ErrorMessage; - bool PreValueOkay; - bool checkDigitIncreaseConsistency; - int DecimalShift; - time_t lastvalue; - float FlowRateAct; // m3 / min + + + ClassFlowAnalog* flowAnalog; + ClassFlowDigit* flowDigit; 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 - string ErrorMessageText; // Fehlermeldung bei Consistency Check - string timeStamp; ClassFlowMakeImage *flowMakeImage; bool LoadPreValue(void); string ShiftDecimal(string in, int _decShift); - string ErsetzteN(string); - float checkDigitConsistency(float input, int _decilamshift, bool _isanalog); + string ErsetzteN(string, float _prevalue); + float checkDigitConsistency(float input, int _decilamshift, bool _isanalog, float _preValue); string RundeOutput(float _in, int _anzNachkomma); + void InitNUMBERS(); + void handleDecimalSeparator(string _decsep, string _value); + void handleMaxRateValue(string _decsep, string _value); + + public: ClassFlowPostProcessing(std::vector* lfc); bool ReadParameter(FILE* pfile, string& aktparamgraph); bool doFlow(string time); - string getReadout(); - string getReadoutParam(bool _rawValue, bool _noerror); - string getReadoutError(); - string getReadoutRate(); - string getReadoutTimeStamp(); - void SavePreValue(float value, string time = ""); - string GetPreValue(); + string getReadout(int _number); + string getReadoutParam(bool _rawValue, bool _noerror, int _number = 0); + string getReadoutError(int _number = 0); + string getReadoutRate(int _number = 0); + string getReadoutTimeStamp(int _number = 0); + void SavePreValue(); + string GetPreValue(std::string _number = ""); + void SetPreValue(float zw, string _numbers); + std::vector GetNumbers(){return NUMBERS;}; string name(){return "ClassFlowPostProcessing";}; }; diff --git a/code/components/jomjol_helper/Helper.cpp b/code/components/jomjol_helper/Helper.cpp index 0a32b30e..fdbd8644 100644 --- a/code/components/jomjol_helper/Helper.cpp +++ b/code/components/jomjol_helper/Helper.cpp @@ -10,6 +10,7 @@ #include #include + #include "ClassLogFile.h" //#include "ClassLogFile.h" @@ -358,3 +359,30 @@ int removeFolder(const char* folderPath, const char* logTag) { return deleted; } + + + +std::vector HelperZerlegeZeile(std::string input, std::string _delimiter = "") +{ + std::vector Output; + std::string delimiter = " =,"; + if (_delimiter.length() > 0){ + delimiter = _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; +} + diff --git a/code/components/jomjol_helper/Helper.h b/code/components/jomjol_helper/Helper.h index 5ecf2f5f..ac6cccae 100644 --- a/code/components/jomjol_helper/Helper.h +++ b/code/components/jomjol_helper/Helper.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include using namespace std; @@ -30,6 +31,8 @@ time_t addDays(time_t startTime, int days); void memCopyGen(uint8_t* _source, uint8_t* _target, int _size); +std::vector HelperZerlegeZeile(std::string input, std::string _delimiter); + /////////////////////////// size_t getInternalESPHeapSize(); size_t getESPHeapSize(); diff --git a/code/components/jomjol_tfliteclass/server_tflite.cpp b/code/components/jomjol_tfliteclass/server_tflite.cpp index f29e384c..3859fd98 100644 --- a/code/components/jomjol_tfliteclass/server_tflite.cpp +++ b/code/components/jomjol_tfliteclass/server_tflite.cpp @@ -18,7 +18,7 @@ #include "ClassLogFile.h" -//#define DEBUG_DETAIL_ON +// #define DEBUG_DETAIL_ON ClassFlowControll tfliteflow; @@ -196,6 +196,8 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req) bool _rawValue = false; bool _noerror = false; + bool _all = false; + std::string _type = "value"; string zw; printf("handler_wasserzaehler uri:\n"); printf(req->uri); printf("\n"); @@ -206,6 +208,22 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req) if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK) { // printf("Query: "); printf(_query); printf("\n"); + if (httpd_query_key_value(_query, "all", _size, 10) == ESP_OK) + { +#ifdef DEBUG_DETAIL_ON + printf("all is found"); printf(_size); printf("\n"); +#endif + _all = true; + } + + if (httpd_query_key_value(_query, "type", _size, 10) == ESP_OK) + { +#ifdef DEBUG_DETAIL_ON + printf("all is found"); printf(_size); printf("\n"); +#endif + _type = std::string(_size); + } + if (httpd_query_key_value(_query, "rawvalue", _size, 10) == ESP_OK) { #ifdef DEBUG_DETAIL_ON @@ -222,6 +240,29 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req) } } + httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); + + if (_all) + { + httpd_resp_set_type(req, "text/plain"); + printf("TYPE: %s\n", _type.c_str()); + int _intype = READOUT_TYPE_VALUE; + if (_type == "prevalue") + _intype = READOUT_TYPE_PREVALUE; + if (_type == "raw") + _intype = READOUT_TYPE_RAWVALUE; + if (_type == "error") + _intype = READOUT_TYPE_ERROR; + + + zw = tfliteflow.getReadoutAll(_intype); + printf("ZW: %s\n", zw.c_str()); + if (zw.length() > 0) + httpd_resp_sendstr_chunk(req, zw.c_str()); + httpd_resp_sendstr_chunk(req, NULL); + return ESP_OK; + } + zw = tfliteflow.getReadout(_rawValue, _noerror); if (zw.length() > 0) httpd_resp_sendstr_chunk(req, zw.c_str()); @@ -498,6 +539,7 @@ esp_err_t handler_prevalue(httpd_req_t *req) char _query[100]; char _size[10] = ""; + char _numbers[50] = "default"; if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK) { @@ -511,15 +553,24 @@ esp_err_t handler_prevalue(httpd_req_t *req) printf("Value: "); printf(_size); printf("\n"); #endif } + + httpd_query_key_value(_query, "numbers", _numbers, 50); } if (strlen(_size) == 0) - zw = tfliteflow.GetPrevalue(); + { + zw = tfliteflow.GetPrevalue(std::string(_numbers)); + } else - zw = "SetPrevalue to " + tfliteflow.UpdatePrevalue(_size); + { + zw = "SetPrevalue to " + tfliteflow.UpdatePrevalue(_size, _numbers); + } resp_str = zw.c_str(); + httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); + + httpd_resp_send(req, resp_str, strlen(resp_str)); /* Respond with an empty chunk to signal HTTP response completion */ httpd_resp_send_chunk(req, NULL, 0); diff --git a/code/components/jomjol_wlan/read_wlanini.cpp b/code/components/jomjol_wlan/read_wlanini.cpp index f7c7299c..72f8ed0b 100644 --- a/code/components/jomjol_wlan/read_wlanini.cpp +++ b/code/components/jomjol_wlan/read_wlanini.cpp @@ -135,7 +135,7 @@ void LoadWlanFromFile(std::string fn, char *&_ssid, char *&_password, char *&_ho fclose(pFile); // Check if Hostname was empty in .ini if yes set to std_hostname - if(hostname.length() >= 0){ + if(hostname.length() == 0){ hostname = std_hostname; } diff --git a/code/main/server_main.cpp b/code/main/server_main.cpp index ba31c09c..e93573df 100644 --- a/code/main/server_main.cpp +++ b/code/main/server_main.cpp @@ -234,7 +234,7 @@ esp_err_t img_tmp_handler(httpd_req_t *req) filetosend = filetosend + "/img_tmp/" + std::string(filename); printf("File to upload: %s\n", filetosend.c_str()); - esp_err_t res = send_file(req, filetosend); + esp_err_t res = send_file(req, filetosend); if (res != ESP_OK) return res; @@ -387,7 +387,7 @@ httpd_handle_t start_webserver(void) httpd_config_t config = { }; config.task_priority = tskIDLE_PRIORITY+5; - config.stack_size = 32384; // bei 32k stürzt das Programm beim Bilderaufnehmen ab + config.stack_size = 32768; // bei 32k stürzt das Programm beim Bilderaufnehmen ab config.core_id = tskNO_AFFINITY; config.server_port = 80; config.ctrl_port = 32768; diff --git a/code/main/version.cpp b/code/main/version.cpp index 7c89f278..1f476acc 100644 --- a/code/main/version.cpp +++ b/code/main/version.cpp @@ -1,4 +1,4 @@ -const char* GIT_REV="6cefc44"; -const char* GIT_TAG="v7.1.0"; -const char* GIT_BRANCH="master"; -const char* BUILD_TIME="2021-05-30 21:47"; \ No newline at end of file +const char* GIT_REV="894c7f6"; +const char* GIT_TAG=""; +const char* GIT_BRANCH="rolling"; +const char* BUILD_TIME="2021-07-04 10:15"; diff --git a/code/platformio.ini b/code/platformio.ini index 50bf0706..be60a9b8 100644 --- a/code/platformio.ini +++ b/code/platformio.ini @@ -37,5 +37,7 @@ lib_deps = jomjol_controlGPIO monitor_speed = 115200 +monitor_rts = 0 +monitor_dtr = 0 debug_tool = esp-prog diff --git a/code/sdkconfig.old b/code/sdkconfig.old index 757645d9..bb4711dd 100644 --- a/code/sdkconfig.old +++ b/code/sdkconfig.old @@ -131,8 +131,8 @@ CONFIG_EXAMPLE_CONNECT_IPV6=y # # Compiler options # -CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y -# CONFIG_COMPILER_OPTIMIZATION_SIZE is not set +# CONFIG_COMPILER_OPTIMIZATION_DEFAULT is not set +CONFIG_COMPILER_OPTIMIZATION_SIZE=y # CONFIG_COMPILER_OPTIMIZATION_PERF is not set # CONFIG_COMPILER_OPTIMIZATION_NONE is not set CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y @@ -165,6 +165,8 @@ CONFIG_APPTRACE_LOCK_ENABLE=y # # CONFIG_BT_ENABLED is not set CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 +CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 +CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF=0 CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF=0 CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF=0 @@ -204,6 +206,12 @@ CONFIG_SPI_MASTER_ISR_IN_IRAM=y CONFIG_SPI_SLAVE_ISR_IN_IRAM=y # end of SPI configuration +# +# CAN configuration +# +# CONFIG_CAN_ISR_IN_IRAM is not set +# end of CAN configuration + # # UART configuration # @@ -239,6 +247,7 @@ CONFIG_ESP_TLS_USING_MBEDTLS=y # # ESP32-specific # +CONFIG_ESP32_ECO3_CACHE_LOCK_FIX=y CONFIG_ESP32_REV_MIN_0=y # CONFIG_ESP32_REV_MIN_1 is not set # CONFIG_ESP32_REV_MIN_2 is not set @@ -598,7 +607,6 @@ CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 # CONFIG_FREERTOS_USE_TRACE_FACILITY is not set # CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set # CONFIG_FREERTOS_DEBUG_INTERNALS is not set -CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y # CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set CONFIG_FREERTOS_DEBUG_OCDAWARE=y @@ -657,8 +665,10 @@ CONFIG_LWIP_SO_REUSE=y CONFIG_LWIP_SO_REUSE_RXTOALL=y # CONFIG_LWIP_SO_RCVBUF is not set # CONFIG_LWIP_NETBUF_RECVINFO is not set -CONFIG_LWIP_IP_FRAG=y -# CONFIG_LWIP_IP_REASSEMBLY is not set +CONFIG_LWIP_IP4_FRAG=y +CONFIG_LWIP_IP6_FRAG=y +# CONFIG_LWIP_IP4_REASSEMBLY is not set +# CONFIG_LWIP_IP6_REASSEMBLY is not set # CONFIG_LWIP_STATS is not set # CONFIG_LWIP_ETHARP_TRUST_IP_MAC is not set CONFIG_LWIP_ESP_GRATUITOUS_ARP=y @@ -682,8 +692,10 @@ CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 # # TCP # +CONFIG_LWIP_TCP_ISN_HOOK=y CONFIG_LWIP_MAX_ACTIVE_TCP=16 CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y CONFIG_LWIP_TCP_MAXRTX=12 CONFIG_LWIP_TCP_SYNMAXRTX=6 CONFIG_LWIP_TCP_MSS=1440 @@ -698,6 +710,7 @@ CONFIG_LWIP_TCP_QUEUE_OOSEQ=y CONFIG_LWIP_TCP_OVERSIZE_MSS=y # CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set # CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +CONFIG_LWIP_TCP_RTO_TIME=1500 # end of TCP # @@ -713,6 +726,8 @@ CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY=y # CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU1 is not set CONFIG_LWIP_TCPIP_TASK_AFFINITY=0x7FFFFFFF # CONFIG_LWIP_PPP_SUPPORT is not set +CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 +CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 # # ICMP @@ -906,6 +921,7 @@ CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20 CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1 +# CONFIG_SPI_FLASH_SIZE_OVERRIDE is not set # # Auto-detect flash chips @@ -913,6 +929,8 @@ CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1 CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP=y CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y # end of Auto-detect flash chips + +CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=y # end of SPI Flash driver # @@ -996,6 +1014,8 @@ CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30 # CONFIG_WPA_MBEDTLS_CRYPTO=y # CONFIG_WPA_TLS_V12 is not set +# CONFIG_WPA_WPS_WARS is not set +# CONFIG_WPA_DEBUG_PRINT is not set # end of Supplicant # @@ -1020,3 +1040,152 @@ CONFIG_CAMERA_CORE0=y # # CONFIG_LEGACY_INCLUDE_COMMON_HEADERS is not set # end of Compatibility options + +# Deprecated options for backward compatibility +CONFIG_TOOLPREFIX="xtensa-esp32-elf-" +# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set +CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y +# CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set +CONFIG_LOG_BOOTLOADER_LEVEL=3 +# CONFIG_APP_ROLLBACK_ENABLE is not set +# CONFIG_FLASH_ENCRYPTION_ENABLED is not set +# CONFIG_FLASHMODE_QIO is not set +# CONFIG_FLASHMODE_QOUT is not set +CONFIG_FLASHMODE_DIO=y +# CONFIG_FLASHMODE_DOUT is not set +# CONFIG_MONITOR_BAUD_9600B is not set +# CONFIG_MONITOR_BAUD_57600B is not set +CONFIG_MONITOR_BAUD_115200B=y +# CONFIG_MONITOR_BAUD_230400B is not set +# CONFIG_MONITOR_BAUD_921600B is not set +# CONFIG_MONITOR_BAUD_2MB is not set +# CONFIG_MONITOR_BAUD_OTHER is not set +CONFIG_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_MONITOR_BAUD=115200 +# CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG is not set +CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE=y +CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set +# CONFIG_CXX_EXCEPTIONS is not set +CONFIG_STACK_CHECK_NONE=y +# CONFIG_STACK_CHECK_NORM is not set +# CONFIG_STACK_CHECK_STRONG is not set +# CONFIG_STACK_CHECK_ALL is not set +# CONFIG_WARN_WRITE_STRINGS is not set +# CONFIG_DISABLE_GCC8_WARNINGS is not set +# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set +CONFIG_ESP32_APPTRACE_DEST_NONE=y +CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y +CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF=0 +CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN_EFF=0 +CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_EFF=0 +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0 +CONFIG_ADC2_DISABLE_DAC=y +CONFIG_SPIRAM_SUPPORT=y +# CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST is not set +CONFIG_TRACEMEM_RESERVE_DRAM=0x0 +# CONFIG_TWO_UNIVERSAL_MAC_ADDRESS is not set +CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y +CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4 +# CONFIG_ULP_COPROC_ENABLED is not set +CONFIG_ULP_COPROC_RESERVE_MEM=0 +CONFIG_BROWNOUT_DET=y +CONFIG_BROWNOUT_DET_LVL_SEL_0=y +# CONFIG_BROWNOUT_DET_LVL_SEL_1 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_7 is not set +CONFIG_BROWNOUT_DET_LVL=0 +CONFIG_REDUCE_PHY_TX_POWER=y +CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y +# CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL is not set +# CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_OSC is not set +# CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_8MD256 is not set +# CONFIG_DISABLE_BASIC_ROM_CONSOLE is not set +# CONFIG_NO_BLOBS is not set +# CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS is not set +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_MAIN_TASK_STACK_SIZE=3584 +CONFIG_IPC_TASK_STACK_SIZE=1024 +CONFIG_TIMER_TASK_STACK_SIZE=3584 +CONFIG_CONSOLE_UART_DEFAULT=y +# CONFIG_CONSOLE_UART_CUSTOM is not set +# CONFIG_CONSOLE_UART_NONE is not set +CONFIG_CONSOLE_UART_NUM=0 +CONFIG_CONSOLE_UART_BAUDRATE=115200 +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_INT_WDT_CHECK_CPU1=y +CONFIG_TASK_WDT=y +# CONFIG_TASK_WDT_PANIC is not set +CONFIG_TASK_WDT_TIMEOUT_S=3 +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +# CONFIG_EVENT_LOOP_PROFILING is not set +CONFIG_POST_EVENTS_FROM_ISR=y +CONFIG_POST_EVENTS_FROM_IRAM_ISR=y +CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND=150 +CONFIG_MB_MASTER_DELAY_MS_CONVERT=200 +CONFIG_MB_QUEUE_LENGTH=20 +CONFIG_MB_SERIAL_TASK_STACK_SIZE=2048 +CONFIG_MB_SERIAL_BUF_SIZE=256 +CONFIG_MB_SERIAL_TASK_PRIO=10 +# CONFIG_MB_CONTROLLER_SLAVE_ID_SUPPORT is not set +CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT=20 +CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 +CONFIG_MB_CONTROLLER_STACK_SIZE=4096 +CONFIG_MB_EVENT_QUEUE_TIMEOUT=20 +CONFIG_MB_TIMER_PORT_ENABLED=y +CONFIG_MB_TIMER_GROUP=0 +CONFIG_MB_TIMER_INDEX=0 +CONFIG_SUPPORT_STATIC_ALLOCATION=y +# CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK is not set +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_TIMER_QUEUE_LENGTH=10 +# CONFIG_L2_TO_L3_COPY is not set +# CONFIG_USE_ONLY_LWIP_SELECT is not set +CONFIG_ESP_GRATUITOUS_ARP=y +CONFIG_GARP_TMR_INTERVAL=60 +CONFIG_TCPIP_RECVMBOX_SIZE=32 +CONFIG_TCP_MAXRTX=12 +CONFIG_TCP_SYNMAXRTX=6 +CONFIG_TCP_MSS=1440 +CONFIG_TCP_MSL=60000 +CONFIG_TCP_SND_BUF_DEFAULT=5744 +CONFIG_TCP_WND_DEFAULT=5744 +CONFIG_TCP_RECVMBOX_SIZE=6 +CONFIG_TCP_QUEUE_OOSEQ=y +# CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set +CONFIG_TCP_OVERSIZE_MSS=y +# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_TCP_OVERSIZE_DISABLE is not set +CONFIG_UDP_RECVMBOX_SIZE=6 +CONFIG_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_TCPIP_TASK_AFFINITY_CPU0 is not set +# CONFIG_TCPIP_TASK_AFFINITY_CPU1 is not set +CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# CONFIG_PPP_SUPPORT is not set +CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_ESP32_PTHREAD_STACK_MIN=768 +CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_0 is not set +# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1 is not set +CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set +# CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT is not set +CONFIG_SUPPORT_TERMIOS=y +# End of deprecated options diff --git a/code/version.cpp b/code/version.cpp index 7c89f278..1f476acc 100644 --- a/code/version.cpp +++ b/code/version.cpp @@ -1,4 +1,4 @@ -const char* GIT_REV="6cefc44"; -const char* GIT_TAG="v7.1.0"; -const char* GIT_BRANCH="master"; -const char* BUILD_TIME="2021-05-30 21:47"; \ No newline at end of file +const char* GIT_REV="894c7f6"; +const char* GIT_TAG=""; +const char* GIT_BRANCH="rolling"; +const char* BUILD_TIME="2021-07-04 10:15"; diff --git a/firmware/html.zip b/firmware/html.zip index d5078f8b..ac6d6ea6 100644 Binary files a/firmware/html.zip and b/firmware/html.zip differ diff --git a/images/numbers.jpg b/images/numbers.jpg new file mode 100644 index 00000000..bf3e71c4 Binary files /dev/null and b/images/numbers.jpg differ diff --git a/images/powermeter.jpg b/images/powermeter.jpg new file mode 100644 index 00000000..4bc5a313 Binary files /dev/null and b/images/powermeter.jpg differ diff --git a/sd-card/config/config.ini b/sd-card/config/config.ini index 9e06820d..d33787ee 100644 --- a/sd-card/config/config.ini +++ b/sd-card/config/config.ini @@ -1,57 +1,56 @@ [MakeImage] ;LogImageLocation = /log/source -;LogfileRetentionInDays = 15 WaitBeforeTakingPicture = 5 +;LogfileRetentionInDays = 15 +Brightness = -2 +;Contrast = 0 +;Saturation = 0 ImageQuality = 5 ImageSize = VGA -;Brightness = -2 FixedExposure = false [Alignment] -InitialRotate=180 -FlipImageSize = false -/config/ref0.jpg 119 273 -/config/ref1.jpg 456 138 +InitialRotate = 179 +;InitialMirror = false SearchFieldX = 20 SearchFieldY = 20 -InitialMirror= false AlignmentAlgo = Default +;FlipImageSize = false +/config/ref0.jpg 104 271 +/config/ref1.jpg 442 142 [Digits] -Model = /config/dig0870s3q.tflite +Model = /config/dig1030s1q.tflite ;LogImageLocation = /log/digit ;LogfileRetentionInDays = 3 ModelInputSize = 20 32 -digit1 306 120 37 67 -digit2 355 120 37 67 -digit3 404 120 37 67 +main.digit1 292 120 37 67 +main.digit2 340 120 37 67 +main.digit3 389 120 37 67 [Analog] -Model = /config/ana0700s1lq.tflite +Model = /config/ana0630s2.tflite ;LogImageLocation = /log/analog ;LogfileRetentionInDays = 3 ModelInputSize = 32 32 -analog1 444 225 92 92 -analog2 391 329 92 92 -analog3 294 369 92 92 -analog4 168 326 92 92 -ExtendedResolution = false +ExtendedResolution = true +main.analog1 430 230 92 92 +main.analog2 376 331 92 92 +main.analog3 279 372 92 92 +main.analog4 150 327 92 92 [PostProcessing] -DecimalShift = 0 +main.DecimalShift = 0 PreValueUse = true PreValueAgeStartup = 720 AllowNegativeRates = false -MaxRateValue = 0.1 +main.MaxRateValue = 0.1 ErrorMessage = true -CheckDigitIncreaseConsistency = false +CheckDigitIncreaseConsistency = true -[MQTT] +;[MQTT] ;Uri = mqtt://IP-ADRESS:1883 -;Topic = wasserzaehler/zaehlerstand -;TopicError = wasserzaehler/error -;TopicRate = wasserzaehler/rate -;TopicTimeStamp = wasserzaehler/timestamp +;MainTopic = wasserzaehler ;ClientID = wasser ;user = USERNAME ;password = PASSWORD @@ -65,9 +64,8 @@ Logfile = false LogfileRetentionInDays = 3 [System] -TimeZone = CET-1CEST,M3.5.0,M10.5.0/3 -;TimeServer = fritz.box -;hostname = watermeter -SetupMode = true - -[Ende] \ No newline at end of file +TimeZone = CET-1CEST +;TimeServer = undefined +;AutoAdjustSummertime = false +;Hostname = undefined +SetupMode = true \ No newline at end of file diff --git a/sd-card/config/dig0870s3q.tflite b/sd-card/config/dig0870s3q.tflite deleted file mode 100644 index c2dd4fdc..00000000 Binary files a/sd-card/config/dig0870s3q.tflite and /dev/null differ diff --git a/sd-card/config/dig1030s1q.tflite b/sd-card/config/dig1030s1q.tflite new file mode 100644 index 00000000..9de4e5f5 Binary files /dev/null and b/sd-card/config/dig1030s1q.tflite differ diff --git a/sd-card/html/edit_alignment.html b/sd-card/html/edit_alignment.html index 96d0e302..8fa933fb 100644 --- a/sd-card/html/edit_alignment.html +++ b/sd-card/html/edit_alignment.html @@ -61,7 +61,7 @@ select { - Storage Path/Name: + Storage Path/Name: x: @@ -90,9 +90,8 @@ select { - - + - - - - + + + + diff --git a/sd-card/html/edit_config.html b/sd-card/html/edit_config.html index 23825d5e..a8c2067e 100644 --- a/sd-card/html/edit_config.html +++ b/sd-card/html/edit_config.html @@ -41,7 +41,6 @@ textarea { - - - - + + + + diff --git a/sd-card/html/edit_reference.html b/sd-card/html/edit_reference.html index e937db5b..56e67447 100644 --- a/sd-card/html/edit_reference.html +++ b/sd-card/html/edit_reference.html @@ -53,7 +53,7 @@ table { - Degrees + Degrees Brightness: @@ -86,7 +86,6 @@ table { - diff --git a/sd-card/html/gethost.js b/sd-card/html/gethost.js index 40a7c87a..3432c724 100644 --- a/sd-card/html/gethost.js +++ b/sd-card/html/gethost.js @@ -7,9 +7,10 @@ function getbasepath(){ var host = window.location.hostname; if ((host == "127.0.0.1") || (host == "localhost")) { -// host = "http://192.168.2.118"; // jomjol interner test -// host = "http://192.168.178.26"; // jomjol interner test - host = "http://192.168.178.22"; // jomjol interner Real +// host = "http://192.168.2.219"; // jomjol interner test + host = "http://192.168.178.46"; // jomjol interner test +// host = "http://192.168.178.22"; // jomjol interner Real + // host = "."; // jomjol interner localhost } diff --git a/sd-card/html/info.html b/sd-card/html/info.html index 66713d32..2bcf7d5b 100644 --- a/sd-card/html/info.html +++ b/sd-card/html/info.html @@ -24,8 +24,25 @@ div { +

Current

+ + + + + +
+ Last restart: + +
+ +
+
+ + +

Host Info

+
diff --git a/sd-card/html/jquery-3.5.1.min.js b/sd-card/html/jquery-3.5.1.min.js deleted file mode 100644 index b0614034..00000000 --- a/sd-card/html/jquery-3.5.1.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! jQuery v3.5.1 | (c) JS Foundation and other contributors | jquery.org/license */ -!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.5.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function D(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||j,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,j=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function qe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function Le(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function He(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Oe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="
",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):("number"==typeof f.top&&(f.top+="px"),"number"==typeof f.left&&(f.left+="px"),c.css(f))}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=$e(y.pixelPosition,function(e,t){if(t)return t=Be(e,n),Me.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0 - - - - -

Set the previous value for consistency check and substitution for NaN

+Choose Number: + + + + -

Current Value:

+

Current Value:

- - -

Set Value:

+

Set Value:

Input (Format = 123.456):

PreValue: Set PreValue

-

Result:

+

Result:

- \ No newline at end of file + + + + + + + + diff --git a/sd-card/html/readconfig.js b/sd-card/html/readconfig.js deleted file mode 100644 index 4a790646..00000000 --- a/sd-card/html/readconfig.js +++ /dev/null @@ -1,427 +0,0 @@ -function readconfig_Version(){ - return "1.0.0 - 20200910"; - } - -var config_gesamt; -var config_split; -var ref = new Array(2); -var digit = new Array(0); -var analog = new Array(0); -var initalrotate = new Object(); -var analogEnabled = false; -var posAnalogHeader; -var digitsEnabled = false; -var posDigitsHeader; - -function MakeRefZW(zw, _basepath){ - _filetarget = zw["name"].replace("/config/", "/img_tmp/"); - _filetarget = _filetarget.replace(".jpg", "_org.jpg"); - url = _basepath + "/editflow.html?task=cutref&in=/config/reference.jpg&out="+_filetarget+"&x=" + zw["x"] + "&y=" + zw["y"] + "&dx=" + zw["dx"] + "&dy=" + zw["dy"]; - var xhttp = new XMLHttpRequest(); - try { - xhttp.open("GET", url, false); - xhttp.send(); } - catch (error) - { -// alert("Deleting Config.ini failed"); - } - _filetarget2 = zw["name"].replace("/config/", "/img_tmp/"); -// _filetarget2 = _filetarget2.replace(".jpg", "_org.jpg"); - FileCopyOnServer(_filetarget, _filetarget2, _basepath); -} - -function CopyReferenceToImgTmp(_basepath) -{ - for (index = 0; index < 2; ++index) - { - _filenamevon = ref[index]["name"]; - _filenamenach = _filenamevon.replace("/config/", "/img_tmp/"); - FileDeleteOnServer(_filenamenach, _basepath); - FileCopyOnServer(_filenamevon, _filenamenach, _basepath); - - _filenamevon = _filenamevon.replace(".jpg", "_org.jpg"); - _filenamenach = _filenamenach.replace(".jpg", "_org.jpg"); - FileDeleteOnServer(_filenamenach, _basepath); - FileCopyOnServer(_filenamevon, _filenamenach, _basepath); - } -} - -function GetReferencesInfo(){ - return ref; -} - -function ParseConfigAlignment(_aktline){ - var akt_ref = 0; - ++_aktline; - - while ((_aktline < config_split.length) - && !(config_split[_aktline][0] == "[") - && !((config_split[_aktline][0] == ";") && (config_split[_aktline][1] == "["))) { - var linesplit = ZerlegeZeile(config_split[_aktline]); - if ((linesplit[0].toUpperCase() == "INITIALMIRROR") && (linesplit.length > 1)) - { - initalrotate["mirror"] = linesplit[1].toUpperCase().localeCompare("TRUE") == 0; - initalrotate["pos_config_mirror"] = _aktline; - } - - if (((linesplit[0].toUpperCase() == "INITALROTATE") || (linesplit[0].toUpperCase() == "INITIALROTATE")) && (linesplit.length > 1)) - { - initalrotate["angle"] = parseInt(linesplit[1]); - initalrotate["pos_config"] = _aktline; - } - if (linesplit.length == 3) - { - ref[akt_ref] = new Object(); - ref[akt_ref]["pos_ref"] = _aktline; - ref[akt_ref]["name"] = linesplit[0]; - ref[akt_ref]["x"] = linesplit[1]; - ref[akt_ref]["y"] = linesplit[2]; - akt_ref++; - } - ++_aktline; - } - return _aktline; -} - -function ParseConfigDigit(_aktline){ - ++_aktline; - digit.length = 0; - - while ((_aktline < config_split.length) - && !(config_split[_aktline][0] == "[") - && !((config_split[_aktline][0] == ";") && (config_split[_aktline][1] == "["))) { - var linesplit = ZerlegeZeile(config_split[_aktline]); - if (linesplit.length >= 5) - { - zw = new Object(); - zw["pos_ref"] = _aktline; - zw["name"] = linesplit[0]; - zw["x"] = linesplit[1]; - zw["y"] = linesplit[2]; - zw["dx"] = linesplit[3]; - zw["dy"] = linesplit[4]; - zw["ar"] = parseFloat(linesplit[3]) / parseFloat(linesplit[4]); - digit.push(zw); - } - ++_aktline; - } - return _aktline; -} - -function GetAnalogEnabled() { - return analogEnabled; -} - - -function GetDigitsEnabled() { - return digitsEnabled; -} - - -function ParseConfigAnalog(_aktline){ - ++_aktline; - analog.length = 0; - - while ((_aktline < config_split.length) - && !(config_split[_aktline][0] == "[") - && !((config_split[_aktline][0] == ";") && (config_split[_aktline][1] == "["))) { - var linesplit = ZerlegeZeile(config_split[_aktline]); - if (linesplit.length >= 5) - { - zw = new Object(); - zw["pos_ref"] = _aktline; - zw["name"] = linesplit[0]; - zw["x"] = linesplit[1]; - zw["y"] = linesplit[2]; - zw["dx"] = linesplit[3]; - zw["dy"] = linesplit[4]; - zw["ar"] = parseFloat(linesplit[3]) / parseFloat(linesplit[4]); - analog.push(zw); - } - ++_aktline; - } - return _aktline; -} - - -function getROIInfo(_typeROI){ - if (_typeROI == "[Digits]"){ - targetROI = digit; - } - if (_typeROI == "[Analog]"){ - targetROI = analog; - } - return targetROI.slice(); // Kopie senden, nicht orginal!!! -} - -function SaveROIToConfig(_ROIInfo, _typeROI, _basepath, _enabled){ - if (_enabled) { - text = _typeROI; - } - else { - text = ";" + _typeROI; - } - - if (_typeROI == "[Digits]"){ - config_split[posDigitsHeader] = text; - targetROI = digit; - } - - if (_typeROI == "[Analog]"){ - config_split[posAnalogHeader] = text; - targetROI = analog; - } - - // Abstimmen Anzahl ROIs: - var _pos = targetROI[targetROI.length-1]["pos_ref"]; - - for (var i = targetROI.length; i < _ROIInfo.length; ++i){ - var zw = config_split[config_split.length-1]; - config_split.push(zw); - for (var j = config_split.length-2; j > _pos + 1; --j){ - config_split[j] = config_split[j-1]; - } - } - - for (i = targetROI.length-1; i > _ROIInfo.length-1; --i){ - var _zwpos = targetROI[i]["pos_ref"]; - config_split.splice(_zwpos, 1); - } - - var linewrite = 0; - for (i = 0; i < _ROIInfo.length; ++i){ - if (i < targetROI.length){ - linewrite = targetROI[i]["pos_ref"]; - } - else { - linewrite++; - } - config_split[linewrite] = _ROIInfo[i]["name"] + " " + _ROIInfo[i]["x"] + " " + _ROIInfo[i]["y"] + " " + _ROIInfo[i]["dx"] + " " + _ROIInfo[i]["dy"]; - } - - SaveConfigToServer(_basepath); -} - - -function ParseConfig() { - config_split = config_gesamt.split("\n"); - var aktline = 0; - - while (aktline < config_split.length){ - if ((config_split[aktline].trim().toUpperCase() == "[ALIGNMENT]") || (config_split[aktline].trim().toUpperCase() == ";[ALIGNMENT]")){ - aktline = ParseConfigAlignment(aktline); - continue; - } - if ((config_split[aktline].trim().toUpperCase() == "[DIGITS]") || (config_split[aktline].trim().toUpperCase() == ";[DIGITS]")){ - posDigitsHeader = aktline; - if (config_split[aktline][0] == "[") { - digitsEnabled = true; - } - aktline = ParseConfigDigit(aktline); - continue; - } - - if ((config_split[aktline].trim().toUpperCase() == "[ANALOG]") || (config_split[aktline].trim().toUpperCase() == ";[ANALOG]")) { - posAnalogHeader = aktline; - if (config_split[aktline][0] == "[") { - analogEnabled = true; - } - aktline = ParseConfigAnalog(aktline); - continue; - } - - aktline++; - } -} - -function getPreRotate(){ - return initalrotate["angle"]; -} - -function setPreRotate(_prerotate){ - initalrotate["angle"] = _prerotate; -} - -function getMirror(){ - if (initalrotate.hasOwnProperty("mirror")) { - return initalrotate["mirror"]; - } - return false; -} - -function setMirror(_mirror){ - initalrotate["mirror"] = _mirror; -} - -function SaveCanvasToImage(_canvas, _filename, _delete = true, _basepath = ""){ - var JPEG_QUALITY=0.8; - var dataUrl = _canvas.toDataURL('image/jpeg', JPEG_QUALITY); - var rtn = dataURLtoBlob(dataUrl); - - if (_delete) { - FileDeleteOnServer(_filename, _basepath); - } - - FileSendContent(rtn, _filename, _basepath); -} - -function SaveConfigToServer(_basepath){ - // leere Zeilen am Ende löschen - var zw = config_split.length - 1; - while (config_split[zw] == "") { - config_split.pop(); - } - - var config_gesamt = ""; - for (var i = 0; i < config_split.length; ++i) - { - config_gesamt = config_gesamt + config_split[i] + "\n"; - } - - FileDeleteOnServer("/config/config.ini", _basepath); - - FileSendContent(config_gesamt, "/config/config.ini", _basepath); -} - -function UpdateConfigFileReferenceChange(_basepath){ - for (var _index = 0; _index < ref.length; ++_index){ - var zeile = ref[_index]["name"] + " " + ref[_index]["x"] + " " + ref[_index]["y"]; - var _pos = ref[_index]["pos_ref"]; - config_split[_pos] = zeile; - } - - zeile = "InitialRotate = " + initalrotate["angle"]; - var _pos = initalrotate["pos_config"]; - config_split[_pos] = zeile; - - var mirror = false; - if (initalrotate.hasOwnProperty("mirror")) { - mirror = initalrotate["mirror"]; - } - var mirror_pos = -1; - if (initalrotate.hasOwnProperty("pos_config_mirror")) { - mirror_pos = initalrotate["pos_config_mirror"]; - } - if (mirror_pos > -1) { - if (mirror) { - config_split[mirror_pos] = "InitialMirror = true"; - } - else { - config_split[mirror_pos] = "InitialMirror = false"; - } - } - else { - if (mirror) { // neue Zeile muss an der richtigen Stelle eingefügt werden - hier direct nach [Alignment] - var aktline = 0; - - while (aktline < config_split.length){ - if (config_split[aktline].trim() == "[Alignment]") { - break; - } - aktline++ - } - - // fuege neue Zeile in config_split ein - var zw = config_split[config_split.length-1]; - config_split.push(zw); - for (var j = config_split.length-2; j > aktline + 1; --j){ - config_split[j] = config_split[j-1]; - } - - config_split[aktline + 1] = "InitialMirror = True" - } - } - - SaveConfigToServer(_basepath); -} - -function UpdateConfigReference(zw, _basepath){ - for (var index = 0; index < 2; ++index) - { - var zeile = zw[index]["name"] + " " + zw[index]["x"] + " " + zw[index]["y"]; - var _pos = zw[index]["pos_ref"]; - config_split[_pos] = zeile; - - _filenamenach = ref[index]["name"]; - _filenamevon = _filenamenach.replace("/config/", "/img_tmp/"); - FileDeleteOnServer(_filenamenach, _basepath); - FileCopyOnServer(_filenamevon, _filenamenach, _basepath); - - _filenamenach = _filenamenach.replace(".jpg", "_org.jpg"); - _filenamevon = _filenamevon.replace(".jpg", "_org.jpg"); - FileDeleteOnServer(_filenamenach, _basepath); - FileCopyOnServer(_filenamevon, _filenamenach, _basepath); - - } - - SaveConfigToServer(_basepath); -} - -function MakeContrastImageZW(zw, _enhance, _basepath){ - _filename = zw["name"].replace("/config/", "/img_tmp/"); - url = _basepath + "/editflow.html?task=cutref&in=/config/reference.jpg&out=" + _filename + "&x=" + zw["x"] + "&y=" + zw["y"] + "&dx=" + zw["dx"] + "&dy=" + zw["dy"]; - if (_enhance == true){ - url = url + "&enhance=true"; - } - - var xhttp = new XMLHttpRequest(); - try { - xhttp.open("GET", url, false); - xhttp.send(); } - catch (error) - { -// alert("Deleting Config.ini failed"); - } -} - - -function GetReferenceSize(name){ - img = new Image(); - var xhttp = new XMLHttpRequest(); - - url = "http://192.168.178.22/fileserver" + name; - xhttp.open("GET", url, false); - xhttp.send(); - - var response = xhttp.responseText; - var binary = "" - - for (var responseText = xhttp.responseText, responseTextLen = responseText.length, binary = "", i = 0; i < responseTextLen; ++i) { - binary += String.fromCharCode(responseText.charCodeAt(i) & 255) - } - img.src = 'data:image/jpeg;base64,'+ window.btoa(binary); - - return [img.width, img.height]; -} - - -function getConfig() { - return config_gesamt; - } - - - -function dataURLtoBlob(dataurl) { - var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], - bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); - while(n--){ - u8arr[n] = bstr.charCodeAt(n); - } - return new Blob([u8arr], {type:mime}); - } - - -function SaveReferenceImage(_id_canvas, _filename, _doDelete, _basepath = ""){ - if (_doDelete){ - FileDeleteOnServer(_filename, _basepath); - } - - var canvas = document.getElementById(_id_canvas); - var JPEG_QUALITY=0.8; - var dataUrl = canvas.toDataURL('image/jpeg', JPEG_QUALITY); - var rtn = dataURLtoBlob(dataUrl); - if (!FileSendContent(rtn, _filename, _basepath)){ - alert("Error on saving reference image (" + _filename + ")!\nPlease retry."); - location.reload(); - }; -} diff --git a/sd-card/html/readconfigcommon.js b/sd-card/html/readconfigcommon.js index f2165dc8..2c79f5d0 100644 --- a/sd-card/html/readconfigcommon.js +++ b/sd-card/html/readconfigcommon.js @@ -20,65 +20,7 @@ function SaveConfigToServer(_basepath){ FileSendContent(config_gesamt, "/config/config.ini", _basepath); } -function UpdateConfigFileReferenceChange(_basepath){ - for (var _index = 0; _index < ref.length; ++_index){ - var zeile = ref[_index]["name"] + " " + ref[_index]["x"] + " " + ref[_index]["y"]; - var _pos = ref[_index]["pos_ref"]; - config_split[_pos] = zeile; - } - - zeile = "InitialRotate = " + initalrotate["angle"]; - var _pos = initalrotate["pos_config"]; - config_split[_pos] = zeile; - - var mirror = false; - if (initalrotate.hasOwnProperty("mirror")) { - mirror = initalrotate["mirror"]; - } - var mirror_pos = -1; - if (initalrotate.hasOwnProperty("pos_config_mirror")) { - mirror_pos = initalrotate["pos_config_mirror"]; - } - if (mirror_pos > -1) { - if (mirror) { - config_split[mirror_pos] = "InitialMirror = true"; - } - else { - config_split[mirror_pos] = "InitialMirror = false"; - } - } - else { - if (mirror) { // neue Zeile muss an der richtigen Stelle eingefügt werden - hier direct nach [Alignment] - var aktline = 0; - - while (aktline < config_split.length){ - if (config_split[aktline].trim() == "[Alignment]") { - break; - } - aktline++ - } - - // fuege neue Zeile in config_split ein - var zw = config_split[config_split.length-1]; - config_split.push(zw); - for (var j = config_split.length-2; j > aktline + 1; --j){ - config_split[j] = config_split[j-1]; - } - - config_split[aktline + 1] = "InitialMirror = True" - } - } - - SaveConfigToServer(_basepath); -} - function UpdateConfig(zw, _index, _enhance, _basepath){ - var zeile = zw["name"] + " " + zw["x"] + " " + zw["y"]; - var _pos = ref[_index]["pos_ref"]; - config_split[_pos] = zeile; - - SaveConfigToServer(_basepath); - var namezw = zw["name"]; FileCopyOnServer("/img_tmp/ref_zw.jpg", namezw, _basepath); var namezw = zw["name"].replace(".jpg", "_org.jpg"); @@ -102,10 +44,10 @@ function createReader(file) { -function ZerlegeZeile(input) +function ZerlegeZeile(input, delimiter = " =,\t\r") { var Output = Array(0); - delimiter = " =,\r"; +// delimiter = " =,\t"; input = trim(input, delimiter); var pos = findDelimiterPos(input, delimiter); @@ -164,6 +106,11 @@ function trim(istring, adddelimiter) } +function getConfig() +{ + return config_gesamt; +} + function loadConfig(_basepath) { var xhttp = new XMLHttpRequest(); @@ -261,4 +208,54 @@ function FileSendContent(_content, _filename, _basepath = ""){ // alert("Deleting Config.ini failed"); } return okay; -} \ No newline at end of file +} + + +function SaveCanvasToImage(_canvas, _filename, _delete = true, _basepath = ""){ + var JPEG_QUALITY=0.8; + var dataUrl = _canvas.toDataURL('image/jpeg', JPEG_QUALITY); + var rtn = dataURLtoBlob(dataUrl); + + if (_delete) { + FileDeleteOnServer(_filename, _basepath); + } + + FileSendContent(rtn, _filename, _basepath); +} + +function MakeContrastImageZW(zw, _enhance, _basepath){ + _filename = zw["name"].replace("/config/", "/img_tmp/"); + url = _basepath + "/editflow.html?task=cutref&in=/config/reference.jpg&out=" + _filename + "&x=" + zw["x"] + "&y=" + zw["y"] + "&dx=" + zw["dx"] + "&dy=" + zw["dy"]; + if (_enhance == true){ + url = url + "&enhance=true"; + } + + var xhttp = new XMLHttpRequest(); + try { + xhttp.open("GET", url, false); + xhttp.send(); } + catch (error) + { +// alert("Deleting Config.ini failed"); + } +} + + + +function MakeRefZW(zw, _basepath){ + _filetarget = zw["name"].replace("/config/", "/img_tmp/"); + _filetarget = _filetarget.replace(".jpg", "_org.jpg"); + url = _basepath + "/editflow.html?task=cutref&in=/config/reference.jpg&out="+_filetarget+"&x=" + zw["x"] + "&y=" + zw["y"] + "&dx=" + zw["dx"] + "&dy=" + zw["dy"]; + var xhttp = new XMLHttpRequest(); + try { + xhttp.open("GET", url, false); + xhttp.send(); } + catch (error) + { +// alert("Deleting Config.ini failed"); + } + _filetarget2 = zw["name"].replace("/config/", "/img_tmp/"); +// _filetarget2 = _filetarget2.replace(".jpg", "_org.jpg"); + FileCopyOnServer(_filetarget, _filetarget2, _basepath); +} + diff --git a/sd-card/html/readconfigparam.js b/sd-card/html/readconfigparam.js index af7a0d00..49b0f6ab 100644 --- a/sd-card/html/readconfigparam.js +++ b/sd-card/html/readconfigparam.js @@ -7,6 +7,8 @@ var config_split; var param; var category; var ref = new Array(2); +var NUMBERS = new Array(0); +var REFERENCES = new Array(0); function ParseConfig() { config_split = config_gesamt.split("\n"); @@ -68,11 +70,11 @@ function ParseConfig() { category[catname]["enabled"] = false; category[catname]["found"] = false; param[catname] = new Object(); - ParamAddValue(param, catname, "DecimalShift"); + ParamAddValue(param, catname, "DecimalShift", 1, true); ParamAddValue(param, catname, "PreValueUse"); ParamAddValue(param, catname, "PreValueAgeStartup"); ParamAddValue(param, catname, "AllowNegativeRates"); - ParamAddValue(param, catname, "MaxRateValue"); + ParamAddValue(param, catname, "MaxRateValue", 1, true); ParamAddValue(param, catname, "ErrorMessage"); ParamAddValue(param, catname, "CheckDigitIncreaseConsistency"); @@ -82,10 +84,7 @@ function ParseConfig() { category[catname]["found"] = false; param[catname] = new Object(); ParamAddValue(param, catname, "Uri"); - ParamAddValue(param, catname, "Topic"); - ParamAddValue(param, catname, "TopicError"); - ParamAddValue(param, catname, "TopicRate"); - ParamAddValue(param, catname, "TopicTimeStamp"); + ParamAddValue(param, catname, "MainTopic"); ParamAddValue(param, catname, "ClientID"); ParamAddValue(param, catname, "user"); ParamAddValue(param, catname, "password"); @@ -115,8 +114,9 @@ function ParseConfig() { ParamAddValue(param, catname, "TimeServer"); ParamAddValue(param, catname, "AutoAdjustSummertime"); ParamAddValue(param, catname, "Hostname"); - ParamAddValue(param, catname, "SetupMode"); - + ParamAddValue(param, catname, "SetupMode"); + + while (aktline < config_split.length){ for (var cat in category) { zw = cat.toUpperCase(); @@ -136,16 +136,15 @@ function ParseConfig() { } } -function ParamAddValue(param, _cat, _param, _anzParam = 1){ +function ParamAddValue(param, _cat, _param, _anzParam = 1, _isIndividual = false){ param[_cat][_param] = new Object(); param[_cat][_param]["found"] = false; param[_cat][_param]["enabled"] = false; param[_cat][_param]["line"] = -1; param[_cat][_param]["anzParam"] = _anzParam; + param[_cat][_param]["Numbers"] = _isIndividual; }; - - function ParseConfigParamAll(_aktline, _catname){ ++_aktline; @@ -156,6 +155,18 @@ function ParseConfigParamAll(_aktline, _catname){ let [isCom, input] = isCommented(_input); var linesplit = ZerlegeZeile(input); ParamExtractValueAll(param, linesplit, _catname, _aktline, isCom); + if (!isCom && (linesplit.length == 5) && (_catname == 'Digits')) + ExtractROIs(input, "digit"); + if (!isCom && (linesplit.length == 5) && (_catname == 'Analog')) + ExtractROIs(input, "analog"); + if (!isCom && (linesplit.length == 3) && (_catname == 'Alignment')) + { + _newref = new Object(); + _newref["name"] = linesplit[0]; + _newref["x"] = linesplit[1]; + _newref["y"] = linesplit[2]; + REFERENCES.push(_newref); + } ++_aktline; } @@ -177,14 +188,50 @@ function ParamExtractValue(_param, _linesplit, _catname, _paramname, _aktline, _ function ParamExtractValueAll(_param, _linesplit, _catname, _aktline, _iscom){ for (var paramname in _param[_catname]) { - if ((_linesplit[0].toUpperCase() == paramname.toUpperCase()) && (_linesplit.length > _param[_catname][paramname]["anzParam"])) + _param_zw = _linesplit[0].substring(_linesplit[0].length - paramname.length, _linesplit[0].length); + if ((_param_zw.toUpperCase() == paramname.toUpperCase()) && (_linesplit.length > _param[_catname][paramname]["anzParam"])) { _param[_catname][paramname]["found"] = true; _param[_catname][paramname]["enabled"] = !_iscom; _param[_catname][paramname]["line"] = _aktline; - for (var j = 1; j <= _param[_catname][paramname]["anzParam"]; ++j) { - _param[_catname][paramname]["value"+j] = _linesplit[j]; + if (_param[_catname][paramname]["Numbers"] == true) // möglicher Multiusage + { + abc = getNUMBERS(_linesplit[0]); + abc[_catname][paramname] = new Object; + abc[_catname][paramname]["found"] = true; + abc[_catname][paramname]["enabled"] = !_iscom; + + for (var j = 1; j <= _param[_catname][paramname]["anzParam"]; ++j) { + abc[_catname][paramname]["value"+j] = _linesplit[j]; + } + if (abc["name"] == "default") + { + _param[_catname][paramname]["found"] = true; + _param[_catname][paramname]["enabled"] = !_iscom; + _param[_catname][paramname]["line"] = _aktline; + for (var j = 1; j <= _param[_catname][paramname]["anzParam"]; ++j) { + _param[_catname][paramname]["value"+j] = _linesplit[j]; + } + for (_num in NUMBERS) // wert mit Default belegen + { + NUMBERS[_num][_catname][paramname]["found"] = true; + NUMBERS[_num][_catname][paramname]["enabled"] = !_iscom; + NUMBERS[_num][_catname][paramname]["line"] = _aktline; + for (var j = 1; j <= _param[_catname][paramname]["anzParam"]; ++j) { + NUMBERS[_num][_catname][paramname]["value"+j] = _linesplit[j]; + } + } } + } + else + { + _param[_catname][paramname]["found"] = true; + _param[_catname][paramname]["enabled"] = !_iscom; + _param[_catname][paramname]["line"] = _aktline; + for (var j = 1; j <= _param[_catname][paramname]["anzParam"]; ++j) { + _param[_catname][paramname]["value"+j] = _linesplit[j]; + } + } } } } @@ -193,6 +240,101 @@ function getConfigParameters() { return param; } +function WriteConfigININew() +{ + config_split = new Array(0); + + for (var cat in param) { + text = "[" + cat + "]"; + if (!category[cat]["enabled"]) { + text = ";" + text; + } + config_split.push(text); + + for (var name in param[cat]) { + if (param[cat][name]["Numbers"]) + { + for (_num in NUMBERS) + { + text = NUMBERS[_num]["name"] + "." + name; + + var text = text + " =" + + for (var j = 1; j <= param[cat][name]["anzParam"]; ++j) { + if (!(typeof NUMBERS[_num][cat][name]["value"+j] == 'undefined')) + text = text + " " + NUMBERS[_num][cat][name]["value"+j]; + } + if (!NUMBERS[_num][cat][name]["enabled"]) { + text = ";" + text; + } + config_split.push(text); + } + } + else + { + var text = name + " =" + + for (var j = 1; j <= param[cat][name]["anzParam"]; ++j) { + if (!(typeof param[cat][name]["value"+j] == 'undefined')) + text = text + " " + param[cat][name]["value"+j]; + } + if (!param[cat][name]["enabled"]) { + text = ";" + text; + } + config_split.push(text); + } + } + if (cat == "Digits") + { + for (var _roi in NUMBERS) + { + if (NUMBERS[_roi]["digit"].length > 0) + { + for (var _roiddet in NUMBERS[_roi]["digit"]) + { + text = NUMBERS[_roi]["name"] + "." + NUMBERS[_roi]["digit"][_roiddet]["name"]; + text = text + " " + NUMBERS[_roi]["digit"][_roiddet]["x"]; + text = text + " " + NUMBERS[_roi]["digit"][_roiddet]["y"]; + text = text + " " + NUMBERS[_roi]["digit"][_roiddet]["dx"]; + text = text + " " + NUMBERS[_roi]["digit"][_roiddet]["dy"]; + config_split.push(text); + } + } + } + } + if (cat == "Analog") + { + for (var _roi in NUMBERS) + { + if (NUMBERS[_roi]["analog"].length > 0) + { + for (var _roiddet in NUMBERS[_roi]["analog"]) + { + text = NUMBERS[_roi]["name"] + "." + NUMBERS[_roi]["analog"][_roiddet]["name"]; + text = text + " " + NUMBERS[_roi]["analog"][_roiddet]["x"]; + text = text + " " + NUMBERS[_roi]["analog"][_roiddet]["y"]; + text = text + " " + NUMBERS[_roi]["analog"][_roiddet]["dx"]; + text = text + " " + NUMBERS[_roi]["analog"][_roiddet]["dy"]; + config_split.push(text); + } + } + } + } + if (cat == "Alignment") + { + for (var _roi in REFERENCES) + { + text = REFERENCES[_roi]["name"]; + text = text + " " + REFERENCES[_roi]["x"]; + text = text + " " + REFERENCES[_roi]["y"]; + config_split.push(text); + } + } + + config_split.push(""); + } +} + function setConfigParameters(_param, _category = "") { for (var cat in _param) { for (var name in _param[cat]) { @@ -275,6 +417,268 @@ function getConfig() { function getConfigCategory() { return category; } + + + +function ExtractROIs(_aktline, _type){ + var linesplit = ZerlegeZeile(_aktline); + abc = getNUMBERS(linesplit[0], _type); + abc["pos_ref"] = _aktline; + abc["x"] = linesplit[1]; + abc["y"] = linesplit[2]; + abc["dx"] = linesplit[3]; + abc["dy"] = linesplit[4]; + abc["ar"] = parseFloat(linesplit[3]) / parseFloat(linesplit[4]); +} + + +function getNUMBERS(_name, _type, _create = true) +{ + _pospunkt = _name.indexOf ("."); + if (_pospunkt > -1) + { + _digit = _name.substring(0, _pospunkt); + _roi = _name.substring(_pospunkt+1); + } + else + { + _digit = "default"; + _roi = _name; + } + + _ret = -1; + + for (i = 0; i < NUMBERS.length; ++i) + { + if (NUMBERS[i]["name"] == _digit) + _ret = NUMBERS[i]; + } + + if (!_create) // nicht gefunden und soll auch nicht erzeugt werden, ggf. geht eine NULL zurück + return _ret; + + if (_ret == -1) + { + _ret = new Object(); + _ret["name"] = _digit; + _ret['digit'] = new Array(); + _ret['analog'] = new Array(); + + for (_cat in param) + for (_param in param[_cat]) + if (param[_cat][_param]["Numbers"] == true){ + if (typeof _ret[_cat] == 'undefined') + _ret[_cat] = new Object(); + _ret[_cat][_param] = new Object(); + _ret[_cat][_param]["found"] = false; + _ret[_cat][_param]["enabled"] = false; + _ret[_cat][_param]["anzParam"] = param[_cat][_param]["anzParam"]; + + } + + NUMBERS.push(_ret); + } + + if (typeof _type == 'undefined') // muss schon existieren !!! - also erst nach Digits / Analog aufrufen + return _ret; + + neuroi = new Object(); + neuroi["name"] = _roi; + _ret[_type].push(neuroi); + + + return neuroi; + +} + + + +function CopyReferenceToImgTmp(_basepath) +{ + for (index = 0; index < 2; ++index) + { + _filenamevon = REFERENCES[index]["name"]; + _filenamenach = _filenamevon.replace("/config/", "/img_tmp/"); + FileDeleteOnServer(_filenamenach, _basepath); + FileCopyOnServer(_filenamevon, _filenamenach, _basepath); + + _filenamevon = _filenamevon.replace(".jpg", "_org.jpg"); + _filenamenach = _filenamenach.replace(".jpg", "_org.jpg"); + FileDeleteOnServer(_filenamenach, _basepath); + FileCopyOnServer(_filenamevon, _filenamenach, _basepath); + } +} + +function GetReferencesInfo(){ + return REFERENCES; +} + + +function UpdateConfigReference(_basepath){ + for (var index = 0; index < 2; ++index) + { + _filenamenach = REFERENCES[index]["name"]; + _filenamevon = _filenamenach.replace("/config/", "/img_tmp/"); + FileDeleteOnServer(_filenamenach, _basepath); + FileCopyOnServer(_filenamevon, _filenamenach, _basepath); + + _filenamenach = _filenamenach.replace(".jpg", "_org.jpg"); + _filenamevon = _filenamevon.replace(".jpg", "_org.jpg"); + FileDeleteOnServer(_filenamenach, _basepath); + FileCopyOnServer(_filenamevon, _filenamenach, _basepath); + + } +} + + +function getNUMBERInfo(){ + return NUMBERS; +} + +function RenameNUMBER(_alt, _neu){ + index = -1; + found = false; + for (i = 0; i < NUMBERS.length; ++i) { + if (NUMBERS[i]["name"] == _alt) + index = i; + if (NUMBERS[i]["name"] == _neu) + found = true; + } + + if (found) + return "Name is already existing - please use another name"; + + NUMBERS[index]["name"] = _neu; + + return ""; +} + +function DeleteNUMBER(_delte){ + if (NUMBERS.length == 1) + return "The last number cannot be deleted." + index = -1; + for (i = 0; i < NUMBERS.length; ++i) { + if (NUMBERS[i]["name"] == _delte) + index = i; + } + if (index > -1) { + NUMBERS.splice(index, 1); + } + + return ""; +} + +function CreateNUMBER(_numbernew){ + found = false; + for (i = 0; i < NUMBERS.length; ++i) { + if (NUMBERS[i]["name"] == _numbernew) + found = true; + } + + if (found) + return "Name does already exist, please choose another one!"; + + _ret = new Object(); + _ret["name"] = _numbernew; + _ret['digit'] = new Array(); + _ret['analog'] = new Array(); + + for (_cat in param) + for (_param in param[_cat]) + if (param[_cat][_param]["Numbers"] == true){ + _ret[_cat] = new Object(); + _ret[_cat][_param] = new Object(); + _ret[_cat][_param]["found"] = false; + _ret[_cat][_param]["enabled"] = false; + _ret[_cat][_param]["anzParam"] = param[_cat][_param]["anzParam"]; + + } + + NUMBERS.push(_ret); + + return ""; +} + + +function getROIInfo(_typeROI, _number){ + index = 0; + for (var i = 0; i < NUMBERS.length; ++i) + if (NUMBERS[i]["name"] == _number) + index = i; + + return NUMBERS[index][_typeROI]; +} + + +function RenameROI(_number, _type, _alt, _neu){ + index = -1; + found = false; + _indexnumber = -1; + for (j = 0; j < NUMBERS.length; ++j) + if (NUMBERS[j]["name"] == _number) + _indexnumber = j; + + for (i = 0; i < NUMBERS[_indexnumber][_type].length; ++i) { + if (NUMBERS[_indexnumber][_type][i]["name"] == _alt) + index = i; + if (NUMBERS[_indexnumber][_type][i]["name"] == _neu) + found = true; + } + + if (found) + return "Name is already existing - please use another name"; + + NUMBERS[_indexnumber][_type][index]["name"] = _neu; + + return ""; +} + +function DeleteNUMBER(_delte){ + if (NUMBERS.length == 1) + return "The last number cannot be deleted." + + + index = -1; + for (i = 0; i < NUMBERS.length; ++i) { + if (NUMBERS[i]["name"] == _delte) + index = i; + } + + if (index > -1) { + NUMBERS.splice(index, 1); + } + + return ""; +} + +function CreateROI(_number, _type, _pos, _roinew, _x, _y, _dx, _dy){ + _indexnumber = -1; + for (j = 0; j < NUMBERS.length; ++j) + if (NUMBERS[j]["name"] == _number) + _indexnumber = j; + + + found = false; + for (i = 0; i < NUMBERS.length; ++i) { + if (NUMBERS[_indexnumber][_type]["name"] == _roinew) + found = true; + } + + if (found) + return "ROI does already exist, please choose another name!"; + + _ret = new Object(); + _ret["name"] = _roinew; + _ret["x"] = _x; + _ret["y"] = _y; + _ret["dx"] = _dx; + _ret["dy"] = _dy; + _ret["ar"] = _dx / _dy; + + NUMBERS[_indexnumber][_type].splice(_pos+1, 0, _ret); + + return ""; +} \ No newline at end of file diff --git a/sd-card/html/sd-card - Verknüpfung.lnk b/sd-card/html/sd-card - Verknüpfung.lnk deleted file mode 100644 index 4c6bfce3..00000000 Binary files a/sd-card/html/sd-card - Verknüpfung.lnk and /dev/null differ diff --git a/sd-card/html/test.html b/sd-card/html/test.html new file mode 100644 index 00000000..5cd12021 --- /dev/null +++ b/sd-card/html/test.html @@ -0,0 +1,32 @@ + + + + + + + + testschrift +
+ + + + + + diff --git a/sd-card/html/version.txt b/sd-card/html/version.txt index e029aa99..47da986f 100644 --- a/sd-card/html/version.txt +++ b/sd-card/html/version.txt @@ -1 +1 @@ -6.8.0 +9.1.0 diff --git a/sd-card/html/wasserzaehler_roi.html b/sd-card/html/wasserzaehler_roi.html index d12cbe64..322c74fb 100644 --- a/sd-card/html/wasserzaehler_roi.html +++ b/sd-card/html/wasserzaehler_roi.html @@ -7,7 +7,7 @@