水文监测数据通信规约SL651-2014 基础架构

sl_651.h
#ifndef __SL_651_H__
#define __SL_651_H__
#include "stdint.h"

typedef enum {
    SOH = 0x7E7E,    // 帧起始(HEX/BCD编码报文帧起始)
    STX = 0x02,      // 传输正文起始
    SYN = 0x16,      // 多包传输正文起始(多包发送,一次确认的传输模式中使用)
    ETX = 0x03,      // 报文结束,后续无报文(表示传输完成,等待退出通信)
    ETB = 0x17,      // 报文结束,后续有报文(在报文分包传输时,表示传输未完成,不可退出通信)
    ENQ = 0x05,      // 询问(作为下行查询及控制命令帧的报文结束符)
    EOT = 0x04,      // 传输结束,退出(作为传输结束确认帧报文结束符,表示可以退出通信)
    ACK = 0x06,      // 肯定确认,继续发送(作为有后续报文帧的"确认帧"报文结束符)
    NAK = 0x15,      // 否定应答,反馈重发(用于要求对方重发某数据包的报文结束符)
    ESC = 0x1B       // 传输结束,终端保持在线(在下行确认帧代替EOT作为报文结束符,要求终端在线,保持在线10分钟内若没有接收到中心站命令,终端退回原先设定的工作状态)
} ControlCharacter;

typedef enum {
    FUNCTION_CODE_RESERVED_00H_2EH = 0x00,   // 00H - 2EH:保留,扩展功能码
    FUNCTION_CODE_LINK_MAINTENANCE = 0x2F,   // 2FH:链路维持报
    FUNCTION_CODE_TEST = 0x30,   // 30H:测试报
    FUNCTION_CODE_UNIFORM_TIME_HYDRO_INFO = 0x31,   // 31H:均匀时段水文信息报
    FUNCTION_CODE_TIMED_REPORT = 0x32,   // 32H:遥测站定时报
    FUNCTION_CODE_ADDITIONAL_REPORT = 0x33,   // 33H:遥测站加报报
    FUNCTION_CODE_HOURLY_REPORT = 0x34,   // 34H:遥测站小时报
    FUNCTION_CODE_MANUAL_SETTING = 0x35,   // 35H:遥测站人工置数报
    FUNCTION_CODE_PICTURE_INFO = 0x36,   // 36H:遥测站图片报或中心站查询遥测站图片采集信息
    FUNCTION_CODE_QUERY_REAL_TIME_DATA = 0x37,   // 37H:中心站查询遥测站实时数据
    FUNCTION_CODE_QUERY_TIME_PERIOD_DATA = 0x38,   // 38H:中心站查询遥测站时段数据
    FUNCTION_CODE_QUERY_MANUAL_SETTING = 0x39,   // 39H:中心站查询遥测站人工置数
    FUNCTION_CODE_QUERY_SPECIFIED_ELEMENT_DATA = 0x3A,   // 3AH:中心站查询遥测站指定要素数据
    FUNCTION_CODE_RESERVED_3B_3FH = 0x3B,   // 3B - 3FH:保留,扩展功能码
    FUNCTION_CODE_MODIFY_STATION_CONFIG = 0x40,   // 40H:中心站修改遥测站基本配置表
    FUNCTION_CODE_READ_STATION_CONFIG = 0x41,   // 41H:中心站读取遥测站基本配置表/遥测站自报基本配置表
    FUNCTION_CODE_MODIFY_RUNNING_PARAM_CONFIG = 0x42,   // 42H:中心站修改遥测站运行参数配置表
    FUNCTION_CODE_READ_RUNNING_PARAM_CONFIG = 0x43,   // 43H:中心站读取遥测站运行参数配置表/遥测站自报运行参数配置表
    FUNCTION_CODE_QUERY_PUMP_MOTOR_DATA = 0x44,   // 44H:中心站查询水泵电机实时工作数据
    FUNCTION_CODE_QUERY_TERMINAL_VERSION = 0x45,   // 45H:查询遥测终端软件版本
    FUNCTION_CODE_QUERY_STATION_STATUS = 0x46,   // 46H:查询遥测站状态和报警信息
    FUNCTION_CODE_INITIALIZE_STORAGE = 0x47,   // 47H:初始化固态存储数据
    FUNCTION_CODE_RESTORE_FACTORY_SETTINGS = 0x48,   // 48H:恢复终端出厂设置
    FUNCTION_CODE_MODIFY_PASSWORD = 0x49,   // 49H:修改密码
    FUNCTION_CODE_SET_STATION_CLOCK = 0x4A,   // 4A:设置遥测站时钟
    FUNCTION_CODE_SET_TERMINAL_IC_CARD_STATUS = 0x4B,   // 4B:设置遥测终端IC卡状态
    FUNCTION_CODE_CONTROL_PUMP_SWITCH = 0x4C,   // 4C:控制水泵开关命令/水泵状态信息自报
    FUNCTION_CODE_CONTROL_VALVE_SWITCH = 0x4D,   // 4D:控制阀门开关命令/阀门状态信息自报
    FUNCTION_CODE_CONTROL_GATE_SWITCH = 0x4E,   // 4E:控制闸门开关命令/闸门状态信息自报
    FUNCTION_CODE_WATER_QUANTITY_CONTROL = 0x4F,   // 4F:水量定值控制命令
    FUNCTION_CODE_QUERY_STATION_EVENT_RECORD = 0x50,   // 50H:中心站查询遥测站事件记录
    FUNCTION_CODE_QUERY_STATION_CLOCK = 0x51,   // 51H:中心站查询遥测站时钟
    FUNCTION_CODE_RESERVED_52H_DFH = 0x52,   // 52H - DFH:保留,扩展功能码
    FUNCTION_CODE_USER_DEFINED_EXTENSION_START = 0xE0   // E0H - FFH:用户自定义扩展区
} FunctionCode;

// 使用枚举定义标识符引导符
typedef enum {
    OBSERVATION_TIME_GUIDE = 0xF0,  // 观测时间引导符
    STATION_CODE_GUIDE = 0xF1,      // 测站编码引导符
    MANUAL_SETTING = 0xF2           // 人工置数
} IdentifierGuides;

// 定义数据格式结构体
#pragma pack(1)
typedef struct {
    uint8_t dataSize : 5;       // 自定义数据大小,5位,包括小数点后的有效位
    uint8_t decimalPlaces : 3; // 自定义数据保留小数,3位
} DataFormat;
// 定义结构体
#pragma pack(1)
typedef struct {
    uint8_t identifier;         // 自定义标识符,1字节HEX
    DataFormat data_format;
    uint8_t *user_data;        //数据为BCD码
} UserDataGroup;

#define USER_DATA_GROUP_FIX_LEN     (1+sizeof(DataFormat))  //信息组固定头长度

// 定义报文上下行标识及长度结构体
#pragma pack(1)
typedef struct {
    uint16_t isUpload: 1;   // 0表示下行,1表示上行,1位用于标识
    uint16_t reserved: 3;   // 保留3位,可用于未来扩展
    uint16_t length: 12;   // 12位用于表示报文正文长度,允许长度为0001 - 4095
} MessageIdentifierAndLength;
// 统一数据结构体
#pragma pack(1)
typedef struct {
    uint16_t start_frame;   // 帧起始符,HEX/BCD编码为7E7EH,ASCII编码为01H
    uint8_t centerStationAddress[6];   // 中心站地址,范围为1 - 255 遥测站地址
    uint16_t password; // 2字节HEX码
    uint8_t functionCode;   // 功能码
    MessageIdentifierAndLength messageIdentifierAndLength;
    uint8_t user_data_start;
    uint16_t serialNumber;   // 流水号,2字节HEX码,范围1 - 65535
    uint8_t reportTime[6];   // 发报时间,6字节BCD码,YYMMDDHHmmSS
    uint8_t *user_data;
    uint8_t end_frame;
    uint16_t checksum;      //校验码前所有字节参与校验计算
} SL651_Frame_T;

