首页 > 其他分享 >华为云应用侧Android Studio开发

华为云应用侧Android Studio开发

时间:2024-10-08 17:19:22浏览次数:10  
标签:IAM String 华为 Token Studio new 参数 Android id

本文将介绍如何使用AndroidStudio开发APP完成与接入华为云IoTDA设备的对接,包括属性参数获以及取命令下发。

一、鉴权认证

应用侧需要通过IAM服务鉴权,获取token,华为账号创建 IAM 用户, 可以为创建的用户分配权限

认证鉴权_设备接入 IoTDA_华为云

1. 创建IAM账户

  1. 在统一身份认证服务,左侧导航窗格中,单击用户--->“创建用户”。
  2. 配置基本信息。在“创建用户”界面填写“用户信息”和“访问方式”。如需一次创建多个用户,可以单击“添加用户”进行批量创建,每次最多可创建10个用户。
  3. 创建用户组
  4. 加入用户组并创建用户
  5. 为用户组授权

2. 获取IAM用户Token

IAM 用户需要通过 HTTPS 协议 POST 请求调用API 接口, 获取 IAM 用户的 Token,华为云认证通过后向应用服务器返回鉴权 X-SubjectToken。 该 Token 用于后续进一步的身份验证和授权操作。Token的有效期为24小时

2.1. 请求示例

POST: https://iam.myhuaweicloud.com/v3/auth/tokens

{
    "auth": {
        "identity": {
            "methods": [
                "password"
            ],
            "password": {
                "user": {
                    "domain": {
                        "name": "IAMDomain"        //IAM用户所属账号名
                    },
                    "name": "IAMUser",             //IAM用户名
                    "password": "IAMPassword"      //IAM用户密码
                }
            }
        },
        "scope": {
           "project": {
                "name": "xxxxxxxx"
            }
        }
    }
}

其中IAM用户名为“IAMUser”,IAM用户密码为“IAMPassword”,所属账号名为“IAMDomain”,在本次实验中个参数如下:

IAMUser:创建用户时填写的名字 DJ_IOT

IAMPassword:创建用户时填写的密码 ********

IAMDomain:在“我的凭证”界面,API凭证页签中,查看账号名、账号ID、用户名、用户ID、项目名称、项目ID。

3. 代码构造

3.1.  添加依赖

本次实验中使用OkHttp3库来发送HTTP请求,首先,在build.gradle(app/build.gradle)文件中添加OkHttp的依赖。

dependencies {
    implementation ("com.squareup.okhttp3:okhttp:4.9.3")
}

3.2. 声明权限

AndroidManifest.xml中声明网络权限,

<uses-permission android:name="android.permission.INTERNET" />

3.3. 构建方法

该方法有4个入参分别是:租户名IAMDomain,用户名IAMUser,密码IAMPassword,请求地址iamTokenUrl,具体内容见上文。

private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
private static final OkHttpClient client = new OkHttpClient(); // 假设OkHttpClient是线程安全的,可以作为静态成员

// 方法签名修改为接受必要的参数
public String getIAMToken(String huaweiName, String iamIname, String iamPassword, String iamTokenUrl) throws IOException {
    // 构建JSON请求体
    String jsonBody = String.format("{\"auth\": {\"identity\": {\"methods\": [\"password\"],\"password\": {\"user\": {\"domain\": {\"name\": \"%s\"},\"name\": \"%s\",\"password\": \"%s\"}}},\"scope\": {\"project\": {\"name\": \"cn-north-4\"}}}}",
            huaweiName, iamIname, iamPassword);

    RequestBody body = RequestBody.create(jsonBody, JSON);

    // 构建请求
    Request request = new Request.Builder()
            .url(iamTokenUrl)
            .post(body)
            .addHeader("Content-Type", "application/json")
            .build();

    // 发送请求并处理响应
    try (Response response = client.newCall(request).execute()) {
        if (!response.isSuccessful()) {
            // 输出错误内容
            System.out.println("Unexpected code " + response);
            throw new IOException("Unexpected code " + response);
        }

        // 从响应头中提取IAM令牌
        String iamToken = response.header("X-Subject-Token");
        if (iamToken == null || iamToken.isEmpty()) {
            // 记录警告日志(如果没有找到令牌)
            throw new IOException("IAM token not found");
        }

        return iamToken;
    } catch (IOException e) {
        // 记录异常日志
        throw e; // 重新抛出异常以便调用者可以处理
    }
}
3.4. 调用

