[英]BACnet encoding/ decoding ASN.1/ C syntax
所以我正在開發一個 BA.net 自動控制系統,我對它比較陌生,因為這是我第一次使用 BA.net。 我將 ASN.1 協議與 asn1c 編譯器一起使用,該編譯器將我的代碼轉換為 C 格式。 由於多種原因,我很難找到一個關於如何實現代碼的清晰示例。 1,我不完全確定 ASN.1 實際上是如何工作的,2,現在代碼已經轉換為 C,它看起來大不相同,物理語法讓我很困惑。 我想知道是否有人可以解釋 ASN.1 傳輸數據的實際過程。 我讀過使用 ASN.1 可以讓手機與超級計算機通信,我想確切地知道如何,而且,如果有人有一個明確的“防白痴”示例,說明如何實際解碼和對可以從 BA.net 消息讀取和寫入的消息進行編碼。 下面我發布了 BA.netObjectIdentifier
#include "BACnetObjectIdentifier.h"
main()
{
int
BACnetObjectIdentifier_constraint(asn_TYPE_descriptor_t *td, const void
asn_app_constraint_failed_f *ctfailcb, void *app_key) {
const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
size_t size;
if(!sptr) {
_ASN_CTFAIL(app_key, td, sptr,
"%s: value not given (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
}
size = st->size;
if((size == 4)) {
/* Constraint check succeeded */
return 0;
} else {
_ASN_CTFAIL(app_key, td, sptr,
"%s: constraint failed (%s:%d)",
td->name, __FILE__, __LINE__);
return -1;
}
}
static void
BACnetObjectIdentifier_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) {
td->free_struct = asn_DEF_OCTET_STRING.free_struct;
td->print_struct = asn_DEF_OCTET_STRING.print_struct;
td->check_constraints = asn_DEF_OCTET_STRING.check_constraints;
td->ber_decoder = asn_DEF_OCTET_STRING.ber_decoder;
td->der_encoder = asn_DEF_OCTET_STRING.der_encoder;
td->xer_decoder = asn_DEF_OCTET_STRING.xer_decoder;
td->xer_encoder = asn_DEF_OCTET_STRING.xer_encoder;
td->uper_decoder = asn_DEF_OCTET_STRING.uper_decoder;
td->uper_encoder = asn_DEF_OCTET_STRING.uper_encoder;
if(!td->per_constraints){
td->per_constraints = asn_DEF_OCTET_STRING.per_constraints;
td->elements = asn_DEF_OCTET_STRING.elements;
td->elements_count = asn_DEF_OCTET_STRING.elements_count;
td->specifics = asn_DEF_OCTET_STRING.specifics;
}
void
BACnetObjectIdentifier_free(asn_TYPE_descriptor_t *td,
void *struct_ptr, int contents_only) {
BACnetObjectIdentifier_1_inherit_TYPE_descriptor(td);
td->free_struct(td, struct_ptr, contents_only);
}
int
BACnetObjectIdentifier_print(asn_TYPE_descriptor_t *td, const void *struct_ptr,
int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
BACnetObjectIdentifier_1_inherit_TYPE_descriptor(td);
return td->print_struct(td, struct_ptr, ilevel, cb, app_key);
}
asn_dec_rval_t
BACnetObjectIdentifier_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
void **structure, const void *bufptr, size_t size, int tag_mode) {
BACnetObjectIdentifier_1_inherit_TYPE_descriptor(td);
return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode);
}
asn_enc_rval_t
BACnetObjectIdentifier_encode_der(asn_TYPE_descriptor_t *td,
void *structure, int tag_mode, ber_tlv_tag_t tag,
asn_app_consume_bytes_f *cb, void *app_key) {
BACnetObjectIdentifier_1_inherit_TYPE_descriptor(td);
return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);
}
asn_dec_rval_t
BACnetObjectIdentifier_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
void **structure, const void *bufptr, size_t size, int tag_mode) {
BACnetObjectIdentifier_1_inherit_TYPE_descriptor(td);
return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode);
}
asn_enc_rval_t
BACnetObjectIdentifier_encode_der(asn_TYPE_descriptor_t *td,
void *structure, int tag_mode, ber_tlv_tag_t tag,
asn_app_consume_bytes_f *cb, void *app_key) {
BACnetObjectIdentifier_1_inherit_TYPE_descriptor(td);
return td->der_encoder(td, structure, tag_mode, tag, cb, app_key);
}
asn_dec_rval_t
BACnetObjectIdentifier_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
void **structure, const char *opt_mname, const void *bufptr, size_t size) {
BACnetObjectIdentifier_1_inherit_TYPE_descriptor(td);
return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size);
}
asn_enc_rval_t
BACnetObjectIdentifier_encode_xer(asn_TYPE_descriptor_t *td, void *structure,
int ilevel, enum xer_encoder_flags_e flags,
asn_app_consume_bytes_f *cb, void *app_key) {
BACnetObjectIdentifier_1_inherit_TYPE_descriptor(td);
return td->xer_encoder(td, structure, ilevel, flags, cb, app_key);
}
asn_dec_rval_t
BACnetObjectIdentifier_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints, void **structure, asn_per_data_t *per_data) {
BACnetObjectIdentifier_1_inherit_TYPE_descriptor(td);
return td->uper_decoder(opt_codec_ctx, td, constraints, structure, per_data);
}
asn_enc_rval_t
BACnetObjectIdentifier_encode_uper(asn_TYPE_descriptor_t *td,
asn_per_constraints_t *constraints,
void *structure, asn_per_outp_t *per_out) {
BACnetObjectIdentifier_1_inherit_TYPE_descriptor(td);
return td->uper_encoder(td, constraints, structure, per_out);
}
static asn_per_constraints_t asn_PER_type_BACnetObjectIdentifier_constr_1 GCC_NOTUSED = {
{ APC_UNCONSTRAINED, -1, -1, 0, 0 },
{ APC_CONSTRAINED, 0, 0, 4, 4 } /* (SIZE(4..4)) */,
0, 0 /* No PER value map */
};
static ber_tlv_tag_t asn_DEF_BACnetObjectIdentifier_tags_1[] = {
(ASN_TAG_CLASS_APPLICATION | (12 << 2)),
(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))
};
asn_TYPE_descriptor_t asn_DEF_BACnetObjectIdentifier = {
"BACnetObjectIdentifier",
"BACnetObjectIdentifier",
BACnetObjectIdentifier_free,
BACnetObjectIdentifier_print,
BACnetObjectIdentifier_constraint,
BACnetObjectIdentifier_decode_ber,
BACnetObjectIdentifier_encode_der,
BACnetObjectIdentifier_decode_xer,
BACnetObjectIdentifier_encode_xer,
BACnetObjectIdentifier_decode_uper,
BACnetObjectIdentifier_encode_uper,
0, /* Use generic outmost tag fetcher */
asn_DEF_BACnetObjectIdentifier_tags_1,
sizeof(asn_DEF_BACnetObjectIdentifier_tags_1)
/sizeof(asn_DEF_BACnetObjectIdentifier_tags_1[0]) - 1, /* 1 */
asn_DEF_BACnetObjectIdentifier_tags_1, /* Same as above */
sizeof(asn_DEF_BACnetObjectIdentifier_tags_1)
/sizeof(asn_DEF_BACnetObjectIdentifier_tags_1[0]), /* 2 */
&asn_PER_type_BACnetObjectIdentifier_constr_1,
0, 0, /* No members */
0 /* No specifics */
};
}
上面的代碼是 asn1c 編譯器生成的。 任何幫助是極大的贊賞。
您需要的是對 ASN.1 的介紹以及對您正在使用的工具的介紹。 對於前者,您可以從這里開始: http://www.obj-sys.com/resources/links_asn1_info.php 。 后者我幫不了你。
為了幫助您定位,一個非常簡短的摘要:ASN.1 是抽象語法表示法。 它是一種抽象地描述消息語法的符號。 “在抽象中”意味着,例如,使用符號,您將指定一個 integer 在序列中跟隨另一個,但您沒有指定這些整數在傳輸中的實際表示方式(例如,將使用多少位?) . 當您將抽象符號與一組編碼規則(例如 BER、PER;編碼規則是標准化的——您無需編寫它們)結合使用時,抽象符號就變得具體了。 編碼規則與抽象語法相結合,完全指定了傳輸的內容。
代碼生成工具的作用在概念上很簡單。 他們讀取 ASN.1 描述並使用您最喜歡的編程語言生成數據結構 model 來自 ASN.1 的消息,以及可以采用這些數據結構並根據您選擇的編碼規則集對相應消息進行編碼/解碼的函數。 作為程序員,您填充數據結構,調用編碼方法,並接收根據您選擇的規則(例如 BER)編碼的 ASN.1 消息。
您真正需要的是一份 Ashrae 135-2012(或更高版本)標准。 (不幸的是,它不是免費的——盡管勘誤表和附錄是免費的)。
ASN1只是描述了一些編碼規則,並不是因為我的郵件是base64編碼的所以你看base64就可以看郵件了。你還需要了解其他的header、context、規則和語義。
Ashrae 135 標准中對編碼、類型、枚舉和服務代碼進行了詳細說明。 而理解和“閱讀”BA.net 數據包確實需要此類信息。
使用 Wireshark 查看和打開一些捕獲的數據包,也確實有幫助,以便了解信息是如何列出和發送的,具體取決於各種消息上下文。
您還可以選擇 BA.net 通信協議的免費或非免費 C 或 Java 或 C#(或其他)實現並使用它。
如果您想深入研究 BA.net(的世界),那么我擔心您可能會從錯誤的角度/直接深入(或至少是它的特定方面/深度)進入它,因此在讓自己有機會涉足之前先考慮復雜性,首先了解/測試水(以更一般/交叉的方式)。
例如,以空手道為例,如果學習 BA.net 是獲得黑帶,那么學習 ASN 可能是進一步提升到一級或二級段位。
我建議嘗試使用像 YABE 這樣的工具,然后(而不是 Wireshark)VTS(可視化測試外殼),然后有一天 - 如果您編寫自己的 BA.net(模擬)設備的一部分,那么您會有所收獲進一步的了解。
(YABE寫在C#,而VTS寫在C++,BA.netStack寫在C。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.