Updates from pi

This commit is contained in:
Tropicananass 2022-07-20 16:57:01 +02:00
parent 84612aded5
commit c1fb89271c
18 changed files with 468 additions and 133 deletions

View 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
View File

@ -0,0 +1,3 @@
{
"cmake.sourceDirectory": "${workspaceFolder}/backend"
}

View File

@ -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)

View File

@ -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"

View File

@ -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"

View File

@ -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

View File

@ -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) {

View File

@ -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]);

View File

@ -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
View 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

View File

@ -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;
} }
} }

View File

@ -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>

View File

@ -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);

View File

@ -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;
}; };
} }

View File

@ -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;
} }
console.log("channel:" + selectedChannel);
function sensitivityCallback(element) {
console.log("e:" + element.value);
if (socket.readyState == WebSocket.OPEN) {
socket.send("e:" + element.value);
} }
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;

View File

@ -7,27 +7,87 @@
<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
View 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

View File

@ -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