在APP启动时调用一次,Android 禁止在主线程中进行网络操作,因为这可能会导致应用界面卡顿或冻结,所以调用的时候使用new Thread创建并启动线程。

String HUAWEINAME="xxxxxxx";  //华为账号名
String IAMINAME="xxxxxxx";    //IAM账户名
String IAMPASSWORD="xxxxxxx"; //IAM账户密码
String URL="https://iam.cn-north-4.myhuaweicloud.com/v3/auth/tokens?nocatalog=false";


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
       
        final Thread t = new Thread() {
            @Override
            public void run() {
                try {
                    IoTDAUtils hw = new IoTDAUtils();
                    String token = hw.getIAMToken(HUAWEINAME,IAMINAME,IAMPASSWORD,URL);
                    System.out.println("获取token:" + token);
                } catch (Exception e) {
                    e.printStackTrace();
                    System.out.println("错误" + e.getMessage().toString());
                }
            }};
        t.start();
       
    }
3.5. token

在logcat中token已经打印出来

二、查看影子消息

        设备影子是一个用于存储和检索设备当前状态信息的JSON文档。每个设备有且只有一个设备影子,由设备ID唯一标识,设备影子用于存储设备上报的(状态)属性和应用程序期望的设备(状态)属性,无论该设备是否在线,都可以通过该影子获取和设置设备的属性。

        利用设备影子消息获取设备属性无论设备是否在线都可以查看最近一次上报的属性,如果使用查询设备属性功能需要与设备端联动下发查询指令设备端收到后上报指令,本次采用影子消息来获取设备属性。

查询设备影子数据_设备接入 IoTDA_华为云

1. URI

GET https://{endpoint}/v5/iot/{project_id}/devices/{device_id}/shadow

路径参数如下

参数

是否必选

参数类型

描述

project_id

String

参数说明:项目ID。获取方法请参见 获取项目ID

device_id

String

参数说明:设备ID,用于唯一标识一个设备。在注册设备时直接指定,

或者由物联网平台分配获得。 取值范围:长度不超过128,只允许字母、数字、下划线(_)、连接符(-)的组合。

请求参数如下:

参数

是否必选

参数类型

描述

X-Auth-Token

String

参数说明:用户Token。通过调用IAM服务 获取IAM用户Token接口获取,接口返回的响应消息头中“X-Subject-Token”就是需要获取的用户Token。简要的获取方法样例请参见 Token认证

Instance-Id

String

参数说明:实例ID。物理多租下各实例的唯一标识,建议携带该参数,在使用专业版时必须携带该参数。您可以在IoTDA管理控制台界面,选择左侧导航栏“总览”页签查看当前实例的ID,具体获取方式请参考查看实例详情

响应Body参数:

参数

参数类型

描述

device_id

String

设备ID,用于唯一标识一个设备。在注册设备时直接指定,或者由物联网平台分配获得。由物联网平台分配时,生成规则为"product_id" + "_" + "node_id"拼接而成。

shadow

Array of DeviceShadowData objects

设备影子数据结构体。

2. 代码构造

2.1. 构建方法
private static String IOTDA_ENDPOINT = "https://iotda.cn-north-4.myhuaweicloud.com/v5/iot/%s/devices/%s/shadow";
String project_id="*******************";
String device_id="********************";

