news 2026/9/8 18:07:45

把园区几百路收进值班台账:bindDevice 入账与 listDeviceDetailsByPage 翻页

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
把园区几百路收进值班台账:bindDevice 入账与 listDeviceDetailsByPage 翻页

目录

  • 东门 NVR、仓库 4G、周界枪机,为什么对不上账
  • 这篇只会碰到这几项能力
  • 轮询、官方 App、一上来写原生,园区为什么扛不住
  • 动手:从创建应用到值班台账数清
  • 台账对上之后,再开远程看和回放
  • 联调会踩的坑
  • 真正省下的不是再买一台相机

东门 NVR、仓库 4G、周界枪机,为什么对不上账

以前园区安防的做法很朴素:东门一套 NVR,仓库几台 4G 机挂在保安私人 App,周界枪机再进另一套厂商软件。值班室三块屏,早会用 Excel 对数。点位少、人盯得住的时候,这套还能交差。

点位涨到几百路就废了。东门通道在 NVR 里是 12,仓库机还在私人号下,周界掉线要第二天对表才知道。再买十台相机,账还是三本。

缺的不是再挂一路镜头,而是用现行 OpenAPI 把设备bindDevice进同一个开发者资产,再用listDeviceDetailsByPage按页拉齐,摊进你自己的园区值班台账。

读完按这个顺序交差:

  1. 在开放平台创建应用,拿到appId/appSecret
  2. 签名自测通过,能拿到accessToken
  3. 抽几台核绑定,再bindDevicecheckDeviceBindOrNot读回isMine=true
  4. pageSize=50翻页,扫完账号下全部设备。
  5. 值班台账按通道计路,东门 / 仓库 / 周界能数清。
  6. 抽一台拔网,台账里对应点位变成offline,在线数对得上。

工业园区几百路分散在 NVR、4G、私人 App。本文用现行 OpenAPI 的bindDevice统一入账、listDeviceDetailsByPage翻页对账,带可运行 Node.js,验到本地/inventory数清路数为止。


##需要用到这几项能力

查询见设备查询说明,添加见设备添加说明。

  1. bindDevice:把设备绑到开发者账号。code按机型传底部安全码或改过的设备密码;没安全码且未改密,文档允许传空。
  2. checkDeviceBindOrNot:先看isBind/isMine。别人账上的机,绑不进来。
  3. listDeviceDetailsByPage:分页拉设备详情。pageSize范围 1~50,page从 1 起。几百路就是翻几页,不是一次拉全量。
  4. 返回里的deviceStatus/channelStatusonlineofflinesleepupgradingsleep是休眠,不要按掉线叫人。
  5. catalog能区分NVRIPC。几百路不等于几百台:一台 NVR 下面有多条channelList
  6. accessToken有效期 3 天,报TK1002再刷,不要每个请求都申。

你负责把点位绑进开发者资产、写清东门仓库周界,开放平台负责按页吐设备详情和在离线。

枪机 / 4G / NVR 通道 │ ▼ bindDevice 入同一开发者账号 │ ▼ listDeviceDetailsByPage(每页最多 50) │ ▼ 你的值班台账(按 channelId 计路) │ ▼ 东门 / 仓库 / 周界 在线数

轮询、官方 App、一上来写原生,园区为什么扛不住

轮询适合对台账、对在线,前提是设备已经在同一个开发者账号下。三套厂商各轮各的,不是统一接入,只是三份定时任务。

只靠官方 App,红点停在保安私人手机里。交接班对不上序列号,仓库机跟着人走,园区后台永远是「少几路」。

一上来做原生客户端更没必要。园区已经有 OA 和值班大屏,缺的是 HTTP 把资产拉进自己的库,不是第三个看监控的 App。


动手:从创建应用到值班台账数清

部署只是开胃菜。真正过关的是:账号下的机全部出现在/inventory,路数对、区域对,抽一台掉线数字会变。

第一步:创建应用,先填园区点位表

打开 乐橙开放平台 注册并创建应用。控制台「我的应用 - 应用信息」能看到appId/appSecret再往下做。没有这两样,后面签名都会废。

