Example #1
0
 /// <summary>
 /// Конструктор
 /// </summary>
 /// <param name="error">Код ошибки выполнения запроса</param>
 /// <param name="description">Описание ошибки</param>
 /// <param name="request">Запрос</param>
 /// <param name="answer">Ответное сообщение на запрос</param>
 public Result(Error error, String description,
     Message request, Message answer)
 {
     _Request = request;
     _ErrorCode = error;
     _Description = description;
     _Answer = answer;
     return;
 }
Example #2
0
 /// <summary>
 /// Конструктор
 /// </summary>
 /// <param name="message">Сообщение отправленное 
 /// мастеру или принятое от него</param>
 public MessageEventArgs(Message.Message message)
 {
     Message = message;
 }
Example #3
0
        //---------------------------------------------------------------------------
        Result INetworkFunctions.ReadHoldingRegisters(Message.Message request)
        {
            Message.Result result;
            Message.Message answer;
            Message.PDU pdu;
            String message;

            if (request.Address == 0)
            {
                // Ошибка. Данная команда не может быть широковещательная
                message = "Широковещательный запрос на выполнение функции 0x03 невозможен";
                result = new Message.Result(Error.RequestError,
                    message, request, null);
            }
            else
            {
                // Проверяем длину PDU (должна равнятся 5 байтам)
                if (request.PDUFrame.ToArray().Length != 5)
                {
                    // Длина сообщения не верная
                    String mes = String.Format(
                        "Длина PDU-фрайма равна в запросе 0x3 равна {0} байт. Должна быть 5 байт",
                        request.PDUFrame.ToArray().Length);

                    result = new Message.Result(Error.DataFormatError, mes, request, null);
                }
                else
                {
                    // Разбираем сообщение
                    Byte[] array = new Byte[2];
                    // Получаем адрес первого регистра входа
                    Array.Copy(request.PDUFrame.Data, 0, array, 0, 2);
                    UInt16 address = Modbus.Convert.ConvertToUInt16(array);
                    // Получаем количесво регистров для чтения
                    Array.Copy(request.PDUFrame.Data, 2, array, 0, 2);
                    UInt16 quantity = Modbus.Convert.ConvertToUInt16(array);

                    if ((quantity == 0) || (quantity > 125))
                    {
                        message =
                            String.Format("Количество регистров для чтения в запросе {0}, а должно быть 1...125",
                            quantity);
                        pdu = new Message.PDU(0x83, new Byte[] { 0x03 });
                        answer = new Message.Message(_Address, pdu);
                        // Отправляем сообщение
                        SendResponse(answer);

                        result = new Message.Result(Error.IllegalDataValue,
                            message, request, answer);
                    }
                    else
                    {
                        // Выполняем запрос. Проверяем доступность в 
                        // системе регистров в указанном диапазоне адресов
                        for (int i = 0; i < quantity; i++)
                        {
                            // Если регистр не существует в системе формируем ответ
                            // c исключение
                            if (HoldingRegisters.Contains(System.Convert.ToUInt16(address + i)) == false)
                            {
                                // Формируем ответ с исключение 2
                                pdu = new Message.PDU(0x83, new Byte[] { 0x02 });
                                answer = new Message.Message(_Address, pdu);

                                message =
                                    String.Format("Регистр с адресом {0} не существует",
                                    (address + i));
                                result = new Message.Result(Error.IllegalDataAddress,
                                    message, request, answer);

                                // Отправляем ответ мастеру
                                SendResponse(answer);

                                return result;
                            }
                        }

                        // Все регистры найдены формируем ответное сообщение
                        Byte[] temp;
                        List<Byte> data = new List<byte>();

                        data.Add(System.Convert.ToByte((quantity * 2)));

                        for (int i = 0; i < quantity; i++)
                        {
                            temp = Modbus.Convert.ConvertToBytes(HoldingRegisters[i].Value);
                            data.AddRange(temp);
                        }
                        pdu = new Message.PDU();
                        pdu.Function = 0x3;
                        pdu.AddDataBytesRange(data.ToArray());
                        answer = new Message.Message(_Address, pdu);

                        result = new Message.Result(Error.NoError, String.Empty, request, answer);
                        // Отправляем ответ мастеру
                        SendResponse(answer);
                    }
                }
            }
            return result;
        }
Example #4
0
        public void SendResponse(Message.Message answer)
        {
            // Останавливаем таймер таймаута
            _TimerTimeoutCurrentTransaction.Stop();
           
            Byte[] array = answer.ToArray();
            // Отсылаем ответ
            _SerialPort.Write(array, 0, array.Length);
            // Останавливаем транзакцию
            _СurrentTransaction.Stop(answer);
            // Формирует событие
            OnResponseWasSent(new MessageEventArgs(answer));

            return;
        }
