aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjakob.stendahl <jakob.stendahl@infomedia.dk>2022-12-04 13:33:45 +0100
committerJakob Stendahl <jakob.stendahl@outlook.com>2022-12-04 13:34:22 +0100
commitc3b4742eeceee9250f8059972dd150f38e2eb021 (patch)
treeedde9ea65b554ff345788a916f238aed4a772b35
parentc5dc2dfb92e4a6584d1e727bc39b8c9578f85b57 (diff)
downloadLuxcena-Neo-c3b4742eeceee9250f8059972dd150f38e2eb021.tar.gz
Luxcena-Neo-c3b4742eeceee9250f8059972dd150f38e2eb021.zip
Fix simulation stuttering (still resource intensive) and some oter QOL upgrades
-rw-r--r--NeoRuntime/Runtime/luxcena_neo/strip.py20
-rw-r--r--src/NeoRuntimeManager/index.js19
-rw-r--r--src/SelfUpdater/index.js2
-rw-r--r--src_frontend/ComponentLib/Button/EditorActionButton.svelte82
-rw-r--r--src_frontend/Components/Editor/Controls.svelte6
-rw-r--r--src_frontend/Components/Editor/Editor.svelte42
-rw-r--r--src_frontend/Components/Editor/Output.svelte13
-rw-r--r--src_frontend/Components/Editor/Pane.svelte14
-rw-r--r--src_frontend/Components/Editor/Simulation.svelte46
-rw-r--r--src_frontend/Components/Editor/TopBar.svelte3
10 files changed, 222 insertions, 25 deletions
diff --git a/NeoRuntime/Runtime/luxcena_neo/strip.py b/NeoRuntime/Runtime/luxcena_neo/strip.py
index 0d23069..aa5b2d2 100644
--- a/NeoRuntime/Runtime/luxcena_neo/strip.py
+++ b/NeoRuntime/Runtime/luxcena_neo/strip.py
@@ -1,9 +1,27 @@
import json
from os import path
-import rpi_ws281x as ws
from .matrix import Matrix, get_segment_range
from .power_calc import calcCurrent
+""" import rpi_ws281x library, or import dummy version. """
+try:
+ import rpi_ws281x as ws
+except ModuleNotFoundError:
+ """ Dummy STRIP used for debugging purposes """
+ class STRIP:
+ def __init__(self, *args, **kwargs): pass
+ def begin(self, *args): pass
+ def blank(self): pass
+ def show(self): pass
+ def setPixelColor(self, *args): pass
+ def setBrightness(self, *args): pass
+ """ Dummy ws implementation """
+ class WS:
+ WS2812_STRIP = 1
+ Adafruit_NeoPixel = STRIP
+ def __init__(*args): print("rpi_ws281x is not installed, using a dummy module")
+ ws = WS()
+
class Strip:
diff --git a/src/NeoRuntimeManager/index.js b/src/NeoRuntimeManager/index.js
index eb38632..1a56b04 100644
--- a/src/NeoRuntimeManager/index.js
+++ b/src/NeoRuntimeManager/index.js
@@ -33,6 +33,8 @@ let modeDebuggerId = null;
let modeDebuggerProcStartHandler = null;
/** @type {object} The last received matrix setup */
let matrix = null;
+/** @type {object} intervall for sending current state */
+let debugModeStateEmitIntervall = null;
eventEmitter.on("proc:exit", (code) => modeExitCode = code);
eventEmitter.on("matrix", (_matrix) => matrix = _matrix);
@@ -131,7 +133,9 @@ function stopMode(restart=false) {
* @return {object} A standardform return object.
*/
function startMode() {
- if (runtimeProcess === null) { return {success: false, reason: "no runtimeprocess", detail: "Runtimeprocess not set, did you mean to call setMode?"}; }
+ if (runtimeProcess === null) {
+ return {success: false, reason: "no runtimeprocess", detail: "Runtimeprocess not set, did you mean to call setMode?"};
+ }
return runtimeProcess.start();
};
@@ -226,6 +230,14 @@ function setVariable(name, value) {
}
/**
+ * A function intented to be used in an interval to emit
+ * the current debug-state.
+ *
+ */
+function debugModeEmitState() {
+}
+
+/**
* Start debugger for a mode
*
* @param {string} modeId - The mode to debug
@@ -248,6 +260,11 @@ function startDebugger(debuggerModeId) {
console.log(modeDebuggerProcStartHandler);
}
+ if (debugModeStateEmitIntervall == null) {
+ debugModeStateEmitIntervall = setInterval(() => {
+ }, 500);
+ }
+
modeDebuggerActive = true;
modeDebuggerId = debuggerModeId;
setTimeout(() => {
diff --git a/src/SelfUpdater/index.js b/src/SelfUpdater/index.js
index 68f6a1d..cc7ce13 100644
--- a/src/SelfUpdater/index.js
+++ b/src/SelfUpdater/index.js
@@ -212,7 +212,7 @@ class Updater {
let arch = (await this.run(`uname`, ["-m"])).out.replace("\n","");
if (arch == "armv6l") {
await this.run("wget", ["https://unofficial-builds.nodejs.org/download/release/v14.10.0/node-v14.10.0-linux-armv6l.tar.gz"]);
- await this.run("tar", ["-xzf" "node-v14.10.0-linux-armv6l.tar.gz"]);
+ await this.run("tar", ["-xzf", "node-v14.10.0-linux-armv6l.tar.gz"]);
await this.run("cp", ["-r", "node-v14.10.0-linux-armv6l/*", "/usr/local"]);
await this.run("rm", ["-r", "node-v14.10.0-linux-armv6l"]);
await this.run("rm", ["node-v14.10.0-linux-armv6l.tar.gz"]);
diff --git a/src_frontend/ComponentLib/Button/EditorActionButton.svelte b/src_frontend/ComponentLib/Button/EditorActionButton.svelte
new file mode 100644
index 0000000..148720c
--- /dev/null
+++ b/src_frontend/ComponentLib/Button/EditorActionButton.svelte
@@ -0,0 +1,82 @@
+<script>
+ export let faIcon = false;
+ export let fullWidth = false;
+ export let backgroundColor = "#444242";
+ export let color = "white";
+
+ export let loadingPromise = null;
+ $: listen(loadingPromise);
+ function listen(promise) {
+ if (promise != null) {
+ loading = true;
+ promise.then(res => {
+ loading = false;
+ success = true;
+ }).catch(err => {
+ loading = false;
+ success = false;
+ });
+ } else {
+ loading = false;
+ }
+ }
+ let loading;
+ let success;
+</script>
+
+<style>
+ button {
+ background: #444242;
+ color: var(--color);
+ border: none;
+ text-decoration: none;
+ /*padding: 5px 15px;*/
+ /*font-size: 15px;*/
+
+ transition: background-color, color 0.1s ease;
+ border-radius: 15px;
+ }
+ button:hover {
+ filter: brightness(0.95);
+ }
+ button:active {
+ filter: brightness(0.90);
+ }
+ .fullWidth {
+ width: 100%;
+ }
+ .iconButton {
+ display: flex;
+ }
+ .iconButton .text {
+ margin: auto;
+ }
+ .active {
+ background-color: var(--active-bg-color);
+ color: var(--active-color);
+ }
+ i {
+ }
+</style>
+
+<button
+ on:click
+ class:fullWidth={fullWidth}
+ class:iconButton={faIcon != false}
+ style="--bg-color: {backgroundColor};
+ --color: {color};">
+
+ {#if faIcon}
+ <div class="icon">
+ <i class={faIcon}></i>
+ </div>
+ {/if}
+
+ {#if loading}
+ <i class="fas fa-spinner fa-pulse"></i>
+ {:else}
+ <div class="text">
+ <slot></slot>
+ </div>
+ {/if}
+</button>
diff --git a/src_frontend/Components/Editor/Controls.svelte b/src_frontend/Components/Editor/Controls.svelte
index 85450a5..36dd9f0 100644
--- a/src_frontend/Components/Editor/Controls.svelte
+++ b/src_frontend/Components/Editor/Controls.svelte
@@ -34,6 +34,10 @@
});
onMount(() => {
+ power_on = false;
+ brightnessValue = 0;
+ variables = {};
+
openSocket.emit("power:get");
openSocket.emit("brightness:get");
openSocket.emit("vars:get")
@@ -100,4 +104,4 @@
{/if}
</div>
{/each}
-</div> \ No newline at end of file
+</div>
diff --git a/src_frontend/Components/Editor/Editor.svelte b/src_frontend/Components/Editor/Editor.svelte
index d77b4f5..4328222 100644
--- a/src_frontend/Components/Editor/Editor.svelte
+++ b/src_frontend/Components/Editor/Editor.svelte
@@ -2,7 +2,7 @@
let debuggerInitialised = false;
</script>
<script>
- import { onDestroy } from "svelte";
+ import { onMount, onDestroy } from "svelte";
import { get } from "svelte/store";
import { pop } from "svelte-spa-router";
import { EditorState, basicSetup } from "@codemirror/basic-setup"
@@ -12,6 +12,7 @@
import { python } from "@codemirror/lang-python"
import { HighlightStyle, tags as t } from "@codemirror/highlight"
import { notif } from "../../stores/notifs";
+ import EditorActionButton from "../../ComponentLib/Button/EditorActionButton.svelte";
import TopBar from "./TopBar.svelte";
import Pane from "./Pane.svelte";
import Controls from "./Controls.svelte";
@@ -200,11 +201,11 @@
parent: codeEditorEl
})
});
- authorizedSocket.on("receivededitor:proc:start", () => {
+ authorizedSocket.on("editor:proc:start", () => {
console.log("received editor:proc:start");
procIsRunning = true
});
- authorizedSocket.on("received editor:proc:exit", (code) => {
+ authorizedSocket.on("editor:proc:exit", (code) => {
console.log("received editor:proc:exit");
procIsRunning = false;
});
@@ -236,6 +237,18 @@
});
}
+ let simulationEnabled;
+ let simulationToggleFn;
+ let simulationBackgrounds = ["--default-bg", "black", "white"];
+ let simlulationBackgroundI = 0;
+ function toggleSimulationPower() { simulationToggleFn(); }
+ function nextSimulationBackground() {
+ simlulationBackgroundI++;
+ if (simlulationBackgroundI >= simulationBackgrounds.length) {
+ simlulationBackgroundI = 0;
+ }
+ }
+
function saveCode(fn) {
if (codeEditorView == null) { return; }
console.log("emitting editor:save");
@@ -257,6 +270,14 @@
});
}
+ onMount(() => {
+ codeEditorHasChanges = false;
+ procIsRunning = false;
+ failCount = 0;
+ reconnecting = false;
+ initDebugger();
+ });
+
onDestroy(() => {
if (get(openSocketConnected)) {
closeDebugger();
@@ -327,10 +348,19 @@
on:stop={stopProc}
on:restart={restartProc}
bind:procIsRunning={procIsRunning} />
-<main use:initDebugger>
+<main>
<div class="simulation">
- <Pane header="simulation">
- <Simulation />
+ <Pane header="simulation" contentBackground={simulationBackgrounds[simlulationBackgroundI]}>
+ <svelte:fragment slot="actions">
+ <EditorActionButton faIcon="fas fa-tint"
+ on:click={nextSimulationBackground}
+ alt="Toggle simulation"></EditorActionButton>
+ <EditorActionButton faIcon="fas fa-power-off"
+ on:click={toggleSimulationPower}
+ color={simulationEnabled ? "green" : "red"}
+ alt="Toggle simulation"></EditorActionButton>
+ </svelte:fragment>
+ <Simulation bind:toggleEnable={simulationToggleFn} bind:enabled={simulationEnabled} />
</Pane>
</div>
diff --git a/src_frontend/Components/Editor/Output.svelte b/src_frontend/Components/Editor/Output.svelte
index 52b7216..59072f9 100644
--- a/src_frontend/Components/Editor/Output.svelte
+++ b/src_frontend/Components/Editor/Output.svelte
@@ -1,10 +1,12 @@
<script>
+ import { onMount, onDestroy } from "svelte";
import { authorizedSocket, authorizedSocketNeeded } from "../../stores/socketStore";
authorizedSocketNeeded.set(true);
let scrollBox;
let htmlCode = "";
let buffer = "";
+ let flushBufferInterval;
function addData(data, classname) {
// let styles = "white-space:pre-wrap;margin:0;";
@@ -28,12 +30,21 @@
htmlCode += buffer;
buffer = "";
};
- setInterval(flushBuffer, 400);
authorizedSocket.on("editor:proc:start", () => htmlCode = "");
authorizedSocket.on("editor:proc:exit", (code) => addData(`\nMode exited with ${code}\n\n`, "exit"));
authorizedSocket.on("editor:proc:stdout", (stdout) => addData(stdout, "stdout"));
authorizedSocket.on("editor:proc:stderr", (stderr) => addData(stderr, "stderr"));
+
+ onMount(() => {
+ htmlCode = "";
+ buffer = "";
+ flushBuffer = setInterval(flushBuffer, 400);
+ });
+
+ onDestroy(() => {
+ clearInterval(flushBufferInterval);
+ });
</script>
<style>
diff --git a/src_frontend/Components/Editor/Pane.svelte b/src_frontend/Components/Editor/Pane.svelte
index 143c569..4a375ac 100644
--- a/src_frontend/Components/Editor/Pane.svelte
+++ b/src_frontend/Components/Editor/Pane.svelte
@@ -2,11 +2,14 @@
export let header;
export let padding = true;
export let scrollable = true;
+
+ export let contentBackground = "--default-bg";
</script>
<style>
.box {
- background-color: #444242;
+ --default-bg: #444242;
+ background-color: var(--default-bg, #444242);
border-radius: 5px;
height: 100%;
}
@@ -15,14 +18,18 @@
padding: 10px;
box-sizing: border-box;
border-bottom: 1px solid #333333;
+ display: flex;
+ align-items: baseline;
}
.header h1 {
margin: 0;
+ margin-right: auto;
font-size: 12px;
font-weight: bold;
text-transform: uppercase;
}
.content {
+ background-color: var(--content-bg, #444242);
height: calc(100% - 35px);
width: 100%;
box-sizing: border-box;
@@ -31,11 +38,12 @@
.scrollable { overflow: auto; }
</style>
-<div class="box">
+<div class="box" style="--content-bg: {contentBackground}">
<div class="header">
<h1>{header}</h1>
+ <slot name="actions"></slot>
</div>
<div class="content" class:padding={padding} class:scrollable={scrollable}>
<slot></slot>
</div>
-</div> \ No newline at end of file
+</div>
diff --git a/src_frontend/Components/Editor/Simulation.svelte b/src_frontend/Components/Editor/Simulation.svelte
index 86cc66c..3a35946 100644
--- a/src_frontend/Components/Editor/Simulation.svelte
+++ b/src_frontend/Components/Editor/Simulation.svelte
@@ -1,11 +1,24 @@
<script>
- import { onMount } from "svelte";
+ import { onMount, onDestroy } from "svelte";
import { authorizedSocket, authorizedSocketNeeded } from "../../stores/socketStore";
authorizedSocketNeeded.set(true);
+ export let enabled = true;
+
+ let target_fps = 60;
let svg;
let pixels = [];
let pixelBuffer = [];
+ let pixelBufferCh = false;
+ let pixelFlushInterval;
+
+ export function toggleEnable() {
+ enabled = !enabled;
+ if (!enabled) {
+ pixelBuffer = pixelBuffer.map(x => 0);
+ flushPixelBuffer(true);
+ }
+ }
function updateMatrix(matrix) {
if (matrix == null) { return; }
@@ -25,31 +38,45 @@
}
async function updateColors(colors) {
+ if (!enabled) { return ; }
pixelBuffer = colors;
+ pixelBufferCh = true;
}
- async function flushPixelBuffer() {
- //console.log(pixelBuffer);
+ async function flushPixelBuffer(force=false) {
+ if (!force && (!pixelBufferCh || !enabled)) { return; }
+ pixelBufferCh = false;
window.requestAnimationFrame((ts) => {
for (let i = 0; i+2 < pixelBuffer.length; i+=3) {
+ let pixel;
try {
- document.querySelector("#sim-pixel-"+(i/3))
- .style
- .setProperty(
- "fill",
- `rgb(${pixelBuffer[i]}, ${pixelBuffer[i+1]}, ${pixelBuffer[i+2]})`);
+ pixel = document.querySelector("#sim-pixel-"+(i/3));
+ if (pixel == null) { continue; }
+ pixel.style.setProperty(
+ "fill",
+ `rgb(${pixelBuffer[i]}, ${pixelBuffer[i+1]}, ${pixelBuffer[i+2]})`
+ );
} catch(e) {
+ console.log(pixel);
console.log(e);
}
}
});
}
- setInterval(flushPixelBuffer, 50);
onMount(() => {
+ pixels = [];
+ pixelBuffer = [];
+ enabled = false;
authorizedSocket.on("matrix", updateMatrix);
authorizedSocket.on("strip_buffer", updateColors);
authorizedSocket.emit("matrix:get");
+
+ pixelFlushInterval = setInterval(flushPixelBuffer, 1000/target_fps);
+ });
+
+ onDestroy(() => {
+ clearInterval(pixelFlushInterval);
});
</script>
@@ -67,7 +94,6 @@
</style>
<div class="wrapper">
- <p>(still quite buggy, especially for very fast changing pixels, if nothing is happening, try to restart the script)</p>
<svg viewBox="0 0 0 0" preserveAspectRatio="xMaxYMax" bind:this={svg}>
{#each pixels as pixel}
<rect id="sim-pixel-{pixel.n}" x="{pixel.x*2+1}" y="{pixel.y*2+1}" width="1" height="1" style="fill:rgb(0,0,0);filter:blur(0.2px);" />
diff --git a/src_frontend/Components/Editor/TopBar.svelte b/src_frontend/Components/Editor/TopBar.svelte
index c74adf0..6ca6e84 100644
--- a/src_frontend/Components/Editor/TopBar.svelte
+++ b/src_frontend/Components/Editor/TopBar.svelte
@@ -1,4 +1,5 @@
<script>
+ import { onMount } from "svelte";
import { createEventDispatcher } from 'svelte';
import { pop } from "svelte-spa-router";
import PrettyVar from "../../ComponentLib/PrettyVar.svelte";
@@ -59,4 +60,4 @@
<button on:click={() => dispatch("start")}><i class="fas fa-play"></i>Start</button>
{/if}
</div>
-</div> \ No newline at end of file
+</div>