主题
HTTP 客户端例程 2:事件触发的同步上报(要服务端回执时才值得同步)
这一页只讲这一个例程。同组其余例程、以及这个库的函数说明都在 05-01-http。
适用:同上 | 依赖模块:http json timer plc | 难度:★☆☆
场景:梯形图判到「料位超高」把 M10 置 1,Lua 轮询到 M10 的上升沿就上报一条告警,并把服务端返回的告警编号写回 D210;处理完把 M11 置 1 通知梯形图「已上报」,梯形图据此清掉 M10。Lua 这一侧只做「需要回执的一次性 POST」,这类事剩下 99% 的周期上报都应该走异步(例程 3)。
完整代码(可直接下载运行):
lua
-- 梯形图 → M10(报警发生) → Lua 上报 → M11(已上报) → 梯形图清 M10
local ALARM = "http://192.168.1.10:8080/api/alarm"
httpc = http.creat(ALARM)
httpc:add_head("Content-Type", "application/json")
local last = 0
timer.start(1000, function()
local now = plc.m(10)
if now ~= 1 or last == 1 then -- 只在 M10 的上升沿上报一次
last = now
return
end
last = now
local body = json.encode({
dev = plc.plc_name(),
code = "LEVEL_HIGH",
ts = os.time()
})
local resp, err = httpc:post(body)
if resp then
local ok, r = pcall(json.decode, resp)
plc.d(210, (ok and r and tonumber(r.id)) or 0)
plc.m(11, 1) -- 通知梯形图:这条已上报
print("告警已上报,回执:", resp)
else
print("告警上报失败:", err, "—— M11 不置位,下个扫描周期会重试")
end
end)要点:
- 上升沿要自己记:
last变量保存上一次读到的 M10 状态,只在0 → 1那一刻上报,避免 M10 一直为 1 时每秒刷一条告警。 - 同步 POST 的代价是「上行这段时间整个 Lua 都不动」,所以前提一定是低频、偶发;持续采集上报请用
post_asy。 - 回执里的
id写回 D210,上位机画面或梯形图可以直接显示「当前告警号」。 - 失败时故意不置 M11:梯形图看到 M11 没来就会把 M10 留着,下一轮自动重试 —— 告警不能因为一次网络抖动就丢。
- 握手位建议成对使用(M10 请求 / M11 应答),具体约定见 Lua 与 PLC 协同开发。
验证方法:
- 下载脚本后,在上位机「在线监视」里把 M10 置 ON(真机上让梯形图的比较触点接通即可)。
- 日志出现
告警已上报,回执: {"id":12,...};D210 变成服务端返回的编号;M11 自动置 1。 - M10 保持 ON 不再重复上报(日志里只有一条)。
- 停掉服务端再置一次 M10:日志打印失败且 M11 不置位,恢复服务端后自动补报成功。
注意事项:
os.time()在没校过时的设备上是 0,服务端收到的时间戳没意义;开机先跑一次 NTP 校时(net.get_ntp_time_async+plc.rtc_set)。- 别把同步 POST 写进 10 秒以内的定时器:一次 15 秒的超时会把整条通道堵死。
- 回执不一定配 JSON:
pcall之后的字段也要用tonumber(...) or 0兜底,不能直接r.id参与运算。