Example #5
0
        //---------------------------------------------------------------------------
        #endregion

        // !!! Необоходимо сделать статическим методами, для того что бы уменьшить
        // размер устройтва в ОЗУ.
        #region INetworkFunctions Members
        //---------------------------------------------------------------------------
        Result INetworkFunctions.ReadCoils(Modbus.OSIModel.Message.Message request)
        {
            Message.Result result;
            Message.Message answer;
            PDU pdu;
            String message;

            if (request.Address == 0)
            {
                // Ошибка. Данная команда не может быть широковещательная
                message = "Широковещательный запрос на выполнение функции 0x01 невозможен";
                result = new Message.Result(Error.RequestError,
                    message, request, null);
            }
            else
            {
                // Проверяем длину PDU (должна равнятся 5 байтам)
                if (request.PDUFrame.ToArray().Length != 5)
                {
                    // Длина сообщения не верная
                    message = String.Format(
                        "Длина PDU-фрайма в запросе {0}. Должна быть 5 байт", request.PDUFrame.ToArray());
                    // Ответное сообщение не отсылается
                    result = new Message.Result(Error.DataFormatError, message,
                        request, null);
                }
                else
                {
                    // Разбираем сообщение
                    Byte[] array = new Byte[2];
                    // Получаем адрес первого реле
                    Array.Copy(request.PDUFrame.Data, 0, array, 0, 2);
                    UInt16 address = Modbus.Convert.ConvertToUInt16(array);
                    // Получаем количесво реле для чтения
                    Array.Copy(request.PDUFrame.Data, 2, array, 0, 2);
                    UInt16 quantity = Modbus.Convert.ConvertToUInt16(array);

                    if ((quantity == 0) || (quantity > 2000))
                    {
                        message = String.Format(
                            "Количество реле для чтения в запросе {0}, а должно быть 1...2000", quantity);
                        pdu = new Message.PDU(0x81, new Byte[] { 0x03 });
                        answer = new Modbus.OSIModel.Message.Message(_Address, pdu);
                        // Отправляем сообщение
                        SendResponse(answer);

                        result = new Message.Result(Error.IllegalDataValue,
                            message, request, answer);

                    }
                    else
                    {
                        // Выполняем запрос. Проверяем доступность в 
                        // системе реле в указанном диапазоне адресов
                        for (int i = 0; i < quantity; i++)
                        {
                            // Проверяем существует ли реле с указанным адресом.
                            // Если реле не существует в системе формируем ответ
                            // c исключение

                            if (Coils.Contains(System.Convert.ToUInt16(address + i)) == false)
                            {
                                // Формируем ответ с исключение 2
                                answer = new Modbus.OSIModel.Message.Message(Address,
                                    new PDU(0x81, new Byte[] { 0x2 }));

                                // Отправляем ответ мастеру
                                SendResponse(answer);

                                result = new Message.Result(Error.IllegalDataAddress,
                                    String.Format("Реле с адресом {0} не существует", 
                                    System.Convert.ToUInt16(address + i)),
                                    request, answer);

                                return result;
                            }
                        }

                        // Все реле найдены формируем ответное сообщение
                        int totalBytes = quantity % 8;

                        if (totalBytes == 0)
                        {
                            totalBytes = quantity / 8;
                        }
                        else
                        {
                            totalBytes = 1 + (quantity / 8);
                        }

                        Byte[] data = new Byte[totalBytes];
                        int number = 0;
                        int index = 0;

                        for (int i = 0; i < quantity; i++)
                        {
                            data[index] = (Byte)(data[index] | 
                                (Byte)(Modbus.Convert.BooleanToBit(
                                Coils[System.Convert.ToUInt16(address + i)].Value) << number));

                            if (++number > 7)
                            {
                                number = 0;
                                ++index;
                            }
                        }
                        pdu = new Message.PDU();
                        pdu.Function = 0x01;
                        pdu.AddDataByte((byte)totalBytes);  // Добавляем количество байт с состояниями реле
                        pdu.AddDataBytesRange(data);        // Добавляем байты с состояниями реле

                        answer = new Modbus.OSIModel.Message.Message(Address, pdu);
                        // Отправляем ответ мастеру
                        SendResponse(answer);
                        result = new Message.Result(Error.NoError, String.Empty, request, answer);
                    }
                }
            }
            return result;

        }
