Git Product home page Git Product logo

remy's Introduction

Remy, a reMarkable tablet manager app

The goal of Remy is to allow simple interaction with the reMarkable tablet over ssh, without needing the cloud service, nor the USB Web UI.

Screenshot

BEWARE

⚠️ Remarkable Software Version 3 is NOT SUPPORTED ⚠️
Remy has only been tested on versions of the remarkable software <=2. In particular Remy does not support v3 and the new v6 file format (yet). See #49 for updates

This is a work-in-progress with incomplete features. It has not been thoroughly tested. These instructions are preliminary and will be expanded with time. Feel free to populate the wiki!

I did my best to make sure usage of Remy will not incur in data loss. Most of the features exclusively read from the tablet and are completely safe, even if they may fail on the computer side. The only features that alters data on the tablet is the upload feature. It is however very unlikely to cause any problem since it only adds files. In any case, it is highly advisable to back up your data before playing with it!

For a basic backup of the tablet's data:

scp -rp REMARKABLEHOST:/home/root/.local/share/remarkable/xochitl .

Installation

Pre-built bundles are in the roadmap but not available yet. The easiest way to install Remy is via pip (from the root of this repo):

pip install --user ".[default]"

There are few variants which might be suitable for different environments:

# To install Remy without PDF preview support:
pip install --user .
# To install Remy with PDF preview support via `PyMuPDF` (equivalent to default):
pip install --user ".[mupdf]"
# To install Remy with PDF preview support via `python-poppler-qt5`:
pip install --user ".[poppler]"
# To install Remy with support for lines simplification:
pip install --user ".[simpl]"

Combinations are also possible, for example pip install --user ".[mupdf,simpl]".

After installation the tool can be launched by running remy from a console (or python -m remy.gui).

Manual installation

Remy's installation has been tested on MacOs Monterey, python version 3.8.

The mandatory dependencies are:

  • requests
  • sip
  • arrow
  • paramiko
  • PyPDF2
  • PyQt5

Only required for previewing PDF files:

  • PyMuPDF (or, alternatively, python-poppler-qt5)

Optional:

  • simplification (this requires python < 3.9)

The entry point is remy.gui:

python -m remy.gui

Usage

The main intended usage is as a GUI for connecting to the tablet. The app however also supports reading from a local backup. The main entry point for the app is remy.gui.

Configuration

Starting it the fist time with python -m remy.gui will show an error message with the path where the app is expecting to find a configuration file (on macOS it would be something like /Users/<user>/Library/Preferences/remy.json). The message box will offer to open the file and populate it with some basic defaults. These should be enough to test basic functionality but much more can be obtained by properly configuring Remy. The configuration file is a JSON file with the following structure:

{
  "sources": {
      "source1": {...},
      "source2": {...},
      ...
  },
  "default_source": "source1",
  "palettes" : {...},
  "preview": {...},
  "export": {...},
  "upload": {...},
  "mathpix" : {...}
}

The only mandatory section is sources. Each section is documented below. The file example_config.json is an example configuration that you can adapt to your needs. IMPORTANT: the format is vanilla JSON; trailing commas and C-like comments are not supported. The file is parsed using Python's standard json module.

Source types

Each source defines a possible way to get the contents to display. The default_source settings indicates which source to load if none is specified in the command line. If default_source is false or not set, then Remy shows a dialog allowing you to pick a source among the available ones. There are three supported kinds of sources: local, ssh and rsync.

Local source

A local source expects to find the data at a local path (e.g. from a backup folder):

{
  "name": "Latest Backup",
  "type": "local",
  "documents": "/path-to/backup/latest",
  "templates": "/path-to/templates"
}

The documents folder is expected to have the same structure as the /home/root/.local/share/remarkable/xochitl on the tablet. The "maintenance" folders .cache, .thumbnails, .textconversion, .highlights are not needed. The templates folder is expected to be a local copy of the /usr/share/remarkable/templates folder on the tablet. Obviously, this source is read-only: you cannot upload PDFs to it.

SSH source

{
  "name": "reMarkable (WiFi)",
  "type": "ssh",
  "host": "192.168.1.154",
  "key": "~/.ssh/id_rsa_remarkable",
  "username": "root",
  "timeout": 3,
  "persist_cache": true,
  "use_banner": "remy-banner.png"
}

The SSH-type source connects to the tabled via SSH. The tablet needs to be either plugged via USB (in which case you should set "host": "10.11.99.1") or via WiFi, in which case you need to find the address assigned to the tablet or you can use the hostname "reMarkable" (if your router supports hostname resolution) in the "About" section of the tablet's settings. Most settings are optional, you can also use password instead of key. The option "host" falls back to the USB configuration "10.11.99.1". The use_banner setting is optional and described below. It is possible to specify remote_documents and remote_templates, these paths need to be absolute ("~" expansion does not work).

It is possible to configure where the cache of the data from the tablet is stored, by setting cache_dir. The cache is kept across runs, and files are re-downloaded if modified date or size have changed. This might leave behind some files and might miss some updates. By setting persist_cache to true the cache is cleared every time.

Rsync source

{
  "name": "reMarkable (RSync)",
  "type": "rsync",
  "data_dir": "/path-to/remy",
  "host": "10.11.99.1",
  "key": "~/.ssh/id_rsa_remarkable",
  "username": "root",
  "timeout": 3,
  "use_banner": "remy-banner.png",
  "cache_mode": "on_demand",
  "rsync_path": "/path/to/local/rsync",
  "rsync_options": [ "--rsync-path=/opt/bin/rsync" ]
}

This is an optimised version of the SSH source. While SSH works without extra dependencies, the rsync source requires rsync to be installed on the reMarkable. A mandatory setting is data_dir which should point to a directory which can be managed by Remy to keep a partial copy of the tablet's data. Every time you connect, only the changes are downloaded. The data-heavy files (PDFs and .rm) are downloaded on demand. The optional settings rsync_path provides the path to the local rsync binary and rsync_options provides additional options, the example above configures the options to find the rsync binary on the remarkable installed using entware.

The cache_mode option can take three values:

  • on_demand: only metadata is synced, other files are downloaded as needed.
  • full_mirror: the full contents of the tablet are synced.
  • light_mirror: everything is synced except for thumbnails.

The mirror options can be used in combination with a local source: it is possible to have two sources, one local (A) and one RSync (B), with A's documents setting pointing at the documents directory inside of data_dir of B (and same for templates). This way every time one connects to B a full backup is stored, and the same backup can be accessed offline through A.

The use_banner option

