Example #1
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 #2
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 #3
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;
            }