Example #6
0
        //---------------------------------------------------------------------------
        Result INetworkFunctions.ReadDiscreteInputs(Message.Message request)
        {
            Message.Result result;
            Message.Message answer;
            Message.PDU pdu;
            String message;

            if (request.Address == 0)
            {
                // Ошибка. Данная команда не может быть широковещательная
                message = "Широковещательный запрос на выполнение функции 0x02 невозможен";
                result = new Message.Result(Error.RequestError,
                    message, request, null);
            }
            else
            {
                // Проверяем длину PDU (должна равнятся 5 байтам)
                if (request.PDUFrame.ToArray().Length != 5)
                {
                    // Длина сообщения не верная
                    String mes = String.Format(
                        "Длина PDU-фрайма равна в запросе 0x2 равна {0} байт. Должна быть 5 байт",
                        request.PDUFrame.ToArray().Length);

                    result = new Message.Result(Error.DataFormatError, mes, request, null);
                    Debug.WriteLine(mes);
                }
                else
                {
                    // Разбираем сообщение
                    Byte[] array = new Byte[2];
                    // Получаем адрес первого дискретного входа
                    Array.Copy(request.PDUFrame.Data, 0, array, 0, 2);
                    UInt16 address = Modbus.Convert.ConvertToUInt16(array);
                    // Получаем количесво дискретных входов для чтения
                    Array.Copy(request.PDUFrame.Data, 2, array, 0, 2);
                    UInt16 quantity = Modbus.Convert.ConvertToUInt16(array);

                    if ((quantity == 0) || (quantity > 2000))
                    {
                        message =
                            String.Format("Количество дискретных входов для чтения в запросе {0}, а должно быть 1...2000",
                            quantity);
                        pdu = new Message.PDU(0x82, new Byte[] { 0x03 });
                        answer = new Modbus.OSIModel.Message.Message(_Address, pdu);

                        // Отправляем сообщение
                        SendResponse(answer);

                        result = new Message.Result(Error.IllegalDataValue,
                            message, request, answer);
                    }
                    else
                    {
                        // Выполняем запрос. Проверяем доступность в 
                        // системе дискретных входов в указанном диапазоне адресов
                        //DiscreteInput[] inputs = new DiscreteInput[quantity];

                        for (int i = 0; i < quantity; i++)
                        {
                            //inputs[i] = _discretesInputs.Find((UInt16)(address + i));
                            if (DiscretesInputs.Contains(System.Convert.ToUInt16(address + i)) == false)
                            {
                            // Если дискретный вход не существует в системе формируем ответ
                            // c исключением 2
                                pdu = new Message.PDU(0x82, new Byte[] { 0x02 });
                                answer = new Message.Message(_Address, pdu);

                                message =
                                    String.Format("Дискретный вход с адресом {0} не существует",
                                    (address + i));
                                result = new Message.Result(Error.IllegalDataAddress,
                                    message, request, answer);

                                // Отправляем ответ мастеру
                                SendResponse(answer);

                                return result;
                            }
                        }

                        // Все дискретные входы найдены формируем ответное сообщение
                        int totalBytes = quantity % 8;

                        if (totalBytes == 0)
                        {
                            totalBytes = quantity / 8;

                            if (totalBytes == 0)
                            {
                                totalBytes++;
                            }
                        }
                        else
                        {
                            totalBytes = 1 + (quantity / 8);
                        }

                        Byte[] data = new Byte[totalBytes];
                        int number = 0;
                        int index = 0;

                        for (int i = 0; i < quantity; i++)
                        {
                            data[index] = (Byte)(data[index] |
                                (Byte)(Modbus.Convert.BooleanToBit(DiscretesInputs[address + i].Value) << number));

                            if (++number > 7)
                            {
                                number = 0;
                                ++index;
                            }
                        }
                        pdu = new Message.PDU();
                        pdu.Function = request.PDUFrame.Function;
                        pdu.AddDataByte((Byte)totalBytes);
                        pdu.AddDataBytesRange(data);
                        answer = new Message.Message(_Address, pdu);

                        result = new Message.Result(Error.NoError, String.Empty, request, answer);
                        // Отправляем ответ мастеру
                        SendResponse(answer);
                    }
                }
            }
            return result;
        }
Example #7
0
 /// <summary>
 /// Метод отправляет ответ slave-устройства мастеру сети на его запрос.
 /// </summary>
 /// <param name="answer">Ответное сообщение</param>
 private void SendResponse(Message.Message answer)
 {
     if (NetworkController != null)
     {
         NetworkController.GetOutcommingMessage(answer);
     }
     else
     {
         throw new NullReferenceException(
             "Невозможно отправить ответ мастеру на запрос. Недоступен контроллер сети");
     }
     return;
 }
Example #8
0
        /// <summary>
        /// Забирает запрос и вызывает необходимые 
        /// для его выполнения функции
        /// </summary>
        /// <param name="request">Запрос от мастера</param>
        protected virtual void RequestParse(Message.Message request)
        {
            Message.Result result;
            
            // Получаем код команды и анализируем сообщение
            switch (request.PDUFrame.Function)
            {
                case 0x01: // Функция 0x1. Чтение реле (не может быть широковещательной)
                    {
                        result = ((INetworkFunctions)this).ReadCoils(request);
                        break;
                    }
                case 0x02: // Функция 0x2. Читает дискретные входы (не может быть широковещательной)
                    {
                        result = ((INetworkFunctions)this).ReadDiscreteInputs(request);
                        break;
                    }
                case 0x03: // Функция 0х3. Читает holding-регистры (не может быть широковещательной)
                    {
                        result = ((INetworkFunctions)this).ReadHoldingRegisters(request);
                        break;
                    }
                case 0x04: // Функция 0х4. Читает входные регистры (не может быть широковещательной)
                    {
                        result = ((INetworkFunctions)this).ReadInputRegisters(request);
                        break;
                    }
                case 0x05: // Функция 0х5. Устанавливает реле в состояние вкл./выкл.
                    {
                        result = ((INetworkFunctions)this).WriteSingleCoil(request);
                        break;
                    }
                case 0x06: // Функция 0x6. Записывает значение в одиночный регистр
                    {
                        result = ((INetworkFunctions)this).WriteSingleRegister(request);
                        break;
                    }
                case 0x0F:
                    {
                        result = ((INetworkFunctions)this).WriteMultipleCoils(request);
                        break;
                    }
                case 0x10:
                    {
                        result = ((INetworkFunctions)this).WriteMultipleRegisters(request);
                        break;
                    }
                case 0x14:
                    {
                        result = ((INetworkFunctions)this).ReadFileRecord(request);
                        break;
                    }
                default:
                    {
                        result = ((INetworkFunctions)this).FunctionNotSupported(request);
                        break;
                    }
            }

        }
