APRUS Lua-ModbusServer配置说明

第一章 概述

1.1 文档说明

APRUS适配器可配置为Modbus服务器,支持与其他支持Modbus协议的客户端设备进行通信。APRUS Lua-ModbusServer主要包括两个文件:aprus.lua和config.lua。配置为Modbus服务器后,用户可将设备运行的过程数据和结果放置到服务器的数据中,供其他设备读取和写入。本文将介绍如何将APRUS适配器可配置为Modbus服务器,并解释各参数的含义。

1.2 参考资料

  1. 《APRUS Lua-数据中心 配置说明》
  2. 《APRUS Lua-AXIO 配置说明》

第二章 配置说明

2.1 aprurs.lua配置

说明:function start() 为主流程入口函数

package.cpath="./?.so"
package.path="./?.lua"
cjson = require "cjson"
config = require "config"
require "AXio"
require "ModbusServer"

function ModbusServer_init()
    mbSvrObj = ModbusServer.new("ModbusServer")
    local MBCfg = cjson.encode(config.ModbusServer.ServerConfig)
    local ret = ModbusServer.config(mbSvrObj, MBCfg)
    --ModbusServer.debug(mbSvrObj, 0x01010101)    --ModbusServer显示详尽的调试信息
end

function MBserver_load_station(svr, cfg)
    for k,v in pairs(cfg)
    do
        print("load Station" .. cjson.encode(v))
        ModbusServer.setStation(svr, cjson.encode(v))
    end    
end

function updateU16(num16)
    DataCenter.DBsetRecord(dbAXio_AI, 17 , num16)
end

function updateU32(num32)
    tl = math.floor(num32 % 0x10000)        --取余
    th,f = math.modf(num32 / 0x10000)        --取整
    DataCenter.DBsetRecord(dbAXio_AI, 16 , th)
    DataCenter.DBsetRecord(dbAXio_AI, 17 , tl)
end

function act_control(m, json)
    for k,v in pairs(json) do
        if k ~= "Act" then
           AXio.write(axioObj, k, v)
        end
    end
end

function mqttdata_handle(m, topic, data)
    local json = cjson.decode(data)
    if json.Act == "Control" then
        act_control(m, json)
    end
end

function mqttsys_handle(m, code)
    if code == 0 then
--        AXio.stop(axioObj)
    elseif code == 1 then
        --AXio.run(axioObj)
    end    
end

function ioevent_handle(session, code, style_L, val_L, style_E, val_E, z)    
    if code == 15 then
        local json = cjson.encode(iobuf[session])
        mqtt.publish(mqtt3Obj, iostr[session], "r", json)    
        iobuf[session] = {}        
    elseif code > 10 then
        iobuf[session][style_L] = val_L
        iobuf[session][style_E] = val_E        
    else 
        local json = cjson.encode({[style_L] = val_L, [style_E] = val_E, ["Z"] = z})
        mqtt.publish(mqtt3Obj, iostr[session], "r", json)        
    end
end

function io_load_nodes(session, nodes)
    for k,v in pairs(nodes)
    do
        AXio.add_node(session, v.m, v.index, v.interval, v.dtype, v.cntmode, v.pMode, v.dStyle, v.dOffset, v.dExt)
    end    
end

function loadDatabase(dbs)
    for k,v in pairs(dbs)
    do
        DataCenter.addDB(cjson.encode(v))
    end
end

function init()
    mqtt3Obj = mqtt.new()     
    user.setluaver(config.AprusX.luaver)
    user.setdevinfo(config.AprusX.devinfo)
    user.ipconfig(config.AprusX.ipmode, config.AprusX.inet_addr, config.AprusX.netmask)
end

