Example #1
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="messages"></param>
        public override void HandleIncomingMessages(Frame[] messages)
        {
            String msg;
            IncomingMessageStuctureServicePdoTransmit msghelper;
            DeviceBase device;
            //ObjectInfo objInfo;

            if (_Status != Status.Running)
            {
                return;
            }
            
            foreach(Frame message in messages)
            {
                msghelper = IncomingMessageStuctureServicePdoTransmit.Parse(message);

                if (!msghelper.IsForService)
                {
                    return;
                }

                if (msghelper.HasIncorrectStructure)
                {
                    // Формат сообщения неверен.
                    msg = String.Format(
                        "Network {0}: Принято сообщение с неверным форматом данных {1}",
                        _NetworkController.Description, message.ToString());
                    //_Logger.Error(msg);
                    return;
                }

                if (!_NetworkController.Devices.Contains(msghelper.NodeId))
                {
                    // Устройство не найдено
                    msg = String.Format(
                        "Network {0}: Пришло сообщение от устройства с NodeId {1}, " +
                        "данное устройство не зарегистрировано в сети. Message - {2}",
                        this.NetworkController.Description, msghelper.NodeId, message.ToString());
                    //Logger.Error(msg);
                    continue;
                }

                device = _NetworkController.Devices[msghelper.NodeId];

                switch (msghelper.Pdo)
                {
                    case PdoType.PDO1:
                        {
                            // Data A (polarisation_pot)
                            device.ObjectDictionary[(UInt16)0x2008].Value =
                                ToUInt16(message.Data[0], message.Data[1]);
                            // Data B (protection_pot)
                            device.ObjectDictionary[(UInt16)0x2009].Value =
                                ToUInt16(message.Data[2], message.Data[3]);
                            // Data C (induced_ac)
                            device.ObjectDictionary[(UInt16)0x200A].Value =
                                ToUInt16(message.Data[4], message.Data[5]);
                            // Data D (protection_cur)
                            device.ObjectDictionary[(UInt16)0x200B].Value =
                                ToUInt16(message.Data[6], message.Data[7]);
                            break;
                        }
                    case PdoType.PDO2:
                        {
                            // Data A (polarisation_cur)
                            device.ObjectDictionary[(UInt16)0x200C].Value =
                                ToUInt16(message.Data[0], message.Data[1]);
                            // Data B (aux_cur1)
                            device.ObjectDictionary[(UInt16)0x200D].Value =
                                ToUInt16(message.Data[2], message.Data[3]);
                            // Data C (induced_ac)
                            device.ObjectDictionary[(UInt16)0x200E].Value =
                                ToUInt16(message.Data[4], message.Data[5]);
                            // Data D (Биты состояния датчиков)
                            // 0bxxxxxD3D2D1: byte
                            // D1 - бит, состояние датчика вскрытия tamper
                            // D2 - бит, состояние supply_voltage_low
                            // D3 - бит, состояние battary_volatage_low
                            device.ObjectDictionary[(UInt16)0x2015].Value =
                                (UInt16)(message.Data[6] & 0x01);
                            device.ObjectDictionary[(UInt16)0x2016].Value =
                                (UInt16)(message.Data[6] & 0x02);
                            device.ObjectDictionary[(UInt16)0x2017].Value =
                                (UInt16)(message.Data[6] & 0x04);
                            break;
                        }
                    case PdoType.PDO3:
                        {
                            // Data A (corrosion_depth)
                            device.ObjectDictionary[(UInt16)0x200F].Value =
                                ToUInt16(message.Data[0], message.Data[1]);
                            // Data B (corrosion_speed)
                            device.ObjectDictionary[(UInt16)0x2010].Value =
                                ToUInt16(message.Data[2], message.Data[3]);
                            // Data C (usipk_state)
                            device.ObjectDictionary[(UInt16)0x2011].Value =
                                message.Data[4];
                            // Data D (Биты состояния датчиков коррозии)
                            // 0bxxxxxD3D2D1: byte
                            // D1 - бит, состояние датчика коррозии 1
                            // D2 - бит, состояние датчика коррозии 2
                            // D3 - бит, состояние датчика коррозии 3
                            device.ObjectDictionary[(UInt16)0x2018].Value =
                                (UInt16)(message.Data[5] & 0x01);
                            device.ObjectDictionary[(UInt16)0x2019].Value =
                                (UInt16)(message.Data[5] & 0x02);
                            device.ObjectDictionary[(UInt16)0x201A].Value =
                                (UInt16)(message.Data[5] & 0x04);
                            break;
                        }
                    case PdoType.PDO4:
                        {
                            // Data A (polarisation_cur_dc)
                            device.ObjectDictionary[(UInt16)0x201B].Value =
                                ToUInt16(message.Data[0], message.Data[1]);
                            // Data B (aux_cur1)
                            device.ObjectDictionary[(UInt16)0x201C].Value =
                                ToUInt16(message.Data[2], message.Data[2]);
                            break;
                        }
                }
            }
        }
Example #2
0
 public abstract void Write(Frame message);
Example #3
0
 public object Clone()
 {
     Frame frm = new Frame();
     frm._FrameFormat = this._FrameFormat;
     frm._FrameType = this._FrameType;
     frm._Identifier = this._Identifier;
     frm._Data = new byte[this._Data.Length];
     for (int i = 0; i < this._Data.Length; i++)
     {
         frm._Data[i] = this._Data[i];
     }
     return frm;
 }
Example #4
0
        /// <summary>
        /// Обработчик события срабатываения таймера.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void EventHandler_TimerSyncMessage_Elapsed(object sender,
            ElapsedEventArgs e)
        {
            //String msg;
            Frame message;
            
            // Формируем сообщение SYNC и посылаем его в сеть
            message = new Frame();
            message.Identifier = 0x80;
            message.FrameFormat = FrameFormat.StandardFrame;
            message.FrameType = FrameType.DATAFRAME;
            message.Data = new Byte[0];

            lock (_SyncRoot)
            {
                _NetworkController.SendMessageToCanPort(message);
            }

            // Записываем в лог...
        }
