admin管理员组

文章数量:1122846

操作手册——软件篇

一、准备工作

  • Windows的Hyper-V功能开启

选择开始菜单,单击设置

选择系统->激活,查看自己的Windows版本是家庭版还是其它

Windows专业版开启Hyper-V功能

开启后,重启电脑,在搜索栏上搜索Hyper-V,看是否存在

Windows家庭版开启Hyper-V功能

1.打开记事本,将下面的代码复制到里面,然后另存为XX.bat,名字可以自定义

@echo off

Pushd "%~dp0"

dir /b %SystemRoot%\servicing\Packages\*Hyper-V*.mum >hyper-v.txt

for /f %%i in ('findstr /i . hyper-v.txt 2^>nul') do dism /online /norestart /add-package:"%SystemRoot%\servicing\Packages\%%i"

del hyper-v.txt

Dism /online /enable-feature /featurename:Microsoft-Hyper-V -All /LimitAccess /ALL

pause

2.运行后,会在当前目录创建hyper.txt文件(可以删除),重启后,搜索Hyper是否存在,如果没有,那就可以使用专业版的方法启动该功能(家庭版默认该功能被隐藏)

参考文章:

Windows家庭版没有Hyper-V功能的解决方案_windows没有hyper-v-CSDN博客

  • 华为DevEco Studio安装手册

文档中心

注意:安装华为DevEco Studio时,一定要先启用Hyper-V功能,否则无法使用模拟器或者预览器

  • 硬件模拟测试软件

MQTTX

MQTTX:全功能 MQTT 客户端工具

二、华为云的使用

  • 华为云IoTDA的搭建

1.登录华为云

2.选择合适的服务区域

3.选择服务列表

4.搜索设备接入IoTDA服务

5.购买实例

6.按照图片所示进行自定义配置

7.确定配置无误后,选择提交

8.进入创建后的实例

9.创建设备之前,先记录一下后续操作需要使用的信息

10.MQTT接入地址是硬件或软件模拟上传数据的服务器地址,HTTPS接入地址是后续使用鸿蒙app进行云端数据获取或者命令下发的endpoint参数

11.选择产品

12.创建产品

13.按照图片所示进行自定义配置

14.所属行业与所属子行业可以随便选择模板,后续是通过自己的自定义模型来添加实际的数据属性和命令

15.选择详情进入产品详情页

16.添加自定义模型

17.自定义服务ID名,该ID也是后续鸿蒙app所使用的serviceid

18.根据自己的需求添加数据属性和命令

19.LedStatus是字符串类型,访问方式可读;命令LedSwitch,下发参数为value(字符串类型),响应参数result(布尔型),不同的命令的下发参数和响应参数可以一样,因为它们是通过命令名称进行区分的。注意: 数据类型要与硬件或者软件模拟的数据类型保存一致,否则会出现问题

20.进入Topic管理

21.记录一下设备ID就是后面所创建的云端设备

平台下发命令给设备:

$oc/devices/设备ID/sys/commands/response/request_id=

设备上报属性数据:

$oc/devices/设备ID/sys/properties/report

22.选择设备->所有设备

23.注册设备,添加云端设备

24.根据下面的图片进行自定义配置

25.保存并关闭后,浏览器会下载一个密钥文件,可以选择自己保存,也可以删除,因为设备详情页里面可以查看

26.进入设备详情页

27.根据图片,记录一下所需内容

  • 件或软件模拟测试硬

1.根据图片,将之前记录的相关信息填入到MQTTX软件中,硬件类似

2.连接成功后,云端设备会显示在线

3.使用$oc/devices/设备ID/sys/properties/report,将数据按照指定格式进行数据的上报。

参考文档:

设备属性上报_设备接入 IoTDA_华为云

4.上报成功后,云端会得到硬件或软件模拟的值

三、鸿蒙app的使用

1.先记录一下自己API凭证,这是后续鸿蒙app的project_id,项目ID

2.一般都是创建一个新的权限不高的IAM用户来获取XToken,在后续的鸿蒙app中用于获取XToken,只有经过验证后的XToken,才能让鸿蒙app获取云端数据或者下发命令

3.在创建的鸿蒙项目的ets目录下创建Tools目录和Models目录,然后在Tools创建一个HttpTool的ArkTS文件,在Models目录下创建一个HW_User的ArkTS文件(这是将常用的Http操作和IAM用户获取X-Token进行封装,方便后续操作)

HW_User.ets

export class HW_User {
  auth: Auth

  constructor(name: string, password: string, domain: string) {
    this.auth = {
      "identity": {
        "methods": [
          "password"
        ],
        "password": {
          "user": {
            "domain": {
              "name": domain        //IAM用户所属账号名
            },
            "name": name, //IAM用户名
            "password": password      //IAM用户密码
          }
        }
      },
      "scope": {
        "domain": {
          "name": domain       //IAM用户所属账号名
        }
      }
    }
  }
}

interface Auth {
  identity: Identity
  scope: Scope
}

interface Identity {
  methods: string[]
  password: Password
}

interface Password {
  user: User
}

interface User {
  name: string
  password: string
  domain: Domain
}

interface Domain {
  name: string
}

interface Scope {
  domain: Domain
}

结构是固定的,通过封装类来实现

参考文档:

获取IAM用户Token(使用密码)_统一身份认证服务 IAM_华为云

文档中的请求示例

HttpTool.ets

import { http } from '@kit.NetworkKit'

import { BusinessError } from '@kit.BasicServicesKit'

export class HttpTool {

  static get(url: string, fn: Function) {

    // 每一个httpRequest对应一个HTTP请求任务,不可复用

    let httpRequest = http.createHttp()

    let options: http.HttpRequestOptions = {

      method: http.RequestMethod.GET,

      // 当使用POST请求时此字段用于传递请求体内容,具体格式与服务端协商确定

      expectDataType: http.HttpDataType.OBJECT, // 可选,指定返回数据的类型

      // 开发者根据自身业务需要添加header字段

      // header: { 'Accept': 'application/json' },

      header: {

        'Content-Type': 'application/json',

        'X-Auth-Token': globalThis.token  //获取云端数据需要xToken认证,这里使用全局变量

      },

    }

    httpRequest.request(url, options, (err: BusinessError, data: http.HttpResponse) => {

      if (!err) {

        fn(data)

      } else {

        console.info('error:' + JSON.stringify(err))

      }

      httpRequest.destroy()

    })

  }

 //一般情况下的post请求

  static post(url: string, param: string | Object | ArrayBuffer, fn: Function) {

    // 每一个httpRequest对应一个HTTP请求任务,不可复用

    let httpRequest = http.createHttp()

    let options: http.HttpRequestOptions = {

      method: http.RequestMethod.POST,

      // 当使用POST请求时此字段用于传递请求体内容,具体格式与服务端协商确定

      extraData: param,

      expectDataType: http.HttpDataType.OBJECT, // 可选,指定返回数据的类型

      // 开发者根据自身业务需要添加header字段

      // header: { 'Accept': 'application/json' },

      header: {

        'Content-Type': 'application/json',

      },

    }

    httpRequest.request(url, options, (err: BusinessError, data: http.HttpResponse) => {

      if (!err) {

        fn(data)

      } else {

        console.info('error:' + JSON.stringify(err))

      }

      httpRequest.destroy()

    })

  }

  //命令下发使用的post请求

  static postCommands(url: string, param: string | Object | ArrayBuffer, fn: Function) {

    // 每一个httpRequest对应一个HTTP请求任务,不可复用

    let httpRequest = http.createHttp()

    let options: http.HttpRequestOptions = {

      method: http.RequestMethod.POST,

      // 当使用POST请求时此字段用于传递请求体内容,具体格式与服务端协商确定

      extraData: param,

      expectDataType: http.HttpDataType.OBJECT, // 可选,指定返回数据的类型

      // 开发者根据自身业务需要添加header字段

      // header: { 'Accept': 'application/json' },

      header: {

        'Content-Type': 'application/json',

        'X-Auth-Token': globalThis.token //下发命令需要xToken认证,这里使用全局变量

      },

    }

    httpRequest.request(url, options, (err: BusinessError, data: http.HttpResponse) => {

      if (!err) {

        fn(data)

      } else {

        console.info('error:' + JSON.stringify(err))

      }

      httpRequest.destroy()

    })

  }

}

