V2X二阶段国标编解码----ASN.1编解码的基本使用

文章介绍了ASN.1作为数据表示和编码的标准,以及如何使用asn1c编译器将ASN.1描述转换为C语言代码。通过示例展示了如何定义和操作如CertainStructure和MyTypes的数据结构,包括填充和解码过程。同时,提到了在v2x二阶段VIR消息填充中遇到的问题及其解决办法。
摘要由CSDN通过智能技术生成

ASN.1编解码的基本使用

​ 最近使用v2x二阶段国标编解码,了解到抽象语义记法ASN.1(Abstract Syntax Notation One) ,学习了一下使用方法,记录一下。

一、ASN.1 基础

​ ASN.1是一种 ISO/ITU-T 标准,描述了一种对数据进行表示、编码、传输和解码的数据格式。它提供了一整套正规的格式用于描述对象的结构,而不管语言上如何执行及这些数据的具体指代,也不用去管到底是什么样的应用程序,也就是说这种记法独立于编程语言,具有平台无关性。

CertainStructure ::= SEQUENCE {
    str     VisibleString,
    num1    INTEGER,
    num2    INTEGER   OPTIONAL,
    reals   SET OF REAL
}

​ 如上所述的ASN.1描述为字符串str,整形,浮点型,用asn1c进行编译,即可生成c语言代码。

typedef struct CertainStructure {
    VisibleString_t  str;
    long             num1;
    long            *num2;        /* OPTIONAL */
    A_SET_OF(double) reals;
} CertainStructure_t;

​ asn1c编译器主要是将ASN.1描述编译成c语言代码。具体过程可以见利用开源ASN1C库实现asn.1的编解码(windows) - 咚咚锵锵 - 博客园 (cnblogs.com)

​ 根据上面创建的数据结构完成的使用流程;write_handle的意思是asn1c编译器的使用提示。

CertainStructure_t *class = 0;
ber_decode(0, &asn_DEF_CertainStructure, &class, buffer, buffer_length);
class->num1 = 123;        /* Modify the contents */
der_encode(&asn_DEF_CertainStructure, class, write_handle, 0);

​ 可以通过代码输出xml格式;

xer_fprint(stdout, &asn_DEF_CertainStructure, class);

二、MyTypes

1、MyType 的 ASN.1 定义为:
MyTypes ::= SEQUENCE {
    myObjectId   OBJECT IDENTIFIER,
    mySeqOf      SEQUENCE OF MyInt,
    myBitString  BIT STRING {
                        muxToken(0), 
                        modemToken(1)
                 }
}
2、编译的C语言结构定义:
/* Dependencies */
typedef enum myBitString {
	myBitString_muxToken	= 0,
	myBitString_modemToken	= 1
} e_myBitString;

/* MyTypes */
typedef struct MyTypes {
	OBJECT_IDENTIFIER_t	 myObjectId;
	struct mySeqOf {
		A_SEQUENCE_OF(MyInt_t) list;
		

		/* Context for parsing across buffer boundaries */
		asn_struct_ctx_t _asn_ctx;
	} mySeqOf;
	BIT_STRING_t	 myBitString;
	
	/* Context for parsing across buffer boundaries */
	asn_struct_ctx_t _asn_ctx;

} MyTypes_t;

上述数据结构中,_asn_ctx用来管理,我们在编写过程中不能显式对其进行修改。其他标签,均和ASN.1 格式匹配。

3、编写asn程序;
#include <stdio.h>	/* for stdout */
#include <stdlib.h>	/* for malloc() */
#include <assert.h>	/* for run-time control */
#include "MyTypes.h"	/* Include MyTypes definition */

int main() {
	/* Define an OBJECT IDENTIFIER value */
	int oid[] = { 1, 3, 6, 1, 4, 1, 9363, 1, 5, 0 }; /* or whatever */

	/* Declare a pointer to a new instance of MyTypes type */
	MyTypes_t *myType;
	/* Declare a pointer to a MyInt type */
	MyInt_t *myInt;
	
	/* Temporary return value */
	int ret;
	
	/* Allocate an instance of MyTypes */
	myType = calloc(1, sizeof *myType);
	assert(myType);	/* Assume infinite memory */
	
	/*
	 * Fill in myObjectId
	 */
	ret = OBJECT_IDENTIFIER_set_arcs(&myType->myObjectId,
			oid, sizeof(oid[0]), sizeof(oid) / sizeof(oid[0]));
	assert(ret == 0);
	
	/*
	 * Fill in mySeqOf with a couple of integers.
	 */
	
	/* Prepare a certain INTEGER */
	myInt = calloc(1, sizeof *myInt);
	assert(myInt);
	*myInt = 123;	/* Set integer value */
	
	/* Fill in mySeqOf with the prepared INTEGER */
	ret = ASN_SEQUENCE_ADD(&myType->mySeqOf, myInt);
	assert(ret == 0);
	
	/* Prepare another integer */
	myInt = calloc(1, sizeof *myInt);
	assert(myInt);
	*myInt = 111222333;	/* Set integer value */
	
	/* Append another INTEGER into mySeqOf */
	ret = ASN_SEQUENCE_ADD(&myType->mySeqOf, myInt);
	assert(ret == 0);
	
	/*
	 * Fill in myBitString
	 */
	
	/* Allocate some space for bitmask */
	myType->myBitString.buf = calloc(1, 1);
	assert(myType->myBitString.buf);
	myType->myBitString.size = 1;	/* 1 byte */
	
	/* Set the value of muxToken */
	myType->myBitString.buf[0] |= 1 << (7 - myBitString_muxToken);
	
	/* Also set the value of modemToken */
	myType->myBitString.buf[0] |= 1 << (7 - myBitString_modemToken);
	
	/* Trim unused bits (optional) */
	myType->myBitString.bits_unused = 6;
	
	/*
	 * Print the resulting structure as XER (XML)
	 */
	xer_fprint(stdout, &asn_DEF_MyTypes, myType);
	
	return 0;

}
4、最终输出xml文件
<MyTypes>
    <myObjectId>1.3.6.1.4.1.9363.1.5.0</myObjectId>
    <mySeqOf>
        <MyInt>123</MyInt>
        <MyInt>111222333</MyInt>
    </mySeqOf>
    <myBitString>
        11
    </myBitString>
