Skip to main content

Carta

Python library for making GUI applications on the reMarkable tablet wrapped around the "simple" application

Simulating the ReMarkable device

It can be a pain having to transfer the script & run the script from the RM each time. Especially if you want to use the device for something else at the time. To help with this, I've made the option to manually set the command to a simple x64 binary that can be run on linux which will write to fb.pnm - This is the framebuffer file that you'll need to read from.

In the misc folder I've provided the binary and a basic script as an example. To use this, just initialize the ReMarkable object like so:

rm = ReMarkable(simple="path/to/simple/binay") 

Finally, checkout remarkable-sim for events (like button clicking) support

Using Carta

Carta's purpose is to function as a Python wrapper around sas - the simple app script for making apps on the reMarkable without need to compiling code. It's written in python and is designed to be as user-friendly and easy to use as possible.

To use it, you'll need to install a few things onto your reMarkable, in an SSH session:

  • toltec - an unofficial reMarkable-specific package manager See instructions on toltec's website.
  • simple opkg install simple
  • rM2 users need display opkg install display
  • pip - the package manager for python
    wget https://bootstrap.pypa.io/get-pip.py
    python get-pip.py
    
  • carta - this library pip install carta

After having installed all the prerequisites, you are ready to start developing. Make a python script on the rM and run chmod +x on the script to make it executable. You'll also need to add a shebang to the script (#!/opt/bin/python at the top) so that it knows what to run it with.

Here's an example script that you can copy:

#!/opt/bin/python 
from carta import ReMarkable, Widget 
rm = ReMarkable() 

my_button = Widget(id="but1", typ="button", value="Hello!", x="50%", y="50%")

rm.add(my_button)
rm.display()

Let's walk through it line by line,

from carta import ReMarkable, Widget 
rm = ReMarkable() 

This imports the necessary "parts" for the library to function. The ReMarkable class is the main "driver" code and handles everything from interacting with simple to display your app to managing the widgets themselves. The widget dataclass are the actual contents themselves and there are 6 core types;

  • Label
  • Paragraph
  • Button
  • TextInput
  • Text Area
  • Image

Please refer to the simple spec for more detailed information.

my_button = Widget(id="but1", typ="button", value="Hello!", x="50%", y="50%")

Here we are making a new Widget which we have assigned to my_button. The following is a table outlining information about supported arguments which can be given.

Argument Required Use Supported inputs Notes
id Yes Used to uniquely identify a widget when being interacted with Any string that hasn't been used before Spaces will be converted to _
typ Yes Gives a widget specific properties so it knows what to be used as Any from the following: label, paragraph, burtton, textinput, textarea, image Range is a WIP
value Yes What will be displayed on the widget Any string (Image path for the image widget type) Be careful about using new lines
x Yes Used to calculate the rendering position of the widget A percentage, keyword or an integer Supported keywords are same (same value as previous item) and step (previous item's cord + previous items size)
y Yes Used to calculate the rendering position of the widget A percentage, keyword or an integer Supported keywords are same (same value as previous item) and step (previous item's cord + previous items size)
width No (Automatically calculated) The width of the widget Any integer You might have some trouble with getting the right value for this
height No (Automatically calculated) The height of the widget Any integer You might have some trouble with getting the right value for this
justify No (Optional for buttons) Where the text sits in a button Any string from the following: center, right, left

Finally, we want to add the widget to the actual screen.

rm.add(my_button)
rm.display()

I've made the decision to have widgets be manually added like this to make it easier to manage when making apps). We can do this easily with add(args*), where args* are any Widget types - For example,

rm.add(my_button, label1, logo)

And then display it to the rM! The display() function will take all the currently active Widgets and convert them into something that simple can understand and render. The active widgets are all stored in the screen list (in this case rm.screen) and you can easily access and modify any of the widgets in there at any time via the lookup function which will return the Widget object that has the corresponding ID

print(rm.lookup("<id>"))

To remove a Widget you can use the remove() function and either supply it an ID or Widget object like so

rm.remove("<id>")

rm.remove(my_button)

In case you want to fully clear the screen, you can use the eclear() function - however this does require the modified updated simple binary which okeh can provide for you!

rm.eclear()

Finally, there are two other options that the ReMarkable class has that we can modify.

  • Fontsize - Changes the fontsize of the text on the screen
  • Timeout - The time after simple quits if no input is given
    • In this case, carrying on the program after rm.display() has been run and no input has been given after a set time

For example, if we wanted to make the fontsize 24 and timeout the program after 30 seconds we would do

rm.timeout = 32
rm.fontsize = 24

When you run the display function, carta will wait on any input being given OR the timeout being reached. When it's done this, it will return a dict object with the input given.

clicked = rm.display()

print(clicked) # {"<id>": True}

If it's a button that has been pressed it will return True as the value, if anything else has been given it will use that specific input (for example, from the keyboard) as the value.

Hope this guide was helpful, feel free to ask if you need some help (jake.sh on discord)

Metadata

Release files for carta 1.3.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for carta 1.3.3
File Size Uploaded Provenance
carta-1.3.3.tar.gz 19.1 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for carta 1.3.3
File Interpreter ABI Platform
carta-1.3.3-py3-none-any.whl Python 3 none any Details

Total release size: 37.8 kB

Release files / carta-1.3.3.tar.gz

Download URL carta-1.3.3.tar.gz
Size 19.1 kB
Tags Source
SHA-256 checksum
How to use checksums
6f354f1f77e6fc3c80dc3e1c68bbf472dabf885f36e7d138f7494bb0d7d774cb
BLAKE2b-256 checksum
How to use checksums
2e95b3478dcff0e1d4c04acda2294d5f7a79bad1f1a6bebede846e4d5f473174
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.1.12 CPython/3.10.12 Linux/6.4.6-76060406-generic

Release files / carta-1.3.3-py3-none-any.whl

Download URL carta-1.3.3-py3-none-any.whl
Size 18.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
783561a129709a1d37555dbc371907140212dba3e0190dbd82664a719e702e10
BLAKE2b-256 checksum
How to use checksums
f294de5755ccac7b1dac9d155d0b3dae0c89092827e6fe5be19d275e83417d8d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.1.12 CPython/3.10.12 Linux/6.4.6-76060406-generic

Security for carta 1.3.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page