Example #5
0
        /// <summary>
        /// Заканчивает текущую транзакцию (удачное завершение)
        /// </summary>
        /// <param name="answer">Ответ slave-устройства</param>
        public void Stop(Frame? answer)
        {
            string msg;

            if (!this.IsRunning)
            {
                throw new InvalidOperationException(
                    String.Format("Transaction ID: {0}; Попытка завершить не начатую транзакцию",
                    _Identifier));
            }
            else
            {
                switch (_TransactionType)
                {
                    case TransactionType.UnicastMode:
                        {
                            if (answer.HasValue)
                            {
                                _Answer = answer;
                            }
                            else
                            {
                                msg = String.Format(
                                    "Transaction ID: {0}; Попытка установить в null ответное сообщение для завершения " +
                                    "транзакции адресованного запроса", _Identifier);
                                Abort(answer, msg);
                                throw new NullReferenceException(msg);
                            }
                            break;
                        }
                    case TransactionType.BroadcastMode:
                        {
                            if (answer != null)
                            {
                                msg = String.Format(
                                    "Transaction ID: {0}; Попытка установить ответное сообщение для завершения транзакции " +
                                    "широковещательного запроса", _Identifier);
                                Abort(answer, msg);
                                throw new InvalidOperationException(msg);
                            }
                            break;
                        }
                    default:
                        {
                            msg = String.Format("Transaction ID: {0}; Попытка остановить сетевую транзакцию " +
                                "тип которой не поддерживается - {1}", _Identifier, _TransactionType);
                            Abort(answer ,msg);
                            throw new NotImplementedException(msg);
                        }
                }

                this._TimeOfEnd = DateTime.Now;
                this._Status = TransactionStatus.Completed;

                // Генерируем событие окончания транзакции.
                OnTransactionWasEnded();

                //Debug.WriteLine(String.Format(
                //    "Transaction ID: {0} - Конец транзакции: {1}; Время транзакции: {2}",
                //    this.Identifier, this._TimeOfEnd, this.TimeOfTransaction));
            }
            return;
        }
Example #6
0
        /// <summary>
        /// Выполняет запрос к удалённому устройству 
        /// (переберая устройства и объекты словаря)
        /// </summary>
        public override void  HandleOutcomingMessages()
        {
            DeviceContext device;
            //ObjectInfo objInfo;

            // Сервис не работает
            if (_Status != Status.Running)
            {
                return;
            }

            if (_Context.Count == 0)
            {
                return;
            }
            // Устанавливаем следующее по списку устройство для обработки
            _Context.Next();
            // Получаем устройство для обработки
            device = _Context.CurrentDevice;

            // Если устройство активно, выполняем запрос
            lock (_SyncRoot)
            {
                if ((device.Device.Status == DeviceStatus.Operational) ||
                    (device.Device.Status == DeviceStatus.Preoperational) ||
                    (device.Device.Status == DeviceStatus.Stopped))
                {
                    if (device.CurrentTransaction == null)
                    {
                        device.CurrentTransaction = new Transaction();
                    }
                    // Проверяем, что последнй запрос (транзакция) к устройству выполнена
                    // Если это так, начинаем новую, в противном случае ничего неделаем (ждём окончания транзакции)
                    if (device.CurrentTransaction.IsRunning)
                    {
                        // Транзакция активна проверяем длительность транзакции
                        if (device.CurrentTransaction.TimeOfStart.AddSeconds(
                            device.Device.PollingInterval) <= DateTime.Now)
                        {
                            // Таймаут на запрос
                            device.CurrentTransaction.Abort(null, "Request timeout");
                            // Пишем в лог...
                        }
                        return;
                    }
                    else
                    {
                        // Если запрос был успешным или неудачным, выжадаем требуемое время
                        // для нового запроса
                        if ((device.CurrentTransaction.Status == TransactionStatus.Aborted) ||
                            (device.CurrentTransaction.Status == TransactionStatus.Completed))
                        {
                            if (device.CurrentTransaction.TimeOfStart.AddSeconds(
                                device.Device.PollingInterval) > DateTime.Now)
                            {
                                return;
                            }
                        }

                        if (device.CurrentTransaction.Status == TransactionStatus.Aborted)
                        {
                            if (device.ErrorCount < TotalAttempts)
                            {
                                // Повторяем запрос
                                device.CurrentTransaction.Repeat();
                                // Отправляем сообщение к устройству
                                _NetworkController.SendMessageToCanPort(
                                    device.CurrentTransaction.Request.Value);
                                return;
                            }
                            else
                            {
                                device.CurrentTransaction = null;
                            }
                        }

                        //Получаем следующий объект словаря для обработки 
                        device.Next();

                        if (!device.CurrentObject.SdoCanRead)
                        {
                            // Данный объект не обрабатывается сервисом SDO
                            return;
                        }
                        Transaction trans = new Transaction();

                        Frame message = new Frame();
                        message.Identifier = System.Convert.ToUInt32(0x600 +
                            device.Device.NodeId);
                        message.FrameFormat = FrameFormat.StandardFrame;
                        message.FrameType = FrameType.DATAFRAME;
                        message.Data = new Byte[8];
                        message.Data[0] = 0x40;
                        message.Data[1] = (byte)device.CurrentObject.Index;
                        message.Data[2] = (byte)(device.CurrentObject.Index >> 8);
                        device.CurrentTransaction = trans;
                        trans.Start(TransactionType.UnicastMode, message);
                    }
                    // Отправляем сообщение к устройству
                    _NetworkController.SendMessageToCanPort(
                        device.CurrentTransaction.Request.Value);
                }
            }
        }
Example #7
0
 /// <summary>
 /// Разбирает ответное сообщение
 /// </summary>
 /// <param name="message">Ответное сообщение</param>
 /// <returns>Структура данных ответа</returns>
 internal static IncomingMessageStuctureBootUp Parse(Frame message)
 {
     const Byte MASK_COBEID = 0x7F; // Выделяет 7 бит содержащих CodeId из поля Id 
     IncomingMessageStuctureBootUp frame = 
         new IncomingMessageStuctureBootUp();
     frame.Answer = message;
     frame.CobeId = (Byte)(((Byte)message.Identifier) & MASK_COBEID);
     frame.DL = message.Data.Length;
     return frame;
 }
Example #8
0
 /// <summary>
 /// Записывает сообщение в порт
 /// </summary>
 /// <param name="identifier"></param>
 /// <param name="frameType"></param>
 /// <param name="frameFormat"></param>
 /// <param name="data"></param>
 public override void WriteMessage(uint identifier, FrameType frameType, 
     FrameFormat frameFormat, byte[] data)
 {
     Frame frame = new Frame();
     frame.Identifier = identifier;
     frame.FrameType = frameType;
     frame.FrameFormat = FrameFormat;
     if (data != null)
     { frame.Data = data; }
     else
     { frame.Data = new byte[0]; }
     
     this.Write(frame);
     return;
 }        
