【监控开发】把车间未戴帽和烟火报警接进安监值班群:workwearDetect 对图与 setMessageCallback 订 smokeAlarm

目录


车间装了镜头,安监群还是听不见

老陈管一家金属加工厂的安监信息化。冲压区、焊接工位、危化品库门口都挂着网络摄像机,回放能翻一周。夜班有人摘了安全帽进冲压区,焊接工位起了一小柱烟------第二天巡检才在硬盘里对上画面。乐橙 App 红点停在班长私人手机里,安监值班群是静的。

问题不在「没拍到」。缺的不是再买一台相机,而是把厂规着装和烟火事件接进自己的安监通道:未规范着装先出一条,烟火再单独叫醒人。

现行文档没有单独的「安全帽接口名」。安全帽走行业 AI 的工装检测:把厂规安全帽、反光衣样本注册进人形工装库,对抓图调 workwearDetect,看 detectResult。烟火不走抽烟检测接口,走设备告警大类里已经列出的 smokeAlarm / fireAlarm / heatImagingTemper,用 setMessageCallbackalarm 推到 HTTPS。

读完按这个顺序交差:

  1. 在开放平台创建应用,把车间枪机绑进开发者资产。
  2. 签名自测通过,能拿到 accessToken
  3. listDeviceDetailsByPage 能看到版本号和在线状态。
  4. 建人形工装库,注册厂规安全帽 / 工装样本。
  5. 对一张车间图调 workwearDetect,控制台打出 detectResult;未规范着装时安监群进一条。
  6. 第一闭环成立后,再订 alarm,把烟火推进同一套值班群。

金属加工车间:镜头会录,App 有红点,安监值班群没有人。本文用现行 OpenAPI 的 workwearDetect 验厂规工装(安全帽注册进工装库),再用 setMessageCallbackalarmsmokeAlarm / fireAlarm,带可运行 Node.js,验到群里响一条为止。


这篇会用到什么

只列本篇会碰到的,不是开放平台功能全集。工装接口见工装检测,AI 模块说明见智能AI服务,事件类型见事件消息类型定义

  1. workwearDetect:上传一张图,识别员工是否规范着装。detectResult=true 符合着装,false 不符合。安全帽作为厂规工装样本进库,不要另编一个头盔接口。
  2. createAiDetectRepositoryrepositoryType=human)+ addAiDetectTarget:建人形工装库,把安全帽、反光衣样本注册进去。检测时把 repositoryId 传给 workwearDetect
  3. alarm 才能收到 smokeAlarm(设备烟感)、fireAlarm(消防网关配件火警)、heatImagingTemper(温度报警)。smokingDetect 是抽烟检测,不是火情。
  4. 同时订 deviceStatus。车间掉线出 offline,别和烟火捆成同一条规则。
  5. 能力集有 MsgSW,PaaS 机用 setDeviceCameraStatusenableType 写成 msgSW,打开报警上报。headerDetect 是人头检测,不要当成安全帽开关。
  6. AI 模块是增值服务。工单或商务没开通试用,工装接口调不通。回调必须先回 HTTP 200,多次无响应平台停推。

你负责绑设备和安监值班群,开放平台负责对图验工装、把烟火推到你的 HTTPS。

text 复制代码
车间枪机 / 焊接工位
   ├─ 抓图或告警图  →  workwearDetect(+工装库)  → detectResult
   ├─ 烟火 / 热成像  →  alarm                  → smokeAlarm / fireAlarm / heatImagingTemper
   └─ 上下线         →  deviceStatus           → offline / online
                         │
                         ▼
              你的 HTTPS(立刻 200)
                         │
                         ▼
              按 deviceId 找到工段 → 安监值班群

为什么轮询、只靠 App、一上来写原生都走不通

轮询报警列表适合对账,不适合当安监主路径。扫得再勤也补不上推送那几秒,更补不上「这张图合不合格工装」------那是对图检测,不是再扫一遍列表。

只靠官方 App,红点停在班长私人手机里。他在另一个工段、通知被系统折叠,值班群不知道有人裸头进冲压区。白班动检把通知刷到「关闭」,夜班更没人看。

一上来写原生客户端没必要。安监已经在企业微信或钉钉,缺的是桥,不是第三个看监控的 App。厂门口也没法让人把镜头擦干净再重新扫码。


动手:从开应用到工装检测出第一条结果

先不要做烟火回调和回放取证。对一张车间图跑通 workwearDetect,未规范着装能进群,再谈第二层。不要在车间点火验收。

第一步:创建应用,填齐车间台账

