diff --git a/Changelog.md b/Changelog.md index 31b01754..de5527b8 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,59 +1,67 @@ -## [Unreleased] - -xxx +## [15.1.0] - 2023-03-12 ### Update Procedure Update Procedure see [online documentation](https://jomjol.github.io/AI-on-the-edge-device-docs/Installation/#update-ota-over-the-air) -:bangbang: Afterwards you should force-reload the Web Interface (usually Ctrl-F5 will do it). +:bangbang: Afterwards you should force-reload the Web Interface (usually Ctrl-F5 will do it)! + +:bangbang: Afterwards you should check your configuration for errors! ### Changes -This release only migrates some parameters, see #2023 for details and a list of all parameter changes. -The parameter migration happens automatically on the next startup. No user interaction is required. -A backup of the config is stored on the SD-card as `config.bak`. - -Beside of the parameter change and the bugfix listed below, no changes are contained in this release! - -If you want to revert back to `v14` or earlier, you will have to revert the migration changes in `config.ini` manually! +For a full list of changes see [Full list of changes](https://github.com/jomjol/AI-on-the-edge-device/compare/v15.0.3...v15.1.0) #### Added +- The Configuration page has now tooltips with enhanced documentation +- MQTT: + - Added `GJ` (`gigajoule`) as an energy meter unit + - Removed State Class and unit from `raw` topic + - Various Improvements (Only send Homeassistant Discovery the first time we connect, ...) (https://github.com/jomjol/AI-on-the-edge-device/pull/2091 +- Added Expert Parameter to change CPU Clock from `160` to `240 Mhz` +- SD card basic read/write check and a folder/file presence check at boot to indicate SD card issues or missing folders / files ([#2085](https://github.com/jomjol/AI-on-the-edge-device/pull/2085)) +- Simplified "WIFI roaming" by client triggered channel scan (AP switching at low RSSI) -> using expert parameter "RSSIThreshold" ([#2120](https://github.com/jomjol/AI-on-the-edge-device/pull/2120)) +- Log WLAN disconnect reason codes (see [WLAN disconnect reasons](https://jomjol.github.io/AI-on-the-edge-device-docs/WLAN-disconnect-reason)) +- Support of InfluxDB v2 ([#2004](https://github.com/jomjol/AI-on-the-edge-device/pull/2004)) -- Additional interface to InfluxDB Version 2 upwards -- Updated the network and corrected problems with quantized version: - - Hybrid CNN network to `dig-cont_0611_s3` - - Analog CNN network to `ana-cont-11.0.5` and `ana-clas100-1.5.7` - - Digital CNN network to `dig-class100-1.6.0` - -- :bangbang: Update Camera driver: contrast, brightness and saturation now working - - :bangbang: **Attention**: this can effect old version as well, because there not all settings were effective! - -- Option to change the CPU frequency (stability vs. speed) -- Homeassistant: add GJ (giga joule) -- Implementes "poor mans" wifi roaming to connect to the nearest access point -- Additional startup checks (sd card, folder / file prescence, boot phase) -- Internal updates (log file handling, boot phase) #### Changed - -- [#2023](https://github.com/jomjol/AI-on-the-edge-device/pull/2023) Migrated Parameters -- Removed old `Topic` parameter, it is not used anymore -- Internal optimization of memory usage to enable new features -- Improve MQTT +- Updated models (tflite files), removed old versions (https://github.com/jomjol/AI-on-the-edge-device/pull/2089, https://github.com/jomjol/AI-on-the-edge-device/pull/2133) + :bangbang: **Attention:** Update your configuration! + - Hybrid CNN network to `dig-cont_0611_s3` + - Analog CNN network to `ana-cont-11.0.5` and `ana-clas100-1.5.7` + - Digital CNN network to `dig-class100-1.6.0` +- Various Web interface Improvements/Enhancements: + - Restructured Menu (Needs cache clearing to be applied) + - Enhanced `Previous Value` page + - Improved/faster Graph page + - Various minor improvements + - ROI config pages improvements + - Improved Backup Functionality +- Added log file logs for Firmware Update +- Improved memory management (moved various stuff to external PSRAM, https://github.com/jomjol/AI-on-the-edge-device/pull/2117) +- Camera driver update: Support of contrast and saturation ([#2048](https://github.com/jomjol/AI-on-the-edge-device/pull/2048)) + :bangbang: **Attention**: This could have impact to old configurations. Please check your configuration and potentially adapt parametrization, if detection is negativly affected. +- Improved error handling and provide more verbose output in error cases during boot phase ([#2020](https://github.com/jomjol/AI-on-the-edge-device/pull/2020)) +- Red board LED is indicating more different errors and states (see [Status LED Blink Codes](https://jomjol.github.io/AI-on-the-edge-device-docs/StatusLED-BlinkCodes)) +- Logfile: Print start indication block after time is synced to indicate start in logfile after a cold boot +- `Image Quality Index`: Limit lower input range to 8 to avoid system instabilities #### Fixed +- Various minor fixes +- Added State Class "measurement" to rate_per_time_unit +- GPIO: Avoid MQTT publishing to empty topic when "MQTT enable" flag is not set +- Fix timezone config parser +- Remote Setup truncated long passwords (https://github.com/jomjol/AI-on-the-edge-device/issues/2167) - Problem with timestamp in InfluxDB interface #### Removed - - n.a. ## [15.0.3] - 2023-02-28 -**Parameter Migration** +**Name: Parameter Migration** ### Update Procedure @@ -93,7 +101,7 @@ If you want to revert back to `v14` or earlier, you will have to revert the migr ## [14.0.3] -2023-02-05 -**Stabilization and Improved User Experience** +**Name: Stabilization and Improved User Experience** Thanks to over 80 Pull Requests from 6 contributors, we can anounce another great release with many many improvements and new features: @@ -147,7 +155,7 @@ For a full list of changes see [Full list of changes](https://github.com/jomjol/ ## [13.0.8] - 2022-12-19 -**Home Assistant MQTT Discovery Support** +**Name: Home Assistant MQTT Discovery Support** ### Update Procedure see [online documentation](https://jomjol.github.io/AI-on-the-edge-device-docs/Installation/#update-ota-over-the-air) @@ -227,7 +235,7 @@ For a full list of changes see [Full list of changes](https://github.com/jomjol/ ## [12.0.1] 2022-09-29 -Improve **u**ser e**x**perience +Name: Improve **u**ser e**x**perience :bangbang: The release breaks a few things in ota update :bangbang: @@ -895,6 +903,7 @@ External Illumination - Initial Version +[15.1.0]: https://github.com/jomjol/AI-on-the-edge-device/compare/v15.0.3...v15.1.0 [15.0.3]: https://github.com/jomjol/AI-on-the-edge-device/compare/v14.0.3...v15.0.3 [14.0.3]: https://github.com/jomjol/AI-on-the-edge-device/compare/v13.0.8...v14.0.3 [13.0.8]: https://github.com/jomjol/AI-on-the-edge-device/compare/v12.0.1...v13.0.8 diff --git a/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp b/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp index 22e4ff72..e9abf7c9 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp @@ -402,7 +402,7 @@ void ClassFlowPostProcessing::handleAllowNegativeRate(string _decsep, string _va _digit = _decsep.substr(0, _pospunkt); else _digit = "default"; - + for (int j = 0; j < NUMBERS.size(); ++j) { bool _rt = false; @@ -841,6 +841,7 @@ bool ClassFlowPostProcessing::doFlow(string zwtime) if (!NUMBERS[j]->AllowNegativeRates) { + LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "handleAllowNegativeRate for device: " + NUMBERS[j]->name); if ((NUMBERS[j]->Value < NUMBERS[j]->PreValue)) { #ifdef SERIAL_DEBUG @@ -848,6 +849,7 @@ bool ClassFlowPostProcessing::doFlow(string zwtime) NUMBERS[j]->PreValue-(2/pow(10, NUMBERS[j]->Nachkomma)) ) ; #endif + // Include inaccuracy of 0.2 for isExtendedResolution. if (NUMBERS[j]->Value >= (NUMBERS[j]->PreValue-(2/pow(10, NUMBERS[j]->Nachkomma))) && NUMBERS[j]->isExtendedResolution) { NUMBERS[j]->Value = NUMBERS[j]->PreValue; diff --git a/code/components/jomjol_time_sntp/time_sntp.cpp b/code/components/jomjol_time_sntp/time_sntp.cpp index 8a92c2c0..78df9d5b 100644 --- a/code/components/jomjol_time_sntp/time_sntp.cpp +++ b/code/components/jomjol_time_sntp/time_sntp.cpp @@ -175,10 +175,15 @@ bool setupTime() { while (configFile.getNextLine(&line, disabledLine, eof) && !configFile.isNewParagraph(line)) { - splitted = ZerlegeZeile(line); + splitted = ZerlegeZeile(line, "="); if (toUpper(splitted[0]) == "TIMEZONE") { - timeZone = splitted[1]; + if (splitted.size() <= 1) { // parameter part is empty + timeZone = ""; + } + else { + timeZone = splitted[1]; + } } if (toUpper(splitted[0]) == "TIMESERVER") { diff --git a/code/main/softAP.cpp b/code/main/softAP.cpp index 62eec287..191bccf4 100644 --- a/code/main/softAP.cpp +++ b/code/main/softAP.cpp @@ -212,55 +212,55 @@ esp_err_t config_ini_handler(httpd_req_t *req) { ESP_LOGD(TAG, "Query: %s", _query); - if (httpd_query_key_value(_query, "ssid", _valuechar, 30) == ESP_OK) + if (httpd_query_key_value(_query, "ssid", _valuechar, 100) == ESP_OK) { ESP_LOGD(TAG, "ssid is found: %s", _valuechar); ssid = UrlDecode(std::string(_valuechar)); } - if (httpd_query_key_value(_query, "pwd", _valuechar, 30) == ESP_OK) + if (httpd_query_key_value(_query, "pwd", _valuechar, 100) == ESP_OK) { ESP_LOGD(TAG, "pwd is found: %s", _valuechar); pwd = UrlDecode(std::string(_valuechar)); } - if (httpd_query_key_value(_query, "ssid", _valuechar, 30) == ESP_OK) + if (httpd_query_key_value(_query, "ssid", _valuechar, 100) == ESP_OK) { ESP_LOGD(TAG, "ssid is found: %s", _valuechar); ssid = UrlDecode(std::string(_valuechar)); } - if (httpd_query_key_value(_query, "hn", _valuechar, 30) == ESP_OK) + if (httpd_query_key_value(_query, "hn", _valuechar, 100) == ESP_OK) { ESP_LOGD(TAG, "hostname is found: %s", _valuechar); hn = UrlDecode(std::string(_valuechar)); } - if (httpd_query_key_value(_query, "ip", _valuechar, 30) == ESP_OK) + if (httpd_query_key_value(_query, "ip", _valuechar, 100) == ESP_OK) { ESP_LOGD(TAG, "ip is found: %s", _valuechar); ip = UrlDecode(std::string(_valuechar)); } - if (httpd_query_key_value(_query, "gw", _valuechar, 30) == ESP_OK) + if (httpd_query_key_value(_query, "gw", _valuechar, 100) == ESP_OK) { ESP_LOGD(TAG, "gateway is found: %s", _valuechar); gw = UrlDecode(std::string(_valuechar)); } - if (httpd_query_key_value(_query, "nm", _valuechar, 30) == ESP_OK) + if (httpd_query_key_value(_query, "nm", _valuechar, 100) == ESP_OK) { ESP_LOGD(TAG, "netmask is found: %s", _valuechar); nm = UrlDecode(std::string(_valuechar)); } - if (httpd_query_key_value(_query, "dns", _valuechar, 30) == ESP_OK) + if (httpd_query_key_value(_query, "dns", _valuechar, 100) == ESP_OK) { ESP_LOGD(TAG, "dns is found: %s", _valuechar); dns = UrlDecode(std::string(_valuechar)); } - if (httpd_query_key_value(_query, "rssithreshold", _valuechar, 30) == ESP_OK) + if (httpd_query_key_value(_query, "rssithreshold", _valuechar, 100) == ESP_OK) { ESP_LOGD(TAG, "rssithreshold is found: %s", _valuechar); rssithreshold = UrlDecode(std::string(_valuechar)); diff --git a/code/test/components/jomjol-flowcontroll/test_flow_pp_negative.cpp b/code/test/components/jomjol-flowcontroll/test_flow_pp_negative.cpp index 87ee56b2..5af4c766 100644 --- a/code/test/components/jomjol-flowcontroll/test_flow_pp_negative.cpp +++ b/code/test/components/jomjol-flowcontroll/test_flow_pp_negative.cpp @@ -76,3 +76,30 @@ void testNegative() { } +/** + * @brief Fehlerberichte aus Issues + * + */ +void testNegative_Issues() { + // Ohne decimal_shift + std::vector digits = { 2.0, 2.0, 0.0, 1.0, 7.2, 9.0, 8.0}; + std::vector analogs = { }; + double preValue_extended = 22018.080; + double preValue = 22018.08; + + const char* expected = "22017.98"; + + // https://github.com/jomjol/AI-on-the-edge-device/issues/2145#issuecomment-1461899094 + // extendResolution=false + // value < preValue + // Prüfung eingeschaltet => Fehler + preValue = 22018.08; // zu groß + UnderTestPost* underTestPost = init_do_flow(analogs, digits, Digital100, false, false, -2); + setAllowNegatives(underTestPost, false); + setPreValue(underTestPost, preValue_extended); + std::string result = process_doFlow(underTestPost); + TEST_ASSERT_EQUAL_STRING("Neg. Rate - Read: - Raw: 22017.98 - Pre: 22018.08 ", underTestPost->getReadoutError().c_str()); + TEST_ASSERT_EQUAL_STRING(expected, result.c_str()); + delete underTestPost; + +} \ No newline at end of file diff --git a/code/test/test_suite_flowcontroll.cpp b/code/test/test_suite_flowcontroll.cpp index 93a459a0..8c36cc1a 100644 --- a/code/test/test_suite_flowcontroll.cpp +++ b/code/test/test_suite_flowcontroll.cpp @@ -108,9 +108,9 @@ extern "C" void app_main() esp_log_level_set("*", ESP_LOG_DEBUG); // set all components to ERROR level UNITY_BEGIN(); - - RUN_TEST(testNegative); - + RUN_TEST(testNegative_Issues); + /* RUN_TEST(testNegative); + RUN_TEST(test_analogToDigit_Standard); RUN_TEST(test_analogToDigit_Transition); RUN_TEST(test_doFlowPP); @@ -121,6 +121,6 @@ extern "C" void app_main() // getReadoutRawString test RUN_TEST(test_getReadoutRawString); - + */ UNITY_END(); } diff --git a/sd-card/config/dig-class100_0160_s2_q.tflite b/sd-card/config/dig-class100_0160_s2_q.tflite new file mode 100644 index 00000000..a1769322 Binary files /dev/null and b/sd-card/config/dig-class100_0160_s2_q.tflite differ diff --git a/sd-card/html/backup.html b/sd-card/html/backup.html index 260354d9..c55c3d3d 100644 --- a/sd-card/html/backup.html +++ b/sd-card/html/backup.html @@ -122,13 +122,13 @@ function fetchFiles(urls, filesData, index, retry, zipFilename) { xhr.timeout = 5000; // time in milliseconds } else if (retry == 2) { // longer timeout - xhr.timeout = 20000; // time in milliseconds + xhr.timeout = 10000; // time in milliseconds } else if (retry == 3) { // longer timeout - xhr.timeout = 30000; // time in milliseconds + xhr.timeout = 20000; // time in milliseconds } else { // very long timeout - xhr.timeout = 60000; // time in milliseconds + xhr.timeout = 30000; // time in milliseconds } xhr.onload = () => { // Request finished @@ -146,6 +146,20 @@ function fetchFiles(urls, filesData, index, retry, zipFilename) { } }; + xhr.onprogress = (e) => { // XMLHttpRequest progress ... extend timeout + xhr.timeout = xhr.timeout + 500; + }; + + xhr.onerror = (e) => { // XMLHttpRequest error loading + console.log("Error on fetching " + url + "!"); + if (retry > 5) { + setStatus("Backup failed, please restart the device and try again!"); + } + else { + fetchFiles(urls, filesData, index, retry+1, zipFilename); + } + }; + xhr.ontimeout = (e) => { // XMLHttpRequest timed out console.log("Timeout on fetching " + url + "!"); if (retry > 5) { diff --git a/sd-card/html/common.js b/sd-card/html/common.js index ba170dee..3c73bb51 100644 --- a/sd-card/html/common.js +++ b/sd-card/html/common.js @@ -1,7 +1,7 @@ /* The UI can also be run locally, but you have to set the IP of your devide accordingly. * And you also might have to disable CORS in your webbrowser! */ -var domainname_for_testing = "192.168.178.62"; +var domainname_for_testing = "192.168.1.153"; diff --git a/sd-card/html/edit_analog.html b/sd-card/html/edit_analog.html index 3c104131..a30bb2a5 100644 --- a/sd-card/html/edit_analog.html +++ b/sd-card/html/edit_analog.html @@ -85,9 +85,6 @@ th, td { Number: @@ -105,8 +102,6 @@ th, td { @@ -120,16 +115,16 @@ th, td { x: Δx: - + y: Δy: - + - + @@ -159,8 +154,8 @@ th, td { cofcat, param, enhanceCon = false; - lockAR = true; - lockSizes = true; + lockAspectRatio = true; + lockSizes = false; domainname = getDomainname(); @@ -222,6 +217,7 @@ function deleteROI(){ aktindex = ROIInfo.length - 1; } UpdateROIs(); + draw(); } function newROI(){ @@ -259,12 +255,13 @@ function moveNext(){ UpdateROIs(); } -function changelockAR(){ - lockAR = document.getElementById("lockAR").checked; +function changelockAspectRatio(){ + lockAspectRatio = document.getElementById("lockAspectRatio").checked; } function changelockSizes(){ lockSizes = document.getElementById("lockSizes").checked; + UpdateROIs(); } function changeCCW(){ @@ -283,7 +280,7 @@ function changeCCW(){ function ChangeSelection(){ aktindex = parseInt(document.getElementById("index").value); -// lockAR = true; +// lockAspectRatio = true; UpdateROIs(); } @@ -317,6 +314,7 @@ function UpdateROIs(_sel){ document.getElementById("newROI").disabled = false; document.getElementById("deleteROI").disabled = true; document.getElementById("index").disabled = true; + document.getElementById("saveroi").disabled = true; document.getElementById("renameROI").disabled = true; document.getElementById("moveNext").disabled = true; document.getElementById("movePrevious").disabled = true; @@ -361,7 +359,7 @@ function UpdateROIs(_sel){ document.getElementById("moveNext").disabled = true; } - document.getElementById("lockAR").checked = lockAR; + document.getElementById("lockAspectRatio").checked = lockAspectRatio; document.getElementById("lockSizes").checked = lockSizes; document.getElementById("refx").value = ROIInfo[aktindex]["x"]; @@ -419,6 +417,29 @@ function UpdateROIs(_sel){ param = getConfigParameters(); cofcat = getConfigCategory(); UpdateNUMBERS(); + + /* Check if the ROIs have same dy and dx. If so, tick the sync checkbox */ + var all_dx_dy_Identical = true; + if (ROIInfo.length > 1) { + for (var i = 1; i < (ROIInfo.length); ++i) { // 2nd .. last ROI + if (parseInt(ROIInfo[i].dx) != parseInt(ROIInfo[0].dx) || + parseInt(ROIInfo[i].dy) != parseInt(ROIInfo[0].dy)) { + all_dx_dy_Identical = false; + break; + } + } + } + + if (all_dx_dy_Identical) { + lockSizes = true; + console.log("All ROI have the same dX and dY, ticking the sync checkbox!"); + document.getElementById("lockSizes").checked = lockSizes; + } + else { + console.log("Not all ROI have the same dX and dY, unticking the sync checkbox!"); + } + + drawImage(); draw(); } @@ -510,11 +531,17 @@ function drawTextBG(context, txt, x, y, padding) { if (typeof ROIInfo === 'undefined') { // During init, ROIInfo is not defined yet return; } + + var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d'); context.drawImage(imageObj, 0, 0); + if (ROIInfo.length == 0) { + return; + } + context.font = "15px Arial"; context.fillStyle = "red"; context.textAlign = "center"; @@ -540,7 +567,7 @@ function drawTextBG(context, txt, x, y, padding) { { if (_nb != _number) { - lw = 1; + lw = 2; context.lineWidth = lw; context.strokeStyle = "#990000"; var x0 = parseInt(ROIInfo[_nb].x) - parseInt(lw/2); @@ -549,12 +576,24 @@ function drawTextBG(context, txt, x, y, padding) { var dy = parseInt(ROIInfo[_nb].dy) + parseInt(lw); context.strokeRect(x0, y0, dx, dy); drawTextBG(context, ROIInfo[_nb]["name"], x0+dx/2-0.5, y0-13, 5); + + lw = 1; + var x0 = parseInt(ROIInfo[_nb].x) - parseInt(lw/2); + var y0 = parseInt(ROIInfo[_nb].y) - parseInt(lw/2); + var dx = parseInt(ROIInfo[_nb].dx) + parseInt(lw); + var dy = parseInt(ROIInfo[_nb].dy) + parseInt(lw); + context.strokeRect(x0, y0, dx, dy); + context.lineWidth = lw; + context.beginPath(); + context.arc(x0+dx/2, y0+dy/2, dx/2, 0, 2 * Math.PI); + context.moveTo(x0+dx/2, y0); + context.lineTo(x0+dx/2, y0+dy); + context.moveTo(x0, y0+dy/2); + context.lineTo(x0+dx, y0+dy/2); + context.stroke(); } - } - - lw = 4 context.lineWidth = lw; context.strokeStyle = "#FF0000"; @@ -622,7 +661,7 @@ function drawTextBG(context, txt, x, y, padding) { zw = getCoords(this) - if (lockAR) { + if (lockAspectRatio) { rect.h = (e.pageY - zw.top) - rect.startY; rect.w = Math.round(rect.h * ROIInfo[aktindex]["ar"]); } else { @@ -657,7 +696,7 @@ function drawTextBG(context, txt, x, y, padding) { if (!drag) { rect.w = document.getElementById("refdx").value; rect.h = document.getElementById("refdy").value; - if (lockAR) { + if (lockAspectRatio) { rect.w = Math.round(rect.h * ROIInfo[aktindex]["ar"]); document.getElementById("refdx").value = rect.w; } @@ -672,7 +711,7 @@ function drawTextBG(context, txt, x, y, padding) { if (!drag) { rect.w = document.getElementById("refdx").value; rect.h = document.getElementById("refdy").value; - if (lockAR) { + if (lockAspectRatio) { rect.h = Math.round(rect.w / ROIInfo[aktindex]["ar"]); document.getElementById("refdy").value = rect.h; } diff --git a/sd-card/html/edit_config_param.html b/sd-card/html/edit_config_param.html index 0853b0b6..625c8d7f 100644 --- a/sd-card/html/edit_config_param.html +++ b/sd-card/html/edit_config_param.html @@ -1309,6 +1309,7 @@ textarea { +

Use timezones.html to find your correct settings.

$TOOLTIP_System_TimeZone diff --git a/sd-card/html/edit_digits.html b/sd-card/html/edit_digits.html index b8e8fce8..12b70356 100644 --- a/sd-card/html/edit_digits.html +++ b/sd-card/html/edit_digits.html @@ -81,9 +81,6 @@ th, td { Number: @@ -101,8 +98,6 @@ th, td { @@ -115,7 +110,7 @@ th, td { x: Δx: - + y: @@ -154,8 +149,8 @@ th, td { cofcat, param, enhanceCon = false; - lockAR = true; - lockSizes = true; + lockAspectRatio = true; + lockSizes = false; lockSpaceEquidistant = true; space = 3; domainname = getDomainname(); @@ -269,12 +264,14 @@ function moveNext(){ valuemanualchanged(); } -function changelockAR(){ - lockAR = document.getElementById("lockAR").checked; +function changelockAspectRatio(){ + lockAspectRatio = document.getElementById("lockAspectRatio").checked; } function changelockSizes(){ lockSizes = document.getElementById("lockSizes").checked; + UpdateROIs(); + valuemanualchangedspace(); if (!lockSizes) { firework.launch("For best results it is in most cases advised to keep the y, Δx and Δy identical!", 'warning', 10000); @@ -283,11 +280,18 @@ function changelockSizes(){ function changeLockSpaceEquidistant(){ lockSpaceEquidistant = document.getElementById("lockSpaceEquidistant").checked; + if (!lockSpaceEquidistant) { + document.getElementById("space").disabled = true; + } + else { + document.getElementById("space").disabled = false; + } + UpdateROIs(); } function ChangeSelection(){ aktindex = parseInt(document.getElementById("index").value); -// lockAR = true; +// lockAspectRatio = true; UpdateROIs(); } @@ -367,10 +371,16 @@ function UpdateROIs(_sel){ document.getElementById("moveNext").disabled = true; } - document.getElementById("lockAR").checked = lockAR; + document.getElementById("lockAspectRatio").checked = lockAspectRatio; document.getElementById("lockSizes").checked = lockSizes; document.getElementById("lockSpaceEquidistant").checked = lockSpaceEquidistant; document.getElementById("space").value = space; + if (!lockSpaceEquidistant) { + document.getElementById("space").disabled = true; + } + else { + document.getElementById("space").disabled = false; + } document.getElementById("refx").value = ROIInfo[aktindex]["x"]; document.getElementById("refy").value = ROIInfo[aktindex]["y"]; @@ -423,8 +433,53 @@ function UpdateROIs(_sel){ cofcat = getConfigCategory(); UpdateNUMBERS(); - space = ROIInfo[1].x - parseInt(ROIInfo[0].x) - parseInt(ROIInfo[0].dx); - document.getElementById("space").value = space; + + /* Check if the ROIs are equidistant. Only if not, untick the checkbox */ + if (ROIInfo.length > 1) { + var distanceROI0_to_ROI1 = parseInt(ROIInfo[1].x) - (parseInt(ROIInfo[0].x) + parseInt(ROIInfo[0].dx)); // Distance between 1st and 2nd ROI + //console.log("0->1: " + distanceROI0_to_ROI1); + for (var i = 1; i < (ROIInfo.length - 1); ++i) { // 2nd .. 2nd-last ROI + //console.log(i + "->" + i+1 + ": " + (parseInt(ROIInfo[i+1].x) - (parseInt(ROIInfo[i].x) + parseInt(ROIInfo[i].dx)))); + if (distanceROI0_to_ROI1 != (parseInt(ROIInfo[i+1].x) - (parseInt(ROIInfo[i].x) + parseInt(ROIInfo[i].dx)))) { + console.log("Not equidistant, unticking the checkbox!"); + lockSpaceEquidistant = false; + document.getElementById("lockSpaceEquidistant").checked = lockSpaceEquidistant; + if (!lockSpaceEquidistant) { + document.getElementById("space").disabled = true; + } + else { + document.getElementById("space").disabled = false; + } + break; + } + } + } + /* Check if the ROIs have same y, dy and dx. If so, tick the sync checkbox */ + var all_y_dx_dy_Identical = true; + if (ROIInfo.length > 1) { + for (var i = 1; i < (ROIInfo.length); ++i) { // 2nd .. last ROI + if (parseInt(ROIInfo[i].y) != parseInt(ROIInfo[0].y) || + parseInt(ROIInfo[i].dx) != parseInt(ROIInfo[0].dx) || + parseInt(ROIInfo[i].dy) != parseInt(ROIInfo[0].dy)) { + all_y_dx_dy_Identical = false; + break; + } + } + } + + if (all_y_dx_dy_Identical) { + lockSizes = true; + console.log("All ROI have the same Y, dX and dY, ticking the sync checkbox!"); + document.getElementById("lockSizes").checked = lockSizes; + } + else { + console.log("Not all ROI have the same Y, dX and dY, unticking the sync checkbox!"); + } + + if (ROIInfo.length > 1) { + space = ROIInfo[1].x - parseInt(ROIInfo[0].x) - parseInt(ROIInfo[0].dx); + document.getElementById("space").value = space; + } drawImage(); draw(); @@ -558,8 +613,19 @@ function draw() { var dy = parseInt(ROIInfo[_nb].dy) + parseInt(lw); context.strokeRect(x0, y0, dx, dy); drawTextBG(context, ROIInfo[_nb]["name"], x0+dx/2, y0-12, 5); - } + lw = 1 + var x0 = parseInt(ROIInfo[_nb].x) - parseInt(lw/2); + var y0 = parseInt(ROIInfo[_nb].y) - parseInt(lw/2); + var dx = parseInt(ROIInfo[_nb].dx) + parseInt(lw); + var dy = parseInt(ROIInfo[_nb].dy) + parseInt(lw); + context.lineWidth = lw; + context.beginPath(); + context.moveTo(x0, y0+dy/2); + context.lineTo(x0+dx, y0+dy/2); + context.stroke(); + context.strokeRect(x0+dx*0.2, y0+dy*0.2, dx*0.6, dy*0.6); + } } lw = 4 @@ -635,7 +701,7 @@ function draw() { return; } - if (lockAR) { + if (lockAspectRatio) { rect.h = (e.pageY - zw.top) - rect.startY; rect.w = Math.round(rect.h * ROIInfo[aktindex]["ar"]); } else { @@ -675,7 +741,7 @@ function draw() { rect.w = document.getElementById("refdx").value; rect.h = document.getElementById("refdy").value; - if (lockAR) { + if (lockAspectRatio) { rect.w = Math.round(rect.h * ROIInfo[aktindex]["ar"]); document.getElementById("refdx").value = rect.w; } @@ -700,7 +766,7 @@ function draw() { rect.w = document.getElementById("refdx").value; rect.h = document.getElementById("refdy").value; - if (lockAR) { + if (lockAspectRatio) { rect.h = Math.round(rect.w / ROIInfo[aktindex]["ar"]); document.getElementById("refdy").value = rect.h; }