本文章来自程序汪背后的私活小团队,线上街机的项目,希望把这些真实案例分享出来,大家能学到点东西,比如硬件怎么通过手机APP操控,软件怎么和硬件配合,在线街机方案是什么样的 具体报价情况等等。
B站【我是程序汪】 (变秃了也变强了)
今年行情变差了,私活项目也变少了,客户价格压的也越来越卷啊,建议大家一定先把本职工作做好,有额外精力可以考虑接点
开发人员(2人)
-
前端 uniapp APP
-
后端 技术栈 springboot
-
开发周期30天
-
开发人数 2人
-
整体费用是10万(APP 5万 后端 5万)
-
走的正规合同
-
云服务器1台 4核8G
技术选型
-
核心框架:Spring Boot
-
数据库连接池:Druid
-
数据库:mysql
-
Netty (tcp)
-
APP uniapp
项目背景
本来甲方就是线下游戏厅的老板,硬件是现成的,我们只是开发软件部分,麻烦的地方就是硬件跟软件的协议接口调试和直播延迟兼容问题,其他部分都是CRUD了,还有点APP甲方要求漂亮点,于是就找了专业的美工。以前程序汪小团队开发过类似的项目(线上抓娃娃机,核心流程几乎一样,接口协议有点区别)
下面是APP部分 注意哦游戏本身不用开发,只需要直播游戏画面即可
远程操控
这里程序汪重点把硬件点列下
硬件就是现成的,工作量主要是硬件的网络配置和接口调试
-
在原有的硬件设备上配置多个网络通讯,这部分没开发量就是配置调试
-
直播游戏画面,街机本身内嵌了视频采集器,这里需要配置推流华为云
简单描述下整个消息链路,涉及硬件部分大家有兴趣可以自己了解下串口协议
APP 后端服务----》TCP(Netty服务)-----〉 网络通讯(4G模块)-----》调用硬件的串口---〉最终操作街机
街机串口通信协议
下面是街机硬件本身的 串口接口的部分文档内容
我们后端构建的报文数据格式就是根据本文档构建的
各种游戏动作对应的消息指令
1、获取下位机ID(指令ID:01)
开始码 | 数据长度 | 指令ID | 指令类型 | 指令数据 | 校验位 | 结束码 |
8A | 03 | 01 | 01 | 无 | 05 | 55 |
示例:下位机接收到8A0301010555表示请求上位机连接到下位机
下位机应答:
开始码 | 数据长度 | 指令ID | 指令类型 | 指令数据 | 校验位 | 结束码 |
8A | 0A | 01 | 02 | 7位ID (F4 06 01 55 70 62 05) | 34 | 55 |
示例:上位机接收到 8A 0A 01 02 F4 06 01 55 70 62 05 34 55 表示与下位机连接功,其中7位数据(F4 06 01 55 70 62 05)为下位机唯一码。
2、投币1命令(指令ID:02)(Coin)
开始码 | 数据长度 | 指令ID | 指令类型 | 指令数据 | 校验位 | 结束码 |
8A | 04 | 02 | 01 | 投币方波个数 | 08 | 55 |
示例:下位机接收到 8A 04 02 01 01 08 55会产生投币方波 (Coin)
下位机应答
开始码 | 数据长度 | 指令ID | 指令类型 | 指令数据 | 校验位 | 结束码 |
8A | 04 | 02 | 02 | 接收到的投币方波个数 | 09 | 55 |
示例:上位机接收到 8A 04 02 02 01 09 55 表示开始产生方波
3、输出脉冲信号命令1(指令ID:03)( OUT2 OUT3 OUT4 )(和投币不可共用)
开始码 | 数据长度 | 指令ID | 指令类型 | 指令数据 | 校验位 | 结束码 |
8A | 04 | 03 | 01 | 输出数据 | 09 | 55 |
示例:8A 04 03 01 FE 06 55 8A 04 03 01 FD 05 55 8A 04 03 01 FB 03 55
输出数据说明:输出数据的8个位,代表8个输出端口,对应的位为0,对应的输出端口就输出一个方波脉冲;为1则不输出。
下位机应答:
开始码 | 数据长度 | 指令ID | 指令类型 | 指令数据 | 校验位 | 结束码 |
8A | 03 | 03 | 02 | 无 | 08 | 55 |
示例:8A 03 03 02 08 55
4、复位下位机(指令ID:04)
开始码 | 数据长度 | 指令ID | 指令类型 | 指令数据 | 校验位 | 结束码 |
8A | 03 | 04 | 01 | 无 | 08 | 55 |
示例:8A 03 04 01 08 55
下位机应答:
开始码 | 数据长度 | 指令ID | 指令类型 | 指令数据 | 校验位 | 结束码 |
8A | 03 | 04 | 02 | 无 | 09 | 55 |
示例:8A 03 04 02 09 55
5、查询下位机状态(指令ID:11)
开始码 | 数据长度 | 指令ID | 指令类型 | 指令数据 | 校验位 | 结束码 |
8A | 03 | 11 | 01 | 无 | 15 | 55 |
示例:8A 03 11 01 15 55
下位机应答:
开始码 | 数据长度 | 指令ID | 指令类型 | 指令数据 | 校验位 | 结束码 |
8A | 07 | 11 | 02 | 00 00 05 00 | 1F | 55 |
示例:8A 07 11 02 00 00 05 00 1F 55
第一个数据表示设备版本号
第二个数据表示当前的线下线上模式的状态( 00线下 01线上,其他数值无效)
第三个数据表示当前设置投币的脉冲宽度(数据X 10ms)
第四个数据表示当前设置的常开常闭参数(仅 00 0F F0 FF 有效,其他为无效操作)详情请查看对应的设置指令
6、上位机主动查询礼品信号(指令ID:06)(IN3)
开始码 | 数据长度 | 指令ID | 指令类型 | 指令数据 | 校验位 | 结束码 |
8A | 03 | 06 | 01 | 无 | 0A | 55 |
示例:8A 03 06 01 0A 55
下位机应答:
开始码 | 数据长度 | 指令ID | 指令类型 | 指令数据 | 校验位 | 结束码 |
8A | 04 | 06 | 02 | 礼品计数01 | 0D | 55 |
礼品计数01表示本次下位机检测到1次礼品信号,下位机发送该数据后会清除计数值为0,该数据最大值是255,要及时查询,以免数据超出
7、扩展输出电平信号命令1(指令ID:07)(OUT5 ---OUT11)
开始码 | 数据长度 | 指令ID | 指令类型 | 指令数据 | 校验位 | 结束码 |
8A | 04 | 07 | 01 | 输出数据 | 0D | 55 |
示例:8A 04 07 01 01 0D 55
8A 04 07 01 FF 0B 55 关闭输出, 所有输出为高(外部上拉)
8A 04 07 01 FE 0A 55 OUT9 输出0
输出数据的分别代表7个输出,对应的位为0则对应端口输出0,为1则输出1.
下位机应答:
开始码 | 数据长度 | 指令ID | 指令类型 | 指令数据 | 校验位 | 结束码 |
8A | 03 | 07 | 02 | 无 | 0C | 55 |
示例:8A 03 07 02 0C 55
8、输出脉冲信号命令2(指令ID:08)(OUT5---OUT11)
开始码 | 数据长度 | 指令ID | 指令类型 | 指令数据 | 校验位 | 结束码 |
8A | 04 | 08 | 01 | 输出数据 | 0E | 55 |
示例:8A 04 08 01 01 0E 55
输出数据说明:输出数据的7个位,代表7个输出端口,对应的位为0,对应的输出端口就输出一个方波脉冲;为1则不输出。
下位机应答:
开始码 | 数据长度 | 指令ID | 指令类型 | 指令数据 | 校验位 | 结束码 |
8A | 03 | 08 | 02 | 无 | 0D | 55 |
示例:8A 03 08 02 0D 55
6、输出脉冲信号命令2(指令ID:09)(OUT12 ---OUT18)
开始码 | 数据长度 | 指令ID | 指令类型 | 指令数据 | 校验位 | 结束码 |
8A | 04 | 09 | 01 | 输出数据 | 0F | 55 |
示例:8A 04 09 01 01 0F 55
输出数据说明:输出数据的8个位,代表8个输出端口,对应的位为0,对应的输出端口就输出一个方波脉冲;为1则不输出。
下位机应答:
开始码 | 数据长度 | 指令ID | 指令类型 | 指令数据 | 校验位 | 结束码 |
8A | 03 | 09 | 02 | 无 | 0E | 55 |
示例:8A 03 09 02 0E 55
7、扩展输出电平信号命令2(指令ID:0A)(OUT12 ---OUT18)
开始码 | 数据长度 | 指令ID | 指令类型 | 指令数据 | 校验位 | 结束码 |
8A | 04 | 0A | 01 | 输出数据 | 10 | 55 |
示例:8A 04 0A 01 01 10 55
8A 04 0A 01 FF 0E 55 关闭输出, 所有输出为高(外部上拉)
下位机应答:
开始码 | 数据长度 | 指令ID | 指令类型 | 指令数据 | 校验位 | 结束码 |
8A | 03 | 0A | 02 | 无 | 0F | 55 |
示例:8A 03 0A 02 0F 55
8、向上位机发送本次退币1数量(指令ID:0B){IN0}
开始码 | 数据长度 | 指令ID | 指令类型 | 数据ID | 指令数据 | 校验位 | 结束码 |
8A | 06 | 0B | 03 | 01 | 退币数量0001 | 16 | 55 |
示例:8A 06 0B 03 01 00 01 16 55
退币数量最大65535;下位机收不到上位机的应答会主动连续发送5次。每次间隔500Ms.
上位机应答:
开始码 | 数据长度 | 指令ID | 指令类型 | 接收的ID | 接收数据 | 校验位 | 结束码 |
8A | 06 | 0B | 04 | 01 | 退币数量0001 | 17 | 55 |
示例:8A 05 0B 04 01 00 01 17 55
·数据ID:用于防止重发与漏发用的一个循环使用的ID,每次使用后加一,溢出归零后继续循环,上位机如接收到的数据ID与上次相同,视为已经处理过,回应成功。如果收到的数据ID不等于上次收到的数据ID表示需要进行处理和回应并将最新的ID记录起来。数据ID的累加由发送方控制,并且在第一次使用时发送方需要使用1.这样不会因初始化都是0时认为重发了,
9、设置线下线上模式(指令ID:10)
开始码 | 数据长度 | 指令ID | 指令类型 | 指令数据 | 校验位 | 结束码 |
8A | 04 | 10 | 01 | 00 | 15 | 55 |
指令数据 00 表示线下模式
01 表示线上模式
其他数值无效
下位机应答
开始码 | 数据长度 | 指令ID | 指令类型 | 指令数据 | 校验位 | 结束码 |
8A | 04 | 10 | 02 | 00 | 16 | 55 |
10、设置上币的脉冲宽度(指令ID:0D)
开始码 | 数据长度 | 指令ID | 指令类型 | 指令数据 | 校验位 | 结束码 |
8A | 04 | 0D | 01 | 00 | 11 | 55 |
指令数据的范围为(数值X 10ms)
03 为30ms
依此类推...
0C 为120ms
设置其他值无效
如果抓力数据为FF 表示本次抓取的抓力为机器的内部默认值
如果抓力数据为00 表示本次抓取的抓力为机器内部的中奖电压,配合模式1可以自己控制中奖概率。
视频采集器
一般直播方案都是采用摄像头,我们这里由于街机本身内嵌了视频采集器,视频然后推流到华为云上面去 来实现直播低延迟
直播时间低延迟问题,采用华为云 比较麻烦的地方是 华为云SDK提供了 原生 安卓 苹果 h5 就是没兼容uniapp的,这里我们自己用vue去解决这个兼容问题折腾了一周
硬件部分
其实目前市面上有现成对在线街机的设备,甲方感觉贵才让我们自己定制下,硬件部分核心是需要开发通讯模块,方便远程操作对接。
配置网络部分需要懂点硬件才行,嵌入式基本的知识要学点
PC后端部分
后端管理核心模块如下
参考:https://support.huaweicloud.com/llLive-live/live_22_0018.html
https://zh.uniapp.dcloud.io/translate.html
https://netty.io/
私活越来越艰难,找到我这边来的甲方大部分也是图便宜
历史私活项目案例分享