MicroPython Development Environment
Project description
MPIDE - MicroPython TUI-REPL powered by mpremote and Textual
This project is currently being set up and not guaranteed to be of any use for
anyone but me.
However mpide runs on my machine and might as well run on yours, too.
Project goal is a 'smart' REPL for MicroPython devices similar to
mpremote
(currently mpide is even based on mpremote), but with additional features like
- automatic synchronization of locally modified files with device
- automatic pre-compiling using
mpy-crossif applicable - providing a powerful set of pure Python base functionality for rapid development
- providing a web based remote update mechanism
- transparent and intuitive device bootstrapping, logging etc.
Usage
Install:
[python3 -m ]pip install [--user] [--upgrade] mpide
Execute:
mpide [<PROJECT-PATH=.>]
Or add mpide as dependency to an existing MicroPython project in order to
synchronize locally modified files while mpide is running.
The mpide package brings with it mpremote and esptool as dependency, so installing
mpide or making it a dependency (e.g. for a poetry based project) provides them
implicitly.
All the following stuff assumes that you've already successfully flashed your device with a recent version of MicroPython
Here is a very quick walk-through for a generic ESP32 based device:
wget https://micropython.org/resources/firmware/ESP32_GENERIC-20240602-v1.23.0.bin
esptool.py -p /dev/ttyACM0 -b 460800 --chip esp32 erase_flash
esptool.py -p /dev/ttyACM0 -b 460800 --chip esp32 write_flash -z 0x1000 ESP32_GENERIC-20240602-v1.23.0.bin
You should now be able to run mpremote to connect to your device and start a REPL.
Press CTRL-D for a soft-reboot, enter Python commands and see the result and press
CTRL-X to exit mpremote.
If that worked you can now use mpide instead of mpremote. If not you have to
find your way yourself for now..
mpide walk through and project integration
While current interaction with a project folder is still quite sparse, you can at
least make mpide watch for filesystem changes in the current project directory
and auto-sync them with the device. There is even support for pre-compiling
.py files to .mpy files before uploading them - more on that later.
In order to let mpide watch and sync, you need to create a file called
mpide_project.py, containing information used on both the development host and
the MicroPython target.
I hear you asking why that configuration does not go to pyproject.toml or
any other fancy modern format instead. The reason is better memory efficiency due
to the fact that you don't have to import a parser on your tiny ESP32 device.
Also, compared to a JSON or YAML file you can import additional stuff or even
dynamically evaluate values (which might be considered a security hazard, but so
is the possibility to upload arbitrary Python code..)
The smallest config file enabling for auto-syncing looks like this:
config = {
"static_files": [
"main.py",
],
}
With this configuration you tell mpide to just sync main.py with /main.py
on the target device every time it changes on your filesystem (while mpide is
running of course) - no pre-compilation involved.
The term static_files implies that files will be written to the filesystem
root, making changes persistent immediately, while also slowly wearing out your
precious flash.
To test your configuration, spin up mpide, open main.py in your favorite
editor and add some meaningful code, e.g.
def run():
print("hello world")
In order to copy files to a volatile directory, you (currently) have to do two
things: declare the file to be dynamic and setup a RAM-disk at /ramdisk.
To do this, modify the config file like this:
config = {
"ramdisk": {
"mountpoint": "/ramdisk",
"block_size": 512,
"num_blocks": 200,
},
"static_files": [
"mpide_config.py",
],
"dynamic_files": [
"main.py",
],
}
(consider '/ramdisk' to be hard-coded for now - this will change in the near future)
You changed a couple of details now:
- added a RAM-disk configuration (will NOT be auto-mounted)
- made
main.py"dynamic", i.e it will now be copied to/ramdisk/main.pyinstead - added
mpide_config.pyto the tracked files - it will now be synchronized as well (but to/mpide_config.py, i.e. stored permanently)
Now by modifying main.py your file will be automatically stored on the ramdisk.
No wait - you just get a badly formatted exception instead, mumbling something about
OSError: [Errno 2] ENOENT..
This is because the RAM-disk has been configured but not actually mounted yet.
While this will be done automatically soon, you have to send :ramdisk once every
time the device has been rebooted..
Once done, saving main.py again you should see a message
copied <project>/main.py to <device>/ramdisk/main.py in the REPL, indicating
that you can now import main and main.run() to execute the code you just
edited.
In order to save time and space on the flash-FS/RAM-disk you can make mpide
involve mpy-cross from the MicroPython toolchain to precompile .mpy files
from your sources and upload them instead.
To do this, you again have to do two things: provide mpy-cross to mpide and
list .mpy files in your mpide_project.py file instead of .py files.
mpide will still watch for changes on .py files in your project folder
but do the mapping to .mpy files for you conveniently.
I take this as an opportunity to show off an advantage of scripted configuration
compared to a static JSON/YAML file. Imagine you have multiple development
machines you're working on, both with a different location for the mpy-cross
executable. You can just add a line
config.update(config_local.config)
to your mpide_project.py file, add a file called config_local.py which
you exclude from your project e.g. by listing it in .gitignore, and put in
all information which might be different among development machines. That
might be only the path to mpy-cross for now, but you can also think of
WiFi credentials, etc.
So here goes the full configuration:
mpide_config.py:
import config_local
config = {
"ramdisk": {
"mountpoint": "/ramdisk",
"block_size": 512,
"num_blocks": 200,
},
"static_files": [
"mpide_config.mpy",
"local_config.mpy",
],
"dynamic_files": [
"main.mpy",
],
}
config.update(config_local.config)
config_local.py:
config = {
"mpy_cross_path": "~/micropython/mpy-cross/build/mpy-cross",
}
Built in commands
:cp <SRC> <DST>
Copies files from SRC on your host machine to <DST> on the target device
:cat <PATH>
Same as Posix cat - plots a file (located on the target device) into the REPL
:ramdisk
Executes the built-in setup_ramdisk snippet, which will create a RAM-disk
mounted at /ramdisk
:snippet <BASENAME> [<EXTRA-SNIPPET>]
Executes an arbitrary snippet taken from a Python source file, identified by
the provided basename. The file will be searched for in your project directory
or - if not found - somewhere in the mpide package directory.
If provided the optional EXTRA-SNIPPET gets attached, so for example
:snippet my_snippet print(foo('bar'))
.. will load my_snippet.py and execute it together with print(foo('bar')).
This comes in handy when you have a file defining a function (here foo()),
which you can call with arbitrary parameters without modifying the actual
source file containing the snippet.
Go ahead and give it a try with this my_snippet.py:
print("my_snippet")
def foo(text: str, count: int) -> None:
for i in range(count):
print(i, text)
Working around all bugs and uncovering undocumented behavior is left for you as homework.
Roadmap
This is what I intend to implement in the near future, since it's what I need in daily live:
Version 1.0 (MLP)
- Textual based IDE stub based on
trickkiste/TuiBaseApp - involve
mpremoteto automatically connect to attached (ESP32) devices running MicroPython - REPL command history
- fix multi-line input
- auto-update mpy/py files on change
- make auto-update optional
- provide RAM-FS for temporarily patched files and to avoid wearing out your flash
- auto-unload updated modules on target device
- persist temporary files via
:persist -
:rmremoves files -
:treelists files -
:helpshows help again - cp whole directories
- one message box for multiple files
- prefix-search in command history with UP
- allow device / connection speed settings
- cleanup exceptions and messages
- bootstrap (i.e. populate a newly flashed device with helper stuff for remote working)
- bootstrap installs dependencies
- support middle mouse -> paste
- auto-sync on re-connect
- cat mpy files
- module unload context manager
- add instructions to build MicroPython
- add pass through command prefix (
!..) - fix dark-mode
- check MicroPython / mpy-cross versions
- cleanup cache folder
- cleanup cache folder
- warning if watch_fs_changes takes too long
Version 1.1
- provide
--initswitch for creating example files to bootstrap a project - auto-update via web
- install stuff via
mip - prompt: TAB expands
- provide basic operations on CLI (boostrap, copy, tree, ..)
- take color codes sent by device are not taken into account
- Web-REPL
- Web-based remote updating
- support terminal colors
- make web-server optional
- add minimal file explorer + editor
- mark + execute snippets in editor
License
For all code contained in this repository the rules of GPLv3 apply unless otherwise noted. That means that you can do what you want with the source code as long as you make the files with their original copyright notice and all modifications available.
See GNU / GPLv3 for details.
This project is not free for machine learning. If you're using any content of this repository to train any sort of machine learned model (e.g. LLMs), you agree to make the whole model trained with this repository and all data needed to train (i.e. reproduce) the model publicly and freely available (i.e. free of charge and with no obligation to register to any service) and make sure to inform the author (me, frans.fuerst@protonmail.com) via email how to get and use that model and any sources needed to train it.
NAQ
- Q: Why don't you host this on GitHub instead (or at least
gitlab.com)?
A: I don't like the way Microsoft (or anyone else) is making money from projects they don't own without asking, providing an option ot opt out or even informing about details
Interesting Links
Working with filesystems https://docs.micropython.org/en/latest/reference/filesystem.html
MicroPython 2.0 Migration Guide https://docs.micropython.org/en/latest/reference/micropython2_migration.html
Quick reference for the ESP32 https://docs.micropython.org/en/latest/esp32/quickref.html
https://github.com/micropython/micropython/wiki/Building-Micropython-Binaries https://docs.micropython.org/en/latest/reference/manifest.html
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mpide-0.2.0.dev3.tar.gz.
File metadata
- Download URL: mpide-0.2.0.dev3.tar.gz
- Upload date:
- Size: 28.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.8.3 CPython/3.11.4 Linux/6.11.5-200.fc40.x86_64
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e75676a5544672d6e6a2173442d7903dade816164fee86e3d2a024f852fca0d6
|
|
| MD5 |
882461384c6471ff883bbe2b831c5664
|
|
| BLAKE2b-256 |
663165ec99604b08c89b7758e6a8011fb8d23870d196ff7239cfad1c1f656f06
|
File details
Details for the file mpide-0.2.0.dev3-py3-none-any.whl.
File metadata
- Download URL: mpide-0.2.0.dev3-py3-none-any.whl
- Upload date:
- Size: 29.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.8.3 CPython/3.11.4 Linux/6.11.5-200.fc40.x86_64
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
693786c0456d1fe4382a60fbb7b1b8da1f942c54835137e70ab09c824161153f
|
|
| MD5 |
b7ddab023ea514f66ec1314c94f56fd5
|
|
| BLAKE2b-256 |
597d76c712a9f3f26f4e78365ca1aa2c4e3be66f984553fe2bbca55cca4403b9
|