跳转至

IEC104服务器接口说明

一、使用示例

创建4种信息对象(对应四摇信号),将这4种数据对象添加到1个“104服务站点”上,将“104服务站点”挂载到“104服务通道”上

#include "iec104_server/iec104_info_obj.h"
#include "iec104_server/iec104_server_dev.h"
#include "iec104_server/iec104_server_ch.h"
#include <unistd.h>
#include <stdio.h>

int main()
{
    // 信息对象1-遥信 M_SP_NA_1 单点遥信变位
    Iec104InfoObj obj1(Iec104InfoObj::M_SP_NA_1, 0x1000, 10);
    // 信息对象2-遥测 M_ME_NC_1 短浮点数
    Iec104InfoObj obj2(Iec104InfoObj::M_ME_NC_1, 0x2000, 10);
    // 信息对象3-遥控 C_SC_NA_1 单点遥控
    Iec104InfoObj obj3(Iec104InfoObj::C_SC_NA_1, 0x3000, 10);
    // 信息对象4-遥调 C_SE_NC_1 设定浮点数值命令
    Iec104InfoObj obj4(Iec104InfoObj::C_SE_NC_1, 0x4000, 10);

    // 创建IEC104服务站点
    Iec104ServerDev dev(1);
    // 为站点挂载信息对象
    dev.AddInfoObj(&obj1);
    dev.AddInfoObj(&obj2);
    dev.AddInfoObj(&obj3);
    dev.AddInfoObj(&obj4);

    // 创建IEC104服务通道
    Iec104ServerCh ch("0.0.0.0", 2404);
    // 为通道挂载设备
    ch.MountDev(&dev);
    // 设置通道定时上报间隔
    ch.SetScheduleReportInterval(10);
    // 启动运行
    ch.Run();

    int count = 0;
    sleep(5);
    while(1) {
        /***************** 信息对象1-遥信 设置单个点的值 *****************/
        int value1[10] = { 0 };
        value1[0] = 1;  obj1.SetDataValue(0x1000, &(value1[0]));
        value1[1] = 0;  obj1.SetDataValue(0x1001, &(value1[1]));
        value1[2] = 1;  obj1.SetDataValue(0x1002, &(value1[2]));
        value1[3] = 0;  obj1.SetDataValue(0x1003, &(value1[3]));
        value1[4] = 1;  obj1.SetDataValue(0x1004, &(value1[4]));
        value1[5] = 0;  obj1.SetDataValue(0x1005, &(value1[5]));
        value1[6] = 1;  obj1.SetDataValue(0x1006, &(value1[6]));
        value1[7] = 0;  obj1.SetDataValue(0x1007, &(value1[7]));
        value1[8] = 0;  obj1.SetDataValue(0x1008, &(value1[8]));
        value1[9] = 1;  obj1.SetDataValue(0x1009, &(value1[9]));
        printf("count=%d, Set addr=[%04X]%5d, value1={%d, %d, %d, %d, %d, %d, %d, %d, %d, %d}\r\n",
            count, 0x1000, 0x1000,
            value1[0], value1[1], value1[2], value1[3], value1[4], value1[5], value1[6], value1[7], value1[8], value1[9]);

        /***************** 信息对象2-遥测 设置多个点的值 *****************/
        float value2[10] = { 0.12, 1.23, 2.34, 3.45, 4.56, 5.67, 6.78, 7.89 };
        value2[8] = count /100.0 + 100;
        value2[9] = count /200.0 + 200;
        obj2.SetDataValue(0x2000, value2, 10);
        printf("count=%d, Set addr=[%04X]%5d, value2={%.02f, %.02f, %.02f, %.02f, %.02f, %.02f, %.02f, %.02f, %.02f, %.02f}\r\n",
            count, 0x2000, 0x2000,
            value2[0], value2[1], value2[2], value2[3], value2[4], value2[5], value2[6], value2[7], value2[8], value2[9]);

        /***************** 信息对象3-遥控 获取单个点的值 *****************/
        int value3[10] = {0};
        obj3.GetDataValue(0x3000, &(value3[0]));
        obj3.GetDataValue(0x3001, &(value3[1]));
        obj3.GetDataValue(0x3002, &(value3[2]));
        obj3.GetDataValue(0x3003, &(value3[3]));
        obj3.GetDataValue(0x3004, &(value3[4]));
        obj3.GetDataValue(0x3005, &(value3[5]));
        obj3.GetDataValue(0x3006, &(value3[6]));
        obj3.GetDataValue(0x3007, &(value3[7]));
        obj3.GetDataValue(0x3008, &(value3[8]));
        obj3.GetDataValue(0x3009, &(value3[9]));
        printf("count=%d, Get addr=[%04X]%5d, value3={%d, %d, %d, %d, %d, %d, %d, %d, %d, %d}\r\n",
            count, 0x3000, 0x3000,
            value3[0], value3[1], value3[2], value3[3], value3[4],
            value3[5], value3[6], value3[7], value3[8], value3[9]);

        /***************** 信息对象4-遥调 获取多个点的值 *****************/
        float value4[8] = { 0 };
        obj4.GetDataValue(0x4000, value4, 8);
        printf("count=%d, Get addr=[%04X]%5d, value4={%.02f, %.02f, %.02f, %.02f, %.02f, %.02f, %.02f, %.02f}\r\n\r\n",
            count, 0x4000, 0x4000,
            value4[0], value4[1], value4[2], value4[3], value4[4], value4[5], value4[6], value4[7]);

        count++;
        sleep(1);
    }

    return 0;
}

