主题
plc.cloud_* — 云平台通信
模块名:plc(云功能是 plc 模块的一组 cloud_ 前缀函数,不是独立模块)
把 PLC 软元件绑定成云端数据点,实现远程监控和远程控制。云连接参数(服务器、设备密钥)由上位机写进 config.lua 后由固件的引导脚本自动 cloud_bind,脚本里通常只需要处理业务数据。
函数总览
| 函数 | 作用 |
|---|---|
plc.cloud_bind(bind_table) | 把软元件批量绑定为云端数据点 |
plc.cloud_publish(...) | 手动上报若干「名称=值」数据 |
plc.cloud_subscribe(...) | 订阅云端数据点 |
plc.cloud_reg(message_type, callback_function) | 注册云事件回调 |
plc.cloud_compute(json_string) | 把任务交给云服务器执行(如发邮件) |
plc.cloud_status | 读当前的云连接状态(有没有连上、上次心跳多久前) |
常量
数据类型(用于 cloud_bind 的 type 字段)
| 常量 | 值 | 说明 |
|---|---|---|
plc.BITE | 0 | 位(只能绑 X/Y/M/S/T 触点/C 触点) |
plc.S16 | 1 | 16 位有符号整数 |
plc.S32 | 2 | 32 位有符号整数 |
plc.FLOAT | 3 | 单精度浮点 |
同步方向(用于 cloud_bind 的 mode 字段)
| 常量 | 值 | 说明 |
|---|---|---|
plc.CLOUD_UP | 0 | 仅上传:本地数据变化时发布到云 |
plc.CLOUD_DOWN | 1 | 仅下发:只接收云端写入,不上报 |
plc.CLOUD_AUTO | 2 | 双向自动同步(mode 省略时的默认值) |
事件类型(用于 cloud_reg 的第一个参数)
| 常量 | 说明 |
|---|---|
plc.PUBLISH | 数据发布成功 |
plc.SUBSCRIBE | 订阅成功 |
plc.COMPUTE | 云端计算结果返回 |
plc.cloud_bind
lua
plc.cloud_bind(bind_list)批量把软元件绑定成云端数据点。绑定后由固件按 mode 自动同步,脚本不需要再手动上报。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | bind_list | table | 是 | — | 数组,每个元素是一条绑定描述,字段见下表 |
bind_list 每个元素的字段:
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
name | string | 是 | — | 云端数据点名称 |
reg | string | 是 | — | 软元件地址字符串,如 "D100"、"M0"、"X10"、"C200",大小写均可 |
type | integer | 是 | — | plc.BITE / plc.S16 / plc.S32 / plc.FLOAT |
mode | integer | 否 | plc.CLOUD_AUTO | 同步方向 |
返回值
无返回值。地址非法的条目会被静默跳过,不报错。
示例
lua
plc.cloud_bind({
{ name = "temperature", reg = "D100", type = plc.FLOAT, mode = plc.CLOUD_UP },
{ name = "humidity", reg = "D102", type = plc.S16, mode = plc.CLOUD_UP },
{ name = "run_flag", reg = "M0", type = plc.BITE, mode = plc.CLOUD_AUTO },
{ name = "setpoint", reg = "D200", type = plc.S16, mode = plc.CLOUD_DOWN },
})说明
reg里的 X/Y 编号按八进制换算("X10"是十进制编号 8 的输入点),这与函数式plc.x(10)(十进制,第 10 号)不一致。绑定 X/Y 时应按面板丝印的八进制编号填写。type与元件必须匹配,否则该条被跳过:BITE只能用于 X/Y/M/S/T 触点/C 触点;D/R 不能用BITE。- 各元件在绑定路径下的上限:X/Y ≤ 255、M ≤ 8511、S ≤ 4095、T 触点 ≤ 511、T 当前值 16 位 ≤ 511 / 32 位 ≤ 510、C 触点 ≤ 255、C 当前值 16 位 ≤ 199 / 32 位 200-255、D ≤ 8511。
- 每处理完一条就会触发一次「完成绑定」,所以一次传完整的列表比多次调用更高效。
plc.cloud_publish
lua
plc.cloud_publish(name1, value1, [name2, value2, ...])手动上报数据点,参数成对出现。适合上报不是直接来自寄存器的计算结果。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1, 3, 5… | name | string | 是 | — | 数据点名称。空串会导致该对被丢弃 |
| 2, 4, 6… | value | any | 是 | "0" | 数据值,内部统一转成字符串上报 |
返回值
无返回值。
示例
lua
timer.start(5000, function()
local t = plc.df(100)
plc.cloud_publish("temperature", t, "status", t > 80 and "alarm" or "ok")
end)说明
- 参数个数为奇数时,最后一个落单的参数被忽略(内部按
参数总数 / 2取整成对处理)。
实用例程
lua
--订阅云服务器上的两个数据,如果多个在后面增加及可
--当订阅的数据在服务器上有变化时会自动订阅订阅数据的回调函数
plc.cloud_subscribe("stll_3177567_d7000")
ds1= timer.start(5000,function()
sjs=math.random() / 10 --产生一个动态的随机数(变化)
stll =plc.df(7000)+0.95+sjs --0.95为闸门泄放的生态流量,以后闸修复后,重新计算一个值(闸门宽4m有2个闸门共8米)
plc.df(50,stll)
print ("D50:",plc.df(50))
print ("D10:",plc.dd(10))
end)
--发布数据,这里模拟定时发送数据到云服务器
--i=0
--j=true;
--定时器=timer.start(2000,function()--定时2秒执行一次
-- if i==0 then i=1
-- elseif i==1 then i=0 end
-- j=not(j)
-- plc.cloud_publish("y1",j)--发布数据,如果多个在后面增加及可
--end
--)把上面的地址、主题、引脚替换成你项目里的即可。
plc.cloud_subscribe
lua
plc.cloud_subscribe(name1, [name2, ...])向云端订阅一个或多个数据点。订阅到的值通过绑定关系写入软元件,或在回调里处理。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1… | name | string | 是 | — | 要订阅的数据点名称,个数不限 |
返回值
无返回值。
示例
lua
plc.cloud_subscribe("setpoint", "alarm_threshold", "remote_cmd")实用例程
lua
--注册订阅数据回调:另一个PLC (SN3177567)为发电机发电流量+翻坝流量
plc.cloud_reg(plc.SUBSCRIBE,function(name,value)
print(name,value)
if name=="stll_3177567_d7000" then plc.df(7000,value) end--如果"y0"数据在服务器上变化,写入到Y0
print ("D7000:",plc.df(7000))
end
)
--订阅云服务器上的两个数据,如果多个在后面增加及可
--当订阅的数据在服务器上有变化时会自动订阅订阅数据的回调函数
plc.cloud_subscribe("stll_3177567_d7000")
ds1= timer.start(5000,function()
sjs=math.random() / 10 --产生一个动态的随机数(变化)
stll =plc.df(7000)+0.95+sjs --0.95为闸门泄放的生态流量,以后闸修复后,重新计算一个值(闸门宽4m有2个闸门共8米)
plc.df(50,stll)
print ("D50:",plc.df(50))
print ("D10:",plc.dd(10))
end)
--发布数据,这里模拟定时发送数据到云服务器
--i=0
--j=true;把上面的地址、主题、引脚替换成你项目里的即可。
plc.cloud_reg
lua
plc.cloud_reg(event, callback)注册云事件回调。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | event | integer | 是 | — | plc.PUBLISH / plc.SUBSCRIBE / plc.COMPUTE |
| 2 | callback | function | 是 | — | 事件回调。类型不是 function 会直接报错 |
返回值
无返回值。
示例
lua
plc.cloud_reg(plc.PUBLISH, function(data)
print("上报成功:", data)
end)
plc.cloud_reg(plc.COMPUTE, function(data)
print("云计算结果:", data)
end)说明
- 回调在 Lua 主线程的消息循环中执行,不要在里面做长阻塞操作。
- 每种事件只保留最后一次注册的回调。
实用例程
lua
--注册订阅数据回调:另一个PLC (SN3177567)为发电机发电流量+翻坝流量
plc.cloud_reg(plc.SUBSCRIBE,function(name,value)
print(name,value)
if name=="stll_3177567_d7000" then plc.df(7000,value) end--如果"y0"数据在服务器上变化,写入到Y0
print ("D7000:",plc.df(7000))
end
)
--订阅云服务器上的两个数据,如果多个在后面增加及可
--当订阅的数据在服务器上有变化时会自动订阅订阅数据的回调函数
plc.cloud_subscribe("stll_3177567_d7000")
ds1= timer.start(5000,function()
sjs=math.random() / 10 --产生一个动态的随机数(变化)
stll =plc.df(7000)+0.95+sjs --0.95为闸门泄放的生态流量,以后闸修复后,重新计算一个值(闸门宽4m有2个闸门共8米)
plc.df(50,stll)
print ("D50:",plc.df(50))
print ("D10:",plc.dd(10))
end)
--发布数据,这里模拟定时发送数据到云服务器把上面的地址、主题、引脚替换成你项目里的即可。
plc.cloud_compute
lua
plc.cloud_compute(json_string)把一段 JSON 任务提交给云服务器执行,结果通过 plc.cloud_reg(plc.COMPUTE, ...) 的回调返回。
服务器按 JSON 中的 cmd 字段查找对应的处理函数,使用的命令表与云平台网页调用的是同一套。设备脚本因此可以直接调用服务器端功能,其中最常用的是发送邮件(cmd = "mail_send")。
参数
| # | 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|---|
| 1 | json_string | string | 是 | — | JSON 字符串,必须是对象且带 cmd 字段 |
通用字段:
| 字段 | 必填 | 说明 |
|---|---|---|
cmd | 是 | 任务命令名,如 "mail_send"、"server_version" |
id | 否 | 任务标识。填写后服务器在回执中原样带回,用于区分对应的任务 |
返回值
无返回值(异步,结果走回调)。
示例
lua
plc.cloud_reg(plc.COMPUTE, function(jsonstring)
local ok, resp = pcall(json.decode, jsonstring)
if ok and resp.cmdreq == "ok" then
print("任务完成", resp.id)
else
print("任务失败", jsonstring)
end
end)
-- 查云服务版本
plc.cloud_compute(json.encode({ cmd = "server_version" }))
-- 发一封邮件
plc.cloud_compute(json.encode({
id = "alarm1",
cmd = "mail_send",
to = "you@example.com",
subject = "现场报警",
body = "1号泵房水位超限",
username = "yourbox@163.com", -- 发信邮箱
password = "SMTP授权码", -- 不是邮箱登录密码
}))说明
- 回执 JSON 中的
cmdreq为"ok"表示成功,否则其内容即服务器返回的错误描述。 - 设备必须已连接云服务。云连接断开时任务被丢弃,不排队补发,调用本身也不会返回失败。
- 服务器不做去重和限频,判断和限频需在脚本中自行实现。
- 完整的发邮件教程(含 SMTP 字段、限频写法、常见问题)见 快速入门 · 让设备自己发报警邮件。
例程
每个例程都是可直接下载运行的完整脚本:注册完绑定/定时器后脚本就结束,固件自动进入消息泵。 云连接参数(服务器、设备密钥)由上位机写进
config.lua、固件启动时自动cloud_bind,脚本里通常只处理业务数据。 统一模板「场景 / 完整代码 / 要点 / 验证方法 / 注意事项」。
例程 1:绑定寄存器自动上云,云端下发设定值写回 D
适用:LP3201 / LP3202 / LP3203 / LP3222 / LP3232 / LP3288 / 软PLC模拟器 / 上位机 | 依赖模块:plc(cloud_*)| 难度:★☆☆
场景:把现场温度(浮点 D100)、运行标志(M0)自动上报到云;云端页面改 setpoint 时,值要自动写回 D200 让梯形图当目标值用。绑定之后固件按 mode 自动同步,脚本不用再手动轮询上报。
完整代码(可直接下载运行):
lua
-- 上报方向:D100 浮点温度、M0 运行标志
plc.cloud_bind({
{ name = "temp", reg = "D100", type = plc.FLOAT, mode = plc.CLOUD_UP },
{ name = "running", reg = "M0", type = plc.BITE, mode = plc.CLOUD_UP },
})
-- 下发方向:云端改 setpoint 会自动写进 D200
plc.cloud_bind({
{ name = "setpoint", reg = "D200", type = plc.S16, mode = plc.CLOUD_DOWN },
})
plc.cloud_subscribe("setpoint")
-- 此后梯形图直接读 D200 当目标值,Lua 不必再管要点:
- 绑定一次传完整列表比多次调用更高效(每处理完一条都会触发一次「完成绑定」)。
mode决定同步方向:CLOUD_UP只上报、CLOUD_DOWN只接收、CLOUD_AUTO(省略时默认)双向。- 绑定 X/Y 时
reg用八进制丝印编号:"X10"是第 8 个输入点,和函数式plc.x(10)(十进制第 10 号)语义不一样,这是最容易踩的坑。 - 地址非法或类型不匹配的条目被静默跳过,不报错 —— 上线前在云平台页面核对数据点是否都出现。
验证方法:
- 上位机配好
config.lua的云参数、下载本脚本,设备连上云。 - 云平台数据点列表出现
temp/running/setpoint三项;本地改 D100 浮点,temp随即更新;置 M0,running翻 ON。 - 在云端把
setpoint改成 350:设备侧 D200 变成 350,梯形图读到新目标值。
注意事项:
cloud_bind里 X/Y 编号是八进制、函数式plc.x/y是十进制,混用会把值绑到错误的点。BITE只能绑 X/Y/M/S/T 触点/C 触点,给 D/R 写BITE会被跳过;想绑 D 用S16/S32/FLOAT。CLOUD_UP是「变化时才上报」,别指望它按固定周期推送(需要定时快照看例程 2)。
例程 2:定时把计算结果快照上报(cloud_publish + 定时器)
适用:同上 | 依赖模块:plc timer json | 难度:★☆☆
场景:云平台要看「每 5 秒一条」的曲线,但 CLOUD_UP 是变化才上报、平时不动就不发。做法是定时器里用 cloud_publish 主动成对上报,连「不是直接来自寄存器」的派生值(如状态字符串)也能一并带上。
完整代码(可直接下载运行):
lua
-- 每 5 秒主动上报一次温度快照 + 状态串
timer.start(5000, function()
local t = plc.df(100)
plc.cloud_publish(
"temperature", t,
"status", t > 80 and "alarm" or "ok"
)
end)要点:
cloud_publish参数成对出现(名称, 值, 名称, 值…);个数为奇数时最后一个落单的被忽略。- 值为
any,内部统一转字符串报上去;所以这里能把t > 80 and "alarm" or "ok"这种字符串也一起发。 - 它适合上报「计算结果」;纯寄存器镜像优先用
cloud_bind,别两个都绑同一项(重复上报)。 - 周期由
timer决定,固件不替您兜底节奏,别写while true + sleep。
验证方法:
- 下载后云平台每 5 秒收到一条
temperature快照;把 D100 浮点改成 81,同一条里status变alarm。 - 故意写成
plc.cloud_publish("a", 1, "b")奇数个参数:日志/云端只收到a,b被丢弃(验证成对规则)。
注意事项:
- 想靠
CLOUD_UP出定时曲线会失望:值不变就不发,曲线断断续续。 cloud_publish没有返回值,上报是否成功只能靠cloud_reg(plc.PUBLISH, …)的回调感知。- 参数个数为奇数时最后一个被静默丢弃,不是报错,调试时容易漏数据。
例程 3:云端下发命令触发本地动作 + 报警时发邮件
适用:同上 | 依赖模块:plc json timer | 难度:★★☆
场景:云端下发的 remote_cmd 为一台泵的启停指令,Lua 收到后写 Y0 并回 ACK;一旦本地温度超 80,除了云上报警还通过 cloud_compute 调云端发一封邮件。关键是:云连接参数不在脚本里,邮件的 SMTP 密码是授权码不是登录密码,且回执里 cmdreq == "ok" 才算成功。
完整代码(可直接下载运行):
lua
-- 订阅云端命令点
plc.cloud_subscribe("remote_cmd")
plc.cloud_reg(plc.SUBSCRIBE, function(name, value)
if name == "remote_cmd" then
plc.y(0, tonumber(value) or 0) -- 下发值写 Y0(启停泵)
print("远端命令执行: Y0 =", plc.y(0))
end
end)
plc.cloud_reg(plc.PUBLISH, function(data) print("上报成功:", data) end)
-- 温度超阈值 → 上报 + 云端发邮件
timer.start(2000, function()
if plc.df(100) > 80 then
plc.cloud_publish("temp_alarm", plc.df(100))
plc.cloud_compute(json.encode({
id = "alarm1",
cmd = "mail_send",
to = "you@example.com",
subject = "现场报警",
body = "1号泵房温度超限",
username = "yourbox@163.com", -- 发信邮箱
password = "SMTP授权码", -- 注意:是 SMTP 授权码,不是邮箱登录密码
}))
end
end)
-- 收云端计算回执
plc.cloud_reg(plc.COMPUTE, function(jsonstring)
local ok, resp = pcall(json.decode, jsonstring)
if ok and resp.cmdreq == "ok" then
print("邮件已发出,任务 id:", resp.id)
else
print("邮件任务失败:", jsonstring)
end
end)要点:
cloud_subscribe订阅后,值会写回绑定软元件,也能在cloud_reg(plc.SUBSCRIBE, …)回调里拿到(入参name, value)。cloud_compute是异步的,结果走cloud_reg(plc.COMPUTE, …)回调;回执 JSON 里cmdreq == "ok"才成功,否则cmdreq是错误描述。- 邮件的
password是邮箱的 SMTP 授权码,不是网页登录密码,填错会认证失败。 - 云连接断开时
cloud_compute的任务被丢弃且不排队补发,调用本身也不返回失败;限频、去重要在脚本里自己做。
验证方法:
- 云端把
remote_cmd设为 1:设备 Y0 吸合,日志远端命令执行: Y0 = 1。 - 把 D100 浮点改成 81:云平台出现
temp_alarm,同时yourbox@163.com收到报警邮件。 - 故意把
password写成邮箱登录密码:回执cmdreq非ok,日志打印失败信息(验证授权码要求)。 - 把
cmdreq == "ok"判据删掉重跑:即使失败也会误判成功,凸显这个判断的必要性。
注意事项:
cloud_compute回调里不判cmdreq == "ok"会「假成功」(失败也被当成完成)。- 邮件限频要自己写(脚本里加个最小间隔或计数),云端不做去重和限频。
cloud_reg每种事件只保留最后一次注册的回调,重复注册会覆盖前面那个。
注意事项
- 绑定 X/Y 用八进制编号(
"X10"= 第 8 点),这一点和plc.x(10)的十进制语义不同,最容易出错。 - 绑定条目地址或类型不合法时不会报错,只是那一条不生效。上线前用云平台页面核对数据点是否都出现了。
CLOUD_UP是「变化时上报」,不要指望它按固定周期推送;需要定时快照请用cloud_publish配合timer。- 云连接参数不在这里配置,由上位机写入
config.lua,固件启动时自动完成连接。