#define SL651_FRAME_FIX_HEAD_LEN    (1+6+2+1+sizeof(MessageIdentifierAndLength)+1+2+6)  //帧头到用户数据正文长度
#define SL651_FRAME_LEN(user_data_length)  (SL651_FRAME_FIX_HEAD_LEN+user_data_length+1+2)  // //帧总长度
#define SL651_DATA_LEN(frame_length)        (frame_length-2-1-5-2-1-2-1-1-2)    //报文正文长度

#endif



sl_651.c
#include "sl_651.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 生成流水号的函数
uint16_t generateSerialNumber() {
    static uint16_t currentSerialNumber = 1;
    uint16_t serialNumber = currentSerialNumber;
    currentSerialNumber++;
    if (currentSerialNumber > 65535) {
        currentSerialNumber = 1;
    }
    return serialNumber;
}

//crc校验
static uint16_t SL651_Crc16(uint8_t *buf, int usDataLen)
{
    int i;
    uint16_t crc_reg, j, check;
    crc_reg = 0xFFFF;
    for (i = 0; i < usDataLen; i++)
    {
        crc_reg = (crc_reg >> 8) ^ buf[i];
        for (j = 0; j < 8; j++)
        {
            check = crc_reg & 0x0001;
            crc_reg >>= 1;
            if (check == 0x0001)
            {
                crc_reg ^= 0xA001;
            }
        }
    }
    return crc_reg;
}

/// @brief 十进制转BCD
/// @param data 
/// @return 
static int dec2bcd(unsigned char data)
{
	unsigned char temp;
	temp = (((data / 10) << 4) + (data % 10));
	return temp;
}
/// @brief double 转换成BCD
/// @param bufIn 
/// @param dval 数据
/// @param nb_byte 总长度
/// @param nb_dec 小数点后位数
static void sl651_dec2bcd(uint8_t* bufIn, double dval, uint16_t nb_byte, int nb_dec)
{
	int val = 0;
	int data_len = 0;
	val = (int)(dval * pow(10, nb_dec));
	char tmp[32];
	memset(tmp, 0, 32);
	sprintf_s(tmp, "%d", val);
	data_len = strlen(tmp);
	memset(tmp, 0, 32);
	for (int i = 0; i < data_len; i++)
	{
		if (data_len % 2)
		{
			tmp[0] = 0;
			tmp[i + 1] = (int)(val / pow(10, data_len - i - 1)) % 10;
		}
		else
		{
			tmp[i] = (int)(val / pow(10, data_len - i - 1)) % 10;
		}
	}
	int index_tmp = 0;
	data_len = data_len % 2 == 0 ? data_len / 2 : data_len / 2 + 1;
	for (int i = nb_byte; i > 0; i--)
	{
		if ((i - data_len) > 0)
		{
			bufIn[nb_byte - i] = 0;
		}
		else
		{
			bufIn[nb_byte - i] = dec2bcd(tmp[0 + index_tmp * 2] * 10 + tmp[1 + index_tmp * 2]);
			index_tmp += 1;
		}
	}
}

/// @brief 获取用户信息组
/// @param buffer 
/// @param identifier 标识符
/// @param data_format 数据格式
/// @param user_data 用户数据 BCD
/// @param user_data_length 数据长度
/// @return 
uint16_t SL651_GetUserDataGroup(uint8_t *buffer,uint8_t identifier,DataFormat data_format,uint8_t *user_data,uint16_t user_data_length)
{
    if(buffer==0)
        return 0;
    UserDataGroup *dataGroup = (UserDataGroup *)buffer;
    dataGroup->identifier =identifier;
    dataGroup->data_format =data_format;
    memcpy(dataGroup->user_data ,user_data,user_data_length);
    return USER_DATA_GROUP_FIX_LEN+user_data_length;
}


