HarmonyOS APP开发---“智泊“智能停车App,需要用到这个库
·
HarmonyOS APP开发—"智泊"智能停车App,需要用到这个库
停车场 200 个车位,每个装一个电池供电的 CoAP 传感器。用户打开 App 要立刻看到空位分布。逐个 HTTP 轮询?200 次请求、传感器电量撑不过一周。CoAP 组播一次请求,200 个传感器各自响应——这就是
@ohos/coap的价值。
📦 仓库地址 |
ohpm install @ohos/coap
场景
"智泊"要做的事:手机连上停车场 WiFi,扫一遍就知道哪些车位空着,点某个车位看详情(占用多久、能否预约),车位状态变化时地图实时更新。
硬件侧是低功耗 MCU + 地磁传感器,电池供电要用好几年。这决定了通信协议必须够轻:
- HTTP:TCP 三次握手 + 几百字节 header,200 次轮询完全不现实
- MQTT:够轻,但要部署 Broker,还得处理 200 个设备的订阅关系
- CoAP:UDP + 4 字节头 + 原生组播,手机和传感器点对点,不需要任何中间件
为什么是 CoAP
| 维度 | HTTP | MQTT | CoAP |
|---|---|---|---|
| 传输层 | TCP | TCP | ✅ UDP |
| 报文头 | 几百字节 | 2 字节 | ✅ 4 字节 |
| 组播发现 | ❌ | ❌ | ✅ 原生支持 |
| 中间服务器 | 需要 | 需要 Broker | ✅ 点对点直连 |
| 设备当服务端 | 难 | 难 | ✅ 原生支持 |
| 传感器功耗 | 高 | 中 | ✅ 低 |
组播是决定性优势:一次广播拿到全部车位状态,比 200 次单播省两个数量级的流量和电量。
关键实现
组播发现全部车位
import {
CoapClient, CoapRequestMethod, CoapRequestType,
CoapResponseCode, CoapBlockMode,
} from '@ohos/coap'
interface SpotInfo {
id: string // 车位号,如 A-023
occupied: boolean
section: string
sensorIp: string // 用于后续单播查询
}
async discoverSpots() {
this.scanning = true
const client = new CoapClient() // 每次请求独立实例
client.setBlockMode(CoapBlockMode.COAP_BLOCK_USE_LIBCOAP)
try {
const data = await client.request(
'coap://224.0.1.187:5683/parking/spot', // CoAP 组播地址
CoapRequestMethod.GET,
CoapRequestType.COAP_MESSAGE_NON, // 组播用 NON,无需确认
)
if (data.code === CoapResponseCode.SUCCESS) {
this.spots.push(JSON.parse(data.message))
}
} finally {
this.scanning = false
}
}
组播必须用 COAP_MESSAGE_NON(Non-confirmable)。如果用 CON,200 个传感器各回一个确认包,网络瞬间拥塞。
单播查详情:控制并发数
用户快速点多个车位时,为每个请求建独立实例,并限制并发:
async queryBatch(spots: SpotInfo[]): Promise<SpotInfo[]> {
const results: SpotInfo[] = []
const CONCURRENCY = 5
for (let i = 0; i < spots.length; i += CONCURRENCY) {
const batch = spots.slice(i, i + CONCURRENCY)
const part = await Promise.all(batch.map(async (spot) => {
const client = new CoapClient() // ✅ 独立实例,不复用
try {
const data = await client.request(
`coap://${spot.sensorIp}:5683/parking/spot/${spot.id}`,
CoapRequestMethod.GET,
CoapRequestType.COAP_MESSAGE_CON, // 单播用 CON,保证可靠
)
return data.code === CoapResponseCode.SUCCESS ? JSON.parse(data.message) : null
} catch (e) { return null }
}))
results.push(...part.filter((r) => r !== null))
}
return results
}
接收传感器主动推送
车位状态变化时传感器主动 POST,App 当服务端接:
import { CoapServer } from '@ohos/coap'
const server = new CoapServer()
server.handle('parking/update', (request) => {
const update = JSON.parse(request.payload)
// 更新本地状态,地图 UI 自动刷新
this.spots = this.spots.map((s) =>
s.id === update.id ? { ...s, occupied: update.occupied } : s
)
return { code: '2.04', payload: 'OK' }
})
server.start('coap://0.0.0.0:5683')
aboutToDisappear() { server.stop() } // 别忘了停
两个容易踩的点
1. Native 日志会打印设备 IP
setNativeLogOpen(true) 调试协议问题很好用,但日志里含 IP 地址,隐私合规过不了。绑到构建配置上,别靠人记:
if (BuildProfile.DEBUG) CoapClient.setNativeLogOpen(true)
else CoapClient.setNativeLogOpen(false)
2. 地下车库信号差,要做退避重试
async requestWithRetry(url: string, maxRetry = 2) {
for (let i = 0; i <= maxRetry; i++) {
const client = new CoapClient() // 每次重试新实例
try {
const data = await client.request(url, CoapRequestMethod.GET, CoapRequestType.COAP_MESSAGE_CON)
if (data.code === CoapResponseCode.SUCCESS) return data
} catch (err) {
if (i < maxRetry) await new Promise((r) => setTimeout(r, 500 * (i + 1))) // 退避
}
}
return null
}
小结
"智泊"这个场景里,@ohos/coap 解决了三件事:组播一次发现 200 个车位、手机既能当客户端查询也能当服务端接推送、UDP 低功耗让电池供电的传感器能跑几年。
关键是不需要在停车场部署任何中间服务器——手机和传感器点对点通信就够了。这是 HTTP 和 MQTT 方案都做不到的一点。
更多推荐



所有评论(0)