先不要写接口。用一张表把现场点位收拢:序列号、区域、通道、验证码来源。NVR 只记一台设备,通道另行列。设备先配网上线,能在官方 App 预览,再谈绑定。

IMOU_APP_ID=lcdxxxxxxxxx IMOU_APP_SECRET=你的密钥 PORT=8080 # 园区点位(deviceId 或 deviceId:channelId) ZONE_EAST_GATE=东门NVR序列号 ZONE_WAREHOUSE=仓库4G序列号 ZONE_PERIMETER=周界枪机序列号

成功:控制台能看到应用;点位表每行都有序列号和区域,没有「在某某私人 App 里」。
兜底:还停在私人号下的机,先从点位表标出来,第三步再核绑定。控制台都没有应用,不要往下抄代码。

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

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

// openapi-client.jsconstcrypto=require('crypto');const{v4:uuidv4}=require('uuid');constOPENAPI_BASE='https://openapi.lechange.cn/openapi';functioncalcSign(time,nonce,appSecret){constraw=`time:${time},nonce:${nonce},appSecret:${appSecret}`;returncrypto.createHash('md5').update(raw,'utf8').digest('hex');}asyncfunctioncallOpenApi(method,appId,appSecret,params={}){consttime=Math.floor(Date.now()/1000);constnonce=uuidv4();constbody={system:{ver:'1.0',appId,time,nonce,sign:calcSign(time,nonce,appSecret)},id:uuidv4(),params,};constres=awaitfetch(`${OPENAPI_BASE}/${method}`,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(body),});constjson=awaitres.json();if(!json.result||json.result.code!=='0'){constmsg=json.result?`${json.result.code}${json.result.msg}`:JSON.stringify(json);thrownewError(`OpenAPI${method}failed:${msg}`);}returnjson.result.data;}module.exports={callOpenApi,calcSign};

成功:calcSign(1706511734, 'f5a1ae2d-c09c-4d39-a744-83a5c2c653c2', 'test123456789test123456789')得到fd37b62889e4757c58b8f3bf05fb9976;再调 accessToken 能打印 token 和expireTime
兜底:对不上标准案例,先别查业务接口,多半是字符串拼错。TK1002再刷 token。签名算法若控制台提示不一致,以现行开发规范为准,不要混网上过时示例。

第三步:先核绑定,再一台一台 bindDevice

这篇入账接口是 bindDevice。先 checkDeviceBindOrNot:isBind=false再绑;isMine=true已经是你的;isBind=trueisMine=false在别人账上,先解绑或走交接,不要死磕。

token=上一步拿到的 accessToken deviceId=仓库4G序列号 code=底部8位安全码或改过的设备密码

未改密且标签没有 8 位安全码,按文档把code传空。一批机不要写循环闷头绑,先抽东门、仓库、周界各一台。

应用开发写明:部分新出厂或升级后的设备,可能无法只靠 HTTPbindDevice完成绑定,要结合客户端 SDK。联调绑失败、核绑定又显示未在本账号,先走这条说明,不要改签名。

成功:bindDevice返回code=0;再查一次,isBind=trueisMine=true
兜底:已经是别人的资产,先让现场从原账号解绑。新机 HTTP 绑不上,按应用开发说明改 SDK 路径。

第四步:pageSize 写成 50,把账号翻完

这篇对账接口是 listDeviceDetailsByPage。pageSize最大 50,自有资产用source=bind;连分享进来的也要入账,用默认的bindAndShare。翻页直到某一页deviceList为空,或累计条数不再增加。

