Example #1
0
        /// <summary>
        /// Генерирует событие по изменению статуса порта
        /// </summary>
        /// <param name="status">Новое состояние CAN-порта</param>
        private void OnPortChangesStatus(CanPortStatus status)
        {
            EventArgsPortChangesStatus    args    = new EventArgsPortChangesStatus(status);
            EventHandlerPortChangesStatus handler = this.PortChangedStatus;

            if (handler != null)
            {
                foreach (EventHandlerPortChangesStatus SingleCast in handler.GetInvocationList())
                {
                    ISynchronizeInvoke syncInvoke = SingleCast.Target as ISynchronizeInvoke;
                    if ((syncInvoke != null) && (syncInvoke.InvokeRequired))
                    {
                        syncInvoke.Invoke(SingleCast, new Object[] { this, args });
                    }
                    else
                    {
                        SingleCast(this, args);
                    }
                }
            }
            return;
        }
 //--------------------------------------------------------------------------------
 /// <summary>
 /// Конструктор
 /// </summary>
 /// <param name="newStatus">Новое состояние CAN-порта</param>
 public EventArgsPortChangesStatus(CanPortStatus newStatus)
 {
     this.Status = newStatus;
 }
Example #3
0
        /// <summary>
        /// Закрывает CAN порт 
        /// </summary>
        public override void Close()
        {
            String msg;

            // Закрываем поток на чтение
            Interlocked.Exchange(ref _FlagMustQuit, 0);
            
            lock (_SyncRoot)
            {
                this._RxEvent.Set();
            }

            for (int i = 0; i < 1; i++)
            {
                if (this._ThreadForInput.IsAlive == true)
                {
                    // Ждём завершение потока
                    Thread.Sleep(500);
                }
                else
                {
                    // Поток завершён
                    break;
                }
            }

            // Если поток не завершился в течнии 10 секунд, значит дело плохо.
            // Выводим об этом трассировочную информацию
            if (this._ThreadForInput.IsAlive == true)
            {
                this._ThreadForInput.Abort();
                msg = String.Format(
                    "{0}: class CanPort.Close(): Рабочий поток не завершился за 0,5 секунду и находится в состоянии {1}",
                    DateTime.Now.ToString(new System.Globalization.CultureInfo("ru-Ru", false)), this._ThreadForInput.ThreadState.ToString());
                Trace.TraceError(msg);
            }

            //SetMode(CANPORTSTATUS.IsPassive);
            _CanController.StopLine();
            //_CanChannel.Deactivate();

            _RxEvent.Close();
            _RxEvent = null;

            // Освобождаем ресурсы
            DisposeVciObject(_CanBusLayer);
            DisposeVciObject(_CanChannel);
            DisposeVciObject(_CanController);
            DisposeVciObject(_CanDevice);
            DisposeVciObject(_Reader);
            DisposeVciObject(_Writer);

            _CanBusLayer = null;
            _CanChannel = null;
            _CanController = null;
            _CanDevice = null;
            _Reader = null;
            _Writer = null;
            
            // Устанавливаем флаг признак "порт закрыт"
            this._PortStatus = CanPortStatus.IsClosed;

            // Формирум событие
            OnPortChangesStatus(CanPortStatus.IsClosed);

            Trace.TraceInformation("{0}: class CanPort.Close(): Порт закрыт",
                DateTime.Now.ToString(new System.Globalization.CultureInfo("ru-Ru")));
            return;
        }
 //--------------------------------------------------------------------------------
 #endregion
 //--------------------------------------------------------------------------------
 #region Constructors
 //--------------------------------------------------------------------------------
 /// <summary>
 /// Конструктор
 /// </summary>
 public EventArgsPortChangesStatus()
 {
     this.Status = CanPortStatus.Unknown;
 }
