今天我就分享一波自己的成果。

心心念念的想做一个物联网的东西出来,终于在上个月搞定了,虽说肯定是有些漏洞(目前我是没有找出来的),但是效果看起来还不错。学了这么久的Python、Qt、liunx命令总算派上用场了。

材料:
树莓派一台
指纹模块(AS608光学指纹识别模块)
OLED液晶屏
usb转TTL
杜邦线

先说明一下

如果想要附件可以点击下面 链接 去下载:

树莓派上的源码下载https://download.csdn.net/download/happy_grass/11253753
电脑上的上位机源码下载https://download.csdn.net/download/happy_grass/11253807
oled上的字体https://download.csdn.net/download/happy_grass/11253815

先上个最终成果的图




看起来感觉还可以,基本完成了电脑和手机都可以获得日志的效果

大家最期待的过程了

现在我来说是我的想法和思路

刚开始看到隔壁实验室的指纹打卡机时好像是那种用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 了

‘’’

import serial
import serial.tools.list_ports
import configparser
import os, sys
from core import dealFile
PATH=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(PATH)SureCore = {0x00: True,  # 表示指令执行完毕或OK;0x01: 101,  # 表示数据包接收错误;0x02: 102,  # 表示传感器上没有手指;0x03: 103,  # 表示录入指纹图像失败;0x06: 202,  # 表示指纹图像太乱而生不成特征;0x07: 203,  # 表示指纹图像正常,但特征点太少而生不成特征;0x15: 204,  # 表示图像缓冲区内没有有效原始图而生不成图像;0x08: 302,  # 表示指纹不匹配;0x09: 402,  # 表示没搜索到;此时页码与得分为 00x0a: 502,  # 表示合并失败(两枚指纹不属于同一手指);0x0d: 802,  # 表示指令执行失败;0x0f: 1002,  # 表示不能发送后续数据包;0x1e: 1602,   # 表示注册失败。0x10: 1202,  # 表示删除模板失败;0x11: 1302,  # 删除 flash 数据库中所有指纹模板}
'''返回= 999 校验和错误'''
isOccupy = 0  # 是否被占用"""串口配置"""
cf = configparser.ConfigParser()
cf = dealFile.readConf(cf)
serialPort = cf.get("serial", "port")
serialBaudrate = cf.getint("serial", "baudrate")
serialTimeout = cf.getint("serial", "timeout")class DealBuff:"""切割收到的数据"""HEAD = [0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF]def __init__(self, buff):self.buff = buff"""处理读出的指纹数据用到"""self.tag = list()  # 包标识self.data = list()self.check = list()passdef read(self):buff = [x for x in bytes(self.buff)]check = self.slit(buff)return self.tag, self.data, checkdef listCut(self, buff, num):"""切割数组"""rec = list()for i in range(num):bytes_buf = (buff.pop(0))# rec.append(buff.pop(0))rec.append(bytes_buf)return rec, buffpassdef slit(self, buff):""""选择数据"""# 初始化中间变量popList = list()check_Num = 0check = list()head = list()if len(buff) < 6:  # 判断是否有效数据return Truehead, buff = self.listCut(buff, 6)  # 选择出头及判断for i in range(6):if head[i] != self.HEAD[i]:return FalsepopList, buff = self.listCut(buff, 1)  # 取出包标识self.tag.append(popList)check_Num += popList[0]  # 计算校验和popList, buff = self.listCut(buff, 2)  # 取出包长度check_Num += popList[0] + popList[1]  # 计算校验和popList, buff = self.listCut(buff, popList[0] * 16 + popList[1])  # 取出包数据check.append(popList.pop())  # 取出校验数据check.append(popList.pop())for i in popList:  # 计算校验和check_Num += iself.data.extend(popList)  # 导入有用数据if check_Num % 65535 != check[0] + check[1]*256:  # 检验校验和return Falserec = self.slit(buff)  # 得到是否正确分析完数据return recpassdef write(self):"""要写的数据打包"""pack = self.dataSeparate(self.buff, 128)   # 将数据分成每组128个元素return packpassdef dataSeparate(self, buff, numPart):"""把数据分组打包"""num = int(len(buff) / numPart)newData = list()for i in range(num):newData.append(buff[i * numPart:(i+1) * numPart])packData = list()for i in range(num-1):data = self.packData(newData[i], 0x02)  # 数据包没结束packData.extend(data)packData.extend(self.packData(newData[num-1], 0x08))  # 数据包结束return packDatapassdef packData(self, buff, flage):num = len(buff) + 2senddata = [flage, int(num / 256), int(num % 256)] + buffsum = 0for i in senddata:sum += isenddata = self.HEAD + senddatasenddata.append(int(sum / 256))senddata.append(int(sum % 256))return senddatapasspass
class DealFinger:"""和指纹模块交互"""HEAD = [0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF]tag = list()  # 包标识cmd = list()  data = list()ser = serial.Serial()# ser.port = '/dev/ttyAMA0'# ser.baudrate = 57600# ser.timeout = 10def __init__(self, cmd=None, data=None, server=None):"""初始化函数"""self.cmd = cmdself.data = dataself.server = serverpassdef run(self, cmd=None):"""启动命令"""if hasattr(self, self.cmd):self.link()func = getattr(self, self.cmd)return func(self.data)passdef link(self):"""连接串口"""self.ser.port = serialPortself.ser.baudrate = serialBaudrateself.ser.timeout = serialTimeout# self.ser.bytesize = 8# self.ser.parity = 'N'# self.ser.xonxoff = 0# self.ser.rtscts = 0:qself.ser.close()self.ser.open()passdef finger(self, data):self.link()check = self.getImage()  # 检测获取图像if check is not True:return check, []self.link()check = self.genChar(data)  # 检测生成特征值if check is not True:return check, []# ================= 生成特征值时图像会清除,所以要重新采集 ========================== #self.link()check = self.getImage()  # 检测获取图像if check is not True:return check, []if self.server is not None:self.server.send("True".encode("utf8"))  # 发送数据说明准备好了self.link()check = self.upImage()  # 上传图像if check is not True:    # 校验和错误return check, []self.tag, self.data = self.getUpImage()if len(self.tag) is 0 and len(self.data) is 0:  # 得到数据错误return False, []return True, []def save(self, data=None):self.link()check = self.regModel()if check is not True:    # 校验和错误return check, []self.link()check = self.upChar(data)  # 上传特征值if check is not True:  # 校验和错误return check, []self.tag, self.data = self.getUpChar()if len(self.tag) is 0 and len(self.data) is 0:  # 得到数据错误return False, []return True, []passdef check(self, data=None):"""检验指纹, 生成特征值"""self.link()check = self.match()   # 比较指纹特征if check is not True:return check, []score = self.data[1]*255 + self.data[2]  # 返回的分数值self.link()check = self.regModel()  # 合成指纹特征值if check is not True:return check, []return True, scorepassdef isFinger(self, data=None):"""判断现在的指纹和下载的指纹是否相同"""self.link()check = self.downCharCheck()if check is not True:    # 判断是否可以发送数据return check, []"""下载指纹"""self.link()self.downCharData(data)"""检验指纹"""self.link()check = self.match()if check is not True:return check, []score = self.data[1] * 255 + self.data[2]  # 返回的分数值return True, scorepassdef saveToHard(self, data=None):"""储存指纹到硬件"""check = self.psEnroll()if check is not True:return check, []return True, self.datapassdef checkPSIdentify(self,data=None):"""自动检测指纹"""check = self.psIdentify()if check is not True:return check, []return True, self.datapassdef creatFinger(self, data=None):"""创建指纹库"""num = len(data)for i in range(num):fingerData = eval(data[i][4])fingerData = DealBuff(fingerData)fingerData = fingerData.write()self.link()check = self.downCharCheck()if check is not True:  # 判断是否可以发送数据return check"""下载指纹"""self.link()self.downCharData(fingerData)"""储存指纹"""self.link()check = self.psStoreChar(eval(data[i][0]))if check is not True:print(check)return checksys.stdout.write("\r"+"#"*(i+1) + str((i+1) * 100 / num))sys.stdout.flush()print("\r")return Truepassdef psEnroll(self, data=None):"""一次性储存  返回页码"""cmd = self.HEAD + [0x01, 0x00, 0x03, 0x10, 0x00, 0x14]return self.isOk(cmd, 14)passdef psEmpty(self, data=None):""" 清空指纹库 """cmd = self.HEAD + [0x01, 0x00, 0x03, 0x0D, 0x00, 0x11]return self.isOk(cmd, 12)passdef psDeletChar(self, data=None):"""删除是定指纹"""num1 = int(data / 256)num2 = int(data % 256)cmd = [0x01, 0x00, 0x07, 0x0C, num1, num2, 0x00, 0x01]check = 0for i in cmd:     # 得到校验和check = check + icmd.append(int(check / 256))cmd.append(int(check % 256))cmd = self.HEAD + cmdreturn self.isOk(cmd, 12)passdef psIdentify(self, data=None):"""自动验证指纹 """cmd = self.HEAD + [0x01, 0x00, 0x03, 0x11, 0x00, 0x15]return self.isOk(cmd, 16)passdef psStoreChar(self, data=None):""" 储存模板 到指定位置"""num1 = int(data / 256)num2 = int(data % 256)cmd = [0x01, 0x00, 0x06, 0x6, 0x02, num1, num2]check = 0for i in cmd:     # 得到校验和check = check + icmd.append(int(check / 256))cmd.append(int(check % 256))cmd = self.HEAD + cmdreturn self.isOk(cmd, 12)passdef getImage(self, data=None):"""获取图像"""cmd = self.HEAD + [0x01, 0x00, 0x03, 0x01, 0x00, 0x05]   # 发送命令获取内容return self.isOk(cmd, 12)passdef genChar(self, data=None):"""生成特征文件"""if data == "1":cmd = self.HEAD + [0x01, 0x00, 0x04, 0x02, 0x01, 0x00, 0x08]  # 发送命令return self.isOk(cmd, 12)  # 图像接收数据 12 大小elif data == "2":cmd = self.HEAD + [0x01, 0x00, 0x04, 0x02, 0x02, 0x00, 0x09]  # 发送命令return self.isOk(cmd, 12)  # 图像接收数据 12 大小passdef match(self, data=None):"""比较指纹特征"""cmd = self.HEAD + [0x01, 0x00, 0x03, 0x03, 0x00, 0x07]   # 发送命令获取内容return self.isOk(cmd, 14)passdef regModel(self, data=None):"""合成指纹特征值"""cmd = self.HEAD + [0x01, 0x00, 0x03, 0x05, 0x00, 0x09]   # 发送命令获取内容return self.isOk(cmd, 12)passdef upChar(self, data=None):"""上传特征模块检测"""buff = bytes()if data == "1":cmd = self.HEAD + [0x01, 0x00, 0x04, 0x08, 0x01, 0x00, 0x0e]  # 发送命令return self.isOk(cmd, 12, False)elif data == "2":cmd = self.HEAD + [0x01, 0x00, 0x04, 0x08, 0x02, 0x00, 0x0F]  # 发送命令return self.isOk(cmd, 12, False)passdef getUpChar(self, data=None):"""上传特征模块数据"""buff = self.ser.read(834)self.ser.close()subpackage = DealBuff(buff)   # 分割内容self.tag, self.data, check = subpackage.read()if check is not True:    # 校验和错误return [], []return self.tag, self.datadef downCharCheck(self, data=None):"""下载特征值检测先要初始化,发送获取图像命令"""self.getImage()self.link()cmd = self.HEAD + [0x01, 0x00, 0x04, 0x09, 0x02, 0x00, 0x10]  # 发送命令 下载的数据放在buff2中return self.isOk(cmd, 12)passdef downCharData(self, data):"""下载特征值的数据"""self.writeRead(data, 0)  # 发送数据 接收为0"""如果不重新断开然后连接会出现卡死:发送的数据丢失"""self.link()self.ser.close()self.link()self.ser.close()passdef upImage(self, data=None):"""上传图像检测"""cmd = self.HEAD + [0x01, 0x00, 0x03, 0x0a, 0x00, 0x0e]  # 发送命令return self.isOk(cmd, 12, False)passdef getUpImage(self, data=None):"""获取后续的图像数据"""buff = self.ser.read(40032)self.ser.close()subpackage = DealBuff(buff)   # 分割内容self.tag, self.data, check = subpackage.read()if check is not True:    # 校验和错误return [], []return self.tag, self.datadef writeRead(self, cmd, length, close=True):"""发送命令读取原始字节"""cmd = bytes(cmd)self.ser.write(cmd)buff = self.ser.read(length)   # 接收数据if close:self.ser.close()    # 接受完数据断开comreturn buffpassdef isOk(self, cmd, length, close=True):"""判断数据是否合格"""buff = self.writeRead(cmd, length, close)  # 图像接收数据 12 大小subpackage = DealBuff(buff)   # 分割内容self.tag, self.data, check = subpackage.read()# 检验数据是否可靠if check is not True:   # 校验和错误return 999return self.check_code(self.data)passdef check_code(self, data):"""检验指令码"""return SureCore[data[0]]passpassif __name__ == "__main__":# HEAD = [0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF]# data = [0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x03, 0x0A, 0x00, 0x0E]# data = HEAD + [0x01, 0x00, 0x03, 0x01, 0x00, 0x05]# data = HEAD + [0x01, 0x00, 0x03, 0x05, 0x00, 0x09]# data = HEAD + [0x01, 0x00, 0x04, 0x08, 0x02, 0x00, 0x0f]

‘’’
注意:

1.可以先在串口调试助手上输入命令,看看数据是怎么样子的然后在分析数据,最后写程序处理数据

2.按照说明书提示最好不要改 模块的地址和密码,不然可能会成为砖头

2.非常重要!!!本人是吃了亏的,真是日了狗, 指纹模块中有个设置波特率的,说明书上是说波特率可以设置为9600倍数,其实并不是这样的,我先开始觉得速度太慢了就设置了先开始是12倍,觉得可以用还是太慢,就设置了24倍,还是可以用,但是还是慢,我一冲动就设置成了96倍,我的个乖乖,然后就是不管怎么唤它都没反应,为此我还和原子哥讨论了很久,结果就是这东西成板砖了。 然后不得已就又买了个便宜的(原子哥虽然服务好,技术支持好,就是东西太贵了,弄懂原理了就不用再买贵的了)。

下面的代码我就不贴出来了太多了还无法折叠可以去下载源程序

2.就是写一个服务器和客户端啦

我是用Qt写的客户端,用python写的服务器,模拟两个电脑通信(虽然只要一个自己的电脑)

先来一波服务器的代码

里面用到了mySql, 用来存储指纹数据

同时为了上传图像到客户端还要下载numpy, PIL 模块,其中python3中没有PIL 要下pillow

用到的cmd命令 pip install numpy, pip install pillow

Tcpserver.py

下面是服务器可能用到的

dealFile.py

服务器完成后就可以写客户端端了。(其实是两个同时进行然后相互补充)

下面是Qt代码

主要是通讯,其他的界面其实都还好,就按照自己的想法

Qt客户端 .cpp文件

客户端头文件 .h

3.然后就是数据库储存了
就是一些简单的mysql语句

dealSql.py

4.可以用Pycharm远程调试树莓派啦
网上有很多远程调试的例子,如果还是不会可以留言

首先用编写打卡的程序,用到树莓派GPIO口

clockIn.py

当能够正常打卡后就需要在液晶屏上显示了

oledshow.py

5.怎么实现物联呢
这就要用到公网平台了,应为我们都是“私网”,

刚开始想用yeelink的,但是发现好像没人维护用不了了,我就发现了“乐为物联”这个平台,操作简单

你首先得在上面注册一个用户,他上面有api的介绍,很容易看懂

再分享一波

我是想在微信上发送命令

weChat.py

如果你不想在注册或者嫌麻烦也可以通过邮箱来发送命令

邮箱的代码在下面

emailSendReceive.py

6.最后看看主程序把
分别写两个脚本运行就好了

fingerStart.py
weChatClient.py
逻辑结构图如下

树莓派:基于物联网的指纹打卡器相关推荐

  1. 关于制作基于STM32的指纹打卡器(不完全体)

    关于制作基于STM32的指纹打卡器(不完全体) 笔者认为首先需要构思好此打卡器需要实现的功能有哪些?作为一个指纹打卡器首先应该具备指纹识别功能.其次需要将我们识别到的用户反馈到显示器上给予打卡者打卡成 ...

  2. 基于物联网的室内环境检测云系统设计(树莓派RPI、Arduino、智能家居、RFID、APP)

    题 目: 基于物联网的室内环境检测云系统设计 关键词: 树莓派RPI.Arduino.智能家居.物联网 目录 摘要 2 引言 3 系统方案 3 系统硬件设计 6 1)Arduino介绍 6 2)DHT ...

  3. 【基于物联网的智能草莓种植系统的设计与实现系列教程】0-项目简介 (课程设计、毕设项目、树莓派、yolov5)

    [基于物联网的智能草莓种植系统]详细实现教程 项目各章节跳转 教程简介 项目简介 系统操作界面展示 系统主要功能概述 系统硬件结构概述 特别致谢 猜你需要 项目各章节跳转 可点击跳转到对应章节 ==& ...

  4. 【基于物联网的智能草莓种植系统的设计与实现系列教程】1-项目相关硬件购买清单与资料下载 (课程设计、毕设项目、树莓派、yolov5)

    [基于物联网的智能草莓种植系统]项目相关硬件购买清单与资料下载 项目各章节跳转 硬件清单 软件下载 代码下载 猜你需要 项目各章节跳转 可点击跳转到对应章节 ==> 努力更新中... 0.基于物 ...

  5. 【基于物联网的智能草莓种植系统的设计与实现系列教程】8.项目整体验证(课程设计、毕设项目、树莓派、yolov5、物联网)

    [基于物联网的智能草莓种植系统]BH1750 光照度传感器验证与参考代码 项目各章节跳转 树莓派环境说明 硬件连接 猜你需要 项目各章节跳转 可点击跳转到对应章节 ==> 努力更新中... 0. ...

  6. 【基于物联网的智能草莓种植系统的设计与实现系列教程】7-树莓派触3.5寸控屏连接翻转与触屏校准 (课程设计、毕设项目、树莓派、yolov5)

    [基于物联网的智能草莓种植系统]项目3.5寸触控屏连接验证与相关问题解决 项目各章节跳转 树莓派环境说明 显示屏硬件连接 驱动获取与传输 驱动安装与调试 猜你需要 项目各章节跳转 可点击跳转到对应章节 ...

  7. (一)基于物联网的智能安防监控机器人2207231212569

    基于物联网的智能安防监控机器人2207231212569 项目摘要: 机器人是人类一直期待的东西,但自动化的东西有点不同.理想情况下,机器人能够做的事情比自动化机器人想做的要多得多.自动化机器人希望实 ...

  8. [读书笔记]从物联到万联——Node.js与树莓派万维物联网构建实战

    前言 本文是"从物联到万联,Node.js与树莓派万维物联网构建实战"一书的读书笔记,该书翻译自"Building the Web of Things with exam ...

  9. 基于物联网图像识别的SF6环网柜气压监测系统

    基于物联网SF6环网柜气压监测系统 1.环网站侧 1)SF6气压表无线传感器研发 六氟化硫(SF6)在常态下是一种无色.无臭.无毒.不燃.无腐蚀性的气态物质,化学性质稳定性强,具有良好的电气绝缘性能及 ...

