smartpi 0.1.22__py3-none-any.whl → 0.1.24__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
smartpi/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  __all__ = ["base_driver"]
2
2
 
3
- __version__ = "0.1.22"
3
+ __version__ = "0.1.24"
4
4
 
smartpi/base_driver.py CHANGED
@@ -641,7 +641,6 @@ def smartpi_init():
641
641
  motor.reset_motor_encoder(5)
642
642
  motor.reset_motor_encoder(6)
643
643
  time.sleep(0.1)
644
- gui.init()
645
644
  serial_lock.release()
646
645
  time.sleep(0.1)
647
646
 
smartpi/gui.py CHANGED
@@ -1,61 +1,238 @@
1
- import socket
2
- import json
3
- import sys
4
-
5
- # 连接对象(模块级单例)
6
- _connection = None
7
-
8
- def init(host="127.0.0.1", port=65167):
9
- """初始化GUI连接"""
10
- global _connection
11
- if _connection is None:
12
- _connection = socket.create_connection((host, port))
13
- _send({"type": "clear"})
14
-
15
- def _send(cmd):
16
- """发送命令到服务器"""
17
- if _connection is None and "pytest" not in sys.modules: # 允许测试环境不初始化
18
- raise ConnectionError("GUI not initialized. Call gui.init() first.")
19
- if _connection:
20
- _connection.sendall((json.dumps(cmd) + "\n").encode())
1
+ #!/usr/bin/env python3
2
+ """
3
+ 可靠触摸屏GUI - 恢复可工作版本
4
+ """
21
5
 
