设备与云端基于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。
查看结果:
- 查看本地日志。
- 在物联网平台控制台,对应实例下设备的设备详情页面,单击默认模块:
- 运行状态页签下,查看设备最后一次上报的属性值和属性数据记录。
- 事件管理页签下,查看设备上报的事件记录。
- 服务调用页签下,查看云端下发的服务调用记录。