数据网关程序架构说明

文章详细阐述了一个数据网关程序架构的修改流程,包括新增设备集采时的步骤,如定义设备类型的json格式的key,初始化点表,配置Modbus指令,以及设置数据上传的周期。此外,还介绍了以基础款多功能表为例的设备配置,并涉及以太网配网的服务器IP、端口等参数设定。
摘要由CSDN通过智能技术生成

数据网关程序架构说明

——新增设备集采时,程序改动流程

程序架构

需改动的程序文件

序号文件说明
1json分组下的1个c、h文件                                                                                                   每种类型的设备定义在1个c文件中,根据和云平台的通信协议,定义了json的key数组、设备ID,用一个 srvc_t 类型的结构体映射了该类型设备的参数。如:基础款多功能仪表,定义在了《energy_multimeter.c》文件,对于该类型的设备,本分组只需改动这个文件即可
2collect.c定义 modbus 指令,针对具体的设备,根据设备的数据手册、通讯协议寄存器表,定义几条modbus指令,读取完所需要的数据;第2步,修改modbus轮询各设备的指令结构体 md_poll md_cmd_poll[]={设备类型代号(实际没用),设备通信地址, 读该设备需要的指令条数,指令指针,读到的数据存放位置指针}。
3time.h配置 网关上传 数据的周期,多长时间上传1其次,改宏定义值即可
4main、data_pkt配置网关要上传的设备类型
5W5500_confg.h配置 W5500本机IP,MAC、默认网关

以基础款多功能表为例进行说明

1. 定义设备类型的 json 格式的 key

修改文件《energy_multimeter.c》

key_t key7[]=
{
    "device_id",
    "device_type",
    "device_status",
    "phase_voltage_a",
    "phase_voltage_b",
    "phase_voltage_c",
    "phase_current_a",
    "phase_current_b",
    "phase_current_c",
    "active_power_a",
    "active_power_b",
    "active_power_c",
    "active_power_total",
    "reactive_power_a",
    "reactive_power_b",
    "reactive_power_c",
    "reactive_power_total",
    "power_factor_a",
    "power_factor_b",
    "power_factor_c",
    "power_factor_total",
    "active_energy_total",
    "reactive_energy_total",
    "time_energy_total",
    "switch_value_1",
    "switch_value_2",
    "line_voltage_ab",
    "line_voltage_bc",
    "line_voltage_ac",
    "apparent_power_a",
    "apparent_power_b",
    "apparent_power_c",
    "apparent_power_total",
    "frequency",   
};

这个数组定义了本设备类型对应的 json 格式的 key。要与云平台通信协议格式一致,也就是数据库中每个字段对应的文本内容。

2. 初始化本设备类型的 点表

#ifdef  __ZY_
node_table_t  zy_talbe[]=
{//中原电气仪表
//  byte    n            adr
    0,        0,        0,    
    0,        0,        0, //数据存储在 coilReg中   
    0,        0x11,        0,  //数据存储在 holdReg中  
    2,        0x00,        12,    
    2,        0x00,        13,    
    2,        0x00,        14,    
    2,        0x09,        15,    
    2,        0x09,        16,    
    2,        0x09,        17,    
    2,        0x01,        0,    
    2,        0x01,        1,    
    2,        0x01,        2,    
    2,        0x01,        3,    
    2,        0x01,        4,    
    2,        0x01,        5,    
    2,        0x01,        6,    
    2,        0x01,        7,    
    2,        0x00,        19,    
    2,        0x00,        20,    
    2,        0x00,        21,    
    2,        0x00,        22,    
    4,        0x01,        35,    
    4,        0x01,        43,    
    0,        0xAA,        0,    
    0,        0xAA,        0,    
    0,        0xAA,        0,    
    2,        0x00,        23,    
    2,        0x00,        24,    
    2,        0x00,        25,    
    2,        0x01,        8,    
    2,        0x01,        9,    
    2,        0x01,        10,    
    2,        0x01,        11,    
    2,        0x00,        27,
};
#endif

