在物聯網實際項目中,有些裝置采用私有協定接入了本地裝置管理系統,有些 NB-IoT 裝置被迫接入了電信 AEP 平台,有些裝置接入了移動 OneNET 平台。但甲方客戶的整體業務都部署在阿裡雲上,我們如何實作整體業務上雲呢?
阿裡雲 IoT 物聯網平台提供了泛化協定SDK接入的方案,在 IoT 裝置零改造的前提下,幫助企業快速建構雲上橋接服務,通過網橋實作 IoT 終端裝置與阿裡雲 IoT 物聯網平台的雙向資料通信。
技術架構
方案1:泛化SDK
泛化協定SDK是協定自适應的架構,用以建構與阿裡雲物聯網平台進行高效雙向通信的橋接服務。
适用場景
泛化協定SDK面向的目标場景包括:
泛化協定SDK使得網橋Server具備與物聯網平台進行通信的能力。
- 提供基于配置檔案的靜态配置管理能力。
- 提供裝置連接配接管理能力。
- 提供上行通信能力。
- 提供下行通信能力。
接入流程 **
使用泛化協定SDK,橋接裝置與物聯網平台的整體流程圖,如下:
開發實戰 **
泛化 SDK 依賴
泛化協定僅支援Java開發語言,添加泛化協定SDK的項目Maven依賴,如下:
<dependency>
<groupId>com.aliyun.openservices</groupId>
<artifactId>iot-as-bridge-sdk-core</artifactId>
<version>2.1.3</version>
</dependency>
初始化 SDK
您需要建立一個BridgeBootstrap對象執行個體,并調用bootstrap方法。泛化協定SDK初始化工作完成後,讀取網橋資訊,并向雲端發起網橋裝置上線請求等。
此外,可以在調用bootstrap方法的同時,向泛化協定SDK注冊一個DownlinkChannelHandler回調,用于接收雲端下行消息。
BridgeBootstrap bridgeBootstrap = new BridgeBootstrap();
bridgeBootstrap.bootstrap(new DownlinkChannelHandler() {
@Override
public boolean pushToDevice(Session session, String topic, byte[] payload) {
// 雲端下行控制指令
String content = new String(bytes);
log.info("Get DownLink message, session:{}, {}, {}", session, topic, content);
return true;
}
@Override
public boolean broadcast(String topic, byte[] payload) {
return false;
}
});
配置泛化網橋身份
建立網橋産品
注冊網橋裝置
網橋配置預設使用配置檔案方式。預設從Java工程預設資源檔案路徑(一般是src/main/resources/)下的application.conf中讀取配置檔案。
# Server endpoint
http2Endpoint = "https://你的ProductKey.iot-as-http2.cn-shanghai.aliyuncs.com:443"
authEndpoint = "https://iot-auth.cn-shanghai.aliyuncs.com/auth/bridge"
# Gateway device info, productKey & deviceName & deviceSecret
productKey = ${bridge-ProductKey}
deviceName = ${bridge-DeviceName}
deviceSecret = ${bridge-DeviceSecret}
# subDeviceConnectMode = 3,即子裝置線上狀态和網關是否線上無關
subDeviceConnectMode = 3
配置網橋下裝置身份
建立子裝置産品
注冊裝置,擷取身份三元組
配置裝置原始身份辨別符和裝置證書資訊的映射關系。預設使用配置檔案方式,預設從Java工程的預設資源檔案路徑(一般是src/main/resources/)下的devices.conf中讀取配置檔案。
${device-original-Identity} {
productKey : ${device-ProductKey}
deviceName : ${device-DeviceName}
deviceSecret : ${device-DeviceSceret}
}
裝置上線
裝置上線時,需要傳Session。下行消息回調時,會把Session回調給網橋。Session中包含裝置的原始身份辨別符字段,以便網橋判斷消息屬于哪個裝置。
UplinkChannelHandler uplinkHandler = new UplinkChannelHandler();
//建立Session
Object channel = new Object();
Session session = Session.newInstance(originalIdentity, channel);
//裝置上線
boolean success = uplinkHandler.doOnline(session, originalIdentity);
if (success) {
// 裝置上線成功,網橋接受後續裝置通信請求。
} else {
// 裝置上線失敗,網橋可以拒絕後續裝置通信請求,如斷開連接配接。
}
裝置通過網橋上報資料
網橋使用泛化協定 SDK 代理裝置上報消息,代碼如下:
// originalIdentity 裝置上報資料
DeviceIdentity deviceIdentity = ConfigFactory.getDeviceConfigManager().getDeviceIdentity(originalIdentity);
ProtocolMessage protocolMessage = new ProtocolMessage();
protocolMessage.setPayload(payload);
protocolMessage.setQos(0);
protocolMessage.setTopic(String.format(TOPIC_TEMPLATE_USER_DEFINE, deviceIdentity.getProductKey(), deviceIdentity.getDeviceName()));
// 網橋代理上報
uplinkChannelHandler.doPublishAsync(originalIdentity, protocolMessage);
裝置接收雲端指令
雲端可以調用Pub API給裝置下發控制指令,網橋監聽和處理雲端消息的代碼如下:
private static ExecutorService executorService = new ThreadPoolExecutor(
Runtime.getRuntime().availableProcessors(),
Runtime.getRuntime().availableProcessors() * 2,
60, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(1000),
new ThreadFactoryBuilder().setDaemon(true).setNameFormat("bridge-downlink-handle-%d").build(),
new ThreadPoolExecutor.AbortPolicy());
public static void main(String args[]) {
//Use application.conf & devices.conf by default
bridgeBootstrap = new BridgeBootstrap();
bridgeBootstrap.bootstrap(new DownlinkChannelHandler() {
@Override
public boolean pushToDevice(Session session, String topic, byte[] payload) {
//get message from cloud
//get downlink message from cloud
executorService.submit(() -> handleDownLinkMessage(session, topic, payload));
return true;
}
@Override
public boolean broadcast(String s, byte[] bytes) {
return false;
}
});
}
private static void handleDownLinkMessage(Session session, String topic, byte[] payload) {
String content = new String(payload);
log.info("Get DownLink message, session:{}, topic:{}, content:{}", session, topic, content);
Object channel = session.getChannel();
String originalIdentity = session.getOriginalIdentity();
//for example, you can send the message to device via channel, it depends on you specific server implementation
}
裝置下線
當裝置從網橋斷開後,可以調用下線接口,告知雲端:
upLinkHandler.doOffline(originalIdentity);
【往期回顧】
1、39張IoT傳感器工作原理GIF圖彙總 2、IoT 裝置發送 MQTT 請求的曲折經曆 3、20元體 Arduino 環境監測儀開發 4、智能手持測溫槍開發實踐 5、JMeter 壓測 MQTT 服務性能實戰