// 填充报文帧函数
uint16_t SL651_FrameFill(uint8_t *buffer,
                         uint8_t centerStationAddress[6],   // 中心站地址,范围为1 - 255 遥测站地址
                         uint16_t password, // 2字节HEX码
                         uint8_t functionCode,   // 功能码
                         MessageIdentifierAndLength messageIdentifierAndLength,
                         uint8_t reportTime[6],   // 发报时间,6字节BCD码,YYMMDDHHmmSS
                         uint8_t *user_data,     // 用户数据
                         uint16_t user_data_length   // 用户数据长度
                        ) 
{
    SL651_Frame_T *frame = (SL651_Frame_T *)buffer;
    // 填充帧起始符
    frame->start_frame = SOH;
    // 填充中心站地址
    memcpy(frame->centerStationAddress, centerStationAddress, 6);
    // 填充密码
    frame->password = password;
    // 填充功能码
    frame->functionCode = functionCode;
    // 填充报文上下行标识及长度
    frame->messageIdentifierAndLength = messageIdentifierAndLength;
    // 填充用户数据起始符(这里假设为0x02,根据实际情况可能需要调整)
    frame->user_data_start = STX;
    // 填充流水号
    frame->serialNumber = generateSerialNumber();
    // 填充发报时间
    memcpy(frame->reportTime, reportTime, 6);
    // 填充用户数据
    memcpy(frame->user_data ,user_data,user_data_length);
    //偏移指针
        frame = frame+user_data_length;
    // 填充帧结束符(这里假设为0x03,根据实际情况可能需要调整)
    frame->end_frame = ETX;
    // 计算并填充校验码
    uint16_t crc = SL651_Crc16((uint8_t *)buffer, SL651_FRAME_LEN(user_data_length)-2);
    frame->checksum = crc;
    return SL651_FRAME_LEN(user_data_length);
}


/// @brief 验证帧是否正确
/// @param buffer 
/// @param length 
/// @return 
uint8_t SL651_FrameVerification(uint8_t *buffer , uint16_t length)
{
    if(buffer == NULL)
        return 0;
    SL651_Frame_T *frame = (SL651_Frame_T *)buffer;
    if(frame->start_frame != SOH || frame->user_data_start!=STX || buffer[length-3] != ETX)
        return 0;
    if(frame->messageIdentifierAndLength.length != SL651_DATA_LEN(length))
        return 0;
    uint16_t crc =SL651_Crc16(buffer,length-2);
    if(memcmp(crc,buffer[length-2],2)!=0)
        return 0;
    return 1;
}

/// @brief 解析报文头
/// @param buffer 缓存
/// @param centerStationAddress 中心站地址
/// @param remoteAddress 遥测站地址
/// @param password 密码
/// @param functionCode 功能码
/// @param messageIdentifierAndLength  
/// @return 
uint8_t SL651_FrameHeadParse(uint8_t *buffer, uint8_t *centerStationAddress,
                             uint8_t *remoteAddress[5], uint16_t *password,
                             uint8_t *functionCode,
                             MessageIdentifierAndLength *messageIdentifierAndLength) 
{
    if (buffer == NULL)
        return 0;
    SL651_Frame_T *frame = (SL651_Frame_T *)buffer;
    // 获取报文上下行标识
    uint8_t isUpload = frame->messageIdentifierAndLength.isUpload;
    // 根据上下行标识提取中心站和遥测站地址
    if (isUpload) {
        // 上行报文:中心站地址在前 6 字节,遥测站地址紧跟其后 5 字节
        memcpy(centerStationAddress, frame->centerStationAddress, 1);
        memcpy(*remoteAddress, frame->centerStationAddress + 1, 5);
    } else {
        // 下行报文:遥测站地址在前 5 字节,中心站地址紧跟其后 6 字节
        memcpy(*remoteAddress, frame->centerStationAddress, 5);
        memcpy(centerStationAddress, frame->centerStationAddress + 5, 1);
    }
    // 提取密码
    *password = frame->password;
    // 提取功能码
    *functionCode = frame->functionCode;
    // 提取报文上下行标识及长度信息
    *messageIdentifierAndLength = frame->messageIdentifierAndLength;
    return 1;
}