22
- def show_text(x, y, text, color="black", size=16):
23
- _send({"type": "text", "x": x, "y": y, "text": text, "color": color, "size": size})
6
+ import tkinter as tk
7
+ from tkinter import font as tkfont
8
+ import os
9
+ import select
10
+ import struct
11
+ import threading
12
+ import time
13
+
14
+ # 全局变量
15
+ _root = None
16
+ _canvas = None
17
+ _fonts = {}
18
+ _touch_x = 0
19
+ _touch_y = 0
20
+ _touch_pressed = False
21
+ _x_cache = 0
22
+ _y_cache = 0
23
+ _exit_triggered = False
24
+
25
+ def _create_fonts():
26
+ """创建字体"""
27
+ global _fonts
28
+ _fonts[16] = tkfont.Font(family="Arial", size=16)
29
+ _fonts[24] = tkfont.Font(family="Arial", size=24)
30
+ _fonts[32] = tkfont.Font(family="Arial", size=32)
31
+ _fonts[40] = tkfont.Font(family="Arial", size=40)
32
+ _fonts[48] = tkfont.Font(family="Arial", size=48)
33
+
34
+ def _read_touch_events():
35
+ """可靠的触摸事件读取 - 使用之前验证过的方法"""
36
+ global _touch_x, _touch_y, _touch_pressed, _x_cache, _y_cache
37
+
38
+ try:
39
+ # 打开输入设备
40
+ fd = os.open('/dev/input/event2', os.O_RDONLY | os.O_NONBLOCK)
41
+ except Exception as e:
42
+ print(f"无法打开设备: {e}")
43
+ return
44
+
45
+ # input_event结构体格式
46
+ EVENT_FORMAT = 'llHHI'
47
+ EVENT_SIZE = struct.calcsize(EVENT_FORMAT)
48
+
49
+ # 事件类型定义
50
+ EV_SYN = 0x00
51
+ EV_ABS = 0x03
52
+
53
+ # 绝对轴定义
54
+ ABS_MT_POSITION_X = 0x35
55
+ ABS_MT_POSITION_Y = 0x36
56
+ ABS_MT_TRACKING_ID = 0x39
57
+
58
+ # 持续读取触摸事件
59
+ while not _exit_triggered:
60
+ try:
61
+ # 使用select等待数据可读
62
+ r, w, e = select.select([fd], [], [], 0.1)
63
+
64
+ if fd in r:
65
+ data = os.read(fd, EVENT_SIZE * 10)
66
+ data_len = len(data)
67
+ pos = 0
68
+
69
+ while pos + EVENT_SIZE <= data_len:
70
+ # 解析事件
71
+ tv_sec, tv_usec, etype, code, value = struct.unpack(EVENT_FORMAT, data[pos:pos+EVENT_SIZE])
72
+ pos += EVENT_SIZE
73
+
74
+ if etype == EV_ABS:
75
+ if code == ABS_MT_POSITION_X:
76
+ _x_cache = value
77
+ _touch_x = value
78
+ elif code == ABS_MT_POSITION_Y:
79
+ _y_cache = value
80
+ _touch_y = value
81
+ elif code == ABS_MT_TRACKING_ID:
82
+ if value >= 0:
83
+ _touch_pressed = True
84
+ _touch_x = _x_cache
85
+ _touch_y = _y_cache
86
+ else:
87
+ _touch_pressed = False
88
+
89
+ # 同步事件
90
+ elif etype == EV_SYN:
91
+ if _touch_pressed:
92
+ _touch_x = _x_cache
93
+ _touch_y = _y_cache
94
+
95
+ except BlockingIOError:
96
+ pass
97
+ except OSError as e:
98
+ if e.errno != 11: # 忽略EAGAIN错误
99
+ print(f"读取错误: {e}")
100
+ break
101
+ except Exception as e:
102
+ print(f"触摸读取异常: {e}")
103
+ break
104
+
105
+ # 关闭设备
106
+ os.close(fd)
107
+
108
+ def _run_gui():
109
+ """运行GUI主循环"""
110
+ global _root, _canvas
111
+
112
+ # 创建GUI
113
+ _root = tk.Tk()
114
+ _root.title("Touch GUI")
115
+ _root.geometry("480x800")
116
+ _root.attributes('-fullscreen', True)
117
+
118
+ _canvas = tk.Canvas(_root, width=480, height=800, bg="white")
119
+ _canvas.pack(fill=tk.BOTH, expand=True)
120
+
121
+ _create_fonts()
122
+
123
+ # 定期检查退出按钮点击
124
+ def check_exit_periodically():
125
+ if _exit_triggered:
126
+ _root.quit()
127
+ return
128
+ _root.after(100, check_exit_periodically)
129
+
130
+ check_exit_periodically()
131
+
132
+ # 启动主循环
133
+ _root.mainloop()
24
134
 
25
- def print(text): # 使用print作为函数名,因为调用时使用gui.print()
26
- _send({"type": "print", "text": text})
135
+ def init():
136
+ """初始化GUI"""
137
+ # 启动GUI线程
138
+ gui_thread = threading.Thread(target=_run_gui, daemon=True)
139
+ gui_thread.start()
140
+
141
+ # 启动触摸事件读取线程
142
+ touch_thread = threading.Thread(target=_read_touch_events, daemon=True)
143
+ touch_thread.start()
144
+
145
+ # 等待GUI初始化完成
146
+ time.sleep(0.2)
27
147
 
28
- def println(text):
29
- _send({"type": "println", "text": text})
30
148
 
31
- def show_image(x, y, path, width, height):
32
- _send({"type": "image", "x": x, "y": y, "path": path, "width": width, "height": height})
149
+ # 公共接口函数
150
+ def show_text(x, y, text, color="black", size=16):
151
+ if _canvas and _fonts:
152
+ font = _fonts.get(size, _fonts[16])
153
+ _root.after(0, lambda: _canvas.create_text(x, y, text=text, fill=color, font=font, anchor="nw"))
33
154
 
34
155
  def draw_line(x1, y1, x2, y2, color="black", width=1):
35
- _send({"type": "line", "x1": x1, "y1": y1, "x2": x2, "y2": y2, "color": color, "width": width})
156
+ if _canvas:
157
+ _root.after(0, lambda: _canvas.create_line(x1, y1, x2, y2, fill=color, width=width))
36
158
 
