esp32blockly/src/serial/repl.js

100 lines
2.5 KiB
JavaScript

import { writeString } from './connection.js';
export async function enterRawRepl() {
await writeString('\x03\x03');
await sleep(100);
await writeString('\x01');
await sleep(100);
}
export async function executeCode(code) {
await enterRawRepl();
await writeString(code);
await writeString('\x04');
}
export async function stopExecution() {
await writeString('\x03\x03');
}
export async function saveToDevice(code, filename = 'main.py') {
const script = [
`f = open('${filename}', 'w')`,
`f.write(${JSON.stringify(code)})`,
`f.close()`,
`print('Saved to ${filename}')`,
].join('\n');
await executeCode(script);
}
export async function writeFileToDevice(content, filename) {
// Escape the content properly for Python string - handle newlines, quotes, backslashes
const escaped = content
.replace(/\\/g, '\\\\')
.replace(/'/g, "\\'")
.replace(/\n/g, '\\n')
.replace(/\r/g, '\\r');
const script = [
`f = open('${filename}', 'w')`,
`f.write('${escaped}')`,
`f.close()`,
`print('Saved ${filename}')`,
].join('\n');
await executeCode(script);
}
export async function readFileFromDevice(filename, onOutput) {
// Read file and print with markers so we can extract content
const startMarker = `__WS_START_${Date.now()}__`;
const endMarker = `__WS_END_${Date.now()}__`;
const script = [
`try:`,
` f = open('${filename}', 'r')`,
` data = f.read()`,
` f.close()`,
` print('${startMarker}')`,
` print(data, end='')`,
` print('${endMarker}')`,
`except Exception as e:`,
` print('Error: ' + str(e))`,
].join('\n');
// Set up a listener to capture output between markers
let captured = '';
let capturing = false;
const listener = (text) => {
if (!onOutput) return;
const startIdx = text.indexOf(startMarker);
const endIdx = text.indexOf(endMarker);
if (startIdx !== -1) {
capturing = true;
captured = text.substring(startIdx + startMarker.length);
}
if (capturing) {
if (endIdx !== -1) {
captured += text.substring(0, endIdx);
capturing = false;
onOutput(captured);
} else {
captured += text;
}
}
};
// This will be handled by the caller setting up the listener
// For now, just execute and let caller handle output
await executeCode(script);
return { startMarker, endMarker };
}
function sleep(ms) {
return new Promise((r) => setTimeout(r, ms));
}