二、Iec104InfoObj类

iec104信息对象类

1. 构造函数

/**
 * @brief 构造函数
 *
 * @param asdu_type     ASDU类型
 * @param start_addr    起始地址
 * @param num           数量
 */
Iec104InfoObj(AsduType_E asdu_type, int start_addr, int num);
  • 参数
  • asdu_type ASDU类型(信息对象类型)
  • start_addr 信息对象点的起始地址
  • num 信息对象点的数量

2. 析构函数

/**
 * @brief 析构函数
 */
~Iec104InfoObj();

3. 设置连续多个数据点的数值

/**
 * @brief 设置连续多个数据点的数值
 *
 * @param start_addr 数据点地址;
 * @param *value     点的值;
 * @param nb         数据点个数;
 *
 * @return 是否合法:1-合法地址;-1-非法地址;
 */
int SetDataValue(int start_addr, int *value, int nb = 1);
int SetDataValue(int start_addr, float *value, int nb = 1);
  • 参数
  • start_addr 数据点地址;
  • value 点的值;
  • nb 数据点个数;
  • 返回值
  • 是否合法:1-合法地址;-1-非法地址;

4. 获取连续多个数据点的数值

/**
 * @brief 获取连续多个数据点的数值
 *
 * @param start_addr 数据点地址;
 * @param *value     点的值;
 * @param nb         数据点个数;
 *
 * @return 是否合法:1-合法地址;-1-非法地址;
 */
int GetDataValue(int start_addr, int *value, int nb = 1);
int GetDataValue(int start_addr, float *value, int nb = 1);
  • 参数
  • start_addr 数据点地址;
  • value 点的值;
  • nb 数据点个数;
  • 返回值
  • 是否合法:1-合法地址;-1-非法地址;

二、Iec104ServerDev类

IEC104服务器的站点

1. 构造函数

/**
 * @brief 构造函数
 *
 * @param addr 站地址
 */
Iec104ServerDev(int addr);

参数

  • addr 站地址(ASDU公共地址);

2. 析构函数

/**
 * @brief 析构函数
 */
~Iec104ServerDev();

3. 获取站地址(ASDU公共地址)

/**
 * @brief 获取站地址(ASDU公共地址)
 *
 * @return 站地址(ASDU公共地址)
 */
int GetAddr();

4. 挂在信息对象

/**
 * @brief 挂添加信息对象
 *
 * 向站点添加信息对象
 *
 * @param obj     信息对象指针;
 * @param iscover 是否强制覆盖(已存在相同类型是否覆盖
 *
 * @return 是否添加成功:1-添加成功;-1-添加失败;
 */
int AddInfoObj(Iec104InfoObj *obj, int iscover = 0);
  • 参数
  • obj 信息对象指针;
  • iscover 是否强制覆盖(已存在相同类型是否覆盖)
  • 返回值
  • 是否添加成功:1-添加成功;-1-添加失败;

