APRUS Lua-ModbusServer配置说明
第一章 概述
1.1 文档说明
APRUS适配器可配置为Modbus服务器,支持与其他支持Modbus协议的客户端设备进行通信。APRUS Lua-ModbusServer主要包括两个文件:aprus.lua和config.lua。配置为Modbus服务器后,用户可将设备运行的过程数据和结果放置到服务器的数据中,供其他设备读取和写入。本文将介绍如何将APRUS适配器可配置为Modbus服务器,并解释各参数的含义。
1.2 参考资料
- 《APRUS Lua-数据中心 配置说明》
- 《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配置说明
对于ModbusServer
的config.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
表示新建一个站点,db1
、db2
、db3
、db4
对应Modbus的01、02、03、04四种功能码。如果不想提供某个功能码,则对应的db字段不填就可以。相反,如果想实现全部4种功能码则需全部填写。配置错误会产生无法预料的错误。数据中心相关知识,请参考《APRUS编程手册_数据中心.pdf》。