Example #9
0
        //---------------------------------------------------------------------------
        Result INetworkFunctions.FunctionNotSupported(Message.Message request)
        {
            Message.Message answer;
            Message.PDU pdu = new Message.PDU();
            pdu.Function = (Byte)(request.PDUFrame.Function | 0x80);
            pdu.AddDataByte(0x01);   //Error.IllegalFunction
            answer = new Modbus.OSIModel.Message.Message(Address, pdu);

            // Отправляем ответ
            SendResponse(answer);

            Message.Result result =
                new Message.Result(Error.IllegalFunction,
                    "Функция не поддерживается данным устройством",
                    request, answer);
            return result;
        }
Example #10
0
 /// <summary>
 /// Метод получает входящие из сети сообщение (от мастера) обрабатываем его
 /// и формирует ответ, если это необходимо (при адресованном запросе)
 /// </summary>
 /// <param name="message">Входящие сообщение</param>
 /// <returns>Исходящие ответное сообщение</returns>
 internal void GetIncommingMessage(Message.Message message)
 {
     // Проверяем статус устройства, если устройство пассивно
     // не обрабатываем запрос и не отвечаем.
     if (Status == Status.Running)
     {
         // Проверяем. Это сообщение адресовано данному устройству или нет
         if ((message.Address == Address) || (message.Address == 0))
         {
             // Сообщение предназначено для данного устройства
             // !!! данную функцию выполнить в отдельном потоке
             RequestParse(message);
         }
         else
         {
             // Нет, это сообщение не предназначено для данного устройства
         }
     }
     return;
 }
