Compare commits

...

4 Commits

43 changed files with 18097 additions and 4446 deletions

View File

@ -3,198 +3,453 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>%DEVICE_NAME%</title> <title>%DEVICENAME%</title>
<meta http-equiv="content-type" content="text/html;charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="static/css/bootstrap.min.css"> <link rel="stylesheet" href="static/css/bootstrap.min.css">
<link rel="stylesheet" href="static/css/custom.css"> <link rel="stylesheet" href="static/css/custom.css">
<script src="static/js/jquery-3.3.1.min.js"></script> <link rel="stylesheet" href="static/css/tweaks.css">
<script src="static/js/bootstrap.bundle.min.js"></script> <script src="static/js/jquery.min.js"></script>
<script src="static/js/bootstrap.min.js"></script>
<script src="static/js/websocket.js"></script>
<link rel="apple-touch-icon" sizes="180x180" href="static/img/apple-touch-icon.png"> <link rel="apple-touch-icon" sizes="180x180" href="static/img/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="static/img/favicon-32x32.png"> <link rel="icon" type="image/png" sizes="32x32" href="static/img/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="static/img/favicon-16x16.png"> <link rel="icon" type="image/png" sizes="16x16" href="static/img/favicon-16x16.png">
<link rel="manifest" href="static/img/site.webmanifest"> <link rel="manifest" href="static/img/site.webmanifest">
<link rel="mask-icon" href="static/img/safari-pinned-tab.svg" color="#111111">
<link rel="shortcut icon" href="static/img/favicon.ico">
<meta name="msapplication-TileColor" content="#111111">
<meta name="msapplication-config" content="static/img/browserconfig.xml">
<meta name="theme-color" content="#111111">
<script type="text/javascript">
var opacity = 0;
var intervalID = 0;
window.onload = setTimeout(() => { fadeout(); }, 4000);
function fadeout() {
intervalID = setInterval(hide, 200);
}
function hide() {
var responseMessage = document.getElementById("responseMessage");
opacity =
Number(window.getComputedStyle(responseMessage).getPropertyValue("opacity"))
if (opacity > 0) {
opacity = opacity - 0.1;
responseMessage.style.opacity = opacity
}
else {
responseMessage.remove()
clearInterval(intervalID);
}
}
</script>
</head> </head>
<body> <body>
<header class="sticky-top">
<nav class="navbar navbar-expand-sm navbar-dark bg-dark">
<a class="navbar-brand" href="#"> <nav class="navbar fixed-top navbar-dark bg-primary" id="navbar1">
<img src="static/img/logo.png" width="30" height="30" class="d-inline-block align-top" alt=""> <a class="navbar-brand" href="#">
%DEVICE_NAME%</a> <img src="static/img/logo.png" width="30" height="30" class="d-inline-block align-top mr-1" alt="">
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" %DEVICENAME%
aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation"> </a>
<span class="navbar-toggler-icon"></span> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#collapsingNavbar"
</button> aria-controls="collapsingNavbar" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="collapsingNavbar">
<ul class="navbar-nav nav mr-auto mt-2 mt-lg-0">
<div class="collapse navbar-collapse pr-2 mt-2 bg-secondary" id="navbarNavAltMarkup"> <li class="nav-item"><a class="nav-link active" role="tab" data-toggle="tab" href="#tab_home">Home</a></li>
<ul class="navbar-nav nav align-items-end"> <li class="nav-item"><a class="nav-link" role="tab" data-toggle="tab" href="#tab_maintenance">Wartung</a></li>
<li class="nav-item"> <li class="nav-item"><a class="nav-link" role="tab" data-toggle="tab" href="#tab_source">Einstellungen</a></li>
<a class="nav-link active" href="#tab_home" data-toggle="tab">Home</a> <li class="nav-item"><a class="nav-link" role="tab" data-toggle="tab" href="#tab_sysinfo">Systeminfo</a></li>
</li> <li class="nav-item"><a class="nav-link" role="tab" data-toggle="tab" href="#tab_fwupdate">Update</a></li>
<li class="nav-item">
<a class="nav-link" href="#tab_settings" data-toggle="tab">Settings</a> </ul>
</li> </div>
</ul> </nav>
</div>
</nav> <main class="container">
</header>
<main class="container-fluid py-3 flex-fill">
<!-- Tabs Content --> <!-- Tabs Content -->
<div class="tab-content"> <div class="tab-content">
<!-- Div Tab Home--> <!-- Div Tab Home-->
<div class="tab-pane fade show active" id="tab_home" role="tabpanel"> <div id="tab_home" class="tab-pane fade show active" role="tabpanel">
<!-- Jumbotron --> <div class="col text-center">
<div class="jumbotron text-center"> <div class="jumbotron">
<p class="p-4"> <img src="static/img/logo.png" width="120" height="120" class="img-fluid" alt="">
<img src="static/img/logo.png"> <h3 class="pt-3">%DEVICENAME%</h3>
</p>
<h3>%DEVICE_NAME%</h3>
</div>
<!-- AlertMessageBox-->
<div id="responseMessage" class="alert alert-%RESP_MESSAGE_TYPE%" %SHOW_RESP_MESSAGE%>
%RESP_MESSAGE%
</div>
<div class="container-fluid pb-5">
<h4>BATTERY: %BATTERY_TYPE%</h4>
<div class="progress">
<div class="progress-bar text-light" role="progressbar" aria-valuenow="%BAT_REMAIN_CAPACITY%"
aria-valuemin="0" aria-valuemax="100" style="width: %BAT_REMAIN_CAPACITY%&#37;">
%BAT_REMAIN_CAPACITY%&#37; / %BAT_VOLTAGE% V
</div>
</div> </div>
</div> </div>
<div class="container-fluid pb-5"> <!-- Div Group Battery remain -->
<h4>FACTIONS</h4> <hr />
<div class="table-responsive"> <p>
<table class="table text-light text-center"> <h4>Akku Ladestand</h4>
<thead> <div class="progress">
<tr> <div class="progress-bar text-light" role="progressbar" aria-valuenow="%BAT_REMAIN_CAPACITY%"
<th scope="col">Faction</td> aria-valuemin="0" aria-valuemax="100" style="width: %BAT_REMAIN_CAPACITY%&#37;">
<th scope="col">Time</td> %BAT_REMAIN_CAPACITY%&#37;
</tr>
</thead>
<tbody>
<tr>
<td class="align-items-center justify-content-center" scope="col">
<a href="#">
<img src="static/img/logo_fac1.png" class="img-responsive" alt="" />
<div class="desc">
<p class="desc_content">%NAME_FAC_1%</p>
</div>
</a>
</td>
<td class="align-items-center justify-content-center" scope="col">%POINTS_FAC_1%</td>
</tr>
<tr>
<td class="align-items-center justify-content-center" scope="col">
<a href="#">
<img src="static/img/logo_fac2.png" class="img-responsive" alt="" />
<div class="desc">
<p class="desc_content">%NAME_FAC_2%</p>
</div>
</a>
</td>
<td class="align-items-center justify-content-center" scope="col">%POINTS_FAC_2%</td>
</tr>
<tr>
<td class="align-items-center justify-content-center" scope="col">
<a href="#">
<img src="static/img/logo_fac3.png" class="img-responsive" alt="" />
<div class="desc">
<p class="desc_content">%NAME_FAC_3%</p>
</div>
</a>
</td>
<td class="align-items-center justify-content-center" scope="col">%POINTS_FAC_3%</td>
</tr>
</tbody>
</table>
</div> </div>
</div> </div>
<div class="container-fluid pb-5" %SHOW_DTC_TABLE%> </p>
<!-- Div Group Battery remain -->
<!-- Div Group current Mode -->
<hr />
<p>
<h4>aktueller Modus</h4>
<input class="form-control" type="text" placeholder="%SYSTEM_STATUS%" readonly>
</p>
<!-- Div Group current Mode -->
<!-- Div Group DTC Table -->
<div %SHOW_DTC_TABLE%>
<hr />
<p>
<h4>Fehlercodes</h4> <h4>Fehlercodes</h4>
<table class="table text-light"> <table class="table">
<tbody> <tbody>
<tr> <tr>
<th class="col-md-4" scope="col">Timestamp</td> <th class="col-6" scope="col">Zeitstempel</th>
<th class="col-md-4" scope="col">DTC</td> <th class="col-2" scope="col">Fehlercode</th>
<th class="col-md-4" scope="col">active</td> <th class="col-2" scope="col">Schwere</th>
<th class="col-2" scope="col">Aktiv</th>
</tr> </tr>
%DTC_TABLE% %DTC_TABLE%
</tbody> </tbody>
</table> </table>
</p>
</div> </div>
<!-- Div Group DTC Table -->
</div> </div>
<!-- Div Tab Home--> <!-- Div Tab Home-->
<!-- Div Tab Settings-->
<div class="tab-pane fade" id="tab_settings" role="tabpanel"> <!-- Div Tab Maintenance -->
<h3>Settings</h3> <div id="tab_maintenance" class="tab-pane fade" role="tabpanel">
<hr> <h3>Wartung</h3>
<form method="POST"> <!-- Div Group EEPROM formatting -->
<hr />
<p>
<h4>EEPROM formatieren</h4>
<div class="alert alert-primary alert-dismissable show fade" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<strong>Achtung!</strong><br>
Das Formatieren der EEPROM-Bereiche sollte nur ausgeführt werden wenn es unbedingt erforderlich ist!
Hierdurch werden alle Einstellungen zurück gesetzt bzw. alle Betriebsdaten gehen verloren.
Folgende Situationen erfordern unter anderem eine Formatierung:
- Erstinitialisierung (bei neu aufgebautem Gerät)
- Firmware-Update (nur wenn es die Release-Notes fordern)
</div>
<form action="post.htm" method="POST" class="form-horizontal">
<div class="form-group row"> <div class="form-group row">
<label for="commandInput" class="col-sm-2 col-form-label">Command</label> <div class="offset-4 col-8">
<div class="col-sm-10"> <div class="form-check">
<input type="text" name="commandInput" class="form-control bg-light" id="commandInput" <input class="form-check-input" type="checkbox" name="reset_ee_cfg" id="reset_ee_cfg">
placeholder="type command here..."> <label class="form-check-label" for="reset_ee_cfg">
Bereich "CFG"
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="reset_ee_pds" id="reset_ee_pds">
<label class="form-check-label" for="reset_ee_pds">
Bereich "PDS"
</label>
</div>
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<div class="col-sm-12"> <div class="col text-center">
<button name="cmdsubmit" type="submit" class="btn btn-primary float-right">Apply</button> <button name="reset_ee_btn" type="submit" class="btn btn-outline-primary">EEPROM formatieren</button>
</div> </div>
</div> </div>
</form> </form>
</p>
<!-- Div Group EEPROM formatting -->
<!-- Div Group Device Reboot -->
<hr />
<p>
<h4>Ger&auml;t neustarten</h4>
<form action="post.htm" method="POST" class="form-horizontal">
<div class="form-group row">
<div class="col text-center">
<button name="reboot" type="submit" class="btn btn-outline-primary">Reboot</button>
</div>
</div>
</form>
</p>
<!-- Div Group Device Reboot -->
</div> </div>
<!-- Div Tab Maintenance -->
<!-- Div Tab Settings--> <!-- Div Tab Settings-->
<div id="tab_source" class="tab-pane fade" role="tabpanel">
<h3>Einstellungen</h3>
<!-- Div Group Battery Type -->
<hr />
<p>
<h4>Akku-Variante</h4>
<form action="post.htm" method="POST" class="form-horizontal">
<div class="form-group row">
<label for="sourceselect" class="control-label col-4">Akku</label>
<div class="col-8">
<select id="sourceselect" name="sourceselect" class="select form-control">
%BATTERY_SELECT_OPTIONS%
</select>
</div>
</div>
<div class="form-group row">
<div class="col text-center">
<button name="sourcesave" type="submit" class="btn btn-outline-primary">&Uuml;bernehmen</button>
</div>
</div>
</form>
</p>
<!-- Div Group Battery Type -->
</div>
<!-- Div Tab Settings -->
<!-- Div Tab SystemInfo -->
<div id="tab_sysinfo" class="tab-pane fade" role="tabpanel">
<h3>Systeminfo</h3>
<!-- Div Group Sysinfo:Geraeteinfo -->
<hr />
<p>
<h4>Ger&auml;t</h4>
<table class="table">
<tbody>
<tr>
<th class="col-7" scope="col">Parameter</td>
<th class="col-5" scope="col">Value</td>
</tr>
<tr>
<td>Hostname</td>
<td>%HOSTNAME%</td>
</tr>
</table>
</p>
<!-- Div Group Sysinfo:Geraeteinfo -->
<!-- Div Group Sysinfo:Settings -->
<hr />
<p>
<h4>Einstellungen</h4>
<table class="table">
<tbody>
<tr>
<th class="col-7" scope="col">Parameter</td>
<th class="col-5" scope="col">Value</td>
</tr>
<tr>
<td>Battery_type</td>
<td>%BATTERY_TYPE%</td>
</tr>
<tr>
<td>EEPROM Version</td>
<td>%EEPROM_VERSION%</td>
</tr>
<tr>
<td>Checksum</td>
<td>%CONFIG_CHECKSUM%</td>
</tr>
</tbody>
</table>
</p>
<!-- Div Group Sysinfo:Settings -->
<!-- Div Group Sysinfo:Persistance -->
<hr />
<p>
<h4>Betriebsdaten</h4>
<table class="table">
<tbody>
<tr>
<th class="col-7" scope="col">Parameter</td>
<th class="col-5" scope="col">Value</td>
</tr>
<tr>
<td>writeCycleCounter</td>
<td>%WRITE_CYCLE_COUNT%</td>
</tr>
<tr>
<td>PersistenceMarker</td>
<td>%PERSISTENCE_MARKER%</td>
</tr>
<tr>
<td>activeFaction</td>
<td>%ACTIVE_FACTION%</td>
</tr>
<tr>
<td>faction_1_timer</td>
<td>%FACTION_1_TIMER%</td>
</tr>
<tr>
<td>faction_2_timer</td>
<td>%FACTION_2_TIMER%</td>
</tr>
<tr>
<td>faction_3_timer</td>
<td>%FACTION_3_TIMER%</td>
</tr>
<tr>
<td>checksum</td>
<td>%PERSISTANCE_CHECKSUM%</td>
</tr>
</table>
</p>
<!-- Div Group Sysinfo:Persistance -->
<!-- Div Group LiveDebug -->
<hr />
<p>
<h4>Live Debug</h4>
<div class="form-group row">
<textarea class="form-control" spellcheck="false" id="livedebug-out" rows="3" readonly></textarea>
</div>
<div class="form-group row">
<div class="col text-center">
<button id="btn-ws-start" class="btn btn-outline-primary">Start</button>
<button id="btn-ws-stop" class="btn btn-outline-primary ml-2">Stop</button>
</div>
</div>
</p>
<!-- Div Group LiveDebug -->
</div>
<!-- Div Tab SystemInfo -->
<!-- Div Tab Firmware Update-->
<div id="tab_fwupdate" class="tab-pane fade" role="tabpanel">
<h3>Firmware</h3>
<!-- Div Group VersionInfo -->
<hr />
<p>
<h4>Version-Info</h4>
<table class="table">
<tbody>
<tr>
<th class="col-7" scope="col">Parameter</td>
<th class="col-5" scope="col">Value</td>
</tr>
<tr>
<td>Firmware Version</td>
<td>%SW_VERSION%</td>
</tr>
<tr>
<td>Flash Version</td>
<td>%FS_VERSION%</td>
</tr>
<tr>
<td>Git Revision</td>
<td>%GIT_REV%</td>
</tr>
</table>
</p>
<!-- Div Group VersionInfo -->
<!-- Div Group EEPROM Backup -->
<hr />
<p>
<h4>EEPROM-Backup</h4>
<div class="form-group row">
<div class="col text-center">
<a class="btn btn-outline-primary" href="eejson" role="button" id="ee-backup-download">Download</a>
</div>
</div>
</p>
<!-- Div Group EEPROM Backup -->
<!-- Div Group EEPROM Restore -->
<hr />
<p>
<h4>EEPROM-Restore</h4>
<form method='POST' action='eeRestore' enctype='multipart/form-data'>
<div class="form-group row">
<div class="custom-file">
<input type="file" name="ee-restore-file" class="custom-file-input" id="ee-restore-file" accept=".ee.json"
required />
<label class="custom-file-label" for="ee-restore-file">EEPROM-Backup ausw&auml;hlen</label>
</div>
</div>
<div class="form-group row">
<div class="col text-center">
<button name="submit" type="submit" class="btn btn-outline-primary">Restore starten</button>
</div>
</div>
</form>
</p>
<!-- Div Group EEPROM Restore -->
<!-- Div Group Firmware Update -->
<hr />
<p>
<h4>Firmware-Update</h4>
<form method='POST' action='doUpdate' enctype='multipart/form-data'>
<div class="form-group row">
<div class="custom-file">
<input type="file" name="fw-update-file" class="custom-file-input" id="fw-update-file"
accept=".fw.bin,.fs.gz" required />
<label class="custom-file-label" for="fw-update-file">Firmware-Update ausw&auml;hlen</label>
</div>
</div>
<div class="form-group row">
<div class="col text-center">
<button name="submit" type="submit" class="btn btn-outline-primary">Update starten</button>
</div>
</div>
</form>
</p>
<!-- Div Group Firmware Update -->
</div>
<!-- Div Tab Firmware Update-->
</div> </div>
<!-- Tabs Content --> <!-- Tabs Content -->
</main> </main>
<!-- Footer --> <!-- Footer -->
<footer class="fixed-bottom bg-secondary font-weight-light text-light text-center py-3">
<!-- Copyright -->
<span class=" footer-copyright">
© 2022 <a class="text-reset fw-bold" href="https://hiabuto.de/">Hiabuto Defence Systems</a>
</span>
<!-- Copyright -->
<footer class="page-footer navbar-dark bg-primary font-small fixed-bottom">
<div class="container-fluid text-center">
<div class="footer-copyright text-center py-3">
<span class="text-muted">© 2023 -
<a class="text-reset fw-bold" href="https://hiabuto.de/">Hiabuto Defence Systems</a></span>
</div>
</div>
</footer> </footer>
<!-- Footer --> <!-- Footer -->
<!-- Modal Dialog -->
<div class="modal fade" id="dtcModal" tabindex="-1" role="dialog" aria-labelledby="dtcModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="dtcModalLabel">DTC-Description</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<p class="dtc-desc">DTC Description</p>
<p class="dtc-debugval">DTC DebugVal</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<!-- Modal Dialog -->
<script>
$('.navbar-nav>li>a').on('click', function () {
$('.navbar-collapse').collapse('hide');
});
document.querySelector('.custom-file-input').addEventListener('change', function (e) {
var fileName = document.getElementById("fw-update-file").files[0].name;
var nextSibling = e.target.nextElementSibling
nextSibling.innerText = fileName
});
$(document).ready(function () {
$("tr[data-dtc]").each(function (i) {
$(this).attr('data-toggle', "modal");
$(this).attr('data-target', "#dtcModal");
});
});
$('#dtcModal').on('show.bs.modal', function (event) {
var dtctr = $(event.relatedTarget)
var dtc = dtctr.data('dtc')
var debugval = dtctr.data('debugval')
var modal = $(this)
$.getJSON('static/tt_dtc/dtc_' + dtc + '.json', function (data) {
modal.find('.modal-title').text(data.title)
modal.find('.dtc-desc').text(data.description)
if (debugval > 0) {
modal.find('.dtc-debugval').text("Debugvalue: " + debugval)
}
else {
modal.find('.dtc-debugval').remove()
}
}).fail(function () {
console.log("An error has occurred.");
modal.find('.modal-title').text("Fehler")
modal.find('.dtc-desc').text("DTC-Beschreibung konnte nicht geladen werden")
});
});
</script>
</body> </body>
</html> </html>

