基于Linux C++多线程服务器 + Qt上位机开发 + STM32 + 8266WIFI的智慧无人超市

前言

针对传统超市购物车结账排队时间长、付款效率低的问题,提出了一种更符合现代社会人们购物方式-基于RFID的自助收银系统。习惯了快节奏生活的人们都会选择自助收银机结账,理由显而易见:自助收银机结账很方便,几乎不用排队,也不用近距离和收银员接触,在防疫时期特别感觉安心。而且自助结账对每件物品的售价更是一次清晰地核对,最终需支付合计购物支出自己也更加清晰明了;这两年来,越来越多的智能设备应用在我们的生活领域里,为我们的生活提供了很多智能和便利。自助收银机从几年前就陆续涌入到各地商场、超市、便利店,自去年疫情发生后自助收银的需求比例更是呈直线上升趋势。自助收银机的启用,不仅节约了超市的人力开支成本,也从根本上提升了超市的购物支付效率,在这个快节奏的社会里,智能自助收银机也从根本上提升了超市等

 

基于Linux C++多线程服务器 + Qt上位机开发 + STM32 + 8266WIFI的智慧无人超市项目

 

 

技术栈+硬件选型

Linux c++应用编程;

Linux socket编程,多线程编程,实时信号(线程通信)

Qt/C++ 客户端开发;

qml(QtLocation)与c++交互 安卓开发;

Mysql 数据存储;

C语言下位机开发;

stm32c8t6 下位机(便宜,够用,市面价格10r);

RC522(RFID模块 SPI协议) 与白卡通信 获取卡号;

DTH11 温湿度采集模块(单总线协议,市面价格 4r);

sg90 舵机模块(PWM协议 市面价9r );

8226 01-s WIFI模块(uart协议 市面价格5r) 连接 C++ 服务器;

蜂鸣器  是为了有白卡与RFID交互声音

GY-NEO6MV2 GPS模块(uart协议 市面价18)

 

 

总设计流程

本次设计的->基于RFID的自助收银系统->设计主要支持的功能和程序如下:
本项目一共有五个程序,Linux C++服务器,Qt管理员端,Qt客户结算端,qml安卓端,单片机下位机端,客户端程序都有服务器断开自动重连(单片机没有,有佬会的话,我想请教一下)

Linux C++服务器:

       基于 socket 接口编写server服务端程序,监听8888端口,然后创建Mysql数据库连接,开始监听。

     面向对象程序设计中最重要的一个概念是继承,所以我编写了一个基类mythread,他有一个纯虚函数,参数为一个定义的一个参数类,包含了数据库封装好的对象,需要服务的客户端套接字,还有连接的客户端网络的信息结构体,当socket客户端成功接入时,取出该客户端套字和网络信息结构体和主函数的数据库对象来填充参数类,然后服务器端根据客户端发过来的第一个消息判断该客户端是上述哪个客户端,然后创建相应的派生类,填入该参数类,然后让mythread指针去指向这个子类对象,发生动多态,此时运行阶段时才确定函数的入口地址,执行派生类中的继承父类的已经实现的纯虚函数,此时派生类创建一个线程绑定线程处理函数去服务处理该socket套接字传过来的消息。绑定不同的线程处理函数服务不同的客户端程序。一共有四种线程处理函数服务上述四种客户端程序,由四个不同的基类去绑定。

    本项目的一个最大的特点,难点,单片机只负责发送卡号给服务器,本项目单片机传过来的卡号有以下走向,注册商品,注册会员,结账,商品入购物车,那么我该怎么知道该卡号是用来做什么呢,当时困扰了几天,然后想到Qt的信号与槽机制,联想到Linux 也有实时信号,还可携带参数,该信号是事件发生时对进程的通知机制,也可以把它称为软件中断,Linux 内核定义了 31 个不同的实时信号,信号编号范围为 34~64,我直接拿来做线程通信,所以现在怎样把他们联系起来呢,当时我想到互斥啥的想法感觉不好实现,然后我就想到了一个方法,就是设置标志位,我设立了一个全局变量 int RES=34,让RES的默认值为34,34很熟悉吧,信号编号范围为 34~64,当单片机收到卡号发给服务器时,服务器直接调用信号发送函数,此时全局变量标志位为34,所以直接发送34这个实时信号,然后触发中断执行这个信号绑定处理函数。我们一共有四个地方需要用到卡号,资源只有一个,所以当需要执行某个用到卡号的操作时,我先判断该RES的值,如果该值等于34,代表该读卡器为空闲,我就更改RES为 35 ,然后下次单片机发过来卡号,我还是直接调用发送信号,此时标志位为35 所以此时执行 35 的信号处理函数,执行完函数,需要将RES 置为默认值 34,释放资源,如果当请求资源时RES不等于 34 代表 读卡器正在被占用,此时回复客户端一个读卡器正忙,以此类推,绑定四个信号处理函数,处理这四个操作请求,一定要释放改为34。我们添加商品到购物车,如果一直点击按钮获取来获取资源就会显得很笨拙,所以默认的 34 信号处理函数为添加商品入购物车,在没有人改变标志位的情况下,就是执行商品入购物车。

   本项目,因为多个线程对数据进行增删改查,存在竞争冒险,所以在执行数据库增删改操作时,我加入条 Mysql 事务操作语句,事务是一个原子操作,执行增删改操作前 开始事务,执行结束,提交事务。

   总结 : 单片机的所有数据全部转发给服务器,服务器跟据消息的种类,标志位,进行处理后,分发给指定客户端,完成一系列操作。