打开 乐橙开放平台 注册并创建应用。控制台能看到 appId / appSecret 再往下做。把冲压区、焊接工位、危化品库门口的枪机绑进这个开发者资产,不要停在私人 App 号下。绑定用 bindDevicecode 是机身 8 位安全码或设备密码。准备一张能公网访问的车间抓图 URL(联调用对象存储,不要用内网路径)。AI 接口先走工单申请试用。

text 复制代码
IMOU_APP_ID=lcdxxxxxxxxx
IMOU_APP_SECRET=你的密钥
DEVICE_PRESS=冲压区序列号
DEVICE_WELD=焊接工位序列号
CHANNEL_ID=0
WORKWEAR_REPO_NAME=厂规工装库
HELMET_SAMPLE_URL=https://img.example.com/helmet-ok.jpg
WORKSHOP_SHOT_URL=https://img.example.com/press-line.jpg
THRESHOLD=0.8
HOOK_EHS=安监值班群机器人地址

成功:控制台能看到应用,设备在资产里;样本图和车间图都能用浏览器打开。

兜底:设备还在私人 App 下,先做绑定。工装接口报没权限,先把试用开下来,不要怀疑签名。

第二步:签名壳,先和文档案例对齐

请求走 https://openapi.lechange.cn/openapi/{method},壳子是 system + params + id。签名按开发规范time:{time},nonce:{nonce},appSecret:{appSecret} 拼成原始串,再做 MD5 小写 32 位。time 与服务器误差不能超过 5 分钟,否则 SN1002nonce 5 分钟内不能重复,否则 SN1005

javascript 复制代码
// openapi-client.js
const crypto = require('crypto');
const { v4: uuidv4 } = require('uuid');

const OPENAPI_BASE = 'https://openapi.lechange.cn/openapi';

function calcSign(time, nonce, appSecret) {
  const raw = `time:${time},nonce:${nonce},appSecret:${appSecret}`;
  return crypto.createHash('md5').update(raw, 'utf8').digest('hex');
}

async function callOpenApi(method, appId, appSecret, params = {}) {
  const time = Math.floor(Date.now() / 1000);
  const nonce = uuidv4();
  const body = {
    system: { ver: '1.0', appId, time, nonce, sign: calcSign(time, nonce, appSecret) },
    id: uuidv4(),
    params,
  };
  const res = await fetch(`${OPENAPI_BASE}/${method}`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body),
  });
  const json = await res.json();
  if (!json.result || json.result.code !== '0') {
    const msg = json.result ? `${json.result.code} ${json.result.msg}` : JSON.stringify(json);
    throw new Error(`OpenAPI ${method} failed: ${msg}`);
  }
  return json.result.data;
}

module.exports = { callOpenApi, calcSign };

成功:calcSign(1706511734, 'f5a1ae2d-c09c-4d39-a744-83a5c2c653c2', 'test123456789test123456789') 得到 fd37b62889e4757c58b8f3bf05fb9976;再调 accessToken 能打印 token,expireTime 单位是秒。

兜底:对不上标准案例,先别查业务接口,多半是字符串拼错。TK1002 再刷 token,不要每个请求都申。管理员 token 有效期 3 天,超过 2 天再申会拿到新的,新旧各自能用。

第三步:列表里先看到版本号

查设备用 listDeviceDetailsByPage。看四样:deviceId 在不在、deviceVersion 有没有值、deviceStatus 是不是 onlineaccessType 是不是 PaaSaccessType 不是 PaaS 时,后面使能不要照抄。

text 复制代码
token=上一步拿到的 accessToken
page=1
pageSize=10
source=bindAndShare

成功:终端能打印出冲压区、焊接工位序列号和版本号。

兜底:列表为空,设备绑在私人号下。没有烟感 / 火警 / 热成像相关能力,不要硬开不存在的使能类型。

第四步:建人形工装库,注册厂规安全帽

创建库用 createAiDetectRepositoryrepositoryType 只能填文档给的值:face 是人脸库,工装必须用 human。注册样本用 addAiDetectTargettype=0 走图片 URL,type=1 走 Base64。样本用厂里真正要求的安全帽、反光衣,正脸、光线够,不要用网图。

text 复制代码
# 建库
token=管理员 accessToken
repositoryName=厂规工装库
repositoryType=human

# 注册安全帽样本(可再注册一件反光衣)
token=管理员 accessToken
repositoryId=上一步返回的 repositoryId
type=0
content=https://img.example.com/helmet-ok.jpg

成功:建库返回 repositoryId;注册返回 targetKey。把这两个写进环境变量。

兜底:repositoryType 写成别的值会建错库。样本打不开或是内网地址,注册失败,先换成公网 URL。