点表的数据类型定义是 结构体,指明了设备寄存器数据特性,即数据存储在本网关的寄存器地址,数据和真实值的比例关系,数据所占的字节长度。原型如下:

typedef struct
{
    u8    byte;  //变量所占字节数;当为开关量时(.n=0xff),表示本寄存器中的位地址
    u8    n;    //通道处理,10的n次方;n<=4,否则特殊处理
    u16   adr;   //寄存器地址   
}node_table_t;

对于已经有的型号,对应点表已经建立好了,就不需要改动。新的未定义的点表定义方式是:

  1. 建立Excel表格,表头有如下几个字段:key、byte(所占字节数)、n(10的次方数)、网关寄存器地址、设备寄存器地址、数据类型
  2. 对照设备的寄存器表,在上述表格中填写对应key 的数据的寄存器地址、及所占字节长度
  3. 根据设备数据说明,转化数据到真实数据,再由平台数据上传的数据比例确定 n 的值,即 上传到数据库的数据值与读到的设备数据值关系如下 数据库值 = 1 0 n × 读到的数据 数据库值 = 10^{n} ×读到的数据 数据库值=10n×读到的数据
  4. 编辑网关寄存器地址。从0开始,按照平台协议的 key 顺序 每个 key 对应1个寄存器地址对应2个字节长读,顺次递增,当数据长度是4字节时,寄存器地址增长步长为2
    如上操作完成后,将点表需要的3个字段的值,按照c语言的语法格式,初始化 node_table_t zy_talbe[] 即可。

特别说明
点表中 n 的说明:

  1. 低3位 表示10的幂次;bit3表示幂次的正负,1表示负幂次。如n=0x09,表示10的-1次幂,等于1,即读到的设备数据不用做处理,等于上传的数据

  2. n=0xAA 、A5、CC表示没有此项数据,上传到平台的数据固定或为空值

  3. n=0xBB表示数据虚拟和其他设备共用,一般用不到,可忽略这种情况

  4. 0xff,代码型开关量,设备的开关量数据存储在 保持寄存器区,用03功能码读取整个16位寄存器,读回来的数据,保存在网关的 线圈寄存器区(一般少用,可忽略)

  5. 0x11,开关量数据,用01、02功能码读取,保存在网关的 线圈寄存器区

3. 初始化 map7[] 数组的其中1个元素:点表指针

map_t   map7[]=
{//仪表类
    #ifdef  __LIKON_ 
    {.table = likon_talbe},
    #endif
    #ifdef  __BRL_
    {.table = brl_talbe}, 
    #endif
    #ifdef  __ZY_
    {.table = zy_talbe},{.table = zy_talbe},{.table = zy_talbe},{.table = zy_talbe},{.table = zy_talbe},//5
    {.table = zy_talbe},{.table = zy_talbe},{.table = zy_talbe},{.table = zy_talbe},{.table = zy_talbe},//10
    {.table = zy_talbe},{.table = zy_talbe},{.table = zy_talbe},{.table = zy_talbe},{.table = zy_talbe},//15 
    {.table = zy_talbe},{.table = zy_talbe},{.table = zy_talbe},{.table = zy_talbe},{.table = zy_talbe},//20
    {.table = zy_talbe},{.table = zy_talbe},{.table = zy_talbe},{.table = zy_talbe},{.table = zy_talbe},//25
    {.table = zy_talbe},{.table = zy_talbe},{.table = zy_talbe},{.table = zy_talbe},{.table = zy_talbe},//30
    {.table = zy_talbe},{.table = zy_talbe},{.table = zy_talbe},{.table = zy_talbe},{.table = zy_talbe},//35 
    {.table = zy_talbe},{.table = zy_talbe},{.table = zy_talbe},{.table = zy_talbe},{.table = zy_talbe},//40
    {.table = zy_talbe},{.table = zy_talbe},{.table = zy_talbe},//43
    #endif

};