Example #5
0
        /// <summary>
        /// Открывает порт
        /// </summary>
        public override void Open()
        {
            String msg;
            IVciDeviceList deviceList;
            String serialNumber;
            Object pack;

            if (this._CanDevice == null)
            {
                // Получаем список доступных устройств
                deviceList = GetDeviceList();
                // Находим нужное нам устройство и открываем его
                foreach (IVciDevice item in deviceList)
                {
                    pack = (Object)item.UniqueHardwareId;
                    serialNumber = GetSerialNumber(ref pack);

                    if (serialNumber == this._SerialNumber)
                    {
                        // Устройство найдено
                        this._CanDevice = item;
                        break;
                    }
                }
            }

            if (this._CanDevice != null)
            {
                // Открываем порт
                Byte numberPort = 0;
                // Устройство найдено, открываем порт
                if (this.InitSocket(numberPort, ref this._CanDevice))
                {
                    // Порт открыт
                    // Устанавливаем флаг начала опроса порта
                    Interlocked.Exchange(ref _FlagMustQuit, Int32.MaxValue);
                    // start the receive thread
                    _ThreadForInput = new Thread(new ThreadStart(HandleQueueIncomingMessages));
                    _ThreadForInput.Start();
                    // Устанавливаем флаг - признак "порт открыт"
                    //_PortStatus = CANPORTSTATUS.IsPassive;
                    
                    // Здесь костыль: Почему-то, инфо-сообщения драйвера о переходе в новый статус при открытии порта не приходят.
                    // Поэтому проверяем в ручную. Если поле _PortStatus не соответсвует текущему состоянию,
                    // то останавливаем принудительно
                    if (this._CanChannel.ChannelStatus.IsActivated)
                    {
                        if (this._PortStatus != CanPortStatus.IsActive)
                        {
                            this._PortStatus = CanPortStatus.IsActive;
                            // Генерируем событие
                            this.OnPortChangesStatus(CanPortStatus.IsActive);
                        }
                    }
                }
                else
                {
                    // Порт не удалось открыть
                    msg = String.Format(
                        "{0}: class CanPort: Невозможно открыть CAN порт. Порт: {1} не удалось открыть.",
                        DateTime.Now.ToString(new System.Globalization.CultureInfo("ru-Ru", false)), this._SerialNumber);
                    Trace.TraceError(msg);
                    throw new InvalidOperationException(msg, null);
                }
            }
            else
            {
                // Устройство не найдено
                msg = String.Format("{0}: class CanPort: Невозможно открыть CAN порт. Порт: {1} не найден", 
                    DateTime.Now.ToString(new System.Globalization.CultureInfo("ru-Ru", false)), this._SerialNumber);
                Trace.TraceError(msg);
                throw new Exception(msg);
                //throw new InvalidOperationException(msg, null);
            }
            return;
        }
Example #6
0
        /// <summary>
        /// Генерирует событие по изменению статуса порта
        /// </summary>
        /// <param name="status">Новое состояние CAN-порта</param>
        protected virtual void OnPortChangesStatus(CanPortStatus status)
        {
            EventArgsPortChangesStatus args = new EventArgsPortChangesStatus(status);
            EventHandlerPortChangesStatus handler = this.PortChangedStatus;

            if (handler != null)
            {
                foreach (EventHandlerPortChangesStatus SingleCast in handler.GetInvocationList())
                {
                    ISynchronizeInvoke syncInvoke = SingleCast.Target as ISynchronizeInvoke;
                    if ((syncInvoke != null) && (syncInvoke.InvokeRequired))
                    {
                        syncInvoke.Invoke(SingleCast, new Object[] { this, args });
                    }
                    else
                    {
                        SingleCast(this, args);
                    }
                }
            }
            return;
        }