public void getDeviceShadow(String token,Callback callback) {
    IOTDA_ENDPOINT = String.format(IOTDA_ENDPOINT, project_id,device_id);
    Request request = new Request.Builder()
            .url(IOTDA_ENDPOINT)
            .addHeader("Content-Type", "application/json")
            .addHeader("X-Auth-Token", token)  // 注意:这里应该使用有效的认证令牌
            .build();

    Call call = client.newCall(request);
    call.enqueue(callback);
}
2.2. 调用
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tev = findViewById(R.id.tev);
        final Thread t = new Thread() {
            @Override
            public void run() {
                try {
                    IoTDAUtils hw = new IoTDAUtils();
                    AUTH_TOKEN = hw.getIAMToken(HUAWEINAME,IAMINAME,IAMPASSWORD,URL);
                    System.out.println("获取token:" + AUTH_TOKEN);
                    hw.getDeviceShadow(AUTH_TOKEN,new Callback() {
                        @Override
                        public void onFailure(Call call, IOException e) {
                            // 处理网络错误或请求失败
                            runOnUiThread(() -> tev.setText("Error: " + e.getMessage()));
                        }

                        @Override
                        public void onResponse(Call call, Response response) throws IOException {
                            if (response.isSuccessful()) {
                                // 处理成功的响应并更新UI
                                String responseBody = response.body().string();
                                runOnUiThread(() -> tev.setText("Device Shadow: " + responseBody));
                            } else {
                                // 处理不成功的响应(如认证失败、资源未找到等)
                                runOnUiThread(() -> tev.setText("Request failed: " + response.code()));
                            }
                        }
                    });
                } catch (Exception e) {
                    e.printStackTrace();
                    System.out.println("错误" + e.getMessage().toString());
                }
            }};
        t.start();
    }
}

三、命令下发

下发设备命令_设备接入 IoTDA_华为云

1. URI

POST https://{endpoint}/v5/iot/{project_id}/devices/{device_id}/commands

路径参数

参数

是否必选

参数类型

描述

project_id

String

参数说明:项目ID。获取方法请参见 获取项目ID

device_id

String

参数说明:下发消息的设备ID,用于唯一标识一个设备,在注册设备时由物联网平台分配获得。 取值范围:长度不超过128,只允许字母、数字、下划线(_)、连接符(-)的组合。

请求Header参数

参数

是否必选

参数类型

描述

X-Auth-Token

String

参数说明:用户Token。通过调用IAM服务 获取IAM用户Token接口获取,接口返回的响应消息头中“X-Subject-Token”就是需要获取的用户Token。简要的获取方法样例请参见 Token认证

Instance-Id

String

参数说明:实例ID。物理多租下各实例的唯一标识,建议携带该参数,在使用专业版时必须携带该参数。您可以在IoTDA管理控制台界面,选择左侧导航栏“总览”页签查看当前实例的ID,具体获取方式请参考查看实例详情

请求Body参数

参数

是否必选

参数类型

描述

service_id

String

参数说明:设备命令所属的设备服务ID,在设备关联的产品模型中定义。 取值范围:长度不超过64的字符串。

最大长度:64

command_name

String

参数说明:设备命令名称,在设备关联的产品模型中定义。 取值范围:长度不超过128的字符串。

最大长度:128

paras

Object

参数说明:设备执行的命令,Json格式,里面是一个个键值对,如果serviceId不为空,每个键都是profile中命令的参数名(paraName);如果serviceId为空则由用户自定义命令格式。设备命令示例:{"value":"1"},具体格式需要应用和设备约定。此参数仅支持Json格式,暂不支持字符串。

最大长度:261952

请求示例

POST https://{endpoint}/v5/iot/{project_id}/devices/{device_id}/commands


{
  "service_id" : "reboot",
  "command_name" : "ON_OFF",
  "paras" : {
    "value" : "ON"
  }
}

2. 代码构造

2.1. 方法构造
private static String IOTDA_ENDPOINT_CMD = "https://iotda.cn-north-4.myhuaweicloud.com/v5/iot/%s/devices/%s/commands";

