Introduction
- asterctl usage
- Linux shell control commands without using asterctl
Motivation
Developing open client software to use the embedded second screen on various Linux distributions. It might also work on Windows, but I neither have that OS, nor plan to install it.
The official proprietary AOOSTAR-X display software is not suitable for NAS and security-minded users:
- All-in-one solution that attempts to do everything, from sensor reading to running a web server for control and configuration (exposed on all interfaces!).
I prefer using existing monitoring tools and combining them to my liking. - Resource hungry, written in Python. Archive of v1.3.4 is 178 MB.
- Closed source, requires root access, distributed over filesharing sites, some without HTTPS.
- Built-in expiration date. One must regularly update the software without being able to verify the source.
- Many untranslated messages in Chinese and missing instructions for included features.
The display remains on continuously (24×7) if the official software is not running.
Goals
-
Reverse engineer the LCD serial protocol to provide open screen software.
- Utilize the official AOOSTAR-X display software by sniffing USB communication, using
strace
, and decompiling the Python app.
- Utilize the official AOOSTAR-X display software by sniffing USB communication, using
- Document known commands so clients in other programming languages can be written.
- Eventually, publish a Rust crate for easy integration into other Rust applications.
Out of scope:
- Reverse engineering the microcontroller firmware on the display board.
That would be an interesting task — potentially uncovering additional display commands — but is outside the project's current scope. - Reimplementing the full AOOSTAR-X display software, which is overly complex for most use cases.
Development
Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
License
Licensed under either of
at your option.
Installation
There are multiple ways to install the asterctl
CLI tool. Choose any one of the methods below that best suit your needs.
Please note that only Linux has been tested so far.
Pre-compiled binaries
Executable binaries are available for download on the GitHub Releases page.
Download the binary for your platform (only Linux available at the moment) and extract the archive.
The archive contains the asterctl
and aster-sysinfo
executables which you can run.
Build from source using Rust
To build the asterctl
and aster-sysinfo
executables from source, you will first need to install Rust and Cargo.
Follow the instructions on the Rust installation page.
At least Rust version 1.88 is required.
The project contains IDE settings for RustRover (or other JetBrain IDEs with the Rust plugin) to get you up and running in no time. This is not a requirement, everything can be easily built on the command line.
Once you have installed Rust, the following commands can be used to build asterclt
and all other binaries:
- On Linux, install required build dependencies (shown for Ubuntu 25.04):
sudo apt install build-essential git pkg-config libudev-dev
- Checkout project:
git clone https://github.com/zehnm/aoostar-rs.git
cd aoostar-rs
- Build
A release build is highly recommended, as it significantly improves graphic rendering performance:
cargo build --release
The binaries will be located in the ./target/release
folder.
A Debian package for easy installation is planned for the future!
See Linux systemd Service on how to automatically switch off the LCD at boot up.
Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Linux systemd Services
Switch Off LCD on Boot
The systemd unit lcd-off.service can be installed to automatically switch off the embedded LCD on boot.
The unit file has been tailored to Debian-based Linux distros and has been tested on Proxmox 8.4 and Ubuntu 25.04.
Requirements:
/dev/ttyACM0
:dialout
group with rw permissions.- To run as root: remove
DynamicUser
andGroup
settings.
- To run as root: remove
Install
As root user, otherwise sudo
is required:
cp asterctl /usr/local/bin/
cp lcd-off.service /etc/systemd/system/
systemctl daemon-reload
systemctl enable lcd-off
Security
The systemd unit file uses strong security settings to only allow operations required for asterctl
:
systemd-analyze security lcd-off.service
NAME DESCRIPTION EXPOSURE
✓ SystemCallFilter=~@swap System call allow list defined for service, and @swap is not included
✓ SystemCallFilter=~@resources System call allow list defined for service, and @resources is not included
✓ SystemCallFilter=~@reboot System call allow list defined for service, and @reboot is not included
✓ SystemCallFilter=~@raw-io System call allow list defined for service, and @raw-io is not included
✓ SystemCallFilter=~@privileged System call allow list defined for service, and @privileged is not included
✓ SystemCallFilter=~@obsolete System call allow list defined for service, and @obsolete is not included
✓ SystemCallFilter=~@mount System call allow list defined for service, and @mount is not included
✓ SystemCallFilter=~@module System call allow list defined for service, and @module is not included
✓ SystemCallFilter=~@debug System call allow list defined for service, and @debug is not included
✓ SystemCallFilter=~@cpu-emulation System call allow list defined for service, and @cpu-emulation is not included
✓ SystemCallFilter=~@clock System call allow list defined for service, and @clock is not included
✓ RemoveIPC= Service user cannot leave SysV IPC objects around
✗ RootDirectory=/RootImage= Service runs within the host's root directory 0.1
✓ User=/DynamicUser= Service runs under a transient non-root user identity
✓ RestrictRealtime= Service realtime scheduling access is restricted
✓ CapabilityBoundingSet=~CAP_SYS_TIME Service processes cannot change the system clock
✓ NoNewPrivileges= Service processes cannot acquire new privileges
✓ AmbientCapabilities= Service process does not receive ambient capabilities
✗ PrivateDevices= Service potentially has access to hardware devices 0.2
✓ CapabilityBoundingSet=~CAP_BPF Service may not load BPF programs
✗ SystemCallArchitectures= Service may execute system calls with all ABIs 0.2
✓ ProtectSystem= Service has strict read-only access to the OS file hierarchy
✓ ProtectProc= Service has restricted access to process tree (/proc hidepid=)
✓ SupplementaryGroups= Service has no supplementary groups
✓ CapabilityBoundingSet=~CAP_SYS_RAWIO Service has no raw I/O access
✓ CapabilityBoundingSet=~CAP_SYS_PTRACE Service has no ptrace() debugging abilities
✓ CapabilityBoundingSet=~CAP_SYS_(NICE|RESOURCE) Service has no privileges to change resource use parameters
✓ CapabilityBoundingSet=~CAP_NET_ADMIN Service has no network configuration privileges
✓ CapabilityBoundingSet=~CAP_NET_(BIND_SERVICE|BROADCAST|RAW) Service has no elevated networking privileges
✗ DeviceAllow= Service has no device ACL 0.2
✓ CapabilityBoundingSet=~CAP_AUDIT_* Service has no audit subsystem access
✓ CapabilityBoundingSet=~CAP_SYS_ADMIN Service has no administrator privileges
✓ PrivateNetwork= Service has no access to the host's network
✓ PrivateTmp= Service has no access to other software's temporary files
✓ ProcSubset= Service has no access to non-process /proc files (/proc subset=)
✓ CapabilityBoundingSet=~CAP_SYSLOG Service has no access to kernel logging
✓ ProtectHome= Service has no access to home directories
✓ KeyringMode= Service doesn't share key material with other services
✓ Delegate= Service does not maintain its own delegated control group subtree
✓ PrivateUsers= Service does not have access to other users
✗ IPAddressDeny= Service does not define an IP address allow list 0.2
✓ NotifyAccess= Service child processes cannot alter service state
✓ ProtectClock= Service cannot write to the hardware clock or system clock
✓ CapabilityBoundingSet=~CAP_SYS_PACCT Service cannot use acct()
✓ CapabilityBoundingSet=~CAP_KILL Service cannot send UNIX signals to arbitrary processes
✓ ProtectKernelLogs= Service cannot read from or write to the kernel log ring buffer
✓ CapabilityBoundingSet=~CAP_WAKE_ALARM Service cannot program timers that wake up the system
✓ CapabilityBoundingSet=~CAP_(DAC_*|FOWNER|IPC_OWNER) Service cannot override UNIX file/IPC permission checks
✓ ProtectControlGroups= Service cannot modify the control group file system
✓ CapabilityBoundingSet=~CAP_LINUX_IMMUTABLE Service cannot mark files immutable
✓ CapabilityBoundingSet=~CAP_IPC_LOCK Service cannot lock memory into RAM
✓ ProtectKernelModules= Service cannot load or read kernel modules
✓ CapabilityBoundingSet=~CAP_SYS_MODULE Service cannot load kernel modules
✓ CapabilityBoundingSet=~CAP_SYS_TTY_CONFIG Service cannot issue vhangup()
✓ CapabilityBoundingSet=~CAP_SYS_BOOT Service cannot issue reboot()
✓ CapabilityBoundingSet=~CAP_SYS_CHROOT Service cannot issue chroot()
✓ PrivateMounts= Service cannot install system mounts
✓ CapabilityBoundingSet=~CAP_BLOCK_SUSPEND Service cannot establish wake locks
✓ MemoryDenyWriteExecute= Service cannot create writable executable memory mappings
✓ RestrictNamespaces=~user Service cannot create user namespaces
✓ RestrictNamespaces=~pid Service cannot create process namespaces
✓ RestrictNamespaces=~net Service cannot create network namespaces
✓ RestrictNamespaces=~uts Service cannot create hostname namespaces
✓ RestrictNamespaces=~mnt Service cannot create file system namespaces
✓ CapabilityBoundingSet=~CAP_LEASE Service cannot create file leases
✓ CapabilityBoundingSet=~CAP_MKNOD Service cannot create device nodes
✓ RestrictNamespaces=~cgroup Service cannot create cgroup namespaces
✓ RestrictNamespaces=~ipc Service cannot create IPC namespaces
✓ ProtectHostname= Service cannot change system host/domainname
✓ CapabilityBoundingSet=~CAP_(CHOWN|FSETID|SETFCAP) Service cannot change file ownership/access mode/capabilities
✓ CapabilityBoundingSet=~CAP_SET(UID|GID|PCAP) Service cannot change UID/GID identities/capabilities
✓ LockPersonality= Service cannot change ABI personality
✓ ProtectKernelTunables= Service cannot alter kernel tunables (/proc/sys, …)
✓ RestrictAddressFamilies=~AF_PACKET Service cannot allocate packet sockets
✓ RestrictAddressFamilies=~AF_NETLINK Service cannot allocate netlink sockets
✓ RestrictAddressFamilies=~AF_UNIX Service cannot allocate local sockets
✓ RestrictAddressFamilies=~… Service cannot allocate exotic sockets
✓ RestrictAddressFamilies=~AF_(INET|INET6) Service cannot allocate Internet sockets
✓ CapabilityBoundingSet=~CAP_MAC_* Service cannot adjust SMACK MAC
✓ RestrictSUIDSGID= SUID/SGID file creation by service is restricted
✓ UMask= Files created by service are accessible only by service's own user by default
→ Overall exposure level for lcd-off.service: 0.8 SAFE 😀
asterctl Daemon
TODO
aster-sysinfo Daemon
‼️ Work in progress. This also requires the asterctl
daemon running.
The systemd unit aster-sysinfo.service
can be installed to automatically collect system sensor information for asterctl
.
Install
As root user, otherwise sudo
is required:
cp aster-sysinfo /usr/local/bin/
cp aster-sysinfo.service /etc/systemd/system/
systemctl daemon-reload
systemctl enable aster-sysinfo
asterctl Documentation
Aster: Greek for star and similar to AOOSTAR.
A work-in-progress "panel-mode" mimics the AOOSTAR-X software and uses the same configuration files for rendering sensor panels with dynamic sensor values.
By default, the original LCD USB UART device 416:90A1
is used. See optional parameters to specify a different device.
./asterctl --help
AOOSTAR WTR MAX and GEM12+ PRO screen control
Usage: asterctl [OPTIONS]
Options:
-d, --device <DEVICE>
Serial device, for example "/dev/cu.usbserial-AB0KOHLS".
Takes priority over --usb option
-u, --usb <USB>
USB serial UART "vid:pid" in hex notation (lsusb output). Default: 416:90A1
--on
Switch display on and exit. This will show the last displayed image
--off
Switch display off and exit
-i, --image <IMAGE>
Image to display, other sizes than 960x376 will be scaled
-c, --config <CONFIG>
AOOSTAR-X json configuration file to parse.
The configuration file will be loaded from the `config_dir` directory
if no full path is specified.
-p, --panels <PANELS>
Include one or more additional custom panels into the base configuration.
Specify the path to the panel directory containing panel.json and fonts /
img subdirectories.
--config-dir <CONFIG_DIR>
Configuration directory containing configuration files and background
images specified in the `config` file. Default: `./cfg`
--font-dir <FONT_DIR>
Font directory for fonts specified in the `config` file. Default: `./fonts`
--sensor-path <SENSOR_PATH>
Single sensor value input file or directory for multiple sensor input files.
Default: `./cfg/sensors`
-o, --off-after <OFF_AFTER>
Switch off display n seconds after loading image or running demo
-w, --write-only
Test mode: only write to the display without checking response
-s, --save
Test mode: save changed images in ./out folder
--simulate
Simulate serial port for testing and development,
`--device` and `--usb` options are ignored
-h, --help
Print help (see a summary with '-h')
-V, --version
Print version
Sensor Panel Mode
asterctl --config monitor.json
Control Commands
The following control commands are available to switch the display off or display a static image.
Switch display on:
asterctl --on
This will display the last image that was shown before the display was switched off.
This image is stored in the display firmware and not sent by asterctl
.
Switch display off:
asterctl --off
Switching the display off is also possible with pure shell commands.
Display an image:
asterctl --image img/aybabtu.png
This expects a 960 × 376 image (other sizes are automatically scaled and the aspect ratio is ignored). See Rust image crate for supported image formats.
Demo app
cargo run --release --bin demo -- --config monitor.json
The --config
parameter is optional. It loads the official configuration file and displays the defined sensors in the
first panel.
Parameters
--device /dev/ttyACM0
— Specify the serial device.--usb 0403:6001
— Specify the USB UART device by USB VID:PID (hexadecimal, as shown bylsusb
).--help
— Show all options.
Linux Shell Control Commands
Turning the display on or off is possible directly in a Linux shell!
Add your user to the dialout
group for access to /dev/ttyACM0
:
sudo usermod -a -G dialout $USER
You may have to log out and back in for group changes to take effect.
If not using a Debian based Linux, the tty device might have a different name, or not using thedialout
group.
Turn display on
stty -F /dev/ttyACM0 raw
printf "\252U\252U\v\0\0\0" > /dev/ttyACM0
Turn display off
stty -F /dev/ttyACM0 raw
printf "\252U\252U\12\0\0\0" > /dev/ttyACM0
Sensor Panels
The asterctl
tool is started in sensor panel mode if the --config
command line option is specified.
Sensor panels are dynamic screens showing various sensor values. Multiple rotating panels are supported.
The sensor values must be provided in simple key-value text files from external scripts or tools. The asterctl
tool
is only responsible for rendering the panels on the embedded screen.
Example panels from the AOOSTAR-X software, rendered with asterctl
using dummy sensor values:


See custom sensor panels for including custom panels.
Supported Features
- One or multiple panels rotating in configurable interval (configuration value
setup.switchTime
). - Each panel can be configured with multiple sensor fields.
- Text sensor value fields are supported (
sensor.mode: 1
), but there are still some text size and positioning issues. - Fan (2), progress (3) and pointer (4) sensor modes are being worked on and not all configuration options are working yet.
- Text sensor value fields are supported (
- Each sensor field can be customized with an individual font, size, color and text alignment.
- Panels are redrawn at a configurable interval (configuration value
setup.refresh
).- Only the updated areas of the image are sent to the display for faster updates.
See Sensor Configuration for more information.
Custom Panels
By default, the defined panels in the main configuration file are loaded and rendered.
Additional custom panels can be included with the --panels
command line parameter.
A custom panel consists of:
- a
panel.json
file with just the json object of thediy
array of the main configuration file. img
subdirectory containing the referenced images inpanel.json
fonts
subdirectory containing the referenced fonts inpanel.json
Example:
.
├── fonts
│ ├── HarmonyOS_Sans_SC_Bold.ttf
│ └── ROGFontsv.ttf
├── img
│ ├── 6ae90fde-d0a1-44ec-9e15-7b6af14e3b7b.jpg
│ ├── 95f38f70-9e0c-4b54-80a9-6bd7b0b4475c_1744449208_1746941971.png
│ ├── f1c3d74c-0157-4b77-82a6-f07e565fe439_1744447224_1746941971.png
│ └── f5d534e5-4527-4ca0-a0e9-69e8eef86f62_1744447151_1746941971.png
└── panel.json
There are lots of custom panel configurations available online.
AOOSTAR support sent the following link: http://pan.sztbkj.com:5244/, look for a file called 有线网卡 windows驱动.rar
in the WTR MAX 6+5盘位/驱动/
subfolder.
Example:
asterctl --config monitor.json --panels cfg/01_custom --panels cfg/02_custom
Sensor Configuration
Specify configuration file to use:
asterctl --config monitor.json
- The configuration file is loaded from the configuration directory if not an absolute path is specified.
- The default configuration directory is
./cfg
and can be changed with the--config-dir
command line option.
The original AOOSTAR-X json configuration file format is used, but only a subset of the configuration is supported:
- Setup object fields:
switchTime
: Optional switch time between panels in seconds, string value interpreted as float and converted to milliseconds. Default: 5refresh
: Panel redraw interval in seconds specified as a float number. Default: 1
- Panel object fields in
diy[]
:img
: Background image filename. Loaded from the specified configuration directory if not an absolute path is specified.sensor
: Array of sensor objects.
- Sensor object fields:
label
: label identifier, also used as sensor value data source identifierintegerDigits
: sensor value format option: number of integer places. Value is 0-prefixed to number of places and set to99
if overflown.decimalDigits
: sensor value format option: number of decimal places.unit
: optional unit label, appended after the sensor valuex
: x-positiony
: y-positionfontFamily
: Font name matching font filename without file extension. Fonts are loaded from the configured font directory.fontSize
: Font sizefontColor
: Font color in#RRGGBB
notation, or-1
if not set. Examples:#ffffff
= white,#ff0000
= red. Default:#ffffff
textAlign
: Text alignment:left
,right
,center
- Fields used for the fan (2), progress (3) and pointer (4) sensor modes:
min_value
andmax_value
width
andheight
direction
pic
: progress image, loaded from the specified configuration directory if not an absolute path is specified.min_angle
andmax_angle
xz_x
andxz_y
Example configuration file: cfg/monitor.json.
Sensor values are not read from the configuration file (the sensor.value
field is ignored).
See Sensor Value Provider.
More options might be supported later.
Sensor Mode 1 Text
A text sensor renders a text label with a sensor value and an optional unit text on the panel. The value can be formatted as a fixed point decimal number or as an integer.
Text sensor configuration fields:
mode
: 1 (for text)label
: label identifier, also used as sensor value data source identifierdirection
: 1 = left to right, 2 = right to left, 3 = top to bottom, 4 = bottom to toplabel
: data source id to retrieve the current value fromunit
: optional unit label, appended after the sensor valuex
,y
: position on the panelfontFamily
: Font name matching font filename without file extension.- Fonts are loaded from the configured font directory, or from the custom panel's
fonts
directory. - An absolute file path can also be used.
- Fonts are loaded from the configured font directory, or from the custom panel's
fontSize
: Font sizefontColor
: Font color in#RRGGBB
notation, or-1
if not set.- Examples:
#ffffff
= white,#ff0000
= red. Default:#ffffff
- Examples:
textAlign
: Text alignment:left
,center
,right
integerDigits
: number of integer digits: -1 or missing field = all digits, > 0 prefix with0
and set to9
if overflowndecimalDigits
: number fixed point digits: -1 = auto, 0 = integer number without decimal digits, > 0 fixed number of decimal digits
Value Formatting
The sensor value can be formatted with the unit
and integerDigits
& decimalDigits
options.
- The unit value is simply appended to the value, without whitespace.
- Example formatting for the value
123.456
withintegerDigits
&decimalDigits
:
integer | decimal | output |
---|---|---|
5 | 2 | 00123.46 |
5 | 1 | 00123.5 |
5 | 0 | 00123 |
-1 | 2 | 123.46 |
-1 | 1 | 123.5 |
-1 | 0 | 123 |
2 | 0 | 99 |
Example
Example panel.json
with two "text" indicator sensors and the following (partial) background image in img
:

The background image and sensor definitions are taken from the default system panel configuration in the AOOSTAR-X app.
{
"name": "Text test panel",
"img": "background.png",
"sensor": [
{
"mode": 1,
"name": "CPU temp",
"label": "cpu_temperature",
"x": 195,
"y": 110,
"value": "65",
"fontFamily": "HarmonyOS_Sans_SC_Bold",
"fontSize": 120,
"fontColor": -1,
"textAlign": "center",
"decimalDigits": 0
},
{
"mode": 1,
"name": "CPU usage",
"label": "cpu_percent",
"unit": "%",
"x": 200,
"y": 285,
"value": "47.4",
"fontFamily": "HarmonyOS_Sans_SC_Bold",
"fontSize": 60,
"fontColor": -1,
"textAlign": "center",
"decimalDigits": 0
}
]
}
The following graphic is rendered for the two text fields defined above:

Known Issues
Text sensor formatting has been reverse engineered from the AOOSTAR-X app. Not all options are supported
- Text position and font size calculation doesn't always match AOOSTAR-X.
- Needs investigation if value is in pixel or points.
- Might also need dpi adjustments.
fontWeight
not yet supported.
Sensor Mode 2 Circular Progress
A circular progress sensor (known as fan
in the AOOSTAR-X software) masks a progress bar image for a certain angular
range based on the corresponding sensor value. The masked image is alpha-blended with the panel image.
Sensor configuration fields:
mode
: 2 (for fan)direction
: 1 = clockwise, 2 = counter-clockwiselabel
: label identifier, also used as sensor value data source identifierx
,y
: position on the panelwidth
,height
: size of the circular progress element (not yet used)pic
: circular progress image to overlay. Should matchwidth
,height
minAngle
,maxAngle
: range of the masked imageminValue
,maxValue
: clamp sensor value to this rangexz_x
,xz_y
Example
The following configuration and graphics are taken from the 仪表盘_windows
panel configuration in 有线网卡 windows驱动.rar
.
Example panel.json
with a single "fan" indicator sensor and the following (partial) background image in img
:

{
"name": "Fan test panel",
"img": "background.jpg",
"sensor": [
{
"id": "29d9ef2d-30b4-459d-b2b0-43cb6d4d6b41",
"itemName": "CPU usage",
"mode": 2,
"direction": 1,
"label": "cpu_percent",
"value": "47.7",
"x": 168,
"y": 184,
"width": 237,
"height": 237,
"minAngle": -160,
"maxAngle": 30,
"minValue": 0,
"maxValue": 80,
"xz_x": 0,
"xz_y": 0,
"pic": "progress_circle.png"
}
]
}
Progress image "pic": "progress_circle.png"
:
The following graphic is rendered for progress example above:

Known Issues
Fan sensor rendering has been reverse engineered from the AOOSTAR-X app. Not all options are supported.
- Work in progress, not yet fully tested
direction: 2
doesn't seem to workwidht
,height
should be considered and auto-resized as for mode 4
Sensor Mode 3 Progress
A progress sensor crops a progress image based on the corresponding sensor value and alpha-blends it with the panel image.
Sensor configuration fields:
mode
: 3 (for progress)label
: label identifier, also used as sensor value data source identifierdirection
: 1 = left to right, 2 = right to left, 3 = top to bottom, 4 = bottom to topx
,y
: position on the panelpic
: progress image to crop and overlayminValue
,maxValue
: clamp sensor value to this range
Example
Example panel.json
with two "progress" indicator sensor and the following (partial) background image in img
:

The background image and sensor definitions are taken from the default system panel configuration in the AOOSTAR-X app.
{
"name": "Progress test panel",
"img": "background.png",
"sensor": [
{
"mode": 3,
"name": "SSD 4 usage",
"label": "storage_ssd4_usage",
"x": 400,
"y": 45,
"direction": 1,
"value": "35",
"minValue": 0,
"maxValue": 100,
"pic": "progress.png"
},
{
"mode": 3,
"name": "SSD 5 usage",
"label": "storage_ssd5_usage",
"x": 400,
"y": 106,
"direction": 1,
"value": "80",
"minValue": 0,
"maxValue": 100,
"pic": "progress.png"
},
{
"mode": 1,
"name": "SSD 4 temp",
"label": "storage_ssd4_temperature",
"x": 580,
"y": 70,
"direction": 1,
"value": "34",
"fontFamily": "HarmonyOS_Sans_SC_Bold",
"fontSize": 24,
"textAlign": "center",
"integerDigits": -1,
"decimalDigits": 0,
"unit": " ℃"
},
{
"mode": 1,
"name": "SSD 5 temp",
"label": "storage_ssd5_temperature",
"x": 580,
"y": 130,
"direction": 1,
"value": "35",
"fontFamily": "HarmonyOS_Sans_SC_Bold",
"fontSize": 24,
"textAlign": "center",
"integerDigits": -1,
"decimalDigits": 0,
"unit": " ℃"
}
]
}
Progress image "pic": "progress.png"
:
The following graphic is rendered for progress example above:

Known Issues
Progress sensor rendering has been reverse engineered from the AOOSTAR-X app. Not all options are supported.
- Work in progress, not yet fully tested
widht
,height
should be considered and auto-resized as for mode 4
Sensor Mode 4 Pointer
A pointer sensor rotates an image at a certain angle calculated from the current sensor value and alpha-blends it with the panel image.
Sensor configuration fields:
mode
: 4 (for pointer)direction
: 1 = clockwise, 2 = counter-clockwiselabel
: label identifier, also used as sensor value data source identifierx
,y
: position on the panelwidth
,height
: size of the pointerpic
: pointer image to overlay. Should matchwidth
,height
, otherwise it will be resizedminAngle
,maxAngle
: range of the rotated imageminValue
,maxValue
: scaling range to apply on the value forminAngle
..maxAngle
(to be verified)xz_x
,xz_y
Example
The following configuration and graphics are taken from the 三环_windows
panel configuration in 有线网卡 windows驱动.rar
.
Example panel.json
with a single "pointer" indicator sensor and the following (partial) background image in img
:

{
"name": "Pointer test panel",
"img": "background.jpg",
"sensor": [
{
"id": "a9d4acac-2af9-4fe0-9f69-86cd09f25696",
"itemName": "CPU dial",
"mode": 4,
"direction": 1,
"label": "cpu_percent",
"value": "47.7",
"x": 160,
"y": 208,
"width": 302,
"height": 302,
"minAngle": -110,
"maxAngle": 110,
"minValue": 0,
"maxValue": 90,
"xz_x": 0,
"xz_y": 0,
"pic": "pointer.png"
}
]
}
Pointer image "pic": "pointer.png"
:
The following graphic is rendered for a sensor value of 47.7
:

Known Issues
Pointer sensor rendering has been reverse engineered from the AOOSTAR-X app. Not all options are supported.
- Work in progress, not yet fully tested
Sensor Value Provider
Text File Data Source
- Text file with ending:
.txt
- Simple key / value pairs, separated by a colon
:
. Example:foo: bar
- Line based: one key / value per line.
- Key and value are trimmed. Any whitespace will be removed.
- Empty lines and comments are ignored.
- Comments start with
#
at the beginning of the line. - Support for special keys: if key ends with
#unit
then the value is the unit for the corresponding key before the suffix- Example:
net_download_speed#unit: M/S
is the unit value fornet_download_speed
. - This can be used for dynamic unit values if they sensor value provider cannot add the unit to the corresponding value.
- Example:
- File contents will automatically be read when updated.
- This requires the sensor value provider to use atomic file updates!
- Best practice is to use a temporary file on the same filesystem and use a move or rename operation after all values have been written.
- One or multiple sensor text files are supported.
- Either a single file can be specified, or a directory path.
- If a directory is specified, all children matching the sensor file naming pattern will be read and monitored.
- Any subdirectories are ignored (no recursive support).
Example text file for the cfg/monitor.json panel configuration:
cpu_temperature: 65
cpu_percent: 98
memory_usage: 77
memory_Temperature: 48
net_ip_address: 146.56.182.244
gpu_core: 98
gpu_temperature: 78
net_upload_speed: 100
net_upload_speed#unit: K/S
net_download_speed: 120
net_download_speed#unit: M/S
motherboard_temperature: 38
storage_ssd[0]['temperature']: 31
storage_ssd[0]['used']: 17
storage_ssd[1]['temperature']: 32
storage_ssd[1]['used']: 27
storage_ssd[2]['temperature']: 33
storage_ssd[2]['used']: 37
storage_ssd[3]['temperature']: 34
storage_ssd[3]['used']: 47
storage_ssd[4]['temperature']: 35
storage_ssd[4]['used']: 57
storage_hdd[0]['temperature']: 36
storage_hdd[0]['used']: 17
storage_hdd[1]['temperature']: 37
storage_hdd[1]['used']: 27
storage_hdd[2]['temperature']: 38
storage_hdd[2]['used']: 37
storage_hdd[3]['temperature']: 39
storage_hdd[3]['used']: 47
storage_hdd[4]['temperature']: 40
storage_hdd[4]['used']: 57
storage_hdd[5]['temperature']: 10
storage_hdd[5]['used']: 67
Sensor Data Provider Shell Scripts
The /linux/scripts directory contains some proof-of-concept Linux shell scripts.
CPU and memory usage are written into a sensor data source text file that can be used by asterctl
.
./cpu_usage.sh -h
Simple PoC script to periodically write the CPU usage into a sensor text file.
Usage:
./cpu_usage.sh [-r REFRESH] [-s SENSOR_FILE] [-t TEMP_DIR]
-r REFRESH refresh in seconds. Default: 1
-s SENSOR_FILE output sensor file. Default: /tmp/sensors/cpu.txt
-t TEMP_DIR temporary directory. Default: /tmp
./mem_usage.sh -h
Simple PoC script to periodically write the memory usage into a sensor text file.
Usage:
./mem_usage.sh [-r REFRESH] [-s SENSOR_FILE] [-t TEMP_DIR]
-r REFRESH refresh in seconds. Default: 5
-s SENSOR_FILE output sensor file. Default: /tmp/sensors/mem.txt
-t TEMP_DIR temporary directory. Default: /tmp
aster-sysinfo Tool
The Rust based aster-sysinfo tool gathers many more system sensor values with the help of the sysinfo crate.
It supports FreeBSD, Linux, macOS, Windows and other OSes, but it has only been tested on Linux so far.
Proof of concept sensor value collection for the asterctl screen control tool
Usage: aster-sysinfo [OPTIONS]
Options:
-o, --out <OUT>
Output sensor file
-t, --temp-dir <TEMP_DIR>
Temporary directory for preparing the output sensor file.
The system temp directory is used if not specified.
The temp directory must be on the same file system for atomic rename
operation!
--console
Print values in console
-r, --refresh <REFRESH>
System sensor refresh interval in seconds
--disk-refresh <DISK_REFRESH>
Enable individual disk refresh logic as used in AOOSTAR-X.
Refresh interval in seconds
--smartctl
Retrieve drive temperature if `disk-update` option is enabled.
Requires smartctl and password-less sudo!
Single test run with printing all sensors in the console:
aster-sysinfo --console
Normal mode providing sensor values for asterctl
in /tmp/sensors/sysinfo.txt
every 3 seconds:
aster-sysinfo --refresh 3 --out /tmp/sensors/aster-sysinfo.txt
Note: the lower the refresh rate, the more resources are used!
LCD Protocol
This page contains the current state of the reverse engineered AOOSTAR display protocol.
See Linux shell commands how you can switch the display on and off with standard Linux commands.
- Resolution: 960 × 376
- Manufacturer: Synwit
- Connected over USB UART with a proprietary serial communication protocol:
- USB device ID:
416:90A1
(as shown bylsusb
) - Linux device (example on Debian):
/dev/ttyACM0
- 1,500,000 baud, 8N1 (likely ignored; actual USB transfer speed is much higher)
- USB device ID:
Display Off
Request:

@startebnf lcd_off
lcd_off = 0xAA, 0x55, 0xAA, 0x55, 0x0A, 0x00, 0x00, 0x00 ;
@endebnf
Response:
- Success: character
A
- Error: unknown
Display On
Request:

@startebnf lcd_on
lcd_on = 0xAA, 0x55, 0xAA, 0x55, 0x0B, 0x00, 0x00, 0x00 ;
@endebnf
Response:
- Success: character
A
- Error: unknown
Note:
- When switching the display on, the last displayed image is immediately shown.
Display Image
Request:

@startebnf send_image
send_image = img_cmd_start, { data_chunk }, img_cmd_end ;
img_cmd_start = 0xAA, 0x55, 0xAA, 0x55, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0F, 0x2F, 0x00, 0x04, 0x0B, 0x00 ;
data_chunk = chunk_header, chunk_offset, rgb565_chunk ;
chunk_header = 0xAA, 0x55, 0xAA, 0x55, 0x08, 0x00, 0x00, 0x00 ;
chunk_offset = ? 32 bit offset in little-endian format ? ;
rgb565_chunk = 47 * ? byte image data in RGB565 format from given index ?;
img_cmd_end = 0xAA, 0x55, 0xAA, 0x55, 0x06, 0x00, 0x00, 0x00 ;
@endebnf
Response:
- Success: character
A
- Error: unknown
Notes:
- When sending an image to the screen, the image must be in RGB565 format (16 bits per pixel).
asterctl
performs all graphic operations on an RGB888 image buffer.asterctl
automatically converts the image to RGB565 when sending it to the display.
- The 1.5 Mbps baud rate set in the client is ignored, as actual USB bulk transfer achieves much higher throughput.
For reference, at the nominal serial rate (~1,500,000 baud), it would take approximately 6 seconds to transfer a full image of 721,920 bytes (960 × 376 × 2):
- Display protocol: payload per chunk = 47 bytes; header per chunk = 12 bytes
- Number of chunks: 721,920 / 47 ≈ 15,360 chunks
- Total transmitted data: 15,360 chunks × 59 bytes/chunk = 906,240 bytes
- Serial frame format: 1 start bit + 8 data bits + 1 stop bit = 10 bits/byte
- Effective byte rate: 1,500,000 bits/sec / 10 bits/byte = 150,000 bytes/sec
- Transfer time: 906,240 bytes / 150,000 bytes/sec ≈ 6 seconds
- Performance:
- Displaying the first fullscreen image takes around 1.3 seconds.
- Once the new image is fully transferred and the end-header command is sent, the display firmware switches to the new image.
- Partial Updates:
asterctl
uses a frame cache to send only changed chunks after the initial image is displayed, greatly speeding up partial screen updates.- The chunk size is 47 bytes, determined from the original app. It is unknown if other chunk sizes are supported.
- There are no fractional chunks: 960x376 x 2 bytes/pixel / 47 bytes/chunk = 15360 chunks