参考文档:

文档中心

Index.ets

import { HW_User } from '../Models/HW_User'

import { HttpTool } from '../Tools/HttpTool'

import { http } from '@kit.NetworkKit'

//通过接口的封装来下达命令和接受返回参数

interface Command {

  service_id: string

  command_name: string

  paras: Paras

}

interface Paras {

  value: string

}

interface Properties {

  LedStatus: string

}

// Command和Paras使用接口来实现命令下发的上传格式,Properties是使用接口获取云端数据的返回数据

@Entry

@Component

struct Index {

  private url: string = 'https://iam.myhuaweicloud/v3/auth/tokens'

  private hw_user = new HW_User('你创建的IAM用户', '你的IAM用户密码', '你的登录或注册的默认用户就是domain')

  // 使用封装的HW_User来进行用户的认证,从左往右依次是新创建的IAM用户及其密码,还有你的默认用户企业管理员

  private endpoint: string = '你的http接入地址'

  private project_id: string = '你的api凭证也就是项目id'

  private device_id: string = '你的设备id'

  //endpoint是你之前复制的https接入地址,project_id是你复制的api凭证(要与区域保持一致),device_id是你的设备id

  private url1: string =

    'https://' + this.endpoint + '/v5/iot/' + this.project_id + '/devices/' + this.device_id + '/shadow'

  private url2: string =

    'https://' + this.endpoint + '/v5/iot/' + this.project_id + '/devices/' + this.device_id + '/commands'

  //url1是获取云端数据的写法,url2是命令下发的写法

  @State properties: Properties = { LedStatus: '' }

  private com: Command = { service_id: 'TS001', command_name: 'LedSwitch', paras: { 'value': 'ON' } }

 //使用接口重载可以方便后续的调整

  build() {

    Column() {

      Column() {

        //onClick事件,当单击文本时,触发里面所写的内容

        Text('获取Token').fontSize(25).onClick(() => {

          HttpTool.post(this.url, this.hw_user, (data: http.HttpResponse) => {

            console.log('result:', JSON.stringify(data.result))

            globalThis.token = data.header['x-subject-token'] //x-subject-token作为全局变量,让封装的HttpTool类可以使用

          })

          // 使用封装类后的HttpTool的post请求获取到x-token的值

        })

        Text('获取数据').fontSize(25).onClick(() => {

          HttpTool.get(this.url1, (data: http.HttpResponse) => {

            console.log('result:', JSON.stringify(data.result)) //打印获取的结果到终端上

            this.properties = data.result['shadow'][0].reported.properties as Properties

            console.log('LedStatus:' + this.properties.LedStatus) //将获取到的LedStatus打印到终端上

          })

        })

        Text('命令下发测试').fontSize(25).onClick(() => {

          HttpTool.postCommands(this.url2, this, (data: http.HttpResponse) => {

            console.log('result:', JSON.stringify(data.result))//将获取到的命令返回结果打印到终端上

          })

        })

      }

    }.width('100%').height('100%')

  }

}

数据获取参考文档

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

命令下发参考文档

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

4.代码写好后,启动预览器或者模拟器,然后打开日志调试终端,进行测试

软件模拟或硬件做出命令回应的格式参考文档

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

软件模拟或硬件上传数据的格式参考文档

设备属性上报_设备接入 IoTDA_华为云

至此,有关鸿蒙app连接华为云获取硬件上传的数据和下发命令的操作教程结束,至于本地服务端的搭建,因每个人所使用的web框架和数据库不一样,这里不在写了。简单来说就是web框架连接数据库,从数据库获取数据,然后使用鸿蒙app的post请求获取web框架的页面路由返回数据,就可以将数据读取到鸿蒙app中。

鸿蒙的ArkTS语言学习参考文档:

官方文档:

文档中心-HarmonyOS NEXT开发文档-华为开发者联盟

官方免费的视频教程:

华为开发者学堂

或者其它平台的学习资源