Example #7
0
        /// <summary>
        /// Функция для приёма данных (запускается в отдельном потоке)
        /// </summary>
        private void HandleQueueIncomingMessages()
        {
            CanMessage canMessage;
            Boolean boolResult;
            Frame message;

            //Trace.TraceInformation("{0}: class CanPort: Поток на чтение данных запущен", 
            //    DateTime.Now.ToString(new System.Globalization.CultureInfo("ru-Ru", false)));
            //#if DEBUG
            //WindowsDebugging.WriteLine("Поток на чтение порта запущен", Category.Information);
            //#endif

            while(this._FlagMustQuit > 0)
            {
                if (_Reader == null)
                {
                    Trace.WriteLine("");
                    Trace.TraceError("{0} class CanPort.ReceiveMessages: Невозможно прочитать порт объект _Reader не существует, прекращаю поток чтения", 
                        DateTime.Now.ToString(new System.Globalization.CultureInfo("ru-Ru", false)));
                    Interlocked.Exchange(ref this._FlagMustQuit, 0);
                    return;
                }

                try
                {
                    // Ждём пока драйвер can-порта установит сигнальное состоние.
                    // Значит полученны данные в порт
                    boolResult = this._RxEvent.WaitOne(System.Threading.Timeout.Infinite, false);
                    //boolResult = this._RxEvent.WaitOne(100, false);

                    if (boolResult)
                    {
                        // По установке сигнального состояния, проверяем флаг. Возможно
                        // сигнальное состояние было установлено для прекращения работы потока
                        if (this._FlagMustQuit == 0)
                        {
                            continue;
                        }
                    }
                    else
                    {
                        // По таймауту.
                        continue;
                    }

                    // read a CAN message from the receive FIFO
                    //boolResult = true;

                    //while (boolResult)
                    while(this._Reader.ReadMessage(out canMessage))
                    {
                        //lock (SynckRoot)
                        //{
                            //if (this._Reader != null)
                            //{
                            //    boolResult = this._Reader.ReadMessage(out canMessage);
                            //}
                            //else
                            //{
                                // Завершаем поток
                            //    this._FlagMustQuit = 0;
                            //    this._PortStatus = CANPORTSTATUS.IsClosed;
                            //    break;
                            //}
                        //}

                        switch (canMessage.FrameType)
                        {
                            // show data frames
                            case CanMsgFrameType.Data:
                                {
                                    //Trace.WriteLine(String.Format("\nTime: {0,10}  ID: {1,3:X}  DLC: {2,1}  Data:",
                                    //    canMessage.TimeStamp, canMessage.Identifier, canMessage.DataLength));
                                    //Trace.TraceInformation("{0}: class CanPort.ReceiveMessages: TimeStamp: {1,10}  ID: {2,3:X}  DLC: {3,1}  Data:",
                                    //    DateTime.Now.ToString(new System.Globalization.CultureInfo("ru-Ru", false)), canMessage.TimeStamp, canMessage.Identifier, canMessage.DataLength);
                                    message = new Frame();
                                    message.TimeStamp = canMessage.TimeStamp;
                                    message.Identifier = canMessage.Identifier;
                                    
                                    if (canMessage.ExtendedFrameFormat)
                                    {
                                        message.FrameFormat = FrameFormat.ExtendedFrame;
                                    }
                                    else
                                    {
                                        message.FrameFormat = FrameFormat.StandardFrame;
                                    }

                                    if (canMessage.RemoteTransmissionRequest)
                                    {
                                        message.FrameType = FrameType.REMOTEFRAME;
                                    }
                                    else
                                    {
                                        message.FrameType = FrameType.DATAFRAME;
                                    }

                                    message.Data = new Byte[canMessage.DataLength];
                                    
                                    for (int index = 0; index < canMessage.DataLength; index++)
                                    {
                                        message.Data[index] = canMessage[index];
                                    }

                                    //#if DEBUG
                                    //WindowsDebugging.WriteLine("IN: " + message.ToString(), Category.Information);
                                    //#endif
                                    // Добавляем сообщение во входной буфер и 
                                    lock (_SyncRoot)
                                    {
                                        this._InputBufferMessages.Enqueue(message);
                                    }
                                    
                                    // Генерируем событие
                                    this.OnDataReceive();
                                    break;
                                }
                                // show informational frames
                            case CanMsgFrameType.Info:
                                {
                                    //message = new Frame();
                                    //message.Data = null;
                                    //message.FrameType = FRAMETYPE.INFOFRAME;

                                    switch ((CanMsgInfoValue)canMessage[0])
                                    {
                                        case CanMsgInfoValue.Start:
                                            //Trace.TraceInformation("{0}: calss CanPort.ReceiveMessages: Принято сообщение от драйвера - CanPort was started", 
                                            //    DateTime.Now.ToString(new System.Globalization.CultureInfo("ru-Ru", false)));
                                            //#if DEBUG
                                            //WindowsDebugging.WriteLine("Принято сообщение от драйвера - CanPort was started", Category.Information);
                                            //#endif

                                            this._PortStatus = CanPortStatus.IsActive;
                                            // Генерируем событие
                                            this.OnPortChangesStatus(CanPortStatus.IsActive);
                                            break;
                                        case CanMsgInfoValue.Stop:
                                            //Trace.TraceInformation("{0}: calss CanPort.ReceiveMessages: Принято сообщение от драйвера - CanPort was stopped",
                                            //    DateTime.Now.ToString(new System.Globalization.CultureInfo("ru-Ru", false)));
                                            //#if DEBUG
                                            //WindowsDebugging.WriteLine("Принято сообщение от драйвера - CanPort was stopped", Category.Information);
                                            //#endif
                                            this._PortStatus = CanPortStatus.IsPassive;
                                            this.OnPortChangesStatus(CanPortStatus.IsPassive);
                                            // Генерируем событие
                                            break;
                                        case CanMsgInfoValue.Reset:
                                            //Trace.TraceInformation("{0}: calss CanPort.ReceiveMessages: Принято сообщение от драйвера - CanPort was reseted",
                                            //    DateTime.Now.ToString(new System.Globalization.CultureInfo("ru-Ru", false)));
                                            //#if DEBUG
                                            //WindowsDebugging.WriteLine("Принято сообщение от драйвера - CanPort was reseted", Category.Information);
                                            //#endif

                                            this._PortStatus = CanPortStatus.IsPassiveAfterReset;
                                            // Генерируем событие
                                            this.OnPortChangesStatus(CanPortStatus.IsPassiveAfterReset);
                                            break;
                                        default:
                                            {
                                                Trace.TraceWarning("{0}: calss CanPort.ReceiveMessages: Получено нейзвестное сообщение от драйвера типа CanMsgFrameType.Info...",
                                                    DateTime.Now.ToString(new System.Globalization.CultureInfo("ru-Ru", false)));
                                                throw new Exception();
                                                //this.OnPortChangesStatus(CANPORTSTATUS.Unknown);
                                                //break;
                                            }
                                    }
                                    break;
                                }
                                // show error frames
                            case CanMsgFrameType.Error:
                                {
                                    // Генерируем событие об ошибке

                                    switch ((CanMsgError)canMessage[0])
                                    {
                                        // Bit stuffing - когда узел передает последовательно в шину 5 бит с одинаковым значением, 
                                        // то он добавляет шестой бит с противоположным значением. Принимающие узлы этот 
                                        // дополнительный бит удаляют. Если узел обнаруживает на шине больше 5 последовательных 
                                        // бит с одинаковым значением, то он генерирует ошибку Stuff Error.
                                        case CanMsgError.Stuff:
                                            //Trace.TraceError("{0}: class CanPort.ReceiveMessages: stuff error...",
                                            //    DateTime.Now.ToString(new System.Globalization.CultureInfo("ru-Ru", false)));
                                            //#if DEBUG 
                                            //WindowsDebugging.WriteLine("stuff error", Category.Error);
                                            //#endif
                                            OnErrorRecive(ERROR.BitStuff);
                                            break;
                                        // Frame Check - некоторые части CAN-сообщения имеют одинаковое значение во всех 
                                        // типах сообщений. Т.е. протокол CAN точно определяет какие уровни напряжения и 
                                        // когда должны появляться на шине. Если формат сообщений нарушается, то узлы 
                                        // генерируют ошибку Form Error.
                                        case CanMsgError.Form:
                                            //Trace.TraceError("{0}: class CanPort.ReceiveMessages: format of frame error...",
                                            //    DateTime.Now.ToString(new System.Globalization.CultureInfo("ru-Ru", false)));
                                            //#if DEBUG
                                            //WindowsDebugging.WriteLine("format of frame error", Category.Error);
                                            //#endif

                                            OnErrorRecive(ERROR.FormatFrame);
                                            break;
                                        // ACKnowledgement Check - каждый узел получив правильное сообщение по сети посылает 
                                        // в сеть доминантный (0) бит. Если же этого не происходит, то передающий узел 
                                        // регистрирует ошибку Acknowledgement Error.
                                        case CanMsgError.Acknowledge:
                                            //Trace.TraceError("{0}: class CanPort.ReceiveMessages: acknowledgment error...",
                                            //    DateTime.Now.ToString(new System.Globalization.CultureInfo("ru-Ru", false)));
                                            //#if DEBUG
                                            //WindowsDebugging.WriteLine("acknowledgment error", Category.Error);
                                            //#endif
                                            
                                            OnErrorRecive(ERROR.Acknowledge);
                                            break;
                                        // Check Bit monitoring - каждый узел во время передачи битов в сеть сравнивает значение 
                                        // передаваемого им бита со значением бита которое появляется на шине. Если эти значения 
                                        // не совпадают, то узел генерирует ошибку Bit Error. Естественно, что во время арбитража 
                                        // на шине (передача поля арбитража в шину) этот механизм проверки ошибок отключается.
                                        case CanMsgError.Bit:
                                            //Trace.TraceError("{0}: class CanPort.ReceiveMessages: bit error...",
                                            //    DateTime.Now.ToString(new System.Globalization.CultureInfo("ru-Ru", false)));
                                            //#if DEBUG
                                            //WindowsDebugging.WriteLine("bit error", Category.Error);
                                            //#endif

                                            OnErrorRecive(ERROR.Bit);
                                            break;
                                        // CRC Check - каждое сообщение CAN содержит CRC сумму, и каждый принимающий узел 
                                        // подсчитывает значение CRC для каждого полученного сообщения. Если подсчитанное 
                                        // значение CRC суммы, не совпадает со значением CRC в теле сообщения, принимающий 
                                        // узел генерирует ошибку CRC Error.
                                        case CanMsgError.Crc:
                                            Trace.TraceError("{0}: class CanPort.ReceiveMessages: CRC error...",
                                                DateTime.Now.ToString(new System.Globalization.CultureInfo("ru-Ru", false)));
                                            OnErrorRecive(ERROR.CRC);
                                            break;
                                        case CanMsgError.Other:
                                            //Trace.TraceError("{0}: class CanPort.ReceiveMessages: other error...",
                                            //    DateTime.Now.ToString(new System.Globalization.CultureInfo("ru-Ru", false)));
                                            //#if DEBUG
                                            //WindowsDebugging.WriteLine("other error", Category.Error);
                                            //#endif

                                            OnErrorRecive(ERROR.Other);
                                            break;
                                    }
                                    break;
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        String msg;
                        Interlocked.Exchange(ref _FlagMustQuit, 0);

                        msg = String.Format("{0}: class CanPort.ReceiveMessages: Чтение сообщения из буфера CanPort вызвало исключение {1}, поток завершён, стек: {2}",
                            DateTime.Now.ToString(new System.Globalization.CultureInfo("ru-Ru", false)), ex.Message, ex.StackTrace);
                        Trace.TraceError(msg);

                        throw;
                    }
                }

            //Trace.TraceInformation("{0}: class CanPort.ReceiveMessages(): Поток на чтение данных завершён", 
            //    DateTime.Now.ToString(new System.Globalization.CultureInfo("ru-Ru")));
            //#if DEBUG
            //WindowsDebugging.WriteLine("Поток на чтение порта зaвершен", Category.Information);
            //#endif

            return;
        }
 //--------------------------------------------------------------------------------
 /// <summary>
 /// Конструктор
 /// </summary>
 /// <param name="newStatus">Новое состояние CAN-порта</param>
 public EventArgsPortChangesStatus(CanPortStatus newStatus)
 {
     this.Status = newStatus;
 }
 //--------------------------------------------------------------------------------
 #endregion
 //--------------------------------------------------------------------------------
 #region Constructors
 //--------------------------------------------------------------------------------
 /// <summary>
 /// Конструктор
 /// </summary>
 public EventArgsPortChangesStatus()
 {
     this.Status = CanPortStatus.Unknown;
 }