简介

HUAWEI HiLink智能家居主要是将传统家电增加HiLink通信模组(包含WiFi模组、蓝牙模组、Zigbee模组),将家电和HiLink联网,从而完成家电的远程控制、智能化场景、设备间的智能联动。
开发者需要,

您将建立什么

在这个Codelab中,你将创建出一个可以接入HiLink生态系统的全彩LED灯。这个灯可以

您将会学到什么

硬件要求

软件要求

按下面的电路图,将HiLink模组开发板和开源JTAG调试器、全彩LED灯、按键连接在一起,构建一个"自带开关的全彩LED灯"硬件调试环境。

下面是实际使用到的HiLink WiFi模组对应的GPIO信息:
LED红色:IO12(PA12),模式是PWM。
LED绿色:IO5(PA5),模式是PWM。
LED蓝色:IO22(PA22),模式是PWM。
按键:IO19(PA19),模式是上拉输入。

FT2232 OpenOCD的开源调试器使用Channel 1。

本步骤是在开发者联盟的智能家居版块中,进行智能产品的创建。通过创建产品,开发者可以获得产品在HiLink生态中必要产品ID等基础数据。 创建产品过程中定义的产品信息,也将通过智能家居呈现给最终消费者。

通过华为开发者联盟网站进入到HiLink智能家居版块。
https://developer.huawei.com/consumer/cn/

点击左侧侧的"+"号,新建一个智能单品的开发项目。

本次Codelab是做一个硬件接入的设备,需要选择"硬件接入"。

本次Codelab是准备开发一款"Codelab全彩灯",属于照明品类里面的智能照明,使用WiFi模组。

进入功能定义后,选择下面3个功能。

本次Codelab主要验证上述3个常用功能。

  1. 开关,开关灯功能。
  2. RGB颜色,对全彩LED灯进行调色。
  3. 定时,定时开启和关闭的任务。

选择需要的3个功能后,需要进行"保存"操作。
到此,开发者完成了产品的功能定义部分。下一步进入智能设备的固件开发。

进入固件开发步骤后,此次Codelab选择使用"爱联(AI-Link)"模组进行开发。本次Codelab分为C语言二次开发。另一个Codelab为JavaScript二次开发。

在选择完成对应的开发方式后,可以进行二次开发包的下载。(通过点击第三步位置的SDK下载)

空白工程部署

HiLink WiFi模组的C语言二次开发的工程已经展开到一个Project1的目录下。开发者可以根据需要修改Project1的目录的名称。下面以RGBLight的工程目录作为演示例子的工程目录名称。

初始展开后的目录如下。开发者的代码主要放在src目录下。

下载和合并产品功能代码框架

准备好空白工程目录后,开发者需要从前面开发者平台中对应产品下载HiLink业务代码框架。这部分代码是根据开发者定义的功能自动生成的。

下载到产品的开发包后,展开获得一个目录。从目录中提取HiLink SDK相关的业务代码目录,合并到空白工程中。

展开后的目录如上。
需要将hilinksdk这个目录拷贝到空白工程的src目录下。

合并代码完成后,使用Visual Studio Code(已经加入HiLink模组编译调试相关的组件)打开RGBLight目录。

可以通过RGBLight的右键菜单中的"Open with Code"或者"Open with Visual Studio Code"的快捷菜单开启工程。

开启工程代码后,查看检查user.mk文件。

合并后的RGBLight工程可以进行编译测试。这个工程虽然还没有加入RGB灯的控制代码、GPIO初始化代码,但是是可以通过编译的。

在Visual Studio Code(后续简称VSC)左侧有一个Task Explorer,通过执行build firmware对RGBLight工程进行编译。

编译成功后,是会输出image_all_ota1.bin的固件

目前完成编译的只是空白工程+自动化生成的产品功能代码框架。下一步,开发者需要根据产品的连线进行GPIO、PWM等的初始化代码补全。

业务代码补全

状态变量和初始化GPIO

src/hilinksdk/hilink_device.c

