mirror of
https://github.com/jomjol/AI-on-the-edge-device.git
synced 2025-12-06 03:26:53 +03:00
v 0.1.0
This commit is contained in:
16
README.md
16
README.md
@@ -1 +1,17 @@
|
||||
# AI-on-the-edge-device
|
||||
|
||||
This is an example of Artificial Intelligence (AI) calculations on a very cheap hardware.
|
||||
|
||||
Details can be found on the Wiki pages.
|
||||
|
||||
## Changelog - lastest version
|
||||
|
||||
##### 0.1.0 (2020-08-07)
|
||||
|
||||
* Inital Version
|
||||
|
||||
|
||||
|
||||
## Know-Bugs
|
||||
|
||||
* spontaneous reboot, especially in case of intensive web server access
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 142 KiB After Width: | Height: | Size: 142 KiB |
@@ -12,7 +12,7 @@ SearchFieldX = 20
|
||||
SearchFieldY = 20
|
||||
|
||||
[Digits]
|
||||
Model=/config/digits.tfl
|
||||
Model=/config/dig0622.tfl
|
||||
ModelInputSize 20, 32
|
||||
LogImageLocation = /log/digit
|
||||
digit1, 291, 97, 37, 67
|
||||
@@ -20,7 +20,7 @@ digit2, 344, 97, 37, 67
|
||||
digit3, 394, 97, 37, 67
|
||||
|
||||
[Analog]
|
||||
Model=/config/analog.tfl
|
||||
Model=/config/ana0622.tfl
|
||||
ModelInputSize 32, 32
|
||||
LogImageLocation = /log/analog
|
||||
analog1, 433, 207, 99, 99
|
||||
@@ -35,8 +35,9 @@ AllowNegativeRates = False
|
||||
MaxRateValue = 0.1
|
||||
ErrorMessage = True
|
||||
|
||||
|
||||
[AutoTimer]
|
||||
AutoStart= true
|
||||
AutoStart= True
|
||||
Intervall = 4.85
|
||||
|
||||
[Ende]
|
||||
127
sd-card/html/index.html
Normal file
127
sd-card/html/index.html
Normal file
@@ -0,0 +1,127 @@
|
||||
<html><head>
|
||||
<title>jomjol - AI on the edge</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style type="text/css" media="screen">
|
||||
nav > ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
nav li {
|
||||
margin: 0.5em;
|
||||
padding: 0;
|
||||
font-size: 1.5em;
|
||||
flex: 1 1 0%;
|
||||
}
|
||||
|
||||
@media (min-width: 45em) {
|
||||
nav > ul {
|
||||
flex-direction: row;
|
||||
}
|
||||
nav li {
|
||||
flex: 1;
|
||||
font-size: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
nav a {
|
||||
display: block;
|
||||
padding: 0.4em;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
border: 1px solid darkblue;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 5px 10px white inset;
|
||||
color: gold;
|
||||
background-color: darkblue;
|
||||
transition: all .25s ease-in;
|
||||
}
|
||||
|
||||
nav li[aria-current] a {
|
||||
background-color: firebrick;
|
||||
color: gold;
|
||||
}
|
||||
|
||||
nav a:focus,
|
||||
nav a:hover,
|
||||
nav li[aria-current] a:focus,
|
||||
nav li[aria-current] a:hover {
|
||||
color: darkblue;
|
||||
background-color: gold;
|
||||
}
|
||||
|
||||
|
||||
html, body {
|
||||
height:100%;
|
||||
width:100%;
|
||||
margin:0;
|
||||
}
|
||||
.h_iframe iframe {
|
||||
width:100%;
|
||||
height:100%;
|
||||
}
|
||||
.h_iframe {
|
||||
height: 100%;
|
||||
width:100%;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
//]]>
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>AI on the edge - an integrated water meter example</h1>
|
||||
<nav>
|
||||
<ul>
|
||||
<li aria-current="page"><a href="#"onclick="document.getElementById('maincontent').src = '/wasserzaehler_roi.html';">wasserzaehler</a>
|
||||
<ul class="submenu">
|
||||
<li><a href="#"onclick="document.getElementById('maincontent').src = '/prevalue_set.html';">PreValue</a> </li>
|
||||
<li><a href="#"onclick="document.getElementById('maincontent').src = '/wasserzaehler.html?full';">wasserzaehler full</a> </li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="#" onclick="document.getElementById('maincontent').src = '/fileserver/';">File Server</a> </li>
|
||||
<li><a href="#">Manuel Mode</a>
|
||||
<ul class="submenu">
|
||||
<li><a href="#"onclick="document.getElementById('maincontent').src = '/doinit';">Init</a> </li>
|
||||
<li><a href="#"onclick="document.getElementById('maincontent').src = '/doflow';">Recognize</a> </li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><a href="#">Image</a>
|
||||
<ul class="submenu">
|
||||
<li><a href="#"onclick="document.getElementById('maincontent').src = '/img_tmp/raw.jpg';">Raw</a> </li>
|
||||
<li><a href="#"onclick="document.getElementById('maincontent').src = '/img_tmp/rot.jpg';">Rotated</a> </li>
|
||||
<li><a href="#"onclick="document.getElementById('maincontent').src = '/img_tmp/alg.jpg';">Aligned</a> </li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#">System</a>
|
||||
<ul class="submenu">
|
||||
<li><a href="#"onclick="document.getElementById('maincontent').src = '/starttime';">Start time</a> </li>
|
||||
<li><a href="#"onclick="document.getElementById('maincontent').src = '/ota_page.html';">OTA Update</a> </li>
|
||||
<li><a href="#"onclick="document.getElementById('maincontent').src = '/reboot_page.html';">Reboot</a> </li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<p>
|
||||
|
||||
<div class="h_iframe">
|
||||
<iframe name="maincontent" id ="maincontent" src="/wasserzaehler_roi.html" title="fileserver" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</body></html>
|
||||
129
sd-card/html/ota_page.html
Normal file
129
sd-card/html/ota_page.html
Normal file
@@ -0,0 +1,129 @@
|
||||
<html><head>
|
||||
<title>jomjol - AI on the edge</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
//]]>
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table class="fixed" border="0">
|
||||
<td>
|
||||
<table border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<label for="newfile">Upload the firmware.bin</label>
|
||||
</td>
|
||||
<td colspan="2">
|
||||
<input id="newfile" type="file" onchange="setpath()" style="width:100%;">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="filepath">Set path on server</label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="filepath" type="text" style="width:100%;" readonly>
|
||||
</td>
|
||||
<td>
|
||||
<button id="upload" type="button" onclick="upload()">Upload</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td>
|
||||
<button id="upload" type="button" onclick="doUpdate()">Do Firmware Update</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<script>
|
||||
function doUpdate() {
|
||||
if (confirm("Are you sure to update the firmware?")) {
|
||||
var stringota = "/ota?file=firmware.bin";
|
||||
window.location = stringota;
|
||||
window.location.href = stringota;
|
||||
window.location.assign(stringota);
|
||||
window.location.replace(stringota);
|
||||
}
|
||||
}
|
||||
|
||||
function setpath() {
|
||||
var fileserverpraefix = "/firmware/firmware.bin";
|
||||
document.getElementById("filepath").value = fileserverpraefix;
|
||||
}
|
||||
|
||||
function upload() {
|
||||
var xhttp = new XMLHttpRequest();
|
||||
|
||||
/* 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!");
|
||||
location.reload()
|
||||
} else {
|
||||
alert(xhttp.status + " Error!\n" + xhttp.responseText);
|
||||
location.reload()
|
||||
}
|
||||
}
|
||||
};
|
||||
xhttp.open("GET", "/ota?delete=firmware.bin", false);
|
||||
xhttp.send();
|
||||
/* ----------------------------- */
|
||||
|
||||
var filePath = document.getElementById("filepath").value;
|
||||
var upload_path = "/upload/" + filePath;
|
||||
var fileInput = document.getElementById("newfile").files;
|
||||
|
||||
/* Max size of an individual file. Make sure this
|
||||
* value is same as that set in file_server.c */
|
||||
var MAX_FILE_SIZE = 2000*1024;
|
||||
var MAX_FILE_SIZE_STR = "2000KB";
|
||||
|
||||
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 > 2000*1024) {
|
||||
alert("File size must be less than 2000KB!");
|
||||
} 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();
|
||||
} else if (xhttp.status == 0) {
|
||||
alert("Server closed the connection abruptly!");
|
||||
location.reload()
|
||||
} else {
|
||||
alert(xhttp.status + " Error!\n" + xhttp.responseText);
|
||||
location.reload()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var file = fileInput[0];
|
||||
xhttp.open("POST", upload_path, true);
|
||||
xhttp.send(file);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
</body></html>
|
||||
43
sd-card/html/prevalue_set.html
Normal file
43
sd-card/html/prevalue_set.html
Normal file
@@ -0,0 +1,43 @@
|
||||
<html><head>
|
||||
<title>jomjol - AI on the edge</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
//]]>
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table style="width:100%">
|
||||
<tr>
|
||||
Current Value:<p>
|
||||
<iframe name="currentvalue" id ="currentvalue" src="/setPreValue.html" title="fileserver" allowfullscreen></iframe>
|
||||
</tr>
|
||||
<tr>
|
||||
Input (Format = 123.456):<p>
|
||||
PreValue:
|
||||
<input type="number" id="myInput" name="myInput"
|
||||
pattern="[0-9]+([\.,][0-9]+)?" step="0.001"
|
||||
title="This should be a number with up to 4 decimal places.">
|
||||
<button type="button" onclick="setprevalue()">Set PreValue</button>
|
||||
</tr>
|
||||
<tr>
|
||||
Result:<p>
|
||||
<iframe name="maincontent" id ="maincontent" src="" title="fileserver" allowfullscreen></iframe>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<script>
|
||||
function setprevalue() {
|
||||
var inputVal = document.getElementById("myInput").value;
|
||||
inputVal = inputVal.replace(",", ".");
|
||||
_value = "/setPreValue.html?value="+inputVal;
|
||||
document.getElementById('maincontent').src = _value;
|
||||
location.reload();
|
||||
}
|
||||
</script>
|
||||
|
||||
</body></html>
|
||||
34
sd-card/html/reboot_page.html
Normal file
34
sd-card/html/reboot_page.html
Normal file
@@ -0,0 +1,34 @@
|
||||
<html><head>
|
||||
<title>jomjol - AI on the edge</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
//]]>
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table class="fixed" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<button id="reboot" type="button" onclick="doReboot()">Reboot</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<script>
|
||||
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);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
</body></html>
|
||||
101
sd-card/html/upload_script.html
Normal file
101
sd-card/html/upload_script.html
Normal file
@@ -0,0 +1,101 @@
|
||||
<table class="fixed" border="0">
|
||||
<col width="300px" /><col width="200px" />
|
||||
<tr><td>
|
||||
<h2>ESP32 File Server</h2>
|
||||
</td><td>
|
||||
<button id="dirup" type="button" onclick="dirup()">Directory up</button>
|
||||
</td>
|
||||
<td>
|
||||
<table border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<label for="newfile">Upload a file</label>
|
||||
</td>
|
||||
<td colspan="2">
|
||||
<input id="newfile" type="file" onchange="setpath()" style="width:100%;">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="filepath">Set path on server</label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="filepath" type="text" style="width:100%;">
|
||||
</td>
|
||||
<td>
|
||||
<button id="upload" type="button" onclick="upload()">Upload</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td></tr>
|
||||
</table>
|
||||
<script>
|
||||
function setpath() {
|
||||
var fileserverpraefix = "/fileserver";
|
||||
var anz_zeichen_fileserver = fileserverpraefix.length;
|
||||
var default_path = window.location.pathname.substring(anz_zeichen_fileserver) + document.getElementById("newfile").files[0].name;
|
||||
document.getElementById("filepath").value = default_path;
|
||||
}
|
||||
|
||||
function dirup() {
|
||||
var str = window.location.href;
|
||||
str = str.substring(0, str.length-1);
|
||||
var zw = str.indexOf("/");
|
||||
var found = zw;
|
||||
while (zw >= 0)
|
||||
{
|
||||
zw = str.indexOf("/", found+1);
|
||||
if (zw >= 0)
|
||||
found = zw;
|
||||
}
|
||||
var res = str.substring(0, found+1);
|
||||
window.location.href = res;
|
||||
}
|
||||
|
||||
function upload() {
|
||||
var filePath = document.getElementById("filepath").value;
|
||||
var upload_path = "/upload/" + filePath;
|
||||
var fileInput = document.getElementById("newfile").files;
|
||||
|
||||
/* Max size of an individual file. Make sure this
|
||||
* value is same as that set in file_server.c */
|
||||
var MAX_FILE_SIZE = 2000*1024;
|
||||
var MAX_FILE_SIZE_STR = "2000KB";
|
||||
|
||||
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 > 2000*1024) {
|
||||
alert("File size must be less than 2000KB!");
|
||||
} else {
|
||||
document.getElementById("newfile").disabled = true;
|
||||
document.getElementById("filepath").disabled = true;
|
||||
document.getElementById("upload").disabled = true;
|
||||
|
||||
var file = fileInput[0];
|
||||
var xhttp = new XMLHttpRequest();
|
||||
xhttp.onreadystatechange = function() {
|
||||
if (xhttp.readyState == 4) {
|
||||
if (xhttp.status == 200) {
|
||||
document.open();
|
||||
document.write(xhttp.responseText);
|
||||
document.close();
|
||||
} else if (xhttp.status == 0) {
|
||||
alert("Server closed the connection abruptly!");
|
||||
location.reload()
|
||||
} else {
|
||||
alert(xhttp.status + " Error!\n" + xhttp.responseText);
|
||||
location.reload()
|
||||
}
|
||||
}
|
||||
};
|
||||
xhttp.open("POST", upload_path, true);
|
||||
xhttp.send(file);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
99
sd-card/html/wasserzaehler_roi.html
Normal file
99
sd-card/html/wasserzaehler_roi.html
Normal file
@@ -0,0 +1,99 @@
|
||||
<html><head>
|
||||
<title>jomjol - AI on the edge</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style type="text/css" media="screen">
|
||||
nav > ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
nav li {
|
||||
margin: 0.5em;
|
||||
padding: 0;
|
||||
font-size: 1.5em;
|
||||
flex: 1 1 0%;
|
||||
}
|
||||
|
||||
@media (min-width: 45em) {
|
||||
nav > ul {
|
||||
flex-direction: row;
|
||||
}
|
||||
nav li {
|
||||
flex: 1;
|
||||
font-size: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
nav a {
|
||||
display: block;
|
||||
padding: 0.4em;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
border: 1px solid darkblue;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 5px 10px white inset;
|
||||
color: gold;
|
||||
background-color: darkblue;
|
||||
transition: all .25s ease-in;
|
||||
}
|
||||
|
||||
nav li[aria-current] a {
|
||||
background-color: firebrick;
|
||||
color: gold;
|
||||
}
|
||||
|
||||
nav a:focus,
|
||||
nav a:hover,
|
||||
nav li[aria-current] a:focus,
|
||||
nav li[aria-current] a:hover {
|
||||
color: darkblue;
|
||||
background-color: gold;
|
||||
}
|
||||
|
||||
|
||||
html, body {
|
||||
height:100%;
|
||||
width:100%;
|
||||
margin:0;
|
||||
}
|
||||
.h_iframe iframe {
|
||||
width:100%;
|
||||
height:100%;
|
||||
}
|
||||
.h_iframe {
|
||||
height: 100%;
|
||||
width:100%;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
//]]>
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table style="width:100%">
|
||||
<tr>
|
||||
<td> <img src="/img_tmp/alg_roi.jpg" alt="ROI-Image"> </td>
|
||||
<td>
|
||||
<table>
|
||||
<tr>
|
||||
Raw Value:<p>
|
||||
<iframe name="maincontent" id ="maincontent" src="/wasserzaehler.html?rawvalue=true" title="fileserver" allowfullscreen></iframe>
|
||||
</tr>
|
||||
<tr>
|
||||
Corrected Value:<p>
|
||||
<iframe name="maincontent" id ="maincontent" src="/wasserzaehler.html" title="fileserver" allowfullscreen></iframe>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</body></html>
|
||||
Reference in New Issue
Block a user