Peak.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  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. //Todo:Dll 에서 상태 가져오기
  91. bool isConnected = false;
  92. public bool IsConnected
  93. {
  94. get => this.isConnected;
  95. set
  96. {
  97. if ( this.isConnected == value ) return;
  98. this.isConnected = value;
  99. if ( value )
  100. this.manager._OnConnected();
  101. else
  102. this.manager._OnDisconnected();
  103. }
  104. }
  105. public void _ThreadPoolingReceiveData()
  106. {
  107. while ( !this.manager.cancel.Canceled )
  108. {
  109. try
  110. {
  111. if ( !IsConnected )
  112. {
  113. Thread.Sleep( 3000 );
  114. this.TryToConnect();
  115. continue;
  116. }
  117. object o = this.qqW.Dequeue();
  118. if ( o is PollingObject ) //Scan 을 주기적 으로 진행.
  119. {
  120. //this.PollingBattery();
  121. this.Write(eSendMode.MANUAL);
  122. this.ReadMessage();
  123. }
  124. //else if ( o is ISetData ) //하나의 명령을 수행.
  125. //{
  126. // //ExecuteSetData( o as ISetData );
  127. //}
  128. else if ( o is DoInvokeChangedReceivedData ) //Scan 이후 결과를 처리. Manager 에서 처리
  129. {
  130. //this.manager._InvokeChgdReceivedData();
  131. this.manager._InvokeChgdWordsAndBits();
  132. }
  133. }
  134. catch ( ThreadAbortException exception )
  135. {
  136. logger.E( $"eSlnet {this.manager.BMUConfig.ID} - {exception.Message}" );
  137. //h.CloseSocket();
  138. }
  139. catch ( ObjectDisposedException exception )
  140. {
  141. this.CanError( );
  142. }
  143. catch ( IOException exception )
  144. {
  145. this.CanError( );
  146. }
  147. catch ( Exception exception )
  148. {
  149. this.CanError( );
  150. logger.E( $"eSlnet {exception.Message}" );
  151. }
  152. }
  153. }
  154. private void PollingBattery()
  155. {
  156. var ll = this.manager.ReceivedDataDic.Values.ToList();
  157. ll.ForEach( x =>
  158. {
  159. var kind = CastTo<eDataKind>.From<Enum>( x.DataKind );
  160. switch ( kind )
  161. {
  162. case eDataKind.Voltage:
  163. break;
  164. case eDataKind.Current:
  165. break;
  166. case eDataKind.BatteryState:
  167. break;
  168. case eDataKind.ChargeCompleteTime:
  169. break;
  170. case eDataKind.DisChargeCompleteTime:
  171. break;
  172. case eDataKind.SOC:
  173. break;
  174. case eDataKind.SOH:
  175. break;
  176. case eDataKind.ResidualCapacity:
  177. break;
  178. case eDataKind.ResidualEnergy:
  179. break;
  180. case eDataKind.Temperature:
  181. break;
  182. default:
  183. break;
  184. }
  185. } );
  186. }
  187. int Write(eSendMode mode)
  188. {
  189. var data = new TPCANMsg();
  190. data.DATA = new byte[ 8 ];
  191. data.ID = idOffset + Convert.ToByte( this.manager.BMUConfig.ID );
  192. data.LEN = Convert.ToByte( 8 );
  193. data.MSGTYPE = TPCANMessageType.PCAN_MESSAGE_STANDARD;
  194. switch ( mode )
  195. {
  196. case eSendMode.MANUAL:
  197. data.DATA[ 0 ] = Convert.ToByte( 0x60 + Convert.ToByte( this.manager.BMUConfig.ID ) );
  198. break;
  199. case eSendMode.AUTO:
  200. data.DATA[ 0 ] = 0xAA;
  201. data.DATA[ 1 ] = 0xE0;
  202. break;
  203. case eSendMode.AUTO_STOP:
  204. data.DATA[ 0 ] = 0xAA;
  205. data.DATA[ 1 ] = 0x60;
  206. break;
  207. }
  208. var result = PCANBasic.Write( this.handle , ref data );
  209. if ( result != TPCANStatus.PCAN_ERROR_OK )
  210. throw new Exception( "Peak Write Fail" );
  211. return 0;
  212. }
  213. int Write(bool auto = false)
  214. {
  215. var data = new TPCANMsg();
  216. data.DATA = new byte[ 8 ];
  217. data.ID = idOffset + Convert.ToByte( this.manager.BMUConfig.ID );
  218. data.LEN = Convert.ToByte( 8 );
  219. data.MSGTYPE = TPCANMessageType.PCAN_MESSAGE_STANDARD;
  220. if ( auto )
  221. {
  222. data.DATA[ 0 ] = 0xAA;
  223. data.DATA[ 1 ] = 0xE0;
  224. }
  225. else
  226. {
  227. data.DATA[ 0 ] = Convert.ToByte( 0x60 + Convert.ToByte(this.manager.BMUConfig.ID) );
  228. }
  229. var result = PCANBasic.Write( this.handle , ref data );
  230. // Write Error
  231. if ( result != TPCANStatus.PCAN_ERROR_OK )
  232. {
  233. logger.E( $"[Battery Peak] - {result} -" );
  234. return 9999;
  235. }
  236. return (int)result;
  237. }
  238. /// <summary>
  239. /// Peak Receive
  240. /// </summary>
  241. /// <returns></returns>
  242. TPCANStatus ReadMessage()
  243. {
  244. TPCANMsg canMsg = new TPCANMsg();
  245. canMsg.DATA = new byte[ 8 ];
  246. TPCANTimestamp CANTimeStamp;
  247. TPCANStatus stsResult = TPCANStatus.PCAN_ERROR_UNKNOWN;
  248. for ( int i = 0; i < 3; i++ )
  249. {
  250. Thread.Sleep( 30 );
  251. stsResult = PCANBasic.Read( this.handle , out canMsg , out CANTimeStamp );
  252. //if ( canMsg.ID != 0x460 )
  253. //{
  254. // this.IsConnected = false;
  255. // return 0;
  256. //}
  257. if ( stsResult == TPCANStatus.PCAN_ERROR_OK && canMsg.ID == 0x460 )
  258. this.PeackCANRecv( canMsg );
  259. else if ( canMsg.ID != 0x460 )
  260. this.isConnected = this.GetStatus();
  261. }
  262. return stsResult;
  263. }
  264. void PeackCANRecv(TPCANMsg recv)
  265. {
  266. var mb = new MemoryBuffer( recv.DATA );
  267. mb.Read1Byte();
  268. var index = ( eCanRecvCase )mb.Read1Byte();
  269. switch ( index )
  270. {
  271. case eCanRecvCase.NONE:
  272. break;
  273. case eCanRecvCase.CASE1:
  274. this.manager.ReceivedDataDic[ eDataKind.Voltage ].Value = mb.ReadLeShort();
  275. this.manager.ReceivedDataDic[eDataKind.Current].Value = mb.ReadLeShort();
  276. this.manager.ReceivedDataDic[ eDataKind.BatteryState ].Value = mb.ReadLeShort();
  277. break;
  278. case eCanRecvCase.CASE2:
  279. this.manager.ReceivedDataDic[ eDataKind.ChargeCompleteTime ].Value = mb.ReadLeShort();
  280. this.manager.ReceivedDataDic[ eDataKind.DisChargeCompleteTime ].Value = mb.ReadLeShort();
  281. this.manager.ReceivedDataDic[ eDataKind.SOC ].Value = mb.ReadByte();
  282. this.manager.ReceivedDataDic[ eDataKind.SOH ].Value = mb.ReadByte();
  283. break;
  284. case eCanRecvCase.CASE3:
  285. this.manager.ReceivedDataDic[ eDataKind.ResidualCapacity ].Value = mb.ReadLeShort();
  286. this.manager.ReceivedDataDic[ eDataKind.ResidualEnergy ].Value = mb.ReadLeShort();
  287. this.manager.ReceivedDataDic[ eDataKind.Temperature ].Value = mb.ReadLeShort();
  288. break;
  289. }
  290. }
  291. /// <summary>
  292. /// Battery State To -> [2^6] Bool List
  293. /// </summary>
  294. /// <param name="state"></param>
  295. void BatteryStateCheck(double state)
  296. {
  297. var cd = Convert.ToByte( state );
  298. var rs = new BitArray( new byte[] { cd } );
  299. var result = rs.Cast<object>().ToList();
  300. }
  301. void CanError()
  302. {
  303. this.IsConnected = false;
  304. var result = PCANBasic.Uninitialize( this.handle );
  305. }
  306. bool GetStatus()
  307. {
  308. bool result = false;
  309. TPCANMsg msg;
  310. msg.DATA = new byte[ 8 ];
  311. TPCANTimestamp canTimeStamp;
  312. Write(eSendMode.MANUAL);
  313. Thread.Sleep( 10 );
  314. var state = PCANBasic.Read( this.handle , out msg , out canTimeStamp );
  315. if ( msg.ID == 0x460 )
  316. result = true;
  317. else
  318. result = false;
  319. return result;
  320. }
  321. private void DisConnect( )
  322. {
  323. this.IsConnected = false;
  324. PCANBasic.Reset( this.handle );
  325. PCANBasic.Uninitialize( this.handle );
  326. this.manager._OnDisconnected();
  327. }
  328. }
  329. }