操作手册——硬件篇

  • 一、OpenHarmony硬件开发环境配置

声明:提供的资料文件有

hi3861_hdu_iot_application240515

DevTools_Hi3861V100_v1.0.zip

CH341SER.EXE

串口调试助手

(一)、安装 Visual Studio Code

1.下载VSCode

VSCode全称是Visual Studio Code,它是一款免费开源的现代化轻量级代码编辑器VSCode官方下载地址是:Visual Studio Code - Code Editing. Redefined我们使用Windows x64 版本

具体安装步骤参考VSCode安装配置使用教程(最新版超详细保姆级含插件)一文就够了_vscode使用教程-CSDN博客

2.安装VSCode相关插件

安装完VSCode后,需要安装如下图的插件:

以C/C++插件安装为例,点击左侧的扩展商店里输入“C/C++”,选择下载第一个

其余插件安装步骤相似,最终安装结果显示如下:

  1. 安装DevEco Device Tool

HUAWEI DevEco Device Tool(以下简称DevEco Device Tool)是HarmonyOS面向智能设备开发者提供的一站式集成开发环境,支持HarmonyOS的组件按需定制,支持代码编辑、编译、烧录和调试等功能,支持C/C++语言,以插件的形式部署在Visual Studio Code上。

  1. 打开HarmonyOS官网开发工具网站:华为集成开发环境IDE DevEco Device Tool下载 | HarmonyOS设备开发

找到“DevEco Device Tool 4.0 Release”

  1. 在控制面板-添加或删除程序中,搜索Python关键字,遭到所有安装的Python进行卸载,特别是安装Anconda环境下的Python,避免干扰环境,确保在cmd中输入python后系统找不到python环境即可。

  1. 双击DevEco Device Tool安装包程序,点击“Next”,进行安装。
  2. 设置安装路径,点击“Next”。

  1. 第2)步中已经卸载Python,所以选择“自定义安装”(注意选择Add Python 3.8 to PATH),然后点击Install Now。安装完成后点击Close即可。

选择添加PATH选项

注意 Python 必须安装在全英文目录!如果默认目录不是全英文目录,需要点击 Customize install ation 选项:

然后点击 Next

勾选 Install for all users 和 Add Python to environment variables,从而保证英文安装目录并添加环境变量。

在界面中点击“安装”进行软件安装。

安装成功后打开VSCode后扩展览显示这四个扩展:

4.启动DevEco Device Tool

1)启用VSCode,在DevEco Device Tool运行时依赖C/C++、CodeLLDB插件,可以在VSCode的扩展包管理处进行搜索和安装。

  1. 重启VSCode软件,点击左侧扩展列表,即可打开DevEco Home界面,表示成功安装开发环境。

5.下载SDK

我会将SDK压缩包提供出来

我们的例程代码位于目录【\\hi3861_hdu_iot_application\src\vendor\hqyj\fs_hi3861\demo】面,可通过编辑【\\hi3861_hdu_iot_application\src\applications\sample\wifi-iot\app\BUILD.gn】中的信息来将编译目录指向我们的例程,如下图所示:

  1. 开发工具下载

1)我将提供DevTools_Hi3861V100_v1.0.zip包,注意解压到全英文目录下,解压后的目录文件结构如下:

2)打开VSCode,打开DevEco Device Tool主页,点击导入工程

3)在导入工程弹窗中选择Hi3861 SDK目录,点击导入

4)在后续导入工程弹窗,SOC栏选择Hi3861,开发板栏选择hi3861,框架栏选择hb,之后点击导入,等待导入成功即可。

  1. 代码导入成功后,即工程创建成功,之后可使用该IDE 实现代码开发、一键编译、一键烧写等功能。

7)配置开发工具路径,点击左侧的工程配置,选中请选择自定义工具包(有的版本可能无此界面,直接进行下一步即可)。

8)然后在右侧窗口中找到“hi3861找到“compiler_bin_path”,选择到之前下载的开发工具。

  1. 配置产品

注意:以下步骤已经在所给文件中配置完成,不用手动配置,后期更改编译文件时在选择性地配置。