最新文章

  1. 集线器、路由器与交换机
  2. 是时候取消Scrum的产品负责人角色了吗?
  3. HTML的标签描述2
  4. ssr面板_碧蓝航线:详解SSR里诺强不强 航母专用保姆 三流防空特化型轻巡
  5. iOS 9 学习系列: Xcode Code Coverage
  6. 激光IMU融合——LIO-Mapping / LIOM / LINS / LIO-SAM算法解析
  7. Guava翻译系列之EventBus
  8. Windows8在激烈竞争的平板电脑市场的优势与特色---移动3G时代失落的windows开发人员的福音...
  9. java函数式 new_Java函数式编程-4.lambda表达式一些高级用法
  10. 严蔚敏数据结构习题第七章
  11. QGIS教程—缓冲区buffer
  12. 快速入门Maxwell基本操作流程(2D部分)
  13. oracle文本类型字段,Oracle字符的5种类型的介绍
  14. P3554 LUK-Triumphal arch 解题报告
  15. Project组合项目案例分享
  16. vue3响应式原理-effect
  17. 计算机配置很不错但是卡,高手告诉你win10电脑明明配置很好却卡顿的详尽处理手法...
  18. 曹操为何杀死神医华佗?
  19. 让我们看看往年的1024传智播客怎么安排的
  20. vue项目中element-ui的分页器(组件封装)

热门文章

  1. TCP通信常用的send,sendto,recv,recvfrom函数详解
  2. python if in 表达式方式
  3. uoj #246. 【UER #7】套路
  4. Hibernate投入JBoss怀抱
  5. 微信一面:一致性哈希是什么,使用场景,解决了什么问题?
  6. Android端集成大疆SDK(MSDK)
  7. .net core identity集成微信授权登录
  8. Mock测试详细介绍及使用
  9. 研发者的重要武器!5大就业方向供你选择
  10. 2022-07-13 第七小组 闫馨月 学习笔记