Using Rot, Oxide's command line interface

As a bit of a proof of concept, as well as to help bridge the gap with languages that don't support D-Bus easily. I wrote a simple command line application that users can use for simple scripting against the API. It abstracts away the D-Bus interfaces into a consistent interface that should be straightforward to use in shell scripting.

The program itself is only 450 or so lines long. Most of what it does is just translate the arguments passed to it into the appropriate D-Bus interfaces calls. I also made the decision to make the output be JSON so that it's fairly straight forward in most languages to work with the data. This does mean that if you intend to use it from a shell script, you'll likely need to install jq unless you plan on parsing JSON by hand.

Usage

You can find more information on the full usage of the rot command line tool here: https://oxide.eeems.codes/documentation/01_usage.html#cli-tool-rot

There are 4 basic actions that rot can do:

  1. Get the value of a property
    rot power get batteryLevel
  2. Set the value of a property.
    rot system set autoSleep 5
  3. Listen for signals.
    rot --once system leftAction
  4. Call a method.
    rot screen call screenshot

These actions can be taken against a base API, like in the previous examples, or it can be taken against an object instance. Like a screenshot, notification, application, bss, or network. When taking an action against one of these objects, you must use the --object option in your rot call. For Example:

rot --object Application:apps/d941cc3512975cd9beb7dde71108afce apps get displayName

This example will get the displayName of the xochitl application. If you notice, the path has a strange hexidecimal string in it. This is because D-Bus has some requirements around what characters are allowed in a path. So the registration name is converted into a hash to play nice with D-Bus.

Complex Example

rot screen get screenshots \
	| jq -cr 'values | join("\n")' \
	| sed 's|/codes/eeems/oxide1/||' \
	| xargs -rI {} rot --object Screenshot:{} screen call remove

This example will remove all the screenshots on the device. I'll go through each portion in detail below:

rot screen get screenshots \
	| jq -cr 'values | join("\n")'

First we get a list of all the screenshot D-Bus paths. Since it returns in JSON, we use jq to spit out all the parsed values on a newline, so that we can work with them.

	| sed 's|/codes/eeems/oxide1/||' \

Next we remove the /codes/eeems/oxide1/ part of the D-Bus path, as the --object flag expects a relative path.

	| xargs -rI {} rot --object Screenshot:{} screen call remove

Finally we loop through all of the results and call the remove method for each of them.

  • xargs handles looping through them all for us, and the -r flag will avoid an error if there are no results.
  • -I {} allows us to place the path where we want in the command.
  • --object Screenshot:{} will then expand to contain the path, and tell rot that we are working with a screenshot object.

So, how does it work?

At it's core, rot is just a basic Qt command line application. It's using the Qt library for argument parsing, D-Bus communication, and JSON serialization/deserialization.

  1. The application will build the arguments parser and start determening what the user has requested.
  2. It will connect to the Oxide D-Bus interface and request access to whatever API is being used.
  3. If --object is specified, it will setup a Qt instance of that object interface to interact with.
  4. Next it will handle whatever action was specified

Get

  1. It will attempt to load the value from the property
  2. If the property exists it will attempt to serialize it into JSON and print the result.

Set

It will attempt to set the property to the value provided

Listen

  1. It will try to find the appropriate signal to listen to based off of the name.
  2. If it finds the signal it will build a SlotHandler that handles serializing the passed in parameters into JSON and print the result
  3. If --once is specified the SlotHandler will exit after the first signal is captured.

Call

  1. It will loop through each of the arguments and attempt to deserialize them into the specified types.
  2. It will then attempt to call the method with the deserialized arguments. If the method is the system API's inhibitSleep or inhibitPowerOff methods, it will start the main Qt application thread and block until the process is signaled to exit. This ensures that the suspend or poweroff are inhibited by the call to rot
  3. It will then attempt to serialize the return value if there was one into JSON and print the result

Writing a Simple reMarkable application
Writing applications on the reMarkable is remarkably straightforward.
I recommend giving this a read as well.
Show Comments