Example #11
0
        //---------------------------------------------------------------------------
        Result INetworkFunctions.ReadFileRecord(Message.Message request)
        {
            Message.Result result;
            Message.Message answer;
            //Message.PDU pdu;
            String message;
            UInt16 var;


            Code0x14SubRequest[] subRequestList;

            const int ByteCountIndex = 0; // Индекс параметра Byte Count в массиве данных запроса  

            if (request.Address == 0)
            {
                // Ошибка. Данная команда не может быть широковещательная
                message = "Широковещательный запрос на выполнение функции 0x14 невозможен";
                result = new Message.Result(Error.RequestError,
                    message, request, null);
                return result;
            }
            else
            {
                if (request.PDUFrame.Length < 7)
                {
                    // Ошибка. Минимальная длина pdu запроса 0х14 это 7 байт
                    message = "Ошибка. Длина pdu запроса 0x14 менее 7 байт";
                    answer = new Message.Message(_Address,
                        new PDU((Byte)(0x14 | 0x80), new byte[] { 0x03 }));

                    result = new Message.Result(Error.RequestError,
                        message, request, answer);
                    // Отправляем ответ
                    SendResponse(answer);
                    return result;
                }
                else
                {
                    if ((request.PDUFrame.Data[ByteCountIndex] < 0x07) ||
                        (request.PDUFrame.Data[ByteCountIndex] > 0xF5))
                    {
                        // Ошибка. Указанная длина Byte Count вне допустимого диапазона значений
                        message = String.Format(
                            "Ошибка. Код функции 0x14. Параметр Byte Count = {0} вне допустимого диапазона 0x07...0xF5",
                            request.PDUFrame.Data[ByteCountIndex], (request.PDUFrame.Length - 2));

                        answer = new Message.Message(_Address,
                        new PDU((Byte)(0x14 | 0x80), new byte[] { 0x03 }));

                        result = new Message.Result(Error.RequestError,
                            message, request, answer);
                        // Отправляем ответ
                        SendResponse(answer);
                        return result;
                    }
                    else
                    {
                        // Проверяем фактическую длину запроса и величину переданную 
                        // в запросе "Byte Count"
                        if ((Int32)request.PDUFrame.Data[ByteCountIndex] != (request.PDUFrame.Length - 2))
                        {
                            // Ошибка. Указанная длина не совпадает с фактической
                            message = String.Format(
                                "Ошибка. Параметр Byte Count = {0} не совпадает с фактической длиной {1}",
                                request.PDUFrame.Data[ByteCountIndex], (request.PDUFrame.Length - 2));

                            answer = new Message.Message(_Address,
                            new PDU((Byte)(0x14 | 0x80), new byte[] { 0x03 }));

                            result = new Message.Result(Error.RequestError,
                                message, request, answer);
                            // Отправляем ответ
                            SendResponse(answer);
                            return result;
                        }
                        else
                        {
                            // Определяем количество групп (подзапросов) в данном запросе
                            if ((request.PDUFrame.Data.Length - 1) % 7 != 0)
                            {
                                // Длина подзапроса всегда равна 7, поэтому должно быть
                                // кратно. Если при делении на 7, остаток не равен 0, то
                                // данные не корректны
                                // Ошибка. Указанная длина не совпадает с фактической
                                message = String.Format("Ошибка. Неверная длина данных в запросе");

                                answer = new Message.Message(_Address,
                                new PDU((Byte)(0x14 | 0x80), new byte[] { 0x03 }));

                                result = new Message.Result(Error.RequestError,
                                    message, request, answer);
                                // Отправляем ответ
                                SendResponse(answer);
                                return result;

                            }
                            else
                            {
                                // Подзапросы имеют корректный формат. Получаем их
                                // Получаем количество подзапросов
                                subRequestList = new Code0x14SubRequest[((request.PDUFrame.Data.Length - 1) / 7)];
                                // Получаем сами подзапросы
                                for (int i = 0; i < subRequestList.Length; i++)
                                {
                                    subRequestList[i].ReferenceType = request.PDUFrame.Data[(7 * i + 1)];
                                    var = (UInt16)(((UInt16)request.PDUFrame.Data[(7 * i + 2)]) << 8); // Hi
                                    var = (UInt16)(var | request.PDUFrame.Data[(7 * i + 3)]); // Lo
                                    subRequestList[i].FileNumber = var;
                                    var = (UInt16)(((UInt16)request.PDUFrame.Data[(7 * i + 4)]) << 8); // Hi
                                    var = (UInt16)(var | request.PDUFrame.Data[(7 * i + 5)]); // Lo
                                    subRequestList[i].RecordNumber = var;
                                    var = (UInt16)(((UInt16)request.PDUFrame.Data[(7 * i + 6)]) << 8); // Hi
                                    var = (UInt16)(var | request.PDUFrame.Data[(7 * i + 7)]); // Lo
                                    subRequestList[i].RecordLength = var;
                                }
                                // Проверяем корректность данных в подзапросах 
                                for (int i = 0; i < subRequestList.Length; i++)
                                {
                                    // Проверяем значение параметра "The reference type". Оно всегда
                                    // должно равняться 0x6
                                    if (subRequestList[i].ReferenceType != 0x6)
                                    {
                                        // Ошибка
                                        answer = new Message.Message(_Address,
                                            new PDU((Byte)(0x80 | 0x14), new byte[] { 0x2 }));
                                        message = "Ошибка: Подзапрос имеет недопустимое значение праметра The reference type";
                                        result = new Result(Error.RequestError, message, request, answer);
                                        
                                        SendResponse(answer);
                                        
                                        return result;
                                    }
                                    else
                                    {
                                        // Проверяем адрес старовтовой записы. Должен быть 
                                        // не более 10000 (0x270F)
                                        if (subRequestList[i].RecordNumber > 0x270F)
                                        {
                                            // Ошибка
                                            answer = new Message.Message(_Address,
                                                new PDU((Byte)(0x80 | 0x14), new byte[] { 0x2 }));
                                            message = "Ошибка: Подзапрос имеет недопустимое значение номера записи файла";
                                            result = new Result(Error.RequestError, message, request, answer);

                                            SendResponse(answer);

                                            return result;
                                        }
                                        else
                                        {
                                            // Проверяем конечный адрес (Начальный адрес + длина блока)
                                            if (subRequestList[i].RecordNumber + subRequestList[i].RecordLength > 0x270F)
                                            {
                                                // Ошибка
                                                answer = new Message.Message(_Address,
                                                    new PDU((Byte)(0x80 | 0x14), new byte[] { 0x2 }));
                                                message = "Ошибка: Подзапрос имеет недопустимое значение длины блока читаемых записей из файла";
                                                result = new Result(Error.RequestError, message, request, answer);

                                                SendResponse(answer);

                                                return result;
                                            }
                                            else
                                            {
                                                // Все проверки пройдены. Теперь можно получать конечные 
                                                // значения
                                            }
                                        }
                                    }
                                }
                                
                                // Определяем общую длину ответа и проверяем превышает ли она допустимый размер
                                var = 2; // Function code + Resp. Data length
                                for (int i = 0; i < subRequestList.Length; i++)
                                {
                                    var = System.Convert.ToUInt16(var + 2); // File resp. length + Ref. Type 
                                    var = System.Convert.ToUInt16(var + (subRequestList[i].RecordLength * 2));
                                }

                                if (var > 253)
                                {
                                    // Ошибка. Длина запрощенных данных превышает максимальную
                                    // длину PDU ответного пакета
                                    answer = new Message.Message(_Address,
                                        new PDU((Byte)(0x80 | 0x14), new byte[] { 0x2 }));
                                    message = "Ошибка: Длина запрошенных данных превышает максимальную длину PDU";
                                    result = new Result(Error.RequestError, message, request, answer);

                                    SendResponse(answer);

                                    return result;
                                }
                                else
                                {
                                    // Если оказались в этой точке, значит запрос корректен. Получаем значения
                                    Code0x14SubRequest subRequest;
                                    List<byte> list = new List<byte>(var);
                                    list.Add(System.Convert.ToByte(var - 2)); // Поле Resp. data length

                                    for (int i = 0; i < subRequestList.Length; i++)
                                    {
                                        subRequest = subRequestList[i];

                                        if (_Files.Contains(subRequest.FileNumber) == true)
                                        {
                                            // Файл найден. Получаем его записи
                                            list.Add(System.Convert.ToByte(subRequest.RecordLength * 2 + 1)); // File resp. length
                                            list.Add(0x06); // Ref. type

                                            File file = _Files[subRequest.FileNumber];
                                            
                                            for (int y = 0; y < subRequest.RecordLength; y++)
                                            {
                                                // Проверяем существует ли запись с данным номером
                                                var = System.Convert.ToUInt16(
                                                    subRequest.RecordNumber + System.Convert.ToUInt16(y)); 
                                                if (file.Records.Contains(var) == true)
                                                {
                                                    // Указанная запись существует. Получаем её значение
                                                    // Сохраняем в ответе в виде последоватлеьности байт
                                                    list.AddRange(Modbus.Convert.ConvertToBytes(
                                                        file.Records[var].Value));
                                                }
                                                else
                                                {
                                                    // Указанной записи не существует в данном файле
                                                    // Ошибка. Длина запрощенных данных превышает максимальную
                                                    // длину PDU ответного пакета
                                                    answer = new Message.Message(_Address,
                                                        new PDU((Byte)(0x80 | 0x14), new byte[] { 0x4 }));
                                                    message = String.Format(
                                                        "Ошибка: Не найдена запрашиваемая запись с номером {0} в запрашиваемом файле c номером {0}",
                                                        var, file.Number);
                                                    result = new Result(Error.RequestError, message, request, answer);

                                                    SendResponse(answer);

                                                    return result;
                                                }
                                            }
                                        }
                                        else
                                        {
                                            // Файла с таким номером не существует. Возвращает исключение
                                            answer = new Message.Message(_Address,
                                                new PDU((Byte)(0x80 | 0x14), new byte[] { 0x4 }));
                                            message = String.Format(
                                                "Ошибка: Не найден запрашиваемый файл c номером {0}",
                                                subRequest.FileNumber);
                                            result = new Result(Error.RequestError, message, request, answer);

                                            SendResponse(answer);

                                            return result;
                                        }
                                    }

                                    // Если оказались в данной точке, значит предыдущий цикл выполнился устпешно
                                    // Можно отправлять данные
                                    answer = new Message.Message(_Address,
                                        new PDU(0x14, list.ToArray()));
                                    message = String.Empty;
                                    result = new Result(Error.NoError, message, request, answer);

                                    SendResponse(answer);

                                    return result;
                                }
                            }
                        }
                    }
                }
            }
            //return result;
        }