sl_main.c 列程
#include "sl_651.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 遥测站自报上行报文生成函数
uint8_t* generateTelemetryStationReport(uint8_t centerStationAddress[6], uint16_t password,
                                         uint8_t reportTime[6], uint8_t *observationData,
                                         uint16_t observationDataLength) {
    // 计算总报文长度
    uint16_t totalLength = SL651_FRAME_LEN(observationDataLength);
    // 分配报文内存空间
    uint8_t *buffer = (uint8_t *)malloc(totalLength);
    if (buffer == NULL) {
        printf("内存分配失败!\n");
        return NULL;
    }

    MessageIdentifierAndLength msgIdLen = {
     .isUpload = 1,
     .reserved = 0,
     .length = totalLength - SL651_FRAME_FIX_HEAD_LEN - 1 - 2  // 减去起始符、结束符、校验码长度
    };

    // 填充报文帧
    uint16_t filledLength = SL651_FrameFill(buffer, centerStationAddress, password,
                                            FUNCTION_CODE_UNIFORM_TIME_HYDRO_INFO,
                                            msgIdLen, reportTime,
                                            observationData, observationDataLength);
    if (filledLength!= totalLength) {
        printf("遥测站自报报文填充失败!\n");
        free(buffer);
        return NULL;
    }

    return buffer;
}

// 遥测站自报上行报文解析函数
void parseTelemetryStationReport(uint8_t *message, uint16_t messageLength) {
    if (!SL651_FrameVerification(message, messageLength)) {
        printf("报文验证失败,可能损坏或格式不正确!\n");
        return;
    }

    uint8_t centerStationAddress[6];
    uint8_t *remoteAddress[5];
    uint16_t password;
    uint8_t functionCode;
    MessageIdentifierAndLength msgIdLen;

    // 解析报文头
    if (!SL651_FrameHeadParse(message, centerStationAddress, remoteAddress, &password,
                             &functionCode, &msgIdLen)) {
        printf("报文头解析失败!\n");
        return;
    }

    printf("遥测站自报上行报文解析结果:\n");
    printf("帧起始符: 0x%04X\n", ((SL651_Frame_T *)message)->start_frame);
    printf("中心站地址: ");
    for (int i = 0; i < 6; i++) {
        printf("%02X ", centerStationAddress[i]);
    }
    printf("\n");
    printf("遥测站地址: ");
    for (int i = 0; i < 5; i++) {
        printf("%02X ", (*remoteAddress)[i]);
    }
    printf("\n");
    printf("密码: 0x%04X\n", password);
    printf("功能码: 0x%02X\n", functionCode);
    printf("是否上行: %s\n", msgIdLen.isUpload? "是" : "否");
    printf("报文正文长度: %d\n", msgIdLen.length);
    printf("流水号: 0x%04X\n", ((SL651_Frame_T *)message)->serialNumber);
    printf("发报时间: ");
    for (int i = 0; i < 6; i++) {
        printf("%02X ", ((SL651_Frame_T *)message)->reportTime[i]);
    }
    printf("\n");
    // 解析用户数据部分(这里简单打印,可根据实际数据格式深入解析)
    printf("用户数据: ");
    for (int i = 0; i < messageLength - SL651_FRAME_FIX_HEAD_LEN - 1 - 2; i++) {
        printf("%02X ", ((SL651_Frame_T *)message)->user_data[i]);
    }
    printf("\n");
    printf("校验码: 0x%04X\n", ((SL651_Frame_T *)message)->checksum);
}

// 中心站查询下行报文生成函数
uint8_t* generateCentralStationQuery(uint8_t centerStationAddress[6], uint16_t password,
                                      FunctionCode functionCode, uint8_t *queryData,
                                      uint16_t queryDataLength) {
    // 计算总报文长度
    uint16_t totalLength = SL651_FRAME_LEN(queryDataLength);
    // 分配报文内存空间
    uint8_t *buffer = (uint8_t *)malloc(totalLength);
    if (buffer == NULL) {
        printf("内存分配失败!\n");
        return NULL;
    }

    MessageIdentifierAndLength msgIdLen = {
     .isUpload = 0,
     .reserved = 0,
     .length = totalLength - SL651_FRAME_FIX_HEAD_LEN - 1 - 2  // 减去起始符、结束符、校验码长度
    };

    // 填充报文帧
    uint16_t filledLength = SL651_FrameFill(buffer, centerStationAddress, password,
                                            functionCode,
                                            msgIdLen, NULL,  // 下行无发报时间
                                            queryData, queryDataLength);
    if (filledLength!= totalLength) {
        printf("中心站查询报文填充失败!\n");
        free(buffer);
        return NULL;
    }

    return buffer;
}

