Blinken der LEDs und des WebInterface in Sync
This commit is contained in:
parent
c39fd04b07
commit
2f23c784ee
|
|
@ -85,7 +85,8 @@ Das System stellt einen vollständig konfigurierbaren Webserver bereit mit folge
|
||||||
**Port-Konfiguration:**
|
**Port-Konfiguration:**
|
||||||
- Individuelle Benennung jedes Ports möglich
|
- Individuelle Benennung jedes Ports möglich
|
||||||
- Aktivieren/Deaktivieren von Ports
|
- Aktivieren/Deaktivieren von Ports
|
||||||
- Persistente Speicherung der Konfiguration in `portconfig.json`
|
- Globale Blinkfrequenz für fehlerhafte Ports einstellbar (in ms)
|
||||||
|
- Persistente Speicherung der Konfiguration in `portconfig.json`, inklusive Blinkintervall
|
||||||
|
|
||||||
### 📡 WiFi & Netzwerkverbindung
|
### 📡 WiFi & Netzwerkverbindung
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,9 @@
|
||||||
<link rel="stylesheet" href="style.css">
|
<link rel="stylesheet" href="style.css">
|
||||||
<title>Port Status</title>
|
<title>Port Status</title>
|
||||||
<style>
|
<style>
|
||||||
|
:root {
|
||||||
|
--blink-duration: 1s;
|
||||||
|
}
|
||||||
.port {
|
.port {
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
|
@ -22,7 +25,7 @@
|
||||||
}
|
}
|
||||||
.missing {
|
.missing {
|
||||||
background-color: red;
|
background-color: red;
|
||||||
animation: blink 1s infinite;
|
animation: blink var(--blink-duration) infinite;
|
||||||
}
|
}
|
||||||
@keyframes blink {
|
@keyframes blink {
|
||||||
0%, 50% { background-color: red; }
|
0%, 50% { background-color: red; }
|
||||||
|
|
@ -43,6 +46,9 @@
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/status/data');
|
const response = await fetch('/status/data');
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
if (data.blink_interval !== undefined) {
|
||||||
|
updateBlinkDuration(data.blink_interval);
|
||||||
|
}
|
||||||
const container = document.getElementById('portsContainer');
|
const container = document.getElementById('portsContainer');
|
||||||
container.innerHTML = '';
|
container.innerHTML = '';
|
||||||
data.ports.forEach((port, index) => {
|
data.ports.forEach((port, index) => {
|
||||||
|
|
@ -72,6 +78,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// blink length updater must be defined before starting
|
||||||
|
async function updateBlinkDuration(blinkInterval) {
|
||||||
|
const period = blinkInterval * 2;
|
||||||
|
document.documentElement.style.setProperty('--blink-duration', period + 'ms');
|
||||||
|
}
|
||||||
|
|
||||||
loadStatus();
|
loadStatus();
|
||||||
setInterval(loadStatus, 1000); // Aktualisiere jede Sekunde
|
setInterval(loadStatus, 1000); // Aktualisiere jede Sekunde
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,9 @@
|
||||||
<body>
|
<body>
|
||||||
<h1>Port Konfiguration</h1>
|
<h1>Port Konfiguration</h1>
|
||||||
<form id="portForm">
|
<form id="portForm">
|
||||||
|
<label>
|
||||||
|
Blinkintervall (ms): <input type="number" id="blinkInput" name="blink_interval" min="1" value="">
|
||||||
|
</label><br>
|
||||||
<div id="portsContainer"></div>
|
<div id="portsContainer"></div>
|
||||||
<input type="submit" value="Speichern">
|
<input type="submit" value="Speichern">
|
||||||
</form>
|
</form>
|
||||||
|
|
@ -19,6 +22,9 @@
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/portconfig/data');
|
const response = await fetch('/portconfig/data');
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
if (data.blink_interval !== undefined) {
|
||||||
|
document.getElementById('blinkInput').value = data.blink_interval;
|
||||||
|
}
|
||||||
const container = document.getElementById('portsContainer');
|
const container = document.getElementById('portsContainer');
|
||||||
container.innerHTML = '';
|
container.innerHTML = '';
|
||||||
data.ports.forEach((port, index) => {
|
data.ports.forEach((port, index) => {
|
||||||
|
|
@ -46,11 +52,14 @@
|
||||||
enabled: formData.has(`enabled${i}`)
|
enabled: formData.has(`enabled${i}`)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
const blink = parseInt(formData.get('blink_interval')) || null;
|
||||||
|
const payload = { ports };
|
||||||
|
if (blink !== null) payload.blink_interval = blink;
|
||||||
try {
|
try {
|
||||||
await fetch('/portconfig', {
|
await fetch('/portconfig', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ ports })
|
body: JSON.stringify(payload)
|
||||||
});
|
});
|
||||||
alert('Konfiguration gespeichert!');
|
alert('Konfiguration gespeichert!');
|
||||||
loadConfig(); // Reload
|
loadConfig(); // Reload
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,9 @@
|
||||||
|
|
||||||
#define NEOPIXEL_PIN D6
|
#define NEOPIXEL_PIN D6
|
||||||
#define BRIGHTNESS 100
|
#define BRIGHTNESS 100
|
||||||
#define BLINK_INTERVAL 500 // Blink interval in milliseconds (0.5 seconds)
|
#define DEFAULT_BLINK_INTERVAL 500 // Blink interval in milliseconds (0.5 seconds)
|
||||||
#define SERIAL_SPEED 115200 // Serial Baudrate for ESP8266
|
#define SERIAL_SPEED 115200 // Serial Baudrate for ESP8266
|
||||||
|
|
||||||
|
// runtime variable - can be modified via web configuration
|
||||||
|
uint16_t blinkInterval = DEFAULT_BLINK_INTERVAL;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,10 @@ struct PortConfig {
|
||||||
bool enabled;
|
bool enabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// global blink interval stored along with port configuration
|
||||||
|
// defined in Config.ino as a variable so it can be changed at runtime
|
||||||
|
extern uint16_t blinkInterval;
|
||||||
|
|
||||||
PCF8575 expander1(EXPANDER1ADDRESS);
|
PCF8575 expander1(EXPANDER1ADDRESS);
|
||||||
uint8_t portStates[AMOUNTOFPORTS];
|
uint8_t portStates[AMOUNTOFPORTS];
|
||||||
uint8_t lastStates[AMOUNTOFPORTS] = {0};
|
uint8_t lastStates[AMOUNTOFPORTS] = {0};
|
||||||
|
|
@ -49,6 +53,10 @@ void loadPortConfig() {
|
||||||
portConfigs[i].name = ports[i]["name"] | ("Port " + String(i));
|
portConfigs[i].name = ports[i]["name"] | ("Port " + String(i));
|
||||||
portConfigs[i].enabled = ports[i]["enabled"] | true;
|
portConfigs[i].enabled = ports[i]["enabled"] | true;
|
||||||
}
|
}
|
||||||
|
// read blink interval if present
|
||||||
|
if (doc.containsKey("blink_interval")) {
|
||||||
|
blinkInterval = doc["blink_interval"] | blinkInterval;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Default
|
// Default
|
||||||
for (int i = 0; i < AMOUNTOFPORTS; i++) {
|
for (int i = 0; i < AMOUNTOFPORTS; i++) {
|
||||||
|
|
@ -73,6 +81,9 @@ void savePortConfig() {
|
||||||
port["name"] = portConfigs[i].name;
|
port["name"] = portConfigs[i].name;
|
||||||
port["enabled"] = portConfigs[i].enabled;
|
port["enabled"] = portConfigs[i].enabled;
|
||||||
}
|
}
|
||||||
|
// store blink interval as well
|
||||||
|
doc["blink_interval"] = blinkInterval;
|
||||||
|
|
||||||
File file = LittleFS.open("/portconfig.json", "w");
|
File file = LittleFS.open("/portconfig.json", "w");
|
||||||
if (file) {
|
if (file) {
|
||||||
serializeJson(doc, file);
|
serializeJson(doc, file);
|
||||||
|
|
@ -181,6 +192,8 @@ void setup() {
|
||||||
port["name"] = portConfigs[i].name;
|
port["name"] = portConfigs[i].name;
|
||||||
port["enabled"] = portConfigs[i].enabled;
|
port["enabled"] = portConfigs[i].enabled;
|
||||||
}
|
}
|
||||||
|
// include current blink interval
|
||||||
|
doc["blink_interval"] = blinkInterval;
|
||||||
String json;
|
String json;
|
||||||
serializeJson(doc, json);
|
serializeJson(doc, json);
|
||||||
server.send(200, "application/json", json);
|
server.send(200, "application/json", json);
|
||||||
|
|
@ -195,6 +208,10 @@ void setup() {
|
||||||
portConfigs[i].name = ports[i]["name"] | ("Port " + String(i));
|
portConfigs[i].name = ports[i]["name"] | ("Port " + String(i));
|
||||||
portConfigs[i].enabled = ports[i]["enabled"] | true;
|
portConfigs[i].enabled = ports[i]["enabled"] | true;
|
||||||
}
|
}
|
||||||
|
// update blink interval if provided
|
||||||
|
if (doc.containsKey("blink_interval")) {
|
||||||
|
blinkInterval = doc["blink_interval"] | blinkInterval;
|
||||||
|
}
|
||||||
savePortConfig();
|
savePortConfig();
|
||||||
}
|
}
|
||||||
server.sendHeader("Location", "/portconfig");
|
server.sendHeader("Location", "/portconfig");
|
||||||
|
|
@ -222,6 +239,9 @@ void setup() {
|
||||||
port["enabled"] = portConfigs[i].enabled;
|
port["enabled"] = portConfigs[i].enabled;
|
||||||
port["state"] = portStates[i];
|
port["state"] = portStates[i];
|
||||||
}
|
}
|
||||||
|
// include blink interval so the webpage can synchronize its animation
|
||||||
|
doc["blink_interval"] = blinkInterval;
|
||||||
|
|
||||||
String json;
|
String json;
|
||||||
serializeJson(doc, json);
|
serializeJson(doc, json);
|
||||||
server.send(200, "application/json", json);
|
server.send(200, "application/json", json);
|
||||||
|
|
@ -257,7 +277,7 @@ void loop() {
|
||||||
if (portStates[i] == 0) {
|
if (portStates[i] == 0) {
|
||||||
pixels->setPixelColor(i, pixels->Color(0, 150, 0)); // grün
|
pixels->setPixelColor(i, pixels->Color(0, 150, 0)); // grün
|
||||||
} else {
|
} else {
|
||||||
bool globalBlinkState = (millis() / BLINK_INTERVAL) % 2;
|
bool globalBlinkState = (millis() / blinkInterval) % 2;
|
||||||
if (globalBlinkState) {
|
if (globalBlinkState) {
|
||||||
pixels->setPixelColor(i, pixels->Color(150, 0, 0)); // rot
|
pixels->setPixelColor(i, pixels->Color(150, 0, 0)); // rot
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,10 @@
|
||||||
<link rel="stylesheet" href="style.css">
|
<link rel="stylesheet" href="style.css">
|
||||||
<title>Port Status</title>
|
<title>Port Status</title>
|
||||||
<style>
|
<style>
|
||||||
|
/* blink duration is defined via CSS variable so we can update it dynamically */
|
||||||
|
:root {
|
||||||
|
--blink-duration: 1s; /* default, will be overwritten by script */
|
||||||
|
}
|
||||||
.port {
|
.port {
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
|
@ -22,7 +26,7 @@
|
||||||
}
|
}
|
||||||
.missing {
|
.missing {
|
||||||
background-color: red;
|
background-color: red;
|
||||||
animation: blink 1s infinite;
|
animation: blink var(--blink-duration) infinite;
|
||||||
}
|
}
|
||||||
@keyframes blink {
|
@keyframes blink {
|
||||||
0%, 50% { background-color: red; }
|
0%, 50% { background-color: red; }
|
||||||
|
|
@ -39,10 +43,22 @@
|
||||||
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
// when status data is received we update the blink animation length
|
||||||
|
async function updateBlinkDuration(blinkInterval) {
|
||||||
|
// period is two intervals (on+off)
|
||||||
|
const period = blinkInterval * 2;
|
||||||
|
document.documentElement.style.setProperty('--blink-duration', period + 'ms');
|
||||||
|
}
|
||||||
|
|
||||||
async function loadStatus() {
|
async function loadStatus() {
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/status/data');
|
const response = await fetch('/status/data');
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
// synchronize blink rate on each update
|
||||||
|
if (data.blink_interval !== undefined) {
|
||||||
|
updateBlinkDuration(data.blink_interval);
|
||||||
|
}
|
||||||
|
|
||||||
const container = document.getElementById('portsContainer');
|
const container = document.getElementById('portsContainer');
|
||||||
container.innerHTML = '';
|
container.innerHTML = '';
|
||||||
data.ports.forEach((port, index) => {
|
data.ports.forEach((port, index) => {
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,9 @@
|
||||||
<body>
|
<body>
|
||||||
<h1>Port Konfiguration</h1>
|
<h1>Port Konfiguration</h1>
|
||||||
<form id="portForm">
|
<form id="portForm">
|
||||||
|
<label>
|
||||||
|
Blinkintervall (ms): <input type="number" id="blinkInput" name="blink_interval" min="1" value="">
|
||||||
|
</label><br>
|
||||||
<div id="portsContainer"></div>
|
<div id="portsContainer"></div>
|
||||||
<input type="submit" value="Speichern">
|
<input type="submit" value="Speichern">
|
||||||
</form>
|
</form>
|
||||||
|
|
@ -20,6 +23,10 @@
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/portconfig/data');
|
const response = await fetch('/portconfig/data');
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
// fill blink interval field if provided
|
||||||
|
if (data.blink_interval !== undefined) {
|
||||||
|
document.getElementById('blinkInput').value = data.blink_interval;
|
||||||
|
}
|
||||||
const container = document.getElementById('portsContainer');
|
const container = document.getElementById('portsContainer');
|
||||||
container.innerHTML = '';
|
container.innerHTML = '';
|
||||||
data.ports.forEach((port, index) => {
|
data.ports.forEach((port, index) => {
|
||||||
|
|
@ -47,11 +54,14 @@
|
||||||
enabled: formData.has(`enabled${i}`)
|
enabled: formData.has(`enabled${i}`)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
const blink = parseInt(formData.get('blink_interval')) || null;
|
||||||
|
const payload = { ports };
|
||||||
|
if (blink !== null) payload.blink_interval = blink;
|
||||||
try {
|
try {
|
||||||
await fetch('/portconfig', {
|
await fetch('/portconfig', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ ports })
|
body: JSON.stringify(payload)
|
||||||
});
|
});
|
||||||
alert('Konfiguration gespeichert!');
|
alert('Konfiguration gespeichert!');
|
||||||
loadConfig(); // Reload
|
loadConfig(); // Reload
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user