Example #12
0
        //---------------------------------------------------------------------------
        Result INetworkFunctions.WriteMultipleRegisters(Message.Message request)
        {
            Message.Result result;
            Message.Message answer;
            Message.PDU pdu;
            String message;

            // Проверяем длину PDU (должна быть не менее 8 байтам)
            if (request.PDUFrame.ToArray().Length < 8)
            {
                // Длина сообщения не верная
                String mes = String.Format(
                    "Длина PDU-фрайма равна в запросе 0x10 равна {0} байт. Должна быть не менее 8 байт",
                    request.PDUFrame.ToArray().Length);

                result = new Message.Result(Error.DataFormatError, mes, request, null);
            }
            else
            {
                // Разбираем сообщение
                Byte[] array = new Byte[2];
                // Получаем адрес первого регистра
                Array.Copy(request.PDUFrame.Data, 0, array, 0, 2);
                UInt16 address = Modbus.Convert.ConvertToUInt16(array);
                // Получаем количесво регистров для записи
                Array.Copy(request.PDUFrame.Data, 2, array, 0, 2);
                UInt16 quantity = Modbus.Convert.ConvertToUInt16(array);
                // Получаем количество байт в пасылке
                Byte count = request.PDUFrame.Data[4];

                if ((quantity == 0) || (quantity > 123) || ((quantity * 2) != count))
                {
                    message =
                        String.Format("Количество регистров для записи в запросе равно {0}, а должно быть 1...123",
                        quantity);
                    pdu = new Message.PDU((Byte)(0x10 | 0x80), new Byte[] { 0x03 });
                    answer = new Modbus.OSIModel.Message.Message(_Address, pdu);

                    // Отправляем сообщение
                    SendResponse(answer);

                    result = new Message.Result(Error.IllegalDataValue,
                        message, request, answer);
                }
                else
                {
                    // Выполняем запрос. Проверяем доступность в 
                    // системе регистров в указанном диапазоне адресов
                    for (int i = 0; i < quantity; i++)
                    {
                        // Если регистр не существует в системе формируем ответ
                        // c исключение
                        if (HoldingRegisters.Contains(System.Convert.ToUInt16(address + i)) == false)
                        {
                            // Формируем ответ с исключение 2
                            pdu = new Message.PDU((Byte)(0x10 | 0x80), new Byte[] { 0x02 });
                            answer = new Message.Message(_Address, pdu);
                            message =
                                String.Format("Регистр с адресом {0} не существует",
                                (address + i));
                            result = new Message.Result(Error.IllegalDataAddress,
                                message, request, answer);

                            // Отправляем ответ мастеру
                            SendResponse(answer);
                            return result;
                        }
                    }

                    // Все регистры найдены, устанавливаем новые значения и
                    // формируем ответное сообщение
                    Byte[] temp = new Byte[2];
                    List<Byte> data = new List<byte>();

                    // Устанавливаем новые значения в регистры
                    for (int i = 0; i < quantity; i++)
                    {
                        Array.Copy(request.PDUFrame.Data, (5 + (i * 2)), temp, 0, 2);
                        _HoldingRegisters[System.Convert.ToUInt16(address + i)].Value = 
                            Modbus.Convert.ConvertToUInt16(temp);
                    }

                    // Формируем ответ.
                    temp = Modbus.Convert.ConvertToBytes(address);
                    data.AddRange(temp);
                    temp = Modbus.Convert.ConvertToBytes(quantity);
                    data.AddRange(temp);

                    pdu = new Message.PDU();
                    pdu.Function = 0x10;
                    pdu.AddDataBytesRange(data.ToArray());
                    answer = new Message.Message(_Address, pdu);
                    result = new Message.Result(Error.NoError, String.Empty, request, answer);
                    // Отправляем ответ мастеру
                    SendResponse(answer);
                    // Формируем событие
                    OnMasterChangedHoldingRegisters();
                }
            }
            return result;
        }