第五步:对车间图跑 workwearDetect,群进未着装

这篇必须先跑通的接口是 workwearDetecttypecontent 对齐:0 配 URL,1 配 Base64。threshold 范围 (0,1],联调先用 0.8detectRegions 最多 3 组,每组 3 到 6 个点,平台会转成最大外接矩形;第一闭环可以不传,整图检测。返回 targets[],每人一个框和 detectResult

text 复制代码
token=管理员 accessToken
type=0
content=https://img.example.com/press-line.jpg
repositoryId=第四步的工装库 ID
threshold=0.8
javascript 复制代码
// workwear-detect.js
require('dotenv').config();
const { callOpenApi } = require('./openapi-client');

(async () => {
  const token = (
    await callOpenApi('accessToken', process.env.IMOU_APP_ID, process.env.IMOU_APP_SECRET, {})
  ).accessToken;

  const data = await callOpenApi('workwearDetect', process.env.IMOU_APP_ID, process.env.IMOU_APP_SECRET, {
    token,
    type: '0',
    content: process.env.WORKSHOP_SHOT_URL,
    repositoryId: process.env.WORKWEAR_REPO_ID,
    threshold: Number(process.env.THRESHOLD || 0.8),
  });

  console.log(JSON.stringify(data, null, 2));
  const bad = (data.targets || []).filter((t) => t.detectResult === false);
  if (bad.length) {
    const text = `【着装待确认】冲压区\n未规范着装 ${bad.length} 人\n先看图,不要直接罚单`;
    console.log('[安监群]', text, process.env.HOOK_EHS ? '→ hook' : '→ 仅日志');
  }
})();

成功:控制台出现 targets,至少一个人有 detectResult;故意用一张未戴帽的车间图,日志打出「着装待确认」,安监群进一条。这就是第一闭环。

兜底:OP1002 / OP1003 先核对 typecontentthreshold。返回空 targets,换一张人更大、更清楚的图,或把检测框缩到通道口。阈值太高会全员不合格,先固定 0.8 再调。


工装结果出来之后:把烟火推进值班群

最小闭环已经成立,才加第二层。仍用同一套现行 OpenAPI,不要外挂无关产品。

打开上报:能力集有 MsgSW,用 setDeviceCameraStatusenableType 写成 msgSW(首字母小写),enable=true。文档没有单独的「烟火使能」字段,不要编 aiFire

登记回调:这篇第二层必须跑通的是 setMessageCallbackstatus=oncallbackUrl 必填,必须公网可达。callbackFlag 写成 alarm,deviceStatus。联调 basePush"2"

text 复制代码
token=管理员 accessToken
status=on
callbackUrl=https://bridge.example.com/imou/callback
callbackFlag=alarm,deviceStatus
basePush=2

成功:getMessageCallback 读回的地址和 callbackFlag 与上面填写项一致。

兜底:localhost 登记成功也收不到。只写出 alarm,掉线你永远收不到。

接收端同步路径零阻塞。文档写明:多次不回 200,平台停推。普通报警体见事件消息格式定义iddidcidmsgTypetime。烟火三类进群;videoMotion 只记日志。不要在车间点火,按机型说明书的测试方式触发。

javascript 复制代码
// bridge-server.js
require('dotenv').config();
const express = require('express');

const ZONES = {
  [process.env.DEVICE_PRESS]: { zone: '冲压区', hook: process.env.HOOK_EHS },
  [process.env.DEVICE_WELD]: { zone: '焊接工位', hook: process.env.HOOK_EHS },
};

const FIRE = new Set(['smokeAlarm', 'fireAlarm', 'heatImagingTemper']);
const seen = new Set();

function zoneOf(did) {
  return ZONES[did] || { zone: did, hook: process.env.HOOK_EHS };
}

async function toEhsGroup(ev) {
  const did = ev.did || ev.deviceId;
  if (ev.msgType === 'offline' || ev.id === -1) {
    const { zone } = zoneOf(did);
    console.log('[安监群]', `【值守 掉线】${zone} ${did} 先看供电,不要当火情`);
    return;
  }
  if (!FIRE.has(ev.msgType)) {
    console.log('[忽略]', ev.msgType, did);
    return;
  }
  const key = String(ev.id);
  if (seen.has(key)) return;
  seen.add(key);
  const { zone } = zoneOf(did);
  const when = new Date(ev.time * 1000).toLocaleString('zh-CN', { hour12: false });
  console.log('[安监群]', `【火情待确认】${zone} ${ev.msgType}\n${did} ${when}\n先看图,不要直接报火`);
}