1)src/applications/sample/wifi-iot/BUILD.gn文件中,修改features,如下所示。该路径用于指示编译系统去哪里寻找需要编译的组件。其中冒号前的demo指的是文件所在的目录,冒号后的demo 指的是该目录下的BUILD.gn文件中的哪个lite_component

2).修改vendor/hqyj/fs_hi3861/demo/BUILD.gn,根据需要编译对应的示例程序:

3)由于编译过程中涉及到部分板级的驱动,因此需要复制光盘资料里的硬件驱动代码到hi3861_hdu_iot_application\src\vendor\hqyj\fs_hi3861\common\bsp目录,并且在程序里引入相应文件时保证该工程下的BUILD.gn文件里面包含了相应的路径。我们提供的工程文件已做好这些内容,因此不用再次操作。

  1. 编译工程

1)配置完成后,点击左侧“Rebuild”,开始编译。

2)初次编译会解压编译工具,时间较长。等待编译完成即可。

  1. 代码烧录
  1. 串口驱动安装

1.先使用配套的Type-C数据线,将开发板与电脑的USB口进行连接。

2.安装CH340G驱动。安装CH341SER.EXE文件。

双击CH341SER.EXE驱动,进入安装界面,点击安装按钮即可,驱动安装成功后,再点击确定按钮,即可显示安装驱动成功。

  1. 打开Windows的设备管理器,查看串口设备,若未出现CH340串口设备,请检查驱动是否安装正常。

  1. 串口烧录
  1. 当前DevEco Device Tool工具支持Hi3861单板一键烧录功能。需要连接开发板,配置开发板对应的串口,在编译结束后,进行烧录。点击左侧工程配置,找到“upload_port”选项,选择开发板对应的烧录串口(注意:如果正在使用Monitor功能,请先关闭Monitor,才能正常烧,否则串口占用无法烧录成功)。

2.打开开发板左下角的电源S1

3.点击VSCode左下角“upload”按键,等待提示(出现Connectingplease reset device...),手动进行开发板复位(按下开发板复位按键)。

4.等待烧录完成,大约30s左右,烧录成功。

10.串口打印

1)烧录完成后,可以通过Monitor界面查看串口打印,配置Monitor串口,如下图所示。

2)配置完Monitor串口后,直接点击monitor按钮,复位开发板,查看开发板端的打印信息。

查看串口信息也可用串口调试助手(UartAssist)进行。注意,如果使用中文,需要选择好编码集。

智能农业的项目实操

  1. 修改文件

对C:\hi3861_hdu_iot_application\src\vendor\hqyj\fs_hi3861\common\bsp\include\hal_bsp_ssd1306_bmps.h路径下的文件进行

#define smartFarm 0 

修改成

#define smartFarm 1

修改

C:\hi3861_hdu_iot_application\src\vendor\hqyj\fs_hi3861\demo\BUILD.gn文件中

的 "smartFarm:smartFarm_demo",将注释的#号去掉

进入我们已经注册过的阿里云物联网平台中,点击进入设备接入ioTDA。

点击试用进入控制台

点击进入iot实例

点击设备—所有设备


进入后可以看到我们在上面已经创建过的设备

点击详情操作页面

找到mqtt连接参数,点击查看

可以查看连接mqtt所需要的参数

回到vccode中

在我们的代码中找到smartfarm的项目文件夹,代码的路径

C:\hi3861_hdu_iot_application\src\vendor\hqyj\fs_hi3861\demo\smartFarm

打开项目中的sys_config.h文件

点击进入配置代码

将mqtt的连接参数复制到代码中,需要注意一一对应且端口号是1883并非是8883.

修改华为云平台的MQTT服务器的IP地址,打开Windows下cmd控制端,在控制端输入内容。

将这个ip地址填入代码中

填入mqtt信息

回到华为云平台iot实例,点击产品

点击详情

进入模型定义界面,点击编辑

添加基础服务(base)

添加控制服务(control)

在基础服务(base)中添加“fan”属性

在基础服务(base)中添加“humidity”属性

在基础服务(base)中添加temperature”属性

在基础服务(base)中添automode属性

在控制服务(control)中添加“fan”命令

在控制服务(control)中添加“automode”命令