Example #9
0
        /// <summary>
        /// Записывает сообщение в порт
        /// </summary>
        /// <param name="message">Сообщение для оправки</param>
        public override void Write(Frame message)
        {
            String msg;
            F_CAN_RESULT result;
            F_CAN_TX buffer;
            F_CAN_STATE status;
            uint count = 0;

            // Если прот закрыт, отсылка сообщения не возможна
            if (!this.IsOpen)
            {
                msg = "Невозможно отправить сообщение, CAN-порт закрыт";
                throw new InvalidOperationException(msg);
            }

            status = this.GetPortStatus();
            if (this.PortStatus != CanPortStatus.IsActive)
            {
                msg = "Невозможно отправить сообщение, CAN-порт отключён от физической сети";
                throw new InvalidOperationException(msg);
            }

            // Разбираем сообщение и подготавливаем его для отправки
            buffer.msg = ConvertNim351.ConvertToF_CAN_MSG(message);

            result = Api.fw_can_send(this._DeviceHandle, ref buffer, 1, ref count);
            //result = Api.fw_can_post_message(this._DeviceHandle, ref buffer);

            if (!Api.f_can_success(result))
            {
                // При отправке сообщения возникла ошибка
                msg = String.Format("Не удалось отправить сообщение. Error: ", result);
                throw new InvalidOperationException(msg);
            }
            return;
        }
Example #10
0
 /// <summary>
 /// Принять сообщения от контроллера сети
 /// </summary>
 /// <param name="messages"></param>
 public virtual void HandleIncomingMessages(Frame[] messages)
 {
     return;
 }
Example #11
0
        /// <summary>
        /// 
        /// </summary>
        public override void HandleOutcomingMessages()
        {
            DeviceContext device;
            DateTime time;
            Frame message;

            // Сервис не работает
            if (_Status != Status.Running)
            {
                return;
            }

            if (_Context.Count == 0)
            {
                return;
            }
            // Получаем следующее устройство в спике
            _Context.Next();
            
            device = _Context.CurrentDevice;
            
            if (device.Device.Status == DeviceStatus.CommunicationError)
            {
                // Если устройство не доступно, пропускаем его
                return;
            }

            // Проверяем статус запроса 
            if (device.CurrentTransaction == null)
            {
                device.CurrentTransaction = new Transaction();
            }

            switch (device.CurrentTransaction.Status)
            {
                case TransactionStatus.Running:
                    {
                        time = device.CurrentTransaction.TimeOfStart.AddSeconds(
                            device.Device.PollingInterval);
                        if (time < DateTime.Now)
                        {
                            // Устройство не ответилo за заданное время. 
                            // Устанавливаем статус неудачной попытки
                            device.CurrentTransaction.Abort(null, "Request timeout"); 
                        }
                        break;
                    }
                case TransactionStatus.Aborted:
                    {
                        // Проверяем количество попыток доступа к устройству.
                        // Если оно достигло предела. Устанавливаем статус ошибки
                        if (device.ErrorCount < TotalAttempts)
                        {
                            // Повторяем запрос
                            device.CurrentTransaction.Repeat();
                            _NetworkController.SendMessageToCanPort(
                                device.CurrentTransaction.Request.Value);
                        }
                        else
                        {
                            // Устанавливаем новый статус устройству
                            device.CurrentTransaction = null;
                            device.Device.Status = DeviceStatus.CommunicationError;
                        }
                        break;
                    }
                case TransactionStatus.NotInitialized:
                    {
                        message = new Frame();
                        message.Identifier =
                            System.Convert.ToUInt32(0x700 + device.Device.NodeId);
                        message.FrameFormat = FrameFormat.StandardFrame;
                        message.FrameType = FrameType.REMOTEFRAME;
                        message.Data = new Byte[0];

                        device.CurrentTransaction = new Transaction();
                        device.CurrentTransaction.Start(TransactionType.UnicastMode, message);
                        // Отправляем запрос
                        _NetworkController.SendMessageToCanPort(
                            device.CurrentTransaction.Request.Value);
                        break;
                    }
                case TransactionStatus.Completed:
                    {
                        // Получаем время последнего опроса устройства. 
                        // Прибавляем к нему время прериода опроса устройства
                        // и сравниваем с текущим временем. Если полученное время меньше текущего, 
                        // то выполняем запрос к устройству.
                        time = device.CurrentTransaction.TimeOfStart.AddSeconds(
                            device.Device.PollingInterval);
                        if (time < DateTime.Now)
                        {
                            message = new Frame();
                            message.Identifier =
                                System.Convert.ToUInt32(0x700 + device.Device.NodeId);
                            message.FrameFormat = FrameFormat.StandardFrame;
                            message.FrameType = FrameType.REMOTEFRAME;
                            message.Data = new Byte[0];

                            device.CurrentTransaction = new Transaction();
                            device.CurrentTransaction.Start(TransactionType.UnicastMode, message);
                            // Отправляем запрос
                            _NetworkController.SendMessageToCanPort(
                                device.CurrentTransaction.Request.Value);
                        }
                        break;
                    }
                default: { throw new Exception(); }
            }
        }
