### Setup Navigation and State Management
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/setup.html
Manages the setup progress, including starting, aborting, navigating between steps, and loading step-specific content. It also controls the visibility and source of stream and main content iframes.
```javascript
var aktstep = 0; var setupCompleted = false;
document.getElementById('stream').style.display = "none"; // Make sure that stream iframe is always hidden
document.getElementById("progressBar").value = 0;
function clickStart() {
aktstep = 0;
setupCompleted = false;
document.getElementById('stream').src = "";
document.getElementById('stream').style.display = "none"; // Make sure that stream iframe is always hidden
LoadStep();
}
function clickAbort() {
setupCompleted = false;
aktstep = 7;
document.getElementById('stream').src = "";
document.getElementById('stream').style.display = "none"; // Make sure that stream iframe is always hidden
LoadStep();
}
function clickNext() {
aktstep++;
if (aktstep > 7) {
aktstep = 7;
}
document.getElementById('stream').src = "";
document.getElementById('stream').style.display = "none"; // Make sure that stream iframe is always hidden
LoadStep();
}
function clickPrevious() {
aktstep--;
if (aktstep < 0) {
aktstep = 0;
}
document.getElementById('stream').src = "";
document.getElementById('stream').style.display = "none"; // Make sure that stream iframe is always hidden
LoadStep();
}
function LoadStep(){
loadRSSI();
switch (aktstep) {
case 0: // Start page
document.getElementById('maincontent').src = 'edit_explain_0.html?v=$COMMIT_HASH';
document.getElementById('maincontent').style.display = "";
document.getElementById('h_iframe_explain').style.display = "none";
document.getElementById("restart").disabled = true;
document.getElementById("previous").disabled = true;
document.getElementById("next").disabled = false;
document.getElementById("skip").disabled = false;
document.getElementById("progressBar").value = 0;
setupCompleted = false;
break;
case 1: // Live stream
document.getElementById('maincontent').style.display = "none";
document.getElementById('h_iframe_explain').style.display = "";
document.getElementById('h_iframe_explain').style="height:155px;"
document.getElementById('explaincontent').style="height:155px;"
document.getElementById('explaincontent').scrolling="yes"
document.getElementById('explaincontent').src = 'explain_1.html?v=$COMMIT_HASH';
document.getElementById("restart").disabled = false;
document.getElementById("previous").disabled = false;
document.getElementById("next").disabled = false;
document.getElementById("skip").disabled = false;
document.getElementById('h_iframe').style="height:480px;"
document.getElementById('stream').style="height:480px;"
document.getElementById("progressBar").value = 1;
setupCompleted = false;
setTimeout(function() {
document.getElementById('stream').src = getDomainname() + '/stream?flashlight=true'; // needs to be the last statement because it's kind of blocking
document.getElementById('stream').style.display = "";
}, 500);
break;
case 2: // Reference image
document.getElementById('maincontent').src = 'edit_reference.html?v=$COMMIT_HASH#description';
document.getElementById('maincontent').style.display = "";
document.getElementById('h_iframe_explain').style.display = "";
document.getElementById('h_iframe_explain').style="height:45px;"
document.getElementById('explaincontent').style="height:45px;"
document.getElementById('explaincontent').src = 'explain_2.html?v=$COMMIT_HASH';
document.getElementById("restart").disabled = false;
document.getElementById("previous").disabled = false;
document.getElementById("next").disabled = false;
document.getElementById("skip").disabled = false;
document.getElementById("progressBar").value = 2;
setupCompleted = false;
break;
case 3: // Alignment marker
document.getElementById('maincontent').src = 'edit_alignment.html?v=$COMMIT_HASH#description';
document.getElementById('h_iframe_explain').style.display = "";
document.getElementById('h_iframe_explain').style="height:45px;"
```
--------------------------------
### JavaScript Function to Complete Setup and Reboot
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/edit_explain_7.html
This function prompts the user for confirmation before completing the setup mode and rebooting the device. It loads configuration, updates setup mode parameters, and then redirects the user to the regular web interface.
```javascript
function reboot() {
if (confirm("Do you want to complete the setup mode and switch to regular web interface?")) {
domainname = getDomainname();
if (!loadConfig(domainname)) {
firework.launch('Setup mode could not be deactivated! Please try again!', 'danger', 30000);
return;
}
// ParseConfig(); // param = getConfigParameters();
param = getCamConfig();
param["System"]["SetupMode"]["enabled"] = true;
param["System"]["SetupMode"]["value1"] = "false";
WriteConfigININew();
SaveConfigToServer(domainname);
var stringota = getDomainname() + "/reboot";
parent.location = stringota;
parent.location.href = stringota;
parent.location.assign(stringota);
parent.location.replace(stringota);
}
}
```
--------------------------------
### Clone Repository and Initialize Submodules
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/code/README.md
Initial setup steps to clone the project repository and update its submodules.
```bash
git clone https://github.com/jomjol/AI-on-the-edge-device.git
cd AI-on-the-edge-device
git checkout main
git submodule update --init
```
--------------------------------
### Update UI for Setup Step 7 (Completion/Abort)
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/setup.html
This snippet handles the UI for the final setup step, displaying either a completion or an abort message based on the 'setupCompleted' flag. It adjusts iframe heights, sets content sources, and updates button states and progress.
```javascript
document.getElementById('h_iframe').style="height:660px;"
document.getElementById('maincontent').style="height:660px;"
if (setupCompleted) {
document.getElementById('maincontent').src = 'edit_explain_7.html?v=$COMMIT_HASH';
} else {
document.getElementById('maincontent').src = 'edit_explain_7_abort.html?v=$COMMIT_HASH';
document.getElementById("previous").disabled = true;
}
document.getElementById('h_iframe_explain').style.display = "none";
document.getElementById("skip").disabled = true;
document.getElementById("restart").disabled = false;
document.getElementById("next").disabled = true;
document.getElementById("progressBar").value = 7;
break;
```
--------------------------------
### Load Start Time
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/info.html
Fetches and displays the system start time. Expects the response in 'YYYYMMDD-HHMMSS' format.
```javascript
function loadLastRestart() {
url = getDomainname() + '/starttime';
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
//Input format: 19700101-010019
var timestamp = xhttp.response.substr(6,2) + "." + xhttp.response.substr(4,2) + "." + xhttp.response.substr(0,4) + " " + xhttp.response.substr(9,2) + ":" + xhttp.response.substr(11,2) + ":" + xhttp.response.substr(13,2);
document.getElementById("starttime").value = timestamp;
}
}
xhttp.open("GET", url, true);
xhttp.send();
}
```
--------------------------------
### Update UI for Setup Step 5 (Analog ROIs)
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/setup.html
This snippet prepares the UI for the Analog ROIs setup step. It sets the main content source, adjusts iframe and content heights, and updates navigation controls and progress.
```javascript
document.getElementById('maincontent').src = 'edit_analog.html?v=$COMMIT_HASH#description';
document.getElementById('h_iframe_explain').style.display = "";
document.getElementById('h_iframe_explain').style="height:45px;"
document.getElementById('explaincontent').style="height:45px;"
document.getElementById('explaincontent').scrolling="no"
document.getElementById('explaincontent').src = 'explain_5.html?v=$COMMIT_HASH';
document.getElementById("restart").disabled = false;
document.getElementById("previous").disabled = false;
document.getElementById("next").disabled = false;
document.getElementById("skip").disabled = false;
document.getElementById("progressBar").value = 5;
setupCompleted = false;
break;
```
--------------------------------
### Start Flow Process
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/index.html
Initiates a 'flow start' process by sending a GET request to the server. Provides feedback via a firework notification based on the server's response.
```javascript
function flow_start() {
var url = getDomainname() + '/flow_start';
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
firework.launch(xhttp.responseText, 'success', 5000);
/*if (xhttp.responseText.substring(0,3) == "001") { firework.launch('Flow start triggered', 'success', 5000); window.location.reload(); } else if (xhttp.responseText.substring(0,3) == "002") { firework.launch('Flow start scheduled. Start after round is completed', 'success', 5000); } else if (xhttp.responseText.substring(0,3) == "099") { firework.launch('Flow start triggered, but start not possible (no flow task available)', 'danger', 5000); }*/
}
}
xhttp.open("GET", url, true);
xhttp.send();
}
```
--------------------------------
### Start Backup Process
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/backup.html
Initiates the backup process by fetching the hostname, listing configuration files, and then zipping them for download. It uses XMLHttpRequest to communicate with the device's API.
```javascript
function startBackup() {
document.getElementById("progress").innerHTML = "Creating backup...
\n";
// Get hostname
try {
var xhttp = new XMLHttpRequest();
xhttp.open("GET", getDomainname() + "/info?type=Hostname", false);
xhttp.send();
hostname = xhttp.responseText;
} catch(err) {
setStatus("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
setStatus("Fetching File List...");
try {
var xhttp = new XMLHttpRequest();
xhttp.open("GET", getDomainname() + "/fileserver/config/", false);
xhttp.send();
var parser = new DOMParser();
var content = parser.parseFromString(xhttp.responseText, 'text/html');
} catch(err) {
setStatus("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(getDomainname() + url);
}
// Pack as zip and download
try {
backup(urls, zipFilename);
} catch(err) {
setStatus("Failed to zip files: " + err.message + "!");
return;
}
}
```
--------------------------------
### JavaScript Function to Abort Setup
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/edit_explain_7_abort.html
This JavaScript function prompts the user to confirm aborting the setup mode. If confirmed, it attempts to load configuration, update setup mode parameters, save the configuration, and then reboots the device to the regular web interface.
```javascript
function reboot() {
if (confirm("Do you want to abort the setup mode and switch to regular web interface?")) {
domainname = getDomainname();
if (!loadConfig(domainname)) {
firework.launch('Setup mode could not be deactivated! Please try again!', 'danger', 30000);
return;
}
ParseConfig();
param = getConfigParameters();
param["System"]["SetupMode"]["enabled"] = true;
param["System"]["SetupMode"]["value1"] = "false";
WriteConfigININew();
SaveConfigToServer(domainname);
var stringota = getDomainname() + "/reboot";
parent.location = stringota;
parent.location.href = stringota;
parent.location.assign(stringota);
parent.location.replace(stringota);
}
}
```
--------------------------------
### Initial Data Loading and Refresh Setup
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/graph.html
Initializes the data display by calling WriteModelFiles and WriteNumbers, then sets up a recurring refresh mechanism using setTimeout.
```javascript
WriteModelFiles();
WriteNumbers();
function Refresh() {
setTimeout (function() {
run();
Refresh();
}, 300000);
}
run();
Refresh();
```
--------------------------------
### Backup Utility Function
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/backup.html
A wrapper function that initiates the backup process by calling fetchFiles. It handles the initial setup and logging before starting the file fetching sequence.
```javascript
const backup = (urls, zipFilename) => {
if(!urls) return;
/* Testing */
/*len = urls.length; for (i = 0; i < len - 3; i++) { urls.pop(); }*/
console.log(urls);
urlIndex = 0;
setStatus("Fetching files...");
fetchFiles(urls, [], 0, 0, zipFilename);
};
```
--------------------------------
### Update UI for Setup Step 3 (Digit ROIs)
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/setup.html
This snippet updates the UI elements to display information and controls for the Digit ROIs setup step. It sets iframe sources, element styles, and button states.
```javascript
document.getElementById('explaincontent').style="height:45px;"
document.getElementById('explaincontent').scrolling="no"
document.getElementById('explaincontent').src = 'explain_3.html?v=$COMMIT_HASH';
document.getElementById("restart").disabled = false;
document.getElementById("previous").disabled = false;
document.getElementById("next").disabled = false;
document.getElementById("skip").disabled = false;
document.getElementById("progressBar").value = 3;
setupCompleted = false;
break;
```
--------------------------------
### JavaScript: Initialize Device Configuration and Refresh
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/overview.html
Initializes the device by getting the domain name and refreshing the display. It includes commented-out code for setting image max width, which is no longer used.
```javascript
function init(){ domainname = getDomainname(); // setImageMaxWidth(); // CamFrameSize was replaced by zoom - CamFrameSize is no longer needed/used for zoom Refresh(); }
```
--------------------------------
### Helper Function to Start Zip Export
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/data_export.html
A wrapper function to initiate the zip export process by calling fetchFiles. It handles cases where the URLs might be null.
```javascript
const startExportZip = (urls, zipFilename) => {
if(!urls) {
return;
}
console.log(urls);
urlIndex = 0;
setStatus("Fetching files...");
fetchFiles(urls, [], 0, 0, zipFilename);
};
```
--------------------------------
### Update UI for Setup Step 6 (Config Page)
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/setup.html
This snippet configures the UI for the configuration page. It sets the main content source, adjusts iframe and content heights (specifically for the explanation iframe), and updates progress and navigation controls.
```javascript
document.getElementById('maincontent').src = 'edit_config.html?v=$COMMIT_HASH#description';
document.getElementById('h_iframe_explain').style.display = "";
document.getElementById('h_iframe_explain').style="height:100px;"
document.getElementById('explaincontent').style="height:100px;"
document.getElementById('explaincontent').scrolling="no"
document.getElementById('explaincontent').src = 'explain_6.html?v=$COMMIT_HASH';
document.getElementById("restart").disabled = false;
document.getElementById("previous").disabled = false;
document.getElementById("next").disabled = false;
document.getElementById("skip").disabled = false;
document.getElementById("progressBar").value = 6;
setupCompleted = true;
break;
```
--------------------------------
### Initiate OTA Update
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/ota_page.html
Initiates the OTA update process by sending a GET request to the server. It constructs the URL with the file path and task parameters. This function is called when the user selects a file and is ready to proceed.
```javascript
function
update() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
if (this.responseText == "OK") {
firework.launch('Update completed!', 'success', 5000);
document.getElementById("file_selector").disabled = false;
document.getElementById("status").innerText = "Status: Update completed";
clearInterval(updateTimer);
} else if (this.responseText == "FAIL") {
firework.launch('Update failed, please try again!', 'danger', 30000);
clearInterval(updateTimer);
} else if (this.responseText == "BUSY") {
firework.launch('Device is busy, please try again later!', 'danger', 30000);
clearInterval(updateTimer);
}
} else if (this.readyState == 4) {
if (this.status == 404) {
firework.launch('File not found! Please check the file name.', 'danger', 30000);
} else {
firework.launch('An error occured: ' + this.statusText, 'danger', 30000);
}
clearInterval(updateTimer);
document.getElementById("status").innerText = "Status: Idle";
document.getElementById("file_selector").disabled = false;
}
};
var file_name = document.getElementById("file_selector").value;
filePath = file_name.split(/[/\\]/).pop();
var url = domainname + "/ota?task=update&file=" + filePath;
xhttp.open("GET", url, true);
xhttp.send();
}
```
--------------------------------
### JavaScript Initialization Function
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/prevalue_set.html
This function initializes the application by getting the domain name, loading configuration, parsing it, updating the number selection, and loading the initial prevalue. Call this function on page load.
```javascript
function init(){
domainname = getDomainname();
loadConfig(domainname);
ParseConfig();
UpdateNUMBERS();
loadPrevalue(domainname);
}
init();
```
--------------------------------
### Initiate Data Export
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/data_export.html
Starts the process of exporting data by zipping the contents of the data folder and initiating a download. It fetches the hostname and current date/time to create a unique filename for the zip archive.
```javascript
function startExportData() {
document.getElementById("progress").innerHTML = "Creating Export Data...
\n";
// Get hostname
try {
var xhttp = new XMLHttpRequest();
xhttp.open("GET", getDomainname() + "/info?type=Hostname", false);
xhttp.send();
hostname = xhttp.responseText;
} catch(err) {
setStatus("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 + "_csv" + ".zip";
console.log(zipFilename);
// Get files list
setStatus("Fetching File List...");
try {
var xhttp = new XMLHttpRequest();
xhttp.open("GET", getDomainname() + "/fileserver/log/data/", false);
xhttp.send();
var parser = new DOMParser();
var content = parser.parseFromString(xhttp.responseText, 'text/html');
} catch(err) {
setStatus("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(getDomainname() + url);
}
// Pack as zip and download
try {
startExportZip(urls, zipFilename);
} catch(err) {
setStatus("Failed to zip files: " + err.message + "!");
return;
}
}
```
--------------------------------
### Update UI for Setup Step 4 (Digit ROIs)
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/setup.html
This snippet configures the UI for the Digit ROIs editing step. It loads the relevant HTML, adjusts iframe heights, and updates progress indicators and button states.
```javascript
document.getElementById('maincontent').src = 'edit_digits.html?v=$COMMIT_HASH#description';
document.getElementById('h_iframe_explain').style.display = "";
document.getElementById('h_iframe_explain').style="height:45px;"
document.getElementById('explaincontent').style="height:45px;"
document.getElementById('explaincontent').scrolling="no"
document.getElementById('explaincontent').src = 'explain_4.html?v=$COMMIT_HASH';
document.getElementById("restart").disabled = false;
document.getElementById("previous").disabled = false;
document.getElementById("next").disabled = false;
document.getElementById("skip").disabled = false;
document.getElementById("progressBar").value = 4;
setupCompleted = false;
break;
```
--------------------------------
### Read and Write Configuration Parameters
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/edit_config_template.html
Demonstrates how to read and write configuration parameters using JavaScript functions. These functions are used to interact with various settings like post-processing options, database fields, and MQTT configurations.
```javascript
ReadParameter(param, "PostProcessing", "MaxRateType", true, NUNBERSAkt);
ReadParameter(param, "PostProcessing", "ExtendedResolution", false, NUNBERSAkt);
ReadParameter(param, "PostProcessing", "IgnoreLeadingNaN", false, NUNBERSAkt);
// ReadParameter(param, "PostProcessing", "IgnoreAllNaN", false, NUNBERSAkt);
ReadParameter(param, "PostProcessing", "AllowNegativeRates", false, NUNBERSAkt);
ReadParameter(param, "PostProcessing", "CheckDigitIncreaseConsistency", false, NUNBERSAkt);
ReadParameter(param, "InfluxDB", "Field", true, NUNBERSAkt);
ReadParameter(param, "InfluxDBv2", "Field", true, NUNBERSAkt);
ReadParameter(param, "InfluxDB", "Measurement", true, NUNBERSAkt);
ReadParameter(param, "InfluxDBv2", "Measurement", true, NUNBERSAkt);
ReadParameter(param, "MQTT", "DomoticzIDX", true, NUNBERSAkt);
// var sel = document.getElementById("Numbers_value1");
NUNBERSAkt = sel.selectedIndex;
// WriteParameter(param, category, "PostProcessing", "PreValueUse", false, NUNBERSAkt);
WriteParameter(param, category, "PostProcessing", "DecimalShift", true, NUNBERSAkt);
WriteParameter(param, category, "PostProcessing", "AnalogToDigitTransitionStart", true, NUNBERSAkt);
WriteParameter(param, category, "PostProcessing", "ChangeRateThreshold", true, NUNBERSAkt);
WriteParameter(param, category, "PostProcessing", "MaxRateValue", true, NUNBERSAkt);
WriteParameter(param, category, "PostProcessing", "MaxRateType", true, NUNBERSAkt);
WriteParameter(param, category, "PostProcessing", "ExtendedResolution", false, NUNBERSAkt);
WriteParameter(param, category, "PostProcessing", "IgnoreLeadingNaN", false, NUNBERSAkt);
// WriteParameter(param, category, "PostProcessing", "IgnoreAllNaN", false, NUNBERSAkt);
WriteParameter(param, category, "PostProcessing", "AllowNegativeRates", false, NUNBERSAkt);
WriteParameter(param, category, "PostProcessing", "CheckDigitIncreaseConsistency", false, NUNBERSAkt);
WriteParameter(param, category, "InfluxDB", "Field", true, NUNBERSAkt);
WriteParameter(param, category, "InfluxDBv2", "Field", true, NUNBERSAkt);
WriteParameter(param, category, "InfluxDB", "Measurement", true, NUNBERSAkt);
WriteParameter(param, category, "InfluxDBv2", "Measurement", true, NUNBERSAkt);
WriteParameter(param, category, "MQTT", "DomoticzIDX", true, NUNBERSAkt);
```
--------------------------------
### JavaScript Get Element Coordinates
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/edit_alignment.html
Calculates the cross-browser absolute position of an element relative to the document.
```javascript
function getCoords(elem) {
// crossbrowser version
var box = elem.getBoundingClientRect();
var body = document.body;
var docEl = document.documentElement;
var scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop;
var scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft;
var clientTop = docEl.clientTop || body.clientTop || 0;
var clientLeft = docEl.clientLeft || body.clientLeft || 0;
var top = box.top + scrollTop - clientTop;
var left = box.left + scrollLeft - clientLeft;
return { top: Math.round(top), left: Math.round(left) };
}
```
--------------------------------
### Reading Configuration Parameters
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/edit_config_template.html
This snippet demonstrates reading various configuration parameters for different services like MQTT, InfluxDB, Webhook, GPIO, and System settings. It also includes backward compatibility settings for older versions.
```javascript
ReadParameter(param, "MQTT", "ClientKey", true); ReadParameter(param, "MQTT", "ValidateServerCert", true); ReadParameter(param, "MQTT", "DomoticzTopicIn", true); ReadParameter(param, "InfluxDB", "Uri", true); ReadParameter(param, "InfluxDB", "Database", true); ReadParameter(param, "InfluxDB", "Measurement", true); ReadParameter(param, "InfluxDB", "user", true); ReadParameter(param, "InfluxDB", "password", true); ReadParameter(param, "InfluxDBv2", "Uri", true); ReadParameter(param, "InfluxDBv2", "Bucket", true); ReadParameter(param, "InfluxDBv2", "Measurement", true); ReadParameter(param, "InfluxDBv2", "Org", true); ReadParameter(param, "InfluxDBv2", "Token", true); // ReadParameter(param, "InfluxDB", "Field", true); ReadParameter(param, "Webhook", "Uri", true); ReadParameter(param, "Webhook", "ApiKey", true); ReadParameter(param, "Webhook", "UploadImg", false); ReadParameter(param, "GPIO", "IO0", true); ReadParameter(param, "GPIO", "IO1", true); ReadParameter(param, "GPIO", "IO3", true); ReadParameter(param, "GPIO", "IO4", true); ReadParameter(param, "GPIO", "IO12", true); ReadParameter(param, "GPIO", "IO13", true); ReadParameter(param, "GPIO", "LEDType", false); ReadParameter(param, "GPIO", "LEDNumbers", false); ReadParameter(param, "GPIO", "LEDColor", false); // Folgende Zeilen sind für Abwärtskompatibität < v9.0.0 notwendig (manchmal parameter auskommentiert) param["GPIO"]["LEDType"]["enabled"] = true; param["GPIO"]["LEDNumbers"]["enabled"] = true; param["GPIO"]["LEDColor"]["enabled"] = true; param["GPIO"]["LEDType"]["found"] = true; param["GPIO"]["LEDNumbers"]["found"] = true; param["GPIO"]["LEDColor"]["found"] = true; //ReadParameter(param, "AutoTimer", "AutoStart", false); ReadParameter(param, "AutoTimer", "Interval", false); ReadParameter(param, "DataLogging", "DataLogActive", false); ReadParameter(param, "DataLogging", "DataFilesRetention", false); ReadParameter(param, "Debug", "LogLevel", false); ReadParameter(param, "Debug", "LogfilesRetention", false); ReadParameter(param, "System", "Tooltip", false); ReadParameter(param, "System", "TimeZone", true); ReadParameter(param, "System", "Hostname", true); ReadParameter(param, "System", "TimeServer", true); ReadParameter(param, "System", "RSSIThreshold", true); ReadParameter(param, "System", "CPUFrequency", true);
```
--------------------------------
### Load Configuration and Initialize Parameters
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/edit_config_template.html
Loads the system configuration and initializes individual camera parameters. It updates UI elements and enables/disables camera zoom and sharpness controls based on the loaded configuration.
```javascript
function LoadConfigNeu() {
if (!loadConfig(domainname)) {
firework.launch('Configuration could not be loaded! Please reload the page!', 'danger', 30000);
return;
}
param = getCamConfig();
category = getConfigCategory();
InitIndivParameter();
UpdateInput();
var sel = document.getElementById("Numbers_value1");
UpdateInputIndividual(sel);
UpdateExpertModus();
UpdateTooltipModus();
document.getElementById("divall").style.display = '';
if(!document.getElementById("TakeImage_CamZoom_value1").selectedIndex) {
// EnDisableItem(_status, _param, _category, _cat, _name, _optional, _number = -1)
EnDisableItem(true, param, category, "TakeImage", "CamZoomOffsetX", false);
EnDisableItem(true, param, category, "TakeImage", "CamZoomOffsetY", false);
EnDisableItem(true, param, category, "TakeImage", "CamZoomSize", false);
} else {
EnDisableItem(false, param, category, "TakeImage", "CamZoomOffsetX", false);
EnDisableItem(false, param, category, "TakeImage", "CamZoomOffsetY", false);
EnDisableItem(false, param, category, "TakeImage", "CamZoomSize", false);
}
if(document.getElementById("TakeImage_CamAutoSharpness_value1").selectedIndex) {
EnDisableItem(true, param, category, "TakeImage", "CamSharpness", false);
} else {
EnDisableItem(false, param, category, "TakeImage", "CamSharpness", false);
}
}
```
--------------------------------
### Mouse Down Event Handler
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/edit_alignment.html
Handles the mousedown event on the canvas to record the starting coordinates for drawing a rectangle.
```javascript
function mouseDown(e) {
var zw = getCoords(this)
rect.startX = e.pageX - zw.left;
rect.startY = e.pageY - zw.top;
document.getElementById("refx").value = rect.startX;
document.getElementById("refy").value = rect.startY;
drag = true;
}
```
--------------------------------
### Get Element Coordinates
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/edit_reference.html
Calculates the bounding box and scroll offsets for an element to determine its position on the page.
```javascript
function getCoords(elem) { // crossbrowser version var box = elem.getBoundingClientRect(); var body = document.body; var docEl = document.documentElement; var scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop; var scrollLeft = window.pageXOffset || docEl.scrollLeft ||
```
--------------------------------
### Initialize Web UI and Load Versions
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/index.html
Loads hostname, firmware version, and web UI version. Sets the default page cookie if none exists and loads the main content frame.
```javascript
LoadHostname();
LoadFwVersion();
LoadWebUiVersion();
HA_send_discovery_visibility();
if (getCookie("page") == "" || getCookie("page") == "reboot_page.html?v=$COMMIT_HASH") {
document.cookie = "page=overview.html?v=$COMMIT_HASH" + "; path=/";
}
console.log("Loading page: " + getCookie("page"));
document.getElementById('maincontent').src = getCookie("page");
```
--------------------------------
### Handle Mouse Down Event for Region Selection
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/edit_analog.html
Initiates the drawing or resizing of a region when the mouse button is pressed. Records the starting coordinates and sets the drag flag.
```javascript
function mouseDown(e) {
zw = getCoords(this)
rect.startX = e.pageX - zw.left;
rect.startY = e.pageY - zw.top;
if (drawFromCenter) {
rect.centerX = rect.startX;
rect.centerY = rect.startY;
}
document.getElementById("refx").value = rect.startX;
document.getElementById("refy").value = rect.startY;
drag = true;
}
```
--------------------------------
### Initialize Application and Event Listeners
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/edit_digits.html
Initializes the application by opening the description, loading configuration, parsing parameters, and attaching mouse event listeners to the canvas. It also performs checks on ROI equidistance and synchronicity.
```javascript
function init() {
openDescription();
domainname = getDomainname();
if (!loadConfig(domainname)) {
firework.launch('Configuration could not be loaded! Please reload the page!', 'danger', 30000);
return;
}
ParseConfig();
param = getConfigParameters();
cofcat = getConfigCategory();
canvas.addEventListener('mousedown', mouseDown, false);
canvas.addEventListener('mouseup', mouseUp, false);
canvas.addEventListener('mousemove', mouseMove, false);
loadCanvas(domainname + "/fileserver/config/reference.jpg");
UpdateNUMBERS();
/* 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 ..
}
```
--------------------------------
### Load and Initialize Reference Image Settings
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/edit_reference.html
Loads a reference image from a URL and initializes various camera parameters and UI elements. It sets initial rotation values, enables/disables specific input fields, and updates the UI state based on reference image settings.
```javascript
function showReference(){
url = domainname + "/fileserver/config/reference.jpg" + "?session=" + Math.floor((Math.random() * 1000000) + 1);
loadCanvas(url, false);
isActReference = true;
var _rotate_temp = param["Alignment"]["InitialRotate"].value1;
if (_rotate_temp < 0) {
document.getElementById("PreRotateAngle_value1").value = Math.ceil(_rotate_temp);
} else {
document.getElementById("PreRotateAngle_value1").value = Math.floor(_rotate_temp);
}
document.getElementById("FineRotate_value1").value = (Number(_rotate_temp) - Number(document.getElementById("PreRotateAngle_value1").value)).toFixed(1);
WriteParameter(param, category, "TakeImage", "CamBrightness", false, true);
WriteParameter(param, category, "TakeImage", "CamContrast", false, true);
WriteParameter(param, category, "TakeImage", "CamSaturation", false, true);
WriteParameter(param, category, "TakeImage", "CamSharpness", false, true);
WriteParameter(param, category, "TakeImage", "CamAutoSharpness", false);
WriteParameter(param, category, "TakeImage", "CamZoom", false);
WriteParameter(param, category, "TakeImage", "CamZoomOffsetX", false);
WriteParameter(param, category, "TakeImage", "CamZoomOffsetY", false);
WriteParameter(param, category, "TakeImage", "CamZoomSize", false);
WriteParameter(param, category, "TakeImage", "CamAec", false);
WriteParameter(param, category, "TakeImage", "CamAec2", false);
WriteParameter(param, category, "TakeImage", "CamAeLevel", false, true);
WriteParameter(param, category, "TakeImage", "CamHmirror", false);
WriteParameter(param, category, "TakeImage", "CamVflip", false);
WriteParameter(param, category, "TakeImage", "CamSpecialEffect", false);
WriteParameter(param, category, "TakeImage", "LEDIntensity", false);
EnDisableItem(false, param, category, "TakeImage", "CamBrightness", false);
EnDisableItem(false, param, category, "TakeImage", "CamSaturation", false);
EnDisableItem(false, param, category, "TakeImage", "CamContrast", false);
EnDisableItem(false, param, category, "TakeImage", "CamSharpness", false);
EnDisableItem(false, param, category, "TakeImage", "CamAutoSharpness", false);
EnDisableItem(false, param, category, "TakeImage", "CamZoom", false);
EnDisableItem(false, param, category, "TakeImage", "CamZoomOffsetX", false);
EnDisableItem(false, param, category, "TakeImage", "CamZoomOffsetY", false);
EnDisableItem(false, param, category, "TakeImage", "CamZoomSize", false);
EnDisableItem(false, param, category, "TakeImage", "CamAec", false);
EnDisableItem(false, param, category, "TakeImage", "CamAec2", false);
EnDisableItem(false, param, category, "TakeImage", "CamAeLevel", false);
EnDisableItem(false, param, category, "TakeImage", "CamHmirror", false);
EnDisableItem(false, param, category, "TakeImage", "CamVflip", false);
EnDisableItem(false, param, category, "TakeImage", "CamSpecialEffect", false);
EnDisableItem(false, param, category, "TakeImage", "LEDIntensity", false);
document.getElementById("ExpertModus_enabled").disabled = true;
document.getElementById("FineRotate_value1").disabled = true;
document.getElementById("FineRotate_text").style.color = "rgb(122, 122, 122)";
document.getElementById("PreRotateAngle_value1").disabled = true;
document.getElementById("PreRotateAngle_text").style.color = "rgb(122, 122, 122)";
document.getElementById("savereferenceimage").disabled = true;
document.getElementById("updatereferenceimage").disabled = true;
document.getElementById("showcurrentreference").disabled = true;
document.getElementById("startreference").disabled = false;
}
```
--------------------------------
### Get URL Parameter by Name
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/edit_config_template.html
Extracts a URL parameter's value from a given URL. Handles URL encoding and special characters in parameter names.
```javascript
function getParameterByName(name, url = window.location.href) {
name = name.replace(/[\[\]]/g, '\$&');
var regex = new RegExp('[\]' + name + '(=([^]*)|\]|#|$)'),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, ' '));
}
```
--------------------------------
### Handling Mouse Down Event for ROI Selection
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/edit_digits.html
Captures the starting coordinates of a mouse drag operation to initiate ROI selection or modification. Updates input fields with initial values.
```javascript
function mouseDown(e) { zw = getCoords(this) rect.startX = e.pageX - zw.left; rect.startY = e.pageY - zw.top; document.getElementById("refx").value = rect.startX; document.getElementById("refy").value = rect.startY; drag = true; }
```
--------------------------------
### Handling Mouse Up Event to Finalize ROI Dimensions
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/edit_digits.html
Finalizes the ROI dimensions after a drag operation, ensuring width and height are positive. Updates input fields with the final dimensions and starting coordinates.
```javascript
function mouseUp() { drag = false; if (rect.w < 0) { rect.w = -rect.w rect.startX-=rect.w } if (rect.h < 0) { rect.h = -rect.h rect.startY-=rect.h } document.getElementById("refdx").value = rect.w; document.getElementById("refdy").value = rect.h; document.getElementById("refx").value = rect.startX; document.getElementById("refy").value = rect.startY; }
```
--------------------------------
### Compile Firmware
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/code/README.md
Command to compile the project for the esp32cam environment using PlatformIO.
```bash
cd code
platformio run --environment esp32cam
```
--------------------------------
### Load Firmware Build Time
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/info.html
Fetches and displays the firmware build time. Expects the response in 'YYYY-MM-DD HH:MM' format and reformats it to 'DD.MM.YYYY HH:MM'.
```javascript
function loadFWBuildTime() {
url = getDomainname() + '/info?type=BuildTime';
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
// Input format: 2023-04-02 10:56
var timestamp = xhttp.response.substr(8,2) + "." + xhttp.response.substr(5,2) + "." + xhttp.response.substr(0,4) + " " + xhttp.response.substr(11,2) + ":" + xhttp.response.substr(14,2);
document.getElementById("build-time").value = timestamp;
}
}
xhttp.open("GET", url, true);
xhttp.send();
}
```
--------------------------------
### Page Initialization
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/sd-card/html/edit_analog.html
Initializes the page by opening the description, loading configuration, parsing parameters, and setting up canvas event listeners. It also checks if all ROIs have identical dimensions and updates the UI accordingly.
```javascript
function init() { openDescription(); domainname = getDomainname(); if (!loadConfig(domainname)) { firework.launch('Configuration could not be loaded! Please reload the page!', 'danger', 30000); return; } ParseConfig(); param = getConfigParameters(); cofcat = getConfigCategory(); canvas.addEventListener('mousedown', mouseDown, false); canvas.addEventListener('mouseup', mouseUp, false); canvas.addEventListener('mousemove', mouseMove, false); loadCanvas(domainname + "/fileserver/config/reference.jpg"); 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!"); } document.getElementById("saveroi").disabled = true; drawImage(); draw(); }
```
--------------------------------
### Adding Extra Component Directories in CMake
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/code/components/jomjol_controlcamera/CMakeLists.txt
This command appends a specific directory path, likely containing common protocol examples, to the EXTRA_COMPONENT_DIRS list. This is useful for including shared components in the build.
```cmake
list(APPEND EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
```
--------------------------------
### Get Git Revision and Build Time
Source: https://github.com/jomjol/ai-on-the-edge-device/blob/main/code/main/CMakeLists.txt
Executes git commands to retrieve the commit revision, diff status, tag, and branch. Also captures the build timestamp. This information is used for versioning the build.
```cmake
execute_process(COMMAND git log --pretty=format:'%h' -n 1
OUTPUT_VARIABLE GIT_REV
ERROR_QUIET)
string(TIMESTAMP BUILD_TIME "%Y-%m-%d %H:%M")
```