smartpi 0.1.23__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.23"
3
+ __version__ = "0.1.24"
4
4
 
smartpi/gui.py CHANGED
@@ -1,87 +1,238 @@
1
- import socket
2
- import json
1
+ #!/usr/bin/env python3
2
+ """
3
+ 可靠触摸屏GUI - 恢复可工作版本
4
+ """
5
+
6
+ import tkinter as tk
7
+ from tkinter import font as tkfont
8
+ import os
9
+ import select
10
+ import struct
11
+ import threading
3
12
  import time
4
13
 
5
- class _gui_client:
6
- def __init__(self, host="127.0.0.1", port=65167):
7
- self.sock = socket.create_connection((host, port))
8
- self.clear()
9
-
10
- def _send(self, cmd):
11
- self.sock.sendall((json.dumps(cmd) + "\n").encode())
12
- time.sleep(0.1)
13
-
14
- def show_text(self, x, y, text, color="black", size=16):
15
- self._send({"type": "text", "x": x, "y": y, "text": text, "color": color, "size": size})
16
-
17
- def print(self, text):
18
- self._send({"type": "print", "text": text})
19
-
20
- def println(self, text):
21
- self._send({"type": "println", "text": text})
22
-
23
- def show_image(self, x, y, path, width, height):
24
- self._send({"type": "image", "x": x, "y": y, "path": path, "width": width, "height": height})
25
-
26
- def draw_line(self, x1, y1, x2, y2, color="black", width=1):
27
- self._send({"type": "line", "x1": x1, "y1": y1, "x2": x2, "y2": y2, "color": color, "width": width})
28
-
29
- def fill_rect(self, x, y, w, h, color="black"):
30
- self._send({"type": "fill_rect", "x": x, "y": y, "w": w, "h": h, "color": color})
31
-
32
- def draw_rect(self, x, y, w, h, width, color="black"):
33
- self._send({"type": "draw_rect", "x": x, "y": y, "w": w, "h": h, "width": width, "color": color})
34
-
35
- def fill_circle(self, cx, cy, r, color="black"):
36
- self._send({"type": "fill_circle", "cx": cx, "cy": cy, "r": r, "color": color})
37
-
38
- def draw_circle(self, cx, cy, r, width, color="black"):
39
- self._send({"type": "draw_circle", "cx": cx, "cy": cy, "r": r, "width": width, "color": color})
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
40
104
 
41
- def clear(self):
42
- self._send({"type": "clear"})
105
+ # 关闭设备
106
+ os.close(fd)
43
107
 
44
- def finish(self):
45
- self.sock.close()
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()
134
+
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)
46
147
 
47
- # 创建全局实例
48
- _client_instance = _gui_client()
49
148
 
50
- # 将类方法提升为模块级别的函数
149
+ # 公共接口函数
51
150
  def show_text(x, y, text, color="black", size=16):
52
- _client_instance.show_text(x, y, text, color, size)
53
-
54
- def print(text):
55
- _client_instance.print(text)
56
-
57
- def println(text):
58
- _client_instance.println(text)
59
-
60
- def show_image(x, y, path, width, height):
61
- _client_instance.show_image(x, y, path, width, height)
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"))
62
154
 
63
155
  def draw_line(x1, y1, x2, y2, color="black", width=1):
64
- _client_instance.draw_line(x1, y1, x2, y2, color, width)
156
+ if _canvas:
157
+ _root.after(0, lambda: _canvas.create_line(x1, y1, x2, y2, fill=color, width=width))
65
158
 
66
159
  def fill_rect(x, y, w, h, color="black"):
67
- _client_instance.fill_rect(x, y, w, h, color)
68
-
160
+ if _canvas:
161
+ _root.after(0, lambda: _canvas.create_rectangle(x, y, x+w, y+h, fill=color, outline=""))
162
+
69
163
  def draw_rect(x, y, w, h, width, color="black"):
70
- _client_instance.draw_rect(x, y, w, h, width, color)
164
+ if _canvas:
165
+ _root.after(0, lambda: _canvas.create_rectangle(x, y, x+w, y+h, width=width, outline=color))
71
166
 
72
167
  def fill_circle(cx, cy, r, color="black"):
73
- _client_instance.fill_circle(cx, cy, r, color)
168
+ if _canvas:
169
+ _root.after(0, lambda: _canvas.create_oval(cx-r, cy-r, cx+r, cy+r, fill=color, outline=""))
74
170
 
75
171
  def draw_circle(cx, cy, r, width, color="black"):
76
- _client_instance.draw_circle(cx, cy, r, width, 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=""))
77
179
 
78
180
  def clear():
79
- _client_instance.clear()
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
80
189
 
81
- def finish():
82
- _client_instance.finish()
190
+ def get_touchscreen():
191
+ return _touch_pressed
83
192
 
84
- # 可选:如果希望仍然可以使用类创建新实例
85
- def create_client(host="127.0.0.1", port=65167):
86
- return _gui_client(host, port)
87
-
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.23
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=vHEaSuG4o0m17zvDoMBhn-lttaKYGct1k73F5y1orhk,55
1
+ smartpi/__init__.py,sha256=mtkDm-FlobRiZdbqGbS77ZzAwe5A9DRGKwIoWdhN2U4,55
2
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=HaupXWg5cWw_n86ge8IxARrvL3gpcDCNRwATK9irwH8,2960
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.23.dist-info/METADATA,sha256=VFDRXlgYEsVNBbHmPcqcwQnuu5VUeoFE0G1VtTfe3Vw,311
18
- smartpi-0.1.23.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
19
- smartpi-0.1.23.dist-info/top_level.txt,sha256=PoLhUCmWAiQUg5UeN2fS-Y1iQyBbF2rdUlizXtpHGRQ,8
20
- smartpi-0.1.23.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,,