主循环如下:

 while (1)
   {
      myret=server.client_socket();
      myret.my_sql=sql_typ;

      std::cout<<"new connect !!"<<endl;
      std::string str=server.readbuf();

      int num; 
      istringstream a(str);
      a >> num;

    
     switch (num)
  {
     {
     case 100001:   
    
         Mythread *android_thread=new androidthread; 
         android_thread->thread_start(myret);
         std::cout<<"安卓客户端连接成功"<<std::endl; 
     }
         break;
     case 100101:
     {
          Mythread  *admin_thread=new adminthread;   
          admin_thread->thread_start(myret);
          std::cout<<"PC客户端连接成功"<<std::endl;
     }
         break;
     case 100111:
     {
          Mythread  *cust_thread=new custthread;    
          cust_thread->thread_start(myret);
          std::cout<<"ARM客户端连接成功"<<std::endl;
     } 
         break;
     case 101001:
     {

          Mythread   *mcu_thread=new mcuthread;    
          mcu_thread->thread_start(myret);
          std::cout<<"STM32客户端连接成功"<<std::endl;
     }  
         break;
     default:
         std::cout<<"未知的错误"<<std::endl;   
         break;
     }

        
   }
   


 

Qt管理员端:

Qt管理员端具有的功能,注册商品,注册会员,充值,查看销售记录,日志。

首先连接服务器成功,自动发指令给服务器,服务器从数据库取出数据发给客户端,初始化,商品,会员,服务器上有一个文本文件记录销售记录,我给服务器文本大小做了一个限制,如果大小大于1M清空文件,清除销售记录,客户端可以通过点击按钮发送一个指令,获取文本内容显示销售记录,日志的话就是从服务器运行阶段开始,对会员充值,会员销毁,商品添加,商品删除,都会直接记录,服务器退出自动销毁。

Qt客户结算端:

Qt客户结算端具有的功能:添加商品入购物车,结算,显示从服务器端获取的温湿度数据。

商品入库取出价格,然后相加,点击结算按钮将总价格发给服务器,然后服务器判断标志位,如果读卡器被占用则取消结账,反之。此时标志位改变,下次刷的卡将充当会员卡进行数据比对,余额不足则返回数据给客户端,反之。执行完毕释放资源置为34。

qml安卓端:

