| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406 |
- using GSG.NET.Concurrent;
- using GSG.NET.Extensions;
- using GSG.NET.Logging;
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- using VehicleControlSystem.ControlLayer.Serial.DataModel;
- namespace VehicleControlSystem.ControlLayer.Serial.BatteryTabos
- {
- public class Advantech
- {
- AdvCANIO device;
- string canPortName;
- static Logger logger = Logger.GetLogger();
- protected TsQueue<object> qqW = new TsQueue<object>( 128 );//write
- BMUManager manager = null;
- object lockObject = new object();
- uint idOffset = 0x460;
- string errormsg = string.Empty;
- //Todo:Dll 에서 상태 가져오기
- bool isConnected = false;
- public bool IsConnected
- {
- get => this.isConnected;
- set
- {
- if ( this.isConnected == value ) return;
- this.isConnected = value;
-
- if ( value )
- this.manager._OnConnected();
- else
- this.manager._OnDisconnected();
- }
- }
- #region Enum
- public enum eSendMode
- {
- MANUAL = 0,
- AUTO,
- AUTO_STOP
- }
- enum eMsgCaseFirst : int
- {
- Voltage_LOW = 2,
- Voltage_HIGH = 3,
- Current_LOW = 4,
- Current_HIGH = 5,
- BatteryBitStatus_LOW = 6,
- BatteryBitStatus_HIGH = 7
- }
- enum eMsgCaseSecond : int
- {
- ChargeFull_LOW = 2,
- ChargeFull_HIGH = 3,
- DisChargeEmpty_LOW,
- DisChargeEmpty_HIGH,
- SOC,
- SOH
- }
- enum eMsgCaseThird
- {
- Capacity_LOW = 2,
- Capacity_High,
- Energy_LOW,
- Energy_HIGH,
- Temperature_LOW,
- Temperature_HIGH
- }
- #endregion
- public Advantech( BMUManager mrg, string canPortName )
- {
- this.manager = mrg;
- this.canPortName = canPortName;
- this.device = new AdvCANIO();
- }
- internal void Enqueue( object o )
- {
- this.qqW.Enqueue( o );
- }
- bool GetConnectState()
- {
- var state = new AdvCan.CanStatusPar_t();
- var ret = this.device.acGetStatus( ref state );
- if ( ret == AdvCANIO.SUCCESS )
- {
- //정상 연결일때 값이 12 들어옴.
- if ( state.status == 12/*AdvCan.STATUS_OK*/ )
- return true;
- else
- return false;
- }
- else
- return false;
- }
- void TryToConnect( )
- {
- this.qqW.Clear();
- var d = this.device.acCanClose();
- Thread.Sleep( 50 );
- var ret = this.device.acCanOpen( this.canPortName, false , 500 , 500 );
- if(ret < AdvCANIO.SUCCESS)
- {
- throw new Exception( "AdvCAN Open Error" );
- }
- ret = this.device.acEnterResetMode();
- if ( ret < AdvCANIO.SUCCESS )
- {
- throw new Exception( "AdvCAN Reset Error" );
- }
- //ret = this.device.acSetAcceptanceFilterMode( AdvCan.PELICAN_SINGLE_FILTER );
- //if ( ret < 0 )
- //{
- // throw new Exception( "AdvCAN AcceptFilterMode Set Error" );
- // return;
- //}
- ret = this.device.acSetBaud(500);
- if ( ret < AdvCANIO.SUCCESS )
- {
- throw new Exception( "AdvCAN BaudRate Set Error" );
- }
- ret = this.device.acSetAcceptanceFilterMask( Convert.ToUInt32( "FFFFFFFF" , 16 ));
- if ( ret < AdvCANIO.SUCCESS )
- {
- throw new Exception( "AdvCAN AcceptFilterMask Set Error " );
- }
- ret = this.device.acSetAcceptanceFilterCode( Convert.ToUInt32( "FFFFFFFF" , 16 ) );
- if ( ret < AdvCANIO.SUCCESS )
- {
- throw new Exception( "AdvCAN AcceptFilterCode Set Error " );
- }
- ret = this.device.acSetTimeOut( 2000 , 2000 );
- if(ret < AdvCANIO.SUCCESS)
- {
- throw new Exception( "AdvCAN TimeOut Set Error " );
- }
- ret = this.device.acSetSelfReception(false);
- if(ret < AdvCANIO.SUCCESS)
- {
- throw new Exception( "AdvCAN SelfReception Set Error" );
- }
- ret = this.device.acEnterWorkMode();
- if(ret < AdvCANIO.SUCCESS)
- {
- throw new Exception( "AdvCAN EnterWorkMode Error" );
- }
- if ( this.Write( eSendMode.MANUAL ) <= AdvCANIO.SUCCESS )
- {
- throw new Exception( "AdvCan Write Error" );
- }
- else
- this.IsConnected = this.GetConnectState();
- }
- public void _ThreadPoolingReceiveData( )
- {
- while ( !this.manager.cancel.Canceled )
- {
- try
- {
- if ( !IsConnected )
- {
- Thread.Sleep( 1000 );
- this.TryToConnect();
- continue;
- }
- object o = this.qqW.Dequeue();
- if ( o is PollingObject ) //Scan 을 주기적 으로 진행.
- {
- this.Write(eSendMode.MANUAL);
- this.ReadMessage();
- }
- //else if ( o is ISetData ) //하나의 명령을 수행.
- //{
- // //ExecuteSetData( o as ISetData );
- //}
- else if ( o is DoInvokeChangedReceivedData ) //Scan 이후 결과를 처리. Manager 에서 처리
- {
- //this.manager._InvokeChgdReceivedData();
- this.manager._InvokeChgdWordsAndBits();
- }
- }
- catch ( ThreadAbortException exception )
- {
- logger.E( $"eSlnet {this.manager.BMUConfig.ID} - {exception.Message}" );
- //h.CloseSocket();
- }
- catch ( ObjectDisposedException exception )
- {
- this.CanError( );
- }
- catch ( IOException exception )
- {
- this.CanError( );
- }
- catch ( Exception exception )
- {
- this.CanError( );
- logger.E( $"eSlnet {exception.Message}" );
- }
- }
- logger.D( "[BMU] - Receive Thread End" );
- }
- /// <summary>
- /// true - auto, false - manual
- /// </summary>
- /// <param name="auto"></param>
- public int Write( eSendMode mode )
- {
- uint pulNumberofWritten = 1;
- AdvCan.canmsg_t[] msg = new AdvCan.canmsg_t[1];
-
- msg[ 0 ].flags = 0; // -> standard = 0,
- msg[ 0 ].cob = 0;
- msg[ 0 ].id = idOffset + Convert.ToByte( this.manager.BMUConfig.ID );
- msg[ 0 ].length = ( short )AdvCan.DATALENGTH;
- msg[ 0 ].data = new byte[ 8 ];
- switch ( mode )
- {
- case eSendMode.MANUAL:
- msg[ 0 ].data[ 0 ] = Convert.ToByte( 0x60 + Convert.ToByte( this.manager.BMUConfig.ID ) );
- break;
- case eSendMode.AUTO:
- msg[ 0 ].data[ 0 ] = 0xAA;
- msg[ 0 ].data[ 1 ] = 0xE0;
- break;
- case eSendMode.AUTO_STOP:
- msg[ 0 ].data[ 0 ] = 0xAA;
- msg[ 0 ].data[ 1 ] = 0x60;
- break;
- }
- var ret = this.device.acCanWrite( msg , (uint)msg.Length , ref pulNumberofWritten );
- if(ret == AdvCANIO.TIME_OUT)
- {
- CanError();
- logger.E( "Battery Write TimeOut Error" );
- return -1;
- }
- else if (ret == AdvCANIO.OPERATION_ERROR)
- {
- CanError();
- logger.E( "Battery Operation Error" );
- return -2;
- }
- return 1;
- }
- /// <summary>
- /// Adv Can Buffer Read
- /// </summary>
- /// <returns></returns>
- void ReadMessage( )
- {
- Thread.Sleep( 10 );
- uint readCount = 3;
- uint pulNumberofRead = 3;
- AdvCan.canmsg_t[] recv = new AdvCan.canmsg_t[ 3 ];
- var ret = this.device.acCanRead(recv, readCount, ref pulNumberofRead );
- if ( ret == AdvCANIO.TIME_OUT )
- {
- CanError( );
- }
- else if ( ret == AdvCANIO.OPERATION_ERROR )
- {
- CanError( );
- }
- else if ( ret == AdvCANIO.SUCCESS )
- {
- this.AdvCanReceive( recv );
- }
- else
- { }
- }
- private void AdvCanReceive( AdvCan.canmsg_t[] recv )
- {
- //null check battery receive
- var ll = recv.Select( x => x.data ).ToList();
-
- if ( ll.Count <= 0 && !ll.Any() )
- return;
- try
- {
- ll.ForEach( r =>
- {
- if ( r[ 1 ] == 1 )
- { CanRecvSave( r , 1 ); }
- else if ( r[ 1 ] == 2 )
- { CanRecvSave( r , 2 ); }
- else if ( r[ 1 ] == 3 )
- { CanRecvSave( r , 3 ); }
- else
- { }
- } );
- }
- catch (Exception e)
- { }
- }
- void CanRecvSave(byte[] data, int index)
- {
- string packet = BitConverter.ToString( data ).Replace( "-" , "" );
-
- List<string> sList = new List<string>();
- for ( int i = 0; i < packet.Length; i++ )
- {
- if ( i % 2 == 0 )
- sList.Add( packet.Substring( i , 2 ) );
- }
- switch (index)
- {
- case 1:
- this.manager.ReceivedDataDic[ eDataKind.Voltage ].Value = Int32.Parse( sList[ ( int )eMsgCaseFirst.Voltage_HIGH ] + sList[ ( int )eMsgCaseFirst.Voltage_LOW ] , System.Globalization.NumberStyles.HexNumber );
- this.manager.ReceivedDataDic[ eDataKind.Current ].Value = Int32.Parse( sList[ ( int )eMsgCaseFirst.Current_HIGH ] + sList[ ( int )eMsgCaseFirst.Current_LOW ] , System.Globalization.NumberStyles.HexNumber );
- this.manager.ReceivedDataDic[ eDataKind.BatteryState ].Value = Int32.Parse( sList[ ( int )eMsgCaseFirst.BatteryBitStatus_HIGH ] + sList[ ( int )eMsgCaseFirst.BatteryBitStatus_LOW ] , System.Globalization.NumberStyles.HexNumber );
- break;
- case 2:
- this.manager.ReceivedDataDic[ eDataKind.ChargeCompleteTime ].Value = Int32.Parse( sList[ ( int )eMsgCaseSecond.ChargeFull_HIGH ] + sList[ ( int )eMsgCaseSecond.ChargeFull_LOW ] , System.Globalization.NumberStyles.HexNumber );
- this.manager.ReceivedDataDic[ eDataKind.DisChargeCompleteTime ].Value = Int32.Parse( sList[ ( int )eMsgCaseSecond.DisChargeEmpty_HIGH ] + sList[ ( int )eMsgCaseSecond.DisChargeEmpty_LOW ] , System.Globalization.NumberStyles.HexNumber );
- this.manager.ReceivedDataDic[ eDataKind.SOC ].Value = Int32.Parse( sList[ ( int )eMsgCaseSecond.SOC ] , System.Globalization.NumberStyles.HexNumber );
- this.manager.ReceivedDataDic[ eDataKind.SOH ].Value = Int32.Parse( sList[ ( int )eMsgCaseSecond.SOH ] , System.Globalization.NumberStyles.HexNumber );
- break;
- case 3:
- this.manager.ReceivedDataDic[ eDataKind.ResidualCapacity ].Value = Int32.Parse( sList[ ( int )eMsgCaseThird.Capacity_High ] + sList[ ( int )eMsgCaseThird.Capacity_LOW ] , System.Globalization.NumberStyles.HexNumber );
- this.manager.ReceivedDataDic[ eDataKind.ResidualEnergy ].Value = Int32.Parse( sList[ ( int )eMsgCaseThird.Energy_HIGH ] + sList[ ( int )eMsgCaseThird.Energy_LOW ] , System.Globalization.NumberStyles.HexNumber );
- this.manager.ReceivedDataDic[ eDataKind.Temperature ].Value = Int32.Parse( sList[ ( int )eMsgCaseThird.Temperature_HIGH ] + sList[ ( int )eMsgCaseThird.Temperature_LOW ] , System.Globalization.NumberStyles.HexNumber );
- break;
- }
- }
- /// <summary>
- /// Battery State To -> [2^6] Bool List
- /// </summary>
- /// <param name="state"></param>
- void BatteryStateCheck( double state )
- {
- var cd = Convert.ToByte( state );
- var rs = new System.Collections.BitArray( new byte[] { cd } );
- var result = rs.Cast<object>().ToList();
- }
- void CanError()
- {
- //var result = PCANBasic.Uninitialize( this.handle );
- //this.IsConnected = false;
- var ret = this.device.acCanClose();
- //logger.E( $"[Battery Advantech] - {e.Message} -" );
- this.IsConnected = false;
- }
- }
- }
|