设备与云端基于Alink协议进行物模型数据通信,包括设备上报属性或事件消息到云端,从云端下发设置属性或调用服务消息到设备。本文提供代码Java Demo,介绍物模型数据通信代码配置。

前提条件

创建产品和设备

首先,需创建产品和设备,为产品定义功能(即物模型)。

  1. 登录物联网平台控制台
  2. 在左侧导航栏,单击设备管理 > 产品
  3. 单击创建产品,创建产品。
    详细操作指导,请参见创建产品
  4. 产品详情功能定义页签下,定义物模型。

    本示例中使用了以下属性、服务和事件:


    物模型通信

    定义物模型的操作方法,请参见新增物模型

  5. 在左侧导航栏,单击设备,创建设备。
    本示例代码中涉及批量设置设备属性和批量调用设备服务,所以需至少创建两个设备。详细操作指导,请参见批量创建设备

下载、安装Demo SDK

本示例提供的SDK Demo中包含了服务端SDK Demo和设备端SDK Demo。

  1. 单击下载iotx-api-demo,并解压缩。
  2. 打开Java开发工具,导入解压缩后的iotx-api-demo文件夹。
  3. java目录下的pom文件中,添加以下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>6.5.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.1</version>
      <scope>compile</scope>
    </dependency>
  4. 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。

    将光标定位到您的账号头像上,选择accesskeys,进入安全信息管理页,可创建或查看您的AccessKey。

    accessKeySecret 您的阿里云账号的AccessKey Secret。查看方法同上AccessKey ID。
    regionId 您的物联网设备所属地域ID。地域ID的表达方法,请参见地域和可用区

设备端SDK上报属性和事件

配置设备端SDK连接物联网平台,上报属性和事件消息。

Demo中,java/src/main/com.aliyun.iot.api.common.deviceApi目录下的ThingTemplate文件是设备端上报属性和事件的Demo。

  • 设置连接信息。

    将代码中productKeydeviceNamedeviceSecretregionId替换为您的设备证书信息和地域ID。

    public static void main(String[] args) {
            /**
             * 设备证书信息
             */
            String productKey = "your productKey";
            String deviceName = "your deviceName";
            String deviceSecret = "your deviceSecret";
            /**
             * mqtt连接信息
             */
            String regionId = "your device regionId";
            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, regionId);
        }
  • 初始化连接。
    public void init(final DeviceInfo deviceInfo, String region) {
            LinkKitInitParams params = new LinkKitInitParams();
            /**
             * 设置 Mqtt 初始化参数
             */
            IoTMqttClientConfig config = new IoTMqttClientConfig();
            config.productKey = deviceInfo.productKey;
            config.deviceName = deviceInfo.deviceName;
            config.deviceSecret = deviceInfo.deviceSecret;
            config.channelHost = deviceInfo.productKey + ".iot-as-mqtt." + region + ".aliyuncs.com:1883";
            /**
             * 是否接受离线消息
             * 对应 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));
    
                    //属性上报
                    handlePropertySet("MicSwitch", new ValueWrapper.IntValueWrapper(3));
    
                    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 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);
      
              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 ProductKey, List<String> DeviceNames, String Items) {
              SetDevicesPropertyResponse response = new SetDevicesPropertyResponse();
              SetDevicesPropertyRequest request = new SetDevicesPropertyRequest();
              request.setDeviceNames(DeviceNames);
              request.setItems(Items);
              request.setProductKey(ProductKey);
      
              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 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);
      
              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 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);
      
      
              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));
              }
          }

设置属性和调用服务的请求示例:

public static void main(String[] args) {
        /**上线设备*/
        String deviceName = "2pxuAQB2I7wGPmqq****";
        String deviceProductkey = "a1QbjI2***";
        //1 设置设备的属性
        SetDeviceProperty(null, deviceProductkey, deviceName,"{\"hue\":0}");
        //2 批量设置设备属性
        List<String>  deviceNames = new ArrayList<>();
        deviceNames.add(deviceName);
        SetDevicesProperty(deviceProductkey, deviceNames, "{\"hue\":0}");
        //3 调用设备的服务
        InvokeThingService(null, deviceProductkey, deviceName, "ModifyVehicleInfo", "{}");
        //4 批量调用设备的服务
        List<String>  deviceNamesService = new ArrayList<>();
        deviceNamesService.add(deviceName);
        InvokeThingsService(null, deviceProductkey, deviceNamesService, "ModifyVehicleInfo", "{}");
    }

运行调试

设备端SDK和云端SDK配置完成后,运行各SDK。

查看结果:

  • 查看本地日志。
    物模型通信
  • 在物联网平台控制台,对应设备的设备详情页,
    • 运行状态页签下,查看设备最后一次上报的属性值和属性数据记录。
    • 事件管理页签下,查看设备上报的事件记录。
    • 服务调用 页签下,查看云端下发的服务调用记录。

    物模型通信