View File

@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>%DEVICE_NAME%</title> <title>KTM CAN Chain Oiler</title>
<meta http-equiv="content-type" content="text/html;charset=UTF-8"> <meta http-equiv="content-type" content="text/html;charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="static/css/bootstrap.min.css"> <link rel="stylesheet" href="static/css/bootstrap.min.css">
@ -14,7 +14,7 @@
<link rel="icon" type="image/png" sizes="32x32" href="static/img/favicon-32x32.png"> <link rel="icon" type="image/png" sizes="32x32" href="static/img/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="static/img/favicon-16x16.png"> <link rel="icon" type="image/png" sizes="16x16" href="static/img/favicon-16x16.png">
<link rel="manifest" href="static/img/site.webmanifest"> <link rel="manifest" href="static/img/site.webmanifest">
<meta http-equiv="refresh" content="3; url='/index.htm'" /> <meta http-equiv="refresh" content="3; url='index.htm'" />
</head> </head>
<body> <body>

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,27 @@
@font-face {
font-family: 'Comfortaa';
font-style: normal;
font-weight: 300;
src: url(../fonts/comfortaa.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
body {
padding-top: 70px;
margin-bottom: 70px;
}
hr {
height: 2px;
border-width: 0;
color: gray;
background-color: gray
}
.dtc-debugval {
color: #F2771A;
font: 0.8rem Inconsolata, monospace;
background-color: black;
padding: 10px;
}

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,84 @@
var gateway = `ws://${window.location.hostname}/ws`;
var websocket;
window.addEventListener("load", onLoad);
function initWebSocket() {
console.log("Trying to open a WebSocket connection...");
websocket = new WebSocket(gateway);
websocket.onopen = onOpen;
websocket.onclose = onClose;
websocket.onmessage = onMessage; // <-- add this line
}
function initButtons() {
document
.getElementById("btn-ws-stop")
.addEventListener("click", livedebug_stop);
document
.getElementById("btn-ws-start")
.addEventListener("click", livedebug_start);
}
function onOpen(event) {
console.log("Connection opened");
}
function onClose(event) {
console.log("Connection closed");
setTimeout(initWebSocket, 2000);
}
function onMessage(event) {
var livedebug_out = document.getElementById("livedebug-out");
var textarea_heigth = livedebug_out.scrollHeight;
livedebug_out.value += event.data;
livedebug_out.scrollTop = livedebug_out.scrollHeight;
do_resize(livedebug_out);
}
function onLoad(event) {
initWebSocket();
initButtons();
}
function livedebug_start() {
websocket.send("start");
}
function livedebug_stop() {
websocket.send("stop");
}
function do_resize(textbox) {
var maxrows = 15;
var minrows = 3;
var txt = textbox.value;
var cols = textbox.cols;
var arraytxt = txt.split("\n");
var rows = arraytxt.length;
for (i = 0; i < arraytxt.length; i++)
rows += parseInt(arraytxt[i].length / cols);
if (rows > maxrows) textbox.rows = maxrows;
else if (rows < minrows) textbox.rows = minrows;
else textbox.rows = rows;
}
function notifyMe() {
if (!("Notification" in window)) {
alert("This browser does not support desktop notification");
} else if (Notification.permission === "granted") {
const notification = new Notification("Hi there!");
// …
} else if (Notification.permission !== "denied") {
Notification.requestPermission().then((permission) => {
if (permission === "granted") {
const notification = new Notification("Hi there!");
// …
}
});
}
}

View File

@ -0,0 +1,4 @@
{
"title": "kein EEPROM gefunden",
"description": "Es wurde kein EEPROM gefunden. Dies lässt einen Hardware-Defekt vermuten."
}

View File

@ -0,0 +1,4 @@
{
"title": "Power-Monitor Fehler",
"description": "Es gibt ein Problem mit dem Power-Monitoring. Die Akku-Überwachung ist ohne Funktion! Bitte Hardware prüfen"
}

View File

@ -0,0 +1,4 @@
{
"title": "Akku-Spannung niedrig",
"description": "Die Akkuspannung ist niedrig. Bitte Akku bald aufladen!"
}

View File

@ -0,0 +1,4 @@
{
"title": "Akku-Spannung kritisch",
"description": "Die Akkuspannung ist sehr niedrig. Bitte Akku umgehend ersetzen um eine schändliche Tiefentladung zu vermeiden!"
}

View File

@ -0,0 +1,4 @@
{
"title": "EEPROM CFG Checksumme",
"description": "Die Checksumme der Config-Partition des EEPROM ist ungültig. Setzen sie den EEPROM-Bereich 'CFG' im Menu 'Wartung' zurück"
}

View File

@ -0,0 +1,4 @@
{
"title": "EEPROM PDS Checksumme",
"description": "Die Checksumme der Betriebsdaten-Partition des EEPROM ist ungültig. Setzen sie den EEPROM-Bereich 'PDS' im Menu 'Wartung' zurück"
}

View File

@ -0,0 +1,4 @@
{
"title": "EEPROM PDS Adresse",
"description": "Die Adresse der Betriebsdaten-Partition im EEPROM ist ungültig. Setzen sie den EEPROM-Bereich 'PDS' im Menu 'Wartung' zurück"
}

View File

@ -0,0 +1,4 @@
{
"title": "EEPROM Version falsch",
"description": "Die Layout-Version des EEPROM stimmt nicht mit der Firmware-Version überein. Setzen sie den EEPROM-Bereich 'CFG' im Menu 'Wartung' zurück"
}

View File

@ -0,0 +1,4 @@
{
"title": "Flashstorage Fehler",
"description": "Der Flashstorage konnte nicht initialisiert werden. Aktualisieren sie Flash & Firmware"
}

View File

@ -0,0 +1,4 @@
{
"title": "Flashstorage Version falsch",
"description": "Die Version des Flashstorage stimmt nicht mit der Firmware-Version überein. Aktualisieren sie den Flash mit der passenden Update-Datei"
}

View File

@ -0,0 +1,4 @@
{
"title": "Config-Validierung",
"description": "Ein oder mehrer Einstellungswerte sind ausserhalb plausibler Werte. Prüfen Sie Ihre Einstellungen"
}

View File

@ -0,0 +1,4 @@
{
"title": "LoRa-Modul Fehler",
"description": "Es gibt ein Problem mit dem LoRa-Modul. Es konnte keine LoRa-Verbindung aufgebaut werden. Bitte Hardware prüfen"
}

View File

@ -1 +1 @@
1.0 1.1

View File

@ -40,28 +40,10 @@
#define I2C_POWER_ADDRESS 0x40 #define I2C_POWER_ADDRESS 0x40
#define I2C_EEPROM_ADDRESS 0x50 #define I2C_EEPROM_ADDRESS 0x50
#define SW_VERSION 1.0
#define FLASH_FS_VERSION 1.0
#ifndef OTA_DELAY #ifndef OTA_DELAY
#define OTA_DELAY 50 // ticks -> 10ms / tick #define OTA_DELAY 50 // ticks -> 10ms / tick
#endif #endif
#ifndef ADMIN_PASSWORD
#error "You need to define ADMIN_PASSWORD for OTA-Update"
#endif
#ifndef WIFI_PASSWORD
#error "You must define an WIFI_PASSWORD for OTA-Update"
#endif
#ifndef WIFI_SSID
#error "You must define an WIFI_SSID for OTA-Update"
#endif
#ifndef WIFI_AP_SSID
#warning "No WIFI_AP_SSID defined. Using DeviceName"
#define WIFI_AP_SSID DEVICE_NAME
#endif
#ifndef WIFI_AP_PASSWORD
#error "You must define an WIFI_AP_PASSWORD for Standalone AP-Mode"
#endif
#endif #endif

View File

@ -43,6 +43,8 @@ const char BatteryString[][10]{
"LiPo 3S" "LiPo 3S"
}; };
const size_t BatteryString_Elements = sizeof(BatteryString) / sizeof(BatteryString[0]);
typedef struct typedef struct
{ {
uint8_t EEPROM_Version = 1; uint8_t EEPROM_Version = 1;

View File

@ -0,0 +1,46 @@
#ifndef _DEBUGGER_H_
#define _DEBUGGER_H_
#include <Arduino.h>
#include "webui.h"
const char PROGMEM helpCmd[] = "sysinfo - System Info\n"
"netinfo - WiFi Info\n"
"formatPDS - Format Persistence EEPROM Data\n"
"formatCFG - Format Configuration EEPROM Data\n"
"checkEE - Check EEPROM with checksum\n"
"dumpEE1k - dump the first 1kb of EEPROM to Serial\n"
"dumpEE - dump the whole EPPROM to Serial\n"
"resetPageEE - Reset the PersistenceData Page\n"
"dumpCFG - print Config struct\n"
"dumpPDS - print PersistanceStruct\n"
"saveEE - save EE-Data\n"
"showdtc - Show all DTCs\n"
"dumpGlobals - print globals\n";
typedef enum DebugStatus_e
{
disabled,
enabled
} DebugStatus_t;
typedef enum DebugPorts_e
{
dbg_Serial,
dbg_Webui,
dbg_cntElements
} DebugPorts_t;
const char sDebugPorts[dbg_cntElements][7] = {
"Serial",
"WebUI"};
extern DebugStatus_t DebuggerStatus[dbg_cntElements];
void initDebugger();
void pushCANDebug(uint32_t id, uint8_t dlc, uint8_t *data);
void Debug_pushMessage(const char *format, ...);
void SetDebugportStatus(DebugPorts_t port, DebugStatus_t status);
void Debug_Process();
#endif

View File

@ -17,14 +17,16 @@ typedef enum DTCNums_e
DTC_EEPROM_CFG_SANITY, DTC_EEPROM_CFG_SANITY,
DTC_NO_LORA_FOUND, DTC_NO_LORA_FOUND,
DTC_NO_BATMNON_FOUND, DTC_NO_BATMNON_FOUND,
DTC_BAT_LOW,
DTC_BAT_CRITICAL,
DTC_LAST_DTC DTC_LAST_DTC
} DTCNums_t; } DTCNums_t;
typedef enum DTCActive_e typedef enum DTCActive_e
{ {
DTC_NONE,
DTC_ACTIVE, DTC_ACTIVE,
DTC_PREVIOUS, DTC_PREVIOUS
DTC_NONE
} DTCActive_t; } DTCActive_t;
typedef enum DTCSeverity_e typedef enum DTCSeverity_e
@ -48,6 +50,7 @@ void ClearDTC(DTCNums_t DTC_no);
void ClearAllDTC(); void ClearAllDTC();
DTCNums_t getlastDTC(boolean only_active); DTCNums_t getlastDTC(boolean only_active);
DTCNums_t getlastDTC_Severity(boolean only_active, DTCSeverity_t severity); DTCNums_t getlastDTC_Severity(boolean only_active, DTCSeverity_t severity);
void DTC_Process();
extern DTCEntry_s DTCStorage[MAX_DTC_STORAGE]; extern DTCEntry_s DTCStorage[MAX_DTC_STORAGE];
#endif #endif

View File

@ -41,5 +41,21 @@ typedef struct Globals_s
} Globals_t; } Globals_t;
extern Globals_t globals; extern Globals_t globals;
typedef struct Constants_s
{
uint8_t FW_Version_major;
uint8_t FW_Version_minor;
uint8_t Required_Flash_Version_major;
uint8_t Required_Flash_Version_minor;
char GitHash[11];
} Constants_t;
const Constants_t constants PROGMEM = {
1,1, // Firmware_Version
1,1, // Required Flash Version
GIT_REV // Git-Hash-String
};
void initGlobals();
#endif #endif

