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://www.uj5u.com/qita/237140.html
標籤:其他
上一篇:RFID——充值消費系統
