Skip to content

Commit b661387

Browse files
authored
Merge pull request #33 from mathoudebine/feature/system-monitor
Release 2.0.0: system monitor
2 parents 8477dfd + f374841 commit b661387

File tree

97 files changed

+2818
-662
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

97 files changed

+2818
-662
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,6 @@ dmypy.json
130130

131131
# PyCharm
132132
.idea/
133+
134+
# Git mergetool backup
135+
*.orig

README.md

+42-30
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
# turing-smart-screen-python
22

3-
| Check out new version with system monitoring features! |
4-
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
5-
| Are you using your Turing Smart Screen for system monitoring? <br>If so, check out the new [**pre-release 2.0.0 beta 1 - 📊 System Monitor**](https://github.com/mathoudebine/turing-smart-screen-python/releases/tag/2.0.0-beta.1) or the `feature/system-monitoring` branch! <br><img src="res/pics/Theme3.5Inch.jpg" height="600" /> <img src="res/pics/ThemeTerminal.jpg" height="600" /> <br>It contains embedded hardware monitoring functions, theme creation from configuration files, serial port auto-detection... <br>See Release Notes to learn more about features and current limitations <br>_Python knowledges recommended._ |
6-
7-
---
8-
93
### ⚠️ DISCLAIMER - PLEASE READ ⚠️
104

115
This project is **not affiliated, associated, authorized, endorsed by, or in any way officially connected with Turing brand**, or any of its subsidiaries, affiliates, manufacturers or sellers of the Turing products. All product and company names are the registered trademarks of their original owners.
@@ -14,42 +8,60 @@ This project is an open-source alternative software, not the USBMonitor.exe orig
148

159
---
1610

17-
A simple Python manager for "Turing Smart Screen" 3.5" IPS USB-C (UART) display, also known as :
11+
A Python system monitor program and a library for "Turing Smart Screen" 3.5" IPS USB-C (UART) display, also known as :
1812
- Turing USB35INCHIPS / USB35INCHIPSV2 (revision A)
1913
- XuanFang display (revision B & flagship)
2014
- [3.5 Inch 320*480 Mini Capacitive Touch Screen IPS Module](https://www.aliexpress.com/item/1005003723773653.html)
2115

22-
## Hardware
23-
<img src="res/pics/smart-screen-3.webp" width="500"/>
16+
<img src="res/docs/smart-screen-2.webp" height="300" />
17+
18+
[**Display hardware revisions supported: A, B & flagship**](https://github.com/mathoudebine/turing-smart-screen-python/wiki/Hardware-revisions).
19+
Flagship backplate RGB LEDs are also supported!
20+
21+
Operating systems supported : macOS, Windows, Linux (incl. Raspberry Pi) and all OS that support Python 3.x
22+
23+
24+
## How to use
2425

25-
The Turing Smart Screen is a 3.5" USB-C display that shows as a serial port once connected.
26-
It cannot be seen by the operating system as a monitor but pictures can be displayed on it.
26+
### [> Follow instructions on the wiki to configure and start this project.](https://github.com/mathoudebine/turing-smart-screen-python/wiki)
2727

28-
There is 3 hardware revisions of the screen: [how to identify my version?](https://github.com/mathoudebine/turing-smart-screen-python/wiki/Hardware-revisions) Version B and "flagship" use the same protocol.
29-
A [Windows-only software is available](https://github.com/mathoudebine/turing-smart-screen-python/wiki/Vendor-apps) is provided by the vendor to manage this display.
30-
This software allows creating themes to display your computer sensors on the screen, but does not offer a simple way to display custom pictures or text.
28+
There are 2 possible uses of this project Python code:
29+
* **[as a System Monitor](#system-monitor)**, a standalone program working with themes to display your computer HW info.
30+
* **[integrated in your project](#control-the-display-from-your-python-projects)**, to control the display from your own Python code.
3131

32-
## Features
33-
This Python script can do some simple operations on the Turing display like :
32+
## System monitor
33+
34+
This project is mainly a complete standalone program to use your screen as a system monitor, like the original vendor app.
35+
Some themes are already included for a quick start!
36+
### [> Configure and start system monitor](https://github.com/mathoudebine/turing-smart-screen-python/wiki/System-monitor-:-how-to-start)
37+
* Fully functional multi-OS code base (operates out of the box, tested on Windows, Linux & MacOS).
38+
* Display configuration using `config.yaml` file: no Python code to edit.
39+
* Support for all [3 screen HW revisions: A, B & flagship](https://github.com/mathoudebine/turing-smart-screen-python/wiki/Hardware-revisions). Flagship backplate RGB LEDs are also supported!
40+
* Support [multiple hardware sensors and metrics (CPU/GPU usage, temperatures, memory, disks, etc)](https://github.com/mathoudebine/turing-smart-screen-python/wiki/System-monitor-:-themes#stats-entry) with configurable refresh intervals.
41+
* Allow [creation of themes (see `res/themes`) with `theme.yaml` files](https://github.com/mathoudebine/turing-smart-screen-python/wiki/System-monitor-:-themes) to be shared with the community!
42+
* Easy to expand: additional code that pulls specific information can be written in a modular way without impacting existing code.
43+
* Auto detect comm port. No longer need to hard set it, or if it changes on you then the config is wrong.
44+
45+
Screenshots from the latest version using included themes:
46+
<img src="res/docs/Theme3.5Inch.jpg" height="400" /> <img src="res/docs/ThemeTerminal.jpg" height="400" />
47+
48+
### [> Themes creation/edition](https://github.com/mathoudebine/turing-smart-screen-python/wiki/System-monitor-:-themes)
49+
50+
## Control the display from your Python projects
51+
52+
If you don't want to use your screen for system monitoring, you can just use this project as a module to do some simple operations on the display from any Python code :
3453
- **Display custom picture**
3554
- **Display text**
3655
- **Display progress bar**
3756
- **Screen rotation**
38-
- Clear the screen (blank) - HW version A only
39-
- Turn the screen on/off - HW version A only
40-
- Display soft reset - HW version A only
57+
- Clear the screen (blank)
58+
- Turn the screen on/off
59+
- Display soft reset
4160
- Set brightness
61+
- Set backplate RGB LEDs color (on supported hardware rev.)
62+
63+
Check `simple-program.py` as an example.
4264

43-
Operating systems supported : macOS, Windows, Linux (incl. Raspberry Pi) and all OS that support Python3.7
65+
### [> Control the display from your code](Control-screen-from-your-own-code)
4466

45-
## Getting started
46-
_Python knowledges recommended._
47-
Download this project by cloning it or using the [Releases sections](https://github.com/mathoudebine/turing-smart-screen-python/releases)
48-
Download and install the latest Python 3.x (min. 3.7) for your OS: https://www.python.org/downloads/
49-
Plug your Turing display to your computer (install the drivers if on Windows)
50-
[Identify your hardware revision (version A or version B/flagship)](https://github.com/mathoudebine/turing-smart-screen-python/wiki/Hardware-revisions)
51-
Open the `mainVersionA.py` or `mainVersionB.py` file and edit the [`COM_PORT`](https://github.com/mathoudebine/turing-smart-screen-python/blob/deb0a60b772f2c5acef377f13b959632ca649f9f/main.py#L15) variable to the port used by the display
52-
Open a terminal and run `python3 mainVersionA.py / mainVersionB.py` or `py -3 mainVersionA.py / mainVersionB.py` depending on your OS
53-
You should see animated content on your Turing display!
5467

55-
You can then edit the `mainVersionA.py / mainVersionB.py` file to change the content displayed, or use this file as a Python module for your personal Python project

config.yaml

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
config:
3+
# Configuration values to set up basic communication
4+
# Set your COM port e.g. COM3 for Windows, /dev/ttyACM0 for Linux...
5+
# COM_PORT: "/dev/ttyACM0"
6+
# COM_PORT: "COM3"
7+
COM_PORT: "AUTO"
8+
9+
# Theme to use (located in res/themes)
10+
# THEME: Terminal_theme
11+
# THEME: Landscape6Grid
12+
THEME: 3.5inchTheme2_theme
13+
14+
display:
15+
# Display resolution in portrait orientation
16+
# Do not use this setting to rotate display! Display orientation is managed by themes
17+
DISPLAY_WIDTH: 320
18+
DISPLAY_HEIGHT: 480
19+
20+
# Display Brightness
21+
# Set this as the desired %, 0 being completely dark and 100 being max brightness
22+
# Warning: screen can get very hot at high brightness!
23+
BRIGHTNESS: 20
24+
25+
# Display revision: A or B (for "flagship" version, use B)
26+
# To identify your revision: https://github.com/mathoudebine/turing-smart-screen-python/wiki/Hardware-revisions
27+
REVISION: A

library/config.py

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import os
2+
import queue
3+
import sys
4+
5+
import yaml
6+
7+
from library.log import logger
8+
9+
10+
def load_yaml(configfile):
11+
with open(configfile, "r") as stream:
12+
yamlconfig = yaml.safe_load(stream)
13+
return yamlconfig
14+
15+
16+
PATH = sys.path[0]
17+
CONFIG_DATA = load_yaml("config.yaml")
18+
19+
try:
20+
theme_path = "res/themes/" + CONFIG_DATA['config']['THEME'] + "/"
21+
logger.info("Loading theme %s from %s" % (CONFIG_DATA['config']['THEME'], theme_path + "theme.yaml"))
22+
THEME_DATA = load_yaml(theme_path + "theme.yaml")
23+
THEME_DATA['PATH'] = theme_path
24+
except:
25+
logger.error("Theme not found or contains errors!")
26+
try:
27+
sys.exit(0)
28+
except:
29+
os._exit(0)
30+
31+
# Queue containing the serial requests to send to the screen
32+
update_queue = queue.Queue()

library/display.py

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
from library import config
2+
from library.lcd_comm import Orientation
3+
from library.lcd_comm_rev_a import LcdCommRevA
4+
from library.lcd_comm_rev_b import LcdCommRevB
5+
from library.log import logger
6+
7+
THEME_DATA = config.THEME_DATA
8+
CONFIG_DATA = config.CONFIG_DATA
9+
10+
11+
def _get_full_path(path, name):
12+
if name:
13+
return path + name
14+
else:
15+
return None
16+
17+
18+
def _get_theme_orientation() -> Orientation:
19+
if THEME_DATA["display"]["DISPLAY_ORIENTATION"] == 'portrait':
20+
return Orientation.PORTRAIT
21+
elif THEME_DATA["display"]["DISPLAY_ORIENTATION"] == 'landscape':
22+
return Orientation.LANDSCAPE
23+
elif THEME_DATA["display"]["DISPLAY_ORIENTATION"] == 'reverse_portrait':
24+
return Orientation.REVERSE_PORTRAIT
25+
elif THEME_DATA["display"]["DISPLAY_ORIENTATION"] == 'reverse_landscape':
26+
return Orientation.REVERSE_LANDSCAPE
27+
else:
28+
logger.warning("Orientation '", THEME_DATA["display"]["DISPLAY_ORIENTATION"], "' unknown, using portrait")
29+
return Orientation.PORTRAIT
30+
31+
32+
class Display:
33+
def __init__(self):
34+
self.lcd = None
35+
if CONFIG_DATA["display"]["REVISION"] == "A":
36+
self.lcd = LcdCommRevA(com_port=CONFIG_DATA['config']['COM_PORT'],
37+
display_width=CONFIG_DATA["display"]["DISPLAY_WIDTH"],
38+
display_height=CONFIG_DATA["display"]["DISPLAY_HEIGHT"],
39+
update_queue=config.update_queue)
40+
elif CONFIG_DATA["display"]["REVISION"] == "B":
41+
self.lcd = LcdCommRevB(com_port=CONFIG_DATA['config']['COM_PORT'],
42+
display_width=CONFIG_DATA["display"]["DISPLAY_WIDTH"],
43+
display_height=CONFIG_DATA["display"]["DISPLAY_HEIGHT"],
44+
update_queue=config.update_queue)
45+
else:
46+
logger.error("Unknown display revision '", CONFIG_DATA["display"]["REVISION"], "'")
47+
48+
def initialize_display(self):
49+
# Reset screen in case it was in an unstable state (screen is also cleared)
50+
self.lcd.Reset()
51+
52+
# Send initialization commands
53+
self.lcd.InitializeComm()
54+
55+
# Set brightness
56+
self.lcd.SetBrightness(CONFIG_DATA["display"]["BRIGHTNESS"])
57+
58+
# Set backplate RGB LED color (for supported HW only)
59+
self.lcd.SetBackplateLedColor(THEME_DATA['display']["DISPLAY_RGB_LED"])
60+
61+
# Set orientation
62+
self.lcd.SetOrientation(_get_theme_orientation())
63+
64+
def display_static_images(self):
65+
if THEME_DATA['static_images']:
66+
for image in THEME_DATA['static_images']:
67+
logger.debug(f"Drawing Image: {image}")
68+
self.lcd.DisplayBitmap(
69+
bitmap_path=THEME_DATA['PATH'] + THEME_DATA['static_images'][image].get("PATH"),
70+
x=THEME_DATA['static_images'][image].get("X", 0),
71+
y=THEME_DATA['static_images'][image].get("Y", 0),
72+
width=THEME_DATA['static_images'][image].get("WIDTH", 0),
73+
height=THEME_DATA['static_images'][image].get("HEIGHT", 0)
74+
)
75+
76+
def display_static_text(self):
77+
if THEME_DATA['static_text']:
78+
for text in THEME_DATA['static_text']:
79+
logger.debug(f"Drawing Text: {text}")
80+
self.lcd.DisplayText(
81+
text=THEME_DATA['static_text'][text].get("TEXT"),
82+
x=THEME_DATA['static_text'][text].get("X", 0),
83+
y=THEME_DATA['static_text'][text].get("Y", 0),
84+
font=THEME_DATA['static_text'][text].get("FONT", "roboto-mono/RobotoMono-Regular.ttf"),
85+
font_size=THEME_DATA['static_text'][text].get("FONT_SIZE", 10),
86+
font_color=THEME_DATA['static_text'][text].get("FONT_COLOR", (0, 0, 0)),
87+
background_color=THEME_DATA['static_text'][text].get("BACKGROUND_COLOR", (255, 255, 255)),
88+
background_image=_get_full_path(THEME_DATA['PATH'],
89+
THEME_DATA['static_text'][text].get("BACKGROUND_IMAGE", None))
90+
)
91+
92+
93+
display = Display()

0 commit comments

Comments
 (0)