設備與云端基于Alink協議進行物模型數據通信,包括設備上報屬性或事件消息到云端,從云端下發設置屬性或調用服務消息到設備。本實踐案例提供Java Demo,介紹物模型數據通信代碼配置。
前提條件
- 已開通物聯網平臺服務。
- 已安裝Java開發環境。
創建產品和設備
首先,需創建產品和設備,為產品定義功能(即物模型)。
下載、安裝Demo SDK
本示例提供的SDK Demo中包含了服務端SDK Demo和設備端SDK Demo。
- 單擊下載iotx-api-demo,并解壓縮。
- 打開Java開發工具,導入解壓縮后的iotx-api-demo文件夾。
- 在pom.xml文件中,添加以下Maven依賴,導入阿里云云端SDK和設備端SDK。
<!-- https://mvnrepository.com/artifact/com.aliyun/aliyun-java-sdk-iot --> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-iot</artifactId> <version>7.33.0</version> </dependency> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core</artifactId> <version>3.5.1</version> </dependency> <dependency> <groupId>com.aliyun.alink.linksdk</groupId> <artifactId>iot-linkkit-java</artifactId> <version>1.2.0</version> <scope>compile</scope> </dependency>
- 在java/src/main/resources/目錄下的config文件中,填入初始化信息。
user.accessKeyID = <your accessKey ID> user.accessKeySecret = <your accessKey Secret> iot.regionId = <regionId> iot.productCode = Iot iot.domain = iot.<regionId>.aliyuncs.com iot.version = 2018-01-20
參數 說明 accessKeyID 您的阿里云賬號的AccessKey ID。 將光標定位到您的賬號頭像上,選擇AccessKey管理,進入安全信息管理頁,可創建或查看您的AccessKey。
accessKeySecret 您的阿里云賬號的AccessKey Secret。查看方法同上AccessKey ID。 regionId 您的物聯網設備所屬地域ID。地域ID的表達方法,請參見地域和可用區。
設備端SDK上報屬性和事件
配置設備端SDK連接物聯網平臺,上報屬性和事件消息。
Demo中,java/src/main/com.aliyun.iot.api.common.deviceApi目錄下的ThingTemplate文件是設備端上報屬性和事件的Demo。
- 設置連接信息。
將代碼中productKey、deviceName、deviceSecret和url替換為您的設備證書信息和MQTT接入域名。接入域名獲取方法,請參見查看和配置實例終端節點信息(Endpoint),接入域名必須攜帶端口1883。
public static void main(String[] args) { /** * 設備證書信息。 */ String productKey = "your productKey"; String deviceName = "your deviceName"; String deviceSecret = "your deviceSecret"; /* TODO: 替換為您物聯網平臺實例的接入地址 */ String url = "iot-6d***ql.mqtt.iothub.aliyuncs.com:1883"; /** * mqtt連接信息。 */ ThingTemplate manager = new ThingTemplate(); DeviceInfo deviceInfo = new DeviceInfo(); deviceInfo.productKey = productKey; deviceInfo.deviceName = deviceName; deviceInfo.deviceSecret = deviceSecret; /** * 服務器端的Java HTTP客戶端使用TSLv1.2。 */ System.setProperty("https.protocols", "TLSv2"); manager.init(deviceInfo, url); }
- 初始化連接。
public void init(final DeviceInfo deviceInfo, String url) { LinkKitInitParams params = new LinkKitInitParams(); /** * 設置mqtt初始化參數。 */ IoTMqttClientConfig config = new IoTMqttClientConfig(); config.productKey = deviceInfo.productKey; config.deviceName = deviceInfo.deviceName; config.deviceSecret = deviceInfo.deviceSecret; config.channelHost = url; /** * 是否接受離線消息。 * 對應mqtt的cleanSession字段。 */ config.receiveOfflineMsg = false; params.mqttClientConfig = config; ALog.setLevel(LEVEL_DEBUG); ALog.i(TAG, "mqtt connetcion info=" + params); /** * 設置初始化,傳入設備證書信息。 */ params.deviceInfo = deviceInfo; /**建立連接。**/ LinkKit.getInstance().init(params, new ILinkKitConnectListener() { public void onError(AError aError) { ALog.e(TAG, "Init Error error=" + aError); } public void onInitDone(InitResult initResult) { ALog.i(TAG, "onInitDone result=" + initResult); List<Property> properties = LinkKit.getInstance().getDeviceThing().getProperties(); ALog.i(TAG, "設備屬性列表" + JSON.toJSONString(properties)); List<Event> getEvents = LinkKit.getInstance().getDeviceThing().getEvents(); ALog.i(TAG, "設備事件列表" + JSON.toJSONString(getEvents)); /*屬性上報。TODO: 需確保所報的屬性, 比如MicSwitch, 是產品的物模型的一部分. 否則會返回錯誤 */ handlePropertySet("MicSwitch", new ValueWrapper.IntValueWrapper(1)); /* 事件上報. TODO: 需確保所報的事件, 比如Offline_alarm, 是產品的物模型的一部分. 否則會返回錯誤 */ Map<String,ValueWrapper> values = new HashMap<>(); values.put("eventValue",new ValueWrapper.IntValueWrapper(0)); OutputParams outputParams = new OutputParams(values); handleEventSet("Offline_alarm",outputParams); } }); }
說明 代碼中的屬性和事件標識符需與物模型中定義的標識符一致。 - 設置設備端上報屬性。
/** * Alink JSON方式設備端上報屬性。 * @param identifier:屬性標識符。 * @param value:上報屬性值。 * @return */ private void handlePropertySet(String identifier, ValueWrapper value ) { ALog.i(TAG, "上報屬性identity=" + identifier); Map<String, ValueWrapper> reportData = new HashMap<>(); reportData.put(identifier, value); LinkKit.getInstance().getDeviceThing().thingPropertyPost(reportData, new IPublishResourceListener() { public void onSuccess(String s, Object o) { // 屬性上報成功。 ALog.i(TAG, "上報成功 onSuccess() called with: s = [" + s + "], o = [" + o + "]"); } public void onError(String s, AError aError) { // 屬性上報失敗。 ALog.i(TAG, "上報失敗onError() called with: s = [" + s + "], aError = [" + JSON.toJSONString(aError) + "]"); } }); }
- 設置設備端上報事件。
/** * Alink JSON方式設備端上報事件。 * @param identifyID:事件標識符。 * @param params:事件上報參數。 * @return */ private void handleEventSet(String identifyID, OutputParams params ) { ALog.i(TAG, "上報事件 identifyID=" + identifyID + " params=" + JSON.toJSONString(params)); LinkKit.getInstance().getDeviceThing().thingEventPost( identifyID, params, new IPublishResourceListener() { public void onSuccess(String s, Object o) { // 事件上報成功。 ALog.i(TAG, "上報成功 onSuccess() called with: s = [" + s + "], o = [" + o + "]"); } public void onError(String s, AError aError) { // 事件上報失敗。 ALog.i(TAG, "上報失敗onError() called with: s = [" + s + "], aError = [" + JSON.toJSONString(aError) + "]"); } }); }
云端SDK下發設置屬性和調用服務指令
- 初始化SDK客戶端。
Demo中,java/src/main/com.aliyun.iot.client目錄下IotClient文件是SDK客戶端初始化Demo。
public class IotClient { private static String accessKeyID; private static String accessKeySecret; private static String regionId; private static String domain; private static String version; public static DefaultAcsClient getClient() { DefaultAcsClient client = null; Properties prop = new Properties(); try { prop.load(Object.class.getResourceAsStream("/config.properties")); accessKeyID = prop.getProperty("user.accessKeyID"); accessKeySecret = prop.getProperty("user.accessKeySecret"); regionId = prop.getProperty("iot.regionId"); domain = prop.getProperty("iot.domain"); version = prop.getProperty("iot.version"); IClientProfile profile = DefaultProfile.getProfile(regionId, accessKeyID, accessKeySecret); DefaultProfile.addEndpoint(regionId, regionId, prop.getProperty("iot.productCode"), prop.getProperty("iot.domain")); // 初始化client。 client = new DefaultAcsClient(profile); } catch (Exception e) { LogUtil.print("初始化client失敗!exception:" + e.getMessage()); } return client; } public static String getRegionId() { return regionId; } public static void setRegionId(String regionId) { IotClient.regionId = regionId; } public static String getDomain() { return domain; } public static void setDomain(String domain) { IotClient.domain = domain; } public static String getVersion() { return version; } public static void setVersion(String version) { IotClient.version = version; } }
- 初始化封裝CommonRequest公共類。
Demo中,java/src/main/com.aliyun.iot.api.common.openApi目錄下的AbstractManager文件是封裝云端API的CommonRequest公共類的Demo。
public class AbstractManager { private static DefaultAcsClient client; static { client = IotClient.getClient(); } /** * 接口請求地址。action:接口名稱。 * domain:線上地址。 * version:接口版本。 */ public static CommonRequest executeTests(String action) { CommonRequest request = new CommonRequest(); request.setDomain(IotClient.getDomain()); request.setMethod(MethodType.POST); request.setVersion(IotClient.getVersion()); request.setAction(action); return request; }
- 配置云端SDK調用物聯網平臺云端API,下發設置屬性和調用服務的指令。
java/src/main/com.aliyun.iot.api.common.openApi目錄下的ThingManagerForPopSDk是云端SDK調用API設置設備屬性和調用設備服務的Demo文件。
- 調用SetDeviceProperty設置設備屬性值。
public static void SetDeviceProperty(String InstanceId, String IotId, String ProductKey, String DeviceName , String Items) { SetDevicePropertyResponse response =null; SetDevicePropertyRequest request=new SetDevicePropertyRequest(); request.setDeviceName(DeviceName); request.setIotId(IotId); request.setItems(Items); request.setProductKey(ProductKey); request.setIotInstanceId(InstanceId); try { response = client.getAcsResponse(request); if (response.getSuccess() != null && response.getSuccess()) { LogUtil.print("設置設備屬性成功"); LogUtil.print(JSON.toJSONString(response)); } else { LogUtil.print("設置設備屬性失敗"); LogUtil.error(JSON.toJSONString(response)); } } catch (ClientException e) { e.printStackTrace(); LogUtil.error("設置設備屬性失敗!" + JSON.toJSONString(response)); } }
- 調用SetDevicesProperty批量設置設備屬性值。
/** * 批量設置設備屬性。 * * @param ProductKey:要設置屬性的設備所隸屬的產品Key。 * @param DeviceNames:要設置屬性的設備名稱列表。 * @param Items:要設置的屬性信息,組成為key:value,數據格式為JSON String,必須傳入。 * * @Des:描述。 */ public static void SetDevicesProperty(String InstanceId, String ProductKey, List<String> DeviceNames, String Items) { SetDevicesPropertyResponse response = new SetDevicesPropertyResponse(); SetDevicesPropertyRequest request = new SetDevicesPropertyRequest(); request.setDeviceNames(DeviceNames); request.setItems(Items); request.setProductKey(ProductKey); request.setIotInstanceId(InstanceId); try { response = client.getAcsResponse(request); if (response.getSuccess() != null && response.getSuccess()) { LogUtil.print("批量設置設備屬性成功"); LogUtil.print(JSON.toJSONString(response)); } else { LogUtil.print("批量設置設備屬性失敗"); LogUtil.error(JSON.toJSONString(response)); } } catch (ClientException e) { e.printStackTrace(); LogUtil.error("批量設置設備屬性失敗!" + JSON.toJSONString(response)); } }
- 調用InvokeThingService調用設備服務。
/** * @param Identifier:服務的Identifier,必須傳入。 * @param Args:要啟用服務的入參信息,必須傳入。 */ public static InvokeThingServiceResponse.Data InvokeThingService(String InstanceId, String IotId, String ProductKey, String DeviceName, String Identifier, String Args) { InvokeThingServiceResponse response =null; InvokeThingServiceRequest request = new InvokeThingServiceRequest(); request.setArgs(Args); request.setDeviceName(DeviceName); request.setIotId(IotId); request.setIdentifier(Identifier); request.setProductKey(ProductKey); request.setIotInstanceId(InstanceId); try { response = client.getAcsResponse(request); if (response.getSuccess() != null && response.getSuccess()) { LogUtil.print("服務執行成功"); LogUtil.print(JSON.toJSONString(response)); } else { LogUtil.print("服務執行失敗"); LogUtil.error(JSON.toJSONString(response)); } return response.getData(); } catch (ClientException e) { e.printStackTrace(); LogUtil.error("服務執行失敗!" + JSON.toJSONString(response)); } return null; }
- 調用InvokeThingsService批量調用設備服務。
/** * @param Identifier:服務的Identifier,必須傳入。 * @param Args:要啟用服務的入參信息,必須傳入。 */ public static void InvokeThingsService(String InstanceId, String IotId, String ProductKey, List<String> DeviceNames, String Identifier, String Args) { InvokeThingsServiceResponse response =null; InvokeThingsServiceRequest request = new InvokeThingsServiceRequest(); request.setArgs(Args); request.setIdentifier(Identifier); request.setDeviceNames(DeviceNames); request.setProductKey(ProductKey); request.setIotInstanceId(InstanceId); try { response = client.getAcsResponse(request); if (response.getSuccess() != null && response.getSuccess()) { LogUtil.print("批量調用設備服務成功"); LogUtil.print(JSON.toJSONString(response)); } else { LogUtil.print("批量調用設備服務失敗"); LogUtil.error(JSON.toJSONString(response)); } } catch (ClientException e) { e.printStackTrace(); LogUtil.error("批量調用設備服務失敗!" + JSON.toJSONString(response)); } }
- 調用SetDeviceProperty設置設備屬性值。
設置屬性和調用服務的請求示例:
public static void main(String[] args) {
/**上線設備的設備名稱和所屬產品的ProductKey。*/
String deviceName = "2pxuAQB2I7wGPmqq***";
String deviceProductkey = "a1QbjI2***";
/**對于企業版實例和新版公共實例,設置InstanceId為具體實例ID值,您可在物聯網平臺控制臺的實例概覽頁面,查看當前實例的ID。
*對于舊版公共實例,設置InstanceId為空值""。
*/
String InstanceId = "iot-***tl02";
//1 設置設備的屬性。
SetDeviceProperty(InstanceId, null, deviceProductkey, deviceName,"{\"hue\":0}");
//2 批量設置設備屬性。
List<String> deviceNames = new ArrayList<>();
deviceNames.add(deviceName);
SetDevicesProperty(InstanceId, deviceProductkey, deviceNames, "{\"hue\":0}");
//3 調用設備的服務。
InvokeThingService(InstanceId, null, deviceProductkey, deviceName, "ModifyVehicleInfo", "{}");
//4 批量調用設備的服務。
List<String> deviceNamesService = new ArrayList<>();
deviceNamesService.add(deviceName);
InvokeThingsService(InstanceId, null, deviceProductkey, deviceNamesService, "ModifyVehicleInfo", "{}");
}
運行調試
設備端SDK和云端SDK配置完成后,運行各SDK。
查看結果:
- 查看本地日志。
- 在物聯網平臺控制臺,對應實例下設備的設備詳情頁面,單擊默認模塊:
- 運行狀態頁簽下,查看設備最后一次上報的屬性值和屬性數據記錄。
- 事件管理頁簽下,查看設備上報的事件記錄。
- 服務調用頁簽下,查看云端下發的服務調用記錄。