1 /* 2 * 3 * iec61850sv_protocol.h 4 * 5 * iec61850采樣協議(9-1、9-2)解析。 6 * 7 * 8 * 本代碼支持win32平台和linux平台。 9 * 10 * Copyright (c)2012,lizhi<ibox> 11 * 12 * 2012-10-10 V1.0 lizhi<QQ:252240557,msn:ddgooo@hotmail.com> created 13 * 14 * 15 * ◆ IEC61850-9-2(特定通信服務映射-基於ISO/IEC 8802-3 的模擬量采樣值) 16 * 以太網通信幀結構格式(9-1、9-2): 17 * Header MAC 01 目標地址 0xFF 18 * 02 0xFF 19 * 03 0xFF 20 * 04 0xFF 21 * 05 0xFF 22 * 06 0xFF 23 * 07 源地址 0x73 24 * 08 0x61 25 * 09 0x63 26 * 10 0x00 27 * 11 0x00 28 * 12 0x01 29 * Priority Tagged 13 TPID 0x81 30 * 14 0x00 31 * 15 TCI 0x80 32 * 16 0x00 33 * Ether-type PDU 17 Ether-type 0x88 34 * 18 0xBA 35 * 19 APPID 0x40 36 * 20 0x00 37 * 21 Length .... 38 * 22 .... 39 * 23 保留 0x00 40 * 24 0x00 41 * 25 保留 0x00 42 * 26 0x00 43 * APDU 27 ~ N 格式見后面 .... 44 * 45 * 【9-2】APDU的內容定義(第27個字節開始): 46 * 其中Len表示asn1的長度, 注意計算方法. 47 * 長度在[0, 7f], 1個字節表示 48 * 長度在[80, ff], 2個字節表示,第一個字節填0x81 49 * 長度在[100, ffff], 3個字節表示,第一個字節填0x82, 后面用網絡字節序 50 * ASDU個數可配,至多12個,采樣頻率SampleRate范圍[1, 255]。SmpCnt前后兩報文之間加一,當達到采樣率時(或溢出時)歸零(歸1)。 51 * 52 * APDU的內容定義: 53 * 1 savPdu 0x60 Len 54 * 2 numOfAsdu 0x80 Len=1 AsduNum 55 * 2 SequenceOfAsdu 0xA2 Len 56 * 3 Sequence Asdu1 0x30 Len Asdu1 57 * 3 Sequence Asdu2 0x30 Len Asdu2 58 * .... ... ... ... 59 * 60 * ASDU內容: 61 * 0x80 svID Len=[10, 34] 10~34個字符串 62 * 0x82 smpCnt Len=2 計數, 變化值 63 * 0x83 confRev Len=1 配置版本 64 * 0x85 smpSynch Len=1 同步標識 65 * 0x87 Dataset Len=64 見下面, 變化值 66 * 4bytes UA 67 * 4bytes UA Quality 68 * 4bytes UB 69 * 4bytes UB Quality 70 * 4bytes UC 71 * 4bytes UC Quality 72 * 4bytes UZ 73 * 4bytes UZQuality 74 * 4bytes IA 75 * 4bytes IA Quality 76 * 4bytes IB 77 * 4bytes IB Quality 78 * 4bytes IC 79 * 4bytes IC Quality 80 * 4bytes IZ 81 * 4bytes IZ Quality 82 * 83 *采樣質量編碼參見 IEC61850-7-3 質量的編碼。 84 * 85 * 86 * 【9-1】APDU的內容定義(第27個字節開始): 87 * 1 savPdu 0x80(TAG) ASDU Length(asn1長度) 88 * 2 numOfAsdu No. of ASDUs(asn1長度) 89 * 3 Sequence Asdu1 Asdu1(46字節) 90 * 3 Sequence Asdu2 Asdu2(46字節) 91 * .... ... 92 * 93 * ASDU內容: 94 * ASDU 報頭 01 ASDU 長度(44) 0x00 95 * 02 0x2c 96 * ASDU(基本數據集) 03 LNName(邏輯節點名總為02) 0x02 97 * 04 DataSetName(數據集名稱為01或者FE) 0x01 98 * 05 LDName(邏輯設備名) ... 99 * 06 ... 100 * 07 額定相電流 ... 101 * 08 ... 102 * 09 額定中線電流 ... 103 * 10 ... 104 * 11 額定相電壓 ... 105 * 12 ... 106 * 13 額定時延 ... 107 * 14 ... 108 * 15 A 相電流, 保護用 ... 109 * 16 ... 110 * 17 B 相電流, 保護用 ... 111 * 18 ... 112 * 19 C 相電流, 保護用 ... 113 * 20 ... 114 * 21 中線電流 ... 115 * 22 ... 116 * 23 A 相電流, 儀表用 ... 117 * 24 ... 118 * 25 B 相電流, 儀表用 ... 119 * 26 ... 120 * 27 C 相電流, 儀表用 ... 121 * 28 ... 122 * 29 A 相電壓 ... 123 * 30 ... 124 * 31 B 相電壓 ... 125 * 32 ... 126 * 33 C 相電壓 ... 127 * 34 ... 128 * 35 零序電壓 ... 129 * 36 ... 130 * 37 母線電壓 ... 131 * 38 ... 132 * 39 狀態字#1 ... 133 * 40 ... 134 * 41 狀態字#2 ... 135 * 42 ... 136 * 43 采樣計數器 ... 137 * 44 ... 138 * 45 采樣率 ... 139 * 46 配置版本號 ... 140 * 141 * 142 */ 143 144 145 #ifndef __INCLUDE_SVPDU_PROTOCOL_H 146 #define __INCLUDE_SVPDU_PROTOCOL_H 147 148 149 /* 150 * 頭文件 151 */ 152 #include "base_type.h" 153 154 155 #if defined (__cplusplus) 156 extern "C" { 157 #endif /* defined (__cplusplus) */ 158 159 160 /* 161 * 宏開關 162 */ 163 #ifndef SVPDU_IOBUFFER 164 #define SVPDU_IOBUFFER 165 #endif 166 167 /* 168 * 宏定義文件的讀寫操作,可以根據需要改寫該接口,如重定義 169 * 為網口的recv\send、串口r\w等。 170 * 171 * _my_read_svpdu_bufn/_my_read_svpdu_bufn - svpdu的讀寫操作 172 * @pfd: 讀寫地址,可以為文件的fd、或者buffer地址等 173 * @buf: 緩沖區地址 174 * @count: 需要讀寫的字節數 175 * 176 */ 177 #if defined(SVPDU_IOFILE) 178 typedef int _my_svpdu_ioptr; 179 #define _my_read_svpdu_bufn(pfd, buf, count) \ 180 do { \ 181 if (read((pfd), (buf), (count)) <= 0) { \ 182 (pfd) = -1; \ 183 } \ 184 } while(0); 185 #define _my_write_svpdu_bufn(pfd, buf, count) \ 186 do { \ 187 if (write((pfd), (buf), (count)) <= 0) { \ 188 (pfd) = -1; \ 189 } \ 190 } while(0); 191 #define _my_check_svpdu_ptr(pfd) \ 192 (((pfd) != -1) && ((pfd) != 0)) 193 #elif defined(SVPDU_IOBUFFER) 194 typedef u8* _my_svpdu_ioptr; 195 #define _my_read_svpdu_bufn(pfd, buf, count) \ 196 do { \ 197 memcpy((buf), (pfd), (count)); \ 198 (pfd) += (count); \ 199 } while(0); 200 #define _my_write_svpdu_bufn(pfd, buf, count) \ 201 do { \ 202 memcpy((pfd), (buf), (count)); \ 203 (pfd) += (count); \ 204 } while(0); 205 #define _my_check_svpdu_ptr(pfd) \ 206 (((pfd) != -1) && ((pfd) != 0)) 207 #endif 208 209 210 /* 211 * 關於鏈路層svpdu報文頭部信息的宏定義 212 */ 213 /* 214 * SVPDU_LPDU_TPID_VLAN - tpid的宏定義,標記的協議標識(Tag Protocol Identifier),虛擬局域網(Virtual Local 215 * Area Network); 216 */ 217 #define SVPDU_LPDU_TPID_VLAN 0x8100 218 /* 219 * svpdu_tci_get_pri/svpdu_tci_set_pri - 關於tci中PRI的取值/賦值的宏定義, 220 * PRI:User priority(優先權),占前3bit(BS3),如果不配置優先級,則應采用以下的缺省值為4 221 * (即二進制100); 222 */ 223 #define svpdu_tci_get_pri(tci) (((tci) & 0xE000) >> 13) 224 #define svpdu_tci_set_pri(tci,pri) ((((pri) << 13) | 0x1FFF) & ((tci) | 0xE000)) 225 /* 226 * svpdu_lpdu_tci_get_cfi/svpdu_tci_set_cfi - 關於tci中CFI的取值/賦值的宏定義;占PRI后面1bit; 227 * 228 */ 229 #define svpdu_tci_get_cfi(tci) (((tci) & 0x1000) >> 12) 230 #define svpdu_tci_set_cfi(tci,cfi) ((((cfi) << 12) | 0xEFFF) & ((tci) | 0x1000)) 231 /* 232 * svpdu_tci_get_vid/svpdu_tci_set_vid - 關於tci中VID的取值/賦值的宏定義;占之后剩下的12bit; 233 * 234 */ 235 #define svpdu_tci_get_vid(tci) ((tci) & 0x0FFF) 236 #define svpdu_tci_set_vid(tci,vid) (((tci) | 0xF000) & ((tci) | 0x0FFF)) 237 238 /* 239 * SVPDU_ETHER_TYPE_XXX - 關於ether type的宏定義 240 * SVPDU_ETHER_TYPE_81_GOOSE - IEC 61850-8-1 GOOSE 241 * SVPDU_ETHER_TYPE_81_GSE - IEC 61850-8-1 GSE 242 * SVPDU_ETHER_TYPE_91_OR_92 - IEC 61850-9-1/9-2 采樣值 243 */ 244 #define SVPDU_ETHER_TYPE_81_GOOSE 0x88B8 245 #define SVPDU_ETHER_TYPE_81_GSE 0x88B9 246 #define SVPDU_ETHER_TYPE_91_OR_92 0x88BA 247 /* 248 * SVPDU_APPID_XXX - 關於appid的宏定義;APPID用以選擇采樣值信息並區分應用關聯。APPID的值是APPID類型 249 * 碼和實際標識的組合,APPID類型碼被定義為其最高兩位;為采樣值保留的取值范圍為 0x4000 250 * 到0x7fff;如果沒有配置APPID,缺省值應為0x4000。缺省值被保留為表明缺少配置; 251 * SVPDU_APPID_TYPE_81_GOOSE_OR_GSE - IEC 61850-8-1 GOOSE/GSE APPID type; 252 * SVPDU_APPID_TYPE_91_OR_92 - IEC 61850-9-1/9-2 APPID type; 253 * SVPDU_APPID_DEFAULT - 缺省值; 254 * svpdu_appid_get_type - 取類型碼值; 255 * svpdu_appid_set_type - 賦值類型碼; 256 * 257 */ 258 #define SVPDU_APPID_TYPE_81_GOOSE_OR_GSE 0x00 259 #define SVPDU_APPID_TYPE_91_OR_92 0x01 260 #define SVPDU_APPID_DEFAULT 0x4000 261 #define svpdu_appid_get_type(appid) (((appid) & 0xC000) >> 14) 262 #define svpdu_appid_set_type(appid,type) ((((type) << 14) | 0x3FFF) & ((appid) | 0xC000)) 263 264 /* 265 * svpdu_lpdu_head - 9-2/9-1采樣值(sample value)鏈路層(link layer)報文(pdu)頭部信息。 266 * @des_mac: 目標地址(為FF:FF:FF:FF:FF:FF表示廣播包),ISO/IEC8802-3標准地址; 267 * @src_mac: 源地址,ISO/IEC8802-3標准地址; 268 * @tpid: 標記的協議標識(Tag Protocol Identifier),有些報文沒有該字段(非標准的); 269 * @tci: 標記的控制信息(Tag Control Information),有些報文沒有該字段(非標准的); 270 * @ether_type: 以太網類型; 271 * @appid: 應用標識,標識不用的應用的采樣值,連續幾個包取得采樣值時需要核對應用標識,否則會導致取得采 272 * 樣值混亂; 273 * @epdu_length: 包括以APPID開始的以太網類型PDU在內的八位位組的數目,其值為8+m(m<1480); 274 * @reserve1: 保留字節,為0; 275 * @reserve2: 保留字節,為0; 276 * 277 * TPID 值:0x8100; 278 * TCI 值: 由三部分組成: 279 * PRI:User priority(優先權),占前3bit(BS3),應對user priority值進行配置,以區分采樣值和定時苛 280 * 刻的、保護相關的GOOSE信息,或低優先級的總線負載。如果不配置優先級,則應采用缺省值(4); 281 * CFI:占PRI后面1bit,用於標識是否含有RIF信息;在以太網標記幀中長度/類型域后沒有嵌入RIF域,值應 282 * 該為0;若值為1,則表明在ISO/IEC8802-3標記幀中,Length/Type域后接着內嵌的路由信息域(RIF); 283 * VID: 占之后剩下的12bit;為支持虛擬局域網是一種可選的機制,如果采用了這種機制,那么配置時應設 284 * 定虛擬局域網標識(VID)。另外,虛擬局域網標識VID 缺省值為0; 285 * 注:IEEE802.1Q允許應用帶有一組優先級限制,高優先級幀應設置其優先級為4~7,低優先級幀則為1~3,優 286 * 先級1為未標記的幀,應避免采用優先級0,因為這會引起正常通信下不可預見的傳輸時延。優先級和虛擬 287 * 網標識(VID)的缺省值表:優先級和虛擬網標識(VID)的缺省值 288 * 服務 VID缺省值 優先級缺省值 289 * 采樣值 0 4 290 * ETHER_TYPE 值: 以太網類型碼16位表示,下表描述[以太網類型碼]取值和[APPID類型碼]取值; 291 * 表:分配的以太網類型碼取值([APPID類型碼]指APPID的最高兩位) 292 * 應用 以太網類型碼取值(16進制) APPID類型 293 * IEC61850-8-1GOOSE 88-B8 0 0 294 * IEC61850-8-1GSE管理 88-B9 0 0 295 * IEC61850-9-1采樣值 88-BA 0 1 296 * IEC61850-9-2采樣值 88-BA 0 1 297 * APPID 值:應用標識。APPID 用以選擇采樣值信息並區分應用關聯。APPID的值是[APPID 類型碼]和[實際標識] 298 * 的組合,APPID 類型碼被定義為其最高兩位(如表8 所定義)。因而采樣值取如下值: 299 * 為采樣值保留的取值范圍為 0x4000~0x7fff。如果沒有配置APPID,缺省值應為0x4000。缺省值被保留為 300 * 表明缺少配置。強烈推薦在同一系統內采用唯一的、面向數據源的采樣值應用標識(SV APPID)。這應當由 301 * 配置系統強迫執行。 302 * 303 */ 304 struct svpdu_lpdu_head { 305 u8 des_mac[6]; 306 u8 src_mac[6]; 307 u16 tpid; 308 u16 tci; 309 u16 ether_type; 310 u16 appid; 311 u16 epdu_length; 312 u16 reserve1; 313 u16 reserve2; 314 }; 315 316 317 /* 318 * SVPDU_APDU_TAG_91/SVPDU_APDU_TAG_92 - 應用層協議標識,可用來區分該數據包類型; 319 */ 320 #define SVPDU_APDU_TAG_91 0x80 321 #define SVPDU_APDU_TAG_92 0x60 322 /* 323 * SVPDU_ASDUNUM_TAG_92 - asdu個數標識(9-2) 324 */ 325 #define SVPDU_ASDUNUM_TAG_92 0x80 326 /* 327 * SVPDU_SECURITY_TAG_92 - 安全信息標識(9-2) 328 */ 329 #define SVPDU_SECURITY_TAG_92 0x81 330 /* 331 * SVPDU_SEQUENCE_TAG_92 - 關於sequence of asdu的宏定義 332 */ 333 #define SVPDU_SEQUENCE_TAG_92 0xA2 334 335 /* 336 * svpdu_apdu_head - 9-2/9-1 svpdu中應用層(Application Layer)apdu頭部信息; 337 * @apdu_tag: 應用層協議標識;為0x60時為9-2數據,為0x80時為9-1數據,該標識可以用來區分該數據包類型; 338 * @apdu_length: apdu數據包的長度值(從apdu_length的下一個數據開始計數);該數據本身是變長數據,采用 339 * ASN.1 基本編碼規則(ISO/IEC 8825-1),在此約定該值不會超過0xffffff,最長為4字節,采用u32 340 * 類型數據存儲; 341 * @asdu_num_tag: asdu個數標識;該值在9-2中為0x80,9-1中沒有該標識; 342 * @asdu_num_length: [asdu個數]的長度值;標識num數據本身的長度信息,該值在9-2中一般為0x01,9-1中沒有 343 * 該標識;該數據本身是變長數據,采用ASN.1編碼;在此約定該值不會超過0xffffff,最長為4 344 * 字節(實際一般為1在字節),采用u32類型數據存儲; 345 * @asdu_num_value: asdu個數;該值在9-2中,該數據是變長數據,長度(字節數)由asdu_num_length中的len 346 * 值(不是碼)決定;在9-1中,固定采用2字節表示;在此直接用2字節表示,應為其值一般不能 347 * 超過2字節; 348 * @asdu_security_tag: 安全信息標識;該值在9-2中為0x81,為可選數據(一般不選);在9-1中無該數據; 349 * @asdu_security_length: 安全信息長度;采用ASN.1編碼,變長,該項在9-2中為可選數據(一般不選),其值一 350 * 般為0;在9-1中無該數據;在此約定該值不會超過0xffffff,最長為4字節,采用u32類型數據存儲; 351 * @asdu_sequence_tag: asdu序列信息標識;該值在9-2中為0xA2;在9-1中無該數據; 352 * @asdu_sequence_length: asdu序列信息長度;采用ASN.1編碼,變長;在9-1中無該數據;在此約定該值不會超過 353 * 0xffffff,最長為4字節,采用u32類型數據存儲; 354 * 355 * 注: 356 * 結構體中的ASN.1長度碼統一采用u32表示,計算實際長度值時,需要解碼;ASN.1長度計算方法如下: 357 * 長度值在[0x000000, 0x00007f],1個字節表示; 358 * 長度值在[0x000080, 0x0000ff],2個字節表示,第一個字節填0x81; 359 * 長度值在[0x000100, 0x00ffff],3個字節表示,第一個字節填0x82,后面用網絡字節序; 360 * 長度值在[0x010000, 0xffffff],4個字節表示,第一個字節填0x83,后面用網絡字節序; 361 * 一般情況下,asdu_security_tag、asdu_security_length沒有; 362 * 61850編碼規則基於ASN.1基本編碼規則(BER),傳輸語法采用8位位組和面向“Big Endian(高字節在前)”的。 363 * 364 */ 365 struct svpdu_apdu_head { 366 u8 apdu_tag; 367 u32 apdu_length; 368 u8 asdu_num_tag; 369 u32 asdu_num_length; 370 u16 asdu_num_value; 371 u8 asdu_security_tag; 372 u32 asdu_security_length; 373 u8 asdu_sequence_tag; 374 u32 asdu_sequence_length; 375 }; 376 377 378 /* 379 * SVPDU_ASDU_TAG_92 - asdu標識(9-2), 380 */ 381 #define SVPDU_ASDU_TAG_92 0x30 382 /* 383 * SVPDU_ASDU_XXX_TAG_92 - 表示9-2中SVID、DATSET、SMPCNT、CONFREV、REFRTM、SMPSYNCH、SMPRATE以及 384 * SMPDATA項的標識; 385 */ 386 #define SVPDU_ASDU_SVID_TAG_92 0x80 387 #define SVPDU_ASDU_DATSET_TAG_92 0x81 388 #define SVPDU_ASDU_SMPCNT_TAG_92 0x82 389 #define SVPDU_ASDU_CONFREV_TAG_92 0x83 390 #define SVPDU_ASDU_REFRTM_TAG_92 0x84 391 #define SVPDU_ASDU_SMPSYNCH_TAG_92 0x85 392 #define SVPDU_ASDU_SMPRATE_TAG_92 0x86 393 #define SVPDU_ASDU_SMPDATA_TAG_92 0x87 394 395 /* 396 * svpdu_asdu_dat92 - IEC61850-9-2中的asdu詳細信息;具體可以包括SVID、DATSET、SMPCNT、CONFREV、 397 * REFRTM、SMPSYNCH、SMPRATE以及SMPDATA項標記、長度、值的詳細信息; 398 * @asdu_tag: asdu標記,詳見宏定義值; 399 * @asdu_length: asdu總的長度信息; 400 * @svid_tag: svid標記,值為0表示不包含該項信息; 401 * @svid_length: svid信息長度; 402 * @svid_value: svid信息值,系統中唯一標識,該值為VisibleString類型; 403 * @datset_tag: datset標記,值為0表示不包含該項信息; 404 * @datset_length: datset信息長度; 405 * @datset_value: datset信息值,來自MSVC或者USVC的值,為ObjectReference類型; 406 * @smpcnt_tag: smpcnt標記,值為0表示不包含該項信息; 407 * @smpcnt_length: smpcnt信息長度; 408 * @smpcnt_value: smpcnt信息值; 409 * @confrev_tag: confrev標記,值為0表示不包含該項信息; 410 * @confrev_length: confrev信息長度; 411 * @confrev_value: confrev信息值; 412 * @refrtm_tag: refrtm標記,值為0表示不包含該項信息; 413 * @refrtm_length: refrtm信息長度; 414 * @refrtm_value: refrtm信息值; 415 * @smpsynch_tag: smpsynch標記,值為0表示不包含該項信息; 416 * @smpsynch_length: smpsynch信息長度; 417 * @smpsynch_value: smpsynch信息值; 418 * @smprate_tag: smprate標記,值為0表示不包含該項信息; 419 * @smprate_length: smprate信息長度; 420 * @smprate_value: smprate信息值; 421 * @smpdata_tag: smpdata標記,值為0表示不包含該項信息; 422 * @smpdata_length: smpdata信息長度; 423 * @smpdata_portnum: 采樣值的端口數; 424 * @smpdata_values: 采樣值詳細; 425 * @smpdata_qualitys: 采樣質量詳細,為NULL表示沒有質量信息; 426 * 427 * 注: 428 * 按照協議上來說,一個asdu包不可同時包含兩個相同的項(即同時有兩個svid或者smpdata項),在次如果存 429 * 在這種情況,第二個相同項將不再解析; 430 * 需要注意的是,在此程序中默認tag值為0時表示不包含該項信息。 431 * 432 */ 433 struct svpdu_asdu_dat92 { 434 u8 asdu_tag; 435 u32 asdu_length; 436 u8 svid_tag; 437 u32 svid_length; 438 u8 *svid_value; 439 u8 datset_tag; 440 u32 datset_length; 441 u8 *datset_value; 442 u8 smpcnt_tag; 443 u32 smpcnt_length; 444 u16 smpcnt_value; 445 u8 confrev_tag; 446 u32 confrev_length; 447 u32 confrev_value; 448 u8 refrtm_tag; 449 u32 refrtm_length; 450 u32 refrtm_value; 451 u8 smpsynch_tag; 452 u32 smpsynch_length; 453 u8 smpsynch_value; 454 u8 smprate_tag; 455 u32 smprate_length; 456 u16 smprate_value; 457 u8 smpdata_tag; 458 u32 smpdata_length; 459 u32 smpdata_portnum; 460 s32 *smpdata_values; 461 u32 *smpdata_qualitys; 462 }; 463 464 465 /* 466 * svpdu_asdu_dat91 - IEC61850-9-1中的asdu詳細信息; 467 * @asdu_length:數據集長度;類型為16位無符號整數,值域為<0..65535>;長度域包含隨后的數據集長度; 468 * 這個長度不包括長度域本身。按IEC 60044-8規定,長度總是44(十進制); 469 * 如果是自定義數據集,長度會變; 470 * @ln_name:邏輯節點名稱;類型為8位枚舉型,值域為<0..255>;邏輯節點名總為2; 471 * @dataset_name: 數據集名(DataSetName) 類型為8枚舉型,值域為<0..255>; 472 * 數據集名是唯一的數字,用於標識數據集結構,也就是數據通道的分配; 473 * 這里允許的取值有01或0xFE(十進制254); 474 * 下表(參見表10)通用數據集(=01)中定義了DataSetName為01時數據通道到信號源的分配; 475 * @ld_name:邏輯設備名(LDName) 類型為16位無符號整數,值域為<0..65535>; 476 * 邏輯設備名在一個變電站中是唯一的,用於標志數據集的來源;邏輯設備名可以在安裝時設置; 477 * @i_pp: 額定相電流;數據類型為16位無符號整數,值域為<0..65535>;如果不使用,用0替代它; 478 * @i_p0: 額定中線電流(零序電流);數據類型為16位無符號整數,值域為<0..65535>;如果不使用,用0替代它; 479 * @v_pp: 額定相電壓;數據類型為16位無符號整數,值域為<0..65535>;如果不使用,用0替代它; 480 * @t_delay: 額定時延;數據類型為16位無符號整數,值域為<0..65535>; 481 * 給出模數轉換和數據處理帶來的延時的額定值,單位是sµ。 482 * 設發數據幀開始發出時刻為tc,這一幀數據表示的電流電壓在一次側出現的時刻為tp, 483 * 則延遲時間為tc-tp。 互感器額定延遲時間為500sµ,允許誤差范圍-100%~+10%; 484 * @smpdata_portnum: 采樣數據端口數,該參數確定smpdata_values的空間大小; 485 * @smpdata_values:采樣值數組;類型為16位整數,值域為<-32768..32767>。 12個數據通道給出各個信號源的瞬時值, 486 * 通道分配由數據集名決定,參見數據集名的說明。保護用相電流的比例因子由保護用電子式電流互感 487 * 器額定輸出值確定,測量用相電流的比例因子由測量用電子式電流互感器額定輸出值確定(參見表10)。 488 * @status_wordX:類型為16位布爾量集。參見【表11】、【表12】; 489 * 如果某個數據通道未使用,則其響應的狀態標志置為無效, 490 * 數據通道內容置為0x0000。 如果一個傳感器故障,其相應的狀態標志置為無效, 491 * 並將需要維護標志(LPHD.PHHealth)置位。 在喚醒期間數據無效, 492 * 所有的數據無效標志和喚醒指示標志都置位。 同步脈沖丟失或無效標志在下面邏輯滿足時置位: 493 * [[同步脈沖丟失 或 同步脈沖無效] 與 [合並器的內部時鍾漂移大於額定相位誤差限制的二分之1]]。 494 *@smp_cnt:類型為16位無符號整數,值域為<0..65535>。 495 * 這個16位采樣計數器用於檢查數據內容是否被連續刷新。每發送一個新的采樣數據集,計數器增加1, 496 * 溢出后回到0重新開始計數。 當合並器使用同步脈沖時,合並器收到每個同步脈沖都將把采樣計數器清零。 497 * 采樣計數器為零的數據幀的數據對應同步脈沖發生時刻的一次電流電壓。 498 *@smp_rate:數據速率;類型為8位無符號整數,值域為<0..255>;給出額定頻率下每周波時間內輸出的采樣數據集數目,為0時無意義。 499 * 這里采樣速率等於互感器的數據速率。 500 *@version:配置版本號;類型為8位無符號整數,值域為<0..255>。 在每次修改邏輯設備配置時增加1,缺省值為0。 501 * 502 * 【表10】:表DataSetName=01(通用應用)的數據通道映射 503 * 信號源 對象路徑名 參考值 比例因子(見表 3) 504 * 數據通道1 A相電流.保護用 PhsATCTR.Amps 額定相電流 SCP 505 * 數據通道2 B相電流.保護用 PhsBTCTR.Amps 額定相電流 SCP 506 * 數據通道3 C相電流.保護用 PhsCTCTR.Amps 額定相電流 SCP 507 * 數據通道4 零序電流 NeutTCTR.Amps 額定零序電流 SCM 508 * 數據通道5 A相電流.測量用 PhsA2TCTR.Amps 額定相電流 SCM 509 * 數據通道6 B相電流.測量用 PhsB2TCTR.Amps 額定相電流 SCM 510 * 數據通道7 C相電流.測量用 PhsC2TCTR.Amps 額定相電流 SCM 511 * 數據通道8 A相電壓 PhsATVTR.Volts 額定相電壓 SV 512 * 數據通道9 B相電壓 PhsBTVTR.Volts 額定相電壓 SV 513 * 數據通道10 C相電壓 PhsCTVTR.Volts 額定相電壓 SV 514 * 數據通道11 零序電壓 NeutTVTR.Volts 額定相電壓 SV 515 * 數據通道12 母線電壓 BBTVTR.Volts 額定相電壓 SV 516 * 注:對象路徑名參見IEC 61850-9-1; DataSetName為0xFE時表示特殊應用數據集,在上表的通道映射 517 * 不能滿足應用要求時使用。這時合並器將通過一定形式將數據集定義提供給二次設備;DataSetName 518 * 的值不能在運行時改變,也就時說在出廠前的設計和配置時便確定數據通道的分配。 519 * 520 * 【表11】:狀態字1(StatusWord#1) 521 * 解釋 備注 522 * 第0位 需要維護(LPHD.PHHealth) 0:正常 523 * 1:告警(需要維護) 524 * 第1位 模式(LLN0.Mode) 0:正常運行 525 * 1:測試 526 * 第2位 喚醒期間指示 喚醒期間數據無效指示 0:正常,數據有效 在喚醒期間被置位 527 * 1:喚醒期間,數據無效 528 * 第3位 合並器同步方式 0:不能使用插值算法同步 529 * 1:可以使用插值算法同步 530 * 第4位 合並器同步標志 0:采樣已同步 如果使用插值算法,這個位將總是1 531 * 1:同步丟失或無效 532 * 第5位 數據通道1無效標志 0:數據有效 533 * 1:數據無效 534 * 第6位 數據通道2無效標志 0:數據有效 535 * 1:數據無效 536 * 第7位 數據通道3無效標志 0:數據有效 537 * 1:數據無效 538 * 第8位 數據通道4無效標志 0:數據有效 539 * 1:數據無效 540 * 第9位 數據通道5無效標志 0:數據有效 541 * 1:數據無效 542 * 第10位 數據通道6無效標志 0:數據有效 543 * 1:數據無效 544 * 第11位 數據通道7無效標志 0:數據有效 545 * 1:數據無效 546 * 第12位 電流傳感器類型 0:電流值 在使用Rogowski線圈且沒有積分環節時置位。 547 * 1:電流的導數 548 * 第13位 量程標志 0:保護電流比例因子SCP=0x01CF 549 * 1:保護電流比例因子SCP=0x00E7 550 * 第14位 備用 551 * 第15位 備用 552 * 553 * 【表12】:狀態字2(StatusWord#2) 554 * 解釋 備注 555 * 第0位 數據通道8無效標志 0:數據有效 556 * 1:數據無效 557 * 第1位 數據通道9無效標志 0:數據有效 558 * 1:數據無效 559 * 第2位 數據通道10無效標志 0:數據有效 560 * 1:數據無效 561 * 第3位 數據通道11無效標志 0:數據有效 562 * 1:數據無效 563 * 第4位 數據通道12無效標志 0:數據有效 564 * 1:數據無效 565 * 第5-7位 備用 566 * 第8-15位 自定義 567 * 568 * 569 */ 570 struct svpdu_asdu_dat91 { 571 u16 asdu_length; 572 u8 ln_name; 573 u8 dataset_name; 574 u16 ld_name; 575 u16 i_pp; 576 u16 i_p0; 577 u16 u_pp; 578 u16 t_delay; 579 u32 smpdata_portnum; 580 s16 *smpdata_values; 581 u16 status_word1; 582 u16 status_word2; 583 u16 smp_cnt; 584 u8 smp_rate; 585 u8 version; 586 }; 587 588 /* 589 * read_svpdu_lpdu_head - 取得鏈路層svpdu報文頭部信息,沒有讀到的數據為其原來的值 590 * @pfd: 輸入輸出參數,地址 591 * @len: 輸入參數,數據緩沖區長度; 592 * @head: 輸出參數,svpdu_lpdu_head值 593 * @counter: 輸出參數,讀取的字節計數器; 594 * 595 * 讀成功返回當前讀pfd地址,否則返回NULL; 596 * 597 */ 598 _my_svpdu_ioptr read_svpdu_lpdu_head(_my_svpdu_ioptr pfd, int len, struct svpdu_lpdu_head *head, int *counter); 599 600 601 /* 602 * read_svpdu_apdu_head - 取得svpdu報文中apdu頭部信息,沒有讀到的數據為其原來的值 603 * @pfd: 輸入輸出參數,地址 604 * @len: 輸入參數,數據緩沖區長度; 605 * @head: 輸出參數,svpdu_lpdu_head值 606 * @counter: 輸出參數,讀取的字節計數器; 607 * 608 * 讀成功返回當前讀pfd地址,否則返回NULL; 609 * 610 */ 611 _my_svpdu_ioptr read_svpdu_apdu_head(_my_svpdu_ioptr pfd, int len, struct svpdu_apdu_head *head, int *counter); 612 613 /* 614 * read_svpdu_asdu_dat92 - 讀取9-2-asdu詳細值; 615 * @pfd: 輸入輸出參數,地址 616 * @len: 輸入參數,數據緩沖區長度; 617 * @dat92: 輸出參數,asdu詳細值; 618 * @smpquality_enable: 是否有質量信息; 619 * @counter: 輸出參數,讀取的字節計數器; 620 * 621 * 讀成功返回當前讀pfd地址,否則返回NULL; 622 * 623 * 讀取過程中可能會利用動態創建空間以保存svid_value、datset_value、smpdata_values、smpdata_qualitys數據; 624 * 625 */ 626 _my_svpdu_ioptr read_svpdu_asdu_dat92(_my_svpdu_ioptr pfd, int len, struct svpdu_asdu_dat92 *dat92, int smpquality_enable, int *counter); 627 628 629 /* 630 * init_svpdu_asdu_dat92 - 初始化Dat92結構體; 631 * @dat92: 輸入輸出參數,asdu詳細值; 632 * @setdefaultval: 參數是否賦默認值; 633 * 634 * 初始化成功返回當前dat92結構體地址,否則返回NULL; 635 * 636 */ 637 struct svpdu_asdu_dat92 * init_svpdu_asdu_dat92(struct svpdu_asdu_dat92 *dat92, int setdefaultval); 638 /* 639 * free_svpdu_asdu_dat92 - 釋放Dat92結構體; 640 * @dat92: 輸入輸出參數,asdu詳細值; 641 * 642 * 初始化成功返回返回NULL,否則返回當前dat92結構體地址; 643 * 644 */ 645 struct svpdu_asdu_dat92 * free_svpdu_asdu_dat92(struct svpdu_asdu_dat92 *dat92); 646 647 /* 648 * read_svpdu_asdu_dat91 - 讀取9-1-asdu詳細值; 649 * @pfd: 輸入輸出參數,地址 650 * @len: 輸入參數,數據緩沖區長度; 651 * @dat91: 輸出參數,asdu詳細值; 652 * @counter: 輸出參數,讀取的字節計數器; 653 * 654 * 讀成功返回當前讀pfd地址,否則返回NULL; 655 * 656 * 讀取過程中可能會利用動態創建空間以保存smpdata_values數據; 657 * 658 */ 659 _my_svpdu_ioptr read_svpdu_asdu_dat91(_my_svpdu_ioptr pfd, int len, struct svpdu_asdu_dat91 *dat91, int *counter); 660 661 /* 662 * init_svpdu_asdu_dat91 - 初始化Dat91結構體; 663 * @dat92: 輸入輸出參數,asdu詳細值; 664 * 665 * 初始化成功返回當前dat91結構體地址,否則返回NULL; 666 * 667 */ 668 struct svpdu_asdu_dat91 * init_svpdu_asdu_dat91(struct svpdu_asdu_dat91 *dat91); 669 /* 670 * free_svpdu_asdu_dat91 - 釋放Dat91結構體; 671 * @dat91: 輸入輸出參數,asdu詳細值; 672 * 673 * 初始化成功返回返回NULL,否則返回當前dat91結構體地址; 674 * 675 */ 676 struct svpdu_asdu_dat91 * free_svpdu_asdu_dat91(struct svpdu_asdu_dat91 *dat91); 677 678 679 /* 680 * write_svpdu_lpdu_head - 寫svpdu_lpdu_head到文件中 681 * @pfd: 輸入參數,寫地址; 682 * @head:輸入參數,svpdu_lpdu_head結構體; 683 * @counter: 輸出參數,成功寫入的字節個數; 684 * 685 * 返回當前pfd指針,寫失敗返回NULL 686 * 687 */ 688 _my_svpdu_ioptr write_svpdu_lpdu_head(_my_svpdu_ioptr pfd, struct svpdu_lpdu_head *head, int *counter); 689 690 691 /* 692 * write_svpdu_apdu_head - 寫svpdu_apdu_head到文件中 693 * @pfd: 輸入參數,寫地址; 694 * @head:輸入參數,svpdu_apdu_head結構體; 695 * @counter: 輸出參數,成功寫入的字節個數; 696 * 697 * 返回當前pfd指針,寫失敗返回NULL 698 * 699 */ 700 _my_svpdu_ioptr write_svpdu_apdu_head(_my_svpdu_ioptr pfd, struct svpdu_apdu_head *head, int *counter); 701 702 703 /* 704 * write_svpdu_asdu_dat92 - 寫svpdu_asdu_dat92到文件中 705 * @pfd: 輸入參數,寫地址; 706 * @dat92:輸入參數,svpdu_asdu_dat92結構體; 707 * @counter: 輸出參數,成功寫入的字節個數; 708 * 709 * 返回當前pfd指針,寫失敗返回NULL 710 * 711 */ 712 _my_svpdu_ioptr write_svpdu_asdu_dat92(_my_svpdu_ioptr pfd, struct svpdu_asdu_dat92 *dat92, int *counter); 713 714 715 /* 716 * write_svpdu_asdu_dat91 - 寫svpdu_asdu_dat91到文件中 717 * @pfd: 輸入參數,寫地址; 718 * @dat91:輸入參數,svpdu_asdu_dat91結構體; 719 * @counter: 輸出參數,成功寫入的字節個數; 720 * 721 * 返回當前pfd指針,寫失敗返回NULL 722 * 723 */ 724 _my_svpdu_ioptr write_svpdu_asdu_dat91(_my_svpdu_ioptr pfd, struct svpdu_asdu_dat91 *dat91, int *counter); 725 726 727 /* 728 * print_svpdu_lpdu_head - 打印數據 729 * @head: 數據包 730 * 731 */ 732 void print_svpdu_lpdu_head(struct svpdu_lpdu_head * head); 733 734 /* 735 * print_svpdu_apdu_head - 打印數據 736 * @head: 數據包 737 * 738 */ 739 void print_svpdu_apdu_head(struct svpdu_apdu_head* head); 740 741 /* 742 * print_svpdu_asdu_dat92 - 打印數據 743 * @dat92: 數據包 744 * @smpquality_enable: 是否包含質量信息 745 * 746 */ 747 void print_svpdu_asdu_dat92(struct svpdu_asdu_dat92* dat92, u8 smpquality_enable); 748 749 /* 750 * print_svpdu_asdu_dat91 - 打印數據 751 * @dat92: 數據包 752 * @smpquality_enable: 是否包含質量信息 753 * 754 */ 755 void print_svpdu_asdu_dat91(struct svpdu_asdu_dat91* dat91); 756 757 758 #pragma pack(pop) 759 760 #if defined (__cplusplus) 761 } 762 #endif /* defined (__cplusplus) */ 763 764 765 #endif /* __INCLUDE_IEC61850SV_PROTOCOL_H */