View File

@ -0,0 +1,21 @@
#ifndef _SANITYCHECK_H_
#define _SANITYCHECK_H_
#ifndef ADMIN_PASSWORD
#error "You need to define ADMIN_PASSWORD for OTA-Update"
#endif
#ifndef WIFI_PASSWORD
#error "You must define an WIFI_PASSWORD for OTA-Update"
#endif
#ifndef WIFI_SSID
#error "You must define an WIFI_SSID for OTA-Update"
#endif
#ifndef WIFI_AP_SSID
#warning "No WIFI_AP_SSID defined. Using DeviceName"
#define WIFI_AP_SSID DEVICE_NAME
#endif
#ifndef WIFI_AP_PASSWORD
#error "You must define an WIFI_AP_PASSWORD for Standalone AP-Mode"
#endif
#endif //_SANITYCHECK_H_

View File

@ -15,7 +15,10 @@
#include "globals.h" #include "globals.h"
#include "dtc.h" #include "dtc.h"
#include "common.h" #include "common.h"
#include "debugger.h"
void initWebUI(); void initWebUI();
void Webserver_Process();
void Websocket_PushLiveDebug(String Message);
#endif #endif

View File

@ -28,6 +28,7 @@ build_flags=
!python git_rev_macro.py !python git_rev_macro.py
-DATOMIC_FS_UPDATE -DATOMIC_FS_UPDATE
;-DFEATURE_ENABLE_WIFI_CLIENT ;-DFEATURE_ENABLE_WIFI_CLIENT
;-DFEATURE_ENABLE_LORA
;-DCAPTIVE ;-DCAPTIVE
-DWIFI_AP_IP_GW=10,0,1,1 -DWIFI_AP_IP_GW=10,0,1,1
-DADMIN_PASSWORD=${wifi_cred.admin_password} -DADMIN_PASSWORD=${wifi_cred.admin_password}