Example #12
0
        /// <summary>
        /// 
        /// </summary>
        public override void HandleOutcomingMessages()
        {
            DeviceContext device;
            String msg;
            DateTime time;
            Frame request;
            Transaction transaction;

            // 1. Проверяем статус устройства: 
            //  1.1 Если устройство находится в состоянии Operational, ничего не делаем
            //  1.2 Если устройство находится в состоянии CommunicationError, ничего не делаем
            //  1.3 Если устройство находится в состоянии ConfigurationError, ничего не делаем
            //  1.4 Если устройства находится в состоянии Stopped, ничего не делаем
            //  1.5 Если устройство находится в состоянии Pre-operational, отправляем команду 
            //      перевода устройства в состояние Operational
            //     1.5.1 Проверяем 

            // Сервис не работает
            if (_Status != Status.Running)
            {
                return;
            }

            // Получаем устройство
            _Context.Next();
            device = _Context.CurrentDevice;

            // Проверяем статус
            if (device.Device.Status == DeviceStatus.Preoperational)
            {
                if (device.CurrentTransaction != null)
                {
                    switch (device.CurrentTransaction.Status)
                    {
                        case TransactionStatus.Running:
                            {
                                // Запрос был уже отправлен. Проверяем таймаут
                                time = device.CurrentTransaction.TimeOfStart;
                                time = time.AddSeconds(device.Device.PollingInterval);

                                if (time < DateTime.Now)
                                {
                                    msg = String.Format("Service NMT: Timeout - устройство" +
                                        "не перешло в режим Operational за заданное время");
                                    // Устройство не перешло из состояние Pre-Operational 
                                    // за заданное время. Устанавливаем статус неудачной попытки
                                    device.CurrentTransaction.Abort(null, msg);
                                }
                                break;
                            }
                        case TransactionStatus.NotInitialized:
                        case TransactionStatus.Completed:
                            {
                                // Устройство перешло в состояние Operational - транзакция выполнена
                                // Однако, по какой-то причине устройство перешло в состояние Pre-Operational
                                // Переводим устройство в состояние Operational
                                request = new Frame();
                                request.Identifier = 0;
                                request.FrameFormat = FrameFormat.StandardFrame;
                                request.FrameType = FrameType.DATAFRAME;
                                request.Data = new Byte[] { 
                                    (Byte)StatusCode.Operational, // Поле комадны
                                    device.Device.NodeId // Поле Node ID
                                    };
                                transaction = new Transaction();
                                transaction.Start(TransactionType.BroadcastMode, request);
                                lock (_SyncRoot)
                                {
                                    _NetworkController.SendMessageToCanPort(
                                        transaction.Request.Value);
                                }
                                break;
                            }
                        case TransactionStatus.Aborted:
                            {
                                // Проверяем количество неудачных попыток и если оно
                                // достигло предела не отсылаем устройству больше запросов
                                if (device.ErrorCount < TotalAttempts)
                                {
                                    // Повторяем запрос
                                    device.CurrentTransaction.Repeat();
                                    lock (_SyncRoot)
                                    {
                                        _NetworkController.SendMessageToCanPort(
                                            device.CurrentTransaction.Request.Value);
                                    }
                                }
                                break;
                            }
                        default:
                            {
                                msg = String.Format(
                                    "Network {0}: ServiceNmt - Обнаружен статус запроса {1} не поддерживаемый " +
                                    "в данной версии ПО", _NetworkController.Description,
                                    device.CurrentTransaction.Status);
                                throw new Exception(msg);
                            }
                    }
                }
                else
                {
                    // Отправляем команду для перевода устройства в состояние Operational
                    request = new Frame();
                    request.Identifier = 0;
                    request.FrameFormat = FrameFormat.StandardFrame;
                    request.FrameType = FrameType.DATAFRAME;
                    request.Data = new Byte[] { 
                        (Byte)StatusCode.Operational, // Поле комадны
                        device.Device.NodeId // Поле Node ID
                    };
                    device.CurrentTransaction = new Transaction();
                    device.CurrentTransaction.Start(TransactionType.UnicastMode, request);
                    lock (_SyncRoot)
                    {
                        _NetworkController.SendMessageToCanPort(
                            device.CurrentTransaction.Request.Value);
                    }
                }
            }
            else
            {
                // Oбратная связь возникает через сервис NodeGuard, 
                // который отслеживает состояние устройства. И только он может установить, что
                // устройство перешло режим Operational и устанавливает статус устройству.
                // По этому, проверяем состояние транзакции и если транзакция активна
                // и устройство изменило статус, то считаем что команда дошла до устройства
                // и завершаем транзакцию.
                if ((device.CurrentTransaction != null) && 
                    (device.CurrentTransaction.IsRunning))
                {
                    // Т.к сервис не получает ответа, останавливаем транзакцию
                    // при помощи пустого фрайма (псевноответа)
                    device.CurrentTransaction.Stop(new Frame());
                }
            }
        }
Example #13
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="messages"></param>
 public override void HandleIncomingMessages(Frame[] messages)
 {
     // Данный сервис не обрабатывает входящие сообщения
     return;
 }
Example #14
0
            /// <summary>
            /// Разбирает ответное сообщение
            /// </summary>
            /// <param name="message">Ответное сообщение</param>
            /// <returns>Структура данных ответа</returns>
            internal static IncomingMessageStuctureServicePdoTransmit Parse(Frame message)
            {
                // Маска для отделения (Fct code: 4 старших бита) от адреса устройства (7 младших бит)
                // переданных в CobId сообщения
                const UInt16 MASK_FCT_CODE = 0x780; // 11110000000;
                // Идентификатор CodId, по которому определяется что входящее сообщение
                // предназначено для данного сервиса
                const UInt16 MASK_PDO1 = 0x180;
                const UInt16 MASK_PDO2 = 0x280;
                const UInt16 MASK_PDO3 = 0x380;
                const UInt16 MASK_PDO4 = 0x480;
                const Byte MASK_COBEID = 0x7F; // Выделяет 7 бит содержащих CodeId из поля Id 
                
                IncomingMessageStuctureServicePdoTransmit frame =
                    new IncomingMessageStuctureServicePdoTransmit();
                
                frame.Answer = message;
                
                // Выделяет 7 бит содержащих CodeId из поля Id
                    // Работаем только с данным типом сообщений другие игнорируем.
                if (frame.Answer.Value.FrameType == FrameType.DATAFRAME)
                {
                    UInt16 cobId = (UInt16)(frame.Answer.Value.Identifier & MASK_FCT_CODE);

                    switch (cobId)
                    {
                        case MASK_PDO1:
                            {
                                frame.Pdo = PdoType.PDO1;
                                frame._IsForService = true;
                                // Проверяем корректность данных
                                frame._IsCorrectStructure = frame.Answer.Value.Data.Length == 8 ?
                                    true : false;
                                break;
                            }
                        case MASK_PDO2:
                            {
                                frame.Pdo = PdoType.PDO2;
                                frame._IsForService = true;
                                // Проверяем корректность данных
                                frame._IsCorrectStructure = frame.Answer.Value.Data.Length == 7 ?
                                    true : false;
                                break;
                            }
                        case MASK_PDO3:
                            {
                                frame.Pdo = PdoType.PDO3;
                                frame._IsForService = true;
                                // Проверяем корректность данных
                                frame._IsCorrectStructure = frame.Answer.Value.Data.Length == 6 ?
                                    true : false;
                                break;
                            }
                        case MASK_PDO4:
                            {
                                frame.Pdo = PdoType.PDO4;
                                frame._IsForService = true;
                                // Проверяем корректность данных
                                frame._IsCorrectStructure = frame.Answer.Value.Data.Length == 4 ?
                                    true : false;
                                break;
                            }
                        default:
                            {
                                frame.Pdo = PdoType.Unknown;
                                frame._IsForService = false;
                                // Проверяем корректность данных
                                frame._IsCorrectStructure = false;
                                break;
                            }
                    }
                }
                else
                {
                    frame.Pdo = PdoType.Unknown;
                    frame._IsForService = false;
                }

                frame.NodeId = (Byte)(((Byte)message.Identifier) & MASK_COBEID);
                frame.DL = message.Data.Length;
                
                
                return frame;
            }
Example #15
0
 /// <summary>
 /// Возвращает индекс объекта в запросе
 /// </summary>
 /// <param name="request"></param>
 /// <returns></returns>
 private UInt16 GetIndex(Frame request)
 {
     UInt16 index = 0;
     
     unchecked
     {
         index = Convert.ToUInt16(request.Data[ANSWER_STUCTURE.INDEXLOW] |
             (request.Data[ANSWER_STUCTURE.INDEXHIGH] << 8));
     }
     return index; 
 }
Example #16
0
 public override bool Read(out Frame message)
 {
     lock (_SyncRoot)
     {
         if (this._InputBufferMessages.Count > 0)
         {
             message = this._InputBufferMessages.Dequeue();
             return true;
         }
         else
         {
             message = new Frame();
             return false;
         }
     }
 }
