Peak.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. using GSG.NET.Concurrent;
  2. using GSG.NET.Extensions;
  3. using GSG.NET.Logging;
  4. using GSG.NET.TCP;
  5. using GSG.NET.Utils;
  6. using Peak.Can.Basic;
  7. using System;
  8. using System.Collections;
  9. using System.Collections.Generic;
  10. using System.IO;
  11. using System.Linq;
  12. using System.Text;
  13. using System.Threading;
  14. using System.Threading.Tasks;
  15. using VehicleControlSystem.ControlLayer.IO;
  16. using VehicleControlSystem.ControlLayer.Serial.DataModel;
  17. namespace VehicleControlSystem.ControlLayer.Serial.BatteryTabos
  18. {
  19. public class Peak : ICanConnecter
  20. {
  21. /// <summary>
  22. /// Peak USB Handle
  23. /// </summary>
  24. UInt16 handle = PCANBasic.PCAN_PCIBUS2;
  25. static Logger logger = Logger.GetLogger();
  26. protected TsQueue<object> qqW = new TsQueue<object>(128);//write
  27. BMUManager manager = null;
  28. object lockObject = new object();
  29. uint idOffset = 0x460;
  30. string errormsg = string.Empty;
  31. #region Enum
  32. public enum eSendMode
  33. {
  34. MANUAL = 0,
  35. AUTO,
  36. AUTO_STOP
  37. }
  38. public enum eCanRecvCase
  39. {
  40. NONE = 0,
  41. CASE1,
  42. CASE2,
  43. CASE3,
  44. }
  45. enum eMsgCaseFirst : int
  46. {
  47. Voltage_LOW = 2,
  48. Voltage_HIGH = 3,
  49. Current_LOW = 4,
  50. Current_HIGH = 5,
  51. BatteryBitStatus_LOW = 6,
  52. BatteryBitStatus_HIGH = 7
  53. }
  54. enum eMsgCaseSecond : int
  55. {
  56. ChargeFull_LOW = 2,
  57. ChargeFull_HIGH = 3,
  58. DisChargeEmpty_LOW,
  59. DisChargeEmpty_HIGH,
  60. SOC,
  61. SOH
  62. }
  63. enum eMsgCaseThird
  64. {
  65. Capacity_LOW = 2,
  66. Capacity_High,
  67. Energy_LOW,
  68. Energy_HIGH,
  69. Temperature_LOW,
  70. Temperature_HIGH
  71. }
  72. #endregion
  73. public Peak(BMUManager mrg)
  74. {
  75. this.manager = mrg;
  76. }
  77. public void Enqueue(object o)
  78. {
  79. this.qqW.Enqueue(o);
  80. }
  81. void TryToConnect()
  82. {
  83. this.qqW.Clear();
  84. var ll = PCANBasic.Reset(this.handle);
  85. ll = PCANBasic.Uninitialize(this.handle);
  86. var result = PCANBasic.Initialize(this.handle, TPCANBaudrate.PCAN_BAUD_500K, TPCANType.PCAN_TYPE_ISA, IOPort: 460, 3);
  87. if (result == TPCANStatus.PCAN_ERROR_OK)
  88. this.IsConnected = this.GetStatus();
  89. }
  90. bool isConnected = false;
  91. public bool IsConnected
  92. {
  93. get => this.isConnected;
  94. set
  95. {
  96. if (this.isConnected == value) return;
  97. this.isConnected = value;
  98. if (value)
  99. this.manager._OnConnected();
  100. else
  101. this.manager._OnDisconnected();
  102. }
  103. }
  104. public void _ThreadPoolingReceiveData()
  105. {
  106. while (!this.manager.cancel.Canceled)
  107. {
  108. try
  109. {
  110. if (!IsConnected)
  111. {
  112. Thread.Sleep(3000);
  113. this.TryToConnect();
  114. continue;
  115. }
  116. object o = this.qqW.Dequeue();
  117. if (o is PollingObject) //Scan 을 주기적 으로 진행.
  118. {
  119. //this.PollingBattery();
  120. this.Write(eSendMode.MANUAL);
  121. this.ReadMessage();
  122. }
  123. //else if ( o is ISetData ) //하나의 명령을 수행.
  124. //{
  125. // //ExecuteSetData( o as ISetData );
  126. //}
  127. else if (o is DoInvokeChangedReceivedData) //Scan 이후 결과를 처리. Manager 에서 처리
  128. {
  129. //this.manager._InvokeChgdReceivedData();
  130. this.manager._InvokeChgdWordsAndBits();
  131. }
  132. }
  133. catch (ThreadAbortException exception)
  134. {
  135. logger.E($"eSlnet {this.manager.BMUConfig.ID} - {exception.Message}");
  136. //h.CloseSocket();
  137. }
  138. catch (ObjectDisposedException exception)
  139. {
  140. logger.E(exception);
  141. this.CanError();
  142. }
  143. catch (IOException exception)
  144. {
  145. logger.E(exception);
  146. this.CanError();
  147. }
  148. catch (Exception exception)
  149. {
  150. this.CanError();
  151. logger.E($"eSlnet {exception.Message}");
  152. }
  153. }
  154. }
  155. private void PollingBattery()
  156. {
  157. var ll = this.manager.ReceivedDataDic.Values.ToList();
  158. ll.ForEach(x =>
  159. {
  160. var kind = CastTo<eDataKind>.From<Enum>(x.DataKind);
  161. switch (kind)
  162. {
  163. case eDataKind.Voltage:
  164. break;
  165. case eDataKind.Current:
  166. break;
  167. case eDataKind.BatteryState:
  168. break;
  169. case eDataKind.ChargeCompleteTime:
  170. break;
  171. case eDataKind.DisChargeCompleteTime:
  172. break;
  173. case eDataKind.SOC:
  174. break;
  175. case eDataKind.SOH:
  176. break;
  177. case eDataKind.ResidualCapacity:
  178. break;
  179. case eDataKind.ResidualEnergy:
  180. break;
  181. case eDataKind.Temperature:
  182. break;
  183. default:
  184. break;
  185. }
  186. });
  187. }
  188. int Write(eSendMode mode)
  189. {
  190. var data = new TPCANMsg();
  191. data.DATA = new byte[8];
  192. data.ID = idOffset + Convert.ToByte(this.manager.BMUConfig.ID);
  193. data.LEN = Convert.ToByte(8);
  194. data.MSGTYPE = TPCANMessageType.PCAN_MESSAGE_STANDARD;
  195. switch (mode)
  196. {
  197. case eSendMode.MANUAL:
  198. data.DATA[0] = Convert.ToByte(0x60 + Convert.ToByte(this.manager.BMUConfig.ID));
  199. break;
  200. case eSendMode.AUTO:
  201. data.DATA[0] = 0xAA;
  202. data.DATA[1] = 0xE0;
  203. break;
  204. case eSendMode.AUTO_STOP:
  205. data.DATA[0] = 0xAA;
  206. data.DATA[1] = 0x60;
  207. break;
  208. }
  209. var result = PCANBasic.Write(this.handle, ref data);
  210. if (result != TPCANStatus.PCAN_ERROR_OK)
  211. throw new Exception("Peak Write Fail");
  212. return 0;
  213. }
  214. int Write(bool auto = false)
  215. {
  216. var data = new TPCANMsg();
  217. data.DATA = new byte[8];
  218. data.ID = idOffset + Convert.ToByte(this.manager.BMUConfig.ID);
  219. data.LEN = Convert.ToByte(8);
  220. data.MSGTYPE = TPCANMessageType.PCAN_MESSAGE_STANDARD;
  221. if (auto)
  222. {
  223. data.DATA[0] = 0xAA;
  224. data.DATA[1] = 0xE0;
  225. }
  226. else
  227. {
  228. data.DATA[0] = Convert.ToByte(0x60 + Convert.ToByte(this.manager.BMUConfig.ID));
  229. }
  230. var result = PCANBasic.Write(this.handle, ref data);
  231. // Write Error
  232. if (result != TPCANStatus.PCAN_ERROR_OK)
  233. {
  234. logger.E($"[Battery Peak] - {result} -");
  235. return 9999;
  236. }
  237. return (int)result;
  238. }
  239. /// <summary>
  240. /// Peak Receive
  241. /// </summary>
  242. /// <returns></returns>
  243. TPCANStatus ReadMessage()
  244. {
  245. TPCANMsg canMsg = new TPCANMsg();
  246. canMsg.DATA = new byte[8];
  247. TPCANTimestamp CANTimeStamp;
  248. TPCANStatus stsResult = TPCANStatus.PCAN_ERROR_UNKNOWN;
  249. for (int i = 0; i < 3; i++)
  250. {
  251. Thread.Sleep(30);
  252. stsResult = PCANBasic.Read(this.handle, out canMsg, out CANTimeStamp);
  253. if (stsResult == TPCANStatus.PCAN_ERROR_OK)
  254. {
  255. if (canMsg.ID == 0x460)
  256. this.PeackCANRecv(canMsg);
  257. }
  258. else
  259. {
  260. this.IsConnected = this.GetStatus();
  261. return stsResult;
  262. }
  263. //else if (canMsg.ID != 0x460)
  264. //{
  265. // this.IsConnected = this.GetStatus();
  266. // return stsResult = TPCANStatus.PCAN_ERROR_UNKNOWN;
  267. //}
  268. }
  269. return stsResult;
  270. }
  271. void PeackCANRecv(TPCANMsg recv)
  272. {
  273. var mb = new MemoryBuffer(recv.DATA);
  274. if (mb.Length < 8)
  275. {
  276. logger.E($" - [Battery Recv Length Error] - {mb.Length} -");
  277. return;
  278. }
  279. mb.Read1Byte();
  280. var index = (eCanRecvCase)mb.Read1Byte();
  281. switch (index)
  282. {
  283. case eCanRecvCase.NONE:
  284. break;
  285. case eCanRecvCase.CASE1:
  286. this.manager.ReceivedDataDic[eDataKind.Voltage].Value = mb.ReadLeShort();
  287. this.manager.ReceivedDataDic[eDataKind.Current].Value = mb.ReadLeShort();
  288. this.manager.ReceivedDataDic[eDataKind.BatteryState].Value = mb.ReadLeShort();
  289. break;
  290. case eCanRecvCase.CASE2:
  291. this.manager.ReceivedDataDic[eDataKind.ChargeCompleteTime].Value = mb.ReadLeShort();
  292. this.manager.ReceivedDataDic[eDataKind.DisChargeCompleteTime].Value = mb.ReadLeShort();
  293. this.manager.ReceivedDataDic[eDataKind.SOC].Value = mb.ReadByte();
  294. this.manager.ReceivedDataDic[eDataKind.SOH].Value = mb.ReadByte();
  295. break;
  296. case eCanRecvCase.CASE3:
  297. this.manager.ReceivedDataDic[eDataKind.ResidualCapacity].Value = mb.ReadLeShort();
  298. this.manager.ReceivedDataDic[eDataKind.ResidualEnergy].Value = mb.ReadLeShort();
  299. this.manager.ReceivedDataDic[eDataKind.Temperature].Value = mb.ReadLeShort();
  300. break;
  301. }
  302. }
  303. /// <summary>
  304. /// Battery State To -> [2^6] Bool List
  305. /// </summary>
  306. /// <param name="state"></param>
  307. void BatteryStateCheck(double state)
  308. {
  309. var cd = Convert.ToByte(state);
  310. var rs = new BitArray(new byte[] { cd });
  311. var result = rs.Cast<object>().ToList();
  312. }
  313. void CanError()
  314. {
  315. this.IsConnected = false;
  316. var result = PCANBasic.Uninitialize(this.handle);
  317. }
  318. bool GetStatus()
  319. {
  320. bool result = false;
  321. TPCANMsg msg;
  322. msg.DATA = new byte[8];
  323. TPCANTimestamp canTimeStamp;
  324. Write(eSendMode.MANUAL);
  325. Thread.Sleep(100);
  326. var state = PCANBasic.Read(this.handle, out msg, out canTimeStamp);
  327. if (state != TPCANStatus.PCAN_ERROR_OK)
  328. {
  329. logger.E($"[BMS] - Disconnected [{state}]");
  330. return false;
  331. }
  332. //if (msg.ID == 0x460)
  333. // result = true;
  334. //else
  335. // result = false;
  336. return true;
  337. }
  338. private void DisConnect()
  339. {
  340. this.IsConnected = false;
  341. PCANBasic.Reset(this.handle);
  342. PCANBasic.Uninitialize(this.handle);
  343. this.manager._OnDisconnected();
  344. }
  345. }
  346. }