SerialPortExample.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. using SerialPortUtility;
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using UnityEngine;
  7. public class SerialPortExample : MonoBehaviour
  8. {
  9. public int baudrate = 115200;
  10. public SerialPortUtilityPro serialPortUtility;
  11. public SerialPortUtilityPro.OpenSystem openMode = SerialPortUtilityPro.OpenSystem.PCI;
  12. private static int baseAddress;
  13. private static int offsetAddress;
  14. private Queue<byte> tempDataQueue;
  15. public string PortName = "";
  16. private int coinsAmount = 0;
  17. private const int SlotCount = 1;
  18. bool urlBack = false;
  19. byte dataIndex = 1;
  20. private static bool _isInit = false;
  21. private void Awake()
  22. {
  23. if (!_isInit)
  24. {
  25. DontDestroyOnLoad(gameObject);
  26. Init();
  27. }
  28. }
  29. private void Init()
  30. {
  31. _isInit = true;
  32. serialPortUtility = gameObject.GetComponent<SerialPortUtilityPro>();
  33. serialPortUtility.OpenMethod = openMode;
  34. serialPortUtility.DeviceName = PortName;
  35. serialPortUtility.StopBit = SerialPortUtilityPro.StopBitEnum.OneBit;
  36. serialPortUtility.DataBit = SerialPortUtilityPro.DataBitEnum.EightBit;
  37. serialPortUtility.Open();
  38. //serialPortUtility.ReadCompleteEventObject.AddListener(ReadStreamingBinary);
  39. //byte[] datas = new byte[8] { 0xAA, 0x08, 0x04, 0x01, 0x00, 0x00, 0x3C, 0xBB };
  40. //serialPortUtility.Write(datas);
  41. if (PortName.Contains("/dev/ttyS0"))
  42. RequestUrl(dataIndex);
  43. }
  44. void Update()
  45. {
  46. #region 测试代码
  47. #if UNITY_EDITOR
  48. if (Input.GetMouseButtonDown(0))
  49. {
  50. //TestPayQR();
  51. }
  52. #endif
  53. #endregion
  54. //if (serialPortUtility != null && serialPortUtility.IsOpened())
  55. // {
  56. // Debug.Log(serialPortUtility.GetSerialDebugString);
  57. // Debug.Log("串口接收到数据");
  58. // }
  59. }
  60. void TestPay()
  61. {
  62. if (!PortName.Contains("/dev/ttyS0"))
  63. return;
  64. Debug.LogError("TestPay");
  65. List<byte> data = new List<byte>();
  66. data.Add(0XAA);
  67. data.Add(0X55);//帧头
  68. data.Add(0x04);//帧长度
  69. data.Add(0x01);//数据编号
  70. data.Add(0XA6);//指令
  71. data.Add(0X01);//数据
  72. data.Add(0X00);//校验位
  73. PrintFrame(data.ToArray());
  74. }
  75. void TestPayQR()
  76. {
  77. if (!PortName.Contains("/dev/ttyS0"))
  78. return;
  79. List<byte> data = new List<byte>();
  80. data.Add(0XAA);
  81. data.Add(0X55);//帧头
  82. data.Add(0x05);//帧长度
  83. data.Add(0xDA);//数据编号
  84. data.Add(0XA1);//指令
  85. data.Add(0X02);//数据
  86. data.Add(0X64);//数据
  87. byte temp = 0;
  88. for (int i = 2; i < data.Count; i++)
  89. {
  90. temp ^= data[i];
  91. }
  92. data.Add(temp);//校验位
  93. Debug.LogError($"TestPayQR temp={temp}");
  94. PrintFrame(data.ToArray());
  95. }
  96. void OnUrlPayResponse(byte[] bytes)
  97. {
  98. if (!PortName.Contains("/dev/ttyS0"))
  99. return;
  100. //计算校验值
  101. byte tempResponseCheck = 0;
  102. for (int i = 2; i < bytes.Length - 1; i++)
  103. {
  104. tempResponseCheck ^= bytes[i];
  105. }
  106. byte responseCheck = bytes[bytes.Length - 1];
  107. //回复云上分
  108. List<byte> response = new List<byte>();
  109. response.Add(0XAA);
  110. response.Add(0X55);//帧头
  111. response.Add(0X04);//帧长
  112. var dataIndex = bytes[3];
  113. response.Add(dataIndex);//数据编号
  114. response.Add(0XA1);//数据编号
  115. var data = responseCheck == tempResponseCheck ? 0X01 : 0x00;
  116. response.Add((byte)data);//数据
  117. var endIdx = bytes[3];
  118. byte temp = 0;
  119. for (int i = 2; i < response.Count; i++)
  120. {
  121. temp ^= response[i];
  122. }
  123. response.Add(temp);//校验位
  124. Debug.LogError($"responseCheck={responseCheck} tempResponseCheck={tempResponseCheck} data ={data} dataIndex={dataIndex} temp={temp}");
  125. serialPortUtility.Write(response.ToArray());
  126. if (data == 0X01)
  127. StandaloneAPI.InsertCoint(bytes[6]);
  128. }
  129. /// <summary>
  130. /// 串口读取二进制流数据
  131. /// </summary>
  132. /// <param name="data"></param>
  133. public void ReadStreamingBinary(object data)
  134. {
  135. var bin = data as byte[];
  136. PrintFrame(bin);
  137. }
  138. void PrintFrame(byte[] bytes)
  139. {
  140. if (bytes[0] == 0xAA)
  141. {
  142. if (bytes[1] == 0x55)//旧
  143. {
  144. if (bytes[4] == 0xA6)//投币
  145. {
  146. Debug.Log("旧版投币数量:" + bytes[4]);
  147. StandaloneAPI.InsertCoint(bytes[5]);
  148. }
  149. else if (bytes[4] == 0xAA) //支付盒子链接请求返回
  150. OnUrlResponse(bytes);
  151. else if (bytes[4] == 0xA1) //支付盒子支付返回(云上分)
  152. OnUrlPayResponse(bytes);
  153. }
  154. else
  155. {
  156. //Debug.Log("bytes[1]命令:" + bytes[1] + "bytes[2]命令:" + bytes[2]);
  157. Debug.Log("接收到的串口命令:" + bytes[0] + bytes[1] + bytes[2] + bytes[3] + bytes[4] + bytes[5]);
  158. //0x04:为按键是否按下的命令
  159. if (bytes[1] == 0x04)//退出
  160. {
  161. Debug.Log("确认按键退出游戏命令");
  162. if (bytes[3] == 0x01)
  163. {
  164. Debug.Log("确认按下按键");
  165. AimHandler.ins.ExitIntoEvent();
  166. SendMessage(bytes, 3);
  167. return;
  168. }
  169. else if(bytes[3] == 0x00)
  170. {
  171. Debug.Log("松开按键");
  172. SendMessage(bytes, 3);
  173. return;
  174. }
  175. }
  176. else if (bytes[1] == 01)//投币
  177. {
  178. Debug.Log("确认投币命令");
  179. StandaloneAPI.InsertCoint(bytes[3]);
  180. SendMessage(bytes, 3);
  181. }
  182. }
  183. }
  184. }
  185. /// <summary>
  186. /// 请求二维码链接
  187. /// </summary>
  188. /// <param name="dataIndex">数据编号 从1开始</param>
  189. private void RequestUrl(byte dataIndex)
  190. {
  191. byte[] datas = new byte[7] { 0xAA, 0x55, 0x04, dataIndex, 0xAA, 0x01, 0xAE };
  192. datas[6] = GetXor(datas);
  193. serialPortUtility.Write(datas);
  194. Invoke("CheckURLBack", 5f);
  195. #if UNITY_EDITOR
  196. TestBackUrl();
  197. #endif
  198. }
  199. private void CheckURLBack()
  200. {
  201. if (!urlBack && dataIndex <= 3)
  202. {
  203. Debug.LogWarning("没有拉取到支付url");
  204. RequestUrl(++dataIndex);
  205. }
  206. }
  207. /// <summary>
  208. /// 测试URL回包
  209. /// </summary>
  210. private void TestBackUrl()
  211. {
  212. var url = $"http://pay.sy1999.com:8901?productNumber=SY4G4365";
  213. var urlData = System.Text.UTF8Encoding.Default.GetBytes(url);
  214. List<byte> data = new List<byte>();
  215. data.Add(0XAA); data.Add(0X55);//帧头
  216. data.Add((byte)(urlData.Length + 3));//帧长度(数据编号到校验位的所有数据长度)
  217. data.Add(0X01);//数据编号
  218. data.Add(0XAA);//指令
  219. data.AddRange(urlData);//数据
  220. data.Add(0X00);//校验位
  221. Debug.Log($"Test: url={url} length={urlData.Length}");
  222. PrintFrame(data.ToArray());
  223. }
  224. /// <summary>
  225. /// URL请求返回
  226. /// </summary>
  227. /// <param name="data"></param>
  228. void OnUrlResponse(byte[] bytes)
  229. {
  230. urlBack = true;
  231. Debug.Log("开始解析二维码数组");
  232. int frameLength = bytes[2];
  233. Debug.Log("帧长度" + frameLength);
  234. frameLength = frameLength - 3;
  235. Debug.Log("解析后的数据长度:" + frameLength);
  236. List<byte> datas = new List<byte>();
  237. var startPos = 5;
  238. for (int i = startPos; i < frameLength + startPos; i++)
  239. {
  240. datas.Add(bytes[i]);
  241. }
  242. byte[] bs = datas.ToArray();
  243. var url = System.Text.Encoding.Default.GetString(bs);
  244. StandaloneAPI.url = url;
  245. var homeView = FindObjectOfType<HomeView>();
  246. if (homeView != null)
  247. homeView.FlushUrlQR();
  248. }
  249. void SendMessage(byte[] bytes,int index)
  250. {
  251. List<byte> s = new List<byte>(bytes);
  252. s.RemoveAt(index);
  253. bytes = s.ToArray();
  254. serialPortUtility.Write(bytes);
  255. }
  256. byte GetXor(byte[] btyes)
  257. {
  258. byte temp = 0;
  259. for (int i = 2; i < btyes.Length; i++)
  260. {
  261. temp ^= btyes[i];
  262. }
  263. return temp;
  264. }
  265. private void OnDestroy()
  266. {
  267. Debug.Log("串口程序被销毁");
  268. serialPortUtility.Close();
  269. }
  270. }