#include <pwmout_api.h> #include <gpio_api.h> #include <los_swtmr.h> static bool s_On = false; // 灯的开关状态 static int s_R = 255; // RGB颜色值 static int s_G = 255; static int s_B = 255; static int s_Mode = 0; // 灯的模式, 0:彩色;1:单色;2:预置流光;3:自定义流光;4:设备预置模式 // 初始化全彩RGB LED所需要的GPIO 和 按键的GPIO // 实验板上的GPIO: // LED R: IO 12 PWM3 // LED G: IO 5 PWM4 // LED B: IO 22 PWM5 // 按键 : IO 19 #define PWM_PERIOD 1000 // 1000us 1KHz #define R_LED PA_12 #define G_LED PA_5 #define B_LED PA_22 #define BUTTON PA_19 static pwmout_t R_pwm, G_pwm, B_pwm; static gpio_t Switch_Button; static UINT16 timer_id; void button_entry(UINT32 arg); void Codelab_RGB_GPIO_Init() { // 初始化LED GPIO为PWM pwmout_init(&R_pwm, R_LED); pwmout_period_us(&R_pwm, PWM_PERIOD); pwmout_pulsewidth_us(&R_pwm, 0); pwmout_init(&G_pwm, G_LED); pwmout_period_us(&G_pwm, PWM_PERIOD); pwmout_pulsewidth_us(&G_pwm, 0); pwmout_init(&B_pwm, B_LED); pwmout_period_us(&B_pwm, PWM_PERIOD); pwmout_pulsewidth_us(&B_pwm, 0); // 启用LiteOS的软件定时器(5ms)来作为按键的防抖检测 gpio_init(&Switch_Button, BUTTON); gpio_dir(&Switch_Button, PIN_INPUT); // 输入 gpio_mode(&Switch_Button, PullUp); // 上拉 // 启动一个5ms定时器(演示代码,实际应用注意判断返回值) LOS_SwtmrCreate(5, LOS_SWTMR_MODE_PERIOD, button_entry, &timer_id, 0); LOS_SwtmrStart(timer_id); } void RGB_Set(int R, int G, int B) { // 根据每个颜色的值,设置PWM占空比 pwmout_pulsewidth_us(&R_pwm, R * 1000 / 255); pwmout_pulsewidth_us(&G_pwm, G * 1000 / 255); pwmout_pulsewidth_us(&B_pwm, B * 1000 / 255); }

这部分代码对RGB灯和按键 GPIO进行初始化。
其中,RGB分别接入的3个引脚都初始化为PWM,并设定PWM的频率为1KHz,也就是1000us的周期宽度。并设置RGB默认是关闭的,即PWM的占空比为0。

同时初始化按键的GPIO为输入方式,且为芯片内部上拉。
再有,启动一个LiteOS的软件定时器,为后续按键的防抖处理做准备。

提供一个RGB_Set的函数,用来控制RGB灯的颜色。通过设定RGB通道的PWM的占空比来调整全彩LED的显示颜色。因为在前面定义功能时,使用默认的功能属性的取值范围为0~255,所以需要对1000us的占空比周期做一个换算。

GPIO和定时器的初始需要通过main.c在初始化系统时调用。

src/hilinksdk/include/hilink_device.h

void Codelab_RGB_GPIO_Init();

src/main.c

rtc_init(); // 初始化实验板上的全彩LED灯和按键使用的GPIO Codelab_RGB_GPIO_Init(); HILINK_ENTRY();

在main.c的main函数中,定时器初始化后,在进入HiLink SDK初始化前,需要对业务使用的外设进行初始化。增加调用Codelab_RGB_GPIO_Init(),对GPIO和定时器等进行初始化。

RGB灯控制代码

HiLink自动生成的代码框架中,控制代码部分在Codelab RGB灯中主要有两个:

  1. 开关灯的控制代码;
  2. RGB颜色控制代码。

开关灯的控制代码通过handle_switch_cmd函数来实现。通过下面代码来实现开关灯效果。

src/hilinksdk/hilink_device.c

