用乐橙 OpenSDK + OpenAPI 搭自有品牌智能家居 App(设备配网→预览→对讲)
去年接智能家居硬件商定制单:门铃、摄像机,合同写 「白牌 App,含配网、预览、语音对讲」。
团队习惯用 RTSP 地址拼播放器——配网谁做?对讲谁做? 投标前一周才发现:客户用乐橙 App 配好的设备,在我们壳里 列表是空的。
后来按 乐橙开放平台 文档拆成两层:OpenSDK 管配网、低延迟预览、对讲;OpenAPI + BFF 管 token、台账、Web HLS。跑通 Android 标准化 Demo 的 DeviceAddModule + MediaModule,两周验收——下面是留给下一单的笔记。
为什么集成商必须「乐橙 SDK + API」双轨
| 用户感知 | 实现 | 由谁做 |
|---|---|---|
| 配网 + 绑定 | 扫码 / 软 AP | OpenSDK DeviceAddModule |
| 实时预览 | 低延迟、抓图 | OpenSDK MediaModule;Web 用 bindDeviceLive |
| 语音对讲 | 双向音频 | OpenSDK LCOpenSDK_Talk(AudioTalk 能力);OpenAPI 不对讲 |
┌─────────────────────────────────────────────┐
│ 自有品牌 App │
│ DeviceAdd │ Media 预览 │ Talk 对讲 (OpenSDK) │
│ ↓ BFF(HTTPS) │
│ accessToken · listDeviceDetailsByPage │
└────────────────────┬────────────────────────┘
▼
乐橙云 openapi.lechange.cn
边界(写进合同附件):
- OpenAPI 可签发 HLS、查设备、
setMessageCallback,不能替代 App 配网与对讲音频。 - 设备须在 开发者主账号;
listDeviceDetailsByPage查不到 = 未绑定。 - 勿用停维护的
deviceList方法。
选型:OpenSDK vs 轻应用
| 路径 | 延迟 | 适合 |
|---|---|---|
| OpenSDK | 低 | 白牌 App、门铃对讲 |
| OpenAPI HLS | 3~8s | Web 分享页 |
| 轻应用 JS | 中 | 7 天 H5 PoC |
白牌交付 主路径 OpenSDK;OpenAPI 做 BFF + Web。
Phase 0 · 注册 + BFF(密钥只在服务端)
① https://open.imou.com 注册 → 我的应用 → appId / appSecret
② 国内 OpenSDK host:openapi.lechange.cn:443(不带 https://)
③ 设备绑定开发者主账号(见 [接入指南](https://open.imou.com/document/introduction/420b95/))
// server/lib/platform-call.js
import crypto from 'node:crypto';
import { randomUUID } from 'node:crypto';
function calcSign(time, nonce, secret) {
const raw = `time:${time},nonce:${nonce},appSecret:${secret}`;
return crypto.createHash('md5').update(raw, 'utf8').digest('hex');
}
export async function platformCall(method, params = {}) {
const time = Math.floor(Date.now() / 1000);
const nonce = randomUUID();
const body = {
system: {
ver: '1.0',
appId: process.env.APP_ID,
sign: calcSign(time, nonce, process.env.APP_SECRET),
time,
nonce,
},
id: randomUUID(),
params,
};
const res = await fetch(`${process.env.OPENAPI_BASE}/${method}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
const json = await res.json();
if (json.result?.code !== '0') throw new Error(json.result?.msg);
return json.result.data;
}
let cached = { token: null, exp: 0 };
export async function adminToken() {
if (Date.now() < cached.exp) return cached.token;
const { accessToken, expireTime } = await platformCall('accessToken', {});
cached = { token: accessToken, exp: Date.now() + (expireTime - 300) * 1000 };
return accessToken;
}
OPENAPI_BASE=https://openapi.lechange.cn/openapi
BFF 设备列表(App 只调你的 API):
app.get('/api/v1/devices', userAuth, async (req, res) => {
const token = await adminToken();
const page = await platformCall('listDeviceDetailsByPage', {
token, pageSize: 50, page: 1, source: 'bindAndShare',
});
res.json(page.deviceList ?? []);
});
踩坑 1:Demo 客户端填 appSecret 能跑 —— 上线必须 BFF,反编译即泄露 我的资源 配额。
Phase 1 · 配网 + 绑定(OpenSDK)
资源下载 → Android 标准化 Demo,模块结构:
DeviceAddModule/ # 配网 + 绑定开发者账号
MediaModule/ # 预览、对讲
MessageModule/ # 告警(可选)
集成顺序:整包 Demo 出画 → 再只移植 DeviceAdd + Media。
用户登录你的账号 → BFF 下发 accessToken
→ LCOpenSDK_Api.initOpenApi(host, token)
→ DeviceAddModule 扫码配网
→ listDeviceDetailsByPage 验收 deviceId
// Android — OpenSDK 初始化(见 OpenSDK 文档)
String host = "openapi.lechange.cn:443";
String token = bffClient.fetchAccessToken();
InitParams params = new InitParams(this, host, token);
LCOpenSDK_Api.initOpenApi(params);
批量工装 可用 OpenAPI bindDevice:
await platformCall('bindDevice', {
token: await adminToken(),
deviceId: process.env.DEVICE_SN,
code: process.env.DEVICE_VERIFY_CODE,
});
踩坑 2:工人用 私人乐橙号 配网 → 开发者列表空。SOP:DeviceAdd 必须绑项目 appId 主账号。
踩坑 3:initOpenApi 前无 token → 预览失败;host 勿写 https://。
Phase 2 · 预览(MediaModule + 可选 HLS)
App 内预览
MediaModule 传入 deviceId、channelId,SDK 内部建链 —— 换皮 UI 即可,勿手拼 RTSP。
能力验收:
const dev = page.deviceList?.find(d => d.deviceId === process.env.DEVICE_SN);
const ab = dev?.deviceAbility ?? '';
console.log({
online: dev?.deviceStatus === 'online',
audioTalk: /AudioTalk|AudioTalkV1/.test(ab),
});
Web / H5 分享页
const live = await platformCall('bindDeviceLive', {
token: await adminToken(),
deviceId,
channelId: '0',
streamId: 1,
liveMode: 'proxy',
});
res.json({ hls: live.streams?.[0]?.hls, ttlSec: 300 });
踩坑 4:m3u8 当 flv 播 → 黑屏。踩坑 5:HLS URL 长期外泄 → 短 ticket + 权限。
Phase 3 · 对讲(OpenSDK,先预览后 talk)
bindDeviceLive 只解决 「看」;对讲走 SDK:
deviceAbility 含 AudioTalk / AudioTalkV1
→ MediaModule 预览已成功
→ LCOpenSDK_Talk.playTalk
→ Android RECORD_AUDIO 权限
// 预览成功后再对讲
TalkParams paramTalk = new TalkParams(deviceId, channelId);
LCOpenSDK_Talk.playTalk(paramTalk);
踩坑 6:方案写「OpenAPI 对讲」→ 验收扯皮,应写 OpenSDK 对讲 + OpenAPI 管理。
踩坑 7:枪机无 AudioTalk → 投标前 listDeviceDetailsByPage 锁 BOM。
MVP Checklist
□ open.imou.com 应用,appSecret 仅 BFF
□ DeviceAddModule 配网,listDeviceDetailsByPage ≥1 online
□ AudioTalk(若合同含对讲)
□ MediaModule 出画 + playTalk 有声
□ [可选] bindDeviceLive 给 H5
Demo → 生产
| Demo | 生产 |
|---|---|
| 客户端 appSecret | 仅 BFF |
| 暴露 HLS | 短 ticket |
| fork 整包 | 模块化移植 |
| deviceList 旧接口 | listDeviceDetailsByPage |
性能
accessTokenRedis 缓存;列表 Cron 同步。- 预览墙 辅码流
streamId: 1。 - Demo 与 SDK 同版本下载,避免 aar 不匹配。
排错
| 现象 | 处理 |
|---|---|
| 列表空 | 开发者主账号绑定 |
| SDK init 失败 | host:443、token 过期 |
| 对讲无声 | AudioTalk、RECORD_AUDIO、先预览 |
| 预览黑屏 | 权限、offline、encryptMode |
小结
白牌智能家居 App,别从 RTSP 字符串起步:
OpenSDK:DeviceAdd → Media → Talk
OpenAPI + BFF:token、listDeviceDetailsByPage、bindDeviceLive(Web)
客户验收三件事:自家 Logo、能添设备、能看能对讲。
延伸阅读
开始接入
在 乐橙开放平台 open.imou.com 注册并创建应用,领取免费设备接入与媒体带宽。平台以视频技术与安全为核心,提供 OpenAPI、OpenSDK、轻应用 一站式能力,帮助集成商快速、低成本交付白牌视频与智能家居 App。
建议新单:下载 Android 标准化 Demo → 管理员模式出第一帧 → 再移植 DeviceAdd/Media 换皮。比从零写配网省几个月。
你卡在 sign、绑定还是 playTalk 无声?评论区说说。
6909

被折叠的 条评论
为什么被折叠?