Example #17
0
        /// <summary>
        /// Обработать принятые сообщения
        /// </summary>
        /// <param name="messages">Входящие сообщения из сети</param>
        public override void HandleIncomingMessages(Frame[] messages)
        {            
            String msg;
            IncomingMessageStuctureSdo msghelper;
            DeviceContext deviceContex;
            DataObject obj;
            // Индексы объектов которые не обрабатываем!!!
            List<UInt16> notHandledIndexes = new List<ushort>();
            notHandledIndexes.AddRange(new UInt16[] { 0x2001, 0x2002 });

            if (Status != Status.Running)
            {
                return;
            }

            foreach(Frame message in messages)
            {            
                // Сообщение для этого сервиса. Получаем структуру сообщения
                msghelper = IncomingMessageStuctureSdo.Parse(message);

                if (!msghelper.IsForService)
                {
                    // Сообещение не для этого сервиса
                    continue;
                }
            
                // Ищем устройство с данным CobId. Если устройство найдено,
                // то устанавливаем флаг
                deviceContex = _Context.FindDevice(msghelper.CobeId);
            
                if (deviceContex == null)
                { 
                    // Устройство не найдено.
                    msg = String.Format(
                        "Network {0}: SDO Service: Получено сообщение от незарегистрированного устройства. " +
                        "Message - {1}", _NetworkController.Description, message.ToString());
                    //Trace.TraceError(msg);
                    continue;                
                }

                // Устройство найдено. Проверяем его текущий запрос, т.е index
                if ((deviceContex.CurrentTransaction != null) && 
                    (deviceContex.CurrentTransaction.Status == TransactionStatus.Running))
                {
                    if (msghelper.HasExсeption)
                    {
                        if (GetIndex(deviceContex.CurrentTransaction.Request.Value) == msghelper.Index)
                        {
                            msg = String.Format(
                                "Network {0}: SDO Service: Устройсво вернуло исключение {1}",
                                _NetworkController.NetworkId, msghelper.ExceptionCode);
                            deviceContex.CurrentTransaction.Abort(msghelper.Answer, msg);
                        }
                        else
                        {
                            msg = String.Format("Network {0}: SDO Service: " +
                                "Индекс в ответе не соответствует запрошенному. Запрос - {1}, Ответ - {2}",
                                NetworkController.NetworkId,deviceContex.CurrentTransaction.Request.Value.ToString(),
                                message.ToString());
                        }
                        continue;
                    }

                    // Проверяем индекс запроса и ответа
                    if (GetIndex(deviceContex.CurrentTransaction.Request.Value) != msghelper.Index)
                    {
                        // Прищёл ответ на несуществующий запрос
                        msg = String.Format("Network {0}: SDO Service: " +
                            "Индекс в ответе не соответствует запрошенному. Запрос - {1}, Ответ - {2}",
                            NetworkController.NetworkId, deviceContex.CurrentTransaction.Request.Value.ToString(),
                            message.ToString());
                        //Trace.TraceError(msg);
                        continue;
                    }
                    else
                    {                    
                        // Устанавливаем ответ на запрос
                        //deviceContex.CurrentTransaction.Answer = frmSdo.Answer;
                        // Проверяем контекст
                        if (deviceContex.CurrentObject.Index != msghelper.Index)
                        {
                            msg = String.Format(
                                "Network {0}: SDO Service: Индекс в ответе соответствует запрошенному {1}, " +
                                "но не соотвествует индексу в контексте {2}", _NetworkController.NetworkId,
                                msghelper.Index, deviceContex.CurrentObject);
                            deviceContex.CurrentTransaction.Abort(msghelper.Answer, msg);
                            throw new Exception(msg);
                        }
                    }

                    // Всё нормально, subindex-ы не проверяем они всегда равны 0;
                    
                    // Исключений нет, устанавливаем новое полученное значение для объекта 
                    // с указанным индексом 
                    // Получаем тип данных соответствующего идекса для соотвествующего профиля устройства
                   ObjectInfo objInfo;

                   if (!deviceContex.Device.Profile.ObjectInfoList.Contains(msghelper.Index))
                   {
                       msg = String.Format("Network {0}: SDO Service: " +
                           "Ненайдено описание объекта c индексом {1} в профиле устройства {2}",
                           _NetworkController.Description, msghelper.Index, deviceContex.Device.Profile.DeviceType);
                       deviceContex.CurrentTransaction.Abort(msghelper.Answer, msg);
                       throw new InvalidOperationException(msg);
                   }
                   else
                   {
                       objInfo = deviceContex.Device.Profile.ObjectInfoList[msghelper.Index];
                   }
                    
                    if (!deviceContex.Device.ObjectDictionary.Contains(msghelper.Index))
                    {
                        msg = String.Format("Network {0}: SDO Service: " +
                            "Ненайден объект c индексом {1} в словаре устройства {2}",
                           _NetworkController.Description, msghelper.Index, deviceContex.Device.NodeId);
                       deviceContex.CurrentTransaction.Abort(msghelper.Answer, msg);
                       throw new InvalidOperationException(msg);
                    }
                    else
                    {
                        obj = deviceContex.Device.ObjectDictionary[msghelper.Index];
                    }
                    // Проверяем модификатор доступа к значению. Если "только для чтения"
                    // и тип: System или Configuration, то параметр конфигурационный. 
                    // В этом случае сравниваем прочитанное значение со значением объета словаря. 
                    // Если они не совпадают, устанавливаем статус "Ошибка конфигурации"
                    // Если тип Measured, то читаем и устанавливаем данное значение из устройства
                    if ((objInfo.ReadOnly) && (objInfo.Category == Category.Configuration ||
                        objInfo.Category == Category.System))
                    {
                        if (notHandledIndexes.Contains(obj.Index))
                        {
                            // Обновляем время последнего прочтения
                            obj.Value = obj.Value;
                            // Закрываем транзакцию
                            deviceContex.CurrentTransaction.Stop(msghelper.Answer);
                            continue;
                        }

                        if (msghelper.Value != obj.Value)
                        {
                            // Ошбика конфигурации
                            msg = String.Format(
                                "Ошбика конфигурации устройства: Устройство NodeId={0}, Индекс объекта={1}. " +
                                "Значение в словаре={2}, прочитнное значение={3}",
                                deviceContex.Device.NodeId, msghelper.Index, obj.Value, msghelper.Value);
                            // Обновляем дату последнего обновления параметра
                            obj.Value = obj.Value;
                            // Устанавливаем код состояния объекта словаря
                            obj.Status = ObjectStatus.ConfigurationError;
                            // Записываем ошибку в лог
                            // ...
                            deviceContex.CurrentTransaction.Abort(msghelper.Answer, msg);
                        }
                        else
                        {
                            // Ошибки нет.
                            // Обновляем дату последнего обновления параметра
                            obj.Value = obj.Value;
                            // Устанавливаем код состояния объекта словаря
                            obj.Status = ObjectStatus.NoError;
                            deviceContex.CurrentTransaction.Stop(msghelper.Answer);
                        }
                    }
                    else
                    {
                        // Записываем новое значение в БД
                        // TODO: реализовать проверку на допустимые значение объекта
                        obj.Value = msghelper.Value;
                        obj.Status = ObjectStatus.NoError;
                        deviceContex.CurrentTransaction.Stop(msghelper.Answer);
                    }
                }
            }
        }
