华为云应用侧Android Studio开发

本文将介绍如何使用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.gradleapp/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";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);final Thread t = new Thread() {@Overridepublic 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. 调用
@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);tev = findViewById(R.id.tev);final Thread t = new Thread() {@Overridepublic 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() {@Overridepublic void onFailure(Call call, IOException e) {// 处理网络错误或请求失败runOnUiThread(() -> tev.setText("Error: " + e.getMessage()));}@Overridepublic void onResponse(Call call, Response response) throws IOException {if (response.isSuccessful()) {// 处理成功的响应并更新UIString 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() {@Overridepublic 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() {@Overridepublic void onFailure(Call call, IOException e) {// 处理网络错误或请求失败runOnUiThread(() -> tev.setText("Error: " + e.getMessage()));}@Overridepublic void onResponse(Call call, Response response) throws IOException {if (response.isSuccessful()) {// 处理成功的响应并更新UIString 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博客

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/444448.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PHP智慧餐饮新风尚点餐系统

智慧餐饮新风尚点餐系统 —— 美食与科技的完美碰撞 &#x1f37d;️ 开篇&#xff1a;智慧餐饮的崛起 在快节奏的现代生活中&#xff0c;智慧餐饮正逐渐成为我们日常的一部分。随着科技的飞速发展&#xff0c;餐饮行业也在不断创新&#xff0c;力求为顾客提供更加便捷、高效…

深信服上网行为管理AC无法注销在线用户

下图用户认证成功后无法注销 很多入网的用户都是使用的这个账号 针对单个IP强制注销也不生效 解决步骤&#xff1a; 接入管理-用户管理-用户绑定管理-用户绑定 删除绑定免认证的配置 删除后所有用户会强制注销掉&#xff0c;重新登录即可 可添加主页联系方式帮忙远程解决问…

codeforces- 973-div2----补题

1、求最小时间 思路&#xff1a;简单的模拟 木桶效应 #include<iostream> #include<algorithm> using namespace std; typedef long long ll; int dx[] { 0,1,0,-1 }; int dy[] { 1,0,-1,0 }; const ll N 2e5 5; const ll mod 1e9 7; ll a[N]; void solve…

免费又好用的保护网站WAF,基于语义引擎的waf雷池社区版推荐

为什么传统规则防护失效了&#xff1f;&#x1f914; 目前&#xff0c;大多数 Web 应用防火墙&#xff08;WAF&#xff09;依赖规则匹配来识别和阻断攻击流量。然而&#xff0c;随着 Web 攻击的低成本、复杂多样的手段和频繁爆发的高危漏洞&#xff0c;管理人员不得不频繁调整防…

pyQT5+vscode python开发环境搭建

1、下载安装python https://www.python.org/ftp/python/3.9.13/python-3.9.13-amd64.exe 注意&#xff1a;高版本python的pyQT5可能有兼容性问题,我之前装的python3.11时pyuic就不工作&#xff0c;就降级为3.9 2、安装pip 及 pyQT python -m ensurepip --default-pip pip i…

蓝桥杯【物联网】零基础到国奖之路:十六. 扩展模块之矩阵按键

蓝桥杯【物联网】零基础到国奖之路:十六. 扩展模块之矩阵按键 第一节 硬件解读第二节 CubeMX配置第三节 MDK代码 第一节 硬件解读 扩展模块和ADC模块是一摸一样的&#xff0c;插在主板上。 引脚对应关系&#xff1a; PB6-ROW1 PB7-ROW2 PB1-COLUMN1 PB0-COLUMN2 PA8-COLUMN3 …

骨传导耳机哪个牌子好?2024年度五大高分骨传导机型推荐!

骨传导耳机哪个牌子好&#xff1f;作为专业健身教练&#xff0c;我平日在训练的时候会使用骨传导耳机来听歌&#xff0c;不过&#xff0c;随着骨传导耳机热度逐渐提高&#xff0c;如今市场上骨传导耳机品牌繁多&#xff0c;类型各异&#xff0c;它们的质量差距也很大。很多网红…

【Java】多线程代码案例

多线程代码案例 单例模式初步了解饿汉模式懒汉模式线程安全问题分析存在的问题 生产者消费者模型初识生产者消费者模型初识阻塞队列生产者消费者模型的意义BlockingQueue阻塞队列模拟实现 定时器初识计时器初识Timer类初识 schedule() 方法简易定时器的实现思路讲解代码书写 线…

耳机座接口会被TYPE-C取代吗?

耳机座接口&#xff0c;即传统的3.5mm耳机插孔&#xff0c;一直以来都是音频设备的标准配置。然而&#xff0c;随着科技的发展和用户需求的变化&#xff0c;TYPE-C接口逐渐崭露头角&#xff0c;成为许多设备的主流选择。这一趋势引发了一个重要问题&#xff1a;耳机座接口会被T…

Collection 集合框架

Collection 集合框架 各类集合 Set TreeSet 基于红黑树实现&#xff0c;支持有序性操作&#xff0c;例如根据一个范围查找元素的操作。但是查找效率不如 HashSet&#xff0c;HashSet 查找的时间复杂度为 O(1)&#xff0c;TreeSet 则为 O(logN)。 HashSet 基于哈希表实现&…

php常用的注释符号

如果没有安装vscode和小皮&#xff0c;请点击下方链接安装&#xff1a; Vscode、小皮面板安装-CSDN博客 在学习php过程中&#xff0c;肯定少不了注释&#xff0c;也可以理解为备注的信息&#xff0c;来提醒自己这段代码有什么用&#xff0c;是什么意思等&#xff0c;接下来就介…

【Redis】网络模型(day10)

在本篇文章中&#xff0c;主要是对五种网络模型进行一个简单的介绍&#xff0c;然后对Redis4.0和6.0的网络模型进行一个概述。 用户空间和内核空间 在Linux系统上&#xff0c;分为用户空间、内核空间和硬件设备。硬件设备主要包括CPU、内存、网卡等物体&#xff0c;内核应用去…

QT开发--QT基础

第0章 QT工具介绍 0.1 编译工具 uic&#xff0c;rcc&#xff0c;moc&#xff0c;qmake 都是 qt 的工具 uic 主要是 编译 .ui文件 -> ui_xxx.h //.ui文件 .h rcc 主要是 编译 资源文件.qrc文件 -> xxx.rcc …

SpringBoot3.3 优雅启停定时任务

定时任务是非常常见的功能,在一个复杂的应用程序中,如何优雅地管理这些定时任务的启动与停止尤为重要。 Spring Boot 提供了强大的任务调度支持,通过@Scheduled注解可以轻松地创建定时任务,并且可以通过配置来灵活地管理这些任务的执行环境。在本文中,我们将深入探讨如何…

如何设置 GitLab 密码过期时间?

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 学习极狐GitLab 的相关资料&#xff1a; 极狐GitLab 60天专业…

使用Pytorch+Numpy+Matplotlib实现手写字体分类和图像显示

文章目录 1.引用2.内置图片数据集加载3.处理为batch类型4.设置运行设备5.查看数据6.绘图查看数据图片(1)不显示图片标签(2)打印图片标签(3)图片显示标签 7.定义卷积函数8.卷积实例化、损失函数、优化器9.训练和测试损失、正确率(1)训练(2)测试(3)循环(4)损失和正确率曲线(5)输出…

高效使用AI,一文掌握提示词的编写原则

ChatGPT问世以后就引爆全网热议&#xff0c;它除了能够聊天&#xff0c;还可以根据所提出的要求进行文字翻译、文案撰写、代码撰写等工作。在 《探秘爆火的ChatGPT&#xff1a;大语言模型是个啥&#xff1f;它到底咋工作的&#xff1f;》 一文中&#xff0c;我已经详细介绍了Ch…

仿IOS桌面悬浮球(支持拖拽、自动吸附、自动改变透明度与点击、兼容PC端与移动端)

使用 pointerdown/pointermove/pointerup 实现仿IOS桌面悬浮球效果&#xff0c;支持拖拽、指定拖拽选对容器&#xff0c;指定拖拽安全区、自动吸附、自动改变透明度与点击&#xff0c;兼容PC端与移动端。 效果展示 https://code.juejin.cn/pen/7423757568268304421 代码实现 …

掌握RocketMQ4.X消息中间件(一)-RocketMQ基本概念与系统架构

1 MQ介绍 MQ(Message Quene) : 翻译为 消息队列,别名为 消息中间件&#xff0c;通过典型的 生产者和消费者模型,生产者不断向消息队列中生产消息&#xff0c;消费者不断的从队列中获取消息。因为消息的生产和消费都是异步的&#xff0c;而且只关心消息的发送和接收&#xff0c…

<Project-8.1 pdf2tx-MM> Python Flask 用浏览器翻译PDF内容 2个翻译引擎 繁简中文结果 从P8更改

更新 Project Name&#xff1a;pdf2tx (P6) Date: 5oct.24 Function: 在浏览器中翻译PDF文件 Code:https://blog.csdn.net/davenian/article/details/142723144 升级 Project Name: pdf2tx-mm (P8) 7oct.24 加入多线程&#xff0c;分页OCR识别&#xff0c;提高性能与速度 使…