HOME > ソフテックだより > 第303号(2018年4月4日発行) 技術レポート「BACnet通信プロトコルの開発 ASN.1」

「ソフテックだより」では、ソフトウェア開発に関する情報や開発現場における社員の取り組みなどを定期的にお知らせしています。
さまざまなテーマを取り上げていますので、他のソフテックだよりも、ぜひご覧下さい。

ソフテックだより(発行日順)のページへ
ソフテックだより 技術レポート(技術分野別)のページへ
ソフテックだより 現場の声(シーン別)のページへ


ソフテックだより 第303号(2018年4月4日発行)
技術レポート

「BACnet通信プロトコルの開発 ASN.1」

1. はじめに

私はソフテックに中途で入社してから7年目になる中堅社員になります。ソフテックに入社してから様々な通信プロトコルの開発に携わりました。そのうちの一つにBACnetがあります。ソフテックだより第239号 「BACnetを利用した組み込みシステム開発」では、BACnetの概要およびBACnetシステムの実装例について紹介しました。
今回のソフテックだよりではBACnet通信プロトコルを実装する上で把握しておく必要のあるBACnet通信プロトコルの電文構成および通信電文の表記方法であるAbstract Syntax Notation One(ASN.1)について紹介します。

2. BACnet通信電文の開発

2.1 通信プロトコルの表記

通信プロトコルを開発する場合、通信仕様書に記載された通信電文フォーマットに則り開発を行います。私が今まで開発した通信プロトコルの場合、ソフテックだより第133号 「PLCでModbus通信 〜横河電機社製での実装例〜」ソフテックだより第159号 「LinuxOSでのDNP3.0通信開発」に記載されている通り、メッセージ形式が図で示されており、データフィールド(通信プロトコルを構成する要素)はバイト単位(オクテット単位)で記載されていました。
ただ、BACnetの場合は図で示されているのではなく、ASN.1という表記方法で表現されていました。ASN.1は図で示すのではなく、プログラムの構造体のような表記方法での記載となります。

2.2 ASN.1について

ASN.1はマシン固有の表現方法に依存せず、曖昧さのない記述を可能とする形式規則を提供します。ASN.1では抽象構文(注1)で通信電文を定義し、符号化規則に則り、データのエンコード(符号化)、デコード(複合化)を行います。
今回のソフテックだよりでは、ASN.1での表記内容を元に、Binary-Inputのインスタンス番号1025の現在値(注2)を取得する電文(PDU(注3))の作成例を紹介します。ただし、説明の簡略化のため、実際のBACnet仕様書に記載されている内容と異なります。

(注1)
抽象構文とはデータの表現形式になります。対義語の具象構文は例えばC言語でのソースコードでの実装形式になります。
(注2)
各用語は第239号 「BACnetを利用した組み込みシステム開発」にて紹介していますので、そちらを参照願います。
(注3)
PDU(Protocol Data Unit)はOSI参照モデルにおけるデータの単位の総称になります。例えばTCP/IPにおけるPDUはパケットになります。

2.3 ASN.1での通信電文表記方法

ASN.1での通信電文表記方法を紹介します。
ASN.1の基本的な表記方法は以下になります。

名前 :== 型名 {
       要素1
       要素2
       ・・・
}

また、今回の例の電文は以下の構成になります。

binary-input, 1025, present-value 取得電文構成
図1. binary-input, 1025, present-value 取得電文構成

以下にBACnet電文の符号化を行う上での基本的な流れおよびASN.1での定義を示します。
括弧の番号はASN.1定義の括弧の番号に対応します。

BACnet電文符号化の流れ
図2. BACnet電文符号化の流れ

(1) PDU定義の選択 (PDU-Type)

BACnet電文をどのPDUの種類で作成するかを選択する定義になります。

PDU-Type :== CHOICE {
      confirmed-request-PDU      	[0] Confirmed-Request-PDU
    					     - (2) PDU構成要素の定義に対応します。
      unconfirmed-request-PDU		[1] Unconfirmed-Request-PDU
}
(2) PDU定義 (Confirmed-Request-PDU)

PDU構成要素の定義になります。

Confirmed-Request-PDU :== SEQUECNE {
      pdu-type				[0] 符号無し整数(0,,15)
					     - このPDU型の場合0にする
      service-choice			[1] ConfirmedService
					     - (3) サービスの選択に対応します。
      service-request			[2] Confirmed-Service-Request
					     - (4) サービス定義の選択に対応します。

}
※pdu-type, service-choiceは1オクテット
※service-requestは符号化された値
(3) サービスの選択 (ConfirmedService)

