Merge branch 'rolling'

This commit is contained in:
jomjol
2022-09-17 09:25:00 +02:00
65 changed files with 1821 additions and 464 deletions

106
.github/workflows/build.yaml vendored Normal file
View File

@@ -0,0 +1,106 @@
name: Build and Pack
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Cache PlatformIO
uses: actions/cache@v2
with:
path: ~/.platformio
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
- name: Set up Python
uses: actions/setup-python@v2
- name: Install PlatformIO
run: |
python -m pip install --upgrade pip
pip install --upgrade platformio
- name: Set Variables
id: vars
run: |
echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
echo "::set-output name=date_time::$(git log -1 --format="%at" | xargs -I{} date -d @{} '+%Y-%m-%d %H:%M:%S')"
echo "::set-output name=date_time_filename::$(git log -1 --format="%at" | xargs -I{} date -d @{} '+%Y-%m-%d_%H-%M-%S')"
#echo "::set-output name=version_string::${{ steps.vars.outputs.date_time_filename }}__${{ github.ref_name }}_(${{ steps.vars.outputs.sha_short }})"
#echo "Version String: ${{ steps.vars.outputs.version_string }}"
- name: Set Version used in HTML Info page
run: echo "${{ steps.vars.outputs.date_time }}, ${{ github.ref_name }} (${{ steps.vars.outputs.sha_short }})" > "sd-card/html/version.txt"
- name: Build Firmware
# run: mkdir -p ./code/.pio/build/esp32cam/; touch ./code/.pio/build/esp32cam/firmware.bin # Testing
run: cd code; platformio run --environment esp32cam
# Old OTA concept
# firmware__*.zip needs to be unpacked before attaching to the release!
# The bin filename can contain versioning.
- name: Rename firmware file to contain versioning (old ota)
run: |
mkdir -p ./dist_old_ota
cp "./code/.pio/build/esp32cam/firmware.bin" "./dist_old_ota/firmware__${{ steps.vars.outputs.date_time_filename }}__${{ github.ref_name }}_(${{ steps.vars.outputs.sha_short }}).bin"
ls -l ./dist_old_ota
- name: Upload Firmware artifact (old OTA concept)
uses: actions/upload-artifact@v3
with:
name: "firmware__extract_before_upload__only_needed_for_migration_from_11.2.0"
path: ./dist_old_ota/*
- name: Upload Web interface artifact (old OTA concept)
uses: actions/upload-artifact@v3
with:
name: "html__only_needed_for_migration_from_11.2.0__${{ steps.vars.outputs.date_time_filename }}__${{ github.ref_name }}_(${{ steps.vars.outputs.sha_short }})"
path: ./sd-card/html/*
# New OTA concept
# update__version.zip file with following content:
# - /firmware.bin
# - (optional) /html/*
# - (optional) /config/*.tfl
- name: Prepare update.zip artifact
run: |
mkdir -p ./dist
cp "./code/.pio/build/esp32cam/firmware.bin" "dist/firmware.bin"
- name: Upload update.zip Artifact (Firmware only)
uses: actions/upload-artifact@v3
with:
name: "update_firmware_only__${{ steps.vars.outputs.date_time_filename }}__${{ github.ref_name }}_(${{ steps.vars.outputs.sha_short }})"
path: ./dist/*
- name: Prepare update.zip artifact (Firmware + Web UI)
run: cp -r ./sd-card/html ./dist/
- name: Upload update.zip artifact (Firmware + Web UI)
uses: actions/upload-artifact@v3
with:
name: "update_firmware+web_ui__${{ steps.vars.outputs.date_time_filename }}__${{ github.ref_name }}_(${{ steps.vars.outputs.sha_short }})"
path: ./dist/*
- name: Prepare update.zip artifact (Firmware + Web UI + CNN)
run: |
mkdir ./dist/config/
cp ./sd-card/config/*.tfl ./dist/config/ 2>/dev/null || true
cp ./sd-card/config/*.tflite ./dist/config/ 2>/dev/null || true
- name: Upload update.zip artifact (Firmware + Web UI + CNN)
uses: actions/upload-artifact@v3
with:
name: "update_firmware+web_ui+cnn__${{ steps.vars.outputs.date_time_filename }}__${{ github.ref_name }}_(${{ steps.vars.outputs.sha_short }})"
path: ./dist/*

View File

@@ -40,6 +40,27 @@ In other cases you can contact the developer via email: <img src="https://raw.gi
------
##### 11.3.0 - Intermediate Digits (2022-09-17)
- **ATTENTION**:
- first update the 'firmware.bin' and ensure that the new version is running
- Only afterwards update the 'html.zip'
- Otherwise the downwards compatibility of the new counter clockwise feature is not given and you end in a reboot loop, that needs manual flashing!
- Increased precision (more than 6-7 digits)
- Implements Counter Clockwise Analog Pointers
- Improved post processing algorithm
- Debugging: intensive use of testcases
- MQTT: improved handling, extended logging, automated reconnect
- HTML: Backup Option for Configuration
- HTML: Improved Reboot
- HTML: Update WebUI (Reboot, Infos, CPU Temp, RSSI)
- This version is largely also based on the work of **[caco3](https://github.com/caco3)**, **[adellafave](https://github.com/adellafave)**, **[haverland](https://github.com/haverland)**, **[stefanbode](https://github.com/stefanbode)**, **[PLCHome](https://github.com/PLCHome)**
##### 11.2.0 - Intermediate Digits (2022-08-28)
- Updated Tensorflow / TFlite to newest tflite (version as of 2022-07-27)

View File

@@ -120,16 +120,6 @@ esp_err_t get_tflite_file_handler(httpd_req_t *req)
}
/* Handler to redirect incoming GET request for /index.html to /
* This can be overridden by uploading file with same name */
// static esp_err_t index_html_get_handler(httpd_req_t *req)
// {
// httpd_resp_set_status(req, "307 Temporary Redirect");
// httpd_resp_set_hdr(req, "Location", "/");
// httpd_resp_send(req, NULL, 0); // Response body can be empty
// return ESP_OK;
// }
/* Send HTTP response with a run-time generated html consisting of
* a list of all files and folders under the requested path.
* In case of SPIFFS this returns empty list when path is any
@@ -716,6 +706,101 @@ void delete_all_in_directory(std::string _directory)
closedir(dir);
}
std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::string _target_bin, std::string _main)
{
int i, sort_iter;
mz_bool status;
size_t uncomp_size;
mz_zip_archive zip_archive;
void* p;
char archive_filename[64];
std::string zw, ret = "";
// static const char* s_Test_archive_filename = "testhtml.zip";
printf("miniz.c version: %s\n", MZ_VERSION);
printf("Zipfile: %s\n", _in_zip_file.c_str());
printf("Target Dir ZIP: %s\n", _target_zip.c_str());
printf("Target Dir BIN: %s\n", _target_bin.c_str());
// Now try to open the archive.
memset(&zip_archive, 0, sizeof(zip_archive));
status = mz_zip_reader_init_file(&zip_archive, _in_zip_file.c_str(), 0);
if (!status)
{
printf("mz_zip_reader_init_file() failed!\n");
return ret;
}
// Get and print information about each file in the archive.
int numberoffiles = (int)mz_zip_reader_get_num_files(&zip_archive);
for (sort_iter = 0; sort_iter < 2; sort_iter++)
{
memset(&zip_archive, 0, sizeof(zip_archive));
status = mz_zip_reader_init_file(&zip_archive, _in_zip_file.c_str(), sort_iter ? MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY : 0);
if (!status)
{
printf("mz_zip_reader_init_file() failed!\n");
return ret;
}
for (i = 0; i < numberoffiles; i++)
{
mz_zip_archive_file_stat file_stat;
mz_zip_reader_file_stat(&zip_archive, i, &file_stat);
sprintf(archive_filename, file_stat.m_filename);
// Try to extract all the files to the heap.
p = mz_zip_reader_extract_file_to_heap(&zip_archive, archive_filename, &uncomp_size, 0);
if (!p)
{
printf("mz_zip_reader_extract_file_to_heap() failed!\n");
mz_zip_reader_end(&zip_archive);
return ret;
}
// Save to File.
zw = std::string(archive_filename);
if (toUpper(zw) == "FIRMWARE.BIN")
{
zw = _target_bin + zw;
ret = zw;
}
else
{
std::string _dir = getDirectory(zw);
if (_dir.length() > 0)
{
zw = _main + zw;
}
else
{
zw = _target_zip + zw;
}
}
printf("Filename to extract: %s", zw.c_str());
DeleteFile(zw);
FILE* fpTargetFile = OpenFileAndWait(zw.c_str(), "wb");
fwrite(p, 1, (uint)uncomp_size, fpTargetFile);
fclose(fpTargetFile);
printf("Successfully extracted file \"%s\", size %u\n", archive_filename, (uint)uncomp_size);
// printf("File data: \"%s\"\n", (const char*)p);
// We're done.
mz_free(p);
}
// Close the archive, freeing any resources it was using
mz_zip_reader_end(&zip_archive);
}
printf("Success.\n");
return ret;
}
void unzip(std::string _in_zip_file, std::string _target_directory){
int i, sort_iter;
mz_bool status;
@@ -860,15 +945,4 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path)
};
httpd_register_uri_handler(server, &file_delete);
/* URI handler for getting tflite files from server */
/*
httpd_uri_t file_tflite = {
.uri = "/tflite", // Match all URIs of type /delete/path/to/file
.method = HTTP_GET,
.handler = get_tflite_file_handler,
.user_ctx = server_data // Pass server data as context
};
httpd_register_uri_handler(server, &file_tflite);
*/
}

View File

@@ -4,6 +4,8 @@
void register_server_file_uri(httpd_handle_t server, const char *base_path);
void unzip(std::string _in_zip_file, std::string _target_directory);
std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::string _target_bin, std::string _main = "/sdcard/");
void delete_all_in_directory(std::string _directory);

View File

@@ -43,6 +43,7 @@ esp_err_t send_file(httpd_req_t *req, std::string filename)
}
ESP_LOGI(TAG, "Sending file : %s ...", filename.c_str());
// httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
set_content_type_from_file(req, filename.c_str());
/* Retrieve the pointer to scratch buffer for temporary storage */
@@ -120,6 +121,8 @@ esp_err_t set_content_type_from_file(httpd_req_t *req, const char *filename)
return httpd_resp_set_type(req, "image/x-icon");
} else if (IS_FILE_EXT(filename, ".js")) {
return httpd_resp_set_type(req, "text/javascript");
} else if (IS_FILE_EXT(filename, ".css")) {
return httpd_resp_set_type(req, "text/css");
}
/* This is a limited set only */
/* For any other type always set as plain text */

View File

@@ -50,6 +50,8 @@ static char ota_write_data[BUFFSIZE + 1] = { 0 };
#define OTA_URL_SIZE 256
static const char *TAGPARTOTA = "server_ota";
esp_err_t handler_reboot(httpd_req_t *req);
static void infinite_loop(void)
{
@@ -207,24 +209,6 @@ static void print_sha256 (const uint8_t *image_hash, const char *label)
static bool diagnostic(void)
{
/*
gpio_config_t io_conf;
io_conf.intr_type = (gpio_int_type_t) GPIO_PIN_INTR_DISABLE;
io_conf.mode = GPIO_MODE_INPUT;
io_conf.pin_bit_mask = (1ULL << CONFIG_EXAMPLE_GPIO_DIAGNOSTIC);
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
gpio_config(&io_conf);
ESP_LOGI(TAGPARTOTA, "Diagnostics (5 sec)...");
vTaskDelay(5000 / portTICK_PERIOD_MS);
bool diagnostic_is_ok = gpio_get_level(CONFIG_EXAMPLE_GPIO_DIAGNOSTIC);
gpio_reset_pin(CONFIG_EXAMPLE_GPIO_DIAGNOSTIC);
return diagnostic_is_ok;
*/
return true;
}
@@ -326,7 +310,7 @@ esp_err_t handler_ota_update(httpd_req_t *req)
if (httpd_query_key_value(_query, "task", _valuechar, 30) == ESP_OK)
{
printf("task is found"); printf(_valuechar); printf("\n");
printf("task is found: "); printf(_valuechar); printf("\n");
_task = std::string(_valuechar);
}
@@ -344,16 +328,105 @@ esp_err_t handler_ota_update(httpd_req_t *req)
};
if (_task.compare("update") == 0)
{
std::string filetype = toUpper(getFileType(fn));
if (filetype.length() == 0)
{
std::string zw = "Update failed - no file specified (zip, bin, tfl, tlite)";
httpd_resp_sendstr_chunk(req, zw.c_str());
httpd_resp_sendstr_chunk(req, NULL);
return ESP_OK;
}
if ((filetype == "TFLITE") || (filetype == "TFL"))
{
std::string out = "/sdcard/config/" + getFileFullFileName(fn);
DeleteFile(out);
CopyFile(fn, out);
DeleteFile(fn);
const char* resp_str = "Neural Network File copied.";
httpd_resp_sendstr_chunk(req, resp_str);
httpd_resp_sendstr_chunk(req, NULL);
return ESP_OK;
}
if (filetype == "ZIP")
{
std::string in, out, outbin, zw, retfirmware;
// in = "/sdcard/firmware/html.zip";
out = "/sdcard/html";
outbin = "/sdcard/firmware";
// delete_all_in_directory(out);
retfirmware = unzip_new(fn, out+"/", outbin+"/");
if (retfirmware.length() > 0)
{
filetype = "BIN";
fn = retfirmware;
zw = "HTML Update Successfull!<br><br>Additioal firmware found in ZIP file.\n";
httpd_resp_sendstr_chunk(req, zw.c_str());
}
else
{
zw = "HTML Update Successfull!<br><br>No reboot necessary.\n";
httpd_resp_sendstr_chunk(req, zw.c_str());
httpd_resp_sendstr_chunk(req, NULL);
return ESP_OK;
}
}
if (filetype == "BIN")
{
const char* resp_str;
KillTFliteTasks();
gpio_handler_deinit();
if (ota_update_task(fn))
{
// resp_str = "rebooting - Firmware Update Successfull!<br><br>You can restart now.";
// httpd_resp_send(req, resp_str, strlen(resp_str));
// httpd_resp_sendstr_chunk(req, NULL);
return handler_reboot(req);
}
else
{
resp_str = "Error during Firmware Update!!!<br><br>Please check output of console.";
}
httpd_resp_send(req, resp_str, strlen(resp_str));
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_ota_update - Done");
#endif
return ESP_OK;
}
std::string zw = "Update failed - no valid file specified (zip, bin, tfl, tlite)";
httpd_resp_sendstr_chunk(req, zw.c_str());
httpd_resp_sendstr_chunk(req, NULL);
return ESP_OK;
}
if (_task.compare("unziphtml") == 0)
{
std::string in, out, zw;
in = "/sdcard/firmware/html.zip";
out = "/sdcard/html/";
out = "/sdcard/html";
delete_all_in_directory(out);
unzip(in, out);
unzip(in, out+"/");
zw = "HTML Update Successfull!<br><br>No reboot necessary";
httpd_resp_sendstr_chunk(req, zw.c_str());
httpd_resp_sendstr_chunk(req, NULL);
@@ -371,6 +444,8 @@ esp_err_t handler_ota_update(httpd_req_t *req)
unlink(fn.c_str());
}
/* Respond with an empty chunk to signal HTTP response completion */
std::string zw = "file deleted!\n";
httpd_resp_sendstr_chunk(req, zw.c_str());
httpd_resp_send_chunk(req, NULL, 0);
return ESP_OK;
}
@@ -437,7 +512,7 @@ esp_err_t handler_reboot(httpd_req_t *req)
LogFile.WriteToFile("handler_reboot");
ESP_LOGI(TAGPARTOTA, "!!! System will restart within 5 sec!!!");
const char* resp_str = "<body style='font-family: arial'> <h3 id=t></h3></body><script>var h='Rebooting!<br>The page will automatically reload.<br>'; document.getElementById('t').innerHTML=h; setInterval(function (){h +='.'; document.getElementById('t').innerHTML=h; fetch(window.location.hostname,{mode: 'no-cors'}).then(r=>{window.location.replace('/wasserzaehler_roi.html');})}, 1000);</script>";
const char* resp_str = "<body style='font-family: arial'> <h3 id=t></h3></body><script>var h='Rebooting!<br>The page will automatically reload after around 25s.<br>'; document.getElementById('t').innerHTML=h; setInterval(function (){h +='.'; document.getElementById('t').innerHTML=h; fetch(window.location.hostname,{mode: 'no-cors'}).then(r=>{parent.location.href=('/index.html');})}, 1000);</script>";
httpd_resp_send(req, resp_str, strlen(resp_str));
doReboot();