Example #18
0
        /// <summary>
        /// Метод для чтения порта. Запускается во вторичном потоке. Поток на чтение запускается при открытии порта 
        /// и завершается при закрытии.
        /// </summary>
        private void HandleQueueIncomingMessages()
        {
            String msg;
            F_CAN_RESULT result;
            F_CAN_RX buffer;
            F_CAN_WAIT wait;
            UInt32 timeout = 500; // мсек
            Frame message;
            //uint count;

            // Если прот закрыт, чтение его буфера не возможно
            //if (this.IsOpen == false)
            //{
            //    msg = "Невозможно прочитать очередь сообщений, CAN-порт закрыт";
            //    throw new InvalidOperationException(msg);
            //}

            // Читаем порт всё время пока открыт
            while (this._FlagMustQuit > 0)
            {
                wait.waitMask = F_CAN_STATUS.CAN_STATUS_EMPTY | F_CAN_STATUS.CAN_STATUS_TXBUF;
                wait.status = F_CAN_STATUS.CAN_STATUS_EMPTY;

                result = Api.fw_can_wait(this._DeviceHandle, ref wait, timeout);

                if ((result == F_CAN_RESULT.CAN_RES_OK) ||
                    (result == F_CAN_RESULT.CAN_RES_TIMEOUT))
                {
                    if (result == F_CAN_RESULT.CAN_RES_TIMEOUT)
                    {
                        //Console.WriteLine("Сработал таймаут ожидания");
                        // Произошло что-то нехорошее, нужно анализировать и что-то делать
                        // Проверяем текущий статус
                        //if (wait.status == wait.waitMask)
                        //{ }
                        // Останавливаем порт
                        this.Stop();
                        // Генерируем событие 
                        OnErrorReceived(ERROR.Other);
                        // Закрываем порт
                        this.Close();
                        // Завершаем работу потока
                        Interlocked.Exchange(ref this._FlagMustQuit, 0);
                        continue;
                    }

                    // Если  флаг установлен, то есть принятые сообщения. Читаем их
                    // и помещаем в буфер исходящих сообщений
                    if (F_CAN_STATUS.CAN_STATUS_RXBUF == 
                        (wait.status & F_CAN_STATUS.CAN_STATUS_RXBUF))
                    {
                        // Читаем буфер адаптера
                        result = Api.fw_can_peek_message(_DeviceHandle, out buffer);
                        // Разбираем принятое сообщение и формируем событие
                        message = new Frame();
                        message = ConvertNim351.ConvertToFrame(buffer.msg);
                        // Помещает принятое сообщение в буфер входных сообщений и генерируем событие приёма
                        lock (_SyncRoot)
                        {
                            this._InputBufferMessages.Enqueue(message);
                        }
                        this.OnMessageReceived();
                    }

                    // Произошла ошибка читаем её и сбрасываем 
                    if (F_CAN_STATUS.CAN_STATUS_ERR == 
                        (wait.status & F_CAN_STATUS.CAN_STATUS_ERR))
                    {
                        F_CAN_ERRORS errors;
                        result = Api.fw_can_get_clear_errors(this._DeviceHandle, out errors);

                        if (Api.f_can_success(result))
                        {
                            // Анализируем счётчики и генерируем событие
                            this.OnErrorReceived(ERROR.Other);
                        }
                        else
                        {
                            msg = String.Format(
                                "При чтении и сбросе счётчика ошибок CAN-адаптера возникла ошибка: {0}", result);
                            throw new InvalidOperationException(msg);
                        }
                    }
                }
                else
                {
                    msg = String.Format("При выполнении функции fw_can_wait произошла ошибка: {0}", 
                        Enum.GetName(typeof(F_CAN_RESULT), result));
                    throw new InvalidOperationException(msg);
                }
            }
            return;
        }
Example #19
0
        /// <summary>
        /// Обработчик входящих сообщений из сети
        /// </summary>
        /// <param name="message">Входящее сообщение для обработки</param>
        //private void HandleIncomingMessages(Frame message)
        public override void HandleIncomingMessages(Frame[] messages)
        {
            String msg;
            IncomingMessageStuctureBootUp msghelper;
            DeviceBase device;
       
            if (Status != Status.Running)
            {
                return;
            }

            foreach (Frame message in messages)
            {
                msghelper = IncomingMessageStuctureBootUp.Parse(message);

                if (!msghelper.IsForService)
                {
                    continue;
                }

                if (msghelper.HasIncorrectStructure)
                {
                    //!!!Warning: Длина данных в поле данных корректна, но содержание неверно
                    // (message.Data[0] == 0x84) || (message.Data[0] == 0x04) ||
                    // (message.Data[0] == 0x85) || (message.Data[0] == 0x05) ||
                    // (message.Data[0] == 0xFF) || (message.Data[0] == 0x7F))
                    // Эти коды используются в протоколе NodeGuard.
                    continue;
                }

                // Сообщение для этого сервиса.
                //msg = String.Format("Network {0}: Сервис {1}: Service BootUp принял сообщение: {2}",
                //    base.NetworkController.NetworkName(), this.ServiceName, message.ToString());
                //_Logger.Trace(msg);

                //Ищем устройство которое прислало сообщение
                if (!_NetworkController.Devices.Contains(msghelper.CobeId))
                {
                    // Устройство не найдено
                    msg = String.Format(
                        "Network {0}: Пришло сообщение от устройства с NodeId {1}, " +
                        "данное устройство не зарегистрировано в сети. Message - {2}",
                        this.NetworkController.Description, msghelper.CobeId, message.ToString());
                    //Logger.Error(msg);
                    continue;
                }

                // Устройство найдено. 
                // Устанавливаем новый статус устройству
                device = _NetworkController.Devices[msghelper.CobeId];

                lock (_SyncRoot)
                {
                    device.Status = DeviceStatus.Preoperational;
                }
                // Пишем в журнал... Не реализовано
            }
        }
Example #20
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;
        }
Example #21
0
 public override void HandleIncomingMessages(Frame[] messages)
 {
     //Данный сервис не имеет входящих сообщений
     return;
 }