330
Software/src/debugger.cpp Normal file
View File

@ -0,0 +1,330 @@
#include "debugger.h"
DebugStatus_t DebuggerStatus[dbg_cntElements];
String IpAddress2String(const IPAddress &ipAddress);
void processCmdDebug(String command);
void Debug_formatCFG();
void Debug_formatPersistence();
void Debug_printSystemInfo();
void Debug_printWifiInfo();
void Debug_CheckEEPOM();
void Debug_dumpConfig();
void Debug_dumpPersistance();
void Debug_ShowDTCs();
void Debug_dumpGlobals();
void Debug_printHelp();
void initDebugger()
{
DebuggerStatus[dbg_Serial] = disabled;
DebuggerStatus[dbg_Webui] = disabled;
Serial.setDebugOutput(false);
}
void Debug_Process()
{
typedef enum InputProcessed_e
{
IDLE,
CMD_COMPLETE,
CMD_ABORT,
CMD_OVERFLOW
} InputProcessed_t;
static int inputCnt = 0;
static char inputBuffer[32];
InputProcessed_t InputProcessed = IDLE;
if (Serial.available())
{
char inputChar = Serial.read();
switch (inputChar)
{
case '\n':
inputBuffer[inputCnt] = 0; // terminate the String
inputCnt = 0;
InputProcessed = CMD_COMPLETE;
break;
case 0x1B: // Esc
inputBuffer[0] = 0;
inputCnt = 0;
InputProcessed = CMD_ABORT;
break;
case 0x21 ... 0x7E: // its a real letter or sign and not some control-chars
inputBuffer[inputCnt] = inputChar;
inputCnt++;
break;
default:
break;
}
if (inputCnt > sizeof(inputBuffer))
{
inputCnt = 0;
inputBuffer[sizeof(inputBuffer) - 1] = 0; // terminate the String
InputProcessed = CMD_OVERFLOW;
}
}
switch (InputProcessed)
{
case CMD_ABORT:
Debug_pushMessage("Abort\n");
break;
case CMD_COMPLETE:
processCmdDebug(String(inputBuffer));
break;
case CMD_OVERFLOW:
Debug_pushMessage("input Buffer overflow\n");
break;
default:
break;
}
InputProcessed = IDLE;
}
void SetDebugportStatus(DebugPorts_t port, DebugStatus_t status)
{
if (status == disabled)
Debug_pushMessage("disable DebugPort %s\n", sDebugPorts[port]);
DebuggerStatus[port] = status;
if (status == enabled)
Debug_pushMessage("enabled DebugPort %s\n", sDebugPorts[port]);
}
void Debug_pushMessage(const char *format, ...)
{
if ((DebuggerStatus[dbg_Serial] == enabled) || (DebuggerStatus[dbg_Webui] == enabled))
{
char buff[64];
va_list arg;
va_start(arg, format);
vsnprintf(buff, sizeof(buff), format, arg);
va_end(arg);
if (DebuggerStatus[dbg_Serial] == enabled)
{
Serial.print(buff);
}
if (DebuggerStatus[dbg_Webui] == enabled)
{
Websocket_PushLiveDebug(String(buff));
}
}
}
void pushCANDebug(uint32_t id, uint8_t dlc, uint8_t *data)
{
if ((DebuggerStatus[dbg_Serial] == enabled) || (DebuggerStatus[dbg_Webui] == enabled))
{
char buff[100];
char *p = buff;
p += snprintf(p, sizeof(buff), "CAN: 0x%08X | %d | ", id, dlc);
for (int i = 0; i < dlc; i++)
{
p += snprintf(p, sizeof(buff) - (p - buff), "%02X ", data[i]);
}
*(p++) = '\n';
*p = '\0';
if (DebuggerStatus[dbg_Serial] == enabled)
{
Serial.print(buff);
}
if (DebuggerStatus[dbg_Webui] == enabled)
{
Websocket_PushLiveDebug(String(buff));
}
}
}
void processCmdDebug(String command)
{
if (command == "help")
Debug_printHelp();
else if (command == "sysinfo")
Debug_printSystemInfo();
else if (command == "netinfo")
Debug_printWifiInfo();
else if (command == "formatCFG")
Debug_formatCFG();
else if (command == "formatPDS")
Debug_formatPersistence();
else if (command == "checkEE")
Debug_CheckEEPOM();
else if (command == "dumpEE1k")
dumpEEPROM(0, 1024);
else if (command == "dumpEE")
dumpEEPROM(0, EEPROM_SIZE_BYTES);
else if (command == "resetPageEE")
MovePersistencePage_EEPROM(true);
else if (command == "dumpCFG")
Debug_dumpConfig();
else if (command == "dumpPDS")
Debug_dumpPersistance();
else if (command == "saveEE")
globals.requestEEAction = EE_ALL_SAVE;
else if (command == "showdtc")
Debug_ShowDTCs();
else if (command == "dumpGlobals")
Debug_dumpGlobals();
else if (command == "sdbg")
SetDebugportStatus(dbg_Serial, enabled);
else
Debug_pushMessage("unknown Command\n");
}
void Debug_formatCFG()
{
Debug_pushMessage("Formatting Config-EEPROM and reseting to default\n");
FormatConfig_EEPROM();
}
void Debug_formatPersistence()
{
Debug_pushMessage("Formatting Persistence-EEPROM and reseting to default\n");
FormatPersistence_EEPROM();
}
void Debug_printSystemInfo()
{
Debug_pushMessage("Souko's ChainOiler Mk1\n");
Debug_pushMessage("Hostname: %s\n", globals.DeviceName);
FlashMode_t ideMode = ESP.getFlashChipMode();
Debug_pushMessage("Sdk version: %s\n", ESP.getSdkVersion());
Debug_pushMessage("Core Version: %s\n", ESP.getCoreVersion().c_str());
Debug_pushMessage("Boot Version: %u\n", ESP.getBootVersion());
Debug_pushMessage("Boot Mode: %u\n", ESP.getBootMode());
Debug_pushMessage("CPU Frequency: %u MHz\n", ESP.getCpuFreqMHz());
Debug_pushMessage("Reset reason: %s\n", ESP.getResetReason().c_str());
Debug_pushMessage("Flash Size: %d\n", ESP.getFlashChipRealSize());
Debug_pushMessage("Flash Size IDE: %d\n", ESP.getFlashChipSize());
Debug_pushMessage("Flash ide mode: %s\n", (ideMode == FM_QIO ? "QIO" : ideMode == FM_QOUT ? "QOUT"
: ideMode == FM_DIO ? "DIO"
: ideMode == FM_DOUT ? "DOUT"
: "UNKNOWN"));
Debug_pushMessage("OTA-Pass: %s\n", QUOTE(ADMIN_PASSWORD));
Debug_pushMessage("Git-Revison: %s\n", constants.GitHash);
Debug_pushMessage("Sw-Version: %d.%02d\n", constants.FW_Version_major, constants.FW_Version_minor);
}
void Debug_dumpConfig()
{
Debug_pushMessage("batteryType: %d\n", ConfigData.batteryType);
Debug_pushMessage("EEPROM_Version: %d\n", ConfigData.EEPROM_Version);
Debug_pushMessage("checksum: 0x%08X\n", ConfigData.checksum);
}
void Debug_dumpGlobals()
{
Debug_pushMessage("systemStatus: %d\n", globals.systemStatus);
Debug_pushMessage("resumeStatus: %d\n", globals.resumeStatus);
Debug_pushMessage("systemStatustxt: %s\n", globals.systemStatustxt);
Debug_pushMessage("battery_level: %d\n", globals.battery_level);
Debug_pushMessage("loadvoltage_mV: %d\n", globals.loadvoltage_mV);
Debug_pushMessage("requestEEAction: %d\n", globals.requestEEAction);
Debug_pushMessage("DeviceName: %s\n", globals.DeviceName);
Debug_pushMessage("DeviceName_ID: %s\n", globals.DeviceName_ID);
Debug_pushMessage("FlashVersion: %s\n", globals.FlashVersion);
Debug_pushMessage("eePersistanceAdress: %d\n", globals.eePersistanceAdress);
Debug_pushMessage("hasDTC: %d\n", globals.hasDTC);
}
void Debug_dumpPersistance()
{
Debug_pushMessage("writeCycleCounter: %d\n", PersistenceData.writeCycleCounter);
Debug_pushMessage("activeFaction: %d\n", PersistenceData.activeFaction);
Debug_pushMessage("faction_1_timer: %d\n", PersistenceData.faction_1_timer);
Debug_pushMessage("faction_2_timer: %d\n", PersistenceData.faction_2_timer);
Debug_pushMessage("faction_3_timer: %d\n", PersistenceData.faction_3_timer);
Debug_pushMessage("checksum: %d\n", PersistenceData.checksum);
Debug_pushMessage("PSD Adress: 0x%04X\n", globals.eePersistanceAdress);
}
void Debug_printWifiInfo()
{
}
void Debug_CheckEEPOM()
{
uint32_t checksum = PersistenceData.checksum;
PersistenceData.checksum = 0;
if (Checksum_EEPROM((uint8_t *)&PersistenceData, sizeof(PersistenceData)) == checksum)
{
Debug_pushMessage("PersistenceData EEPROM Checksum OK\n");
}
else
{
Debug_pushMessage("PersistenceData EEPROM Checksum BAD\n");
}
PersistenceData.checksum = checksum;
checksum = ConfigData.checksum;
ConfigData.checksum = 0;
if (Checksum_EEPROM((uint8_t *)&ConfigData, sizeof(ConfigData)) == checksum)
{
Debug_pushMessage("ConfigData EEPROM Checksum OK\n");
}
else
{
Debug_pushMessage("ConfigData EEPROM Checksum BAD\n");
}
ConfigData.checksum = checksum;
}
void Debug_ShowDTCs()
{
char buff_timestamp[16]; // Format: DD-hh:mm:ss:xxx
char buff_active[9];
Debug_pushMessage("\n timestamp | DTC-Nr. | status | severity\n");
for (uint32_t i = 0; i < MAX_DTC_STORAGE; i++)
{
if (DTCStorage[i].Number < DTC_LAST_DTC)
{
sprintf(buff_timestamp, "%02d-%02d:%02d:%02d:%03d",
DTCStorage[i].timestamp / 86400000, // Days
DTCStorage[i].timestamp / 360000 % 24, // Hours
DTCStorage[i].timestamp / 60000 % 60, // Minutes
DTCStorage[i].timestamp / 1000 % 60, // Seconds
DTCStorage[i].timestamp % 1000); // milliseconds
if (DTCStorage[i].active == DTC_ACTIVE)
strcpy(buff_active, "active");
else if (DTCStorage[i].active == DTC_PREVIOUS)
strcpy(buff_active, "previous");
else
strcpy(buff_active, "none");
Debug_pushMessage("%s %7d %8s %8d\n", buff_timestamp, DTCStorage[i].Number, buff_active, DTCStorage[i].severity);
}
}
}
void Debug_printHelp()
{
char buff[64];
for (int i = sizeof(helpCmd) / 63; i < sizeof(helpCmd) / 63; i++)
{
memcpy_P(buff, (helpCmd + (i * 63)), 63);
buff[63] = 0;
Debug_pushMessage(buff);
}
}