37
159
  def fill_rect(x, y, w, h, color="black"):
38
- _send({"type": "fill_rect", "x": x, "y": y, "w": w, "h": h, "color": color})
39
-
160
+ if _canvas:
161
+ _root.after(0, lambda: _canvas.create_rectangle(x, y, x+w, y+h, fill=color, outline=""))
162
+
40
163
  def draw_rect(x, y, w, h, width, color="black"):
41
- _send({"type": "draw_rect", "x": x, "y": y, "w": w, "h": h, "width": width, "color": color})
164
+ if _canvas:
165
+ _root.after(0, lambda: _canvas.create_rectangle(x, y, x+w, y+h, width=width, outline=color))
42
166
 
43
167
  def fill_circle(cx, cy, r, color="black"):
44
- _send({"type": "fill_circle", "cx": cx, "cy": cy, "r": r, "color": color})
168
+ if _canvas:
169
+ _root.after(0, lambda: _canvas.create_oval(cx-r, cy-r, cx+r, cy+r, fill=color, outline=""))
45
170
 
46
171
  def draw_circle(cx, cy, r, width, color="black"):
47
- _send({"type": "draw_circle", "cx": cx, "cy": cy, "r": r, "width": width, "color": color})
172
+ if _canvas:
173
+ _root.after(0, lambda: _canvas.create_oval(cx-r, cy-r, cx+r, cy+r, width=width, outline=color))
174
+
175
+ def fill_polygon(points, color):
176
+ """填充多边形"""
177
+ if _canvas:
178
+ _root.after(0, lambda: _canvas.create_polygon(points, fill=color, outline=""))
48
179
 
49
180
  def clear():
50
- _send({"type": "clear"})
51
-
52
- def close():
53
- """关闭GUI连接"""
54
- global _connection
55
- if _connection:
56
- _connection.close()
57
- _connection = None
58
-
59
- # 注册程序退出时自动关闭连接
60
- import atexit
61
- atexit.register(close)
181
+ if _canvas:
182
+ _root.after(0, lambda: _canvas.delete("all"))
183
+
184
+ def get_touch_x():
185
+ return _touch_x
186
+
187
+ def get_touch_y():
188
+ return _touch_y
189
+
190
+ def get_touchscreen():
191
+ return _touch_pressed
192
+
193
+ def should_exit():
194
+ """检查是否应该退出程序"""
195
+ return _exit_triggered
196
+
197
+ def draw_exit_button():
198
+ """绘制退出按钮"""
199
+ if not _canvas:
200
+ return
201
+
202
+ # 退出按钮位置 - 底部中间
203
+ button_width = 100
204
+ button_height = 80
205
+ x1 = 480//2 - button_width//2
206
+ y1 = 800 - button_height - 20
207
+ x2 = 480//2 + button_width//2
208
+ y2 = 800 - 20
209
+
210
+ # 绘制朝向左边的蓝色三角形
211
+ triangle_size = 50
212
+ center_x = (x1 + x2) // 2
213
+ center_y = (y1 + y2) // 2
214
+
215
+ # 三角形顶点坐标 - 朝向左边的三角形
216
+ points = [
217
+ center_x - triangle_size//2, center_y, # 左顶点
218
+ center_x + triangle_size//2, center_y - triangle_size//2, # 右上顶点
219
+ center_x + triangle_size//2, center_y + triangle_size//2 # 右下顶点
220
+ ]
221
+
222
+ _root.after(0, lambda: _canvas.create_polygon(points, fill="blue", outline=""))
223
+
224
+ def check_exit_button(x, y):
225
+ """检查是否点击了退出按钮"""
226
+ # 退出按钮位置 - 底部中间
227
+ button_width = 100
228
+ button_height = 80
229
+ x1 = 480//2 - button_width//2
230
+ y1 = 800 - button_height - 20
231
+ x2 = 480//2 + button_width//2
232
+ y2 = 800 - 20
233
+
234
+ if x1 <= x <= x2 and y1 <= y <= y2:
235
+ global _exit_triggered
236
+ _exit_triggered = True
237
+ return True
238
+ return False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: smartpi
3
- Version: 0.1.22
3
+ Version: 0.1.24
4
4
  Summary: A library use for H2-RCU
