save/load working

node_mode
Jake 2025-09-29 14:07:25 +08:00
parent ff653ad2b4
commit e7e5e403c4
3 changed files with 92 additions and 6 deletions

View File

@ -3,13 +3,13 @@
<head>
<meta charset="UTF-8">
<title>ESP32 Animation Creator</title>
<title>Little Sophia Control Panel</title>
<script src="https://unpkg.com/nexusui"></script>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h2>ESP32 Animation Creator</h2>
<h2>Little Sophia Control Panel</h2>
<button id="connect">Connect</button>
<button id="disconnect" hidden>Disconnect</button>
</div>

View File

@ -199,14 +199,22 @@ window.onload = () => {
});
break;
case 0x03: { // CMD_LOAD_FILE
case 0x03: // CMD_LOAD_FILE
const fileData = new Uint8Array(payload);
console.log(`Received file (${fileData.length} bytes)`);
document.getElementById('log').value += `Loaded file\n`;
// 🔹 Do something with the file
handleLoadedFile(fileData);
break;
}
case 0x05: // CMD_SAVE_FILE
console.log(`Saved file Response Recieved`);
console.log(new Uint8Array(payload));
document.getElementById('log').value += `Saved file Response Recieved\n`;
// 🔹 Do something with the file
//handleLoadedFile(fileData);
break;
// Add more cases as needed
default:
@ -306,6 +314,77 @@ window.onload = () => {
deleteButton.disabled = false;
}
async function sendAnimationToESP32() {
const frameCount = 500;
const numChannels = 5;
const frameRate = 50;
const version = 1;
const headerSize = 16;
const frameDataSize = frameCount * numChannels * 2;
const keyframeCount = dialKeyframes.reduce((sum, channel) => {
return sum + Object.keys(channel).length;
}, 0);
///const keyframeCount = dialKeyframes.length;
const keyframeDataSize = keyframeCount * 5;
for (var i = 0; i < 5; i++) {
console.log(dialKeyframes[i]);
}
console.log(dialKeyframes);
console.log(keyframeCount);
const totalSize = headerSize + 2 + keyframeDataSize;
console.log(totalSize);
const buffer = new ArrayBuffer(totalSize);
const view = new DataView(buffer);
let offset = 0;
// 🔹 Header
view.setUint8(offset++, "A".charCodeAt(0));
view.setUint8(offset++, "N".charCodeAt(0));
view.setUint8(offset++, "I".charCodeAt(0));
view.setUint8(offset++, "M".charCodeAt(0));
view.setUint16(offset, frameCount, true); offset += 2;
view.setUint8(offset++, version);
view.setUint8(offset++, frameRate);
offset += 8; // reserved
// 🔹 Frame data (all zeroes)
//offset += frameDataSize;
// 🔹 Keyframe count
view.setUint16(offset, keyframeCount, true); offset += 2;
const keyframeList = [];
Object.entries(dialKeyframes).forEach(([motorIdStr, frameMap]) => {
const motorId = parseInt(motorIdStr, 10);
Object.entries(frameMap).forEach(([frameStr, position]) => {
const frame = parseInt(frameStr, 10);
if (position !== undefined) {
keyframeList.push({ motorId, frame, position });
}
});
});
// 🔹 Keyframes
keyframeList.forEach(({ motorId, frame, position }) => {
view.setUint8(offset++, motorId);
view.setUint16(offset, frame, true); offset += 2;
view.setUint16(offset, position, true); offset += 2;
});
console.log("Keyframe count: " + keyframeCount);
console.log(keyframeList);
// 🔹 Send to ESP32
const payload = new Uint8Array(buffer);
serial.saveFile(payload); // CMD_SAVE_ANIMATION
}
@ -472,7 +551,7 @@ window.onload = () => {
document.getElementById('saveAnimation').onclick = async () => {
await sendAnimationToESP32();
};

View File

@ -7,6 +7,7 @@ const BAUD_RATE = 1000000;
const CMD_ID_REQUEST = 0x01;
const CMD_FILE_LIST = 0x02;
const CMD_LOAD_FILE = 0x03;
const CMD_SAVE_FILE = 0x05;
const CMD_DELETE_FILE = 0x04;
export class SerialManager {
@ -50,11 +51,17 @@ export class SerialManager {
}
async requestFile(filename) {
console.log("Requesting File: " + filename);
const encoder = new TextEncoder();
const payload = Array.from(encoder.encode(filename));
await this.send(CMD_LOAD_FILE, payload); // CMD_LOAD_FILE
}
async saveFile(payload){
console.log("Saving File: " + "filename");
await this.send(CMD_SAVE_FILE, payload);
}
startReading(onPacket) {
const decoder = new TextDecoder();