public void sendDeviceCommand(String commandPayload,String token, Callback callback) {
    MediaType JSON = MediaType.parse("application/json; charset=utf-8");
    RequestBody body = RequestBody.create(JSON, commandPayload);
    IOTDA_ENDPOINT_CMD = String.format(IOTDA_ENDPOINT_CMD, project_id,device_id);
    Request request = new Request.Builder()
            .url(IOTDA_ENDPOINT_CMD)
            .post(body)
            .addHeader("Content-Type", "application/json")
            .addHeader("X-Auth-Token", token)
            .build();

    client.newCall(request).enqueue(callback);
}
2.2. 调用
@Override
public void onClick(View view) {
    final Thread t = new Thread() {
        @Override
        public void run() {
            try {
                IoTDAUtils hw = new IoTDAUtils();

                str_cmd = String.format(str_cmd, service_id,command_name,paras);
                System.out.println(str_cmd);
                hw.sendDeviceCommand(str_cmd,AUTH_TOKEN,new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        // 处理网络错误或请求失败
                        runOnUiThread(() -> tev.setText("Error: " + e.getMessage()));
                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        if (response.isSuccessful()) {
                            // 处理成功的响应并更新UI
                            String responseBody = response.body().string();
                            runOnUiThread(() -> tev.setText("Device Shadow: " + responseBody));
                        } else {
                            // 处理不成功的响应(如认证失败、资源未找到等)
                            runOnUiThread(() -> tev.setText("Request failed: " + response.code()));
                        }
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("错误" + e.getMessage().toString());
            }
        }};
    t.start();
}

四、工具类

根据以上内容整理完成IoTDAUtils工具类

package com.example.huawei_iotda_app;

import java.io.IOException;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class IoTDAUtils {
    private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
    private static final OkHttpClient client = new OkHttpClient();


    public String getIAMToken(String huaweiName, String iamIname, String iamPassword, String iamTokenUrl) throws IOException {
        // 构建JSON请求体
        String jsonBody = String.format("{\"auth\": {\"identity\": {\"methods\": [\"password\"],\"password\": {\"user\": {\"domain\": {\"name\": \"%s\"},\"name\": \"%s\",\"password\": \"%s\"}}},\"scope\": {\"project\": {\"name\": \"cn-north-4\"}}}}",
                huaweiName, iamIname, iamPassword);
        RequestBody body = RequestBody.create(jsonBody, JSON);
        // 构建请求
        Request request = new Request.Builder()
                .url(iamTokenUrl)
                .post(body)
                .addHeader("Content-Type", "application/json")
                .build();

        // 发送请求并处理响应
        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                // 输出错误内容
                System.out.println("Unexpected code " + response);
                throw new IOException("Unexpected code " + response);
            }

            // 从响应头中提取IAM令牌
            String iamToken = response.header("X-Subject-Token");
            if (iamToken == null || iamToken.isEmpty()) {
                // 记录警告日志(如果没有找到令牌)
                throw new IOException("IAM token not found");
            }
            return iamToken;
        } catch (IOException e) {
            // 记录异常日志
            throw e; // 重新抛出异常以便调用者可以处理
        }
    }

    public void getDeviceShadow(String token,String url,Callback callback) {
        Request request = new Request.Builder()
                .url(url)
                .addHeader("Content-Type", "application/json")
                .addHeader("X-Auth-Token", token)  // 注意:这里应该使用有效的认证令牌
                .build();

        Call call = client.newCall(request);
        call.enqueue(callback);
    }

    public void sendDeviceCommand(String commandPayload,String token,String url, Callback callback) {
        MediaType JSON = MediaType.parse("application/json; charset=utf-8");
        RequestBody body = RequestBody.create(JSON, commandPayload);

        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .addHeader("Content-Type", "application/json")
                .addHeader("X-Auth-Token", token)
                .build();

        client.newCall(request).enqueue(callback);
    }
}

后续将按照以上内容开发一个便于测试的APP,可关注后续文章。

文章及源码地址:华为云应用侧Android测试APP-CSDN博客

 

标签:IAM,String,华为,Token,Studio,new,参数,Android,id
From: https://blog.csdn.net/LJ_96/article/details/142755061