5. 获取信息对象的容器指针

/**
 * @brief 获取信息对象的Map容器
 *
 * @param 无
 *
 * @return 返回信息对象的Map容器指针
 */
std::map<Iec104InfoObj::AsduType_E, Iec104InfoObj*> *GetInfoObjMap();
  • 参数
  • 返回值
  • 返回信息对象的Map容器指针

三、Iec104ServerCh类

IEC104通讯通道

1. 构造函数

/**
 * @brief 构造函数
 *
 * @param *ip_addr 本机监听的IP地址,一般为"0.0.0.0";
 * @param port     本机监听的端口号,一般为2404;
 */
Iec104ServerCh(const char *ip_addr = "0.0.0.0", int port = 2404);
  • 参数
  • *ip_addr 本机监听的IP地址,一般为"0.0.0.0";
  • port 本机监听的端口号,一般为2404;

2. 析构函数

/**
 * @brief 析构函数
 */
~Iec104ServerCh();

3. 挂载站点

/**
 * @brief 挂载站点
 *
 * 向IEC104通道挂载站点
 *
 * @param dev     站点;
 * @param iscover 是否强制覆盖(已存在相同站地址时是否覆盖);
 *
 * @return 是否添加成功:1-添加成功;-1-添加失败;
 */
int MountDev(Iec104ServerDev *dev, int cover = 0);
  • 参数
  • dev 站点;
  • iscover 是否强制覆盖(已存在相同站地址时是否覆盖);
  • 返回值
  • 是否添加成功:1-添加成功;-1-添加失败;

4. 获取指定站地址的站点指针

/**
 * @brief 获取指定站地址的站点指针
 *
 * @param addr 站点地址;
 * @param *dev 返回的站点指针;
 *
 * @return 是否获取成功:1-获取成功;-1-获取失败;
 */
int GetDev(int devaddr, Iec104ServerDev **dev);
  • 参数
  • addr 站点地址;
  • *dev 返回的站点指针;
  • 返回值
  • 是否获取成功:1-获取成功;-1-获取失败;

5. 启动函数

/**
 * @brief 启动函数
 *
 * @param 无
 *
 * @return 无
 */
void Run();

6. 设置最大连接数

/**
 * @brief 设置最大连接数
 *
 * @param max_conn 最大连接数,默认为10;
 *
 * @return 无
 */
void SetMaxConn(int max_conn = 10);
  • 参数
  • max_conn 最大连接数,默认为10;
  • 返回值
  • 无;

7. 设置链路滑动窗口I帧最大限制数

/**
 * @brief 设置链路滑动窗口I帧最大限制数
 *
 * @param k 发送尚未确认I帧数量,默认为12;
 * @param w 接收暂不确认I帧数量,默认为8;
 *
 * @return 无
 */
void SetSlidingWindowIframeLimit(int k = 12, int w = 8);
  • 参数
  • k 发送尚未确认I帧数量,默认为12;
  • w 接收暂不确认I帧数量,默认为8;
  • 返回值
  • 无;

8. 设置连接超时时间

/**
 * @brief 设置连接超时时间
 *
 * @param t0 TCP连接超时,默认为10s;
 * @param t1 帧确认超时,默认为15s;
 * @param t2 无捎带I帧超时发送S帧,默认为10s;
 * @param t3 活跃检测超时,默认为20s;
 *
 * @return 无
 */
void SetLinkTimeout(int t0 = 10, int t1 = 15, int t2 = 10, int t3 = 20);
  • 参数
  • t0 TCP连接超时,默认为10s;
  • t1 帧确认超时,默认为15s;
  • t2 无捎带I帧超时发送S帧,默认为10s;
  • t3 活跃检测超时,默认为20s;
  • 返回值
  • 无;

9. 设置定时上报周期

/**
 * @brief 设置定时上报周期
 *
 * @param interval_s 定时上报周期,单位为秒;
 *
 * @return 无
 */
void SetScheduleReportInterval(int interval_s = 10);
  • 参数
  • interval_s 定时上报周期,单位为秒;
  • 返回值
  • 无;