如何通过BACnet IP协议设置和读取时间

本文提供了一个使用BACnet IP协议的示例程序,该程序在ARM Linux系统上操作RTC时间。程序包括获取当前时间及设置RTC时间的函数,并在主循环中处理BACnet请求,定时更新RTC。

下面是一个使用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(&current_time);
    timeinfo = localtime(&current_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(&current_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(&current_time);
            set_rtc_time(timeinfo);
        }
    }

    return 0;
}

上述程序使用BACnet IP协议实现了设备对象的设置和读取。其中,get_current_time函数用于获取当前时间,set_rtc_time函数用于设置RTC时间。在主函数中,首先初始化BACnet对象,然后设置RTC时间为当前时间。接着使用while循环运行BACnet协议栈,并在循环中处理接收到的BACnet请求。最后,使用定时器定时更新RTC时间。

请注意,上述程序仅用于示例用途,实际应用中还需要根据实际需求进行修改。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

章鱼哥嵌入式开发

坚持不易,你们的鼓励是我的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值