// sync-devices.jsrequire('dotenv').config();const{callOpenApi}=require('./openapi-client');asyncfunctionlistAllDevices(appId,appSecret,token){constall=[];letpage=1;constpageSize=50;while(true){constdata=awaitcallOpenApi('listDeviceDetailsByPage',appId,appSecret,{token,page,pageSize,source:'bind',});constchunk=data.deviceList||[];all.push(...chunk);if(chunk.length<pageSize)break;page+=1;}returnall;}functionflattenChannels(deviceList,zoneOf){constrows=[];for(constdofdeviceList){constchannels=d.channelList&&d.channelList.length?d.channelList:[{channelId:0,channelStatus:d.deviceStatus}];for(constchofchannels){rows.push({deviceId:d.deviceId,deviceName:d.deviceName,catalog:d.catalog,deviceStatus:d.deviceStatus,channelId:ch.channelId,channelStatus:ch.channelStatus||d.deviceStatus,deviceVersion:d.deviceVersion,zone:zoneOf(d.deviceId),});}}returnrows;}module.exports={listAllDevices,flattenChannels};

成功:控制台打印出deviceIdcatalogdeviceStatusdeviceVersion;有 NVR 时,同一deviceId下出现多条channelId。400 路大约 8 页,几百路听起来吓人,其实就是pageSize=50翻几页。把每次返回的count和本页deviceList.length记下来,方便对「少了一页」这种问题。
兜底:只打了第 1 页就停,台账会永远少一大截。pageSize写成 100,以现行文档为准,合法值是 1~50。分享进来的机要用bindAndShare,只写bind会漏。

第五步:值班台账服务,按通道计路

本地映射区域,摊平通道,露出/inventory。这是接收侧:开放平台吐列表,你的服务收成园区能看的一张账。还没数清之前,不要去创建直播。

# zones.json 填写模板(对齐写字段) { "东门NVR序列号": "东门", "仓库4G序列号": "仓库", "周界枪机序列号": "周界" }
// inventory-server.jsrequire('dotenv').config();constexpress=require('express');const{callOpenApi}=require('./openapi-client');const{listAllDevices,flattenChannels}=require('./sync-devices');constZONES=require('./zones.json');functionzoneOf(deviceId){returnZONES[deviceId]||'未分区';}letcache={rows:[],syncedAt:0};asyncfunctionrefresh(){consttoken=(awaitcallOpenApi('accessToken',process.env.IMOU_APP_ID,process.env.IMOU_APP_SECRET,{})).accessToken;constdevices=awaitlistAllDevices(process.env.IMOU_APP_ID,process.env.IMOU_APP_SECRET,token);cache={rows:flattenChannels(devices,zoneOf),syncedAt:Date.now()};}constapp=express();app.get('/health',(_req,res)=>res.status(200).send('ok'));app.get('/inventory',async(_req,res)=>{if(!cache.rows.length)awaitrefresh();constonline=cache.rows.filter((r)=>r.channelStatus==='online').length;constoffline=cache.rows.filter((r)=>r.channelStatus==='offline').length;constsleep=cache.rows.filter((r)=>r.channelStatus==='sleep').length;res.json({totalChannels:cache.rows.length,online,offline,sleep,syncedAt:cache.syncedAt,rows:cache.rows,});});app.post('/inventory/refresh',async(_req,res)=>{awaitrefresh();res.json({totalChannels:cache.rows.length,syncedAt:cache.syncedAt});});app.listen(process.env.PORT||8080);

成功:浏览器打开/health返回okGET /inventory能看到totalChannels、按区域分好的rows,以及deviceVersion。值班大屏只读这个 JSON,不要让前端直接拿appSecret去翻页。
兜底:数字对不上现场,先看是不是按设备计台、没按通道计路。未分区太多,回去补zones.json,不要先改签名。refresh里已经申过 token,同一次同步不要再打accessToken

第六步:抽一台拔网,台账变了才算闭环

按勾,不要跳步。

  1. /inventorytotalChannels对得上点位表(NVR 按通道加总)。
  2. 东门、仓库、周界三行都能对上deviceId
  3. 抽仓库或周界一台拔网 / 断 4G,调POST /inventory/refresh,该行channelStatusdeviceStatus变为offlineoffline计数加一。
  4. 插回网线,再刷一次,回到online

成功:上面四条都对得上。这就是「值班台账数清了」。
兜底:列表有机、刷新状态不变,隔一两分钟再刷;4G 上的sleep不要按掉线打电话。单台复核可用 listDeviceDetailsByIds 或 deviceOnline。注意:deviceOnlineonLine0/1/3/4,和列表里的英文枚举不是同一套字,对账时不要混着比。