function start()
    print("<--------------------user lua start------------------------>")
    init()
    print("<--------------------DataCenter_load_database()------------------------>")
    loadDatabase(config.DataCenter)

    IOCfg = config.AXIO
    axioObj = nil
    iobuf = {axioObj}
    iostr = {axioObj}

    print("<--------------------AXio.new()------------------------>")
    axioObj = AXio.new()
    dbAXio_AI = DataCenter.getDB("AXio_AI")
    DataCenter.DBresize(dbAXio_AI,20)
    iobuf[axioObj] = {}
    iostr[axioObj] = "io"
    print("<--------------------io_load_nodes()------------------------>")
    io_load_nodes(axioObj, IOCfg.node)

    print("<--------------------ModbusServer_init()------------------------>")
    ModbusServer_init()
    print("<--------------------ModbusStation_init()------------------------>")
    MBserver_load_station(mbSvrObj, config.ModbusServer.Stations)
    print("<--------------------ModbusServer.run------------------------>")
    ModbusServer.run(mbSvrObj)
    AXio.run(axioObj)
    mqtt.run(mqtt3Obj)

    counter = 0
    while true do
        local msg = user.waitmsg()
        if msg.from == "mqtt-sys" then
            mqttsys_handle(msg.session, msg.code)
        elseif msg.from == "mqtt-msg" then
            mqttdata_handle(msg.session, msg.topic, msg.payload)
        elseif msg.from == "io" then
            ioevent_handle(msg.session, msg.code, msg.style_L, msg.val_L, msg.style_E, msg.val_E, msg.z)

            counter = counter+1
            DataCenter.DBsetRecord(dbAXio_AI, 18 , counter)
        end
    end
end
start()
# 2. ModbusServer相关函数和操作

## 2.2 解释ModbusServer相关的函数和操作

### 2.2.1 创建ModbusServer实例

**功能:**创建ModbusServer实例  
*示例:* `mbSvrObj = ModbusServer.new("ModbusServer")`  

| 参数        || 说明                         |
|-------------|---------------|------------------------------|
| "ModbusServer" |               | 模块运行实例的名称           |

### 2.2.2 配置ModbusServer实例

**功能:**配置ModbusServer实例  
*示例:* `ModbusServer.config(mbSvrObj, MBCfg)`  

| 参数          || 说明                     |
|---------------|--------------------------------------------------|--------------------------|
| mbSvrObj      |                                                  | ModbusServer.new实例的返回值 |
| MBCfg         | `cjson.encode(config.ModbusServer.ServerConfig)` | ModbusServer配置参数(详见config.lua) |

### 2.2.3 配置Modbus站点信息

**功能:**配置Modbus站点信息  
*示例:* `ModbusServer.setStation(mbSvrObj, cjson.encode(stationConfig))`  

| 参数          || 说明                     |
|---------------|--------------------------------------------------|--------------------------|
| mbSvrObj      |                                                  | ModbusServer.new实例的返回值 |
| stationConfig |                                                  | ModbusServer的站点配置(详见config.lua) |

### 2.2.4 创建ModbusServer启动实例

**功能:**创建ModbusServer启动实例  
*示例:* `ModbusServer.run(mbSvrObj)`  

| 参数          || 说明                         |
|---------------|---------------|------------------------------|
| mbSvrObj      |               | ModbusServer.new实例的返回值 |

### 2.2.5 加载ModbusServer站点配置

**使ModbusServer加载config.lua中ModbusServer.Stations段配置的ModbusServer服务器。**

*函数原型如下(使用循环方式添加config.lua文件中Stations段的每一行):*

