import path from "path"; import React from "react"; import { observable, makeObservable } from "mobx"; import { registerClass, PropertyType, EezObject, ClassInfo } from "project-editor/core/object"; import { ProjectContext } from "project-editor/project/context"; import { CodeEditor } from "eez-studio-ui/code-editor"; import * as notification from "eez-studio-ui/notification"; import { updateObject } from "project-editor/store"; import { ProjectEditor } from "project-editor/project-editor-interface"; import { showSelectInstrumentDialog } from "project-editor/flow/components/actions/instrument"; import { EditorComponent } from "project-editor/project/ui/EditorComponent"; import type { ProjectEditorFeature } from "project-editor/store/features"; import { MICROPYTHON_ICON } from "project-editor/ui-components/icons"; //////////////////////////////////////////////////////////////////////////////// export class MicroPythonEditor extends EditorComponent { static contextType = ProjectContext; declare context: React.ContextType; render() { return ( { updateObject(this.context.project.micropython, { code: value }); }} mode={"python"} style={{ height: "100%" }} /> ); } } //////////////////////////////////////////////////////////////////////////////// export class MicroPython extends EezObject { code: string; static classInfo: ClassInfo = { properties: [ { name: "code", type: PropertyType.MultilineText, hideInPropertyGrid: true } ], icon: MICROPYTHON_ICON(24) }; override makeEditable() { super.makeEditable(); makeObservable(this, { code: observable }); } async runScript() { const projectStore = ProjectEditor.getProjectStore(this); const partsPromise = projectStore.build(); const instrument = await showSelectInstrumentDialog(undefined); if (!instrument) { return; } const parts = await partsPromise; if (!parts) { notification.error("Build error...", { autoClose: false }); return; } const toastId = notification.info("Uploading ...", { autoClose: false }); const connection = instrument.connection; connection.connect(); for (let i = 0; i < 10; i++) { if (instrument.isConnected) { break; } await new Promise(resolve => setTimeout(resolve, 100)); } if (!instrument.isConnected) { notification.update(toastId, { type: notification.ERROR, render: `Instrument not connected`, autoClose: 1000 }); return; } let acquired = false; let acquireError; for (let i = 0; i < 10; i++) { try { await connection.acquire(false); acquired = true; break; } catch (err) { acquireError = err; await new Promise(resolve => setTimeout(resolve, 100)); } } if (!acquired) { notification.update(toastId, { type: notification.ERROR, render: `Error: ${acquireError.toString()}`, autoClose: 1000 }); return; } try { const destinationFolderPath = projectStore.getAbsoluteFilePath( projectStore.project.settings.build.destinationFolder || "." ); const resDestinationFileName = `${path.basename( projectStore.filePath || "", ".eez-project" )}.res`; const resSourceFilePath = `${destinationFolderPath}/${resDestinationFileName}`; const pyDestinationFileName = `${path.basename( projectStore.filePath || "", ".eez-project" )}.py`; const pySourceFilePath = `${destinationFolderPath}/${pyDestinationFileName}`; await new Promise((resolve, reject) => { const uploadInstructions = Object.assign( {}, instrument.defaultFileUploadInstructions, { sourceFilePath: resSourceFilePath, destinationFileName: resDestinationFileName, destinationFolderPath: "/Scripts" } ); connection.upload(uploadInstructions, resolve, reject); }); await new Promise((resolve, reject) => { const uploadInstructions = Object.assign( {}, instrument.defaultFileUploadInstructions, { sourceFilePath: pySourceFilePath, destinationFileName: pyDestinationFileName, destinationFolderPath: "/Scripts" } ); connection.upload(uploadInstructions, resolve, reject); }); connection.command(`SYST:DEL 100`); const runningScript = await connection.query(`SCR:RUN?`); if (runningScript != "" && runningScript != `""`) { connection.command(`SCR:STOP`); connection.command(`SYST:DEL 100`); } connection.command(`SCR:RUN "/Scripts/${pyDestinationFileName}"`); notification.update(toastId, { type: notification.SUCCESS, render: `Script started`, autoClose: 1000 }); return; } catch (err) { notification.update(toastId, { type: notification.ERROR, render: `Error: ${err.toString()}`, autoClose: 1000 }); return; } finally { connection.release(); } } } registerClass("MicroPython", MicroPython); //////////////////////////////////////////////////////////////////////////////// const feature: ProjectEditorFeature = { name: "eezstudio-project-feature-micropython", version: "0.1.0", description: "MicroPython", author: "EEZ", authorLogo: "../eez-studio-ui/_images/eez_logo.png", displayName: "MicroPython", mandatory: false, key: "micropython", type: PropertyType.Object, typeClass: MicroPython, icon: MICROPYTHON_ICON(24), create: () => { return { code: "" }; } }; export default feature;