map7的数据类型是结构体,定义如下

typedef struct
{
    reg_t           reg;  // 读取到的设备的原始数据
    node_table_t    *table;        //点表指针
    prprty_t        val[VAL_NUM];   //json 格式的val 值(经过了通道处理)
//    char            ID[10];
//     struct
//     {
//         u16   holdReg[VAL_NUM];    
//         u16   coilReg[VAL_NUM];
//     }; //从机返回的数据寄存器
}map_t;

有多少个设备ID就初始化多少个map元素,每个元素的点表,对应初始化为设备的点表指针。

4. 初始化 设备ID

char    *ID7[] = {
    "072302280710",
    "072302280730",
    "072302280731",
    "072302280732",
    "072302280733",
    "072302280734",
    "072302280735",
    "072302280736",
    "072302280737",
    "072302280740",
    "072302280741",
    "072302280742",
    "072302280743",
    "072302280744",
    "072302280745",
    "072302280746",
    "072302280747",
    "072302280810",
    "072302280830",
    "072302280831",
    "072302280832",
    "072302280833",
    "072302280834",
    "072302280835",
    "072302280836",
    "072302280837",
    "072302280840",
    "072302280841",
    "072302280842",
    "072302280843",
    "072302280844",
    "072302280845",
    "072302280846",
    "072302280847",
    "072302280910",
    "072302280930",
    "072302280931",
    "072302280932",
    "072302280933",
    "072302280934",
    "072302280935",
    "072302280936",
    "072302280937",

};
char    *ID7[] = {
    "072302280710",
    "072302280730",
    "072302280731",
    "072302280732",
    "072302280733",
    "072302280734",
    "072302280735",
    "072302280736",
    "072302280737",
    "072302280740",
    "072302280741",
    "072302280742",
    "072302280743",
    "072302280744",
    "072302280745",
    "072302280746",
    "072302280747",
    "072302280810",
    "072302280830",
    "072302280831",
    "072302280832",
    "072302280833",
    "072302280834",
    "072302280835",
    "072302280836",
    "072302280837",
    "072302280840",
    "072302280841",
    "072302280842",
    "072302280843",
    "072302280844",
    "072302280845",
    "072302280846",
    "072302280847",
    "072302280910",
    "072302280930",
    "072302280931",
    "072302280932",
    "072302280933",
    "072302280934",
    "072302280935",
    "072302280936",
    "072302280937",

};

至此,json分组下文件修改完毕。

5.修改《collect.c》,定义modbus指令

md_cmd_t  md_cmd_zy[]=
{//中原电气仪表
  0x03,    0x01,    0x2D,    0x00,    0x2D, //从301地址开始读取45个寄存器
};

可以有多条指令,按照如上格式,一条一条追加在后面即可。指令数据原型为:

//Modbus 轮询从机指令
typedef struct
{
    u8        func; //功能码
    u8        adrH;  //起始地址高字节
    u8        adrL; //起始地址低字节
    u8        numH;   //读取的寄存器(开关量)数量 
    u8        numL;  // 读取的寄存器(开关量)数量低字节    
}md_cmd_t;

6.初始化网关轮询485总线下的设备的 指令结构体