View File

@ -1,4 +1,5 @@
#include "dtc.h" #include "dtc.h"
#include "debugger.h"
DTCEntry_s DTCStorage[MAX_DTC_STORAGE]; DTCEntry_s DTCStorage[MAX_DTC_STORAGE];
@ -10,7 +11,7 @@ void MaintainDTC(DTCNums_t DTC_no, DTCSeverity_t DTC_severity, boolean active, u
{ {
if (active && DTCStorage[i].active != DTC_ACTIVE) if (active && DTCStorage[i].active != DTC_ACTIVE)
{ {
Serial.printf("DTC gone active: %d, DebugVal: %d\n", DTC_no, DebugValue); Debug_pushMessage("DTC gone active: %d, DebugVal: %d\n", DTC_no, DebugValue);
DTCStorage[i].timestamp = millis(); DTCStorage[i].timestamp = millis();
DTCStorage[i].active = DTC_ACTIVE; DTCStorage[i].active = DTC_ACTIVE;
DTCStorage[i].severity = DTC_severity; DTCStorage[i].severity = DTC_severity;
@ -18,7 +19,7 @@ void MaintainDTC(DTCNums_t DTC_no, DTCSeverity_t DTC_severity, boolean active, u
} }
if (!active && DTCStorage[i].active == DTC_ACTIVE) if (!active && DTCStorage[i].active == DTC_ACTIVE)
{ {
Serial.printf("DTC gone previous: %d\n", DTC_no); Debug_pushMessage("DTC gone previous: %d\n", DTC_no);
DTCStorage[i].active = DTC_PREVIOUS; DTCStorage[i].active = DTC_PREVIOUS;
} }
return; return;
@ -33,11 +34,12 @@ void MaintainDTC(DTCNums_t DTC_no, DTCSeverity_t DTC_severity, boolean active, u
{ {
if (DTCStorage[i].Number == DTC_LAST_DTC) if (DTCStorage[i].Number == DTC_LAST_DTC)
{ {
Serial.printf("new DTC registered: %d, DebugVal: %d\n", DTC_no, DebugValue); Debug_pushMessage("new DTC registered: %d, DebugVal: %d\n", DTC_no, DebugValue);
DTCStorage[i].Number = DTC_no; DTCStorage[i].Number = DTC_no;
DTCStorage[i].timestamp = millis(); DTCStorage[i].timestamp = millis();
DTCStorage[i].active = DTC_ACTIVE; DTCStorage[i].active = DTC_ACTIVE;
DTCStorage[i].debugVal = DebugValue; DTCStorage[i].debugVal = DebugValue;
DTCStorage[i].severity = DTC_severity;
return; return;
} }
} }
@ -106,3 +108,32 @@ DTCNums_t getlastDTC_Severity(boolean only_active, DTCSeverity_t severity)
return pointer >= 0 ? DTCStorage[pointer].Number : DTC_LAST_DTC; return pointer >= 0 ? DTCStorage[pointer].Number : DTC_LAST_DTC;
} }
void DTC_Process()
{
static tSystem_Status preserverSysStatusError;
if (getlastDTC(false) < DTC_LAST_DTC)
{
globals.hasDTC = true;
if (getlastDTC_Severity(true, DTC_CRITICAL) < DTC_LAST_DTC && globals.systemStatus != sysStat_Shutdown)
{
if (globals.systemStatus != sysStat_Error)
{
preserverSysStatusError = globals.systemStatus;
}
globals.systemStatus = sysStat_Error;
}
else
{
if (globals.systemStatus == sysStat_Error)
{
globals.systemStatus = preserverSysStatusError;
}
}
}
else
{
globals.hasDTC = false;
}
}

10
Software/src/globals.cpp Normal file
View File

@ -0,0 +1,10 @@
#include "globals.h"
Globals_t globals;
void initGlobals()
{
globals.systemStatus = sysStat_Startup;
globals.resumeStatus = sysStat_Normal;
globals.requestEEAction = EE_IDLE;
}

View File

@ -11,16 +11,17 @@
#include <ArduinoJson.h> #include <ArduinoJson.h>
// local includes // local includes
#include "common.h"
#include "sanitycheck.h"
#include "defaults.h" #include "defaults.h"
#include "webui.h" #include "webui.h"
#include "config.h" #include "config.h"
#include "globals.h" #include "globals.h"
#include "dtc.h" #include "dtc.h"
#include "common.h" #include "debugger.h"
#ifdef FEATURE_ENABLE_LORA
#include "lora_net.h" #include "lora_net.h"
#endif
#ifdef WIFI_CLIENT
#include <WiFiMulti.h>
#ifdef FEATURE_ENABLE_WIFI_CLIENT #ifdef FEATURE_ENABLE_WIFI_CLIENT
#include <ESP8266WiFiMulti.h> #include <ESP8266WiFiMulti.h>
@ -46,10 +47,13 @@ void SetBatteryType(batteryType_t type);
void ProcessKeyCombos(bool *btnState); void ProcessKeyCombos(bool *btnState);
void OverrideDisplay(const uint8_t *message, uint32_t time); void OverrideDisplay(const uint8_t *message, uint32_t time);
void initGlobals(); void initGlobals();
void setMPins_Helper(int pin, int status);
#ifdef FEATURE_ENABLE_LORA
void setMPins_Helper(int pin, int status);
void tmrCallback_StatusSender(); void tmrCallback_StatusSender();
Ticker tmrStatusSender(tmrCallback_StatusSender, 30000, 0, MILLIS); Ticker tmrStatusSender(tmrCallback_StatusSender, 30000, 0, MILLIS);
#endif
void tmrCallback_PowerMonitor(); void tmrCallback_PowerMonitor();
Ticker tmrPowerMonitor(tmrCallback_PowerMonitor, 10000, 0, MILLIS); Ticker tmrPowerMonitor(tmrCallback_PowerMonitor, 10000, 0, MILLIS);
void tmrCallback_FactionTicker(); void tmrCallback_FactionTicker();
@ -67,19 +71,12 @@ Ticker tmrWiFiMaintainConnection(tmrCallback_WiFiMaintainConnection, 1000, 0, MI
uint32_t DisplayOverrideFlag = 0; uint32_t DisplayOverrideFlag = 0;
char DisplayOverrideValue[5] = {0}; char DisplayOverrideValue[5] = {0};
Globals_t globals; #ifdef FEATURE_ENABLE_LORA
void initGlobals()
{
globals.requestEEAction = EE_IDLE;
globals.resumeStatus = sysStat_Normal;
globals.systemStatus = sysStat_Startup;
}
void setMPins_Helper(int pin, int status) void setMPins_Helper(int pin, int status)
{ {
i2c_io.write(pin, status); i2c_io.write(pin, status);
} }
#endif
void setup() void setup()
{ {
@ -100,6 +97,7 @@ void setup()
InitEEPROM(); InitEEPROM();
GetConfig_EEPROM(); GetConfig_EEPROM();
GetPersistence_EEPROM(); GetPersistence_EEPROM();
Serial.print("\nEE-Init done");
if (i2c_io.begin()) if (i2c_io.begin())
{ {
@ -120,6 +118,7 @@ void setup()
Serial.print("INA219 not Initialized\n"); Serial.print("INA219 not Initialized\n");
} }
#ifdef FEATURE_ENABLE_LORA
if (InitLoRa(&setMPins_Helper)) if (InitLoRa(&setMPins_Helper))
{ {
Serial.printf("Initialized LoRa_Transceiver"); Serial.printf("Initialized LoRa_Transceiver");
@ -129,6 +128,7 @@ void setup()
{ {
Serial.print("LoRa not Initialized\n"); Serial.print("LoRa not Initialized\n");
} }
#endif
#ifdef FEATURE_ENABLE_WIFI_CLIENT #ifdef FEATURE_ENABLE_WIFI_CLIENT
WiFi.mode(WIFI_STA); WiFi.mode(WIFI_STA);
@ -183,15 +183,17 @@ void setup()
Serial.println("Receive Failed"); Serial.println("Receive Failed");
else if (error == OTA_END_ERROR) else if (error == OTA_END_ERROR)
Serial.println("End Failed"); }); Serial.println("End Failed"); });
ArduinoOTA.begin();
ArduinoOTA.begin();
Serial.print("\nOTA-Init done");
initWebUI();
Serial.print("\nWebUI-Init done");
initGlobals();
Serial.print("\nglobals-Init done");
#ifdef CAPTIVE #ifdef CAPTIVE
dnsServer.start(53, "*", WiFi.softAPIP()); dnsServer.start(53, "*", WiFi.softAPIP());
#endif #endif
initWebUI();
initGlobals();
disp_FAC_1.init(); disp_FAC_1.init();
disp_FAC_1.setBrightness(5); disp_FAC_1.setBrightness(5);
disp_FAC_2.init(); disp_FAC_2.init();
@ -203,7 +205,7 @@ void setup()
tmrFactionTicker.start(); tmrFactionTicker.start();
tmrInputGetter.start(); tmrInputGetter.start();
Serial.println("Setup Done"); Serial.print("\nSetup Done\n");
} }
void loop() void loop()
@ -212,13 +214,19 @@ void loop()
tmrEEPROMCyclicPDS.update(); tmrEEPROMCyclicPDS.update();
tmrFactionTicker.update(); tmrFactionTicker.update();
tmrInputGetter.update(); tmrInputGetter.update();
tmrStatusSender.update();
tmrPowerMonitor.update(); tmrPowerMonitor.update();
ArduinoOTA.handle(); ArduinoOTA.handle();
SevenSeg_Output(); SevenSeg_Output();
EEPROM_Process(); EEPROM_Process();
Webserver_Process();
DTC_Process();
Debug_Process();
#ifdef FEATURE_ENABLE_LORA
tmrStatusSender.update();
LoRa_Process(); LoRa_Process();
#endif
#ifdef CAPTIVE #ifdef CAPTIVE
dnsServer.processNextRequest(); dnsServer.processNextRequest();
@ -362,10 +370,12 @@ void tmrCallback_InputGetter()
} }
} }
#ifdef FEATURE_ENABLE_LORA
void tmrCallback_StatusSender() void tmrCallback_StatusSender()
{ {
sendStatus_LoRa(); sendStatus_LoRa();
} }
#endif
void tmrCallback_PowerMonitor() void tmrCallback_PowerMonitor()
{ {
@ -402,6 +412,9 @@ void tmrCallback_PowerMonitor()
break; break;
} }
MaintainDTC(DTC_BAT_CRITICAL, DTC_CRITICAL, (battery_level < 5 ? true : false), battery_level);
MaintainDTC(DTC_BAT_LOW, DTC_WARN, (battery_level < 15 ? true : false), battery_level);
// Serial.printf("Battery Level: %d %%\n", globals.battery_level); // Serial.printf("Battery Level: %d %%\n", globals.battery_level);
// Serial.printf("Bus Voltage: %f V\n", busvoltage); // Serial.printf("Bus Voltage: %f V\n", busvoltage);
// Serial.printf("Shunt Voltage: %f mV\n", shuntvoltage); // Serial.printf("Shunt Voltage: %f mV\n", shuntvoltage);
@ -415,7 +428,7 @@ void tmrCallback_EEPROMCyclicPDS()
StorePersistence_EEPROM(); StorePersistence_EEPROM();
} }
#ifdef WIFI_CLIENT #ifdef FEATURE_ENABLE_WIFI_CLIENT
void tmrCallback_WiFiMaintainConnection() void tmrCallback_WiFiMaintainConnection()
{ {
static uint32_t WiFiFailCount = 0; static uint32_t WiFiFailCount = 0;
@ -445,7 +458,7 @@ void toggleWiFiAP(boolean shutdown)
if (WiFi.getMode() != WIFI_OFF) if (WiFi.getMode() != WIFI_OFF)
{ {
WiFi.mode(WIFI_OFF); WiFi.mode(WIFI_OFF);
debugV("WiFi turned off"); Serial.println("WiFi turned off");
#ifdef FEATURE_ENABLE_WIFI_CLIENT #ifdef FEATURE_ENABLE_WIFI_CLIENT
WiFiMaintainConnectionTicker.stop(); WiFiMaintainConnectionTicker.stop();
#endif #endif
@ -457,9 +470,9 @@ void toggleWiFiAP(boolean shutdown)
WiFi.softAP(QUOTE(WIFI_AP_SSID), QUOTE(WIFI_AP_PASSWORD)); WiFi.softAP(QUOTE(WIFI_AP_SSID), QUOTE(WIFI_AP_PASSWORD));
#ifdef FEATURE_ENABLE_WIFI_CLIENT #ifdef FEATURE_ENABLE_WIFI_CLIENT
WiFiMaintainConnectionTicker.stop(); WiFiMaintainConnectionTicker.stop();
debugV("WiFi AP started, stopped Maintain-Timer"); Serial.println("WiFi AP started, stopped Maintain-Timer");
#else #else
debugV("WiFi AP started"); Serial.println("WiFi AP started");
#endif #endif
} }
} }