Example #13
0
        //---------------------------------------------------------------------------
        Result INetworkFunctions.WriteMultipleCoils(Message.Message request)
        {
            Message.Result result;
            Message.Message answer;
            Message.PDU pdu; 
            String message;


            // Проверяем длину PDU (должна быть не менее 7 байтам)
            if (request.PDUFrame.ToArray().Length < 7)
            {
                // Длина сообщения не верная
                String mes = String.Format(
                    "Длина PDU-фрайма равна в запросе 0x0F равна {0} байт. Должна быть не менее 7 байт",
                    request.PDUFrame.ToArray().Length);

                result = new Message.Result(Error.DataFormatError, mes, request, null);
            }
            else
            {
                // Разбираем сообщение
                Byte[] array = new Byte[2];
                // Получаем адрес первого реле
                Array.Copy(request.PDUFrame.Data, 0, array, 0, 2);
                UInt16 address = Modbus.Convert.ConvertToUInt16(array);
                // Получаем количесво реле для записи
                Array.Copy(request.PDUFrame.Data, 2, array, 0, 2);
                UInt16 quantity = Modbus.Convert.ConvertToUInt16(array);
                // Получаем количество байт в пасылке
                Byte count = request.PDUFrame.Data[4];

                int totalBytes = quantity % 8;

                if (totalBytes == 0)
                {
                    totalBytes = quantity / 8;
                }
                else
                {
                    totalBytes = 1 + (quantity / 8);
                }

                if ((quantity == 0) || (quantity > 0x7B0) || (totalBytes != count))
                {
                    message =
                        String.Format("Количество реле для записи в запросе равно {0}, а должно быть 1...0x7B0",
                        quantity);
                    pdu = new Message.PDU((Byte)(0xF | 0x80), new Byte[] { 0x03 });
                    answer = new Message.Message(_Address, pdu);

                    // Отправляем сообщение
                    SendResponse(answer);

                    result = new Message.Result(Error.IllegalDataValue,
                        message, request, answer);
                }
                else
                {
                    // Выполняем запрос. Проверяем доступность в 
                    // системе регистров в указанном диапазоне адресов
                    for (int i = 0; i < quantity; i++)
                    {
                        // Если регистр не существует в системе формируем ответ
                        // c исключение
                        if (Coils.Contains(System.Convert.ToUInt16(address + i)) == false)
                        {
                            // Формируем ответ с исключение 2
                            pdu = new Message.PDU((Byte)(0x80 | 0x0F), new Byte[] { 0x02 });
                            answer = new Message.Message(Address, pdu);

                            message =
                                String.Format("Реле с адресом {0} не существует",
                                (address + i));
                            result = new Message.Result(Error.IllegalDataAddress,
                                message, request, answer);

                            // Отправляем ответ мастеру
                            SendResponse(answer);
                            return result;
                        }
                    }

                    // Все реле найдены, устанавливаем новые значения и
                    // формируем ответное сообщение
                    Byte status;
                    // Устанавливаем новые значения в реле

                    for (int i = 0; i < count; i++)
                    {
                        status = request.PDUFrame.Data[5 + i];

                        for (int y = 0; y < 8; y++)
                        {
                            totalBytes = i * 8 + y;

                            if (totalBytes < quantity)
                            {
                                if (((status >> y) & 0x01) == 0)
                                {
                                    Coils[System.Convert.ToUInt16(address + totalBytes)].Value = 
                                        Modbus.Convert.ToBoolean(State.Off); 
                                    //rows[totalBytes]["Value"] = Modbus.Convert.ToBoolean(State.Off);
                                }
                                else
                                {
                                    Coils[System.Convert.ToUInt16(address + totalBytes)].Value =
                                        Modbus.Convert.ToBoolean(State.On);
                                    //rows[totalBytes]["Value"] = Modbus.Convert.ToBoolean(State.On);
                                }
                            }
                        }
                    }
                    // Формируем ответ.
                    List<Byte> data_ = new List<byte>();
                    data_.AddRange(Modbus.Convert.ConvertToBytes(address));
                    data_.AddRange(Modbus.Convert.ConvertToBytes(quantity));

                    pdu = new Message.PDU();
                    pdu.Function = 0x0F;
                    pdu.AddDataBytesRange(data_.ToArray());
                    answer = new Message.Message(_Address, pdu);

                    result = new Message.Result(Error.NoError, String.Empty, request, answer);
                    // Отправляем ответ мастеру
                    SendResponse(answer);
                    // Формируем событие
                    OnMasterChangedCoils();
                }
            }
            return result;
        }