//modbus 轮询指令-end----------------------------------------------------------
md_poll   md_cmd_poll[]=
{
    0x07, 42, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[0].reg,
    0x07, 32, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[1].reg,
    0x07, 33, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[2].reg,
    0x07, 34, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[3].reg,
    0x07, 35, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[4].reg,
    0x07, 36, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[5].reg,
    0x07, 39, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[6].reg,
    0x07, 40, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[7].reg,
    0x07, 41, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[8].reg,
    0x07, 22, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[9].reg,
    0x07, 23, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[10].reg,
    0x07, 26, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[11].reg,
    0x07, 27, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[12].reg,
    0x07, 28, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[13].reg,
    0x07, 29, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[14].reg,
    0x07, 30, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[15].reg,
    0x07, 31, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[16].reg,
    0x07, 1, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[17].reg,
    0x07, 2, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[18].reg,
    0x07, 3, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[19].reg,
    0x07, 6, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[20].reg,
    0x07, 7, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[21].reg,
    0x07, 8, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[22].reg,
    0x07, 9, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[23].reg,
    0x07, 10, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[24].reg,
    0x07, 11, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[25].reg,
    0x07, 12, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[26].reg,
    0x07, 13, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[27].reg,    
    0x07, 14, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[28].reg,
    0x07, 15, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[29].reg,
    0x07, 16, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[30].reg,
    0x07, 19, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[31].reg,
    0x07, 20, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[32].reg,
    0x07, 21, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[33].reg,
    0x07, 53, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[34].reg,
    0x07, 43, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[35].reg,
    0x07, 44, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[36].reg,
    0x07, 45, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[37].reg,
    0x07, 46, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[38].reg,
    0x07, 47, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[39].reg,
    0x07, 48, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[40].reg,
    0x07, 50, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[41].reg,
    0x07, 51, sizeof(md_cmd_zy)/sizeof(md_cmd_t), md_cmd_zy,&map7[42].reg,

};
数据原型:
typedef struct
{
    u8        devType;
    u8        adr;  //modbus 从机地址        
    u8        num;  //每种设备类型的指令条数 =sizeof(.cmd)/sizeof(md_cmd_t)
    md_cmd_t  *cmd; //每种类型对应的几条Modbus指令
    reg_t     *reg; //从机,返回的数据存储寄存器
}md_poll;   //可根据设备类型,处理相应的返回数据

注意:前文定义的 ID 和这里的 从机地址、返回的数据存储寄存器,需要对应,否则设备数据会对应错误

7.初始化大类设备结构体数组
定义了本网关,要采集的设备类型,及对应设备类型的 ID指针,可以有多种不同类型的设备,逐条追加即可

//注册所接的终端设备---用户初始化自定义---------------------
psrvc_t service[] = {
    &multimeter,         ID7,
//        &double_power,       ID8,
};
//----------------------------------------------------------

以太网方式的程序,本结构体初始化 在文件《data_pkt.c》中;
4G程序,本结构体初始化在《main.c》中。

8.定义数据上传的频次
修改 time.h 文件 宏定义
以太网方式

#define  Ts(a)     (a * 1000)  //a 秒
#define  Tms(a)    (a)  //a 毫秒
#define  T_net     Tms(400)    //上传周期

4G方式

#define  Tmin(a)     (a * 60 *1000)  //a 分钟
#define  T_4G        Tmin(1) //4G上传周期

至此,数据采集相关的修改已完成


以太网配网

配置服务器 IP、端口(对应本司服务器固定,不用配置),文件《W5500_confg.h》

#define  MAX_CONTENT_LENGTH    16000               //16k字节内,发送的报文长度 14600
#define  SERVER_IP             114,115,221,203     //服务器域名/IP
#define  SERVER_PORT           6003                //服务器端口号    
#define  URL                   "/hardware/t2?"     //url
/*定义MAC地址,如果多块W5500网络适配板在同一现场工作,请使用不同的MAC地址*/
#define  MAC_DEF              192,168,1,88

配置本数据网关的IP等参数

#define  MAC_W5500       {0x00,0x08,0xdc,0x11,0x11,0x21}

/*定义默认IP信息*/
#define  LOCAL_IP        {192,168,0,51}            /*定义W5500默认IP地址*/
#define  SUBNET          {255,255,255,0}        /*定义W5500默认子网掩码*/
#define  GATEWAY         {192,168,0,1}            /*定义W5500默认网关*/
#define  DNS_SERVER      {114,114,114,114}        /*定义W5500默认DNS*/

#define  LOCAL_PORT      (5000)                 //本地端口
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值