qml安卓端具有的功能:地图显示当前手机与MCU的位置和距离,在售商品查询,购买记录查询,姓名号码登录。

这个安卓端其实有点画蛇添足的意思,我就是想炫耀一下我的GPS模块,然后地图显示当前手机GPS数据与MCU的GPS模块的距离和位置,功能太单调了,我就加了一个在售商品查看功能,然后给Mysql添加了1000大小的varcahr字段,存储当前用户购买记录,加了一个登录界面。

   qml的教程挺少,之前学过一遍,没有及时巩固,当时写这个qml真的炸裂,很多坑。想入门qml也简单,学一下qml与C++交互,信号与槽,函数互调。qml界面的话让gpt去写,百度CV。

STM32单片机开发:

stm32具体的功能:stm32c8t6主控芯片,DTH11温湿度采集发送给服务器客户端显示,sg90舵机模拟开门,GY-NEO6MV2 GPS 获取GPS,8226 01-s 与tcp 服务器数据交互,RC522与白卡交互,蜂鸣器提示刷卡成功。

32这调试是最恶心的,一般调试是直接通过串口打印到电脑,但是串口用来初始化8266了,问题就是这个8266,当时连接服务器一直连接不上,我就去找原因,有供电原因,还有at指令的原因,供电最好直接从32vcc上引出来,因为我是根据客户端程序连接成功后根据发过来的第一条数据来创建对应线程服务,不知道为啥这个32程序按复位键的话8266没有从第一条指令开始运行,然后就创建不了对应线程服务,只能断电,然后在重新烧录一次,调试巨麻烦。

GPS的话也是串口通信,重新初始化一个串口资源就好了,这个信号很差必须在阳台上,有条件的还是买好一点的吧我采集数据还有抱着一大堆线接个充电宝在阳台调试。gps数据有个NMEA协议,需要对数据解析出经纬度,有很多类型数据,最重要的一条就是包含经纬度的 

 

"$GPGLL,2547.35222,N,11306.12283,E,111129.00,A,A*6D";

这是当时当时在阳台调试出来的,这里我偷了个小懒,因为c语言字符串处理很鸡肋,所以我直接在32这里过滤出这条消息,一整条发给服务器,然后服务器发给Qt客户端,让Qt的QString去解分割分析处理,分分钟的事情,封装好的库就是简单

 

f4eff0cf6b7a4b8fa8a8ca56f53c46cc.png

很简单吧!

8266的话我初始化很随意,快准狠,直接配置tcp,连接WiFi然连接服务器,哈哈。

e5ae932d216c4862aed5ce3270a5ab51.png

温湿度舵机什么的没什么好讲,一个单总线写按时序拉低拉高电平就行了,一个设置指定占空比。RC522的话,驱动很复杂,我水平不太行,写不出来,直接调厂家的库了。

主循环就这样了

3af14c79a4c84857a7c467f3d64038cb.png

 

 

最后留言:

本项目一共写了半个月,遇到很多坑,当时地图传的坐标经纬度传犯了,调试了一下午才发现了这个问题,还有Linux 实时信号 是一个软件中断嘛,然后当时server的while循环的accept直接导通解除阻塞了,程序直接崩溃。查了很多资料才知道了,最后加一个goto语句哈哈就解决了。

ret_client  Myserver::client_socket()
{
reboot:
     ret_client ret;
  
     m_client_socket= accept(m_socket,(struct sockaddr *)&ret.client_struct,&len);

     if(m_client_socket==-1)
     {
       goto reboot;
     }

    ret.client_socket=m_client_socket;
    return ret;

}

这是sql语句啊,本人挺懒的,全用varchar了。

CREATE DATABASE shopping;

CREATE TABLE users(
id VARCHAR(20) unique key,
name VARCHAR(50),
phone VARCHAR(15) unique key,
balance VARCHAR(25),
text VARCHAR(1000)
)

CREATE TABLE me(
pid VARCHAR(20) unique key,
pname VARCHAR(50),
price VARCHAR(15),
brand VARCHAR(25)
)

