全部产品
Search
文档中心

阿里云物联网平台:实例迁移服务端修改示例

更新时间:Aug 18, 2023

实例迁移后相关业务的云端API运行需要切换到目标企业版实例下,因此您需开发更新数据库中设备所属实例ID信息的方法,以及在调用云端API控制设备服务时,传入更新后企业版实例ID的方法。本文以Java语言的开发环境为例,介绍实例迁移相关业务系统中服务端的修改示例。

背景信息

实例迁移的详细说明,请参见使用前必读

订阅实例迁移数据的方法,请参见设置数据流转规则

开发环境说明

开发环境如下:

示例代码说明

功能

说明

更新设备数据

解析公共实例通过规则引擎订阅的实例迁移消息:解析迁移成功的设备流转消息,根据设备信息更新数据库存储的实例ID信息。

控制设备服务

修改控制设备相关业务的接口调用方法: 调用云端接口时,先查询数据库表中实例ID信息(企业版实例ID),然后设置接口请求参数IotInstanceId为该企业版实例ID,最后调用接口。

更新设备数据的示例代码

您需依赖AMQP客户端接入的SDK,开发更新设备数据的方法。AMQP客户端接入示例,请参见Java SDK接入示例

更新处理实例迁移消息的方法:processMessage方法,替换为如下代码。其中updateDeviceInstanceId(productKey, deviceName, targetInstanceId)recoverDeviceInstanceId(productKey, deviceName)是实现数据库更新数据的方法,需开发者根据实际场景自行完成开发。

private static void processMessage(Message message) {
        try {
            byte[] body = message.getBody(byte[].class);
            String content = new String(body);
            String topic = message.getStringProperty("topic");
            String messageId = message.getStringProperty("messageId");
            logger.info("receive message"
                + ",\n topic = " + topic
                + ",\n messageId = " + messageId
                + ",\n content = " + content);

            if (null == content) {
                logger.error("content is null");
            }

            JSONObject object = JSON.parseObject(content);
            String status = object.getString("status");

            // 更新迁移成功的设备实例ID。
            String targetInstanceId = object.getString("targetInstance");

            // 处理迁移成功的设备, 更新为目标企业实例ID。
            if (StringUtils.equals(status, "GRAY_EXECUTING") || StringUtils.equals(status, "ALL_EXECUTING")) {
                JSONArray successDevices = object.getJSONArray("successDevices");

                if (successDevices == null) {
                    return;
                }

                for (int i = 0; i < successDevices.size(); i++) {
                    JSONObject device = successDevices.getJSONObject(i);
                    if (null == device) {
                        return;
                    }

                    String deviceName = device.getString("deviceName");
                    String productKey = device.getString("productKey");

                    // todo:根据productKey和deviceName, 按照target更新数据库中迁移成功的设备实例ID。
                    // updateDeviceInstanceId(productKey, deviceName, targetInstanceId)


                }
            }

            // 处理回滚成功的设备,恢复为原有实例ID。
            if (StringUtils.equals("status", "ROLL_BACK_EXECUTING")) {
                JSONArray successDevices = object.getJSONArray("successDevices");
                if (successDevices == null) {
                    return;
                }

                for (int i = 0; i < successDevices.size(); i++) {
                    JSONObject device = successDevices.getJSONObject(i);
                    if (null == device) {
                        return;
                    }

                    String deviceName = device.getString("deviceName");
                    String productKey = device.getString("productKey");

                    // todo:根据productKey和deviceName, 恢复数据库中的instanceId. 恢复策略具体需要区分业务场景。
                    // 1、原有公共实例调用业务没有存实例ID, 恢复实例ID为null。
                    // 2、原有公共实例调用存了实例ID特定值, 恢复实例ID为原有默认值。
                    // recoverDeviceInstanceId(productKey, deviceName)
                }
            }
        } catch (Exception e) {
            logger.error("processMessage occurs error ", e);
        }
    }

控制设备服务的示例代码

您需依赖物联网平台云端SDK,开发调用设备相关业务API的方法。云端SDK使用示例,请参见Java SDK使用说明

配置依赖的接口调用方法:以Pub接口为例,如下代码新增调用接口方法pub(client, productKey, deviceName)。其中getInstanceId(productKey, deviceName)方法实现逻辑,需开发者根据实际场景自行完成开发。

  public static void main(String[] args) {
        String accessKey = "${accessKey}";
        String accessSecret = "${accessSecret}";
        String productKey = "${productKey}";
        String deviceName = "${deviceName}";
        IClientProfile profile = DefaultProfile.getProfile("cn-shanghai", accessKey, accessSecret);
        DefaultAcsClient client = new DefaultAcsClient(profile);

        pub(client, productKey, deviceName);
    }

    private static void pub(DefaultAcsClient client, String productKey, String deviceName) {
        PubRequest request = new PubRequest();
        //从数据库中获取实例ID。
        String instanceId = getInstanceId(productKey, deviceName);

        //如果实例ID不为空,传参设置实例ID。注意只有企业实例需要传入此参数,公共实例无需传入此参数。
        if (!StringUtils.isEmpty(instanceId)) {
            request.setIotInstanceId(instanceId);
        }

        request.setProductKey("${productKey}");
        request.setMessageContent(Base64.encodeBase64String("hello world".getBytes()));
        request.setTopicFullName("/${productKey}/${deviceName}/user/get");
        request.setQos(0); //目前支持QoS0和QoS1。
        try {
            PubResponse response = client.getAcsResponse(request);
            System.out.println(response.getSuccess());
            System.out.println(response.getCode());
            System.out.println(response.getErrorMessage());
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            System.out.println("ErrCode:" + e.getErrCode());
            System.out.println("ErrMsg:" + e.getErrMsg());
            e.printStackTrace();
        }
    }

    /**
     * 从数据库中获取实例ID。
     *
     * @param productKey
     * @param deviceName
     * @return
     */
    private static String getInstanceId(String productKey, String deviceName) {
        String instanceId = "";
        // todo:按照 productKey和deviceName从数据库中查询梳理信息。
        // instanceId = query(productKey, deviceName);

        return instanceId;
    }