View File

@ -2,52 +2,46 @@
AsyncWebServer webServer(80); AsyncWebServer webServer(80);
typedef enum const char *PARAM_MESSAGE = "message";
{
RESPMSG_HIDE,
RESPMSG_SUCCESS,
RESPMSG_INFO,
RESPMSG_WARNING,
RESPMSG_DANGER
} statusResponseMessage_Type_t;
char StatusResponseMessage[64];
statusResponseMessage_Type_t StatusResponseMessage_Type = RESPMSG_INFO;
#ifdef CAPTIVE
DNSServer dnsServer;
#endif
AsyncWebServer server(80);
String processor(const String &var); String processor(const String &var);
void WebserverPOST_Callback(AsyncWebServerRequest *request); void WebserverPOST_Callback(AsyncWebServerRequest *request);
void WebserverNotFound_Callback(AsyncWebServerRequest *request); void WebserverNotFound_Callback(AsyncWebServerRequest *request);
void Webserver_Callback(AsyncWebServerRequest *request); void Webserver_Callback(AsyncWebServerRequest *request);
void WebserverCommands_Callback(String input);
void WebserverFirmwareUpdate_Callback(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final); void WebserverFirmwareUpdate_Callback(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final);
void WebserverEERestore_Callback(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final); void WebserverEERestore_Callback(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final);
void WebServerEEJSON_Callback(AsyncWebServerRequest *request); void WebServerEEJSON_Callback(AsyncWebServerRequest *request);
void GetFlashVersion(char *buff, size_t buff_size); void GetFlashVersion(char *buff, size_t buff_size);
AsyncWebSocket webSocket("/ws");
void WebsocketEvent_Callback(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len);
void Websocket_HandleMessage(void *arg, uint8_t *data, size_t len);
void initWebUI() void initWebUI()
{ {
if (!LittleFS.begin()) if (!LittleFS.begin())
{ {
Serial.println("An Error has occurred while mounting LittleFS"); Debug_pushMessage("An Error has occurred while mounting LittleFS\n");
MaintainDTC(DTC_FLASHFS_ERROR, DTC_CRITICAL, true); MaintainDTC(DTC_FLASHFS_ERROR, DTC_CRITICAL, true);
return; return;
} }
GetFlashVersion(globals.FlashVersion, sizeof(globals.FlashVersion)); GetFlashVersion(globals.FlashVersion, sizeof(globals.FlashVersion));
if (strcmp(globals.FlashVersion, QUOTE(FLASH_FS_VERSION))) char buffer[6];
snprintf(buffer, sizeof(buffer), "%d.%02d", constants.Required_Flash_Version_major, constants.Required_Flash_Version_minor);
if (strcmp(globals.FlashVersion, buffer))
{ {
MaintainDTC(DTC_FLASHFS_VERSION_ERROR, DTC_WARN, true); MaintainDTC(DTC_FLASHFS_VERSION_ERROR, DTC_WARN, true);
} }
MDNS.begin(globals.DeviceName); MDNS.begin(globals.DeviceName);
MDNS.addService("telnet", "tcp", 23);
MDNS.addService("http", "tcp", 80); MDNS.addService("http", "tcp", 80);
webSocket.onEvent(WebsocketEvent_Callback);
webServer.addHandler(&webSocket);
webServer.serveStatic("/static/", LittleFS, "/static/").setCacheControl("max-age=360000"); webServer.serveStatic("/static/", LittleFS, "/static/").setCacheControl("max-age=360000");
webServer.on("/", HTTP_GET, [](AsyncWebServerRequest *request) webServer.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
{ request->redirect("/index.htm"); }); { request->redirect("/index.htm"); });
@ -63,51 +57,63 @@ void initWebUI()
webServer.begin(); webServer.begin();
} }
void Webserver_Process()
{
webSocket.cleanupClients();
}
String processor(const String &var) String processor(const String &var)
{ {
if (var == "HOSTNAME")
return String(globals.DeviceName);
if (var == "SYSTEM_STATUS")
return String(globals.systemStatustxt);
if (var == "SW_VERSION")
{
char buffer[6];
snprintf(buffer, sizeof(buffer), "%d.%02d", constants.FW_Version_major, constants.FW_Version_minor);
return String(buffer);
}
if (var == "FS_VERSION")
return String(globals.FlashVersion);
if (var == "GIT_REV")
return String(constants.GitHash);
if (var == "SHOW_DTC_TABLE") if (var == "SHOW_DTC_TABLE")
return globals.systemStatus == sysStat_Error ? "" : "hidden"; return globals.systemStatus == sysStat_Error ? "" : "hidden";
if (var == "SHOW_RESP_MESSAGE")
return StatusResponseMessage_Type != RESPMSG_HIDE ? "" : "hidden";
if (var == "RESP_MESSAGE_TYPE")
{
switch (StatusResponseMessage_Type)
{
case RESPMSG_SUCCESS:
return "success";
case RESPMSG_INFO:
return "info";
case RESPMSG_WARNING:
return "warning";
case RESPMSG_DANGER:
return "danger";
default:
return "info";
}
}
if (var == "RESP_MESSAGE")
return String(StatusResponseMessage);
if (var == "BAT_REMAIN_CAPACITY") if (var == "BAT_REMAIN_CAPACITY")
return String(globals.battery_level); return String(globals.battery_level);
if (var == "DEVICENAME")
if (var == "DEVICE_NAME")
return String(globals.DeviceName); return String(globals.DeviceName);
if (var == "BATTERY_TYPE")
return String(ConfigData.batteryType);
if (var == "BAT_VOLTAGE") if (var == "BAT_VOLTAGE")
return String((float)globals.loadvoltage_mV / 1000.0); return String((float)globals.loadvoltage_mV / 1000.0);
if (var == "PERSISTANCE_CHECKSUM")
{
char buffer[7];
sprintf(buffer, "0x%04X", PersistenceData.checksum);
return String(buffer);
}
if (var == "WRITE_CYCLE_COUNT")
return String(PersistenceData.writeCycleCounter);
if (var == "PERSISTENCE_MARKER")
return String(globals.eePersistanceAdress);
if (var == "EEPROM_VERSION")
return String(ConfigData.EEPROM_Version);
if (var == "CONFIG_CHECKSUM")
{
char buffer[7];
sprintf(buffer, "0x%04X", ConfigData.checksum);
return String(buffer);
}
if (var == "DTC_TABLE") if (var == "DTC_TABLE")
{ {
String temp; String temp = "";
char buff_timestamp[16]; // Format: DD-hh:mm:ss:xxx char buff_timestamp[16]; // Format: DD-hh:mm:ss:xxx
for (uint32_t i = 0; i < MAX_DTC_STORAGE; i++) for (uint32_t i = 0; i < MAX_DTC_STORAGE; i++)
{ {
if (DTCStorage[i].Number > 0) if (DTCStorage[i].Number < DTC_LAST_DTC)
{ {
sprintf(buff_timestamp, "%02d-%02d:%02d:%02d:%03d", sprintf(buff_timestamp, "%02d-%02d:%02d:%02d:%03d",
DTCStorage[i].timestamp / 86400000, // Days DTCStorage[i].timestamp / 86400000, // Days
@ -116,8 +122,23 @@ String processor(const String &var)
DTCStorage[i].timestamp / 1000 % 60, // Seconds DTCStorage[i].timestamp / 1000 % 60, // Seconds
DTCStorage[i].timestamp % 1000); // milliseconds DTCStorage[i].timestamp % 1000); // milliseconds
temp = "<tr><td>" + String(buff_timestamp); temp = temp + "<tr data-dtc=" + String(DTCStorage[i].Number);
temp = temp + " data-debugval=" + String(DTCStorage[i].debugVal) + "><td>" + String(buff_timestamp);
temp = temp + "</td><td>" + String(DTCStorage[i].Number) + "</td><td>"; temp = temp + "</td><td>" + String(DTCStorage[i].Number) + "</td><td>";
temp = temp + "<img src=static/img/";
switch (DTCStorage[i].severity)
{
case DTC_CRITICAL:
temp = temp + "critical";
break;
case DTC_WARN:
temp = temp + "warn";
break;
case DTC_INFO:
temp = temp + "info";
break;
}
temp = temp + ".png></td><td>";
if (DTCStorage[i].active == DTC_ACTIVE) if (DTCStorage[i].active == DTC_ACTIVE)
temp = temp + "active"; temp = temp + "active";
@ -174,20 +195,15 @@ String processor(const String &var)
if (var == "NAME_FAC_3") if (var == "NAME_FAC_3")
return FACTION_3_NAME; return FACTION_3_NAME;
if (var == "TITLE") if (var == "BATTERY_SELECT_OPTIONS")
return DEVICE_NAME;
if (var == "BATTERY_LEVEL")
{ {
return String(globals.battery_level); String temp;
} for (uint32_t i = 0; i < BatteryString_Elements; i++)
if (var == "BATTERY_TYPE") {
{ String selected = ConfigData.batteryType == i ? " selected " : "";
return String(BatteryString[ConfigData.batteryType]); temp = temp + "<option value=\"" + i + "\"" + selected + ">" + BatteryString[i] + "</option>";
} }
if (var == "BATTERY_VOLTAGE") return temp;
{
return String((float)globals.loadvoltage_mV / 1000.0);
} }
return String(); return String();
@ -196,19 +212,24 @@ String processor(const String &var)
void Webserver_Callback(AsyncWebServerRequest *request) void Webserver_Callback(AsyncWebServerRequest *request)
{ {
request->send(LittleFS, "/index.htm", "text/html", false, processor); request->send(LittleFS, "/index.htm", "text/html", false, processor);
StatusResponseMessage_Type = RESPMSG_HIDE;
} }
void WebserverPOST_Callback(AsyncWebServerRequest *request) void WebserverPOST_Callback(AsyncWebServerRequest *request)
{ {
request->send(LittleFS, "/post.htm", "text/html", false, processor);
Debug_pushMessage("POST:\n");
int paramsNr = request->params(); int paramsNr = request->params();
for (int i = 0; i < paramsNr; i++) for (int i = 0; i < paramsNr; i++)
{ {
AsyncWebParameter *p = request->getParam(i); AsyncWebParameter *p = request->getParam(i);
if (p->name() == "commandInput") Debug_pushMessage("%s : %s\n", p->name().c_str(), p->value().c_str());
WebserverCommands_Callback(p->value());
// begin: POST Form Settings
if (p->name() == "cmdsubmit")
globals.requestEEAction = EE_CFG_SAVE;
// end: POST Form Settings
} }
request->send(LittleFS, "/index.htm", "text/html", false, processor);
} }
void WebserverNotFound_Callback(AsyncWebServerRequest *request) void WebserverNotFound_Callback(AsyncWebServerRequest *request)
@ -216,41 +237,6 @@ void WebserverNotFound_Callback(AsyncWebServerRequest *request)
request->send(404, "text/html", "Not found"); request->send(404, "text/html", "Not found");
} }
void WebserverCommands_Callback(String input)
{
String command = input.substring(0, input.indexOf(' '));
command.toUpperCase();
StatusResponseMessage_Type = RESPMSG_HIDE;
if (command == "RESET")
{
strcpy(StatusResponseMessage, "Counter Reset done");
StatusResponseMessage_Type = RESPMSG_SUCCESS;
PersistenceData.faction_1_timer = 0;
PersistenceData.faction_2_timer = 0;
PersistenceData.faction_3_timer = 0;
PersistenceData.activeFaction = NONE;
}
else if (command == "BAT3S")
{
strcpy(StatusResponseMessage, "Set BatteryType to LiPo 3S");
StatusResponseMessage_Type = RESPMSG_SUCCESS;
ConfigData.batteryType = BATTERY_LIPO_3S;
globals.requestEEAction = EE_CFG_SAVE;
}
else if (command == "BAT2S")
{
strcpy(StatusResponseMessage, "Set BatteryType to LiPo 2S");
StatusResponseMessage_Type = RESPMSG_SUCCESS;
ConfigData.batteryType = BATTERY_LIPO_2S;
globals.requestEEAction = EE_CFG_SAVE;
}
}
void GetFlashVersion(char *buff, size_t buff_size) void GetFlashVersion(char *buff, size_t buff_size)
{ {
File this_file = LittleFS.open("version", "r"); File this_file = LittleFS.open("version", "r");
@ -273,7 +259,7 @@ void WebserverFirmwareUpdate_Callback(AsyncWebServerRequest *request, const Stri
if (!index) if (!index)
{ {
Serial.println("Update"); Debug_pushMessage("Update");
size_t content_len = request->contentLength(); size_t content_len = request->contentLength();
int cmd = (filename.indexOf(".fs") > -1) ? U_FS : U_FLASH; int cmd = (filename.indexOf(".fs") > -1) ? U_FS : U_FLASH;
Update.runAsync(true); Update.runAsync(true);
@ -289,7 +275,7 @@ void WebserverFirmwareUpdate_Callback(AsyncWebServerRequest *request, const Stri
} }
else else
{ {
Serial.printf("Progress: %d%%\n", (Update.progress() * 100) / Update.size()); Debug_pushMessage("Progress: %d%%\n", (Update.progress() * 100) / Update.size());
} }
if (final) if (final)
@ -304,8 +290,7 @@ void WebserverFirmwareUpdate_Callback(AsyncWebServerRequest *request, const Stri
} }
else else
{ {
Serial.println("Update complete"); Debug_pushMessage("Update complete\n");
Serial.flush();
globals.systemStatus = sysStat_Shutdown; globals.systemStatus = sysStat_Shutdown;
} }
} }
@ -313,31 +298,68 @@ void WebserverFirmwareUpdate_Callback(AsyncWebServerRequest *request, const Stri
void WebserverEERestore_Callback(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final) void WebserverEERestore_Callback(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final)
{ {
bool ee_done = false; bool ee_done = false;
bool validext = false; static bool validext = false;
static char *buffer = NULL;
static uint32_t read_ptr = 0;
DeserializationError error;
if (!index) if (!index)
{ {
Serial.println("EEPROM restore");
validext = (filename.indexOf(".ee.json") > -1); validext = (filename.indexOf(".ee.json") > -1);
if (validext)
{
buffer = (char *)malloc(1536);
read_ptr = 0;
if (buffer == NULL)
Debug_pushMessage("malloc() failed for EEPROM-Restore");
}
} }
if (validext) if (buffer != NULL)
{ {
Serial.println("Restoring EEPROM-Stuff"); memcpy(buffer + read_ptr, data, len);
read_ptr = read_ptr + len;
} }
if (final) if (final)
{ {
if (buffer != NULL)
{
Serial.print(buffer);
StaticJsonDocument<1536> doc;
error = deserializeJson(doc, buffer);
if (error)
{
Debug_pushMessage("deserializeJson() failed: %s\n", error.f_str());
}
else
{
ConfigData.batteryType = (batteryType_t)doc["config"]["batteryType"].as<uint32_t>();
ConfigData.EEPROM_Version = doc["config"]["EEPROM_Version"].as<uint32_t>();
PersistenceData.writeCycleCounter = doc["persis"]["writeCycleCounter"].as<uint16_t>();
PersistenceData.activeFaction = (factions_t)doc["persis"]["activeFaction"].as<uint32_t>();
PersistenceData.faction_1_timer = doc["persis"]["faction_1_timer"].as<uint32_t>();
PersistenceData.faction_2_timer = doc["persis"]["faction_2_timer"].as<uint32_t>();
PersistenceData.faction_3_timer = doc["persis"]["faction_3_timer"].as<uint32_t>();
PersistenceData.checksum = doc["persis"]["checksum"].as<uint32_t>();
ee_done = true;
}
}
free(buffer);
AsyncWebServerResponse *response = request->beginResponse(302, "text/plain", "Please wait while the device reboots"); AsyncWebServerResponse *response = request->beginResponse(302, "text/plain", "Please wait while the device reboots");
response->addHeader("Refresh", "20"); response->addHeader("Refresh", "20");
response->addHeader("Location", "/"); response->addHeader("Location", "/");
request->send(response); request->send(response);
if (ee_done) if (ee_done)
{ {
Serial.println("Update complete"); Debug_pushMessage("Update complete");
Serial.flush();
globals.systemStatus = sysStat_Shutdown; globals.systemStatus = sysStat_Shutdown;
} }
else else
@ -355,13 +377,16 @@ void WebServerEEJSON_Callback(AsyncWebServerRequest *request)
char buffer[16]; char buffer[16];
fwinfo["DeviceName"] = globals.DeviceName; fwinfo["DeviceName"] = globals.DeviceName;
fwinfo["FW-Version"] = QUOTE(SW_VERSION); sprintf(buffer, "%d.%02d", constants.Required_Flash_Version_major, constants.Required_Flash_Version_minor);
fwinfo["FW-Version"] = buffer;
fwinfo["FS-Version"] = globals.FlashVersion; fwinfo["FS-Version"] = globals.FlashVersion;
snprintf_P(buffer, sizeof(buffer), "%s", constants.GitHash);
fwinfo["Git-Hash"] = buffer;
JsonObject config = json.createNestedObject("config"); JsonObject config = json.createNestedObject("config");
config["EEPROM_Version"] = ConfigData.EEPROM_Version; config["EEPROM_Version"] = ConfigData.EEPROM_Version;
config["batteryType"] = ConfigData.batteryType;
sprintf(buffer, "0x%08X", ConfigData.checksum); sprintf(buffer, "0x%08X", ConfigData.checksum);
config["checksum"] = buffer; config["checksum"] = buffer;
@ -373,7 +398,10 @@ void WebServerEEJSON_Callback(AsyncWebServerRequest *request)
JsonObject persis = json.createNestedObject("persis"); JsonObject persis = json.createNestedObject("persis");
persis["writeCycleCounter"] = PersistenceData.writeCycleCounter; persis["writeCycleCounter"] = PersistenceData.writeCycleCounter;
persis["activeFaction"] = PersistenceData.activeFaction;
persis["faction_1_timer"] = PersistenceData.faction_1_timer;
persis["faction_2_timer"] = PersistenceData.faction_2_timer;
persis["faction_3_timer"] = PersistenceData.faction_3_timer;
sprintf(buffer, "0x%08X", PersistenceData.checksum); sprintf(buffer, "0x%08X", PersistenceData.checksum);
persis["checksum"] = buffer; persis["checksum"] = buffer;
@ -383,3 +411,51 @@ void WebServerEEJSON_Callback(AsyncWebServerRequest *request)
request->send(response); request->send(response);
} }
void WebsocketEvent_Callback(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len)
{
switch (type)
{
case WS_EVT_CONNECT:
Debug_pushMessage("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str());
break;
case WS_EVT_DISCONNECT:
Debug_pushMessage("WebSocket client #%u disconnected\n", client->id());
break;
case WS_EVT_DATA:
Websocket_HandleMessage(arg, data, len);
break;
case WS_EVT_PONG:
case WS_EVT_ERROR:
break;
}
}
void Websocket_HandleMessage(void *arg, uint8_t *data, size_t len)
{
AwsFrameInfo *info = (AwsFrameInfo *)arg;
if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT)
{
data[len] = 0;
Debug_pushMessage("Got WebSocket Message: %s \n", (char *)data);
if (strcmp((char *)data, "start") == 0)
{
SetDebugportStatus(dbg_Webui, enabled);
}
else if (strcmp((char *)data, "stop") == 0)
{
SetDebugportStatus(dbg_Webui, disabled);
}
else if (strcmp((char *)data, "foo") == 0)
{
Debug_pushMessage("Got WebSocket Message 'foo' from client\n");
}
}
}
void Websocket_PushLiveDebug(String Message)
{
webSocket.textAll(Message + "\n");
}