12 changed files with 1544 additions and 1352 deletions
-
0html/accesspoint.html
-
0html/accesspoint_EN.html
-
727html/management.html
-
0html/management_EN.html
-
639html/website.html
-
101processHtml.py
-
6src/HTMLaccesspoint.h
-
2src/HTMLaccesspoint_EN.h
-
728src/HTMLmanagement.h
-
2src/HTMLmanagement_EN.h
-
19src/main.cpp
-
640src/websiteMgmt.h
@ -0,0 +1,727 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html lang="de"> |
||||
|
<head> |
||||
|
<title>ESPuino-Konfiguration</title> |
||||
|
<meta charset="utf-8"> |
||||
|
<meta name="viewport" content="width=device-width, initial-scale=1"> |
||||
|
<link rel="stylesheet" href="https://ts-cs.de/tonuino/css/bootstrap.min.css"> |
||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css"/> |
||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css"/> |
||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css"/> |
||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/11.0.2/css/bootstrap-slider.min.css" /> |
||||
|
<script src="https://ts-cs.de/tonuino/js/jquery.min.js"></script> |
||||
|
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"></script> |
||||
|
<script src="https://ts-cs.de/tonuino/js/popper.min.js"></script> |
||||
|
<script src="https://ts-cs.de/tonuino/js/bootstrap.min.js"></script> |
||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"></script> |
||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script> |
||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/11.0.2/bootstrap-slider.min.js"></script> |
||||
|
<style type="text/css"> |
||||
|
.filetree { |
||||
|
border: 1px solid black; |
||||
|
height: 200px; |
||||
|
margin: 0em 0em 1em 0em; |
||||
|
overflow-y: scroll; |
||||
|
} |
||||
|
.slider.slider-horizontal { |
||||
|
width: 60%; |
||||
|
margin-left: 1em; |
||||
|
margin-right: 1em; |
||||
|
|
||||
|
} |
||||
|
.slider-handle{ |
||||
|
height: 30px; |
||||
|
width: 30px; |
||||
|
top: -5px; |
||||
|
} |
||||
|
|
||||
|
legend.scheduler-border { |
||||
|
width:inherit; /* Or auto */ |
||||
|
padding:0 10px; /* To give a bit of padding on the left and right */ |
||||
|
border-bottom:none; |
||||
|
} |
||||
|
|
||||
|
.icon-pos{ |
||||
|
top: 0.3em; |
||||
|
position: relative; |
||||
|
} |
||||
|
.reboot{ |
||||
|
color:white; |
||||
|
} |
||||
|
.reboot:hover{ |
||||
|
color: orange; |
||||
|
} |
||||
|
|
||||
|
.fa-sync:hover { |
||||
|
color: #666666; |
||||
|
} |
||||
|
|
||||
|
.clickForRefresh { |
||||
|
text-align: center; |
||||
|
color: gray; |
||||
|
cursor: pointer; |
||||
|
margin-top: 5em; |
||||
|
} |
||||
|
|
||||
|
.clickForRefresh:hover { |
||||
|
color: darkgray; |
||||
|
} |
||||
|
|
||||
|
.filetree-container { |
||||
|
position: relative; |
||||
|
} |
||||
|
|
||||
|
.indexing-progress { |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
position: absolute; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
opacity: 0.7; |
||||
|
display: none; |
||||
|
} |
||||
|
|
||||
|
.refreshAction{ |
||||
|
text-align: right; |
||||
|
font-size: 0.8em; |
||||
|
} |
||||
|
|
||||
|
.refreshAction:hover{ |
||||
|
cursor: pointer; |
||||
|
color: darkgray; |
||||
|
} |
||||
|
|
||||
|
.overlay { |
||||
|
z-index: 9; |
||||
|
opacity: 0.8; |
||||
|
background: #1a1919; |
||||
|
height: 200px; |
||||
|
display: none; |
||||
|
width: 100%; |
||||
|
} |
||||
|
</style> |
||||
|
</head> |
||||
|
<body> |
||||
|
<nav class="navbar navbar-expand-sm bg-primary navbar-dark"> |
||||
|
<div class="col-md-12"> |
||||
|
<a class="float-left navbar-brand"> |
||||
|
<img src="https://raw.githubusercontent.com/biologist79/Tonuino-ESP32-I2S/master/html/tonuino_logo.png" |
||||
|
width="30" height="30" class="d-inline-block align-top" alt=""/> |
||||
|
Tonuino |
||||
|
</a> |
||||
|
|
||||
|
<a class="reboot float-right nav-link" href="/restart"><i class="fas fa-power-off"></i> Neustart</a> |
||||
|
</div> |
||||
|
</nav> |
||||
|
<br/> |
||||
|
<nav> |
||||
|
<div class="container nav nav-tabs" id="nav-tab" role="tablist"> |
||||
|
<a class="nav-item nav-link active" id="nav-rfid-tab" data-toggle="tab" href="#nav-rfid" role="tab" aria-controls="nav-rfid" aria-selected="true"><i class="fas fa-dot-circle"></i> RFID</a> |
||||
|
<a class="nav-item nav-link" id="nav-wifi-tab" data-toggle="tab" href="#nav-wifi" role="tab" aria-controls="nav-wifi" aria-selected="false"><i class="fas fa-wifi"></i><span class=".d-sm-none .d-md-block"> WLAN</span></a> |
||||
|
<a class="nav-item nav-link" id="nav-mqtt-tab" data-toggle="tab" href="#nav-mqtt" role="tab" aria-controls="nav-mqtt" aria-selected="false"><i class="fas fa-network-wired"></i> MQTT</a> |
||||
|
<a class="nav-item nav-link" id="nav-ftp-tab" data-toggle="tab" href="#nav-ftp" role="tab" aria-controls="nav-ftp" aria-selected="false"><i class="fas fa-folder"></i> FTP</a> |
||||
|
<a class="nav-item nav-link" id="nav-general-tab" data-toggle="tab" href="#nav-general" role="tab" aria-controls="nav-general" aria-selected="false"><i class="fas fa-sliders-h"></i> Allgemein</a> |
||||
|
<a class="nav-item nav-link" id="nav-tools-tab" data-toggle="tab" href="#nav-tools" role="tab" aria-controls="nav-tools" aria-selected="false"><i class="fas fa-wrench"></i> Tools</a> |
||||
|
</div> |
||||
|
</nav> |
||||
|
<br> |
||||
|
<div class="tab-content" id="nav-tabContent"> |
||||
|
<div class="tab-pane fade" id="nav-wifi" role="tabpanel" aria-labelledby="nav-wifi-tab"> |
||||
|
<div class="container" id="wifiConfig"> |
||||
|
<form action="#wifiConfig" method="POST" onsubmit="wifiConfig('wifiConfig'); return false"> |
||||
|
<div class="form-group col-md-12"> |
||||
|
<label for="ssid">WLAN-Name (SSID):</label> |
||||
|
<input type="text" class="form-control" id="ssid" placeholder="SSID" name="ssid" required> |
||||
|
<div class="invalid-feedback"> |
||||
|
Bitte SSID des WLANs eintragen. |
||||
|
</div> |
||||
|
<label for="pwd">Passwort:</label> |
||||
|
<input type="password" class="form-control" id="pwd" placeholder="Passwort" name="pwd" required> |
||||
|
<label for="hostname">Tonuino-Name (Hostname):</label> |
||||
|
<input type="text" class="form-control" id="hostname" placeholder="tonuino" name="hostname" |
||||
|
value="%HOSTNAME%" pattern="^[^-\.]{2,32}" required> |
||||
|
</div> |
||||
|
<br> |
||||
|
<div class="text-center"> |
||||
|
<button type="reset" class="btn btn-secondary">Reset</button> |
||||
|
<button type="submit" class="btn btn-primary">Absenden</button> |
||||
|
</div> |
||||
|
</form> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="tab-pane fade show active" id="nav-rfid" role="tabpanel" aria-labelledby="nav-rfid-tab"> |
||||
|
<div class="container" id="rfidMusicTags"> |
||||
|
<fieldset> |
||||
|
<legend>RFID-Zuweisungen</legend> |
||||
|
<form action="#rfidMusicTags" method="POST" onsubmit="rfidAssign('rfidMusicTags'); return false"> |
||||
|
<div class="form-group col-md-12"> |
||||
|
<label for="rfidIdMusic">RFID-Chip-Nummer (12-stellig)</label> |
||||
|
<input type="text" class="form-control" id="rfidIdMusic" maxlength="12" pattern="[0-9]{12}" |
||||
|
placeholder="%RFID_TAG_ID%" name="rfidIdMusic" required> |
||||
|
<label for="fileOrUrl">Datei, Verzeichnis oder URL (^ und # als Zeichen nicht erlaubt)</label> |
||||
|
<input type="text" class="form-control" id="fileOrUrl" maxlength="255" placeholder="z.B. /mp3/Hoerspiele/Yakari/Yakari_und_seine_Freunde.mp3" pattern="^[^\^#]+$" name="fileOrUrl" required> |
||||
|
<div class="filetree-container"> |
||||
|
<div id="filebrowser"> |
||||
|
<div class="filetree demo" id="filetree"></div> |
||||
|
<div class="refreshAction"> |
||||
|
<span id="refreshAction" data-toggle="tooltip" data-placement="top" title="Datei Liste aktualisieren."><i class="fas fa-sync fa-1x"></i> Dateiliste aktualisieren</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div id="indexing-progress" class="indexing-progress overlay"> |
||||
|
<div style="text-align: center; color:white; margin-top:2em;"> |
||||
|
<div><i class="fas fa-sync fa-spin fa-2x"></i> <br><br> Der Prozess kann mehrere Minuten dauern...</div> |
||||
|
<div id="currentProcessedFile"></div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<label for="playMode">Abspielmodus</label> |
||||
|
<select class="form-control" id="playMode" name="playMode"> |
||||
|
<option class="option-file" value="1">Einzelner Titel</option> |
||||
|
<option class="option-file" value="2">Einzelner Titel (Endlosschleife)</option> |
||||
|
<option class="option-file-and-folder" value="3">Hörbuch</option> |
||||
|
<option class="option-file-and-folder" value="4">Hörbuch (Endlosschleife)</option> |
||||
|
<option class="option-folder" value="5">Alle Titel eines Verzeichnis (sortiert)</option> |
||||
|
<option class="option-folder" value="6">Alle Titel eines Verzeichnis (zufällig)</option> |
||||
|
<option class="option-folder" value="7">Alle Titel eines Verzeichnis (sortiert, Endlosschleife)</option> |
||||
|
<option class="option-folder" value="9">Alle Titel eines Verzeichnis (zufällig, Endlosschleife)</option> |
||||
|
<option class="option-stream" value="8">Webradio</option> |
||||
|
</select> |
||||
|
</div> |
||||
|
<br> |
||||
|
<div class="text-center"> |
||||
|
<button type="reset" class="btn btn-secondary">Reset</button> |
||||
|
<button type="submit" class="btn btn-primary">Absenden</button> |
||||
|
</div> |
||||
|
</form> |
||||
|
</fieldset> |
||||
|
</div> |
||||
|
|
||||
|
<br> |
||||
|
<br> |
||||
|
<div class="container" id="rfidModTags"> |
||||
|
<fieldset> |
||||
|
<legend>RFID-Modifkationen</legend> |
||||
|
<form class="needs-validation" action="#rfidModTags" method="POST" onsubmit="rfidMods('rfidModTags'); return false"> |
||||
|
<div class="form-group col-md-12"> |
||||
|
<label for="rfidIdMod">RFID-Chip-Nummer (12-stellig)</label> |
||||
|
<input type="text" class="form-control" id="rfidIdMod" maxlength="12" pattern="[0-9]{12}" |
||||
|
placeholder="%RFID_TAG_ID%" name="rfidIdMod" required> |
||||
|
<div class="invalid-feedback"> |
||||
|
Bitte eine 12-stellige Zahl eingeben. |
||||
|
</div> |
||||
|
<label for="modId">Konfiguraiton</label> |
||||
|
<select class="form-control" id="modId" name="modId"> |
||||
|
<option value="100">Tastensperre</option> |
||||
|
<option value="101">Schlafen nach 15 Minuten</option> |
||||
|
<option value="102">Schlafen nach 30 Minuten</option> |
||||
|
<option value="103">Schlafen nach 1 Stunde</option> |
||||
|
<option value="104">Schlafen nach 2 Stunden</option> |
||||
|
<option value="105">Schlafen nach Ende des Titels</option> |
||||
|
<option value="106">Schlafen nach Ende der Playlist</option> |
||||
|
<option value="107">Schlafen nach fünf Titeln</option> |
||||
|
<option value="110">Wiederhole Playlist (endlos)</option> |
||||
|
<option value="111">Wiederhole Titel (endlos)</option> |
||||
|
<option value="112">Dimme LEDs (Nachtmodus)</option> |
||||
|
<option value="130">Aktiviere/deaktive WLAN</option> |
||||
|
</select> |
||||
|
</div> |
||||
|
<br> |
||||
|
<div class="text-center"> |
||||
|
<button type="reset" class="btn btn-secondary">Reset</button> |
||||
|
<button type="submit" class="btn btn-primary">Absenden</button> |
||||
|
</div> |
||||
|
</form> |
||||
|
</fieldset> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="tab-pane fade" id="nav-mqtt" role="tabpanel" aria-labelledby="nav-mqtt-tab"> |
||||
|
<div class="container" id="mqttConfig"> |
||||
|
|
||||
|
<form class="needs-validation" action="#mqttConfig" method="POST" |
||||
|
onsubmit="mqttSettings('mqttConfig'); return false"> |
||||
|
<div class="form-check col-md-12"> |
||||
|
<input class="form-check-input" type="checkbox" value="1" id="mqttEnable" name="mqttEnable" %MQTT_ENABLE%> |
||||
|
<label class="form-check-label" for="mqttEnable"> |
||||
|
MQTT aktivieren |
||||
|
</label> |
||||
|
</div> |
||||
|
<div class="form-group my-2 col-md-12"> |
||||
|
<label for="mqttServer">MQTT-Server</label> |
||||
|
<input type="text" class="form-control" id="mqttServer" minlength="7" maxlength="%MQTT_SERVER_LENGTH%" |
||||
|
placeholder="z.B. 192.168.2.89" name="mqttServer" value="%MQTT_SERVER%"> |
||||
|
<label for="mqttUser">MQTT-Benutzername (optional):</label> |
||||
|
<input type="text" class="form-control" id="mqttUser" maxlength="%MQTT_USER_LENGTH%" |
||||
|
placeholder="Benutzername" name="mqttUser" value="%MQTT_USER%"> |
||||
|
<label for="mqttPwd">Passwort (optional):</label> |
||||
|
<input type="password" class="form-control" id="mqttPwd" maxlength="%MQTT_PWD_LENGTH%" |
||||
|
placeholder="Passwort" name="mqttPwd" value="%MQTT_PWD%"> |
||||
|
</div> |
||||
|
<br> |
||||
|
<div class="text-center"> |
||||
|
<button type="reset" class="btn btn-secondary">Reset</button> |
||||
|
<button type="submit" class="btn btn-primary">Absenden</button> |
||||
|
</div> |
||||
|
</form> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="tab-pane fade" id="nav-ftp" role="tabpanel" aria-labelledby="nav-ftp-tab"> |
||||
|
<div class="container" id="ftpConfig"> |
||||
|
|
||||
|
<form action="#ftpConfig" method="POST" onsubmit="ftpSettings('ftpConfig'); return false"> |
||||
|
<div class="form-group col-md-12"> |
||||
|
<label for="ftpUser">FTP-Benutzername:</label> |
||||
|
<input type="text" class="form-control" id="ftpUser" maxlength="%FTP_USER_LENGTH%" |
||||
|
placeholder="Benutzername" name="ftpUser" value="%FTP_USER%" required> |
||||
|
<label for="pwd">Passwort:</label> |
||||
|
<input type="password" class="form-control" id="ftpPwd" maxlength="%FTP_PWD_LENGTH%" placeholder="Passwort" |
||||
|
name="ftpPwd" value="%FTP_PWD%" required> |
||||
|
</div> |
||||
|
<br> |
||||
|
<div class="text-center"> |
||||
|
<button type="reset" class="btn btn-secondary">Reset</button> |
||||
|
<button type="submit" class="btn btn-primary">Absenden</button> |
||||
|
</div> |
||||
|
</form> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="tab-pane fade" id="nav-general" role="tabpanel" aria-labelledby="nav-general-tab"> |
||||
|
<div class="container" id="generalConfig"> |
||||
|
|
||||
|
<form action="#generalConfig" method="POST" onsubmit="genSettings('generalConfig'); return false"> |
||||
|
<div class="form-group col-md-12"> |
||||
|
<fieldset> |
||||
|
<legend class="w-auto">Lautstärke</legend> |
||||
|
<label for="initialVolume">Nach dem Einschalten</label> |
||||
|
<div class="text-center"> |
||||
|
<i class="fas fa-volume-down fa-2x .icon-pos"></i> <input data-provide="slider" type="number" data-slider-min="1" data-slider-max="21" min="1" max="21" class="form-control" id="initialVolume" name="initialVolume" |
||||
|
data-slider-value="%INIT_VOLUME%" value="%INIT_VOLUME%" required> <i class="fas fa-volume-up fa-2x .icon-pos"></i></div> |
||||
|
<br> |
||||
|
<label for="maxVolumeSpeaker">Maximal Lautsprecher</label> |
||||
|
<div class="text-center"> |
||||
|
<i class="fas fa-volume-down fa-2x .icon-pos"></i> <input data-provide="slider" type="number" data-slider-min="1" data-slider-max="21" min="1" max="21" class="form-control" id="maxVolumeSpeaker" name="maxVolumeSpeaker" |
||||
|
data-slider-value="%MAX_VOLUME_SPEAKER%" value="%MAX_VOLUME_SPEAKER%" required> <i class="fas fa-volume-up fa-2x .icon-pos"></i> |
||||
|
</div> |
||||
|
<br> |
||||
|
<label for="maxVolumeHeadphone">Maximal Kopfhörer</label> |
||||
|
<div class="text-center"> |
||||
|
<i class="fas fa-volume-down fa-2x .icon-pos"></i> <input data-provide="slider" type="number" data-slider-min="1" data-slider-max="21" min="1" max="21" class="form-control" id="maxVolumeHeadphone" name="maxVolumeHeadphone" |
||||
|
data-slider-value="%MAX_VOLUME_HEADPHONE%" value="%MAX_VOLUME_HEADPHONE%" required> <i class="fas fa-volume-up fa-2x .icon-pos"></i> |
||||
|
</div> |
||||
|
</fieldset> |
||||
|
</div> |
||||
|
<br> |
||||
|
<div class="form-group col-md-12"> |
||||
|
<fieldset > |
||||
|
<legend class="w-auto">Neopixel (Helligkeit)</legend> |
||||
|
<label for="initBrightness">Nach dem Einschalten:</label> |
||||
|
<div class="text-center"> |
||||
|
<i class="far fa-sun fa-2x .icon-pos"></i> |
||||
|
<input data-provide="slider" type="number" data-slider-min="0" data-slider-max="255" min="0" max="255" class="form-control" id="initBrightness" name="initBrightness" |
||||
|
data-slider-value="%INIT_LED_BRIGHTNESS%" value="%INIT_LED_BRIGHTNESS%" required><i class="fas fa-sun fa-2x .icon-pos"></i> |
||||
|
</div> |
||||
|
|
||||
|
<label for="nightBrightness">Im Nachtmodus</label> |
||||
|
<div class="text-center"> |
||||
|
<i class="far fa-sun fa-2x .icon-pos"></i><input data-provide="slider" type="number" data-slider-min="0" data-slider-max="255" min="0" max="255" class="form-control" id="nightBrightness" name="nightBrightness" data-slider-value="%NIGHT_LED_BRIGHTNESS%" value="%NIGHT_LED_BRIGHTNESS%" required><i class="fas fa-sun fa-2x .icon-pos"></i> |
||||
|
</div> |
||||
|
</fieldset> |
||||
|
</div> |
||||
|
<br> |
||||
|
<div class="form-group col-md-12"> |
||||
|
<fieldset> |
||||
|
<legend>Deep Sleep</legend> |
||||
|
|
||||
|
<label for="inactivityTime">Inaktivität nach (in Minuten)</label> |
||||
|
<div class="text-center"><i class="fas fa-hourglass-start fa-2x .icon-pos"></i> <input type="number" data-provide="slider" data-slider-min="0" data-slider-max="30" min="1" max="120" class="form-control" id="inactivityTime" name="inactivityTime" |
||||
|
data-slider-value="%MAX_INACTIVITY%" value="%MAX_INACTIVITY%" required><i class="fas fa-hourglass-end fa-2x .icon-pos"></i></div> |
||||
|
</fieldset> |
||||
|
</div> |
||||
|
<br> |
||||
|
|
||||
|
<div class="form-group col-md-12"> |
||||
|
<fieldset> |
||||
|
<legend>Batterie</legend> |
||||
|
<div>Status über Neopixel anzeigen</div> |
||||
|
<br> |
||||
|
<label for="warningLowVoltage">Spannungsgrenze für Status Anzeige. |
||||
|
</label> |
||||
|
<div class="text-center"> |
||||
|
<i class="fas fa-battery-quarter fa-2x .icon-pos"></i> <input data-provide="slider" data-slider-step="0.1" data-slider-min="3.0" data-slider-max="5.0" min="3.0" max="5.0" type="text" class="form-control" id="warningLowVoltage" name="warningLowVoltage" |
||||
|
data-slider-value="%WARNING_LOW_VOLTAGE%" value="%WARNING_LOW_VOLTAGE%" pattern="^\d{1,2}(\.\d{1,3})?" required> <i class="fas fa-battery-three-quarters fa-2x .icon-pos" fa-2x .icon-pos></i> |
||||
|
</div> |
||||
|
<br> |
||||
|
<label for="voltageIndicatorLow">Unterer Akkuspannungslevel |
||||
|
</label> |
||||
|
<div class="text-center"> |
||||
|
<i class="fas fa-battery-quarter fa-2x .icon-pos"></i> <input data-provide="slider" min="2.0" data-slider-step="0.1" data-slider-min="2.0" data-slider-max="5.0" max="5.0"type="text" class="form-control" id="voltageIndicatorLow" name="voltageIndicatorLow" |
||||
|
data-slider-value="%VOLTAGE_INDICATOR_LOW%" value="%VOLTAGE_INDICATOR_LOW%" pattern="^\d{1,2}(\.\d{1,3})?" required> <i class="fas fa-battery-three-quarters fa-2x .icon-pos" fa-2x .icon-pos></i> |
||||
|
</div> |
||||
|
<br> |
||||
|
<label for="voltageIndicatorHigh">Oberer Akkuspannungslevel</label> |
||||
|
|
||||
|
<div class="text-center"> |
||||
|
<i class="fas fa-battery-quarter fa-2x .icon-pos"></i><input data-provide="slider" data-slider-step="0.1" data-slider-min="2.0" data-slider-max="5.0" min="2.0" max="5.0" type="text" class="form-control" id="voltageIndicatorHigh" name="voltageIndicatorHigh" |
||||
|
data-slider-value="%VOLTAGE_INDICATOR_HIGH%" value="%VOLTAGE_INDICATOR_HIGH%" pattern="^\d{1,2}(\.\d{1,3})?" required> <i class="fas fa-battery-three-quarters fa-2x .icon-pos" fa-2x .icon-pos></i> |
||||
|
</div> |
||||
|
|
||||
|
<br> |
||||
|
<label for="voltageCheckInterval"> Interval der Messung (in Minuten)</label> |
||||
|
<div class="text-center"><i class="fas fa-hourglass-start fa-2x .icon-pos"></i> |
||||
|
<input data-provide="slider" data-slider-min="1" data-slider-max="60" type="number" min="1" max="60" class="form-control" id="voltageCheckInterval" |
||||
|
data-slider-value="%VOLTAGE_CHECK_INTERVAL%" name="voltageCheckInterval" value="%VOLTAGE_CHECK_INTERVAL%" required><i class="fas fa-hourglass-end fa-2x .icon-pos"></i> |
||||
|
</div> |
||||
|
|
||||
|
</fieldset> |
||||
|
</div> |
||||
|
<br> |
||||
|
<div class="text-center"> |
||||
|
<button type="reset" class="btn btn-secondary">Reset</button> |
||||
|
<button type="submit" class="btn btn-primary">Absenden</button> |
||||
|
</div> |
||||
|
</form> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="tab-pane fade" id="nav-tools" role="tabpanel" aria-labelledby="nav-tools-tab"> |
||||
|
<div class="container my-5" id="importNvs"> |
||||
|
<h2>NVS-Importer</h2> |
||||
|
<form action="/upload" enctype="multipart/form-data" method="POST"> |
||||
|
<div class="form-group"> |
||||
|
<label for="nvsUpload">Hier kann eine Backup-Datei importiert werden.</label> |
||||
|
<input type="file" class="form-control-file" id="nvsUpload" name="nvsUpload" accept=".txt"> |
||||
|
</div> |
||||
|
<br> |
||||
|
<div class="text-center"> |
||||
|
<button type="submit" class="btn btn-primary">Absenden</button> |
||||
|
</div> |
||||
|
</form> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<script type="text/javascript"> |
||||
|
var DEBUG = false; |
||||
|
var lastIdclicked = ''; |
||||
|
var host = $(location).attr('hostname'); |
||||
|
|
||||
|
if (DEBUG) { |
||||
|
host = "192.168.178.114"; |
||||
|
} |
||||
|
|
||||
|
toastr.options = { |
||||
|
"closeButton": false, |
||||
|
"debug": false, |
||||
|
"newestOnTop": false, |
||||
|
"progressBar": false, |
||||
|
"positionClass": "toast-top-right", |
||||
|
"preventDuplicates": false, |
||||
|
"onclick": null, |
||||
|
"showDuration": "300", |
||||
|
"hideDuration": "1000", |
||||
|
"timeOut": "5000", |
||||
|
"extendedTimeOut": "1000", |
||||
|
"showEasing": "swing", |
||||
|
"hideEasing": "linear", |
||||
|
"showMethod": "fadeIn", |
||||
|
"hideMethod": "fadeOut" |
||||
|
}; |
||||
|
|
||||
|
function postRendering(event, data) { |
||||
|
Object.keys(data.instance._model.data).forEach(function (key, index) { |
||||
|
|
||||
|
var cur = data.instance.get_node(data.instance._model.data[key]); |
||||
|
var lastFolder = cur['id'].split('/').filter(function (el) { |
||||
|
return el.trim().length > 0; |
||||
|
}).pop(); |
||||
|
if ((/\.(mp3|MP3|ogg|wav|WAV|OGG|wma|WMA|acc|ACC|flac|FLAC)$/i).test(lastFolder)) { |
||||
|
data.instance.set_type(data.instance._model.data[key], 'audio'); |
||||
|
} else { |
||||
|
if (data.instance._model.data[key]['type'] == "file") { |
||||
|
data.instance.disable_node(data.instance._model.data[key]); |
||||
|
} |
||||
|
} |
||||
|
data.instance.rename_node(data.instance._model.data[key], lastFolder); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function renderFileTree() { |
||||
|
|
||||
|
var filesURI = "/files"; |
||||
|
if (DEBUG) { |
||||
|
filesURI = "http://" + host + "/files"; |
||||
|
} |
||||
|
$('#filetree').jstree({ |
||||
|
'core': { |
||||
|
'check_callback': true, |
||||
|
'data': { |
||||
|
url: filesURI, |
||||
|
error: function (XMLHttpRequest, textStatus, errorThrown) { |
||||
|
$('#j1_loading').hide(); |
||||
|
$("#refreshAction").hide(); |
||||
|
$('#filetree').html("<div class='clickForRefresh' ><i class='fas fa-sync fa-1x'><span id='#clickForRefresh' > Dateien suchen.</span></div>"); |
||||
|
$('#filetree').on("click", function () { |
||||
|
refreshFileList(); |
||||
|
}); |
||||
|
toastr.error("Die Verzeichnis-Liste konnte nicht geladen werden."); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
}, |
||||
|
'types': { |
||||
|
'folder': { |
||||
|
'icon': "fa fa-folder" |
||||
|
}, |
||||
|
'file': { |
||||
|
'icon': "fa fa-file" |
||||
|
}, |
||||
|
'audio': { |
||||
|
'icon': "fa fa-file-audio" |
||||
|
}, |
||||
|
'default': { |
||||
|
'icon': "fa fa-folder" |
||||
|
} |
||||
|
}, |
||||
|
'plugins': ["themes", "types"] |
||||
|
}).bind('loaded.jstree', function (event, data) { |
||||
|
postRendering(event, data); |
||||
|
if ((data.instance._model.data['#']['children'].length == 0)) { |
||||
|
toastr.info("Der SD-Karten-Index muss erzeugt werden."); |
||||
|
} |
||||
|
}).bind('refresh.jstree', function (event, data) { |
||||
|
postRendering(event, data); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
$('#filetree').on('select_node.jstree', function (e, data) { |
||||
|
$('input[name=fileOrUrl]').val(data.node.id); |
||||
|
|
||||
|
if (data.node.type == "folder") { |
||||
|
$('.option-folder').show(); |
||||
|
$('.option-file').hide(); |
||||
|
$('#playMode option').removeAttr('selected').filter('[value=3]').attr('selected', true); |
||||
|
} |
||||
|
|
||||
|
if (data.node.type == "audio") { |
||||
|
$('.option-file').show(); |
||||
|
$('.option-folder').hide(); |
||||
|
$('#playMode option').removeAttr('selected').filter('[value=1]').attr('selected', true); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
$('#refreshAction').on("click", function () { |
||||
|
refreshFileList(); |
||||
|
$("#indexing-progress").show(); |
||||
|
$("#refreshAction").hide(); |
||||
|
}); |
||||
|
|
||||
|
$('#playMode').on("change", function () { |
||||
|
if (this.value == 8) { |
||||
|
$('#filebrowser').slideUp(); |
||||
|
} else { |
||||
|
$('#filebrowser').slideDown(); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
function showFileIndexingState() { |
||||
|
$("#indexing-progress").show(); |
||||
|
$("#refreshAction").hide(); |
||||
|
} |
||||
|
|
||||
|
function hideFileIndexingState() { |
||||
|
$("#indexing-progress").hide(); |
||||
|
$("#refreshAction").show(); |
||||
|
} |
||||
|
|
||||
|
var socket = undefined; |
||||
|
var tm; |
||||
|
|
||||
|
function connect() { |
||||
|
socket = new WebSocket("ws://" + host + "/ws"); |
||||
|
|
||||
|
socket.onopen = function () { |
||||
|
setInterval(ping, 15000); |
||||
|
}; |
||||
|
|
||||
|
socket.onclose = function (e) { |
||||
|
console.log('Socket is closed. Reconnect will be attempted in 1 second.', e.reason); |
||||
|
socket = null; |
||||
|
setTimeout(function () { |
||||
|
connect(); |
||||
|
}, 5000); |
||||
|
}; |
||||
|
|
||||
|
socket.onerror = function (err) { |
||||
|
console.error('Socket encountered error: ', err.message, 'Closing socket'); |
||||
|
}; |
||||
|
|
||||
|
socket.onmessage = function(event) { |
||||
|
console.log(event.data); |
||||
|
var socketMsg = JSON.parse(event.data); |
||||
|
if (socketMsg.rfidId != null) { |
||||
|
document.getElementById('rfidIdMod').value = socketMsg.rfidId; |
||||
|
document.getElementById('rfidIdMusic').value = socketMsg.rfidId; |
||||
|
toastr.info("RFID Tag mit "+ socketMsg.rfidId + " erkannt." ); |
||||
|
|
||||
|
$("#rfidIdMusic").effect("highlight", {color:"#abf5af"}, 3000); |
||||
|
$("#rfidIdMod").effect("highlight", {color:"#abf5af"}, 3000); |
||||
|
|
||||
|
} if ("status" in socketMsg) { |
||||
|
if (socketMsg.status == "ok") { |
||||
|
toastr.success("Aktion erfolgreich ausgeführt." ); |
||||
|
} |
||||
|
} if ("pong" in socketMsg) { |
||||
|
if (socketMsg.pong == 'pong') { |
||||
|
pong(); |
||||
|
} |
||||
|
} if ("refreshFileList" in socketMsg) { |
||||
|
hideFileIndexingState(); |
||||
|
toastr.info("Die Dateiliste wurde neu erzeugt!"); |
||||
|
$('#filetree').jstree(true).refresh(); |
||||
|
|
||||
|
} |
||||
|
if ("indexingState" in socketMsg) { |
||||
|
if(socketMsg.indexingState != null) { |
||||
|
$("#currentProcessedFile").text(socketMsg.indexingState); |
||||
|
console.log(socketMsg.indexingState); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
function ping() { |
||||
|
var myObj = { |
||||
|
"ping": { |
||||
|
ping: 'ping' |
||||
|
} |
||||
|
}; |
||||
|
var myJSON = JSON.stringify(myObj); |
||||
|
socket.send(myJSON); |
||||
|
tm = setTimeout(function () { |
||||
|
toastr.warning('Die Verbindung zum Tonuino ist unterbrochen! Bitte Seite neu laden.'); |
||||
|
}, 5000); |
||||
|
} |
||||
|
|
||||
|
function pong() { |
||||
|
clearTimeout(tm); |
||||
|
} |
||||
|
|
||||
|
function refreshFileList(clickedId) { |
||||
|
lastIdclicked = clickedId; |
||||
|
var myObj = { |
||||
|
"refreshFileList": true |
||||
|
}; |
||||
|
var myJSON = JSON.stringify(myObj); |
||||
|
$("#refreshAction").hide(); |
||||
|
socket.send(myJSON); |
||||
|
showFileIndexingState(); |
||||
|
}; |
||||
|
|
||||
|
function genSettings(clickedId) { |
||||
|
lastIdclicked = clickedId; |
||||
|
var myObj = { |
||||
|
"general": { |
||||
|
iVol: document.getElementById('initialVolume').value, |
||||
|
mVolSpeaker: document.getElementById('maxVolumeSpeaker').value, |
||||
|
mVolHeadphone: document.getElementById('maxVolumeHeadphone').value, |
||||
|
iBright: document.getElementById('initBrightness').value, |
||||
|
nBright: document.getElementById('nightBrightness').value, |
||||
|
iTime: document.getElementById('inactivityTime').value, |
||||
|
vWarning: document.getElementById('warningLowVoltage').value, |
||||
|
vIndLow: document.getElementById('voltageIndicatorLow').value, |
||||
|
vIndHi: document.getElementById('voltageIndicatorHigh').value, |
||||
|
vInt: document.getElementById('voltageCheckInterval').value |
||||
|
} |
||||
|
}; |
||||
|
var myJSON = JSON.stringify(myObj); |
||||
|
socket.send(myJSON); |
||||
|
} |
||||
|
|
||||
|
function ftpSettings(clickedId) { |
||||
|
lastIdclicked = clickedId; |
||||
|
var myObj = { |
||||
|
"ftp": { |
||||
|
ftpUser: document.getElementById('ftpUser').value, |
||||
|
ftpPwd: document.getElementById('ftpPwd').value |
||||
|
} |
||||
|
}; |
||||
|
var myJSON = JSON.stringify(myObj); |
||||
|
socket.send(myJSON); |
||||
|
} |
||||
|
|
||||
|
function mqttSettings(clickedId) { |
||||
|
lastIdclicked = clickedId; |
||||
|
var val; |
||||
|
if (document.getElementById('mqttEnable').checked) { |
||||
|
val = document.getElementById('mqttEnable').value; |
||||
|
} else { |
||||
|
val = 0; |
||||
|
} |
||||
|
var myObj = { |
||||
|
"mqtt": { |
||||
|
mqttEnable: val, |
||||
|
mqttServer: document.getElementById('mqttServer').value, |
||||
|
mqttUser: document.getElementById('mqttUser').value, |
||||
|
mqttPwd: document.getElementById('mqttPwd').value |
||||
|
} |
||||
|
}; |
||||
|
var myJSON = JSON.stringify(myObj); |
||||
|
socket.send(myJSON); |
||||
|
} |
||||
|
|
||||
|
function rfidMods(clickedId) { |
||||
|
lastIdclicked = clickedId; |
||||
|
var myObj = { |
||||
|
"rfidMod": { |
||||
|
rfidIdMod: document.getElementById('rfidIdMod').value, |
||||
|
modId: document.getElementById('modId').value |
||||
|
} |
||||
|
}; |
||||
|
var myJSON = JSON.stringify(myObj); |
||||
|
socket.send(myJSON); |
||||
|
} |
||||
|
|
||||
|
function removeTrSlash(str) { |
||||
|
if (str.substr(-1) === '/') { |
||||
|
return str.substr(0, str.length - 1); |
||||
|
} |
||||
|
return str; |
||||
|
} |
||||
|
|
||||
|
function rfidAssign(clickedId) { |
||||
|
lastIdclicked = clickedId; |
||||
|
var myObj = { |
||||
|
"rfidAssign": { |
||||
|
rfidIdMusic: document.getElementById('rfidIdMusic').value, |
||||
|
fileOrUrl: removeTrSlash(document.getElementById('fileOrUrl').value), |
||||
|
playMode: document.getElementById('playMode').value |
||||
|
} |
||||
|
}; |
||||
|
var myJSON = JSON.stringify(myObj); |
||||
|
socket.send(myJSON); |
||||
|
} |
||||
|
|
||||
|
function wifiConfig(clickedId) { |
||||
|
lastIdclicked = clickedId; |
||||
|
var myObj = { |
||||
|
"wifiConfig": { |
||||
|
ssid: document.getElementById('ssid').value, |
||||
|
pwd: document.getElementById('pwd').value, |
||||
|
hostname: document.getElementById('hostname').value |
||||
|
} |
||||
|
}; |
||||
|
var myJSON = JSON.stringify(myObj); |
||||
|
socket.send(myJSON); |
||||
|
} |
||||
|
|
||||
|
$(document).ready(function () { |
||||
|
connect(); |
||||
|
renderFileTree(); |
||||
|
|
||||
|
console.log(parseInt(document.getElementById('warningLowVoltage').value)); |
||||
|
$(function () { |
||||
|
$('[data-toggle="tooltip"]').tooltip(); |
||||
|
}); |
||||
|
|
||||
|
}); |
||||
|
</script> |
||||
|
</body> |
||||
|
</html> |
@ -1,639 +0,0 @@ |
|||||
<!DOCTYPE html> |
|
||||
<html lang="de"> |
|
||||
<head> |
|
||||
<title>ESPuino-Konfiguration</title> |
|
||||
<meta charset="utf-8"> |
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|
||||
<link rel="stylesheet" href="https://ts-cs.de/tonuino/css/bootstrap.min.css"> |
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css"/> |
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css"/> |
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css"/> |
|
||||
<script src="https://ts-cs.de/tonuino/js/jquery.min.js"></script> |
|
||||
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"></script> |
|
||||
<script src="https://ts-cs.de/tonuino/js/popper.min.js"></script> |
|
||||
<script src="https://ts-cs.de/tonuino/js/bootstrap.min.js"></script> |
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"></script> |
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script> |
|
||||
<style type="text/css"> |
|
||||
.filetree { |
|
||||
border: 1px solid black; |
|
||||
height: 200px; |
|
||||
margin: 0em 0em 1em 0em; |
|
||||
overflow-y: scroll; |
|
||||
} |
|
||||
|
|
||||
.fa-sync:hover { |
|
||||
color: #666666; |
|
||||
} |
|
||||
|
|
||||
.clickForRefresh { |
|
||||
text-align: center; |
|
||||
color: gray; |
|
||||
cursor: pointer; |
|
||||
margin-top: 5em; |
|
||||
} |
|
||||
|
|
||||
.clickForRefresh:hover { |
|
||||
color: darkgray; |
|
||||
} |
|
||||
|
|
||||
.filetree-container { |
|
||||
position: relative; |
|
||||
} |
|
||||
|
|
||||
.indexing-progress { |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
left: 0; |
|
||||
opacity: 0.7; |
|
||||
display: none; |
|
||||
} |
|
||||
|
|
||||
.refreshAction{ |
|
||||
text-align: right; |
|
||||
font-size: 0.8em; |
|
||||
} |
|
||||
|
|
||||
.refreshAction:hover{ |
|
||||
cursor: pointer; |
|
||||
color: darkgray; |
|
||||
} |
|
||||
|
|
||||
.overlay { |
|
||||
z-index: 9; |
|
||||
opacity: 0.8; |
|
||||
background: #1a1919; |
|
||||
height: 200px; |
|
||||
display: none; |
|
||||
width: 100%; |
|
||||
} |
|
||||
</style> |
|
||||
</head> |
|
||||
<body> |
|
||||
<nav class="navbar navbar-expand-sm bg-primary navbar-dark"> |
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" |
|
||||
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> |
|
||||
<span class="navbar-toggler-icon"></span> |
|
||||
</button> |
|
||||
<a class="navbar-brand"> |
|
||||
<img src="https://raw.githubusercontent.com/biologist79/Tonuino-ESP32-I2S/master/html/tonuino_logo.png" |
|
||||
width="30" height="30" class="d-inline-block align-top" alt=""/> |
|
||||
Tonuino |
|
||||
</a> |
|
||||
<div class="collapse navbar-collapse" id="collapsibleNavbar"> |
|
||||
<ul class="navbar-nav mr-auto"> |
|
||||
<li class="nav-item"> |
|
||||
<a class="nav-link" href="#wifiConfig">WLAN</a> |
|
||||
</li> |
|
||||
<li class="nav-item"> |
|
||||
<a class="nav-link" href="#rfidMusicTags">RFID-Zuweisungen</a> |
|
||||
</li> |
|
||||
<li class="nav-item"> |
|
||||
<a class="nav-link" href="#rfidModTags">RFID-Modifikationen</a> |
|
||||
</li> |
|
||||
<li class="nav-item"> |
|
||||
<a class="nav-link" href="#mqttConfig">MQTT</a> |
|
||||
</li> |
|
||||
<li class="nav-item"> |
|
||||
<a class="nav-link" href="#ftpConfig">FTP</a> |
|
||||
</li> |
|
||||
<li class="nav-item"> |
|
||||
<a class="nav-link" href="#generalConfig">Allgemein</a> |
|
||||
</li> |
|
||||
<li class="nav-item"> |
|
||||
<a class="nav-link" href="#importNvs">NVS-Importer</a> |
|
||||
</li> |
|
||||
<li class="nav-item"> |
|
||||
<a class="nav-link" href="/restart" style="color: orange">Neustart Tonuino</a> |
|
||||
</li> |
|
||||
</ul> |
|
||||
</div> |
|
||||
</nav> |
|
||||
<br/> |
|
||||
<div class="container" id="wifiConfig"> |
|
||||
<h2>WLAN-Konfiguration</h2> |
|
||||
<form action="#wifiConfig" method="POST" onsubmit="wifiConfig('wifiConfig'); return false"> |
|
||||
<div class="form-group col-md-6"> |
|
||||
<label for="ssid">WLAN-Name (SSID):</label> |
|
||||
<input type="text" class="form-control" id="ssid" placeholder="SSID" name="ssid" required> |
|
||||
<div class="invalid-feedback"> |
|
||||
Bitte SSID des WLANs eintragen. |
|
||||
</div> |
|
||||
<label for="pwd">Passwort:</label> |
|
||||
<input type="password" class="form-control" id="pwd" placeholder="Passwort" name="pwd" required> |
|
||||
<label for="hostname">Tonuino-Name (Hostname):</label> |
|
||||
<input type="text" class="form-control" id="hostname" placeholder="tonuino" name="hostname" |
|
||||
value="%HOSTNAME%" pattern="^[^-\.]{2,32}" required> |
|
||||
</div> |
|
||||
<button type="reset" class="btn btn-secondary">Reset</button> |
|
||||
<button type="submit" class="btn btn-primary">Absenden</button> |
|
||||
</form> |
|
||||
<div class="messages col-md-6 my-2"></div> |
|
||||
</div> |
|
||||
<div class="container my-5" id="rfidMusicTags"> |
|
||||
<h2>RFID-Zuweisungen</h2> |
|
||||
<form action="#rfidMusicTags" method="POST" onsubmit="rfidAssign('rfidMusicTags'); return false"> |
|
||||
<div class="form-group col-md-6"> |
|
||||
<label for="rfidIdMusic">RFID-Chip-Nummer (12-stellig)</label> |
|
||||
<input type="text" class="form-control" id="rfidIdMusic" maxlength="12" pattern="[0-9]{12}" |
|
||||
placeholder="%RFID_TAG_ID%" name="rfidIdMusic" required> |
|
||||
<label for="fileOrUrl">Datei, Verzeichnis oder URL (^ und # als Zeichen nicht erlaubt)</label> |
|
||||
<input type="text" class="form-control" id="fileOrUrl" maxlength="255" placeholder="z.B. /mp3/Hoerspiele/Yakari/Yakari_und_seine_Freunde.mp3" pattern="^[^\^#]+$" name="fileOrUrl" required> |
|
||||
<div class="filetree-container"> |
|
||||
<div id="filebrowser"> |
|
||||
<div class="filetree demo" id="filetree"></div> |
|
||||
<div class="refreshAction"> |
|
||||
<span id="refreshAction" data-toggle="tooltip" data-placement="top" title="Datei Liste aktualisieren."><i class="fas fa-sync fa-1x"></i> Dateiliste aktualisieren</span> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div id="indexing-progress" class="indexing-progress overlay"> |
|
||||
<div style="text-align: center; color:white; margin-top:2em;"> |
|
||||
<div><i class="fas fa-sync fa-spin fa-2x"></i> <br><br> Der Prozess kann mehrere Minuten dauern...</div> |
|
||||
<div id="currentProcessedFile"></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<label for="playMode">Abspielmodus</label> |
|
||||
<select class="form-control" id="playMode" name="playMode"> |
|
||||
<option class="option-file" value="1">Einzelner Titel</option> |
|
||||
<option class="option-file" value="2">Einzelner Titel (Endlosschleife)</option> |
|
||||
<option class="option-file-and-folder" value="3">Hörbuch</option> |
|
||||
<option class="option-file-and-folder" value="4">Hörbuch (Endlosschleife)</option> |
|
||||
<option class="option-folder" value="5">Alle Titel eines Verzeichnis (sortiert)</option> |
|
||||
<option class="option-folder" value="6">Alle Titel eines Verzeichnis (zufällig)</option> |
|
||||
<option class="option-folder" value="7">Alle Titel eines Verzeichnis (sortiert, Endlosschleife)</option> |
|
||||
<option class="option-folder" value="9">Alle Titel eines Verzeichnis (zufällig, Endlosschleife)</option> |
|
||||
<option class="option-stream" value="8">Webradio</option> |
|
||||
</select> |
|
||||
</div> |
|
||||
<button type="reset" class="btn btn-secondary">Reset</button> |
|
||||
<button type="submit" class="btn btn-primary">Absenden</button> |
|
||||
</form> |
|
||||
<div class="messages col-md-6 my-2"></div> |
|
||||
</div> |
|
||||
<div class="container my-5" id="rfidModTags"> |
|
||||
<h2>RFID-Modifkationen</h2> |
|
||||
<form class="needs-validation" action="#rfidModTags" method="POST" onsubmit="rfidMods('rfidModTags'); return false"> |
|
||||
<div class="form-group col-md-6"> |
|
||||
<label for="rfidIdMod">RFID-Chip-Nummer (12-stellig)</label> |
|
||||
<input type="text" class="form-control" id="rfidIdMod" maxlength="12" pattern="[0-9]{12}" |
|
||||
placeholder="%RFID_TAG_ID%" name="rfidIdMod" required> |
|
||||
<div class="invalid-feedback"> |
|
||||
Bitte eine 12-stellige Zahl eingeben. |
|
||||
</div> |
|
||||
<label for="modId">Abspielmodus</label> |
|
||||
<select class="form-control" id="modId" name="modId"> |
|
||||
<option value="100">Tastensperre</option> |
|
||||
<option value="101">Schlafen nach 15 Minuten</option> |
|
||||
<option value="102">Schlafen nach 30 Minuten</option> |
|
||||
<option value="103">Schlafen nach 1 Stunde</option> |
|
||||
<option value="104">Schlafen nach 2 Stunden</option> |
|
||||
<option value="105">Schlafen nach Ende des Titels</option> |
|
||||
<option value="106">Schlafen nach Ende der Playlist</option> |
|
||||
<option value="107">Schlafen nach fünf Titeln</option> |
|
||||
<option value="110">Wiederhole Playlist (endlos)</option> |
|
||||
<option value="111">Wiederhole Titel (endlos)</option> |
|
||||
<option value="112">Dimme LEDs (Nachtmodus)</option> |
|
||||
<option value="130">Aktiviere/deaktive WLAN</option> |
|
||||
</select> |
|
||||
</div> |
|
||||
<button type="reset" class="btn btn-secondary">Reset</button> |
|
||||
<button type="submit" class="btn btn-primary">Absenden</button> |
|
||||
</form> |
|
||||
<div class="messages col-md-6 my-2"></div> |
|
||||
</div> |
|
||||
<div class="container my-5" id="mqttConfig"> |
|
||||
<h2>MQTT-Konfiguration</h2> |
|
||||
<form class="needs-validation" action="#mqttConfig" method="POST" |
|
||||
onsubmit="mqttSettings('mqttConfig'); return false"> |
|
||||
<div class="form-check col-md-6"> |
|
||||
<input class="form-check-input" type="checkbox" value="1" id="mqttEnable" name="mqttEnable" %MQTT_ENABLE%> |
|
||||
<label class="form-check-label" for="mqttEnable"> |
|
||||
MQTT aktivieren |
|
||||
</label> |
|
||||
</div> |
|
||||
<div class="form-group my-2 col-md-6"> |
|
||||
<label for="mqttServer">MQTT-Server</label> |
|
||||
<input type="text" class="form-control" id="mqttServer" minlength="7" maxlength="%MQTT_SERVER_LENGTH%" |
|
||||
placeholder="z.B. 192.168.2.89" name="mqttServer" value="%MQTT_SERVER%"> |
|
||||
<label for="mqttUser">MQTT-Benutzername (optional):</label> |
|
||||
<input type="text" class="form-control" id="mqttUser" maxlength="%MQTT_USER_LENGTH%" |
|
||||
placeholder="Benutzername" name="mqttUser" value="%MQTT_USER%"> |
|
||||
<label for="mqttPwd">Passwort (optional):</label> |
|
||||
<input type="password" class="form-control" id="mqttPwd" maxlength="%MQTT_PWD_LENGTH%" |
|
||||
placeholder="Passwort" name="mqttPwd" value="%MQTT_PWD%"> |
|
||||
</div> |
|
||||
<button type="reset" class="btn btn-secondary">Reset</button> |
|
||||
<button type="submit" class="btn btn-primary">Absenden</button> |
|
||||
</form> |
|
||||
<div class="messages col-md-6 my-2"></div> |
|
||||
</div> |
|
||||
<div class="container" id="ftpConfig"> |
|
||||
<h2>FTP-Konfiguration</h2> |
|
||||
<form action="#ftpConfig" method="POST" onsubmit="ftpSettings('ftpConfig'); return false"> |
|
||||
<div class="form-group col-md-6"> |
|
||||
<label for="ftpUser">FTP-Benutzername:</label> |
|
||||
<input type="text" class="form-control" id="ftpUser" maxlength="%FTP_USER_LENGTH%" |
|
||||
placeholder="Benutzername" name="ftpUser" value="%FTP_USER%" required> |
|
||||
<label for="pwd">Passwort:</label> |
|
||||
<input type="password" class="form-control" id="ftpPwd" maxlength="%FTP_PWD_LENGTH%" placeholder="Passwort" |
|
||||
name="ftpPwd" value="%FTP_PWD%" required> |
|
||||
</div> |
|
||||
<button type="reset" class="btn btn-secondary">Reset</button> |
|
||||
<button type="submit" class="btn btn-primary">Absenden</button> |
|
||||
</form> |
|
||||
<div class="messages col-md-6 my-2"></div> |
|
||||
</div> |
|
||||
<div class="container my-5" id="generalConfig"> |
|
||||
<h2>Allgemeine Konfiguration</h2> |
|
||||
<form action="#generalConfig" method="POST" onsubmit="genSettings('generalConfig'); return false"> |
|
||||
<div class="form-group col-md-6"> |
|
||||
<label for="initialVolume">Lautstärke nach dem Einschalten</label> |
|
||||
<input type="number" min="1" max="21" class="form-control" id="initialVolume" name="initialVolume" |
|
||||
value="%INIT_VOLUME%" required> |
|
||||
<label for="maxVolumeSpeaker">Maximale Lautstärke (Lautsprecher)</label> |
|
||||
<input type="number" min="1" max="21" class="form-control" id="maxVolumeSpeaker" name="maxVolumeSpeaker" |
|
||||
value="%MAX_VOLUME_SPEAKER%" required> |
|
||||
<label for="maxVolumeHeadphone">Maximale Lautstärke (Kopfhörer)</label> |
|
||||
<input type="number" min="1" max="21" class="form-control" id="maxVolumeHeadphone" name="maxVolumeHeadphone" |
|
||||
value="%MAX_VOLUME_HEADPHONE%" required> |
|
||||
</div> |
|
||||
<div class="form-group col-md-6"> |
|
||||
<label for="initBrightness">Neopixel-Helligkeit nach dem Einschalten</label> |
|
||||
<input type="number" min="0" max="255" class="form-control" id="initBrightness" name="initBrightness" |
|
||||
value="%INIT_LED_BRIGHTNESS%" required> |
|
||||
<label for="nightBrightness">Neopixel-Helligkeit im Nachtmodus</label> |
|
||||
<input type="number" min="0" max="255" class="form-control" id="nightBrightness" name="nightBrightness" |
|
||||
value="%NIGHT_LED_BRIGHTNESS%" required> |
|
||||
</div> |
|
||||
<div class="form-group col-md-6"> |
|
||||
<label for="inactivityTime">Deep-Sleep nach Inaktivität (Minuten)</label> |
|
||||
<input type="number" min="1" max="1440" class="form-control" id="inactivityTime" name="inactivityTime" |
|
||||
value="%MAX_INACTIVITY%" required> |
|
||||
</div> |
|
||||
<div class="form-group col-md-6"> |
|
||||
<label for="warningLowVoltage">(Optional) Spannungsgrenze (Batterie), ab der Warnung auf Neopixel angezeigt |
|
||||
wird (z.B. 3.4)</label> |
|
||||
<input type="text" class="form-control" id="warningLowVoltage" name="warningLowVoltage" |
|
||||
value="%WARNING_LOW_VOLTAGE%" pattern="^\d{1,2}(\.\d{1,3})?" required> |
|
||||
</div> |
|
||||
<div class="form-group col-md-6"> |
|
||||
<label for="voltageIndicatorLow">(Optional) Unterer Akkuspannungslevel (Batterie) für Neopixel-Anzeige (z.B. |
|
||||
3.1)</label> |
|
||||
<input type="text" class="form-control" id="voltageIndicatorLow" name="voltageIndicatorLow" |
|
||||
value="%VOLTAGE_INDICATOR_LOW%" pattern="^\d{1,2}(\.\d{1,3})?" required> |
|
||||
</div> |
|
||||
<div class="form-group col-md-6"> |
|
||||
<label for="voltageIndicatorHigh">(Optional) Oberer Akkuspannungslevel (Batterie) für Neopixel-Anzeige (z.B. |
|
||||
4.2)</label> |
|
||||
<input type="text" class="form-control" id="voltageIndicatorHigh" name="voltageIndicatorHigh" |
|
||||
value="%VOLTAGE_INDICATOR_HIGH%" pattern="^\d{1,2}(\.\d{1,3})?" required> |
|
||||
</div> |
|
||||
<div class="form-group col-md-6"> |
|
||||
<label for="voltageCheckInterval">(Optional) Häufigkeit der Spannungsmessung (Batterie) in Minuten</label> |
|
||||
<input type="number" min="1" max="180" class="form-control" id="voltageCheckInterval" |
|
||||
name="voltageCheckInterval" value="%VOLTAGE_CHECK_INTERVAL%" required> |
|
||||
</div> |
|
||||
<button type="reset" class="btn btn-secondary">Reset</button> |
|
||||
<button type="submit" class="btn btn-primary">Absenden</button> |
|
||||
</form> |
|
||||
<div class="messages col-md-6 my-2"></div> |
|
||||
</div> |
|
||||
<div class="container my-5" id="importNvs"> |
|
||||
<h2>NVS-Importer</h2> |
|
||||
<form action="/upload" enctype="multipart/form-data" method="POST"> |
|
||||
<div class="form-group"> |
|
||||
<label for="nvsUpload">Hier kann eine Backup-Datei importiert werden.</label> |
|
||||
<input type="file" class="form-control-file" id="nvsUpload" name="nvsUpload" accept=".txt"> |
|
||||
</div> |
|
||||
<button type="submit" class="btn btn-primary">Absenden</button> |
|
||||
</form> |
|
||||
<div class="messages col-md-6 my-2"></div> |
|
||||
</div> |
|
||||
<script type="text/javascript"> |
|
||||
var DEBUG = false; |
|
||||
var lastIdclicked = ''; |
|
||||
var host = $(location).attr('hostname'); |
|
||||
|
|
||||
if (DEBUG) { |
|
||||
host = "192.168.178.112"; |
|
||||
} |
|
||||
|
|
||||
toastr.options = { |
|
||||
"closeButton": false, |
|
||||
"debug": false, |
|
||||
"newestOnTop": false, |
|
||||
"progressBar": false, |
|
||||
"positionClass": "toast-top-right", |
|
||||
"preventDuplicates": false, |
|
||||
"onclick": null, |
|
||||
"showDuration": "300", |
|
||||
"hideDuration": "1000", |
|
||||
"timeOut": "5000", |
|
||||
"extendedTimeOut": "1000", |
|
||||
"showEasing": "swing", |
|
||||
"hideEasing": "linear", |
|
||||
"showMethod": "fadeIn", |
|
||||
"hideMethod": "fadeOut" |
|
||||
}; |
|
||||
|
|
||||
function postRendering(event, data) { |
|
||||
Object.keys(data.instance._model.data).forEach(function (key, index) { |
|
||||
|
|
||||
var cur = data.instance.get_node(data.instance._model.data[key]); |
|
||||
var lastFolder = cur['id'].split('/').filter(function (el) { |
|
||||
return el.trim().length > 0; |
|
||||
}).pop(); |
|
||||
if ((/\.(mp3|MP3|ogg|wav|WAV|OGG|wma|WMA|acc|ACC|flac|FLAC)$/i).test(lastFolder)) { |
|
||||
data.instance.set_type(data.instance._model.data[key], 'audio'); |
|
||||
} else { |
|
||||
if (data.instance._model.data[key]['type'] == "file") { |
|
||||
data.instance.disable_node(data.instance._model.data[key]); |
|
||||
} |
|
||||
} |
|
||||
data.instance.rename_node(data.instance._model.data[key], lastFolder); |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
function renderFileTree() { |
|
||||
|
|
||||
var filesURI = "/files"; |
|
||||
if (DEBUG) { |
|
||||
filesURI = "http://" + host + "/files"; |
|
||||
} |
|
||||
$('#filetree').jstree({ |
|
||||
'core': { |
|
||||
'check_callback': true, |
|
||||
'data': { |
|
||||
url: filesURI, |
|
||||
error: function (XMLHttpRequest, textStatus, errorThrown) { |
|
||||
$('#j1_loading').hide(); |
|
||||
$("#refreshAction").hide(); |
|
||||
$('#filetree').html("<div class='clickForRefresh' ><i class='fas fa-sync fa-1x'><span id='#clickForRefresh' > Dateien suchen.</span></div>"); |
|
||||
$('#filetree').on("click", function () { |
|
||||
refreshFileList(); |
|
||||
}); |
|
||||
toastr.error("Die Verzeichnis-Liste konnte nicht geladen werden."); |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
}, |
|
||||
'types': { |
|
||||
'folder': { |
|
||||
'icon': "fa fa-folder" |
|
||||
}, |
|
||||
'file': { |
|
||||
'icon': "fa fa-file" |
|
||||
}, |
|
||||
'audio': { |
|
||||
'icon': "fa fa-file-audio" |
|
||||
}, |
|
||||
'default': { |
|
||||
'icon': "fa fa-folder" |
|
||||
} |
|
||||
}, |
|
||||
'plugins': ["themes", "types"] |
|
||||
}).bind('loaded.jstree', function (event, data) { |
|
||||
postRendering(event, data); |
|
||||
if ((data.instance._model.data['#']['children'].length == 0)) { |
|
||||
toastr.info("Der SD-Karten-Index muss erzeugt werden."); |
|
||||
} |
|
||||
}).bind('refresh.jstree', function (event, data) { |
|
||||
postRendering(event, data); |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
$('#filetree').on('select_node.jstree', function (e, data) { |
|
||||
$('input[name=fileOrUrl]').val(data.node.id); |
|
||||
|
|
||||
if (data.node.type == "folder") { |
|
||||
$('.option-folder').show(); |
|
||||
$('.option-file').hide(); |
|
||||
$('#playMode option').removeAttr('selected').filter('[value=3]').attr('selected', true); |
|
||||
} |
|
||||
|
|
||||
if (data.node.type == "audio") { |
|
||||
$('.option-file').show(); |
|
||||
$('.option-folder').hide(); |
|
||||
$('#playMode option').removeAttr('selected').filter('[value=1]').attr('selected', true); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
$('#refreshAction').on("click", function () { |
|
||||
refreshFileList(); |
|
||||
$("#indexing-progress").show(); |
|
||||
$("#refreshAction").hide(); |
|
||||
}); |
|
||||
|
|
||||
$('#playMode').on("change", function () { |
|
||||
if (this.value == 8) { |
|
||||
$('#filebrowser').slideUp(); |
|
||||
} else { |
|
||||
$('#filebrowser').slideDown(); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
function showFileIndexingState() { |
|
||||
$("#indexing-progress").show(); |
|
||||
$("#refreshAction").hide(); |
|
||||
} |
|
||||
|
|
||||
function hideFileIndexingState() { |
|
||||
$("#indexing-progress").hide(); |
|
||||
$("#refreshAction").show(); |
|
||||
} |
|
||||
|
|
||||
var socket = undefined; |
|
||||
var tm; |
|
||||
|
|
||||
function connect() { |
|
||||
socket = new WebSocket("ws://" + host + "/ws"); |
|
||||
|
|
||||
socket.onopen = function () { |
|
||||
setInterval(ping, 15000); |
|
||||
}; |
|
||||
|
|
||||
socket.onclose = function (e) { |
|
||||
console.log('Socket is closed. Reconnect will be attempted in 1 second.', e.reason); |
|
||||
socket = null; |
|
||||
setTimeout(function () { |
|
||||
connect(); |
|
||||
}, 5000); |
|
||||
}; |
|
||||
|
|
||||
socket.onerror = function (err) { |
|
||||
console.error('Socket encountered error: ', err.message, 'Closing socket'); |
|
||||
}; |
|
||||
|
|
||||
socket.onmessage = function(event) { |
|
||||
console.log(event.data); |
|
||||
var socketMsg = JSON.parse(event.data); |
|
||||
if (socketMsg.rfidId != null) { |
|
||||
document.getElementById('rfidIdMod').value = socketMsg.rfidId; |
|
||||
document.getElementById('rfidIdMusic').value = socketMsg.rfidId; |
|
||||
toastr.info("RFID Tag mit "+ socketMsg.rfidId + " erkannt." ); |
|
||||
|
|
||||
$("#rfidIdMusic").effect("highlight", {color:"#abf5af"}, 3000); |
|
||||
$("#rfidIdMod").effect("highlight", {color:"#abf5af"}, 3000); |
|
||||
|
|
||||
} if ("status" in socketMsg) { |
|
||||
if (socketMsg.status == "ok") { |
|
||||
toastr.success("Aktion erfolgreich ausgeführt." ); |
|
||||
} |
|
||||
} if ("pong" in socketMsg) { |
|
||||
if (socketMsg.pong == 'pong') { |
|
||||
pong(); |
|
||||
} |
|
||||
} if ("refreshFileList" in socketMsg) { |
|
||||
hideFileIndexingState(); |
|
||||
toastr.info("Die Dateiliste wurde neu erzeugt!"); |
|
||||
$('#filetree').jstree(true).refresh(); |
|
||||
|
|
||||
} |
|
||||
if ("indexingState" in socketMsg) { |
|
||||
if(socketMsg.indexingState != null) { |
|
||||
$("#currentProcessedFile").text(socketMsg.indexingState); |
|
||||
console.log(socketMsg.indexingState); |
|
||||
} |
|
||||
} |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
function ping() { |
|
||||
var myObj = { |
|
||||
"ping": { |
|
||||
ping: 'ping' |
|
||||
} |
|
||||
}; |
|
||||
var myJSON = JSON.stringify(myObj); |
|
||||
socket.send(myJSON); |
|
||||
tm = setTimeout(function () { |
|
||||
toastr.warning('Die Verbindung zum Tonuino ist unterbrochen! Bitte Seite neu laden.'); |
|
||||
}, 5000); |
|
||||
} |
|
||||
|
|
||||
function pong() { |
|
||||
clearTimeout(tm); |
|
||||
} |
|
||||
|
|
||||
function refreshFileList(clickedId) { |
|
||||
lastIdclicked = clickedId; |
|
||||
var myObj = { |
|
||||
"refreshFileList": true |
|
||||
}; |
|
||||
var myJSON = JSON.stringify(myObj); |
|
||||
$("#refreshAction").hide(); |
|
||||
socket.send(myJSON); |
|
||||
showFileIndexingState(); |
|
||||
}; |
|
||||
|
|
||||
function genSettings(clickedId) { |
|
||||
lastIdclicked = clickedId; |
|
||||
var myObj = { |
|
||||
"general": { |
|
||||
iVol: document.getElementById('initialVolume').value, |
|
||||
mVolSpeaker: document.getElementById('maxVolumeSpeaker').value, |
|
||||
mVolHeadphone: document.getElementById('maxVolumeHeadphone').value, |
|
||||
iBright: document.getElementById('initBrightness').value, |
|
||||
nBright: document.getElementById('nightBrightness').value, |
|
||||
iTime: document.getElementById('inactivityTime').value, |
|
||||
vWarning: document.getElementById('warningLowVoltage').value, |
|
||||
vIndLow: document.getElementById('voltageIndicatorLow').value, |
|
||||
vIndHi: document.getElementById('voltageIndicatorHigh').value, |
|
||||
vInt: document.getElementById('voltageCheckInterval').value |
|
||||
} |
|
||||
}; |
|
||||
var myJSON = JSON.stringify(myObj); |
|
||||
socket.send(myJSON); |
|
||||
} |
|
||||
|
|
||||
function ftpSettings(clickedId) { |
|
||||
lastIdclicked = clickedId; |
|
||||
var myObj = { |
|
||||
"ftp": { |
|
||||
ftpUser: document.getElementById('ftpUser').value, |
|
||||
ftpPwd: document.getElementById('ftpPwd').value |
|
||||
} |
|
||||
}; |
|
||||
var myJSON = JSON.stringify(myObj); |
|
||||
socket.send(myJSON); |
|
||||
} |
|
||||
|
|
||||
function mqttSettings(clickedId) { |
|
||||
lastIdclicked = clickedId; |
|
||||
var val; |
|
||||
if (document.getElementById('mqttEnable').checked) { |
|
||||
val = document.getElementById('mqttEnable').value; |
|
||||
} else { |
|
||||
val = 0; |
|
||||
} |
|
||||
var myObj = { |
|
||||
"mqtt": { |
|
||||
mqttEnable: val, |
|
||||
mqttServer: document.getElementById('mqttServer').value, |
|
||||
mqttUser: document.getElementById('mqttUser').value, |
|
||||
mqttPwd: document.getElementById('mqttPwd').value |
|
||||
} |
|
||||
}; |
|
||||
var myJSON = JSON.stringify(myObj); |
|
||||
socket.send(myJSON); |
|
||||
} |
|
||||
|
|
||||
function rfidMods(clickedId) { |
|
||||
lastIdclicked = clickedId; |
|
||||
var myObj = { |
|
||||
"rfidMod": { |
|
||||
rfidIdMod: document.getElementById('rfidIdMod').value, |
|
||||
modId: document.getElementById('modId').value |
|
||||
} |
|
||||
}; |
|
||||
var myJSON = JSON.stringify(myObj); |
|
||||
socket.send(myJSON); |
|
||||
} |
|
||||
|
|
||||
function removeTrSlash(str) { |
|
||||
if (str.substr(-1) === '/') { |
|
||||
return str.substr(0, str.length - 1); |
|
||||
} |
|
||||
return str; |
|
||||
} |
|
||||
|
|
||||
function rfidAssign(clickedId) { |
|
||||
lastIdclicked = clickedId; |
|
||||
var myObj = { |
|
||||
"rfidAssign": { |
|
||||
rfidIdMusic: document.getElementById('rfidIdMusic').value, |
|
||||
fileOrUrl: removeTrSlash(document.getElementById('fileOrUrl').value), |
|
||||
playMode: document.getElementById('playMode').value |
|
||||
} |
|
||||
}; |
|
||||
var myJSON = JSON.stringify(myObj); |
|
||||
socket.send(myJSON); |
|
||||
} |
|
||||
|
|
||||
function wifiConfig(clickedId) { |
|
||||
lastIdclicked = clickedId; |
|
||||
var myObj = { |
|
||||
"wifiConfig": { |
|
||||
ssid: document.getElementById('ssid').value, |
|
||||
pwd: document.getElementById('pwd').value, |
|
||||
hostname: document.getElementById('hostname').value |
|
||||
} |
|
||||
}; |
|
||||
var myJSON = JSON.stringify(myObj); |
|
||||
socket.send(myJSON); |
|
||||
} |
|
||||
|
|
||||
$(document).ready(function () { |
|
||||
connect(); |
|
||||
renderFileTree(); |
|
||||
|
|
||||
$(function () { |
|
||||
$('[data-toggle="tooltip"]').tooltip(); |
|
||||
}); |
|
||||
}); |
|
||||
</script> |
|
||||
</body> |
|
||||
</html> |
|
@ -1,61 +1,74 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
#!/usr/bin/python |
#!/usr/bin/python |
||||
import re |
|
||||
|
### |
||||
|
# Use this script for creating PROGMEM header files from html files. |
||||
|
# needs pip install requests |
||||
|
## |
||||
|
# html file base names |
||||
|
import requests |
||||
|
import argparse |
||||
|
|
||||
content = '' |
|
||||
content2 = '' |
|
||||
contentEN = '' |
|
||||
content2EN = '' |
|
||||
|
def str2bool(v): |
||||
|
if isinstance(v, bool): |
||||
|
return v |
||||
|
if v.lower() in ('yes', 'true', 't', 'y', '1'): |
||||
|
return True |
||||
|
elif v.lower() in ('no', 'false', 'f', 'n', '0'): |
||||
|
return False |
||||
|
else: |
||||
|
raise argparse.ArgumentTypeError('Boolean value expected.') |
||||
|
|
||||
# TODO: Add a JS Minifier python lib |
|
||||
with open('html/website.html', 'r') as r: |
|
||||
|
HTML_FILES = ["management","management_EN", "accesspoint", "accesspoint_EN"] |
||||
|
|
||||
|
class htmlHeaderProcessor(object): |
||||
|
|
||||
|
""" |
||||
|
Returns a minified HTML string, uses html-minifier.com api. |
||||
|
""" |
||||
|
def minifyHTML(self, filename): |
||||
|
with open('html/' + filename + '.html', 'r') as r: |
||||
data = r.read() |
data = r.read() |
||||
|
return requests.post('https://html-minifier.com/raw', data=dict(input=data)).text.encode('utf8') |
||||
|
|
||||
|
def escape_html(self, data): |
||||
data = data.replace('\n', '\\\n') |
data = data.replace('\n', '\\\n') |
||||
data = data.replace('\"', '\\"') |
data = data.replace('\"', '\\"') |
||||
data = data.replace('\\d', '\\\d') |
data = data.replace('\\d', '\\\d') |
||||
data = data.replace('\\.', '\\\.') |
data = data.replace('\\.', '\\\.') |
||||
data = data.replace('\\^', '\\\\^') |
data = data.replace('\\^', '\\\\^') |
||||
data = data.replace('%;', '%%;') |
data = data.replace('%;', '%%;') |
||||
content += data |
|
||||
|
|
||||
with open('src/websiteMgmt.h', 'w') as w: |
|
||||
w.write("static const char mgtWebsite[] PROGMEM = \"") |
|
||||
w.write(content) |
|
||||
w.write("\";") |
|
||||
|
return data |
||||
|
|
||||
with open('html/website_EN.html', 'r') as ren: |
|
||||
data = ren.read().replace('\n', '\\\n') |
|
||||
data = data.replace('\"', '\\"') |
|
||||
data = data.replace('\\d', '\\\d') |
|
||||
data = data.replace('\\.', '\\\.') |
|
||||
data = data.replace('\\^', '\\\\^') |
|
||||
contentEN += data |
|
||||
|
def html_to_c_header(self, filename): |
||||
|
content = "" |
||||
|
with open('html/' + filename + '.html', 'r') as r: |
||||
|
data = r.read() |
||||
|
content += self.escape_html(data) |
||||
|
return content |
||||
|
|
||||
with open('src/websiteMgmt_EN.h', 'w') as wen: |
|
||||
wen.write("static const char mgtWebsite[] PROGMEM = \"") |
|
||||
wen.write(contentEN) |
|
||||
wen.write("\";") |
|
||||
|
|
||||
with open('html/websiteBasic.html', 'r') as r2: |
|
||||
data = r2.read().replace('\n', '\\\n') |
|
||||
data = data.replace('\"', '\\"') |
|
||||
content2 += data |
|
||||
|
def write_header_file(self, filename, content): |
||||
|
with open('src/HTML' + filename + '.h', 'w') as w: |
||||
|
varname = filename.split('_')[0] |
||||
|
w.write("static const char " + varname + "_HTML[] PROGMEM = \"") |
||||
|
w.write(content) |
||||
|
w.write("\";") |
||||
|
|
||||
with open('src/websiteBasic.h', 'w') as w2: |
|
||||
w2.write("static const char basicWebsite[] PROGMEM = \"") |
|
||||
w2.write(content2) |
|
||||
w2.write("\";") |
|
||||
|
def main(self): |
||||
|
parser = argparse.ArgumentParser(description='Create c code PROGMEM header files from HTML files.') |
||||
|
parser.add_argument("--minify", type=str2bool, nargs='?', |
||||
|
const=True, default=False, |
||||
|
help="Minify HTML Code") |
||||
|
args = parser.parse_args() |
||||
|
|
||||
with open('html/websiteBasic_EN.html', 'r') as r2en: |
|
||||
data = r2en.read().replace('\n', '\\\n') |
|
||||
data = data.replace('\"', '\\"') |
|
||||
content2EN += data |
|
||||
|
for file in HTML_FILES: |
||||
|
if args.minify: |
||||
|
|
||||
with open('src/websiteBasic_EN.h', 'w') as w2en: |
|
||||
w2en.write("static const char basicWebsite[] PROGMEM = \"") |
|
||||
w2en.write(content2EN) |
|
||||
w2en.write("\";") |
|
||||
|
self.header_file_content = self.minifyHTML(file) |
||||
|
self.header_file_content = self.escape_html(self.header_file_content) |
||||
|
else: |
||||
|
self.header_file_content = self.html_to_c_header(file) |
||||
|
self.write_header_file(file, self.header_file_content) |
||||
|
|
||||
r.close() |
|
||||
w.close() |
|
||||
r2.close() |
|
||||
w2.close() |
|
||||
|
if __name__ == '__main__': |
||||
|
htmlHeaderProcessor().main() |
@ -1,4 +1,4 @@ |
|||||
static const char basicWebsite[] PROGMEM = "<!DOCTYPE html>\ |
|
||||
|
static const char accesspoint_HTML[] PROGMEM = "<!DOCTYPE html>\ |
||||
<html>\ |
<html>\ |
||||
<head>\ |
<head>\ |
||||
<title>Wifi-configuration</title>\ |
<title>Wifi-configuration</title>\ |
@ -0,0 +1,728 @@ |
|||||
|
static const char management_HTML[] PROGMEM = "<!DOCTYPE html>\ |
||||
|
<html lang=\"de\">\ |
||||
|
<head>\ |
||||
|
<title>ESPuino-Konfiguration</title>\ |
||||
|
<meta charset=\"utf-8\">\ |
||||
|
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\ |
||||
|
<link rel=\"stylesheet\" href=\"https://ts-cs.de/tonuino/css/bootstrap.min.css\">\ |
||||
|
<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css\"/>\ |
||||
|
<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css\"/>\ |
||||
|
<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css\"/>\ |
||||
|
<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/11.0.2/css/bootstrap-slider.min.css\" />\ |
||||
|
<script src=\"https://ts-cs.de/tonuino/js/jquery.min.js\"></script>\ |
||||
|
<script src=\"https://code.jquery.com/ui/1.12.0/jquery-ui.min.js\"></script>\ |
||||
|
<script src=\"https://ts-cs.de/tonuino/js/popper.min.js\"></script>\ |
||||
|
<script src=\"https://ts-cs.de/tonuino/js/bootstrap.min.js\"></script>\ |
||||
|
<script src=\"https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js\"></script>\ |
||||
|
<script src=\"https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js\"></script>\ |
||||
|
<script src=\"https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/11.0.2/bootstrap-slider.min.js\"></script>\ |
||||
|
<style type=\"text/css\">\ |
||||
|
.filetree {\ |
||||
|
border: 1px solid black;\ |
||||
|
height: 200px;\ |
||||
|
margin: 0em 0em 1em 0em;\ |
||||
|
overflow-y: scroll;\ |
||||
|
}\ |
||||
|
.slider.slider-horizontal {\ |
||||
|
width: 60%%;\ |
||||
|
margin-left: 1em;\ |
||||
|
margin-right: 1em;\ |
||||
|
\ |
||||
|
}\ |
||||
|
.slider-handle{\ |
||||
|
height: 30px;\ |
||||
|
width: 30px;\ |
||||
|
top: -5px;\ |
||||
|
}\ |
||||
|
\ |
||||
|
legend.scheduler-border {\ |
||||
|
width:inherit; /* Or auto */\ |
||||
|
padding:0 10px; /* To give a bit of padding on the left and right */\ |
||||
|
border-bottom:none;\ |
||||
|
}\ |
||||
|
\ |
||||
|
.icon-pos{\ |
||||
|
top: 0.3em;\ |
||||
|
position: relative;\ |
||||
|
}\ |
||||
|
.reboot{\ |
||||
|
color:white;\ |
||||
|
}\ |
||||
|
.reboot:hover{\ |
||||
|
color: orange;\ |
||||
|
}\ |
||||
|
\ |
||||
|
.fa-sync:hover {\ |
||||
|
color: #666666;\ |
||||
|
}\ |
||||
|
\ |
||||
|
.clickForRefresh {\ |
||||
|
text-align: center;\ |
||||
|
color: gray;\ |
||||
|
cursor: pointer;\ |
||||
|
margin-top: 5em;\ |
||||
|
}\ |
||||
|
\ |
||||
|
.clickForRefresh:hover {\ |
||||
|
color: darkgray;\ |
||||
|
}\ |
||||
|
\ |
||||
|
.filetree-container {\ |
||||
|
position: relative;\ |
||||
|
}\ |
||||
|
\ |
||||
|
.indexing-progress {\ |
||||
|
width: 100%%;\ |
||||
|
height: 100%%;\ |
||||
|
position: absolute;\ |
||||
|
top: 0;\ |
||||
|
left: 0;\ |
||||
|
opacity: 0.7;\ |
||||
|
display: none;\ |
||||
|
}\ |
||||
|
\ |
||||
|
.refreshAction{\ |
||||
|
text-align: right;\ |
||||
|
font-size: 0.8em;\ |
||||
|
}\ |
||||
|
\ |
||||
|
.refreshAction:hover{\ |
||||
|
cursor: pointer;\ |
||||
|
color: darkgray;\ |
||||
|
}\ |
||||
|
\ |
||||
|
.overlay {\ |
||||
|
z-index: 9;\ |
||||
|
opacity: 0.8;\ |
||||
|
background: #1a1919;\ |
||||
|
height: 200px;\ |
||||
|
display: none;\ |
||||
|
width: 100%%;\ |
||||
|
}\ |
||||
|
</style>\ |
||||
|
</head>\ |
||||
|
<body>\ |
||||
|
<nav class=\"navbar navbar-expand-sm bg-primary navbar-dark\">\ |
||||
|
<div class=\"col-md-12\">\ |
||||
|
<a class=\"float-left navbar-brand\">\ |
||||
|
<img src=\"https://raw.githubusercontent.com/biologist79/Tonuino-ESP32-I2S/master/html/tonuino_logo.png\"\ |
||||
|
width=\"30\" height=\"30\" class=\"d-inline-block align-top\" alt=\"\"/>\ |
||||
|
Tonuino\ |
||||
|
</a>\ |
||||
|
\ |
||||
|
<a class=\"reboot float-right nav-link\" href=\"/restart\"><i class=\"fas fa-power-off\"></i> Neustart</a>\ |
||||
|
</div>\ |
||||
|
</nav>\ |
||||
|
<br/>\ |
||||
|
<nav>\ |
||||
|
<div class=\"container nav nav-tabs\" id=\"nav-tab\" role=\"tablist\">\ |
||||
|
<a class=\"nav-item nav-link active\" id=\"nav-rfid-tab\" data-toggle=\"tab\" href=\"#nav-rfid\" role=\"tab\" aria-controls=\"nav-rfid\" aria-selected=\"true\"><i class=\"fas fa-dot-circle\"></i> RFID</a>\ |
||||
|
<a class=\"nav-item nav-link\" id=\"nav-wifi-tab\" data-toggle=\"tab\" href=\"#nav-wifi\" role=\"tab\" aria-controls=\"nav-wifi\" aria-selected=\"false\"><i class=\"fas fa-wifi\"></i><span class=\".d-sm-none .d-md-block\"> WLAN</span></a>\ |
||||
|
<a class=\"nav-item nav-link\" id=\"nav-mqtt-tab\" data-toggle=\"tab\" href=\"#nav-mqtt\" role=\"tab\" aria-controls=\"nav-mqtt\" aria-selected=\"false\"><i class=\"fas fa-network-wired\"></i> MQTT</a>\ |
||||
|
<a class=\"nav-item nav-link\" id=\"nav-ftp-tab\" data-toggle=\"tab\" href=\"#nav-ftp\" role=\"tab\" aria-controls=\"nav-ftp\" aria-selected=\"false\"><i class=\"fas fa-folder\"></i> FTP</a>\ |
||||
|
<a class=\"nav-item nav-link\" id=\"nav-general-tab\" data-toggle=\"tab\" href=\"#nav-general\" role=\"tab\" aria-controls=\"nav-general\" aria-selected=\"false\"><i class=\"fas fa-sliders-h\"></i> Allgemein</a>\ |
||||
|
<a class=\"nav-item nav-link\" id=\"nav-tools-tab\" data-toggle=\"tab\" href=\"#nav-tools\" role=\"tab\" aria-controls=\"nav-tools\" aria-selected=\"false\"><i class=\"fas fa-wrench\"></i> Tools</a>\ |
||||
|
</div>\ |
||||
|
</nav>\ |
||||
|
<br>\ |
||||
|
<div class=\"tab-content\" id=\"nav-tabContent\">\ |
||||
|
<div class=\"tab-pane fade\" id=\"nav-wifi\" role=\"tabpanel\" aria-labelledby=\"nav-wifi-tab\">\ |
||||
|
<div class=\"container\" id=\"wifiConfig\">\ |
||||
|
<form action=\"#wifiConfig\" method=\"POST\" onsubmit=\"wifiConfig('wifiConfig'); return false\">\ |
||||
|
<div class=\"form-group col-md-12\">\ |
||||
|
<label for=\"ssid\">WLAN-Name (SSID):</label>\ |
||||
|
<input type=\"text\" class=\"form-control\" id=\"ssid\" placeholder=\"SSID\" name=\"ssid\" required>\ |
||||
|
<div class=\"invalid-feedback\">\ |
||||
|
Bitte SSID des WLANs eintragen.\ |
||||
|
</div>\ |
||||
|
<label for=\"pwd\">Passwort:</label>\ |
||||
|
<input type=\"password\" class=\"form-control\" id=\"pwd\" placeholder=\"Passwort\" name=\"pwd\" required>\ |
||||
|
<label for=\"hostname\">Tonuino-Name (Hostname):</label>\ |
||||
|
<input type=\"text\" class=\"form-control\" id=\"hostname\" placeholder=\"tonuino\" name=\"hostname\"\ |
||||
|
value=\"%HOSTNAME%\" pattern=\"^[^-\\.]{2,32}\" required>\ |
||||
|
</div>\ |
||||
|
<br>\ |
||||
|
<div class=\"text-center\">\ |
||||
|
<button type=\"reset\" class=\"btn btn-secondary\">Reset</button>\ |
||||
|
<button type=\"submit\" class=\"btn btn-primary\">Absenden</button>\ |
||||
|
</div>\ |
||||
|
</form>\ |
||||
|
</div>\ |
||||
|
</div>\ |
||||
|
<div class=\"tab-pane fade show active\" id=\"nav-rfid\" role=\"tabpanel\" aria-labelledby=\"nav-rfid-tab\">\ |
||||
|
<div class=\"container\" id=\"rfidMusicTags\">\ |
||||
|
<fieldset>\ |
||||
|
<legend>RFID-Zuweisungen</legend>\ |
||||
|
<form action=\"#rfidMusicTags\" method=\"POST\" onsubmit=\"rfidAssign('rfidMusicTags'); return false\">\ |
||||
|
<div class=\"form-group col-md-12\">\ |
||||
|
<label for=\"rfidIdMusic\">RFID-Chip-Nummer (12-stellig)</label>\ |
||||
|
<input type=\"text\" class=\"form-control\" id=\"rfidIdMusic\" maxlength=\"12\" pattern=\"[0-9]{12}\"\ |
||||
|
placeholder=\"%RFID_TAG_ID%\" name=\"rfidIdMusic\" required>\ |
||||
|
<label for=\"fileOrUrl\">Datei, Verzeichnis oder URL (^ und # als Zeichen nicht erlaubt)</label>\ |
||||
|
<input type=\"text\" class=\"form-control\" id=\"fileOrUrl\" maxlength=\"255\" placeholder=\"z.B. /mp3/Hoerspiele/Yakari/Yakari_und_seine_Freunde.mp3\" pattern=\"^[^\\^#]+$\" name=\"fileOrUrl\" required>\ |
||||
|
<div class=\"filetree-container\">\ |
||||
|
<div id=\"filebrowser\">\ |
||||
|
<div class=\"filetree demo\" id=\"filetree\"></div>\ |
||||
|
<div class=\"refreshAction\">\ |
||||
|
<span id=\"refreshAction\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"Datei Liste aktualisieren.\"><i class=\"fas fa-sync fa-1x\"></i> Dateiliste aktualisieren</span>\ |
||||
|
</div>\ |
||||
|
</div>\ |
||||
|
<div id=\"indexing-progress\" class=\"indexing-progress overlay\">\ |
||||
|
<div style=\"text-align: center; color:white; margin-top:2em;\">\ |
||||
|
<div><i class=\"fas fa-sync fa-spin fa-2x\"></i> <br><br> Der Prozess kann mehrere Minuten dauern...</div>\ |
||||
|
<div id=\"currentProcessedFile\"></div>\ |
||||
|
</div>\ |
||||
|
</div>\ |
||||
|
</div>\ |
||||
|
<label for=\"playMode\">Abspielmodus</label>\ |
||||
|
<select class=\"form-control\" id=\"playMode\" name=\"playMode\">\ |
||||
|
<option class=\"option-file\" value=\"1\">Einzelner Titel</option>\ |
||||
|
<option class=\"option-file\" value=\"2\">Einzelner Titel (Endlosschleife)</option>\ |
||||
|
<option class=\"option-file-and-folder\" value=\"3\">Hörbuch</option>\ |
||||
|
<option class=\"option-file-and-folder\" value=\"4\">Hörbuch (Endlosschleife)</option>\ |
||||
|
<option class=\"option-folder\" value=\"5\">Alle Titel eines Verzeichnis (sortiert)</option>\ |
||||
|
<option class=\"option-folder\" value=\"6\">Alle Titel eines Verzeichnis (zufällig)</option>\ |
||||
|
<option class=\"option-folder\" value=\"7\">Alle Titel eines Verzeichnis (sortiert, Endlosschleife)</option>\ |
||||
|
<option class=\"option-folder\" value=\"9\">Alle Titel eines Verzeichnis (zufällig, Endlosschleife)</option>\ |
||||
|
<option class=\"option-stream\" value=\"8\">Webradio</option>\ |
||||
|
</select>\ |
||||
|
</div>\ |
||||
|
<br>\ |
||||
|
<div class=\"text-center\">\ |
||||
|
<button type=\"reset\" class=\"btn btn-secondary\">Reset</button>\ |
||||
|
<button type=\"submit\" class=\"btn btn-primary\">Absenden</button>\ |
||||
|
</div>\ |
||||
|
</form>\ |
||||
|
</fieldset>\ |
||||
|
</div>\ |
||||
|
\ |
||||
|
<br>\ |
||||
|
<br>\ |
||||
|
<div class=\"container\" id=\"rfidModTags\">\ |
||||
|
<fieldset>\ |
||||
|
<legend>RFID-Modifkationen</legend>\ |
||||
|
<form class=\"needs-validation\" action=\"#rfidModTags\" method=\"POST\" onsubmit=\"rfidMods('rfidModTags'); return false\">\ |
||||
|
<div class=\"form-group col-md-12\">\ |
||||
|
<label for=\"rfidIdMod\">RFID-Chip-Nummer (12-stellig)</label>\ |
||||
|
<input type=\"text\" class=\"form-control\" id=\"rfidIdMod\" maxlength=\"12\" pattern=\"[0-9]{12}\"\ |
||||
|
placeholder=\"%RFID_TAG_ID%\" name=\"rfidIdMod\" required>\ |
||||
|
<div class=\"invalid-feedback\">\ |
||||
|
Bitte eine 12-stellige Zahl eingeben.\ |
||||
|
</div>\ |
||||
|
<label for=\"modId\">Konfiguraiton</label>\ |
||||
|
<select class=\"form-control\" id=\"modId\" name=\"modId\">\ |
||||
|
<option value=\"100\">Tastensperre</option>\ |
||||
|
<option value=\"101\">Schlafen nach 15 Minuten</option>\ |
||||
|
<option value=\"102\">Schlafen nach 30 Minuten</option>\ |
||||
|
<option value=\"103\">Schlafen nach 1 Stunde</option>\ |
||||
|
<option value=\"104\">Schlafen nach 2 Stunden</option>\ |
||||
|
<option value=\"105\">Schlafen nach Ende des Titels</option>\ |
||||
|
<option value=\"106\">Schlafen nach Ende der Playlist</option>\ |
||||
|
<option value=\"107\">Schlafen nach fünf Titeln</option>\ |
||||
|
<option value=\"110\">Wiederhole Playlist (endlos)</option>\ |
||||
|
<option value=\"111\">Wiederhole Titel (endlos)</option>\ |
||||
|
<option value=\"112\">Dimme LEDs (Nachtmodus)</option>\ |
||||
|
<option value=\"130\">Aktiviere/deaktive WLAN</option>\ |
||||
|
</select>\ |
||||
|
</div>\ |
||||
|
<br>\ |
||||
|
<div class=\"text-center\">\ |
||||
|
<button type=\"reset\" class=\"btn btn-secondary\">Reset</button>\ |
||||
|
<button type=\"submit\" class=\"btn btn-primary\">Absenden</button>\ |
||||
|
</div>\ |
||||
|
</form>\ |
||||
|
</fieldset>\ |
||||
|
</div>\ |
||||
|
</div>\ |
||||
|
<div class=\"tab-pane fade\" id=\"nav-mqtt\" role=\"tabpanel\" aria-labelledby=\"nav-mqtt-tab\">\ |
||||
|
<div class=\"container\" id=\"mqttConfig\">\ |
||||
|
\ |
||||
|
<form class=\"needs-validation\" action=\"#mqttConfig\" method=\"POST\"\ |
||||
|
onsubmit=\"mqttSettings('mqttConfig'); return false\">\ |
||||
|
<div class=\"form-check col-md-12\">\ |
||||
|
<input class=\"form-check-input\" type=\"checkbox\" value=\"1\" id=\"mqttEnable\" name=\"mqttEnable\" %MQTT_ENABLE%>\ |
||||
|
<label class=\"form-check-label\" for=\"mqttEnable\">\ |
||||
|
MQTT aktivieren\ |
||||
|
</label>\ |
||||
|
</div>\ |
||||
|
<div class=\"form-group my-2 col-md-12\">\ |
||||
|
<label for=\"mqttServer\">MQTT-Server</label>\ |
||||
|
<input type=\"text\" class=\"form-control\" id=\"mqttServer\" minlength=\"7\" maxlength=\"%MQTT_SERVER_LENGTH%\"\ |
||||
|
placeholder=\"z.B. 192.168.2.89\" name=\"mqttServer\" value=\"%MQTT_SERVER%\">\ |
||||
|
<label for=\"mqttUser\">MQTT-Benutzername (optional):</label>\ |
||||
|
<input type=\"text\" class=\"form-control\" id=\"mqttUser\" maxlength=\"%MQTT_USER_LENGTH%\"\ |
||||
|
placeholder=\"Benutzername\" name=\"mqttUser\" value=\"%MQTT_USER%\">\ |
||||
|
<label for=\"mqttPwd\">Passwort (optional):</label>\ |
||||
|
<input type=\"password\" class=\"form-control\" id=\"mqttPwd\" maxlength=\"%MQTT_PWD_LENGTH%\"\ |
||||
|
placeholder=\"Passwort\" name=\"mqttPwd\" value=\"%MQTT_PWD%\">\ |
||||
|
</div>\ |
||||
|
<br>\ |
||||
|
<div class=\"text-center\">\ |
||||
|
<button type=\"reset\" class=\"btn btn-secondary\">Reset</button>\ |
||||
|
<button type=\"submit\" class=\"btn btn-primary\">Absenden</button>\ |
||||
|
</div>\ |
||||
|
</form>\ |
||||
|
</div>\ |
||||
|
</div>\ |
||||
|
<div class=\"tab-pane fade\" id=\"nav-ftp\" role=\"tabpanel\" aria-labelledby=\"nav-ftp-tab\">\ |
||||
|
<div class=\"container\" id=\"ftpConfig\">\ |
||||
|
\ |
||||
|
<form action=\"#ftpConfig\" method=\"POST\" onsubmit=\"ftpSettings('ftpConfig'); return false\">\ |
||||
|
<div class=\"form-group col-md-12\">\ |
||||
|
<label for=\"ftpUser\">FTP-Benutzername:</label>\ |
||||
|
<input type=\"text\" class=\"form-control\" id=\"ftpUser\" maxlength=\"%FTP_USER_LENGTH%\"\ |
||||
|
placeholder=\"Benutzername\" name=\"ftpUser\" value=\"%FTP_USER%\" required>\ |
||||
|
<label for=\"pwd\">Passwort:</label>\ |
||||
|
<input type=\"password\" class=\"form-control\" id=\"ftpPwd\" maxlength=\"%FTP_PWD_LENGTH%\" placeholder=\"Passwort\"\ |
||||
|
name=\"ftpPwd\" value=\"%FTP_PWD%\" required>\ |
||||
|
</div>\ |
||||
|
<br>\ |
||||
|
<div class=\"text-center\">\ |
||||
|
<button type=\"reset\" class=\"btn btn-secondary\">Reset</button>\ |
||||
|
<button type=\"submit\" class=\"btn btn-primary\">Absenden</button>\ |
||||
|
</div>\ |
||||
|
</form>\ |
||||
|
</div>\ |
||||
|
</div>\ |
||||
|
\ |
||||
|
<div class=\"tab-pane fade\" id=\"nav-general\" role=\"tabpanel\" aria-labelledby=\"nav-general-tab\">\ |
||||
|
<div class=\"container\" id=\"generalConfig\">\ |
||||
|
\ |
||||
|
<form action=\"#generalConfig\" method=\"POST\" onsubmit=\"genSettings('generalConfig'); return false\">\ |
||||
|
<div class=\"form-group col-md-12\">\ |
||||
|
<fieldset>\ |
||||
|
<legend class=\"w-auto\">Lautstärke</legend>\ |
||||
|
<label for=\"initialVolume\">Nach dem Einschalten</label>\ |
||||
|
<div class=\"text-center\">\ |
||||
|
<i class=\"fas fa-volume-down fa-2x .icon-pos\"></i> <input data-provide=\"slider\" type=\"number\" data-slider-min=\"1\" data-slider-max=\"21\" min=\"1\" max=\"21\" class=\"form-control\" id=\"initialVolume\" name=\"initialVolume\"\ |
||||
|
data-slider-value=\"%INIT_VOLUME%\" value=\"%INIT_VOLUME%\" required> <i class=\"fas fa-volume-up fa-2x .icon-pos\"></i></div>\ |
||||
|
<br>\ |
||||
|
<label for=\"maxVolumeSpeaker\">Maximal Lautsprecher</label>\ |
||||
|
<div class=\"text-center\">\ |
||||
|
<i class=\"fas fa-volume-down fa-2x .icon-pos\"></i> <input data-provide=\"slider\" type=\"number\" data-slider-min=\"1\" data-slider-max=\"21\" min=\"1\" max=\"21\" class=\"form-control\" id=\"maxVolumeSpeaker\" name=\"maxVolumeSpeaker\"\ |
||||
|
data-slider-value=\"%MAX_VOLUME_SPEAKER%\" value=\"%MAX_VOLUME_SPEAKER%\" required> <i class=\"fas fa-volume-up fa-2x .icon-pos\"></i>\ |
||||
|
</div>\ |
||||
|
<br>\ |
||||
|
<label for=\"maxVolumeHeadphone\">Maximal Kopfhörer</label>\ |
||||
|
<div class=\"text-center\">\ |
||||
|
<i class=\"fas fa-volume-down fa-2x .icon-pos\"></i> <input data-provide=\"slider\" type=\"number\" data-slider-min=\"1\" data-slider-max=\"21\" min=\"1\" max=\"21\" class=\"form-control\" id=\"maxVolumeHeadphone\" name=\"maxVolumeHeadphone\"\ |
||||
|
data-slider-value=\"%MAX_VOLUME_HEADPHONE%\" value=\"%MAX_VOLUME_HEADPHONE%\" required> <i class=\"fas fa-volume-up fa-2x .icon-pos\"></i>\ |
||||
|
</div>\ |
||||
|
</fieldset>\ |
||||
|
</div>\ |
||||
|
<br>\ |
||||
|
<div class=\"form-group col-md-12\">\ |
||||
|
<fieldset >\ |
||||
|
<legend class=\"w-auto\">Neopixel (Helligkeit)</legend>\ |
||||
|
<label for=\"initBrightness\">Nach dem Einschalten:</label>\ |
||||
|
<div class=\"text-center\">\ |
||||
|
<i class=\"far fa-sun fa-2x .icon-pos\"></i>\ |
||||
|
<input data-provide=\"slider\" type=\"number\" data-slider-min=\"0\" data-slider-max=\"255\" min=\"0\" max=\"255\" class=\"form-control\" id=\"initBrightness\" name=\"initBrightness\"\ |
||||
|
data-slider-value=\"%INIT_LED_BRIGHTNESS%\" value=\"%INIT_LED_BRIGHTNESS%\" required><i class=\"fas fa-sun fa-2x .icon-pos\"></i>\ |
||||
|
</div>\ |
||||
|
\ |
||||
|
<label for=\"nightBrightness\">Im Nachtmodus</label>\ |
||||
|
<div class=\"text-center\">\ |
||||
|
<i class=\"far fa-sun fa-2x .icon-pos\"></i><input data-provide=\"slider\" type=\"number\" data-slider-min=\"0\" data-slider-max=\"255\" min=\"0\" max=\"255\" class=\"form-control\" id=\"nightBrightness\" name=\"nightBrightness\" data-slider-value=\"%NIGHT_LED_BRIGHTNESS%\" value=\"%NIGHT_LED_BRIGHTNESS%\" required><i class=\"fas fa-sun fa-2x .icon-pos\"></i>\ |
||||
|
</div>\ |
||||
|
</fieldset>\ |
||||
|
</div>\ |
||||
|
<br>\ |
||||
|
<div class=\"form-group col-md-12\">\ |
||||
|
<fieldset>\ |
||||
|
<legend>Deep Sleep</legend>\ |
||||
|
\ |
||||
|
<label for=\"inactivityTime\">Inaktivität nach (in Minuten)</label>\ |
||||
|
<div class=\"text-center\"><i class=\"fas fa-hourglass-start fa-2x .icon-pos\"></i> <input type=\"number\" data-provide=\"slider\" data-slider-min=\"0\" data-slider-max=\"30\" min=\"1\" max=\"120\" class=\"form-control\" id=\"inactivityTime\" name=\"inactivityTime\"\ |
||||
|
data-slider-value=\"%MAX_INACTIVITY%\" value=\"%MAX_INACTIVITY%\" required><i class=\"fas fa-hourglass-end fa-2x .icon-pos\"></i></div>\ |
||||
|
</fieldset>\ |
||||
|
</div>\ |
||||
|
<br>\ |
||||
|
\ |
||||
|
<div class=\"form-group col-md-12\">\ |
||||
|
<fieldset>\ |
||||
|
<legend>Batterie</legend>\ |
||||
|
<div>Status über Neopixel anzeigen</div>\ |
||||
|
<br>\ |
||||
|
<label for=\"warningLowVoltage\">Spannungsgrenze für Status Anzeige.\ |
||||
|
</label>\ |
||||
|
<div class=\"text-center\">\ |
||||
|
<i class=\"fas fa-battery-quarter fa-2x .icon-pos\"></i> <input data-provide=\"slider\" data-slider-step=\"0.1\" data-slider-min=\"3.0\" data-slider-max=\"5.0\" min=\"3.0\" max=\"5.0\" type=\"text\" class=\"form-control\" id=\"warningLowVoltage\" name=\"warningLowVoltage\"\ |
||||
|
data-slider-value=\"%WARNING_LOW_VOLTAGE%\" value=\"%WARNING_LOW_VOLTAGE%\" pattern=\"^\\d{1,2}(\\.\\d{1,3})?\" required> <i class=\"fas fa-battery-three-quarters fa-2x .icon-pos\" fa-2x .icon-pos></i>\ |
||||
|
</div>\ |
||||
|
<br>\ |
||||
|
<label for=\"voltageIndicatorLow\">Unterer Akkuspannungslevel\ |
||||
|
</label>\ |
||||
|
<div class=\"text-center\">\ |
||||
|
<i class=\"fas fa-battery-quarter fa-2x .icon-pos\"></i> <input data-provide=\"slider\" min=\"2.0\" data-slider-step=\"0.1\" data-slider-min=\"2.0\" data-slider-max=\"5.0\" max=\"5.0\"type=\"text\" class=\"form-control\" id=\"voltageIndicatorLow\" name=\"voltageIndicatorLow\"\ |
||||
|
data-slider-value=\"%VOLTAGE_INDICATOR_LOW%\" value=\"%VOLTAGE_INDICATOR_LOW%\" pattern=\"^\\d{1,2}(\\.\\d{1,3})?\" required> <i class=\"fas fa-battery-three-quarters fa-2x .icon-pos\" fa-2x .icon-pos></i>\ |
||||
|
</div>\ |
||||
|
<br>\ |
||||
|
<label for=\"voltageIndicatorHigh\">Oberer Akkuspannungslevel</label>\ |
||||
|
\ |
||||
|
<div class=\"text-center\">\ |
||||
|
<i class=\"fas fa-battery-quarter fa-2x .icon-pos\"></i><input data-provide=\"slider\" data-slider-step=\"0.1\" data-slider-min=\"2.0\" data-slider-max=\"5.0\" min=\"2.0\" max=\"5.0\" type=\"text\" class=\"form-control\" id=\"voltageIndicatorHigh\" name=\"voltageIndicatorHigh\"\ |
||||
|
data-slider-value=\"%VOLTAGE_INDICATOR_HIGH%\" value=\"%VOLTAGE_INDICATOR_HIGH%\" pattern=\"^\\d{1,2}(\\.\\d{1,3})?\" required> <i class=\"fas fa-battery-three-quarters fa-2x .icon-pos\" fa-2x .icon-pos></i>\ |
||||
|
</div>\ |
||||
|
\ |
||||
|
<br>\ |
||||
|
<label for=\"voltageCheckInterval\"> Interval der Messung (in Minuten)</label>\ |
||||
|
<div class=\"text-center\"><i class=\"fas fa-hourglass-start fa-2x .icon-pos\"></i>\ |
||||
|
<input data-provide=\"slider\" data-slider-min=\"1\" data-slider-max=\"60\" type=\"number\" min=\"1\" max=\"60\" class=\"form-control\" id=\"voltageCheckInterval\"\ |
||||
|
data-slider-value=\"%VOLTAGE_CHECK_INTERVAL%\" name=\"voltageCheckInterval\" value=\"%VOLTAGE_CHECK_INTERVAL%\" required><i class=\"fas fa-hourglass-end fa-2x .icon-pos\"></i>\ |
||||
|
</div>\ |
||||
|
\ |
||||
|
</fieldset>\ |
||||
|
</div>\ |
||||
|
<br>\ |
||||
|
<div class=\"text-center\">\ |
||||
|
<button type=\"reset\" class=\"btn btn-secondary\">Reset</button>\ |
||||
|
<button type=\"submit\" class=\"btn btn-primary\">Absenden</button>\ |
||||
|
</div>\ |
||||
|
</form>\ |
||||
|
</div>\ |
||||
|
</div>\ |
||||
|
<div class=\"tab-pane fade\" id=\"nav-tools\" role=\"tabpanel\" aria-labelledby=\"nav-tools-tab\">\ |
||||
|
<div class=\"container my-5\" id=\"importNvs\">\ |
||||
|
<h2>NVS-Importer</h2>\ |
||||
|
<form action=\"/upload\" enctype=\"multipart/form-data\" method=\"POST\">\ |
||||
|
<div class=\"form-group\">\ |
||||
|
<label for=\"nvsUpload\">Hier kann eine Backup-Datei importiert werden.</label>\ |
||||
|
<input type=\"file\" class=\"form-control-file\" id=\"nvsUpload\" name=\"nvsUpload\" accept=\".txt\">\ |
||||
|
</div>\ |
||||
|
<br>\ |
||||
|
<div class=\"text-center\">\ |
||||
|
<button type=\"submit\" class=\"btn btn-primary\">Absenden</button>\ |
||||
|
</div>\ |
||||
|
</form>\ |
||||
|
</div>\ |
||||
|
</div>\ |
||||
|
</div>\ |
||||
|
<script type=\"text/javascript\">\ |
||||
|
var DEBUG = false;\ |
||||
|
var lastIdclicked = '';\ |
||||
|
var host = $(location).attr('hostname');\ |
||||
|
\ |
||||
|
if (DEBUG) {\ |
||||
|
host = \"192.168.178.114\";\ |
||||
|
}\ |
||||
|
\ |
||||
|
toastr.options = {\ |
||||
|
\"closeButton\": false,\ |
||||
|
\"debug\": false,\ |
||||
|
\"newestOnTop\": false,\ |
||||
|
\"progressBar\": false,\ |
||||
|
\"positionClass\": \"toast-top-right\",\ |
||||
|
\"preventDuplicates\": false,\ |
||||
|
\"onclick\": null,\ |
||||
|
\"showDuration\": \"300\",\ |
||||
|
\"hideDuration\": \"1000\",\ |
||||
|
\"timeOut\": \"5000\",\ |
||||
|
\"extendedTimeOut\": \"1000\",\ |
||||
|
\"showEasing\": \"swing\",\ |
||||
|
\"hideEasing\": \"linear\",\ |
||||
|
\"showMethod\": \"fadeIn\",\ |
||||
|
\"hideMethod\": \"fadeOut\"\ |
||||
|
};\ |
||||
|
\ |
||||
|
function postRendering(event, data) {\ |
||||
|
Object.keys(data.instance._model.data).forEach(function (key, index) {\ |
||||
|
\ |
||||
|
var cur = data.instance.get_node(data.instance._model.data[key]);\ |
||||
|
var lastFolder = cur['id'].split('/').filter(function (el) {\ |
||||
|
return el.trim().length > 0;\ |
||||
|
}).pop();\ |
||||
|
if ((/\\.(mp3|MP3|ogg|wav|WAV|OGG|wma|WMA|acc|ACC|flac|FLAC)$/i).test(lastFolder)) {\ |
||||
|
data.instance.set_type(data.instance._model.data[key], 'audio');\ |
||||
|
} else {\ |
||||
|
if (data.instance._model.data[key]['type'] == \"file\") {\ |
||||
|
data.instance.disable_node(data.instance._model.data[key]);\ |
||||
|
}\ |
||||
|
}\ |
||||
|
data.instance.rename_node(data.instance._model.data[key], lastFolder);\ |
||||
|
});\ |
||||
|
}\ |
||||
|
\ |
||||
|
function renderFileTree() {\ |
||||
|
\ |
||||
|
var filesURI = \"/files\";\ |
||||
|
if (DEBUG) {\ |
||||
|
filesURI = \"http://\" + host + \"/files\";\ |
||||
|
}\ |
||||
|
$('#filetree').jstree({\ |
||||
|
'core': {\ |
||||
|
'check_callback': true,\ |
||||
|
'data': {\ |
||||
|
url: filesURI,\ |
||||
|
error: function (XMLHttpRequest, textStatus, errorThrown) {\ |
||||
|
$('#j1_loading').hide();\ |
||||
|
$(\"#refreshAction\").hide();\ |
||||
|
$('#filetree').html(\"<div class='clickForRefresh' ><i class='fas fa-sync fa-1x'><span id='#clickForRefresh' > Dateien suchen.</span></div>\");\ |
||||
|
$('#filetree').on(\"click\", function () {\ |
||||
|
refreshFileList();\ |
||||
|
});\ |
||||
|
toastr.error(\"Die Verzeichnis-Liste konnte nicht geladen werden.\");\ |
||||
|
}\ |
||||
|
},\ |
||||
|
\ |
||||
|
},\ |
||||
|
'types': {\ |
||||
|
'folder': {\ |
||||
|
'icon': \"fa fa-folder\"\ |
||||
|
},\ |
||||
|
'file': {\ |
||||
|
'icon': \"fa fa-file\"\ |
||||
|
},\ |
||||
|
'audio': {\ |
||||
|
'icon': \"fa fa-file-audio\"\ |
||||
|
},\ |
||||
|
'default': {\ |
||||
|
'icon': \"fa fa-folder\"\ |
||||
|
}\ |
||||
|
},\ |
||||
|
'plugins': [\"themes\", \"types\"]\ |
||||
|
}).bind('loaded.jstree', function (event, data) {\ |
||||
|
postRendering(event, data);\ |
||||
|
if ((data.instance._model.data['#']['children'].length == 0)) {\ |
||||
|
toastr.info(\"Der SD-Karten-Index muss erzeugt werden.\");\ |
||||
|
}\ |
||||
|
}).bind('refresh.jstree', function (event, data) {\ |
||||
|
postRendering(event, data);\ |
||||
|
});\ |
||||
|
}\ |
||||
|
\ |
||||
|
$('#filetree').on('select_node.jstree', function (e, data) {\ |
||||
|
$('input[name=fileOrUrl]').val(data.node.id);\ |
||||
|
\ |
||||
|
if (data.node.type == \"folder\") {\ |
||||
|
$('.option-folder').show();\ |
||||
|
$('.option-file').hide();\ |
||||
|
$('#playMode option').removeAttr('selected').filter('[value=3]').attr('selected', true);\ |
||||
|
}\ |
||||
|
\ |
||||
|
if (data.node.type == \"audio\") {\ |
||||
|
$('.option-file').show();\ |
||||
|
$('.option-folder').hide();\ |
||||
|
$('#playMode option').removeAttr('selected').filter('[value=1]').attr('selected', true);\ |
||||
|
}\ |
||||
|
});\ |
||||
|
\ |
||||
|
$('#refreshAction').on(\"click\", function () {\ |
||||
|
refreshFileList();\ |
||||
|
$(\"#indexing-progress\").show();\ |
||||
|
$(\"#refreshAction\").hide();\ |
||||
|
});\ |
||||
|
\ |
||||
|
$('#playMode').on(\"change\", function () {\ |
||||
|
if (this.value == 8) {\ |
||||
|
$('#filebrowser').slideUp();\ |
||||
|
} else {\ |
||||
|
$('#filebrowser').slideDown();\ |
||||
|
}\ |
||||
|
});\ |
||||
|
\ |
||||
|
function showFileIndexingState() {\ |
||||
|
$(\"#indexing-progress\").show();\ |
||||
|
$(\"#refreshAction\").hide();\ |
||||
|
}\ |
||||
|
\ |
||||
|
function hideFileIndexingState() {\ |
||||
|
$(\"#indexing-progress\").hide();\ |
||||
|
$(\"#refreshAction\").show();\ |
||||
|
}\ |
||||
|
\ |
||||
|
var socket = undefined;\ |
||||
|
var tm;\ |
||||
|
\ |
||||
|
function connect() {\ |
||||
|
socket = new WebSocket(\"ws://\" + host + \"/ws\");\ |
||||
|
\ |
||||
|
socket.onopen = function () {\ |
||||
|
setInterval(ping, 15000);\ |
||||
|
};\ |
||||
|
\ |
||||
|
socket.onclose = function (e) {\ |
||||
|
console.log('Socket is closed. Reconnect will be attempted in 1 second.', e.reason);\ |
||||
|
socket = null;\ |
||||
|
setTimeout(function () {\ |
||||
|
connect();\ |
||||
|
}, 5000);\ |
||||
|
};\ |
||||
|
\ |
||||
|
socket.onerror = function (err) {\ |
||||
|
console.error('Socket encountered error: ', err.message, 'Closing socket');\ |
||||
|
};\ |
||||
|
\ |
||||
|
socket.onmessage = function(event) {\ |
||||
|
console.log(event.data);\ |
||||
|
var socketMsg = JSON.parse(event.data);\ |
||||
|
if (socketMsg.rfidId != null) {\ |
||||
|
document.getElementById('rfidIdMod').value = socketMsg.rfidId;\ |
||||
|
document.getElementById('rfidIdMusic').value = socketMsg.rfidId;\ |
||||
|
toastr.info(\"RFID Tag mit \"+ socketMsg.rfidId + \" erkannt.\" );\ |
||||
|
\ |
||||
|
$(\"#rfidIdMusic\").effect(\"highlight\", {color:\"#abf5af\"}, 3000);\ |
||||
|
$(\"#rfidIdMod\").effect(\"highlight\", {color:\"#abf5af\"}, 3000);\ |
||||
|
\ |
||||
|
} if (\"status\" in socketMsg) {\ |
||||
|
if (socketMsg.status == \"ok\") {\ |
||||
|
toastr.success(\"Aktion erfolgreich ausgeführt.\" );\ |
||||
|
}\ |
||||
|
} if (\"pong\" in socketMsg) {\ |
||||
|
if (socketMsg.pong == 'pong') {\ |
||||
|
pong();\ |
||||
|
}\ |
||||
|
} if (\"refreshFileList\" in socketMsg) {\ |
||||
|
hideFileIndexingState();\ |
||||
|
toastr.info(\"Die Dateiliste wurde neu erzeugt!\");\ |
||||
|
$('#filetree').jstree(true).refresh();\ |
||||
|
\ |
||||
|
}\ |
||||
|
if (\"indexingState\" in socketMsg) {\ |
||||
|
if(socketMsg.indexingState != null) {\ |
||||
|
$(\"#currentProcessedFile\").text(socketMsg.indexingState);\ |
||||
|
console.log(socketMsg.indexingState);\ |
||||
|
}\ |
||||
|
}\ |
||||
|
};\ |
||||
|
}\ |
||||
|
\ |
||||
|
function ping() {\ |
||||
|
var myObj = {\ |
||||
|
\"ping\": {\ |
||||
|
ping: 'ping'\ |
||||
|
}\ |
||||
|
};\ |
||||
|
var myJSON = JSON.stringify(myObj);\ |
||||
|
socket.send(myJSON);\ |
||||
|
tm = setTimeout(function () {\ |
||||
|
toastr.warning('Die Verbindung zum Tonuino ist unterbrochen! Bitte Seite neu laden.');\ |
||||
|
}, 5000);\ |
||||
|
}\ |
||||
|
\ |
||||
|
function pong() {\ |
||||
|
clearTimeout(tm);\ |
||||
|
}\ |
||||
|
\ |
||||
|
function refreshFileList(clickedId) {\ |
||||
|
lastIdclicked = clickedId;\ |
||||
|
var myObj = {\ |
||||
|
\"refreshFileList\": true\ |
||||
|
};\ |
||||
|
var myJSON = JSON.stringify(myObj);\ |
||||
|
$(\"#refreshAction\").hide();\ |
||||
|
socket.send(myJSON);\ |
||||
|
showFileIndexingState();\ |
||||
|
};\ |
||||
|
\ |
||||
|
function genSettings(clickedId) {\ |
||||
|
lastIdclicked = clickedId;\ |
||||
|
var myObj = {\ |
||||
|
\"general\": {\ |
||||
|
iVol: document.getElementById('initialVolume').value,\ |
||||
|
mVolSpeaker: document.getElementById('maxVolumeSpeaker').value,\ |
||||
|
mVolHeadphone: document.getElementById('maxVolumeHeadphone').value,\ |
||||
|
iBright: document.getElementById('initBrightness').value,\ |
||||
|
nBright: document.getElementById('nightBrightness').value,\ |
||||
|
iTime: document.getElementById('inactivityTime').value,\ |
||||
|
vWarning: document.getElementById('warningLowVoltage').value,\ |
||||
|
vIndLow: document.getElementById('voltageIndicatorLow').value,\ |
||||
|
vIndHi: document.getElementById('voltageIndicatorHigh').value,\ |
||||
|
vInt: document.getElementById('voltageCheckInterval').value\ |
||||
|
}\ |
||||
|
};\ |
||||
|
var myJSON = JSON.stringify(myObj);\ |
||||
|
socket.send(myJSON);\ |
||||
|
}\ |
||||
|
\ |
||||
|
function ftpSettings(clickedId) {\ |
||||
|
lastIdclicked = clickedId;\ |
||||
|
var myObj = {\ |
||||
|
\"ftp\": {\ |
||||
|
ftpUser: document.getElementById('ftpUser').value,\ |
||||
|
ftpPwd: document.getElementById('ftpPwd').value\ |
||||
|
}\ |
||||
|
};\ |
||||
|
var myJSON = JSON.stringify(myObj);\ |
||||
|
socket.send(myJSON);\ |
||||
|
}\ |
||||
|
\ |
||||
|
function mqttSettings(clickedId) {\ |
||||
|
lastIdclicked = clickedId;\ |
||||
|
var val;\ |
||||
|
if (document.getElementById('mqttEnable').checked) {\ |
||||
|
val = document.getElementById('mqttEnable').value;\ |
||||
|
} else {\ |
||||
|
val = 0;\ |
||||
|
}\ |
||||
|
var myObj = {\ |
||||
|
\"mqtt\": {\ |
||||
|
mqttEnable: val,\ |
||||
|
mqttServer: document.getElementById('mqttServer').value,\ |
||||
|
mqttUser: document.getElementById('mqttUser').value,\ |
||||
|
mqttPwd: document.getElementById('mqttPwd').value\ |
||||
|
}\ |
||||
|
};\ |
||||
|
var myJSON = JSON.stringify(myObj);\ |
||||
|
socket.send(myJSON);\ |
||||
|
}\ |
||||
|
\ |
||||
|
function rfidMods(clickedId) {\ |
||||
|
lastIdclicked = clickedId;\ |
||||
|
var myObj = {\ |
||||
|
\"rfidMod\": {\ |
||||
|
rfidIdMod: document.getElementById('rfidIdMod').value,\ |
||||
|
modId: document.getElementById('modId').value\ |
||||
|
}\ |
||||
|
};\ |
||||
|
var myJSON = JSON.stringify(myObj);\ |
||||
|
socket.send(myJSON);\ |
||||
|
}\ |
||||
|
\ |
||||
|
function removeTrSlash(str) {\ |
||||
|
if (str.substr(-1) === '/') {\ |
||||
|
return str.substr(0, str.length - 1);\ |
||||
|
}\ |
||||
|
return str;\ |
||||
|
}\ |
||||
|
\ |
||||
|
function rfidAssign(clickedId) {\ |
||||
|
lastIdclicked = clickedId;\ |
||||
|
var myObj = {\ |
||||
|
\"rfidAssign\": {\ |
||||
|
rfidIdMusic: document.getElementById('rfidIdMusic').value,\ |
||||
|
fileOrUrl: removeTrSlash(document.getElementById('fileOrUrl').value),\ |
||||
|
playMode: document.getElementById('playMode').value\ |
||||
|
}\ |
||||
|
};\ |
||||
|
var myJSON = JSON.stringify(myObj);\ |
||||
|
socket.send(myJSON);\ |
||||
|
}\ |
||||
|
\ |
||||
|
function wifiConfig(clickedId) {\ |
||||
|
lastIdclicked = clickedId;\ |
||||
|
var myObj = {\ |
||||
|
\"wifiConfig\": {\ |
||||
|
ssid: document.getElementById('ssid').value,\ |
||||
|
pwd: document.getElementById('pwd').value,\ |
||||
|
hostname: document.getElementById('hostname').value\ |
||||
|
}\ |
||||
|
};\ |
||||
|
var myJSON = JSON.stringify(myObj);\ |
||||
|
socket.send(myJSON);\ |
||||
|
}\ |
||||
|
\ |
||||
|
$(document).ready(function () {\ |
||||
|
connect();\ |
||||
|
renderFileTree();\ |
||||
|
\ |
||||
|
console.log(parseInt(document.getElementById('warningLowVoltage').value));\ |
||||
|
$(function () {\ |
||||
|
$('[data-toggle=\"tooltip\"]').tooltip();\ |
||||
|
});\ |
||||
|
\ |
||||
|
});\ |
||||
|
</script>\ |
||||
|
</body>\ |
||||
|
</html>\ |
||||
|
"; |
@ -1,4 +1,4 @@ |
|||||
static const char mgtWebsite[] PROGMEM = "<!DOCTYPE html>\ |
|
||||
|
static const char management_HTML[] PROGMEM = "<!DOCTYPE html>\ |
||||
<html lang=\"de\">\ |
<html lang=\"de\">\ |
||||
<head>\ |
<head>\ |
||||
<title>ESPuino-configuration</title>\ |
<title>ESPuino-configuration</title>\ |
@ -1,640 +0,0 @@ |
|||||
static const char mgtWebsite[] PROGMEM = "<!DOCTYPE html>\ |
|
||||
<html lang=\"de\">\ |
|
||||
<head>\ |
|
||||
<title>ESPuino-Konfiguration</title>\ |
|
||||
<meta charset=\"utf-8\">\ |
|
||||
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\ |
|
||||
<link rel=\"stylesheet\" href=\"https://ts-cs.de/tonuino/css/bootstrap.min.css\">\ |
|
||||
<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css\"/>\ |
|
||||
<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css\"/>\ |
|
||||
<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css\"/>\ |
|
||||
<script src=\"https://ts-cs.de/tonuino/js/jquery.min.js\"></script>\ |
|
||||
<script src=\"https://code.jquery.com/ui/1.12.0/jquery-ui.min.js\"></script>\ |
|
||||
<script src=\"https://ts-cs.de/tonuino/js/popper.min.js\"></script>\ |
|
||||
<script src=\"https://ts-cs.de/tonuino/js/bootstrap.min.js\"></script>\ |
|
||||
<script src=\"https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js\"></script>\ |
|
||||
<script src=\"https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js\"></script>\ |
|
||||
<style type=\"text/css\">\ |
|
||||
.filetree {\ |
|
||||
border: 1px solid black;\ |
|
||||
height: 200px;\ |
|
||||
margin: 0em 0em 1em 0em;\ |
|
||||
overflow-y: scroll;\ |
|
||||
}\ |
|
||||
\ |
|
||||
.fa-sync:hover {\ |
|
||||
color: #666666;\ |
|
||||
}\ |
|
||||
\ |
|
||||
.clickForRefresh {\ |
|
||||
text-align: center;\ |
|
||||
color: gray;\ |
|
||||
cursor: pointer;\ |
|
||||
margin-top: 5em;\ |
|
||||
}\ |
|
||||
\ |
|
||||
.clickForRefresh:hover {\ |
|
||||
color: darkgray;\ |
|
||||
}\ |
|
||||
\ |
|
||||
.filetree-container {\ |
|
||||
position: relative;\ |
|
||||
}\ |
|
||||
\ |
|
||||
.indexing-progress {\ |
|
||||
width: 100%%;\ |
|
||||
height: 100%%;\ |
|
||||
position: absolute;\ |
|
||||
top: 0;\ |
|
||||
left: 0;\ |
|
||||
opacity: 0.7;\ |
|
||||
display: none;\ |
|
||||
}\ |
|
||||
\ |
|
||||
.refreshAction{\ |
|
||||
text-align: right;\ |
|
||||
font-size: 0.8em;\ |
|
||||
}\ |
|
||||
\ |
|
||||
.refreshAction:hover{\ |
|
||||
cursor: pointer;\ |
|
||||
color: darkgray;\ |
|
||||
}\ |
|
||||
\ |
|
||||
.overlay {\ |
|
||||
z-index: 9;\ |
|
||||
opacity: 0.8;\ |
|
||||
background: #1a1919;\ |
|
||||
height: 200px;\ |
|
||||
display: none;\ |
|
||||
width: 100%%;\ |
|
||||
}\ |
|
||||
</style>\ |
|
||||
</head>\ |
|
||||
<body>\ |
|
||||
<nav class=\"navbar navbar-expand-sm bg-primary navbar-dark\">\ |
|
||||
<button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#navbarSupportedContent\"\ |
|
||||
aria-controls=\"navbarSupportedContent\" aria-expanded=\"false\" aria-label=\"Toggle navigation\">\ |
|
||||
<span class=\"navbar-toggler-icon\"></span>\ |
|
||||
</button>\ |
|
||||
<a class=\"navbar-brand\">\ |
|
||||
<img src=\"https://raw.githubusercontent.com/biologist79/Tonuino-ESP32-I2S/master/html/tonuino_logo.png\"\ |
|
||||
width=\"30\" height=\"30\" class=\"d-inline-block align-top\" alt=\"\"/>\ |
|
||||
Tonuino\ |
|
||||
</a>\ |
|
||||
<div class=\"collapse navbar-collapse\" id=\"collapsibleNavbar\">\ |
|
||||
<ul class=\"navbar-nav mr-auto\">\ |
|
||||
<li class=\"nav-item\">\ |
|
||||
<a class=\"nav-link\" href=\"#wifiConfig\">WLAN</a>\ |
|
||||
</li>\ |
|
||||
<li class=\"nav-item\">\ |
|
||||
<a class=\"nav-link\" href=\"#rfidMusicTags\">RFID-Zuweisungen</a>\ |
|
||||
</li>\ |
|
||||
<li class=\"nav-item\">\ |
|
||||
<a class=\"nav-link\" href=\"#rfidModTags\">RFID-Modifikationen</a>\ |
|
||||
</li>\ |
|
||||
<li class=\"nav-item\">\ |
|
||||
<a class=\"nav-link\" href=\"#mqttConfig\">MQTT</a>\ |
|
||||
</li>\ |
|
||||
<li class=\"nav-item\">\ |
|
||||
<a class=\"nav-link\" href=\"#ftpConfig\">FTP</a>\ |
|
||||
</li>\ |
|
||||
<li class=\"nav-item\">\ |
|
||||
<a class=\"nav-link\" href=\"#generalConfig\">Allgemein</a>\ |
|
||||
</li>\ |
|
||||
<li class=\"nav-item\">\ |
|
||||
<a class=\"nav-link\" href=\"#importNvs\">NVS-Importer</a>\ |
|
||||
</li>\ |
|
||||
<li class=\"nav-item\">\ |
|
||||
<a class=\"nav-link\" href=\"/restart\" style=\"color: orange\">Neustart Tonuino</a>\ |
|
||||
</li>\ |
|
||||
</ul>\ |
|
||||
</div>\ |
|
||||
</nav>\ |
|
||||
<br/>\ |
|
||||
<div class=\"container\" id=\"wifiConfig\">\ |
|
||||
<h2>WLAN-Konfiguration</h2>\ |
|
||||
<form action=\"#wifiConfig\" method=\"POST\" onsubmit=\"wifiConfig('wifiConfig'); return false\">\ |
|
||||
<div class=\"form-group col-md-6\">\ |
|
||||
<label for=\"ssid\">WLAN-Name (SSID):</label>\ |
|
||||
<input type=\"text\" class=\"form-control\" id=\"ssid\" placeholder=\"SSID\" name=\"ssid\" required>\ |
|
||||
<div class=\"invalid-feedback\">\ |
|
||||
Bitte SSID des WLANs eintragen.\ |
|
||||
</div>\ |
|
||||
<label for=\"pwd\">Passwort:</label>\ |
|
||||
<input type=\"password\" class=\"form-control\" id=\"pwd\" placeholder=\"Passwort\" name=\"pwd\" required>\ |
|
||||
<label for=\"hostname\">Tonuino-Name (Hostname):</label>\ |
|
||||
<input type=\"text\" class=\"form-control\" id=\"hostname\" placeholder=\"tonuino\" name=\"hostname\"\ |
|
||||
value=\"%HOSTNAME%\" pattern=\"^[^-\\.]{2,32}\" required>\ |
|
||||
</div>\ |
|
||||
<button type=\"reset\" class=\"btn btn-secondary\">Reset</button>\ |
|
||||
<button type=\"submit\" class=\"btn btn-primary\">Absenden</button>\ |
|
||||
</form>\ |
|
||||
<div class=\"messages col-md-6 my-2\"></div>\ |
|
||||
</div>\ |
|
||||
<div class=\"container my-5\" id=\"rfidMusicTags\">\ |
|
||||
<h2>RFID-Zuweisungen</h2>\ |
|
||||
<form action=\"#rfidMusicTags\" method=\"POST\" onsubmit=\"rfidAssign('rfidMusicTags'); return false\">\ |
|
||||
<div class=\"form-group col-md-6\">\ |
|
||||
<label for=\"rfidIdMusic\">RFID-Chip-Nummer (12-stellig)</label>\ |
|
||||
<input type=\"text\" class=\"form-control\" id=\"rfidIdMusic\" maxlength=\"12\" pattern=\"[0-9]{12}\"\ |
|
||||
placeholder=\"%RFID_TAG_ID%\" name=\"rfidIdMusic\" required>\ |
|
||||
<label for=\"fileOrUrl\">Datei, Verzeichnis oder URL (^ und # als Zeichen nicht erlaubt)</label>\ |
|
||||
<input type=\"text\" class=\"form-control\" id=\"fileOrUrl\" maxlength=\"255\" placeholder=\"z.B. /mp3/Hoerspiele/Yakari/Yakari_und_seine_Freunde.mp3\" pattern=\"^[^\\^#]+$\" name=\"fileOrUrl\" required>\ |
|
||||
<div class=\"filetree-container\">\ |
|
||||
<div id=\"filebrowser\">\ |
|
||||
<div class=\"filetree demo\" id=\"filetree\"></div>\ |
|
||||
<div class=\"refreshAction\">\ |
|
||||
<span id=\"refreshAction\" data-toggle=\"tooltip\" data-placement=\"top\" title=\"Datei Liste aktualisieren.\"><i class=\"fas fa-sync fa-1x\"></i> Dateiliste aktualisieren</span>\ |
|
||||
</div>\ |
|
||||
</div>\ |
|
||||
<div id=\"indexing-progress\" class=\"indexing-progress overlay\">\ |
|
||||
<div style=\"text-align: center; color:white; margin-top:2em;\">\ |
|
||||
<div><i class=\"fas fa-sync fa-spin fa-2x\"></i> <br><br> Der Prozess kann mehrere Minuten dauern...</div>\ |
|
||||
<div id=\"currentProcessedFile\"></div>\ |
|
||||
</div>\ |
|
||||
</div>\ |
|
||||
</div>\ |
|
||||
<label for=\"playMode\">Abspielmodus</label>\ |
|
||||
<select class=\"form-control\" id=\"playMode\" name=\"playMode\">\ |
|
||||
<option class=\"option-file\" value=\"1\">Einzelner Titel</option>\ |
|
||||
<option class=\"option-file\" value=\"2\">Einzelner Titel (Endlosschleife)</option>\ |
|
||||
<option class=\"option-file-and-folder\" value=\"3\">Hörbuch</option>\ |
|
||||
<option class=\"option-file-and-folder\" value=\"4\">Hörbuch (Endlosschleife)</option>\ |
|
||||
<option class=\"option-folder\" value=\"5\">Alle Titel eines Verzeichnis (sortiert)</option>\ |
|
||||
<option class=\"option-folder\" value=\"6\">Alle Titel eines Verzeichnis (zufällig)</option>\ |
|
||||
<option class=\"option-folder\" value=\"7\">Alle Titel eines Verzeichnis (sortiert, Endlosschleife)</option>\ |
|
||||
<option class=\"option-folder\" value=\"9\">Alle Titel eines Verzeichnis (zufällig, Endlosschleife)</option>\ |
|
||||
<option class=\"option-stream\" value=\"8\">Webradio</option>\ |
|
||||
</select>\ |
|
||||
</div>\ |
|
||||
<button type=\"reset\" class=\"btn btn-secondary\">Reset</button>\ |
|
||||
<button type=\"submit\" class=\"btn btn-primary\">Absenden</button>\ |
|
||||
</form>\ |
|
||||
<div class=\"messages col-md-6 my-2\"></div>\ |
|
||||
</div>\ |
|
||||
<div class=\"container my-5\" id=\"rfidModTags\">\ |
|
||||
<h2>RFID-Modifkationen</h2>\ |
|
||||
<form class=\"needs-validation\" action=\"#rfidModTags\" method=\"POST\" onsubmit=\"rfidMods('rfidModTags'); return false\">\ |
|
||||
<div class=\"form-group col-md-6\">\ |
|
||||
<label for=\"rfidIdMod\">RFID-Chip-Nummer (12-stellig)</label>\ |
|
||||
<input type=\"text\" class=\"form-control\" id=\"rfidIdMod\" maxlength=\"12\" pattern=\"[0-9]{12}\"\ |
|
||||
placeholder=\"%RFID_TAG_ID%\" name=\"rfidIdMod\" required>\ |
|
||||
<div class=\"invalid-feedback\">\ |
|
||||
Bitte eine 12-stellige Zahl eingeben.\ |
|
||||
</div>\ |
|
||||
<label for=\"modId\">Abspielmodus</label>\ |
|
||||
<select class=\"form-control\" id=\"modId\" name=\"modId\">\ |
|
||||
<option value=\"100\">Tastensperre</option>\ |
|
||||
<option value=\"101\">Schlafen nach 15 Minuten</option>\ |
|
||||
<option value=\"102\">Schlafen nach 30 Minuten</option>\ |
|
||||
<option value=\"103\">Schlafen nach 1 Stunde</option>\ |
|
||||
<option value=\"104\">Schlafen nach 2 Stunden</option>\ |
|
||||
<option value=\"105\">Schlafen nach Ende des Titels</option>\ |
|
||||
<option value=\"106\">Schlafen nach Ende der Playlist</option>\ |
|
||||
<option value=\"107\">Schlafen nach fünf Titeln</option>\ |
|
||||
<option value=\"110\">Wiederhole Playlist (endlos)</option>\ |
|
||||
<option value=\"111\">Wiederhole Titel (endlos)</option>\ |
|
||||
<option value=\"112\">Dimme LEDs (Nachtmodus)</option>\ |
|
||||
<option value=\"130\">Aktiviere/deaktive WLAN</option>\ |
|
||||
</select>\ |
|
||||
</div>\ |
|
||||
<button type=\"reset\" class=\"btn btn-secondary\">Reset</button>\ |
|
||||
<button type=\"submit\" class=\"btn btn-primary\">Absenden</button>\ |
|
||||
</form>\ |
|
||||
<div class=\"messages col-md-6 my-2\"></div>\ |
|
||||
</div>\ |
|
||||
<div class=\"container my-5\" id=\"mqttConfig\">\ |
|
||||
<h2>MQTT-Konfiguration</h2>\ |
|
||||
<form class=\"needs-validation\" action=\"#mqttConfig\" method=\"POST\"\ |
|
||||
onsubmit=\"mqttSettings('mqttConfig'); return false\">\ |
|
||||
<div class=\"form-check col-md-6\">\ |
|
||||
<input class=\"form-check-input\" type=\"checkbox\" value=\"1\" id=\"mqttEnable\" name=\"mqttEnable\" %MQTT_ENABLE%>\ |
|
||||
<label class=\"form-check-label\" for=\"mqttEnable\">\ |
|
||||
MQTT aktivieren\ |
|
||||
</label>\ |
|
||||
</div>\ |
|
||||
<div class=\"form-group my-2 col-md-6\">\ |
|
||||
<label for=\"mqttServer\">MQTT-Server</label>\ |
|
||||
<input type=\"text\" class=\"form-control\" id=\"mqttServer\" minlength=\"7\" maxlength=\"%MQTT_SERVER_LENGTH%\"\ |
|
||||
placeholder=\"z.B. 192.168.2.89\" name=\"mqttServer\" value=\"%MQTT_SERVER%\">\ |
|
||||
<label for=\"mqttUser\">MQTT-Benutzername (optional):</label>\ |
|
||||
<input type=\"text\" class=\"form-control\" id=\"mqttUser\" maxlength=\"%MQTT_USER_LENGTH%\"\ |
|
||||
placeholder=\"Benutzername\" name=\"mqttUser\" value=\"%MQTT_USER%\">\ |
|
||||
<label for=\"mqttPwd\">Passwort (optional):</label>\ |
|
||||
<input type=\"password\" class=\"form-control\" id=\"mqttPwd\" maxlength=\"%MQTT_PWD_LENGTH%\"\ |
|
||||
placeholder=\"Passwort\" name=\"mqttPwd\" value=\"%MQTT_PWD%\">\ |
|
||||
</div>\ |
|
||||
<button type=\"reset\" class=\"btn btn-secondary\">Reset</button>\ |
|
||||
<button type=\"submit\" class=\"btn btn-primary\">Absenden</button>\ |
|
||||
</form>\ |
|
||||
<div class=\"messages col-md-6 my-2\"></div>\ |
|
||||
</div>\ |
|
||||
<div class=\"container\" id=\"ftpConfig\">\ |
|
||||
<h2>FTP-Konfiguration</h2>\ |
|
||||
<form action=\"#ftpConfig\" method=\"POST\" onsubmit=\"ftpSettings('ftpConfig'); return false\">\ |
|
||||
<div class=\"form-group col-md-6\">\ |
|
||||
<label for=\"ftpUser\">FTP-Benutzername:</label>\ |
|
||||
<input type=\"text\" class=\"form-control\" id=\"ftpUser\" maxlength=\"%FTP_USER_LENGTH%\"\ |
|
||||
placeholder=\"Benutzername\" name=\"ftpUser\" value=\"%FTP_USER%\" required>\ |
|
||||
<label for=\"pwd\">Passwort:</label>\ |
|
||||
<input type=\"password\" class=\"form-control\" id=\"ftpPwd\" maxlength=\"%FTP_PWD_LENGTH%\" placeholder=\"Passwort\"\ |
|
||||
name=\"ftpPwd\" value=\"%FTP_PWD%\" required>\ |
|
||||
</div>\ |
|
||||
<button type=\"reset\" class=\"btn btn-secondary\">Reset</button>\ |
|
||||
<button type=\"submit\" class=\"btn btn-primary\">Absenden</button>\ |
|
||||
</form>\ |
|
||||
<div class=\"messages col-md-6 my-2\"></div>\ |
|
||||
</div>\ |
|
||||
<div class=\"container my-5\" id=\"generalConfig\">\ |
|
||||
<h2>Allgemeine Konfiguration</h2>\ |
|
||||
<form action=\"#generalConfig\" method=\"POST\" onsubmit=\"genSettings('generalConfig'); return false\">\ |
|
||||
<div class=\"form-group col-md-6\">\ |
|
||||
<label for=\"initialVolume\">Lautstärke nach dem Einschalten</label>\ |
|
||||
<input type=\"number\" min=\"1\" max=\"21\" class=\"form-control\" id=\"initialVolume\" name=\"initialVolume\"\ |
|
||||
value=\"%INIT_VOLUME%\" required>\ |
|
||||
<label for=\"maxVolumeSpeaker\">Maximale Lautstärke (Lautsprecher)</label>\ |
|
||||
<input type=\"number\" min=\"1\" max=\"21\" class=\"form-control\" id=\"maxVolumeSpeaker\" name=\"maxVolumeSpeaker\"\ |
|
||||
value=\"%MAX_VOLUME_SPEAKER%\" required>\ |
|
||||
<label for=\"maxVolumeHeadphone\">Maximale Lautstärke (Kopfhörer)</label>\ |
|
||||
<input type=\"number\" min=\"1\" max=\"21\" class=\"form-control\" id=\"maxVolumeHeadphone\" name=\"maxVolumeHeadphone\"\ |
|
||||
value=\"%MAX_VOLUME_HEADPHONE%\" required>\ |
|
||||
</div>\ |
|
||||
<div class=\"form-group col-md-6\">\ |
|
||||
<label for=\"initBrightness\">Neopixel-Helligkeit nach dem Einschalten</label>\ |
|
||||
<input type=\"number\" min=\"0\" max=\"255\" class=\"form-control\" id=\"initBrightness\" name=\"initBrightness\"\ |
|
||||
value=\"%INIT_LED_BRIGHTNESS%\" required>\ |
|
||||
<label for=\"nightBrightness\">Neopixel-Helligkeit im Nachtmodus</label>\ |
|
||||
<input type=\"number\" min=\"0\" max=\"255\" class=\"form-control\" id=\"nightBrightness\" name=\"nightBrightness\"\ |
|
||||
value=\"%NIGHT_LED_BRIGHTNESS%\" required>\ |
|
||||
</div>\ |
|
||||
<div class=\"form-group col-md-6\">\ |
|
||||
<label for=\"inactivityTime\">Deep-Sleep nach Inaktivität (Minuten)</label>\ |
|
||||
<input type=\"number\" min=\"1\" max=\"1440\" class=\"form-control\" id=\"inactivityTime\" name=\"inactivityTime\"\ |
|
||||
value=\"%MAX_INACTIVITY%\" required>\ |
|
||||
</div>\ |
|
||||
<div class=\"form-group col-md-6\">\ |
|
||||
<label for=\"warningLowVoltage\">(Optional) Spannungsgrenze (Batterie), ab der Warnung auf Neopixel angezeigt\ |
|
||||
wird (z.B. 3.4)</label>\ |
|
||||
<input type=\"text\" class=\"form-control\" id=\"warningLowVoltage\" name=\"warningLowVoltage\"\ |
|
||||
value=\"%WARNING_LOW_VOLTAGE%\" pattern=\"^\\d{1,2}(\\.\\d{1,3})?\" required>\ |
|
||||
</div>\ |
|
||||
<div class=\"form-group col-md-6\">\ |
|
||||
<label for=\"voltageIndicatorLow\">(Optional) Unterer Akkuspannungslevel (Batterie) für Neopixel-Anzeige (z.B.\ |
|
||||
3.1)</label>\ |
|
||||
<input type=\"text\" class=\"form-control\" id=\"voltageIndicatorLow\" name=\"voltageIndicatorLow\"\ |
|
||||
value=\"%VOLTAGE_INDICATOR_LOW%\" pattern=\"^\\d{1,2}(\\.\\d{1,3})?\" required>\ |
|
||||
</div>\ |
|
||||
<div class=\"form-group col-md-6\">\ |
|
||||
<label for=\"voltageIndicatorHigh\">(Optional) Oberer Akkuspannungslevel (Batterie) für Neopixel-Anzeige (z.B.\ |
|
||||
4.2)</label>\ |
|
||||
<input type=\"text\" class=\"form-control\" id=\"voltageIndicatorHigh\" name=\"voltageIndicatorHigh\"\ |
|
||||
value=\"%VOLTAGE_INDICATOR_HIGH%\" pattern=\"^\\d{1,2}(\\.\\d{1,3})?\" required>\ |
|
||||
</div>\ |
|
||||
<div class=\"form-group col-md-6\">\ |
|
||||
<label for=\"voltageCheckInterval\">(Optional) Häufigkeit der Spannungsmessung (Batterie) in Minuten</label>\ |
|
||||
<input type=\"number\" min=\"1\" max=\"180\" class=\"form-control\" id=\"voltageCheckInterval\"\ |
|
||||
name=\"voltageCheckInterval\" value=\"%VOLTAGE_CHECK_INTERVAL%\" required>\ |
|
||||
</div>\ |
|
||||
<button type=\"reset\" class=\"btn btn-secondary\">Reset</button>\ |
|
||||
<button type=\"submit\" class=\"btn btn-primary\">Absenden</button>\ |
|
||||
</form>\ |
|
||||
<div class=\"messages col-md-6 my-2\"></div>\ |
|
||||
</div>\ |
|
||||
<div class=\"container my-5\" id=\"importNvs\">\ |
|
||||
<h2>NVS-Importer</h2>\ |
|
||||
<form action=\"/upload\" enctype=\"multipart/form-data\" method=\"POST\">\ |
|
||||
<div class=\"form-group\">\ |
|
||||
<label for=\"nvsUpload\">Hier kann eine Backup-Datei importiert werden.</label>\ |
|
||||
<input type=\"file\" class=\"form-control-file\" id=\"nvsUpload\" name=\"nvsUpload\" accept=\".txt\">\ |
|
||||
</div>\ |
|
||||
<button type=\"submit\" class=\"btn btn-primary\">Absenden</button>\ |
|
||||
</form>\ |
|
||||
<div class=\"messages col-md-6 my-2\"></div>\ |
|
||||
</div>\ |
|
||||
<script type=\"text/javascript\">\ |
|
||||
var DEBUG = false;\ |
|
||||
var lastIdclicked = '';\ |
|
||||
var host = $(location).attr('hostname');\ |
|
||||
\ |
|
||||
if (DEBUG) {\ |
|
||||
host = \"192.168.178.112\";\ |
|
||||
}\ |
|
||||
\ |
|
||||
toastr.options = {\ |
|
||||
\"closeButton\": false,\ |
|
||||
\"debug\": false,\ |
|
||||
\"newestOnTop\": false,\ |
|
||||
\"progressBar\": false,\ |
|
||||
\"positionClass\": \"toast-top-right\",\ |
|
||||
\"preventDuplicates\": false,\ |
|
||||
\"onclick\": null,\ |
|
||||
\"showDuration\": \"300\",\ |
|
||||
\"hideDuration\": \"1000\",\ |
|
||||
\"timeOut\": \"5000\",\ |
|
||||
\"extendedTimeOut\": \"1000\",\ |
|
||||
\"showEasing\": \"swing\",\ |
|
||||
\"hideEasing\": \"linear\",\ |
|
||||
\"showMethod\": \"fadeIn\",\ |
|
||||
\"hideMethod\": \"fadeOut\"\ |
|
||||
};\ |
|
||||
\ |
|
||||
function postRendering(event, data) {\ |
|
||||
Object.keys(data.instance._model.data).forEach(function (key, index) {\ |
|
||||
\ |
|
||||
var cur = data.instance.get_node(data.instance._model.data[key]);\ |
|
||||
var lastFolder = cur['id'].split('/').filter(function (el) {\ |
|
||||
return el.trim().length > 0;\ |
|
||||
}).pop();\ |
|
||||
if ((/\\.(mp3|MP3|ogg|wav|WAV|OGG|wma|WMA|acc|ACC|flac|FLAC)$/i).test(lastFolder)) {\ |
|
||||
data.instance.set_type(data.instance._model.data[key], 'audio');\ |
|
||||
} else {\ |
|
||||
if (data.instance._model.data[key]['type'] == \"file\") {\ |
|
||||
data.instance.disable_node(data.instance._model.data[key]);\ |
|
||||
}\ |
|
||||
}\ |
|
||||
data.instance.rename_node(data.instance._model.data[key], lastFolder);\ |
|
||||
});\ |
|
||||
}\ |
|
||||
\ |
|
||||
function renderFileTree() {\ |
|
||||
\ |
|
||||
var filesURI = \"/files\";\ |
|
||||
if (DEBUG) {\ |
|
||||
filesURI = \"http://\" + host + \"/files\";\ |
|
||||
}\ |
|
||||
$('#filetree').jstree({\ |
|
||||
'core': {\ |
|
||||
'check_callback': true,\ |
|
||||
'data': {\ |
|
||||
url: filesURI,\ |
|
||||
error: function (XMLHttpRequest, textStatus, errorThrown) {\ |
|
||||
$('#j1_loading').hide();\ |
|
||||
$(\"#refreshAction\").hide();\ |
|
||||
$('#filetree').html(\"<div class='clickForRefresh' ><i class='fas fa-sync fa-1x'><span id='#clickForRefresh' > Dateien suchen.</span></div>\");\ |
|
||||
$('#filetree').on(\"click\", function () {\ |
|
||||
refreshFileList();\ |
|
||||
});\ |
|
||||
toastr.error(\"Die Verzeichnis-Liste konnte nicht geladen werden.\");\ |
|
||||
}\ |
|
||||
},\ |
|
||||
\ |
|
||||
},\ |
|
||||
'types': {\ |
|
||||
'folder': {\ |
|
||||
'icon': \"fa fa-folder\"\ |
|
||||
},\ |
|
||||
'file': {\ |
|
||||
'icon': \"fa fa-file\"\ |
|
||||
},\ |
|
||||
'audio': {\ |
|
||||
'icon': \"fa fa-file-audio\"\ |
|
||||
},\ |
|
||||
'default': {\ |
|
||||
'icon': \"fa fa-folder\"\ |
|
||||
}\ |
|
||||
},\ |
|
||||
'plugins': [\"themes\", \"types\"]\ |
|
||||
}).bind('loaded.jstree', function (event, data) {\ |
|
||||
postRendering(event, data);\ |
|
||||
if ((data.instance._model.data['#']['children'].length == 0)) {\ |
|
||||
toastr.info(\"Der SD-Karten-Index muss erzeugt werden.\");\ |
|
||||
}\ |
|
||||
}).bind('refresh.jstree', function (event, data) {\ |
|
||||
postRendering(event, data);\ |
|
||||
});\ |
|
||||
}\ |
|
||||
\ |
|
||||
$('#filetree').on('select_node.jstree', function (e, data) {\ |
|
||||
$('input[name=fileOrUrl]').val(data.node.id);\ |
|
||||
\ |
|
||||
if (data.node.type == \"folder\") {\ |
|
||||
$('.option-folder').show();\ |
|
||||
$('.option-file').hide();\ |
|
||||
$('#playMode option').removeAttr('selected').filter('[value=3]').attr('selected', true);\ |
|
||||
}\ |
|
||||
\ |
|
||||
if (data.node.type == \"audio\") {\ |
|
||||
$('.option-file').show();\ |
|
||||
$('.option-folder').hide();\ |
|
||||
$('#playMode option').removeAttr('selected').filter('[value=1]').attr('selected', true);\ |
|
||||
}\ |
|
||||
});\ |
|
||||
\ |
|
||||
$('#refreshAction').on(\"click\", function () {\ |
|
||||
refreshFileList();\ |
|
||||
$(\"#indexing-progress\").show();\ |
|
||||
$(\"#refreshAction\").hide();\ |
|
||||
});\ |
|
||||
\ |
|
||||
$('#playMode').on(\"change\", function () {\ |
|
||||
if (this.value == 8) {\ |
|
||||
$('#filebrowser').slideUp();\ |
|
||||
} else {\ |
|
||||
$('#filebrowser').slideDown();\ |
|
||||
}\ |
|
||||
});\ |
|
||||
\ |
|
||||
function showFileIndexingState() {\ |
|
||||
$(\"#indexing-progress\").show();\ |
|
||||
$(\"#refreshAction\").hide();\ |
|
||||
}\ |
|
||||
\ |
|
||||
function hideFileIndexingState() {\ |
|
||||
$(\"#indexing-progress\").hide();\ |
|
||||
$(\"#refreshAction\").show();\ |
|
||||
}\ |
|
||||
\ |
|
||||
var socket = undefined;\ |
|
||||
var tm;\ |
|
||||
\ |
|
||||
function connect() {\ |
|
||||
socket = new WebSocket(\"ws://\" + host + \"/ws\");\ |
|
||||
\ |
|
||||
socket.onopen = function () {\ |
|
||||
setInterval(ping, 15000);\ |
|
||||
};\ |
|
||||
\ |
|
||||
socket.onclose = function (e) {\ |
|
||||
console.log('Socket is closed. Reconnect will be attempted in 1 second.', e.reason);\ |
|
||||
socket = null;\ |
|
||||
setTimeout(function () {\ |
|
||||
connect();\ |
|
||||
}, 5000);\ |
|
||||
};\ |
|
||||
\ |
|
||||
socket.onerror = function (err) {\ |
|
||||
console.error('Socket encountered error: ', err.message, 'Closing socket');\ |
|
||||
};\ |
|
||||
\ |
|
||||
socket.onmessage = function(event) {\ |
|
||||
console.log(event.data);\ |
|
||||
var socketMsg = JSON.parse(event.data);\ |
|
||||
if (socketMsg.rfidId != null) {\ |
|
||||
document.getElementById('rfidIdMod').value = socketMsg.rfidId;\ |
|
||||
document.getElementById('rfidIdMusic').value = socketMsg.rfidId;\ |
|
||||
toastr.info(\"RFID Tag mit \"+ socketMsg.rfidId + \" erkannt.\" );\ |
|
||||
\ |
|
||||
$(\"#rfidIdMusic\").effect(\"highlight\", {color:\"#abf5af\"}, 3000);\ |
|
||||
$(\"#rfidIdMod\").effect(\"highlight\", {color:\"#abf5af\"}, 3000);\ |
|
||||
\ |
|
||||
} if (\"status\" in socketMsg) {\ |
|
||||
if (socketMsg.status == \"ok\") {\ |
|
||||
toastr.success(\"Aktion erfolgreich ausgeführt.\" );\ |
|
||||
}\ |
|
||||
} if (\"pong\" in socketMsg) {\ |
|
||||
if (socketMsg.pong == 'pong') {\ |
|
||||
pong();\ |
|
||||
}\ |
|
||||
} if (\"refreshFileList\" in socketMsg) {\ |
|
||||
hideFileIndexingState();\ |
|
||||
toastr.info(\"Die Dateiliste wurde neu erzeugt!\");\ |
|
||||
$('#filetree').jstree(true).refresh();\ |
|
||||
\ |
|
||||
}\ |
|
||||
if (\"indexingState\" in socketMsg) {\ |
|
||||
if(socketMsg.indexingState != null) {\ |
|
||||
$(\"#currentProcessedFile\").text(socketMsg.indexingState);\ |
|
||||
console.log(socketMsg.indexingState);\ |
|
||||
}\ |
|
||||
}\ |
|
||||
};\ |
|
||||
}\ |
|
||||
\ |
|
||||
function ping() {\ |
|
||||
var myObj = {\ |
|
||||
\"ping\": {\ |
|
||||
ping: 'ping'\ |
|
||||
}\ |
|
||||
};\ |
|
||||
var myJSON = JSON.stringify(myObj);\ |
|
||||
socket.send(myJSON);\ |
|
||||
tm = setTimeout(function () {\ |
|
||||
toastr.warning('Die Verbindung zum Tonuino ist unterbrochen! Bitte Seite neu laden.');\ |
|
||||
}, 5000);\ |
|
||||
}\ |
|
||||
\ |
|
||||
function pong() {\ |
|
||||
clearTimeout(tm);\ |
|
||||
}\ |
|
||||
\ |
|
||||
function refreshFileList(clickedId) {\ |
|
||||
lastIdclicked = clickedId;\ |
|
||||
var myObj = {\ |
|
||||
\"refreshFileList\": true\ |
|
||||
};\ |
|
||||
var myJSON = JSON.stringify(myObj);\ |
|
||||
$(\"#refreshAction\").hide();\ |
|
||||
socket.send(myJSON);\ |
|
||||
showFileIndexingState();\ |
|
||||
};\ |
|
||||
\ |
|
||||
function genSettings(clickedId) {\ |
|
||||
lastIdclicked = clickedId;\ |
|
||||
var myObj = {\ |
|
||||
\"general\": {\ |
|
||||
iVol: document.getElementById('initialVolume').value,\ |
|
||||
mVolSpeaker: document.getElementById('maxVolumeSpeaker').value,\ |
|
||||
mVolHeadphone: document.getElementById('maxVolumeHeadphone').value,\ |
|
||||
iBright: document.getElementById('initBrightness').value,\ |
|
||||
nBright: document.getElementById('nightBrightness').value,\ |
|
||||
iTime: document.getElementById('inactivityTime').value,\ |
|
||||
vWarning: document.getElementById('warningLowVoltage').value,\ |
|
||||
vIndLow: document.getElementById('voltageIndicatorLow').value,\ |
|
||||
vIndHi: document.getElementById('voltageIndicatorHigh').value,\ |
|
||||
vInt: document.getElementById('voltageCheckInterval').value\ |
|
||||
}\ |
|
||||
};\ |
|
||||
var myJSON = JSON.stringify(myObj);\ |
|
||||
socket.send(myJSON);\ |
|
||||
}\ |
|
||||
\ |
|
||||
function ftpSettings(clickedId) {\ |
|
||||
lastIdclicked = clickedId;\ |
|
||||
var myObj = {\ |
|
||||
\"ftp\": {\ |
|
||||
ftpUser: document.getElementById('ftpUser').value,\ |
|
||||
ftpPwd: document.getElementById('ftpPwd').value\ |
|
||||
}\ |
|
||||
};\ |
|
||||
var myJSON = JSON.stringify(myObj);\ |
|
||||
socket.send(myJSON);\ |
|
||||
}\ |
|
||||
\ |
|
||||
function mqttSettings(clickedId) {\ |
|
||||
lastIdclicked = clickedId;\ |
|
||||
var val;\ |
|
||||
if (document.getElementById('mqttEnable').checked) {\ |
|
||||
val = document.getElementById('mqttEnable').value;\ |
|
||||
} else {\ |
|
||||
val = 0;\ |
|
||||
}\ |
|
||||
var myObj = {\ |
|
||||
\"mqtt\": {\ |
|
||||
mqttEnable: val,\ |
|
||||
mqttServer: document.getElementById('mqttServer').value,\ |
|
||||
mqttUser: document.getElementById('mqttUser').value,\ |
|
||||
mqttPwd: document.getElementById('mqttPwd').value\ |
|
||||
}\ |
|
||||
};\ |
|
||||
var myJSON = JSON.stringify(myObj);\ |
|
||||
socket.send(myJSON);\ |
|
||||
}\ |
|
||||
\ |
|
||||
function rfidMods(clickedId) {\ |
|
||||
lastIdclicked = clickedId;\ |
|
||||
var myObj = {\ |
|
||||
\"rfidMod\": {\ |
|
||||
rfidIdMod: document.getElementById('rfidIdMod').value,\ |
|
||||
modId: document.getElementById('modId').value\ |
|
||||
}\ |
|
||||
};\ |
|
||||
var myJSON = JSON.stringify(myObj);\ |
|
||||
socket.send(myJSON);\ |
|
||||
}\ |
|
||||
\ |
|
||||
function removeTrSlash(str) {\ |
|
||||
if (str.substr(-1) === '/') {\ |
|
||||
return str.substr(0, str.length - 1);\ |
|
||||
}\ |
|
||||
return str;\ |
|
||||
}\ |
|
||||
\ |
|
||||
function rfidAssign(clickedId) {\ |
|
||||
lastIdclicked = clickedId;\ |
|
||||
var myObj = {\ |
|
||||
\"rfidAssign\": {\ |
|
||||
rfidIdMusic: document.getElementById('rfidIdMusic').value,\ |
|
||||
fileOrUrl: removeTrSlash(document.getElementById('fileOrUrl').value),\ |
|
||||
playMode: document.getElementById('playMode').value\ |
|
||||
}\ |
|
||||
};\ |
|
||||
var myJSON = JSON.stringify(myObj);\ |
|
||||
socket.send(myJSON);\ |
|
||||
}\ |
|
||||
\ |
|
||||
function wifiConfig(clickedId) {\ |
|
||||
lastIdclicked = clickedId;\ |
|
||||
var myObj = {\ |
|
||||
\"wifiConfig\": {\ |
|
||||
ssid: document.getElementById('ssid').value,\ |
|
||||
pwd: document.getElementById('pwd').value,\ |
|
||||
hostname: document.getElementById('hostname').value\ |
|
||||
}\ |
|
||||
};\ |
|
||||
var myJSON = JSON.stringify(myObj);\ |
|
||||
socket.send(myJSON);\ |
|
||||
}\ |
|
||||
\ |
|
||||
$(document).ready(function () {\ |
|
||||
connect();\ |
|
||||
renderFileTree();\ |
|
||||
\ |
|
||||
$(function () {\ |
|
||||
$('[data-toggle=\"tooltip\"]').tooltip();\ |
|
||||
});\ |
|
||||
});\ |
|
||||
</script>\ |
|
||||
</body>\ |
|
||||
</html>\ |
|
||||
"; |
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue