From 429e594eb120c93ce1e02225d4db5ada7bfe8446 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=9B=E5=A5=B6=E5=91=B3=E6=9B=B2=E5=A5=87?= <9429238+milk-cookies@user.noreply.gitee.com> Date: Mon, 19 Jul 2021 01:02:48 +0000 Subject: [PATCH 01/37] =?UTF-8?q?=E6=96=B0=E5=BB=BA=20AS608?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AS608/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 AS608/.keep diff --git a/AS608/.keep b/AS608/.keep new file mode 100644 index 0000000..e69de29 -- Gitee From e58be3a7447ea235f7d91ebcc8c3903fec6a7059 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=9B=E5=A5=B6=E5=91=B3=E6=9B=B2=E5=A5=87?= <9429238+milk-cookies@user.noreply.gitee.com> Date: Mon, 19 Jul 2021 01:07:20 +0000 Subject: [PATCH 02/37] =?UTF-8?q?AS608=E7=9A=84=E4=B8=BB=E8=A6=81=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=BA=93=20=E7=9B=B8=E5=BD=93=E4=BA=8E=E9=80=9A?= =?UTF-8?q?=E8=BF=87=E8=AE=A1=E7=AE=97=E6=9C=BA=E5=90=91=E4=BC=A0=E6=84=9F?= =?UTF-8?q?=E5=99=A8=E4=BC=A0=E8=BE=93=E6=8C=87=E4=BB=A4=EF=BC=8C=E7=84=B6?= =?UTF-8?q?=E5=90=8E=E5=BE=97=E5=88=B0=E7=9B=B8=E5=BA=94=E7=9A=84=E6=95=B0?= =?UTF-8?q?=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AS608/AS608.py | 146 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 AS608/AS608.py diff --git a/AS608/AS608.py b/AS608/AS608.py new file mode 100644 index 0000000..6b4a152 --- /dev/null +++ b/AS608/AS608.py @@ -0,0 +1,146 @@ +from machine import UART, Pin, SPI +import st7789 +import utime + +def uart_init(): + uart = UART(1) + uart.init(baudrate=57600, parity=None, tx=Pin(0), rx=Pin(5)) # 构造串口,启用uart通信协议 + return uart + +def fingerprint1(display,uart): + for i in range(0, 8): # 指令(1):录入指纹 + uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x01\x00\x05') + utime.sleep(1) + dd = uart.read() + print(dd)#测试点 + if dd[9] == 0: # 指纹成功录入 + display.draw_string(10, 50, "School success!", size=3, color=st7789.color565(34, 139, 34), bg=st7789.color565(65, 105, 225)) + break + if i == 7: # 指纹没有录入成功 + display.draw_string(10, 50, "Entry failure!", size=3, color=st7789.color565(255, 125, 64), bg=st7789.color565(65, 105, 225)) + utime.sleep(2) + +def buffer1(display,uart): + for i in range(0, 8): # 指令(2):指纹生成模板存于Buffer1 + uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x04\x02\x01\x00\x08') + utime.sleep(1) + aa = uart.read() + print(aa)#测试点 + if aa[9] == 0: # 成功上传到Buffer1 + display.draw_string(10, 80, "Successfully upload!", size=2, color=st7789.color565(0, 255, 0), bg=st7789.color565(65, 105, 225)) + break + if i == 7: # 无法上传到Buffer1 + display.draw_string(10, 80, "Fail to upload!", size=2, color=st7789.color565(255, 97, 3), bg=st7789.color565(65, 105, 225)) + utime.sleep(3) + +def fingerprint2(display,uart): + for i in range(0, 8): # 指令(1):录入指纹,第二次录入指纹 + uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x01\x00\x05') + utime.sleep(1) + dd = uart.read() + print(dd)#测试点 + if dd[9] == 0: # 指纹成功录入 + display.draw_string(10, 110, "School success!", size=3, color=st7789.color565(34, 139, 34), bg=st7789.color565(65, 105, 225)) + break + if i == 7: # 指纹没有录入成功 + display.draw_string(10, 110, "Entry failure!", size=3, color=st7789.color565(255, 125, 64), bg=st7789.color565(65, 105, 225)) + utime.sleep(2) + +def buffer2(display,uart): + for i in range(0, 8): # 指令(2):指纹生成模板存于Buffer2 + uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x04\x02\x02\x00\x09') + utime.sleep(1) + aa = uart.read() + print(aa) + if aa[9] == 0: # 成功上传到Buffer2 + display.draw_string(10, 140, "Successfully upload!", size=2, color=st7789.color565(0, 255, 0), bg=st7789.color565(65, 105, 225)) + break + if i == 7: # 无法上传到Buffer2 + display.draw_string(10, 140, "Fail to upload!", size=2, color=st7789.color565(255, 97, 3), bg=st7789.color565(65, 105, 225)) + utime.sleep(2) + +def compare(display,uart,str1): + for i in range(0, 8): # 指令(3):对比两次录入指纹的质量 + uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x03\x00\x07') + utime.sleep(1) + aa = uart.read() + print(aa)#测试点 + if aa[9] == 0: # 对比成功,显示匹配度 + if aa[10] + aa[11] > 15: + display.draw_string(10, 10, "It's a good match!", size=2, color=st7789.color565(0, 255, 0), bg=st7789.color565(160, 32, 240)) + display.draw_string(10, 40, "Your match", size=3,color=st7789.color565(0, 0, 0), bg=st7789.color565(160, 32, 240)) + display.draw_string(10, 70, "score is ", size=3, color=st7789.color565(0, 0, 0), bg=st7789.color565(160, 32, 240)) + display.draw_string(10, 100, str(aa[10] + aa[11]), size=4,color=st7789.color565(255, 0, 0), bg=st7789.color565(160, 32, 240)) + else:# 对比成功,匹配度较低 + display.draw_string(10, 10, "The match is", size=2, color=st7789.color565(0, 0, 255), bg=st7789.color565(160, 32, 240)) + display.draw_string(10, 40, "a little bit bad", size=2, color=st7789.color565(0, 0, 255), bg=st7789.color565(160, 32, 240)) + display.draw_string(10, 70, "Your match", size=3, color=st7789.color565(0, 0, 0), bg=st7789.color565(160, 32, 240)) + display.draw_string(10, 100, "score is ", size=3, color=st7789.color565(0, 0, 0), bg=st7789.color565(160, 32, 240)) + display.draw_string(10, 130, str(aa[10] + aa[11]), size=4,color=st7789.color565(255, 0, 0), bg=st7789.color565(160, 32, 240)) + utime.sleep(2) + + for j in range(0, 8): # 指令(5):将Buffer1与Buffer2中的特征文件合并生成模板,结果存于Buffer1与Buffer2。 + uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x05\x00\x09') + utime.sleep(1) + bb = uart.read() + print(bb)#测试点 + if bb[9] == 0: # 传入成功 + display.draw_string(10, 160, "Merger success!", size=3, color=st7789.color565(0, 255, 0), bg=st7789.color565(160, 32, 240)) + break + if j == 7: # 传入失败 + display.draw_string(10, 160, "Merger failure!", size=3, color=st7789.color565(227, 23, 13), bg=st7789.color565(160, 32, 240)) + utime.sleep(2) + + for i in range(0, 8): # 指令(6):将匹配好的指纹储存到指纹库指定位置 + uart.write(str1) #可以自己选择储存的位置,这边只是做一个案例 + utime.sleep(1) + dd = uart.read() + print(dd)#测试点 + if dd[9] == 0:#储存成功 + display.draw_string(10, 190, "Store success!", size=3, color=st7789.color565(0, 255, 0), bg=st7789.color565(160, 32, 240)) + break + if i == 7:#储没有成功 + display.draw_string(10, 190, "Store failure!", size=3, color=st7789.color565(227, 23, 13), bg=st7789.color565(160, 32, 240)) + utime.sleep(2) + + break + if i == 7: # 匹配没有成功,无法存入指纹库 + display.draw_string(10, 30, "Match failure!!!", size=3, color=st7789.color565(255, 0, 0), bg=st7789.color565(160, 32, 240)) + utime.sleep(2) + +def search(display,uart): + for i in range(0, 8): # 搜索指纹(现场自动匹配) + uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x11\x00\x15') # 可以自己选择储存的位置,这边只是做一个案例 + utime.sleep(1) + dd = uart.read() + print(dd)#测试点 + if dd[9] == 0: # 用户搜索成功,返回用户ID以及匹配度 + if dd[10] + dd[11] > 15: + display.draw_string(10, 10, "The search ", size=3, color=st7789.color565(0, 255, 0), bg=st7789.color565(255, 255, 0)) + display.draw_string(10, 60, "is a good match!", size=3, color=st7789.color565(0, 255, 0), bg=st7789.color565(255, 255, 0)) + display.draw_string(10, 120, str(dd[10] + dd[11]) + ", Your match score is ", size=2,color=st7789.color565(0, 0, 0), bg=st7789.color565(255, 255, 0)) + display.draw_string(10, 120, str(dd[12] + dd[13]), size=2,color=st7789.color565(160, 32, 240)) + else: + display.draw_string(10, 10, "Your match ", size=3, color=st7789.color565(255, 0, 0), bg=st7789.color565(255, 255, 0)) + display.draw_string(10, 60, "is not good!", size=3, color=st7789.color565(255, 0, 0), bg=st7789.color565(255, 255, 0)) + display.draw_string(10, 120, str(dd[10] + dd[11]) + ", Your match score is ", size=2,color=st7789.color565(0, 0, 0), bg=st7789.color565(255, 255, 0)) + display.draw_string(10, 120, str(dd[12] + dd[13]), size=2, color=st7789.color565(160, 32, 240), bg=st7789.color565(255, 255, 0)) + break + if i == 7:#搜索失败 + display.draw_string(10, 10, "Search failure!", size=3, color=st7789.color565(240, 230, 140), bg=st7789.color565(255, 255, 0)) + utime.sleep(2) + +def clear(display,uart): + for i in range(0, 8): # 指令(13):清空指纹库 + uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x0d\x00\x11') + utime.sleep(1) + aa = uart.read() + print(aa)#测试点 + if aa[9] == 0: #清空成功 + display.draw_string(10, 230, "Empty the success!", size=1, color=st7789.color565(0, 0, 0)) + break + if i == 7: #清空失败 + display.draw_string(10, 230, "Empty the failure!", size=1, color=st7789.color565(0, 0, 0)) + utime.sleep(2) + +print(1)#判断库是否调用正确的一个测试点 \ No newline at end of file -- Gitee From d185164ee82cc5c10739927231eb0fd10f45803d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=9B=E5=A5=B6=E5=91=B3=E6=9B=B2=E5=A5=87?= <9429238+milk-cookies@user.noreply.gitee.com> Date: Mon, 19 Jul 2021 01:09:05 +0000 Subject: [PATCH 03/37] =?UTF-8?q?MQTT=E5=BA=93=20=E7=94=A8=E4=BA=8E?= =?UTF-8?q?=E4=B8=8E=E6=89=8B=E6=9C=BA=E7=94=A8=E6=88=B7=E7=9A=84=E4=BA=A4?= =?UTF-8?q?=E4=BA=92=E7=95=8C=E9=9D=A2=E6=9E=84=E9=80=A0=EF=BC=8C=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E5=8F=AF=E4=BB=A5=E9=80=9A=E8=BF=87MQTT=E8=BD=AF?= =?UTF-8?q?=E4=BB=B6=E4=BC=A0=E8=BE=93=E6=8C=87=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AS608/MQTT.py | 223 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 AS608/MQTT.py diff --git a/AS608/MQTT.py b/AS608/MQTT.py new file mode 100644 index 0000000..a10b0be --- /dev/null +++ b/AS608/MQTT.py @@ -0,0 +1,223 @@ +try: + import usocket as socket +except: + import socket +import ustruct as struct +from ubinascii import hexlify +#引入需要库 +class MQTTException(Exception): + pass +class MQTTClient: + + def __init__(self, client_id, server, port=0, user=None, password=None, keepalive=0, + ssl=False, ssl_params={}): + if port == 0: + port = 8883 if ssl else 1883 + self.client_id = client_id + self.sock = None + self.server = server + self.port = port + self.ssl = ssl + self.ssl_params = ssl_params + self.pid = 0 + self.cb = None + self.user = user + self.pswd = password + self.keepalive = keepalive + self.lw_topic = None + self.lw_msg = None + self.lw_qos = 0 + self.lw_retain = False + + def _send_str(self, s): + self.sock.write(struct.pack("!H", len(s))) + self.sock.write(s) + + def _recv_len(self): + n = 0 + sh = 0 + while 1: + b = self.sock.read(1)[0] + n |= (b & 0x7f) << sh + if not b & 0x80: + return n + sh += 7 + + def set_callback(self, f): + self.cb = f + + def set_last_will(self, topic, msg, retain=False, qos=0): + assert 0 <= qos <= 2 + assert topic + self.lw_topic = topic + self.lw_msg = msg + self.lw_qos = qos + self.lw_retain = retain + + def connect(self, clean_session=True): + self.sock = socket.socket() + addr = socket.getaddrinfo(self.server, self.port)[0][-1] + self.sock.connect(addr) + if self.ssl: + import ussl + self.sock = ussl.wrap_socket(self.sock, **self.ssl_params) + premsg = bytearray(b"\x10\0\0\0\0\0") + msg = bytearray(b"\x04MQTT\x04\x02\0\0") + + sz = 10 + 2 + len(self.client_id) + msg[6] = clean_session << 1 + if self.user is not None: + sz += 2 + len(self.user) + 2 + len(self.pswd) + msg[6] |= 0xC0 + if self.keepalive: + assert self.keepalive < 65536 + msg[7] |= self.keepalive >> 8 + msg[8] |= self.keepalive & 0x00FF + if self.lw_topic: + sz += 2 + len(self.lw_topic) + 2 + len(self.lw_msg) + msg[6] |= 0x4 | (self.lw_qos & 0x1) << 3 | (self.lw_qos & 0x2) << 3 + msg[6] |= self.lw_retain << 5 + + i = 1 + while sz > 0x7f: + premsg[i] = (sz & 0x7f) | 0x80 + sz >>= 7 + i += 1 + premsg[i] = sz + + self.sock.write(premsg, i + 2) + self.sock.write(msg) + self._send_str(self.client_id) + if self.lw_topic: + self._send_str(self.lw_topic) + self._send_str(self.lw_msg) + if self.user is not None: + self._send_str(self.user) + self._send_str(self.pswd) + resp = self.sock.read(4) + assert resp[0] == 0x20 and resp[1] == 0x02 + if resp[3] != 0: + raise MQTTException(resp[3]) + return resp[2] & 1 + + def disconnect(self): + self.sock.write(b"\xe0\0") + self.sock.close() + + def ping(self): + self.sock.write(b"\xc0\0") + + def publish(self, topic, msg, retain=False, qos=0): + pkt = bytearray(b"\x30\0\0\0") + pkt[0] |= qos << 1 | retain + sz = 2 + len(topic) + len(msg) + if qos > 0: + sz += 2 + assert sz < 2097152 + i = 1 + while sz > 0x7f: + pkt[i] = (sz & 0x7f) | 0x80 + sz >>= 7 + i += 1 + pkt[i] = sz + #print(hex(len(pkt)), hexlify(pkt, ":")) + self.sock.write(pkt, i + 1) + self._send_str(topic) + if qos > 0: + self.pid += 1 + pid = self.pid + struct.pack_into("!H", pkt, 0, pid) + self.sock.write(pkt, 2) + self.sock.write(msg) + if qos == 1: + while 1: + op = self.wait_msg() + if op == 0x40: + sz = self.sock.read(1) + assert sz == b"\x02" + rcv_pid = self.sock.read(2) + rcv_pid = rcv_pid[0] << 8 | rcv_pid[1] + if pid == rcv_pid: + return + elif qos == 2: + assert 0 + + def subscribe(self, topic, qos=0): + assert self.cb is not None, "Subscribe callback is not set" + pkt = bytearray(b"\x82\0\0\0") + self.pid += 1 + struct.pack_into("!BH", pkt, 1, 2 + 2 + len(topic) + 1, self.pid) + #print(hex(len(pkt)), hexlify(pkt, ":")) + self.sock.write(pkt) + self._send_str(topic) + self.sock.write(qos.to_bytes(1, "little")) + while 1: + op = self.wait_msg() + if op == 0x90: + resp = self.sock.read(4) + #print(resp) + assert resp[1] == pkt[2] and resp[2] == pkt[3] + if resp[3] == 0x80: + raise MQTTException(resp[3]) + return + + # Wait for a single incoming MQTT message and process it. + # Subscribed messages are delivered to a callback previously + # set by .set_callback() method. Other (internal) MQTT + # messages processed internally. + def wait_msg(self): + res = self.sock.read(1) + self.sock.setblocking(True) + if res is None: + return None + if res == b"": + raise OSError(-1) + if res == b"\xd0": # PINGRESP + sz = self.sock.read(1)[0] + assert sz == 0 + return None + op = res[0] + if op & 0xf0 != 0x30: + return op + sz = self._recv_len() + topic_len = self.sock.read(2) + topic_len = (topic_len[0] << 8) | topic_len[1] + topic = self.sock.read(topic_len) + sz -= topic_len + 2 + if op & 6: + pid = self.sock.read(2) + pid = pid[0] << 8 | pid[1] + sz -= 2 + msg = self.sock.read(sz) + self.cb(topic, msg) + if op & 6 == 2: + pkt = bytearray(b"\x40\x02\0\0") + struct.pack_into("!H", pkt, 2, pid) + self.sock.write(pkt) + elif op & 6 == 4: + assert 0 + + # Checks whether a pending message from server is available. + # If not, returns immediately with None. Otherwise, does + # the same processing as wait_msg. + def check_msg(self): + self.sock.setblocking(False) + return self.wait_msg() + + def sub_cb(topic, msg): + print((topic, msg)) + client.publish(topic_pub, msg) + + def connect_and_subscribe(): + global client_id, mqtt_server, topic_sub, mqtt_user, mqtt_password + client = MQTTClient(client_id, mqtt_server, user=mqtt_user, password=mqtt_password, port=port) + client.set_callback(sub_cb) + client.connect() + client.subscribe(topic_sub) + print('Connected to %s MQTT broker, subscribed to %s topic' % (mqtt_server, topic_sub)) + return client + + def restart_and_reconnect(): + print('Failed to connect to MQTT broker. Reconnecting...') + utime.sleep(10) + machine.reset() -- Gitee From 51b689bfd4befd7f5dd00bcad069c2cf0e687909 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=9B=E5=A5=B6=E5=91=B3=E6=9B=B2=E5=A5=87?= <9429238+milk-cookies@user.noreply.gitee.com> Date: Mon, 19 Jul 2021 01:10:50 +0000 Subject: [PATCH 04/37] =?UTF-8?q?=E4=B8=BB=E5=87=BD=E6=95=B0=20=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=E5=9F=BA=E6=9C=AC=E5=8A=9F=E8=83=BD=E7=9A=84=E4=B8=BB?= =?UTF-8?q?=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AS608/Main.py | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 AS608/Main.py diff --git a/AS608/Main.py b/AS608/Main.py new file mode 100644 index 0000000..a6701db --- /dev/null +++ b/AS608/Main.py @@ -0,0 +1,153 @@ +from machine import UART, Pin, SPI +import st7789 +import utime, network +from AS608 import uart_init, fingerprint1, buffer1, fingerprint2, buffer2, compare, search, clear +from MQTT import MQTTClient + +global Mymsg +mymsg=None + +wl = network.WLAN(network.STA_IF) +wl.active(1) +wl.connect('LAPTOP-8FIJU2IS 3092',';F23595m',security=network.AUTH_PSK) + +client_id = "xcy" +mqtt_server = "thingworx.zucc.edu.cn" +port=1883 +topic_sub = "xucongyu" +topic_pub = "xucongyu" +mqtt_user = "" +mqtt_password = "" + +def sub_cb(topic, msg): + global mymsg + mymsg=msg + #print((topic, msg)) + #client.publish(topic_pub, msg) + +def connect_and_subscribe(): + global client_id, mqtt_server, topic_sub, mqtt_user, mqtt_password + client = MQTTClient(client_id, mqtt_server, user=mqtt_user, password=mqtt_password,port=port) + client.set_callback(sub_cb) + client.connect() + client.subscribe(topic_sub) + print('Connected to %s MQTT broker, subscribed to %s topic' % (mqtt_server, topic_sub)) + return client + +def restart_and_reconnect(): + print('Failed to connect to MQTT broker. Reconnecting...') + utime.sleep(10) + machine.reset() + +try: + client = connect_and_subscribe() +except OSError as e: + restart_and_reconnect() + +uart = uart_init()#uart初始化 +str1 = b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x06\x06\x02\x00\x01\x00\x10' # 对比储存的一个案例字符串,这里我们默认从1开始 + +spi = SPI(0, baudrate=40000000, polarity=1, phase=0, bits=8, endia=0, sck=Pin(6), mosi=Pin(8)) +display = st7789.ST7789(spi, 240, 240, reset=Pin(11, func=Pin.GPIO, dir=Pin.OUT), dc=Pin(7, func=Pin.GPIO, dir=Pin.OUT)) +display.init() +display.fill(st7789.color565(255, 255, 255)) + + +x = 0 +y = 0 +while True: # 绘制网格界面 + display.vline(x, 0, 240, st7789.color565(255, 0, 0)) + display.hline(0, y, 240, st7789.color565(255, 0, 0)) + x = x + 30 + y = y + 30 + if (x >= 240): + break + +display.draw_string(10, 10, "Welcome", size=4, color=st7789.color565(255, 0, 0)) # 界面初始化 +utime.sleep(0.5) +display.draw_string(10, 60, "to", size=4, color=st7789.color565(0, 0, 255)) # 界面初始化 +utime.sleep(0.5) +display.draw_string(10, 110, "Login", size=4, color=st7789.color565(255, 97, 0)) # 界面初始化 +utime.sleep(0.5) +display.draw_string(10, 160, "Interface", size=4, color=st7789.color565(0, 255, 0)) # 界面初始化 +utime.sleep(4) # 休眠一段时间后进行录入指纹操作 + +for d in range(0, 2): + display.fill(st7789.color565(0, 255, 0)) # 进行交互界面 + + display.draw_string(10, 10, "Function 1:", size=2, color=st7789.color565(61, 89, 171), + bg=st7789.color565(61, 89, 171)) # 界面初始化 + display.draw_string(10, 40, "Input fingerprint", size=2, color=st7789.color565(61, 89, 171), + bg=st7789.color565(61, 89, 171)) # 界面初始化 + display.draw_string(10, 70, "Function 2:", size=2, color=st7789.color565(61, 89, 171), + bg=st7789.color565(61, 89, 171)) # 界面初始化 + display.draw_string(10, 100, "Upload fingerprints", size=2, color=st7789.color565(61, 89, 171), + bg=st7789.color565(61, 89, 171)) # 界面初始化 + display.draw_string(10, 130, "Function 3:", size=2, color=st7789.color565(61, 89, 171), + bg=st7789.color565(61, 89, 171)) # 界面初始化 + display.draw_string(10, 160, "Search for fingerprints", size=2, color=st7789.color565(61, 89, 171), + bg=st7789.color565(61, 89, 171)) # 界面初始化 + display.draw_string(10, 190, "Function 4:", size=2, color=st7789.color565(61, 89, 171), + bg=st7789.color565(61, 89, 171)) # 界面初始化 + display.draw_string(10, 220, "Clear the library", size=2, color=st7789.color565(61, 89, 171), + bg=st7789.color565(61, 89, 171)) # 界面初始化 + + while True: + client.subscribe(topic_sub) + if mymsg!=None: + Mymsg=str(mymsg,'utf-8') + if Mymsg=='1': + client.subscribe(topic_sub) + mymsg=None + display.fill(st7789.color565(65, 105, 225)) # 初始化界面,接下来开始录入部分 + utime.sleep(0.3) + display.draw_string(10, 10, "Start typing fingerprints", size=1, color=st7789.color565(0, 0, 0), + bg=st7789.color565(65, 105, 225)) # 开始录入指纹 + fingerprint1(display, uart) # 手指放在传感器上,过一段时间进行第一次录入 + buffer1(display, uart) # 第一次录入存到buffer1缓冲区,显示传感器是否成功录入指纹 + fingerprint2(display, uart) # 延时一段时间后会进行第二次录入 + buffer2(display, uart) # 第二次录入存到buffer2缓冲区,显示传感器是否成功录入指纹 + break + + elif Mymsg=='2': + client.subscribe(topic_sub) + mymsg=None + display.fill(st7789.color565(160, 32, 240)) # 录入部分结束,再次初始化界面,接下来开始储存部分 + utime.sleep(0.3) + compare(display, uart, str1) # 进行两次指纹录入的对比,若精确度高,则合成模板存入buffer1和buffer2中,延时一段时间后就会自动把模板传入指纹数据库的相应位置 + str1 = bytearray(str1) + i = int(str1[12]) + i += 1 + j = int(str1[14]) + j += 1 + str1[12] = i + str1[14] = j # 相当于从ID=1开始,每一次循环后都会使ID+1,每一次都往后延顺一个用户,这样就可以实现与用户的简单交互 + break + + elif Mymsg=='3': + client.subscribe(topic_sub) + mymsg=None + display.fill(st7789.color565(255, 255, 0)) # 录入及储存部分结束,再次初始化界面,接下来开始搜索部分 + search(display, uart) + break + # 一次循环结束 + display.fill(st7789.color565(0, 200, 0)) # 填充绿色进入休息时间 + display.draw_string(60, 60, 'Thanks', size=4, color=st7789.color565(255, 255, 255)) + display.draw_string(0, 100, 'Please go to', size=4, color=st7789.color565(255, 255, 255)) + display.draw_string(0, 150, 'the next one', size=4, color=st7789.color565(255, 255, 255)) # 每一个用户实现功能之后,会有一个短暂的休息 + utime.sleep(5) + +display.fill(st7789.color565(0, 255, 0)) + +x = 0 +y = 0 +while True: # 绘制网格界面 + display.vline(x, 0, 240, st7789.color565(0, 0, 0)) + display.hline(0, y, 240, st7789.color565(0, 0, 0)) + x = x + 30 + y = y + 30 + if (x >= 240): + break + +display.draw_string(30, 60, 'Thank you', size=4, color=st7789.color565(61, 89, 171), bg=st7789.color565(61, 89, 171)) +display.draw_string(10, 120, 'patronizing', size=4, color=st7789.color565(30, 144, 255),bg=st7789.color565(30, 144, 255)) # 结束 \ No newline at end of file -- Gitee From bdf10376c0e74ac59e6ee273fbc58acdb7e2db75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=9B=E5=A5=B6=E5=91=B3=E6=9B=B2=E5=A5=87?= <9429238+milk-cookies@user.noreply.gitee.com> Date: Mon, 19 Jul 2021 01:11:09 +0000 Subject: [PATCH 05/37] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20AS?= =?UTF-8?q?608/.keep?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AS608/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 AS608/.keep diff --git a/AS608/.keep b/AS608/.keep deleted file mode 100644 index e69de29..0000000 -- Gitee From 497d892edf1294143c4b42ec0deaa6d7b815ef68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=9B=E5=A5=B6=E5=91=B3=E6=9B=B2=E5=A5=87?= <9429238+milk-cookies@user.noreply.gitee.com> Date: Mon, 19 Jul 2021 01:13:20 +0000 Subject: [PATCH 06/37] =?UTF-8?q?=E6=96=B0=E5=BB=BA=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AS608/code/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 AS608/code/.keep diff --git a/AS608/code/.keep b/AS608/code/.keep new file mode 100644 index 0000000..e69de29 -- Gitee From 52bd13d9449227af131c2f1df88558747556f001 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=9B=E5=A5=B6=E5=91=B3=E6=9B=B2=E5=A5=87?= <9429238+milk-cookies@user.noreply.gitee.com> Date: Mon, 19 Jul 2021 01:13:48 +0000 Subject: [PATCH 07/37] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20AS?= =?UTF-8?q?608/AS608.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AS608/AS608.py | 146 ------------------------------------------------- 1 file changed, 146 deletions(-) delete mode 100644 AS608/AS608.py diff --git a/AS608/AS608.py b/AS608/AS608.py deleted file mode 100644 index 6b4a152..0000000 --- a/AS608/AS608.py +++ /dev/null @@ -1,146 +0,0 @@ -from machine import UART, Pin, SPI -import st7789 -import utime - -def uart_init(): - uart = UART(1) - uart.init(baudrate=57600, parity=None, tx=Pin(0), rx=Pin(5)) # 构造串口,启用uart通信协议 - return uart - -def fingerprint1(display,uart): - for i in range(0, 8): # 指令(1):录入指纹 - uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x01\x00\x05') - utime.sleep(1) - dd = uart.read() - print(dd)#测试点 - if dd[9] == 0: # 指纹成功录入 - display.draw_string(10, 50, "School success!", size=3, color=st7789.color565(34, 139, 34), bg=st7789.color565(65, 105, 225)) - break - if i == 7: # 指纹没有录入成功 - display.draw_string(10, 50, "Entry failure!", size=3, color=st7789.color565(255, 125, 64), bg=st7789.color565(65, 105, 225)) - utime.sleep(2) - -def buffer1(display,uart): - for i in range(0, 8): # 指令(2):指纹生成模板存于Buffer1 - uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x04\x02\x01\x00\x08') - utime.sleep(1) - aa = uart.read() - print(aa)#测试点 - if aa[9] == 0: # 成功上传到Buffer1 - display.draw_string(10, 80, "Successfully upload!", size=2, color=st7789.color565(0, 255, 0), bg=st7789.color565(65, 105, 225)) - break - if i == 7: # 无法上传到Buffer1 - display.draw_string(10, 80, "Fail to upload!", size=2, color=st7789.color565(255, 97, 3), bg=st7789.color565(65, 105, 225)) - utime.sleep(3) - -def fingerprint2(display,uart): - for i in range(0, 8): # 指令(1):录入指纹,第二次录入指纹 - uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x01\x00\x05') - utime.sleep(1) - dd = uart.read() - print(dd)#测试点 - if dd[9] == 0: # 指纹成功录入 - display.draw_string(10, 110, "School success!", size=3, color=st7789.color565(34, 139, 34), bg=st7789.color565(65, 105, 225)) - break - if i == 7: # 指纹没有录入成功 - display.draw_string(10, 110, "Entry failure!", size=3, color=st7789.color565(255, 125, 64), bg=st7789.color565(65, 105, 225)) - utime.sleep(2) - -def buffer2(display,uart): - for i in range(0, 8): # 指令(2):指纹生成模板存于Buffer2 - uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x04\x02\x02\x00\x09') - utime.sleep(1) - aa = uart.read() - print(aa) - if aa[9] == 0: # 成功上传到Buffer2 - display.draw_string(10, 140, "Successfully upload!", size=2, color=st7789.color565(0, 255, 0), bg=st7789.color565(65, 105, 225)) - break - if i == 7: # 无法上传到Buffer2 - display.draw_string(10, 140, "Fail to upload!", size=2, color=st7789.color565(255, 97, 3), bg=st7789.color565(65, 105, 225)) - utime.sleep(2) - -def compare(display,uart,str1): - for i in range(0, 8): # 指令(3):对比两次录入指纹的质量 - uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x03\x00\x07') - utime.sleep(1) - aa = uart.read() - print(aa)#测试点 - if aa[9] == 0: # 对比成功,显示匹配度 - if aa[10] + aa[11] > 15: - display.draw_string(10, 10, "It's a good match!", size=2, color=st7789.color565(0, 255, 0), bg=st7789.color565(160, 32, 240)) - display.draw_string(10, 40, "Your match", size=3,color=st7789.color565(0, 0, 0), bg=st7789.color565(160, 32, 240)) - display.draw_string(10, 70, "score is ", size=3, color=st7789.color565(0, 0, 0), bg=st7789.color565(160, 32, 240)) - display.draw_string(10, 100, str(aa[10] + aa[11]), size=4,color=st7789.color565(255, 0, 0), bg=st7789.color565(160, 32, 240)) - else:# 对比成功,匹配度较低 - display.draw_string(10, 10, "The match is", size=2, color=st7789.color565(0, 0, 255), bg=st7789.color565(160, 32, 240)) - display.draw_string(10, 40, "a little bit bad", size=2, color=st7789.color565(0, 0, 255), bg=st7789.color565(160, 32, 240)) - display.draw_string(10, 70, "Your match", size=3, color=st7789.color565(0, 0, 0), bg=st7789.color565(160, 32, 240)) - display.draw_string(10, 100, "score is ", size=3, color=st7789.color565(0, 0, 0), bg=st7789.color565(160, 32, 240)) - display.draw_string(10, 130, str(aa[10] + aa[11]), size=4,color=st7789.color565(255, 0, 0), bg=st7789.color565(160, 32, 240)) - utime.sleep(2) - - for j in range(0, 8): # 指令(5):将Buffer1与Buffer2中的特征文件合并生成模板,结果存于Buffer1与Buffer2。 - uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x05\x00\x09') - utime.sleep(1) - bb = uart.read() - print(bb)#测试点 - if bb[9] == 0: # 传入成功 - display.draw_string(10, 160, "Merger success!", size=3, color=st7789.color565(0, 255, 0), bg=st7789.color565(160, 32, 240)) - break - if j == 7: # 传入失败 - display.draw_string(10, 160, "Merger failure!", size=3, color=st7789.color565(227, 23, 13), bg=st7789.color565(160, 32, 240)) - utime.sleep(2) - - for i in range(0, 8): # 指令(6):将匹配好的指纹储存到指纹库指定位置 - uart.write(str1) #可以自己选择储存的位置,这边只是做一个案例 - utime.sleep(1) - dd = uart.read() - print(dd)#测试点 - if dd[9] == 0:#储存成功 - display.draw_string(10, 190, "Store success!", size=3, color=st7789.color565(0, 255, 0), bg=st7789.color565(160, 32, 240)) - break - if i == 7:#储没有成功 - display.draw_string(10, 190, "Store failure!", size=3, color=st7789.color565(227, 23, 13), bg=st7789.color565(160, 32, 240)) - utime.sleep(2) - - break - if i == 7: # 匹配没有成功,无法存入指纹库 - display.draw_string(10, 30, "Match failure!!!", size=3, color=st7789.color565(255, 0, 0), bg=st7789.color565(160, 32, 240)) - utime.sleep(2) - -def search(display,uart): - for i in range(0, 8): # 搜索指纹(现场自动匹配) - uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x11\x00\x15') # 可以自己选择储存的位置,这边只是做一个案例 - utime.sleep(1) - dd = uart.read() - print(dd)#测试点 - if dd[9] == 0: # 用户搜索成功,返回用户ID以及匹配度 - if dd[10] + dd[11] > 15: - display.draw_string(10, 10, "The search ", size=3, color=st7789.color565(0, 255, 0), bg=st7789.color565(255, 255, 0)) - display.draw_string(10, 60, "is a good match!", size=3, color=st7789.color565(0, 255, 0), bg=st7789.color565(255, 255, 0)) - display.draw_string(10, 120, str(dd[10] + dd[11]) + ", Your match score is ", size=2,color=st7789.color565(0, 0, 0), bg=st7789.color565(255, 255, 0)) - display.draw_string(10, 120, str(dd[12] + dd[13]), size=2,color=st7789.color565(160, 32, 240)) - else: - display.draw_string(10, 10, "Your match ", size=3, color=st7789.color565(255, 0, 0), bg=st7789.color565(255, 255, 0)) - display.draw_string(10, 60, "is not good!", size=3, color=st7789.color565(255, 0, 0), bg=st7789.color565(255, 255, 0)) - display.draw_string(10, 120, str(dd[10] + dd[11]) + ", Your match score is ", size=2,color=st7789.color565(0, 0, 0), bg=st7789.color565(255, 255, 0)) - display.draw_string(10, 120, str(dd[12] + dd[13]), size=2, color=st7789.color565(160, 32, 240), bg=st7789.color565(255, 255, 0)) - break - if i == 7:#搜索失败 - display.draw_string(10, 10, "Search failure!", size=3, color=st7789.color565(240, 230, 140), bg=st7789.color565(255, 255, 0)) - utime.sleep(2) - -def clear(display,uart): - for i in range(0, 8): # 指令(13):清空指纹库 - uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x0d\x00\x11') - utime.sleep(1) - aa = uart.read() - print(aa)#测试点 - if aa[9] == 0: #清空成功 - display.draw_string(10, 230, "Empty the success!", size=1, color=st7789.color565(0, 0, 0)) - break - if i == 7: #清空失败 - display.draw_string(10, 230, "Empty the failure!", size=1, color=st7789.color565(0, 0, 0)) - utime.sleep(2) - -print(1)#判断库是否调用正确的一个测试点 \ No newline at end of file -- Gitee From ae9b6ed754ac294314ea02f23f29ad5c32214379 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=9B=E5=A5=B6=E5=91=B3=E6=9B=B2=E5=A5=87?= <9429238+milk-cookies@user.noreply.gitee.com> Date: Mon, 19 Jul 2021 01:14:26 +0000 Subject: [PATCH 08/37] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20AS?= =?UTF-8?q?608/MQTT.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AS608/MQTT.py | 223 -------------------------------------------------- 1 file changed, 223 deletions(-) delete mode 100644 AS608/MQTT.py diff --git a/AS608/MQTT.py b/AS608/MQTT.py deleted file mode 100644 index a10b0be..0000000 --- a/AS608/MQTT.py +++ /dev/null @@ -1,223 +0,0 @@ -try: - import usocket as socket -except: - import socket -import ustruct as struct -from ubinascii import hexlify -#引入需要库 -class MQTTException(Exception): - pass -class MQTTClient: - - def __init__(self, client_id, server, port=0, user=None, password=None, keepalive=0, - ssl=False, ssl_params={}): - if port == 0: - port = 8883 if ssl else 1883 - self.client_id = client_id - self.sock = None - self.server = server - self.port = port - self.ssl = ssl - self.ssl_params = ssl_params - self.pid = 0 - self.cb = None - self.user = user - self.pswd = password - self.keepalive = keepalive - self.lw_topic = None - self.lw_msg = None - self.lw_qos = 0 - self.lw_retain = False - - def _send_str(self, s): - self.sock.write(struct.pack("!H", len(s))) - self.sock.write(s) - - def _recv_len(self): - n = 0 - sh = 0 - while 1: - b = self.sock.read(1)[0] - n |= (b & 0x7f) << sh - if not b & 0x80: - return n - sh += 7 - - def set_callback(self, f): - self.cb = f - - def set_last_will(self, topic, msg, retain=False, qos=0): - assert 0 <= qos <= 2 - assert topic - self.lw_topic = topic - self.lw_msg = msg - self.lw_qos = qos - self.lw_retain = retain - - def connect(self, clean_session=True): - self.sock = socket.socket() - addr = socket.getaddrinfo(self.server, self.port)[0][-1] - self.sock.connect(addr) - if self.ssl: - import ussl - self.sock = ussl.wrap_socket(self.sock, **self.ssl_params) - premsg = bytearray(b"\x10\0\0\0\0\0") - msg = bytearray(b"\x04MQTT\x04\x02\0\0") - - sz = 10 + 2 + len(self.client_id) - msg[6] = clean_session << 1 - if self.user is not None: - sz += 2 + len(self.user) + 2 + len(self.pswd) - msg[6] |= 0xC0 - if self.keepalive: - assert self.keepalive < 65536 - msg[7] |= self.keepalive >> 8 - msg[8] |= self.keepalive & 0x00FF - if self.lw_topic: - sz += 2 + len(self.lw_topic) + 2 + len(self.lw_msg) - msg[6] |= 0x4 | (self.lw_qos & 0x1) << 3 | (self.lw_qos & 0x2) << 3 - msg[6] |= self.lw_retain << 5 - - i = 1 - while sz > 0x7f: - premsg[i] = (sz & 0x7f) | 0x80 - sz >>= 7 - i += 1 - premsg[i] = sz - - self.sock.write(premsg, i + 2) - self.sock.write(msg) - self._send_str(self.client_id) - if self.lw_topic: - self._send_str(self.lw_topic) - self._send_str(self.lw_msg) - if self.user is not None: - self._send_str(self.user) - self._send_str(self.pswd) - resp = self.sock.read(4) - assert resp[0] == 0x20 and resp[1] == 0x02 - if resp[3] != 0: - raise MQTTException(resp[3]) - return resp[2] & 1 - - def disconnect(self): - self.sock.write(b"\xe0\0") - self.sock.close() - - def ping(self): - self.sock.write(b"\xc0\0") - - def publish(self, topic, msg, retain=False, qos=0): - pkt = bytearray(b"\x30\0\0\0") - pkt[0] |= qos << 1 | retain - sz = 2 + len(topic) + len(msg) - if qos > 0: - sz += 2 - assert sz < 2097152 - i = 1 - while sz > 0x7f: - pkt[i] = (sz & 0x7f) | 0x80 - sz >>= 7 - i += 1 - pkt[i] = sz - #print(hex(len(pkt)), hexlify(pkt, ":")) - self.sock.write(pkt, i + 1) - self._send_str(topic) - if qos > 0: - self.pid += 1 - pid = self.pid - struct.pack_into("!H", pkt, 0, pid) - self.sock.write(pkt, 2) - self.sock.write(msg) - if qos == 1: - while 1: - op = self.wait_msg() - if op == 0x40: - sz = self.sock.read(1) - assert sz == b"\x02" - rcv_pid = self.sock.read(2) - rcv_pid = rcv_pid[0] << 8 | rcv_pid[1] - if pid == rcv_pid: - return - elif qos == 2: - assert 0 - - def subscribe(self, topic, qos=0): - assert self.cb is not None, "Subscribe callback is not set" - pkt = bytearray(b"\x82\0\0\0") - self.pid += 1 - struct.pack_into("!BH", pkt, 1, 2 + 2 + len(topic) + 1, self.pid) - #print(hex(len(pkt)), hexlify(pkt, ":")) - self.sock.write(pkt) - self._send_str(topic) - self.sock.write(qos.to_bytes(1, "little")) - while 1: - op = self.wait_msg() - if op == 0x90: - resp = self.sock.read(4) - #print(resp) - assert resp[1] == pkt[2] and resp[2] == pkt[3] - if resp[3] == 0x80: - raise MQTTException(resp[3]) - return - - # Wait for a single incoming MQTT message and process it. - # Subscribed messages are delivered to a callback previously - # set by .set_callback() method. Other (internal) MQTT - # messages processed internally. - def wait_msg(self): - res = self.sock.read(1) - self.sock.setblocking(True) - if res is None: - return None - if res == b"": - raise OSError(-1) - if res == b"\xd0": # PINGRESP - sz = self.sock.read(1)[0] - assert sz == 0 - return None - op = res[0] - if op & 0xf0 != 0x30: - return op - sz = self._recv_len() - topic_len = self.sock.read(2) - topic_len = (topic_len[0] << 8) | topic_len[1] - topic = self.sock.read(topic_len) - sz -= topic_len + 2 - if op & 6: - pid = self.sock.read(2) - pid = pid[0] << 8 | pid[1] - sz -= 2 - msg = self.sock.read(sz) - self.cb(topic, msg) - if op & 6 == 2: - pkt = bytearray(b"\x40\x02\0\0") - struct.pack_into("!H", pkt, 2, pid) - self.sock.write(pkt) - elif op & 6 == 4: - assert 0 - - # Checks whether a pending message from server is available. - # If not, returns immediately with None. Otherwise, does - # the same processing as wait_msg. - def check_msg(self): - self.sock.setblocking(False) - return self.wait_msg() - - def sub_cb(topic, msg): - print((topic, msg)) - client.publish(topic_pub, msg) - - def connect_and_subscribe(): - global client_id, mqtt_server, topic_sub, mqtt_user, mqtt_password - client = MQTTClient(client_id, mqtt_server, user=mqtt_user, password=mqtt_password, port=port) - client.set_callback(sub_cb) - client.connect() - client.subscribe(topic_sub) - print('Connected to %s MQTT broker, subscribed to %s topic' % (mqtt_server, topic_sub)) - return client - - def restart_and_reconnect(): - print('Failed to connect to MQTT broker. Reconnecting...') - utime.sleep(10) - machine.reset() -- Gitee From a8d6d3247ecf3c4b717bd703f41e8a719922429d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=9B=E5=A5=B6=E5=91=B3=E6=9B=B2=E5=A5=87?= <9429238+milk-cookies@user.noreply.gitee.com> Date: Mon, 19 Jul 2021 01:14:32 +0000 Subject: [PATCH 09/37] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20AS?= =?UTF-8?q?608/Main.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AS608/Main.py | 153 -------------------------------------------------- 1 file changed, 153 deletions(-) delete mode 100644 AS608/Main.py diff --git a/AS608/Main.py b/AS608/Main.py deleted file mode 100644 index a6701db..0000000 --- a/AS608/Main.py +++ /dev/null @@ -1,153 +0,0 @@ -from machine import UART, Pin, SPI -import st7789 -import utime, network -from AS608 import uart_init, fingerprint1, buffer1, fingerprint2, buffer2, compare, search, clear -from MQTT import MQTTClient - -global Mymsg -mymsg=None - -wl = network.WLAN(network.STA_IF) -wl.active(1) -wl.connect('LAPTOP-8FIJU2IS 3092',';F23595m',security=network.AUTH_PSK) - -client_id = "xcy" -mqtt_server = "thingworx.zucc.edu.cn" -port=1883 -topic_sub = "xucongyu" -topic_pub = "xucongyu" -mqtt_user = "" -mqtt_password = "" - -def sub_cb(topic, msg): - global mymsg - mymsg=msg - #print((topic, msg)) - #client.publish(topic_pub, msg) - -def connect_and_subscribe(): - global client_id, mqtt_server, topic_sub, mqtt_user, mqtt_password - client = MQTTClient(client_id, mqtt_server, user=mqtt_user, password=mqtt_password,port=port) - client.set_callback(sub_cb) - client.connect() - client.subscribe(topic_sub) - print('Connected to %s MQTT broker, subscribed to %s topic' % (mqtt_server, topic_sub)) - return client - -def restart_and_reconnect(): - print('Failed to connect to MQTT broker. Reconnecting...') - utime.sleep(10) - machine.reset() - -try: - client = connect_and_subscribe() -except OSError as e: - restart_and_reconnect() - -uart = uart_init()#uart初始化 -str1 = b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x06\x06\x02\x00\x01\x00\x10' # 对比储存的一个案例字符串,这里我们默认从1开始 - -spi = SPI(0, baudrate=40000000, polarity=1, phase=0, bits=8, endia=0, sck=Pin(6), mosi=Pin(8)) -display = st7789.ST7789(spi, 240, 240, reset=Pin(11, func=Pin.GPIO, dir=Pin.OUT), dc=Pin(7, func=Pin.GPIO, dir=Pin.OUT)) -display.init() -display.fill(st7789.color565(255, 255, 255)) - - -x = 0 -y = 0 -while True: # 绘制网格界面 - display.vline(x, 0, 240, st7789.color565(255, 0, 0)) - display.hline(0, y, 240, st7789.color565(255, 0, 0)) - x = x + 30 - y = y + 30 - if (x >= 240): - break - -display.draw_string(10, 10, "Welcome", size=4, color=st7789.color565(255, 0, 0)) # 界面初始化 -utime.sleep(0.5) -display.draw_string(10, 60, "to", size=4, color=st7789.color565(0, 0, 255)) # 界面初始化 -utime.sleep(0.5) -display.draw_string(10, 110, "Login", size=4, color=st7789.color565(255, 97, 0)) # 界面初始化 -utime.sleep(0.5) -display.draw_string(10, 160, "Interface", size=4, color=st7789.color565(0, 255, 0)) # 界面初始化 -utime.sleep(4) # 休眠一段时间后进行录入指纹操作 - -for d in range(0, 2): - display.fill(st7789.color565(0, 255, 0)) # 进行交互界面 - - display.draw_string(10, 10, "Function 1:", size=2, color=st7789.color565(61, 89, 171), - bg=st7789.color565(61, 89, 171)) # 界面初始化 - display.draw_string(10, 40, "Input fingerprint", size=2, color=st7789.color565(61, 89, 171), - bg=st7789.color565(61, 89, 171)) # 界面初始化 - display.draw_string(10, 70, "Function 2:", size=2, color=st7789.color565(61, 89, 171), - bg=st7789.color565(61, 89, 171)) # 界面初始化 - display.draw_string(10, 100, "Upload fingerprints", size=2, color=st7789.color565(61, 89, 171), - bg=st7789.color565(61, 89, 171)) # 界面初始化 - display.draw_string(10, 130, "Function 3:", size=2, color=st7789.color565(61, 89, 171), - bg=st7789.color565(61, 89, 171)) # 界面初始化 - display.draw_string(10, 160, "Search for fingerprints", size=2, color=st7789.color565(61, 89, 171), - bg=st7789.color565(61, 89, 171)) # 界面初始化 - display.draw_string(10, 190, "Function 4:", size=2, color=st7789.color565(61, 89, 171), - bg=st7789.color565(61, 89, 171)) # 界面初始化 - display.draw_string(10, 220, "Clear the library", size=2, color=st7789.color565(61, 89, 171), - bg=st7789.color565(61, 89, 171)) # 界面初始化 - - while True: - client.subscribe(topic_sub) - if mymsg!=None: - Mymsg=str(mymsg,'utf-8') - if Mymsg=='1': - client.subscribe(topic_sub) - mymsg=None - display.fill(st7789.color565(65, 105, 225)) # 初始化界面,接下来开始录入部分 - utime.sleep(0.3) - display.draw_string(10, 10, "Start typing fingerprints", size=1, color=st7789.color565(0, 0, 0), - bg=st7789.color565(65, 105, 225)) # 开始录入指纹 - fingerprint1(display, uart) # 手指放在传感器上,过一段时间进行第一次录入 - buffer1(display, uart) # 第一次录入存到buffer1缓冲区,显示传感器是否成功录入指纹 - fingerprint2(display, uart) # 延时一段时间后会进行第二次录入 - buffer2(display, uart) # 第二次录入存到buffer2缓冲区,显示传感器是否成功录入指纹 - break - - elif Mymsg=='2': - client.subscribe(topic_sub) - mymsg=None - display.fill(st7789.color565(160, 32, 240)) # 录入部分结束,再次初始化界面,接下来开始储存部分 - utime.sleep(0.3) - compare(display, uart, str1) # 进行两次指纹录入的对比,若精确度高,则合成模板存入buffer1和buffer2中,延时一段时间后就会自动把模板传入指纹数据库的相应位置 - str1 = bytearray(str1) - i = int(str1[12]) - i += 1 - j = int(str1[14]) - j += 1 - str1[12] = i - str1[14] = j # 相当于从ID=1开始,每一次循环后都会使ID+1,每一次都往后延顺一个用户,这样就可以实现与用户的简单交互 - break - - elif Mymsg=='3': - client.subscribe(topic_sub) - mymsg=None - display.fill(st7789.color565(255, 255, 0)) # 录入及储存部分结束,再次初始化界面,接下来开始搜索部分 - search(display, uart) - break - # 一次循环结束 - display.fill(st7789.color565(0, 200, 0)) # 填充绿色进入休息时间 - display.draw_string(60, 60, 'Thanks', size=4, color=st7789.color565(255, 255, 255)) - display.draw_string(0, 100, 'Please go to', size=4, color=st7789.color565(255, 255, 255)) - display.draw_string(0, 150, 'the next one', size=4, color=st7789.color565(255, 255, 255)) # 每一个用户实现功能之后,会有一个短暂的休息 - utime.sleep(5) - -display.fill(st7789.color565(0, 255, 0)) - -x = 0 -y = 0 -while True: # 绘制网格界面 - display.vline(x, 0, 240, st7789.color565(0, 0, 0)) - display.hline(0, y, 240, st7789.color565(0, 0, 0)) - x = x + 30 - y = y + 30 - if (x >= 240): - break - -display.draw_string(30, 60, 'Thank you', size=4, color=st7789.color565(61, 89, 171), bg=st7789.color565(61, 89, 171)) -display.draw_string(10, 120, 'patronizing', size=4, color=st7789.color565(30, 144, 255),bg=st7789.color565(30, 144, 255)) # 结束 \ No newline at end of file -- Gitee From 532844c95eb21a4f25cb6aa8b1c453e160aa4428 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=9B=E5=A5=B6=E5=91=B3=E6=9B=B2=E5=A5=87?= <9429238+milk-cookies@user.noreply.gitee.com> Date: Mon, 19 Jul 2021 01:15:13 +0000 Subject: [PATCH 10/37] =?UTF-8?q?MQTT=E5=BA=93=20=E6=89=8B=E6=9C=BA?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E5=8F=AF=E9=80=9A=E8=BF=87MQTT=E5=90=91?= =?UTF-8?q?=E8=AE=A1=E7=AE=97=E6=9C=BA=E4=BC=A0=E5=85=A5=E6=8C=87=E4=BB=A4?= =?UTF-8?q?=EF=BC=8C=E4=BB=8E=E8=80=8C=E5=AE=9E=E7=8E=B0=E4=BA=A4=E4=BA=92?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AS608/code/MQTT.py | 223 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 AS608/code/MQTT.py diff --git a/AS608/code/MQTT.py b/AS608/code/MQTT.py new file mode 100644 index 0000000..a10b0be --- /dev/null +++ b/AS608/code/MQTT.py @@ -0,0 +1,223 @@ +try: + import usocket as socket +except: + import socket +import ustruct as struct +from ubinascii import hexlify +#引入需要库 +class MQTTException(Exception): + pass +class MQTTClient: + + def __init__(self, client_id, server, port=0, user=None, password=None, keepalive=0, + ssl=False, ssl_params={}): + if port == 0: + port = 8883 if ssl else 1883 + self.client_id = client_id + self.sock = None + self.server = server + self.port = port + self.ssl = ssl + self.ssl_params = ssl_params + self.pid = 0 + self.cb = None + self.user = user + self.pswd = password + self.keepalive = keepalive + self.lw_topic = None + self.lw_msg = None + self.lw_qos = 0 + self.lw_retain = False + + def _send_str(self, s): + self.sock.write(struct.pack("!H", len(s))) + self.sock.write(s) + + def _recv_len(self): + n = 0 + sh = 0 + while 1: + b = self.sock.read(1)[0] + n |= (b & 0x7f) << sh + if not b & 0x80: + return n + sh += 7 + + def set_callback(self, f): + self.cb = f + + def set_last_will(self, topic, msg, retain=False, qos=0): + assert 0 <= qos <= 2 + assert topic + self.lw_topic = topic + self.lw_msg = msg + self.lw_qos = qos + self.lw_retain = retain + + def connect(self, clean_session=True): + self.sock = socket.socket() + addr = socket.getaddrinfo(self.server, self.port)[0][-1] + self.sock.connect(addr) + if self.ssl: + import ussl + self.sock = ussl.wrap_socket(self.sock, **self.ssl_params) + premsg = bytearray(b"\x10\0\0\0\0\0") + msg = bytearray(b"\x04MQTT\x04\x02\0\0") + + sz = 10 + 2 + len(self.client_id) + msg[6] = clean_session << 1 + if self.user is not None: + sz += 2 + len(self.user) + 2 + len(self.pswd) + msg[6] |= 0xC0 + if self.keepalive: + assert self.keepalive < 65536 + msg[7] |= self.keepalive >> 8 + msg[8] |= self.keepalive & 0x00FF + if self.lw_topic: + sz += 2 + len(self.lw_topic) + 2 + len(self.lw_msg) + msg[6] |= 0x4 | (self.lw_qos & 0x1) << 3 | (self.lw_qos & 0x2) << 3 + msg[6] |= self.lw_retain << 5 + + i = 1 + while sz > 0x7f: + premsg[i] = (sz & 0x7f) | 0x80 + sz >>= 7 + i += 1 + premsg[i] = sz + + self.sock.write(premsg, i + 2) + self.sock.write(msg) + self._send_str(self.client_id) + if self.lw_topic: + self._send_str(self.lw_topic) + self._send_str(self.lw_msg) + if self.user is not None: + self._send_str(self.user) + self._send_str(self.pswd) + resp = self.sock.read(4) + assert resp[0] == 0x20 and resp[1] == 0x02 + if resp[3] != 0: + raise MQTTException(resp[3]) + return resp[2] & 1 + + def disconnect(self): + self.sock.write(b"\xe0\0") + self.sock.close() + + def ping(self): + self.sock.write(b"\xc0\0") + + def publish(self, topic, msg, retain=False, qos=0): + pkt = bytearray(b"\x30\0\0\0") + pkt[0] |= qos << 1 | retain + sz = 2 + len(topic) + len(msg) + if qos > 0: + sz += 2 + assert sz < 2097152 + i = 1 + while sz > 0x7f: + pkt[i] = (sz & 0x7f) | 0x80 + sz >>= 7 + i += 1 + pkt[i] = sz + #print(hex(len(pkt)), hexlify(pkt, ":")) + self.sock.write(pkt, i + 1) + self._send_str(topic) + if qos > 0: + self.pid += 1 + pid = self.pid + struct.pack_into("!H", pkt, 0, pid) + self.sock.write(pkt, 2) + self.sock.write(msg) + if qos == 1: + while 1: + op = self.wait_msg() + if op == 0x40: + sz = self.sock.read(1) + assert sz == b"\x02" + rcv_pid = self.sock.read(2) + rcv_pid = rcv_pid[0] << 8 | rcv_pid[1] + if pid == rcv_pid: + return + elif qos == 2: + assert 0 + + def subscribe(self, topic, qos=0): + assert self.cb is not None, "Subscribe callback is not set" + pkt = bytearray(b"\x82\0\0\0") + self.pid += 1 + struct.pack_into("!BH", pkt, 1, 2 + 2 + len(topic) + 1, self.pid) + #print(hex(len(pkt)), hexlify(pkt, ":")) + self.sock.write(pkt) + self._send_str(topic) + self.sock.write(qos.to_bytes(1, "little")) + while 1: + op = self.wait_msg() + if op == 0x90: + resp = self.sock.read(4) + #print(resp) + assert resp[1] == pkt[2] and resp[2] == pkt[3] + if resp[3] == 0x80: + raise MQTTException(resp[3]) + return + + # Wait for a single incoming MQTT message and process it. + # Subscribed messages are delivered to a callback previously + # set by .set_callback() method. Other (internal) MQTT + # messages processed internally. + def wait_msg(self): + res = self.sock.read(1) + self.sock.setblocking(True) + if res is None: + return None + if res == b"": + raise OSError(-1) + if res == b"\xd0": # PINGRESP + sz = self.sock.read(1)[0] + assert sz == 0 + return None + op = res[0] + if op & 0xf0 != 0x30: + return op + sz = self._recv_len() + topic_len = self.sock.read(2) + topic_len = (topic_len[0] << 8) | topic_len[1] + topic = self.sock.read(topic_len) + sz -= topic_len + 2 + if op & 6: + pid = self.sock.read(2) + pid = pid[0] << 8 | pid[1] + sz -= 2 + msg = self.sock.read(sz) + self.cb(topic, msg) + if op & 6 == 2: + pkt = bytearray(b"\x40\x02\0\0") + struct.pack_into("!H", pkt, 2, pid) + self.sock.write(pkt) + elif op & 6 == 4: + assert 0 + + # Checks whether a pending message from server is available. + # If not, returns immediately with None. Otherwise, does + # the same processing as wait_msg. + def check_msg(self): + self.sock.setblocking(False) + return self.wait_msg() + + def sub_cb(topic, msg): + print((topic, msg)) + client.publish(topic_pub, msg) + + def connect_and_subscribe(): + global client_id, mqtt_server, topic_sub, mqtt_user, mqtt_password + client = MQTTClient(client_id, mqtt_server, user=mqtt_user, password=mqtt_password, port=port) + client.set_callback(sub_cb) + client.connect() + client.subscribe(topic_sub) + print('Connected to %s MQTT broker, subscribed to %s topic' % (mqtt_server, topic_sub)) + return client + + def restart_and_reconnect(): + print('Failed to connect to MQTT broker. Reconnecting...') + utime.sleep(10) + machine.reset() -- Gitee From 610d9d93c26f2ba0e4970a20ab50d7eaf4814197 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=9B=E5=A5=B6=E5=91=B3=E6=9B=B2=E5=A5=87?= <9429238+milk-cookies@user.noreply.gitee.com> Date: Mon, 19 Jul 2021 01:15:20 +0000 Subject: [PATCH 11/37] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20AS?= =?UTF-8?q?608/code/.keep?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AS608/code/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 AS608/code/.keep diff --git a/AS608/code/.keep b/AS608/code/.keep deleted file mode 100644 index e69de29..0000000 -- Gitee From 799b6bd5f523f2223ad259859de0e34f5b7e2f7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=9B=E5=A5=B6=E5=91=B3=E6=9B=B2=E5=A5=87?= <9429238+milk-cookies@user.noreply.gitee.com> Date: Mon, 19 Jul 2021 01:16:25 +0000 Subject: [PATCH 12/37] =?UTF-8?q?AS608=E7=9A=84=E4=B8=BB=E8=A6=81=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=BA=93=20AS608=E9=83=A8=E5=88=86=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E7=9A=84=E5=BA=93=EF=BC=8C=E9=80=9A=E8=BF=87=E4=BC=A0=E8=BE=93?= =?UTF-8?q?=E6=8C=87=E4=BB=A4=E7=94=A8=E4=BA=8E=E5=AE=9E=E7=8E=B0=E7=9B=B8?= =?UTF-8?q?=E5=BA=94=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AS608/code/AS608.py | 146 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 AS608/code/AS608.py diff --git a/AS608/code/AS608.py b/AS608/code/AS608.py new file mode 100644 index 0000000..6b4a152 --- /dev/null +++ b/AS608/code/AS608.py @@ -0,0 +1,146 @@ +from machine import UART, Pin, SPI +import st7789 +import utime + +def uart_init(): + uart = UART(1) + uart.init(baudrate=57600, parity=None, tx=Pin(0), rx=Pin(5)) # 构造串口,启用uart通信协议 + return uart + +def fingerprint1(display,uart): + for i in range(0, 8): # 指令(1):录入指纹 + uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x01\x00\x05') + utime.sleep(1) + dd = uart.read() + print(dd)#测试点 + if dd[9] == 0: # 指纹成功录入 + display.draw_string(10, 50, "School success!", size=3, color=st7789.color565(34, 139, 34), bg=st7789.color565(65, 105, 225)) + break + if i == 7: # 指纹没有录入成功 + display.draw_string(10, 50, "Entry failure!", size=3, color=st7789.color565(255, 125, 64), bg=st7789.color565(65, 105, 225)) + utime.sleep(2) + +def buffer1(display,uart): + for i in range(0, 8): # 指令(2):指纹生成模板存于Buffer1 + uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x04\x02\x01\x00\x08') + utime.sleep(1) + aa = uart.read() + print(aa)#测试点 + if aa[9] == 0: # 成功上传到Buffer1 + display.draw_string(10, 80, "Successfully upload!", size=2, color=st7789.color565(0, 255, 0), bg=st7789.color565(65, 105, 225)) + break + if i == 7: # 无法上传到Buffer1 + display.draw_string(10, 80, "Fail to upload!", size=2, color=st7789.color565(255, 97, 3), bg=st7789.color565(65, 105, 225)) + utime.sleep(3) + +def fingerprint2(display,uart): + for i in range(0, 8): # 指令(1):录入指纹,第二次录入指纹 + uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x01\x00\x05') + utime.sleep(1) + dd = uart.read() + print(dd)#测试点 + if dd[9] == 0: # 指纹成功录入 + display.draw_string(10, 110, "School success!", size=3, color=st7789.color565(34, 139, 34), bg=st7789.color565(65, 105, 225)) + break + if i == 7: # 指纹没有录入成功 + display.draw_string(10, 110, "Entry failure!", size=3, color=st7789.color565(255, 125, 64), bg=st7789.color565(65, 105, 225)) + utime.sleep(2) + +def buffer2(display,uart): + for i in range(0, 8): # 指令(2):指纹生成模板存于Buffer2 + uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x04\x02\x02\x00\x09') + utime.sleep(1) + aa = uart.read() + print(aa) + if aa[9] == 0: # 成功上传到Buffer2 + display.draw_string(10, 140, "Successfully upload!", size=2, color=st7789.color565(0, 255, 0), bg=st7789.color565(65, 105, 225)) + break + if i == 7: # 无法上传到Buffer2 + display.draw_string(10, 140, "Fail to upload!", size=2, color=st7789.color565(255, 97, 3), bg=st7789.color565(65, 105, 225)) + utime.sleep(2) + +def compare(display,uart,str1): + for i in range(0, 8): # 指令(3):对比两次录入指纹的质量 + uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x03\x00\x07') + utime.sleep(1) + aa = uart.read() + print(aa)#测试点 + if aa[9] == 0: # 对比成功,显示匹配度 + if aa[10] + aa[11] > 15: + display.draw_string(10, 10, "It's a good match!", size=2, color=st7789.color565(0, 255, 0), bg=st7789.color565(160, 32, 240)) + display.draw_string(10, 40, "Your match", size=3,color=st7789.color565(0, 0, 0), bg=st7789.color565(160, 32, 240)) + display.draw_string(10, 70, "score is ", size=3, color=st7789.color565(0, 0, 0), bg=st7789.color565(160, 32, 240)) + display.draw_string(10, 100, str(aa[10] + aa[11]), size=4,color=st7789.color565(255, 0, 0), bg=st7789.color565(160, 32, 240)) + else:# 对比成功,匹配度较低 + display.draw_string(10, 10, "The match is", size=2, color=st7789.color565(0, 0, 255), bg=st7789.color565(160, 32, 240)) + display.draw_string(10, 40, "a little bit bad", size=2, color=st7789.color565(0, 0, 255), bg=st7789.color565(160, 32, 240)) + display.draw_string(10, 70, "Your match", size=3, color=st7789.color565(0, 0, 0), bg=st7789.color565(160, 32, 240)) + display.draw_string(10, 100, "score is ", size=3, color=st7789.color565(0, 0, 0), bg=st7789.color565(160, 32, 240)) + display.draw_string(10, 130, str(aa[10] + aa[11]), size=4,color=st7789.color565(255, 0, 0), bg=st7789.color565(160, 32, 240)) + utime.sleep(2) + + for j in range(0, 8): # 指令(5):将Buffer1与Buffer2中的特征文件合并生成模板,结果存于Buffer1与Buffer2。 + uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x05\x00\x09') + utime.sleep(1) + bb = uart.read() + print(bb)#测试点 + if bb[9] == 0: # 传入成功 + display.draw_string(10, 160, "Merger success!", size=3, color=st7789.color565(0, 255, 0), bg=st7789.color565(160, 32, 240)) + break + if j == 7: # 传入失败 + display.draw_string(10, 160, "Merger failure!", size=3, color=st7789.color565(227, 23, 13), bg=st7789.color565(160, 32, 240)) + utime.sleep(2) + + for i in range(0, 8): # 指令(6):将匹配好的指纹储存到指纹库指定位置 + uart.write(str1) #可以自己选择储存的位置,这边只是做一个案例 + utime.sleep(1) + dd = uart.read() + print(dd)#测试点 + if dd[9] == 0:#储存成功 + display.draw_string(10, 190, "Store success!", size=3, color=st7789.color565(0, 255, 0), bg=st7789.color565(160, 32, 240)) + break + if i == 7:#储没有成功 + display.draw_string(10, 190, "Store failure!", size=3, color=st7789.color565(227, 23, 13), bg=st7789.color565(160, 32, 240)) + utime.sleep(2) + + break + if i == 7: # 匹配没有成功,无法存入指纹库 + display.draw_string(10, 30, "Match failure!!!", size=3, color=st7789.color565(255, 0, 0), bg=st7789.color565(160, 32, 240)) + utime.sleep(2) + +def search(display,uart): + for i in range(0, 8): # 搜索指纹(现场自动匹配) + uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x11\x00\x15') # 可以自己选择储存的位置,这边只是做一个案例 + utime.sleep(1) + dd = uart.read() + print(dd)#测试点 + if dd[9] == 0: # 用户搜索成功,返回用户ID以及匹配度 + if dd[10] + dd[11] > 15: + display.draw_string(10, 10, "The search ", size=3, color=st7789.color565(0, 255, 0), bg=st7789.color565(255, 255, 0)) + display.draw_string(10, 60, "is a good match!", size=3, color=st7789.color565(0, 255, 0), bg=st7789.color565(255, 255, 0)) + display.draw_string(10, 120, str(dd[10] + dd[11]) + ", Your match score is ", size=2,color=st7789.color565(0, 0, 0), bg=st7789.color565(255, 255, 0)) + display.draw_string(10, 120, str(dd[12] + dd[13]), size=2,color=st7789.color565(160, 32, 240)) + else: + display.draw_string(10, 10, "Your match ", size=3, color=st7789.color565(255, 0, 0), bg=st7789.color565(255, 255, 0)) + display.draw_string(10, 60, "is not good!", size=3, color=st7789.color565(255, 0, 0), bg=st7789.color565(255, 255, 0)) + display.draw_string(10, 120, str(dd[10] + dd[11]) + ", Your match score is ", size=2,color=st7789.color565(0, 0, 0), bg=st7789.color565(255, 255, 0)) + display.draw_string(10, 120, str(dd[12] + dd[13]), size=2, color=st7789.color565(160, 32, 240), bg=st7789.color565(255, 255, 0)) + break + if i == 7:#搜索失败 + display.draw_string(10, 10, "Search failure!", size=3, color=st7789.color565(240, 230, 140), bg=st7789.color565(255, 255, 0)) + utime.sleep(2) + +def clear(display,uart): + for i in range(0, 8): # 指令(13):清空指纹库 + uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x0d\x00\x11') + utime.sleep(1) + aa = uart.read() + print(aa)#测试点 + if aa[9] == 0: #清空成功 + display.draw_string(10, 230, "Empty the success!", size=1, color=st7789.color565(0, 0, 0)) + break + if i == 7: #清空失败 + display.draw_string(10, 230, "Empty the failure!", size=1, color=st7789.color565(0, 0, 0)) + utime.sleep(2) + +print(1)#判断库是否调用正确的一个测试点 \ No newline at end of file -- Gitee From 0cc0a2fb58b2fb237faf484d1337e44176704588 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=9B=E5=A5=B6=E5=91=B3=E6=9B=B2=E5=A5=87?= <9429238+milk-cookies@user.noreply.gitee.com> Date: Mon, 19 Jul 2021 01:18:08 +0000 Subject: [PATCH 13/37] =?UTF-8?q?=E4=B8=BB=E5=87=BD=E6=95=B0=20=E4=B8=BB?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E7=94=A8=E4=BA=8E=E5=AE=9E=E7=8E=B0=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E7=9A=84=E4=BC=A0=E8=BE=93=E5=92=8C=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E7=9A=84=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AS608/code/Main.py | 153 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 AS608/code/Main.py diff --git a/AS608/code/Main.py b/AS608/code/Main.py new file mode 100644 index 0000000..a6701db --- /dev/null +++ b/AS608/code/Main.py @@ -0,0 +1,153 @@ +from machine import UART, Pin, SPI +import st7789 +import utime, network +from AS608 import uart_init, fingerprint1, buffer1, fingerprint2, buffer2, compare, search, clear +from MQTT import MQTTClient + +global Mymsg +mymsg=None + +wl = network.WLAN(network.STA_IF) +wl.active(1) +wl.connect('LAPTOP-8FIJU2IS 3092',';F23595m',security=network.AUTH_PSK) + +client_id = "xcy" +mqtt_server = "thingworx.zucc.edu.cn" +port=1883 +topic_sub = "xucongyu" +topic_pub = "xucongyu" +mqtt_user = "" +mqtt_password = "" + +def sub_cb(topic, msg): + global mymsg + mymsg=msg + #print((topic, msg)) + #client.publish(topic_pub, msg) + +def connect_and_subscribe(): + global client_id, mqtt_server, topic_sub, mqtt_user, mqtt_password + client = MQTTClient(client_id, mqtt_server, user=mqtt_user, password=mqtt_password,port=port) + client.set_callback(sub_cb) + client.connect() + client.subscribe(topic_sub) + print('Connected to %s MQTT broker, subscribed to %s topic' % (mqtt_server, topic_sub)) + return client + +def restart_and_reconnect(): + print('Failed to connect to MQTT broker. Reconnecting...') + utime.sleep(10) + machine.reset() + +try: + client = connect_and_subscribe() +except OSError as e: + restart_and_reconnect() + +uart = uart_init()#uart初始化 +str1 = b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x06\x06\x02\x00\x01\x00\x10' # 对比储存的一个案例字符串,这里我们默认从1开始 + +spi = SPI(0, baudrate=40000000, polarity=1, phase=0, bits=8, endia=0, sck=Pin(6), mosi=Pin(8)) +display = st7789.ST7789(spi, 240, 240, reset=Pin(11, func=Pin.GPIO, dir=Pin.OUT), dc=Pin(7, func=Pin.GPIO, dir=Pin.OUT)) +display.init() +display.fill(st7789.color565(255, 255, 255)) + + +x = 0 +y = 0 +while True: # 绘制网格界面 + display.vline(x, 0, 240, st7789.color565(255, 0, 0)) + display.hline(0, y, 240, st7789.color565(255, 0, 0)) + x = x + 30 + y = y + 30 + if (x >= 240): + break + +display.draw_string(10, 10, "Welcome", size=4, color=st7789.color565(255, 0, 0)) # 界面初始化 +utime.sleep(0.5) +display.draw_string(10, 60, "to", size=4, color=st7789.color565(0, 0, 255)) # 界面初始化 +utime.sleep(0.5) +display.draw_string(10, 110, "Login", size=4, color=st7789.color565(255, 97, 0)) # 界面初始化 +utime.sleep(0.5) +display.draw_string(10, 160, "Interface", size=4, color=st7789.color565(0, 255, 0)) # 界面初始化 +utime.sleep(4) # 休眠一段时间后进行录入指纹操作 + +for d in range(0, 2): + display.fill(st7789.color565(0, 255, 0)) # 进行交互界面 + + display.draw_string(10, 10, "Function 1:", size=2, color=st7789.color565(61, 89, 171), + bg=st7789.color565(61, 89, 171)) # 界面初始化 + display.draw_string(10, 40, "Input fingerprint", size=2, color=st7789.color565(61, 89, 171), + bg=st7789.color565(61, 89, 171)) # 界面初始化 + display.draw_string(10, 70, "Function 2:", size=2, color=st7789.color565(61, 89, 171), + bg=st7789.color565(61, 89, 171)) # 界面初始化 + display.draw_string(10, 100, "Upload fingerprints", size=2, color=st7789.color565(61, 89, 171), + bg=st7789.color565(61, 89, 171)) # 界面初始化 + display.draw_string(10, 130, "Function 3:", size=2, color=st7789.color565(61, 89, 171), + bg=st7789.color565(61, 89, 171)) # 界面初始化 + display.draw_string(10, 160, "Search for fingerprints", size=2, color=st7789.color565(61, 89, 171), + bg=st7789.color565(61, 89, 171)) # 界面初始化 + display.draw_string(10, 190, "Function 4:", size=2, color=st7789.color565(61, 89, 171), + bg=st7789.color565(61, 89, 171)) # 界面初始化 + display.draw_string(10, 220, "Clear the library", size=2, color=st7789.color565(61, 89, 171), + bg=st7789.color565(61, 89, 171)) # 界面初始化 + + while True: + client.subscribe(topic_sub) + if mymsg!=None: + Mymsg=str(mymsg,'utf-8') + if Mymsg=='1': + client.subscribe(topic_sub) + mymsg=None + display.fill(st7789.color565(65, 105, 225)) # 初始化界面,接下来开始录入部分 + utime.sleep(0.3) + display.draw_string(10, 10, "Start typing fingerprints", size=1, color=st7789.color565(0, 0, 0), + bg=st7789.color565(65, 105, 225)) # 开始录入指纹 + fingerprint1(display, uart) # 手指放在传感器上,过一段时间进行第一次录入 + buffer1(display, uart) # 第一次录入存到buffer1缓冲区,显示传感器是否成功录入指纹 + fingerprint2(display, uart) # 延时一段时间后会进行第二次录入 + buffer2(display, uart) # 第二次录入存到buffer2缓冲区,显示传感器是否成功录入指纹 + break + + elif Mymsg=='2': + client.subscribe(topic_sub) + mymsg=None + display.fill(st7789.color565(160, 32, 240)) # 录入部分结束,再次初始化界面,接下来开始储存部分 + utime.sleep(0.3) + compare(display, uart, str1) # 进行两次指纹录入的对比,若精确度高,则合成模板存入buffer1和buffer2中,延时一段时间后就会自动把模板传入指纹数据库的相应位置 + str1 = bytearray(str1) + i = int(str1[12]) + i += 1 + j = int(str1[14]) + j += 1 + str1[12] = i + str1[14] = j # 相当于从ID=1开始,每一次循环后都会使ID+1,每一次都往后延顺一个用户,这样就可以实现与用户的简单交互 + break + + elif Mymsg=='3': + client.subscribe(topic_sub) + mymsg=None + display.fill(st7789.color565(255, 255, 0)) # 录入及储存部分结束,再次初始化界面,接下来开始搜索部分 + search(display, uart) + break + # 一次循环结束 + display.fill(st7789.color565(0, 200, 0)) # 填充绿色进入休息时间 + display.draw_string(60, 60, 'Thanks', size=4, color=st7789.color565(255, 255, 255)) + display.draw_string(0, 100, 'Please go to', size=4, color=st7789.color565(255, 255, 255)) + display.draw_string(0, 150, 'the next one', size=4, color=st7789.color565(255, 255, 255)) # 每一个用户实现功能之后,会有一个短暂的休息 + utime.sleep(5) + +display.fill(st7789.color565(0, 255, 0)) + +x = 0 +y = 0 +while True: # 绘制网格界面 + display.vline(x, 0, 240, st7789.color565(0, 0, 0)) + display.hline(0, y, 240, st7789.color565(0, 0, 0)) + x = x + 30 + y = y + 30 + if (x >= 240): + break + +display.draw_string(30, 60, 'Thank you', size=4, color=st7789.color565(61, 89, 171), bg=st7789.color565(61, 89, 171)) +display.draw_string(10, 120, 'patronizing', size=4, color=st7789.color565(30, 144, 255),bg=st7789.color565(30, 144, 255)) # 结束 \ No newline at end of file -- Gitee From e6b5f22f9622b1ccf2d142f7a9cd99ad45106cf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=9B=E5=A5=B6=E5=91=B3=E6=9B=B2=E5=A5=87?= <9429238+milk-cookies@user.noreply.gitee.com> Date: Mon, 19 Jul 2021 01:19:57 +0000 Subject: [PATCH 14/37] =?UTF-8?q?=E6=96=B0=E5=BB=BA=20image?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AS608/image/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 AS608/image/.keep diff --git a/AS608/image/.keep b/AS608/image/.keep new file mode 100644 index 0000000..e69de29 -- Gitee From a0199d368f18d68765d27053a0d3b21eee321f59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=9B=E5=A5=B6=E5=91=B3=E6=9B=B2=E5=A5=87?= <9429238+milk-cookies@user.noreply.gitee.com> Date: Mon, 19 Jul 2021 02:15:01 +0000 Subject: [PATCH 15/37] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20AS?= =?UTF-8?q?608/code/Main.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AS608/code/Main.py | 153 --------------------------------------------- 1 file changed, 153 deletions(-) delete mode 100644 AS608/code/Main.py diff --git a/AS608/code/Main.py b/AS608/code/Main.py deleted file mode 100644 index a6701db..0000000 --- a/AS608/code/Main.py +++ /dev/null @@ -1,153 +0,0 @@ -from machine import UART, Pin, SPI -import st7789 -import utime, network -from AS608 import uart_init, fingerprint1, buffer1, fingerprint2, buffer2, compare, search, clear -from MQTT import MQTTClient - -global Mymsg -mymsg=None - -wl = network.WLAN(network.STA_IF) -wl.active(1) -wl.connect('LAPTOP-8FIJU2IS 3092',';F23595m',security=network.AUTH_PSK) - -client_id = "xcy" -mqtt_server = "thingworx.zucc.edu.cn" -port=1883 -topic_sub = "xucongyu" -topic_pub = "xucongyu" -mqtt_user = "" -mqtt_password = "" - -def sub_cb(topic, msg): - global mymsg - mymsg=msg - #print((topic, msg)) - #client.publish(topic_pub, msg) - -def connect_and_subscribe(): - global client_id, mqtt_server, topic_sub, mqtt_user, mqtt_password - client = MQTTClient(client_id, mqtt_server, user=mqtt_user, password=mqtt_password,port=port) - client.set_callback(sub_cb) - client.connect() - client.subscribe(topic_sub) - print('Connected to %s MQTT broker, subscribed to %s topic' % (mqtt_server, topic_sub)) - return client - -def restart_and_reconnect(): - print('Failed to connect to MQTT broker. Reconnecting...') - utime.sleep(10) - machine.reset() - -try: - client = connect_and_subscribe() -except OSError as e: - restart_and_reconnect() - -uart = uart_init()#uart初始化 -str1 = b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x06\x06\x02\x00\x01\x00\x10' # 对比储存的一个案例字符串,这里我们默认从1开始 - -spi = SPI(0, baudrate=40000000, polarity=1, phase=0, bits=8, endia=0, sck=Pin(6), mosi=Pin(8)) -display = st7789.ST7789(spi, 240, 240, reset=Pin(11, func=Pin.GPIO, dir=Pin.OUT), dc=Pin(7, func=Pin.GPIO, dir=Pin.OUT)) -display.init() -display.fill(st7789.color565(255, 255, 255)) - - -x = 0 -y = 0 -while True: # 绘制网格界面 - display.vline(x, 0, 240, st7789.color565(255, 0, 0)) - display.hline(0, y, 240, st7789.color565(255, 0, 0)) - x = x + 30 - y = y + 30 - if (x >= 240): - break - -display.draw_string(10, 10, "Welcome", size=4, color=st7789.color565(255, 0, 0)) # 界面初始化 -utime.sleep(0.5) -display.draw_string(10, 60, "to", size=4, color=st7789.color565(0, 0, 255)) # 界面初始化 -utime.sleep(0.5) -display.draw_string(10, 110, "Login", size=4, color=st7789.color565(255, 97, 0)) # 界面初始化 -utime.sleep(0.5) -display.draw_string(10, 160, "Interface", size=4, color=st7789.color565(0, 255, 0)) # 界面初始化 -utime.sleep(4) # 休眠一段时间后进行录入指纹操作 - -for d in range(0, 2): - display.fill(st7789.color565(0, 255, 0)) # 进行交互界面 - - display.draw_string(10, 10, "Function 1:", size=2, color=st7789.color565(61, 89, 171), - bg=st7789.color565(61, 89, 171)) # 界面初始化 - display.draw_string(10, 40, "Input fingerprint", size=2, color=st7789.color565(61, 89, 171), - bg=st7789.color565(61, 89, 171)) # 界面初始化 - display.draw_string(10, 70, "Function 2:", size=2, color=st7789.color565(61, 89, 171), - bg=st7789.color565(61, 89, 171)) # 界面初始化 - display.draw_string(10, 100, "Upload fingerprints", size=2, color=st7789.color565(61, 89, 171), - bg=st7789.color565(61, 89, 171)) # 界面初始化 - display.draw_string(10, 130, "Function 3:", size=2, color=st7789.color565(61, 89, 171), - bg=st7789.color565(61, 89, 171)) # 界面初始化 - display.draw_string(10, 160, "Search for fingerprints", size=2, color=st7789.color565(61, 89, 171), - bg=st7789.color565(61, 89, 171)) # 界面初始化 - display.draw_string(10, 190, "Function 4:", size=2, color=st7789.color565(61, 89, 171), - bg=st7789.color565(61, 89, 171)) # 界面初始化 - display.draw_string(10, 220, "Clear the library", size=2, color=st7789.color565(61, 89, 171), - bg=st7789.color565(61, 89, 171)) # 界面初始化 - - while True: - client.subscribe(topic_sub) - if mymsg!=None: - Mymsg=str(mymsg,'utf-8') - if Mymsg=='1': - client.subscribe(topic_sub) - mymsg=None - display.fill(st7789.color565(65, 105, 225)) # 初始化界面,接下来开始录入部分 - utime.sleep(0.3) - display.draw_string(10, 10, "Start typing fingerprints", size=1, color=st7789.color565(0, 0, 0), - bg=st7789.color565(65, 105, 225)) # 开始录入指纹 - fingerprint1(display, uart) # 手指放在传感器上,过一段时间进行第一次录入 - buffer1(display, uart) # 第一次录入存到buffer1缓冲区,显示传感器是否成功录入指纹 - fingerprint2(display, uart) # 延时一段时间后会进行第二次录入 - buffer2(display, uart) # 第二次录入存到buffer2缓冲区,显示传感器是否成功录入指纹 - break - - elif Mymsg=='2': - client.subscribe(topic_sub) - mymsg=None - display.fill(st7789.color565(160, 32, 240)) # 录入部分结束,再次初始化界面,接下来开始储存部分 - utime.sleep(0.3) - compare(display, uart, str1) # 进行两次指纹录入的对比,若精确度高,则合成模板存入buffer1和buffer2中,延时一段时间后就会自动把模板传入指纹数据库的相应位置 - str1 = bytearray(str1) - i = int(str1[12]) - i += 1 - j = int(str1[14]) - j += 1 - str1[12] = i - str1[14] = j # 相当于从ID=1开始,每一次循环后都会使ID+1,每一次都往后延顺一个用户,这样就可以实现与用户的简单交互 - break - - elif Mymsg=='3': - client.subscribe(topic_sub) - mymsg=None - display.fill(st7789.color565(255, 255, 0)) # 录入及储存部分结束,再次初始化界面,接下来开始搜索部分 - search(display, uart) - break - # 一次循环结束 - display.fill(st7789.color565(0, 200, 0)) # 填充绿色进入休息时间 - display.draw_string(60, 60, 'Thanks', size=4, color=st7789.color565(255, 255, 255)) - display.draw_string(0, 100, 'Please go to', size=4, color=st7789.color565(255, 255, 255)) - display.draw_string(0, 150, 'the next one', size=4, color=st7789.color565(255, 255, 255)) # 每一个用户实现功能之后,会有一个短暂的休息 - utime.sleep(5) - -display.fill(st7789.color565(0, 255, 0)) - -x = 0 -y = 0 -while True: # 绘制网格界面 - display.vline(x, 0, 240, st7789.color565(0, 0, 0)) - display.hline(0, y, 240, st7789.color565(0, 0, 0)) - x = x + 30 - y = y + 30 - if (x >= 240): - break - -display.draw_string(30, 60, 'Thank you', size=4, color=st7789.color565(61, 89, 171), bg=st7789.color565(61, 89, 171)) -display.draw_string(10, 120, 'patronizing', size=4, color=st7789.color565(30, 144, 255),bg=st7789.color565(30, 144, 255)) # 结束 \ No newline at end of file -- Gitee From cffc3462bc2b607362822c613a5ee533589d11ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=9B=E5=A5=B6=E5=91=B3=E6=9B=B2=E5=A5=87?= <9429238+milk-cookies@user.noreply.gitee.com> Date: Mon, 19 Jul 2021 02:15:06 +0000 Subject: [PATCH 16/37] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20AS?= =?UTF-8?q?608/code/AS608.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AS608/code/AS608.py | 146 -------------------------------------------- 1 file changed, 146 deletions(-) delete mode 100644 AS608/code/AS608.py diff --git a/AS608/code/AS608.py b/AS608/code/AS608.py deleted file mode 100644 index 6b4a152..0000000 --- a/AS608/code/AS608.py +++ /dev/null @@ -1,146 +0,0 @@ -from machine import UART, Pin, SPI -import st7789 -import utime - -def uart_init(): - uart = UART(1) - uart.init(baudrate=57600, parity=None, tx=Pin(0), rx=Pin(5)) # 构造串口,启用uart通信协议 - return uart - -def fingerprint1(display,uart): - for i in range(0, 8): # 指令(1):录入指纹 - uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x01\x00\x05') - utime.sleep(1) - dd = uart.read() - print(dd)#测试点 - if dd[9] == 0: # 指纹成功录入 - display.draw_string(10, 50, "School success!", size=3, color=st7789.color565(34, 139, 34), bg=st7789.color565(65, 105, 225)) - break - if i == 7: # 指纹没有录入成功 - display.draw_string(10, 50, "Entry failure!", size=3, color=st7789.color565(255, 125, 64), bg=st7789.color565(65, 105, 225)) - utime.sleep(2) - -def buffer1(display,uart): - for i in range(0, 8): # 指令(2):指纹生成模板存于Buffer1 - uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x04\x02\x01\x00\x08') - utime.sleep(1) - aa = uart.read() - print(aa)#测试点 - if aa[9] == 0: # 成功上传到Buffer1 - display.draw_string(10, 80, "Successfully upload!", size=2, color=st7789.color565(0, 255, 0), bg=st7789.color565(65, 105, 225)) - break - if i == 7: # 无法上传到Buffer1 - display.draw_string(10, 80, "Fail to upload!", size=2, color=st7789.color565(255, 97, 3), bg=st7789.color565(65, 105, 225)) - utime.sleep(3) - -def fingerprint2(display,uart): - for i in range(0, 8): # 指令(1):录入指纹,第二次录入指纹 - uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x01\x00\x05') - utime.sleep(1) - dd = uart.read() - print(dd)#测试点 - if dd[9] == 0: # 指纹成功录入 - display.draw_string(10, 110, "School success!", size=3, color=st7789.color565(34, 139, 34), bg=st7789.color565(65, 105, 225)) - break - if i == 7: # 指纹没有录入成功 - display.draw_string(10, 110, "Entry failure!", size=3, color=st7789.color565(255, 125, 64), bg=st7789.color565(65, 105, 225)) - utime.sleep(2) - -def buffer2(display,uart): - for i in range(0, 8): # 指令(2):指纹生成模板存于Buffer2 - uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x04\x02\x02\x00\x09') - utime.sleep(1) - aa = uart.read() - print(aa) - if aa[9] == 0: # 成功上传到Buffer2 - display.draw_string(10, 140, "Successfully upload!", size=2, color=st7789.color565(0, 255, 0), bg=st7789.color565(65, 105, 225)) - break - if i == 7: # 无法上传到Buffer2 - display.draw_string(10, 140, "Fail to upload!", size=2, color=st7789.color565(255, 97, 3), bg=st7789.color565(65, 105, 225)) - utime.sleep(2) - -def compare(display,uart,str1): - for i in range(0, 8): # 指令(3):对比两次录入指纹的质量 - uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x03\x00\x07') - utime.sleep(1) - aa = uart.read() - print(aa)#测试点 - if aa[9] == 0: # 对比成功,显示匹配度 - if aa[10] + aa[11] > 15: - display.draw_string(10, 10, "It's a good match!", size=2, color=st7789.color565(0, 255, 0), bg=st7789.color565(160, 32, 240)) - display.draw_string(10, 40, "Your match", size=3,color=st7789.color565(0, 0, 0), bg=st7789.color565(160, 32, 240)) - display.draw_string(10, 70, "score is ", size=3, color=st7789.color565(0, 0, 0), bg=st7789.color565(160, 32, 240)) - display.draw_string(10, 100, str(aa[10] + aa[11]), size=4,color=st7789.color565(255, 0, 0), bg=st7789.color565(160, 32, 240)) - else:# 对比成功,匹配度较低 - display.draw_string(10, 10, "The match is", size=2, color=st7789.color565(0, 0, 255), bg=st7789.color565(160, 32, 240)) - display.draw_string(10, 40, "a little bit bad", size=2, color=st7789.color565(0, 0, 255), bg=st7789.color565(160, 32, 240)) - display.draw_string(10, 70, "Your match", size=3, color=st7789.color565(0, 0, 0), bg=st7789.color565(160, 32, 240)) - display.draw_string(10, 100, "score is ", size=3, color=st7789.color565(0, 0, 0), bg=st7789.color565(160, 32, 240)) - display.draw_string(10, 130, str(aa[10] + aa[11]), size=4,color=st7789.color565(255, 0, 0), bg=st7789.color565(160, 32, 240)) - utime.sleep(2) - - for j in range(0, 8): # 指令(5):将Buffer1与Buffer2中的特征文件合并生成模板,结果存于Buffer1与Buffer2。 - uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x05\x00\x09') - utime.sleep(1) - bb = uart.read() - print(bb)#测试点 - if bb[9] == 0: # 传入成功 - display.draw_string(10, 160, "Merger success!", size=3, color=st7789.color565(0, 255, 0), bg=st7789.color565(160, 32, 240)) - break - if j == 7: # 传入失败 - display.draw_string(10, 160, "Merger failure!", size=3, color=st7789.color565(227, 23, 13), bg=st7789.color565(160, 32, 240)) - utime.sleep(2) - - for i in range(0, 8): # 指令(6):将匹配好的指纹储存到指纹库指定位置 - uart.write(str1) #可以自己选择储存的位置,这边只是做一个案例 - utime.sleep(1) - dd = uart.read() - print(dd)#测试点 - if dd[9] == 0:#储存成功 - display.draw_string(10, 190, "Store success!", size=3, color=st7789.color565(0, 255, 0), bg=st7789.color565(160, 32, 240)) - break - if i == 7:#储没有成功 - display.draw_string(10, 190, "Store failure!", size=3, color=st7789.color565(227, 23, 13), bg=st7789.color565(160, 32, 240)) - utime.sleep(2) - - break - if i == 7: # 匹配没有成功,无法存入指纹库 - display.draw_string(10, 30, "Match failure!!!", size=3, color=st7789.color565(255, 0, 0), bg=st7789.color565(160, 32, 240)) - utime.sleep(2) - -def search(display,uart): - for i in range(0, 8): # 搜索指纹(现场自动匹配) - uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x11\x00\x15') # 可以自己选择储存的位置,这边只是做一个案例 - utime.sleep(1) - dd = uart.read() - print(dd)#测试点 - if dd[9] == 0: # 用户搜索成功,返回用户ID以及匹配度 - if dd[10] + dd[11] > 15: - display.draw_string(10, 10, "The search ", size=3, color=st7789.color565(0, 255, 0), bg=st7789.color565(255, 255, 0)) - display.draw_string(10, 60, "is a good match!", size=3, color=st7789.color565(0, 255, 0), bg=st7789.color565(255, 255, 0)) - display.draw_string(10, 120, str(dd[10] + dd[11]) + ", Your match score is ", size=2,color=st7789.color565(0, 0, 0), bg=st7789.color565(255, 255, 0)) - display.draw_string(10, 120, str(dd[12] + dd[13]), size=2,color=st7789.color565(160, 32, 240)) - else: - display.draw_string(10, 10, "Your match ", size=3, color=st7789.color565(255, 0, 0), bg=st7789.color565(255, 255, 0)) - display.draw_string(10, 60, "is not good!", size=3, color=st7789.color565(255, 0, 0), bg=st7789.color565(255, 255, 0)) - display.draw_string(10, 120, str(dd[10] + dd[11]) + ", Your match score is ", size=2,color=st7789.color565(0, 0, 0), bg=st7789.color565(255, 255, 0)) - display.draw_string(10, 120, str(dd[12] + dd[13]), size=2, color=st7789.color565(160, 32, 240), bg=st7789.color565(255, 255, 0)) - break - if i == 7:#搜索失败 - display.draw_string(10, 10, "Search failure!", size=3, color=st7789.color565(240, 230, 140), bg=st7789.color565(255, 255, 0)) - utime.sleep(2) - -def clear(display,uart): - for i in range(0, 8): # 指令(13):清空指纹库 - uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x0d\x00\x11') - utime.sleep(1) - aa = uart.read() - print(aa)#测试点 - if aa[9] == 0: #清空成功 - display.draw_string(10, 230, "Empty the success!", size=1, color=st7789.color565(0, 0, 0)) - break - if i == 7: #清空失败 - display.draw_string(10, 230, "Empty the failure!", size=1, color=st7789.color565(0, 0, 0)) - utime.sleep(2) - -print(1)#判断库是否调用正确的一个测试点 \ No newline at end of file -- Gitee From 8b38bbc77ba7017e2c2dcc6b8ceb13b403edd21a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=9B=E5=A5=B6=E5=91=B3=E6=9B=B2=E5=A5=87?= <9429238+milk-cookies@user.noreply.gitee.com> Date: Mon, 19 Jul 2021 02:15:57 +0000 Subject: [PATCH 17/37] =?UTF-8?q?=E4=B8=BB=E5=87=BD=E6=95=B0=20=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=E7=94=A8=E6=88=B7=E4=B8=8E=E8=AE=A1=E7=AE=97=E6=9C=BA?= =?UTF-8?q?=E4=BA=A4=E4=BA=92=E7=9A=84=E7=B3=BB=E7=BB=9F=E7=95=8C=E9=9D=A2?= =?UTF-8?q?=EF=BC=8C=E5=AE=9E=E7=8E=B0=E4=B8=80=E7=B3=BB=E5=88=97=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AS608/code/Main.py | 167 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 AS608/code/Main.py diff --git a/AS608/code/Main.py b/AS608/code/Main.py new file mode 100644 index 0000000..3d8f122 --- /dev/null +++ b/AS608/code/Main.py @@ -0,0 +1,167 @@ +from machine import UART, Pin, SPI +import st7789 +import utime, network +from AS608 import uart_init, fingerprint1, buffer1, fingerprint2, buffer2, compare, search, clear +from MQTT import MQTTClient + + +#MQTT交互程序设计 +global Mymsg +mymsg=None + +wl = network.WLAN(network.STA_IF) +wl.active(1) +wl.connect('LAPTOP-8FIJU2IS 3092',';F23595m',security=network.AUTH_PSK) + +client_id = "xcy" +mqtt_server = "thingworx.zucc.edu.cn" +port=1883 +topic_sub = "xucongyu" +topic_pub = "xucongyu" +mqtt_user = "" +mqtt_password = "" + +def sub_cb(topic, msg): + global mymsg + mymsg=msg + #print((topic, msg)) + #client.publish(topic_pub, msg) + +def connect_and_subscribe(): + global client_id, mqtt_server, topic_sub, mqtt_user, mqtt_password + client = MQTTClient(client_id, mqtt_server, user=mqtt_user, password=mqtt_password,port=port) + client.set_callback(sub_cb) + client.connect() + client.subscribe(topic_sub) + print('Connected to %s MQTT broker, subscribed to %s topic' % (mqtt_server, topic_sub)) + return client + +def restart_and_reconnect(): + print('Failed to connect to MQTT broker. Reconnecting...') + utime.sleep(10) + machine.reset() + +try: + client = connect_and_subscribe() +except OSError as e: + restart_and_reconnect() + + +uart = uart_init()#uart初始化 +str1 = b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x06\x06\x02\x00\x01\x00\x10' # 对比储存的一个案例字符串,这里我们默认从1开始 + +spi = SPI(0, baudrate=40000000, polarity=1, phase=0, bits=8, endia=0, sck=Pin(6), mosi=Pin(8)) +display = st7789.ST7789(spi, 240, 240, reset=Pin(11, func=Pin.GPIO, dir=Pin.OUT), dc=Pin(7, func=Pin.GPIO, dir=Pin.OUT)) +display.init() +display.fill(st7789.color565(255, 255, 255)) + +flag=0#构建退出程序的标志 + +x = 0 +y = 0 +while True: # 绘制网格界面 + display.vline(x, 0, 240, st7789.color565(255, 0, 0)) + display.hline(0, y, 240, st7789.color565(255, 0, 0)) + x = x + 30 + y = y + 30 + if (x >= 240): + break + + +display.draw_string(10, 10, "Welcome", size=4, color=st7789.color565(255, 0, 0)) # 界面初始化 +utime.sleep(0.5) +display.draw_string(10, 60, "to", size=4, color=st7789.color565(0, 0, 255)) # 界面初始化 +utime.sleep(0.5) +display.draw_string(10, 110, "Login", size=4, color=st7789.color565(255, 97, 0)) # 界面初始化 +utime.sleep(0.5) +display.draw_string(10, 160, "Interface", size=4, color=st7789.color565(0, 255, 0)) # 界面初始化 +utime.sleep(4) # 休眠一段时间后进行录入指纹操作 + + +while True: + display.fill(st7789.color565(0, 255, 0)) # 进行交互界面 + + display.draw_string(10, 10, "Function 1:", size=2, color=st7789.color565(61, 89, 171), + bg=st7789.color565(61, 89, 171)) # 界面初始化 + display.draw_string(10, 40, "Input fingerprint", size=2, color=st7789.color565(61, 89, 171), + bg=st7789.color565(61, 89, 171)) # 界面初始化 + display.draw_string(10, 70, "Function 2:", size=2, color=st7789.color565(61, 89, 171), + bg=st7789.color565(61, 89, 171)) # 界面初始化 + display.draw_string(10, 100, "Upload fingerprints", size=2, color=st7789.color565(61, 89, 171), + bg=st7789.color565(61, 89, 171)) # 界面初始化 + display.draw_string(10, 130, "Function 3:", size=2, color=st7789.color565(61, 89, 171), + bg=st7789.color565(61, 89, 171)) # 界面初始化 + display.draw_string(10, 160, "Search for fingerprints", size=2, color=st7789.color565(61, 89, 171), + bg=st7789.color565(61, 89, 171)) # 界面初始化 + display.draw_string(10, 190, "Function 4:", size=2, color=st7789.color565(61, 89, 171), + bg=st7789.color565(61, 89, 171)) # 界面初始化 + display.draw_string(10, 220, "Clear the library", size=2, color=st7789.color565(61, 89, 171), + bg=st7789.color565(61, 89, 171)) # 界面初始化 + + while True: + client.subscribe(topic_sub) + if mymsg!=None: + Mymsg=str(mymsg,'utf-8') + if Mymsg=='0':#记录到0的时候退出程序 + flag=1 + break + + if Mymsg=='1':#开始指纹录入 + client.subscribe(topic_sub) + mymsg=None + display.fill(st7789.color565(65, 105, 225)) # 初始化界面,接下来开始录入部分 + utime.sleep(0.3) + display.draw_string(10, 10, "Start typing fingerprints", size=1, color=st7789.color565(0, 0, 0), + bg=st7789.color565(65, 105, 225)) # 开始录入指纹 + fingerprint1(display, uart) # 手指放在传感器上,过一段时间进行第一次录入 + buffer1(display, uart) # 第一次录入存到buffer1缓冲区,显示传感器是否成功录入指纹 + fingerprint2(display, uart) # 延时一段时间后会进行第二次录入 + buffer2(display, uart) # 第二次录入存到buffer2缓冲区,显示传感器是否成功录入指纹 + break + + elif Mymsg=='2':#开始指纹传送功能 + client.subscribe(topic_sub) + mymsg=None + display.fill(st7789.color565(160, 32, 240)) # 录入部分结束,再次初始化界面,接下来开始储存部分 + utime.sleep(0.3) + compare(display, uart, str1) # 进行两次指纹录入的对比,若精确度高,则合成模板存入buffer1和buffer2中,延时一段时间后就会自动把模板传入指纹数据库的相应位置 + str1 = bytearray(str1) + i = int(str1[12]) + i += 1 + j = int(str1[14]) + j += 1 + str1[12] = i + str1[14] = j # 相当于从ID=1开始,每一次循环后都会使ID+1,每一次都往后延顺一个用户,这样就可以实现与用户的简单交互 + break + + elif Mymsg=='3':#开始指纹搜索功能 + client.subscribe(topic_sub) + mymsg=None + display.fill(st7789.color565(255, 255, 0)) # 录入及储存部分结束,再次初始化界面,接下来开始搜索部分 + search(display, uart) + break + + if flag==1: + break + # 循环结束,退出程序 + display.fill(st7789.color565(0, 200, 0)) # 填充绿色进入休息时间 + display.draw_string(60, 60, 'Thanks', size=4, color=st7789.color565(255, 255, 255)) + display.draw_string(0, 100, 'Please go to', size=4, color=st7789.color565(255, 255, 255)) + display.draw_string(0, 150, 'the next one', size=4, color=st7789.color565(255, 255, 255)) # 每一个用户实现功能之后,会有一个短暂的休息 + utime.sleep(5)#继续循环执行功能 + + +display.fill(st7789.color565(0, 255, 0))#开始结束界面的构建 + +x = 0 +y = 0 +while True: # 绘制网格界面 + display.vline(x, 0, 240, st7789.color565(0, 0, 0)) + display.hline(0, y, 240, st7789.color565(0, 0, 0)) + x = x + 30 + y = y + 30 + if (x >= 240): + break + +display.draw_string(30, 60, 'Thank you', size=4, color=st7789.color565(61, 89, 171), bg=st7789.color565(61, 89, 171)) +display.draw_string(10, 120, 'patronizing', size=4, color=st7789.color565(30, 144, 255),bg=st7789.color565(30, 144, 255)) # 结束 \ No newline at end of file -- Gitee From 1cb63da9d7edc7f6e207d8dd9f15af3e9c8686db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=9B=E5=A5=B6=E5=91=B3=E6=9B=B2=E5=A5=87?= <9429238+milk-cookies@user.noreply.gitee.com> Date: Mon, 19 Jul 2021 02:16:35 +0000 Subject: [PATCH 18/37] =?UTF-8?q?AS608=E7=9A=84=E4=B8=BB=E8=A6=81=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=BA=93=20AS608=E9=83=A8=E5=88=86=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E7=9A=84=E5=BA=93=EF=BC=8C=E7=94=A8=E4=BA=8E=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E7=9B=B8=E5=BA=94=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AS608/code/AS608.py | 146 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 AS608/code/AS608.py diff --git a/AS608/code/AS608.py b/AS608/code/AS608.py new file mode 100644 index 0000000..163313e --- /dev/null +++ b/AS608/code/AS608.py @@ -0,0 +1,146 @@ +from machine import UART, Pin, SPI +import st7789 +import utime + +def uart_init(): + uart = UART(1) + uart.init(baudrate=57600, parity=None, tx=Pin(0), rx=Pin(5)) # 构造串口,启用uart通信协议 + return uart + +def fingerprint1(display,uart): + for i in range(0, 8): # 指令(1):录入指纹 + uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x01\x00\x05') + utime.sleep(1) + dd = uart.read() + print(dd)#测试点 + if dd[9] == 0: # 指纹成功录入 + display.draw_string(10, 50, "School success", size=3, color=st7789.color565(34, 139, 34), bg=st7789.color565(65, 105, 225)) + break + if i == 7: # 指纹没有录入成功 + display.draw_string(10, 50, "Entry failure", size=3, color=st7789.color565(255, 125, 64), bg=st7789.color565(65, 105, 225)) + utime.sleep(2) + +def buffer1(display,uart): + for i in range(0, 8): # 指令(2):指纹生成模板存于Buffer1 + uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x04\x02\x01\x00\x08') + utime.sleep(1) + aa = uart.read() + print(aa)#测试点 + if aa[9] == 0: # 成功上传到Buffer1 + display.draw_string(10, 80, "Successfully upload", size=2, color=st7789.color565(0, 255, 0), bg=st7789.color565(65, 105, 225)) + break + if i == 7: # 无法上传到Buffer1 + display.draw_string(10, 80, "Fail to upload", size=2, color=st7789.color565(255, 97, 3), bg=st7789.color565(65, 105, 225)) + utime.sleep(3) + +def fingerprint2(display,uart): + for i in range(0, 8): # 指令(1):录入指纹,第二次录入指纹 + uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x01\x00\x05') + utime.sleep(1) + dd = uart.read() + print(dd)#测试点 + if dd[9] == 0: # 指纹成功录入 + display.draw_string(10, 110, "School success", size=3, color=st7789.color565(34, 139, 34), bg=st7789.color565(65, 105, 225)) + break + if i == 7: # 指纹没有录入成功 + display.draw_string(10, 110, "Entry failure", size=3, color=st7789.color565(255, 125, 64), bg=st7789.color565(65, 105, 225)) + utime.sleep(2) + +def buffer2(display,uart): + for i in range(0, 8): # 指令(2):指纹生成模板存于Buffer2 + uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x04\x02\x02\x00\x09') + utime.sleep(1) + aa = uart.read() + print(aa) + if aa[9] == 0: # 成功上传到Buffer2 + display.draw_string(10, 140, "Successfully upload", size=2, color=st7789.color565(0, 255, 0), bg=st7789.color565(65, 105, 225)) + break + if i == 7: # 无法上传到Buffer2 + display.draw_string(10, 140, "Fail to upload", size=2, color=st7789.color565(255, 97, 3), bg=st7789.color565(65, 105, 225)) + utime.sleep(2) + +def compare(display,uart,str1): + for i in range(0, 8): # 指令(3):对比两次录入指纹的质量 + uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x03\x00\x07') + utime.sleep(1) + aa = uart.read() + print(aa)#测试点 + if aa[9] == 0: # 对比成功,显示匹配度 + if aa[10] + aa[11] > 15: + display.draw_string(10, 10, "It's a good match", size=2, color=st7789.color565(0, 255, 0), bg=st7789.color565(160, 32, 240)) + display.draw_string(10, 40, "Your match", size=3,color=st7789.color565(0, 0, 0), bg=st7789.color565(160, 32, 240)) + display.draw_string(10, 70, "score is ", size=3, color=st7789.color565(0, 0, 0), bg=st7789.color565(160, 32, 240)) + display.draw_string(10, 120, str(aa[10] + aa[11]), size=4,color=st7789.color565(255, 0, 0), bg=st7789.color565(160, 32, 240)) + else:# 对比成功,匹配度较低 + display.draw_string(10, 10, "The match is", size=2, color=st7789.color565(0, 0, 255), bg=st7789.color565(160, 32, 240)) + display.draw_string(10, 40, "a little bit bad", size=2, color=st7789.color565(0, 0, 255), bg=st7789.color565(160, 32, 240)) + display.draw_string(10, 70, "Your match", size=3, color=st7789.color565(0, 0, 0), bg=st7789.color565(160, 32, 240)) + display.draw_string(10, 100, "score is ", size=3, color=st7789.color565(0, 0, 0), bg=st7789.color565(160, 32, 240)) + display.draw_string(10, 150, str(aa[10] + aa[11]), size=4,color=st7789.color565(255, 0, 0), bg=st7789.color565(160, 32, 240)) + utime.sleep(2) + + for j in range(0, 8): # 指令(5):将Buffer1与Buffer2中的特征文件合并生成模板,结果存于Buffer1与Buffer2。 + uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x05\x00\x09') + utime.sleep(1) + bb = uart.read() + print(bb)#测试点 + if bb[9] == 0: # 传入成功 + display.draw_string(10, 160, "Merger success", size=3, color=st7789.color565(0, 255, 0), bg=st7789.color565(160, 32, 240)) + break + if j == 7: # 传入失败 + display.draw_string(10, 160, "Merger failure", size=3, color=st7789.color565(227, 23, 13), bg=st7789.color565(160, 32, 240)) + utime.sleep(2) + + for i in range(0, 8): # 指令(6):将匹配好的指纹储存到指纹库指定位置 + uart.write(str1) #可以自己选择储存的位置,这边只是做一个案例 + utime.sleep(1) + dd = uart.read() + print(dd)#测试点 + if dd[9] == 0:#储存成功 + display.draw_string(10, 190, "Store success", size=3, color=st7789.color565(0, 255, 0), bg=st7789.color565(160, 32, 240)) + break + if i == 7:#储没有成功 + display.draw_string(10, 190, "Store failure", size=3, color=st7789.color565(227, 23, 13), bg=st7789.color565(160, 32, 240)) + utime.sleep(2) + + break + if i == 7: # 匹配没有成功,无法存入指纹库 + display.draw_string(10, 30, "Match failure", size=3, color=st7789.color565(255, 0, 0), bg=st7789.color565(160, 32, 240)) + utime.sleep(2) + +def search(display,uart): + for i in range(0, 8): # 搜索指纹(现场自动匹配) + uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x11\x00\x15') # 可以自己选择储存的位置,这边只是做一个案例 + utime.sleep(1) + dd = uart.read() + print(dd)#测试点 + if dd[9] == 0: # 用户搜索成功,返回用户ID以及匹配度 + if dd[12] + dd[13] > 15: + display.draw_string(10, 10, "The search ", size=3, color=st7789.color565(0, 255, 0), bg=st7789.color565(255, 255, 0)) + display.draw_string(10, 60, "is a good match", size=3, color=st7789.color565(0, 255, 0), bg=st7789.color565(255, 255, 0)) + display.draw_string(10, 120, str(dd[10] + dd[11]) + ", Your match score is ", size=2,color=st7789.color565(0, 0, 0), bg=st7789.color565(255, 255, 0)) + display.draw_string(60, 170, str(dd[12] + dd[13]), size=4,color=st7789.color565(160, 32, 240), bg=st7789.color565(255, 255, 0)) + else: + display.draw_string(10, 10, "Your match ", size=3, color=st7789.color565(255, 0, 0), bg=st7789.color565(255, 255, 0)) + display.draw_string(10, 60, "is not good", size=3, color=st7789.color565(255, 0, 0), bg=st7789.color565(255, 255, 0)) + display.draw_string(10, 120, str(dd[10] + dd[11]) + ", Your match score is ", size=2,color=st7789.color565(0, 0, 0), bg=st7789.color565(255, 255, 0)) + display.draw_string(60, 170, str(dd[12] + dd[13]), size=4, color=st7789.color565(160, 32, 240), bg=st7789.color565(255, 255, 0)) + break + if i == 7:#搜索失败 + display.draw_string(10, 10, "Search failure", size=3, color=st7789.color565(255, 0 , 0), bg=st7789.color565(255, 255, 0)) + utime.sleep(2) + +def clear(display,uart): + for i in range(0, 8): # 指令(13):清空指纹库 + uart.write(b'\xEF\x01\xFF\xFF\xFF\xFF\x01\x00\x03\x0d\x00\x11') + utime.sleep(1) + aa = uart.read() + print(aa)#测试点 + if aa[9] == 0: #清空成功 + display.draw_string(10, 230, "Empty the success", size=1, color=st7789.color565(0, 0, 0)) + break + if i == 7: #清空失败 + display.draw_string(10, 230, "Empty the failure", size=1, color=st7789.color565(0, 0, 0)) + utime.sleep(2) + +print(1)#判断库是否调用正确的一个测试点 \ No newline at end of file -- Gitee From a77b9c7373a85555ba8f8efaac99d3c348185476 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=9B=E5=A5=B6=E5=91=B3=E6=9B=B2=E5=A5=87?= <9429238+milk-cookies@user.noreply.gitee.com> Date: Mon, 19 Jul 2021 02:25:38 +0000 Subject: [PATCH 19/37] =?UTF-8?q?AS608=E5=AE=9E=E7=89=A9=E5=9B=BE.JPG=20AS?= =?UTF-8?q?608=E5=AE=9E=E7=89=A9=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...08\344\274\240\346\204\237\345\231\250.jpg" | Bin 0 -> 214508 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 "AS608/image/AS608\344\274\240\346\204\237\345\231\250.jpg" diff --git "a/AS608/image/AS608\344\274\240\346\204\237\345\231\250.jpg" "b/AS608/image/AS608\344\274\240\346\204\237\345\231\250.jpg" new file mode 100644 index 0000000000000000000000000000000000000000..5b38ea2e277f4bfa8dbc4c04d571409663fc7b69 GIT binary patch literal 214508 zcmbTdc~nw+*aphrh(iu&ie_qNKxvXVl$vOQh@uQmajYE5fYKaJrZ(YNZM9G-4b6zr zv7@DB<1tG!i&DUjIUTdI)NE4gG@WyI-*?x&Yu&%@z1t-s8}{P;4e$HB&-3j6hX0#{ zm{3R|BnT7=fk43@$bX}dEf9pRuAZ(ALQhZ60D&+twlXm`GBRFaVQFf$YUOGt$CZu_ z&TGBaJ7e$|2S>L69DbwE=FOW|y9R}9@g;ltZT9(f5h%jIz}U#x*2Kit2knUV`TuI_2T8L z>DO;&W
O0{)!6bH@#NddR@?3vGAwSGhAjSR`f)A}pQo&sTr^725wq_Wv%h{QqB({a=Co
z-*JsV4B=34^5CWrf5_}YM2x(YhKwo9z3R+-A3mX*TVl(kbU-t@1Ppu!qCt^InX!44cGp_@$F+w%ocdhYK-%So2}ys+{NjMXF!V
*ZJG_Th%{$zGdMep=`t!S7uu*x6
znnmQ|Jg{7NTSI!=0Z(>cW9wMXaXm$T=GIJ$L>h^64;~i4;Nc>9r;xoCIQUcX{tF_<
zJBoUIO*m%~MFtxp9
t$MXn)uf;Z!gsu`Q6U(_7pqKe~_xD{CROtT=L)yIg0a-)LYy|ip*7K
z0hI |rrKFBlW!*d?=)dCNZ%`DV$b!c)$mj3+vl8B#zo^1&~fDCNJr
z(`aZH!dsqPg@-6CtQE
Of)I~868(IFYURq)cIt$7QhV~M**1}%Ali(H zj5E#5o0?h$-mgA|{8mVxF8W8W^Lm=k)>uAA&Mx*QnUnt!;xo!ak~zh1i}hFF zY+mQ}6jLK~x!+h$pQki`wy^bjMyAlb%QC}EOC>zTX+wXzGzUbQ5oLYBJR)#&mJzsq z?*RyBR~IzZL%?fwjCm*2-XUt*n{?&;?SjU;6br~}uEh9qPX LIEEzQ8&iu9-YPgPvq* zt #!<=&E&w=7@S*<)ezg#zc!R6Hie z_*2`uY{5U!9z7dni=l6-KikY__}V4sniI+Ix;Q wG*O`|hgqJCs>bwVw z5rgc~!5g$?E!g9%t+|YPs~0q9octfT1Z2OW{}`L}g=X!EiN|rB^cRXXTQ}Vte0fCw z(@a}Bk-3@+=ZD4?tdU^HdvMs+G%N^`6R}Py(zA4lIdn+u(tC6#G&|SF`RUoukDru3 zCOs;cQwcd{Hcw}sI*)Drgsp4AJh%Ya+9N3co#IrOkMF)`MLgc*PPZ}lw9Oj6!oD6a zmO~}}`p70WRWg2)wXxFR^N)Y$cWSmd=lOePm)3% zh|^uQ^l97a y2 zUOvH?)g^5uyi@!kiS)~w4iNg3)01#%r4r|E7pfgJ&aINA;!UFB&J*xfnTD&jCm@d` zc(FOK1WKpEd0Q?2M38$AZBeDJc`~}=Rq{A$D{ZEnt(ar4`O6(q@9zQ!vElx +YA z?sU!c$4Rh@X`Zjvm;cz|FXDOoeMu}==h^zFxQ^-HdpX&+4`#jz3x{)8$i;3Pmw$ff zmh&oNj?;IYf&Im7VarEgEU~|}0oC|OShAdt&+7GL%)UkWr^LuUWTBh(PWP;6?BpCP zjCVSCN}pjdRf2FqCz+TvDoFoOMK1>I6 Zge{53t+^|OrEpUu~l{H@N80VpS`+wrqy=h 6>leqJp?rn8T>PnY! z?*$(5l!dnbk2pq#>d$9d8y2A}+3ztcwX|CI0Rw^Npl7dMf}0yjXjdUNJYiuRF_td< zoa!fcu>J2SdskCVXVQ^pJgKJY^>R+Hd@-c&XelU2%`@sKmQO1`3Vefbk#fh6hX>*- zHRgyKw>Dw HY`Yrrt;SSQx8Q1Nh~BBJG^ZlO{W_Q%BM==I+8sPSiG$jCCtUH2C!3 z^sj-sHi?8T-R^<`2{K!dGN^|m#-!!2Z;Nn>wY%>@hpk=g+Ro+GRNqrz?pU?g8E^K~ z@h#$xD%MYh=8QInJ|gk&cY^ Z&{tmvr#WTx*CRbkP8g^u?GZ zN<7s{-&rC=Q-+}ff-7zanZSLmG&`Shc#k0A;9eE*#!uf*4SEl*F;#yTpUG_0wbO5M ze~fcnpe&7c_;V4WEi3bnWj-oy{m5j5&XuCFibM#;;s@W6E8}v_ssgvZAfT7Cm6m)I zD}}8VFZcI#az8cO^)^VnLp_18qXgG_4t2>TDtxxFU~2I`RD5J2a#}N0zhRS^`g60} zI($^UhA?9iEcv2?P!$iuGA4+3P+(;F1U1BJ6~(J{^WP94uM}#P0Kzqyx#M9#2Qiqt z*tTgh!=#CS7VYvZSymhvPk&ZE>}yM|&!bN`n^~(K8K2-1neiLV+IaT{!qs6mzuqlU z=)@Q>73&pY5y`Mv*nOxKz2(c>MMh3v{iLf3vr}*P{yg9{GUH&dt?KPVd~OIV^9>Xi zf}x+hhQ%_IQ-tS7&cyTnW7b~mqAy}1+%Uvy#f6dwFX8Jl{|I=wmc-AysskH~`Slsy zXiv0lJXBi>t#H@>;o;Ce?CvN!-VWJ>iq@4Ysn!il5qN}*$iHc__`yMd36Z2vJ)$Z{ zLCyrc>Zg>@mGWsBk-5J Ipjl0PWn$GjLR5%h);8VsC&oQ7S;<`vw+%`b z-$(j!&o+J;DBwrbIfWTq0rPRW1yiyAn(cZ nop=%sEyMJ?YStTq$z#odZ-jKJF?Dz zN~TMx+*dy_hU%^L2d&^LOO1Vt5N7* 6&7Xl`B_Wj* zvzb)Q;#>STTEt${`jOK^(X|p%qJMVPoV0Xt%^VihJQW&dj<_{7y?T@0Eoen@eC+`+ zj!cNi`lVnmW?o6)J5pF7omoGE%2A4}A9##>-@09N2Qx~#WaeT{4i)V)&ilXApciFY zCEd)q#5ff()k5&!mG$`9h62mvgZr$Ud^r9evQFv66H?$o;{1LVDBsksQI9{tfJP?O zL9IXuoh~Ir*M2E^T!hjHq5O46mvoE|expU;@LVEx6-V+3F+1k8M3ZGq0Ff~Q%$G1E zWx@cRflUCnOlCt Qq<(MYRjzMcY%2xXEBMMV5dQg4EU+9mM;>kbMDO!D0wl3L=r>ePr N`VLUj zQRpNPAoI#%$nG+Fdo6{r5|S@6+9+)^jNVMuPl2s8x - z5_wdf&nCA-4GBv;@e~&7tppy+hp)HdoQpM(6<{>-_b#od U-cbl%lPkRSj(;RxU3OILbwy#&aV4{ z4sD*%;uTFLE$)Lr^&&1?9%l$yhxiYzu<$l)- |PQAJcA+|i*4p61(h38z~)_me? zy7`UF)fOEHMVv?uSq22_yLRL8>A?A|U0_I#-%I8{%VCuO6)V^Ji@pl93+S7x7O|<$lD*}}{0MCySvGS0 zhHtHP|FV6gY|iGHALf#_l_)iN_akBt6ASyqA9%;o*G1`9k-C92R3c<(84-GrqKx 3B-_!J37 zUz02E;fo*0yx-S{oGiaCG_%IE8N5?q!tXw)du2Ey_f&mg?TrkdG#r|VRGrq y76yxB|c*~J^Z14-lU@vqq$KmwiK8xNbT$tfcP_b>sG^8>KAi_ z`tkbyM+Y#)@7tKm$4|7I&xQ7-igrfqoi<^^wWC;6Hk8?dKwbn{oG!rr_SydV)Q`)B zGfX{ooSv!d)Qn+yQ^U~cCs)b5oPY>nZ|E~TC_e_0zTB#c|LF7A-ZM_14+~tziyb?~ zx$)=VvqujxpFiZ%jwC40%wLv zuQW%RXPQ~ampub{G+#eoZ?~6O_i1)fAGchixEO>aismlI!QS=E5w1zN2KRgQjfs2L z?){IzKM^av6A$NF>*@xrCeI*a&C}k+;a3YKuGpTSK*U;U) g7JhJA{8n7oLTp{4=%85}$`>@{vGe2P>j_TsGF z6bw?V+%BS$R6N!2XLt`h?P`tv)83)?Jd;0@J;Z9 zvcQMyy~b;j6h=$Y*t+L^Oh)zw-y3!HPAg}(xhJM>HxJ 7!zpvoV-#ekUl2hOc4cJ<8BzX8ijT)~N zR@-j_kD}XEp?>dTuXY%CB0F6DgSP3CD=1syYZCK@qQYz5l=q|!(nJn4t?!MF?QwhI zl4F#^cQb668b`bv=4a#eRB0eZST8h566A@bJ8>=TFwv&q5b(G7T`GsK8|*R@=JnNu zBR`@lRR7jgzXLTIYk_kC0EDP?dQ;r>)MWjq@|8TENT3n1=%8 g4V}md&_Nx3rT#4Lvr7W-8;TADJf5n%Oj?Zp|D#0&RDMobBUrO$4iH#2t#wQmZ zMCBA|l{yztQujE8mkny>N!7#=c-F(41@_7kGDhmAM#0j|s9{m1s?PeYz?96$Xv%rD z^AbR$+(K$C<0%Q-G<(NNRQC-*0EZdckOkrc+AO8eF@qd`1sQmPOUNJG7Y{oxi4?zU zUN6T{z-$;DoDwq|^@ixj0A&>s)vH&9T~)bmzL|9tw&5{J@-9 yPN|*Jl_=Dg&s>6+%pJaczX6k*1 ?>!8IYxZs 4VZgWrMNu(Lzpm?(|!ro7U0V9L(>)OQxV#@ zL_L42LSRqcDB_v47?=bD_o0dxl_43%qy*QPAKU4w(jJF4yeE#Boe*TR63u3WmJ9Cc zl81e^O~yb(VdoW@ mjmzfym7` {8mz5rS^YI?HvLGI z)xyT-W3ZIufwbovgF{6N_&MFldd`?x=(BP3!ri1M2h_U*tK`kpm}n*3Yh?$?TBQ08 z`LqRyG}>rN;2g(Od?>^I2am+I_+A}kn$b=9T$HfR_~~JZJ&U#;PIiFkt?`ct%{yj| zebcKX8e4Ub0r--f&YdA_*h1xbgb9#Jloeg%c!r@VI$es re zizTeTPrVusv?A0@iUk5eWDOYl8DFmC-V`;v>ho~LB#U>wC~E?9$ssYt%m;A~xSnjI z2rn{Ss^s$34<(dyi^r1)pn Lq0!f4;EtayonvR@W7S^G~N&FUo?*p-rDdE(M zrsKf20yVI3GZ4t3-%x^itUE;La63~3+PIipG@YpvAWraapH)dusP@~ca-CI8Agfo< z8pzhPuWt#KJ4>B@eO?gGMbeDWRxNTY4?C@H;BJ|)%m_P0|3F#ZeH&%a#O$$M)Knu; z!2z!zGN%%#ANi*~xfNv&(VVsc ZeNwai`JVVZOQq1b`1zmf<1_G2|^gODUy^CXo{53B`+{@ z)gm?5pCIY%2ZmMen*uAYUQCewBNS;+4*Didgr=z~;eLTfNFy?%ka5R`!OSk`KZ2C# zej+E;>D3upEQu-&AIf74#7&FT58^} (29CO)I_v&WA z>&lwp7?RPjGudNV{XstQ{X4pN*_!=S+C}yIJln1LwNLkU3QyQeaE3?x0R%ukyy*kF zIbYuM8!+36o9UwFNukqr;6;j3GAw09=g_iziq~f*6Ne7LStD40i+VhY8M?U5)xakb za3XCNsqJXS&+%=`mgjt-^Y3Fv48mA&Gr0#{2t6NC=O|>kblFI#)CN_C;^IPFI|_bJ z@S?#SGcDoANVUy7^K7=t;59efo$3^N-@x%A*ZV)cf~<9pVbI#%;(j}gr@BABAoyA{ zFCd C z>njo4I`nzFRbL*v=d%ByeNo=(jSz%|lk_^>p0-D$A!l~ePd+#qXWuHyLNVJxE!Mj& zEcG^H*Z$?Fd{%vcN$YvF0jo!Zm8M_QoCg1!{D{2lb`w=)lk#2LJBY-jDRg@>1*kBn zrjJr#iE7y#xxm==v90n2rqZQTlNA!cup-eEo5l_qL$E=z%`Azc_AN#RL4gy$f-1`? z0;BBym9O7~5)t(%&-|Q|pP3mC(S0pna-x_ZtcN`Se~z6Ds2wjhIj$XTvkteC3Bx_J z&uG^e6W4}9a(r#at!=xYAZrn19b;;K#vX!832Gp<*9Izv%wgP_rI!L~+8=bp9$BD# zLMxed0*!Qs_wB{ef%@Jlyam(07aLQugoy $l2=-PL;yAo=fK zK4s}0*`3N(+J-n^RNq;f3v{(yrk1uI^fztPR+#lq&%dl>N$qkz3q?hQ%um@^HBuGH zP$X@Cn1C3j>`%<}(P&f_abYzKtIwsDlOkr=oAed%ELAT(aZ-Mj!?QRKVM+H|!*rF4 zYVN~~*P)Z=Ro{-8rxqOVoHvhc>QNlSO4027cGuthUcZ_8XqP^Nlk+Q#S+tVZ%*y#^ z`>I)>6Ra}(A7EqVYibkQp%I-?1S;XosQ+nOm-2_>)NEBmMrihyF)8!68`i@aYR>xn ze_^Nrw0LT1NS#M2{nM0Q?A!jiye%!Ke5TK>@QPW-Tk`sIS^kL^XOr``p)F5kV%d}7 zVn|?0F#AB~?|$%~CcJNM_-q;`#-2>jN{Rj71CJ*-v7c(QwJtZ4{6C)t5afeWYa!zQ z_-?C%49G{PtIH>n&kH%O%1L%jKkNpazN~1KcrEac+l&v(7sgk;7ix1b#{Kq->VeDD z;j_PX`>+bU@$dF#$BK#{D^(d54x!=WHd=BoB<0ugEmF1y33WdleM9=|_=;4R&k?GT z4UIh#)e4v%-g_T=7$4?6dhE*ik2!pIJc4=gV`roDpL>=C qTY!%Gj4Xn&32q&DzbI-HZ(Y1ks!Dg{@1r<~KkLNJ^2Ay-K zlt{~GivnXK_f|2#&)0hYWfjXL@G$kh%G&+Bu+p1xBk}}?T$HP^GDpG6zHzipVv~xO zKeA=%)$$tQW)8(lyZ@S4=yi&CT#b5uYYx(pi=He9?5#^k8|3Zp@JY_2{I}chy}Kek z+cZn&W2?p9JqVe%yX0aRRznWA{#JbZt{Qb1@2OTh%EoL@T`RQy#mmCi$yI4t=)=?t zPs}r-4~LQw67P9(dKvEa4yuQ`oj=TdODt6C27G4DpOAhefuJ2NsV1fg&y_Ns18szd zoX=!SkKBgO8DlS_uf#=ZQLmqt-VXR=rd;;1q|A^k2(d*s90oPL@Zn*edTXLRI7;oy zswH x#1823l4d@ptaB3OQN z+#GDSTd8A=Z~P?{>ktac+^gi4iAG)8L_@Yr e=llN z_eg(q(&1Ro #yRksSG50DQ5iN9@1-n`21%QK3rX; z^1?E3w_hIPZZDA#DHI;ssd%dEc{kTUGw3d^l*5O;(Eq9I^hd3FHrtv-eOtR?{moAE zke@3bNP6dBb}pw1aK~fde*k1)U5Ffi7w4);INlwCPu47p(UM5i0-ESy;euvK@+qDR zO?On96{VwCSu5_-*d7bHe@C8*CD?Xo1@b1P1nWz_J+gYhG`` oFL0Y@(0sf)SLf@ z?EKo~&NosE%8c;JRevMVx;6mPVdyaZ$bj(eWtF+H7oe@`kmV}^(#wI%SJL8Dgu6-p zjY)AZ0XA U!sFbyt#>jKh9>73jKM}dR9V|M X@|o{vxs>w?`p|G}UxAk~S*3`>;f|` OG 3(}G0zqdj9% zL_q&G{69cML7nHf0rU2@@9Hn_A84y|8PlcOI#pj(5wlw5e|7$_9(REm04t>yHLaov z)*V3(^N>{ikgrSlhmQc_!zo!z1yc(f2M9?bMc7gqECV8+j;x8C?q>d=2T%H9ZZlMA zs}AMo&`n4C+IqMt?I}ZLT`YYJn-U%xiWoUHAtm9}@4$b-YEu|+>7c%Npk*51+I$XJ zDq9Y)c%WNHrZ5VkU~4J}pAqC}P(cZ%ifB`ozNzxkU{i kdoKmQci|p$fF9bd68enJ+)4sG7Mvj&W_KD1vIXZ?f_IPcWj|D%E&Lb{zv-tk zDS_=a{}@q$wY49_42I`;lS?d_kn&tpCFLA|hXLlVY@ImR;D^Qw{20BgvkEC(*DfH6 zxiINIg0Dl%4q0=Z@!SF%fEObo9Hf~m?^b8r%2r}p+Yj|O8cNI{H{VR5kS6CN5*y?5 zMEOqw1{VC15)c`7!BAtLa!xheR9o5$9NB{~KkP{Jv%``g65t5S)`I{&Y#etS!nj2^ zCYCF9{=UtzYL7R2wUV^1_r^xm_4Ef>p+2{FcSXk964*{DW4u(Br3jf>Bmad5nrlsV zN3bKmS=afszD4qXfDXIstkHP#*ZS&5sN%0LUM~7({|8t`GiW+wETVy7hVoNc0)R2G z>?d6cuCknG6~rQ+yYxkRfH-Ph>`IfRWC-_- p7s{+&X?gWz=%_473jenYMI1mm3!+U;r%3xsuirT1Q1idJBOy%eC5~e z3NW>{Gbn4JBE}z;?hMTL*S`a@axD1|AZ#AJp4W>1g)@BnAjX)+#4TwSr{*-6Z?HYh zi0QX_%=cy8IGkXtDe1vb!T*Rih!q~`pk5-x6YxdcI4jyUPHb2_igv2S0#M{QMwCq0 zXX62;2xlaRauR&p-RG6oDzzHSe4^!DQX}PER$w@W+Ie(L_${^gS%vSIMm CB#T@M~auqw-I^z!! zE9`%!H0<$#bt(o`$%nmzyGj(jLoNEpLUVeJ4^c Q*&@R zA?V$z?}7P1ymT%oJ7znAGLJJ+OOeO`8B7F%-@r>73_e8>0eh)c{0QBXc@00pYJ;J2 zKOo?+$tiE!blZ&a)@;4}kH8-Zt?tbCz}~WQ_-}tyT%D>S%5Dfl|CQgPVoS?)#WQ#o zY4|P)xqWmS!o1}@-EamGg+GGTLvXhOhrER*E(EXXe}F`9;hvSXPgy<7m&N9tP9z}n zU7HoVIhwYGL`dvDTh~2|j&04JSf`hDx-Xm3Sl|Wf@8N<1x?4GO{&X0vs13DG=sWo= zjPXQS7;6jN)o})O4$BEc<-9jviF;PY^o^i>NN09VpQ~MHIqk_bKps;L>J}8p!`??* zHq|z{ZUoFhsbd`i$}lIZZ-Of_H^Z6(?=&($5@A3GIUhvmELZ)4C_HhMbF|L+BowDc zR|kdP6H4En9mI5q*mrZWITuj%bbW4qtI|1K(`Ed$wcYuqw|dw5-KaG|BhnrU`zY(4 znturusx=Se)N C$emc?L~fBWDUYtDQ1_0E=wO5{Jyk-R*ucHwghRiVA(lTRKK>y*A1oWAvZ{o;#I zmbta$im`(0rW^lC6=%`gs#~=%8J (OAJbj2ca_v52b zT;q=o4mJcun5(RbzX5%YROcb&tJQ<8wi-d12GgHmclHfWa?c@M^s%?D&}VN|os yzadMVIf3WF64yd1s>9s54yx5H25_2(!1Qa}Ix-_M_GrplVCY zDphFo(rfBx_Oj`CG_#FTHG|ECG|b7RlXfGnlDggf*X%L=a@SDaw^_{RCgDROvgOU| z_}V_FgiFL)gX@mq?!ClYsfduJS0miDr QO?&mf3@DLI6 zH#?`HDy`traA O`q;Q4dLn=;h%AsR>BkB%LvG(&6`E1q4D z1a1;+N-+F0?UbKX_p0sd^RPAjMW+SiNqYDfuYvTvsTD+?*93qmgbs}thvewKwjdv0 zAY>*RZXr_=$uGg3@A`KH&Ofko$t6Db--T^WF?r&$byG1GLCIa 8o>VUpFGDM(>WF% 8-%+EGG zweEOmb=a`ncO!SMK!`xuGG8N9n*Fd}+IF >_SdKg`Yl8m~0AgGoLkSB$b# zx#jUT`MMtRh_bXM2)fWI+4fw=X9{}}C%&wy^2Vy@>$*+uEqcZVvY-9$v5jzD^+mpX zY3A6kaDzSRJ!Lq<9~=QA{Sf)$MDW_Gz@W-*C@kx j%*q(;+j?)5%?xZp%FhT(v&l$_{Brr& z5ccEdvxq;#RNl{Y0`K+y_|d3kc=-3ypNx<`1=rM)_m)XsscEA^xS1y@y{1~AiLhu> z13gtTa-;@6_ksFgi0!VTT; V`v>-L`VHG$GG;E z|5NRa;oK6&?XJ|m4}6$4kByV#o37?9WsVk4sF4=;Wm_#>K38fA!ldVOJg)p LO8%(iT4U;rZ)1k !*wWr)NJhzma7{HKlToAEy_A>*$2k%@ot_15}& zVtj*f)9lw7_dl}5D01?p)O@9v@K=^k+Xj73W3oqvT2C=c+S-J~10eg$+Wf6Hg}{?t z^$ziF#gtAHrt2ht;2R%U5ik-=a4Yuu-|pJ9Ud7+}$GL(sjoNBeiUS~a<5vaWe2`3! zq(Ka1eo9;y_(?Nxl+S8$Blz!| m>HqG57KY4Yg zTN#1MlobDTx|&BYXT1;46b^b(CiEuFydEid;7nLC5dHR^xiVO~Rmw+0FIEW$Fm6&3 z$V(Qb4XMa;whbow=PJ625L1c}A$EEl{WeNK@vI6+Vp6ej3jt^U0>|n#g_~P%G?N=r zC5?D6#wBaJD(!@UB?AzmX6lOF(^^Zv!DbW~@p_QRy*F1e%}PvB*gSH 1u_>r)C?Hp=*=+UZT~1XW@8aA)tkhu!D _lG*q2{N@%ebTsQV z3uRaefojZ)z9`8kxsMt3=8RI~I|Ia+5a|Sz#_O-A(f4(-6X#Lu zAE&i1lhx%W_sA+~?07$Z5y&U@P@(nIXJ^_CaDIVNZodD(o(lT7`oaCYa;}EbW41i8 zyU&Xgt0$j58IjE3en~BKua%lfsy~m$2;QruBtR6xYy>AL#B%ePNT kp_f&JpA=_1=33-J@SiUOvNX3^*L!iUdn)hTK xMG6rBwpN?+HdHf79TQ36s11=bWl_{g^ry#Uh7`cECR3g_s)D_AX80L2DVx14 zFF~ZH6{*^^r~jDXQR^{iGAC$cj>>vzqYPbv>(lt&sC2?omhZ^iC@5EnGf}_jv96U= z*<+M# Y1m`;ekSKU1}&8{Hmi1Xyo!eFlH %zoab%TjKdhz&y6 z@S4caFddbrR$GDWU{2mtlG**sJ>e+i6U@`IuX}95%^ycfMVG~?1KJZ3eMN_1z9KK% zrw2MQ6K4XhLEsm*kLs}NPo6mVbBHR41mvuM+lqyl7KMu5>7;EoIK4!8I7rf^G+TYD zITu{@FtN%;C-cmS hVD*Z_0$>C%N#hVtuyzjm@@~n_DljSF5k#8B~lRo_Y2`LmA2pbbl8(J8y z5UDz{r%P}Ii`ouF6&7W2x+w`EzG@cjq>2j9*<(T({VuqFgI*-<#Bx7;(=ho 4Uc4g*&rPSy~vmbHdt z*?wD7)>m1!8>YGgl4SIzpzk7NDWdBoMc1;^x7|){g-`lhW<3T+Ns+5(uUVJuei;Nt znQXs>E$rA9BSpNXk1|~%=I&JAYB-IyEX}b528Km&N-9WuB S~)qI^5T&=Y^YTXpyj#2MQFg*Q)(?A3PAx+L^dCl41`e zjAuiGfvh4f$26s7=v27`_4HIBE0ua=<;WZ%g>hA5_>CN%5%u;4#zblvx(k9lzHDIX zt&O=sMrLn!&Gy &3LlNABX91 z4Kb@)Dmq)*y%wn}W*>>lpPsdlpkn6ieVhFgf({k0x8dK|w+FJZHOBxrAeF9EN??X| z)0I|N!T~u>0rXw3#k{aAuIZyuZ=T4%P~xiL;6V%_v3Vyt(y}K{^{uecppz~Kr8?H=`1el+@ zH$U@GJ<`u5&*~p_FXW{`kSBeLZtfERmS#@1UL|Sc8B~IE7oV!ce@wum=B4Zi11ba7 z`&pI-PF>aLEGvA~$eRe*Qqw5c2N4dpU!F#~M5nlbzK<2)I#Y(+zq$BCyO456^vN*R z|J}>d{{UU4dVcda(?`5rVE(9Y2teH&^}Z>S-Sn8(zszrqtxAH(P148A>0C}=lUzk) zn@`n%mN;0)ZJ<^MOMm!;w!6R&d|)y_p=LU+wUEe`8-Z+Q%T=gF9GET^m6&ZaNED%L z+1D`g`q!3al^7p^ZT{Sz3~lowa8vs|?^%dS-1CTpO0;n6p-z*h$!r-{<34_^an_LIrUzkR*7da1bW8OY?oaW1>|Vxtmx)Z$(z z6#SaHblA33Cc))dhyCfF+|O@@S6x2Qn?I@CvuHOOL&igycjZY;AX(EdVRQPU;!~IJ z9;9#;jZWI6Uf|Tkx}4dY_${Q0UX)itta@O}EIKT2E4+OuE-P0FyQW-3zS9t#v8lEE zF+B#(p+7+z$K0A61Tbc>){R=d!r-^3Ot$0G(H)zE>n{_OpI4;Hc=(T)vF9@-&nhv0 zGYrZhHm4B`w@pt^@j8e~2&s~mEP^(r+V}=cUi^LHz;I-K_j>w%^6oYM? T~K1PG3_pX!ETjTys6>aMb gTE_% QkNhjq<74 zMzA@VHH9l-$PN#TrmZFGy}@x&-uW`aIQO<`T3IdaH{Pgo=L+Z(>h1e})TSoRS?QmC zL*T|FDTv7oVbKVODP;Pda%MlbuN?nkP9V`q@pv9jbrDWY`SdpWae+*;dJ1LV%Ol$~ z+W9^Qq!Ta8_oKF3g{k<_=gOOev#&Fi3Xu`79?=i@MFq*Ye;gD03VD`}*Uver34K4b z_z}{+(mKepBz-m3s7*OKQ-M97gT~POlQzi%{^?`A7TuFz!tk2ef$LrOrd!&fC2N|; zGq=s_V}l=_j!*!>uXmFCw?4Gu9nJ5$h(AUgZC8;LEo4$v2bIRn02Wmvm~#t-J|l?e zlaqk3&Ir-PP$`RtV$4|ysjxvLB?&$SG$hnh6208xi{Z~LlT7(;8%bx)x!8U95B9rb zK2lO4a10_7$@pl0B?qkLfOfvjj^z3J{(h$!QAb?QH9jmwm1#*KV>XHl$eAO1yF*)p z981IL{%Rtoc){*dme&R(H&HtUesXg03*1+w@fD|iF}j{v?>NX*A)oMnUnu4#_ek{t zse(VsO;thX8N$M=h(@aBj^h27J47SS_ewuGPWjd5p4-FUsehI*U8$e)x3q6{+(DeD zi$5eyAANPTIx$d~v`l{7^fKbB^P5ctX!wi3fgwt{_cF&?DBH0|%WW*yKasn)3RU^b za&p6jIduc LQl)vRwsu2u1`3%Wz}Z4rP$lI><)X+kRM}yZ zMdT!Dy&7`!FtP%B0xZ(f6`8oV3Zu7ts1Tr~D2E09WW);FnF;uuz_Abk3tP`)e4eoL zJ$&V$7oL;nkJ-bhZnViPPttwCB5VF_soM B*D7AFEQe|Y#c z1eX@b+d`H;qM-BOEAvbVsGe}Vp&wc<7A$?Nf6q3et9`Cd?+?m~E*3Y@7rRr+#s^xc zIO^3PW$tU9;wB6M;+!6$4uX%gC_O5Z8DRXwnuYB{ntD#GI#Y|D!kb8&kP9*>Xb2TB zcJ!dLdQ{mC $+9ye!dNCC|dX2 Ew&k!rO=?^C`%{Yn{I?$Bxg7CI4MU?5xwd-lgX0@bL@Hbn42RV4Yo<$x zBp69h{SAEab2O@hZcR2FV*c9#Ipj=wHDf9rjTF)JaK~dw$E|oRzmB!5d;xhW$FDW3 zZSgx(P9=4J_l08U$i8HII;x(gl&JNuE4KKdG5gR)euovO2gIv)z>?BI?jEO-U5Ct% zKs!YlPfFwA@&1<~!wD1XS0V9+ktyQn52>Wn>^5{veX1jmN}(3HV=(zHqd$#U7m&Ef zkx$UpO%zB)FoQ|wCVJBOtJv0d7|b`NIAk7_d4SW@=cQ7J+a9 rSgsq zCzHiy(=3g-s9H8PWW|b!l!}KDCPX4{T6dIvX?|*6eQIn~#)!!8QU%2(Xy&OQ4**i& zRD9BcYea-fu01M1!l4=Tr-N3BWVxrQH5&6$C>iToq8T7#M(S__6me7`xip}fUMS*# z7L3yi(@WClL1IkO6Hyr{rb;=`SeGX~X+ig>cN0#{9OJPjed#hiYBNpGG+ZoL0)nQR zhNT9Wh{B&rkw>*S5l>Pok`M*sr8{jXVMgIriDF`u3O5Q&( IxL}rqa?< z0j8M5)Pz$Aq%tNZo0FckAr#%T018@AwC$9WU^4=mR8+eur42g)7STr0Qu$_qAGJ+} zM~Y4=UoRBaTvBLgVW#4SZM~`^HF8$O)2F*BCdV8KX>3$aa4HA8QQo|o*`$8UHdI-2 z&7^67?^!bHNT0+jKI2?P=-IAMui`3vDCvd~v!IgnN7br@*0&U6mi=p!zSmi@5vvm7 z{&};>#cN9sh^wsG>Cww?td5^h@lZfkBcFQaFLisnvUf4tQAcMy*uZ0&)3)&Jvj9)? zuR<7j(>*B14Ts#p`JSAxIp`~}gTjgc%2nvRHyRJQT08xdnyzUDqz)z<86U3|p>Jwp zuC! _r`MM Wp!W~LYIu7*{U8w2JR*{}V!s3x(Znf1432u3{aq^$Qg`VWF;9{yVXRQ>pcH}Kt zhee&v=3ENsP)lP48nt&ZlF+wNSFQA!W?`~2ee0rwPqVf_U* zo*A0) zzC|iNmAj?*A_%b4{O8iUOI 42r0_W!=+eMm*N7mxnkTmbs-`Ph+AqlHBFY zH+QX>S&nM`pN5`Xe7~J`R{kGI@OF>Jwyi87hzy`6p-Gg|ISW4tV+EGB?R+^DU}Xh# z0abbcDNCrSZ@8{egG`1jVMSd?5l0FIG|mS~jjn(kwMK!dISMMY*9i)p!~t2Fmc13C zpPQepa60FT?k)==xe4rRcvHEYrqR&&gT--M21pw%_32)JsA}`yNJ}~A-m6I@w~}L? zYg0_{<;Bs?-aYH5-GVarre(oy^Egns&34)bgB%L8T#v%7*m!Ym5EB?L>sqO&$VNI> z4O~U^M^!2*ZdhCRE!S!Q0H&Qtx#OiYX$13 jF6GfXZ;PFISFqpa*$!6Byy%^-@N z5`Y@tH8eze)TaWF$N;1=77Qr^l{85>6; w+f!3mF{pyjQ-kaxADMYmMZl)D1 zDkWjorbqUqHK758k7{AGX6;&0;P$I1iH?*DoWvFl>H1UGPHgn8yf39F+n$wT=Q7hx z4ZT2iWFs7)G^#Y06VL-y7NrAykbU?=!#h8G q raigp7iC74_2uJNI!~`5aBS#T4PMUw2d12 z)P6uc>P9J*PkM#IF{yseJ!u30Qys<&bbi#Wrz;MXB8`Tn6ZWPTGbPgpWU7+si`@t1 zT?XQNQW%5vrOeP= x8>3aF@Y@lP; z4bD1qQ6CN6j*DG%M0Yi9JiK+S7GYU+BkHg?7V!Px{{WU|nsjTm{{WU>rFtk>%?2pX zVOFzB$cKc1=8|c*Db^$TRcEug>#*0P+*!ut@maSPN}%Ct)@xLssX*bD*6EHsvsa+e z?&Tne&2O81r>E&w?e09R1By>Fs3nAnjTeV?2I`e+KMUUx$i;M)_tBhu)u$B7z+l#I zF{nSQMB>kdu7Mkm9qOlv=1VO-Eo0z;gI onaY}u z$2|Ean~IZdCfe&UBgGi0Hqo|#BgGi0HqnXzXcV+!ilGc5fJi)br;)`%#|D5k>}3f& zQZdF3c&~8MZdX?D!Z^cbJ*K=C&A%L1s(duPGg@3*Gn2ETRhct|*6mH6sVeskQAZ$k z=DKf)I&g;k%@zP|waD8M-;-2`YUS`$jE3f%g#ATCuB_W}gHm#w^%X=ChCsPeRlVv! ztHE!O{{VS=)B->VW$1r|(~D#89uMP+VkTh6?l(W)r3r=kxo-5tkj6*MeZ37!<{1It zW81Y*4^=<|u1}~mxDC(|noQvULC1P=Bmh)?RLEm|wQO>CFJnrqe&|j;>A<|1Byzn? z8 DL&dkz<5spD@`p_{6$otgYqq(R2r?oYJ&olt2m_K+N(@6^1c+`REOke>R z;M0?7%DWDIX#nlZ&}0Vf+K?$vkYgUy-Htd+l@tzp&;-1$44jV4I*LF(a>tcEl*Np0 z$Z~zD`6^D(GJ58i$8HKXn8EbsgUXD652vLtJ`U4>-%4=@jIZTDhMl2~7m9c(x1pph z@{9ra(@uRT5i*tP2s8qm^S|1diifGe_NNe=y5fKgrv8Ks{*>jBqLXs2=>2`E2_bmH z3VKLNaGx(q0MflkH60b6G4m+l4{FNrexTO6i&@Fh&lPJ 7hPZ9 Bz1xmaAM GU zi&HLpElw2|wJzlyg<3+n2=hHD!Cdt;^B|-%0Zc9?&r?Wny(tTp=}WYlSL`y4%==C% zznWXUTDrC_4P+;s6P0e6qSqfWbg`yxa(Yu#o()bU0CcR{Eine+ij#Q)np|R-&Pd{s zOmk1^O%ky^Y7q-= aD} z=A~PNQ-Co@2P`2+JXB8_Zsn=%I+6FPFjcyY&;hm|T+pnE(Q`^8PPnE!Dvl@uH*i~p zr^FXID^Z4K><8AKPQk+u!hj}cjYnKmUU5Gv)oGj)l4-HchT}hlJB-j+SaSV6>8~U) zgMhiJrKg*rY dYrc8IMLKPJUYLn&k zq)?u;q=8gG;J|jKml^3uMtT~B<9zW+jFIFOPU(-9aZ;3g^r)wajAx3Kt0?j>6HLvj zNt52QBR?f-__i-ER&noGMopr GOr@a76MKn0| zrQAJf+y? rTxVB 8)@;6ab9KNjc93C zA&X&8TJ)
GY?nzW1`P&-(+J8fyX>ojA~XBX}Xm5lJa6~abH7CaIz@@ zyH|_&vdBfNOCTLhNlBO%;O-n&gp%!1im46*bgK@b#XA#lTgDY2y>8^xA| 6~)jWn5h&9nXL z@^xX@Q@483`nQ>0*!Ea8{W^cSc^~Im5!}Tf%1W*DHQ`~8V^$%&xP*@`c^4jxMMSXe z2en7JaB {6csVWCIw54%DGvT3WbV_w&|L#@e0OD#Ue08 zN}yC2+G)X!N@FM5w7W$@9Mgd&wL&ErrvNG-rk(++L^5RyPXTHr%}Suws7!t-Ij2!n zNX}_Fr 96$Xyie1sELPqU4&JGx7M0KrOH*v2sGSt z)}~-7g+%}gzz($k05cU3QJRn_p$UoR8gjc*U{rush(fEJQ@0ubrNvPJxYB}YF-iqH zh;XM4l+jM01*D@ilmNJ-BAuE_MGPXFwxlAGfB>}cw7^X}cfA)7@C6%IqcVl-Q9aUu z)}nQ3$95KFgS1p-)OV^AUxAz&qb8tp*1Ve8y&8H$Q+QCDHeP7gsj72dAQ%R*r__f$ z)@<6K8RopIxutr#Q&u}+gzj$5s0GgEtm*Y+T;Z#pxz$S&GHW_ZsTlBUpV-x`?@^tQ z!^Is0`qAeGv**>MKgU^4&PGdOp=ki?&34kj!?Ea6!zNpoQe&T()i=0zKQ3vB8&22* zirdrlN0 Fn7)J^D){J%$Mmbuyy+Ep0T9v)9%#vcXP)CbX6FED!Sn?vrN`g-* zE1uLmV+>hX6LBBj70q9Gg8KB4=a|s{01DNp95peqUkTV=_=iuj1U#Xbe+aH-{{Y3a z&Pv)xuzz^gD7P$kF)UB5Teh)zSSqG!)iiO+y;`qAoYGz0KIvpFpL$@kB=qLGh&(>n z4J!m%dyOi?hH&j#s(08Uhi_RJR@yZ3<7{NstQrbOhMj=+r~d$IT}}*kaA7+&Pj97P z-JR3QN3b=taMJr)9Z^)^wA78KwX^vkh%;1p)HMUOBl6eQx9t2s8sjUt*33FepdT(O z`6<)$FP?904qDH{@*EkMlUtU$GDbjD1K$<2meE2edx+v0QBvyL;ROrsLk66xdFfUH zLl31;y4E9%9Gq4S?}?y~IDN*s=Ue%WRWqob`Z&kl#be)V@xrHcfPOW{-RsvEPF5U& zR9eFF@wYp%&2q}O@|_W*ZOxni02Xe_z;bIETbtcMy0#5ySomuU43*H@=@3GrfmpdV zY@(uamih#ekkV$g?KB9J8CvK>aj4-(6ot`ELx{P`E2qT}7!@>VtI$z3!Yc7p&GLrM zdR9%E>dWP^PDcZr)-<}IZWL5sY@LT3R($NPLv`*@bu~_HMGzbs&CIRK6IAY>U^z6o zr6H)KUYAt^CpCwt_>je&rm^)sSVjt?S2;Dzw{L)RT~z3GW)&(Wv1?P+?k?m%IW=0> zPoDL@RAx1?q4-|wQIHac9`)%uH->HW=)q(K>!r;@NSH<~yU65pKL$6;HOk<6S7U9a zM{a>5Kme_Ufmfo8eJOmg{om5LCZ#8 < eGT4pzw zBKM@;>(@1>BuP*-3+qbbD=dW6sN#{4MMTfHrBWS>iUU-u5|LS==&9*arSZiv7rcQ; zU><_2t?#Wr?O^w(ax6>b QSPJGb)i# zJV-}DO=$@oX`W&At3?cGhiZaIh|Vh4-l+ruhgzh^a~e(Rc+ClP%hxrfJ&?y0N$kka z6+v;!dZX5*Th%;Pe2~0-ssnJy*u?;C35#=@W4iaM33y1URm_H};3UYc(A8NGpy^tX zTaF18Gg?OD1!%Y!amdJXiqN;zb`EOC_F|rbpnW@QP_-qD)-@yc0?KdzuQ0xt&2;Wg zcO2Jg;>)oND{hA#wZk_j-n~pbERQy;yAp~huA>m5iYNf0iYNiJQAIEchEY?Bjz!Hd zA8Nr{71ww>Rg+HDlgd)wXB%^j*B2XM_^pjT<)FEWWXLGM)uR*Cd~srLbisBa*yu9L zURxOo&AW^m_JcHf*M`?<^If9-ab7)tYSy>U8~W7N4t@OP#l91Y!iQ}&hl zLFrV8V}axZse@s|5oqxF1f{ zBzs6ZK4JaRaZF_Bz>|t$8@d8bAsawrmHw2XLQl*{J(v!($s97c0oh3GM+Tg)##NW* z>a@(B@&iih+#D+o;C7&7tAmlx(27< DUa9qG*K>^6>n+TfZ--5Q2qaA@5ezjW?l z>)L=F<$=jxo7=SmhdZMU=|&0yHtzgsGyUR!!kEX9c5X2T`gWyINXFV?kd5*-b5a8# z``}~RfCh^lIi@ghcvFg1BXPka*wU*KIvh|Sz`)3-95+rWK5Y6^RIvvsjCY_1E>scg zN;16(0)kYLjwuL`4Zw}G2$~7ZH!<#2aD97J-XXRZmO|wZ-0Uikn!9#LxgV`-Y33)i zcygm7qf&bn7iLfJ=KIW9Y$b1*K4i^$5+KERy^Yi8TKdY2LWjY}abC4=sinjy=yDij zSC3jM5 zdQ*g8cB0LNh;qlJ9#geh+9`2Y%9yTK7VX^A#kZ|ZoKd=;vq&yPA_A9gDdf@;D6ohn zQfnsq0=Z#ZL@6C=oy=Zhm84OT6r-VPnNEAwSkvxO@X6*Kp#93&iVs?eBH}8bBbsY% z2Bc)i0Mrc=ZtGc>al>(^jsBFeA;n19QJM#Fj2{$<8|OKsGZJx9EXbpp0^m@drlM#^ z_o@D7^U%{y0nQCET!>o+Z=0n} XB z#B`=m!45w0raMHZoS&sU<+@VFm_IU#1~xTPGqV)zZ#W!OrGoK{)MiW`69$kHc|&L3 zs2Vltnrq7;<2a_GwsORp08+3i 6iLDTDcoTt$s8ng2$FJnKq^L+6Yeg4wBJ3X>#=FrcPChfSC{ap z<&`7oYP7Q|j!8f6)JrT))mVSMNJGBX9!;h3{^+Y4$xo6Zf7}n%W`8!rw|Bd8Hd8 z0Yw8VO7{ew6c2idBDi 4WtDv?n5MWJXyz4 =hmXfG;N~cV!*m#P8WyLs?rmRE*39+yQT@P z8x3;i)Po$Xze8O9>T=7rn2yanTXx-KVrssn=4w{PP}z{zG?!a@)tL2HPrAf@Gysil zG$Smv3(i62tVyZ7!vxh iaIn7A7bqcBxj8nuYd(#z(MamxaAejwTYixI@ z%w$jofOI|Sc jSk#51rHPd*1#By0Ef#&%unyfBT zs-d~*;qy-b*EenABy44sg U{5gS>ESIa6rp zg;+~wQ;|+-QFy7|F;Q?0VasECiUl|dXr~IKNaf_zgA^=z6!nNzq$b1+2WpjFX+%ru zPZ1%l5+RHdXSF jjg*PIB2~A*W*%V|@1#%jj zwW`hqC{a^lipqwh2~&j>yG1mFLL;E21xiR28!)CaGI35;sLAG(8dn)GYH(vw15XW9 zK_=>4)O+X-Y1j!fO)P1 (@l#F8f%mH!VrfHm zQj2B6Kpkoqkw@`W32%EXRe9OEn(}cO%_w{tn?i$onsQwt_o~mRW1+0~bL&-|oS&2$ z@@i&v>c4kGqBLN)FU@@I)wrsXUUAgaB^>?Z#X~WMF_wIvO2gS#t*n{R7{Vhby*$-9 zFPxq#QmsD Q>AO0N)f P!6F*QlDS9wg+==KGnxx_=vW1COxYH>s)5e z)A-j!V9ye!I#PCmJ4^2uO~{84uc@wj?^ic0S>`TJy>l{ZZ7zOn(Gg+N5wf3%v;k%tMr4_lkZkkoB zK;2!dIQ|u H9#y=|4lAKMhm%@%lJ3VVu zJFaJCQ~WDh_C6GbEHfZx@0#mi(~>pl7wJ|)MIZ2iS-Q!5D6U5LGHrBN;{y?e{3}K) z7-AgamP@$M9z|weYcRqN=>Ys|3D$3RYZ_gRa`8kyTnec^ppo&K gO%gtmQaq|@|>piz|-sIbPJ02Mozbc{Pa4k$q0Ijv~z zqKphEsa(drNUC=?u|_`l{3$k&^<|?ZNl`ugF^)}Q-0JDkYc6}Yn4B8QRXZ9gH{9so zSb=l%W~ooDBYnY|#fm0#(3;V=)7k$3g0pgLwN5B&UffP`jw#7+G=~^9t8b?8GAl+4 zFr5~K7DTEfV?(Al1dg?OJuyHT6|N!!twDDza6(<%3bm@Eb0<}^Hs; V!ZRj zI?9)5p_75!RQ@XQSDMXlZ1{|E$9m)Aj$7%!h~)EKbm*n4F_lL2Kn%BX?dO{AJTKtU zKG~;Jx6q1zg?u2zlH%nsqmT%%Lxob_Fp;QGJt}Hcwuo_E!pg?p#xRkf81IU*%%-6- zZlebrRwWYd0+V bnzBGc_(?v3Jc{JkeA#)a ;oS a3TC2b!YO7CmWJH-43yoQ+fv_qk) Y5C{!B$^xdO#TFID@rqmuF-cJL7@a81 zAvBp4Hvt&pqhn8FO~5q`lt< bL*_Hao>WwCZ?d$STCXY1OPU38gXKk3 zmgK4HS`x>&bgEKWmOUzNjg^Yx?=-%CY5xFVBee$5j@0gHbRJ+LlyZ91MiyEy%S=Vo zh;_|Qv4P&R#Ox{J>8b+8iH%668+0{UZjXAECkBg?W+b*M!=`IGeK9)it${GdT4OS| zQ&yV`7!PVA=(LFY4@%aaH6Y@%CWPeTtC*r#u5r-*6>=-2J$N;O?9raIE#U`~R0mHS zs>iK1< i`@1<0bQHT8Il9@C*DG9j`7BrY_&FQ5@b8S-J`(Tn_6qJ#`F16$T8P# zbpHSlZAA8|G9fGnFYQ_)8Rqb_6dcu+=LEKDq(=j&t0)2NPtvH8Kz?qS6*BF9yi`E* z(-i(k%m}7KM4<>gH7+syAbZntPjO1B4|<|WL!NLl4Jwl$>^`*LD>=Y8UbJC2+0U&o zBpD~};CIbEO2*$O3*A aMor`8U`MxV4#K=;{{W>#vMxv?Z_ JmA#U z-z1>!AbVAJjdPq6L}Z5??G%7KM`!{p(d6#yU01{VsP44m42LpAanGe Szl)phy8PI!E4bl_CQ|3rklP2BG8^0>6CC8;!lI4ebmn1$$Uujp? zp?L;)ssd>ly{cfu)bkdiIzkUzR32F;uN5g$X{1Oy3{n`}BKy&to}g2Nd%BTM7U|sP zorWNcaC6NsmWS_C*sAub(@Fs0fc$BI`8>7gF;Fz4)}Uv0>hyq>=)0&HIcMxRrZ>0* z)N;t(2rKlZiWYIeH6S=jSB&D3<9RvVQ!S_Ws! zV+@xpIW488nvL$mI=dG fP>E>97lA6iR&KI(2=f{$v}FsgGagH3sW`D5wpKov%wAsi6KrHUs# z0jU&*BXOyG;67BqpkxLhqa>1Q300Wnu~F?-obNk&pK5ZV#4^M4rUf4({+pl5iofT_ z=(JD l~{>KnDA3;DE M1oSiIH!xJAH;t;hnh@LadMYd{l|KhH6|T# zS-7K-MZ=WWT}?ZRkZLfVwTY2N>{W9U%5SaQE&Np=k~7hTbAiuePZK!k#-A{`4va7~ zxvT+sBL4sxrwu|;{8V!XDY`%+s?9S*eq4&8x{Ri~F9c~2_=0IZ*B|cF6`e`gQl-qS zV%qBx#exlL!LL6Y*Jp9?*F=*(QI$U$$-4MqGGy7^?(|m`kF+>yW$ElvgIyeDj%z{< zdB!$Q!||*uzX)rVInAp`qq^2(M|*16mN$ $ zBV^3D_o#H2L$aP^ GJnTvII5oLx;@v({1lyxN{VB#RZgxi* zN~X-{xD;lfx4pBuP|!@L+cjg3^-SGKJ%;XV^rSA-<4wj*CR(t@l!{@vH6un1MA2fh zY`Y J z1w_kFq{e6{fQ(Qxnx9~$3I}Rd85pI-Nw%6+o6rW)lTAEQZ^wFvQrm@x0B9!_8{8_6 zwNgvaE6>Dc6lwJ}g(l0bAYP`cOLiB4YK)gm=Yv(*nXALEnN+EzG;}OKa^u~5)Gu+K z^;_)nlb&i+x5f*#bF4NZyVTKgM0&Yn#ZI>D;-NCb5bIGsu^e1(#d=tLuADWhLz{aS z#j+ @ODYbtF{ONPX3aZ*KY^77o*YK=JQ2#V5smF{k?u3KzTm0wzt(@&N8 zkbZTwX<#rottjo42TJIthH}-DD%`pwGTTfz9Ad7mnx_Y?S$0_Zn&)-D5Q{}3GnTI9 zPBBE&jY`tAOFEvTZDA4IMn`JmH63zm*$PI)A@r&mh5XmjmS!hCsg`jcFm4qs``+p9 z)2BlT4r-55-JY8FGH&Z#MwOu~Ks%4lt5{xGY4L7kF8!*WrQ(?-I~BaR{RL|pcRqg~ zpT)aVXI& !CpTx#FwWdT4bQ z{w8?|-63OK{ob`Blk-+Qw{FLdXo}i