智能外卖自提柜系统的设计与实现
2020-08-19王鑫许智鸿胡华昌杨丰羽
王鑫 许智鸿 胡华昌 杨丰羽
摘要:随着经济社会的高速发展,“互联网+”时代的到来,基于Online To Offline(020)商业模式的外卖配送行业迅速崛起,其发展前景一片广阔,在提供方便快捷服务的同时也带动了社会经济的发展[1]。但是随着外卖配送行业的进一步壮大,基于外卖配送的很多问题也日益凸显,比如外卖偷盗和错拿以及配送过程中带来的交通安全和社会违法犯罪隐患等[2]。通过智能外卖自提柜系统,配送员将外卖暂存于智能外卖自提柜中,可以有效地解决外卖配送过程中出现的各种问题,安全有保障地将外卖送达到客户手中[3]。本文通过对移动端APP、PC端Web信息管理平台、设备端实体柜以及服务器四个部分的整体设计与分析来整合搭建一套完整可运行的智能自提柜系统,并较为详细地对各部分之间交互通信方式的设计和实现原理进行了分析。
关键词:智能外卖自提柜系统;Netty框架;Android;Flask MVC框架;stm32单片机;数据库
中图分类号:TP311 文献标识码:A
文章编号:1009-3044(2020)19-0010-04
开放科学(资源服务)标识码(OSID):
1 智能外卖自提柜系统工作原理
智能外卖自提柜系统以服务器为中心,移动端和设备端通过自定义通信协议与服务器进行通信。系统采用前后端完全分离的设计模式,将系统数据库搭建在服务器端,并对来自移动端和设备端的请求消息进行编解码和事务处理。PC端平台与服务器共享系统数据库,实现系统数据的可视化管理,系统的总体设计图如图1所示。
2 服务器端开发
服务器端选择完全异步非阻塞的Netty框架作为底层的通信框架,Netty是对NIO的优化和封装,其API使用更简单,开发门槛更低[4]。同时服务器整合了MyBatis框架来管理MySQL数据库。服务器分为移动端服务器和设备端服务器两部分。其中,Netty服务器创建启动的时序图如图2所示。
2.1 移动端服务器开发
2.1.1移动端通信传输协议
移动端通信协议由数据头部和消息两部分组成,其中数据头部的内容为消息长度,消息部分为传输的消息对象的Json格式字符串的二进制。同时,本系统选择速度较快的阿里巴巴的Json转换工具Fastj son来实现JavaBean与字符串之间的转换。协议格式如图3所示。
2.1.2 移动端通信框架的实现
TCP/IP协议是以字节为单位的流式的数据传输协议,数据之间是连续的没有界限的,这就导致一次收到的数据帧可能不是完整的,也就是常见的TCP粘包/拆包问题。为了解决这个问题,Netty提供了很多数据编解码器,来帮助开发人员更方便地完成数据的编解码任务。
协议头部的数据长度部分是由NetW提供的LengthField-Prepender自定义长度编码器添加的,它可以计算当前待发送消息的二进制字节长度,将该长度添加到待发送数据的头部。同时,在此之前还需要通过一个自定义编码器来将传输对象转换为JSON格式字符串,并进一步转换为二进制数据。与自定义长度编码器配套使用的是LengthFieldBasedFrameDecoder解码器,通过该解码器可以读取数据帧头部的长度部分,并会在此后连续读取长度部分个字节,将这些字节作为一个完整的消息传递到下一个自定义消息解码器中,进一步转换为消息对象,再交给自定义事务处理器ServerHandler进行处理。
2.1.3移动端服务器事务处理
Android移动端的事务处理请求被封装为一个Interacti-veRequest类,其内部的成员变量msgType表示该请求的事务类型。移动端发送给服务器的所有请求包括:注册请求,登录请求,订单查询请求,空柜查询请求,存放请求,注销请求等。当服务器端接收到移动端发来的消息时,首先经过解码器将消息转换为消息对象,然后在ServiceHandler的ChannelRead0方法中获取其类型属性,根据属性的值确定其代表的事务类型,并进行相应的事务处理,最终返回给客户端相应的处理结果。
2.2 设备端服务器开发
2.2.1设备端通信传输协议
服务器与设备实体柜之间使用自定义通信传输协议进行TCP通信,数据桢格式如下表l所示。部分指令类型的详细设计如下表3所示。
2.2.2 设备端通信框架的实现
服务器端通过自定义解码器DeviceDecoder来解决TCP粘包/拆包问题,当解码器读到四个连续的OxOa时才认为是读到了一个数据帧的帧头,并获取其后两个字节的帧长度,若Byte-Buf中剩余字节数量大于等于帧长度,则将帧头后连续帧长度个字节作为一个完整的消息进行处理。否则,则认为发生了拆包现象,标记ByteBuf读取位置,等待下一次读取再处理。
本系统规定除应答消息外,不论是服务器端还是设备端对于接收到的其他指令都必须回复一个应答消息来通知另一端已经接收到正确信息。但是考虑到在通信过程中可能会发生数据丢失或者数据出错等情况,所以系统规定对于丢失或者出错的数据均采取丢弃处理,不予应答,并制定了相应的指令超時重传和指令重复不处理的机制。对于服务器端来说:
(1)对于接收的设备端指令的处理
服务器端在每个设备端对应的服务器端DeviceHandler中维护一个已接收并处理指令集ReceiveMap和一个已发送但未应答指令集SendMesMap,分别用来存储已成功接收到的设备端的指令Frameld和已发送的但还未收到应答的服务器端指令Frameld,则存在以下情况:
若设备端指令在传输过程中丢失或者校验和检验出错,服务器端采用丢弃处理,不予应答。
若设备端指令完整接收,且校验和无误,则立即返回给设备一个应答消息指令,其Frameld为接收的设备端消息的编号,表示对于设备传输的该编号指令已经接收并且无误。并且将该指令的编号存储到相应的ReceiveMap中,表示该指令已处理过,防止由于应答消息丢失导致的设备端重传指令的重复处理。
若设备端指令为应答指令,则将SendMesMap中相应编号的已发送服务器端指令进行删除。
(2)对于发送的服务器端指令的处理
对于服务器端发送给设备端的指令采用超时重传机制。使用scheduleAtFixedRate0方法在每个设备对应的服务器端线程中开启一个定时器,每隔一段时间都会将相应SendMesMap中还没收到应答的指令进行重传。
2.2.3 设备端服务器事务处理
由于各类型指令除Content部分外其它部分数据格式以及整体编解码方式都一致,所以采用模板方法模式设计指令类。服务器端将父类指令封装为Devlnstruction抽象类,各类型指令封装为类Devlnstruction000-006.均继承自父类指令。其中,父类中给出整体指令编解码的逻辑骨架,Content部分的编解码方法以及指令的具体业务处理逻辑被设置为抽象方法,在子类中进行方法的挂钩和具体实现。
为了更好地管理设备和用户,向不同的设备和用户主动的发送消息,服务器维护了ChanneIDevList和ChanneIUserList列表来管理在线设备和用户,并使用Collections.synchronizedList0方法对List进行包装来获取一个线程安全的List。同时在线列表提供了对指定用户或设备的消息发送方法,允许服务器对指定的设备和用户进行消息传输,实现了设备端服务器和设备服务器之间的通信。
3 移动端开发
3.1 Netty通信客户端的整合
移动端选择广泛使用的Android平台开发移动端手机APP.Android APP需要通过Netty客户端与服务器端进行自定义协议通信,所以需要将移动端程序与Netty客户端框架进行整合,其中,Netty客户端创建启动的时序图如下图4所示。
Application是Android的一个系统组件,Android系统会为每个程序运行时创建一个Application类的对象且仅创建一个,因为它是全局的单例的,所以我们将Netty客户端搭建在自定义的Application组件中,并对外提供与服务器传输消息的方法来实现通信。在程序启动时,系统就在Application的OnCreate0方法中初始化Netty客户端连接。
4 PC端开发
PC端在Python主流开发语言环境下,利用Flask工具搭建一个可高效扩展开发的基于MVC的自提柜信息管理平台[6],同时使用SQLAlchemy创建ORM模型,然后利用ORM模型对数据库进行操作。开发简单快捷,拓展性极强,运行效率较高。同时采用了Nginx、uWSGI的部署模式,提高了服务的并发能力。
4.1 服务器架构
PC端设计了Web服务器、应用服务器、Web应用以及数据库服务器的四层服务器架构,其交互逻辑如下图5所示。
Nginx作为直接对外的服务接口,负责接收客户端发送过来的HrITP请求。当用户端发起HTTP请求时,如果是静态文件请求,Nginx就根据Nginx配置的静态文件目录返回请求的静态资源;如果是动态请求,Nginx就通过配置文件将请求传递给uWSGI。uWSGI根据请求的URL调用Flask App对应的函数。涉及数据库的部分,便通过SQIAlchemy高效访问MySQL数据库,并返回数据库操作结果给Flask。
全部处理完后Flask将结果转发回uWSGI,uWSGI接收后转发回Nginx,Nginx最终将结果返回给客户端。
4.2 MVC框架搭建
MVC框架(Model View Controller)是一种将应用程序的逻辑层和视图层相分离设计,并通过控制层連接的开发模式[7]。其中模型、视图、控制器三个核心部件构成了整个Web应用程序。在本系统中,通过对Flask原生的MVC架构进行改装[8],框架的工程目录设计清晰明了,各部分功能明确,当开发人员使用MVC框架进行二次开发时,只需要根据自己开发任务的要求,对各个目录功能进行扩展和善即可高效开发。
5 设备端开发
设备端硬件平台基于stm32单片机,使用WIFI模块和GPRS模块实现通信功能,支持WIFI网络和运营商网络,满足多数投放环境的需要。软件平台基于FreeRTOS实时操作系统,平衡单片机资源和设备功能需求,保证设备交互和通信的实时性,设备投放简单,易于维护,具有高可扩展性。
5.1硬件设计
设备硬件由通信模块、设备交互模块、控制核心和转接模块构成,其中转接模块根据设备功能需求定制,不同的转接模块可以组建不同配置的柜体。
(1)通信模块:采用SIM800+ESP8266模块,二者都通过AT指令与单片机通讯,可根据投放地的网络情况选择不同的连接方式。
(2)设备交互模块:包括按键和显示屏,当前方案为按键输入取货密码,显示屏提示信息,设备后续迭代升级较为方便,例如按键输入可升级为扫描二维码。
(3)控制核心:使用stm32f103RBT6,片内有20k字节RAM,128k字节flash,满足系统运行和数据缓存的需求,支持捧电检测,当外部断电时,切换至内部电源供电,同时向服务器报警,当内部电源电量过低时,进入掉电模式,所有缓存数据存人flash中,保证掉电后设备数据不丢失,同时通知服务器,等待维护人员更换电源。
(4)转接模块:考虑到设备的多样化和可扩展性,硬件设计中,将柜体的控制部分独立,做成转接模块,由于设备电锁等开关型器件较多,10口资源有限,转接模块中使用74HC595等串人并出的IC节省输出10口,转接模块板载了stm32f0单片机,实现柜体中数字传感器数据采样和处理。
5.2 软件设计
软件设计中的任务设计框图如图7所示。由于设备与服务器之间吞吐数据量小,指令固定,因此使用自定义通信协议,除了协议格式的确定.还需加入应答机制、数据重发机制。每条指令有唯一的Frameld,指令发送后,接收方会返回对应Fra-meld的应答帧,如指定时间内未收到应答,则需重发。
利用FreeRTOS动态分配任务栈的特点,可以方便得实现上述需求,本设计通过动态创建和删除数据重发任务实现多条指令并行的应答等待和数据重发。设计中用到数据解析任务和数据重发任务。
(1)数据解析任务:解析接收到的指令,指令分为应答帧和非应答帧,非应答帧包含服务器的控制指令,应答帧包含其父指令的Frameld(将每帧数据称为其对应的应答帧的父指令)。数据解析任务如果收到应答帧,会将其中包含的Frameld存人消息队列MsgBox_Rpy中。
(2)数据重发任务:每条指令发送后都会根据Frameld创建唯一的数据重发任务,任务被创建后,执行如下操作:
申请内存,将该帧数据缓存。
每5s检测一次消息队列MsgBox_Rpy,检测完成则重发数据,最多重发3次,3次后删除本任务。
如果检测到MsgBox_Rpy中有数据,则判断其中的数据是否和本任务的Frameld匹配,如果匹配,则删除本任务。
参考文献:
[1]张文红.020模式下的餐饮外卖行业分析研究[J].农村经济与科技,2019,30(474):124-125.
[2]黄子成,网络外卖引发的社会治安问题及综合治理对策研究[J].现代商贸工业,2018,39:151-153.
[3]王恩全,李鑫雨,刘雪薇,等.互联网时代保温自提柜在外卖配送行业的应用与展望[J].中国市场,2019(17):161-162.
[3]王恩全,李鑫雨,刘雪薇,等.互联网时代保温自提柜在外卖配送行业的应用与展望[J].中国市场,2019(17):161-162.
[4]魏瑩.基于Netty框架的智能终端与服务器通信的研究[Dl.西安:西安电子科技大学,2017.
[5]李林锋.Netty权威指南[M].北京:电子工业出版社,2014:11-45.
[6]李超,徐云龙,华中伟,等.一种基于Python Flask的Web服务器端设计[J].信息与电脑,2019(8):87-88.
[7]李守振,张南平,常国锋.Web应用分层与开发框架设计研究[Jl.计算机工程,2006,32(22):274-276.
[8]边蓓蓓,于萍.MVC模式在Web中的应用研究[J].信息技术与信息化,2015(6):82-83.
【通联编辑:李雅琪】
收稿日期:2020-03-27
作者简介:王鑫(1999-),男,山东泰安人,山东科技大学,本科;许智鸿(1998-),男,山东菏泽人,山东科技大学,本科;胡华昌(2000一),男,湖北黄冈人,山东科技大学,本科;杨丰羽(1999-),男,山东青岛人,山东科技大学,本科。