Skip to content

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 协同开发。

验证方法:

  1. 下载脚本后,在上位机「在线监视」里把 M10 置 ON(真机上让梯形图的比较触点接通即可)。
  2. 日志出现 告警已上报,回执: {"id":12,...};D210 变成服务端返回的编号;M11 自动置 1。
  3. M10 保持 ON 不再重复上报(日志里只有一条)。
  4. 停掉服务端再置一次 M10:日志打印失败且 M11 不置位,恢复服务端后自动补报成功。

注意事项:

  • os.time() 在没校过时的设备上是 0,服务端收到的时间戳没意义;开机先跑一次 NTP 校时(net.get_ntp_time_async + plc.rtc_set)。
  • 别把同步 POST 写进 10 秒以内的定时器:一次 15 秒的超时会把整条通道堵死。
  • 回执不一定配 JSON:pcall 之后的字段也要用 tonumber(...) or 0 兜底,不能直接 r.id 参与运算。

LPPLC 工业物联网云平台 · 软硬件与云平台全栈自研