Example #22
0
        /// <summary>
        /// Читает из входного буфера сообщение. 
        /// </summary>
        /// <returns>Если буфер пуст возвращается false</returns>
        public Boolean ReadMessage(out Frame message)
        {
            Boolean result;

            lock (_SyncRoot)
            {
                if (_InputBufferMessages.Count != 0)
                {
                    message = (Frame)_InputBufferMessages.Dequeue();
                    result = true;
                }
                else
                {
                    message = new Frame();
                    result = false;
                }
            }
            return result;
        }
Example #23
0
        /// <summary>
        /// Начинает новую транзакцию
        /// </summary>
        public void Start(TransactionType type, Frame request)
        {
            string msg;

            if (this.IsRunning)
            {
                msg = String.Format(
                    "Transaction ID: {0}; Попытка запустить уже запущенную (активную) транзакцию",
                    _Identifier);
                throw new InvalidOperationException(msg);
            }
            else
            {
                _Request = request;
                _Status = TransactionStatus.Running;

                switch (type)
                {
                    case TransactionType.BroadcastMode:
                    case TransactionType.UnicastMode:
                        {
                            _TimeOfStart = DateTime.Now;
                            this._TransactionType = type;
                            break;
                        }
                    case TransactionType.Undefined:
                        {
                            msg = String.Format(
                                "Transaction ID: {0}; Попытка начать сетевую транзакцию неопределённого типа",
                                _Identifier);
                            Abort(null, msg);
                            throw new InvalidOperationException(msg);
                        }
                    default:
                        {
                            msg = String.Format("Transaction ID: {0}; Попытка начать сетевую транзакцию " +
                                "тип которой не поддерживается - {1}", _Identifier, _TransactionType);
                            Abort(null, msg);
                            throw new NotImplementedException(msg);
                        }
                }
                //Debug.WriteLine(String.Format(
                //    "Transaction ID: {0} - Начало транзакции: {1} мсек",
                //    this.Identifier.ToString(), this._TimeOfStart));
            }
            return;
        }
Example #24
0
        public override void Write(Frame message)
        {
            String msg;

            // Проверяем корректность данных. Можно отправить только фреймы двух типов
            // FRAMETYPE.DATAFRAME и FRAMETYPE.REMOTEFRAME остальные не допустимы (служебные)
            // !!! FRAMETYPE.OVERLOADFRAME не разобрался 
            if (!((message.FrameType == FrameType.DATAFRAME) ||
                (message.FrameType == FrameType.REMOTEFRAME)))
            {
                msg = String.Format(
                    "{0}: class CanPort.ICanPort.Write(Frame message): Недопустимый тип фрайма, подустимы только FRAMETYPE.DATAFRAME и FRAMETYPE.REMOTEFRAME",
                    DateTime.Now.ToString(new System.Globalization.CultureInfo("ru-Ru", false)));
                Trace.TraceError(msg);
                throw new ArgumentException(msg, "message.FrameType");
            }
            else if (!((message.FrameFormat == FrameFormat.ExtendedFrame) || 
                (message.FrameFormat == FrameFormat.StandardFrame)))
            {
                msg = String.Format(
                    "{0}: class CanPort.ICanPort.Write(Frame message): Недопустимый формат фрайма, допустимы только FRAMEFORMAT.ExtendedFrame и FRAMEFORMAT.StandardFrame",
                    DateTime.Now.ToString(new System.Globalization.CultureInfo("ru-Ru", false)));
                throw new ArgumentException(msg, "message.FrameFormat"); 
            }
            else
            {
                if (message.Data != null)
                {
                    if (message.Data.Length > 8)
                    {
                        msg = String.Format(
                            "{0}: class CanPort.ICanPort.Write(Frame message): Попытка передать сообещение, содержащее поле данных более 8 байт",
                            DateTime.Now.ToString(new System.Globalization.CultureInfo("ru-Ru", false)));
                        throw new ArgumentException(msg, "message.Data.Length");
                    }
                    else
                    {
                        this.WriteMessage(message.Identifier, message.FrameType, message.FrameFormat, message.Data);
                    }
                }
                else
                {
                    message.Data = new Byte[0];
                    this.WriteMessage(message.Identifier, message.FrameType, message.FrameFormat, message.Data);
                }
            }
            return;
        }
Example #25
0
        /// <summary>
        /// Прерывает текущую транзакцию, произошла ошибка
        /// </summary>
        /// <param name="answer">Ответ, если он есть</param>
        /// <param name="description">Описывает ситуацию отмены текущей транзакции</param>
        public void Abort(Frame? answer, String description)
        {
            string msg;

            if (!IsRunning)
            {
                msg = String.Format("Transaction ID: {0}; Попытка отменить не начатую транзакцию",
                    this.Identifier);
                throw new InvalidOperationException(msg);
            }
            else
            {
                _Answer = answer;
                _TimeOfEnd = DateTime.Now;
                _Status = TransactionStatus.Aborted;
                _DescriptionError = String.IsNullOrEmpty(description) ? String.Empty : description; 
            }
            // Генерируем событие
            OnTransactionWasEnded();
            return;
        }
Example #26
0
 public override bool Read(out Frame message)
 {
     return this.ReadMessage(out message);
 }
Example #27
0
 public abstract bool Read(out Frame message);