需要源码的哥们三连加评论邮箱,直接发邮箱

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/551127.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MongoDB的安装配置及使用

文章目录 前言一、MongoDB的下载、安装、配置二、检验MongoDB是否安装成功三、Navicat 操作MongoDB四、创建一个集合&#xff0c;存放三个文档总结 前言 本文内容&#xff1a; &#x1f4ab; MongoDB的下载、安装、配置 &#x1f4ab; 检验MongoDB是否安装成功 ❤️ Navicat 操…

【全开源】多功能完美运营版商城 虚拟商品全功能商城 全能商城小程序 智慧商城系统 全品类百货商城

内容目录 一、详细介绍二、效果展示1.部分代码2.效果图展示 三、学习资料下载 一、详细介绍 完美运营版商城/拼团/团购/秒杀/积分/砍价/实物商品/虚拟商品等全功能商城 干干净净 没有一丝多余收据 还没过手其他站 还没乱七八走的广告和后门 后台可以自由拖曳修改前端UI页面 …

Unity之XR Interaction Toolkit如何在VR中实现渐变黑屏效果

前言 做VR的时候,有时会有跳转场景,切换位置,切换环境,切换进度等等需求,此时相机的画面如果不切换个黑屏,总会感觉很突兀。刚好Unity的XR Interaction Toolkit插件在2.5.x版本,出了一个TunnelingVignette的效果,我们今天就来分析一下他是如何使用的,然后我们自己再来…

numpy的使用

numpy的介绍 numpy是一个python开源的科学计算库 使用numpy可以方便的使用数组、矩阵&#xff08;列表套列表&#xff09;进行计算 包括线性代数、傅里叶变换&#xff0c;随机数生成等大量函数 python源代码和numpy和的区别 import numpy as np def func(n):a np.arange(n) *…

SAP 内部订单(二)-内部订单相关操作

业务背景&#xff1a;公司A要举办一个展会&#xff0c;持续时间大概一个月&#xff0c;涉及到材料费&#xff0c;人工费&#xff0c;外部服务费等&#xff0c;老板想要知道这个展会总共的花销是多少&#xff0c;明细是哪些&#xff0c;并且这些费用最终都进入市场部的成本中心。…

Jackson 2.x 系列【25】Spring Boot 集成之起步依赖、自动配置

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Jackson 版本 2.17.0 本系列Spring Boot 版本 3.2.4 源码地址&#xff1a;https://gitee.com/pearl-organization/study-jaskson-demo 文章目录 1. 前言2. 起步依赖3. 自动配置3.1 JacksonPrope…

数学建模-最优包衣厚度终点判别法-二(K-Means聚类)

&#x1f49e;&#x1f49e; 前言 hello hello~ &#xff0c;这里是viperrrrrrr~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f4a5;个人主页&#xff…

PyTorch小技巧:使用Hook可视化网络层激活(各层输出)

这篇文章将演示如何可视化PyTorch激活层。可视化激活&#xff0c;即模型内各层的输出&#xff0c;对于理解深度神经网络如何处理视觉信息至关重要&#xff0c;这有助于诊断模型行为并激发改进。 我们先安装必要的库: pip install torch torchvision matplotlib加载CIFAR-10数据…

淘宝扭蛋机小程序开发:开启购物娱乐新纪元

在数字时代浪潮的推动下&#xff0c;小程序作为新兴的交互平台&#xff0c;正在不断引领着购物方式的革新。淘宝扭蛋机小程序的开发&#xff0c;便是这一变革中的一颗璀璨明星&#xff0c;它将传统扭蛋机的趣味与电商购物的便捷完美融合&#xff0c;为用户带来了前所未有的购物…

微服务整合Spring Cloud Gateway动态路由