回到demo代码中,进入

C:\hi3861_hdu_iot_application\src\vendor\hqyj\fs_hi3861\common\bsp\src\hal_bsp_nfc_to_wifi.c文件将上面部分注释掉

并添加这串代码

uint8_t wechat_GetWiFi_ssid_passwd(const char *nfc_buff, char *wifi_name,char *wifi_passwd)

{

    uint8_t payload_len = nfc_buff[NDEF_PROTOCOL_DATA_LENGTH_OFFSET]; // 获取数据长度

    //uint8_t payload_len = nfc_buff[2]; // 获取数据长度

    uint8_t *payload = (uint8_t *)malloc(payload_len + 1);

    uint8_t ret = 0;

    if (payload == NULL) {

        printf("payload malloc failed.\r\n");

        return 0;

    }

    memset_s(payload, payload_len + 1, 0, payload_len + 1);

    //memcpy_s(payload, payload_len + 1, nfc_buff + NDEF_PROTOCOL_VALID_DATA_OFFSET, payload_len);

    memcpy_s(payload, payload_len + 1, nfc_buff + 9, payload_len);

    printf("Use Wechat system..........\n");

    printf("payload = %s\r\n", payload);

    cJSON *root = cJSON_Parse(payload);

    cJSON *ssid = cJSON_GetObjectItem(root, "ssid");

    cJSON *password = cJSON_GetObjectItem(root, "passwd");

    if (root != NULL && ssid != NULL && password != NULL) {

        printf("ssid = %s, password = %s", ssid->valuestring, password->valuestring);

        if (strcpy_s(wifi_name, strlen(ssid->valuestring) + 1, ssid->valuestring) == 0) {

            ret = 1;

        } else {

            ret = 0;

        }

        if (strcpy_s(wifi_passwd, strlen(password->valuestring) + 1, password->valuestring) == 0) {

            ret = 1; // 成功获取到WiFi名称和密码

        } else {

            ret = 0;

        }

    cJSON_Delete(root);

    free(payload);

    ssid = NULL;

    password = NULL;

    root = NULL;

    payload = NULL;

    return ret;

}

}

uint32_t NFC_configuresWiFiNetwork(uint16_t *ndefBuff)

{

   

    if (ndefBuff == NULL) {

        printf("NFC_configuresWiFiNetwork to ndefBuff is NULL\r\n");

        return -1;

    }

    uint8_t ret = 0;

    char *  wifi_name[MAX_BUFF] = {0}; // WiFi名称

    char *  wifi_passwd[MAX_BUFF] = {0}; // WiFi密码

    //使用微信小程序进行配网

    #if 0

    if (ndefBuff[NDEF_PROTOCOL_DATA_TYPE_OFFSET] == 't') {

        ret = wechat_GetWiFi_ssid_passwd(ndefBuff, wifi_name, wifi_passwd);

    } else {

        ret = ios_GetWiFi_ssid_passwd(ndefBuff, wifi_name, wifi_passwd);

     }

     #endif

     ret = wechat_GetWiFi_ssid_passwd(ndefBuff, wifi_name, wifi_passwd);

    if (ret)

   

   

        //char *wifi_name = "peigezhao";

        //char *wifi_passwd = "peigezhao";

        printf("wifi_name: %s\n", wifi_name);

        printf("wifi_passwd: %s\n", wifi_passwd);

 

        // 连接wifi

        if (WIFI_SUCCESS == WiFi_connectHotspots(wifi_name, wifi_passwd)) {

            printf("thongth to nfc connect wifi is success.\r\n");

            ret= 0;

        } else {

            printf("thongth to nfc connect wifi is failed.\r\n");

            ret=1;

        }

       return ret;

}

对修改的代码进行编译

编译如果出现succes的绿色字体证明编译成功

点击烧录按钮,需要检测端口号是否正确

手机下载nfc标签助手

点击进入软件进行nfc配网

点击文本

在里面以josn的格式输入自己的wifi名和wifi密码

写入后靠近hi3861开发板,重启开发板即可配网成功

重启后可观察到开发版的实际效果

本文标签: 华为鸿蒙操作手册硬件软件