update and test with rpi zero 2

This commit is contained in:
2025-05-12 17:53:09 +02:00
parent c1fb89271c
commit 4b3b2d1772
73 changed files with 215772 additions and 2600 deletions

View File

@@ -28,16 +28,23 @@ server {
server_name _;
location / {
root /home/pi/LedBars/RpiLedBars/frontend/webapp/dist;
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
root /home/pi/RpiLedBars/frontend/web/;
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
location /old/ {
alias /home/pi/LedBars/RpiLedBars/frontend/web/;
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
alias /home/pi/RpiLedBars/frontend/web/;
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ index.html =404;
}
location /dev/ {
alias /home/pi/LedBars/RpiLedBars/frontend/webapp/dist;
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ index.html =404;
}
}

View File

@@ -20,7 +20,8 @@
<body class="bg-dark text-white">
<!-- Modal -->
<div class="modal fade text-black" id="reconnectBackdrop" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="connectionLostLabel" aria-hidden="true">
<div class="modal fade text-black" id="reconnectBackdrop" data-bs-backdrop="static" data-bs-keyboard="false"
tabindex="-1" aria-labelledby="connectionLostLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
@@ -31,9 +32,10 @@
Try reconnecting in <span id="time-left">60s</span>
</div>
<form id="ws-input" class="btn-group" role="group" aria-label="Select ws">
<input type="radio" class="btn-check" name="ws-selection" id="hotspot-ws" autocomplete="off" value="0" checked>
<input type="radio" class="btn-check" name="ws-selection" id="local-ws" autocomplete="off" value="1">
<input type="radio" class="btn-check" name="ws-selection" id="distant-ws" autocomplete="off" value="2">
<input type="radio" class="btn-check" name="ws-selection" id="hotspot-ws" autocomplete="off"
checked>
<input type="radio" class="btn-check" name="ws-selection" id="local-ws" autocomplete="off">
<input type="radio" class="btn-check" name="ws-selection" id="distant-ws" autocomplete="off">
</form>
<div class="modal-footer">
<button type="button" class="btn btn-primary" onclick="{timeout=1;}">Reconnect now</button>
@@ -50,17 +52,23 @@
<div class="row pt-2 gy-2">
<div class="col d-flex justify-content-center">
<form id="mode-input" class="btn-group" role="group" aria-label="Select mode">
<input type="radio" class="btn-check" name="mode-selection" id="test-mode" autocomplete="off" value="0" checked>
<input type="radio" class="btn-check" name="mode-selection" id="artnet-mode" autocomplete="off" value="1">
<input type="radio" class="btn-check" name="mode-selection" id="auto-mode" autocomplete="off" value="2">
<input type="radio" class="btn-check" name="mode-selection" id="manual-mode" autocomplete="off" value="3">
<input type="radio" class="btn-check" name="mode-selection" id="test-mode" autocomplete="off"
checked>
<input type="radio" class="btn-check" name="mode-selection" id="artnet-mode" autocomplete="off">
<input type="radio" class="btn-check" name="mode-selection" id="auto-mode" autocomplete="off">
<input type="radio" class="btn-check" name="mode-selection" id="manual-mode" autocomplete="off">
</form>
</div>
<div class="col d-flex justify-content-center">
<form id="pattern-input" class="btn-group" role="group" aria-label="Select pattern">
<input type="radio" class="btn-check" name="pattern-selection" id="pulse-pattern" autocomplete="off" value="0" checked>
<input type="radio" class="btn-check" name="pattern-selection" id="travel-pattern" autocomplete="off" value="1">
<input type="radio" class="btn-check" name="pattern-selection" id="strobe-pattern" autocomplete="off" value="2">
<input type="radio" class="btn-check" name="pattern-selection" id="bounce-pattern"
autocomplete="off" checked>
<input type="radio" class="btn-check" name="pattern-selection" id="pulse-pattern"
autocomplete="off">
<input type="radio" class="btn-check" name="pattern-selection" id="travel-pattern"
autocomplete="off">
<input type="radio" class="btn-check" name="pattern-selection" id="strobe-pattern"
autocomplete="off">
</form>
</div>
</div>
@@ -77,15 +85,16 @@
<div class="col d-flex justify-content-center">
<form id="channel-input" class="btn-group" role="group" aria-label="Select channel">
<!-- todo: Change to checkbox -->
<input type="radio" class="btn-check" name="channel-selection" id="all-channel" autocomplete="off" value="8" checked>
<input type="radio" class="btn-check" name="channel-selection" id="0-channel" autocomplete="off" value="0">
<input type="radio" class="btn-check" name="channel-selection" id="1-channel" autocomplete="off" value="1">
<input type="radio" class="btn-check" name="channel-selection" id="2-channel" autocomplete="off" value="2">
<input type="radio" class="btn-check" name="channel-selection" id="3-channel" autocomplete="off" value="3">
<input type="radio" class="btn-check" name="channel-selection" id="4-channel" autocomplete="off" value="4">
<input type="radio" class="btn-check" name="channel-selection" id="5-channel" autocomplete="off" value="5">
<input type="radio" class="btn-check" name="channel-selection" id="6-channel" autocomplete="off" value="6">
<input type="radio" class="btn-check" name="channel-selection" id="7-channel" autocomplete="off" value="7">
<input type="radio" class="btn-check" name="channel-selection" id="0-channel" autocomplete="off">
<input type="radio" class="btn-check" name="channel-selection" id="1-channel" autocomplete="off">
<input type="radio" class="btn-check" name="channel-selection" id="2-channel" autocomplete="off">
<input type="radio" class="btn-check" name="channel-selection" id="3-channel" autocomplete="off">
<input type="radio" class="btn-check" name="channel-selection" id="4-channel" autocomplete="off">
<input type="radio" class="btn-check" name="channel-selection" id="5-channel" autocomplete="off">
<input type="radio" class="btn-check" name="channel-selection" id="6-channel" autocomplete="off">
<input type="radio" class="btn-check" name="channel-selection" id="7-channel" autocomplete="off">
<input type="radio" class="btn-check" name="channel-selection" id="all-channel" autocomplete="off"
checked>
</form>
</div>
</div>
@@ -94,7 +103,8 @@
<label class="form-label col-9 col-sm-2 text-sm-end" for="formControlRange">Sensitivity</label>
<span class="col-3 col-sm-1 text-end">64</span>
<div class="col col-sm-9">
<input type="range" class="form-range" id="formControlRange" max="127" oninput="sensitivityCallback(this)">
<input type="range" class="form-range" id="formControlRange" max="127"
oninput="sensitivityCallback(this)">
</div>
</div>
@@ -102,15 +112,25 @@
<label class="form-label col-9 col-sm-2 text-sm-end" for="formControlRange">Gravity</label>
<span class="col-3 col-sm-1 text-end">64</span>
<div class="col col-sm-9">
<input type="range" class="form-range col-auto" id="formControlRange" max="127" oninput="gravityCallback(this)">
<input type="range" class="form-range col-auto" id="formControlRange" max="127"
oninput="gravityCallback(this)">
</div>
</div>
<div class="row pt-2 gy-2">
<label class="form-label col-9 col-sm-2 text-sm-end" for="formControlRange">Hue interval</label>
<span class="col-3 col-sm-1 text-end">0</span>
<div class="col col-sm-9">
<input type="range" class="form-range col-auto" id="formControlRange" min="-63" max="63"
oninput="hueIntervalCallback(this)">
</div>
</div>
<div class="row pt-2 gy-2">
<div class="col">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="modulateColor" onclick="colorModulateCallback(this)">
<input class="form-check-input" type="checkbox" id="modulateColor"
onclick="colorModulateCallback(this)">
<label class="form-check-label" for="modulateColor">Modulate color</label>
</div>
</div>
@@ -118,20 +138,29 @@
<div class="row pt-2 gy-2">
<div id="mainPicker" class="col d-flex justify-content-center"></div>
<div id="modulationPicker" class="col d-none d-flex justify-content-center"></div>
</div>
<div class="row pt-2 gy-2">
<label class="form-label col-9 col-sm-2 text-sm-end" for="formControlRange">Modulation interval</label>
<span class="col-3 col-sm-1 text-end">0</span>
<div class="col col-sm-9">
<input type="range" class="form-range col-auto" id="formControlRange" min="-63" max="63"
oninput="modulationIntervalCallback(this)">
</div>
</div>
<div class="row pt-2 gy-2">
<label class="form-label col-9 col-sm-2 text-sm-end" for="formControlRange">Modulation speed</label>
<span class="col-3 col-sm-auto text-end" id="rangeval">50</span>
<span class="col-3 col-sm-1 text-end" id="rangeval">50</span>
<div class="col col-sm-9">
<input type="range" class="form-range col-auto" id="formControlRange" oninput="rangeCallback(this)">
<input type="range" class="form-range col-auto" id="formControlRange" max="127"
oninput="modulationSpeedCallback(this)">
</div>
</div>
<div class="row pt-2 gy-2">
<label class="form-label col-9 col-sm-2 text-sm-end" for="formControlRange">Freq</label>
<span class="col-3 col-sm-auto text-end" id="rangeval">50</span>
<span class="col-3 col-sm-1 text-end" id="rangeval">50</span>
<div class="col col-sm-9">
<input type="range" class="form-range col-auto" id="formControlRange" oninput="rangeCallback(this)">
</div>

View File

@@ -17,21 +17,21 @@ function addLabelAndListener(name, callback) {
label.classList.add("text-capitalize");
label.setAttribute("for", element.id);
labelText = element.id.split('-')[0];
element.value = inputIndex;
label.innerHTML = labelText;
element.insertAdjacentElement("afterend", label);
}
}
addLabelAndListener("ws", wsSelectCallback);
addLabelAndListener("mode", modeSelectCallback);
addLabelAndListener("pattern", patternSelectCallback);
addLabelAndListener("channel", channelSelectCallback);
addLabelAndListener("ws", buttonSelectCallback);
addLabelAndListener("mode", buttonSelectCallback);
addLabelAndListener("pattern", buttonSelectCallback);
addLabelAndListener("channel", buttonSelectCallback);
// addLabelAndListener("channelGlobal", channelSelectCallback);
var colorPicker = new iro.ColorPicker('#mainPicker', {
colors: [
'hsl(0, 100, 50)', // pure red
'hsl(180, 50, 100)' // pure green
],
layout: [{
component: iro.ui.Wheel,
@@ -51,28 +51,28 @@ var colorPicker = new iro.ColorPicker('#mainPicker', {
handleRadius: 14
});
var modulationPicker = new iro.ColorPicker('#modulationPicker', {
colors: [
'hsl(0, 100, 50)', // pure red
],
layout: [{
component: iro.ui.Wheel,
options: {
wheelLightness: false
}
}, {
component: iro.ui.Slider,
options: {
sliderType: 'value'
}
}],
layoutDirection: 'horizontal',
// display: "flex",
width: 250,
margin: 0,
handleRadius: 14
});
// var modulationPicker = new iro.ColorPicker('#modulationPicker', {
// colors: [
// 'hsl(0, 100, 50)', // pure red
// ],
// layout: [{
// component: iro.ui.Wheel,
// options: {
// wheelLightness: false
// }
// }, {
// component: iro.ui.Slider,
// options: {
// sliderType: 'value'
// }
// }],
// layoutDirection: 'horizontal',
// // display: "flex",
// width: 250,
// margin: 0,
// handleRadius: 14
// });
reconnect();
colorPicker.on("color:change", colorChangeCallback);
modulationPicker.on("color:change", modulationColorChangeCallback);
// modulationPicker.on("color:change", modulationColorChangeCallback);

View File

@@ -11,24 +11,19 @@ function wait_reconnection() {
}
function reconnect() {
// for (i in ws_address_list) {
// console.log("try to connect " + ws_address_list[i])
// try {
socket = new WebSocket(ws_address_list[ws_index]);
// } catch (error) {
// console.error("failed to connect to " + ws_address_list[i] + "\n" + error);
// }
// }
// socket = new WebSocket("ws://192.168.1.130");
address = window.location.href.replace(/(http|https):\/\//i, "ws://")
address = address.slice(0, address.length - 1) + ":8080"
console.log("connecting to " + address)
socket = new WebSocket(address)
timeout = 60;
socket.onopen = function(e) {
socket.onopen = function (e) {
console.log("[open] ws: Connection established");
clearInterval(timer);
modal.hide();
};
socket.onmessage = function(event) {
socket.onmessage = function (event) {
console.log(`[message] ws: Data received from server: ${event.data}`);
let message = event.data.split(":");
let command = message[0];
@@ -44,7 +39,7 @@ function reconnect() {
}
};
socket.onclose = function(event) {
socket.onclose = function (event) {
if (event.wasClean) {
console.log(`[close] ws: Connection closed cleanly, code=${event.code} reason=${event.reason}`);
} else {
@@ -56,7 +51,7 @@ function reconnect() {
}
};
socket.onerror = function(error) {
socket.onerror = function (error) {
console.log(`[error] ws: ${error.message}`);
++ws_index;
if (ws_index >= ws_address_list.length) {

View File

@@ -1,3 +1,5 @@
var eventd;
function wsSelectCallback(event) {
// todo: disable form on this != auto
if (event.target.nodeName == 'INPUT') {
@@ -6,12 +8,14 @@ function wsSelectCallback(event) {
}
}
function modeSelectCallback(event) {
function buttonSelectCallback(event) {
// todo: disable form on this != auto
eventd = event
if (event.target.nodeName == 'INPUT') {
console.log("m:" + event.target.value);
newMode = event.target.parentElement.id.split('-')[0] + ":" + event.target.value
console.log(newMode);
if (socket.readyState == WebSocket.OPEN) {
socket.send("m:" + event.target.value);
socket.send(newMode);
}
}
}
@@ -51,15 +55,21 @@ function gravityCallback(element) {
rangeCallback(element);
}
var eventd;
function hueIntervalCallback(element) {
console.log("i:" + (Number(element.value) + 63 + 1));
if (socket.readyState == WebSocket.OPEN) {
socket.send("i:" + (Number(element.value) + 63 + 1));
}
rangeCallback(element);
}
function colorModulateCallback(element) {
eventd = element;
if (element.checked) {
document.getElementById("modulationPicker").classList.remove("d-none");
} else {
document.getElementById("modulationPicker").classList.add("d-none");
}
// eventd = element;
// if (element.checked) {
// document.getElementById("modulationPicker").classList.remove("d-none");
// } else {
// document.getElementById("modulationPicker").classList.add("d-none");
// }
console.log("s: " + element.checked);
if (socket.readyState == WebSocket.OPEN) {
socket.send("s:" + element.checked);
@@ -73,11 +83,20 @@ function colorChangeCallback(color) {
}
}
function modulationColorChangeCallback(color) {
console.log("c: " + (color.index + 2) + ", h: " + color.hsl.h + ", s: " + color.hsl.s + ", l: " + color.hsl.l + "}");
function modulationIntervalCallback(element) {
console.log("t:" + (Number(element.value) + 63 + 1));
if (socket.readyState == WebSocket.OPEN) {
socket.send("c:" + (color.index + 2) + "," + color.hsl.h + "," + color.hsl.s + "," + color.hsl.l);
socket.send("t:" + (Number(element.value) + 63 + 1));
}
rangeCallback(element);
}
function modulationSpeedCallback(element) {
console.log("u:" + element.value);
if (socket.readyState == WebSocket.OPEN) {
socket.send("u:" + element.value);
}
rangeCallback(element);
}
function rangeCallback(element) {