// 中心站查询下行报文解析函数
void parseCentralStationQuery(uint8_t *message, uint16_t messageLength) {
    if (!SL651_FrameVerification(message, messageLength)) {
        printf("报文验证失败,可能损坏或格式不正确!\n");
        return;
    }

    uint8_t centerStationAddress[6];
    uint8_t *remoteAddress[5];
    uint16_t password;
    uint8_t functionCode;
    MessageIdentifierAndLength msgIdLen;

    // 解析报文头
    if (!SL651_FrameHeadParse(message, centerStationAddress, remoteAddress, &password,
                             &functionCode, &msgIdLen)) {
        printf("报文头解析失败!\n");
        return;
    }

    printf("中心站查询下行报文解析结果:\n");
    printf("帧起始符: 0x%04X\n", ((SL651_Frame_T *)message)->start_frame);
    printf("中心站地址: ");
    for (int i = 0; i < 6; i++) {
        printf("%02X ", centerStationAddress[i]);
    }
    printf("\n");
    printf("遥测站地址: ");
    for (int i = 0; i < 5; i++) {
        printf("%02X ", (*remoteAddress)[i]);
    }
    printf("\n");
    printf("密码: 0x%04X\n", password);
    printf("功能码: 0x%02X\n", functionCode);
    printf("是否上行: %s\n", msgIdLen.isUpload? "是" : "否");
    printf("报文正文长度: %d\n", msgIdLen.length);
    printf("流水号: 0x%04X\n", ((SL651_Frame_T *)message)->serialNumber);
    // 下行无发报时间,此处不打印
    // 解析用户数据部分(这里简单打印,可根据实际数据格式深入解析)
    printf("用户数据: ");
    for (int i = 0; i < messageLength - SL651_FRAME_FIX_HEAD_LEN - 1 - 2; i++) {
        printf("%02X ", ((SL651_Frame_T *)message)->user_data[i]);
    }
    printf("\n");
    printf("校验码: 0x%04X\n", ((SL651_Frame_T *)message)->checksum);
}

// 中心站设置下行报文生成函数
uint8_t* generateCentralStationSetting(uint8_t centerStationAddress[6], uint16_t password,
                                       FunctionCode functionCode, uint8_t *settingData,
                                       uint16_t settingDataLength) {
    // 计算总报文长度
    uint16_t totalLength = SL651_FRAME_LEN(settingDataLength);
    // 分配报文内存空间
    uint8_t *buffer = (uint8_t *)malloc(totalLength);
    if (buffer == NULL) {
        printf("内存分配失败!\n");
        return NULL;
    }

    MessageIdentifierAndLength msgIdLen = {
     .isUpload = 0,
     .reserved = 0,
     .length = totalLength - SL651_FRAME_FIX_HEAD_LEN - 1 - 2  // 减去起始符、结束符、校验码长度
    } ;

    // 填充报文帧
    uint16_t filledLength = SL651_FrameFill(buffer, centerStationAddress, password,
                                            functionCode,
                                            msgIdLen, NULL,  // 下行无发报时间
                                            settingData, settingDataLength);
    if (filledLength!= totalLength) {
        printf("中心站设置报文填充失败!\n");
        free(buffer);
        return NULL;
    }

    return buffer;
}