int handle_switch_cmd(bool* on) { // 实现对on属性的修改 if (on == NULL) { return HILINK_ERR; } // 若同步操作改变设备状态, 状态改变后, 返回HILINK_OK // 若异步操作改变设备状态, 此处返回HILINK_PROCESSING, 待状态改变后主动上报新状态 if ( s_On == *on ) { // 状态无变化 return HILINK_OK; } // 改变全彩灯的状态,利用记忆的RGB开灯。关灯时,不改变RGB值 if (*on) { // 开灯 RGB_Set(s_R, s_G, s_B); } else { // 关灯 RGB_Set(0, 0, 0); } s_On = *on; //上报状态 report_switch_state(s_On); return HILINK_OK; }

RGB颜色控制代码则通过handle_colour_cmd函数进行控制。
src/hilinksdk/hilink_device.c

int handle_colour_cmd(int* red, int* green, int* blue) { if ( ( s_R == *red ) && ( s_G == *green ) && ( s_B == * blue ) ) { // 没有变化,不做任何操作 return HILINK_OK; } // 若同步操作改变设备状态, 状态改变后, 返回HILINK_OK // 若异步操作改变设备状态, 此处返回HILINK_PROCESSING, 待状态改变后主动上报新状态 // 检查当前总开关状态,如果是关闭状态,只刷新缓存数据,不设置到GPIO上 if (s_On) { RGB_Set(*red, *green, *blue); } s_R = *red; s_G = *green; s_B = *blue; report_colour_state(s_R, s_G, s_B); return HILINK_OK; }

彩色灯的标准功能中会附带一个模式控制。Codelab暂不对这个模式进行处理。使用默认生成的代码即可。

RGB灯状态获取代码

HiLink智能家居App、HiLink智能家居云会根据实际运行情况,对联网的智能设备进行设备状态的查询。所以需要对状态获取部分的请求进行正确的代码补充。

src/hilinksdk/hilink_device.c

int get_switch_state(bool* on) { // 返回当前全彩LED灯的开关状态 *on = s_On; return HILINK_RET_SUCCESS; } int get_colourMode_state(int* mode) { // 返回当前全彩灯的模式 *mode = s_Mode; return HILINK_RET_SUCCESS; } int get_colour_state(int* red, int* green, int* blue) { // 返回当前彩色值 *red = s_R; *green = s_G; *blue = s_B; return HILINK_RET_SUCCESS; }

状态的读取在Codelab RGB灯涉及到3个状态:当前开关状态、当前模式、当前RGB数值。实际反馈状态时,只需要将模组(或者产品)当前缓存的状态返回即可。

按键代码

在本次Codelab中,为增加全彩LED产品产生事件,来联动其他场景或设备,特别增加了一个按键。这个按键会配合这个产品实现两个功能:

  1. 开关全彩灯。开启后,重新打开上次关闭的颜色。(短按按键)
  2. 恢复出厂设置。(长按10秒)

src/hilinksdk/hilink_device.c

// ====================== Codelab实验板按键处理代码 ================= static int s_Button_Down = 0; static int s_Button_Down_Count = 0; static int s_Button_Up_Count = 0; void button_click() { // 开关灯 bool on = !s_On; // 翻转 handle_switch_cmd(&on); } void button_long_click() { // 恢复出厂设置 hilink_restore_factory_settings(); } // 简单消抖和长按处理代码:用5ms定时检查安装状态,判断连续按下时间,只有按下达到100ms,如果中途有10ms抖动,就会重新计数 // 连续按下10秒,判断为长按。 void button_entry(UINT32 arg) { // 1ms检查一次按键状态 int state = gpio_read(&Switch_Button); if (s_Button_Down == 1) { if (state == 0) { s_Button_Down_Count++; s_Button_Up_Count = 0; if (s_Button_Down_Count > 2000) { // 长按10秒了,亮绿灯指示 // Status_LED_on(); } } else { s_Button_Up_Count++; if (s_Button_Up_Count > 2) { s_Button_Down = 0; if (s_Button_Down_Count > 20) { // 有按下动作 if (s_Button_Down_Count < 200) { // 短按 button_click(); } else if (s_Button_Down_Count > 2000) { // 长按10秒 button_long_click(); } else { // 中间临界位置,不做处理 } } s_Button_Down_Count = 0; } } } else { if (state == 0) { s_Button_Down_Count = 0; s_Button_Up_Count = 0; s_Button_Down = 1; } } }

通过增加上述代码来实现对按键的消抖判断,以及短按、长按的判断。
短按后,调用开关函数。
长按10秒后,调用HiLink模组恢复出厂设置的接口。

编译、加载、调试

完成上述业务代码的补全后,就可以进行编译。编译方法和前面空白工程的编译方法一样,执行Task Explorer中的build firmware任务。
编译有错误时,根据错误提示,进行代码修改。
完成编译后,可以进行Flash加载。还是通过Task Explorer中的flash firmware任务,将编译好的固件通过JTAG调试器写入到模组的flash中。

Flash写入完成后,Codelab的RGB灯就完成所有的开发任务。

Flash写入成功后,模组会自动重启,全彩灯就可以进入到配网模式,可以通过开发版的智能家居App进行设备的添加操作。

在Codelab环境下,会配置一个串口监视工具,查看从HiLink WiFi模组的调试串口输出的信息。

可以查看到系统引导过程的信息。

开发完固件后,需要进入下一步,交互开发。

但是,因为固件没有上传,所以下一步没法继续。
在Codelab中,可以通过点击流程上的"产品配置",暂时跳过固件开发这个步骤。
实际产品开发过程,只要上传固件和填写合适信息后,就可以正常进入下一步。

每款产品在HiLink智能家居App上都有自己配套的UI控制界面。目前开放的UI界面开发方式有两种:

  1. 使用开发者联盟上的UI+在线开发工具来快速拖拽一个智能产品控制页面;
  2. 或者使用线下的HTML5方式开发控制页面,并将这个页面打包上传到平台

本次Codelab主要体验使用HiLink提供的UI+快速界面开发工具。

进入界面设计后,默认启用UI+工具,并根据当前产品的品类,以及产品选择的标准功能,自动生成一个默认布局的UI控制界面。如上图。
我们设定一个目标界面,如下图

将RGB演示调节这个控件,调整为 一个长条形的,这样布局看上去比较合理。
首先,需要选中RGB颜色这个部件。

选中RGB颜色控件(实际是选中RGB颜色控件的容器),此时在右侧功能操作区中出现3个部件的列表。
将RGB颜色区域的"显示长卡片"勾选。

RGB颜色区域将变成一个长条形的控制区域。
倒计时和定时就会重新排列在一起。
修改后的界面将更加合理。

界面设计完成后,这个界面开发步骤完成。但是,开发者可能更希望在实际的设备上体验一把实际在移动设备上的效果。

可以通过UI+工具的预览功能进行查看。

在右侧区域中,有一个保存按键,首先存储当前的设计。实际,在设计过程中,可以随时保存UI设计过程。

然后第二个按键,是一个QR Code按键。这个按键按下后会呈现一个二维码。这个二维码实际是一个移动端Web页面。

通过手机的扫一扫功能,浏览这个移动网页,可以在移动设备上预览产品的UI控制界面的效果。
完成产品UI界面开发后,下一步是做产品配置。

产品配置中主要有上述的3类,配网步骤图、产品图、场景联动。
本次Codelab主要体验设备联动配置,即IFTTT。(因时间关系,就不进行配网步骤图、产品图的处理了,使用默认空白的)

管理场景联动配置界面中,选择"开关"这个属性,既可以作为触发条件,也可以作为执行任务。然后点击保存,保存场景联动配置。

恭喜,完成上面的工作后,一个智能产品的开发基本完成了!

在实际产品开发中,还有最后一个"HiLink认证"步骤,这个是产品完成调测、自测,解决Bug后,可以提交给华为或第三方认证机构进行HiLink认证。完成认证后,HiLink的智能设备就可以最终进入到商用环境,消费者就可以使用。
Codelab演练时,并不会进入到商用环境。

调测准备

打开开发调试版本的智能家居App后,需要进入到"关于"中,进行相关配置。

需要将App连接的云修改到"厂家认证云"和切换环境目录到"测试环境(guide目录)"。

发现添加设备

在HiLink模组写入固件并成功启动后,这个HiLink设备首次引导就进入配网模式,等待智能家居App的发现和配置。

打开智能家居App后,会自动发现一个新设备。这个设备的名称会根据开发者在创建产品时提供的产品名称。
然后根据智能家居App完成设备添加。建议,给新增的设备取合适的名称,避免和其他开发者重复(因为Codelab现场可能会有多个Demo共用同一个临时开发账号)。

点击进入产品控制页面后,会呈现该产品在UI+上设计的界面。开发者可以对该设备进行开关、调色、设置倒计时定时的功能。

测试设备基础功能

测试设备联动场景

在Codelab场景中,会配置另一个HiLink灯泡作为联动场景的另一个设备。
目标:创建两个联动场景

  1. 开启Codelab全彩灯,同时开启另一个HiLink灯泡
  2. 关闭Codelab全彩灯,同时关闭另一个HiLink灯泡

首先进入到智能家居App的"智能"卡片中的"我的"。

然后通过点击"+"按键,添加智能场景

选择添加"智能编排"。
创建两个场景:
同时开

同时关

完成后,可以看到两个新增的智能编排(IFTTT)。

此时,就可以通过按动Codelab全彩灯开发板上的按键,在开启和关闭开发板上全彩LED灯的同时,另外联动的HiLink灯也会跟随一起开启和关闭。

干得好,你已经成功完成了Codelab并学到了:

本Codelab中所用demo源码下载地址如下:

源码下载

已复制代码