下面是一个使用BACnet IP协议的device对象设置和读取ARM Linux RTC时间的程序示例:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include "bacnet.h"
#include "bacenum.h"
#include "bacapp.h"
#include "iam.h"
#include "device.h"
#define BACNET_PORT 47808
#define MAX_APDU 1476
#define BACNET_MAX_OBJECTS 1024
// BACnet设备号
uint32_t Object_Instance_Number = 12345;
// RTC设备文件路径
char *RTC_DEVICE_FILE = "/dev/rtc0";
// 读取当前时间
time_t get_current_time()
{
time_t current_time;
struct tm *timeinfo;
// 获取当前时间
time(¤t_time);
timeinfo = localtime(¤t_time);
current_time = mktime(timeinfo);
return current_time;
}
// 设置RTC时间
int set_rtc_time(struct tm *time)
{
int rtc_fd, ret;
struct rtc_time rtc_tm;
// 打开RTC设备文件
rtc_fd = open(RTC_DEVICE_FILE, O_WRONLY);
if (rtc_fd < 0) {
perror("open RTC");
return -1;
}
// 将tm结构体转换为rtc_time结构体
rtc_tm.tm_sec = time->tm_sec;
rtc_tm.tm_min = time->tm_min;
rtc_tm.tm_hour = time->tm_hour;
rtc_tm.tm_mday = time->tm_mday;
rtc_tm.tm_mon = time->tm_mon;
rtc_tm.tm_year = time->tm_year;
rtc_tm.tm_wday = time->tm_wday;
rtc_tm.tm_yday = time->tm_yday;
rtc_tm.tm_isdst = time->tm_isdst;
// 设置RTC时间
ret = ioctl(rtc_fd, RTC_SET_TIME, &rtc_tm);
if (ret < 0) {
perror("set RTC time");
close(rtc_fd);
return -1;
}
// 关闭RTC设备文件
close(rtc_fd);
return 0;
}
// BACnet对象列表
static object_functions_t Object_Table[BACNET_MAX_OBJECTS];
// 初始化BACnet对象
void init_objects(void)
{
Device_Init(NULL);
}
// 处理BACnet请求
void handler_unconfirmed_service_request(
BACNET_ADDRESS *src,
uint8_t *pdu,
uint16_t pdu_len)
{
(void) src;
int len = 0;
BACNET_NPDU_DATA npdu_data;
BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT;
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
BACNET_SERVICE_ACK_DETAILS ack_details;
bacnet_npdudata_init(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
if (iam_device_id() == Device_Object_Instance_Number()) {
error_code = bacapp_unconfirmed_handler(
&pdu[0], pdu_len, &ack_details);
if (error_code != ERROR_CODE_OK) {
printf("BACnet Unconfirmed Service Request error: %d\n", (int)error_code);
}
} else {
printf("BACnet Unconfirmed Service Request received for device %u\n", iam_device_id());
}
len =
bactext_ack_encode_apdu(&Handler_Transmit_Buffer[0],
sizeof(Handler_Transmit_Buffer), &ack_details);
if (len > 0) {
npdu_data.protocol_version = BACNET_PROTOCOL_VERSION;
npdu_data.dnet = 0;
npdu_data.snet = src->net;
npdu_data.slen = src->len;
npdu_data.sadr = src->adr;
npdu_data.expecting_reply = false;
len =
npdu_encode_pdu(&Handler_Transmit_Buffer[0], &npdu_data);
if (len > 0) {
send_pdu(src, &Handler_Transmit_Buffer[0], len);
}
}
}
// 主函数
int main(int argc, char *argv[])
{
uint16_t port = BACNET_PORT;
bacnet_init(); // 初始化BACnet
// 初始化BACnet对象
init_objects();
// 设置RTC时间为当前时间
time_t current_time = get_current_time();
struct tm *timeinfo = localtime(¤t_time);
set_rtc_time(timeinfo);
// 运行BACnet协议栈
while (true) {
uint8_t Rx_Buf[MAX_APDU];
BACNET_ADDRESS src;
uint16_t pdu_len = 0;
// 从网络接收BACnet请求
pdu_len = receive_pdu(&src, &Rx_Buf[0], MAX_APDU, port);
if (pdu_len) {
// 处理BACnet请求
handler_unconfirmed_service_request(&src, &Rx_Buf[0], pdu_len);
}
// 定时更新RTC时间
if (get_current_time() - current_time >= 60) {
current_time = get_current_time();
timeinfo = localtime(¤t_time);
set_rtc_time(timeinfo);
}
}
return 0;
}
上述程序使用BACnet IP协议实现了设备对象的设置和读取。其中,get_current_time函数用于获取当前时间,set_rtc_time函数用于设置RTC时间。在主函数中,首先初始化BACnet对象,然后设置RTC时间为当前时间。接着使用while循环运行BACnet协议栈,并在循环中处理接收到的BACnet请求。最后,使用定时器定时更新RTC时间。
请注意,上述程序仅用于示例用途,实际应用中还需要根据实际需求进行修改。
本文提供了一个使用BACnet IP协议的示例程序,该程序在ARM Linux系统上操作RTC时间。程序包括获取当前时间及设置RTC时间的函数,并在主循环中处理BACnet请求,定时更新RTC。
451

被折叠的 条评论
为什么被折叠?