const app = express();
app.use(express.json({ limit: '1mb' }));
app.post('/imou/callback', (req, res) => {
  res.status(200).json({ code: '0', msg: 'ok' });
  const body = req.body || {};
  const ev = body.msgType ? body : body.data || body;
  setImmediate(() => toEhsGroup(ev).catch((e) => console.error(e)));
});
app.get('/health', (_req, res) => res.status(200).send('ok'));
app.listen(process.env.PORT || 8080);

成功:/health 返回 ok;按说明书触发一次,日志出现 smokeAlarmfireAlarm,安监群进一条「火情待确认」。

兜底:App 有告警、服务安静,回头看地址和 callbackFlag。日志只有 videoMotion,不要把动检当烟火。smokingDetect 是对图验抽烟,和这条推送不是同一条管子。

确认抓图:用 getAlarmMessageById 把回调里的 id 当成 alarmId。返回里的 picurlArray 尽快落到自己的对象存储,文档写明图片保存有时限。值班员看图:焊烟、镜头脏污,停在待确认;真烟真火,才升「已确认」。着装那条也可以拿告警图再跑一遍 workwearDetect,不要每秒对直播流狂打。

取证:叫醒走回调,回放走 queryLocalRecordsgetCloudRecords。上下线体的 id 固定是 -1,不能拿去查告警详情。生产把内存 seen 换成 Redis。派单 SLA、跨车间值班表是下一篇的事。


联调会踩的坑

现象 多半是什么 先做什么
工装接口调不通 增值服务未开通试用 工单或商务申请,不要改签名
targets 为空 人太小、图太暗、样本不是厂规帽 换近景图;样本用本厂安全帽
全员 detectResult=false 阈值偏高,或库里样本和现场帽不一致 先固定 0.8;重新注册本厂样本
headerDetect 当安全帽 那是人头检测使能 着装只走 workwearDetect + 工装库
smokingDetect 当火情 那是抽烟检测 火情只认 smokeAlarm / fireAlarm / heatImagingTemper
登记成功但一条都没有 URL 不是公网 / 证书 / 路径 404 curl -X POST 打自己的回调
收过一阵突然没了 同步路径堵了,多次没回 200 修好后重新 setMessageCallback
只有 videoMotion 机型出不了烟火类型 查能力集,换机或加配件,不要编使能名
拿上下线 id 去查抓图 文档写明固定为 -1 只用烟火事件的 idgetAlarmMessageById

真正省下的不是再买一台相机

这篇省下的不是再挂一路镜头,而是安监员不用第二天翻回放,才在群里问「夜班那顶帽子谁看过」。电视墙已经够亮了,缺的是能进业务的那一条。

只做值班大屏预览、不接群的,不必在这里把工装检测和回调搭起来。现场有人值守、违章当场能喊停的工位,也没必要上这一套。

appSecret、机器人地址只放环境变量。公网回调建议加自有校验。车间抓图按安监留存周期转存,不要把现场图长期堆在聊天记录里。人脸不要进工装库。接口只走现行 OpenAPI,不要混已标注不再维护的旧协议栏目。


++++++更多有关工厂车间安防 相关的监控开发信息请点击云开放平台进行了解++++++

→→ 云开放平台


更多信息:

相关推荐
计算机毕设定制辅导-无忧学长1 小时前
基于Spring Boot的玄幻小说个性化推荐平台设计与实现
java·vue.js·spring boot·后端·mysql·推荐算法
码路漫漫1 小时前
LRU 真的能解决日志按业务 Key 分文件的落地瓶颈吗?
java·后端
小满zs1 小时前
Go语言第十一章(协程)
后端·go
jianqiang.xue2 小时前
ESP-IDF保姆级入门23|MQTT物联网通信全解:发布订阅模式/QoS等级/遗嘱消息/主题设计/断线重连,掌握工业级标准消息通信
stm32·单片机·mcu·物联网·51单片机·iot
1001101_QIA3 小时前
从 CPU 到 GPU:高速缓存、指令并行与 CUDA 执行原理入门
java·后端·spring
2501_928996223 小时前
信创备份一体机性能焦虑根源与中科热备国产CPU平台实测拆解
后端·数据安全·测试
jianqiang.xue3 小时前
ESP-IDF保姆级入门29|FreeRTOS任务管理与调度全解:任务创建/状态切换/优先级调度/双核负载均衡/实时性优化,掌握嵌入式多任务编程核心
stm32·单片机·mcu·物联网·51单片机·iot
程序员清风3 小时前
聊聊怎么缓解找工作的焦虑感?
java·后端·面试
不一样的少年_4 小时前
明明做了很多事,为什么简历看起来还是没含金量?
前端·后端·招聘