View File

@@ -10,7 +10,7 @@
static const char* TAG = "flow_analog";
bool debugdetailgeneral = false;
bool debugdetailgeneral = true;
ClassFlowCNNGeneral::ClassFlowCNNGeneral(ClassFlowAlignment *_flowalign, t_CNNType _cnntype) : ClassFlowImage(NULL, TAG)
{
@@ -201,7 +201,7 @@ int ClassFlowCNNGeneral::ZeigerEvalHybridNeu(float zahl, float zahl_vorgaenger,
if (AnalogerVorgaenger)
{
// result = ZeigerEvalAnalogToDigitNeu(zahl, eval_vorgaenger);
result = ZeigerEvalAnalogToDigitNeu(zahl, zahl_vorgaenger);
result = ZeigerEvalAnalogToDigitNeu(zahl, zahl_vorgaenger, eval_vorgaenger);
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalHybridNeu - Analoger Vorgänger, Bewertung über ZeigerEvalAnalogNeu = " + std::to_string(result) +
" zahl: " + std::to_string(zahl) + " zahl_vorgaenger = " + std::to_string(zahl_vorgaenger)+ " eval_vorgaenger = " + std::to_string(eval_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe));
return result;
@@ -232,20 +232,20 @@ int ClassFlowCNNGeneral::ZeigerEvalHybridNeu(float zahl, float zahl_vorgaenger,
}
// bleibt nur >= 9.5 --> noch kein Nulldurchgang --> 2.8 --> 2, und 3.1 --> 2
// hier auf 4 reduziert, da erst ab Vorgänder 9 anfängt umzustellen. Bei 9.5 Vorgänger kann die aktuelle
// Zahl noch x.4 - x.5 sein.
// alles >=x.4 kann als aktuelle Zahl gelten im Übergang. Bei 9.5 Vorgänger kann die aktuelle
// Zahl noch x.6 - x.7 sein.
if (ergebnis_nachkomma >= 4)
result = ergebnis_vorkomma;
else
result = (ergebnis_vorkomma - 1 + 10) % 10;
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalHybridNeu - KEIN Analoger Vorgänger, >= 9.5 --> noch kein Nulldurchgang = " + std::to_string(result) +
" zahl: " + std::to_string(zahl) + " zahl_vorgaenger = " + std::to_string(zahl_vorgaenger)+ " eval_vorgaenger = " + std::to_string(eval_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe));
" zahl: " + std::to_string(zahl) + " zahl_vorgaenger = " + std::to_string(zahl_vorgaenger)+ " eval_vorgaenger = " + std::to_string(eval_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe) + " ergebnis_nachkomma = " + std::to_string(ergebnis_nachkomma));
return result;
}
int ClassFlowCNNGeneral::ZeigerEvalAnalogToDigitNeu(float zahl, float ziffer_vorgaenger)
int ClassFlowCNNGeneral::ZeigerEvalAnalogToDigitNeu(float zahl, float ziffer_vorgaenger, int eval_vorgaenger)
{
int result;
int ergebnis_nachkomma = ((int) floor(zahl * 10)) % 10;
@@ -272,7 +272,8 @@ int ClassFlowCNNGeneral::ZeigerEvalAnalogToDigitNeu(float zahl, float ziffer_vor
return result;
}
if (ziffer_vorgaenger <= 1) // Nulldurchgang hat stattgefunden (!Bewertung über Prev_value und nicht Zahl!) --> hier aufrunden (2.8 --> 3, aber auch 3.1 --> 3)
if (ziffer_vorgaenger <= 1 && eval_vorgaenger<9) // Nulldurchgang hat stattgefunden (!Bewertung über Prev_value und nicht Zahl!) --> hier aufrunden (2.8 --> 3, aber auch 3.1 --> 3)
// aber Sonderfall ziffer_vorgaeger = 0.1 vor_vorgaenger 9.9 => eval_vorgaenger ist 9, damit hat Nulldurchgang nicht stattgefunden.
{
if (ergebnis_nachkomma > 5)
result = (ergebnis_vorkomma + 1) % 10;
@@ -339,38 +340,6 @@ int ClassFlowCNNGeneral::ZeigerEvalAnalogNeu(float zahl, int ziffer_vorgaenger)
}
/*
int ClassFlowCNNGeneral::ZeigerEval(float zahl, int ziffer_vorgaenger)
{
int ergebnis_nachkomma = ((int) floor(zahl * 10) + 10) % 10;
int ergebnis_vorkomma = ((int) floor(zahl) + 10) % 10;
int ergebnis;
float ergebnis_rating;
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEval erg_v=" + std::to_string(ergebnis_vorkomma) + ", erg_n=" + std::to_string(ergebnis_nachkomma) + ", ziff_v=" + std::to_string(ziffer_vorgaenger));
if (ziffer_vorgaenger == -1)
return ergebnis_vorkomma % 10;
// Ist die aktuelle Stelle schon umgesprungen und die Vorstelle noch nicht?
// Akt.: 2.1, Vorstelle = 0.9 => 1.9
// Problem sind mehrere Rundungen
// Bsp. zahl=4.5, Vorgänger= 9.6 (ziffer_vorgaenger=0)
// Tritt nur auf bei Übergang von analog auf digit
ergebnis_rating = ergebnis_nachkomma - ziffer_vorgaenger;
if (ergebnis_nachkomma >= 5)
ergebnis_rating-=5.1;
else
ergebnis_rating+=5;
ergebnis = (int) round(zahl);
if (ergebnis_rating < 0)
ergebnis-=1;
if (ergebnis == -1)
ergebnis+=10;
ergebnis = (ergebnis + 10) % 10;
return ergebnis;
}
*/
bool ClassFlowCNNGeneral::ReadParameter(FILE* pfile, string& aktparamgraph)
{
@@ -416,11 +385,6 @@ bool ClassFlowCNNGeneral::ReadParameter(FILE* pfile, string& aktparamgraph)
{
this->logfileRetentionInDays = std::stoi(zerlegt[1]);
}
// if ((toUpper(zerlegt[0]) == "MODELTYPE") && (zerlegt.size() > 1))
// {
// if (toUpper(zerlegt[1]) == "DIGITHYPRID")
// CNNType = DigitalHyprid;
// }
if ((toUpper(zerlegt[0]) == "MODEL") && (zerlegt.size() > 1))
{
@@ -439,6 +403,11 @@ bool ClassFlowCNNGeneral::ReadParameter(FILE* pfile, string& aktparamgraph)
neuroi->posy = std::stoi(zerlegt[2]);
neuroi->deltax = std::stoi(zerlegt[3]);
neuroi->deltay = std::stoi(zerlegt[4]);
neuroi->CCW = false;
if (zerlegt.size() >= 6)
{
neuroi->CCW = toUpper(zerlegt[5]) == "TRUE";
}
neuroi->result_float = -1;
neuroi->image = NULL;
neuroi->image_org = NULL;
@@ -511,7 +480,7 @@ general* ClassFlowCNNGeneral::GetGENERAL(string _name, bool _create = true)
_ret->ROI.push_back(neuroi);
printf("GetGENERAL - GENERAL %s - roi %s\n", _analog.c_str(), _roi.c_str());
printf("GetGENERAL - GENERAL %s - roi %s - CCW: %d\n", _analog.c_str(), _roi.c_str(), neuroi->CCW);
return _ret;
}
@@ -658,10 +627,11 @@ bool ClassFlowCNNGeneral::getNetworkParameter()
CNNType = Digital;
printf("TFlite-Type set to Digital\n");
break;
case 20:
/* case 20:
CNNType = DigitalHyprid10;
printf("TFlite-Type set to DigitalHyprid10\n");
break;
*/
// case 22:
// CNNType = DigitalHyprid;
// printf("TFlite-Type set to DigitalHyprid\n");
@@ -724,8 +694,13 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
f1 = tflite->GetOutputValue(0);
f2 = tflite->GetOutputValue(1);
float result = fmod(atan2(f1, f2) / (M_PI * 2) + 2, 1);
GENERAL[_ana]->ROI[i]->result_float = result * 10;
printf("Result General(Analog)%i: %f\n", i, GENERAL[_ana]->ROI[i]->result_float);
if(GENERAL[_ana]->ROI[i]->CCW)
GENERAL[_ana]->ROI[i]->result_float = 10 - (result * 10);
else
GENERAL[_ana]->ROI[i]->result_float = result * 10;
printf("Result General(Analog)%i - CCW: %d - %f\n", i, GENERAL[_ana]->ROI[i]->CCW, GENERAL[_ana]->ROI[i]->result_float);
if (isLogImage)
LogImage(logPath, GENERAL[_ana]->ROI[i]->name, &GENERAL[_ana]->ROI[i]->result_float, NULL, time, GENERAL[_ana]->ROI[i]->image_org);
} break;
@@ -790,6 +765,7 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
}
} break;
*/
/*
case DigitalHyprid10:
{
int _num, _nachkomma;
@@ -825,6 +801,7 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
}
}
} break;
*/
case DoubleHyprid10:
{
@@ -858,7 +835,7 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
_fit = _val + _valminus;
}
if (result > 10)
if (result >= 10)
result = result - 10;
if (result < 0)
result = result + 10;
@@ -916,15 +893,17 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
_num = tflite->GetOutClassification();
GENERAL[_ana]->ROI[i]->result_float = (float)_num / 10.0;
if(GENERAL[_ana]->ROI[i]->CCW)
GENERAL[_ana]->ROI[i]->result_float = 10 - ((float)_num / 10.0);
else
GENERAL[_ana]->ROI[i]->result_float = (float)_num / 10.0;
_result_save_file = GENERAL[_ana]->ROI[i]->result_float;
GENERAL[_ana]->ROI[i]->isReject = false;
printf("Result General(Analog)%i: %f\n", i, GENERAL[_ana]->ROI[i]->result_float);
printf("Result General(Analog)%i - CCW: %d - %f\n", i, GENERAL[_ana]->ROI[i]->CCW, GENERAL[_ana]->ROI[i]->result_float);
if (isLogImage)
{

View File

@@ -10,7 +10,6 @@ enum t_CNNType {
Analogue,
Analogue100,
Digital,
// DigitalHyprid,
DigitalHyprid10,
DoubleHyprid10,
Digital100,
@@ -30,21 +29,18 @@ protected:
int DigitalBand = 3;
float DigitalAnalogerVorgaengerUebergangsbereich = 2;
float DigitalUebergangsbereichVorgaengerAnalogToDigit = 1; // war vorher 2
float DigitalUebergangsbereichVorgaenger = 0.9;
float DigitalUebergangsbereichVorgaenger = 0.7; // 9.3 - 0.7
string cnnmodelfile;
int modelxsize, modelysize, modelchannel;
bool isLogImageSelect;
string LogImageSelect;
ClassFlowAlignment* flowpostalignment;
// ClassFlowPostProcessing *flowpostprocessing = NULL;
bool SaveAllFiles;
// bool extendedResolution;
// int ZeigerEval(float zahl, int ziffer_vorgaenger);
// int ZeigerEvalHybrid(float zahl, float zahl_vorgaenger, int eval_vorgaenger);
bool SaveAllFiles;
int ZeigerEvalAnalogNeu(float zahl, int ziffer_vorgaenger);
int ZeigerEvalAnalogToDigitNeu(float zahl, float ziffer_vorgaenger);
int ZeigerEvalAnalogToDigitNeu(float zahl, float ziffer_vorgaenger, int eval_vorgaenger);
int ZeigerEvalHybridNeu(float zahl, float zahl_vorgaenger, int eval_vorgaenger, bool AnalogerVorgaenger = false);

View File

@@ -7,7 +7,7 @@ struct roi {
int posx, posy, deltax, deltay;
float result_float;
int result_klasse;
bool isReject;
bool isReject, CCW;
string name;
CImageBasis *image, *image_org;
};
@@ -33,9 +33,9 @@ struct NumberPost {
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
double FlowRateAct; // m3 / min
double PreValue; // letzter Wert, der gut ausgelesen wurde
double Value; // letzer ausgelesener Wert, inkl. Korrekturen
string ReturnRateValue; // RückgabewertRate
string ReturnChangeAbsolute; // RückgabewertRate
string ReturnRawValue; // Rohwert (mit N & führenden 0)

View File

@@ -63,7 +63,12 @@ void ClassFlowImage::LogImage(string logPath, string name, float *resultFloat, i
if (*resultFloat < 0)
sprintf(buf, "N.N_");
else
{
sprintf(buf, "%.1f_", *resultFloat);
if (strcmp(buf, "10.0_"))
sprintf(buf, "0.0_");
}
} else if (resultInt != NULL) {
sprintf(buf, "%d_", *resultInt);
} else {

View File

@@ -6,6 +6,7 @@
#include "time_sntp.h"
#include "interface_mqtt.h"
#include "ClassFlowPostProcessing.h"
#include "ClassLogFile.h"
#include <time.h>
@@ -31,9 +32,7 @@ void ClassFlowMQTT::SetInitialParameter(void)
ListFlowControll = NULL;
disabled = false;
MQTTenable = false;
keepAlive = 600; // TODO This must be greater than the Flow Interval!
}
ClassFlowMQTT::ClassFlowMQTT()
@@ -124,11 +123,50 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
printf("InitMQTTInit\n");
mainerrortopic = maintopic + "/connection";
printf("Init MQTT with uri: %s, clientname: %s, user: %s, password: %s, maintopic: %s\n", uri.c_str(), clientname.c_str(), user.c_str(), password.c_str(), mainerrortopic.c_str());
MQTTInit(uri, clientname, user, password, mainerrortopic, 60);
MQTTPublish(mainerrortopic, "connected", SetRetainFlag);
MQTTenable = true;
if (!MQTTInit(uri, clientname, user, password, mainerrortopic, keepAlive))
{ // Failed
MQTTenable = false;
return true; // We need to return true despite we failed, else it will retry 5x and then reboot!
}
}
// Try sending mainerrortopic. If it fails, re-run init
if (!MQTTPublish(mainerrortopic, "connected", SetRetainFlag))
{ // Failed
LogFile.WriteToFile("MQTT - Re-running init...!");
if (!MQTTInit(this->uri, this->clientname, this->user, this->password, this->mainerrortopic, keepAlive))
{ // Failed
MQTTenable = false;
return false;
}
}
// Try again and quit if it fails
if (!MQTTPublish(mainerrortopic, "connected", SetRetainFlag))
{ // Failed
MQTTenable = false;
return false;
}
/* if (!MQTTPublish(mainerrortopic, "connected", SetRetainFlag))
{ // Failed
LogFile.WriteToFile("MQTT - Could not publish connection status!");
MQTTenable = false;
return true; // We need to return true despite we failed, else it will retry 5x and then reboot!
}*/
/* if(!MQTTPublish(_LWTContext, "", 1))
{
LogFile.WriteToFile("MQTT - Could not publish LWT!");
MQTTenable = false;
return true; // We need to return true despite we failed, else it will retry 5x and then reboot!
}*/
MQTTenable = true;
return true;
}
@@ -141,8 +179,44 @@ string ClassFlowMQTT::GetMQTTMainTopic()
bool ClassFlowMQTT::doFlow(string zwtime)
{
if (!MQTTenable)
return true;
// if (!MQTTenable) {
// LogFile.WriteToFile("MQTT not enabled!");
//
// // Try again to init it
// if (!MQTTInit(this->uri, this->clientname, this->user, this->password, this->mainerrortopic, keepAlive))
// { // Failed
// MQTTenable = false;
// return true; // We need to return true despite we failed, else it will retry 5x and then reboot!
// }
//
// if (!MQTTPublish(mainerrortopic, "connected", SetRetainFlag))
// { // Failed
// MQTTenable = false;
// return true; // We need to return true despite we failed, else it will retry 5x and then reboot!
// }
//
// LogFile.WriteToFile("MQTT is now enabled");
// MQTTenable = true;
// }
// Try sending mainerrortopic. If it fails, re-run init
if (!MQTTPublish(mainerrortopic, "connected", SetRetainFlag))
{ // Failed
LogFile.WriteToFile("MQTT - Re-running init...!");
if (!MQTTInit(this->uri, this->clientname, this->user, this->password, this->mainerrortopic, keepAlive))
{ // Failed
MQTTenable = false;
return true; // We need to return true despite we failed, else it will retry 5x and then reboot!
}
}
// Try again and quit if it fails
if (!MQTTPublish(mainerrortopic, "connected", SetRetainFlag))
{ // Failed
MQTTenable = false;
return true; // We need to return true despite we failed, else it will retry 5x and then reboot!
}
std::string result;
std::string resulterror = "";
@@ -153,7 +227,10 @@ bool ClassFlowMQTT::doFlow(string zwtime)
string zw = "";
string namenumber = "";
MQTTPublish(mainerrortopic, "connected");
// if (!MQTTPublish(mainerrortopic, "connected", SetRetainFlag))
//{ // Failed, skip other topics
// return true; // We need to return true despite we failed, else it will retry 5x and then reboot!
//}
zw = maintopic + "/" + "uptime";
char uptimeStr[11];
@@ -163,13 +240,19 @@ bool ClassFlowMQTT::doFlow(string zwtime)
zw = maintopic + "/" + "freeMem";
char freeheapmem[11];
sprintf(freeheapmem, "%zu", esp_get_free_heap_size());
MQTTPublish(zw, freeheapmem, SetRetainFlag);
if (!MQTTPublish(zw, freeheapmem, SetRetainFlag))
{ // Failed, skip other topics
return true; // We need to return true despite we failed, else it will retry 5x and then reboot!
}
zw = maintopic + "/" + "wifiRSSI";
char rssi[11];
sprintf(rssi, "%d", get_WIFI_RSSI());
MQTTPublish(zw, rssi, SetRetainFlag);
zw = maintopic + "/" + "CPUtemp";
std::string cputemp = std::to_string(temperatureRead());
MQTTPublish(zw, cputemp, SetRetainFlag);
if (flowpostprocessing)
{

View File

@@ -15,6 +15,7 @@ protected:
std::string user, password;
int SetRetainFlag;
bool MQTTenable;
int keepAlive;
std::string maintopic, mainerrortopic;
void SetInitialParameter(void);

View File

@@ -9,6 +9,7 @@
#include <time.h>
#include "time_sntp.h"
//#define SERIAL_DEBUG // testing debug on serial enabled
#define PREVALUE_TIME_FORMAT_OUTPUT "%Y-%m-%dT%H:%M:%S"
@@ -68,7 +69,7 @@ string ClassFlowPostProcessing::GetPreValue(std::string _number)
return result;
}
void ClassFlowPostProcessing::SetPreValue(float zw, string _numbers, bool _extern)
void ClassFlowPostProcessing::SetPreValue(double zw, string _numbers, bool _extern)
{
printf("SetPrevalue: %f, %s\n", zw, _numbers.c_str());
for (int j = 0; j < NUMBERS.size(); ++j)
@@ -126,7 +127,7 @@ bool ClassFlowPostProcessing::LoadPreValue(void)
{
if (NUMBERS[j]->name == name)
{
NUMBERS[j]->PreValue = stof(zwvalue.c_str());
NUMBERS[j]->PreValue = stod(zwvalue.c_str());
NUMBERS[j]->ReturnPreValue = RundeOutput(NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma + 1); // SIcherheitshalber 1 Stelle mehr, da ggf. Exgtended Resolution an ist (wird erst beim ersten Durchlauf gesetzt)
time_t tStart;
@@ -177,7 +178,7 @@ bool ClassFlowPostProcessing::LoadPreValue(void)
fclose(pFile);
printf("%s", zw);
zwvalue = trim(std::string(zw));
NUMBERS[0]->PreValue = stof(zwvalue.c_str());
NUMBERS[0]->PreValue = stod(zwvalue.c_str());
time_t tStart;
int yy, month, dd, hh, mm, ss;
@@ -663,7 +664,9 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
previous_value = zw - 48;
}
}
#ifdef SERIAL_DEBUG
printf("After analog->getReadout: ReturnRaw %s\n", NUMBERS[j]->ReturnRawValue.c_str());
#endif
if (NUMBERS[j]->digit_roi && NUMBERS[j]->analog_roi)
NUMBERS[j]->ReturnRawValue = "." + NUMBERS[j]->ReturnRawValue;
@@ -674,16 +677,22 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
else
NUMBERS[j]->ReturnRawValue = flowDigit->getReadout(j, NUMBERS[j]->isExtendedResolution, previous_value); // Extended Resolution nur falls es keine analogen Ziffern gibt
}
#ifdef SERIAL_DEBUG
printf("After digital->getReadout: ReturnRaw %s\n", NUMBERS[j]->ReturnRawValue.c_str());
#endif
NUMBERS[j]->ReturnRawValue = ShiftDecimal(NUMBERS[j]->ReturnRawValue, NUMBERS[j]->DecimalShift);
printf("ReturnRaw %s", NUMBERS[j]->ReturnRawValue.c_str());
#ifdef SERIAL_DEBUG
printf("After ShiftDecimal: ReturnRaw %s\n", NUMBERS[j]->ReturnRawValue.c_str());
#endif
if (IgnoreLeadingNaN)
while ((NUMBERS[j]->ReturnRawValue.length() > 1) && (NUMBERS[j]->ReturnRawValue[0] == 'N'))
NUMBERS[j]->ReturnRawValue.erase(0, 1);
#ifdef SERIAL_DEBUG
printf("After IgnoreLeadingNaN: ReturnRaw %s\n", NUMBERS[j]->ReturnRawValue.c_str());
#endif
NUMBERS[j]->ReturnValue = NUMBERS[j]->ReturnRawValue;
if (findDelimiterPos(NUMBERS[j]->ReturnValue, "N") != std::string::npos)
@@ -693,18 +702,38 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
else
continue; // es gibt keinen Zahl, da noch ein N vorhanden ist.
}
#ifdef SERIAL_DEBUG
printf("After findDelimiterPos: ReturnValue %s\n", NUMBERS[j]->ReturnRawValue.c_str());
#endif
// Lösche führende Nullen (außer es ist nur noch einen 0)
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);
#ifdef SERIAL_DEBUG
printf("After removeLeadingZeros: ReturnValue %s\n", NUMBERS[j]->ReturnRawValue.c_str());
#endif
NUMBERS[j]->Value = std::stod(NUMBERS[j]->ReturnValue);
#ifdef SERIAL_DEBUG
printf("After setting the Value: Value %f and as double is %f\n", NUMBERS[j]->Value, std::stod(NUMBERS[j]->ReturnValue));
#endif
if (NUMBERS[j]->checkDigitIncreaseConsistency)
{
NUMBERS[j]->Value = checkDigitConsistency(NUMBERS[j]->Value, NUMBERS[j]->DecimalShift, NUMBERS[j]->analog_roi != NULL, NUMBERS[j]->PreValue);
if (flowDigit)
{
if (flowDigit->getCNNType() != Digital)
printf("checkDigitIncreaseConsistency = true - ignored due to wrong CNN-Type (not Digital Classification)\n");
else
NUMBERS[j]->Value = checkDigitConsistency(NUMBERS[j]->Value, NUMBERS[j]->DecimalShift, NUMBERS[j]->analog_roi != NULL, NUMBERS[j]->PreValue);
}
else
{
printf("checkDigitIncreaseConsistency = true - no digital numbers defined!\n");
}
}
#ifdef SERIAL_DEBUG
printf("After checkDigitIncreaseConsistency: Value %f\n", NUMBERS[j]->Value);
#endif
if (!NUMBERS[j]->AllowNegativeRates)
@@ -717,7 +746,9 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
continue;
}
}
#ifdef SERIAL_DEBUG
printf("After AllowNegativeRates: Value %f\n", NUMBERS[j]->Value);
#endif
double difference = difftime(imagetime, NUMBERS[j]->lastvalue); // in Sekunden
difference /= 60;
NUMBERS[j]->FlowRateAct = (NUMBERS[j]->Value - NUMBERS[j]->PreValue) / difference;
@@ -725,7 +756,7 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
if (NUMBERS[j]->useMaxRateValue && PreValueUse && NUMBERS[j]->PreValueOkay)
{
float _ratedifference;
double _ratedifference;
if (NUMBERS[j]->RateType == RateChange)
_ratedifference = NUMBERS[j]->FlowRateAct;
else
@@ -740,7 +771,9 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
continue;
}
}
#ifdef SERIAL_DEBUG
printf("After MaxRateCheck: Value %f\n", NUMBERS[j]->Value);
#endif
NUMBERS[j]->ReturnChangeAbsolute = RundeOutput(NUMBERS[j]->Value - NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma);
NUMBERS[j]->lastvalue = imagetime;
NUMBERS[j]->PreValue = NUMBERS[j]->Value;
@@ -818,7 +851,7 @@ string ClassFlowPostProcessing::getReadoutParam(bool _rawValue, bool _noerror, i
return NUMBERS[_number]->ReturnValue;
}
string ClassFlowPostProcessing::RundeOutput(float _in, int _anzNachkomma){
string ClassFlowPostProcessing::RundeOutput(double _in, int _anzNachkomma){
std::stringstream stream;
int _zw = _in;
// printf("AnzNachkomma: %d\n", _anzNachkomma);
@@ -842,7 +875,7 @@ string ClassFlowPostProcessing::RundeOutput(float _in, int _anzNachkomma){
}
string ClassFlowPostProcessing::ErsetzteN(string input, float _prevalue)
string ClassFlowPostProcessing::ErsetzteN(string input, double _prevalue)
{
int posN, posPunkt;
int pot, ziffer;
@@ -873,7 +906,7 @@ string ClassFlowPostProcessing::ErsetzteN(string input, float _prevalue)
return input;
}
float ClassFlowPostProcessing::checkDigitConsistency(float input, int _decilamshift, bool _isanalog, float _preValue){
float ClassFlowPostProcessing::checkDigitConsistency(double input, int _decilamshift, bool _isanalog, double _preValue){
int aktdigit, olddigit;
int aktdigit_before, olddigit_before;
int pot, pot_max;
@@ -885,8 +918,14 @@ float ClassFlowPostProcessing::checkDigitConsistency(float input, int _decilamsh
{
pot++;
}
#ifdef SERIAL_DEBUG
printf("checkDigitConsistency: pot=%d, decimalshift=%d\n", pot, _decilamshift);
#endif
pot_max = ((int) log10(input)) + 1;
float not_checked_input = floorf(input * pow(10, pot)) / pow(10, pot);
#ifdef SERIAL_DEBUG
printf("checkDigitConsistency: not_checked_input=%f\n", not_checked_input);
#endif
while (pot <= pot_max)
{
zw = input / pow(10, pot-1);
@@ -915,11 +954,13 @@ float ClassFlowPostProcessing::checkDigitConsistency(float input, int _decilamsh
input = input + ((float) (1)) * pow(10, pot); // addiere 1 an der Stelle
}
}
#ifdef SERIAL_DEBUG
printf("checkDigitConsistency: input=%f", input);
#endif
pot++;
}
return input;
return not_checked_input + input;
}
string ClassFlowPostProcessing::getReadoutRate(int _number)

View File

@@ -32,9 +32,9 @@ protected:
bool LoadPreValue(void);
string ShiftDecimal(string in, int _decShift);
string ErsetzteN(string, float _prevalue);
float checkDigitConsistency(float input, int _decilamshift, bool _isanalog, float _preValue);
string RundeOutput(float _in, int _anzNachkomma);
string ErsetzteN(string, double _prevalue);
float checkDigitConsistency(double input, int _decilamshift, bool _isanalog, double _preValue);
string RundeOutput(double _in, int _anzNachkomma);
void InitNUMBERS();
void handleDecimalSeparator(string _decsep, string _value);
@@ -58,7 +58,7 @@ public:
string getReadoutTimeStamp(int _number = 0);
void SavePreValue();
string GetPreValue(std::string _number = "");
void SetPreValue(float zw, string _numbers, bool _extern = false);
void SetPreValue(double zw, string _numbers, bool _extern = false);
std::string GetJSON(std::string _id = "", std::string _mac = "", std::string _lineend = "\n");

View File

@@ -209,6 +209,21 @@ size_t findDelimiterPos(string input, string delimiter)
return pos;
}
void DeleteFile(string fn)
{
// ESP_LOGI(logTag, "Deleting file : %s", fn.c_str());
/* Delete file */
FILE* fpSourceFile = OpenFileAndWait(fn.c_str(), "rb");
if (!fpSourceFile) // Sourcefile existiert nicht sonst gibt es einen Fehler beim Kopierversuch!
{
printf("DeleteFile: File %s existiert nicht!\n", fn.c_str());
return;
}
fclose(fpSourceFile);
unlink(fn.c_str());
}
void CopyFile(string input, string output)
{
@@ -243,18 +258,48 @@ void CopyFile(string input, string output)
// Close The Files
fclose(fpSourceFile);
fclose(fpTargetFile);
printf("File copied: %s to %s", input.c_str(), output.c_str());
}
string getFileFullFileName(string filename)
{
size_t lastpos = filename.find_last_of('/');
if (lastpos == string::npos)
return "";
// printf("Last position: %d\n", lastpos);
string zw = filename.substr(lastpos + 1, filename.size() - lastpos);
return zw;
}
string getDirectory(string filename)
{
size_t lastpos = filename.find('/');
if (lastpos == string::npos)
return "";
// printf("Directory: %d\n", lastpos);
string zw = filename.substr(0, lastpos - 1);
return zw;
}
string getFileType(string filename)
{
int lastpos = filename.find(".", 0);
int neu_pos;
size_t lastpos = filename.find(".", 0);
size_t neu_pos;
while ((neu_pos = filename.find(".", lastpos + 1)) > -1)
{
lastpos = neu_pos;
}
if (lastpos == string::npos)
return "";
string zw = filename.substr(lastpos + 1, filename.size() - lastpos);
zw = toUpper(zw);

View File

@@ -10,6 +10,7 @@ std::string FormatFileName(std::string input);
void FindReplace(std::string& line, std::string& oldString, std::string& newString);
void CopyFile(string input, string output);
void DeleteFile(string fn);
FILE* OpenFileAndWait(const char* nm, const char* _mode, int _waitsec = 1);
@@ -19,6 +20,8 @@ string trim(string istring, string adddelimiter = "");
bool ctype_space(const char c, string adddelimiter);
string getFileType(string filename);
string getFileFullFileName(string filename);
string getDirectory(string filename);
int mkdir_r(const char *dir, const mode_t mode);
int removeFolder(const char* folderPath, const char* logTag);

View File

@@ -129,6 +129,7 @@ void ClassLogFile::WriteToFile(std::string info, bool _time)
std::string logpath = logroot + "/" + buffer;
WriteToDedicatedFile(logpath, info, _time);
printf((info + "\n").c_str());
}
std::string ClassLogFile::GetCurrentFileName()

View File

@@ -19,18 +19,43 @@ esp_mqtt_event_id_t esp_mmqtt_ID = MQTT_EVENT_ANY;
bool mqtt_connected = false;
esp_mqtt_client_handle_t client = NULL;
void MQTTPublish(std::string _key, std::string _content, int retained_flag){
if (client && mqtt_connected) {
int msg_id;
std::string zw;
msg_id = esp_mqtt_client_publish(client, _key.c_str(), _content.c_str(), 0, 1, retained_flag);
zw = "sent publish successful in MQTTPublish, msg_id=" + std::to_string(msg_id) + ", " + _key + ", " + _content;
if (debugdetail) LogFile.WriteToFile(zw);
ESP_LOGD(TAG_INTERFACEMQTT, "sent publish successful in MQTTPublish, msg_id=%d, %s, %s", msg_id, _key.c_str(), _content.c_str());
bool MQTTPublish(std::string _key, std::string _content, int retained_flag){
// if (!client) {
// LogFile.WriteToFile("MQTT - client not initialized!");
// return false;
// }
// LogFile.WriteToFile("MQTT - client initialized!"); // Debug
//
// if (!mqtt_connected) {
// LogFile.WriteToFile("MQTT - Can not publish, not connected!");
// ESP_LOGW(TAG_INTERFACEMQTT, "Problem with Publish, client=%d, mqtt_connected %d", (int) client, (int) mqtt_connected);
// return false;
// }
// LogFile.WriteToFile("MQTT - connected!"); // Debug
/* if (client && mqtt_connected) {
LogFile.WriteToFile("MQTT - connected!"); // Debug
}
else {
ESP_LOGW(TAG_INTERFACEMQTT, "Problem with Publish, client=%d, mqtt_connected %d", (int) client, (int) mqtt_connected);
else { // init needed
if (!MQTTInit(this->uri, this->clientname, this->user, password, mainerrortopic, keepAlive)) // validate{
{ // Failed
return false;
}
}*/
int msg_id;
std::string zw;
msg_id = esp_mqtt_client_publish(client, _key.c_str(), _content.c_str(), 0, 1, retained_flag);
if (msg_id < 0) {
LogFile.WriteToFile("MQTT - Failed to publish '" + _key + "'!");
return false;
}
zw = "MQTT - sent publish successful in MQTTPublish, msg_id=" + std::to_string(msg_id) + ", " + _key + ", " + _content;
if (debugdetail) LogFile.WriteToFile(zw);
ESP_LOGD(TAG_INTERFACEMQTT, "sent publish successful in MQTTPublish, msg_id=%d, %s, %s", msg_id, _key.c_str(), _content.c_str());
return true;
}
@@ -90,11 +115,23 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
mqtt_event_handler_cb((esp_mqtt_event_handle_t) event_data);
}
void MQTTInit(std::string _mqttURI, std::string _clientid, std::string _user, std::string _password, std::string _LWTContext, int _keepalive){
bool MQTTInit(std::string _mqttURI, std::string _clientid, std::string _user, std::string _password, std::string _LWTContext, int _keepalive){
std::string _zwmessage = "connection lost";
int _lzw = _zwmessage.length();
/* LWTContext = _LWTContext;
mqtt_cfg.uri = _mqttURI.c_str();
mqtt_cfg.client_id = _clientid.c_str();
mqtt_cfg.lwt_topic = _LWTContext.c_str();
mqtt_cfg.lwt_msg = _zwmessage.c_str();
mqtt_cfg.lwt_retain = 1;
mqtt_cfg.lwt_msg_len = _lzw;
mqtt_cfg.keepalive = _keepalive;
*/
esp_mqtt_client_config_t mqtt_cfg = {
.uri = _mqttURI.c_str(),
.client_id = _clientid.c_str(),
@@ -105,12 +142,51 @@ void MQTTInit(std::string _mqttURI, std::string _clientid, std::string _user, st
.keepalive = _keepalive
};
LogFile.WriteToFile("MQTT - Init");
if (_user.length() && _password.length()){
mqtt_cfg.username = _user.c_str();
mqtt_cfg.password = _password.c_str();
ESP_LOGI(TAG_INTERFACEMQTT, "Connect to MQTT: %s, %s", mqtt_cfg.username, mqtt_cfg.password);
};
MQTTdestroy();
client = esp_mqtt_client_init(&mqtt_cfg);
if (client)
{
if (esp_mqtt_client_register_event(client, esp_mmqtt_ID, mqtt_event_handler, client) != ESP_OK)
{
LogFile.WriteToFile("MQTT - Could not register event!");
return false;
}
if (esp_mqtt_client_start(client) != ESP_OK)
{
LogFile.WriteToFile("MQTT - Could not start client!");
return false;
}
/* if(!MQTTPublish(_LWTContext, "", 1))
{
LogFile.WriteToFile("MQTT - Could not publish LWT!");
return false;
}*/
}
else
{
LogFile.WriteToFile("MQTT - Could not Init client!");
return false;
}
LogFile.WriteToFile("MQTT - Init successful");
return true;
}
/*
void MQTTReConnect(){
std::string _zwmessage = "connection lost";
int _lzw = _zwmessage.length();
>>>>>>> Stashed changes
client = esp_mqtt_client_init(&mqtt_cfg);
if (client)
{
@@ -119,14 +195,25 @@ void MQTTInit(std::string _mqttURI, std::string _clientid, std::string _user, st
if (esp_mqtt_client_start(client) != ESP_OK)
LogFile.WriteToFile("MQTT - Could not start client!");
MQTTPublish(_LWTContext, "", 1);
<<<<<<< Updated upstream
if(MQTTPublish(_LWTContext, "", 1)) {
LogFile.WriteToFile("MQTT - Client init successful");
}
=======
if (mqtt_connected)
MQTTPublish(LWTContext, "", 1);
else
LogFile.WriteToFile("Problem with (Re)Connection not successful!");
>>>>>>> Stashed changes
}
else
{
LogFile.WriteToFile("MQTT - Could not Init MQTT Client!");
LogFile.WriteToFile("MQTT - Could not Init client!");
}
}
*/
void MQTTdestroy() {
if (client != NULL) {
@@ -185,6 +272,7 @@ void MQTTregisterSubscribeFunction(std::string topic, std::function<bool(std::st
void MQTTconnected(){
if (mqtt_connected) {
LogFile.WriteToFile("MQTT - Connected");
if (connectFunktionMap != NULL) {
for(std::map<std::string, std::function<void()>>::iterator it = connectFunktionMap->begin(); it != connectFunktionMap->end(); ++it) {
it->second();
@@ -192,10 +280,11 @@ void MQTTconnected(){
}
}
if (subscribeFunktionMap != NULL) {
if (subscribeFunktionMap != NULL) {
for(std::map<std::string, std::function<bool(std::string, char*, int)>>::iterator it = subscribeFunktionMap->begin(); it != subscribeFunktionMap->end(); ++it) {
int msg_id = esp_mqtt_client_subscribe(client, it->first.c_str(), 0);
ESP_LOGD(TAG_INTERFACEMQTT, "topic %s subscribe successful, msg_id=%d", it->first.c_str(), msg_id);
LogFile.WriteToFile("MQTT - topic " + it->first + " subscribe successful, msg_id=" + std::to_string(msg_id));
}
}
}

View File

@@ -5,12 +5,12 @@
#include <map>
#include <functional>
void MQTTInit(std::string _mqttURI, std::string _clientid, std::string _user, std::string _password, std::string _LWTContext, int _keepalive);
bool MQTTInit(std::string _mqttURI, std::string _clientid, std::string _user, std::string _password, std::string _LWTContext, int _keepalive);
void MQTTdestroy();
//void MQTTInit(std::string _mqttURI, std::string _clientid, std::string _user = "", std::string _password = "");
void MQTTPublish(std::string _key, std::string _content, int retained_flag = 1); // retained Flag as Standart
bool MQTTPublish(std::string _key, std::string _content, int retained_flag = 1); // retained Flag as Standart
bool MQTTisConnected();

View File

@@ -21,6 +21,7 @@
#include "server_GPIO.h"
#include "server_file.h"
#include "connect_wlan.h"
#define DEBUG_DETAIL_ON
@@ -590,6 +591,55 @@ esp_err_t handler_statusflow(httpd_req_t *req)
return ESP_OK;
};
esp_err_t handler_cputemp(httpd_req_t *req)
{
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_cputemp - Start");
#endif
const char* resp_str;
char cputemp[20];
sprintf(cputemp, "CPU Temp: %4.1f°C", temperatureRead());
resp_str = cputemp;
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);
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_cputemp - End");
#endif
return ESP_OK;
};
esp_err_t handler_rssi(httpd_req_t *req)
{
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_rssi - Start");
#endif
const char* resp_str;
char rssi[20];
sprintf(rssi, "RSSI: %idBm", get_WIFI_RSSI());
resp_str = rssi;
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);
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_rssi - End");
#endif
return ESP_OK;
};
esp_err_t handler_prevalue(httpd_req_t *req)
{
@@ -643,7 +693,7 @@ esp_err_t handler_prevalue(httpd_req_t *req)
httpd_resp_send_chunk(req, NULL, 0);
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_prevalue - Start");
LogFile.WriteHeapInfo("handler_prevalue - End");
#endif
return ESP_OK;
@@ -766,11 +816,26 @@ void register_server_tflite_uri(httpd_handle_t server)
camuri.user_ctx = (void*) "Light Off";
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/cputemp.html";
camuri.handler = handler_cputemp;
camuri.user_ctx = (void*) "Light Off";
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/rssi.html";
camuri.handler = handler_rssi;
camuri.user_ctx = (void*) "Light Off";
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/editflow.html";
camuri.handler = handler_editflow;
camuri.user_ctx = (void*) "EditFlow";
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/value.html";
camuri.handler = handler_wasserzaehler;
camuri.user_ctx = (void*) "Value";
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/wasserzaehler.html";
camuri.handler = handler_wasserzaehler;
camuri.user_ctx = (void*) "Wasserzaehler";

View File

@@ -1,4 +1,4 @@
const char* GIT_REV="234925c";
const char* GIT_TAG="";
const char* GIT_BRANCH="master";
const char* BUILD_TIME="2022-08-28 19:59";
const char* GIT_REV="N/A";
const char* GIT_TAG="N/A";
const char* GIT_BRANCH="N/A";
const char* BUILD_TIME="2022-09-17 09:00";

View File

@@ -13,7 +13,7 @@ extern "C"
#include "Helper.h"
#include <fstream>
const char* GIT_BASE_BRANCH = "master - v11.2.0 - 2022-08-28";
const char* GIT_BASE_BRANCH = "master - v11.3.0 - 2022-09-16";
const char* git_base_branch(void)

View File

@@ -12,12 +12,12 @@
[platformio]
src_dir = main
[env:esp32cam]
platform = espressif32@4.4.0
;platform = espressif32@5.1.0
;platform = espressif32
board = esp32cam
;board = m5stack-core-esp32
framework = espidf
;board_build.partitions = partitions_singleapp.csv
@@ -45,3 +45,6 @@ monitor_rts = 0
monitor_dtr = 0
debug_tool = esp-prog
; Enable and adapt for logging over USB
;upload_port = /dev/ttyUSB0

View File

@@ -1028,7 +1028,7 @@ CONFIG_MQTT_TRANSPORT_SSL=y
CONFIG_MQTT_TRANSPORT_WEBSOCKET=y
CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y
# CONFIG_MQTT_MSG_ID_INCREMENTAL is not set
# CONFIG_MQTT_SKIP_PUBLISH_IF_DISCONNECTED is not set
CONFIG_MQTT_SKIP_PUBLISH_IF_DISCONNECTED is not set
# CONFIG_MQTT_REPORT_DELETED_MESSAGES is not set
# CONFIG_MQTT_USE_CUSTOM_CONFIG is not set
# CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED is not set

View File

@@ -1036,7 +1036,7 @@ CONFIG_MQTT_TRANSPORT_SSL=y
CONFIG_MQTT_TRANSPORT_WEBSOCKET=y
CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y
# CONFIG_MQTT_MSG_ID_INCREMENTAL is not set
# CONFIG_MQTT_SKIP_PUBLISH_IF_DISCONNECTED is not set
CONFIG_MQTT_SKIP_PUBLISH_IF_DISCONNECTED=y
# CONFIG_MQTT_REPORT_DELETED_MESSAGES is not set
# CONFIG_MQTT_USE_CUSTOM_CONFIG is not set
# CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED is not set

View File

@@ -5,7 +5,8 @@
#include <ClassFlowMakeImage.h>
void setUpClassFlowPostprocessing(void);
string process_doFlow(std::vector<float> analog, std::vector<float> digits);
string process_doFlow(std::vector<float> analog, std::vector<float> digits, t_CNNType digType = Digital100,
bool checkConsistency=false, bool extendedResolution=false, int decimal_shift=0);
ClassFlowCNNGeneral* _analog;
ClassFlowCNNGeneral* _digit;
@@ -43,13 +44,14 @@ void test_doFlow() {
std::vector<float> digits = { 1.2, 6.7};
std::vector<float> analogs = { 9.5, 8.4};
const char* expected = "16.98";
const char* expected_extended = "16.984";
std::string result = process_doFlow(analogs, digits);
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
/*
* https://github.com/jomjol/AI-on-the-edge-device/issues/921
*
* Das Ergebnis sollte "376529.6" sein. Bzw. 16.98 ohne Extended true
* Das Ergebnis sollte "376529.6" sein.
*/
digits = { 3.0, 7.0, 6.0, 5.0, 2.5, 9.6};
analogs = { 6.4};
@@ -158,11 +160,154 @@ void test_doFlow() {
expected = "194.9089";
result = process_doFlow(analogs, digits);
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
// Fehler bei V11.2.0
// https://github.com/jomjol/AI-on-the-edge-device/issues/921#issuecomment-1229552041
digits = { 2.9, 7.0, 7.0, 9.1, 8.1, 8.5}; // 376.9884(1) als falsches Ergebnis
analogs = { 4.1 };
expected = "377988.4";
result = process_doFlow(analogs, digits);
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
// Fehler bei V11.2.0
// https://github.com/jomjol/AI-on-the-edge-device/issues/921#issuecomment-1233149877
digits = { 0.0, 0.0, 7.0, 8.9}; // 79.9999(6) als falsches Ergebnis
analogs = { 0.1, 0.1, 0.1, 9.6};
expected = "78.9999";
result = process_doFlow(analogs, digits);
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
// Fehler bei V11.2.0
// https://github.com/jomjol/AI-on-the-edge-device/issues/921#issuecomment-1236119370
digits = { 3.1, 9.1, 5.7}; // 9.1 führt zu falscher Erkennung eines unvollständigen Übergangs
analogs = { 8.8, 6.1, 3.0, 2.0};
expected = "395.8632";
result = process_doFlow(analogs, digits);
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
// Fehler bei V11.2.0
// https://github.com/jomjol/AI-on-the-edge-device/discussions/950#discussion-4338615
digits = { 1.0, 9.0, 9.0}; // Übergang wurde um 1 erhöht (200, statt 199)
analogs = { 7.1, 4.8, 8.3};
expected = "199.748";
result = process_doFlow(analogs, digits, Digital);
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
// Fehler bei Rolling (2002-09-09)
// https://github.com/jomjol/AI-on-the-edge-device/issues/921#issuecomment-1242730397
digits = { 3.0, 2.0, 2.0, 8.0, 9.0, 4.0, 1.7, 9.8}; // falscher Wert 32290.420
analogs = { };
expected = "32289.420";
expected_extended= "32289.4198";
// FALSCH! wegen ungenügender Präzision von NUMBERS->Value
// expected_extended= "32289.4198";
// extendResolution=false, checkConsistency=false
result = process_doFlow(analogs, digits, Digital100, false, false, -3);
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
// extendResolution=true
result = process_doFlow(analogs, digits, Digital100, false, true, -3);
TEST_ASSERT_EQUAL_STRING(expected_extended, result.c_str());
// checkConsistency=true und extendResolution=true
result = process_doFlow(analogs, digits, Digital100, false, true, -3);
TEST_ASSERT_EQUAL_STRING(expected_extended, result.c_str());
// Fehler Rolling (2022-09-10)
// not documented as issue
digits = { 0.0, 0.0, 7.9, 3.8}; // 84.99401 als falsches Ergebnis
analogs = { 0.0, 9.4, 4.1, 0.1};
expected = "83.9940";
expected_extended= "83.99401";
// checkConsistency=false
result = process_doFlow(analogs, digits, Digital100, false);
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
// checkConsistency=true
result = process_doFlow(analogs, digits, Digital100, true);
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
// extendResolution=true
result = process_doFlow(analogs, digits, Digital100, false, true);
TEST_ASSERT_EQUAL_STRING(expected_extended, result.c_str());
// checkConsistency=true und extendResolution=true
result = process_doFlow(analogs, digits, Digital100, false, true);
TEST_ASSERT_EQUAL_STRING(expected_extended, result.c_str());
// Fehler Rolling (2022-09-10)
// https://github.com/jomjol/AI-on-the-edge-device/issues/994#issue-1368570945
digits = { 0.0, 0.0, 1.0, 2.0, 2.8, 1.9, 2.8, 5.6}; // 123245.6 als falsches Ergebnis
analogs = { };
expected = "123236";
expected_extended= "123235.6";
// checkConsistency=true
result = process_doFlow(analogs, digits, Digital100, false, false);
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
// checkConsistency=true
result = process_doFlow(analogs, digits, Digital100, true, false);
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
// extendResolution=true
result = process_doFlow(analogs, digits, Digital100, false, true);
TEST_ASSERT_EQUAL_STRING(expected_extended, result.c_str());
// Fehler bei V11.2.0
// https://github.com/jomjol/AI-on-the-edge-device/discussions/950#discussioncomment-3661982
digits = { 3.0, 2.0, 4.1, 9.0, 4.0, 6.3, 9.2}; // 3249.459 als falsches Ergebnis
analogs = { };
expected = "3249.469";
expected_extended= "3249.4692";
// checkConsistency=true
result = process_doFlow(analogs, digits, Digital100, false, false, -3);
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
// checkConsistency=true
// checkConsistency NOT working correctly
//result = process_doFlow(analogs, digits, Digital100, true, false, -3);
//TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
// extendResolution=true
result = process_doFlow(analogs, digits, Digital100, false, true, -3);
TEST_ASSERT_EQUAL_STRING(expected_extended, result.c_str());
// Fehler bei V11.2.0
// https://github.com/jomjol/AI-on-the-edge-device/issues/1020#issue-1375648891
digits = { 0.0, 2.0, 6.1, 9.2}; // 259.9227 als falsches Ergebnis
analogs = { 9.0, 2.5, 2.9, 7.2};
expected = "269.9227";
expected_extended= "269.92272";
// Float Value reduziert die Genauigkeit hier. Korrekt wäre
// expected_extended= "269.92272";
// checkConsistency=true
result = process_doFlow(analogs, digits, Digital100, false, false);
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
// checkConsistency=true
// checkConsistency NOT working correctly
//result = process_doFlow(analogs, digits, Digital100, true, false, -3);
//TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
// checkConsistency=true und extendResolution=true
result = process_doFlow(analogs, digits, Digital100, false, true);
TEST_ASSERT_EQUAL_STRING(expected_extended, result.c_str());
}
void setUpClassFlowPostprocessing(void)
void setUpClassFlowPostprocessing(t_CNNType digType, t_CNNType anaType)
{
// wird im doFlow verwendet
@@ -170,18 +315,19 @@ void setUpClassFlowPostprocessing(void)
FlowControll.push_back(flowmakeimage);
// Die Modeltypen werden gesetzt, da keine Modelle verwendet werden.
_analog = new ClassFlowCNNGeneral(nullptr, Analogue100);
_analog = new ClassFlowCNNGeneral(nullptr, anaType);
_digit = new ClassFlowCNNGeneral(nullptr, Digital100);
_digit = new ClassFlowCNNGeneral(nullptr, digType);
undertestPost = new UnderTestPost(&FlowControll, _analog, _digit);
}
std::string process_doFlow(std::vector<float> analog, std::vector<float> digits) {
std::string process_doFlow(std::vector<float> analog, std::vector<float> digits, t_CNNType digType,
bool checkConsistency, bool extendedResolution, int decimal_shift) {
// setup the classundertest
setUpClassFlowPostprocessing();
setUpClassFlowPostprocessing(digType, Analogue100);
printf("SetupClassFlowPostprocessing completed.\n");
@@ -189,11 +335,11 @@ std::string process_doFlow(std::vector<float> analog, std::vector<float> digits)
if (digits.size()>0) {
general* gen_digit = _digit->GetGENERAL("default", true);
gen_digit->ROI.clear();
for (int i = 0; i<digits.size(); i++) {
roi* digitROI = new roi();
string name = "digit_" + std::to_string(i);
digitROI->name = name;
digitROI->result_klasse = (int) digits[i];
digitROI->result_float = digits[i];
gen_digit->ROI.push_back(digitROI);
}
@@ -215,6 +361,30 @@ std::string process_doFlow(std::vector<float> analog, std::vector<float> digits)
printf("Setup ROIs completed.\n");
undertestPost->InitNUMBERS();
if (checkConsistency) {
printf("checkConsistency=true\n");
std::vector<NumberPost*>* NUMBERS = undertestPost->GetNumbers();
for (int _n = 0; _n < (*NUMBERS).size(); ++_n) {
printf("Set checkConsistency on number: %d\n", _n);
(*NUMBERS)[_n]->checkDigitIncreaseConsistency = true;
}
}
if (extendedResolution ) {
std::vector<NumberPost*>* NUMBERS = undertestPost->GetNumbers();
for (int _n = 0; _n < (*NUMBERS).size(); ++_n) {
printf("Set extendedResolution on number: %d\n", _n);
(*NUMBERS)[_n]->isExtendedResolution = true;
}
}
if (decimal_shift!=0) {
std::vector<NumberPost*>* NUMBERS = undertestPost->GetNumbers();
for (int _n = 0; _n < (*NUMBERS).size(); ++_n) {
printf("Set decimalshif on number: %d to %d\n", _n, decimal_shift);
(*NUMBERS)[_n]->DecimalShift = decimal_shift;
(*NUMBERS)[_n]->DecimalShiftInitial = decimal_shift;
}
}
string time;
// run test

View File

@@ -1,4 +1,4 @@
const char* GIT_REV="234925c";
const char* GIT_TAG="";
const char* GIT_BRANCH="master";
const char* BUILD_TIME="2022-08-28 19:59";
const char* GIT_REV="N/A";
const char* GIT_TAG="N/A";
const char* GIT_BRANCH="N/A";
const char* BUILD_TIME="2022-09-17 09:00";

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -25,9 +25,9 @@ Model = /config/dig-cont_0570_s3.tflite
CNNGoodThreshold = 0.5
;LogImageLocation = /log/digit
;LogfileRetentionInDays = 3
main.dig1 294 126 30 54
main.dig2 343 126 30 54
main.dig3 391 126 30 54
main.dig1 294 126 30 54 false
main.dig2 343 126 30 54 false
main.dig3 391 126 30 54 false
[Analog]
Model = /config/ana-cont_11.3.0_s2.tflite
@@ -35,10 +35,10 @@ CNNGoodThreshold = 0.5
;LogImageLocation = /log/analog
;LogfileRetentionInDays = 3
ExtendedResolution = true
main.ana1 432 230 92 92
main.ana2 379 332 92 92
main.ana3 283 374 92 92
main.ana4 155 328 92 92
main.ana1 432 230 92 92 false
main.ana2 379 332 92 92 false
main.ana3 283 374 92 92 false
main.ana4 155 328 92 92 false
[PostProcessing]
main.DecimalShift = 0

Binary file not shown.

3
sd-card/html/FileSaver.min.js vendored Normal file
View File

@@ -0,0 +1,3 @@
(function(a,b){if("function"==typeof define&&define.amd)define([],b);else if("undefined"!=typeof exports)b();else{b(),a.FileSaver={exports:{}}.exports}})(this,function(){"use strict";function b(a,b){return"undefined"==typeof b?b={autoBom:!1}:"object"!=typeof b&&(console.warn("Deprecated: Expected third argument to be a object"),b={autoBom:!b}),b.autoBom&&/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(a.type)?new Blob(["\uFEFF",a],{type:a.type}):a}function c(a,b,c){var d=new XMLHttpRequest;d.open("GET",a),d.responseType="blob",d.onload=function(){g(d.response,b,c)},d.onerror=function(){console.error("could not download file")},d.send()}function d(a){var b=new XMLHttpRequest;b.open("HEAD",a,!1);try{b.send()}catch(a){}return 200<=b.status&&299>=b.status}function e(a){try{a.dispatchEvent(new MouseEvent("click"))}catch(c){var b=document.createEvent("MouseEvents");b.initMouseEvent("click",!0,!0,window,0,0,0,80,20,!1,!1,!1,!1,0,null),a.dispatchEvent(b)}}var f="object"==typeof window&&window.window===window?window:"object"==typeof self&&self.self===self?self:"object"==typeof global&&global.global===global?global:void 0,a=/Macintosh/.test(navigator.userAgent)&&/AppleWebKit/.test(navigator.userAgent)&&!/Safari/.test(navigator.userAgent),g=f.saveAs||("object"!=typeof window||window!==f?function(){}:"download"in HTMLAnchorElement.prototype&&!a?function(b,g,h){var i=f.URL||f.webkitURL,j=document.createElement("a");g=g||b.name||"download",j.download=g,j.rel="noopener","string"==typeof b?(j.href=b,j.origin===location.origin?e(j):d(j.href)?c(b,g,h):e(j,j.target="_blank")):(j.href=i.createObjectURL(b),setTimeout(function(){i.revokeObjectURL(j.href)},4E4),setTimeout(function(){e(j)},0))}:"msSaveOrOpenBlob"in navigator?function(f,g,h){if(g=g||f.name||"download","string"!=typeof f)navigator.msSaveOrOpenBlob(b(f,h),g);else if(d(f))c(f,g,h);else{var i=document.createElement("a");i.href=f,i.target="_blank",setTimeout(function(){e(i)})}}:function(b,d,e,g){if(g=g||open("","_blank"),g&&(g.document.title=g.document.body.innerText="downloading..."),"string"==typeof b)return c(b,d,e);var h="application/octet-stream"===b.type,i=/constructor/i.test(f.HTMLElement)||f.safari,j=/CriOS\/[\d]+/.test(navigator.userAgent);if((j||h&&i||a)&&"undefined"!=typeof FileReader){var k=new FileReader;k.onloadend=function(){var a=k.result;a=j?a:a.replace(/^data:[^;]*;/,"data:attachment/file;"),g?g.location.href=a:location=a,g=null},k.readAsDataURL(b)}else{var l=f.URL||f.webkitURL,m=l.createObjectURL(b);g?g.location=m:location.href=m,g=null,setTimeout(function(){l.revokeObjectURL(m)},4E4)}});f.saveAs=g.saveAs=g,"undefined"!=typeof module&&(module.exports=g)});
//# sourceMappingURL=FileSaver.min.js.map

File diff suppressed because one or more lines are too long

140
sd-card/html/backup.html Normal file
View File

@@ -0,0 +1,140 @@
<!DOCTYPE html>
<html>
<head>
<link rel="icon" href="favicon.ico" type="image/x-icon">
<title>Backup/Restore Configuration</title>
<meta charset="utf-8">
<style>
h1 {font-size: 2em;}
h2 {font-size: 1.5em;}
h3 {font-size: 1.2em;}
p {font-size: 1em;}
input[type=number] {
width: 138px;
padding: 10px 5px;
display: inline-block;
border: 1px solid #ccc;
font-size: 16px;
}
.button {
padding: 10px 20px;
width: 211px;
font-size: 16px;
}
</style>
</head>
<body style="font-family: arial; padding: 0px 10px;">
<h2>Backup Configuration</h2>
<p>With the following action the <a href="/fileserver/config/" target="_self">config</a> folder on the SD-card gets zipped and provided as a download.</p>
<table border="0">
</tr>
<td>
<button class="button" id="doBackup" type="button" onclick="doBackup()">Create Config backup</button>
</td>
<td>
<p id=progress></p>
</td>
</tr>
</table>
<hr>
<h2>Restore Configuration</h2>
<p>Use the <a href="/fileserver/config/" target="_self">File Server</a> to upload individual files.</p>
</body>
<script src="jszip.min.js"></script>
<script src="FileSaver.min.js"></script>
<script>
function doBackup() {
document.getElementById("progress").innerHTML = "Creating backup...";
// Get hostname
try {
var xhttp = new XMLHttpRequest();
xhttp.open("GET", "/version?type=Hostname", false);
xhttp.send();
hostname = xhttp.responseText;
}
catch(err) {
alert("Failed to fetch hostname: " + err.message);
return;
}
// get date/time
var dateTime = new Date().toJSON().slice(0,10) + "_" + new Date().toJSON().slice(11,19).replaceAll(":", "-");
zipFilename = hostname + "_" + dateTime + ".zip";
console.log(zipFilename);
// Get files list
try {
var xhttp = new XMLHttpRequest();
xhttp.open("GET", "/fileserver/config/", false);
xhttp.send();
var parser = new DOMParser();
var content = parser.parseFromString(xhttp.responseText, 'text/html'); }
catch(err) {
alert("Failed to fetch files list: " + err.message);
return;
}
const list = content.querySelectorAll("a");
var urls = [];
for (a of list) {
url = a.getAttribute("href");
urls.push(url);
}
// Pack as zip and download
try {
saveZip(zipFilename, urls);
}
catch(err) {
alert("Failed to zip files: " + err.message);
return;
}
}
const saveZip = (filename, urls) => {
if(!urls) return;
const zip = new JSZip();
const folder = zip.folder("");
var i = 0;
urls.forEach((url) => {
const blobPromise = fetch(url).then((r) => {
if (r.status === 200) return r.blob();
return Promise.reject(new Error(r.statusText));
});
const name = url.substring(url.lastIndexOf("/") + 1);
folder.file(name, blobPromise);
});
zip.generateAsync({ type: "blob" },
function updateCallback(metadata) {
var msg = "Progress: " + metadata.percent.toFixed(0) + "%";
if(metadata.currentFile) {
msg += ", " + metadata.currentFile;
}
console.log(msg);
document.getElementById("progress").innerHTML = msg;
}
).then((blob) => saveAs(blob, filename));
};
</script>
</html>

31
sd-card/html/common.js Normal file
View File

@@ -0,0 +1,31 @@
var basepath = "http://192.168.178.22";
function LoadHostname() {
_basepath = getbasepath();
var xhttp = new XMLHttpRequest();
xhttp.addEventListener('load', function(event) {
if (xhttp.status >= 200 && xhttp.status < 300) {
hostname = xhttp.responseText;
document.title = hostname + " - AI on the edge";
document.getElementById("id_title").innerHTML = "Digitizer - AI on the edge - " + hostname;
}
else {
console.warn(request.statusText, request.responseText);
}
});
// var xhttp = new XMLHttpRequest();
try {
url = _basepath + '/version?type=Hostname';
xhttp.open("GET", url, true);
xhttp.send();
}
catch (error)
{
// alert("Loading Hostname failed");
}
}

View File

@@ -86,7 +86,10 @@ select {
<table>
<tr>
<td colspan="2"><input class="button" type="submit" name="saveroi" onclick="SaveToConfig()" value="Save all to Config.ini"></td>
<td><input class="button" type="submit" name="saveroi" onclick="SaveToConfig()" value="Save all to Config.ini"></td>
</tr>
<tr>
<td><button class="button" id="reboot" type="button" onclick="doReboot()">Reboot to activate saved config</button></td>
</tr>
</table>
@@ -107,7 +110,17 @@ select {
basepath = "http://192.168.178.26";
basepath = "",
param;
function doReboot() {
if (confirm("Are you sure you want to reboot? Did you save the config?")) {
var stringota = "/reboot";
window.location = stringota;
window.location.href = stringota;
window.location.assign(stringota);
window.location.replace(stringota);
}
}
function ChangeSelection(){
aktindex = parseInt(document.getElementById("index").value);
UpdateReference();

View File

@@ -116,18 +116,22 @@ th, td {
<tr>
<td>x: <input type="number" name="refx" id="refx" step=1 onchange="valuemanualchanged()" tabindex=2></td>
<td>dx: <input type="number" name="refdx" id="refdx" step=1 onchange="valuemanualchangeddx()" tabindex=4></td>
<td rowspan="2"><label for="lockAR"> Lock aspect ratio: </label><input type="checkbox" id="lockAR" name="lockAR" value="1" onclick="changelockAR()" checked tabindex=6></td>
<td rowspan="1"><label for="lockAR"> Lock aspect ratio: </label><input type="checkbox" id="lockAR" name="lockAR" value="1" onclick="changelockAR()" checked tabindex=6></td>
</tr>
<tr>
<td>y: <input type="number" name="refy" id="refy" step=1 onchange="valuemanualchanged()" tabindex=3></td>
<td>dy: <input type="number" name="refdy" id="refdy" step=1 onchange="valuemanualchanged()" tabindex=5></td>
<td rowspan="1"><label for="CCW"> Counter-Clockwise Rotation: </label><input type="checkbox" id="CCW" name="CCW" value="0" onclick="changeCCW()" unchecked tabindex=7></td>
</tr>
</table>
</div>
<table>
<tr>
<td><input class="button" type="submit" id="saveroi" name="saveroi" onclick="SaveToConfig()" value="Save all to Config.ini" tabindex=7></td>
<td><input class="button" type="submit" id="saveroi" name="saveroi" onclick="SaveToConfig()" value="Save all to Config.ini" tabindex=8></td>
</tr>
<tr>
<td><button class="button" id="reboot" type="button" onclick="doReboot()">Reboot to activate saved config</button></td>
</tr>
</table>
@@ -147,8 +151,17 @@ th, td {
enhanceCon = false;
lockAR = true;
basepath = "http://192.168.178.26";
function doReboot() {
if (confirm("Are you sure you want to reboot? Did you save the config?")) {
var stringota = "/reboot";
window.location = stringota;
window.location.href = stringota;
window.location.assign(stringota);
window.location.replace(stringota);
}
}
function EnDisableAnalog() {
isEnabled = document.getElementById("Category_Analog_enabled").checked;
@@ -204,9 +217,9 @@ function newROI(){
var _roinew = prompt("Please enter name of new ROI", "name");
if (ROIInfo.length > 0)
erg = CreateROI(_number, "analog", sel.selectedIndex, _roinew, 1, 1, ROIInfo[aktindex]["dx"], ROIInfo[aktindex]["dy"]);
erg = CreateROI(_number, "analog", sel.selectedIndex, _roinew, 1, 1, ROIInfo[aktindex]["dx"], ROIInfo[aktindex]["dy"], ROIInfo[aktindex]["CCW"]=="true");
else
erg = CreateROI(_number, "analog", sel.selectedIndex, _roinew, 1, 1, 30, 30);
erg = CreateROI(_number, "analog", sel.selectedIndex, _roinew, 1, 1, 30, 30, false);
if (erg != "")
alert(erg);
@@ -234,6 +247,20 @@ function changelockAR(){
lockAR = document.getElementById("lockAR").checked;
}
function changeCCW(){
var sel = document.getElementById("Numbers_value1");
var _number = sel.options[sel.selectedIndex].text;
ROIInfo = getROIInfo("analog", _number);
aktindex = parseInt(document.getElementById("index").value);
if (document.getElementById("CCW").checked)
ROIInfo[aktindex]["CCW"] = "true";
else
ROIInfo[aktindex]["CCW"] = "false";
UpdateROIs();
}
function ChangeSelection(){
aktindex = parseInt(document.getElementById("index").value);
// lockAR = true;
@@ -249,7 +276,7 @@ function SaveToConfig(){
}
function UpdateROIs(){
function UpdateROIs(_sel){
document.getElementById("Category_Analog_enabled").checked = true;
var sel = document.getElementById("Numbers_value1");
var _number = sel.options[sel.selectedIndex].text;
@@ -320,6 +347,8 @@ function UpdateROIs(){
document.getElementById("refy").value = ROIInfo[aktindex]["y"];
document.getElementById("refdx").value = ROIInfo[aktindex]["dx"];
document.getElementById("refdy").value = ROIInfo[aktindex]["dy"];
document.getElementById("CCW").checked = ROIInfo[aktindex]["CCW"] == "true";
rect.startX = ROIInfo[aktindex]["x"];
rect.startY = ROIInfo[aktindex]["y"];
rect.w = ROIInfo[aktindex]["dx"];

View File

@@ -611,8 +611,12 @@ textarea {
<input type="text" id="MQTT_MainTopic_value1">
</td>
<td style="font-size: 80%;">
MQTT main topic, under which the counters are published. The single value will be published with the following key: MAINTOPIC/VALUE_NAME/PARAMETER <br>
where parameters are: value, rate, timestamp, error<br>
MQTT main topic, under which the counters are published. <br>
The single value will be published with the following key: MAINTOPIC/VALUE_NAME/PARAMETER where
<ul>
<li> VALUE_NAME is the name of the value (a meter might have more than one value) as defined during analog and digital ROI configuration (defaults to "main")</li>
<li> and PARAMETERS are: value, rate, timestamp, error</li>
</ul>
The general connection status can be found in MAINTOPIC/CONNECTION
</td>
</tr>

View File

@@ -119,6 +119,9 @@ th, td {
<table>
<tr>
<td><input class="button" type="submit" id="saveroi" name="saveroi" onclick="SaveToConfig()" value="Save all to Config.ini" tabindex=7></td>
</tr>
<tr>
<td><button class="button" id="reboot" type="button" onclick="doReboot()">Reboot to activate saved config</button></td>
</tr>
</table>
@@ -140,6 +143,15 @@ th, td {
lockAR = true;
basepath = "http://192.168.178.26";
function doReboot() {
if (confirm("Are you sure you want to reboot? Did you save the config?")) {
var stringota = "/reboot";
window.location = stringota;
window.location.href = stringota;
window.location.assign(stringota);
window.location.replace(stringota);
}
}
function EnDisableDigits() {
isEnabled = document.getElementById("Category_Digits_enabled").checked;
@@ -197,9 +209,9 @@ function newROI() {
var _roinew = prompt("Please enter name of new ROI", "name");
if (ROIInfo.length > 0)
erg = CreateROI(_number, "digit", sel.selectedIndex, _roinew, 1, 1, ROIInfo[aktindex]["dx"], ROIInfo[aktindex]["dy"]);
erg = CreateROI(_number, "digit", sel.selectedIndex, _roinew, 1, 1, ROIInfo[aktindex]["dx"], ROIInfo[aktindex]["dy"], 0);
else
erg = CreateROI(_number, "digit", sel.selectedIndex, _roinew, 1, 1, 30, 51);
erg = CreateROI(_number, "digit", sel.selectedIndex, _roinew, 1, 1, 30, 51, 0);
if (erg != "")
alert(erg);

View File

@@ -2,14 +2,11 @@
<html style="width: fit-content">
<head>
<link rel="icon" href="favicon.ico" type="image/x-icon">
<title>jomjol - AI on the edge</title>
<title>AI on the edge</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.h_iframe iframe {width:995px;height:605px;}
.h_iframe {width:995px;height:605px;}
h1 {font-size: 2em; margin-block-end: 0.3em;}
h2 {font-size: 1.5em;margin-block-start: 0.3em;}
h3 {font-size: 1.2em;}

View File

@@ -2,14 +2,11 @@
<html style="width: fit-content">
<head>
<link rel="icon" href="favicon.ico" type="image/x-icon">
<title>jomjol - AI on the edge</title>
<title>AI on the edge</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.h_iframe iframe {width:995px;height:605px;}
.h_iframe {width:995px;height:605px;}
h1 {font-size: 2em; margin-block-end: 0.3em;}
h2 {font-size: 1.5em;margin-block-start: 0.3em;}
h3 {font-size: 1.2em;}

View File

@@ -35,6 +35,7 @@ table {
<body style="font-family: arial; padding: 0px 10px;">
<h2>Create Reference out of Raw Image</h2>
<p><b>Note: After saving a new Reference Image, make sure to update the Alignment Marks and the ROI's and reboot once!</b></p>
<table>
<tr>
@@ -85,6 +86,9 @@ table {
</tr>
<tr>
<td><input class="button" type="button" id="updatereferenceimage" value="Update Reference Image" onclick="SaveReference()"></td>
</tr>
<tr>
<td><button class="button" id="reboot" type="button" onclick="doReboot()">Reboot to activate saved Reference</button></td>
</tr>
</table>
@@ -102,6 +106,16 @@ table {
basepath = "http://192.168.178.26";
isActReference = false;
param;
function doReboot() {
if (confirm("Are you sure you want to reboot? Did you save the config?")) {
var stringota = "/reboot";
window.location = stringota;
window.location.href = stringota;
window.location.assign(stringota);
window.location.replace(stringota);
}
}
function doTake(){
var xhttp = new XMLHttpRequest();

View File

@@ -2,14 +2,11 @@
<html style="width: fit-content">
<head>
<link rel="icon" href="favicon.ico" type="image/x-icon">
<title>jomjol - AI on the edge</title>
<title>AI on the edge</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.h_iframe iframe {width:995px;height:605px;}
.h_iframe {width:995px;height:605px;}
h1 {font-size: 2em; margin-block-end: 0.3em;}
h2 {font-size: 1.5em;margin-block-start: 0.3em;}
h3 {font-size: 1.2em;}

View File

@@ -2,13 +2,11 @@
<html style="width: fit-content">
<head>
<link rel="icon" href="favicon.ico" type="image/x-icon">
<title>jomjol - AI on the edge</title>
<title>AI on the edge</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.h_iframe iframe {width:995px;height:605px;}
.h_iframe {width:995px;height:605px;}
h1 {font-size: 2em; margin-block-end: 0.3em;}
h2 {font-size: 1.5em;margin-block-start: 0.3em;}

View File

@@ -2,14 +2,11 @@
<html style="width: fit-content">
<head>
<link rel="icon" href="favicon.ico" type="image/x-icon">
<title>jomjol - AI on the edge</title>
<title>AI on the edge</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.h_iframe iframe {width:995px;height:605px;}
.h_iframe {width:995px;height:605px;}
h1 {font-size: 2em; margin-block-end: 0.3em;}
h2 {font-size: 1.5em;margin-block-start: 0.3em;}
h3 {font-size: 1.2em;}

View File

@@ -2,13 +2,11 @@
<html style="width: fit-content">
<head>
<link rel="icon" href="favicon.ico" type="image/x-icon">
<title>jomjol - AI on the edge</title>
<title>AI on the edge</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.h_iframe iframe {width:995px;height:605px;}
.h_iframe {width:995px;height:605px;}
h1 {font-size: 2em; margin-block-end: 0.3em;}
h2 {font-size: 1.5em;margin-block-start: 0.3em;}

View File

@@ -2,14 +2,11 @@
<html style="width: fit-content">
<head>
<link rel="icon" href="favicon.ico" type="image/x-icon">
<title>jomjol - AI on the edge</title>
<title>AI on the edge</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.h_iframe iframe {width:995px;height:605px;}
.h_iframe {width:995px;height:605px;}
h1 {font-size: 2em; margin-block-end: 0.3em;}
h2 {font-size: 1.5em;margin-block-start: 0.3em;}
h3 {font-size: 1.2em;}

View File

@@ -2,14 +2,11 @@
<html style="width: fit-content">
<head>
<link rel="icon" href="favicon.ico" type="image/x-icon">
<title>jomjol - AI on the edge</title>
<title>AI on the edge</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.h_iframe iframe {width:995px;height:605px;}
.h_iframe {width:995px;height:605px;}
h1 {font-size: 2em; margin-block-end: 0.3em;}
h2 {font-size: 1.5em;margin-block-start: 0.3em;}
h3 {font-size: 1.2em;}

View File

@@ -2,13 +2,11 @@
<html style="width: fit-content">
<head>
<link rel="icon" href="favicon.ico" type="image/x-icon">
<title>jomjol - AI on the edge</title>
<title>AI on the edge</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.h_iframe iframe {width:995px;height:605px;}
.h_iframe {width:995px;height:605px;}
h1 {font-size: 2em; margin-block-end: 0.3em;}
h2 {font-size: 1.5em;margin-block-start: 0.3em;}

View File

@@ -1,78 +1,123 @@
<!DOCTYPE html>
<html style="width: fit-content">
<html>
<head>
<link rel="icon" href="favicon.ico" type="image/x-icon">
<title>jomjol - AI on the edge</title>
<title>AI on the edge</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- <link rel="stylesheet" href="style.css" type="text/css" > -->
<style>
.h_iframe iframe {width:995px;height:605px;}
.h_iframe {width:995px;height:605px;}
/* Older Firmware versions (11.2.0 and older) do not support css files, therefore we need to keep it integrated for now! */
body, html {
width: 100%;
height: 100%;
min-height: 800px;
margin: 0px 0px 0px 2px;
padding: 0;
font-family: arial;
width: fit-content;
}
h1 {font-size: 2em; margin-block-end: 0.3em;}
h2 {font-size: 1.5em;margin-block-start: 0.3em;}
h3 {font-size: 1.2em;}
p {font-size: 1em;}
.main {
display: flex;
width: 100%;
height: 100%;
flex-direction: column;
overflow: hidden;
}
.iframe {
flex-grow: 1;
margin: 5px 7px 4px 0px;
padding: 0;
border: 2px solid black;
}
h1 {
font-size: 2em;
margin-block-end: 0.3em;
}
h2 {
font-size: 1.5em;
margin-block-start: 0.3em;
}
h3 {
font-size: 1.2em;
}
p {
font-size: 1em;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #333;
width:1000px;
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #333;
width:1000px;
}
li {
float: left;
font-family: arial;
font-size: 18px;
float: left;
font-family: arial;
font-size: 18px;
}
li a, .dropbtn {
display: inline-block;
color: white;
text-align: center;
padding: 14px 16px;
text-decoration: none;
display: inline-block;
color: white;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
li a:hover, .dropdown:hover .dropbtn {
background-color: red;
background-color: red;
}
li.dropdown {
display: inline-block;
display: inline-block;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
font-family: arial;
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
font-family: arial;
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
text-align: left;
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
text-align: left;
}
.dropdown-content a:hover {background-color: #f1f1f1;}
.dropdown-content a:hover {
color: white;
background-color: red;
}
.dropdown:hover .dropdown-content {
display: block;
}
display: block;
}
</style>
<script type="text/javascript" src="common.js"></script>
<script type="text/javascript" src="gethost.js"></script>
<script type="text/javascript" src="readconfigcommon.js"></script>
<script type="text/javascript" src="readconfigparam.js"></script>
</head>
<body style="font-family: arial">
<body>
<div class="main">
<table style="border: none">
<tr><td style="padding-right: 10px;"><img src="favicon.ico"></td>
@@ -82,71 +127,35 @@ li.dropdown {
</table>
<ul>
<li><a href="#"onclick="document.getElementById('maincontent').src = '/wasserzaehler_roi.html';">Overview</a></li>
<li class="dropdown">
<li><a href="#"onclick="document.getElementById('maincontent').src = '/wasserzaehler_roi.html';">Overview</a></li>
<li class="dropdown">
<a href="javascript:void(0)" class="dropbtn">Configuration</a>
<div class="dropdown-content">
<a href="#"onclick="document.getElementById('maincontent').src = '/prevalue_set.html';">Set preValue</a>
<a href="index_configure.html">Edit Configuration</a>
<a href="#"onclick="document.getElementById('maincontent').src = '/prevalue_set.html';">Set Previous Value</a>
<a href="index_configure.html">Edit Configuration</a>
</div>
</li>
<li><a href="#"onclick="document.getElementById('maincontent').src = '/wasserzaehler.html?full';">Recognition</a></li>
<li><a href="#"onclick="document.getElementById('maincontent').src = '/fileserver/';">File Server</a></li>
<li class="dropdown">
</li>
<li><a href="#"onclick="document.getElementById('maincontent').src = '/wasserzaehler.html?full';">Recognition</a></li>
<li><a href="#"onclick="document.getElementById('maincontent').src = '/fileserver/';">File Server</a></li>
<li class="dropdown">
<a href="javascript:void(0)" class="dropbtn">System</a>
<div class="dropdown-content">
<a href="#"onclick="document.getElementById('maincontent').src = '/ota_page.html';">OTA Update</a>
<a href="#"onclick="document.getElementById('maincontent').src = '/fileserver/log/message/?readonly=true';">Log Viewer</a>
<a href="#"onclick="document.getElementById('maincontent').src = '/reboot_page.html';">Reboot</a>
<a href="#"onclick="document.getElementById('maincontent').src = '/info.html';">Info</a>
<a href="#"onclick="document.getElementById('maincontent').src = '/backup.html';">Backup/Restore</a>
<a href="#"onclick="document.getElementById('maincontent').src = '/ota_page.html';">OTA Update</a>
<a href="#"onclick="document.getElementById('maincontent').src = '/fileserver/log/message/?readonly=true';">Log Viewer</a>
<a href="#"onclick="document.getElementById('maincontent').src = '/reboot_page.html';">Reboot</a>
<a href="#"onclick="document.getElementById('maincontent').src = '/info.html';">Info</a>
</div>
</li>
</ul>
<p>
<div class="h_iframe">
<iframe name="maincontent" id ="maincontent" src="/wasserzaehler_roi.html" title="fileserver" allowfullscreen></iframe>
</div>
<script type="text/javascript" src="./gethost.js"></script>
<script type="text/javascript" src="./readconfigcommon.js"></script>
<script type="text/javascript" src="./readconfigparam.js"></script>
<iframe name="maincontent" class="iframe" id="maincontent" src="wasserzaehler_roi.html"></iframe>
<script type="text/javascript">
var basepath = "http://192.168.178.22";
function LoadHostname() {
_basepath = getbasepath();
var xhttp = new XMLHttpRequest();
xhttp.addEventListener('load', function(event) {
if (xhttp.status >= 200 && xhttp.status < 300) {
hostname = xhttp.responseText;
document.title = hostname + " - jomjol - AI on the edge";
document.getElementById("id_title").innerHTML = "Digitizer - AI on the edge - " + hostname;
} else {
console.warn(request.statusText, request.responseText);
}
});
// var xhttp = new XMLHttpRequest();
try {
url = _basepath + '/version?type=Hostname';
xhttp.open("GET", url, true);
xhttp.send();
}
catch (error)
{
// alert("Loading Hostname failed");
}
}
LoadHostname();
</script>
</div>
</body>
</html>

View File

@@ -2,76 +2,117 @@
<html>
<head>
<link rel="icon" href="favicon.ico" type="image/x-icon">
<title>jomjol - AI on the edge</title>
<title>AI on the edge</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- <link rel="stylesheet" href="style.css" type="text/css" > -->
<style>
.h_iframe iframe {width:995px;height:765px;}
.h_iframe {width:995px;height:765px;}
/* Older Firmware versions (11.2.0 and older) do not support css files, therefore we need to keep it integrated for now! */
body, html {
width: 100%;
height: 100%;
min-height: 800px;
margin: 0px 0px 0px 2px;
padding: 0;
font-family: arial;
width: fit-content;
}
h1 {font-size: 2em; margin-block-end: 0.3em;}
h2 {font-size: 1.5em;margin-block-start: 0.3em;}
h3 {font-size: 1.2em;}
p {font-size: 1em;}
.main {
display: flex;
width: 100%;
height: 100%;
flex-direction: column;
overflow: hidden;
}
.iframe {
flex-grow: 1;
margin: 5px 7px 4px 0px;
padding: 0;
border: 2px solid black;
}
h1 {
font-size: 2em;
margin-block-end: 0.3em;
}
h2 {
font-size: 1.5em;
margin-block-start: 0.3em;
}
h3 {
font-size: 1.2em;
}
p {
font-size: 1em;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #333;
width:1000px;
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #333;
width:1000px;
}
li {
float: left;
font-family: arial;
font-size: 18px;
float: left;
font-family: arial;
font-size: 18px;
}
li a, .dropbtn {
display: inline-block;
color: white;
text-align: center;
padding: 14px 16px;
text-decoration: none;
display: inline-block;
color: white;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
li a:hover, .dropdown:hover .dropbtn {
background-color: red;
background-color: red;
}
li.dropdown {
display: inline-block;
display: inline-block;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
font-family: arial;
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
font-family: arial;
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
text-align: left;
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
text-align: left;
}
.dropdown-content a:hover {background-color: #f1f1f1;}
.dropdown-content a:hover {
color: white;
background-color: red;
}
.dropdown:hover .dropdown-content {
display: block;
}
display: block;
}
</style>
</head>
<body style="font-family: arial">
<body>
<div class="main">
<table style="border: none">
<tr><td style="padding-right: 10px;"><img src="favicon.ico"></td>
@@ -81,62 +122,44 @@ li.dropdown {
</table>
<ul>
<li aria-current="page"><a href="index.html">Main Page</a>
<li><a href="#"onclick="document.getElementById('maincontent').src = 'edit_config_param.html';">Configuration</a></li>
<li aria-current="page"><a href="index.html">Main Page</a>
<li><a href="#"onclick="document.getElementById('maincontent').src = 'edit_config_param.html';">Configuration</a></li>
<li class="dropdown">
<a href="javascript:void(0)" class="dropbtn">Alignment</a>
<div class="dropdown-content">
<a href="#"onclick="document.getElementById('maincontent').src = 'edit_reference.html';">Reference Image</a>
<a href="#"onclick="document.getElementById('maincontent').src = 'edit_alignment.html';">Alignment Marks</a>
</div>
</li>
<a href="javascript:void(0)" class="dropbtn">Alignment</a>
<div class="dropdown-content">
<a href="#"onclick="document.getElementById('maincontent').src = 'edit_reference.html';">Reference Image</a>
<a href="#"onclick="document.getElementById('maincontent').src = 'edit_alignment.html';">Alignment Marks</a>
</div>
</li>
<li class="dropdown">
<a href="javascript:void(0)" class="dropbtn">Regions Of Interest (ROI)</a>
<div class="dropdown-content">
<a href="#"onclick="document.getElementById('maincontent').src = 'edit_digits.html';">Digital ROIs</a>
<a href="#"onclick="document.getElementById('maincontent').src = 'edit_analog.html';">Analog ROIs</a>
</div>
</li>
<a href="javascript:void(0)" class="dropbtn">Regions Of Interest (ROI)</a>
<div class="dropdown-content">
<a href="#"onclick="document.getElementById('maincontent').src = 'edit_digits.html';">Digital ROIs</a>
<a href="#"onclick="document.getElementById('maincontent').src = 'edit_analog.html';">Analog ROIs</a>
</div>
</li>
<li class="dropdown">
<a href="javascript:void(0)" class="dropbtn">System</a>
<div class="dropdown-content">
<a href="#"onclick="document.getElementById('maincontent').src = '/backup.html';">Backup/Restore</a>
<a href="#"onclick="document.getElementById('maincontent').src = '/ota_page.html';">OTA Update</a>
<a href="#"onclick="document.getElementById('maincontent').src = '/fileserver/log/message/?readonly=true';">Log Viewer</a>
<a href="#"onclick="document.getElementById('maincontent').src = '/reboot_page.html';">Reboot</a>
<a href="#"onclick="document.getElementById('maincontent').src = '/info.html';">Info</a>
</div>
</li>
</ul>
<p>
<div class="h_iframe">
<iframe width="1020px" height="650px" name="maincontent" id ="maincontent" src="edit_config_param.html" title="fileserver"></iframe>
</div>
<script type="text/javascript" src="./gethost.js"></script>
<iframe name="maincontent" class="iframe" id="maincontent" src="edit_config_param.html"></iframe>
<script type="text/javascript" src="common.js"></script>
<script type="text/javascript" src="gethost.js"></script>
<script type="text/javascript">
var basepath = "http://192.168.178.22";
function LoadHostname() {
_basepath = getbasepath();
var xhttp = new XMLHttpRequest();
xhttp.addEventListener('load', function(event) {
if (xhttp.status >= 200 && xhttp.status < 300) {
hostname = xhttp.responseText;
document.title = hostname + " - Configure";
document.getElementById("id_title").innerHTML = "Configure - " + hostname;
} else {
console.warn(request.statusText, request.responseText);
}
});
// var xhttp = new XMLHttpRequest();
try {
url = _basepath + '/version?type=Hostname';
xhttp.open("GET", url, true);
xhttp.send();
}
catch (error)
{
// alert("Loading Hostname failed");
}
}
LoadHostname();
</script>
</div>
</body>
</html>

View File

@@ -2,7 +2,7 @@
<html>
<head>
<link rel="icon" href="favicon.ico" type="image/x-icon">
<title>Set PreValue</title>
<title>Info</title>
<meta charset="utf-8">
<style>
@@ -136,6 +136,8 @@ div {
</tr>
</table>
<h3>Copyright</h3>
Copyright &copy; 2020 - 2022 by <a href="https://github.com/jomjol/AI-on-the-edge-device" target=_blank>Jomjol</a> and others.
</body>
</html>

13
sd-card/html/jszip.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -29,7 +29,9 @@ input[type=number] {
</head>
<body style="font-family: arial; padding: 0px 10px;">
<h3>It is strongly recommended to update firmware and content of /html directory on SD-card at the same time!</h3>
Check at <a href="https://github.com/jomjol/AI-on-the-edge-device/releases" target=_blank>https://github.com/jomjol/AI-on-the-edge-device/releases</a> to see if there is an update available.
<h3>It is strongly recommended to update firmware and web interface (stored separately in the html directory on SD-card) at the same time!</h3>
<hr>
<h2>1. Firmware Update</h2>
<table class="fixed" border="0">
<tr>
@@ -37,18 +39,21 @@ input[type=number] {
<table border="0">
<tr>
<td style="width: 230px">
<label for="newfile">Select the firmware file:</label>
<label for="newfile">Select the firmware file (firmware.bin):</label>
</td>
<td colspan="2">
<input id="newfile" type="file" onchange="setpath()" style="width:100%;">
</td>
<td rowspan="2" style="padding-left:50px">
<button class="button" id="doUpdate" type="button" onclick="doUpdate()">Flash the firmware<br>(Takes about 60s)</button>
</td>
</tr>
<tr>
<td>
<label for="filepath">Set path on server:</label>
</td>
<td>
<input id="filepath" type="text" style="width:100%;" readonly>
<input id="filepath" type="text" style="width:100%; border: 0" readonly>
</td>
<td>
<button id="upload" type="button" onclick="upload()">Upload</button>
@@ -57,41 +62,29 @@ input[type=number] {
</table>
</td>
</tr>
<tr>
<td>
<table border="0">
<tr>
<td style="width: 230px">
<button class="button" id="doUpdate" type="button" onclick="doUpdate()">Flash the firmware</button>
</td>
<td>
(Takes about 60s)
</td>
</tr>
</table>
</td>
</tr>
</table>
<h2>2. Update "/html" directory</h2>
<h2>2. Web Interface Update</h2>
<table class="fixed" border="0">
<tr>
<td>
<table border="0">
<tr>
<td style="width: 230px">
<label for="newfilehtml">Select the zipped /html content:</label>
<label for="newfilehtml">Select the Web Interface file (html.zip):</label>
</td>
<td colspan="2">
<input id="newfilehtml" type="file" onchange="setpathhtml()" style="width:100%;">
</td>
<td rowspan="2" style="padding-left:50px">
<button class="button" id="doUpdatehtml" type="button" onclick="doUpdatehtml()">Update Web Interface</button>
</td>
</tr>
<tr>
<td>
<label for="filepathhtml">Set path on server:</label>
</td>
<td>
<input id="filepathhtml" type="text" style="width:100%;" readonly>
<input id="filepathhtml" type="text" style="width:100%; border: 0" readonly>
</td>
<td>
<button id="uploadhtml" type="button" onclick="uploadhtml()">Upload</button>
@@ -100,21 +93,12 @@ input[type=number] {
</table>
</td>
</tr>
<tr>
<td>
<button class="button" id="doUpdatehtml" type="button" onclick="doUpdatehtml()">Update "/html" directory</button>
</td>
</tr>
</table>
<h2>3. Reboot</h2>
<table class="fixed" border="0">
<tr>
<td>
<button class="button" id="reboot" type="button" onclick="doReboot()">Reboot to activate updates</button>
</td>
</tr>
</table>
<h2>4. Upload neural network definition (tfl/tflite file)</h2>
<hr>
<h2>Upload Neural Network Definition (tfl/tflite file)</h2>
<b>The file must be set active afterwards on the <a href="index_configure.html" target="_parent">Config</a> page</b>!
<table class="fixed" border="0">
<tr>
<td>
@@ -132,7 +116,7 @@ input[type=number] {
<label for="filepathtfl">Set path on server</label>
</td>
<td>
<input id="filepathtfl" type="text" style="width:100%;" readonly>
<input id="filepathtfl" type="text" style="width:100%; border: 0" readonly>
</td>
<td>
<button id="uploadtfl" type="button" onclick="uploadtfl()" disabled>Upload</button>
@@ -141,7 +125,6 @@ input[type=number] {
</table>
</td>
</tr>
The file must be activated in the config.ini file.
</table>

View File

@@ -0,0 +1,207 @@
<!DOCTYPE html>
<html>
<head>
<link rel="icon" href="favicon.ico" type="image/x-icon">
<title>OTA Update</title>
<meta charset="utf-8">
<style>
h1 {font-size: 2em;}
h2 {font-size: 1.5em;}
h3 {font-size: 1.2em;}
p {font-size: 1em;}
input[type=number] {
width: 138px;
padding: 10px 5px;
display: inline-block;
border: 1px solid #ccc;
font-size: 16px;
}
.button {
padding: 10px 20px;
width: 211px;
font-size: 16px;
}
</style>
</head>
<body style="font-family: arial; padding: 0px 10px;">
Check at <a href="https://github.com/jomjol/AI-on-the-edge-device/releases" target=_blank>https://github.com/jomjol/AI-on-the-edge-device/releases</a> to see if there is an update available.
<h3>It is strongly recommended to update firmware and web interface (stored separately in the html directory on SD-card) at the same time!</h3>
<hr>
<h2>Update</h2>
<table class="fixed" border="0">
<tr>
<td>
<table border="0">
<tr>
<td style="width: 230px">
<label for="newfile">Select the update file (update.zip, firmware.bin, html.zip, *.tfl/tflite):</label>
</td>
<td colspan="2">
<input id="newfile" type="file" onchange="setpath()" style="width:100%;">
</td>
<td rowspan="2" style="padding-left:50px">
<button class="button" id="doUpdate" type="button" onclick="doUpdate()">Flash the firmware<br>(Takes about 60s)</button>
</td>
</tr>
<tr>
<td>
<label for="filepath">Selected upload file:</label>
</td>
<td>
<input id="filepath" type="text" style="width:100%; border: 0" readonly>
</td>
<td>
<button id="upload" type="button" onclick="upload()">Upload</button>
</td>
</tr>
</table>
</td>
</tr>
</table>
<h2>Reboot</h2>
<button class="button" id="reboot" type="button" onclick="doReboot()">Reboot to activate updates</button>
<hr>
<script type="text/javascript" src="./gethost.js"></script>
<script language="JavaScript">
var basepath = "http://192.168.178.26";
function init(){
basepath = getbasepath();
document.getElementById("reboot").disabled = true;
document.getElementById("upload").disabled = true;
document.getElementById("doUpdate").disabled = true;
}
function doUpdate() {
if (confirm("Are you sure to update the firmware?")) {
var stringota = "/ota?file=firmware.bin";
document.getElementById("doUpdate").disabled = true;
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4) {
if (xhttp.status == 200) {
document.getElementById("reboot").disabled = false;
alert("Flash successfull - Reboot necessary to make changes active.");
/* keine Reaktion, damit sich das Dokument nicht ändert */
} else if (xhttp.status == 0) {
alert("Server closed the connection abruptly!");
UpdatePage();
} else {
alert(xhttp.status + " Error!\n" + xhttp.responseText);
UpdatePage();
}
}
};
xhttp.open("GET", stringota, true);
xhttp.send();
}
}
function doReboot() {
if (confirm("Are you sure you want to reboot the ESP32?")) {
var stringota = "/reboot";
window.location = stringota;
window.location.href = stringota;
window.location.assign(stringota);
window.location.replace(stringota);
}
}
function setpath() {
var nameneu = document.getElementById("newfile").value;
nameneu = nameneu.split(/[\\\/]/).pop();
document.getElementById("filepath").value = nameneu;
document.getElementById("upload").disabled = false;
}
function upload() {
var xhttp = new XMLHttpRequest();
var filePath = document.getElementById("filepath").value;
var upload_path = "/upload/firmware/" + filePath;
var fileInput = document.getElementById("newfile").files;
/* first delete the old firmware */
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4) {
if (xhttp.status == 200) {
/* keine Reaktion, damit sich das Dokument nicht ändert */
} else if (xhttp.status == 0) {
alert("Server closed the connection abruptly!");
UpdatePage();
} else {
alert(xhttp.status + " Error!\n" + xhttp.responseText);
UpdatePage();
}
}
};
var _toDo = basepath + "/ota?delete=" + filePath;
xhttp.open("GET", _toDo, false);
xhttp.send();
/* ----------------------------- */
/* Max size of an individual file. Make sure this
* value is same as that set in file_server.c */
var MAX_FILE_SIZE = 6000*1024;
var MAX_FILE_SIZE_STR = "6MB";
if (fileInput.length == 0) {
alert("No file selected!");
} else if (filePath.length == 0) {
alert("File path on server is not set!");
} else if (filePath.indexOf(' ') >= 0) {
alert("File path on server cannot have spaces!");
} else if (filePath[filePath.length-1] == '/') {
alert("File name not specified after path!");
} else if (fileInput[0].size > MAX_FILE_SIZE) {
alert("File size must be less than " + MAX_FILE_SIZE_STR + "!");
} else {
document.getElementById("newfile").disabled = true;
document.getElementById("filepath").disabled = true;
document.getElementById("upload").disabled = true;
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4) {
if (xhttp.status == 200) {
alert("Upload successfull!")
// document.reload();
document.getElementById("reboot").disabled = false;
document.getElementById("doUpdate").disabled = false;
} else if (xhttp.status == 0) {
alert("Server closed the connection abruptly!");
UpdatePage();
} else {
alert(xhttp.status + " Error!\n" + xhttp.responseText);
UpdatePage();
}
}
};
var file = fileInput[0];
xhttp.open("POST", upload_path, true);
xhttp.send(file);
}
}
init();
</script>
</body>
</html>

View File

@@ -1,7 +1,7 @@
<html>
<head>
<link rel="icon" href="data:,">
<title>jomjol - AI on the edge</title>
<title>AI on the edge</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="text/javascript">

View File

@@ -86,8 +86,6 @@ function ParseConfig() {
ParamAddValue(param, catname, "CNNGoodThreshold", 1);
ParamAddValue(param, catname, "LogImageLocation");
ParamAddValue(param, catname, "LogfileRetentionInDays");
// ParamAddValue(param, catname, "ModelInputSize", 2);
var catname = "Analog";
category[catname] = new Object();
@@ -97,7 +95,6 @@ function ParseConfig() {
ParamAddValue(param, catname, "Model");
ParamAddValue(param, catname, "LogImageLocation");
ParamAddValue(param, catname, "LogfileRetentionInDays");
// ParamAddValue(param, catname, "ModelInputSize", 2);
var catname = "PostProcessing";
category[catname] = new Object();
@@ -236,9 +233,9 @@ 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'))
if (!isCom && (linesplit.length >= 5) && (_catname == 'Digits'))
ExtractROIs(input, "digit");
if (!isCom && (linesplit.length == 5) && (_catname == 'Analog'))
if (!isCom && (linesplit.length >= 5) && (_catname == 'Analog'))
ExtractROIs(input, "analog");
if (!isCom && (linesplit.length == 3) && (_catname == 'Alignment'))
{
@@ -398,6 +395,7 @@ function WriteConfigININew()
text = text + " " + NUMBERS[_roi]["digit"][_roiddet]["y"];
text = text + " " + NUMBERS[_roi]["digit"][_roiddet]["dx"];
text = text + " " + NUMBERS[_roi]["digit"][_roiddet]["dy"];
text = text + " " + NUMBERS[_roi]["digit"][_roiddet]["CCW"];
config_split.push(text);
}
}
@@ -416,6 +414,7 @@ function WriteConfigININew()
text = text + " " + NUMBERS[_roi]["analog"][_roiddet]["y"];
text = text + " " + NUMBERS[_roi]["analog"][_roiddet]["dx"];
text = text + " " + NUMBERS[_roi]["analog"][_roiddet]["dy"];
text = text + " " + NUMBERS[_roi]["analog"][_roiddet]["CCW"];
config_split.push(text);
}
}
@@ -484,6 +483,9 @@ function ExtractROIs(_aktline, _type){
abc["dx"] = linesplit[3];
abc["dy"] = linesplit[4];
abc["ar"] = parseFloat(linesplit[3]) / parseFloat(linesplit[4]);
abc["CCW"] = "false";
if (linesplit.length >= 6)
abc["CCW"] = linesplit[5];
}
@@ -712,7 +714,7 @@ function DeleteNUMBER(_delte){
return "";
}
function CreateROI(_number, _type, _pos, _roinew, _x, _y, _dx, _dy){
function CreateROI(_number, _type, _pos, _roinew, _x, _y, _dx, _dy, _CCW){
_indexnumber = -1;
for (j = 0; j < NUMBERS.length; ++j)
if (NUMBERS[j]["name"] == _number)
@@ -735,6 +737,7 @@ function CreateROI(_number, _type, _pos, _roinew, _x, _y, _dx, _dy){
_ret["dx"] = _dx;
_ret["dy"] = _dy;
_ret["ar"] = _dx / _dy;
_ret["CCW"] = _CCW;
NUMBERS[_indexnumber][_type].splice(_pos+1, 0, _ret);

View File

@@ -2,7 +2,7 @@
<html style="width: fit-content">
<head>
<link rel="icon" href="favicon.ico" type="image/x-icon">
<title>jomjol - AI on the edge</title>
<title>AI on the edge</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">

100
sd-card/html/style.css Normal file
View File

@@ -0,0 +1,100 @@
body, html {
width: 100%;
height: 100%;
min-height: 800px;
margin: 0px 0px 0px 2px;
padding: 0;
font-family: arial;
width: fit-content;
}
.main {
display: flex;
width: 100%;
height: 100%;
flex-direction: column;
overflow: hidden;
}
.iframe {
flex-grow: 1;
margin: 5px 7px 4px 0px;
padding: 0;
border: 2px solid black;
}
h1 {
font-size: 2em;
margin-block-end: 0.3em;
}
h2 {
font-size: 1.5em;
margin-block-start: 0.3em;
}
h3 {
font-size: 1.2em;
}
p {
font-size: 1em;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #333;
width:1000px;
}
li {
float: left;
font-family: arial;
font-size: 18px;
}
li a, .dropbtn {
display: inline-block;
color: white;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
li a:hover, .dropdown:hover .dropbtn {
background-color: red;
}
li.dropdown {
display: inline-block;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
font-family: arial;
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
text-align: left;
}
.dropdown-content a:hover {
color: white;
background-color: red;
}
.dropdown:hover .dropdown-content {
display: block;
}

View File

@@ -1 +1 @@
15.1.0
16.4.1

View File

@@ -20,7 +20,7 @@
<table class="tg">
<tr>
<td class="tg-1" rowspan="9"><div id="img"></div></td>
<td class="tg-1" rowspan="9" style="vertical-align: top"><div id="img"></div></td>
<th class="th">Value:</th>
</tr>
<tr>
@@ -57,6 +57,8 @@
<td class="tg-3">
<div id="timestamp" ></div>
<div id="statusflow" ></div>
<div id="cputemp" ></div>
<div id="rssi" ></div>
</td>
</tr>
</table>
@@ -83,6 +85,8 @@ function addZero(i) {
$('#img').html('<img src="/img_tmp/alg_roi.jpg" style="max-height:555px; display:block; margin-left:auto; margin-right:auto;"></img>');
$('#timestamp').html("Last Page Refresh:" + (h + ":" + m + ":" + s));
loadStatus();
loadCPUTemp();
loadRSSI();
refresh();
});
@@ -94,10 +98,10 @@ function refresh() {
var h = addZero(d.getHours());
var m = addZero(d.getMinutes());
var s = addZero(d.getSeconds());
// reassign the url to be like alg_roi.jpg?timestamp=456784512 based on timestamp
$('#img').html('<img src="/img_tmp/alg_roi.jpg?timestamp='+ timestamp +'"max-height:555px; display:block; margin-left:auto; margin-right:auto;"></img>');
$('#timestamp').html("Last Page Refresh:" + (h + ":" + m + ":" + s));
loadStatus();
init();
refresh();
}, 300000);
@@ -120,6 +124,32 @@ function refresh() {
xhttp.send();
}
function loadCPUTemp() {
url = basepath + '/cputemp.html';
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var _rsp = xhttp.responseText;
$('#cputemp').html(_rsp);
}
}
xhttp.open("GET", url, true);
xhttp.send();
}
function loadRSSI() {
url = basepath + '/rssi.html';
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var _rsp = xhttp.responseText;
$('#rssi').html(_rsp);
}
}
xhttp.open("GET", url, true);
xhttp.send();
}
function loadValue(_type, _div, _style) {
url = basepath + '/wasserzaehler.html?all=true&type=' + _type;
var xhttp = new XMLHttpRequest();
@@ -167,6 +197,8 @@ function refresh() {
loadValue("prevalue", "prevalue");
loadValue("error", "error", "font-size:8px");
loadStatus();
loadCPUTemp();
loadRSSI();
}
init();