1、前言
当我们基于AliOS Things做应用或项目开发时,会发现自己写的很多代码具备很强的可复用性,不单本项目可以使用,可能后续的类似项目都可以用到。那我们怎么把这部分功能抽象成OS的一个能力呢?显然,我们把这部分代码从project中挪到components中当作一个组件是非常合适的。
接下来我们将详细介绍如何快速开发一个AliOS Thing的标准组件。
本案例基于以下平台:
- OS版本:AliOS Things3.1
- 硬件平台:HaaS100
2、快速掌握AliOS Things的编译系统
AliOS Things 编译系统由两部分组件。
- 负责组件配置的Config.in
- 负责具体编译的aos.mk
2.1、Config.in 介绍
如果大家玩过linux内核编译,应该清楚Config.in是munuconfig图形化配置的配置文件。
对于一个组件,需要一个config选项,如下格式:
-
config AOS_COMP_XXX1
-
bool
"xxxx"
-
select AOS_COMP_XXX2
-
default n
-
help
-
what is this.
四要素:
- config后接组件名(配置系统中的名称);
- bool 代表选项类型,对于一个组件来说存在“选中“和“不选中“两种状态,故使用bool类型,bool后空一个写其在menuconfig中显示的名称;
- select 用于选中其必须依赖的组件,如CoAP这种应用层协议会依赖tcp/ip协议栈LwIP。
- default 默认状态,对于bool类型,只有“n”或“y”两种状态,建议默认n。
- help 功能描述。
另外需要注意的是,AliOS Things3.1支持创建工程,因此对Config.in做了一定的改造,加了“AOS_CREATE_PROJECT”控制开关,如果我们需要能主动创建工程,择需要如下方式改造一下,做前后兼容:
-
#注意这里,如果AOS_CREATE_PROJECT使能的话,无需设置组件名,并且默认使能
-
if AOS_CREATE_PROJECT
-
config AOS_COMP_XXX1
-
bool
-
select AOS_COMP_XXX2
-
default y
-
help
-
what is this.
-
endif
-
-
#注意这里,如果AOS_CREATE_PROJECT未使能的话,则按传统方式设置组件名,并且默认不使能
-
if !AOS_CREATE_PROJECT
-
config AOS_COMP_XXX1
-
bool
"xxx"
-
default n
-
select AOS_COMP_XXX2
-
help
-
what is this.
-
endif
详细介绍可参考 配置系统简介。
2.2、aos.mk介绍
aos.mk其实就是makefile,语法保持一致。
mk文件参数说明。
1、组件名:
NAME := mcoap
2、依赖组件,当有Config.in保证依赖关系时,此处可以不填写:
$(NAME)_COMPONENTS :=
3、编译类型:
$(NAME)_MBINS_TYPE := kernel
4、组件版本:
$(NAME)_VERSION := 1.0.0
5、组件描述:
$(NAME)_SUMMARY := Your component description.
6、指定编译源文件:
-
#包含src目录下全部.c
-
$(NAME)_SOURCES := src/*.c
-
#包含src目录下指定.c
-
$(NAME)_SOURCES := src/xxx.c src/xxxy.c
7、指定头文件路径:
-
#全局头文件,组件外也可以找到
-
GLOBAL_INCLUDES += public/
-
#内部头文件,仅组件使用
-
$(NAME)_INCLUDES += private/
8、定义全局宏:
-
#整个编译系统下可见的宏
-
GLOBAL_DEFINES += CONFIG_COAP
-
#仅组件下可见的宏
-
$(NAME)_DEFINES += CONFIG_COAP_WITH_TLS
9、CFLAGS设置:
-
#整个编译系统下可见的CFLAG
-
#GLOBAL_CFLAGS += -DON_DAILY
-
#仅组件下可见的CFLAG
-
$(NAME)_CFLAGS += -DON_DAILY
2.3、目录格式
组件默认都放在components目录下,然后根据具体功能又可细分目录,如我们示例移植一份开源的coap库,则可以放在components/network目录下。目录格式建议为:
-
your_comp_dir
-
--include
-
--src
3、一步步实现自有组件
鉴于代码开源相关风险,本用例使用一个mit lisense的开源coap库(示例代码来源:https://github.com/1248/microcoap)当做示例代码加入到AliOS Things中,使其成为其标准组件。
1、在components/network/下新建microcoap文件夹,并新建两个子文件夹include/src分别用于存放.h和.c文件;
2、在src/include文件夹下分别创建你的.c和.h文件;
3、按2章节方法在microcoap目录下新建Config.in:
-
#注意这里,如果AOS_CREATE_PROJECT使能的话,无需设置组件名,并且默认使能
-
if AOS_CREATE_PROJECT
-
config AOS_COMP_MICROCOAP
-
bool
-
select AOS_COMP_LWIP
-
default y
-
help
-
A tiny open
source CoAP server
for microcontrollers.
-
endif
-
-
#注意这里,如果AOS_CREATE_PROJECT未使能的话,则按传统方式设置组件名,并且默认不使能
-
if !AOS_CREATE_PROJECT
-
config AOS_COMP_MICROCOAP
-
bool
"microcoap"
-
default n
-
select AOS_COMP_LWIP
-
help
-
A tiny open
source CoAP server
for microcontrollers.
-
endif
同时在build/Config.in中增加此文件的索引:
-
menu
"Network Configuration"
-
...
-
source
"components/network/microcoap/Config.in"
-
...
4、按2章节方法在microcoap目录下新建aos.mk文件:
-
NAME := microcoap
-
-
$(NAME)_MBINS_TYPE := kernel
-
$(NAME)_VERSION := 1.0.0
-
$(NAME)_SUMMARY := A tiny open
source CoAP server
for microcontrollers.
-
-
$(NAME)_SOURCES := src/coap.c src/endpoints.c
-
-
GLOBAL_INCLUDES := include
5、完成代码开发(示例使用开源代码演示,略过)。
至此整个文件结构如图:
4、测试验证
4.1、编写测试demo
1、拷贝已经存在的helloworld_demo例程为模板创建自有demo:mcoap_demo。
2、修改aos.mk,如下:
-
NAME := mcoap_demo
-
-
$(NAME)_MBINS_TYPE := app
-
$(NAME)_VERSION := 1.0.0
-
$(NAME)_SUMMARY := microcoap demo
-
$(NAME)_SOURCES := appdemo.c maintask.c
-
-
$(NAME)_COMPONENTS += osal_aos cli
-
-
$(NAME)_INCLUDES += ./
3、修改Config.in,如下:
-
config AOS_APP_MCOAP_DEMO
-
bool
"mcoap Demo"
-
select AOS_COMP_OSAL_AOS
if !AOS_CREATE_PROJECT
-
select AOS_COMP_MICROCOAP
if !AOS_CREATE_PROJECT
-
select AOS_COMP_YLOOP
if !AOS_CREATE_PROJECT
-
select AOS_COMP_NETMGR
if !AOS_CREATE_PROJECT
-
help
-
microcoap demo
-
-
if AOS_APP_MCOAP_DEMO
-
# Configurations for app mcoap_demo
-
config SYSINFO_APP_VERSION
-
string
"Firmware Version"
-
default
"app-1.0.0-20201208.140831"
-
help
-
application main firmware version
-
endif
4、编辑application/example/Config.in,增加本demo信息:
-
source
"application/example/mcoap_demo/Config.in"
-
if AOS_APP_MCOAP_DEMO
-
config AOS_BUILD_APP
-
default
"mcoap_demo"
-
endif
5、编辑appdemo.c,增加自己的测试验证代码。如下:
-
/*
-
* Copyright (C) 2015-2020 Alibaba Group Holding Limited
-
*/
-
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <aos/errno.h>
-
#include <aos/kernel.h>
-
#include "aos/init.h"
-
#include "board.h"
-
#include <k_api.h>
-
#include "coap.h"
-
#include "network/network.h"
-
#include "aos/yloop.h"
-
#include "netmgr.h"
-
-
#define PORT 5683
-
-
int test_main(void *data)
-
{
-
int fd;
-
-
struct sockaddr_in servaddr, cliaddr;
-
-
uint8_t buf[
1024];
-
uint8_t scratch_raw[
1024];
-
coap_rw_buffer_t scratch_buf = {scratch_raw,
sizeof(scratch_raw)};
-
-
-
fd = socket(AF_INET,SOCK_DGRAM,
0);
-
-
-
bzero(&servaddr,
sizeof(servaddr));
-
-
servaddr.sin_family = AF_INET;
-
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
-
servaddr.sin_port = htons(PORT);
-
-
bind(fd,(struct sockaddr *)&servaddr,
sizeof(servaddr));
-
-
endpoint_setup();
-
-
while(
1)
-
{
-
int n, rc;
-
socklen_t len =
sizeof(cliaddr);
-
coap_packet_t pkt;
-
-
n = recvfrom(fd, buf,
sizeof(buf),
0, (struct sockaddr *)&cliaddr, &len);
-
#ifdef DEBUG
-
printf(
"Received: ");
-
coap_dump(buf, n,
true);
-
printf(
"\n");
-
#endif
-
-
if (
0 != (rc = coap_parse(&pkt, buf, n)))
-
printf(
"Bad packet rc=%d\n", rc);
-
else
-
{
-
size_t rsplen =
sizeof(buf);
-
coap_packet_t rsppkt;
-
#ifdef DEBUG
-
coap_dumpPacket(&pkt);
-
#endif
-
coap_handle_req(&scratch_buf, &pkt, &rsppkt);
-
-
if (
0 != (rc = coap_build(buf, &rsplen, &rsppkt)))
-
printf(
"coap_build failed rc=%d\n", rc);
-
else
-
{
-
#ifdef DEBUG
-
printf(
"Sending: ");
-
coap_dump(buf, rsplen,
true);
-
printf(
"\n");
-
#endif
-
#ifdef DEBUG
-
coap_dumpPacket(&rsppkt);
-
#endif
-
-
sendto(fd, buf, rsplen,
0, (struct sockaddr *)&cliaddr,
sizeof(cliaddr));
-
}
-
}
-
}
-
}
-
-
-
/*
-
* WiFi Got IP event
-
*/
-
static void wifi_service_event(input_event_t *event, void *priv_data)
-
{
-
static
int started =
0;
-
if (event->type != EV_WIFI) {
-
return;
-
}
-
-
if (event->code != CODE_WIFI_ON_GOT_IP) {
-
return;
-
}
-
-
netmgr_ap_config_t config;
-
memset(&config,
0,
sizeof(
netmgr_ap_config_t));
-
netmgr_get_ap_config(&config);
-
LOG(
"wifi_service_event config.ssid %s", config.ssid);
-
if (
strcmp(config.ssid,
"adha") ==
0 ||
strcmp(config.ssid,
"aha") ==
0) {
-
return;
-
}
-
-
/* Start CoAP task */
-
if (!started) {
-
aos_task_new(
"iotx_example", test_main,
NULL,
1024*
6);
-
started =
1;
-
}
-
}
-
-
int application_start(int argc, char *argv[])
-
{
-
int count =
0;
-
-
printf(
"nano entry here!\r\n");
-
-
/* Register WiFi event handle */
-
aos_register_event_filter(EV_WIFI, wifi_service_event,
NULL);
-
-
/* Initialize and start net manager */
-
netmgr_init();
-
netmgr_start(
false);
-
-
aos_loop_run();
-
-
}
4.2、编译&测试
1、编译我们新增加的demo程序,生产固件。
-
aos make mcoap_demo@haas100 -c config
-
aos make
2、将上述编译的固件按照haas100开发板烧入指导手册烧入板中,进行相关功能验证。
5、总结
将一个通用能力集合当作一个组件加入到AliOS Things中并不难。主要有以下几步:
- 编写组件功能代码;
- 编写Config.in;
- 编写aos.mk;
- 将组件Config.in加入配置体系;
- 至此主要流程已经完成。当然你还可以做如下工作用于验证组件是否能正常工作:
- 编写测试demo;
- 编译测试固件,上板验证。
你学会了没?最后欢迎大家将自己的组件贡献到AliOS Things生态中来,可通过(https://github.com/alibaba/AliOS-Things/pulls)等开源仓库提交你的代码,我们审核通过后就将成为AliOS Things的一部分!
同时,我们推出了HaaS 年度大玩家计划,除了成为AliOS Things的一部分,也欢迎同学们在CSDN上踊跃投稿,还有机会被邀请到 云栖大会 现场来进行颁奖哦
6、开发者技术支持
如需更多技术支持,可加入钉钉开发者群,或者关注微信公众号
更多技术与解决方案介绍,请访问阿里云AIoT首页https://iot.aliyun.com/
转载:https://blog.csdn.net/HaaSTech/article/details/111351624