Updates from pi
This commit is contained in:
parent
84612aded5
commit
c1fb89271c
18
RpiLedBars/.vscode/c_cpp_properties.json
vendored
Normal file
18
RpiLedBars/.vscode/c_cpp_properties.json
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Linux",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/**"
|
||||||
|
],
|
||||||
|
"defines": [],
|
||||||
|
"compilerPath": "/usr/bin/gcc",
|
||||||
|
"cStandard": "gnu17",
|
||||||
|
"cppStandard": "gnu++14",
|
||||||
|
"intelliSenseMode": "linux-gcc-arm",
|
||||||
|
"compileCommands": "${workspaceFolder}/build/compile_commands.json",
|
||||||
|
"configurationProvider": "ms-vscode.cmake-tools"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
3
RpiLedBars/.vscode/settings.json
vendored
Normal file
3
RpiLedBars/.vscode/settings.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"cmake.sourceDirectory": "${workspaceFolder}/backend"
|
||||||
|
}
|
@ -7,4 +7,6 @@ set(CMAKE_C_STANDARD 99)
|
|||||||
|
|
||||||
add_subdirectory(libs)
|
add_subdirectory(libs)
|
||||||
|
|
||||||
|
configure_file(cava_config ../ COPYONLY)
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
@ -1,5 +1,6 @@
|
|||||||
# make
|
# make
|
||||||
cp ./bin/pixled bin/service_pixled
|
install -v -D ../build/src/RpiLedBars cava_config -t /opt/pixled/
|
||||||
|
# cp ./bin/pixled bin/service_pixled
|
||||||
sudo -s bash -c "cp pixled.service /etc/systemd/system; systemctl daemon-reload"
|
sudo -s bash -c "cp pixled.service /etc/systemd/system; systemctl daemon-reload"
|
||||||
# sudo -s bash -c "systemctl enable pixled"
|
# sudo -s bash -c "systemctl enable pixled"
|
||||||
sudo -s bash -c "systemctl restart pixled"
|
sudo -s bash -c "systemctl restart pixled"
|
@ -1,5 +1,7 @@
|
|||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
|
set(FETCHCONTENT_FULLY_DISCONNECTED ON)
|
||||||
|
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
logc
|
logc
|
||||||
GIT_REPOSITORY "https://github.com/Tropicananass/log.c.git"
|
GIT_REPOSITORY "https://github.com/Tropicananass/log.c.git"
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=pixled
|
Description=RpiLedBars
|
||||||
After=network.target
|
After=network.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
ExecStart=pixled -n 60 -d 2
|
WorkingDirectory=/opt/pixled
|
||||||
|
ExecStart=/opt/pixled/RpiLedBars -n 60 -d 2
|
||||||
Restart=always
|
Restart=always
|
||||||
User=root
|
User=root
|
||||||
Group=root
|
Group=root
|
||||||
|
@ -106,7 +106,7 @@ void set_sensitivity(int channel, int8_t sensitivity8) {
|
|||||||
} else {
|
} else {
|
||||||
param.ledbar[channel].sensitivity = sensitivity;
|
param.ledbar[channel].sensitivity = sensitivity;
|
||||||
}
|
}
|
||||||
log_debug("Sensitivity : %f", sensitivity);
|
log_debug("Sensitivity[%d] : %f", channel, sensitivity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_hue_base(int channel, int8_t hueBase8) {
|
void set_hue_base(int channel, int8_t hueBase8) {
|
||||||
|
@ -187,7 +187,7 @@ static int start_cava_process() {
|
|||||||
if (cavaPid == 0) {
|
if (cavaPid == 0) {
|
||||||
/* Child process*/
|
/* Child process*/
|
||||||
// int fdLogOut;
|
// int fdLogOut;
|
||||||
char *args[] = {"cava", "-p", "/home/pi/LedBars/RpiLedBars/cava_config", NULL};
|
char *args[] = {"cava", "-p", "./cava_config", NULL};
|
||||||
|
|
||||||
/* Close reading end of the pipe */
|
/* Close reading end of the pipe */
|
||||||
close(fdCavaPipe[0]);
|
close(fdCavaPipe[0]);
|
||||||
|
@ -34,6 +34,8 @@
|
|||||||
|
|
||||||
int client_fd = -1;
|
int client_fd = -1;
|
||||||
|
|
||||||
|
int channel = LED_NCHANS;
|
||||||
|
|
||||||
/***************************************************************************************************
|
/***************************************************************************************************
|
||||||
* Internal Function Prototypes
|
* Internal Function Prototypes
|
||||||
**************************************************************************************************/
|
**************************************************************************************************/
|
||||||
@ -77,6 +79,14 @@ void pattern_command_handler(char *payload);
|
|||||||
|
|
||||||
void color_command_handler(char *payload);
|
void color_command_handler(char *payload);
|
||||||
|
|
||||||
|
void modulate_command_handler(char *payload);
|
||||||
|
|
||||||
|
void channel_command_handler(char *payload);
|
||||||
|
|
||||||
|
void sensitivity_command_handler(char *payload);
|
||||||
|
|
||||||
|
void gravity_command_handler(char *payload);
|
||||||
|
|
||||||
/***************************************************************************************************
|
/***************************************************************************************************
|
||||||
* External Function Definitions
|
* External Function Definitions
|
||||||
**************************************************************************************************/
|
**************************************************************************************************/
|
||||||
@ -142,6 +152,18 @@ void onmessage(int fd, const unsigned char *msg, uint64_t size, int type) {
|
|||||||
case 'c':
|
case 'c':
|
||||||
color_command_handler(payload);
|
color_command_handler(payload);
|
||||||
break;
|
break;
|
||||||
|
case 's':
|
||||||
|
modulate_command_handler(payload);
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
channel_command_handler(payload);
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
sensitivity_command_handler(payload);
|
||||||
|
break;
|
||||||
|
case 'g':
|
||||||
|
gravity_command_handler(payload);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
log_warn("Unkown command in \"%s\"", msgStr);
|
log_warn("Unkown command in \"%s\"", msgStr);
|
||||||
@ -187,8 +209,36 @@ void color_command_handler(char *payload) {
|
|||||||
log_debug(" - %s", tokenArray[n]);
|
log_debug(" - %s", tokenArray[n]);
|
||||||
}
|
}
|
||||||
if (atoi(tokenArray[0]) == 0) {
|
if (atoi(tokenArray[0]) == 0) {
|
||||||
set_hue_base(LED_NCHANS, atoi(tokenArray[1]) * INT8_MAX / HUE_MAX);
|
set_hue_base(channel, atoi(tokenArray[1]) * INT8_MAX / HUE_MAX);
|
||||||
set_saturation(LED_NCHANS, atoi(tokenArray[2]) * INT8_MAX / 100);
|
set_saturation(channel, atoi(tokenArray[2]) * INT8_MAX / 100);
|
||||||
set_luminosity(LED_NCHANS, atoi(tokenArray[3]) * INT8_MAX / 100);
|
set_luminosity(channel, atoi(tokenArray[3]) * INT8_MAX / 100);
|
||||||
|
} else {
|
||||||
|
set_saturation(channel, atoi(tokenArray[2]) * INT8_MAX / 100);
|
||||||
|
set_luminosity(channel, atoi(tokenArray[3]) * INT8_MAX / 100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void modulate_command_handler(char *payload) {
|
||||||
|
bool modulate;
|
||||||
|
modulate = strcmp(payload, "true") == 0;
|
||||||
|
log_debug("modulate :%s", modulate ? "true" : "false");
|
||||||
|
set_hue_auto_shift(modulate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void channel_command_handler(char *payload) {
|
||||||
|
int newChannel = atoi(payload);
|
||||||
|
if (0 <= newChannel && newChannel <= LED_NCHANS) {
|
||||||
|
log_debug("Channel: %d", newChannel);
|
||||||
|
channel = newChannel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sensitivity_command_handler(char *payload) {
|
||||||
|
int newSensitivity = atoi(payload);
|
||||||
|
set_sensitivity(channel, newSensitivity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gravity_command_handler(char *payload) {
|
||||||
|
int newGravity = atoi(payload);
|
||||||
|
set_gravity(newGravity);
|
||||||
|
}
|
24
RpiLedBars/cava_config
Normal file
24
RpiLedBars/cava_config
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
[general]
|
||||||
|
framerate = 60
|
||||||
|
autosens = 0
|
||||||
|
sensitivity = 200
|
||||||
|
bars = 128
|
||||||
|
|
||||||
|
[input]
|
||||||
|
method = alsa
|
||||||
|
source = plughw:1
|
||||||
|
|
||||||
|
[output]
|
||||||
|
method = raw
|
||||||
|
channels = mono
|
||||||
|
mono_option = left
|
||||||
|
data_format = ascii
|
||||||
|
ascii_max_range=65535
|
||||||
|
bit_format = 16bit
|
||||||
|
|
||||||
|
[smoothing]
|
||||||
|
integral = 77
|
||||||
|
monstercat = 0
|
||||||
|
waves = 0
|
||||||
|
gravity = 0
|
||||||
|
|
@ -38,6 +38,6 @@ server {
|
|||||||
alias /home/pi/LedBars/RpiLedBars/frontend/web/;
|
alias /home/pi/LedBars/RpiLedBars/frontend/web/;
|
||||||
# First attempt to serve request as file, then
|
# First attempt to serve request as file, then
|
||||||
# as directory, then fall back to displaying a 404.
|
# as directory, then fall back to displaying a 404.
|
||||||
try_files $uri $uri/ index.html =404;
|
try_files $uri $uri/ =404;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,11 @@
|
|||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
Try reconnecting in <span id="time-left">60s</span>
|
Try reconnecting in <span id="time-left">60s</span>
|
||||||
</div>
|
</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">
|
||||||
|
</form>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-primary" onclick="{timeout=1;}">Reconnect now</button>
|
<button type="button" class="btn btn-primary" onclick="{timeout=1;}">Reconnect now</button>
|
||||||
</div>
|
</div>
|
||||||
@ -72,32 +77,32 @@
|
|||||||
<div class="col d-flex justify-content-center">
|
<div class="col d-flex justify-content-center">
|
||||||
<form id="channel-input" class="btn-group" role="group" aria-label="Select channel">
|
<form id="channel-input" class="btn-group" role="group" aria-label="Select channel">
|
||||||
<!-- todo: Change to checkbox -->
|
<!-- todo: Change to checkbox -->
|
||||||
<input type="radio" class="btn-check" name="channel-selection" id="all-channel" autocomplete="off" checked>
|
<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" 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" checked>
|
<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" checked>
|
<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" checked>
|
<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" checked>
|
<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" checked>
|
<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" checked>
|
<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" checked>
|
<input type="radio" class="btn-check" name="channel-selection" id="7-channel" autocomplete="off" value="7">
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row pt-2 gy-2">
|
<div class="row pt-2 gy-2">
|
||||||
<label class="form-label col-9 col-sm-2 text-sm-end" for="formControlRange">Sensitivity</label>
|
<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">50</span>
|
<span class="col-3 col-sm-1 text-end">64</span>
|
||||||
<div class="col col-sm-9">
|
<div class="col col-sm-9">
|
||||||
<input type="range" class="form-range" id="formControlRange" oninput="rangeCallback(this)">
|
<input type="range" class="form-range" id="formControlRange" max="127" oninput="sensitivityCallback(this)">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row pt-2 gy-2">
|
<div class="row pt-2 gy-2">
|
||||||
<label class="form-label col-9 col-sm-2 text-sm-end" for="formControlRange">Gravity</label>
|
<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">50</span>
|
<span class="col-3 col-sm-1 text-end">64</span>
|
||||||
<div class="col col-sm-9">
|
<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="gravityCallback(this)">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ function addLabelAndListener(name, callback) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addLabelAndListener("ws", wsSelectCallback);
|
||||||
addLabelAndListener("mode", modeSelectCallback);
|
addLabelAndListener("mode", modeSelectCallback);
|
||||||
addLabelAndListener("pattern", patternSelectCallback);
|
addLabelAndListener("pattern", patternSelectCallback);
|
||||||
addLabelAndListener("channel", channelSelectCallback);
|
addLabelAndListener("channel", channelSelectCallback);
|
||||||
@ -74,4 +75,4 @@ var modulationPicker = new iro.ColorPicker('#modulationPicker', {
|
|||||||
|
|
||||||
reconnect();
|
reconnect();
|
||||||
colorPicker.on("color:change", colorChangeCallback);
|
colorPicker.on("color:change", colorChangeCallback);
|
||||||
modulationPicker.on("color:change", colorChangeCallback);
|
modulationPicker.on("color:change", modulationColorChangeCallback);
|
@ -1,3 +1,6 @@
|
|||||||
|
var ws_index = 0
|
||||||
|
const ws_address_list = ["ws://192.168.4.1:8080", "ws://192.168.1.130:8080", "ws://tropicananass.ovh:8080"]
|
||||||
|
|
||||||
function wait_reconnection() {
|
function wait_reconnection() {
|
||||||
--timeout;
|
--timeout;
|
||||||
document.getElementById("time-left").innerHTML = timeout + "s";
|
document.getElementById("time-left").innerHTML = timeout + "s";
|
||||||
@ -8,7 +11,15 @@ function wait_reconnection() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function reconnect() {
|
function reconnect() {
|
||||||
socket = new WebSocket("ws://tropicananass.ovh:8080");
|
// 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");
|
||||||
timeout = 60;
|
timeout = 60;
|
||||||
|
|
||||||
socket.onopen = function(e) {
|
socket.onopen = function(e) {
|
||||||
@ -47,5 +58,10 @@ function reconnect() {
|
|||||||
|
|
||||||
socket.onerror = function(error) {
|
socket.onerror = function(error) {
|
||||||
console.log(`[error] ws: ${error.message}`);
|
console.log(`[error] ws: ${error.message}`);
|
||||||
|
++ws_index;
|
||||||
|
if (ws_index >= ws_address_list.length) {
|
||||||
|
ws_index = 0;
|
||||||
|
}
|
||||||
|
document.getElementById("ws-input").elements["ws-selection"][ws_index].checked = true;
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -1,3 +1,11 @@
|
|||||||
|
function wsSelectCallback(event) {
|
||||||
|
// todo: disable form on this != auto
|
||||||
|
if (event.target.nodeName == 'INPUT') {
|
||||||
|
console.log("ws:" + event.target.value);
|
||||||
|
ws_index = event.target.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function modeSelectCallback(event) {
|
function modeSelectCallback(event) {
|
||||||
// todo: disable form on this != auto
|
// todo: disable form on this != auto
|
||||||
if (event.target.nodeName == 'INPUT') {
|
if (event.target.nodeName == 'INPUT') {
|
||||||
@ -20,28 +28,27 @@ function patternSelectCallback(event) {
|
|||||||
|
|
||||||
function channelSelectCallback(event) {
|
function channelSelectCallback(event) {
|
||||||
if (event.target.nodeName == 'INPUT') {
|
if (event.target.nodeName == 'INPUT') {
|
||||||
channel = event.target.id.split("-")[0];
|
console.log("h:" + event.target.value);
|
||||||
if (channel == "all") {
|
if (socket.readyState == WebSocket.OPEN) {
|
||||||
// inputArray = document.getElementById("channel-input").elements[name + "channel-selection"]
|
socket.send("h:" + event.target.value);
|
||||||
// for (let inputIndex = 0; inputIndex < inputArray.length; inputIndex++) {
|
|
||||||
// inputArray[inputIndex].checked = false;
|
|
||||||
// }
|
|
||||||
selectedChannel = 8;
|
|
||||||
} else if (channel == "none") {
|
|
||||||
inputArray = document.getElementById("channel-input").elements[name + "channel-selection"]
|
|
||||||
for (let inputIndex = 0; inputIndex < inputArray.length; inputIndex++) {
|
|
||||||
inputArray[inputIndex].checked = false;
|
|
||||||
}
|
}
|
||||||
selectedChannel = -1;
|
|
||||||
} else {
|
|
||||||
inputArray = document.getElementById("channelGlobal-input").elements[name + "channelGlobal-selection"]
|
|
||||||
for (let inputIndex = 0; inputIndex < inputArray.length; inputIndex++) {
|
|
||||||
inputArray[inputIndex].checked = false;
|
|
||||||
}
|
}
|
||||||
selectedChannel = channel;
|
}
|
||||||
|
|
||||||
|
function sensitivityCallback(element) {
|
||||||
|
console.log("e:" + element.value);
|
||||||
|
if (socket.readyState == WebSocket.OPEN) {
|
||||||
|
socket.send("e:" + element.value);
|
||||||
}
|
}
|
||||||
console.log("channel:" + selectedChannel);
|
rangeCallback(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
function gravityCallback(element) {
|
||||||
|
console.log("g:" + element.value);
|
||||||
|
if (socket.readyState == WebSocket.OPEN) {
|
||||||
|
socket.send("g:" + element.value);
|
||||||
}
|
}
|
||||||
|
rangeCallback(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
var eventd;
|
var eventd;
|
||||||
@ -54,6 +61,9 @@ function colorModulateCallback(element) {
|
|||||||
document.getElementById("modulationPicker").classList.add("d-none");
|
document.getElementById("modulationPicker").classList.add("d-none");
|
||||||
}
|
}
|
||||||
console.log("s: " + element.checked);
|
console.log("s: " + element.checked);
|
||||||
|
if (socket.readyState == WebSocket.OPEN) {
|
||||||
|
socket.send("s:" + element.checked);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function colorChangeCallback(color) {
|
function colorChangeCallback(color) {
|
||||||
@ -63,6 +73,13 @@ function colorChangeCallback(color) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function modulationColorChangeCallback(color) {
|
||||||
|
console.log("c: " + (color.index + 2) + ", h: " + color.hsl.h + ", s: " + color.hsl.s + ", l: " + color.hsl.l + "}");
|
||||||
|
if (socket.readyState == WebSocket.OPEN) {
|
||||||
|
socket.send("c:" + (color.index + 2) + "," + color.hsl.h + "," + color.hsl.s + "," + color.hsl.l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function rangeCallback(element) {
|
function rangeCallback(element) {
|
||||||
eventd = this
|
eventd = this
|
||||||
element.parentNode.parentElement.getElementsByTagName('span')[0].innerText = element.value;
|
element.parentNode.parentElement.getElementsByTagName('span')[0].innerText = element.value;
|
||||||
|
@ -1,33 +1,93 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="bg-dark text-white">
|
<div class="bg-dark text-white">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row py-4 text-center" id="header">
|
<div class="row py-4 text-center" id="header">
|
||||||
<h1> Tropicananass Leds </h1>
|
<h1>Tropicananass Leds</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Reconnect></Reconnect>
|
<Reconnect></Reconnect>
|
||||||
|
|
||||||
<ModeSelect :mode_list="{Test, Artnet, Auto, Manual}"></ModeSelect>
|
<ModeSelect mode_list="{Test, Artnet, Auto, Manual}"></ModeSelect>
|
||||||
|
|
||||||
<div class="row pt-2 gy-2">
|
<div class="row pt-2 gy-2">
|
||||||
<div class="col d-flex justify-content-center">
|
<div class="col d-flex justify-content-center">
|
||||||
<form id="mode-input" class="btn-group" role="group" aria-label="Select mode">
|
<form
|
||||||
<input type="radio" class="btn-check" name="mode-selection" id="test-mode" autocomplete="off" value="0" checked>
|
id="mode-input"
|
||||||
<input type="radio" class="btn-check" name="mode-selection" id="artnet-mode" autocomplete="off" value="1">
|
class="btn-group"
|
||||||
<input type="radio" class="btn-check" name="mode-selection" id="auto-mode" autocomplete="off" value="2">
|
role="group"
|
||||||
<input type="radio" class="btn-check" name="mode-selection" id="manual-mode" autocomplete="off" value="3">
|
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"
|
||||||
|
/>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="col d-flex justify-content-center">
|
<div class="col d-flex justify-content-center">
|
||||||
<form id="pattern-input" class="btn-group" role="group" aria-label="Select pattern">
|
<form
|
||||||
<input type="radio" class="btn-check" name="pattern-selection" id="pulse-pattern" autocomplete="off" value="0" checked>
|
id="pattern-input"
|
||||||
<input type="radio" class="btn-check" name="pattern-selection" id="travel-pattern" autocomplete="off" value="1">
|
class="btn-group"
|
||||||
<input type="radio" class="btn-check" name="pattern-selection" id="strobe-pattern" autocomplete="off" value="2">
|
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"
|
||||||
|
/>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="row pt-2 gy-2">
|
<div class="row pt-2 gy-2">
|
||||||
<legend class="col-12 col-sm-auto">Channel</legend>
|
<legend class="col-12 col-sm-auto">Channel</legend>
|
||||||
<!-- <div class="col d-flex justify-content-center">
|
<!-- <div class="col d-flex justify-content-center">
|
||||||
@ -37,87 +97,199 @@
|
|||||||
</form>
|
</form>
|
||||||
</div> -->
|
</div> -->
|
||||||
<div class="col d-flex justify-content-center">
|
<div class="col d-flex justify-content-center">
|
||||||
<form id="channel-input" class="btn-group" role="group" aria-label="Select channel">
|
<form
|
||||||
|
id="channel-input"
|
||||||
|
class="btn-group"
|
||||||
|
role="group"
|
||||||
|
aria-label="Select channel"
|
||||||
|
>
|
||||||
<!-- todo: Change to checkbox -->
|
<!-- todo: Change to checkbox -->
|
||||||
<input type="radio" class="btn-check" name="channel-selection" id="all-channel" autocomplete="off" checked>
|
<input
|
||||||
<input type="radio" class="btn-check" name="channel-selection" id="0-channel" autocomplete="off" checked>
|
type="radio"
|
||||||
<input type="radio" class="btn-check" name="channel-selection" id="1-channel" autocomplete="off" checked>
|
class="btn-check"
|
||||||
<input type="radio" class="btn-check" name="channel-selection" id="2-channel" autocomplete="off" checked>
|
name="channel-selection"
|
||||||
<input type="radio" class="btn-check" name="channel-selection" id="3-channel" autocomplete="off" checked>
|
id="all-channel"
|
||||||
<input type="radio" class="btn-check" name="channel-selection" id="4-channel" autocomplete="off" checked>
|
autocomplete="off"
|
||||||
<input type="radio" class="btn-check" name="channel-selection" id="5-channel" autocomplete="off" checked>
|
checked
|
||||||
<input type="radio" class="btn-check" name="channel-selection" id="6-channel" autocomplete="off" checked>
|
/>
|
||||||
<input type="radio" class="btn-check" name="channel-selection" id="7-channel" autocomplete="off" checked>
|
<input
|
||||||
|
type="radio"
|
||||||
|
class="btn-check"
|
||||||
|
name="channel-selection"
|
||||||
|
id="0-channel"
|
||||||
|
autocomplete="off"
|
||||||
|
checked
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
class="btn-check"
|
||||||
|
name="channel-selection"
|
||||||
|
id="1-channel"
|
||||||
|
autocomplete="off"
|
||||||
|
checked
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
class="btn-check"
|
||||||
|
name="channel-selection"
|
||||||
|
id="2-channel"
|
||||||
|
autocomplete="off"
|
||||||
|
checked
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
class="btn-check"
|
||||||
|
name="channel-selection"
|
||||||
|
id="3-channel"
|
||||||
|
autocomplete="off"
|
||||||
|
checked
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
class="btn-check"
|
||||||
|
name="channel-selection"
|
||||||
|
id="4-channel"
|
||||||
|
autocomplete="off"
|
||||||
|
checked
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
class="btn-check"
|
||||||
|
name="channel-selection"
|
||||||
|
id="5-channel"
|
||||||
|
autocomplete="off"
|
||||||
|
checked
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
class="btn-check"
|
||||||
|
name="channel-selection"
|
||||||
|
id="6-channel"
|
||||||
|
autocomplete="off"
|
||||||
|
checked
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
class="btn-check"
|
||||||
|
name="channel-selection"
|
||||||
|
id="7-channel"
|
||||||
|
autocomplete="off"
|
||||||
|
checked
|
||||||
|
/>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row pt-2 gy-2">
|
<div class="row pt-2 gy-2">
|
||||||
<label class="form-label col-9 col-sm-2 text-sm-end" for="formControlRange">Sensitivity</label>
|
<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">50</span>
|
<span class="col-3 col-sm-1 text-end">50</span>
|
||||||
<div class="col col-sm-9">
|
<div class="col col-sm-9">
|
||||||
<input type="range" class="form-range" id="formControlRange" oninput="rangeCallback(this)">
|
<input
|
||||||
|
type="range"
|
||||||
|
class="form-range"
|
||||||
|
id="formControlRange"
|
||||||
|
oninput="rangeCallback(this)"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row pt-2 gy-2">
|
<div class="row pt-2 gy-2">
|
||||||
<label class="form-label col-9 col-sm-2 text-sm-end" for="formControlRange">Gravity</label>
|
<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">50</span>
|
<span class="col-3 col-sm-1 text-end">50</span>
|
||||||
<div class="col col-sm-9">
|
<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"
|
||||||
|
oninput="rangeCallback(this)"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="row pt-2 gy-2">
|
<div class="row pt-2 gy-2">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="form-check form-switch">
|
<div class="form-check form-switch">
|
||||||
<input class="form-check-input" type="checkbox" id="modulateColor" onclick="colorModulateCallback(this)">
|
<input
|
||||||
<label class="form-check-label" for="modulateColor">Modulate color</label>
|
class="form-check-input"
|
||||||
|
type="checkbox"
|
||||||
|
id="modulateColor"
|
||||||
|
onclick="colorModulateCallback(this)"
|
||||||
|
/>
|
||||||
|
<label class="form-check-label" for="modulateColor"
|
||||||
|
>Modulate color</label
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row pt-2 gy-2">
|
<div class="row pt-2 gy-2">
|
||||||
<div id="mainPicker" class="col d-flex justify-content-center"></div>
|
<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
|
||||||
|
id="modulationPicker"
|
||||||
|
class="col d-none d-flex justify-content-center"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row pt-2 gy-2">
|
<div class="row pt-2 gy-2">
|
||||||
<label class="form-label col-9 col-sm-2 text-sm-end" for="formControlRange">Modulation speed</label>
|
<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-auto text-end" id="rangeval">50</span>
|
||||||
<div class="col col-sm-9">
|
<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"
|
||||||
|
oninput="rangeCallback(this)"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row pt-2 gy-2">
|
<div class="row pt-2 gy-2">
|
||||||
<label class="form-label col-9 col-sm-2 text-sm-end" for="formControlRange">Freq</label>
|
<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-auto text-end" id="rangeval">50</span>
|
||||||
<div class="col col-sm-9">
|
<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"
|
||||||
|
oninput="rangeCallback(this)"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1>Hello !!</h1>
|
<h1>Hello !!</h1>
|
||||||
<img alt="Vue logo" src="./assets/logo.png">
|
<img alt="Vue logo" src="./assets/logo.png" />
|
||||||
<HelloWorld msg="Welcome to Your Vue.js App"/>
|
<HelloWorld msg="Welcome to Your Vue.js App" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Reconnect from './components/Reconnect.vue'
|
import Reconnect from "./components/Reconnect.vue";
|
||||||
import ModeSelect from './components/ModeSelect.vue'
|
import ModeSelect from "./components/ModeSelect.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'App',
|
name: "App",
|
||||||
components: {
|
components: {
|
||||||
Reconnect,
|
Reconnect,
|
||||||
ModeSelect
|
ModeSelect,
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style></style>
|
||||||
</style>
|
|
||||||
|
18
RpiLedBars/install.sh
Normal file
18
RpiLedBars/install.sh
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#! /usr/bin/env bash
|
||||||
|
|
||||||
|
target=pi_hotspot
|
||||||
|
dir_target=~/RpiLedBars
|
||||||
|
|
||||||
|
# I - Copy project to pi target
|
||||||
|
## 1 - select target from ssh config
|
||||||
|
|
||||||
|
## 2 - rsync project
|
||||||
|
rsync -avz --delete --backup-dir=../RpiLedBars_backup/"$(date +%F_%H-%M-%S)" ./ -e ssh ${target}:${dir_target}
|
||||||
|
|
||||||
|
# II - Connect to pi target
|
||||||
|
## 1 - Check prequistite (cava, i2s micropphone module, CMake)
|
||||||
|
|
||||||
|
## 2 - Build project
|
||||||
|
ssh ${target} "cd ${dir_target}/frontend && "
|
||||||
|
|
||||||
|
## 3 - Install project
|
@ -1,5 +1,10 @@
|
|||||||
#! /usr/bin/env python3
|
#! /usr/bin/env python3
|
||||||
|
|
||||||
|
###
|
||||||
|
# This is a test script for testing rgb led strip reacting to i2S microphone input.
|
||||||
|
# This do not use hardware acceleration.
|
||||||
|
###
|
||||||
|
|
||||||
import alsaaudio
|
import alsaaudio
|
||||||
import audioop
|
import audioop
|
||||||
import board
|
import board
|
||||||
|
Loading…
Reference in New Issue
Block a user