When this option is set, the main UI of the tabled will be temporarily disabled while Remy is open. This is intended as an helpful prompt and a way to avoid conflicts on data access. The feature works best if the setting is the filename (can be absolute, or relative to home) of a png file stored on the tablet (there's a nice remy-banner.png in the asset folders you can upload with scp) and remarkable-splash is installed on the tablet.

If Remy crashes and the remarkable seems unresponsive it is only because Remy re-enables the main UI of the tabled on exit; to regain control of the tablet you have three options: try and run Remy again and close it cleanly; or run ssh REMARKABLEHOST /bin/systemctl start xochitl; or manually reboot the device. Don't worry nothing bad is happening to the tablet in this circumstance.

Palettes section

The palettes section is a dictionary of color palettes, for example:

"palettes": {
    "review": {
        "black": "red",
        "gray": "#009C26"
    },
    "grayscale": {
        "black": "black",
        "gray": "#bbbbbb",
        "blend_gray": "#7fbbbbbb",
        "white": "white",
        "blue": "#cccccc",
        "red": "#dddddd",
        "highlight": "#7fcccccc",
        "yellow": "#7fcccccc",
        "green": "#7fbbbbbb",
        "pink": "#7fdddddd"
    }
}

There is always a 'default' palette with the built-in choice of colors. You can overwrite it by redefining it in the palettes dictionary. All other palettes inherit the non-specified colors from the built-in defaults.

The palettes defined in the section are used in two ways:

  • they are offered as options in the Export dialog
  • the defined names can be used as values of the palette setting in the preview and export sections.

The color identifiers are black, gray, white, blue, and red, and for the highlighter colors they are highlight (for the old opacity-based yellow highlighter) yellow, green, pink, and blend_gray for the opacity-based gray introduced in update 2.13.

Currently it is not possible to change the pencil's color.

Render options

The preview and export sections can contain settings that affect the rendering (which we will group in the explanation as RENDER_OPTIONS).

All these settings are optional. The RENDER_OPTIONS settings can set the following keys:

  • palette can be set either to the name of a palette defined in the palettes section, or to a dictionary with color definitions (as used in the palettes dictionary).

  • pencil_resolution can be set to a number indicating how much to scale the texture of pencil brushes. Bigger scale means coarser texture. Default is 0.4. Due to limitations of Qt, the PDF export currently ignores this setting.

  • simplify can be set to a number indicating a tolerance for the precision of strokes. High tolerance means strokes will be more approximate. Requires the simplification library. Default is 0 (no simplification).

  • smoothen can be set to true or false. Default is false. If set, the renderer would produce beziers interpolating the original strokes. Can be used in combination with simplify to obtain smaller files with smooth lines. The feature is still experimental.

  • eraser_mode can be set to either "accurate", "ignore", "quick", or "auto". Default is "auto".

    • The "accurate" method clips the paths so that the erased areas are see-through. This incurs in expensive calculations and bigger files. It makes a difference only when the eraser is used to carve out precise bits out of wide stroked areas.
    • The "ignore" method gives generally the best tradeoff. It simply ignores the eraser strokes. The tablet already removes from the file the strokes that were completely covered by eraser strokes. The only inaccuracies come from strokes that were only partially covered. For written notes or line art this is the best method.
    • The "quick" method paints white strokes to render the eraser tool. This results in quicker rendering times but inaccurate results: the layers below the strokes would be covered by the eraser which is undesirable.
    • "auto" will use "ignore" and automatically switch to "accurate" when the page contains strokes that may need the accurate method to be rendered precisely (e.g. with very wide strokes).
  • thickness_scale controls the ratio of the thickness of lines that should actually be rendered (1 is full scale).

  • exclude_layers can be set to a list of numbers between 1 and 5 indicating which layers to exclude from the rendering.

  • orientation can be set to auto, landscape or portrait.

  • include_base_layer can be set to true or false, determining whether the template/pdf/epub layer is to be included or not in the rendering. Default is true.

Preview options

The preview section contains RENDER_OPTIONS determining how the previewer will render notebooks.

"preview": {
  RENDER_OPTIONS
}

Export options

The export section determines the defaults used for exporting notebooks to PDFs. In addition to RENDER_OPTIONS you can also set the default_dir and the open_exported settings

"export": {
  "default_dir": "/path/to/folder",
  "open_exported": true,
  RENDER_OPTIONS
}

The highlighter colors will be rendered with opacity 50% since the PDF exporter of Qt5 does not support blend modes.

Upload options

The upload section determines the defaults used for documents uploaded via Remy. This section can contain three sub-sections, all optional:

"export": {
  "default_options": UPLOAD_OPTIONS,
  "pdf_options": UPLOAD_OPTIONS,
  "epub_options": UPLOAD_OPTIONS
}

Here, UPLOAD_OPTIONS is a dictionary which would overwrite the default values stored in the .contents metadata files on the tablet. This includes information about the initial tool settings like selected tool, width for each tool, color for each tool etc. The available options are whichever ones are supported by the tablet. They are undocumented and so this setting is done through guesswork; making mistakes should not be harmful however.

The options in pdf_options and epub_options inherit the ones in default_options. Here is an example:

"default_options": {
    "extraMetadata": {
        "LastBallpointv2Color": "Black",
        "LastBallpointv2Size": "2",
        "LastCalligraphyColor": "Black",
        "LastCalligraphySize": "3",
        "LastEraserSize": "1",
        "LastEraserTool": "Eraser",
        "LastFinelinerv2Color": "Black",
        "LastFinelinerv2Size": "1",
        "LastHighlighterv2Color": "HighlighterYellow",
        "LastMarkerv2Color": "White",
        "LastMarkerv2Size": "3",
        "LastPaintbrushv2Color": "Black",
        "LastPaintbrushv2Size": "3",
        "LastPencilv2Color": "Black",
        "LastPencilv2Size": "2",
        "LastSharpPencilv2Color": "Black",
        "LastSharpPencilv2Size": "2",
        "LastPen": "Ballpointv2",
        "LastTool": "Ballpointv2"
    }
},
"pdf_options": {
    "extraMetadata": {
        "LastFinelinerSize": "1",
        "LastPen": "Finelinerv2",
        "LastTool": "Finelinerv2"
    }
},
"epub_options": {
    "extraMetadata": {
        "LastPen": "Highlighterv2",
        "LastTool": "Highlighterv2"
    }
}

Mathpix options

To use the mathpix API you need to obtain personal tokens at https://mathpix.com/ocr (they have a free plan). Once obtained, the API tokens should be saved in the configuration as follows:

"mathpix" : {
  "app_id":"xxx_xxx_xxx_xxx_xxxxxx",
  "app_key":"xxxxxxxxxxxxxxxxxxxx"
}

The support for mathpix is currently experimental. Only one page at a time can be exported (via context menu in preview) and the data is sent in vector form, which means the eraser tool is ignored.

Features

Once the configuration file contains the necessary info, you can run Remy by running

remy [SOURCE]

The option is the id of one of the sources defined in the configuration file. With no option, the default source will be selected.

The app displays the tree of the files in the main window and allows to search by name/type.

Preview

Double clicking on a PDF or notebook will open a preview window. Use the arrows to got to next/prev page. You can zoom in and out with + and - or mouse wheel. Ctrl+Left/Right rotates the view. The context menu shows some further actions. Pressing S increases the simplification of the lines, Shift+S decreases it (this is only a rendering effect, the notebooks are unaffected). This is just a preview of an experimental feature.

Export and rendering

PDFs are rendered in the previewer at a fixed resolution. The export function overlays the vectorial data from annotations to the original PDF so the quality of both is preserved.

The rendering of notebooks/annotations has been redeveloped from scratch. Features:

  • control over the rendering of eraser (including accurate mode)
  • pencil textures
  • control over layers to be rendered, colors to be used
  • page ranges for export
  • thickness scale
  • optional simplification and smoothening (experimental)

Planned features include:

  • fully parametric rendering to be able to control the colors/style of each element from settings
  • batch export
  • previewer with text recognition, annotations, and rendering options panels
  • text search
  • raster and SVG export

Upload

From the tree view, select a folder (or deselect to select the root) and drag and drop on the info panel any PDF (multiple PDFs/EPUBs at once are supported, folders are planned but not supported yet). Alternatively, choose Upload Here... from the contextual menu of the destination folder.


Every source can in addition overwrite other global settings by using the settings key, for example you could have a per-source default export folder:

{
  "sources": {
    "source1": {...},
    "source2": {
      ...
      "settings": {
        "export": {
          "default_dir": "/path-to/love-letters"
        }
      }
     },
    ...
  },
  "export": {
    "default_dir": "/path-to/work"
  }
}

Credits

Disclaimer

This project is not affiliated to, nor endorsed by, reMarkable AS. I assume no responsibility for any damage done to your device due to the use of this software.

Licence

GPLv3

remy's People

Contributors

bordaigorl avatar gbatiz avatar zerone01y avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

remy's Issues

Restart the current launcher when it is not `xochitl`

Thanks for this amazingly useful tool!

On my device, after each use of remy the UI was all messed up until the next reboot. This quote from the readme put me on the right track:

If Remy crashes and the remarkable seems unresponsive it is only because Remy re-enables the main UI of the tabled on exit; to regain control of the tablet you have three options: try and run Remy again and close it cleanly; or run ssh REMARKABLEHOST /bin/systemctl start xochitl; or manually reboot the device. Don't worry nothing bad is happening to the tablet in this circumstance.

As far as I can tell by xochitl is hardcoded, see here and here, maybe other places. However on my device I use remux and so restarting xochitl lead to a visual mess (I'm surprised it even works!)

As a quick fix, I hardcoded remux in remy/remarkable/filesource.py: so far it seems to work, but I imagine it would be worth either making it a configurable string in config.json, or executing systemctl on the device to know which launcher is running and restart that one.

Happy to try and draft a PR with either solution if you think it's worth it!

RM2 support?

This tool looks pretty cool. Does it support reMarkable 2?

Poppler issues

Ubuntu 20.04. I tried on a fresh virtualbox install to avoid messing with qt libraries installed in the main system.

Followed the instructions in readme:

  • don't have brew in ubuntu, but I've ran apt install cmake libpoppler-qt5-1, and also apt build-dep cmake libpoppler-qt5-1 -- just in case some build dependencies are also necessary
  • successfully ran both pip commands
  • when trying to open a PDF in the app, I get
Traceback (most recent call last):
  File "/shared/remy/remy/gui/filebrowser.py", line 442, in openEntry
    self.viewers[uid] = NotebookViewer(index.get(uid))
  File "/shared/remy/remy/gui/notebookview.py", line 99, in __init__
    self._maxPage = document.baseDocument().numPages() - 1
  File "/shared/remy/remy/remarkable/metadata.py", line 256, in baseDocument
    from popplerqt5 import Poppler
ImportError: /home/dev/.local/lib/python3.8/site-packages/PyQt5/QtXml.abi3.so: undefined symbol: _ZN12QDomDocument10setContentEP16QXmlStreamReaderbP7QStringPiS4_, version Qt_5

Seems like a mismatch between python API and the installed library.

I also tried installing via brew, but even though it installed successfully, it still couldn't find the poppler library, unless I installed it via apt.

And the final option I tried -- running pip3 uninstall pyqt5 pyqt5-sip python-poppler-qt5 and then installing them via the package manager (generally this would mean more consistent versions): apt install python3-poppler-qt5 python3-pyq. Then when opening a pdf I'm getting

Traceback (most recent call last):
  File "/shared/remy/remy/gui/filebrowser.py", line 442, in openEntry
    self.viewers[uid] = NotebookViewer(index.get(uid))
  File "/shared/remy/remy/gui/notebookview.py", line 99, in __init__
    self._maxPage = document.baseDocument().numPages() - 1
  File "/shared/remy/remy/remarkable/metadata.py", line 262, in baseDocument
    self._pdf.setRenderHint(Poppler.Document.HideAnnotations)
AttributeError: type object 'Document' has no attribute 'HideAnnotations

not sure if it's much better though, presumably this method was added in a more recent poppler version, and that's why you were suggesting to install from github in the first place?

Some Issues

Hi,
I am trying to get remy working in nixos.
I already get it to launch but there are still two problems:

if I work with a local copy of my remarkable folders I get as far as to see my notebooks but if I double click any file I get tracebacks of the form:

Started
Configuration loaded from '/home/benneti/.config/remy.json'.
LOAD TIME: 0.048436
Traceback (most recent call last):
  File "/nix/store/18h689vj846lh37kk0k6mj70nyi41zvj-remy-0-git/src/remy/gui/filebrowser.py", line 442, in openEntry
    self.viewers[uid] = NotebookViewer(index.get(uid))
  File "/nix/store/18h689vj846lh37kk0k6mj70nyi41zvj-remy-0-git/src/remy/gui/notebookview.py", line 102, in __init__
    self.loadPage(document.lastOpenedPage or 0)
  File "/nix/store/18h689vj846lh37kk0k6mj70nyi41zvj-remy-0-git/src/remy/gui/notebookview.py", line 175, in loadPage
    self._page_cache[i] = self.makePageScene(i, eraser_mode=ermode)
  File "/nix/store/18h689vj846lh37kk0k6mj70nyi41zvj-remy-0-git/src/remy/gui/notebookview.py", line 164, in makePageScene
    PageGraphicsItem(page, scene=scene, simplify=simplify, smoothen=smoothen, eraser_mode=eraser_mode, parent=r)
  File "/nix/store/18h689vj846lh37kk0k6mj70nyi41zvj-remy-0-git/src/remy/gui/pagerender.py", line 154, in __init__
    if eraser_mode >= AUTO_ERASER:
TypeError: '>=' not supported between instances of 'NoneType' and 'int'
/nix/store/18h689vj846lh37kk0k6mj70nyi41zvj-remy-0-git/bin/.remy-gui-wrapped: line 3: 10095 Aborted                 (core dumped) /nix/store/2vjlf8bip418y0d9vglaplfgpz29spd5-python3-3.8.6-env/bin/python /nix/store/18h689vj846lh37kk0k6mj70nyi41zvj-remy-0-git/src/remygui.py $@

Also if I try to use rsync (installed via entware) I get

Started
Configuration loaded from '/home/benneti/.config/remy.json'.
Connecting...
Connected to 10.11.99.1
DATA STORED IN:
	/home/benneti/.local/share/remy/documents
	/home/benneti/.local/share/remy/templates
Traceback (most recent call last):
  File "/nix/store/18h689vj846lh37kk0k6mj70nyi41zvj-remy-0-git/src/remygui.py", line 4, in <module>
    app.main()
  File "/nix/store/18h689vj846lh37kk0k6mj70nyi41zvj-remy-0-git/src/remy/gui/app.py", line 87, in main
    fsource = fileSourceFromSSH(LiveFileSourceRsync,  **src)
  File "/nix/store/18h689vj846lh37kk0k6mj70nyi41zvj-remy-0-git/src/remy/remarkable/filesource.py", line 480, in fileSourceFromSSH
    return cls(name, client, **kw)
  File "/nix/store/18h689vj846lh37kk0k6mj70nyi41zvj-remy-0-git/src/remy/remarkable/filesource.py", line 367, in __init__
    self._bulk_download(
  File "/nix/store/18h689vj846lh37kk0k6mj70nyi41zvj-remy-0-git/src/remy/remarkable/filesource.py", line 397, in _bulk_download
    return subprocess.run(cmd)
  File "/nix/store/papbnjfxwrdkmz6xfp7v2q7nxyvgcr5l-python3-3.8.6/lib/python3.8/subprocess.py", line 489, in run
    with Popen(*popenargs, **kwargs) as process:
  File "/nix/store/papbnjfxwrdkmz6xfp7v2q7nxyvgcr5l-python3-3.8.6/lib/python3.8/subprocess.py", line 854, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/nix/store/papbnjfxwrdkmz6xfp7v2q7nxyvgcr5l-python3-3.8.6/lib/python3.8/subprocess.py", line 1702, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: '/opt/bin/rsync'

or without "rsync_path": "/opt/bin/rsync", in the configuration I get

Started
Configuration loaded from '/home/benneti/.config/remy.json'.
Connecting...
Connected to 10.11.99.1
DATA STORED IN:
	/home/benneti/.local/share/remy/documents
	/home/benneti/.local/share/remy/templates
sh: rsync: command not found
rsync: connection unexpectedly closed (0 bytes received so far) [Receiver]
rsync error: error in rsync protocol data stream (code 12) at io.c(228) [Receiver=3.2.3]
Traceback (most recent call last):
  File "/nix/store/18h689vj846lh37kk0k6mj70nyi41zvj-remy-0-git/src/remygui.py", line 4, in <module>
    app.main()
  File "/nix/store/18h689vj846lh37kk0k6mj70nyi41zvj-remy-0-git/src/remy/gui/app.py", line 87, in main
    fsource = fileSourceFromSSH(LiveFileSourceRsync,  **src)
  File "/nix/store/18h689vj846lh37kk0k6mj70nyi41zvj-remy-0-git/src/remy/remarkable/filesource.py", line 480, in fileSourceFromSSH
    return cls(name, client, **kw)
  File "/nix/store/18h689vj846lh37kk0k6mj70nyi41zvj-remy-0-git/src/remy/remarkable/filesource.py", line 373, in __init__
    with open(self._local("templates.json", branch=TEMPLDIR), 'r') as f:
FileNotFoundError: [Errno 2] No such file or directory: '/home/benneti/.local/share/remy/templates/templates.json

I think the latter can simply be fixed by allowing to specify --rsync-path via the configuration, if you want I can implement this one. Pointers for the first problem would be appreciated.

xochitl not restarted when using "type": "rsync"

It seems that the cleanup method of the LiveFileSourceRsync class is not called when the class is deleted.
This effectively makes Remarkable freeze, unless one pushes the power button for several second or restarts
xochitl via ssh.

A possible (admittedly very trivial) fix would be

---
 remy/remarkable/filesource.py | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/remy/remarkable/filesource.py b/remy/remarkable/filesource.py
index 41bb953..8cc9bfb 100644
--- a/remy/remarkable/filesource.py
+++ b/remy/remarkable/filesource.py
@@ -1,5 +1,6 @@
 import paramiko
 import os
+import atexit
 import shutil
 import os.path as path
 import json
@@ -398,6 +399,8 @@ class LiveFileSourceRsync(LiveFileSourceSSH):
     self.host = host
     self.username = username
     self.cache_mode = cache_mode
+    
+    atexit.register(self.cleanup)
 
     if rsync_path:
       self.RSYNC = [ rsync_path ]

Then it works as expected.

rsync failures are not reported

When using an rsync config, and when the rsync command fails (e.g. because of issue #44), Remy does not show any error message, but instead opens with an out-of-date state.

Instead, it should at least warn the user that the local state could not be synced with the tablet.

Segfaults when opening files

When open a pdf or epub file, remy crashes and produces the following error log:

[I] STARTING: Sat Jan 28 00:23:01 2023
[I] Configuration loaded from /home/cycatz/.config/remy/config.json.
[W] No key nor password given. System-wide SSH connection parameters are going to be used.
[I] Using system default known hosts file
[I] Loading system default known hosts file, this may take a while...
[I] System default known host file loaded
[I] Connecting...
[I] Connected to 192.168.10.16
[I] LOAD TIME: 0.088373
[I] Initialised, launching browser
[W] Could not create thumbnail for ffa6ce5a-8941-44ff-a6e4-412fe68d3efa [arguments did not match any overloaded call:
  QImage(): too many arguments
  QImage(size: QSize, format: QImage.Format): argument 1 has unexpected type 'float'
  QImage(width: int, height: int, format: QImage.Format): argument 1 has unexpected type 'float'
  QImage(data: bytes, width: int, height: int, format: QImage.Format): argument 1 has unexpected type 'float'
  QImage(data: PyQt5.sip.voidptr, width: int, height: int, format: QImage.Format): argument 1 has unexpected type 'float'
  QImage(data: bytes, width: int, height: int, bytesPerLine: int, format: QImage.Format): argument 1 has unexpected type 'float'
  QImage(data: PyQt5.sip.voidptr, width: int, height: int, bytesPerLine: int, format: QImage.Format): argument 1 has unexpected type 'float'
  QImage(xpm: List[str]): argument 1 has unexpected type 'float'
  QImage(fileName: str, format: typing.Optional[str] = None): argument 1 has unexpected type 'float'
  QImage(a0: QImage): argument 1 has unexpected type 'float'
  QImage(variant: Any): too many arguments]
zsh: segmentation fault (core dumped)  python -m remy.guif

My remarkable version is 3.0.4.1305, and uses remy at version df2c1ae

Unable to connect, charmap codec can't decode byte

Hello!

Lovely tool here, however sadly I cannot seem to connect to my RM2 - 2.14.1.866 [Toltec installed, no DDVK hacks]

image

....and the config file:

"default_source": false,
    "sources": {
        "default": {
            "name": "reMarkable",
            "hidden": false,
            "type": "ssh",
            "host": "10.11.99.1",
            "username": "root",
            "host_key_policy": "ask",
            "timeout": 3,
            "use_banner": false,
            "password": "XXXXXXXXXXX",
            "enable_webui_export": false
        }
    },

Log output for debuggingg:

[I] STARTING: Thu Sep 15 17:34:05 2022
[I] Configuration loaded from C:\Users\Jacob\AppData\Local\remy\remy\config.json.
[I] Using known hosts file: C:\Users\Jacob\AppData\Local\remy\remy\known_hosts
[I] Loaded known hosts from C:\Users\Jacob\AppData\Local\remy\remy\known_hosts
[I] Connecting...
[I] Connected to 10.11.99.1
[E] RETRY? ['charmap' codec can't decode byte 0x8d in position 3936: character maps to <undefined>]
[I] Configuration at 'C:\Users\Jacob\AppData\Local\remy\remy\config.json'
[I] Waiting for stray threads
[I] Done waiting
[I] QUITTING: Thu Sep 15 17:34:08 2022

Feedback (WSL 2 Ubuntu 20.04)

Thanks for this wonderful application, works like a charm!

As requested here is some feedback:

  1. Exporting documents works fine, however it doesn't seem to support epub/ebooks. I guess that's intended?

  2. Importing files doesn't work at all on my system. The info panel simply rejects the upload of PDFs.

  3. No matter where I put remy-banner.png it doesn't recognize it. Tried to adapt the config.json file but had no sucess so far. Any advice?

Looking forward to your response and already stoked for new features.

Thanks again!

Feedback

As you requested feedback, I will try to give some using a new issue. Remy it self works flawlessly! Thanks!

Some issues I faced:

  1. Before I was able to start, I needed to manually copy the template folder from my remarkable to my remy folder
  2. Segmentation faults and errors, when opening up PDFs (probably only due to my anaconda setup)
sent 76 bytes  received 36539 bytes  24410.00 bytes/sec
total size is 532032  speedup is 14.53
LOAD TIME: 1.031118
objc[70088]: Class RunLoopModeTracker is implemented in both /Users/schneider/anaconda3/lib/libQt5Core.5.dylib (0x10a640a80) and /usr/local/opt/qt/lib/QtCore.framework/Versions/5/QtCore (0x126a7cb40). One of the two will be used. Which one is undefined.
  1. erasing strokes are also acknowledged. I think its possible to remove those (@ddvk had a method to do that), Only effects the preview, not the export.

Screenshot 2020-07-07 at 13 42 12

  1. Where to put remy-banner.png? I used /usr/share/remarkable and it didnt recognise it.

  2. It would be extremly nice to be able to export multiple files (like a folder) to pdf and save them on the computer :D

Thanks again!

No templates.json file

When I try to run python remygui.py wifi (wifi is rsync), I'm getting the following error complaining it doesn't find a templates.jsonfile:

File "/home/user/Downloads/software/remarkable/remy/remy/remarkable/filesource.py", line 372, in __init__
    with open(self._local("templates.json", branch=TEMPLDIR), 'r') as f:
FileNotFoundError: [Errno 2] No such file or directory: '~/remarkable/rsync/templates/templates.json'

Not sure what this templates.json file is supposed to be or where to get one to adapt. FWIW my remy.json config file is at https://gist.github.com/mefistoso/c2b2ab081ecf1949a4af3fe3765a412b

Application can not be executed

Steps to reproduce the issue:

  1. git clone https://github.com/bordaigorl/remy.git
  2. cd remy
  3. $python3 -m remy.gui

Traceback (most recent call last):
File "/usr/lib/python3.10/runpy.py", line 196, in _run_module_as_main
return _run_code(code, main_globals, None,
File "/usr/lib/python3.10/runpy.py", line 86, in _run_code
exec(code, run_globals)
File "/home/shamot/Remarkable2/remy/remy/gui/main.py", line 1, in
from remy.gui import app
File "/home/shamot/Remarkable2/remy/remy/gui/app.py", line 18, in
import remy.gui.resources
ModuleNotFoundError: No module named 'remy.gui.resources'

EPUB import

Thanks for your work!

Is it impossible to import EPUB files to reMarkable using remy?
When I try to import a EPUB, it is then shown as a PDF in remy, and of course reMarkable cannot read it.

PdfFileReader deprecated

When exporting a PDF on my recently upgraded Linux Mint system, I get the error:

'''
Something went wrong while exporting.

PdfFileReader is deprecated and was removed in PyPDF2 3.0.0. Use PdfReader instead.
'''

[devel] setup.py problem

I think hwr on github is incomplete right now, as it includes "from remy.hwr.mathpix import mathpixRaster, MathPixError" which does not exist.

rsync: change_dir failed

Hi all,

as the title describes, reMy refuse to connect.
Terminal output:

% python3 remygui.py                                
[I] STARTING: Sun May  8 16:18:26 2022
[I] Configuration loaded from /home/pityhero/.config/remy/config.json.
[I] Using known hosts file: /home/pityhero/.config/remy/known_hosts
[I] Loaded known hosts from /home/pityhero/.config/remy/known_hosts
[I] Connecting...
[I] Connected to 192.168.12.234
[I] DATA STORED IN:
	/home/user/bin/remy/data2/documents
	/home/user/bin/remy/data2/templates
receiving file list ... 
rsync: change_dir "/home/root//'/usr/share/remarkable/templates" failed: No such file or directory (2)
done

sent 8 bytes  received 116 bytes  248.00 bytes/sec
total size is 0  speedup is 0.00
rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1835) [Receiver=v3.2.4]
rsync: [Receiver] write error: Broken pipe (32)
[E] RETRY? [[Errno 2] No such file or directory: '/home/pityhero/bin/remy/data2/templates/templates.json']
[I] Waiting for stray threads
[I] Done waiting
[I] QUITTING: Sun May  8 16:18:30 2022

Config:

      "rM (makeAp)": {
        "name": "reMarkable (makeAp)",
        "type": "rsync",
        "data_dir": "/home/user/bin/remy/data2",
        "host": "192.168.12.234",
        "key": "/home/pityhero/.ssh/id_rsa",
        "username": "root",
        "timeout": 3,
        "use_banner": "remy-banner.png"
      }

I am able to ssh into remarkable normally with ssh [email protected].

Can not start the app

I'm trying to run the app on Linux Mint.

$ python3 remygui.py

[I] STARTING: Fri Feb 18 12:05:45 2022
qt5ct: using qt5ct plugin
[I] Configuration loaded from defaults.
Traceback (most recent call last):
File "remygui.py", line 4, in
app.main()
File "/home/shamot/Downloads/remy-master/remy/gui/app.py", line 364, in main
app.requestInit()
File "/home/shamot/Downloads/remy-master/remy/gui/app.py", line 115, in requestInit
init = RemyInitWorker(*self.config.connectionArgs(**overrides))
File "/home/shamot/Downloads/remy-master/remy/remarkable/config.py", line 193, in connectionArgs
t = c.pop('type')
KeyError: 'type'

Slow loading

Hi all,

Not sure if this behaviour is experienced by others, but everytime I run remy, it takes 1-2 minutes to run the initialization ...

suggestion: server sync

I have a system service on my remarkable setup (using systemds path watching) to push new files to my server whenever I change something, to be able to use these It would be necessary to set the remote_roots folder, are you open to me implementing a setting for this?

support for .lines file, version=6 (rM v3.0)

It seems reMarkable have changed the .lines file format with their recent v3.0 software.
It now says version=6 and even if remy's version check is bypassed there's errors (of course),
example from lines.py:
readStruct
return fmt.unpack(buff)
struct.error: unpack requires a buffer of 24 bytes

Any idea how to fix this?

Installing in virtualenv

I cannot manage to install this inside a virtualenv (using python 3.7.9), the first issue is with it not finding the module sipdistutils with error message ModuleNotFoundError: No module named 'sipdistutils'. As per frescobaldi/python-poppler-qt5#14 the sip install from PIP doesn't include the sipdistutils.py file so you can copy it manually as they explain in that issue as a workaround.

After that running pip3 install -r requirements.txtagain I get the following error message: ModuleNotFoundError: No module named 'sipconfig'. Which points towards a similar problem as with sipdistutils.py. A workaround again is suggested in frescobaldi/frescobaldi#992 (comment) , which is copying the system's sipconfig.py file to the virtualenv, in my case it was with something like cp /usr/lib/python3.9/site-packages/sipconfig.py env/lib/python3.7/site-packages (yeah, I have py3.9 in the system but remy requires 3.7 because of the simplification package, afaik).

A third time running pip3 install -r requirements.txt I get a ModuleNotFoundError: No module named 'PyQt5'. So I go ahead and install manually PyQt5 with pip3 install PyQt5==5.14.2 (pip cannot handle the order sometimes when using a requirements.txt file).

Then, the fourth time I run pip3 install -r requirements.txt it advances more but resulting in the following nasty error error: command '/usr/bin/sip' failed with exit status 1 along with many other lines (complete error at https://gist.github.com/ijpulidos/3bc11e535a93e59ef1e91d23e5cad7d4 ). And even though I have /usr/bin/sip in my system it fails (sip in system is 4.19.x). I would've thought that the sip command should come with the sip package from PyPI, but apparently that's not the case. SO in the end, this is one big mess to install remy inside a virtualenv, which is desired for those whose OS python's version is >3.7, since the simplification dependency for remy needs 3.7.x.

Better support for virtualenv (if even possible) would be nice to have.

Better antialiasing for pencil

I'm in the habit of using the mechanical pencil for most of my notes. When I look at a page I've written, the combination of the Qt Dense3Pattern and my display resolution lead to some really horrible aliasing in the preview window.

Adding the lines below to the PageGraphicsItem setup helped a lot, but there was still a bit of aliasing.

self.setRenderHint(QPainter.Antialiasing);
self.setRenderHint(QPainter.SmoothPixmapTransform);

Maybe there are other flags to set? It's been a long time since I've used Qt, so I'm just shooting in the dark at the moment.

Problem with pip install

Hi there,

I am trying to run remy on my M1 Mac and I keep getting this installation error. I've tried the manual installation, and replacing qtpy5 with qtpy but I still can't install it.

Any ideas?

Processing /Users/skinnylatte/Documents/Remarkable/export/remy
  Installing build dependencies ... error
  error: subprocess-exited-with-error

  × pip subprocess to install build dependencies did not run successfully.
  │ exit code: 1
  ╰─> [49 lines of output]
      Collecting setuptools
        Obtaining dependency information for setuptools from https://files.pythonhosted.org/packages/4f/ab/0bcfebdfc3bfa8554b2b2c97a555569c4c1ebc74ea288741ea8326c51906/setuptools-68.1.2-py3-none-any.whl.metadata
        Using cached setuptools-68.1.2-py3-none-any.whl.metadata (6.2 kB)
      Collecting wheel
        Obtaining dependency information for wheel from https://files.pythonhosted.org/packages/b8/8b/31273bf66016be6ad22bb7345c37ff350276cfd46e389a0c2ac5da9d9073/wheel-0.41.2-py3-none-any.whl.metadata
        Using cached wheel-0.41.2-py3-none-any.whl.metadata (2.2 kB)
      Collecting PyQt5
        Using cached PyQt5-5.15.9.tar.gz (3.2 MB)
        Installing build dependencies: started
        Installing build dependencies: finished with status 'done'
        Getting requirements to build wheel: started
        Getting requirements to build wheel: finished with status 'done'
        Preparing metadata (pyproject.toml): started
        Preparing metadata (pyproject.toml): finished with status 'error'
        error: subprocess-exited-with-error

        × Preparing metadata (pyproject.toml) did not run successfully.
        │ exit code: 1
        ╰─> [20 lines of output]
            Querying qmake about your Qt installation...
            Traceback (most recent call last):
              File "/opt/homebrew/lib/python3.11/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 353, in <module>
                main()
              File "/opt/homebrew/lib/python3.11/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 335, in main
                json_out['return_val'] = hook(**hook_input['kwargs'])
                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
              File "/opt/homebrew/lib/python3.11/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 152, in prepare_metadata_for_build_wheel
                whl_basename = backend.build_wheel(metadata_directory, config_settings)
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
              File "/opt/homebrew/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/sipbuild/api.py", line 46, in build_wheel
                project = AbstractProject.bootstrap('wheel',
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
              File "/opt/homebrew/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/sipbuild/abstract_project.py", line 87, in bootstrap
                project.setup(pyproject, tool, tool_description)
              File "/opt/homebrew/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/sipbuild/project.py", line 602, in setup
                self.update(tool)
              File "/private/var/folders/wy/0ggz_3dn51s0zpxp_5yp5l500000gn/T/pip-install-_fdz2oei/pyqt5_b3719a7cd08349648ba847a07997dd5b/project.py", line 165, in update
                raise UserException(
            sipbuild.exceptions.UserException
            [end of output]

        note: This error originates from a subprocess, and is likely not a problem with pip.
      error: metadata-generation-failed

      × Encountered error while generating package metadata.
      ╰─> See above for output.

      note: This is an issue with the package mentioned above, not pip.
      hint: See above for details.
      [end of output]

  note: This error originates from a subprocess, and is likely not a problem with pip.
error: subprocess-exited-with-error

× pip subprocess to install build dependencies did not run successfully.
│ exit code: 1
╰─> See above for output.

note: This error originates from a subprocess, and is likely not a problem with pip.

remycli

It would be nice if remycli would be a cli interface comparable to rmapi, is this in scope?

Connection attempt failed

I think I'm doing something worng. I continue to receive this message:
image

And this is the command promt:

C:\Users\User>python -m remy.gui
[I] STARTING: Mon May  8 17:11:11 2023
[I] Configuration loaded from C:\Users\User\AppData\Local\remy\remy\config.json.
[W] No key nor password given. System-wide SSH connection parameters are going to be used.
[I] Using known hosts file: C:\Users\User\AppData\Local\remy\remy\known_hosts
[I] Loaded known hosts from C:\Users\User\AppData\Local\remy\remy\known_hosts
[I] Connecting...
[E] Could not connect to 10.11.99.1: No authentication methods available
[E] RETRY? [No authentication methods available]

and here is my config file:

{
  "default_source": "default",
  "sources": {
    "default": {
      "name": "reMarkable (USB-SSH)",
      "type": "ssh",
      "host": "10.11.99.1",
      "password": "{I wrote the password}",
      "username": "root",
      "timeout": 3,
      "use_banner": "remy-banner.png"
    },
    "wifi": {
      "name": "reMarkable (RSync)",
      "type": "rsync",
      "data_dir": "/Users/bordaigorl/remy",
      "host": "remarkable",
      "key": "~/.ssh/id_rsa",
      "username": "root",
      "timeout": 3,
      "use_banner": "remy-banner.png"
    },
    "backup": {
      "name": "Latest Backup",
      "type": "local",
      "documents": "/Users/bordaigorl/rmbackup/latest",
      "templates": "/Users/bordaigorl/rmbackup/templates"
    }
  },
  "preview": {
    "eraser_mode": "accurate"
  },
  "export": {
    "default_dir": "/Users/bordaigorl/Documents",
    "open_exported": true
  }
}

what am I doing worng?

Plans for doing a full backup?

First of all, many thanks for this handy tool. I use to backup my RM1 and
to export my notes as PDF files and everything really works great.

Since I wanted to have full backups of the xochitl folder, I slightly modified the
source code, removing the asterisk in excludes.

 @@ -401,11 +401,11 @@ class LiveFileSourceRsync(LiveFileSourceSSH):
         self.templates[name]['png'] = t["filename"] + '.png'
 
   def _remote_rsync(self, path):
     return "%s@%s:'%s'" % (self.username, self.host, path)
 
-  def _bulk_download(self, fr, to, excludes=['*'], includes=[], delete=True):
+  def _bulk_download(self, fr, to, excludes=[], includes=[], delete=True):
     cmd = self.RSYNC + ['-vaz', '--prune-empty-dirs']
     if delete:
       cmd.append('--delete')
     for i in includes:
       cmd.append("--include")
@@ -413,10 +413,11 @@ class LiveFileSourceRsync(LiveFileSourceSSH):
     for e in excludes:
       cmd.append("--exclude")
       cmd.append(e)
     cmd.append(self._remote_rsync(fr + "/"))
     cmd.append(to)
+    print(cmd)
     return subprocess.run(cmd)
 
   def _file_download(self, fr, to):
     dirname = path.dirname(to)
     if not path.isdir(dirname):
@@ -448,11 +449,11 @@ class LiveFileSourceRsync(LiveFileSourceSSH):
       _includes = [ ]
     elif self.cache_mode == "light_mirror":
       _excludes = ['*.thumbnails']
       _includes = [ ]
     else:
-      _excludes = [ '*' ]
+      _excludes = []
       _includes = ['*.metadata', '*.content', '*.pagedata']
     self._bulk_download(self._remote(), self._local(), includes=_includes, excludes=_excludes)
     with os.scandir(self._local()) as entries:
       for entry in entries:
         if entry.is_file():

Perhaps one could also offer something like that as a dedicated option for the sake of users
who are less familiar with python and rsync. Just a suggestion from my side.

Can't connect after importing a PDF

Running devel branch. I imported a PDF directly into the root (maybe I wasn't supposed to, but I was just clicking around trying to figure out how this works). The upload was successful, but after doing this, I could no longer connect to the reMarkable 2:

[I] Connected to 10.0.11.5
[E] RETRY? ['NoneType' object has no attribute 'append']

I hacked around to get it to print an actual backtrace, and the error was here:

Traceback (most recent call last):
  File "/home/alex/src/remy/remy/gui/app.py", line 120, in retryInit
    raise e
  File "/home/alex/src/remy/remy/gui/app.py", line 335, in run
    index = RemarkableIndex(fsource, progress=self._progress)
  File "/home/alex/src/remy/remy/remarkable/metadata.py", line 400, in __init__
    index[parent].files.append(k)

I was able to make it "work" by doing this, but I have no idea what I'm doing lol so take this more as a hint to where the problem lies than a suggestion on how to fix it

diff --git a/remy/remarkable/metadata.py b/remy/remarkable/metadata.py
index 510f0e0..964d8af 100644
--- a/remy/remarkable/metadata.py
+++ b/remy/remarkable/metadata.py
@@ -505,7 +505,11 @@ class RemarkableIndex:
           if prop.type == FOLDER_TYPE:
             index[parent].folders.append(k)
           elif prop.type == DOCUMENT_TYPE:
-            index[parent].files.append(k)
+            try:
+                index[parent].files.append(k)
+            except AttributeError:
+              print("SKIP", str(index[parent]), str(k))
+              continue
       except KeyError as e:
         raise RemarkableDocumentError("Could not find field {0} in document {1}".format(e,k))

With this in place, everything appears to still be functional. Looks like it's created a PDFDoc entry with no parent and is trying to access its parent.

FR: delete files deleted from trash but still on disk.

Hi bordaigorl,

Could you please add a feature to delete files that's still on the disk. Logged out my remarkable account, so it's a problem now, as those files were meant to be deleted when they got synced.

Thank you for the great app.

Pencil export NOT accurate

Pencil + brush tools are NOT 'natural'. Dots are too dark and thick (not like feather-like soft touch as visually in preview or on tablet screen).

Install fails on M1 Mac - PyQT5/SIP module issue

Attempting to run pip install --user . on an M1 Macbook Pro fails with a dependency error — it attempts to install PyQT5, which requires sip, which then fails due to difficulties with installing PyQT5 on ARM. I put the stack trace below; the error appears related to this error with rmview—the suggestion there is that updating to PyQT6 that has multi-arch support is the "correct" answer, but I know that's definitely not a small task since the API changed!

I've tried a couple of the recommended workarounds (install through Homebrew, install under Rosetta) and haven't gotten anything working yet; would love to hear if anyone else has success with this.


Stack Trace:

└─> pip install --user .    
Processing /Users/jpurvis/src/external/remy
  Installing build dependencies ... error
  error: subprocess-exited-with-error
  
  × pip subprocess to install build dependencies did not run successfully.
  │ exit code: 2
  ╰─> [76 lines of output]
      Collecting setuptools
        Using cached setuptools-65.5.1-py3-none-any.whl (1.2 MB)
      Collecting wheel
        Using cached wheel-0.38.2-py3-none-any.whl (36 kB)
      Collecting PyQt5
        Using cached PyQt5-5.15.7.tar.gz (3.2 MB)
        Installing build dependencies: started
        Installing build dependencies: finished with status 'done'
        Getting requirements to build wheel: started
        Getting requirements to build wheel: finished with status 'done'
      ERROR: Exception:
      Traceback (most recent call last):
        File "/opt/homebrew/lib/python3.10/site-packages/pip/_internal/cli/base_command.py", line 160, in exc_logging_wrapper
          status = run_func(*args)
        File "/opt/homebrew/lib/python3.10/site-packages/pip/_internal/cli/req_command.py", line 247, in wrapper
          return func(self, options, args)
        File "/opt/homebrew/lib/python3.10/site-packages/pip/_internal/commands/install.py", line 400, in run
          requirement_set = resolver.resolve(
        File "/opt/homebrew/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/resolver.py", line 92, in resolve
          result = self._result = resolver.resolve(
        File "/opt/homebrew/lib/python3.10/site-packages/pip/_vendor/resolvelib/resolvers.py", line 481, in resolve
          state = resolution.resolve(requirements, max_rounds=max_rounds)
        File "/opt/homebrew/lib/python3.10/site-packages/pip/_vendor/resolvelib/resolvers.py", line 348, in resolve
          self._add_to_criteria(self.state.criteria, r, parent=None)
        File "/opt/homebrew/lib/python3.10/site-packages/pip/_vendor/resolvelib/resolvers.py", line 172, in _add_to_criteria
          if not criterion.candidates:
        File "/opt/homebrew/lib/python3.10/site-packages/pip/_vendor/resolvelib/structs.py", line 151, in __bool__
          return bool(self._sequence)
        File "/opt/homebrew/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py", line 155, in __bool__
          return any(self)
        File "/opt/homebrew/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py", line 143, in <genexpr>
          return (c for c in iterator if id(c) not in self._incompatible_ids)
        File "/opt/homebrew/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py", line 47, in _iter_built
          candidate = func()
        File "/opt/homebrew/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/factory.py", line 206, in _make_candidate_from_link
          self._link_candidate_cache[link] = LinkCandidate(
        File "/opt/homebrew/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/candidates.py", line 297, in __init__
          super().__init__(
        File "/opt/homebrew/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/candidates.py", line 162, in __init__
          self.dist = self._prepare()
        File "/opt/homebrew/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/candidates.py", line 231, in _prepare
          dist = self._prepare_distribution()
        File "/opt/homebrew/lib/python3.10/site-packages/pip/_internal/resolution/resolvelib/candidates.py", line 308, in _prepare_distribution
          return preparer.prepare_linked_requirement(self._ireq, parallel_builds=True)
        File "/opt/homebrew/lib/python3.10/site-packages/pip/_internal/operations/prepare.py", line 491, in prepare_linked_requirement
          return self._prepare_linked_requirement(req, parallel_builds)
        File "/opt/homebrew/lib/python3.10/site-packages/pip/_internal/operations/prepare.py", line 577, in _prepare_linked_requirement
          dist = _get_prepared_distribution(
        File "/opt/homebrew/lib/python3.10/site-packages/pip/_internal/operations/prepare.py", line 69, in _get_prepared_distribution
          abstract_dist.prepare_distribution_metadata(
        File "/opt/homebrew/lib/python3.10/site-packages/pip/_internal/distributions/sdist.py", line 48, in prepare_distribution_metadata
          self._install_build_reqs(finder)
        File "/opt/homebrew/lib/python3.10/site-packages/pip/_internal/distributions/sdist.py", line 118, in _install_build_reqs
          build_reqs = self._get_build_requires_wheel()
        File "/opt/homebrew/lib/python3.10/site-packages/pip/_internal/distributions/sdist.py", line 95, in _get_build_requires_wheel
          return backend.get_requires_for_build_wheel()
        File "/opt/homebrew/lib/python3.10/site-packages/pip/_internal/utils/misc.py", line 685, in get_requires_for_build_wheel
          return super().get_requires_for_build_wheel(config_settings=cs)
        File "/opt/homebrew/lib/python3.10/site-packages/pip/_vendor/pep517/wrappers.py", line 173, in get_requires_for_build_wheel
          return self._call_hook('get_requires_for_build_wheel', {
        File "/opt/homebrew/lib/python3.10/site-packages/pip/_vendor/pep517/wrappers.py", line 319, in _call_hook
          raise BackendUnavailable(data.get('traceback', ''))
      pip._vendor.pep517.wrappers.BackendUnavailable: Traceback (most recent call last):
        File "/opt/homebrew/lib/python3.10/site-packages/pip/_vendor/pep517/in_process/_in_process.py", line 77, in _build_backend
          obj = import_module(mod_path)
        File "/opt/homebrew/Cellar/[email protected]/3.10.8/Frameworks/Python.framework/Versions/3.10/lib/python3.10/importlib/__init__.py", line 126, in import_module
          return _bootstrap._gcd_import(name[level:], package, level)
        File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
        File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
        File "<frozen importlib._bootstrap>", line 992, in _find_and_load_unlocked
        File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
        File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
        File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
        File "<frozen importlib._bootstrap>", line 1004, in _find_and_load_unlocked
      ModuleNotFoundError: No module named 'sipbuild'
      
      [end of output]
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
error: subprocess-exited-with-error

× pip subprocess to install build dependencies did not run successfully.
│ exit code: 2
╰─> See above for output.

note: This error originates from a subprocess, and is likely not a problem with pip.

Version check:

└─> pip --version
pip 22.3.1 from /opt/homebrew/lib/python3.10/site-packages/pip (python 3.10)
└─> python --version
Python 3.10.8

Can't upload into root folder from context menu

I've just started using remy -- it looks great! One problem I have is that when I click "Upload Here" and choose a document, it gets uploaded not into the main folder on the remarkable, but into the alphabetically first subfolder. Is this a bug or a problem with my configuration?

Could not read configuration

Thanks for your awesome tool! I am looking forward to get it working on my remarkable.

When I start remygui.py I still get the following message:

Started
Could not read configuration from '/Users/schneider/Library/Preferences/remy.json'!

I installed all the dependencies and created the config json in /Users/schneider/Library/Preferences/remy.json with the following content:

{
  "sources": {
      "source1": {
  	"name": "reMarkable (RSync)",
  	"type": "rsync",
  	"data_dir": "/Users/schneider/Documents/remarkable/remy",
  	"address": "192.168.178.16",
  	"host": "remarkable",
  	"key": "~/.ssh/id_rsa",
  	"username": "root",
  	"timeout": 3,
  	"use_banner": "remy-banner.png"
	}
  },
  "default_source": "source1",
}

What am I doing wrong?
Thanks!

'upload' options block missing from reference config, crash if it's absent

It looks like the recent merge of the 'devel' branch added a new mandatory 'upload' configuration block. Without it, I found uploading documents via ssh caused a crash ala:

Traceback (most recent call last):                                                        
  File "/home/brettk/git/remy/remy/gui/browser/__init__.py", line 376, in _requestUpload  
    opt = QApplication.instance().config.upload                                           
  File "/home/brettk/git/remy/remy/remarkable/config.py", line 178, in upload
    return self.renderOptionsFrom('upload')                                               
  File "/home/brettk/git/remy/remy/remarkable/config.py", line 155, in renderOptionsFrom  
    opt = deepcopy(self.get(key))                                                         
  File "/home/brettk/git/remy/remy/remarkable/config.py", line 151, in get                
    raise RemyConfigException("Option '%s' not found in configuration." % opt)            

I can't find any reference document around this and the example_config.json doesn't include this block.

I was able to fix it by adding this JSON block to my configuration, and while it's sufficient to get it to work, it's unclear to me if everything in it is necessary:

    "upload": {                                                                           
        "default_options": {}                                                             
    }    

I'm happy to throw together a PR to correct these issues if I got some raw material for the settings that could go in the block and how they're used. I suspect I could also throw in some better error handling in the case where the block is absent.

Efficiency vs accuracy of rendering eraser strokes

@karlicoss asked:

I didn't quite understand from the readme (and from a brief look at pagerender.py), what's the core cause of slow erasing? Is this because without eraser drawing is relatively straightforward -- you need to draw the layers from bottom to top; whereas the eraser acts on all the layers simultaneously? Or is it because it's not a 'native' operation in QT canvas, and you have to 'subtract' the strokes?

Mainly it's because there is no native way to clip to the outline of a path.
I don't know if there is a better way, but my best guess to reproduce the eraser accurately works like this:

  1. you draw everything from bottom to top (i.e. following the order of appearance in the file)
  2. when processing an eraser stroke you have to clip everything you drew in the current layer so far
  3. the clipping needs to be wrt the complement of the outline of the strokes of the eraser, drawn as if it was a fineliner stroke. The expensive part is computing the complement of the outline: in Qt this triggers a path simplification routine which blocks everything and is very expensive on the kind of strokes produced by the remarkable.

Annoyingly:

  • you cannot just do one clip per layer
  • you cannot really avoid the simplification step
  • you could ignore the eraser strokes completely if they only intersect with some other strokes like fineliner: this is because the tablet itself already removes the strokes that intersect with the eraser from the file; but for dynamic width brushes that can be used to paint wide black areas (like paintbrush) some parts of the eraser strokes may have intersections with the painted area that cannot be reduced to removing strokes (try painting an area black and then erase a smiley from it with the various tools)
  • you cannot use Qt.transparent because it only works as expected in raster mode

As far as I know, all other renderers either:

  • ignore eraser strokes completely
  • paint white
  • only properly handle eraser in raster output

I am opening this issue in case somebody has suggestions on how to improve eraser rendering.

Include a requirements.txt file

Firstly, this is a really useful app, thank you!

However I had a few issues installing dependencies the first time because of PyPDF2 just released a new version with breaking changes (version 2.0.0)

Specifically they removed the PyPDF.pdf module. (See here)
This causes the following error:

Traceback (most recent call last):
  File "<github directory>/remygui.py", line 1, in <module>
    from remy.gui import app                               
  File "<github directory>/remy/gui/app.py", line 19, in <module>
    from remy.gui.notebookview import *
  File "<github directory>/remy/gui/notebookview/__init__.py", line 11, in <module>
    from remy.gui.notebookview.view import *
  File "<github directory>/remy/gui/notebookview/view.py", line 11, in <module>
    from remy.gui.export import exportDocument
  File "<github directory>/gui/export/__init__.py", line 8, in <module>
    from remy.remarkable.export import Exporter, CancelledExporter
  File "<github directory>/remy/remarkable/export.py", line 9, in <module>
    from PyPDF2.pdf import PageObject
ModuleNotFoundError: No module named 'PyPDF2.pdf'

With this in mind it would be really useful to include a requirements.txt with the latest supported dependencies so new users installing this for the first time can just run pip3 install -r requirements.txt and be done! This makes sure that only the compatible versions of the libraries are installed.

(For anyone coming across the same problem, installing with pip3 install PyPDF2==1.28.4 fixed this issue for me.)

Allow writing to "local source" which is externally synced

I've been using syncthing on my rM1 to keep a continuous backup of my files on my computer, and I can use reMy to view those files. I'd like to be able to use reMy to upload files to that "backup" directory, which would then get synced over to the tablet.

  1. Is there any reason not to do this? Perhaps the JSON config file should specify that a local source can be written to, to avoid the case of accidentally overwriting a backup?

  2. I'm happy to submit a PR; does this just require changes in the LocalFileSource class?

    class LocalFileSource(FileSource):

Highlights NOT transparent

Expected

Text visible under text

pkb dev bup - dPaper backup script _2_0611_2022-09-18_T16-52-02
remy Preview mode. Highlights transparent.
pkb dev bup - dPaper backup script _2_0612_2022-09-18_T16-52-10
remy Preview mode. Export settings.

Actual

Highlights overlap/foreground as solid colours. Lines/Text under highlight NOT visible.

pkb dev bup - dPaper backup script _2_0613_2022-09-18_T16-54-53
remy exported version. View on Adobe Reader.

no matching host key type found. Their offer: ssh-rsa

Hi,

I just wanted to mention that upon upgrading to Fedora 37 (OpenSSL 3.0.5 5, rsync version 3.2.7 protocol version 31)
remy stopped working for me.

The ssh part goes through just fine (it connects and can send commands to my Remarkable 1), but the rsync
part fails with the error message

Unable to negotiate with 10.11.99.1 port 22: no matching host key type found. Their offer: ssh-rsa
rsync: connection unexpectedly closed (0 bytes received so far) [Receiver]
rsync error: unexplained error (code 255) at io.c(231) [Receiver=3.2.7]
Unable to negotiate with 10.11.99.1 port 22: no matching host key type found. Their offer: ssh-rsa
rsync: connection unexpectedly closed (0 bytes received so far) [Receiver]
rsync error: unexplained error (code 255) at io.c(231) [Receiver=3.2.7]

The quick and dirty fix is to change the line

ssh_config = ['-e', '%s -o batchmode=yes' % which("ssh")]

in filesource.py to

ssh_config = ['-e', '%s -o batchmode=yes -o HostKeyAlgorithms=+ssh-rsa' % which("ssh")]

Then everything works again :)

Cheers,
Vladyslav

Painter not active

When I try to export a file I get:

QPainter::begin(): Returned false
QPainter::setWorldTransform: Painter not active
QPainter::setOpacity: Painter not active
QPainter::restore: Unbalanced save/restore
QPainter::end: Painter not active, aborted

...and many pages of the same messages repeated.

I'm on Manjaro Linux. Using the default config, just changed the source "host" and export "default_dir". The browsing UI seems to connect to the device and work well, it's just export that has a problem. The first export directory I tried had a space in it. I then tried a directory without a space. No change.

Any thoughts? Could it be missing a dependency?

default page ranges for export

It seems there is no way to set a default page range for exporting. I would like this since I usually just need to export the last few pages.

I tried adding "page_ranges": "-5:end", to the config file under "export", but it didn't work.

rsync does not work after adding new key

When the Remarkable tablet is updated, the SSH server has a new key, which requires to update the known_hosts file on the client side.

Remy offers several options, the first one being, IIUC, to add a known_hosts file in ~/.config/remy, and use that one for SSH connection.

The problem is: once that is done, my rsync based config does not work anymore, because while Remy manages to SSH to the Remarkable, the subsequent rsync does not.

If there is a way to configure rsync to use ~/.config/remy/known_hosts instead of the default one, it should be used. Otherwise, the option to automatically add the new ket should have a big red warning "this will break your rsync based configs".

No image file upload?

I thought the rM2 supported viewing JPGs and PNGs. I just tried uploading a JPG, nothing was uploaded, and checking the terminal found this error: "remy.remarkable.metadata.RemarkableError: Can only upload PDF and EPUB files, but was given a .JPG"

Preview / Export does not render writings on 3.0 beta

Hi,

first of all, thank you so much for making this nice piece of software.

Just wanted to let you know, on 3.0.1192, any documents that have been edited since on the new firmware will fail to render the writings properly. It seems anything written when on the new firmware is not displayed at all, but I'm not certain.

This is probably due to breaking changes in the reMarkable firmware (introducing infinite pages, etc).

Best,
Ben

All notebooks are blank

Hi,

I have been using ReMy since last year, but haven't touched it for quite a while xD. Just picked up my dusty Remarkable, and I noticed that all my notebooks render as blank in Remy. Other PDF books seems to be ok.

image

After I download those files with builtin downloader and open with system PDF readers, they show up as empty as well.

PyPDF2

Hi,

After recent updates, I find the program unable to bootstrap due to

File "/home/pityhero/bin/remy/remy/remarkable/export.py", line 9, in
from PyPDF2.pdf import PageObject
ModuleNotFoundError: No module named 'PyPDF2.pdf'

I have the PyPDF2 properly installed and configured, it just seems like they changed the API.

Thanks.

Private ssh key considered as invalid

I'm using a ssh key to log in to my Remarkable 2.
It seems remy has problems with this fully working ssh key which I am using daily:

Screenshot from 2022-02-18 14-44-12

my private key:
$ file /home/shamot/.ssh/id_rsa-Thinkpad
/home/shamot/.ssh/id_rsa-Thinkpad: OpenSSH private key

configuration part:
...
13 "source2": {
14 "name": "reMarkable (WiFi)",
15 "type": "ssh",
16 "host": "192.168.0.40",
17 "key": "/home/shamot/.ssh/id_rsa-Thinkpad",
18 "username": "root",
19 "timeout": 3,
20 "use_banner": "remy-banner.png"
21 }
...

GUI stopped working

Hi,

having upgraded to Fedora 35 (Python 3.10, python-poppler-qt5 21.1.0, PyQt5 5.15.6) I noticed that I cannot start the remy GUI
anymore

[I] STARTING: Sun Jan 23 14:34:26 2022

(python:338599): Gtk-WARNING **: 14:34:26.984: Theme parsing error: gtk.css:20:4: Junk at end of value for padding
[I] Configuration loaded from /home/vs/.config/remy/config.json.
[I] LOAD TIME: 0.103348
Traceback (most recent call last):
  File "/media/Data/Software/remy/remy/gui/app.py", line 213, in initialised
    self.tree = FileBrowser(index)
  File "/media/Data/Software/remy/remy/gui/browser/__init__.py", line 211, in __init__
    info = self.info = InfoPanel(index, splitter)
  File "/media/Data/Software/remy/remy/gui/browser/info.py", line 174, in __init__
    self.setEntry()
  File "/media/Data/Software/remy/remy/gui/browser/info.py", line 220, in setEntry
    self.setInfo(**self._defaults)
  File "/media/Data/Software/remy/remy/gui/browser/info.py", line 210, in setInfo
    self.setIcon(QPixmap())
  File "/media/Data/Software/remy/remy/gui/browser/info.py", line 195, in setIcon
    self.icon.setContentsMargins(0, m, 0, m)
TypeError: arguments did not match any overloaded call:
  setContentsMargins(self, int, int, int, int): argument 2 has unexpected type 'float'
  setContentsMargins(self, QMargins): argument 1 has unexpected type 'int'
/home/vs/bin/vsRemyExplore: Zeile 3: 338599 Abgebrochen             (Speicherabzug geschrieben) python /media/Data/Software/remy/remygui.py LocalBackup

I'm on the devel branch.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.