```lua
function MBserver_load_station(svr, cfg)
    for k,v in pairs(cfg) do
        print("load Station" .. cjson.encode(v))
        ModbusServer.setStation(svr, cjson.encode(v))
    end    
end

2. ModbusServer相关函数和操作

2.2 此处仅解释一下ModbusServer相关的函数和操作:

2.2.1 ModbusServer.new

功能:创建ModbusServer实例
示例:mbSvrObj = ModbusServer.new(“ModbusServer”)

参数 说明
“ModbusServer” 模块运行实例的名称

2.2.2 ModbusServer.config

功能:配置ModbusServer实例
示例:ModbusServer.config(mbSvrObj, MBCfg)

参数 说明
mbSvrObj ModbusServer. new实例的返回值
MBCfg cjson.encode(config.ModbusServer.ServerConfig) ModbusServer配置参数(详见config.lua)

2.2.3 MBserver.setStation

功能:配置Modbus站点信息
示例:ModbusServer.setStation(mbSvrObj, cjson.encode(stationConfig))

参数 说明
mbSvrObj ModbusServer. new实例的返回值
stationConfig ModbusServer的站点配置(详见config.lua)

2.2.4 ModbusServer.run

功能:创建ModbusServer启动实例
示例:ModbusServer.run(mbSvrObj).

参数 说明
mbSvrObj ModbusServer. new实例的返回值

2.2.5 MBserver_load_station(mbSvrObj, config.ModbusServer.Stations)

使ModbusServer加载config.lua中ModbusServer.Stations段配置的ModbusServer服务器。

函数原型如下(使用循环方式添加config.lua文件中Stations段的每一行):

function MBserver_load_station(svr, cfg)
    for k,v in pairs(cfg) do
        print("load Station" .. cjson.encode(v))
        ModbusServer.setStation(svr, cjson.encode(v))
    end    
end

1. ModbusServer调试信息启用

ModbusServer.debug(mbSvrObj, 0x01010101)
启用详细的Modbus服务器调试信息。 第一个参数为ModbusServer.new实例的返回值,第二个参数的值为32位十六进制数字,这个数值分成4个字节,单独每个字节为1时开启对应功能,为0时关闭对应功能。从低位到高4个字节的功能分别是:错误信息、连接信息和一般信息、接收内容详情、发送内容详情。此设置可以帮助您了解设备的运行情况,排查错误,优化性能。请根据需要选择要开启的调试信息级别。

例:ModbusServer.debug(mbSvrObj, 0x01000101)

LOG中打印错误信息、一般信息和发送内容详情。

2. config.lua配置说明

对于ModbusServerconfig.lua一般需要配置两大部分:ModbusServer参数(ServerConfig段)、站点配置参数(Stations段)

2.1 config.lua示例:

ModbusServer=
{
    ServerConfig=
    {
        ifname="eth0",
        ip="192.168.123.88", 
        port = 502,
    },
    Stations=
    {
        {station=1,db1="DB_1_100",db2="DB_2_100",db3="DB_3_100", db4="DB_4_100"},
        {station=2, db1="AXio_DO", db2="AXio_DI", db4="AXio_AI"},
        {station=8, db1="DB_1_100", db3="DB_3_100"},
    },
}

3.1 ModbusServer参数(ServerConfig段)

ServerConfig段参数的功能如下表所示:

序号 参数 说明
1 ifname “eth0” 绑定物理网口到指定接口(非必要)。可配置有usb0, eth0, eth0:n, eth1, wlan0。配置成非eth0:n时,请不要同时配置IP地址C_ip=”xxx”。如果不配置,使用任意可用网络连接
2 ip “192.168.123.88” 服务器IP地址(如果相应的物理网口已有地址,此处可不填写)
3 port 502 Modbus服务端口

3.2 站点配置参数(Stations段)

Stations段参数的功能如下表所示:

序号 参数 说明
1 station 1 station=站号(必要),对应ModbusServer的ID号
2 db1 “DB_1_100” 可读写开关量,对应功能码01(非必要)。这个值来自于数据中心内的数据库的名称。服务器启动时会到数据中心里查找对应名称的数据库。如果相应的数据库没有定义,则无法实现对应的功能码。要求其数据库的单元长度为1字节
3 db2 “DB_2_100” 只读开关量,对应功能码02(非必要)。要求其数据库的单元长度为1字节
4 Db3 “DB_3_100” 可读写16位数据,对应功能码03(非必要)。要求其数据库的单元长度为2字节
5 Db4 “DB_4_100” 只读16位数据,对应功能码04(非必要)。要求其数据库的单元长度为2字节

注意: config.lua中每一行station xxxxxx表示新建一个站点,db1db2db3db4对应Modbus的01、02、03、04四种功能码。如果不想提供某个功能码,则对应的db字段不填就可以。相反,如果想实现全部4种功能码则需全部填写。配置错误会产生无法预料的错误。数据中心相关知识,请参考《APRUS编程手册_数据中心.pdf》。

文档更新时间: 2025-01-10 17:44   作者:CGL