台账对上之后,再开远程看和回放

最小闭环已经成立,才加第二层。仍用同一套现行 OpenAPI,不要另起一套协议。

值班员要点开东门看一眼:先 bindDeviceLive 创建设备源直播,再 getLiveStreamInfo 取 HLS。没创建过直播,后一个接口拿不到地址。直播地址对外等于公开画面,只给值班内网,不要进公共群。

事后取证:同一天时段用 queryCloudRecords 查云录像片段(queryRange最大 100),再用 createDeviceRecordHls 生成回放地址。beginTime/endTime格式是yyyy-MM-dd HH:mm:ss,文档写明不支持跨天。recordTypecloudRecordlocalRecord,以该点位是否开通云存储、是否有本地卡为准。

告警进工单、遮挡掉线进群,是下一篇的事。这篇停在「一张账能数清,抽一台掉线数字会变」。


联调会踩的坑

现象多半是什么先做什么
台账只有几十路只拉了第 1 页pageSize=50一直翻到不足一页
现场 200 路,台账 40 台按设备计台,没按通道计路展开channelList,NVR 按channelId
仓库机列表里没有还在私人 App,isMine=falsecheckDeviceBindOrNot,再bindDevice
HTTP 绑失败新机 / 新固件不走纯 HTTP 绑定看应用开发的 SDK 说明
sleep当成掉线打电话4G 省电offline分开看
签名对不上标准案例原始串拼错或混了过时算法先对齐 MD5 案例,再谈业务
隔天一批接口全挂token 过了约 3 天收到TK1002再刷,不要每个请求都申
列表英文状态和单查对不上deviceOnline用的是0/1/3/4两套枚举分开映射

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

这篇省下的不是多一路镜头,而是值班室不用三块屏、三份 Excel,才能回答「园区现在在线多少路、掉的是东门还是仓库」。

只做网页预览、不建资产台账的,去看轻应用嵌入那条线就够了,不必在这里把翻页和区域映射搭起来。家里两台相机、出事了有人盯 App 的散户,也没必要上这一套。

appSecret、设备密码只放环境变量。直播地址当密钥管。日志里的序列号对外部打码。接口以现行文档为准,不要混已标注不再维护的栏目。


想获取更多有关园区摄像头的监控开发服务信息,
欢迎关注乐橙云开放平台
点击注册即送免费10路摄像头接入额度和1M免费带宽。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/8 18:06:21

国产算力集群7×24小时稳定性压测实践:从指标设计到故障排查

说实话&#xff0c;接到这个任务的时候我心里是有准备的&#xff0c;但真正跑完这七天&#xff0c;还是有很多没想到的地方。国产算力集群的稳定性测试&#xff0c;和以往在常规GPU集群上做压测&#xff0c;完全是两种体验&#xff1a;工具链要自己拼、监控要自己搭、驱动日志要…

作者头像 李华
网站建设 2026/9/8 18:04:46

CMSIS-5全景解析:架构分层、核心模块与工程落地实践

搞嵌入式开发这么多年&#xff0c;CMSIS 是我见过最“熟悉又陌生”的东西。熟悉的是&#xff0c;几乎每个 Cortex-M 项目里都有它的身影&#xff0c;不管是 STM32、NXP 还是 GD32&#xff0c;打开工程第一眼看到的不是 main.c&#xff0c;而是 core_cm4.h、system_stm32f1xx.c …

作者头像 李华
网站建设 2026/9/8 18:03:24

国产MCU替代STM32:Pin-to-Pin兼容背后的启动与移植陷阱

上个月帮朋友看一块板子&#xff0c;场景特别典型&#xff1a;成本压力下来之后&#xff0c;采购想换成国产MCU&#xff0c;供应商拍着胸口说型号是Pin-to-Pin兼容STM32F103C8T6&#xff0c;原理图不用动、PCB钢网都不用改&#xff0c;把原来的芯片直接焊上去就行。结果板子确实…

作者头像 李华