Skip to content

Commit a7dd870

Browse files
authored
Merge pull request #3 from mathoudebine/feature/progress-bar
Feature: add progress bar support
2 parents 216fc47 + 2377d2c commit a7dd870

File tree

2 files changed

+72
-15
lines changed

2 files changed

+72
-15
lines changed

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,14 @@ Operating systems supported : macOS, Windows, Linux (incl. Raspberry Pi) and all
1111
This is a 3.5" USB-C display that shows as a serial port once connected.
1212
It cannot be seen by the operating system as a monitor but picture can be displayed on it.
1313

14-
A Windows-only software is [available here](https://translate.google.com/translate?sl=auto&u=https://gitee.com/emperg/usblcd/raw/master/dev0/realse.ini) to manage this display.
14+
A Windows-only software is [available in Chinese](https://lgb123-1253504678.cos.ap-beijing.myqcloud.com/35inch.rar) or [in English](https://lgb123-1253504678.cos.ap-beijing.myqcloud.com/35inchENG.rar) to manage this display.
1515
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.
1616

1717
This Python script has been created to do some simple operations on this display like :
1818
- **Display custom picture**
1919
- **Display text**
20+
- **Display progress bar**
2021
- Clear the screen (blank)
2122
- Turn the screen on/off
2223
- Display soft reset
2324
- Set brightness
24-
25-

main.py

Lines changed: 70 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class Command:
2828
DISPLAY_BITMAP = 197
2929

3030

31-
def SendReg(ser, cmd, x, y, ex, ey):
31+
def SendReg(ser: serial.Serial, cmd: int, x: int, y: int, ex: int, ey: int):
3232
byteBuffer = bytearray(6)
3333
byteBuffer[0] = (x >> 2)
3434
byteBuffer[1] = (((x & 3) << 6) + (y >> 4))
@@ -39,31 +39,35 @@ def SendReg(ser, cmd, x, y, ex, ey):
3939
ser.write(bytes(byteBuffer))
4040

4141

42-
def Reset(ser):
42+
def Reset(ser: serial.Serial):
4343
SendReg(ser, Command.RESET, 0, 0, 0, 0)
4444

4545

46-
def Clear(ser):
46+
def Clear(ser: serial.Serial):
4747
SendReg(ser, Command.CLEAR, 0, 0, 0, 0)
4848

4949

50-
def ScreenOff(ser):
50+
def ScreenOff(ser: serial.Serial):
5151
SendReg(ser, Command.SCREEN_OFF, 0, 0, 0, 0)
5252

5353

54-
def ScreenOn(ser):
54+
def ScreenOn(ser: serial.Serial):
5555
SendReg(ser, Command.SCREEN_ON, 0, 0, 0, 0)
5656

5757

58-
def SetBrightness(ser, level):
58+
def SetBrightness(ser: serial.Serial, level: int):
5959
# Level : 0 (brightest) - 255 (darkest)
60+
assert 255 >= level >= 0, 'Brightness level must be [0-255]'
6061
SendReg(ser, Command.SET_BRIGHTNESS, level, 0, 0, 0)
6162

6263

63-
def DisplayPILImage(ser, image, x, y):
64+
def DisplayPILImage(ser: serial.Serial, image: Image, x: int, y: int):
6465
image_height = image.size[1]
6566
image_width = image.size[0]
6667

68+
assert image_height > 0, 'Image width must be > 0'
69+
assert image_width > 0, 'Image height must be > 0'
70+
6771
SendReg(ser, Command.DISPLAY_BITMAP, x, y, x + image_width - 1, y + image_height - 1)
6872

6973
pix = image.load()
@@ -78,7 +82,7 @@ def DisplayPILImage(ser, image, x, y):
7882
line += struct.pack('H', rgb)
7983

8084
# Send image data by multiple of DISPLAY_WIDTH bytes
81-
if len(line) >= DISPLAY_WIDTH*4:
85+
if len(line) >= DISPLAY_WIDTH * 8:
8286
ser.write(line)
8387
line = bytes()
8488

@@ -89,20 +93,23 @@ def DisplayPILImage(ser, image, x, y):
8993
sleep(0.01) # Wait 10 ms after picture display
9094

9195

92-
def DisplayBitmap(ser, bitmap_path, x=0, y=0):
96+
def DisplayBitmap(ser: serial.Serial, bitmap_path: str, x=0, y=0):
9397
image = Image.open(bitmap_path)
9498
DisplayPILImage(ser, image, x, y)
9599

96100

97-
def DisplayText(ser, text, x=0, y=0,
101+
def DisplayText(ser: serial.Serial, text: str, x=0, y=0,
98102
font="roboto/Roboto-Regular.ttf",
99103
font_size=20,
100104
font_color=(0, 0, 0),
101105
background_color=(255, 255, 255),
102-
background_image=None):
106+
background_image: str = None):
103107
# Convert text to bitmap using PIL and display it
104108
# Provide the background image path to display text with transparent background
105109

110+
assert len(text) > 0, 'Text must not be empty'
111+
assert font_size > 0, "Font size must be > 0"
112+
106113
if background_image is None:
107114
# A text bitmap is created with max width/height by default : text with solid background
108115
text_image = Image.new('RGB', (DISPLAY_WIDTH, DISPLAY_HEIGHT), background_color)
@@ -122,6 +129,41 @@ def DisplayText(ser, text, x=0, y=0,
122129
DisplayPILImage(ser, text_image, x, y)
123130

124131

132+
def DisplayProgressBar(ser: serial.Serial, x: int, y: int, width: int, height: int, min_value=0, max_value=100,
133+
value=50,
134+
bar_color=(0, 0, 0),
135+
bar_outline=True,
136+
background_color=(255, 255, 255),
137+
background_image: str = None):
138+
# Generate a progress bar and display it
139+
# Provide the background image path to display progress bar with transparent background
140+
141+
assert x + width <= DISPLAY_WIDTH, 'Progress bar width exceeds display width'
142+
assert y + height <= DISPLAY_HEIGHT, 'Progress bar height exceeds display height'
143+
assert min_value <= value <= max_value, 'Progress bar value shall be between min and max'
144+
145+
if background_image is None:
146+
# A bitmap is created with solid background
147+
bar_image = Image.new('RGB', (width, height), background_color)
148+
else:
149+
# A bitmap is created from provided background image
150+
bar_image = Image.open(background_image)
151+
152+
# Crop bitmap to keep only the progress bar background
153+
bar_image = bar_image.crop(box=(x, y, x + width, y + height))
154+
155+
# Draw progress bar
156+
bar_filled_width = value / (max_value - min_value) * width
157+
draw = ImageDraw.Draw(bar_image)
158+
draw.rectangle([0, 0, bar_filled_width-1, height-1], fill=bar_color, outline=bar_color)
159+
160+
if bar_outline:
161+
# Draw outline
162+
draw.rectangle([0, 0, width-1, height-1], fill=None, outline=bar_color)
163+
164+
DisplayPILImage(ser, bar_image, x, y)
165+
166+
125167
stop = False
126168

127169
if __name__ == "__main__":
@@ -130,6 +172,7 @@ def sighandler(signum, frame):
130172
global stop
131173
stop = True
132174

175+
133176
# Set the signal handlers, to send a complete frame to the LCD before exit
134177
signal.signal(signal.SIGINT, sighandler)
135178
signal.signal(signal.SIGTERM, sighandler)
@@ -173,12 +216,27 @@ def sighandler(signum, frame):
173216
font_color=(255, 255, 255),
174217
background_image="res/example.png")
175218

176-
# Display the current time as fast as possible
219+
# Display the current time and some progress bars as fast as possible
220+
bar_value = 0
177221
while not stop:
178222
DisplayText(lcd_comm, str(datetime.now().time()), 160, 2,
179223
font="roboto/Roboto-Bold.ttf",
180224
font_size=20,
181225
font_color=(255, 0, 0),
182226
background_image="res/example.png")
183227

228+
DisplayProgressBar(lcd_comm, 10, 40,
229+
width=140, height=30,
230+
min_value=0, max_value=100, value=bar_value,
231+
bar_color=(255, 255, 0), bar_outline=True,
232+
background_image="res/example.png")
233+
234+
DisplayProgressBar(lcd_comm, 160, 40,
235+
width=140, height=30,
236+
min_value=0, max_value=19, value=bar_value % 20,
237+
bar_color=(0, 255, 0), bar_outline=False,
238+
background_image="res/example.png")
239+
240+
bar_value = (bar_value + 2) % 101
241+
184242
lcd_comm.close()

0 commit comments

Comments
 (0)