</MyTypes>
5、从xml中取数据
#include <stdio.h>	/* for stdout */
#include <stdlib.h>	/* for malloc() */
#include <assert.h>	/* for run-time control */
#include "MyTypes.h"	/* Include MyTypes definition */

int main(int argc, char *argv[]) {
	char buf[1024];	/* Hope, sufficiently large buffer */
	MyTypes_t *myType = 0;
	asn_dec_rval_t rval;
	char *filename;
	size_t size;
	FILE *f;

	/*
	 * Target variables.
	 */
	int *oid_array;	/* holds myObjectId */
	int oid_size;
	int *int_array;	/* holds mySeqOf */
	int int_size;
	int muxToken_set;	/* holds single bit */
	int modemToken_set;	/* holds single bit */
	
	/*
	 * Read in the input file.
	 */
	assert(argc == 2);
	filename = argv[1];
	f = fopen(filename, "r");
	assert(f);
	size = fread(buf, 1, sizeof buf, f);
	if(size == 0 || size == sizeof buf) {
		fprintf(stderr, "%s: Too large input\n", filename);
		exit(1);
	}
	
	/*
	 * Decode the XER buffer.
	 */
	rval = xer_decode(0, &asn_DEF_MyTypes, &myType, buf, size);
	assert(rval.code == RC_OK);
	
	/*
	 * Convert the OBJECT IDENTIFIER into oid_array/oid_size pair.
	 */
	/* Figure out the number of arcs inside OBJECT IDENTIFIER */
	oid_size = OBJECT_IDENTIFIER_get_arcs(&myType->myObjectId,
			0, sizeof(oid_array[0]), 0);
	assert(oid_size >= 0);
	/* Create the array of arcs and fill it in */
	oid_array = malloc(oid_size * sizeof(oid_array[0]));
	assert(oid_array);
	(void)OBJECT_IDENTIFIER_get_arcs(&myType->myObjectId,
			oid_array, sizeof(oid_array[0]), oid_size);
	
	/*
	 * Convert the sequence of integers into array of integers.
	 */
	int_size = myType->mySeqOf.list.count;
	int_array = malloc(int_size * sizeof(int_array[0]));
	assert(int_array);
	for(int_size = 0; int_size < myType->mySeqOf.list.count; int_size++)
		int_array[int_size] = *myType->mySeqOf.list.array[int_size];
	
	if(myType->myBitString.buf) {
		muxToken_set   = myType->myBitString.buf[0]
					& (1 << (7 - myBitString_muxToken));
		modemToken_set = myType->myBitString.buf[0]
					& (1 << (7 - myBitString_modemToken));
	} else {
		muxToken_set = modemToken_set = 0;	/* Nothing is set */
	}/*
	 * Print the resulting structure as XER (XML)
	 */
	xer_fprint(stdout, &asn_DEF_MyTypes, myType);
	
	return 0;

}

参考链接:ASN.1编解码:asn1c的基本使用_rtoax的博客-CSDN博客_asn1c

三、v2x二阶段VIR消息集合

1、VIR填充问题
typedef struct IARData {
	struct PathPlanningPoint	*currentPos	/* OPTIONAL */;
	struct PathPlanning	*path_Planning	/* OPTIONAL */;
	DriveBehavior_t	*currentBehavior	/* OPTIONAL */;
	struct reqs {
		A_SEQUENCE_OF(struct DriveRequest) list;

		/* Context for parsing across buffer boundaries */
		asn_struct_ctx_t _asn_ctx;
	} *reqs;
	/*
	 * This type is extensible,
	 * possible extensions are below.
	 */
	
	/* Context for parsing across buffer boundaries */
	asn_struct_ctx_t _asn_ctx;

} IARData_t;

在cpp文件中想要给reqs申请地址空间时,如果使用:

    iAD->reqs = (struct reqs*)malloc(sizeof(struct reqs));

VsCode会报出不允许使用不完整的类型 的错误。

// cpp 解决方案
iAD->reqs = (struct IARData::reqs*)malloc(sizeof(struct IARData::reqs);
//c 解决方案
iAD->reqs = (struct reqs*)malloc(sizeof(struct reqs));

VIR消息其它字段的填充方式类似于MyStype的填充。

需要注意的问题:
  1、对于消息集中可选“optional”的字段,若不填充数据,则将其置为NULL,不然填充失败;若想填充数据,需要先为其申请空间,不然会报段错误。
  2、对于消息集中某些字段的数值,需要注意其定义的大小范围,在填充时其值不能超过最大值,不然虽然能够填充成功,但是编码会失败。
  3、注意填充数据分辨率。

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值