Example #14
0
        //---------------------------------------------------------------------------
        Result INetworkFunctions.WriteSingleRegister(Message.Message request)
        {
            Message.Result result;
            Message.Message answer;
            Message.PDU pdu;
            String message;

            // Проверяем длину PDU (должна быть 5 байт)
            if (request.PDUFrame.ToArray().Length != 5)
            {
                // Длина сообщения не верная
                String mes = String.Format(
                    "Длина PDU-фрайма равна в запросе 0x06 равна {0} байт. Должна быть 5 байт",
                    request.PDUFrame.ToArray().Length);

                result = new Message.Result(Error.DataFormatError, mes, request, null);
            }
            else
            {
                // Разбираем сообщение
                Byte[] array = new Byte[2];
                // Получаем адрес регистра
                Array.Copy(request.PDUFrame.Data, 0, array, 0, 2);
                UInt16 address = Modbus.Convert.ConvertToUInt16(array);
                // Получаем значение регистра
                Array.Copy(request.PDUFrame.Data, 2, array, 0, 2);
                UInt16 value = Modbus.Convert.ConvertToUInt16(array);

                // Выполняем запрос. Проверяем доступность в 
                // регистра 
                if (_HoldingRegisters.Contains(address) == false)
                {
                    // Если регистр не существует в системе формируем ответ
                    // c исключение
                    // Формируем ответ с исключение 2
                    pdu = new Message.PDU((Byte)(0x06 | 0x80), new Byte[] { 0x02 });
                    answer = new Message.Message(_Address, pdu);

                    message =
                        String.Format("Регистр с адресом {0} не существует", address);
                    
                    result = new Message.Result(Error.IllegalDataAddress,
                        message, request, answer);

                    // Отправляем ответ мастеру
                    SendResponse(answer);

                    return result;
                }
                else
                {
                    // Все регистры найдены, устанавливаем новые значения и
                    // формируем ответное сообщение
                    _HoldingRegisters[address].Value = value;

                    // Формируем ответ.
                    pdu = new Message.PDU();
                    pdu.Function = 0x06;
                    pdu.AddDataBytesRange(Modbus.Convert.ConvertToBytes(address));
                    pdu.AddDataBytesRange(Modbus.Convert.ConvertToBytes(value));
                    answer = new Modbus.OSIModel.Message.Message(_Address, pdu);

                    result = new Message.Result(Error.NoError, String.Empty, request, answer);
                    // Отправляем ответ мастеру
                    SendResponse(answer);
                    // Формируем событие
                    OnMasterChangedHoldingRegisters();
                }
            }
            return result;
        }
Example #15
0
        //---------------------------------------------------------------------------
        Result INetworkFunctions.WriteSingleCoil(Message.Message request)
        {
            Message.Result result;
            Message.Message answer;
            Message.PDU pdu;
            String message;

            // Проверяем длину PDU (должна быть 5 байт)
            if (request.PDUFrame.ToArray().Length != 5)
            {
                // Длина сообщения не верная
                String mes = String.Format(
                    "Длина PDU-фрайма равна в запросе 0x05 равна {0} байт. Должна быть 5 байт",
                    request.PDUFrame.ToArray().Length);

                result = new Message.Result(Error.DataFormatError, mes, request, null);
            }
            else
            {
                // Разбираем сообщение
                Byte[] array = new Byte[2];
                // Получаем адрес реле
                Array.Copy(request.PDUFrame.Data, 0, array, 0, 2);
                UInt16 address = Modbus.Convert.ConvertToUInt16(array);
                // Получаем значение реле для записи
                Array.Copy(request.PDUFrame.Data, 2, array, 0, 2);
                UInt16 status = Modbus.Convert.ConvertToUInt16(array);
                State coilValue;
                // Получаем количество байт в пасылке
                switch (status)
                {
                    case 0x0000:
                        {
                            coilValue = State.Off;
                            break;
                        }
                    case 0xFF00:
                        {
                            coilValue = State.On;
                            break;
                        }
                    default:
                        {
                            // Ошибка
                            message =
                                String.Format(
                                "Неверный формат данных для кодировки состояния реле {0}, а должно быть 0x0000 или 0xFF00",
                                status.ToString("X4"));
                            pdu = new Message.PDU((Byte)(0x05 | 0x80), new Byte[] { 0x03 });
                            answer = new Modbus.OSIModel.Message.Message(_Address, pdu);
                            // Отправляем сообщение
                            SendResponse(answer);

                            result = new Message.Result(Error.IllegalDataValue,
                                message, request, answer);
                            return result;
                        }
                }

                // Выполняем запрос. Проверяем доступность в 
                // системе регистров в указанном диапазоне адресов

                // Если регистр не существует в системе формируем ответ
                // c исключение
                if (Coils.Contains(address) == false)
                {
                    // Формируем ответ с исключение 2
                    pdu = new Message.PDU((Byte)(0x80 | 0x05), new Byte[] { 0x02 });
                    answer = new Modbus.OSIModel.Message.Message(_Address, pdu);
                    message =
                        String.Format("Реле с адресом {0} не существует",
                            address);
                    result = new Message.Result(Error.IllegalDataAddress,
                        message, request, answer);

                    // Отправляем ответ мастеру
                    SendResponse(answer);
                    return result;
                }
                else
                {
                    // Реле найдено, устанавливаем новое значение и
                    // формируем ответное сообщение
                    Coils[address].Value = Modbus.Convert.ToBoolean(coilValue);

                    // Формируем ответ.
                    List<Byte> data_ = new List<byte>();
                    data_.AddRange(Modbus.Convert.ConvertToBytes(address));
                    data_.AddRange(Modbus.Convert.StateToArray(coilValue));

                    pdu = new Message.PDU();
                    pdu.Function = 0x05;
                    pdu.AddDataBytesRange(data_.ToArray());
                    answer = new Message.Message(_Address, pdu);

                    result = new Message.Result(Error.NoError, String.Empty, request, answer);
                    // Отправляем ответ мастеру
                    SendResponse(answer);
                    // Формируем событие
                    OnMasterChangedCoils();
                }
            }
            return result;
        }