模块划分: 客户端:C --Qt开发界面--跨平台使用 统一的要求: 功能结构体: 请求结构体: 数据头--固定 数据体--不同模块,不一样 响应结构体: 数据头 数据体 举例: enum TypeInfo { REGISTER_REQ, // 注册请求 REGISTER_RES, // 注册响应 }; struct Head // 通用 { int type; int len; }; 以注册为例: struct RegisterReq { Head head; char username[32]; char password[32]; char email[32]; char tel[32]; char department[32]; RegisterReq() { head.type = REGISTER_REQ; head.len = sizeof(RegisterReq); } }; struct RegisterRes { Head head; char username[32]; int status; RegisterRes() { head.type = REGISTER_RES; head.len = sizeof(RegisterRes); } }; 3星 1、注册登录 注册: 输入信息:用户名、密码、确认密码、邮箱、手机号、部门 自动补充的信息:状态、注册时间、默认的权限--在服务端补充 校验:客户端本地校验:用户名、密码、合法字符的判断 邮箱、手机号格式的判断、两次密码比较是否一样 服务端二次校验:用户名、密码、合法字符的判断 服务端判断:用户名是否存在,不存在则写入[用户名唯一] 安全:密码加密的处理,防止明文传输和明文显示 加密算法:双向非对称加密 RSA 公钥--私钥:公钥加密,私钥解密 客户端:拿到公钥,加密,放到结构体里面传输密文 服务端:用私钥解密,得到密码明文 公钥、私钥的产生,是在服务端每次随机生成固定长度的一组密钥 将公钥发给对应的客户端,私钥在服务端留着用来解密密文 原始内容:123456 密钥:公钥 xxww99 加密算法:(2个参数:原始内容,密钥-公钥) --> 返回计算结果:密文:x8sdsdsaxxxxadsadsadsadsda889e21ess 密钥:私钥 uuyy84 将密文发给另一端之后,解密算法(2个参数:密文,密钥-私钥)--> 明文:123456 登录: 输入信息:用户名、密码、验证码[可选] 校验:客户端本地校验:用户名、密码、合法字符的判断 服务端二次校验:用户名、密码、合法字符的判断 安全:密码加密的处理,防止明文传输和明文显示 状态:成功--显示主界面--根据用户拥有的权限,来显示不同的子界面 失败--再次登录 UI美化:QSS样式美化 -------------------------------------------- 数据库表:用户信息表、角色权限表 --------------------------------------------- 5星 2、考勤识别、管理、异常处理 考勤识别: AI识别,需要传入图片,将图片放到AI算法里面调用模型进行识别,返回所属的分类,通过分类ID获取数据库里面用户信息表中的用户信息,并且将信息展示到界面上。 获取图片:打开摄像头--获取一张有人脸的照片 OpenCV库来打开摄像头并获取人脸照片 服务端识别:客户端上传图片到服务端,调用服务端AI算法,返回识别结果 本地识别:需要在客户端机器上部署AI模型,将图片传入调用AI算法识别,拿到分类ID,再把ID发送给服务端,进行数据库查询,拿到查询结果,在客户端UI展示 识别:成功--要记录人脸打开信息:考勤信息表--用户名[id]、考勤时间、考勤设备id 失败--提示失败 管理: 查询--展示一个特定时间段的考勤统计结果 考勤判断:上班时间段--下班时间段 忘打卡--补打卡次数: 5次/月 异常处理: 考勤异常:迟到、早退、缺勤、请假-[细分....] 4星 3、权限管理 前提条件:管理员才能管理这个模块 管理: 先查询到特定用户,再点开特定用户的权限信息,对权限勾选/去勾选,最后提交修改,保存到服务端是数据库 界面:查询条件----用户名、工号、注册时间段、部门、邮箱、手机号等 查询结果展示----用二维表视图展示[MVD] 右击菜单--选择特定用户--修改权限、禁用用户[修改状态] 修改权限----显示当前选定用户拥有的权限[勾选√],没有的权限不勾 修改的话,对选项勾选或去勾选之后,提交修改 权限:有就是1,无就是0 admin 管理员 export 报表导出 log_search 日志查询 img_in 图像录入 map_mark_change 地图标注修改 history 历史回放、历史查询 warning_man 警报管理 device_man 设备管理 version_man 客户端版本管理 数据库表: id 角色名 具体的权限...【9个】 5星 4、客户端版本更新 更新方式:增量更新、全量更新 增量更新:逐版本更新 全量更新:某个版本的完整更新,就是整个安装包 更新逻辑:比较版本--最新[不更新] --不是最新--更新--比较要要更新文件的大小--选择更新方式 增量更新: 循环操作: 当前版本--找到下一个版本要更新的文件--下载--覆盖到客户端本地目录--完成更新--再接着比较版本... 全量更新:下载最新版的完整安装包,安装到本地即可 核心: 文件传输--大文件--要支持 断点续传--记录一些传输的信息--确认断点位置--续传 数据库表: 版本信息表--读取 id 当前版本号 依赖版本号[前置版本] 文件名 文件大小 文件MD5 文件S端路径 文件C端路径[相对路径] 状态 产生时间 传输记录表[可选] 界面: 更新进度展示:进度条、详细信息罗列... 更新程序:和主程序要相互独立 update.exe client.exe 版本如何记录? 配置文件来记录,可以是 version.ini 或 version.xml 3星 5、报表导出 逻辑:提前数据[日志、历史...]--导出到文件: 文档、表格[csv,xlsx]、pdf 、html--保存到本次磁盘 一、提供接口,让别的模块传参调用 二、用列表展示已经导出的记录,可预览相应的文件 5星 6、实时播放 逻辑:客户端先获取所有可查看的摄像头信息,形成一个菜单配置[1-4-9-16-25] 然后在根据播放视图选择,组合菜单配置形成播放的实时画面 播放:要给选好的画面连接,进行多线程的拉流处理--RTSP协议--FFmpeg --拉流过来之后:解码形成图片--在标签上显示 数据库表: 摄像头信息--设备信息表--会包含每个摄像头的url[网址] 数据流:H.265压缩内容,200倍的压缩比,要解压--解码 在三方库中已经完成了:FFmpeg库 有2部分的东西: 1、常规业务 查询请求--拿到所有可用摄像头的信息 请求:只需要指定结构体头里面的功能类型值就行 struct RealtimeShowReq { Head head; RealtimeShowReq() { head.type = xx; // xx为提前定好的枚举变量 head.len = sizeof(RealtimeShowReq); } }; 响应:回一个摄像头信息[柔性数组]的响应 struct VideoInfo { int id; char url[256]; // 拼接好的摄像头网址 协议://ip:port/1/last.ts // ... }; struct RealtimeShowRes { Head head; VideoInfo vi[0]; // 柔性数组 }; 2、视频业务 用FFmpeg去拉rtsp url的地址流数据过来,用FFmpeg来解压缩、解码就行 3星 7、系统设置 客户端的设置: 样式控制:字体、颜色、外观调整 国际化的显示:中文、英文、法文... 快捷键: 自启动的服务:开机启动 自动登录:要记录用户名、密码[加密记录] ...... 如何生效:将配置信息保存到xml文件中,启动时加载设置 3星 8、日志查询 查询条件:级别、时间段等 显示结果:用表格显示[MVD的视图]、分页显示--分页算法-将结果分成更小的块来显示,提升性能 1 2 3 ... 98 99 100 跳转__页[下拉框/编辑框] 导出:调用报表导出接口 4星 9、图像录入 用于训练模型,每个新员工都需要采集一些特定数量的图片来训练,训练完了之后,用于识别--考勤等 逻辑:客户端--先把要录入的员工工号输入--确认工号信息正确--再点开摄像头--获取该员工特定数量、视角的照片--上传到服务端特定目录下保存--用于模型训练 界面: 通过输入工号--获取员工信息--显示--通过操作员判断正确否 点一下录入按钮:就会提示分别路哪些视角:正脸、侧脸、眨眼、张嘴等 每个录完之后,用标签显示一下录到的照片--预览 确认无误--提交--上传到服务器特定工号目录保存--同时记录到数据库表 数据库表:图片信息表:id、图片名字、路径、所属工号、上传时间、是否已训练... 5星 10、地图标注-摄像头、设备 特殊的地方:编译器得使用MSVC的编译器,才能支持浏览器的绘制 通过绘制的浏览器,加载百度在线地图 标注:设备的坐标[经度、纬度],设备名称、编号、状态等显示出来 核心: QT 和 网页的JS要交互,使用信号槽来交互 用到的技术 webchannal.js 需要额外掌握:HTML、JS代码的编写 [会C/C++,必然能秒懂] 逻辑: 显示地图的标注点--去查询设备的经纬度--拿到所有可用设备经纬度--标记到网页地图里 修改标注点:改状态、改名字、调整经纬度等 数据库表: 设备信息表 要经度、维度 名字 id 状态 等 5星 11、历史回放、历史数据查询分析 历史回放 -- 回放的是视频内容 查询特定时间段、特定设备类型、编号---拿到了特定时间段内的视频文件url ----使用FFmpeg对【RTSP】url 进行拉流--解码显示 操作: 截图--保存某一帧图片 快进、后退、暂停、播放等控制视频的操作 历史数据查询分析 -- 查看的是环境信息的历史数据 需要指定查询条件--时间段、设备等--拿到历史数据--展示到二维表 --分析[日、周、月、年]:最小值、最大值、平均值、中位数--形成图形、曲线 --用到QChart库,或者三分库 QCustomPlot来显示更多数据量的图形 结构体里面如何表示内容每次查询都不一样,但是都能拿到:用不定长结构体[柔性数组] 数据库表: 视频信息表、环境信息表...... 5星 12、实时环境信息展示 逻辑: 得用一个大屏来实时显示环境信息 分不同区域来显示,还可以显示别的数据到大屏里面来 主要是环境信息[温度、湿度、粉尘浓度、施工进度等] 其他信息:看一下小地图、看一下考勤情况、动态切换一下监控摄像头情况 跟具体模块负责人对接,要接口就行 实时环境信息:现场的各种传感器采集而来 测试环境--可以模拟数据发送过来 实时信息:通过硬件上传数据之后,到服务端了,给所有在线的客户端转发的 数据库表: 环境信息表:id 设备id 温度 适度 粉尘浓度 施工进度表:id 施工类型 预计工作量 当前完成量 时间 ... 真假实时:转发为真,轮询为假 4星 13、警报管理 针对哪些做出警报的判断? 温度、湿度、粉尘浓度、施工进度等 要对特定指标进行阈值的管理:可以动态调整阈值--最大、最小值 发生了警报,怎么处理? 1、预警--硬件端先触发声、光警报,接着软件部分会给所有在线客户端提示预警信息 2、解决--控制现场设备,自动调节--失败了--给值班室派单--解决问题 数据库表: 阈值信息表、警报信息表 界面: 管理阈值的界面--先查询-再修改 显示警报的界面--要在主窗口中,所有子模块都能同时看见的位置显示 如何触发: 数据到了服务端之后,除了实时转发的操作,还要一个预警判断的操作 发生异常了,同时记录到警报信息表,且给所有在线客户端转发警报提示 3星 14、设备管理 设备:摄像头、硬盘录像机、各种工地的设备[资产管理的] 对设备进行增删改查 添加:新设备--录入信息--对于外露固定位置的设备,要有安装位置的经纬度 删除:修改设备状态--废弃、不可用、维修、正常 改:修改已经录入的信息 查询:查看都有哪些设备 数据库表:设备信息表 id 设备类型 名字 序列号 状态 安装时间 经度 维度 负责人 服务端:S 5星 1、网络搭建、TCP、UDP实现 确定并发量:1000--5000的并发量来设置 select + 线程池 最终的服务端:在linux平台下运行--Ubuntu 20.3--也可以使用epoll来处理高并发 解耦操作: 把业务当任务处理,要写一个通用的任务类来表示不同的业务 线程池的实现:先考虑使用C++实现--鸿蒙系统的线程池 还需要确定的: 1、每个用到网络的模块,要提交:请求结构体、响应结构体 2、要给每一个请求、响应结构体,分配枚举类型内容--type--用来区分不同的业务功能 3、任务类可以使用模板来处理,结合业务抽象类[纯虚函数],定好统一当接口 4、考虑使用高级的操作--设计模式的选择:工厂模式、观察者模式等 协议相关: TCP--心跳检测、粘包处理 RTSP[udp]--使用Live555框架来支撑rtsp服务即可--开源框架 4星 2、数据库搭建 MySQL数据库--建库--建表 建库:统一建一个库名: znwl_db 建表:需要和每一个用到数据库的负责人--对接--要他们的数据库表--整合重复的内容--建表 SQL脚本导出:完成建库、建表之后,要导出sql语句,形成一个脚本,其他人使用脚本,本地即可生成一个新的库、表 封装:提供接口,给其他人使用--作为子服务来使用的 类--公有的接口--给他人调用 接口:增删改查的操作--先以sql语句为参数--拿结果集或拿条数 升级v2:写一个类来组装sql语句,每一条语句,就是一个对象,较安全 安全校验:防注入校验--正则匹配 私有API:自动初始化使用的--实例化对象时,自动把数据库连上 升级:数据库连接池--解决连接复用的问题 备份导出:shell脚本--定时导出--打包--上传到指定的ftp服务器保存 3星 3、日志封装 日志作用:用于问题定位的 级别:常规、调试、警告、错误、致命等 写到哪里? 文件、数据库表 文件:所有级别的记录 -- 超过指定大小之后-- 文件翻滚 -- 换一个文件继续记录 -- 实现文件翻滚算法 数据库表: 警告、错误、致命等重要的级别的日志内容 写日志:同步、异步的选择?---- 异步高效 -- 用队列来缓冲--记录任务 封装:类--提供对应的接口--函数宏[跟级别挂钩]:只需要选择宏,给一个日志描述,其他的自动生成 内容: id 级别 时间 日志描述 文件名 函数名 行号 等 内容一式两份,一个写到文件,一个写到数据库表 参考框架: log4c log4cPlus等框架,仅作参考,还是要自己实现封装的功能 5星 4、CNN模型搭建 作用:提供识别功能的模块, 需要产生一个模型文件,通过训练的方式产生 对传进来的图片,使用模型去快速匹配到相应的分类,从而实现AI的人脸识别功能 CNN: 卷积神经网络算法:核心过程--卷积--池化--全连接 反向训练:随机梯度下降算法 搭建:神经网络--需要搭建很多层,逐层去计算并处理各种特征--图片特征--能最终快速找到分类--产生:训练好的模型 训练: 输入:一堆图片特征--都是处理过的图片 输出:模型文件 识别: 输入: 一张图片 过程:将图片处理之后,去训练好的模型里面,匹配特征,找到分类,返回 输出: 这张图片对应的所属分类 提供: 模型文件 接口函数 --------------------------------------------- 迁移学习: 已经训练了一个模型了,再来新员工,如何加到模型里面去 两种方案:一、加进来之后,重新全部再来一遍 二、加进来之后,在已有的基础上,进行二次训练--迁移 --------------------------------------------- 细节: 拟合问题:过拟合、欠拟合 活体检测问题:3维成像效果--立体的方式 配合动作来识别 ----------------------------------------- 技术: 框架 TensorFlow--谷歌的开源框架 真正的智能体,也就是所谓的通用AI,真正牛逼起来的时候:量子计算机量产的时候 ----------------------------------------- 4星 5、图像管理 图像--人脸照片 用来直接训练的图片--采集好的 识别产生的单张照片--识别时保存的 分类:用工号来作为子目录,保存每个员工的人脸照片 什么时候创建子目录? 注册成功的时候,产生了员工id,此时就可以触发--调用接口来创建子目录 接口:传进来一个工号[字符串],会到图像根目录去创建这个工号子目录 对于用于不同功能的图片,记录的时候,可以加上标志--训练否 接口:删除已经无用的照片--不再用于训练的照片、有干扰的照片 【是否要用界面显示对应子目录下的照片,并进行相应的操作--查询、修改】 4星 6、模型数据预处理 处理的是照片,要把原始的照片--处理--变成矩阵特征 处理方式:向量化、灰度化、二值化、浮点归一化、降噪等处理方式 原理:图片中的每一个像素点,体现的都是RGB的颜色值 (255,255,255) 使用的框架:OpenCV 3星 7、配置管理 作用:使得服务端,不需要再进行二次编码,特别是一些参数要变的时候:ip、port、路径...... 配置信息存放:xml文件来保存,如:config.xml 内容: socket:ip、port MySQL: host、user、password、db、port等 log: 文件翻滚--大小限定,存放的路径、是否启动异步模式 图片存放:根目录 配置服务的启动方式:冷启动、热启动 内容提供方式:饿汉=0、懒汉=1 客户端文件版本存放:根目录 解析库:tinyxml2 使用三方库的头文件和源文件就可以搞定 提供内容的方式: 在主函数中第一个加载起来 饿汉式:一开始就全局所有的内容--可以使用全局变量来存储最新的内容 懒汉式:需要时,再提供--提供函数接口,调用--返回结果 启动方案: 定时监控配置内容是否发生变化,变化了,要随时做出相应的重启服务 定时监控:使用一条子线程,间隔10秒读一下xml配置文件和上一次的数据对比 有变化了,就按配置的方式启动 5星 8、客户端文件版本管理 权限--版本管理权限 获取版本号:查询到所有版本号,放到一个下拉框中展示 添加已经变化的文件:-- 增量更新 专门的UI界面: 选择文件的本地路径 版本号[规则],依赖版本号 服务端的存放路径,客户端的存放路径 二维表:点击添加文件之后,会将上述的内容,写到表格中 当添加完所有变化的文件之后 再点击提交按钮,上传到服务端,文件存到磁盘对应目录[服务端的存放路径],相应的信息写到数据库表 技术: 文件上传、断点续传 文件打包:所有文件打包成一个安装包,作为全量更新的安装包 数据库表:版本信息表--写入 3星 9、视频存储管理 先铺垫一下:视频文件在哪里? 存在硬盘录像机里面 摄像头--数据线--硬盘录像机[存视频文件]--软件服务端--MySQL数据库[存信息] | 客户端 管理视频文件: 连上每一个硬盘录像机--查看对应的摄像头目录下都有哪些视频文件 还可以调整一下摄像头对应的文件夹名字--默认是摄像头id 动作:查询、修改 增加--是摄像头的事情 [还可以加上UI来显示,操作会更加方便] 设置覆盖周期:只会保存多久的视频--30天、60天... 设置每个视频文件的时长:5min,10min...... 品牌: 海康威视、大华、宇视科技等[全国前三] 4星 10、活体检测处理 4星 11、推送、通知管理 本质:群发,给所有在线的客户端群发的 什么时候发? 有新通知的时候,群发 群发之后,要记录每一个已经发过的账号信息 如果后面在登录,要判断是否已经发过某一条通知,没发过的接着发,发过的不要再发了 推送记录表:id、用户名、通知id、发送时间、状态 通知信息表: id、通知标题、通知内容、创建时间、状态、用户id 管理通知: 增删改查 最好是用一个ui界面管理一下相关的通知 保证所有登录成功的用户,都能收到一次最新的通知 【参考邮件系统】 通知:还可以有推送的记录,以及阅读的状态:未读、已读 ================================================================================== 业务分离:只要是自己业务相关的,不管在客户端还是服务端, 都要写代码去实现 前后分离:分界线是:前端(客户端),后端(服务端) 前端只做前端的业务 后端只做后端的业务 前后的业务通信,需要商量好特定的格式 --------------------------------------- 业务分离: 必须得2个端的开发语言一样 前后分离: 2个端开发的语言不一样时,就得使用 --------------------------------------- 现在的项目:采用业务分离的方式 ============================================================================================== 合代码的一些细节: 1、客户端的代码合并 A、保证所有模块使用同一个套接字,这样收包的时候,就统一在一个地方了 B、模块对应的类名,一定要根据功能来命名,不允许使用默认的名字 C、合代码的原则:尽量少修改的原则,只需要在主模块添加适当的代码为主 子模块的功能保持不动 D、合代码之后,保证原有的功能不会被修改,且不影响其他模块的使用 2、服务端的代码合并 A、自己的子服务模块要先合并好,是一种被动调用的方式 B、客户端的业务要合到服务端来时,要用类的方式来合并[xx.h,xx.cpp]