5
5
  Author: ZMROBO
6
6
  Classifier: Programming Language :: Python :: 3
@@ -1,9 +1,9 @@
1
- smartpi/__init__.py,sha256=dbeSgtxUXUnzBRBUqAF0gP2AbNr9dwL8WvaeDNMTegY,55
2
- smartpi/base_driver.py,sha256=dhdmWK0_ff2GduYtGXiZ3W4ICRMf-gIROYgRhXYjZok,24204
1
+ smartpi/__init__.py,sha256=mtkDm-FlobRiZdbqGbS77ZzAwe5A9DRGKwIoWdhN2U4,55
2
+ smartpi/base_driver.py,sha256=jP8cuQ0LRfjMuVQ2I6tY7fxp3JsjcUH8fdWKooIogME,24188
3
3
  smartpi/color_sensor.py,sha256=YXJjknYjp7teTZsHYZRAWgi73CH0MhBp1go9y0Inxyo,498
4
4
  smartpi/cw2015.py,sha256=1lAF-pi_ye_ya1AZQS1sjbgsDf7MThO5IAskKsNGBzA,5695
5
5
  smartpi/flash.py,sha256=-pUqg6FSVoBiLFKqrG9B4dFqn8lICnQsSPJr_MtZLIU,4132
6
- smartpi/gui.py,sha256=E98_soyWbEf_dwYhXZgMSXrgY5QuYoDTuFCPK63flIQ,2102
6
+ smartpi/gui.py,sha256=nUFfU-jbDMOHIqZOyiy-7bwO0gMTJllscjnTLyoPYsk,7228
7
7
  smartpi/humidity.py,sha256=nZwiBtMWKNipVM83ymajZACPHxkC2vUJjDMmCOPN9lw,499
8
8
  smartpi/led.py,sha256=flvN7EJfP6VDTSiC93w1uR8pRxcZD9w2vLXA1GbJTo8,538
9
9
  smartpi/light_sensor.py,sha256=MayyVikWcXQfjeZrtYRnwYgHBDzu2g-mfJLpdd29EG8,1852
@@ -14,7 +14,7 @@ smartpi/temperature.py,sha256=VT79CYA41q1d_4AM-Y0eIMeIw7AtCkSXjWVws6Yx5yE,462
14
14
  smartpi/touch_sensor.py,sha256=P57RRQlqY0KexpMi-ydqwF5albOKCBOGb0Rb6zeVTqk,440
15
15
  smartpi/trace.py,sha256=tut7BMbq87ShaR5eNuv7PZtAEz9DS5_BDf0_muIZ-tQ,4577
16
16
  smartpi/ultrasonic.py,sha256=kmVpUfvE1oHoqgv92ZU6Fi-sO6DSwm10ssKsImNeOkY,624
17
- smartpi-0.1.22.dist-info/METADATA,sha256=znbfoZEXR-TzNdaUl9258HXSkWdCQAlj_aOfY2EZ4C0,311
18
- smartpi-0.1.22.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
19
- smartpi-0.1.22.dist-info/top_level.txt,sha256=PoLhUCmWAiQUg5UeN2fS-Y1iQyBbF2rdUlizXtpHGRQ,8
20
- smartpi-0.1.22.dist-info/RECORD,,
17
+ smartpi-0.1.24.dist-info/METADATA,sha256=EQIoqPSL55ic97bXSlKHbMhQYTH37iI-k9tCJHCJPXc,311
18
+ smartpi-0.1.24.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
19
+ smartpi-0.1.24.dist-info/top_level.txt,sha256=PoLhUCmWAiQUg5UeN2fS-Y1iQyBbF2rdUlizXtpHGRQ,8
20
+ smartpi-0.1.24.dist-info/RECORD,,