相关文章

  • 华为欧拉openGauss数据库部署及配置远程连接
    1.前置工作1.1配置hosts文件vi/etc/hosts#新增192.168.19.128openeuleros1.2配置limit.conf文件vi/etc/security/limits.confommsoftnprocunlimitedommhardnprocunlimitedommsoftnofile102400ommhardnofile102400ommsoftstackunlimitedomm......
  • 华为Datacom考什么?要考几门?
    华为认证细致地分为HCIA、HCIP和HCIE这三个具有显著差异的级别。就在今天,让咱们一同分别针对改版后三个级别的Datacom考试展开全面且深入的介绍。细致探讨看看它们各自具体考查哪些内容,究竟要通过考几门课程才能成功获取证书。01、HCIA-Datacom认证考几门HCIA-D......
  • 【源码+文档+调试讲解】基于Android的固定资产借用管理平台
    摘 要固定资产借用管理平台设计的目的是为用户提供使用申请、故障报修、设备归还、意见反馈等管理方面的平台。与PC端应用程序相比,固定资产借用管理平台的设计主要为管理员和用户提供便利。用户可以通过Android及时查看设备信息等。固定资产借用管理平台是在Android操作......
  • Android车载音频系统概览
    目录1.什么是Android车载音频系统2.Android声音和声音流2.1Android声音2.2外部声音流2.3输出设备章节说明:本节内容是Android车载音频系统简介。1.什么是Android车载音频系统官方英文名称是:Automotiveaudiosystems由于汽车上无论是音频设备的数量还是......
  • visual studio 使用技巧 1:快速找到接口的实现类
    在VisualStudio中,可以通过以下几种方法快速查找接口的实现类:1.使用“查找所有引用”功能右键点击接口名称。选择“查找所有引用”(FindAllReferences)。在结果窗口中,您可以看到所有实现了该接口的类。2.使用“导航到实现”功能(推荐)这个我......
  • FL Studio 24.1.2.4381中文版免费下载及FL Studio 24最新使用学习教程
    家好呀,作为一个资深的音乐爱好者和制作人,今天我要安利一个我最近超级痴迷的数字音频工作站软件——FLStudio24.1.2.4381中文版。这款产品可是让我的音乐创作之路如虎添翼,快来跟我一起看看它的炫酷功能吧!最近接到很多小伙伴的私信,都在问我平时会使用哪些音乐软件,能不能给一......
  • Android 11 如何不要验证Wi-Fi CA 凭证(手工连接WIFI, 需要ROOT)
    Android11如何不要验证Wi-FiCA凭证(手工连接WIFI,需要ROOT)在获取了ROOT权限的基础上,如果因为您机器所使用OS版本的限制无法在GUI界面选择符合您企业设置的WI-FI选项,可以使用本文教程中指出的手工连接WIFI的方式.Step1.检查adbshellsucat/data/misc/apexdata/c......
  • 谷歌:过渡到 Rust 使得 Android 漏洞大幅下降
    谷歌:过渡到Rust使得Android漏洞大幅下降来源:OSCHINA编辑: 白开水不加糖2024-09-2810:54:58 6谷歌在最新的一篇文章中指出,内存安全问题导致的漏洞百分比与新代码使用的开发语言密切相关。而随着其将开发转向内存安全语言,Android内存安全漏洞的百分比已经......
  • Android 工程目录结构
    App工程分为两个层次,第一个层次是项目,另一个层次是模块.模块依附于项目,每个项目至少有一个模块,也能拥有多个模块.一般所言的“编译运行App”,指的是运行某个模块,而非运行某个项目,因为模块才对应实际的App.App项目下面有两个分类:app(代表app模块)、GradleScripts.app下面有3个......
  • Visual Studio 小技巧记录
    1、将行距设置成1.15跟舒服一些。2、括号进行颜色对比。效果:3、显示参数内联提示。效果:4、保存时规范化代码。配置文件:5、将滚动条修改为缩略图效果:......