サービスに対応する値の定義になります。

ConfirmedService :== CHOICE {
      confirmedCOVNotification 		(1),
      confirmedEventNotification	(2),
      readProperty			(12),
}
(4) サービス定義の選択 (Confirmed-Service-Request)
Confirmed-Service-Request :== CHOICE {
      confirmedCOVNotification		[1] ConfirmedCOVNotification-Request
      confirmedEventNotification	[2] ConfirmedEventNotification-Request
			・・・・・・・・・・
      readProperty			[12] ReadProperty-Request
					     - (5) サービス定義に対応します。
}
(5) サービス定義 (ReadProperty-Request)

roperty情報を取得するためのサービスであるReadProperty-Requestの構成要素の定義になります。

ReadProperty-Request :== SEQUENCE {
      objectId				[0] ObjectId
					     - (6) アプリケーションタイプの定義に対応します。
      propertyId			[1] PropertyId
					     - (7) アプリケーションタイプの定義に対応します。
}
(6) アプリケーションタイプの定義

BACnetで使用する型の定義になります。

-- NULL					[APPLICATION 0]と等価
-- INTEGER(符号付き整数)		[APPLICATION 1]と等価
-- ENUMURATED				[APPLICATION 9]と等価
-- ObjcetId				[APPLICATION 12] オクテット列
・APPLICATION 12 (ObjectId)
APPLICATION 12はデータ構成が特殊ですので、以下に構成を紹介します。

APPLICATION 12 (ObjectId)
図3. APPLICATION 12 (ObjectId)

※ObjectTypeは(7) 基本型の定義のObjectTypeに対応します。

(7) 基本型の定義

BACnetで使用する型の定義になります。

PropertyId :== ENUMERATED {
      present-value			(85),
      status-flags			(111),
}
ObjectType :== ENUMERATED{
      binary-input			(3),
}

2.4 符号化

各構成要素はタグと呼ぶ単位で符号化します。タグは要素の先頭、および条件によって、要素の後尾にも使用します。タグは以下のように定義されています。

タグ構成
図4. タグ構成

Tag Number = タグが属するクラスにおけるタグ番号
Class = タグのクラス(アプリケーションまたはコンテクスト規定)

0 : アプリケーションタグ
1 : コンテクスト規定タグ
Length/Value/Type =
タグに続くデータが基本要素データか構造体データか、長さまたは基本要素データの値のいずれか
Tag NumberおよびClassによって格納される種類が決まる
2.4.1 ReadProperty-Requestの符号化例

以下に、ReadProperty-Requestの符号化例を紹介します。

ReadProperty-Request符号化の流れ
図5. ReadProperty-Request符号化の流れ

2.4.2 復号化

電文が符号化されて通知されるため、解析のために復号化を行います。
復号化は符号化の逆の手順を行います。

ReadProperty-Request復号化の流れ
図6. ReadProperty-Request復号化の流れ

3. おわりに

BACnet電文の表記に使用しているASN.1ですが、以下のメリットデメリットがあると感じました。

メリット

  1. 電文内容を検討する際、各種要素を検討しておけば、サイズによる依存を検討する必要がなくなる。
  2. 電文を作成するプログラムを作る時、記載された内容に従って作成しやすい。
  3. 大量のパターンの電文を表現するとき、手間が少ない。

デメリット

  1. 電文と仕様書でデータを解析しようとすると、かなり大変。解析するには解析プログラムを用いないと、理解しにくい。
  2. プロトコルとしてのパラメータが少ないと符号化、復号化する手順を実装するのにかなり手間がかかる。

BACnetはサービスやパラメータが多く、また、サイズもかなり自由なプロトコルになります。そのため、ASN.1の表記方法がマッチしていると感じます。 ただ、Modbusのような単純なプロトコルをASN.1で表記した場合、無駄に難易度が高くなり、採用されにくくなるように感じます。
そのため、ただ単に表現しやすいから、拡張性をしやすいからという理由で選択するのではなく、本当にそれに合った方法を採用するのが良い選択になるのだと感じました。

最後までお読みいただきありがとうございました。

(S.O.)

[参考]
BACnet(ASHRAE SSPC 135 )公式サイト http://www.bacnet.org/


関連ページへのリンク

関連するソフテックだより

ページTOPへ