分析bacnet协议栈中的Device Communication Control服务
来源:互联网 发布:皖南医学院校园网络 编辑:程序博客网 时间:2024/06/16 08:06
Device Communication Control服务,是一个客户端的BACnet用户使用设备通信控制服务向一个远程设备发送指令,指示这个设备在一个规定的时间内停止其起始和响应除了设备通信控制或者重新初始化设备之外的所有APDU。DCC主要由操作者用来进行设备诊断。
在dcc.c文件中,先是定义了BACNET_COMMUNICATION_ENABLE_DISABLE这个枚举值,用于表示当前设备的会话状态:
typedef enum { COMMUNICATION_ENABLE = 0, COMMUNICATION_DISABLE = 1, COMMUNICATION_DISABLE_INITIATION = 2, MAX_BACNET_COMMUNICATION_ENABLE_DISABLE = 3 } BACNET_COMMUNICATION_ENABLE_DISABLE;</span></strong>
由于设备在使用DCC服务时可能存在相应的时间期限,因此需要对DCC服务的时间期限进行设置:
bool dcc_set_status_duration(BACNET_COMMUNICATION_ENABLE_DISABLE status, uint16_t minutes){ bool valid = false; /* valid? */ if (status < MAX_BACNET_COMMUNICATION_ENABLE_DISABLE) { // COMMUNICATION_ENABLE = 0, COMMUNICATION_DISABLE = 1, COMMUNICATION_DISABLE_INITIATION = 2 DCC_Enable_Disable = status; if (status == COMMUNICATION_ENABLE) { DCC_Time_Duration_Seconds = 0; } else { DCC_Time_Duration_Seconds = minutes * 60; } valid = true; } return valid;}dcc_set_status_duration判断是否设置了时间期限(Time Duration),如果设置了,则需要将这个时间以秒的形式表示。
同时,可以看到对DCC的状态有三种设置方法:
bool dcc_communication_enabled(void);
bool dcc_communication_disabled(void);
bool dcc_communication_initiation_disabled(void);
在VTS中,也同样只有三种状态:
接下来看看dcc_encode_apdu(.......)这个函数:
int dcc_encode_apdu( uint8_t * apdu, uint8_t invoke_id, uint16_t timeDuration, /* 0=optional */ BACNET_COMMUNICATION_ENABLE_DISABLE enable_disable, BACNET_CHARACTER_STRING * password){ /* NULL=optional */ int len = 0; /* length of each encoding */ int apdu_len = 0; /* total length of the apdu, return value */ if (apdu) { apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST; apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU); apdu[2] = invoke_id; apdu[3] = SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL; apdu_len = 4; /* optional timeDuration */ if (timeDuration) { len = encode_context_unsigned(&apdu[apdu_len], 0, timeDuration); apdu_len += len; } /* enable disable */ len = encode_context_enumerated(&apdu[apdu_len], 1, enable_disable); apdu_len += len; /* optional password */ if (password) { /* FIXME: must be at least 1 character, limited to 20 characters */ len = encode_context_character_string(&apdu[apdu_len], 2, password); apdu_len += len; } } return apdu_len;}
首先,先来看看设备通信控制服务的原语结构:
其中,Time Duration 和 Password 是用户可选,Enable 和 Disable 是必选参数。
apdu[0]~adpu[3] 是常规的定义,具体可参考前面的文章。接下来是判断 Time Duration 是否有设定,如果Time Duration有设定,参照VTS中关于Time Duration的信息可知:
对 time duration 编码的过程中需要进行标记编码,由于 time duration 是一个无符号整型类型,因此也需要对其进行无符号整型编码。在 encode_context_unsigned(...) 中包括了 encode_tag(...) 和 encode_bacnet_unsigned(...)。
接下来是 使能 / 禁止参数,这是一个必选参数。需要进行标记编码和枚举值编码,由于枚举值属于无符号整型类型的一种,因此也需要进行无符号标记编码。
最后是对password的编码。协议中规定password属性是一个不超过20个字符的字符串。在这里调用了一个字符串编码函数:
int encode_context_character_string( uint8_t * apdu, uint8_t tag_number, BACNET_CHARACTER_STRING * char_string){ int len = 0; int string_len = 0; string_len = (int) characterstring_length(char_string) + 1 /* for encoding */ ; len += encode_tag(&apdu[0], tag_number, true, (uint32_t) string_len); if ((len + string_len) < MAX_APDU) { len += encode_bacnet_character_string(&apdu[len], char_string); } else { len = 0; } return len;}在这个函数中,其参数有这样一个类型BACNET_CHARACTER_STRING,它的定义如下:
<span style="font-family:Microsoft YaHei;">typedef struct BACnet_Character_String { size_t length; uint8_t encoding; /* limit - 6 octets is the most our tag and type could be */ char value[MAX_CHARACTER_STRING_BYTES];} BACNET_CHARACTER_STRING;</span>characterstring_length(...)这个函数获取的是BACNET_CHARACTER_STRING结构体中的 length 参数加上1。然后调用标记编码函数为这个password字符串进行标记。对这个字符串长度进行判断,看其是否小于APDU的最大长度1476,如果符合要求,则对这个password字符串的内容进行编码。encode_bacnet_character_string(...)包含三个编码过程,参照VTS中password字符串的信息,包括了length, value 和 ASCII Character Encoding。由此可知,在BACnet协议中,任何关于字符串的编码都包括了这三方面的内容。
最后我们就得到了在这个编码过程中得到的长度。
- 分析bacnet协议栈中的Device Communication Control服务
- 分析bacnet协议栈源码 AtomicReadFile 服务
- BACnet协议栈分析之Makefile文件
- BACnet WHO-IS服务协议栈代码分析(1)------whois_encode_apdu(....)函数
- BACnet WHO-IS服务协议栈代码分析(2) ------ whois_decode_service_request(....)函数
- BACnet协议栈移植分析之一:rs485.c
- BACnet协议栈移植分析之二:rs485.mak
- BACnet协议栈移植分析之三:mstpsnap.c
- BACnet协议
- 结合VTS和BACnet协议栈源码分析Write Property读属性
- BACnet 协议栈浅析(Java 版)之 BACnet 协议简介
- 使用VTS分析bacnet协议的ReadProperty(一)
- 使用VTS分析bacnet协议的ReadProperty(二)
- 关于BACnet协议中的InvokeID的一些知识
- BACnet协议开发
- BACnet协议栈学习、研究的一点tips
- 利用VTS与bacnet协议栈进行通信---ReadProperty
- BACnet协议栈中一个Ringbuff编程范例
- iOS-CGContextAddArc各参数说明
- fetch实践 替代jquery封装的ajax
- HDU 5194 DZY Loves Balls
- 反射知识点总结
- Sublime Text 3 快捷键使用
- 分析bacnet协议栈中的Device Communication Control服务
- MultiImageSelector Github项目地址
- android条形码二维码
- Ubuntu中SVN客户端安装+使用
- oracle数据迁移--复制表--create table as select & select into & insert into
- Dialog - 常用类型 & 自定义布局
- 数据结构之数组和广义表
- npm install -g ionic 安装
- 根据两个经纬度计算距离