НовостиСИГМА-группа компанийНаукаПроизводствоСтатьи и публикацииСертификатыЛицензииНаградыОтзывыКонтактыЦентральный офисСеверо-ЗападВакансииЛоготипы
| |
BACnet – путь к интеграции систем безопасности в общую систему управления зданием. Часть 6
Сергей ЛЁВИН,
главный конструктор СИГМА–ИС
Протокол BACnet Data Unit
В этой статье рассматривается основной протокол передачи данных BACnet. Прикладной уровень этого протокола (APDU – Application Layer Protocol Data Units) используется в BACnet для передачи информации, содержащейся в службах приложений и их параметрах.
Стандарт ISO 8824, спецификация нотации абстрактного синтаксиса ASN.1, был выбран как метод для представления данных в службах BACnet. ASN.1 предоставляет абстрактный синтаксис. Тем не менее, точный побитовый формат APDU может иметь несколько форм, в зависимости от выбранных правил кодирования или представления данных в пакете. Внутри модели OSI (модель взаимодействия открытых систем) правила формирования данных для передачи выбираются на уровне представления. Причем определяются не только базовые правила кодирования данных, но также и будут ли данные подвергаться дополнительным манипуляциям, таким как компрессия, шифрование и т.д. Так как BACnet использует упрощенную модель OSI, которая не предоставляет никакой функциональности уровня представления, правила формирования ADPU должны быть определены самими коммуникационными устройствами. Правила кодирования данных в BACnet были разработаны в соответствии с требованиями систем автоматизации и управления зданиями к простоте и компактности. В принципе, службы и процедуры BACnet могут быть использованы в будущем в полностью в OSI-совместимой сети путем добавления поддержки уровня представления.
Кодирование согласно ASN.1, определенное в ISO 8825 (спецификация базовых правил кодирования) применяется ко всем элементам пакета PDU. Каждый элемент данных представляется тремя компонентами: идентификатор, длина, и собственно данные. Явная идентификация каждого элемента данных позволяет разрабатывать парсеры, которые могут декодировать любой пакет без знания формата или семантики контента. Альтернатива явному описанию каждого элемента данных является общее соглашение о формате и размещении данных внутри пакета. Первый подход более общий, но и более затратный, второй – более эффективный по затратам, но и более строгий в реализации. Вариант выбранный в BACnet является компромиссным. Фиксированные части пакета содержат управляющие данные протокола и их формат подразумевается, что известен, то есть в самом пакете данных о формате не содержится. Переменная часть пакета содержит контекстно-зависимую информацию и явно описана в PDU. В результате значительно снижаются затраты на описание предопределенных данных и в то же время имеется возможность добавления данных новых служб в пакет.
Фиксированная часть пакета APDU
BACnet APDU содержит управляющую информацию протокола и также некоторые пользовательские данные. Блок PCI (Protocol Control Information) содержит данные, необходимые для работы протокола прикладного уровня и включает в себя тип APDU, информацию в соответствии с запросами и ответами служб, данные для сборки сегментированных сообщений. Эта информация содержится в заголовке пакета, фиксированной части APDU. Пользовательские данные содержат информацию, специфичную для индивидуальных запросов и ответов служб и относятся к переменной части APDU. Так как каждый пакет APDU содержит поля PCI, BACnet упаковывает эти данные без использования тегов или длины данных, несмотря на то, что ASN.1 формально требует наличие тегов в синтаксическом описании всех полей. Теги используются для описания переменного контента пользовательских данных. Таким выборочным использованием тегов достигается уменьшение размера пакета.
В качестве примера рассмотрим формат заголовка пакета запроса с подтверждением.
BACnet-Confirmed-Request-PDU ::= SEQUENCE {
pdu-type [0] Unsigned(0..15) – 0 для этого типа PDU
segmented-message [1] BOOLEAN
more-follows [2] BOOLEAN
segment-response-accepted [3] BOOLEAN
reserved [4] Unsigned (0..3) – должно быть равно 0
max-segment-accepted [5] Unsigned (0..7)
max-APDU-length-accepted [6] Unsigned (0..15)
invokeID [7] Unsigned (0..255)
sequence-number [8] Unsigned (0..255) – только если сообщение
сегментировано
proposed-window-size [9] Unsigned (0..127) – только если сообщение
сегментировано
service-choice [10] BACnetConfirmedServiceChoice
service-request [11] BACnetConfirmedServiceRequest
}
Описание полей заголовка
Поле |
Описание |
pdu-type |
Тип пакета |
segmented-message |
Этот параметр указывает, содержится ли запрос полностью в этом пакете, или только часть запроса. Если запрос представлен полностью, значение устанавливается равным FALSE. Если данный пакет содержит только фрагмент запроса, параметр будет равен TRUE. |
more-follows |
Этот параметр имеет значение, только если segmented-message = TRUE. В этом случае данный параметр устанавливается в TRUE для всех сегментов данного запроса, за исключением последнего и равен FALSE для финального сегмента запроса. Если segmented-message = FALSE, тогда more-follows устанавливается энкодером пакетов в FALSE и игнорируется декодером. |
segmented-response-accepted |
Этот параметр равен TRUE, если устройство формирующее запрос готово принять сегментированное составное сообщение в качестве ответа, иначе устанавливается значение FALSE. Считав значение этого параметра, отвечающее устройство может определить как формировать ответ. |
max-segment-accepted |
Этот опциональный параметр определяет максимальное количество сегментов, которое устройство может принять. |
max-APDU-length-accepted |
Параметр определяет максимальный размер одного пакета, который устройство может принять. |
invokeID |
Этот параметр может принимать целые значения в диапазоне 0 – 255. Используется для связывания ответа с запросом. Параметр формируется устройством, выполняющим запрос. Значение должно быть уникальным для всех исходящих запросов от данного устройства. Одно и тоже значение должно быть во всех сегментах составного запроса. Когда invokeID связывается с пакетом, это значение задействуется в устройстве, пока не будет получен ответ с тем же значением invokeID, либо пока не наступит таймаут ожидания ответа. После этого данное значение освобождается для повторного использования. |
sequence-number |
Опциональный параметр, который используется только в сегментированных сообщениях. В этом случае, sequence-number последовательно инкрементируемое целое значение по модулю 256, которое идентифицирует каждый сегмент в составном запросе. Значение используется отвечающим устройством для подтверждения приема одного или более сегментов запроса. Значение параметра для первого сегмента составного запроса должно быть равно 0. |
proposed-window-size |
Опциональный параметр, который используется только в сегментированных сообщениях. В этом случае параметр обозначает значение максимального количества сегментов, которые отправитель способен и может послать. |
service-choice |
Этот параметр значение службы BACnetConfirmedServiceChoice (будет описано позднее). |
service-request |
Дополнительные сервисные параметры. |
В ответ принимающее устройство может сформировать два типа сообщения: простое подтверждение приема запроса BACnet-SimpleACK-PDU, если кроме подтверждения никаких данных отправлять не нужно. Или BACnet-ComplexACK-PDU, если в ответ передаются какие-либо данные.
Структура простого ответа:
BACnet-SimpleACK-PDU ::= SEQUENCE {
pdu-type [0] Unsigned(0..15) – 2 для этого типа PDU
reserved [1] Unsigned (0..15) – должно быть равно 0
original-invokeID [2] Unsigned (0..255)
service-ACK-choice [3] BACnetConfirmedServiceChoice
}
Описание полей заголовка
Поле |
Описание |
pdu-type |
Тип пакета |
original-invokeID |
Содержит значение invokeID, полученное в запросе. |
service-choice |
также повторяет значение соответствующего поля запроса. |
Структура ответа с дополнительными данными
BACnet-ComplexACK-PDU ::= SEQUENCE {
pdu-type [0] Unsigned(0..15) – 3 для этого типа PDU
segmented-message [1] BOOLEAN
more-follows [2] BOOLEAN
reserved [3] Unsigned (0..3) – должно быть равно 0
original-invokeID [4] Unsigned (0..255)
sequence-number [5] Unsigned (0..255) – только если сообщение
сегментировано
proposed-window-size [6] Unsigned (0..127) – только если сообщение
сегментировано
service-ACK-choice [7] BACnetConfirmedServiceChoice
service-ACK [8] BACnet-Confirmed-Service-ACK
}
Описание полей заголовка
Поле |
Описание |
pdu-type |
Тип пакета |
segmented-message |
Этот параметр указывает, содержится ли ответ полностью в этом пакете, или только часть ответа. Если ответ представлен полностью, значение устанавливается равным FALSE. Если данный пакет содержит только фрагмент ответа, параметр будет равен TRUE. |
more-follows |
Этот параметр имеет значение, только если segmented-message = TRUE. В этом случае данный параметр устанавливается в TRUE для всех сегментов данного ответа, за исключением последнего и равен FALSE для финального сегмента ответа. Если segmented-message = FALSE, тогда more-follows устанавливается энкодером пакетов в FALSE и игнорируется декодером. |
original-invokeID |
Содержит значение invokeID, полученное в запросе. Одно и тоже значение должно быть во всех сегментах составного ответа. |
sequence-number |
Опциональный параметр, который используется только в сегментированных сообщениях. В этом случае, sequence-number последовательно инкрементируемое целое значение по модулю 256, которое идентифицирует каждый сегмент в составном ответе. Значение используется запрашивающим устройством для подтверждения приема одного или более сегментов ответа. Значение параметра для первого сегмента составного ответа должно быть равно 0. |
proposed-window-size |
Опциональный параметр, который используется только в сегментированных сообщениях. В этом случае параметр обозначает значение максимального количества сегментов, которые могут быть в ответе. |
service-ACK-choice |
Этот параметр значение службы BACnetConfirmedServiceChoice (будет описано позднее). |
service-ACK |
Дополнительные сервисные параметры. |
Когда принимающее устройство принимает сегмент составного запроса, то на каждый принятый сегмент формируется подтверждение BACnet-SegmentACK-PDU. Это сообщение также служит запросом на принятие следующего сегмента.
BACnet-SegmentACK-PDU ::= SEQUENCE {
pdu-type [0] Unsigned(0..15) – 4 для этого типа PDU
reserved [1] Unsigned (0..3) – должно быть равно 0
negative-ACK [2] BOOLEAN
server [3] BOOLEAN
original-invokeID [4] Unsigned (0..255)
sequence-number [5] Unsigned (0..255)
actual-window-size [6] Unsigned (0..127)
}
Описание полей заголовка
Поле |
Описание |
pdu-type |
Тип пакета |
negative-ack |
Этот параметр устанавливается в TRUE, если сегмент принят в неправильном порядке, то есть имеются пропущенные сегменты. Иначе значение будет FALSE. |
server |
Этот параметр устанавливается в TRUE, если подтверждение отправляется сервером. То есть это подтверждение приема сегмента составного ответа. |
original-invokeID |
Содержит значение invokeID, полученное в запросе. |
sequence-number |
Этот параметр содержит значение sequence-number, принятое в предыдущем сегменте. |
actual-window-size |
Определяет количество сегментов сообщения, содержащих original-invokeID, которые отправитель будет принимать перед отправкой другого SegmentACK. |
service-ACK-choice |
Этот параметр значение службы BACnetConfirmedServiceChoice (будет описано позднее). |
service-ACK |
Дополнительные сервисные параметры. |
В случае каких-либо ошибок при разборе принятого пакета устройство отправляет уведомление об ошибке BACnet-Error-PDU.
BACnet-Error-PDU ::= SEQUENCE {
pdu-type [0] Unsigned (0..15) – 5 для этого типа PDU
reserved [1] Unsigned (0..15) – должно быть равно 0
original-invokeID [2] Unsigned (0..255)
error-choice [3] BACnetConfirmedServiceChoice
error [4] BACnet-Error
}
Описание полей заголовка
Поле |
Описание |
pdu-type |
Тип пакета |
original-invokeID |
Содержит значение invokeID, полученное в запросе. |
error-choice |
Содержит значение тег значения BACnet-Error |
error |
Содержит код ошибки |
Устройство также может отклонить принятое сообщение в случае каких-либо синтаксических ошибок или других ошибок протокола. Только сообщения с подтверждением могут быть отклонены.
BACnet-Reject-PDU ::= SEQUENCE {
pdu-type [0] Unsigned (0..15) – 6 для этого типа PDU
reserved [1] Unsigned (0..15) – должно быть равно 0
original-invokeID [2] Unsigned (0..255)
reject-reason [3] BACnetRejectReason
}
Описание полей заголовка
Поле |
Описание |
pdu-type |
Тип пакета |
original-invokeID |
Содержит значение invokeID, полученное в запросе. |
reject-reason |
Содержит причину отклонения сообщения. |
Для прерывания передачи текущего сообщения служит команда BACnet-Abort-PDU.
BACnet-Abort-PDU ::= SEQUENCE {
pdu-type [0] Unsigned (0..15) – 7 для этого типа PDU
reserved [1] Unsigned (0..15) – должно быть равно 0
server [2] BOOLEAN
original-invokeID [3] Unsigned (0..255)
abort-reason [4] BACnetAbortReason
}
Описание полей заголовка
Поле |
Описание |
pdu-type |
Тип пакета |
server |
Этот параметр устанавливается в TRUE, если это сообщение отправляется сервером. |
original-invokeID |
Содержит значение invokeID, полученное в запросе. |
break-reason |
Содержит причину прекращения передачи сообщения. |
Переменная часть пакета APDU
Мы рассмотрели формат фиксированного заголовка пакета. Теперь вкратце о полезной нагрузке сообщения (BACnetConfirmedServiceChoice) или сервисных параметрах. Все элементы данных параметров называются тегами. Каждый тег обозначает уникальный параметр или подпараметр. BACnet использует два класса тегов. Первый определяет фундаментальный тип данных используемых и определенных в BACnet, такие как BOOLEAN, Unsigned, CharacterString, Date, Time или BACnetObjectIdentifier. Второй класс тегов используется для идентификации элементов данных, которые могут зависеть от контекста, в котором они используются. Такие теги называются контекстно-зависимыми. В некоторых случаях тип данных параметра не может быть ясен из контекста, где он используется. Тогда может потребоваться применение и контекстно-зависимых и предопределенных тегов. В этой ситуации по спецификации ASN.1 используются так называемые сервисные параметры, в которых типы данных индицируются ключевыми словами ABSTRACT-SYNTAX, CHOICE, SEQUENCE или SEQUENCE OF.
Теги BACnet описываются начальным байтом и, возможно, дополнительными последующими байтами. Начальный байт или октет определен следующим образом:
Начальный октет тега
Биты |
Поле |
Описание |
7-4 |
Номер тега |
Номер тега внутри класса |
3 |
Класс |
Класс тега (зависит от приложения или контекста). 0 – для предопределенных тегов, 1 – для контекстно-зависимых тегов. |
2-0 |
Длина/значение/тип |
В зависимости от данных тега определяет длину, значение или тип данных. |
В следующих байтах тега помещаются непосредственно данные, специфичные для класса и типа тега. Таким образом, в BACnet предоставляется возможность определить и передать в стандартном сообщении данные практически любого типа.
Продолжение следует.
Архив публикаций