前置 创建 Spring Cloud项目 参考&#xff1a;创建Spring Cloud Maven工程-CSDN博客 1. 创建一个maven jar类型项目 在idea中右键父工程-》New-》Module 创建一个maven工程 2. 引入相关依赖 在POM文件中引入下面的依赖 <project xmlns"http://maven.apache.org/P…

【C++】力扣OJ题:构建杨辉三角

Hello everybody!今天给大家介绍一道我认为比较经典的编程练习题&#xff0c;之所以介绍它是因为这道题涉及到二维数组的构建&#xff0c;如果用C语言动态构建二维数组是比较麻烦的&#xff0c;而用C中STL的vector<vector<int>>,就可以立马构建出来&#xff0c;这也…

本地生活服务平台都有哪些,靠谱吗?

随着本地生活服务的发展潜力和盈利方式被不断挖掘&#xff0c;越来越多的人开始发现其中所蕴含着的巨大商机&#xff0c;大家所熟悉的抖音、小红书和支付宝等平台也纷纷上线了本地生活板块&#xff0c;再次印证了其前景的广阔。在此背景下&#xff0c;普通人想要趁势入局分一杯…

前端开发攻略---从源码角度分析Vue3的Propy比Vue2的defineproperty到底好在哪里。一篇文章让你彻底弄懂响应式原理。

1、思考 Vue的响应式到底要干什么&#xff1f; 无非就是要知道当你读取对象的时候&#xff0c;要知道它读了。要做一些别的事情无非就是要知道当你修改对象的时候&#xff0c;要知道它改了。要做一些别的事情所以要想一个办法&#xff0c;把读取和修改的动作变成一个函数&#…

Python语言在地球科学领域中的实践技术应用教程

原文链接&#xff1a;Python语言在地球科学领域中的实践技术应用教程https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247601506&idx6&snee03d6abdbcbe0216a07340c1b49cb8d&chksmfa820c85cdf585934051f111b1d95877ba54e71cbe74be87f9e0bd07b8d46d97bbc7d…

深入理解大语言模型微调技术

一、概念解析 1、什么是微调&#xff08;Fine-tuning&#xff09;&#xff1f; 大模型微调&#xff0c;也称为Fine-tuning&#xff0c;是指在已经预训练好的大型语言模型基础上&#xff08;一般称为“基座模型”&#xff09;&#xff0c;使用特定的数据集进行进一步的训练&am…

基于Springboot的某大药房管理系统

开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven…

小成本搏大流量:微信/支付宝小程序搜索排名优化

随着移动互联网的快速发展&#xff0c;小程序已成为企业和个人开发者重要的流量入口和业务承载平台。而小程序搜索排名则是影响小程序曝光量、用户获取及业务转化的关键因素。小柚在本文和大家探讨如何制定有效的优化方案&#xff0c;提升小程序在搜索结果中的排名。 首先跟我…

【图文教程】在PyCharm中导入Conda环境

文章目录 &#xff08;1&#xff09;在Anaconda Prompt中新建一个conda虚拟环境&#xff08;2&#xff09;使用PyCharm打开需要搭建环境的项目&#xff08;3&#xff09;配置环境 &#xff08;1&#xff09;在Anaconda Prompt中新建一个conda虚拟环境 conda create - myenv py…

Python SQL解析和转换库之sqlglot使用详解

概要 Python SQLGlot是一个基于Python的SQL解析和转换库,可以帮助开发者更加灵活地处理和操作SQL语句。本文将介绍SQLGlot库的安装、特性、基本功能、高级功能、实际应用场景等方面。 安装 安装SQLGlot库非常简单,可以使用pip命令进行安装: pip install sqlglot安装完成后…

Jenkins打包app并通过openssh上传到服务器

1、下载安装openssh 网上很多教程&#xff0c;包括开端口的&#xff0c;可以搜下 2、配置openssh根目录 进入C:\ProgramData\ssh打开文件sshd_config&#xff0c;添加配置ChrootDirectory D:\wxs\soft&#xff0c;想改端口的也在这个文件 3、安装Jenkins 参考上一篇 4、新…