首页 > 编程 > C# > 正文

通过C#实现自动售货机接口

2019-10-29 21:39:45
字体:
来源:转载
供稿:网友

这篇文章主要介绍了通过C#实现自动售货机接口,需要的朋友可以参考下

下面分几部分介绍C#实现自动售货机接口的方法,代码写的非常详细,不懂的地方有注释可以参考下。

MachineJP类:

第1部分:串口初始化,串口数据读写

 

 
  1. using System; 
  2. using System.Collections.Generic; 
  3. using System.IO.Ports; 
  4. using System.Linq; 
  5. using System.Text; 
  6. using System.Threading; 
  7. using System.Threading.Tasks; 
  8. using System.Windows.Forms; 
  9. using MachineJPDll.Models; 
  10. using MachineJPDll.Utils; 
  11.  
  12. namespace MachineJPDll 
  13. /// <summary> 
  14. /// 售货机接口(接口) 
  15. /// </summary> 
  16. public partial class MachineJP 
  17. #region 变量 
  18. /// <summary> 
  19. /// 串口资源 
  20. /// </summary> 
  21. private SerialPort m_SerialPort = null
  22. /// <summary> 
  23. /// 待发送给串口的命令列表 
  24. /// </summary> 
  25. private List<Cmd> m_CommandList = new List<Cmd>(); 
  26. /// <summary> 
  27. /// 等待ACK_RPT或NAK_RPT的PC端向VMC端发送的消息列表 
  28. /// </summary> 
  29. private List<MT> m_WaitResultMTList = new List<MT>(); 
  30. /// <summary> 
  31. /// 从串口接收的数据集合(数据已通过验证) 
  32. /// </summary> 
  33. private ReceiveDataCollection m_ReceiveDataCollection = new ReceiveDataCollection(); 
  34. #endregion 
  35.  
  36. #region 构造函数与析构函数 
  37. /// <summary> 
  38. /// 售货机接口(接口) 
  39. /// </summary> 
  40. public MachineJP() 
  41.  
  42.  
  43. ~MachineJP() 
  44. if (m_SerialPort != null
  45. m_SerialPort.Close(); 
  46. m_SerialPort.Dispose(); 
  47. m_SerialPort = null
  48. #endregion 
  49.  
  50. #region 读取串口数据 
  51. /// <summary> 
  52. /// 读取串口数据 
  53. /// </summary> 
  54. /// <returns>从串口读取的数据</returns> 
  55. private byte[] ReadPort() 
  56. //读取串口数据 
  57. DateTime dt = DateTime.Now; 
  58. while (m_SerialPort.BytesToRead < 2) 
  59. Thread.Sleep(1); 
  60.  
  61. if (DateTime.Now.Subtract(dt).TotalMilliseconds > 1500) //超时 
  62. return new byte[0]; 
  63. List<byte> recList = new List<byte>(); 
  64. byte[] recData = new byte[m_SerialPort.BytesToRead]; 
  65. m_SerialPort.Read(recData, 0, recData.Length); 
  66. recList.AddRange(recData); 
  67. int length = recData[1] + 2; //报文数据总长度 
  68. while (recList.Count < length) 
  69. if (m_SerialPort.BytesToRead > 0) 
  70. recData = new byte[m_SerialPort.BytesToRead]; 
  71. m_SerialPort.Read(recData, 0, recData.Length); 
  72. recList.AddRange(recData); 
  73. Thread.Sleep(1); 
  74.  
  75. return recList.ToArray(); 
  76. #endregion 
  77.  
  78. #region 向串口发送数据 
  79. /// <summary> 
  80. /// 向串口发送数据 
  81. /// </summary> 
  82. /// <param name="cmd">待发送的命令</param> 
  83. /// <param name="SN">序列号</param> 
  84. private void WritePort(Cmd cmd, byte SN) 
  85. //发送数据 
  86. List<byte> sendData = cmd.Data; 
  87. sendData[1] = (byte)sendData.Count; 
  88. sendData[2] = SN; 
  89. byte[] checkCode = CommonUtil.CalCheckCode(sendData, sendData.Count); 
  90. sendData.AddRange(checkCode); 
  91. if (cmd.Mt != null
  92. m_WaitResultMTList.Add(cmd.Mt); 
  93. m_SerialPort.Write(sendData.ToArray(), 0, sendData.Count); 
  94. LogHelper.Log(LogMsgType.Info, true, sendData.ToArray()); 
  95. #endregion 
  96.  
  97. #region 发送ACK消息 
  98. /// <summary> 
  99. /// 发送ACK消息 
  100. /// </summary> 
  101. /// <param name="SN">序列号</param> 
  102. private void SendACK(byte SN) 
  103. List<byte> sendData = new List<byte>() { 0xE5, 0x00, 0x00, 0x40, 0x80 }; 
  104. WritePort(new Cmd(sendData), SN); 
  105. #endregion 
  106.  
  107. #region Init 初始化 
  108. /// <summary> 
  109. /// 初始化 
  110. /// </summary> 
  111. /// <param name="com">串口号(例:COM1)</param> 
  112. public void Init(string com) 
  113. if (m_SerialPort == null
  114. m_SerialPort = new SerialPort(com, 9600, Parity.None, 8, StopBits.One); 
  115. m_SerialPort.ReadBufferSize = 1024; 
  116. m_SerialPort.WriteBufferSize = 1024; 
  117. m_SerialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived); 
  118.  
  119. if (!m_SerialPort.IsOpen) 
  120. m_SerialPort.Open(); 
  121.  
  122. GET_SETUP(); 
  123. CONTROL_IND(0x13, new byte[] { 0x00 }); //初始化完成标志 
  124. GET_STATUS(); 
  125.  
  126. SetDecimalPlaces(2); //设置小数点位数 
  127. #endregion 
  128.  
  129. #region Close 关闭连接 
  130. /// <summary> 
  131. /// 关闭连接 
  132. /// </summary> 
  133. public void Close() 
  134. m_SerialPort.Close(); 
  135. #endregion 
  136.  
  137. #region 接收串口数据 
  138. /// <summary> 
  139. /// 接收串口数据 
  140. /// </summary> 
  141. /// <param name="type">消息类型</param> 
  142. /// <param name="subtype">消息子类型</param> 
  143. public byte[] Receive(byte type, byte subtype) 
  144. return m_ReceiveDataCollection.Get(type, subtype); 
  145.  
  146. /// <summary> 
  147. /// 接收串口数据 
  148. /// </summary> 
  149. /// <param name="type">消息类型</param> 
  150. /// <param name="subtype">消息子类型</param> 
  151. public byte[] WaitReceive(byte type, byte subtype) 
  152. DateTime time = DateTime.Now; 
  153. while (true
  154. byte[] receiveData = m_ReceiveDataCollection.Get(type, subtype); 
  155. if (receiveData != nullreturn receiveData; 
  156.  
  157. if (DateTime.Now.Subtract(time).TotalMinutes > 3) return null
  158.  
  159. Thread.Sleep(50); 
  160.  
  161. /// <summary> 
  162. /// 接收串口数据 
  163. /// </summary> 
  164. /// <param name="type">消息类型</param> 
  165. public byte[] WaitReceive(byte type) 
  166. DateTime time = DateTime.Now; 
  167. while (true
  168. byte[] receiveData = m_ReceiveDataCollection.Get(type); 
  169. if (receiveData != nullreturn receiveData; 
  170.  
  171. if (DateTime.Now.Subtract(time).TotalMinutes > 3) return null
  172.  
  173. Thread.Sleep(50); 
  174. #endregion 
  175.  
  176. #region 判断消息是否发送成功 
  177. /// <summary> 
  178. /// 判断消息是否发送成功 
  179. /// </summary> 
  180. public bool SendSuccess(byte type, byte subtype) 
  181. DateTime time = DateTime.Now; 
  182. while (true
  183. if (DateTime.Now.Subtract(time).TotalMinutes > 3) 
  184. return false
  185. byte[] ack = m_ReceiveDataCollection.Get(type, subtype); 
  186. byte[] nak = m_ReceiveDataCollection.Get(type, subtype); 
  187. if (ack != nullreturn true
  188. if (nak != nullreturn false
  189.  
  190. Thread.Sleep(1); 
  191. #endregion 
  192.  

第2部分:接收串口数据,并响应货机,向货机发送数据

 

 
  1. using System; 
  2. using System.Collections.Generic; 
  3. using System.IO.Ports; 
  4. using System.Linq; 
  5. using System.Text; 
  6. using MachineJPDll.Models; 
  7. using MachineJPDll.Utils; 
  8.  
  9. /* 
  10. * VMC->PC数据的接收,货机事件的分发 
  11. */ 
  12.  
  13. namespace MachineJPDll 
  14. partial class MachineJP 
  15. #region serialPort_DataReceived 
  16. /// <summary> 
  17. /// 数据接收事件的方法 
  18. /// </summary> 
  19. public void serialPort_DataReceived(object obj, SerialDataReceivedEventArgs args) 
  20. byte[] receiveData = ReadPort(); 
  21.  
  22. if (CommonUtil.ValidReceiveData(receiveData)) //只处理验证正确的数据,不正确的数据抛弃不处理 
  23. LogHelper.Log(LogMsgType.Info, false, receiveData); 
  24. byte SN = CommonUtil.GetSN(receiveData); 
  25. MT mt = new MT(receiveData); 
  26.  
  27. #region 轮询(POLL) 
  28. if (mt.Type == 0x03) 
  29. if (m_CommandList.Count > 0) 
  30. WritePort(m_CommandList[0], SN); 
  31. m_CommandList.RemoveAt(0); 
  32. else 
  33. //发送ACK消息 
  34. SendACK(SN); 
  35. #endregion 
  36.  
  37. #region 发送ACK消息 
  38. if (CommonUtil.NeedACK(receiveData)) 
  39. SendACK(SN); //发送ACK消息 
  40. #endregion 
  41.  
  42. #region VMC系统参数 
  43. if (mt.Type == 0x05) 
  44. m_ReceiveDataCollection.Add(mt.Type, mt.Subtype, receiveData); 
  45. #endregion 
  46.  
  47. #region ACK_RPT或NAK_RPT 
  48. if (mt.Type == 0x01 //ACK_RPT 
  49. || mt.Type == 0x02) //NAK_RPT 
  50. if (m_WaitResultMTList.Count > 0) 
  51. m_ReceiveDataCollection.Add(m_WaitResultMTList[0].Type, m_WaitResultMTList[0].Subtype, receiveData); 
  52. m_WaitResultMTList.RemoveAt(0); 
  53. #endregion 
  54.  
  55. #region INFO_RPT 数据报告 
  56. if (mt.Type == 0x11) 
  57. #region 纸币器信息 
  58. if (mt.Subtype == 16) 
  59. m_ReceiveDataCollection.Add(mt.Type, mt.Subtype, receiveData); 
  60. #endregion 
  61.  
  62. #region 硬币器信息 
  63. if (mt.Subtype == 17) 
  64. m_ReceiveDataCollection.Add(mt.Type, mt.Subtype, receiveData); 
  65. #endregion 
  66.  
  67. #region 用户投币余额 
  68. if (mt.Subtype == 3) 
  69. m_ReceiveDataCollection.Add(mt.Type, mt.Subtype, receiveData); 
  70. #endregion 
  71. #endregion 
  72.  
  73. #region VENDOUT_RPT 出货报告 
  74. if (mt.Type == 0x08) 
  75. m_ReceiveDataCollection.Add(mt.Type, mt.Subtype, receiveData); 
  76. #endregion 
  77.  
  78. #region STATUS_RPT VMC整机状态报告 
  79. if (mt.Type == 0x0D) 
  80. m_ReceiveDataCollection.Add(mt.Type, mt.Subtype, receiveData); 
  81. #endregion 
  82.  
  83. #region SALEPRICE_IND 设置当前商品售价 
  84. if (mt.Type == 0x8E) 
  85. m_ReceiveDataCollection.Add(mt.Type, mt.Subtype, receiveData); 
  86. #endregion 
  87.  
  88. #region PAYIN_RPT VMC发送现金投币报告给PC 
  89. if (mt.Type == 0x06) 
  90. m_ReceiveDataCollection.Add(mt.Type, mt.Subtype, receiveData); 
  91. #endregion 
  92.  
  93. #region PAYOUT_RPT 出币报告 
  94. if (mt.Type == 0x07) 
  95. m_ReceiveDataCollection.Add(mt.Type, mt.Subtype, receiveData); 
  96. #endregion 
  97.  
  98. #region COST_RPT VMC扣款报告 
  99. if (mt.Type == 0x10) 
  100. m_ReceiveDataCollection.Add(mt.Type, mt.Subtype, receiveData); 
  101. #endregion 
  102.  
  103. #region ACTION_RPT 售货机行为报告 
  104. if (mt.Type == 0x0B) 
  105. m_ReceiveDataCollection.Add(mt.Type, mt.Subtype, receiveData); 
  106. #endregion 
  107.  
  108. #region HUODAO_RPT VMC货道报告 
  109. if (mt.Type == 0x0E) 
  110. m_ReceiveDataCollection.Add(mt.Type, mt.Subtype, receiveData); 
  111. #endregion 
  112. else //接收到的数据没有验证通过 
  113. LogHelper.LogException(LogMsgType.Error, false"数据异常", receiveData); 
  114. #endregion 
  115.  

第3部分:货机状态、投币、出货等接口

 

 
  1. using System; 
  2. using System.Collections.Generic; 
  3. using System.Linq; 
  4. using System.Text; 
  5. using System.Threading; 
  6. using MachineJPDll.Enums; 
  7. using MachineJPDll.Models; 
  8. using MachineJPDll.Utils; 
  9.  
  10. /* 
  11. * PC->VMC数据的发送(并非直接发送,只是添加到发送列表) 
  12. */ 
  13.  
  14. namespace MachineJPDll 
  15. partial class MachineJP 
  16. #region GET_SETUP 
  17. /// <summary> 
  18. /// PC通知VMC发送VMC_SETUP 
  19. /// </summary> 
  20. public VmcSetup GET_SETUP() 
  21. List<byte> sendData = new List<byte>() { 0xE5, 0x00, 0x00, 0x40, 0x90 }; 
  22. m_CommandList.Add(new Cmd(sendData)); 
  23.  
  24. byte[] receiveData = WaitReceive(0x05); 
  25. if (receiveData != null
  26. return new VmcSetup(receiveData); 
  27. return null
  28. #endregion 
  29.  
  30. #region CONTROL_IND PC控制售货机完成对应的动作 
  31. /// <summary> 
  32. /// PC控制VMC 
  33. /// </summary> 
  34. public bool CONTROL_IND(byte subtype, byte[] value) 
  35. List<byte> sendData = new List<byte>() { 0xE5, 0x00, 0x00, 0x41, 0x85 }; 
  36. sendData.Add(subtype); 
  37. if (value != null && value.Length > 0) 
  38. sendData.AddRange(value); 
  39. m_CommandList.Add(new Cmd(sendData, new MT(sendData))); 
  40.  
  41. return SendSuccess(0x85, subtype); 
  42. #endregion 
  43.  
  44. #region 设置小数点位数 
  45. /// <summary> 
  46. /// 设置小数点位数 
  47. /// 用于PC 通知VMC,双方的金额数据比例系数关系,PC 每次启动时,都会给 
  48. /// VMC 下发一次type=18 的消息,VMC 需要自己永久保存该数据,直到被PC 再 
  49. /// 次更新。 
  50. /// 取值范围:0、1、2 分别表示以 元、 角 、分 为单位 
  51. /// </summary> 
  52. public bool SetDecimalPlaces(int data) 
  53. return CONTROL_IND(18, new byte[] { (byte)data }); 
  54. #endregion 
  55.  
  56. #region GET_STATUS PC通知VMC发送STATUS_RPT 
  57. /// <summary> 
  58. /// PC通知VMC发送STATUS_RPT 
  59. /// </summary> 
  60. public StatusRpt GET_STATUS() 
  61. List<byte> sendData = new List<byte>() { 0xE5, 0x00, 0x00, 0x40, 0x86 }; 
  62. m_CommandList.Add(new Cmd(sendData)); 
  63.  
  64. byte[] receiveData = WaitReceive(0x0D); 
  65. if (receiveData != null
  66. return new StatusRpt(receiveData); 
  67. return null
  68. #endregion 
  69.  
  70. #region GET_INFO PC通知VMC发送INFO_RPT 
  71. /// <summary> 
  72. /// PC通知VMC发送INFO_RPT 
  73. /// </summary> 
  74. public byte[] GET_INFO(byte subtype) 
  75. List<byte> sendData = new List<byte>() { 0xE5, 0x00, 0x00, 0x40, 0x8C }; 
  76. sendData.Add(subtype); 
  77. m_CommandList.Add(new Cmd(sendData)); 
  78.  
  79. return WaitReceive(0x11); 
  80. #endregion 
  81.  
  82. #region VENDOUT_IND 出货 
  83. /// <summary> 
  84. /// PC出货指示 
  85. /// </summary> 
  86. /// <param name="device">售货机的箱体号 例如柜1 为 0x01 以此类推</param> 
  87. /// <param name="method">method =1:VMC 通过商品ID 指示出货,如果商品ID 不存在,回复NAK_RPT method =2:VMC 通过货道ID 指示VMC 出货,如果货道ID 不存在,回复NAK_RPT</param> 
  88. /// <param name="sp_id_hd_id">sp_id:通过商品ID 指示VMC 出货 hd_id:通过货道ID 指示VMC 出货</param> 
  89. /// <param name="type">如果type=0,cost 代表本次出货扣款金额 如果TYPE 不为0,则COST 必须为0</param> 
  90. /// <param name="cost">cost 代表本次出货扣款金额</param> 
  91. public VendoutRpt VENDOUT_IND(byte device, byte method, byte sp_id_hd_id, byte type, int cost) 
  92. List<byte> sendData = new List<byte>() { 0xE5, 0x00, 0x00, 0x41, 0x83 }; 
  93. sendData.AddRange(new byte[] { device, method, sp_id_hd_id, type }); 
  94. sendData.AddRange(CommonUtil.Int2ByteArray(cost, 2)); 
  95. m_CommandList.Add(new Cmd(sendData, new MT(sendData))); 
  96.  
  97. if (SendSuccess(0x83, 0x00)) 
  98. byte[] receiveData = WaitReceive(0x08); 
  99. if (receiveData != null
  100. return new VendoutRpt(receiveData); 
  101. return null
  102. #endregion 
  103.  
  104. #region HUODAO_SET_IND 设置货道商品数量 
  105. /// <summary> 
  106. /// PC通知VMC,当前货道对应商品的数量等信息 
  107. /// </summary> 
  108. /// <param name="device">表示箱柜号</param> 
  109. /// <param name="huodao">zyxxxxxx “z”固定填0 “y”固定填0 “xxxxxx”,表示商品余量,如果商品余量大于63,则统一为63</param> 
  110. public bool HUODAO_SET_IND(byte device, List<int> huodao) 
  111. List<byte> sendData = new List<byte>() { 0xE5, 0x00, 0x00, 0x41, 0x8F }; 
  112. sendData.Add(device); 
  113. for (int i = 0; i < huodao.Count; i++) 
  114. if (huodao[i] > 63) 
  115. huodao[i] = 63; 
  116. sendData.AddRange(huodao.ConvertAll<byte>(a => (byte)a)); 
  117. m_CommandList.Add(new Cmd(sendData, new MT(sendData))); 
  118.  
  119. return SendSuccess(0x8F, 0x00); 
  120. #endregion 
  121.  
  122. #region SALEPRICE_IND 设置当前商品售价 
  123. /// <summary> 
  124. /// PC通知VMC,当前商品售价 
  125. /// </summary> 
  126. /// <param name="device">表示箱柜号</param> 
  127. /// <param name="type">表示设置单价的方式;Type = 0:为按商品ID 发送单价,可以变长发送,商品种类最大不超过80 个;Type = 1: 为按货道号发送,固定发送80 个货道的单价信息</param> 
  128. /// <param name="sp_price">商品售价</param> 
  129. public bool SALEPRICE_IND(byte device, byte type, List<int> sp_price) 
  130. List<byte> sendData = new List<byte>() { 0xE5, 0x00, 0x00, 0x41, 0x8E }; 
  131. sendData.Add(device); 
  132. sendData.Add(type); 
  133. sendData.AddRange(sp_price.ConvertAll<byte>(a => (byte)a)); 
  134. m_CommandList.Add(new Cmd(sendData, new MT(sendData))); 
  135.  
  136. return SendSuccess(0x8E, 0x00); 
  137. #endregion 
  138.  
  139. #region PAYOUT_IND PC指示VMC出币 
  140. /// <summary> 
  141. /// PC指示VMC出币 
  142. /// </summary> 
  143. /// <param name="device">出币设备</param> 
  144. /// <param name="value">本次出币总金额</param> 
  145. /// <param name="type">出币类型 无需理解type 的含义,只需要在出币完成后的PAYOUT_RPT 中将该type 值回传给PC 即可</param> 
  146. public PayoutRpt PAYOUT_IND(PayoutType device, int value, byte type) 
  147. List<byte> sendData = new List<byte>() { 0xE5, 0x00, 0x00, 0x41, 0x89 }; 
  148. sendData.Add((byte)device); 
  149. sendData.AddRange(CommonUtil.Int2ByteArray(value, 2)); 
  150. sendData.Add(type); 
  151. m_CommandList.Add(new Cmd(sendData, new MT(sendData))); 
  152.  
  153. if (SendSuccess(0x89, 0x00)) 
  154. byte[] receiveData = WaitReceive(0x07); 
  155. if (receiveData != null
  156. return new PayoutRpt(receiveData); 
  157. return null
  158. #endregion 
  159.  
  160. #region COST_IND PC扣款指示 
  161. /// <summary> 
  162. /// PC扣款指示 
  163. /// </summary> 
  164. /// <param name="device">device=0,从用户投币总额中扣款;优先从用户非暂存金额中扣除(纸币尽量滞后压钞),参见《现金扣款顺序》</param> 
  165. /// <param name="value">扣款金额</param> 
  166. /// <param name="type">VMC 不用理解type 的含义,只需上报对应的COST_RPT 时回传即可</param> 
  167. public CostRpt COST_IND(byte device, int value, byte type) 
  168. List<byte> sendData = new List<byte>() { 0xE5, 0x00, 0x00, 0x41, 0x8B }; 
  169. sendData.Add(device); 
  170. sendData.AddRange(CommonUtil.Int2ByteArray(value, 2)); 
  171. sendData.Add(type); 
  172. m_CommandList.Add(new Cmd(sendData, new MT(sendData))); 
  173.  
  174. if (SendSuccess(0x8B, 0x00)) 
  175. byte[] receiveData = WaitReceive(0x10); 
  176. if (receiveData != null
  177. return new CostRpt(receiveData); 
  178. return null
  179. #endregion 
  180.  
  181. #region GET_HUODAO PC通知VMC上报HUODAO_RPT 
  182. /// <summary> 
  183. /// PC通知VMC上报HUODAO_RPT 
  184. /// </summary> 
  185. /// <param name="device">箱柜号</param> 
  186. public HuoDaoRpt GET_HUODAO(byte device) 
  187. List<byte> sendData = new List<byte>() { 0xE5, 0x00, 0x00, 0x40, 0x8A }; 
  188. sendData.Add(device); 
  189. m_CommandList.Add(new Cmd(sendData)); 
  190.  
  191. byte[] receiveData = WaitReceive(0x0E); 
  192. if (receiveData != null
  193. return new HuoDaoRpt(receiveData); 
  194. return null
  195. #endregion 
  196.  
  197. #region SET_HUODAO PC发送配置货道信息 
  198. /// <summary> 
  199. /// PC发送配置货道信息 
  200. /// </summary> 
  201. /// <param name="Cabinet">箱柜号</param> 
  202. /// <param name="hd_no">货道逻辑编号,十进制</param> 
  203. /// <param name="Hd_id">商品ID号</param> 
  204. /// <param name="Hd_count">货道剩余量</param> 
  205. /// <param name="Hd_price">货道单价</param> 
  206. /// <param name="Reserved">保留字段VMC忽略此字段,PC最好将此字段置为0</param> 
  207. public bool SET_HUODAO(byte Cabinet, int hd_no, int Hd_id, int Hd_count, int Hd_price, int Reserved = 0) 
  208. List<byte> sendData = new List<byte>() { 0xE5, 0x00, 0x00, 0x41, 0x93 }; 
  209. sendData.Add(Cabinet); 
  210. sendData.Add((byte)hd_no); 
  211. sendData.Add((byte)Hd_id); 
  212. sendData.Add((byte)Hd_count); 
  213. sendData.AddRange(CommonUtil.Int2ByteArray(Hd_price, 2)); 
  214. sendData.AddRange(CommonUtil.Int2ByteArray(Reserved, 2)); 
  215. m_CommandList.Add(new Cmd(sendData, new MT(sendData))); 
  216.  
  217. return SendSuccess(0x93, 0x00); 
  218. #endregion 
  219.  
  220. #region 开启纸硬币器 
  221. /// <summary> 
  222. /// 现金收银模组(纸币器、硬币器)开关 
  223. /// </summary> 
  224. /// <param name="open">true:开,false:关</param> 
  225. public bool CtrlCoinPaper(bool open) 
  226. if (open) 
  227. return CONTROL_IND(2, new byte[] { 1 }); 
  228. else 
  229. return CONTROL_IND(2, new byte[] { 0 }); 
  230. #endregion 
  231.  
  232. #region 找零 
  233. /// <summary> 
  234. /// 找零 
  235. /// 与手工拨弄物理找零开关相同 
  236. /// </summary> 
  237. public bool MakeChange() 
  238. return CONTROL_IND(6, new byte[] { 0 }); 
  239. #endregion 
  240.  
  241. #region 获取硬币器信息 
  242. /// <summary> 
  243. /// 获取硬币器信息 
  244. /// </summary> 
  245. public InfoRpt_17 GetCoinInfo() 
  246. return new InfoRpt_17(GET_INFO(17)); 
  247. #endregion 
  248.  
  249. #region 获取纸币器信息 
  250. /// <summary> 
  251. /// 获取纸币器信息 
  252. /// </summary> 
  253. public InfoRpt_16 GetPaperInfo() 
  254. return new InfoRpt_16(GET_INFO(16)); 
  255. #endregion 
  256.  
  257. #region 获取现金投币报告 
  258. /// <summary> 
  259. /// 获取现金投币报告 
  260. /// </summary> 
  261. public PayinRpt GetPayinRpt() 
  262. byte[] receiveData = Receive(0x06, 0x00); 
  263. if (receiveData != null
  264. return new PayinRpt(receiveData); 
  265. return null
  266. #endregion 
  267.  
  268. #region 获取用户投币余额 
  269. /// <summary> 
  270. /// 获取用户投币余额 
  271. /// </summary> 
  272. public InfoRpt_3 GetRemaiderAmount() 
  273. byte[] receiveData = WaitReceive(0x11, 0x003); 
  274. if (receiveData != null
  275. return new InfoRpt_3(receiveData); 
  276. return null
  277. #endregion 
  278.  

ReceiveDataCollection类和ReceiveData类:

 

 
  1. using System; 
  2. using System.Collections.Generic; 
  3. using System.Linq; 
  4. using System.Text; 
  5.  
  6. namespace MachineJPDll.Models 
  7. /// <summary> 
  8. /// 从串口接收到的数据(数据已通过验证) 
  9. /// </summary> 
  10. public class ReceiveData 
  11. /// <summary> 
  12. /// 从串口接收到的数据(数据已通过验证) 
  13. /// </summary> 
  14. public byte[] Data { get; set; } 
  15. /// <summary> 
  16. /// 添加到集合ReceiveDataCollection的时间 
  17. /// </summary> 
  18. public DateTime AddTime { get; set; } 
  19. /// <summary> 
  20. /// 消息类型 
  21. /// </summary> 
  22. public byte Type { get; set; } 
  23. /// <summary> 
  24. /// 消息子类型 
  25. /// </summary> 
  26. public byte Subtype { get; set; } 
  27.  
  28. /// <summary> 
  29. /// 从串口接收到的数据(数据已通过验证) 
  30. /// </summary> 
  31. /// <param name="type">消息类型</param> 
  32. /// <param name="subtype">消息子类型</param> 
  33. /// <param name="data">从串口接收到的数据(数据已通过验证)</param> 
  34. /// <param name="addTime">添加到集合ReceiveDataCollection的时间</param> 
  35. public ReceiveData(byte type, byte subtype, byte[] data, DateTime addTime) 
  36. this.Type = type; 
  37. this.Subtype = subtype; 
  38. this.Data = data; 
  39. this.AddTime = addTime; 

 

 
  1. using System; 
  2. using System.Collections.Generic; 
  3. using System.Linq; 
  4. using System.Text; 
  5.  
  6. namespace MachineJPDll.Models 
  7. /// <summary> 
  8. /// 从串口接收到的数据集合(数据已通过验证) 
  9. /// </summary> 
  10. public class ReceiveDataCollection 
  11. /// <summary> 
  12. /// 从串口接收到的数据集合(数据已通过验证) 
  13. /// </summary> 
  14. private List<ReceiveData> m_ReceiveDataList = new List<ReceiveData>(); 
  15. /// <summary> 
  16. /// 数据过期时间 
  17. /// </summary> 
  18. private int m_Timeout = 3; 
  19. private static object _lock = new object(); 
  20.  
  21. /// <summary> 
  22. /// 添加到集合 
  23. /// </summary> 
  24. /// <param name="type">消息类型</param> 
  25. /// <param name="subtype">消息子类型</param> 
  26. /// <param name="data">从串口接收到的数据(数据已通过验证)</param> 
  27. public void Add(byte type, byte subtype, byte[] data) 
  28. lock (_lock) 
  29. ReceiveData receiveData = new ReceiveData(type, subtype, data, DateTime.Now); 
  30. m_ReceiveDataList.Add(receiveData); 
  31. for (int i = m_ReceiveDataList.Count - 1; i >= 0; i--) 
  32. if (DateTime.Now.Subtract(m_ReceiveDataList[i].AddTime).TotalMinutes > m_Timeout) 
  33. m_ReceiveDataList.RemoveAt(i); 
  34.  
  35. /// <summary> 
  36. /// 从集合中获取串口接收到的数据(数据已通过验证) 
  37. /// </summary> 
  38. /// <param name="type">消息类型</param> 
  39. /// <param name="subtype">消息子类型</param> 
  40. /// <returns>从串口接收到的数据(数据已通过验证)</returns> 
  41. public byte[] Get(byte type, byte subtype) 
  42. lock (_lock) 
  43. ReceiveData receiveData = null
  44. for (int i = 0; i < m_ReceiveDataList.Count; i++) 
  45. if (m_ReceiveDataList[i].Type == type && m_ReceiveDataList[i].Subtype == subtype) 
  46. receiveData = m_ReceiveDataList[i]; 
  47. m_ReceiveDataList.RemoveAt(i); 
  48. return receiveData.Data; 
  49. return null
  50.  
  51. /// <summary> 
  52. /// 从集合中获取串口接收到的数据(数据已通过验证) 
  53. /// </summary> 
  54. /// <param name="type">消息类型</param> 
  55. /// <returns>从串口接收到的数据(数据已通过验证)</returns> 
  56. public byte[] Get(byte type) 
  57. lock (_lock) 
  58. ReceiveData receiveData = null
  59. for (int i = 0; i < m_ReceiveDataList.Count; i++) 
  60. if (m_ReceiveDataList[i].Type == type) 
  61. receiveData = m_ReceiveDataList[i]; 
  62. m_ReceiveDataList.RemoveAt(i); 
  63. return receiveData.Data; 
  64. return null

Models:

StatusRpt类:

 

 
  1. using System; 
  2. using System.Collections.Generic; 
  3. using System.Linq; 
  4. using System.Text; 
  5. using MachineJPDll; 
  6. using MachineJPDll.Enums; 
  7. using MachineJPDll.Utils; 
  8.  
  9. namespace MachineJPDll.Models 
  10. /// <summary> 
  11. /// VMC状态报告 
  12. /// </summary> 
  13. public class StatusRpt 
  14. /// <summary> 
  15. /// 从串口读取的通过验证的数据 
  16. /// </summary> 
  17. private byte[] m_data; 
  18.  
  19. /// <summary> 
  20. /// VMC状态报告 
  21. /// </summary> 
  22. /// <param name="data">从串口读取的通过验证的数据</param> 
  23. public StatusRpt(byte[] data) 
  24. m_data = data; 
  25.  
  26. public override string ToString() 
  27. StringBuilder sb = new StringBuilder(); 
  28. sb.AppendFormat("出货检测设备状态:{0}/r/n", check_st.ToString()); 
  29. sb.AppendFormat("纸币器状态:{0}/r/n", bv_st.ToString()); 
  30. sb.AppendFormat("硬币器状态:{0}/r/n", cc_st.ToString()); 
  31. sb.AppendFormat("VMC状态:{0}/r/n", vmc_st.ToString()); 
  32. sb.AppendFormat("展示位状态:{0} {1} {2} {3}/r/n", pos_st[0].ToString(), pos_st[1].ToString(), pos_st[2].ToString(), pos_st[3].ToString()); 
  33. sb.AppendFormat("机器中可用的找零量总金额(包括硬币和纸币):{0}/r/n", change.ToString()); 
  34. sb.AppendFormat("货仓1货仓2货仓3货仓4温度:{0} {1} {2} {3}/r/n", tem1.ToString(), tem2.ToString(), tem3.ToString(), tem4.ToString()); 
  35. sb.AppendFormat("货仓状态设置值:{0} {1} {2} {3}/r/n", tem_st[0].ToString(), tem_st[1].ToString(), tem_st[2].ToString(), tem_st[3].ToString()); 
  36. if (this.自动退币 == 255) 
  37. sb.AppendFormat("自动退币时间:永不自动退币/r/n"); 
  38. else 
  39. sb.AppendFormat("自动退币时间:{0}/r/n", 自动退币.ToString()); 
  40. sb.AppendFormat("找零余量(1#--6#):{0} {1} {2} {3} {4} {5}/r/n"this.找零余量1, this.找零余量2, this.找零余量3, this.找零余量4, this.找零余量5, this.找零余量6); 
  41.  
  42. return sb.ToString(); 
  43.  
  44. /// <summary> 
  45. /// 出货检测设备状态 
  46. /// </summary> 
  47. public CheckSt check_st 
  48. get 
  49. byte val = m_data[5]; 
  50. return (CheckSt)CommonUtil.GetFromByte(val, 0, 2); 
  51.  
  52. /// <summary> 
  53. /// 纸币器状态 
  54. /// </summary> 
  55. public DeviceSt bv_st 
  56. get 
  57. byte val = m_data[5]; 
  58. return (DeviceSt)CommonUtil.GetFromByte(val, 2, 2); 
  59.  
  60. /// <summary> 
  61. /// 硬币器状态 
  62. /// </summary> 
  63. public DeviceSt cc_st 
  64. get 
  65. byte val = m_data[5]; 
  66. return (DeviceSt)CommonUtil.GetFromByte(val, 4, 2); 
  67.  
  68. /// <summary> 
  69. /// VMC状态 
  70. /// </summary> 
  71. public VmcSt vmc_st 
  72. get 
  73. byte val = m_data[5]; 
  74. return (VmcSt)CommonUtil.GetFromByte(val, 6, 2); 
  75.  
  76. /// <summary> 
  77. /// 展示位状态 
  78. /// </summary> 
  79. public List<DeviceSt> pos_st 
  80. get 
  81. List<DeviceSt> deviceStList = new List<DeviceSt>(); 
  82.  
  83. byte val = m_data[6]; 
  84. for (int i = 0; i < 4; i++) 
  85. DeviceSt deviceSt = (DeviceSt)CommonUtil.GetFromByte(val, i * 2, 2); 
  86. deviceStList.Add(deviceSt); 
  87.  
  88. return deviceStList; 
  89.  
  90. /// <summary> 
  91. /// 机器中,可用的找零量总金额(包括硬币和纸币) 
  92. /// </summary> 
  93. public int change 
  94. get 
  95. return CommonUtil.ByteArray2Int(m_data, 7, 2); 
  96.  
  97. /// <summary> 
  98. /// 货仓1 温度,8 位有符号数,该温度通过货仓内传感器获取,单位:℃ 
  99. /// </summary> 
  100. public TemSub tem1 
  101. get 
  102. return new TemSub(m_data[9]); 
  103.  
  104. /// <summary> 
  105. /// 货仓2 温度,8 位有符号数,该温度通过货仓内传感器获取,单位:℃ 
  106. /// </summary> 
  107. public TemSub tem2 
  108. get 
  109. return new TemSub(m_data[10]); 
  110.  
  111. /// <summary> 
  112. /// 货仓3 温度,8 位有符号数,该温度通过货仓内传感器获取,单位:℃ 
  113. /// </summary> 
  114. public TemSub tem3 
  115. get 
  116. return new TemSub(m_data[11]); 
  117.  
  118. /// <summary> 
  119. /// 货仓4 温度,8 位有符号数,该温度通过货仓内传感器获取,单位:℃ 
  120. /// </summary> 
  121. public TemSub tem4 
  122. get 
  123. return new TemSub(m_data[12]); 
  124.  
  125. /// <summary> 
  126. /// 货仓状态设置值,共支持4 个货仓 
  127. /// </summary> 
  128. public List<TemSt> tem_st 
  129. get 
  130. List<TemSt> temStList = new List<TemSt>(); 
  131. for (int i = 0; i < 4; i++) 
  132. TemSt temSt = (TemSt)CommonUtil.GetFromByte(m_data[13], i * 2, 2); 
  133. temStList.Add(temSt); 
  134. return temStList; 
  135.  
  136. /// <summary> 
  137. /// 自动退币时间。 
  138. /// 0:表示商品出货后,立即自动退币 
  139. /// 255:表示永不自动退币 
  140. /// 1-254:表示商品出货后,自动退币时间(单位:秒) 
  141. /// </summary> 
  142. public int 自动退币 
  143. get 
  144. return m_data[14]; 
  145.  
  146. /// <summary> 
  147. /// 找零余量“找零量1#”…“找零量6#”,分别对应硬币器信息INFO_RPT.type=17 的“找零 
  148. /// 1#”…“找零6#”中每种钱币的找零数量; 
  149. /// * 找零量最大为255,超过255 时上报为255; 
  150. /// * 找零量单位为“个”,代表可找零硬币的个数。 
  151. /// </summary> 
  152. public int 找零余量1 
  153. get 
  154. return m_data[15]; 
  155.  
  156. /// <summary> 
  157. /// 找零余量“找零量1#”…“找零量6#”,分别对应硬币器信息INFO_RPT.type=17 的“找零 
  158. /// 1#”…“找零6#”中每种钱币的找零数量; 
  159. /// * 找零量最大为255,超过255 时上报为255; 
  160. /// * 找零量单位为“个”,代表可找零硬币的个数。 
  161. /// </summary> 
  162. public int 找零余量2 
  163. get 
  164. return m_data[16]; 
  165.  
  166. /// <summary> 
  167. /// 找零余量“找零量1#”…“找零量6#”,分别对应硬币器信息INFO_RPT.type=17 的“找零 
  168. /// 1#”…“找零6#”中每种钱币的找零数量; 
  169. /// * 找零量最大为255,超过255 时上报为255; 
  170. /// * 找零量单位为“个”,代表可找零硬币的个数。 
  171. /// </summary> 
  172. public int 找零余量3 
  173. get 
  174. return m_data[17]; 
  175.  
  176. /// <summary> 
  177. /// 找零余量“找零量1#”…“找零量6#”,分别对应硬币器信息INFO_RPT.type=17 的“找零 
  178. /// 1#”…“找零6#”中每种钱币的找零数量; 
  179. /// * 找零量最大为255,超过255 时上报为255; 
  180. /// * 找零量单位为“个”,代表可找零硬币的个数。 
  181. /// </summary> 
  182. public int 找零余量4 
  183. get 
  184. return m_data[18]; 
  185.  
  186. /// <summary> 
  187. /// 找零余量“找零量1#”…“找零量6#”,分别对应硬币器信息INFO_RPT.type=17 的“找零 
  188. /// 1#”…“找零6#”中每种钱币的找零数量; 
  189. /// * 找零量最大为255,超过255 时上报为255; 
  190. /// * 找零量单位为“个”,代表可找零硬币的个数。 
  191. /// </summary> 
  192. public int 找零余量5 
  193. get 
  194. return m_data[19]; 
  195.  
  196. /// <summary> 
  197. /// 找零余量“找零量1#”…“找零量6#”,分别对应硬币器信息INFO_RPT.type=17 的“找零 
  198. /// 1#”…“找零6#”中每种钱币的找零数量; 
  199. /// * 找零量最大为255,超过255 时上报为255; 
  200. /// * 找零量单位为“个”,代表可找零硬币的个数。 
  201. /// </summary> 
  202. public int 找零余量6 
  203. get 
  204. return m_data[20]; 
  205.  

以上就是C#实现自动售货机接口的代码,需要的朋友可以来学习。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表