树莓派基于物联网的指纹打孔器
今天我就分享一波自己的成果。
心心念念的想做一个物联网的东西出来,终于在上个月搞定了,虽说肯定是有些漏洞(目前我是没有找出来的),但是效果看起来还不错。学了这么久的Python、Qt、liunx命令总算派上用场了。
材料:
- 树莓派一台
- 指纹模块(AS608光学指纹识别模块)
- OLED液晶屏
- usb转TTL
- 杜邦线
先说明一下
博客园无法分享附件就只能这样分享了
如果想要附件可以点击下面 链接,我在****上注册了一个号可以去下载:
树莓派上的源码下载
电脑上的上位机源码下载
oled上的字体
先上个最终成果的图
看起来感觉还可以,基本完成了电脑和手机都可以获得日志的效果
大家最期待的过程了
现在我来说是我的想法和思路
刚开始看到隔壁实验室的指纹打卡机时好像是那种用usb读取数据的(好像是节约成本吧),我就想能这也太不智能了吧,就想着能不能让它智能些,比如通过电脑看到它的日志啊,或者用手机看到它的日志啊什么的(后来我才知道淘宝上TM已经出现这种完善的成品指纹考勤机了)。光想没用啊,还是要靠实践来检验真理。于是我就想到了手上的树莓派,想想就有些兴奋,可以向网上那些大佬一样DIY一个东西出来了,由于我的知识有限,无法自己搞个指纹打卡模块,就到网上买了一个,先开始买的正点原子的指纹模块,原子哥不愧是我原子哥,和他讨论问题时真是尽心尽力。文档很好,不过他那个和模块通信的程序不是很全,就几个,可以能是直接储存在模块里的缘故,可是我不想储存在模块里啊,我学了Python加上Mysql,我想直接存在数据库里,这样更加安全可靠。于是我就开始解决通信问题,将他发回来的数据解码,捣鼓了2天才完成,有点心酸。
先把配置文件分享了,下面代码会用到
# 用户root 给电脑连接的 [root] pwd = 123 # 数据库 [db] db_port = 3306 db_user = root db_host = 127.0.0.1 db_pwd = 123456 db_database = finger db_table = test1 # smtpServer 发送请求服务 # popServer 接收请求服务 # smtpSrcAddr 服务端的地址 # smtpSrcAddrPwd 服务端的密码 # smtpDstAddr 发送的目的邮箱 # smtpPort 端口号 qq端口号为 465 [email] smtpServer = smtp.qq.com popServer = pop.qq.com smtpSrcAddr = 发送请求的你的邮箱 smtpSrcAddrPwd = 允许的密码 smtpDstAddr = 目的邮箱
smtpPort = 465 # TCP服务 [TCP] ip = 192.168.137.249 port = 9090 # 串口服务 [serial] port = /dev/ttyAMA0 (先不用这个串口,这个是我配置过的,你可以先用usb转ttl连接树莓派的usb口和指纹模块) baudrate = 57600 timeout = 10 # 乐联网 网关信息 [lewei] ip = tcp.lewei50.com port = 9960 userKey = 你自己的userKey gatewayNode = 02
1.首先要在电脑上调通指纹发送数据的所有命令
分享一波代码
要用电脑和指纹模块通信首先要装
python要serial模块,在cmd命令行中用命令 pip install serial 就可以下载serial 了
1 # -*-coding=utf8-*- 2 3 import serial 4 import serial.tools.list_ports 5 6 import os, sys 7 PATH=os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 8 sys.path.append(PATH) 9 10 SureCore = { 11 0x00: True, # 表示指令执行完毕或OK; 12 0x01: 101, # 表示数据包接收错误; 13 0x02: 102, # 表示传感器上没有手指; 14 0x03: 103, # 表示录入指纹图像失败; 15 0x06: 202, # 表示指纹图像太乱而生不成特征; 16 0x07: 203, # 表示指纹图像正常,但特征点太少而生不成特征; 17 0x15: 204, # 表示图像缓冲区内没有有效原始图而生不成图像; 18 0x08: 302, # 表示指纹不匹配; 19 0x09: 402, # 表示没搜索到;此时页码与得分为 0 20 0x0a: 502, # 表示合并失败(两枚指纹不属于同一手指); 21 0x0d: 802, # 表示指令执行失败; 22 0x0f: 1002, # 表示不能发送后续数据包; 23 } 24 '''返回= 999 校验和错误''' 25 26 27 class DealBuff: 28 """切割收到的数据""" 29 HEAD = [0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF] 30 31 def __init__(self, buff): 32 self.buff = buff 33 """处理读出的指纹数据用到""" 34 self.tag = list() # 包标识 35 self.data = list() 36 self.check = list() 37 pass 38 39 def read(self): 40 buff = [x for x in bytes(self.buff)] 41 check = self.slit(buff) 42 return self.tag, self.data, check 43 44 def listCut(self, buff, num): 45 """切割数组""" 46 rec = list() 47 for i in range(num): 48 bytes_buf = (buff.pop(0)) 49 # rec.append(buff.pop(0)) 50 rec.append(bytes_buf) 51 return rec, buff 52 pass 53 54 def slit(self, buff): 55 """"选择数据""" 56 # 初始化中间变量 57 popList = list() 58 check_Num = 0 59 check = list() 60 head = list() 61 62 if len(buff) < 6: # 判断是否有效数据 63 return True 64 65 head, buff = self.listCut(buff, 6) # 选择出头及判断 66 for i in range(6): 67 if head[i] != self.HEAD[i]: 68 return False 69 70 popList, buff = self.listCut(buff, 1) # 取出包标识 71 self.tag.append(popList) 72 check_Num += popList[0] # 计算校验和 73 74 popList, buff = self.listCut(buff, 2) # 取出包长度 75 check_Num += popList[0] + popList[1] # 计算校验和 76 77 popList, buff = self.listCut(buff, popList[0] * 16 + popList[1]) # 取出包数据 78 check.append(popList.pop()) # 取出校验数据 79 check.append(popList.pop()) 80 for i in popList: # 计算校验和 81 check_Num += i 82 83 self.data.extend(popList) # 导入有用数据 84 if check_Num % 65535 != check[0] + check[1]*256: # 检验校验和 85 return False 86 87 rec = self.slit(buff) # 得到是否正确分析完数据 88 return rec 89 pass 90 91 def write(self): 92 """要写的数据打包""" 93 pack = self.dataSeparate(self.buff, 128) # 将数据分成每组128个元素 94 return pack 95 pass 96 97 def dataSeparate(self, buff, numPart): 98 """把数据分组打包""" 99 num = int(len(buff) / numPart) 100 newData = list() 101 for i in range(num): 102 newData.append(buff[i * numPart:(i+1) * numPart]) 103 104 packData = list() 105 for i in range(num-1): 106 data = self.packData(newData[i], 0x02) # 数据包没结束 107 packData.extend(data) 108 109 packData.extend(self.packData(newData[num-1], 0x08)) # 数据包结束 110 return packData 111 pass 112 113 def packData(self, buff, flage): 114 num = len(buff) + 2 115 senddata = [flage, int(num / 256), int(num % 256)] + buff 116 sum = 0 117 for i in senddata: 118 sum += i 119 senddata = self.HEAD + senddata 120 senddata.append(int(sum / 256)) 121 senddata.append(int(sum % 256)) 122 return senddata 123 pass 124 125 pass 126 127 128 class DealFingeer: 129 """和指纹模块交互""" 130 HEAD = [0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF] 131 tag = list() # 包标识 132 cmd = list() # 133 data = list() 134 ser = serial.Serial() 135 def __init__(self, cmd, data=None, server=None): 136 """初始化函数""" 137 self.cmd = cmd 138 self.data = data 139 self.server = server 140 pass 141 142 def run(self): 143 if hasattr(self, self.cmd): 144 func = getattr(self, self.cmd) 145 return func(self.data) 146 pass 147 148 def link(self): 149 """连接串口""" 150 self.ser.port = "COM5" 151 self.ser.baudrate = 57600 152 self.ser.bytesize = 8 153 self.ser.parity = 'N' 154 self.ser.xonxoff = 0 155 self.ser.rtscts = 0 156 self.ser.close() 157 self.ser.open() 158 pass 159 160 def finger(self, data): 161 self.link() 162 check = self.getImage() # 检测获取图像 163 if check is not True: 164 return check, [] 165 166 self.link() 167 check = self.genChar(data) # 检测生成特征值 168 if check is not True: 169 return check, [] 170 # ================= 生成特征值时图像会清除,所以要重新采集 ========================== # 171 self.link() 172 check = self.getImage() # 检测获取图像 173 if check is not True: 174 return check, [] 175 176 if self.server is not None: 177 self.server.send("True".encode("utf8")) # 发送数据说明准备好了 178 179 self.link() 180 check = self.upImage() # 上传图像 181 if check is not True: # 校验和错误 182 return check, [] 183 self.tag, self.data = self.getUpImage() 184 185 if len(self.tag) is 0 and len(self.data) is 0: # 得到数据错误 186 return False, [] 187 return True, [] 188 189 def save(self, data=None): 190 self.link() 191 check = self.regModel() 192 if check is not True: # 校验和错误 193 return check, [] 194 195 self.link() 196 check = self.upChar(data) # 上传特征值 197 if check is not True: # 校验和错误 198 return check, [] 199 self.tag, self.data = self.getUpChar() 200 201 if len(self.tag) is 0 and len(self.data) is 0: # 得到数据错误 202 return False, [] 203 return True, [] 204 pass 205 206 def check(self, data=None): 207 """检验指纹, 生成特征值""" 208 self.link() 209 check = self.match() # 比较指纹特征 210 if check is not True: 211 return check, [] 212 score = self.data[1]*255 + self.data[2] # 返回的分数值 213 214 self.link() 215 check = self.regModel() # 合成指纹特征值 216 if check is not True: 217 return check, [] 218 return True, score 219 pass 220 221 def isFinger(self, data=None): 222 """判断现在的指纹和下载的指纹是否相同""" 223 self.link() 224 check = self.downCharCheck() 225 if check is not True: # 判断是否可以发送数据 226 return check, [] 227 """下载指纹""" 228 self.link() 229 self.downCharData(data) 230 """检验指纹""" 231 self.link() 232 check = self.match() 233 if check is not True: 234 return check, [] 235 score = self.data[1] * 255 + self.data[2] # 返回的分数值 236 return True, score 237 pass 238 239 def getImage(self, data=None): 240 """获取图像""" 241 cmd = self.HEAD + [0x01, 0x00, 0x03, 0x01, 0x00, 0x05] # 发送命令获取内容 242 return self.isOk(cmd, 12) 243 pass 244 245 def genChar(self, data=None): 246 """生成特征文件""" 247 if data == "1": 248 cmd = self.HEAD + [0x01, 0x00, 0x04, 0x02, 0x01, 0x00, 0x08] # 发送命令 249 return self.isOk(cmd, 12) # 图像接收数据 12 大小 250 elif data == "2": 251 cmd = self.HEAD + [0x01, 0x00, 0x04, 0x02, 0x02, 0x00, 0x09] # 发送命令 252 return self.isOk(cmd, 12) # 图像接收数据 12 大小 253 pass 254 255 def match(self, data=None): 256 """比较指纹特征""" 257 cmd = self.HEAD + [0x01, 0x00, 0x03, 0x03, 0x00, 0x07] # 发送命令获取内容 258 return self.isOk(cmd, 14) 259 pass 260 261 def regModel(self, data=None): 262 """合成指纹特征值""" 263 cmd = self.HEAD + [0x01, 0x00, 0x03, 0x05, 0x00, 0x09] # 发送命令获取内容 264 return self.isOk(cmd, 12) 265 pass 266 267 def upChar(self, data=None): 268 """上传特征模块检测""" 269 buff = bytes() 270 if data == "1": 271 cmd = self.HEAD + [0x01, 0x00, 0x04, 0x08, 0x01, 0x00, 0x0e] # 发送命令 272 return self.isOk(cmd, 12, False) 273 elif data == "2": 274 cmd = self.HEAD + [0x01, 0x00, 0x04, 0x08, 0x02, 0x00, 0x0F] # 发送命令 275 return self.isOk(cmd, 12, False) 276 pass 277 278 def getUpChar(self, data=None): 279 """上传特征模块数据""" 280 buff = self.ser.read(834) 281 self.ser.close() 282 subpackage = DealBuff(buff) # 分割内容 283 self.tag, self.data, check = subpackage.read() 284 if check is not True: # 校验和错误 285 return 999 286 return self.tag, self.data 287 288 def downCharCheck(self, data=None): 289 """ 290 下载特征值检测 291 先要初始化,发送获取图像命令 292 """ 293 self.getImage() 294 self.link() 295 cmd = self.HEAD + [0x01, 0x00, 0x04, 0x09, 0x02, 0x00, 0x10] # 发送命令 下载的数据放在buff2中 296 return self.isOk(cmd, 12) 297 pass 298 299 def downCharData(self, data): 300 """下载特征值的数据""" 301 self.writeRead(data, 0) # 发送数据 接收为0 302 pass 303 304 305 def upImage(self, data=None): 306 """上传图像检测""" 307 cmd = self.HEAD + [0x01, 0x00, 0x03, 0x0a, 0x00, 0x0e] # 发送命令 308 return self.isOk(cmd, 12, False) 309 pass 310 311 def getUpImage(self, data=None): 312 """获取后续的图像数据""" 313 buff = self.ser.read(40032) 314 self.ser.close() 315 subpackage = DealBuff(buff) # 分割内容 316 self.tag, self.data, check = subpackage.read() 317 if check is not True: # 校验和错误 318 return [], [] 319 return self.tag, self.data 320 321 def writeRead(self, cmd, length, close=True): 322 """发送命令读取原始字节""" 323 cmd = bytes(cmd) 324 self.ser.write(cmd) 325 buff = self.ser.read(length) # 图像接收数据 326 if close: 327 self.ser.close() # 接受完数据断开com 328 return buff 329 pass 330 331 def isOk(self, cmd, length, close=True): 332 """判断数据是否合格""" 333 buff = self.writeRead(cmd, length, close) # 图像接收数据 12 大小 334 subpackage = DealBuff(buff) # 分割内容 335 self.tag, self.data, check = subpackage.read() 336 # 检验数据是否可靠 337 if check is not True: # 校验和错误 338 return 999 339 return self.check_code(self.data) 340 pass 341 342 def check_code(self, data): 343 """检验指令码""" 344 return SureCore[data[0]] 345 pass 346 347 pass 348 349 350 if __name__ == "__main__": 351 # HEAD = [0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF] 352 # data = [0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x03, 0x0A, 0x00, 0x0E] 353 # data = HEAD + [0x01, 0x00, 0x03, 0x01, 0x00, 0x05] 354 # data = HEAD + [0x01, 0x00, 0x03, 0x05, 0x00, 0x09] 355上一篇: 基于深度学习的手势识别系统(Python 代码,用户界面版本)
下一篇: 跨领域掌纹识别
推荐阅读