start of project
This commit is contained in:
7
init.sh
Executable file
7
init.sh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
#source node binaries
|
||||
. nodetopath.sh
|
||||
npm install -g typescript
|
||||
npm install chart.js@4.4.1
|
||||
npm install chartjs-plugin-annotation@3.1.0
|
||||
8
nodetopath.sh
Normal file
8
nodetopath.sh
Normal file
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ "$(echo $PATH | grep 'node-v22.16.0' | wc -l)" == "0" ]
|
||||
then
|
||||
echo add node to path
|
||||
PATH=$(pwd)/../node/node-v22.16.0-linux-x64/bin/:$PATH
|
||||
fi
|
||||
|
||||
139
src/roast.ts
Normal file
139
src/roast.ts
Normal file
@@ -0,0 +1,139 @@
|
||||
let timer = 0;
|
||||
let isRunning = false;
|
||||
let log: Array<{ time: string, event: string, temp?: number }> = [];
|
||||
let targets: number[] = [];
|
||||
let currentTargetIndex = 0;
|
||||
let interval: NodeJS.Timeout | null = null;
|
||||
|
||||
function startTimer(): void {
|
||||
if (isRunning) {
|
||||
alert("Timer is already running. Click again to reset.");
|
||||
return;
|
||||
}
|
||||
isRunning = true;
|
||||
interval = setInterval(() => {
|
||||
timer++;
|
||||
updateTimerDisplay();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function stopTimer(): void {
|
||||
clearInterval(interval!);
|
||||
isRunning = false;
|
||||
}
|
||||
|
||||
function updateTimerDisplay(): void {
|
||||
const minutes = Math.floor(timer / 60);
|
||||
const seconds = timer % 60;
|
||||
document.getElementById("timer")!.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
function logEvent(eventName: string): void {
|
||||
if (eventName === "Charge") {
|
||||
if (log.length > 0) {
|
||||
log = [];
|
||||
timer = 0;
|
||||
isRunning = false;
|
||||
}
|
||||
startTimer();
|
||||
log.push({ time: formatTime(timer), event: eventName, temp: null });
|
||||
updateLog();
|
||||
return;
|
||||
}
|
||||
if (eventName === "Drop") {
|
||||
stopTimer();
|
||||
log.push({ time: formatTime(timer), event: eventName, temp: null });
|
||||
updateLog();
|
||||
document.getElementById("create-plan")!.classList.add("hidden");
|
||||
const tempButtons = document.getElementById("temp-buttons")!;
|
||||
tempButtons.innerHTML = "";
|
||||
return;
|
||||
}
|
||||
log.push({ time: formatTime(timer), event: eventName, temp: null });
|
||||
updateLog();
|
||||
}
|
||||
|
||||
function resetSystem(): void {
|
||||
stopTimer();
|
||||
log = [];
|
||||
updateLog();
|
||||
document.getElementById("create-plan")!.classList.add("hidden");
|
||||
const tempButtons = document.getElementById("temp-buttons")!;
|
||||
tempButtons.innerHTML = "";
|
||||
}
|
||||
|
||||
function formatTime(seconds: number): string {
|
||||
const minutes = Math.floor(seconds / 60);
|
||||
const secs = seconds % 60;
|
||||
return `${minutes}:${secs.toString().padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
function setPlan(): void {
|
||||
const input = (document.getElementById("plan-input") as HTMLInputElement).value;
|
||||
targets = input.split(',').map(Number);
|
||||
currentTargetIndex = 0;
|
||||
document.getElementById("controls")!.classList.remove("hidden");
|
||||
document.getElementById("create-plan")!.classList.add("hidden");
|
||||
generateTempButtons();
|
||||
}
|
||||
|
||||
function generateTempButtons(): void {
|
||||
const container = document.getElementById("temp-buttons")!;
|
||||
container.innerHTML = "";
|
||||
if (targets.length === 0) {
|
||||
container.innerHTML = "<p>No temperature plan set.</p>";
|
||||
return;
|
||||
}
|
||||
const currentTarget = targets[currentTargetIndex];
|
||||
const buttons: string[] = [];
|
||||
buttons.push('<button class="nav-btn" onclick="navigateTemp(-1);"><<</button>');
|
||||
for (let i = -2; i <= 2; i++) {
|
||||
const temp = currentTarget + i;
|
||||
buttons.push(`<button onclick="logTemp(${temp})">${temp}</button>`);
|
||||
}
|
||||
buttons.push('<button class="nav-btn" onclick="navigateTemp(1);">>></button>');
|
||||
container.innerHTML = buttons.join(" ");
|
||||
}
|
||||
|
||||
function navigateTemp(direction: number): void {
|
||||
currentTargetIndex += direction;
|
||||
if (currentTargetIndex < 0) {
|
||||
currentTargetIndex = 0;
|
||||
} else if (currentTargetIndex >= targets.length) {
|
||||
currentTargetIndex = targets.length - 1;
|
||||
}
|
||||
generateTempButtons();
|
||||
}
|
||||
|
||||
function logTemp(temp: number): void {
|
||||
log.push({ time: formatTime(timer), event: "Temp", temp });
|
||||
updateLog();
|
||||
currentTargetIndex++;
|
||||
if (currentTargetIndex >= targets.length) {
|
||||
currentTargetIndex = targets.length - 1;
|
||||
}
|
||||
generateTempButtons();
|
||||
}
|
||||
|
||||
function updateLog(): void {
|
||||
const tbody = document.getElementById("log-body")!;
|
||||
tbody.innerHTML = log.map(entry => `
|
||||
<tr>
|
||||
<td>${entry.time}</td>
|
||||
<td>${entry.event}</td>
|
||||
<td>${entry.temp !== null ? entry.temp : ''}</td>
|
||||
</tr>
|
||||
`).join("");
|
||||
}
|
||||
|
||||
function exportCSV(): void {
|
||||
const csvContent = "Time,Event,Temperature\n" + log.map(entry => `${entry.time},${entry.event},${entry.temp !== null ? entry.temp : ''}`).join("\n");
|
||||
const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
|
||||
const link = document.createElement("a");
|
||||
link.setAttribute("href", URL.createObjectURL(blob));
|
||||
link.setAttribute("download", "roast_log.csv");
|
||||
link.style.display = "none";
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
}
|
||||
Reference in New Issue
Block a user