<!-- markdownlint-disable MD013--> # 認識 DNP3 通訊協定 - 應用層 在認識 Application Layer 前,建議讀者先瞭解 DNP3 的資料傳遞流程。 可以參考此篇:[認識 DNP3 通訊協定 - 概述](https://hackmd.io/@newt/dnp3-overview) ## 關鍵術語 ### 點(Point) 在 DNP3 中,`點(Point)` 用於識別物理或邏輯實體。 Point 與特定的測量訊號或計算的模擬量有關: * 輸入訊號 * 類比 * 數位 * 計數器 * 輸出訊號 * 類比 * 數位 此外,Point 除了值還會具有其他的 `屬性(Attribute)`。 `Point Type(點類型)` 是對於具有相關特徵、相似功能以及與物理硬體或邏輯空間相關的 Point 進行分類的方法。 每個 Point Type 都是獨立的陣列,透過索引來識別每個 Point。 > **以 Analog Input 為例:** > > * 單一個 Analog Input 就算是一個 Point。 > * 除了測量值以外,還可以具有名稱、比例因子、事件偵測的死區值和其他 Attribute。 > * Analog Input 屬於 Analog Input Point Type。 ### 索引(Index) DNP3 將 `索引(Index)` 用於識別 Point Type 陣列中的 Point,其最低值為 0。 > **以下圖為例:** > >  > > * 這是一個具有可傳輸五種 Point Type 的 DNP3 Outstation。 > * Analog Input Point Type 有五個 Analog Input Point。 > * 透過Index 編號 0 ~ 4 來識別這五個 Point。 ### 群組(Group) `群組(Group)` 用於分類訊息中的資料類型。 每個 Group 編號共享同一種 Point Type 以及資料產生或建立的方法,也可用於指定報告時間值、檔案傳輸以及設備資訊等所需的資料類型。 > **以 Analog Input 為例:** > > * Group 30 用於報告 Analog Input 當前值。 > * Group 31 用於報告 Analog Input 凍結值。 > * Group 32 用於報告 Analog Input 當前值變更的 Event。 > * Group 33 用於報告 Analog Input 凍結值變更的 Event。 設備並非支援所有 Group,而是依照供應商的系統設計而定。 ### 變體(Variation) DNP3 為許多資料類型提供了多種資料格式的選擇,這些資料格式稱為 `變體(Variation)`。 每個 Group 編號都有一組獨立的 Variation。 > **以 Group 30 為例:** > > * Variation 1 為帶有標誌 32-bit 的整數值 > * Variation 2 為帶有標誌 16-bit 的整數值 > * Variation 3 為無標誌 32-bit 的整數值 > * Variation 4 為無標誌 16-bit 的整數值 > * Variation 5 為帶有標誌 32-bit 的浮點數值 > * Variation 6 為帶有標誌 16-bit 的浮點數值 `標誌(Flag)` 用於表示當前的設備在線狀況、設備是否已重啟或值已超出測量範圍等補充內容或是條件。 * Object 通用 Flag(值為 Bool) * ONLINE * RESTART * COMM_LOST * REMOTE_FORCED * LOCAL_FORCED ### DNP3 物件(DNP3 Object) `DNP3 物件(DNP3 Object)` 由 Point 或其他結構的資料,進行編碼後所取得。 DNP3 Object 會根據其 Group 編號和 Variation 編號進行格式化以便資料透過訊息傳輸。 訊息中可以包含多個 Object,每個 Object 代表 Point 的當前值或是向 Point 發送的命令。 ### 靜態(Static) `靜態(Static)` 表示 Point 的當前值。 DNP3 允許透過 Request 來取得全部或部分 Static 的資料。 ### 事件(Event) `事件(Event)` 與有意義的事情發生有關。 有些 DNP3 Object 會稱其為 Event Object,這只是 Event 的表示方法,並非在 Outstation 中儲存的實際數據。 只有在 Event 資訊傳遞到 Master(在 DNP3 Object 中), 並且 Outstation 有接收到來自 Master 回傳 "確認收到 Event" 的 `確認(Confirmation)` 後, Event 才會從 Outstation 的 `事件緩衝區(Event Buffer)` 中刪除。 > **以 Analog Input 為例:** > > * 狀態的變化。 > * 當前值的變化超過死區值。 > * 特定時間所取得的數據快照。 > * 等等... DNP3 並沒有定義 Event Buffer 的數量、結構、資料組織以及內容,而是依照供應商的系統設計而定。 ### 類別(Class) DNP3 透過 `類別(Class)` 來將 Static 跟 Event 進行分類: * Class 0 - Static Data * Class 1, 2, 3 - Event Data 大多數資料類型的 Point 可以分配到其中一種 Class。 如果某個 Point 是被分配到 Class 0, 當 Master 向 Outstation 作 Class 0 `輪詢(Poll)` 時,必須回傳該 Point 的當前值(Event 不會被記錄或回傳)。 如果某個 Point 是被分配到 Class 1、Class 2 或 Class 3, 那麼 Outstation 則必須記錄該 Point 所發生的 Event,並在 Class 0 Poll 時回覆其當前值。 如果某個 Point 完全沒有被分配到任何 Class, 那麼 Outstation 則不會記錄該 Point 所發生的 Event,也不會在 Class 0 Poll 時回覆其當前值。 不過,當 Master 對該 Point 實施 Static Poll,Outstation 仍然必須回傳該 Point 的當前值。 不同的 Poll 對上不同的 Class,其運作如下表: ||無分配|Class 0|Class 1|Class 2|Class 3| |-|:-:|:-:|:-:|:-:|:-:| |**Static Poll**|✓|✓|✓|✓|✓| |**Class 0 Poll**||✓|✓|✓|✓| |**Class 1 Poll**|||✓||| |**Class 2 Poll**||||✓|| |**Class 3 Poll**|||||✓| ## 訊息結構 Application Layer 的 `片段(Fragment)` 包含在 Request 或 Response 的訊息中,結構如下表: |Application Header|First Object Header|DNP3 Object|...|Last Object Header|DNP3 Object| |-|-|-|-|-|-| 每個 Fragment 都以包含控制資訊的 `應用標頭(Application Header)` 開始,無論它們出現在單一還是多個 Fragment 訊息中。 然而,通常單獨的 Application Header 不足以傳遞完整的訊息。 因此在 Application Header 後面會加上一或多組的 `物件標頭(Object Header)` 及 DNP3 Object 來形成完整訊息所需的附加資訊。 ## Application Header 由 `應用控制(Application Control)` 跟 `功能碼(Function Code)` 組成。 不過 Response 的 Application Header 多了 `內部指示(Internal Indication, IIN)`。 * Application **Request** Header 的結構如下表: |Application Control|Function Code| |:-:|:-:| |1 octet|1 octet| * Application **Response** Header 的結構如下表: |Application Control|Function Code|IIN| |:-:|:-:|:-:| |1 octet|1 octet|2 octets| ### Application Control Application Control 的訊息大小為 1 個 Octet。 提供建構跟重組多個 Fragment 訊息所需的參數,並且指示接收方的 Application Layer 是否必須回覆 Confirmation 及協助檢測重複的訊息。 Application Control 由 FIR、FIN、CON、UNS 跟 SEQ 五種參數組成,其結構如下:  * **FIR - 1 bit** * FIR = 0 表示這不是訊息中的第一個 Fragment * FIR = 1 表示這是訊息中的第一個 Fragment * **FIN - 1 bit** * FIN = 0 表示後面還有其他的 Fragment * FIN = 1 表示這是訊息中的最後一個 Fragment * **CON - 1 bit** * CON = 0 表示接收端不回覆 Confirmation * CON = 1 表示接收端必須回覆 Confirmation * **UNS - 1 bit** * UNS = 0 表示這是 Response 的 Fragment * UNS = 1 表示這是 Unsolicited Response 的 Fragment * **SEQ - 4 bits** 用於驗證 Fragment 是否以正確的順序接收,並檢查是否重複。 值的範圍為 0 ~ 15,並以 1 為單位遞增。值為 15 後,下一個值為 0。 Response 跟 Unsolicited Response 的 SEQ 值,兩者獨立互不相關。 ### Function Code Function Code 的訊息大小為 1 個 Octet。 用於識別 Fragment 訊息的目的。 * Request 訊息所使用的 Function Code 範圍為 0x01 ~ 0x80 * Response 訊息所使用的 Function Code 範圍為 0x81 ~ 0xFF * Confirmation 訊息所使用的 Function Code 為 0x00。 Function Code 的種類較多,因此將簡易說明放到這篇:[DNP3 - Function Code](https://hackmd.io/@newt/dnp3-function_code) ### IIN IIN 的訊息大小為 2 個 Octet。 透過特定位元來表示 Outstation 內的某些狀態或是錯誤,其結構如下:  DNP3 透過代碼的方式來指定特定位元:IIN x.y。 * x 表示第一個或是第二個 Octet * y 則是表示 bit 的索引編號 關於 Internal Indication 的簡易說明如下表: | 代碼 | 名稱 | 簡要說明 | |:------- | --------------------- |:-------------------------------------------- | | IIN 1.0 | ALL_STATIONS | 收到廣播訊息 | | IIN 1.1 | CLASS_1_EVENTS | Outstation 有未報告的 Class 1 Event | | IIN 1.2 | CLASS_2_EVENTS | Outstation 有未報告的 Class 2 Event | | IIN 1.3 | CLASS_3_EVENTS | Outstation 有未報告的 Class 3 Event | | IIN 1.4 | NEED_TIME | 需要時間同步 | | IIN 1.5 | LOCAL_CONTROL | Outstation 的一或多個 Point 處於本地控制模式 | | IIN 1.6 | DEVICE_TROUBLE | Outstation 存在 "異常" 或 "設備特定的情況" | | IIN 1.7 | DEVICE_RESTART | Outstation 重啟 | | IIN 2.0 | NO_FUNC_CODE_SUPPORT | Outstation 不支援該 Function Code。 | | IIN 2.1 | OBJECT_UNKNOWN | Outstation 不支援該 Object 的 Request 操作 | | IIN 2.2 | PARAMETER_ERROR | 偵測到參數錯誤 | | IIN 2.3 | EVENT_BUFFER_OVERFLOW | Outstation 的 Event Buffer 出現溢位的情況 | | IIN 2.4 | ALREADY_EXECUTING | 【可選】Request 的操作已執行 | | IIN 2.5 | CONFIG_CORRUPT | 【可選】Outstation 偵測到損壞的設置 | | IIN 2.6 | RESERVED_2 | 【值常駐為 0】保留 | | IIN 2.7 | RESERVED_1 | 【值常駐為 0】保留 | > **以發生 Outstation 不支援該 Object 的 Request 操作的狀態為例:** > > * 該狀態的 IIN 代碼為 IIN2.1 > * 因此在 IIN 的第二個 Octet 中,第二個 bit 的值會為 1 ## Object Header 由 `物件類型符(Object Type Field)`、`限定符(Qualifier Field)` 以及 `範圍符(Range Field)` 組成。 Object Header 的結構如下表: |Object Type Field|Qualifier Field|Range Field| |:-:|:-:|:-:| |2 octet|1 octet|N octets(取決於 Qualifier Field)| > **以一個想要從 Outstation 讀取十個 Analog Input 的 Master 為例:** > > * Master 會使用 Function Code 0x01(READ)來制定 Request 訊息。 > * 而 Object Header 會指定: > * 想要的 Analog Input Point Type 資料。 > * Outstation 傳送資料時,應該使用的整數或浮點格式。 > * 那十個 Analog Input Point 的 Index。 > * Request 中不會包含 DNP3 Object,只會有一或多個 Object Header。 > 因為 Master 不傳送值,只傳送讓 Outstation 知道 Master 需要的值或是資料格式。 > * 接著,Outstation 會使用 RESPONSE(0x81)的 Function Code 來制定 Response 訊息。 > 其中包含了與 Request 相同或相似的 Object Header,並在後面接著 DNP3 Object。 > 後面接著的所有 DNP3 Object,每個都包含來自單個 Index 的單一 Analog 值。 ### Object Type Field Object Type Field 的訊息大小為 2 個 Octet,**Group** 跟 **Variation** 各占一個 Octet。 關於 Group 跟 Variation 的說明請看本篇章節:[關鍵術語 - Group](#群組(Group)) 跟 [關鍵術語 - Variation](#變體(Variation)) ### Qualifier Field 跟 Range Field Qualifier Field 的訊息大小為 1 個 Octet,而 Range Field 則取決於 Qualifier Field 的內容。 Qualifier Field 由 Res、Object Prefix Code 跟 Range Specifier Code 三種參數組成,其結構如下:  * **Res - 1 bit** 保留,且值常駐為 0。 * **Object Prefix Code - 3 bits** `前綴(Prefix)` 可以用來表示 Object 的 Index 編號或 Object 的大小。 它會出現在 Object Header 後的每個 DNP3 Object 前面,位置如下:  而 Object Prefix Code 則是用於指定 Prefix 的內容,其代碼說明如下表: |值|說明|Prefix 的大小| |-|-|-| |0x00|不使用 Prefix|| |0x01|以 Index 作為 Prefix|1 octet| |0x02|以 Index 作為 Prefix|2 octets| |0x03|以 Index 作為 Prefix|4 octets| |0x04|以 Object Size 作為 Prefix|1 octet| |0x05|以 Object Size 作為 Prefix|2 octets| |0x06|以 Object Size 作為 Prefix|4 octets| |0x07|保留| > **以 Master 想要讀取一連串 Index 為 "非連續排列" 的 Analog Input Point 為例:** > > * Master 會將 Object Prefix Code 設置為 0x01、0x02 或 0x03。 > * 並發送以 Index 為 Prefix 的 0 octet 的空 Object。 > * 該 Request 的 Fragment 將會如下: > >  若讀取的是 Index 為 "連續排列" 的情況下, 接下來要介紹的 Range Specifier Code 就可以指定起始跟截止的 Index 範圍, 並且不需要加入 Prefix(Object Prefix Code 設置為 0x00)。 * **Range Specifier Code - 4 bits** Range Specifier Code 指定是否使用 Range Field,並定義 Range Field 的內容及大小。 其代碼說明如下表: |值|說明|Range Field 的大小| |-|-|-| |0x00|1 octet 的起始 Index 跟截止 Index|2 octets| |0x01|2 octets 的起始 Index 跟截止 Index|4 octets| |0x02|4 octets 的起始 Index 跟截止 Index|8 octets| |0x03|1 octet 的起始虛擬地址跟截止虛擬地址|2 octets| |0x04|2 octets 的起始虛擬地址跟截止虛擬地址|4 octets| |0x05|4 octets 的起始虛擬地址跟截止虛擬地址|8 octets| |0x06|不使用 Range Field|0 octet| |0x07|1 octet 的 Objects 數量|1 octet| |0x08|2 octets 的 Objects 數量|2 octets| |0x09|4 octets 的 Objects 數量|4 octets| |0x0A|保留|| |0x0B|1 octet 的 Objects 數量(可變長度的格式)|1 octet| |0x0C|保留|| |0x0D|保留|| |0x0E|保留|| |0x0F|保留|| Range Field 的訊息大小以及內容取決於 Qualifier Field 的 Range Specifier Code。 ### Unsolicited Response `自發性回應(Unsolicited Response)` 是當重要的事件發生時,在 Master 沒有發起 Request 情況下由 Outstation 發送訊息。 此功能是否啟用,是依照供應商的系統設計而定。
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up