主题
mc_server — 三菱 MC 协议从站服务器
模块名:mc_server
让本机变成一台三菱 MC 协议从站(FX3U-ENET-ADP 兼容,1E 帧 / 格式 1),触摸屏(GT Designer)、组态软件或其它 MC 主机可以通过网络直接读写本机 PLC 软元件。协议解析和软元件映射固件已做好,脚本只要 start 一下,不用注册回调。
函数总览
库级函数
| 函数 | 作用 |
|---|---|
mc_server.start([port, max_sockets, buffer_size]) | 启动服务器 |
对象上只有 __gc,没有其它方法。被回收时自动停止服务。
mc_server.start
lua
mc_server.start([port, max_sockets, buffer_size]) --> server启动 MC 协议从站并立即监听。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | port | integer | 否 | 5000 | 监听端口 |
| 2 | max_sockets | integer | 否 | 1 | 最大并发客户端数 |
| 3 | buffer_size | integer | 否 | 1024 | 每连接的收发缓冲区字节数 |
返回值
| 类型 | 说明 |
|---|---|
| userdata | 服务器对象。必须用全局变量接住,被 GC 回收会立刻停止服务 |
示例
lua
-- 5000 端口,允许 2 个客户端同时连
server = mc_server.start(5000, 2)说明
- 没有停止方法。要停就让持有它的变量置
nil并等 GC,或重启脚本。 - 没有任何身份认证,也不校验 PC 站号(报文里 PC 号必须是
0xFF,其它值会返回错误)。任何能连到端口的客户端都能读写本机 PLC。不要暴露在公网,放内网或用防火墙限制。 - 同时支持 BIN 和 ASCII 两种帧格式,服务端按首字节自动识别,触摸屏侧选哪种都行。
实用例程
lua
--开启mc协议服务器,端口为5000
mcs=mc_server.start(5000,4,1024)
--读取电表
state=data.creat(0)
dlt=com_dlt645.creat('<设备ID或凭据>',state)--建立电表驱动参数为表号12位表号2007广播表号
kwh=data.creat(0)
kw=data.creat(0)
dlt:add_channel(com_dlt645.KW_2007,kw);--读取功率
dlt:add_channel(com_dlt645.KWH_2007,kwh);--读取正向有功总电量到D0
com1=com.setup(1,2400,com.EVEN,8,1)--打开串口父设备2007表默认2400BPS
com1:add_device(dlt)--在串口父设备中加入电表子设备
com1:start()--启动串口父设备
local 倍率=1
dssc=timer.start(5000,function()--启动定时器 5 秒发布一个数据
local kwhreal=kwh:get_num()*倍率
--local kwhreal = string.format("%.2f",kwh:get_num()*倍率)
local jsontable =
{
name="<名称>",
kw=kw:get_num()*倍率,
kwh = kwhreal,
}
plc.df(200,kwhreal)--把电能浮点值保存到D200
local jsonstring = json.encode(jsontable)
--print(jsonstring)
print("<名称>",plc.df(200),"<名称>",plc.dd(204))
end
)把上面的地址、主题、引脚替换成你项目里的即可。
mc_server.creat / mc_server.set / mc_server.get_bool / mc_server.get_num / mc_server.get_string —— 本模块没有这些函数
有些流传的 API 清单会把这五个名字挂在 mc_server 名下——那不可信。mc_server 模块从注册到运行只有 start 一个入口,对象上也只有回收用的 __gc。对服务器对象调用任何别的方法都会直接报错:
lua
server = mc_server.start(5000)
server:set(...) --> 报错:attempt to call method 'set' (a nil value)参数
这五个名字实际是 data 模块(共享变量对象)的库函数与对象方法,与 mc_server 无关:
creat—— 实际入口是data.creat([初值]),创建一个值容器set—— 实际入口是d:set(值),往容器写值(只能用冒号写法)get_num—— 实际入口是d:get_num(),按数字读出get_bool—— 实际入口是d:get_bool(),按布尔读出get_string—— 实际入口是d:get_string(),按原始字节串读出
返回值
以 mc_server.* 形式调用一律报错、没有返回值;按 data.* 形式调用时的返回值见 data 模块文档。
示例
lua
-- 正确:这五个函数在 data 模块里,用法与 mc_server 无关
value = data.creat(0)
value:set(1)
print(value:get_num(), value:get_bool()) -- 1 true支持的命令
| 命令码 | 作用 | 一次上限 |
|---|---|---|
| 00 | 成批读位(BR) | 256 点 |
| 01 | 成批读字(WR) | 32 个字 |
| 02 | 成批写位(BW) | 160 点 |
| 03 | 成批写字(WW) | 10 个字 |
| 04 | 随机写位(BT) | 80 点 |
| 05 | 随机写字(WT) | 10 个字 |
| 0x13 | 远程读(RR) | — |
| 0x14 | 远程运行/停止(RS) | — |
| 0x15 | 读 PLC 型号(PC) | — |
| 0x16 | 回环测试(TT) | — |
其它命令返回格式错误(0x11)。
可访问的软元件
位软元件(BR / BW / BT)
| MC 软元件 | 说明 |
|---|---|
| X | 输入 |
| Y | 输出 |
| M | 辅助继电器 |
| S | 状态 |
| TS | 定时器触点 |
| CS | 计数器触点 |
字软元件(WR / WW / WT)
| MC 软元件 | 说明 |
|---|---|
| D | 数据寄存器 |
| TN | 定时器当前值 |
| CN | 计数器当前值(C0–C199 为 16 位,C200–C255 为 32 位,占 2 个字) |
说明
- 软元件名是 2 字符 MC 编码(如
X、Y、M、D、TN、CN),触摸屏组态里按三菱 FX 地址直接填写即可。 - CN 的 C200–C255 是 32 位计数器,一个点占 2 个字,读写时长度要算对。
常见用法
给触摸屏开一个 MC 口
lua
server = mc_server.start(5000)触摸屏(GT Designer 等)侧配置:
- 通信协议:三菱 FX 系列 MC(FX3U-ENET-ADP,1E 帧)
- IP:本机 IP,端口:5000
- 直接用
D100、M10、Y0等地址读写
换非标端口
lua
server = mc_server.start(6000, 4)注意事项
- 必须用全局变量持有返回值,
local出作用域后服务会停。 - 无认证、无加密,只在可信网络里开放。
- PC 站号必须是 0xFF,触摸屏侧按 FX3U-ENET-ADP 默认配置即可。
- 想同时以主站身份采集三菱 PLC,用
pipe.setup("mc", ...)(仅上位机 / Linux 版本),两者不冲突。
例程
本模块从注册到运行只有
start一个入口,没有回调、没有set/creat/get_*等方法。脚本只要start并全局持有返回对象即可。统一模板「场景 / 完整代码 / 要点 / 验证方法 / 注意事项」。
例程 1:给触摸屏开一个 MC 口
适用:LP3201 / LP3202 / LP3203 / LP3222 / LP3232 / LP3288 / 软PLC模拟器 / 上位机 | 依赖模块:mc_server | 难度:★☆☆
场景:现场一台三菱系触摸屏(GT Designer),希望直接读写本机 PLC 的 D/M/Y,无需任何 Lua 逻辑。
完整代码(可直接下载运行):
lua
server = mc_server.start(5000) -- 默认端口 5000,必须用全局变量持有要点:
- 只有
start一个入口,无需注册回调;协议解析和软元件映射固件已完成。 - 返回对象必须用全局变量接住,被 GC 回收后服务立即停止。
验证方法:
- 触摸屏侧配:三菱 FX 系列 MC(FX3U-ENET-ADP,1E 帧),IP 填本机、端口 5000。
- 直接用
D100、M10、Y0等地址读写,应实时生效。
注意事项:
- 无任何身份认证,谁连上就能读写本机 PLC——只放内网,公网务必用防火墙限制。
- 触摸屏侧 PC 站号必须填 0xFF(FX3U-ENET-ADP 默认),填别的会被拒。
local server = ...在脚本主体里出作用域后服务会停,用全局变量。
例程 2:换非标端口 / 允许多个客户端
适用:同上 | 依赖模块:mc_server | 难度:★☆☆
场景:502/5000 被占用,或要同时接多台上位机。
完整代码(可直接下载运行):
lua
server = mc_server.start(6000, 4) -- 端口 6000,最多 4 个客户端同时连要点:
- 第 2 参
max_sockets默认 1;第 3 参buffer_size默认 1024。 - 同时支持 BIN 和 ASCII 两种帧格式,服务端按首字节自动识别。
验证方法:多台触摸屏/组态连 6000 端口均可用。
注意事项:默认 max_sockets=1,第二台连不上要显式调大;返回对象仍须全局持有。
例程 3:注意事项——误以为 mc_server 有 creat/set 等方法
适用:同上 | 依赖模块:mc_server data | 难度:★☆☆
场景:某些自动生成的 API 清单会把 creat/set/get_num/get_bool/get_string 挂在 mc_server 名下——那是错的。这五个名字实际属于 data 模块。
完整代码(可直接下载运行):
lua
-- ❌ 错误:mc_server 对象上调这些方法会直接报错
server = mc_server.start(5000)
server:set(...) --> attempt to call method 'set' (a nil value)
-- ✅ 正确:这些函数在 data 模块里
value = data.creat(0)
value:set(1)
print(value:get_num(), value:get_bool()) -- 1 true要点:
mc_server从注册到运行只有start;对象上也只有回收用的__gc,没有别的实例方法。creat/set/get_num/get_bool/get_string都是data模块的库函数/对象方法,与mc_server无关。
验证方法:正确写法不报错并打印 1 true;错误写法直接抛 nil method 异常。
注意事项:想临时存个值、改 mc_server 对象——做不到,用 data.creat 建独立共享对象。