// 中心站设置下行报文解析函数
void parseCentralStationSetting(uint8_t *message, uint16_t messageLength) {
    if (!SL651_FrameVerification(message, messageLength)) {
        printf("报文验证失败,可能损坏或格式不正确!\n");
        return;
    }

    uint8_t centerStationAddress[6];
    uint8* remoteAddress[5];
    uint16_t password;
    uint8_t functionCode;
    MessageIdentifierAndLength msgIdLen;

    // 解析报文头
    if (!SL651_FrameHeadParse(message, centerStationAddress, remoteAddress, &password,
                             &functionCode, &msgIdLen)) {
        printf("报文头解析失败!\n");
        return;
    }

    printf("中心站设置下行报文解析结果:\n");
    printf("帧起始符: 0x%04X\n", ((SL651_Frame_T *)message)->start_frame);
    printf("中心站地址: ");
    for (int i = 0; i < 6; i++) {
        printf("02X ", centerStationAddress[i]);
    }
    printf("\n");
    printf("遥测站地址: ");
    for (int i = 0; i < 5; i):
        printf("%02X ", (*remoteAddress)[i]);
    printf("\n");
    printf("密码: 0x%04X\n", password);
    printf("功能码: 0x%02X\n", functionCode);
    printf("是否上行: %s\n", msgIdLen.isUpload? "是" : "否");
    printf("报文正文长度: %d\n", msgIdLen.length);
    printf("流水号: 0x%04X\n", ((SL651_Frame_T *)image)->serialNumber);
    // 下行无发报时间,此处不打印
    // 解析用户数据部分(这里简单打印,可根据实际数据格式深入解析)
    printf("用户数据: ");
    for (int i = 0; i < messageLength - SL651_FRAME_FIX_HEAD_LEN - 1 - 2; i++) {
        printf("%02X ", ((SL651_Frame_T *)message)->user_data[i]);
    }
    printf("\n");
    printf("校验码: 0x%04X\n", ((SL651_Frame_T *)message)->checksum);
}

int main() {
    // 示例中心站地址和密码
    uint8_t centerStationAddress[6] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB};
    uint16_t password = 0x1234;

    // 生成遥测站自报上行报文示例
    uint8_t reportTime[6] = {0x23, 0x08, 0x15, 0x10, 0x00, 0x00};
    // 假设一些观测数据(这里简单示例,应根据实际数据格式构造)
    uint8_t observationData[10] = {0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x10, 0x11};
    uint8_t *telemetryStationReport = generateTelemetryStationReport(centerStationAddress, password,
                                                                      reportTime, observationData,
                                                                      sizeof(observationData));
    if (telemetryStationReport!= NULL) {
        printf("生成的遥测站自报上行报文:\n");
        for (int i = 0; i < SL651_FRAME_LEN(sizeof(observationData)); i++) {
            printf("%02X ", telemetryStationReport[i]);
        }
        printf("\n");

        // 解析遥测站自报上行报文
        parseTelemetryStationReport(telemetryStationReport, SL651_FRAME_LEN(sizeof(observationData)));

        free(telemetryStationReport);
    }

    // 生成中心站查询下行报文示例
    // 假设一些查询数据(这里简单示例,应根据实际数据格式构造)
    uint8_t queryData[5] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE};
    uint8_t *centralStationQuery = generateCentralStationQuery(centerStationAddress, password,
                                                               FUNCTION_CODE_QUERY_REAL_TIME_DATA,
                                                               queryData, sizeof(queryData));
    if (centralStationQuery!= NULL) {
        printf("生成的中心站查询下行报文:\n");
        for (int i = 0; i < SL651_FRAME_LEN(sizeof(queryData)); i++) {
            printf("%02X ", centralStationQuery[i]);
        }
        printf("\n");

        // 解析中心站查询下行报文
        parseCentralStationQuery(centralStationQuery, SL651_FRAME_LEN(sizeof(queryData)));

        free(centralStationQuery);
    }

    // 生成中心站设置下行报文示例
    // 假设一些设置数据(这里简单示例,应根据实际数据格式构造)
    uint8_t settingData[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
    uint8_t *centralStationSetting = generateCentralStationSetting(centerStationAddress, password,
                                                                   FUNCTION_CODE_MODIFY_STATION_CONFIG,
                                                                   settingData, sizeof(settingData));
    if (centralStationSetting!= NULL) {
        printf("生成的中心站设置下行报文:\n");
        for (int i = 0; i < SL651_FRAME_LEN(sizeof(settingData)); i++) {
            printf("%02X ", centralStationSetting[i]);
        }
        printf("\n");

        // 解析中心站设置下行报文
        parseCentralStationSetting(centralStationSetting, SL651_FRAME_LEN(sizeof(settingData)));

        free(centralStationSetting);
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值