Example #28
0
            /// <summary>
            /// Разбирает ответное сообщение
            /// </summary>
            /// <param name="message">Ответное сообщение</param>
            /// <returns>Структура данных ответа</returns>
            internal static IncomingMessageStuctureSdo Parse(Frame message)
            {
                const Byte MASK_COBEID = 0x7F; // Выделяет 7 бит содержащих CodeId из поля Id 

                IncomingMessageStuctureSdo frame = new IncomingMessageStuctureSdo();
                frame.Answer = message;
                frame.CobeId = (Byte)(((Byte)message.Identifier) & MASK_COBEID);
                // Длина данных ответа в SDO всегда 8
                if (message.Data.Length == 8)
                {
                    frame.DL = (DataLenght)message.Data[ANSWER_STUCTURE.DL];
                    switch (frame.DL)
                    {
                        case DataLenght.OneByte:
                            {
                                frame.Value = message.Data[ANSWER_STUCTURE.D0];
                                break;
                            }
                        case DataLenght.TwoBytes:
                            {
                                frame.Value = System.Convert.ToUInt32(
                                    (message.Data[ANSWER_STUCTURE.D0] |
                                    ((UInt32)message.Data[ANSWER_STUCTURE.D1] << 8)));
                                break;
                            }
                        case DataLenght.ThreeBytes:
                            {
                                frame.Value = System.Convert.ToUInt32(
                                    (message.Data[ANSWER_STUCTURE.D0] |
                                    ((UInt32)message.Data[ANSWER_STUCTURE.D1] << 8) |
                                    ((UInt32)message.Data[ANSWER_STUCTURE.D2] << 16)));
                                break;
                            }
                        case DataLenght.FourBytes:
                        case DataLenght.Ecxeption:
                            {
                                frame.Value = System.Convert.ToUInt32(
                                    (message.Data[ANSWER_STUCTURE.D0] |
                                    ((UInt32)message.Data[ANSWER_STUCTURE.D1] << 8) |
                                    ((UInt32)message.Data[ANSWER_STUCTURE.D2] << 16) |
                                    ((UInt32)message.Data[ANSWER_STUCTURE.D3] << 32)));
                                break;
                            }
                        case DataLenght.NotDefined:
                        default:
                            {
                                frame._HasIncorrectStructure = true;
                                frame.Value = 0; break;
                            }
                    }
                }
                else
                {
                    frame._HasIncorrectStructure = true;
                    frame.Value = 0;
                }

                if (!frame._HasIncorrectStructure)
                {
                    frame.Index = message.Data[ANSWER_STUCTURE.INDEXLOW];
                    frame.Index = System.Convert.ToUInt16((frame.Index | (message.Data[ANSWER_STUCTURE.INDEXHIGH] << 8)));
                    frame.SubIndex = message.Data[ANSWER_STUCTURE.SUBINDEX];
                }
                else
                {
                    frame.Index = 0;
                    frame.SubIndex = 0;
                }
                return frame;
            }
Example #29
0
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        /// <summary>
        /// Обработчик клика по ячейкам грида исходящих сообщений
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void EventHandler_DataGridViewOutcomingMessages_CellClick(object sender, 
            DataGridViewCellEventArgs e)
        {
            DataGridView dgv;
            DataGridViewRow row;
            Message.Frame message;
            dgv = (DataGridView)sender;
            // Определяем от какой ячейки, какого столбца пришло событие
            // Если от столбца "Отправить", то отправляем сообщение
            if ((dgv.Columns[e.ColumnIndex] is DataGridViewButtonColumn) &&
                (e.RowIndex >= 0))
            {
                row = dgv.Rows[e.RowIndex];
                message = new Frame();
                message.Identifier = (UInt32)row.Cells[1].Value;
                message.FrameFormat = (Message.FrameFormat)row.Cells[2].Value;
                message.FrameType = (Message.FrameType)row.Cells[3].Value;
                message.Data = (Byte[])row.Cells[4].Value;
                
                //MessageBox.Show(String.Format("Сообщение отправлено: {0}", message.ToString()));
                if (this._CanPort.IsOpen)
                {
                    this._CanPort.Write(message);
                }
            }

            return;
        }
Example #30
0
        /// <summary>
        /// Обработчик входящих сообщений из сети
        /// </summary>
        /// <param name="message">Входящее сообщение для обработки</param>
        //private void HandleIncomingMessages(Frame message)
        public override void HandleIncomingMessages(Frame[] messages)
        {
            String msg;
            IncomingMessageStuctureEmcy msghelper;
            DeviceBase device;
            UInt16 index;


            if (Status != Status.Running)
            {
                return;
            }

            foreach (Frame message in messages)
            {
                msghelper = IncomingMessageStuctureEmcy.Parse(message);

                if (!msghelper.IsForService)
                {
                    continue;
                }

                if (msghelper.HasIncorrectStructure)
                {
                    continue;
                }

                // Сообщение для этого сервиса.
                //msg = String.Format("Network {0}: Сервис {1}: Service Emcy принял сообщение: {2}",
                //    base.NetworkController.NetworkName(), this.ServiceName, message.ToString());
                //_Logger.Trace(msg);

                //Ищем устройство которое прислало сообщение
                if (!_NetworkController.Devices.Contains(msghelper.CobeId))
                {
                    // Устройство не найдено
                    msg = String.Format(
                        "Network {0}: Пришло сообщение от устройства с NodeId {1}, " +
                        "данное устройство не найдено конфигурации в сети. Message - {2}",
                        this.NetworkController.Description, msghelper.CobeId, message.ToString());
                    //Logger.Error(msg);
                    continue;
                }

                // Устройство найдено. 
                // Устанавливаем новый статус устройству
                device = _NetworkController.Devices[msghelper.CobeId];

                //Анализируем код ошибки (источник или причина возникновения ошибки)
                switch (msghelper.ErrorCode)
                {
                    case IncomingMessageStuctureEmcy.ErrCode.NoError:
                        {
                            // Все ошибки исправлены
                            if (msghelper.ErrorRegister.FlagsByte != 0)
                            {
                                msg = String.Format(
                                    "Неверное состояние - передан ErrCode=0 и ожидается err_reg=0, a получено err_reg = {0}",
                                    msghelper.ErrorRegister);
                                throw new Exception(msg);
                            }

                            // Сбрасываем ошибки в устройстве если были
                            IEmcyErrors err = (IEmcyErrors)device;
                            
                            lock (_SyncRoot)
                            {
                                err.BatteryError = false;
                                err.ConnectedServiceConnector = false;
                                err.DuplicateAddressError = false;
                                err.MainSupplyPowerError = false;
                                err.RegistrationError = false;
                                err.Tamper = false;
                            }                            

                            break;
                        }
                    case IncomingMessageStuctureEmcy.ErrCode.Tamper:
                    case IncomingMessageStuctureEmcy.ErrCode.BatteryError:
                    case IncomingMessageStuctureEmcy.ErrCode.MainSupplyPowerError:
                    case IncomingMessageStuctureEmcy.ErrCode.ConnectedServiceConnector:
                    case IncomingMessageStuctureEmcy.ErrCode.DuplicateAddressError: // TODO: обработать поле Х - номер канала шлюза
                    case IncomingMessageStuctureEmcy.ErrCode.RegistrationError: // TODO: обработать поле Х - номер канала шлюза
                        {
                            IEmcyErrors err = (IEmcyErrors)device;

                            lock (_SyncRoot)
                            {
                                err.BatteryError = msghelper.ErrorRegister.BatteryError;
                                err.ConnectedServiceConnector = 
                                    msghelper.ErrorRegister.ConnectedServiceConnector;
                                err.DuplicateAddressError = 
                                    msghelper.ErrorRegister.DuplicateAddressError;
                                err.MainSupplyPowerError = 
                                    msghelper.ErrorRegister.MainSupplyPowerError;
                                err.RegistrationError = 
                                    msghelper.ErrorRegister.RegistrationError;
                                err.Tamper = msghelper.ErrorRegister.Tamper;
                            } 

                            break;
                        }
                    default:
                        {
                            throw new NotImplementedException();
                        }
                }

                //TODO: Пишем в журнал... Не реализовано
            }
        }