WiFi设备端开发指南
更新时间:2018-11-05 17:12:52
wifi设备端开发指南
1 简介
《wifi设备端开发指南》基于已经适配过alios-things的芯片平台,在alios-things上开发以下几种功能:
配网开发
设备重置
设备控制开发
FOTA开发
2 芯片平台
本开发指南使用庆科MK3060模组(micokit-3060)开发板作为硬件设备,alios-things支持MK3060的模组
3 源码获取
请从github上下载最新的alios-things的release版本:https://github.com/alibaba/AliOS-Things/releases
4 配网开发
4.1 4种配网模式
alios-things支持的配网模式有以下4种:
- 一键配网(Smartconfig)/手机热点配网(phone-config) App直接给设备配网
- 路由器热点配网(router-config)
- 零配(zero-config) 已配网设备为待配网设备配网
- 蓝牙配网(ble-config) 借助BT/BLE为设备配网
alios-things里面的配网代码已经开源,目录是AliOS-Things/middleware/linkkit/sdk-c/src/services/awss,仓库是https://github.com/alibaba/AliOS-Things.git,分支:rel_2.0.0
4.2 配网API
配网的api有以下几个:
启动配网服务:
int awss_start()
确认进行配网:
int awss_config_press()
配网重置:
void awss_report_reset()
系统状态:
int iotx_event_regist_cb(void (*monitor_cb)(int event))
配网的详细api请参考:智能生活开放平台-配网服务
4.3 添加组件
在mk文件中需要添加如下ywss4linkkit
组件:
$(NAME)_COMPONENTS += ywss4linkkit
4.4 配网流程
配网流程可以分为以下几步:
第一步:启动配网服务
第二步:确认进行配网
第三步:配网过程
第四步:上报token到云端
该流程是配合Demo APP来介绍的。用户在创建产品后,可以创建测试设备,会为每台设备生成三元组(ProductKey,DeviceName,DeviceSecret),APP中需要设置对应的ProductKey,才能够正常完成该设备的配网流程。具体操作请参考Demo App使用文档。
第一步:启动配网服务
设备上电后,调用函数:int awss_start()
启动配网服务,此时并没有正式开始配网,而是处于扫描模式。
第二步:确认进行配网
当用户操作app后(也可以先操作设备,但是要注意超时时间),app提示需要触控设备开始进行配网,此时设备端监听到触控事件,就调用函数int awss_config_press()
确认进行配网,配网过程会有10s以上的等待时间,等配网成功后,app端会显示配网成功。
Note:
- 如果awss_config_press没有被调用,awss仅仅解析热点列表,不解析配网包,所以要配网,一定要调用awss_config_press
- 产品和厂商只要可以检测用户触控设备,然后调用awss_config_press即可,并不需要一定要用按键,其他的方式也是可以的,只要可以检测用户触控设备即可,比如连续开关等等;
- 设备端一定要烧录完整的设备信息(Product Key, Product Secret, Device Name, Device Secret),否则配网可能会失败,Product Secret不烧录,一键配网肯定会失败
AliOS的参考代码是通过按键实现的,一般情况就是使用aos_register_event_filter()
注册按键事件:
aos_register_event_filter(EV_KEY, linkkit_key_process, NULL);
然后在按键事件里面调用awss_config_press()
启动配网过程。
void linkkit_key_process(input_event_t *eventinfo, void *priv_data)
{
if (eventinfo->type != EV_KEY) {
return;
}
if (eventinfo->code != CODE_BOOT) {
return;
}
...
if (eventinfo->value == VALUE_KEY_CLICK) {
awss_config_press();
...
}
}
第三步:配网过程
配网过程主要是APP端和设备端的交互,该过程无需开发者关注,app端和设备端会自动完成配网的过程。
第四步:配网过程
设备配网成功后,使用局域网广播(CoAP广播)对外通告配网成功,App收到该通告后,提示配网成功;
第五步:上报token到云端
当设备端配网成功,设备会建立与云端的CMP通道,然后把用于绑定设备的Token上报到云端,并确认云端收到Token后,通过局域网广播(CoAP广播)对外通告设备绑定信息,这套流程是linkkit和awss内部已经实现,对上层应用透明,也即上层应用不用做额外的处理;
4.5 配网过程示例
下面以mk3060平台的linkkitapp的示例来展示配网的过程。
4.5.1 app开发并设置三元组
用户在创建产品后,可以创建测试设备,会为每台设备生成三元组(ProductKey,DeviceName,DeviceSecret),APP中需要设置对应的ProductKey,才能够正常完成该设备的配网流程。具体操作请参考Demo App使用文档。
4.5.2 单板烧写程序
单板需要将原始用例的可执行文件烧录到mk3060单板中(即master最新的未修改过的代码,通过编译命令aos make linkkitapp@mk3060得到的可执行文件linkkitapp@mk3060.ota.bin)。
烧写的命令是长按boot键的同时短按reboot键,使MK3060进入bootloader,使用如下指令进入烧写模式:
write 0x13200
4.5.3 单板进入配网模式
- 短按reboot键,单板复位,如果设备没有连网,则待设备进入moniter模式后,出现ssid扫描列表:
- 再短按boot键,激活配网模式(短按boot键会调用到函数do_awss_active);
如果设备已配好网,reboot后不会进入moniter模式,会直接连云;
长按boot键5S,会恢复出厂设置,则可以重复1、2步骤,重新配网;
4.5.3 APP配网
待单板进入配网模式后,手机侧进行以下操作,完成一键式配网:
4.6 配网状态指示
对于WiFi设备而言,首先设备需要可以连接到WiFI热点然后才能进行设备的管理,而WiFi配网是用户使用中最容易失败的一个步骤,因此建议设备厂商在产品设计时增加一个LED灯用于配网状态的指示,下面是对配网指示灯设计的建议:
LED指示灯支持黄色、蓝色显示;
当设备未启动配网时,LED指示灯不亮;
在设备上启动配网之后,LED指示灯颜色变为黄色,表示设备进入配网状态;配网过程失败,则LED指示灯熄灭;
当设备接收到WiFi热点信息后颜色变为蓝色;
当设备连接到AP之后LED指示灯开始闪烁(快闪,亮0.1s,灭0.5s),表示设备开始尝试连接阿里云IoT平台;
当设备连接到云端之后LED指示灯变为蓝色,常亮不闪烁。
当设备已经配网成功,并重启之后该LED的指示灯显示为:
LED灯初始点亮,颜色为蓝色;
设备连接到AP之后开始闪烁(快闪,亮0.1s,灭0.5s);
设备连接到云端之后LED灯变为蓝色常亮,停止闪烁
注:设备当前位于的各种状态参考下面章节的“设备运行状态获取”进行获取,然后进行LED灯的相应控制,如果产品有语音播报能力,也可以在配网过程中设计语音提示。
5 设备运行状态获取
产品在开发时上层应用可能需要感知当前设备所处的状态,然后通过LED显示或者语音播报将状态向用户进行通告,从而让用户明确知道设备当前的运行状态,减少用户不清楚设备状态而联系客服进行咨询,降低用户支持成本、同时也提高用户满意度。设备厂商在开发产品时可以注册事件通告来实时获取设备的状态,所有的事件列表定义在文件iot_export_event.h中:
int iotx_event_regist_cb(void (*monitor_cb)(int event));
enum iotx_event_t {
IOTX_AWSS_START = 0x1000, // AWSS start without enbale, just supports device discover
IOTX_AWSS_ENABLE, // AWSS enable
IOTX_AWSS_LOCK_CHAN, // AWSS lock channel(Got AWSS sync packet)
IOTX_AWSS_CS_ERR, // AWSS AWSS checksum is error
IOTX_AWSS_PASSWD_ERR, // AWSS decrypt passwd error
IOTX_AWSS_GOT_SSID_PASSWD, // AWSS parse ssid and passwd successfully
IOTX_AWSS_CONNECT_ADHA, // AWSS try to connnect adha (device discover, router solution)
IOTX_AWSS_CONNECT_ADHA_FAIL, // AWSS fails to connect adha
IOTX_AWSS_CONNECT_AHA, // AWSS try to connect aha (AP solution)
IOTX_AWSS_CONNECT_AHA_FAIL, // AWSS fails to connect aha
IOTX_AWSS_SETUP_NOTIFY, // AWSS sends out device setup information (AP and router solution)
IOTX_AWSS_CONNECT_ROUTER, // AWSS try to connect destination router
IOTX_AWSS_CONNECT_ROUTER_FAIL, // AWSS fails to connect destination router.
IOTX_AWSS_GOT_IP, // AWSS connects destination successfully and got ip address
IOTX_AWSS_SUC_NOTIFY, // AWSS sends out success notify (AWSS sucess)
IOTX_AWSS_BIND_NOTIFY, // AWSS sends out bind notify information to support bind between user and device
IOTX_AWSS_ENABLE_TIMEOUT, // AWSS enable timeout(user needs to call awss_config_press again to enable awss)
IOTX_CONN_CLOUD = 0x2000, // Device try to connect cloud
IOTX_CONN_CLOUD_FAIL, // Device fails to connect cloud, refer to net_sockets.h for error code
IOTX_CONN_CLOUD_SUC, // Device connects cloud successfully
IOTX_RESET = 0x3000, // Linkkit reset success (just got reset response from cloud without any other operation)
};
事件处理示例:
static void linkkit_event_monitor(int event)
{
switch (event) {
case IOTX_AWSS_START: // AWSS start without enbale, just supports device
// discover
// operate led to indicate user
LOG("IOTX_AWSS_START");
break;
case IOTX_AWSS_ENABLE: // AWSS enable
LOG("IOTX_AWSS_ENABLE");
// operate led to indicate user
break;
case IOTX_AWSS_LOCK_CHAN: // AWSS lock channel(Got AWSS sync packet)
LOG("IOTX_AWSS_LOCK_CHAN");
// operate led to indicate user
break;
case IOTX_AWSS_PASSWD_ERR: // AWSS decrypt passwd error
LOG("IOTX_AWSS_PASSWD_ERR");
// operate led to indicate user
break;
case IOTX_AWSS_GOT_SSID_PASSWD:
LOG("IOTX_AWSS_GOT_SSID_PASSWD");
// operate led to indicate user
break;
case IOTX_AWSS_CONNECT_ADHA: // AWSS try to connnect adha (device
// discover, router solution)
LOG("IOTX_AWSS_CONNECT_ADHA");
// operate led to indicate user
break;
case IOTX_AWSS_CONNECT_ADHA_FAIL: // AWSS fails to connect adha
LOG("IOTX_AWSS_CONNECT_ADHA_FAIL");
// operate led to indicate user
break;
case IOTX_AWSS_CONNECT_AHA: // AWSS try to connect aha (AP solution)
LOG("IOTX_AWSS_CONNECT_AHA");
// operate led to indicate user
break;
case IOTX_AWSS_CONNECT_AHA_FAIL: // AWSS fails to connect aha
LOG("IOTX_AWSS_CONNECT_AHA_FAIL");
// operate led to indicate user
break;
case IOTX_AWSS_SETUP_NOTIFY: // AWSS sends out device setup information
// (AP and router solution)
LOG("IOTX_AWSS_SETUP_NOTIFY");
// operate led to indicate user
break;
case IOTX_AWSS_CONNECT_ROUTER: // AWSS try to connect destination router
LOG("IOTX_AWSS_CONNECT_ROUTER");
// operate led to indicate user
break;
case IOTX_AWSS_CONNECT_ROUTER_FAIL: // AWSS fails to connect destination
// router.
LOG("IOTX_AWSS_CONNECT_ROUTER_FAIL");
// operate led to indicate user
break;
case IOTX_AWSS_GOT_IP: // AWSS connects destination successfully and got
// ip address
LOG("IOTX_AWSS_GOT_IP");
// operate led to indicate user
break;
case IOTX_AWSS_SUC_NOTIFY: // AWSS sends out success notify (AWSS
// sucess)
LOG("IOTX_AWSS_SUC_NOTIFY");
// operate led to indicate user
break;
case IOTX_AWSS_BIND_NOTIFY: // AWSS sends out bind notify information
// to support bind between user and device
LOG("IOTX_AWSS_BIND_NOTIFY");
// operate led to indicate user
break;
case IOTX_AWSS_ENABLE_TIMEOUT: // AWSS enable timeout
// user needs to enable AWSS to config device again
LOG("IOTX_AWSS_ENABLE_TIMEOUT");
// operate led to indicate user
break;
case IOTX_CONN_CLOUD: // Device try to connect cloud
LOG("IOTX_CONN_CLOUD");
// operate led to indicate user
break;
case IOTX_CONN_CLOUD_FAIL: // Device fails to connect cloud, refer to
// net_sockets.h for error code
LOG("IOTX_CONN_CLOUD_FAIL");
// operate led to indicate user
break;
case IOTX_CONN_CLOUD_SUC: // Device connects cloud successfully
LOG("IOTX_CONN_CLOUD_SUC");
// operate led to indicate user
break;
case IOTX_RESET: // Linkkit reset success (just got reset response from
// cloud without any other operation)
LOG("IOTX_RESET");
// operate led to indicate user
break;
default:
break;
}
}
static void start_netmgr(void *p)
{
iotx_event_regist_cb(linkkit_event_monitor);
netmgr_start(true);
aos_task_exit(0);
}
6 设备重置
6.1 设备端配网信息重置
当设备配网成功后,alios-things中的netmgr组件会自动把AP的SSID和密码存储到flash中,如果需要配网重置的话,就需要把SSID和密码从flash中擦除掉,清除配网信息请参考netmgr的API:
void netmgr_clear_ap_config(void);
清除完SSID之后,也建议重启设备(1s后重启):
aos_post_delayed_action(1000,reboot_system,NULL);
6.2 云端的设备信息重置
当设备配网成功后,云端会把设备和用户账户绑定在一块,如果需要设备重置的话,同时也需要重置云端的设备信息,使用如下的API:
void awss_report_reset(void);
配网的详细api请参考:智能生活开放平台-配网服务
该函数是一个阻塞函数,根据当前网络情况,会有不同的阻塞时间,所以建议单独给这个函数创建一个task:
aos_task_new("reset", awss_report_reset, NULL, 2048);
7 设备控制开发
7.1 设备控制开发概要
设备控制开发前先确认以下功能已经具备:
- 设备能够连接到阿里的 智能生活开放平台
- 已经通过智能生活开放平台获取到了设备的激活码,并得到设备联网需要的
ProductKey
、ProductSecret
、DeviceName
、DeviceSecret
。 - 根据设备的功能定义,获取到物的模型(TSL),即一段json格式的描述信息。
关于智能生活开放平台的云端配置以及设备创建等步骤这里不详细描述,详情请参考如何获得设备激活码
设备控制开发需要进行如下的几步:
- 修改设备凭证:
ProductKey
、ProductSecret
、DeviceName
、DeviceSecret
。 - 设置TSL信息。
- 实现设备控制相关函数接口:
- linkkit服务程序初始化:
linkkit_start()
和linkkit_ops_t
结构体中的回调函数 - 事件分发处理:
linkkit_dispatch()
- 创建物的对象:
linkkit_set_tsl()
- 设置对象的TSL属性:
linkkit_set_value()
- 上报设备属性到云端:
linkkit_post_property()
- 上报事件到云端:
linkkit_trigger_event()
- linkkit服务程序初始化:
(国际站)连接海外服务器的设备,需切换阿里云服务器地址:
linkkit默认的阿里云服务器地址为国内的地址,如果需要更改为国外的阿里云服务器地址的话,请更改example/linkkitapp/linkkit_app.c
文件中linkkit_start()
传入的参数:
另外,修改对应的example/linkkitapp/linkkitapp.mk
修改为:
域名地址的enum定义如下:
/* domain type */
/* please sync with dm_cloud_domain_type_t */
typedef enum {
/* iot-as-mqtt.cn-shanghai.aliyuncs.com */
linkkit_cloud_domain_shanghai,
/* USA */
linkkit_cloud_domain_singapore,
linkkit_cloud_domain_max,
} linkkit_cloud_domain_type_t;
linkkit_start()
的具体参数请参考基础API7.2 接口实现
7.2.1 修改设备凭证
根据云端产生的设备凭证,修改头文件framework/protocol/linkkit/iotkit/sdk-encap/imports/iot_import_product.h
下的设备凭证信息。
#define PRODUCT_KEY "a1BDCKKSpdu"
#define PRODUCT_SECRET "Rp0aCxyRnd2ecrCX"
#define DEVICE_NAME "MVwo1x7hB2pyEbXlLkzE"
#define DEVICE_SECRET "OKHWuIaMzwtJAjUzPRLG1rcYxFo43akU"
7.2.2 修改TSL信息
在产品功能定义完成后,平台将自动生成JSON格式的TSL(即 Thing Specification Language),用来描述物的模型。该信息经过“压缩并转义”后,转换成C语言下的字符串格式,这样可以添加到设备端的TSL信息中。“压缩并转义”的方式可以参考链接:https://www.sojson.com/yasuo.html
在创建物的对象时,需要转义后的TSL信息,其修改可以参考文件:example/linkkitapp/linkkit_app.c
中的const char TSL_STRING[]
的定义。
7.2.3 linkkit函数接口
linkkit服务例程初始化需要在配网完成之后,建议注册在事件CODE_WIFI_ON_GOT_IP
里。linkkit示例分为以下步骤顺序完成:linkkit服务程序初始化,进入事件分发处理,创建对象,设置物对象的TSL属性、上报云端。后面会介绍该过程,具体请参考(aos\example\linkkitapp
下的用例代码,入口函数为linkkit_main()
)
7.2.3.1 linkkit服务程序初始化
名称 | 描述 |
---|---|
函数 | int linkkit_start(int max_buffered_msg, int get_tsl_from_cloud, linkkit_loglevel_t log_level, linkkit_ops_t *ops, linkkit_cloud_domain_type_t domain_type, void *user_context) |
说明 | 启动 linkkit 服务,与云端建立连接并安装回调函数 |
返回值 | 0: linkkit 服务程序启动成功; -1: linkkit 服务程序启动失败 |
参数 | 类型 | 描述 | 备注 |
---|---|---|---|
max_buffered_msg | int | 消息队列大小 | 此参数影响事件消息最大暂存数,频繁业务可适当增大此参数,建议值 [16~32] |
get_tsl_from_cloud | int | 获取 TSL 路径 | 0: 从本地获取物模型,非0: 从云端获取物模型 |
log_level | linkkit_loglevel_t | 设置打印的日志等级 | [0~5]: 数字越大, 打印越详细 |
ops | linkkit_ops_t* | linkkit 事件回调函数 | linkkit 通过回调函数将事件通知给用户 |
domain_type | linkkit_cloud_domain_type_t | 云服务器域名 | linkkit_cloud_domain_sh: 上海域名linkkit_cloud_domain_usa: 美国域名 |
user_context | void* | 用户上下文环境指针 | 用户自定义结构体的指针, 回调函数中传出 |
事件类型以及对应的事件回调函数如下所示,每当linkkit处理完相应的事件后,都会执行用户注册的回调函数,具体实现可参考linkkit_app.c内的实现:
typedef enum {
dm_callback_type_property_value_set = 0,
dm_callback_type_service_requested,
#ifdef RRPC_ENABLED
dm_callback_type_rrpc_requested,
#endif /* RRPC_ENABLED */
dm_callback_type_cloud_connected,
dm_callback_type_cloud_disconnected,
dm_callback_type_new_thing_created,
dm_callback_type_thing_disabled,
dm_callback_type_thing_enabled,
dm_callback_type_raw_data_arrived,
dm_callback_type_number,
} dm_callback_type_t;
static linkkit_ops_t alinkops = {
.on_connect = on_connect,
.on_disconnect = on_disconnect,
.raw_data_arrived = raw_data_arrived,
.thing_create = thing_create,
.thing_enable = thing_enable,
.thing_disable = thing_disable,
.thing_call_service = thing_call_service,
.thing_prop_changed = thing_prop_changed,
};
7.2.3.2 创建对象
根据设备描述信息(tsl),创建物的对象,并添加到linkkit中。如果创建成功,会返回物的唯一标志符,后续只需要通过该标识符来管理对象。
名称 | 描述 |
---|---|
函数 | void* linkkit_set_tsl(const char* tsl, int tsl_len) |
说明 | 从本地读取 TSL 文件,生成物的对象并添加到 linkkit 中 |
返回值 | 0: 成功; -1: 物的唯一标识符 |
参数 | 类型 | 描述 | 备注 |
---|---|---|---|
tsl | const char* | 设备描述信息( JSON 类型) | tsl 必须和设备三元组所属的产品的 Alink JSON 格式协议相同 |
tsl_len | int | 设备描述信息长度 | - |
代码示例
int linkkit_main()
{
sample_context_t* sample_ctx = &g_sample_context;
int execution_time = 0;
int get_tsl_from_cloud = 0;
execution_time = execution_time < 1 ? 1 : execution_time;
memset(sample_ctx, 0, sizeof(sample_context_t));
sample_ctx->thing_enabled = 1;
linkkit_start(16, get_tsl_from_cloud, linkkit_loglevel_debug, &alinkops, linkkit_cloud_domain_sh, sample_ctx);
if (!get_tsl_from_cloud) {
linkkit_set_tsl(TSL_STRING, strlen(TSL_STRING));
}
aos_post_delayed_action(1000, linkkit_action, sample_ctx);
return 0;
}
7.2.3.3 事件分发处理
linkkit服务程序初始化之后,需要周期性地进行进行事件分发处理,建议放到任务或delay事件中执行。该函数会根据事件回调的类型来执行相应的回调函数,linkkit_app.c的用例代码中已默认调用了该接口。
名称 | 描述 |
---|---|
函数 | int linkkit_dispatch() |
说明 | 事件分发函数,触发linkkit_start安装的回调 |
返回值 | 0: 成功; -1: 失败 |
代码示例
void linkkit_action(void *params)
{
int ret;
sample_context_t* sample_ctx = params;
linkkit_dispatch();
aos_post_delayed_action(200, linkkit_action, sample_ctx);
}
7.2.3.4 设置对象的TSL属性
设置TSL属性,就是给已创建的对象的TSL属性赋值,赋值完成后,可以通过接口linkkit_post_property
将对象属性上报到云端,也可以通过linkkit_trigger_event
将事件上报云端。
名称 | 描述 |
---|---|
函数 | int linkkit_set_value(linkkit_method_set_t method_set, const void* thing_id, const char* identifier, const void* value, const char* value_str) |
说明 | 根据identifier设置物对象的 TSL 属性,如果标识符为struct类型、event output类型或者service output类型,使用点'.'分隔字段;例如"identifier1.identifier2"指向特定的项 |
返回值 | 0: 物对象 TSL 属性设置成功; -1: 物对象 TSL 属性设置失败 |
参数 | 类型 | 描述 | 备注 |
---|---|---|---|
method_set | linkkit_method_set_t | 设置 TSL 属性的类型 | linkkit_method_set_property_value:设置模型property valuelinkkit_method_set_event_output_value:设置物模型event output valuelinkkit_method_set_service_output_value:设置物模型service output value |
thing_id | const void* | 物的唯一标识符 | 物对象的标识符,可从 thing_create 回调获得linkkit创建的 thing id |
identifier | const char* | TSL 属性标示符 | 物对象 TSL 属性的标识符 |
value | const void* | 输入的属性值 | 和 value_str, 二选一必填 |
value_str | const char* | 输入的字符串格式的属性值 | 和 value, 二选一必填 |
7.2.3.5 上报设备属性到云端
名称 | 描述 |
---|---|
函数 | int linkkit_post_property(const void* thing_id, const char* property_identifier) |
说明 | 上报设备属性到云端 |
返回值 | 0: 上报成功; -1: 上报失linkkit_post_property败 |
参数 | 类型 | 描述 | 备注 |
---|---|---|---|
thing_id | const void* | 物的唯一标识符 | 物对象的标识符,可从 thing_create 回调获得 linkkit 创建的 thing id |
property_identifier | const char* | 属性标示符 | 上报的物对象的TSL属性标识符 |
物对象的TSL标识符请参考物的TSL字符串或下图中的“标识符”列
int linkkit_data_publish(const char* identifier, const void* value, const char* value_str)
{
int ret = 0;
ret = linkkit_set_value(linkkit_method_set_property_value,g_thing_id,identifier,value,value_str);
if(0 != ret) {
return ret;
}
ret = linkkit_post_property(g_thing_id,identifier);
return ret;
}
int data_publish_test()
{
int ret = 0;
/*温度值为24.6*/
ret = linkkit_data_publish("CurrentTemperature",NULL,"24.6");
if(0 != ret) {
return ret;
}
/*湿度值为43%*/
ret = linkkit_data_publish("CurrentHumidity",NULL,"43");
if(0 != ret) {
return ret;
}
return 0;
}
7.2.3.6 上报事件到云端
linkkit_set_value
的第一个参数值选择linkkit_method_set_event_output_value
,则可以设置完事件(event)的TSL信息,之后可以通过linkkit_trigger_event
将事件发送到云端。
名称 | 描述 |
---|---|
函数 | int linkkit_trigger_event(const void* thing_id, const char* event_identifier) |
说明 | 上报设备事件到云端 |
返回值 | 0: 上报成功; -1: 上报失败 |
参数 | 类型 | 描述 | 备注 |
---|---|---|---|
thing_id | const void* | 物的唯一标识符 | 物对象的标识符,可从 thing_create 回调获得 linkkit创建的thing id |
event_identifier | const char* | 事件标示符 | 上报的事件标识符 |
设备端详细的API使用请参考文档:https://living.aliyun.com/doc#cusllk.html
7.3 用例编译
编译前确保aos\example\linkkitapp
目录下面为修改过的用例(参考第3章介绍)
编译命令为:
aos make linkkitapp@mk3060
其中 linkkitapp 为用例名称;mk3060为单板类型
编译后生成的文件为aos\out\linkkitapp@mk3060\binary\linkkitapp@mk3060.ota.bin
7.4 用例执行
用原始的linkkitapp可执行文件配网成功后,然后替换新的用例执行,在云端可以看到设备已经是在线状态:
而当设备端上传数据成功后,可以在云端看到设备上传的数据:
8 FOTA开发
8.1 准备工作
FOTA服务支持mqtt、coap、alink等协议连接阿里云,使用fota之前请确保以下功能已经具备:
至少支持了mqtt、coap、alink其中一种
bootloader支持固件升级
支持flash操作
8.2 启动FOTA服务
启动FOTA服务无需其他的初始化代码,只需要在连接上阿里云之后,调用该函数启动FOTA服务即可。
aos_post_event(EV_SYS, CODE_SYS_ON_START_FOTA, 0u);
8.3 实现FOTA回调函数
当启动了FOTA服务之后,系统会自动和云端交互。当有固件需要更新的时候,FOTA服务会自动从云端下载固件,然后通过FOTA的回调函数写入固件到flash中。
所以通过实现平台相关的的FOTA的回调函数就可以对接上FOTA功能。FOTA回调函数的实现代码位于platform/mcu/xxx/hal/ota_port.c
中。
FOTA回调函数的声明:
struct hal_ota_module_s {
hal_module_base_t base;
/* Link to HW */
int (*init)(hal_ota_module_t *m, void *something);
int (*ota_write)(hal_ota_module_t *m, volatile uint32_t *off_set,
uint8_t *in_buf , uint32_t in_buf_len);
int (*ota_read)(hal_ota_module_t *m, volatile uint32_t *off_set,
uint8_t *out_buf , uint32_t out_buf_len);
int (*ota_set_boot)(hal_ota_module_t *m, void *something);
};
这些回调函数一般在platform/mcu/xxx/hw.c
中的hw_start_hal()
函数中注册到ota服务中:
hal_ota_register_module(&esp8266_ota_module);
其中
esp8266_ota_module
类型为struct hal_ota_module_s
.具体的api详细说明请参考OTA服务
8.4 FOTA功能验证
本指南使用linkkit连接阿里IoT平台,以MQTT作为交互通道进行固件新版本查询,下载链接获取及进度上报;以http/https作为下载通道进行固件下载;
FOTA功能验证前先确认以下功能已经具备:
- 设备能够正常连接到阿里的 智能生活开放平台
- 已经通过智能生活开放平台获取到了设备的激活码,并得到设备联网需要的
ProductKey
、ProductSecret
、DeviceName
、DeviceSecret
。
8.4.1 修改设备凭证
根据云端产生的设备凭证,修改头文件framework/protocol/linkkit/iotkit/sdk-encap/imports/iot_import_product.h
下的设备凭证信息。
#define PRODUCT_KEY "a1kxXZkfbQZ"
#define PRODUCT_SECRET "nLZxX3i0T9UMFw9K"
#define DEVICE_NAME "aos_air_box_01"
#define DEVICE_SECRET "bFwGW47hp4vmsBtAeWMGDq8JLJClDoRq"
8.4.2 准备更新固件文件
修改文件:framework/common/common.mk
:
先将app版本号改为app-2开头,目的:让服务器端版本高于终端运行版本。
编译 相关的例程,以 mk3060 为例:
aos make clean
aos make linkkitapp@mk3060
生成的linkkitapp bin 文件,路径:out/linkkitapp@mk3060/binary/linkkitapp@mk3060.bin
8.4.3 下载固件到mk3060
8.4.4 查看设备上线状态
在智能生活开放平台中可以看到当前设备的ProductKey
、DeviceName
、DeviceSecret
、固件版本号,也能看到当前设备是否上线:
8.4.5 固件上传
在智能生活开放平台中,点击固件升级栏目,新增固件,填入如下的信息,并上传固件bin文件:
8.4.6 固件升级
点击固件栏目的右边的验证固件按钮,选择固件版本号,开始更新固件,更新完成后,会有更新成功提示: