rel_1.6.0 init

This commit is contained in:
guocheng.kgc 2020-06-18 20:06:52 +08:00 committed by shengdong.dsd
commit 27b3e2883d
19359 changed files with 8093121 additions and 0 deletions

View file

@ -0,0 +1,606 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdio.h>
#include <string.h>
#include <aos/aos.h>
#include <hal/wifi.h>
#include <hal/hal.h>
#include <netmgr.h>
#include "iot_import.h"
#include "ali_crypto.h"
autoconfig_plugin_t g_alink_smartconfig;
#ifdef MANUFACT_AP_FIND_ENABLE
manufact_ap_find_t g_manufact_ap_find_module;
#endif
/**
* @brief Wi-Fi网口的MAC地址, "XX:XX:XX:XX:XX:XX"
*
* @param mac_str : MAC地址字符串的缓冲区数组
* @return
*/
char *HAL_Wifi_Get_Mac(_OU_ char mac_str[HAL_MAC_LEN])
{
uint8_t mac[6] = { 0 };
hal_wifi_get_mac_addr(NULL, mac);
snprintf(mac_str, HAL_MAC_LEN, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0],
mac[1], mac[2], mac[3], mac[4], mac[5]);
return mac_str;
}
extern void wifi_get_ip(char ips[16]);
/**
* @brief Wi-Fi网口的IP地址, ,
* , ()
*
* @param ifname : Wi-Fi网络接口的名字
* @param ip_str : IP地址字符串的数组
* @return IP地址, ()
*/
uint32_t HAL_Wifi_Get_IP(_OU_ char ip_str[NETWORK_ADDR_LEN],
_IN_ const char *ifname)
{
//(void *)ifname;
wifi_get_ip(ip_str);
return 0;
}
/**
* @brief (`AWSS`),
*
* @return ,
* @note 180000,3min
*/
int HAL_Awss_Get_Timeout_Interval_Ms(void)
{
return 3 * 60 * 1000;
}
/**
* @brief (`channel`),
*
* @return ,
* @note 200400
*/
int HAL_Awss_Get_Channelscan_Interval_Ms(void)
{
return 250;
}
/**
* @brief 802.11, 802.11 Frame传递给这个函数
*
* @param[in] buf @n 80211 frame buffer, or pointer to struct ht40_ctrl
* @param[in] length @n 80211 frame buffer length
* @param[in] link_type @n AWSS_LINK_TYPE_NONE for most rtos HAL,
* and for linux HAL, do the following step to check
* which header type the driver supported.
@verbatim
a) iwconfig wlan0 mode monitor #open monitor mode
b) iwconfig wlan0 channel 6 #switch channel 6
c) tcpdump -i wlan0 -s0 -w file.pacp #capture 80211 frame
& save d) open file.pacp with wireshark or omnipeek check the link header
type and fcs included or not
@endverbatim
* @param[in] with_fcs @n 80211 frame buffer include fcs(4 byte) or not
* @param[in] rssi @n rssi of packet
*/
awss_recv_80211_frame_cb_t g_ieee80211_handler;
static void monitor_data_handler(uint8_t *buf, int len,
hal_wifi_link_info_t *info)
{
int with_fcs = 0;
int link_type = AWSS_LINK_TYPE_NONE;
(*g_ieee80211_handler)((char *)buf, len, link_type, with_fcs,
info->rssi);
}
/**
* @brief Wi-Fi网卡工作在监听(Monitor),
* 802.11
*
* @param[in] cb @n A function pointer, called back when wifi receive a
* frame.
*/
void HAL_Awss_Open_Monitor(_IN_ awss_recv_80211_frame_cb_t cb)
{
hal_wifi_module_t *module = hal_wifi_get_default_module();
if (module == NULL) {
return;
}
g_ieee80211_handler = cb;
hal_wifi_register_monitor_cb(module, monitor_data_handler);
hal_wifi_start_wifi_monitor(module);
HAL_Awss_Switch_Channel(6, 0, NULL);
}
/**
* @brief Wi-Fi网卡离开监听(Monitor),
* (Station)
*/
void HAL_Awss_Close_Monitor(void)
{
hal_wifi_module_t *module;
module = hal_wifi_get_default_module();
if (module == NULL) {
return;
}
hal_wifi_register_monitor_cb(module, NULL);
hal_wifi_stop_wifi_monitor(module);
}
/**
* @brief SoftAP模式
*
* @param[in] ssid @n ssid字符
* @param[in] passwd @n passwd字符
* @param[in] beacon_interval @n Beacon广播周期广
* @param[in] hide @n hide:0, ,
* @return
@verbatim
= 0: success
= -1: unsupported
= -2: failure with system error
= -3: failure with no memory
= -4: failure with invalid parameters
@endverbatim
* @Note:
* 1ssid和passwd都是以'\0'passwd字符串的
* 0Open模式
* 2beacon_interval表示热点的Beacon广播间隔
* 100ms
* 3hide表示创建的热点是否是隐藏热点hide=0
*
*/
int HAL_Awss_Open_Ap(const char *ssid, const char *passwd, int beacon_interval, int hide)
{
hal_wifi_module_t *module;
module = hal_wifi_get_default_module();
if (module == NULL || module->start_ap == NULL) {
return -1;
}
return module->start_ap(module, ssid, passwd, beacon_interval, hide);
}
/**
* @brief SoftAP模式切换到Station模式
*
* @return
@verbatim
= 0: success
= -1: unsupported
= -2: failure
@endverbatim
* @Note:
* 1
*
* 2Station模式Station+SoftAP模式和
* SoftAP模式Station模式
* 3Wi-Fi状态机需要切换到初始化状态
*
*/
int HAL_Awss_Close_Ap()
{
hal_wifi_module_t *module;
module = hal_wifi_get_default_module();
if (module == NULL || module->stop_ap == NULL) {
return -1;
}
return module->stop_ap(module);
}
/**
* @brief Wi-Fi网卡切换到指定的信道(channel)
*
* @param[in] primary_channel @n Primary channel.
* @param[in] secondary_channel @n Auxiliary channel if 40Mhz channel is
* supported, currently this param is always 0.
* @param[in] bssid @n A pointer to wifi BSSID on which awss lock the
* channel, most HAL may ignore it.
*/
void HAL_Awss_Switch_Channel(_IN_ char primary_channel,
_IN_OPT_ char secondary_channel,
_IN_OPT_ uint8_t bssid[ETH_ALEN])
{
hal_wifi_module_t *module;
module = hal_wifi_get_default_module();
if (module == NULL) {
return;
}
hal_wifi_set_channel(module, (int)primary_channel);
}
int HAL_Sys_Net_Is_Ready()
{
return netmgr_get_ip_state() == true ? 1 : 0;
}
/**
* @brief Wi-Fi网卡连接指定热点(Access Point)
*
* @param[in] connection_timeout_ms @n AP connection timeout in ms or
HAL_WAIT_INFINITE
* @param[in] ssid @n AP ssid
* @param[in] passwd @n AP passwd
* @param[in] auth @n optional(AWSS_AUTH_TYPE_INVALID), AP auth info
* @param[in] encry @n optional(AWSS_ENC_TYPE_INVALID), AP encry info
* @param[in] bssid @n optional(NULL or zero mac address), AP bssid info
* @param[in] channel @n optional, AP channel info
* @return
@verbatim
= 0: connect AP & DHCP success
= -1: connect AP or DHCP fail/timeout
@endverbatim
* @see None.
* @note
* If the STA connects the old AP, HAL should disconnect from the old
AP firstly.
*/
int HAL_Awss_Connect_Ap(_IN_ uint32_t connection_timeout_ms,
_IN_ char ssid[HAL_MAX_SSID_LEN],
_IN_ char passwd[HAL_MAX_PASSWD_LEN],
_IN_OPT_ enum AWSS_AUTH_TYPE auth,
_IN_OPT_ enum AWSS_ENC_TYPE encry,
_IN_OPT_ uint8_t bssid[ETH_ALEN],
_IN_OPT_ uint8_t channel)
{
int ms_cnt = 0;
netmgr_ap_config_t config = { 0 };
if (ssid != NULL) {
strncpy(config.ssid, ssid, sizeof(config.ssid) - 1);
}
if (passwd != NULL) {
strncpy(config.pwd, passwd, sizeof(config.pwd) - 1);
}
if (bssid != NULL) {
memcpy(config.bssid, bssid, ETH_ALEN);
}
netmgr_set_ap_config(&config);
#ifndef ESP8266_CONFIG
printf("------------------------suspend station\n");
hal_wifi_suspend_station(NULL);
#endif
// LOGI("aos_awss", "Will reconnect wifi: %s %s", ssid, passwd);
netmgr_reconnect_wifi();
while (ms_cnt < connection_timeout_ms) {
if (netmgr_get_ip_state() == false) {
LOGD("[waitConnAP]", "waiting for connecting AP");
aos_msleep(500);
ms_cnt += 500;
} else {
LOGI("[waitConnAP]", "AP connected");
return 0;
}
}
// if AP connect fail, should inform the module to suspend station
// to avoid module always reconnect and block Upper Layer running
hal_wifi_suspend_station(NULL);
return -1;
}
#define FRAME_ACTION_MASK (1 << FRAME_ACTION)
#define FRAME_BEACON_MASK (1 << FRAME_BEACON)
#define FRAME_PROBE_REQ_MASK (1 << FRAME_PROBE_REQ)
#define FRAME_PROBE_RESP_MASK (1 << FRAME_PROBE_RESPONSE)
#define FRAME_DATA_MASK (1 << FRAME_DATA)
/**
* @brief (channel)(1Mbps)802.11(raw
802.11 frame)
*
* @param[in] type @n see enum HAL_Awss_frame_type, currently only
FRAME_BEACON
* FRAME_PROBE_REQ is used
* @param[in] buffer @n 80211 raw frame, include complete mac header & FCS
field
* @param[in] len @n 80211 raw frame length
* @return
@verbatim
= 0, send success.
= -1, send failure.
= -2, unsupported.
@endverbatim
* @see None.
* @note awss use this API send raw frame in wifi monitor mode & station
mode
*/
int HAL_Wifi_Send_80211_Raw_Frame(_IN_ enum HAL_Awss_Frame_Type type,
_IN_ uint8_t *buffer, _IN_ int len)
{
return hal_wlan_send_80211_raw_frame(NULL, buffer, len);
}
/**
* @brief
*
* @param[in] buffer @n 80211 raw frame or ie(information element) buffer
* @param[in] len @n buffer length
* @param[in] rssi_dbm @n rssi in dbm, set it to 0 if not supported
* @param[in] buffer_type @n 0 when buffer is a 80211 frame,
* 1 when buffer only contain IE info
* @return None.
* @see None.
* @note None.
*/
typedef void (*awss_wifi_mgmt_frame_cb_t)(_IN_ uint8_t *buffer,
_IN_ int len,
_IN_ signed char rssi_dbm,
_IN_ int buffer_type);
static awss_wifi_mgmt_frame_cb_t monitor_cb = NULL;
static void mgnt_rx_cb(uint8_t *data, int len, hal_wifi_link_info_t *info)
{
if (monitor_cb) {
monitor_cb(data, len, info->rssi, 0);
}
}
/**
* @brief (Station)使
*
* @param[in] filter_mask @n see mask macro in enum HAL_Awss_frame_type,
* currently only FRAME_PROBE_REQ_MASK &
FRAME_BEACON_MASK is used
* @param[in] vendor_oui @n oui can be used for precise frame match,
optional
* @param[in] callback @n see awss_wifi_mgmt_frame_cb_t, passing 80211
* frame or ie to callback. when callback is NULL
* disable sniffer feature, otherwise enable it.
* @return
@verbatim
= 0, success
= -1, fail
= -2, unsupported.
@endverbatim
* @see None.
* @note awss use this API to filter specific mgnt frame in wifi station
mode
*/
int HAL_Wifi_Enable_Mgmt_Frame_Filter(
_IN_ uint32_t filter_mask, _IN_OPT_ uint8_t vendor_oui[3],
_IN_ awss_wifi_mgmt_frame_cb_t callback)
{
monitor_cb = callback;
if (callback != NULL) {
hal_wlan_register_mgnt_monitor_cb(NULL, mgnt_rx_cb);
} else {
hal_wlan_register_mgnt_monitor_cb(NULL, NULL);
}
return 0;
}
/**
* @brief handle one piece of AP information from wifi scan result
*
* @param[in] ssid @n name of AP
* @param[in] bssid @n mac address of AP
* @param[in] channel @n AP channel
* @param[in] rssi @n rssi range[-127, -1].
* the higher the RSSI number, the stronger the signal.
* @param[in] is_last_ap @n this AP information is the last one if
* is_last_ap > 0. this AP information is not the last one if is_last_ap ==
* 0.
* @return 0 for wifi scan is done, otherwise return -1
* @see None.
* @note None.
*/
typedef int (*awss_wifi_scan_result_cb_t)(const char ssid[HAL_MAX_SSID_LEN],
const uint8_t bssid[ETH_ALEN],
enum AWSS_AUTH_TYPE auth,
enum AWSS_ENC_TYPE encry,
uint8_t channel, signed char rssi,
int is_last_ap);
/**
* @brief Wi-Fi的空中扫描(Scan)
*
* @param[in] cb @n pass ssid info(scan result) to this callback one by one
* @return 0 for wifi scan is done, otherwise return -1
* @see None.
* @note
* This API should NOT exit before the invoking for cb is finished.
* This rule is something like the following :
* HAL_Wifi_Scan() is invoked...
* ...
* for (ap = first_ap; ap <= last_ap; ap = next_ap){
* cb(ap)
* }
* ...
* HAL_Wifi_Scan() exit...
*/
int HAL_Wifi_Scan(awss_wifi_scan_result_cb_t cb)
{
netmgr_register_wifi_scan_result_callback(
(netmgr_wifi_scan_result_cb_t)cb);
hal_wifi_start_scan_adv(NULL);
while (netmgr_get_scan_cb_finished() != true) { // block
aos_msleep(50);
}
return 0;
}
/**
* @brief (Access Point)
*
* @param[out] ssid: array to store ap ssid. It will be null if ssid is not
required.
* @param[out] passwd: array to store ap password. It will be null if ap
password is not required.
* @param[out] bssid: array to store ap bssid. It will be null if bssid is
not required.
* @return
@verbatim
= 0: succeeded
= -1: failed
@endverbatim
* @see None.
* @note None.
*/
int HAL_Wifi_Get_Ap_Info(_OU_ char ssid[HAL_MAX_SSID_LEN],
_OU_ char passwd[HAL_MAX_PASSWD_LEN],
_OU_ uint8_t bssid[ETH_ALEN])
{
netmgr_ap_config_t config = { 0 };
netmgr_get_ap_config(&config);
if (ssid) {
strncpy(ssid, config.ssid, HAL_MAX_SSID_LEN - 1);
}
if (passwd) {
#ifdef DISABLE_SECURE_STORAGE
strncpy(passwd, config.pwd, HAL_MAX_PASSWD_LEN - 1);
#else
extern int iotx_ss_decrypt(const char* in_data, int in_len, char* out_data, int out_len);
iotx_ss_decrypt(config.pwd, MAX_PWD_SIZE, passwd, MAX_PWD_SIZE);
#endif
}
if (bssid) {
memcpy(bssid, config.bssid, ETH_ALEN);
}
return 0;
}
int HAL_Awss_Get_Encrypt_Type()
{
return 3;
}
int HAL_Awss_Get_Conn_Encrypt_Type()
{
char invalid_ds[DEVICE_SECRET_LEN + 1] = {0};
char ds[DEVICE_SECRET_LEN + 1] = {0};
HAL_GetDeviceSecret(ds);
if (memcmp(invalid_ds, ds, sizeof(ds)) == 0)
return 3;
memset(invalid_ds, 0xff, sizeof(invalid_ds));
if (memcmp(invalid_ds, ds, sizeof(ds)) == 0)
return 3;
return 4;
}
/**
* @brief Station模式与AP连接状态的信息
*
* @param[out] p_rssi: rssi value of current link
* @param[out] p_channel: channel of current link
*
* @return
@verbatim
= 0: succeeded
= -1: failed
@endverbatim
* @see None.
* @note None.
* @note awss use this API to get rssi and channel of current link
*/
int HAL_Wifi_Get_Link_Stat(_OU_ int *p_rssi,
_OU_ int *p_channel)
{
int ret;
hal_wifi_link_stat_t link_stat;
if (netmgr_get_ip_state() == true)
{
ret = hal_wifi_get_link_stat(NULL, &link_stat);
if ((ret == 0) && link_stat.is_connected) {
*p_rssi = link_stat.wifi_strength;
*p_channel = link_stat.channel;
} else {
return -1;
}
} else {
return -1;
}
return 0;
}
#ifdef CONFIG_YWSS
static int smart_config_start(void)
{
extern int awss_start();
awss_start();
return 0;
}
static void smart_config_stop(void)
{
netmgr_ap_config_t config;
memset(&config, 0, sizeof(netmgr_ap_config_t));
netmgr_get_ap_config(&config);
if (strcmp(config.ssid, "adha") == 0 ||
strcmp(config.ssid, "aha") == 0) {
return;
}
printf("%s %d\r\n", __func__, __LINE__);
// awss_stop();
}
static void smart_config_result_cb(int result, uint32_t ip)
{
aos_post_event(EV_WIFI, CODE_WIFI_ON_GOT_IP, 0u);
}
autoconfig_plugin_t g_alink_smartconfig = {
.description = "alink_smartconfig",
.autoconfig_start = smart_config_start,
.autoconfig_stop = smart_config_stop,
.config_result_cb = smart_config_result_cb
};
#endif
#ifdef MANUFACT_AP_FIND_ENABLE
static int manuap_info_set(char *p_ssid, char *p_pwd) {
extern int manufact_ap_info_set(char *p_ssid_manu, char *p_pwd_manu);
return manufact_ap_info_set(p_ssid, p_pwd);
}
static int manuap_find(char *p_ssid, char *p_pwd, uint8_t *p_bssid) {
extern int manufact_ap_find(char *p_ssid_manu, char *p_pwd_manu, uint8_t *p_bssid_manu);
return manufact_ap_find(p_ssid, p_pwd, p_bssid);
}
manufact_ap_find_t g_manufact_ap_find_module = {
.pf_manufact_ap_info_set = manuap_info_set,
.pf_manufact_ap_find = manuap_find
};
#endif
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,218 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include <string.h>
#include <aos/aos.h>
#include "iot_import.h"
#include "ali_crypto.h"
#define AES_BLOCK_SIZE 16
#define KEY_LEN 16 // aes 128 cbc
#define p_aes128_t p_HAL_Aes128_t
#define PLATFORM_AES_ENCRYPTION HAL_AES_ENCRYPTION
#define PLATFORM_AES_DECRYPTION HAL_AES_DECRYPTION
/**
* @brief AES加密的结构体
*
* @param[in] key:
* @param[in] iv:
* @param[in] dir: AES_ENCRYPTION or AES_DECRYPTION
* @return AES128_t
@verbatim None
@endverbatim
* @see None.
* @note None.
*/
p_HAL_Aes128_t HAL_Aes128_Init(_IN_ const uint8_t *key, _IN_ const uint8_t *iv,
_IN_ AES_DIR_t dir)
{
ali_crypto_result result;
void *aes_ctx;
size_t aes_ctx_size, alloc_siz;
uint8_t *p;
bool is_en = true; // encrypto by default
if (dir == PLATFORM_AES_DECRYPTION) {
is_en = false;
}
result = ali_aes_get_ctx_size(AES_CBC, &aes_ctx_size);
if (result != ALI_CRYPTO_SUCCESS) {
LOGE("aos_awss", "get ctx size fail(%08x)", result);
return NULL;
}
alloc_siz = aes_ctx_size + KEY_LEN * 2 + sizeof(bool);
aes_ctx = HAL_Malloc(alloc_siz);
if (aes_ctx == NULL) {
LOGE("aos_awss", "kmalloc(%d) fail", (int)aes_ctx_size);
return NULL;
}
memset(aes_ctx, 0, alloc_siz);
p = (uint8_t *)aes_ctx + aes_ctx_size;
memcpy(p, key, KEY_LEN);
p += KEY_LEN;
memcpy(p, iv, KEY_LEN);
p += KEY_LEN;
*((bool *)p) = is_en;
return aes_ctx;
}
/**
* @brief AES加密的结构体
*
* @param[in] aes:
* @return
@verbatim
= 0: succeeded
= -1: failed
@endverbatim
* @see None.
* @note None.
*/
int HAL_Aes128_Destroy(_IN_ p_HAL_Aes128_t aes)
{
if (aes) {
HAL_Free(aes);
}
return 0;
}
static int platform_aes128_encrypt_decrypt(p_HAL_Aes128_t aes_ctx,
const void *src, size_t siz,
void *dst, aes_type_t t)
{
ali_crypto_result result;
size_t dlen, in_len = siz, ctx_siz;
uint8_t *p, *key, *iv;
bool is_en;
if (aes_ctx == NULL) {
LOGE("aos_awss", "platform_aes128_encrypt_decrypt aes_ctx is NULL");
return -1;
}
result = ali_aes_get_ctx_size(AES_CBC, &ctx_siz);
if (result != ALI_CRYPTO_SUCCESS) {
LOGE("aos_awss", "get ctx size fail(%08x)", result);
return 0;
}
p = (uint8_t *)aes_ctx + ctx_siz;
key = p;
p += KEY_LEN;
iv = p;
p += KEY_LEN;
is_en = *((uint8_t *)p);
in_len <<= t == AES_CBC ? 4 : 0;
dlen = in_len;
result = ali_aes_init(t, is_en, key, NULL, KEY_LEN, iv, aes_ctx);
if (result != ALI_CRYPTO_SUCCESS) {
LOGE("aos_awss", "ali_aes_init fail(%08x)", result);
return 0;
}
result = ali_aes_finish(src, in_len, dst, &dlen, SYM_NOPAD, aes_ctx);
if (result != ALI_CRYPTO_SUCCESS) {
LOGE("aos_awss", "aes_finish fail(%08x)", result);
return -1;
}
memcpy(iv, dst + dlen - 16, 16);
return 0;
}
/**
* @brief `AES-CBC-128`,
`HAL_Aes128_Init()`
*
* @param[in] aes: AES handler
* @param[in] src: plain data
* @param[in] blockNum: plain data number of 16 bytes size
* @param[out] dst: cipher data
* @return
@verbatim
= 0: succeeded
= -1: failed
@endverbatim
* @see None.
* @note None.
*/
int HAL_Aes128_Cbc_Encrypt(_IN_ p_HAL_Aes128_t aes, _IN_ const void *src,
_IN_ size_t blockNum, _OU_ void *dst)
{
return platform_aes128_encrypt_decrypt(aes, src, blockNum, dst, AES_CBC);
}
/**
* @brief `AES-CBC-128`,
`HAL_Aes128_Init()`
*
* @param[in] aes: AES handler
* @param[in] src: cipher data
* @param[in] blockNum: plain data number of 16 bytes size
* @param[out] dst: plain data
* @return
@verbatim
= 0: succeeded
= -1: failed
@endverbatim
* @see None.
* @note None.
*/
int HAL_Aes128_Cbc_Decrypt(_IN_ p_HAL_Aes128_t aes, _IN_ const void *src,
_IN_ size_t blockNum, _OU_ void *dst)
{
return platform_aes128_encrypt_decrypt(aes, src, blockNum, dst, AES_CBC);
}
/**
* @brief `AES-CFB-128`,
`HAL_Aes128_Init()`
*
* @param[in] aes: AES handler
* @param[in] src: plain data
* @param[in] length: plain data number of 16 bytes size
* @param[out] dst: cipher data
* @return
@verbatim
= 0: succeeded
= -1: failed
@endverbatim
* @see None.
* @note None.
*/
int HAL_Aes128_Cfb_Encrypt(_IN_ p_HAL_Aes128_t aes, _IN_ const void *src,
_IN_ size_t length, _OU_ void *dst)
{
return platform_aes128_encrypt_decrypt(aes, src, length, dst, AES_CFB128);
}
/**
* @brief `AES-CFB-128`,
`HAL_Aes128_Init()`
*
* @param[in] aes: AES handler
* @param[in] src: cipher data
* @param[in] length: plain data number of 16 bytes size
* @param[out] dst: plain data
* @return
@verbatim
= 0: succeeded
= -1: failed
@endverbatim
* @see None.
* @note None.
*/
int HAL_Aes128_Cfb_Decrypt(_IN_ p_HAL_Aes128_t aes, _IN_ const void *src,
_IN_ size_t length, _OU_ void *dst)
{
return platform_aes128_encrypt_decrypt(aes, src, length, dst, AES_CFB128);
}
//#endif

View file

@ -0,0 +1,560 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <sys/time.h>
#include "aos/aos.h"
#include "iot_import.h"
#ifdef COAP_DTLS_SUPPORT
#include "ali_crypto.h"
#include "mbedtls/config.h"
#include "mbedtls/net_sockets.h"
#include "mbedtls/debug.h"
#include "mbedtls/ssl.h"
#include "mbedtls/error.h"
#include "mbedtls/timing.h"
#ifdef MBEDTLS_ENTROPY_C
#include "mbedtls/entropy.h"
#endif
#include "mbedtls/ssl_cookie.h"
#define LOG_TAG "HAL_DTLS"
#define platform_trace(format, ...) // LOGW(LOG_TAG, format,##__VA_ARGS__)
#define platform_info(format, ...) // LOGI(LOG_TAG, format,##__VA_ARGS__)
#define platform_err(format, ...) LOGE(LOG_TAG, format, ##__VA_ARGS__)
static dtls_hooks_t g_dtls_hooks = {HAL_Malloc, HAL_Free};
#if defined(MBEDTLS_DEBUG_C)
extern int csp_printf(const char *fmt, ...);
static void ssl_debug(void *ctx, int level, const char *file, int line,
const char *str)
{
(void)ctx;
(void)level;
csp_printf("%s, line: %d: %s", file ? file : NULL_STR, line,
str ? str : NULL_STR);
return;
}
#endif
typedef void DTLSContext;
mbedtls_ssl_session *saved_session = NULL;
typedef struct
{
mbedtls_ssl_context context;
mbedtls_ssl_config conf;
#ifdef MBEDTLS_ENTROPY_C
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_entropy_context entropy;
#endif
#ifdef MBEDTLS_X509_CRT_PARSE_C
mbedtls_x509_crt cacert;
#endif
mbedtls_net_context fd;
mbedtls_timing_delay_context timer;
mbedtls_ssl_cookie_ctx cookie_ctx;
} dtls_session_t;
#define MBEDTLS_MEM_TEST 1
#ifdef MBEDTLS_MEM_TEST
#define MBEDTLS_MEM_INFO_MAGIC 0x12345678
static unsigned int mbedtls_mem_used = 0;
static unsigned int mbedtls_max_mem_used = 0;
typedef struct
{
int magic;
int size;
} mbedtls_mem_info_t;
static int ssl_random(void *prng, unsigned char *output, size_t output_len)
{
struct timeval tv;
(void)prng;
gettimeofday(&tv, NULL);
ali_seed((uint8_t *)&tv.tv_usec, sizeof(suseconds_t));
ali_rand_gen(output, output_len);
return 0;
}
void *_DTLSCalloc_wrapper(size_t n, size_t size)
{
void * buf = NULL;
mbedtls_mem_info_t *mem_info = NULL;
if (n == 0 || size == 0) {
return NULL;
}
buf = malloc(n * size + sizeof(mbedtls_mem_info_t));
if (NULL == buf) {
return NULL;
} else {
memset(buf, 0, n * size + sizeof(mbedtls_mem_info_t));
}
mem_info = (mbedtls_mem_info_t *)buf;
mem_info->magic = MBEDTLS_MEM_INFO_MAGIC;
mem_info->size = n * size;
buf += sizeof(mbedtls_mem_info_t);
mbedtls_mem_used += mem_info->size;
if (mbedtls_mem_used > mbedtls_max_mem_used) {
mbedtls_max_mem_used = mbedtls_mem_used;
}
/* platform_trace("INFO -- mbedtls malloc: %p %d total used: %d max used:
%d\r\n", buf, (int)size, mbedtls_mem_used, mbedtls_max_mem_used); */
return buf;
}
void _DTLSFree_wrapper(void *ptr)
{
mbedtls_mem_info_t *mem_info = NULL;
if (NULL == ptr) {
return;
}
mem_info = ptr - sizeof(mbedtls_mem_info_t);
if (mem_info->magic != MBEDTLS_MEM_INFO_MAGIC) {
platform_trace("Warning - invalid mem info magic: 0x%x\r\n",
mem_info->magic);
return;
}
mbedtls_mem_used -= mem_info->size;
/* platform_trace("INFO mbedtls free: %p %d total used: %d max used:
%d\r\n", ptr, mem_info->size, mbedtls_mem_used, mbedtls_max_mem_used);*/
free(mem_info);
}
#else
static void *_DTLSCalloc_wrapper(size_t n, size_t s)
{
void * ptr = NULL;
size_t len = n * s;
ptr = aos_malloc(len);
if (NULL != ptr) {
memset(ptr, 0x00, len);
}
return ptr;
}
static void _DTLSFree_wrapper(void *ptr)
{
if (NULL != ptr) {
aos_free(ptr);
ptr = NULL;
}
}
#endif
#ifdef DTLS_SESSION_SAVE
static int _DTLSSession_save(const mbedtls_ssl_session *session,
unsigned char *buf, size_t buf_len, size_t *olen)
{
unsigned char *p = buf;
size_t left = buf_len;
#if defined(MBEDTLS_X509_CRT_PARSE_C)
size_t cert_len;
#endif /* MBEDTLS_X509_CRT_PARSE_C */
if (left < sizeof(mbedtls_ssl_session)) {
return (MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL);
}
memcpy(p, session, sizeof(mbedtls_ssl_session));
p += sizeof(mbedtls_ssl_session);
left -= sizeof(mbedtls_ssl_session);
#if defined(MBEDTLS_X509_CRT_PARSE_C)
if (session->peer_cert == NULL) {
cert_len = 0;
} else {
cert_len = session->peer_cert->raw.len;
}
if (left < 3 + cert_len) {
return (MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL);
}
*p++ = (unsigned char)(cert_len >> 16 & 0xFF);
*p++ = (unsigned char)(cert_len >> 8 & 0xFF);
*p++ = (unsigned char)(cert_len & 0xFF);
if (session->peer_cert != NULL) {
memcpy(p, session->peer_cert->raw.p, cert_len);
}
p += cert_len;
#endif /* MBEDTLS_X509_CRT_PARSE_C */
*olen = p - buf;
return (0);
}
#endif
static unsigned int _DTLSVerifyOptions_set(dtls_session_t *p_dtls_session,
unsigned char * p_ca_cert_pem)
{
int result;
unsigned int err_code = DTLS_SUCCESS;
#ifdef MBEDTLS_X509_CRT_PARSE_C
if (p_ca_cert_pem != NULL) {
#ifndef TEST_COAP_DAILY
mbedtls_ssl_conf_authmode(&p_dtls_session->conf,
MBEDTLS_SSL_VERIFY_REQUIRED);
#else
mbedtls_ssl_conf_authmode(&p_dtls_session->conf,
MBEDTLS_SSL_VERIFY_OPTIONAL);
#endif
platform_trace("Call mbedtls_ssl_conf_authmode\r\n");
platform_trace("x509 ca cert pem len %d\r\n%s\r\n",
(int)strlen((char *)p_ca_cert_pem) + 1, p_ca_cert_pem);
result =
mbedtls_x509_crt_parse(&p_dtls_session->cacert, p_ca_cert_pem,
strlen((const char *)p_ca_cert_pem) + 1);
platform_trace("mbedtls_x509_crt_parse result 0x%04x\r\n", result);
if (0 != result) {
err_code = DTLS_INVALID_CA_CERTIFICATE;
} else {
mbedtls_ssl_conf_ca_chain(&p_dtls_session->conf,
&p_dtls_session->cacert, NULL);
}
} else
#endif
{
mbedtls_ssl_conf_authmode(&p_dtls_session->conf,
MBEDTLS_SSL_VERIFY_NONE);
}
return err_code;
}
static unsigned int _DTLSContext_setup(dtls_session_t * p_dtls_session,
coap_dtls_options_t *p_options)
{
int result = 0;
mbedtls_ssl_init(&p_dtls_session->context);
result = mbedtls_ssl_setup(&p_dtls_session->context, &p_dtls_session->conf);
platform_trace("mbedtls_ssl_setup result 0x%04x\r\n", result);
if (result == 0) {
if (p_dtls_session->conf.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
mbedtls_ssl_set_timer_cb(
&p_dtls_session->context, (void *)&p_dtls_session->timer,
mbedtls_timing_set_delay, mbedtls_timing_get_delay);
}
#ifdef MBEDTLS_X509_CRT_PARSE_C
platform_trace("mbedtls_ssl_set_hostname %s\r\n", p_options->p_host);
mbedtls_ssl_set_hostname(&p_dtls_session->context, p_options->p_host);
#endif
mbedtls_ssl_set_bio(&p_dtls_session->context,
(void *)&p_dtls_session->fd, mbedtls_net_send,
mbedtls_net_recv, mbedtls_net_recv_timeout);
platform_trace("mbedtls_ssl_set_bio result 0x%04x\r\n", result);
if (NULL != saved_session) {
mbedtls_ssl_set_session(&p_dtls_session->context, saved_session);
}
do {
result = mbedtls_ssl_handshake(&p_dtls_session->context);
} while (result == MBEDTLS_ERR_SSL_WANT_READ ||
result == MBEDTLS_ERR_SSL_WANT_WRITE);
platform_trace("mbedtls_ssl_handshake result 0x%04x\r\n", result);
#ifdef MBEDTLS_MEM_TEST
platform_trace(
"mbedtls handshake memory total used: %d max used: %d\r\n",
mbedtls_mem_used, mbedtls_max_mem_used);
#endif
if (0 == result) {
if (NULL == saved_session) {
saved_session = aos_malloc(sizeof(mbedtls_ssl_session));
}
if (NULL != saved_session) {
memset(saved_session, 0x00, sizeof(mbedtls_ssl_session));
result = mbedtls_ssl_get_session(&p_dtls_session->context,
saved_session);
platform_trace(
"mbedtls_ssl_get_session_session return 0x%04x\r\n", result);
}
}
}
return (result ? DTLS_HANDSHAKE_FAILED : DTLS_SUCCESS);
}
dtls_session_t *_DTLSSession_init()
{
dtls_session_t *p_dtls_session = NULL;
p_dtls_session = aos_malloc(sizeof(dtls_session_t));
#if defined(MBEDTLS_DEBUG_C)
mbedtls_debug_set_threshold(0);
#endif
#ifdef MBEDTLS_MEM_TEST
mbedtls_mem_used = 0;
mbedtls_max_mem_used = 0;
#endif
// mbedtls_platform_set_calloc_free(_DTLSCalloc_wrapper, _DTLSFree_wrapper);
if (NULL != p_dtls_session) {
memset(p_dtls_session, 0x00, sizeof(dtls_session_t));
// mbedtls_net_init(&p_dtls_session->fd);
mbedtls_ssl_init(&p_dtls_session->context);
mbedtls_ssl_config_init(&p_dtls_session->conf);
mbedtls_net_init(&p_dtls_session->fd);
mbedtls_ssl_cookie_init(&p_dtls_session->cookie_ctx);
#ifdef MBEDTLS_X509_CRT_PARSE_C
mbedtls_x509_crt_init(&p_dtls_session->cacert);
#endif
#ifdef MBEDTLS_ENTROPY_C
mbedtls_ctr_drbg_init(&p_dtls_session->ctr_drbg);
mbedtls_entropy_init(&p_dtls_session->entropy);
#endif
platform_info("HAL_DTLSSession_init success\r\n");
}
return p_dtls_session;
}
unsigned int _DTLSSession_deinit(dtls_session_t *p_dtls_session)
{
int ret;
if (p_dtls_session != NULL) {
do {
ret = mbedtls_ssl_close_notify(&p_dtls_session->context);
} while (ret == MBEDTLS_ERR_SSL_WANT_WRITE);
mbedtls_net_free(&p_dtls_session->fd);
#ifdef MBEDTLS_X509_CRT_PARSE_C
mbedtls_x509_crt_free(&p_dtls_session->cacert);
#endif
mbedtls_ssl_cookie_free(&p_dtls_session->cookie_ctx);
mbedtls_ssl_config_free(&p_dtls_session->conf);
mbedtls_ssl_free(&p_dtls_session->context);
#ifdef MBEDTLS_ENTROPY_C
mbedtls_ctr_drbg_free(&p_dtls_session->ctr_drbg);
mbedtls_entropy_free(&p_dtls_session->entropy);
#endif
aos_free(p_dtls_session);
}
return DTLS_SUCCESS;
}
DLL_HAL_API int HAL_DTLSHooks_set(dtls_hooks_t *hooks)
{
if (hooks == NULL || hooks->malloc == NULL || hooks->free == NULL) {
return DTLS_INVALID_PARAM;
}
g_dtls_hooks.malloc = hooks->malloc;
g_dtls_hooks.free = hooks->free;
return DTLS_SUCCESS;
}
DTLSContext *HAL_DTLSSession_create(coap_dtls_options_t *p_options)
{
char port[6] = { 0 };
int result = 0;
dtls_session_t *p_dtls_session = NULL;
p_dtls_session = _DTLSSession_init();
if (NULL != p_dtls_session) {
mbedtls_ssl_config_init(&p_dtls_session->conf);
#ifdef MBEDTLS_ENTROPY_C
result =
mbedtls_ctr_drbg_seed(&p_dtls_session->ctr_drbg, mbedtls_entropy_func,
&p_dtls_session->entropy,
(const unsigned char *)"IoTx", strlen("IoTx"));
if (0 != result) {
platform_err("mbedtls_ctr_drbg_seed result 0x%04x\r\n", result);
goto error;
}
#endif
result = mbedtls_ssl_config_defaults(
&p_dtls_session->conf, MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_PRESET_DEFAULT);
if (0 != result) {
platform_err("mbedtls_ssl_config_defaults result 0x%04x\r\n",
result);
goto error;
}
mbedtls_ssl_conf_rng(&p_dtls_session->conf, ssl_random, NULL);
#if defined(MBEDTLS_DEBUG_C)
mbedtls_ssl_conf_dbg(&p_dtls_session->conf, ssl_debug, NULL);
#endif
// mbedtls_ssl_conf_dbg(&p_dtls_session->conf, _DTLSLog_wrapper, NULL);
#ifdef MBEDTLS_ENTROPY_C
result = mbedtls_ssl_cookie_setup(&p_dtls_session->cookie_ctx,
mbedtls_ctr_drbg_random,
&p_dtls_session->ctr_drbg);
if (0 != result) {
platform_err("mbedtls_ssl_cookie_setup result 0x%04x\r\n", result);
goto error;
}
#endif
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
mbedtls_ssl_conf_dtls_cookies(
&p_dtls_session->conf, mbedtls_ssl_cookie_write,
mbedtls_ssl_cookie_check, &p_dtls_session->cookie_ctx);
#endif
result =
_DTLSVerifyOptions_set(p_dtls_session, p_options->p_ca_cert_pem);
if (DTLS_SUCCESS != result) {
platform_err("DTLSVerifyOptions_set result 0x%04x\r\n", result);
goto error;
}
sprintf(port, "%u", p_options->port);
result = mbedtls_net_connect(&p_dtls_session->fd, p_options->p_host,
port, MBEDTLS_NET_PROTO_UDP);
if (0 != result) {
platform_err("mbedtls_net_connect result 0x%04x\r\n", result);
goto error;
}
#ifdef MBEDTLS_SSL_PROTO_DTLS
if (p_dtls_session->conf.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
mbedtls_ssl_conf_min_version(&p_dtls_session->conf,
MBEDTLS_SSL_MAJOR_VERSION_3,
MBEDTLS_SSL_MINOR_VERSION_3);
mbedtls_ssl_conf_max_version(&p_dtls_session->conf,
MBEDTLS_SSL_MAJOR_VERSION_3,
MBEDTLS_SSL_MINOR_VERSION_3);
mbedtls_ssl_conf_handshake_timeout(
&p_dtls_session->conf, (MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN * 2),
(MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN * 2 * 4));
}
#endif
result = _DTLSContext_setup(p_dtls_session, p_options);
if (DTLS_SUCCESS != result) {
platform_err("DTLSVerifyOptions_set result 0x%04x\r\n", result);
goto error;
}
return (DTLSContext *)p_dtls_session;
}
error:
if (NULL != p_dtls_session) {
_DTLSSession_deinit(p_dtls_session);
}
return NULL;
}
unsigned int HAL_DTLSSession_write(DTLSContext * context,
const unsigned char *p_data,
unsigned int * p_datalen)
{
int len = 0;
unsigned int err_code = DTLS_SUCCESS;
dtls_session_t *p_dtls_session = (dtls_session_t *)context;
if (NULL != p_dtls_session && NULL != p_data && p_datalen != NULL) {
len = (*p_datalen);
len = mbedtls_ssl_write(&p_dtls_session->context, p_data, len);
if (len < 0) {
if (len == MBEDTLS_ERR_SSL_CONN_EOF) {
if (p_dtls_session->context.state <
MBEDTLS_SSL_HANDSHAKE_OVER) {
err_code = DTLS_HANDSHAKE_IN_PROGRESS;
}
}
} else {
(*p_datalen) = len;
err_code = DTLS_SUCCESS;
}
}
return err_code;
}
unsigned int HAL_DTLSSession_read(DTLSContext *context, unsigned char *p_data,
unsigned int *p_datalen, unsigned int timeout)
{
int len = 0;
unsigned int err_code = DTLS_READ_DATA_FAILED;
dtls_session_t *p_dtls_session = (dtls_session_t *)context;
if (NULL != p_dtls_session && NULL != p_data && p_datalen != NULL) {
mbedtls_ssl_conf_read_timeout(&(p_dtls_session->conf), timeout);
len = mbedtls_ssl_read(&p_dtls_session->context, p_data, *p_datalen);
if (0 < len) {
*p_datalen = len;
err_code = DTLS_SUCCESS;
platform_trace("mbedtls_ssl_read len %d bytes\r\n", len);
} else {
*p_datalen = 0;
if (MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE == len) {
err_code = DTLS_FATAL_ALERT_MESSAGE;
platform_err("Recv peer fatal alert message\r\n");
} else if (MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY == len) {
err_code = DTLS_PEER_CLOSE_NOTIFY;
platform_err("The DTLS session was closed by peer\r\n");
} else if (MBEDTLS_ERR_SSL_TIMEOUT == len) {
err_code = DTLS_SUCCESS;
platform_err("DTLS recv timeout\r\n");
}
// else {
// platform_trace("mbedtls_ssl_read error result (-0x%04x)\r\n",
// len);
// }
}
}
return err_code;
}
unsigned int HAL_DTLSSession_free(DTLSContext *context)
{
dtls_session_t *p_dtls_session = NULL;
if (NULL != context) {
p_dtls_session = (dtls_session_t *)context;
return _DTLSSession_deinit(p_dtls_session);
}
return DTLS_INVALID_PARAM;
}
#endif

View file

@ -0,0 +1,35 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include <stdio.h>
void *HAL_Fopen(const char *path, const char *mode)
{
return NULL;
}
size_t HAL_Fread(void * buff,size_t size, size_t count, void *stream)
{
return 0;
}
size_t HAL_Fwrite(const void * ptr, size_t size, size_t count, void * stream)
{
return 0;
}
int HAL_Fseek(void *stream,long offset,int framewhere)
{
return 0;
}
int HAL_Fclose(FILE *stream)
{
return 0;
}
long HAL_Ftell(void *stream)
{
return 0;
}

View file

@ -0,0 +1,564 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <aos/aos.h>
#include <hal/wifi.h>
#include <hal/hal.h>
#include "activation.h"
#include "chip_code.h"
#include "iot_import.h"
#include "iot_import_product.h"
#include "utils_sysinfo.h"
#define DEFAULT_THREAD_PRI AOS_DEFAULT_APP_PRI
#define _RHINO_SDK_DEMO__ 1
#define PLATFORM_LINUX_LOG(format, ...) \
do { \
printf("Linux:%s:%d %s()| " format "\n", __FILE__, __LINE__, \
__FUNCTION__, ##__VA_ARGS__); \
fflush(stdout); \
} while (0);
void *HAL_MutexCreate(void)
{
aos_mutex_t mutex;
if (0 != aos_mutex_new(&mutex)) {
return NULL;
}
return mutex.hdl;
}
void HAL_MutexDestroy(_IN_ void *mutex)
{
if (NULL != mutex) {
aos_mutex_free((aos_mutex_t *)&mutex);
}
}
void HAL_MutexLock(_IN_ void *mutex)
{
if (NULL != mutex) {
aos_mutex_lock((aos_mutex_t *)&mutex, AOS_WAIT_FOREVER);
}
}
void HAL_MutexUnlock(_IN_ void *mutex)
{
if (NULL != mutex) {
aos_mutex_unlock((aos_mutex_t *)&mutex);
}
}
void *HAL_Malloc(_IN_ uint32_t size)
{
return aos_malloc(size);
}
void *HAL_Realloc(_IN_ void *ptr, _IN_ uint32_t size)
{
return aos_realloc(ptr, size);
}
// void *HAL_Calloc(_IN_ uint32_t nmemb, _IN_ uint32_t size)
// {
// return aos_calloc(nmemb, size);
// }
void HAL_Free(_IN_ void *ptr)
{
aos_free(ptr);
}
void HAL_Reboot(void)
{
aos_reboot();
}
int aliot_platform_ota_start(const char *md5, uint32_t file_size)
{
printf("this interface is NOT support yet.");
return -1;
}
int aliot_platform_ota_write(_IN_ char *buffer, _IN_ uint32_t length)
{
printf("this interface is NOT support yet.");
return -1;
}
int aliot_platform_ota_finalize(_IN_ int stat)
{
printf("this interface is NOT support yet.");
return -1;
}
uint64_t HAL_UptimeMs(void)
{
return aos_now_ms();
}
void HAL_SleepMs(_IN_ uint32_t ms)
{
aos_msleep(ms);
}
uint64_t aliot_platform_time_left(uint64_t t_end, uint64_t t_now)
{
uint64_t t_left;
if (t_end > t_now) {
t_left = t_end - t_now;
} else {
t_left = 0;
}
return t_left;
}
int HAL_Snprintf(_IN_ char *str, const int len, const char *fmt, ...)
{
va_list args;
int rc;
va_start(args, fmt);
rc = vsnprintf(str, len, fmt, args);
va_end(args);
return rc;
}
int HAL_Vsnprintf(_IN_ char *str, _IN_ const int len, _IN_ const char *format,
va_list ap)
{
return vsnprintf(str, len, format, ap);
}
extern int LITE_get_loglevel(void);
void HAL_Printf(_IN_ const char *fmt, ...)
{
va_list args;
#ifdef AOS_DISABLE_ALL_LOGS
if (0 == log_get_enable_aos_log_flag()) return;
#endif
if (LITE_get_loglevel() == AOS_LL_V_NONE) return;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
fflush(stdout);
}
void HAL_Srandom(uint32_t seed)
{
// srandom(seed);
srand(seed);
}
uint32_t HAL_Random(uint32_t region)
{
return (region > 0) ? (rand() % region) : 0;
// return 0;
}
void *HAL_SemaphoreCreate(void)
{
aos_sem_t sem;
if (0 != aos_sem_new(&sem, 0)) {
return NULL;
}
return sem.hdl;
}
void HAL_SemaphoreDestroy(_IN_ void *sem)
{
aos_sem_free((aos_sem_t *)&sem);
}
void HAL_SemaphorePost(_IN_ void *sem)
{
aos_sem_signal((aos_sem_t *)&sem);
}
int HAL_SemaphoreWait(_IN_ void *sem, _IN_ uint32_t timeout_ms)
{
if (PLATFORM_WAIT_INFINITE == timeout_ms) {
return aos_sem_wait((aos_sem_t *)&sem, AOS_WAIT_FOREVER);
} else {
return aos_sem_wait((aos_sem_t *)&sem, timeout_ms);
}
}
typedef struct {
aos_task_t task;
int detached;
void *arg;
void *(*routine)(void *arg);
} task_context_t;
static void task_wrapper(void *arg)
{
task_context_t *task = arg;
if (task == NULL)
{
printf("HAL_CreateThread arg is NULL\r\n");
return;
}
task->routine(task->arg);
if (task) {
aos_free(task);
task = NULL;
}
}
#define DEFAULT_THREAD_NAME "AosThread"
#define DEFAULT_THREAD_SIZE 4096
int HAL_ThreadCreate(_OU_ void **thread_handle,
_IN_ void *(*work_routine)(void *), _IN_ void *arg,
_IN_ hal_os_thread_param_t *hal_os_thread_param,
_OU_ int *stack_used)
{
int ret = -1;
if (stack_used != NULL) {
*stack_used = 0;
}
char *tname;
size_t ssiz;
int detach_state = 0;
int priority;
if (hal_os_thread_param) {
detach_state = hal_os_thread_param->detach_state;
}
if (!hal_os_thread_param || !hal_os_thread_param->name) {
tname = DEFAULT_THREAD_NAME;
} else {
tname = hal_os_thread_param->name;
}
if (!hal_os_thread_param || hal_os_thread_param->stack_size == 0) {
ssiz = DEFAULT_THREAD_SIZE;
} else {
ssiz = hal_os_thread_param->stack_size;
}
if (!hal_os_thread_param || hal_os_thread_param->priority == 0) {
priority = DEFAULT_THREAD_PRI;
} else if (hal_os_thread_param->priority < os_thread_priority_idle ||
hal_os_thread_param->priority > os_thread_priority_realtime) {
priority = DEFAULT_THREAD_PRI;
} else {
priority = DEFAULT_THREAD_PRI - hal_os_thread_param->priority;
}
task_context_t *task = aos_malloc(sizeof(task_context_t));
if (!task) {
return -1;
}
memset(task, 0, sizeof(task_context_t));
task->arg = arg;
task->routine = work_routine;
task->detached = detach_state;
ret = aos_task_new_ext(&task->task, tname, task_wrapper, task, ssiz,
priority);
*thread_handle = (void *)task;
return ret;
}
void HAL_ThreadDetach(_IN_ void *thread_handle)
{
task_context_t *task = thread_handle;
task->detached = 1;
}
void HAL_ThreadDelete(_IN_ void *thread_handle)
{
}
void HAL_Firmware_Persistence_Start(void) {}
int HAL_Firmware_Persistence_Write(_IN_ char *buffer, _IN_ uint32_t length)
{
return 0;
}
int HAL_Firmware_Persistence_Stop(void)
{
return 0;
}
int HAL_Config_Write(const char *buffer, int length)
{
if (!buffer || length <= 0) {
return -1;
}
return aos_kv_set("alink", buffer, length, 1);
}
int HAL_Config_Read(char *buffer, int length)
{
if (!buffer || length <= 0) {
return -1;
}
return aos_kv_get("alink", buffer, &length);
}
int HAL_Kv_Set(const char *key, const void *val, int len, int sync)
{
int ret = 0;
ret = aos_kv_set(key, val, len, sync);
return ret;
}
int HAL_Kv_Get(const char *key, void *buffer, int *buffer_len)
{
int ret = 0;
ret = aos_kv_get(key, buffer, buffer_len);
return ret;
}
int HAL_Kv_Del(const char *key)
{
int ret = 0;
ret = aos_kv_del(key);
return ret;
}
int HAL_Kv_Del_By_Prefix(const char *prefix)
{
int ret = 0;
ret = aos_kv_del_by_prefix(prefix);
return ret;
}
typedef struct {
const char *name;
int ms;
aos_call_t cb;
void *data;
} schedule_timer_t;
static void schedule_timer(void *p)
{
if (p == NULL) {
return;
}
schedule_timer_t *pdata = p;
aos_post_delayed_action(pdata->ms, pdata->cb, pdata->data);
}
static void schedule_timer_cancel(void *p)
{
if (p == NULL) {
return;
}
schedule_timer_t *pdata = p;
aos_cancel_delayed_action(-1, pdata->cb, pdata->data);
}
static void schedule_timer_delete(void *p)
{
if (p == NULL) {
return;
}
schedule_timer_t *pdata = p;
aos_cancel_delayed_action(-1, pdata->cb, pdata->data);
aos_free(p);
}
#define USE_YLOOP
void *HAL_Timer_Create(const char *name, void (*func)(void *), void *user_data)
{
#ifdef USE_YLOOP
schedule_timer_t *timer =
(schedule_timer_t *)aos_malloc(sizeof(schedule_timer_t));
if (timer == NULL) {
return NULL;
}
timer->name = name;
timer->cb = func;
timer->data = user_data;
return timer;
#else
return NULL;
#endif
}
int HAL_Timer_Start(void *t, int ms)
{
#ifdef USE_YLOOP
if (t == NULL) {
return -1;
}
schedule_timer_t *timer = t;
timer->ms = ms;
return aos_schedule_call(schedule_timer, t);
#else
return 0;
#endif
}
int HAL_Timer_Stop(void *t)
{
#ifdef USE_YLOOP
if (t == NULL) {
return -1;
}
return aos_schedule_call(schedule_timer_cancel, t);
#else
return 0;
#endif
}
int HAL_Timer_Delete(void *timer)
{
#ifdef USE_YLOOP
if (timer == NULL) {
return -1;
}
return aos_schedule_call(schedule_timer_delete, timer);
#else
return 0;
#endif
}
static int64_t delta_ms = 0;
void HAL_UTC_Set(long long ms)
{
delta_ms = ms - aos_now_ms();
}
long long HAL_UTC_Get(void)
{
long long ret = aos_now_ms() + delta_ms;
return ret;
}
int get_aos_hex_version(const char *str, unsigned char hex[VERSION_NUM_SIZE])
{
char *p = NULL;
char *q = NULL;
int i = 0;
char str_ver[32] = { 0 };
if (str == NULL) {
return -1;
}
if (hex == NULL) {
return -1;
}
strncpy(str_ver, str, sizeof(str_ver) - 1);
p = strtok(str_ver, "-");
for (i = 0; i < 2; i++) {
if (p == NULL) {
return -1;
}
p = strtok(NULL, "-");
}
q = strtok(p, ".");
for (i = 0; i < 4; i++) {
if (q == NULL) {
break;
} else {
hex[i] = atoi(q);
}
q = strtok(NULL, ".");
}
return 0;
}
/**
* 使kernel版本号字节数组
*/
void aos_get_version_hex(unsigned char version[VERSION_NUM_SIZE])
{
memset(version, 0, VERSION_NUM_SIZE);
get_aos_hex_version(aos_version_get(), version);
}
/**
* 使mac地址
*/
void aos_get_mac_hex(unsigned char mac[MAC_ADDRESS_SIZE])
{
memset(mac, 0, MAC_ADDRESS_SIZE);
hal_wifi_get_mac_addr(NULL, mac);
// return mac;
}
/**
* 使ID
*/
void aos_get_chip_code(unsigned char chip_code[CHIP_CODE_SIZE])
{
memset(chip_code, 0, CHIP_CODE_SIZE);
// MCU_ID import by -D option
chip_code_st *p_chip_code_obj = get_chip_code(MCU_FAMILY);
if (p_chip_code_obj != NULL) {
chip_code[0] = (uint8_t)(p_chip_code_obj->vendor >> 8);
chip_code[1] = (uint8_t)p_chip_code_obj->vendor;
chip_code[2] = (uint8_t)(p_chip_code_obj->id >> 8);
chip_code[3] = (uint8_t)p_chip_code_obj->id;
}
// return chip_code;
}
int HAL_GetNetifInfo(char *nif_str)
{
memset(nif_str, 0x0, NIF_STRLEN_MAX);
#ifdef __DEMO__
/* if the device have only WIFI, then list as follow, note that the len MUST NOT exceed NIF_STRLEN_MAX */
const char *net_info = "WiFi|03ACDEFF0032";
strncpy(nif_str, net_info, strlen(net_info));
/* if the device have ETH, WIFI, GSM connections, then list all of them as follow, note that the len MUST NOT exceed NIF_STRLEN_MAX */
// const char *multi_net_info = "ETH|0123456789abcde|WiFi|03ACDEFF0032|Cellular|imei_0123456789abcde|iccid_0123456789abcdef01234|imsi_0123456789abcde|msisdn_86123456789ab");
// strncpy(nif_str, multi_net_info, strlen(multi_net_info));
#else
uint8_t mac[6];
memset(mac, 0x0, 6);
hal_wifi_get_mac_addr(NULL, mac);
snprintf(nif_str, NIF_STRLEN_MAX, "WiFi|%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
#endif
return strlen(nif_str);
}

View file

@ -0,0 +1,200 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <string.h>
#include <aos/aos.h>
#include "iot_import.h"
#include "iot_import_product.h"
//#include "iot_import_awss.h"
/* <TODO> */
#define PARTNER_ID "AliOSThings"
#define MODULE_ID "GeneralID"
#define DEVICE_ID "AosAwssDeviceID"
#define FW_VERSION "AosAwssFwVersion"
#define CHIP_ID "AosAwssChiID"
#define __DEMO__
#ifdef __DEMO__
char _product_key[PRODUCT_KEY_LEN + 1];
char _product_secret[PRODUCT_SECRET_LEN + 1];
char _device_name[DEVICE_NAME_LEN + 1];
char _device_secret[DEVICE_SECRET_LEN + 1];
#endif
int HAL_SetProductKey(_IN_ char *product_key)
{
int len = strlen(product_key);
#ifdef __DEMO__
if (len > PRODUCT_KEY_LEN) {
return -1;
}
memset(_product_key, 0x0, PRODUCT_KEY_LEN + 1);
strncpy(_product_key, product_key, len);
#endif
return len;
}
int HAL_SetDeviceName(_IN_ char *device_name)
{
int len = strlen(device_name);
#ifdef __DEMO__
if (len > DEVICE_NAME_LEN) {
return -1;
}
memset(_device_name, 0x0, DEVICE_NAME_LEN + 1);
strncpy(_device_name, device_name, len);
#endif
return len;
}
int HAL_SetDeviceSecret(_IN_ char *device_secret)
{
int len = strlen(device_secret);
#ifdef __DEMO__
if (len > DEVICE_SECRET_LEN) {
return -1;
}
memset(_device_secret, 0x0, DEVICE_SECRET_LEN + 1);
strncpy(_device_secret, device_secret, len);
#endif
return len;
}
int HAL_SetProductSecret(_IN_ char *product_secret)
{
int len = strlen(product_secret);
#ifdef __DEMO__
if (len > PRODUCT_SECRET_LEN) {
return -1;
}
memset(_product_secret, 0x0, PRODUCT_SECRET_LEN + 1);
strncpy(_product_secret, product_secret, len);
#endif
return len;
}
int HAL_GetProductKey(_OU_ char *product_key)
{
int len = strlen(_product_key);
memset(product_key, 0x0, PRODUCT_KEY_LEN);
#ifdef __DEMO__
strncpy(product_key, _product_key, len);
#endif
return len;
}
int HAL_GetProductSecret(_OU_ char *product_secret)
{
int len = strlen(_product_secret);
memset(product_secret, 0x0, PRODUCT_SECRET_LEN);
#ifdef __DEMO__
strncpy(product_secret, _product_secret, len);
#endif
return len;
}
int HAL_GetDeviceName(_OU_ char *device_name)
{
int len = strlen(_device_name);
memset(device_name, 0x0, DEVICE_NAME_LEN);
#ifdef __DEMO__
strncpy(device_name, _device_name, len);
#endif
return strlen(device_name);
}
int HAL_GetDeviceSecret(_OU_ char *device_secret)
{
int len = strlen(_device_secret);
memset(device_secret, 0x0, DEVICE_SECRET_LEN);
#ifdef __DEMO__
strncpy(device_secret, _device_secret, len);
#endif
return len;
}
/**
* @brief `Partner ID`,
*
* @param pid_str : Partner ID字符串的数组
* @return pid_str[], (Byte)
*/
int HAL_GetPartnerID(char *pid_str)
{
memset(pid_str, 0x0, PID_STRLEN_MAX);
#ifdef __DEMO__
strncpy(pid_str, SYSINFO_PRODUCT_MODEL, PID_STRLEN_MAX - 1);
#endif
return strlen(pid_str);
}
int HAL_GetModuleID(char *mid_str)
{
memset(mid_str, 0x0, MID_STRLEN_MAX);
#ifdef __DEMO__
strncpy(mid_str, SYSINFO_DEVICE_NAME, MID_STRLEN_MAX - 1);
#endif
return strlen(mid_str);
}
void aos_get_chip_code(unsigned char *chip_code);
char *HAL_GetChipID(_OU_ char *cid_str)
{
uint8_t chip_code[4];
memset(cid_str, 0x0, HAL_CID_LEN);
aos_get_chip_code(chip_code);
snprintf(cid_str, HAL_CID_LEN, "%02x%02x%02x%02x", chip_code[0],
chip_code[1], chip_code[2], chip_code[3]);
cid_str[HAL_CID_LEN - 1] = '\0';
return cid_str;
// return strlen(cid_str);
}
int HAL_GetDeviceID(_OU_ char *device_id)
{
memset(device_id, 0x0, DEVICE_ID_LEN);
#ifdef __DEMO__
HAL_Snprintf(device_id, DEVICE_ID_LEN, "%s.%s", _product_key, _device_name);
device_id[DEVICE_ID_LEN - 1] = '\0';
#endif
return strlen(device_id);
}
/**
* @brief
*
* @param version :
* @return version[], (Byte)
*/
int HAL_GetFirmwareVersion(_OU_ char version[FIRMWARE_VERSION_MAXLEN])
{
memset(version, 0x0, FIRMWARE_VERSION_MAXLEN);
#ifdef __DEMO__
strncpy(version, aos_get_app_version(), FIRMWARE_VERSION_MAXLEN - 1);
version[FIRMWARE_VERSION_MAXLEN - 1] = '\0';
#endif
return strlen(version);
}

View file

@ -0,0 +1,273 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <string.h>
#include "aos/aos.h"
#include <aos/errno.h>
#include <aos/network.h>
#include "iot_import.h"
extern uint64_t aliot_platform_time_left(uint64_t t_end, uint64_t t_now);
#define PLATFORM_LOG_D(format, ...) \
do { \
printf("D: %d %s() | " format "\n", __LINE__, __FUNCTION__, \
##__VA_ARGS__); \
} while (0);
#define PLATFORM_LOG_E(format, ...) \
do { \
printf("E: %d %s() | " format "\n", __LINE__, __FUNCTION__, \
##__VA_ARGS__); \
} while (0);
#ifndef CONFIG_NO_TCPIP
uintptr_t HAL_TCP_Establish(_IN_ const char *host, _IN_ uint16_t port)
// intptr_t HAL_TCP_Establish(const char *host, uint16_t port)
{
struct addrinfo hints;
struct addrinfo *addrInfoList = NULL;
struct addrinfo *cur = NULL;
int fd = 0;
int rc = -1;
char service[6];
memset(&hints, 0, sizeof(hints));
PLATFORM_LOG_D("establish tcp connection with server(host=%s port=%u)", host, port);
hints.ai_family = AF_INET; // only IPv4
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
sprintf(service, "%u", port);
if ((rc = getaddrinfo(host, service, &hints, &addrInfoList)) != 0) {
PLATFORM_LOG_E("getaddrinfo error: %d", rc);
return -1;
}
for (cur = addrInfoList; cur != NULL; cur = cur->ai_next) {
if (cur->ai_family != AF_INET) {
PLATFORM_LOG_E("socket type error");
rc = -1;
continue;
}
fd = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol);
if (fd < 0) {
PLATFORM_LOG_E("create socket error");
rc = -1;
continue;
}
if (connect(fd, cur->ai_addr, cur->ai_addrlen) == 0) {
rc = fd;
break;
}
close(fd);
PLATFORM_LOG_E("connect error");
rc = -1;
}
if (-1 == rc) {
PLATFORM_LOG_D("fail to establish tcp");
} else {
PLATFORM_LOG_D("success to establish tcp, fd=%d", rc);
}
freeaddrinfo(addrInfoList);
return (uintptr_t)rc;
}
int32_t HAL_TCP_Destroy(uintptr_t fd)
{
int rc;
// Shutdown both send and receive operations.
rc = shutdown((int)fd, 2);
if (0 != rc) {
PLATFORM_LOG_E("shutdown error");
return -1;
}
rc = close((int)fd);
if (0 != rc) {
PLATFORM_LOG_E("closesocket error");
return -1;
}
return 0;
}
int32_t HAL_TCP_Write(uintptr_t fd, const char *buf, uint32_t len,
uint32_t timeout_ms)
{
int ret, err_code;
uint32_t len_sent;
uint64_t t_end, t_left;
fd_set sets;
if (fd >= FD_SETSIZE) {
return -1;
}
t_end = HAL_UptimeMs() + timeout_ms;
len_sent = 0;
err_code = 0;
ret = 1; // send one time if timeout_ms is value 0
do {
t_left = aliot_platform_time_left(t_end, HAL_UptimeMs());
if (0 != t_left) {
struct timeval timeout;
FD_ZERO(&sets);
FD_SET(fd, &sets);
timeout.tv_sec = t_left / 1000;
timeout.tv_usec = (t_left % 1000) * 1000;
ret = select(fd + 1, NULL, &sets, NULL, &timeout);
if (ret > 0) {
if (0 == FD_ISSET(fd, &sets)) {
PLATFORM_LOG_D("Should NOT arrive");
// If timeout in next loop, it will not sent any data
ret = 0;
continue;
}
} else if (0 == ret) {
// PLATFORM_LOG_D("select-write timeout %lu", fd);
break;
} else {
if (EINTR == errno) {
PLATFORM_LOG_D("EINTR be caught");
continue;
}
err_code = -1;
PLATFORM_LOG_E("select-write fail");
break;
}
}
if (ret > 0) {
ret = send(fd, buf + len_sent, len - len_sent, 0);
if (ret > 0) {
len_sent += ret;
} else if (0 == ret) {
PLATFORM_LOG_D("No data be sent");
} else {
if (EINTR == errno) {
PLATFORM_LOG_D("EINTR be caught");
continue;
}
err_code = -1;
PLATFORM_LOG_E("send fail");
break;
}
}
} while ((len_sent < len) &&
(aliot_platform_time_left(t_end, HAL_UptimeMs()) > 0));
return err_code == 0 ? len_sent : err_code;
}
int32_t HAL_TCP_Read(uintptr_t fd, char *buf, uint32_t len, uint32_t timeout_ms)
{
int ret, err_code;
uint32_t len_recv;
uint64_t t_end, t_left;
fd_set sets;
struct timeval timeout;
if (fd >= FD_SETSIZE) {
PLATFORM_LOG_E("%s error: fd (%d) >= FD_SETSIZE (%d)", __func__, fd, FD_SETSIZE);
return -1;
}
t_end = HAL_UptimeMs() + timeout_ms;
len_recv = 0;
err_code = 0;
do {
t_left = aliot_platform_time_left(t_end, HAL_UptimeMs());
if (0 == t_left) {
PLATFORM_LOG_D("%s no time left", __func__);
err_code = -1;
break;
}
FD_ZERO(&sets);
FD_SET(fd, &sets);
timeout.tv_sec = t_left / 1000;
timeout.tv_usec = (t_left % 1000) * 1000;
ret = select(fd + 1, &sets, NULL, NULL, &timeout);
if (ret > 0) {
if (0 == FD_ISSET(fd, &sets)) {
PLATFORM_LOG_D("%s No data for fd %d", __func__, fd);
ret = 0;
continue;
}
ret = recv(fd, buf + len_recv, len - len_recv, 0);
if (ret > 0) {
len_recv += ret;
} else {
if ((EINTR == errno) || (EAGAIN == errno) || (EWOULDBLOCK == errno) ||
(EPROTOTYPE == errno) || (EALREADY == errno) || (EINPROGRESS == errno)) {
continue;
}
if (ret == 0)
{
PLATFORM_LOG_D("%s recv 0 for fd %d", __func__, fd);
}
else
{
PLATFORM_LOG_E("recv fail (fd: %d), errno: %d, ret: %d", fd, errno, ret);
}
err_code = -2;
break;
}
} else if (0 == ret) {
//select timeout is not error
//PLATFORM_LOG_D("%s select (fd: %d) timeout", __func__, fd);
//err_code = -1;
break;
} else {
PLATFORM_LOG_E("select-recv (fd: %d) fail errno=%d",fd, errno);
err_code = -2;
break;
}
} while ((len_recv < len));
// priority to return data bytes if any data be received from TCP
// connection. It will get error code on next calling
return (0 != len_recv) ? len_recv : err_code;
}
#else
uintptr_t HAL_TCP_Establish(_IN_ const char *host, _IN_ uint16_t port)
{
return 0;
}
int32_t HAL_TCP_Destroy(uintptr_t fd)
{
return 0;
}
int32_t HAL_TCP_Write(uintptr_t fd, const char *buf, uint32_t len,
uint32_t timeout_ms)
{
return 0;
}
int32_t HAL_TCP_Read(uintptr_t fd, char *buf, uint32_t len, uint32_t timeout_ms)
{
return 0;
}
#endif

View file

@ -0,0 +1,434 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <string.h>
//#include <memory.h>
#include <stdlib.h>
#include <string.h>
#include "aos/aos.h"
#include "itls/ssl.h"
#include "itls/net.h"
#include "itls/debug.h"
#include "itls/platform.h"
#include "iot_import.h"
#define LOG_TAG "HAL_iTLS"
#define platform_info(format, ...) LOGI(LOG_TAG, format, ##__VA_ARGS__)
#define platform_err(format, ...) LOGE(LOG_TAG, format, ##__VA_ARGS__)
#define CONFIG_ITLS_TIME_TEST
#define SEND_TIMEOUT_SECONDS (10)
typedef struct _TLSDataParams {
mbedtls_ssl_context ssl; /**< iTLS control context. */
mbedtls_net_context fd; /**< iTLS network context. */
mbedtls_ssl_config conf; /**< iTLS configuration context. */
} TLSDataParams_t, *TLSDataParams_pt;
/**< set debug log level, 0 close*/
#define DEBUG_LEVEL 0
#define ITLS_READ_HEADER_TIMEOUT 30 // 30 ms
#define ITLS_READ_PAYLOAD_TIMEOUT 20000 // 20s
#if defined(CONFIG_ITLS_TIME_TEST)
#include <sys/time.h>
static struct timeval tv1, tv2;
#endif
static unsigned int _avRandom()
{
return (((unsigned int)rand() << 16) + rand());
}
static int _ssl_random(void *p_rng, unsigned char *output, size_t output_len)
{
uint32_t rnglen = output_len;
uint8_t rngoffset = 0;
while (rnglen > 0) {
*(output + rngoffset) = (unsigned char)_avRandom() ;
rngoffset++;
rnglen--;
}
return 0;
}
static void _ssl_debug(void *ctx, int level, const char *file, int line, const char *str)
{
((void) ctx);
((void) level);
platform_info("%s:%04d: %s", file, line, str);
}
#if defined(_PLATFORM_IS_LINUX_)
static int net_prepare(void)
{
#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
!defined(EFI32)
WSADATA wsaData;
static int wsa_init_done = 0;
if (wsa_init_done == 0) {
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
return (MBEDTLS_ERR_NET_SOCKET_FAILED);
}
wsa_init_done = 1;
}
#else
#if !defined(EFIX64) && !defined(EFI32)
signal(SIGPIPE, SIG_IGN);
#endif
#endif
return (0);
}
static int mbedtls_net_connect_timeout(mbedtls_net_context *ctx, const char *host,
const char *port, int proto, unsigned int timeout)
{
int ret;
struct addrinfo hints, *addr_list, *cur;
struct timeval sendtimeout;
if ((ret = net_prepare()) != 0) {
return (ret);
}
/* Do name resolution with both IPv6 and IPv4 */
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
if (getaddrinfo(host, port, &hints, &addr_list) != 0) {
return (MBEDTLS_ERR_NET_UNKNOWN_HOST);
}
/* Try the sockaddrs until a connection succeeds */
ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
for (cur = addr_list; cur != NULL; cur = cur->ai_next) {
ctx->fd = (int) socket(cur->ai_family, cur->ai_socktype,
cur->ai_protocol);
if (ctx->fd < 0) {
ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
continue;
}
sendtimeout.tv_sec = timeout;
sendtimeout.tv_usec = 0;
if (0 != setsockopt(ctx->fd, SOL_SOCKET, SO_SNDTIMEO, &sendtimeout, sizeof(sendtimeout))) {
perror("setsockopt");
platform_err("setsockopt error");
}
platform_info("setsockopt SO_SNDTIMEO timeout: %ds", sendtimeout.tv_sec);
if (connect(ctx->fd, cur->ai_addr, cur->ai_addrlen) == 0) {
ret = 0;
break;
}
close(ctx->fd);
ret = MBEDTLS_ERR_NET_CONNECT_FAILED;
}
freeaddrinfo(addr_list);
return (ret);
}
#endif
/**
* @brief This function connects to the specific SSL server with TLS.
* @param[in] n is the the network structure pointer.
* @param[in] addr is the Server Host name or IP address.
* @param[in] port is the Server Port.
* @param[in] product_key is the product name.
* @param[in] product_secret is the product secret.
*
* @retval 0 : success.
* @retval < 0 : fail.
*/
static int _TLSConnectNetwork(TLSDataParams_t *pTlsData,
const char *addr,
const char *port,
const char *product_key,
const char *product_secret)
{
int ret = -1;
/*
* 0. Initialize the RNG and the session data
*/
#if defined(MBEDTLS_DEBUG_C)
mbedtls_debug_set_threshold(DEBUG_LEVEL);
#endif
mbedtls_ssl_init(&(pTlsData->ssl));
mbedtls_net_init(&(pTlsData->fd));
mbedtls_ssl_config_init(&(pTlsData->conf));
/*
* 1. Start the connection
*/
platform_info("Connecting to /%s/%s...", addr, port);
#if defined(_PLATFORM_IS_LINUX_)
if (0 != (ret = mbedtls_net_connect_timeout(&(pTlsData->fd),
addr, port, MBEDTLS_NET_PROTO_TCP, SEND_TIMEOUT_SECONDS))) {
platform_err(" failed ! net_connect returned -0x%04x", -ret);
return ret;
}
#else
if (0 != (ret = mbedtls_net_connect(&(pTlsData->fd), addr, port, MBEDTLS_NET_PROTO_TCP))) {
platform_err(" failed ! net_connect returned -0x%04x", -ret);
return ret;
}
#endif
platform_info(" ok");
/*
* 2. Setup stuff
*/
platform_info(" . Setting up the SSL/TLS structure...");
if ((ret = mbedtls_ssl_config_defaults(&(pTlsData->conf),
MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
platform_err(" failed! mbedtls_ssl_config_defaults returned %d", ret);
goto _out;
}
mbedtls_ssl_conf_max_version(&pTlsData->conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);
mbedtls_ssl_conf_min_version(&pTlsData->conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);
platform_info(" ok");
mbedtls_ssl_conf_rng(&(pTlsData->conf), _ssl_random, NULL);
mbedtls_ssl_conf_dbg(&(pTlsData->conf), _ssl_debug, NULL);
/* "OPTIONAL", set extra data for client authentication */
if ((ret = mbedtls_ssl_conf_auth_extra(&(pTlsData->conf), product_key, strlen(product_key))) != 0) {
platform_err(" failed! mbedtls_ssl_config_auth_extra returned %d", ret);
goto _out;
}
/* "OPTIONAL", token for id2 one-time provisioning */
if ((ret = mbedtls_ssl_conf_auth_token(&(pTlsData->conf), product_secret, strlen(product_secret))) != 0) {
platform_err( " failed\n ! mbedtls_ssl_conf_auth_token returned %d\n\n", ret );
goto _out;
}
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
if ((ret = mbedtls_ssl_conf_max_frag_len(&(pTlsData->conf), MBEDTLS_SSL_MAX_FRAG_LEN_1024)) != 0) {
platform_err( " failed\n ! mbedtls_ssl_conf_max_frag_len returned %d\n\n", ret );
goto _out;
}
#endif
if ((ret = mbedtls_ssl_setup(&(pTlsData->ssl), &(pTlsData->conf))) != 0) {
platform_err(" failed! mbedtls_ssl_setup returned %d", ret);
goto _out;
}
mbedtls_ssl_set_bio(&(pTlsData->ssl), &(pTlsData->fd), mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout);
/*
* 3. Handshake
*/
platform_info("Performing the SSL/TLS handshake...");
#if defined(CONFIG_ITLS_TIME_TEST)
gettimeofday(&tv1, NULL);
#endif
while ((ret = mbedtls_ssl_handshake(&(pTlsData->ssl))) != 0) {
if ((ret != MBEDTLS_ERR_SSL_WANT_READ) && (ret != MBEDTLS_ERR_SSL_WANT_WRITE)) {
platform_err("failed ! mbedtls_ssl_handshake returned -0x%04x", -ret);
goto _out;
}
}
#if defined(CONFIG_ITLS_TIME_TEST)
gettimeofday(&tv2, NULL);
platform_info("=========================== iTLS handshake used time(usec): %d\n",
(int)((tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec)));
#endif
platform_info(" ok");
_out:
if (ret != 0) {
mbedtls_net_free(&(pTlsData->fd));
mbedtls_ssl_free(&(pTlsData->ssl));
mbedtls_ssl_config_free(&(pTlsData->conf));
}
return ret;
}
static int _network_ssl_read(TLSDataParams_t *pTlsData, char *buffer, int len, int timeout_ms)
{
uint32_t readLen = 0;
static int net_status = 0;
int ret = -1;
#if defined(CONFIG_ITLS_TIME_TEST)
gettimeofday(&tv1, NULL);
#endif
if (len > 1) { /* len > 1 indicates that trying to read payload */
timeout_ms = ITLS_READ_PAYLOAD_TIMEOUT;
} else if (timeout_ms < ITLS_READ_HEADER_TIMEOUT) {
timeout_ms = ITLS_READ_HEADER_TIMEOUT; /* wait for at least 30ms for header type or packet length */
}
mbedtls_ssl_conf_read_timeout(&(pTlsData->conf), timeout_ms);
while (readLen < len) {
ret = mbedtls_ssl_read(&(pTlsData->ssl), (unsigned char *)(buffer + readLen), (len - readLen));
if (ret > 0) {
readLen += ret;
net_status = 0;
} else if (ret == 0) {
/* if ret is 0 and net_status is -2, indicate the connection is closed during last call */
return (net_status == -2) ? net_status : readLen;
} else {
if (MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY == ret) {
platform_err("ssl recv peer close notify");
net_status = -2; /* connection is closed */
break;
} else if ((MBEDTLS_ERR_SSL_TIMEOUT == ret)
|| (MBEDTLS_ERR_SSL_CONN_EOF == ret)
|| (MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED == ret)
|| (MBEDTLS_ERR_SSL_NON_FATAL == ret)) {
/* read already complete */
/* if call mbedtls_ssl_read again, it will return 0 (means EOF) */
return readLen;
} else {
#ifdef CSP_LINUXHOST
if (MBEDTLS_ERR_SSL_WANT_READ == ret && errno == EINTR) {
continue;
}
#endif
platform_err("ssl recv error: code = %d", ret);
net_status = -1;
return -1; /* Connection error */
}
}
}
#if defined(CONFIG_ITLS_TIME_TEST)
gettimeofday(&tv2, NULL);
platform_info("=========================== iTLS receive data(%d bytes) used time(usec): %d\n",
readLen, (int)((tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec)));
#endif
return (readLen > 0) ? readLen : net_status;
}
static int _network_ssl_write(TLSDataParams_t *pTlsData, const char *buffer, int len, int timeout_ms)
{
uint32_t writtenLen = 0;
int ret = -1;
#if defined(CONFIG_ITLS_TIME_TEST)
gettimeofday(&tv1, NULL);
#endif
while (writtenLen < len) {
ret = mbedtls_ssl_write(&(pTlsData->ssl), (unsigned char *)(buffer + writtenLen), (len - writtenLen));
if (ret > 0) {
writtenLen += ret;
continue;
} else if (ret == 0) {
platform_err("ssl write timeout");
return 0;
} else {
platform_err("ssl write error, code = %d", ret);
return -1;
}
}
#if defined(CONFIG_ITLS_TIME_TEST)
gettimeofday(&tv2, NULL);
platform_info("iTLS send data(%d bytes) used time(usec): %d\n",
writtenLen, (int)((tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec)));
#endif
return writtenLen;
}
static void _network_ssl_disconnect(TLSDataParams_t *pTlsData)
{
mbedtls_ssl_close_notify(&(pTlsData->ssl));
mbedtls_net_free(&(pTlsData->fd));
mbedtls_ssl_free(&(pTlsData->ssl));
mbedtls_ssl_config_free(&(pTlsData->conf));
platform_info("ssl_disconnect");
}
uintptr_t HAL_SSL_Establish(const char *host,
uint16_t port,
const char *ca_crt,
size_t ca_crt_len)
{
char port_str[6];
TLSDataParams_pt pTlsData;
const char *product_key = NULL;
const char *product_secret = NULL;
if (host == NULL || ca_crt == NULL) {
platform_err("input params are NULL");
return 0;
}
product_key = ca_crt;
product_secret = ca_crt + strlen(product_key) + 1;
pTlsData = HAL_Malloc(sizeof(TLSDataParams_t));
if (NULL == pTlsData) {
return (uintptr_t)NULL;
}
memset(pTlsData, 0x0, sizeof(TLSDataParams_t));
sprintf(port_str, "%u", port);
if (0 != _TLSConnectNetwork(pTlsData, host, port_str, product_key, product_secret)) {
HAL_Free((void *)pTlsData);
return (uintptr_t)NULL;
}
return (uintptr_t)pTlsData;
}
int32_t HAL_SSL_Destroy(uintptr_t handle)
{
if ((uintptr_t)NULL == handle) {
platform_err("handle is NULL");
return 0;
}
_network_ssl_disconnect((TLSDataParams_t *)handle);
HAL_Free((void *)handle);
return 0;
}
int32_t HAL_SSL_Write(uintptr_t handle, const char *buf, int len, int timeout_ms)
{
return _network_ssl_write((TLSDataParams_t *)handle, buf, len, timeout_ms);
}
int32_t HAL_SSL_Read(uintptr_t handle, char *buf, int len, int timeout_ms)
{
return _network_ssl_read((TLSDataParams_t *)handle, buf, len, timeout_ms);;
}

View file

@ -0,0 +1,936 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string.h>
#include "aos/aos.h"
#include "mbedtls/config.h"
#include "mbedtls/error.h"
#include "mbedtls/ssl.h"
#include "mbedtls/net.h"
#include "mbedtls/x509_crt.h"
#include "mbedtls/pk.h"
#include "mbedtls/debug.h"
#include "mbedtls/platform.h"
#include "utils_hmac.h"
#include "iot_import.h"
#ifdef CONFIG_NET_LWIP
#include <lwip/netdb.h>
#include <lwip/sockets.h>
#endif
#define LOG_TAG "HAL_TLS"
#define platform_info(format, ...) LOGI(LOG_TAG, format, ##__VA_ARGS__)
#define platform_err(format, ...) LOGE(LOG_TAG, format, ##__VA_ARGS__)
#define SEND_TIMEOUT_SECONDS (10)
static ssl_hooks_t g_ssl_hooks = {HAL_Malloc, HAL_Free};
typedef struct _TLSDataParams {
mbedtls_ssl_context ssl; /**< mbed TLS control context. */
mbedtls_net_context fd; /**< mbed TLS network context. */
mbedtls_ssl_config conf; /**< mbed TLS configuration context. */
mbedtls_x509_crt cacertl; /**< mbed TLS CA certification. */
mbedtls_x509_crt clicert; /**< mbed TLS Client certification. */
mbedtls_pk_context pkey; /**< mbed TLS Client key. */
} TLSDataParams_t, *TLSDataParams_pt;
#define DEBUG_LEVEL 10
#define TLS_AUTH_MODE_CA 0
#define TLS_AUTH_MODE_PSK 1
/* config authentication mode */
#ifndef TLS_AUTH_MODE
#define TLS_AUTH_MODE TLS_AUTH_MODE_CA
#endif
#if defined(TLS_SAVE_TICKET)
#define KEY_MAX_LEN 64
#define TLS_MAX_SESSION_BUF 384
#define KV_SESSION_KEY_PREFIX "TLS_"
#define KV_SESSION_KEY_FMT "%s%s:%s"
extern int HAL_Kv_Set(const char *key, const void *val, int len, int sync);
extern int HAL_Kv_Get(const char *key, void *val, int *buffer_len);
static mbedtls_ssl_session *saved_session = NULL;
static int ssl_serialize_session(const mbedtls_ssl_session *session,
unsigned char *buf, size_t buf_len,
size_t *olen)
{
unsigned char *p = buf;
size_t left = buf_len;
if (left < sizeof(mbedtls_ssl_session)) {
return (MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL);
}
memcpy(p, session, sizeof(mbedtls_ssl_session));
p += sizeof(mbedtls_ssl_session);
left -= sizeof(mbedtls_ssl_session);
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
if (left < sizeof(mbedtls_ssl_session)) {
return (MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL);
}
memcpy(p, session->ticket, session->ticket_len);
p += session->ticket_len;
left -= session->ticket_len;
#endif
*olen = p - buf;
return (0);
}
static int ssl_deserialize_session(mbedtls_ssl_session *session,
const unsigned char *buf, size_t len)
{
const unsigned char *p = buf;
const unsigned char *const end = buf + len;
if (sizeof(mbedtls_ssl_session) > (size_t)(end - p)) {
return (MBEDTLS_ERR_SSL_BAD_INPUT_DATA);
}
memcpy(session, p, sizeof(mbedtls_ssl_session));
p += sizeof(mbedtls_ssl_session);
#if defined(MBEDTLS_X509_CRT_PARSE_C)
session->peer_cert = NULL;
#endif
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
if (session->ticket_len > 0) {
if (session->ticket_len > (size_t)(end - p)) {
return (MBEDTLS_ERR_SSL_BAD_INPUT_DATA);
}
session->ticket = HAL_Malloc(session->ticket_len);
if (session->ticket == NULL) {
return (MBEDTLS_ERR_SSL_ALLOC_FAILED);
}
memcpy(session->ticket, p, session->ticket_len);
p += session->ticket_len;
platform_info("saved ticket len = %d", (int)session->ticket_len);
}
#endif
if (p != end) {
return (MBEDTLS_ERR_SSL_BAD_INPUT_DATA);
}
return (0);
}
#endif
int HAL_SSL_Del_KV_Session_Ticket(void)
{
int ret = 0;
#if defined(TLS_SAVE_TICKET)
#if BUILD_AOS
ret = HAL_Kv_Del_By_Prefix(KV_SESSION_KEY_PREFIX);
platform_info("del KV ticket:%d", ret);
#endif
#endif
return ret;
}
#if (TLS_AUTH_MODE == TLS_AUTH_MODE_CA)
static void _srand(unsigned int seed)
{
#define SEED_MAGIC 0x123
int ret = 0;
int seed_len = 0;
unsigned int seed_val = 0;
static char *g_seed_key = "seed_key";
seed_len = sizeof(seed_val);
ret = HAL_Kv_Get(g_seed_key, &seed_val, &seed_len);
if (ret) {
seed_val = SEED_MAGIC;
}
seed_val += seed;
srand(seed_val);
seed_val = rand();
HAL_Kv_Set(g_seed_key, &seed_val, sizeof(seed_val), 1);
}
#endif
static unsigned int _avRandom()
{
return (((unsigned int)rand() << 16) + rand());
}
static int _ssl_random(void *p_rng, unsigned char *output, size_t output_len)
{
uint32_t rnglen = output_len;
uint8_t rngoffset = 0;
while (rnglen > 0) {
*(output + rngoffset) = (unsigned char)_avRandom();
rngoffset++;
rnglen--;
}
return 0;
}
static void _ssl_debug(void *ctx, int level, const char *file, int line,
const char *str)
{
((void)level);
if (NULL != ctx) {
#if 0
fprintf((FILE *) ctx, "%s:%04d: %s", file, line, str);
fflush((FILE *) ctx);
#endif
platform_info("%s", str);
}
}
static int _real_confirm(int verify_result)
{
platform_info("certificate verification result: 0x%02x", verify_result);
#if defined(FORCE_SSL_VERIFY)
if ((verify_result & MBEDTLS_X509_BADCERT_EXPIRED) != 0) {
platform_err("! fail ! ERROR_CERTIFICATE_EXPIRED");
return -1;
}
if ((verify_result & MBEDTLS_X509_BADCERT_REVOKED) != 0) {
platform_err("! fail ! server certificate has been revoked");
return -1;
}
if ((verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH) != 0) {
platform_err("! fail ! CN mismatch");
return -1;
}
if ((verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED) != 0) {
platform_err("! fail ! self-signed or not signed by a trusted CA");
return -1;
}
#endif
return 0;
}
static int _ssl_client_init(mbedtls_ssl_context *ssl,
mbedtls_net_context *tcp_fd,
mbedtls_ssl_config *conf,
mbedtls_x509_crt *crt509_ca, const char *ca_crt,
size_t ca_len, mbedtls_x509_crt *crt509_cli,
const char *cli_crt, size_t cli_len,
mbedtls_pk_context *pk_cli, const char *cli_key,
size_t key_len, const char *cli_pwd, size_t pwd_len)
{
#if (TLS_AUTH_MODE == TLS_AUTH_MODE_CA)
int ret = -1;
#endif
/*
* 0. Initialize the RNG and the session data
*/
#if defined(MBEDTLS_DEBUG_C)
mbedtls_debug_set_threshold((int)DEBUG_LEVEL);
#endif
mbedtls_net_init(tcp_fd);
mbedtls_ssl_init(ssl);
mbedtls_ssl_config_init(conf);
#if (TLS_AUTH_MODE == TLS_AUTH_MODE_CA)
mbedtls_x509_crt_init(crt509_ca);
_srand(HAL_UptimeMs());
/*verify_source->trusted_ca_crt==NULL
* 0. Initialize certificates
*/
platform_info("Loading the CA root certificate ...");
if (NULL != ca_crt) {
if (0 != (ret = mbedtls_x509_crt_parse(
crt509_ca, (const unsigned char *)ca_crt, ca_len))) {
platform_err(" failed ! x509parse_crt returned -0x%04x", -ret);
return ret;
}
}
platform_info(" ok (%d skipped)", ret);
/* Setup Client Cert/Key */
#if defined(MBEDTLS_CERTS_C)
mbedtls_x509_crt_init(crt509_cli);
mbedtls_pk_init(pk_cli);
#endif
if (cli_crt != NULL && cli_key != NULL) {
#if defined(MBEDTLS_CERTS_C)
platform_info("start prepare client cert .");
ret = mbedtls_x509_crt_parse(crt509_cli, (const unsigned char *)cli_crt,
cli_len);
#else
{
ret = 1;
platform_err("MBEDTLS_CERTS_C not defined.");
}
#endif
if (ret != 0) {
platform_err(" failed! mbedtls_x509_crt_parse returned -0x%x\n",
-ret);
return ret;
}
#if defined(MBEDTLS_CERTS_C)
platform_info("start mbedtls_pk_parse_key[%s]", cli_pwd);
ret =
mbedtls_pk_parse_key(pk_cli, (const unsigned char *)cli_key, key_len,
(const unsigned char *)cli_pwd, pwd_len);
#else
{
ret = 1;
platform_err("MBEDTLS_CERTS_C not defined.");
}
#endif
if (ret != 0) {
platform_err(" failed\n ! mbedtls_pk_parse_key returned -0x%x\n",
-ret);
return ret;
}
}
#endif /* #if (TLS_AUTH_MODE == TLS_AUTH_MODE_CA) */
return 0;
}
#if !defined(CSP_LINUXHOST) && !defined(BOARD_ESP8266)
static int net_prepare(void)
{
#if defined(_PLATFORM_IS_LINUX_)
#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
!defined(EFI32)
WSADATA wsaData;
static int wsa_init_done = 0;
if (wsa_init_done == 0) {
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
return (MBEDTLS_ERR_NET_SOCKET_FAILED);
}
wsa_init_done = 1;
}
#else
#if !defined(EFIX64) && !defined(EFI32)
signal(SIGPIPE, SIG_IGN);
#endif
#endif
#endif /* _PLATFORM_IS_LINUX_ */
return (0);
}
static int mbedtls_net_connect_timeout(mbedtls_net_context *ctx,
const char *host, const char *port,
int proto, unsigned int timeout)
{
int ret;
struct addrinfo hints, *addr_list, *cur;
struct timeval sendtimeout;
if ((ret = net_prepare()) != 0) {
return (ret);
}
/* Do name resolution with both IPv6 and IPv4 */
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype =
proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
hints.ai_protocol =
proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
#ifdef CONFIG_NET_LWIP
hints.ai_socktype &= ~O_NONBLOCK;
#else
hints.ai_socktype &= ~SOCK_NONBLOCK;
#endif
#ifdef DEV_OFFLINE_LOG_ENABLE
diagnosis_offline_log(LOG_LEVEL_I, "get ip start\r\n");
#endif
ret = getaddrinfo(host, port, &hints, &addr_list);
#ifdef DEV_OFFLINE_LOG_ENABLE
diagnosis_offline_log(LOG_LEVEL_I, "get ip %s\r\n", (ret != 0)?"fail":"success");
#endif
if (ret != 0) {
return (MBEDTLS_ERR_NET_UNKNOWN_HOST);
}
/* Try the sockaddrs until a connection succeeds */
ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
for (cur = addr_list; cur != NULL; cur = cur->ai_next) {
ctx->fd =
(int)socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol);
if (ctx->fd < 0) {
ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
continue;
}
sendtimeout.tv_sec = timeout;
sendtimeout.tv_usec = 0;
if (0 != setsockopt(ctx->fd, SOL_SOCKET, SO_SNDTIMEO, &sendtimeout,
sizeof(sendtimeout))) {
platform_err("setsockopt SO_SNDTIMEO error");
}
#ifdef CONFIG_NET_LWIP
if (0 != setsockopt(ctx->fd, SOL_SOCKET, SO_RCVTIMEO, &sendtimeout,
sizeof(sendtimeout))) {
#else
if (0 != setsockopt(ctx->fd, SOL_SOCKET, SO_RECVTIMEO, &sendtimeout,
sizeof(sendtimeout))) {
#endif
platform_err("setsockopt SO_RECVTIMEO error");
}
platform_info("setsockopt SO_SNDTIMEO SO_RECVTIMEO timeout: %ds",
sendtimeout.tv_sec);
if (connect(ctx->fd, cur->ai_addr, cur->ai_addrlen) == 0) {
ret = 0;
break;
}
close(ctx->fd);
ret = MBEDTLS_ERR_NET_CONNECT_FAILED;
}
freeaddrinfo(addr_list);
return (ret);
}
#endif
/**
* @brief This function connects to the specific SSL server with TLS, and
* returns a value that indicates whether the connection is create successfully
* or not. Call #NewNetwork() to initialize network structure before calling
* this function.
* @param[in] n is the the network structure pointer.
* @param[in] addr is the Server Host name or IP address.
* @param[in] port is the Server Port.
* @param[in] ca_crt is the Server's CA certification.
* @param[in] ca_crt_len is the length of Server's CA certification.
* @param[in] client_crt is the client certification.
* @param[in] client_crt_len is the length of client certification.
* @param[in] client_key is the client key.
* @param[in] client_key_len is the length of client key.
* @param[in] client_pwd is the password of client key.
* @param[in] client_pwd_len is the length of client key's password.
* @sa #NewNetwork();
* @return If the return value is 0, the connection is created successfully. If
* the return value is -1, then calling lwIP #socket() has failed. If the return
* value is -2, then calling lwIP #connect() has failed. Any other value
* indicates that calling lwIP #getaddrinfo() has failed.
*/
static int _TLSConnectNetwork(TLSDataParams_t *pTlsData, const char *addr,
const char *port, const char *ca_crt,
size_t ca_crt_len, const char *client_crt,
size_t client_crt_len, const char *client_key,
size_t client_key_len, const char *client_pwd,
size_t client_pwd_len)
{
int ret = -1;
/*
* 0. Init
*/
if (0 != (ret = _ssl_client_init(
&(pTlsData->ssl), &(pTlsData->fd), &(pTlsData->conf),
&(pTlsData->cacertl), ca_crt, ca_crt_len, &(pTlsData->clicert),
client_crt, client_crt_len, &(pTlsData->pkey), client_key,
client_key_len, client_pwd, client_pwd_len))) {
platform_err(" failed ! ssl_client_init returned -0x%04x", -ret);
return ret;
}
/*
* 1. Start the connection
*/
platform_info("Connecting to /%s/%s...", addr, port);
#if !defined(CSP_LINUXHOST) && !defined(BOARD_ESP8266)
if (0 != (ret = mbedtls_net_connect_timeout(&(pTlsData->fd), addr, port,
MBEDTLS_NET_PROTO_TCP,
SEND_TIMEOUT_SECONDS))) {
platform_err(" failed ! net_connect returned -0x%04x", -ret);
return ret;
}
#else
if (0 != (ret = mbedtls_net_connect(&(pTlsData->fd), addr, port,
MBEDTLS_NET_PROTO_TCP))) {
platform_err(" failed ! net_connect returned -0x%04x", -ret);
return ret;
}
#endif
platform_info(" ok");
/*
* 2. Setup stuff
*/
platform_info(" . Setting up the SSL/TLS structure...");
if ((ret = mbedtls_ssl_config_defaults(
&(pTlsData->conf), MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
platform_err(" failed! mbedtls_ssl_config_defaults returned %d", ret);
return ret;
}
mbedtls_ssl_conf_max_version(&pTlsData->conf, MBEDTLS_SSL_MAJOR_VERSION_3,
MBEDTLS_SSL_MINOR_VERSION_3);
mbedtls_ssl_conf_min_version(&pTlsData->conf, MBEDTLS_SSL_MAJOR_VERSION_3,
MBEDTLS_SSL_MINOR_VERSION_3);
platform_info(" ok");
/* OPTIONAL is not optimal for security, but makes interop easier in this
* simplified example */
if (ca_crt != NULL) {
#if defined(FORCE_SSL_VERIFY)
mbedtls_ssl_conf_authmode(&(pTlsData->conf),
MBEDTLS_SSL_VERIFY_REQUIRED);
#else
mbedtls_ssl_conf_authmode(&(pTlsData->conf),
MBEDTLS_SSL_VERIFY_OPTIONAL);
#endif
} else {
mbedtls_ssl_conf_authmode(&(pTlsData->conf), MBEDTLS_SSL_VERIFY_NONE);
}
#if (TLS_AUTH_MODE == TLS_AUTH_MODE_CA)
mbedtls_ssl_conf_ca_chain(&(pTlsData->conf), &(pTlsData->cacertl), NULL);
if ((ret = mbedtls_ssl_conf_own_cert(
&(pTlsData->conf), &(pTlsData->clicert), &(pTlsData->pkey))) != 0) {
platform_err(" failed\n ! mbedtls_ssl_conf_own_cert returned %d\n",
ret);
return ret;
}
#elif (TLS_AUTH_MODE == TLS_AUTH_MODE_PSK)
{
static const int ciphersuites[] = {MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA,
MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA,
MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA,
MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA,
MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA};
char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
char device_secret[IOTX_DEVICE_SECRET_LEN + 1] = {0};
char *auth_type = "devicename";
char *sign_method = "hmacsha256";
char *timestamp = "2524608000000";
char *psk_identity = NULL, string_to_sign[IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 33] = {0};
uint32_t psk_identity_len = 0;
//uint8_t sign_hex[32] = {0};
char sign_string[65] = {0};
int i = 0;
HAL_GetProductKey(product_key);
HAL_GetDeviceName(device_name);
HAL_GetDeviceSecret(device_secret);
/* psk identity length */
psk_identity_len = strlen(auth_type) + strlen(sign_method) + strlen(product_key) + strlen(device_name) + strlen(
timestamp) + 5;
psk_identity = HAL_Malloc(psk_identity_len);
if (psk_identity == NULL) {
printf("psk_identity malloc failed\n");
return -1;
}
memset(psk_identity, 0, psk_identity_len);
memcpy(psk_identity, auth_type, strlen(auth_type));
memcpy(psk_identity + strlen(psk_identity), "|", strlen("|"));
memcpy(psk_identity + strlen(psk_identity), sign_method, strlen(sign_method));
memcpy(psk_identity + strlen(psk_identity), "|", strlen("|"));
memcpy(psk_identity + strlen(psk_identity), product_key, strlen(product_key));
memcpy(psk_identity + strlen(psk_identity), "&", strlen("&"));
memcpy(psk_identity + strlen(psk_identity), device_name, strlen(device_name));
memcpy(psk_identity + strlen(psk_identity), "|", strlen("|"));
memcpy(psk_identity + strlen(psk_identity), timestamp, strlen(timestamp));
/* string to sign */
memcpy(string_to_sign, "id", strlen("id"));
memcpy(string_to_sign + strlen(string_to_sign), product_key, strlen(product_key));
memcpy(string_to_sign + strlen(string_to_sign), "&", strlen("&"));
memcpy(string_to_sign + strlen(string_to_sign), device_name, strlen(device_name));
memcpy(string_to_sign + strlen(string_to_sign), "timestamp", strlen("timestamp"));
memcpy(string_to_sign + strlen(string_to_sign), timestamp, strlen(timestamp));
utils_hmac_sha256(string_to_sign, strlen(string_to_sign), sign_string, device_secret, strlen(device_secret));
for (i = 0; i < strlen(sign_string); i++) {
if (sign_string[i] >= 'a' && sign_string[i] <= 'z') {
sign_string[i] -= 'a' - 'A';
}
}
printf("psk_identity: %s\n",psk_identity);
/*
printf("psk : %s\n",sign_string);
*/
mbedtls_ssl_conf_psk(&(pTlsData->conf), (const unsigned char *)sign_string, strlen(sign_string),
(uint8_t *)psk_identity, strlen(psk_identity));
mbedtls_ssl_conf_ciphersuites(&(pTlsData->conf), ciphersuites);
HAL_Free(psk_identity);
printf("mbedtls psk config finished\n");
}
#endif /* #elif (TLS_AUTH_MODE == TLS_AUTH_MODE_PSK) */
mbedtls_ssl_conf_rng(&(pTlsData->conf), _ssl_random, NULL);
mbedtls_ssl_conf_dbg(&(pTlsData->conf), _ssl_debug, NULL);
/* mbedtls_ssl_conf_dbg( &(pTlsData->conf), _ssl_debug, stdout ); */
if ((ret = mbedtls_ssl_setup(&(pTlsData->ssl), &(pTlsData->conf))) != 0) {
platform_err("failed! mbedtls_ssl_setup returned %d", ret);
return ret;
}
if (GUIDER_ENV_DAILY == iotx_guider_get_env() || GUIDER_ENV_PRERELEASE == iotx_guider_get_env())
{
platform_err("env prerelease or daily not set ssl hostname");
}
else
{
#if defined(_PLATFORM_IS_LINUX_)
/* only set hostname when addr isn't ip string and hostname isn't preauth_shanghai */
if (inet_aton(addr, &in) == 0 && strcmp("iot-auth-pre.cn-shanghai.aliyuncs.com", addr)) {
mbedtls_ssl_set_hostname(&(pTlsData->ssl), addr);
}
#else
if (strcmp("iot-auth-pre.cn-shanghai.aliyuncs.com", addr)) {
mbedtls_ssl_set_hostname(&(pTlsData->ssl), addr);
}
#endif /* #if defined(_PLATFORM_IS_LINUX_) */
}
mbedtls_ssl_set_bio(&(pTlsData->ssl), &(pTlsData->fd), mbedtls_net_send,
mbedtls_net_recv, mbedtls_net_recv_timeout);
#if defined(TLS_SAVE_TICKET)
if (NULL == saved_session) {
do {
int len = TLS_MAX_SESSION_BUF;
unsigned char *save_buf = HAL_Malloc(TLS_MAX_SESSION_BUF);
char key_buf[KEY_MAX_LEN] = {0};
if (save_buf == NULL) {
platform_err(" malloc failed");
break;
}
saved_session = HAL_Malloc(sizeof(mbedtls_ssl_session));
if (saved_session == NULL) {
platform_err(" malloc failed");
HAL_Free(save_buf);
save_buf = NULL;
break;
}
memset(save_buf, 0x00, TLS_MAX_SESSION_BUF);
memset(saved_session, 0x00, sizeof(mbedtls_ssl_session));
HAL_Snprintf(key_buf,KEY_MAX_LEN -1, KV_SESSION_KEY_FMT, KV_SESSION_KEY_PREFIX, addr, port);
ret = HAL_Kv_Get(key_buf, save_buf, &len);
if (ret != 0 || len == 0) {
platform_info("get kv ticket ret=%d", ret);
HAL_Free(saved_session);
HAL_Free(save_buf);
save_buf = NULL;
saved_session = NULL;
break;
}
ret = ssl_deserialize_session(saved_session, save_buf, len);
if (ret < 0) {
platform_err("ssl_deserialize_session err,ret = %d", ret);
HAL_Free(saved_session);
HAL_Free(save_buf);
save_buf = NULL;
saved_session = NULL;
break;
}
HAL_Free(save_buf);
} while (0);
}
if (NULL != saved_session) {
mbedtls_ssl_set_session(&(pTlsData->ssl), saved_session);
platform_info("use saved session!!");
}
#endif
/*
* 4. Handshake
*/
platform_info("Performing the SSL/TLS handshake...");
mbedtls_ssl_conf_read_timeout(&(pTlsData->conf), 10000);
while ((ret = mbedtls_ssl_handshake(&(pTlsData->ssl))) != 0) {
if ((ret != MBEDTLS_ERR_SSL_WANT_READ) &&
(ret != MBEDTLS_ERR_SSL_WANT_WRITE)) {
platform_err("failed ! mbedtls_ssl_handshake returned -0x%04x",
-ret);
#if defined(TLS_SAVE_TICKET)
if (saved_session != NULL) {
mbedtls_ssl_session_free(saved_session);
HAL_Free(saved_session);
saved_session = NULL;
}
#endif
return ret;
}
}
platform_info(" ok");
#if defined(TLS_SAVE_TICKET)
do {
size_t real_session_len = 0;
mbedtls_ssl_session *new_session = NULL;
new_session = HAL_Malloc(sizeof(mbedtls_ssl_session));
if (NULL == new_session) {
break;
}
memset(new_session, 0x00, sizeof(mbedtls_ssl_session));
ret = mbedtls_ssl_get_session(&(pTlsData->ssl), new_session);
if (ret != 0) {
HAL_Free(new_session);
break;
}
if (saved_session == NULL) {
ret = 1;
} else if (new_session->ticket_len != saved_session->ticket_len) {
ret = 1;
} else {
ret = memcmp(new_session->ticket, saved_session->ticket, new_session->ticket_len);
}
if ((ret != 0) && (new_session->ticket_len > 0)) {
unsigned char *save_buf = HAL_Malloc(TLS_MAX_SESSION_BUF);
if (save_buf == NULL) {
mbedtls_ssl_session_free(new_session);
HAL_Free(new_session);
new_session = NULL;
break;
}
memset(save_buf, 0x00, sizeof(TLS_MAX_SESSION_BUF));
ret = ssl_serialize_session(new_session, save_buf, TLS_MAX_SESSION_BUF, &real_session_len);
platform_info("mbedtls_ssl_get_session_session return 0x%04x real_len=%d", ret, (int)real_session_len);
if (ret == 0) {
char key_buf[KEY_MAX_LEN] = {0};
HAL_Snprintf(key_buf,KEY_MAX_LEN -1, KV_SESSION_KEY_FMT, KV_SESSION_KEY_PREFIX, addr, port);
ret = HAL_Kv_Set(key_buf, (void *)save_buf, real_session_len, 1);
if (ret < 0) {
platform_info("save ticket to kv failed ret =%d ,len = %d", ret, (int)real_session_len);
}
}
HAL_Free(save_buf);
}
mbedtls_ssl_session_free(new_session);
HAL_Free(new_session);
} while (0);
if (saved_session != NULL) {
mbedtls_ssl_session_free(saved_session);
HAL_Free(saved_session);
saved_session = NULL;
}
#endif
/*
* 5. Verify the server certificate
*/
platform_info(" . Verifying peer X.509 certificate..");
if (0 != (ret = _real_confirm(
mbedtls_ssl_get_verify_result(&(pTlsData->ssl))))) {
platform_err(" failed ! verify result not confirmed.");
return ret;
}
/* n->my_socket = (int)((n->tlsdataparams.fd).fd); */
/* WRITE_IOT_DEBUG_LOG("my_socket=%d", n->my_socket); */
return 0;
}
static int _network_ssl_read(TLSDataParams_t *pTlsData, char *buffer, int len,
int timeout_ms)
{
uint32_t readLen = 0;
static int net_status = 0;
int ret = -1;
uint32_t cur_time = HAL_UptimeMs();
uint32_t expire_time = cur_time + timeout_ms;
mbedtls_ssl_conf_read_timeout(&(pTlsData->conf), timeout_ms);
while (readLen < len) {
ret = mbedtls_ssl_read(&(pTlsData->ssl),
(unsigned char *)(buffer + readLen),
(len - readLen));
if (ret > 0) {
readLen += ret;
net_status = 0;
} else if (ret == 0) {
/* if ret is 0 and net_status is -2, indicate the connection is
* closed during last call */
return (net_status == -2) ? net_status : readLen;
} else {
if (MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY == ret) {
// mbedtls_strerror(ret, err_str, sizeof(err_str));
platform_err("ssl recv error: code = %d", ret);
net_status = -2; /* connection is closed */
break;
}
#ifdef CSP_LINUXHOST
else if (MBEDTLS_ERR_SSL_WANT_READ == ret && errno == EINTR) {
cur_time = HAL_UptimeMs();
if((cur_time- expire_time) < (UINT32_MAX / 2)){
return readLen;
}
HAL_SleepMs(10);
continue;
}
#endif
else if ((MBEDTLS_ERR_SSL_TIMEOUT == ret) ||
(MBEDTLS_ERR_SSL_CONN_EOF == ret) ||
(MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED == ret) ||
(MBEDTLS_ERR_SSL_WANT_READ == ret) ||
(MBEDTLS_ERR_SSL_NON_FATAL == ret)) {
/* read already complete */
/* if call mbedtls_ssl_read again, it will return 0 (means EOF)
*/
return readLen;
} else {
platform_err("ssl recv error: code = %d", ret);
net_status = -1;
return -1; /* Connection error */
}
}
}
return (readLen >= 0) ? readLen : net_status;
}
static int _network_ssl_write(TLSDataParams_t *pTlsData, const char *buffer,
int len, int timeout_ms)
{
uint32_t writtenLen = 0;
int ret = -1;
while (writtenLen < len) {
ret = mbedtls_ssl_write(&(pTlsData->ssl),
(unsigned char *)(buffer + writtenLen),
(len - writtenLen));
if (ret > 0) {
writtenLen += ret;
continue;
} else if (ret == 0) {
platform_err("ssl write timeout");
return 0;
} else {
// mbedtls_strerror(ret, err_str, sizeof(err_str));
platform_err("ssl write fail, code=%d", ret);
return -1; /* Connnection error */
}
}
return writtenLen;
}
static void _network_ssl_disconnect(TLSDataParams_t *pTlsData)
{
mbedtls_ssl_close_notify(&(pTlsData->ssl));
mbedtls_net_free(&(pTlsData->fd));
#if (TLS_AUTH_MODE == TLS_AUTH_MODE_CA)
mbedtls_x509_crt_free(&(pTlsData->cacertl));
if ((pTlsData->pkey).pk_info != NULL) {
platform_info("need release client crt&key");
#if defined(MBEDTLS_CERTS_C)
mbedtls_x509_crt_free(&(pTlsData->clicert));
mbedtls_pk_free(&(pTlsData->pkey));
#endif
}
#endif /* #if (TLS_AUTH_MODE == TLS_AUTH_MODE_CA) */
mbedtls_ssl_free(&(pTlsData->ssl));
mbedtls_ssl_config_free(&(pTlsData->conf));
platform_info("ssl_disconnect");
}
int32_t HAL_SSL_Read(uintptr_t handle, char *buf, int len, int timeout_ms)
{
return _network_ssl_read((TLSDataParams_t *)handle, buf, len, timeout_ms);
;
}
int32_t HAL_SSL_Write(uintptr_t handle, const char *buf, int len,
int timeout_ms)
{
return _network_ssl_write((TLSDataParams_t *)handle, buf, len, timeout_ms);
}
int32_t HAL_SSL_Destroy(uintptr_t handle)
{
if ((uintptr_t)NULL == handle) {
platform_err("handle is NULL");
return 0;
}
_network_ssl_disconnect((TLSDataParams_t *)handle);
HAL_Free((void *)handle);
return 0;
}
int HAL_SSLHooks_set(ssl_hooks_t *hooks)
{
if (hooks == NULL || hooks->malloc == NULL || hooks->free == NULL) {
return DTLS_INVALID_PARAM;
}
g_ssl_hooks.malloc = hooks->malloc;
g_ssl_hooks.free = hooks->free;
return DTLS_SUCCESS;
}
uintptr_t HAL_SSL_Establish(const char *host, uint16_t port, const char *ca_crt,
size_t ca_crt_len)
{
char port_str[6];
TLSDataParams_pt pTlsData;
pTlsData = HAL_Malloc(sizeof(TLSDataParams_t));
if (NULL == pTlsData) {
return (uintptr_t)NULL;
}
memset(pTlsData, 0x0, sizeof(TLSDataParams_t));
sprintf(port_str, "%u", port);
if (0 != _TLSConnectNetwork(pTlsData, host, port_str, ca_crt, ca_crt_len,
NULL, 0, NULL, 0, NULL, 0)) {
_network_ssl_disconnect(pTlsData);
HAL_Free((void *)pTlsData);
return (uintptr_t)NULL;
}
return (uintptr_t)pTlsData;
}

View file

@ -0,0 +1,378 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <aos/errno.h>
#include <aos/log.h>
#include <aos/aos.h>
#include "aos/network.h"
#include "iot_import.h"
#define TRANSPORT_ADDR_LEN 16
#ifndef IP_PKTINFO
#define IP_PKTINFO IP_MULTICAST_IF
#endif
#ifndef IPV6_PKTINFO
#define IPV6_PKTINFO IPV6_V6ONL
#endif
#define NETWORK_ADDR_LEN (16)
#define LOG_TAG "HAL_TL"
#define platform_info(format, ...) LOGI(LOG_TAG, format, ##__VA_ARGS__)
#define platform_err(format, ...) LOGE(LOG_TAG, format, ##__VA_ARGS__)
/**
* @brief Create a UDP socket.
*
* @param [in] port: @n Specify the UDP port of UDP socket
*
* @retval < 0 : Fail.
* @retval >= 0 : Success, the value is handle of this UDP socket.
* @see None.
*/
intptr_t HAL_UDP_create(char *host, unsigned short port)
{
int rc = -1;
long socket_id = -1;
char port_ptr[6] = {0};
struct addrinfo hints;
char addr[NETWORK_ADDR_LEN] = {0};
struct addrinfo *res, *ainfo;
struct sockaddr_in *sa = NULL;
if (NULL == host) {
return (-1);
}
sprintf(port_ptr, "%u", port);
memset((char *)&hints, 0x00, sizeof(hints));
hints.ai_socktype = SOCK_DGRAM;
hints.ai_family = AF_INET;
hints.ai_protocol = IPPROTO_UDP;
rc = getaddrinfo(host, port_ptr, &hints, &res);
if (0 != rc) {
printf("getaddrinfo error");
return (-1);
}
for (ainfo = res; ainfo != NULL; ainfo = ainfo->ai_next) {
if (AF_INET == ainfo->ai_family) {
sa = (struct sockaddr_in *)ainfo->ai_addr;
inet_ntop(AF_INET, &sa->sin_addr, addr, NETWORK_ADDR_LEN);
printf("The host IP %s, port is %d\r\n", addr, ntohs(sa->sin_port));
socket_id = socket(ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol);
if (socket_id < 0) {
printf("create socket error");
continue;
}
if (0 == connect(socket_id, ainfo->ai_addr, ainfo->ai_addrlen)) {
break;
}
close(socket_id);
}
}
freeaddrinfo(res);
return socket_id;
}
intptr_t HAL_UDP_create_without_connect(const char *host, unsigned short port)
{
int flag = 1;
int ret = -1;
int socket_id = -1;
struct sockaddr_in local_addr; /*local addr*/
if ((socket_id = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
platform_err("socket create failed\r\n");
return (intptr_t) - 1;
}
ret = setsockopt(socket_id, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));
if (ret < 0) {
close(socket_id);
platform_err("setsockopt SO_REUSEADDR failed");
return (intptr_t) - 1;
}
flag = 1;
#ifdef IP_RECVPKTINFO
if ((ret = setsockopt(socket_id, IPPROTO_IP, IP_RECVPKTINFO, &flag,
sizeof(flag))) < 0)
#else /* IP_RECVPKTINFO */
if ((ret = setsockopt(socket_id, IPPROTO_IP, IP_PKTINFO, &flag,
sizeof(flag))) < 0)
#endif /* IP_RECVPKTINFO */
if (ret < 0) {
close(socket_id);
platform_err("setsockopt IP_PKTINFO failed\r\n");
return (intptr_t) - 1;
}
memset(&local_addr, 0x00, sizeof(local_addr));
local_addr.sin_family = AF_INET;
if (NULL != host) {
inet_aton(host, &local_addr.sin_addr);
} else {
local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
}
local_addr.sin_port = htons(port);
ret = bind(socket_id, (struct sockaddr *)&local_addr, sizeof(local_addr));
// fprintf(stderr,"\r\n[%s LINE #%d] Create socket port %d fd %d ret
// %d\r\n",
// __FILE__, __LINE__, port, socket_id, ret);
return (intptr_t)socket_id;
}
int HAL_UDP_close_without_connect(_IN_ intptr_t sockfd)
{
return close((int)sockfd);
}
int HAL_UDP_recvfrom(intptr_t sockfd, NetworkAddr *p_remote,
unsigned char *p_data, unsigned int datalen,
unsigned int timeout_ms)
{
int socket_id = -1;
struct sockaddr from;
int count = -1, ret = -1;
socklen_t addrlen = 0;
struct timeval tv;
fd_set read_fds;
if (NULL == p_remote || NULL == p_data) {
return -1;
}
socket_id = (int)sockfd;
FD_ZERO(&read_fds);
FD_SET(socket_id, &read_fds);
tv.tv_sec = timeout_ms / 1000;
tv.tv_usec = (timeout_ms % 1000) * 1000;
ret = select(socket_id + 1, &read_fds, NULL, NULL,
timeout_ms == 0 ? NULL : &tv);
/* Zero fds ready means we timed out */
if (ret == 0) {
return -2; /* receive timeout */
}
if (ret < 0) {
if (errno == EINTR) {
return -3; /* want read */
}
return -4; /* receive failed */
}
addrlen = sizeof(struct sockaddr);
count = recvfrom(socket_id, p_data, (size_t)datalen, 0, &from, &addrlen);
if (-1 == count) {
return -1;
}
if (from.sa_family == AF_INET) {
struct sockaddr_in *sin = (struct sockaddr_in *)&from;
inet_ntop(AF_INET, &sin->sin_addr, (char *)p_remote->addr,
NETWORK_ADDR_LEN);
p_remote->port = ntohs(sin->sin_port);
}
return count;
}
int HAL_UDP_recv(intptr_t sockfd, unsigned char *p_data, unsigned int datalen,
unsigned int timeout_ms)
{
return 0;
}
int HAL_UDP_sendto(intptr_t sockfd, const NetworkAddr *p_remote,
const unsigned char *p_data, unsigned int datalen,
unsigned int timeout_ms)
{
int rc = -1;
int socket_id = -1;
struct sockaddr_in remote_addr;
if (NULL == p_remote || NULL == p_data) {
return -1;
}
socket_id = (int)sockfd;
remote_addr.sin_family = AF_INET;
if (1 !=
(rc = inet_pton(remote_addr.sin_family, (const char *)p_remote->addr,
&remote_addr.sin_addr.s_addr))) {
return -1;
}
remote_addr.sin_port = htons(p_remote->port);
rc = sendto(socket_id, p_data, (size_t)datalen, 0,
(const struct sockaddr *)&remote_addr, sizeof(remote_addr));
if (-1 == rc) {
return -1;
}
return rc;
}
int HAL_UDP_send(_IN_ intptr_t sockfd, _IN_ const unsigned char *p_data,
_IN_ unsigned int datalen, _IN_ unsigned int timeout_ms)
{
int ret;
fd_set write_fds;
struct timeval timeout = { timeout_ms / 1000, (timeout_ms % 1000) * 1000 };
FD_ZERO(&write_fds);
FD_SET(sockfd, &write_fds);
ret = select(sockfd + 1, NULL, &write_fds, NULL, &timeout);
if (ret == 0) {
return 0; /* write timeout */
}
if (ret < 0) {
if (errno == EINTR) {
return -3; /* want write */
}
return -4; /* write failed */
}
ret = send(sockfd, (char *)p_data, (int)datalen, 0);
if (ret < 0) {
platform_err("send");
}
return ret;
}
int HAL_UDP_read(intptr_t p_socket, unsigned char *p_data, unsigned int datalen)
{
long socket_id = -1;
int count = -1;
if (NULL == p_data || p_socket < 0) {
return -1;
}
socket_id = (long)p_socket;
count = (int)read(socket_id, p_data, datalen);
return count;
}
int HAL_UDP_joinmulticast(intptr_t sockfd, char *p_group)
{
int err = -1;
int socket_id = -1;
if (NULL == p_group) {
return -1;
}
/*set loopback*/
int loop = 1;
socket_id = (int)sockfd;
err =
setsockopt(socket_id, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop));
if (err < 0) {
fprintf(stderr, "setsockopt():IP_MULTICAST_LOOP failed\r\n");
return err;
}
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr(p_group);
mreq.imr_interface.s_addr = htonl(INADDR_ANY); /*default networt interface*/
/*join to the mutilcast group*/
err =
setsockopt(socket_id, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
if (err < 0) {
fprintf(stderr, "setsockopt():IP_ADD_MEMBERSHIP failed\r\n");
return err;
}
return 0;
}
void HAL_UDP_close(_IN_ intptr_t sockfd)
{
long socket_id = -1;
socket_id = (int)sockfd;
close(socket_id);
}
int HAL_UDP_write(intptr_t p_socket, const unsigned char *p_data,
unsigned int datalen)
{
int rc = -1;
long socket_id = -1;
socket_id = (long)p_socket;
rc = send(socket_id, (char *)p_data, (int)datalen, 0);
if (-1 == rc) {
return -1;
}
return rc;
}
int HAL_UDP_readTimeout(intptr_t p_socket, unsigned char *p_data,
unsigned int datalen, unsigned int timeout)
{
int ret;
struct timeval tv;
fd_set read_fds;
long socket_id = -1;
if (NULL == p_data) {
return -1;
}
socket_id = (long)p_socket;
if (socket_id < 0) {
return -1;
}
FD_ZERO(&read_fds);
FD_SET(socket_id, &read_fds);
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
ret =
select(socket_id + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv);
/* Zero fds ready means we timed out */
if (ret == 0) {
return -2; /* receive timeout */
}
if (ret < 0) {
if (errno == EINTR) {
return -3; /* want read */
}
return -4; /* receive failed */
}
/* This call will not block */
return HAL_UDP_read(p_socket, p_data, datalen);
}

View file

@ -0,0 +1,34 @@
NAME := iotx-hal
$(NAME)_MBINS_TYPE := kernel
$(NAME)_VERSION := 2.3.0
$(NAME)_SUMMARY :=
$(NAME)_SOURCES := HAL_OS_rhino.c \
HAL_TCP_rhino.c \
HAL_PRODUCT_rhino.c \
HAL_UDP_rhino.c \
HAL_Crypt_rhino.c \
HAL_AWSS_rhino.c
$(NAME)_COMPONENTS += \
digest_algorithm \
utility/log \
activation \
chip_code \
framework/netmgr
ifneq (,$(filter ywss4linkkit,$(COMPONENTS)))
$(NAME)_SOURCES += HAL_AWSS_rhino.c
endif
ifeq (y,$(strip $(FEATURE_SUPPORT_ITLS)))
$(info FEATURE_SUPPORT_ITLS = y, so using iTLS)
$(NAME)_SOURCES += HAL_TLS_itls.c
$(NAME)_COMPONENTS += security/itls
else
$(info FEATURE_SUPPORT_ITLS != y, so using normal TLS)
$(NAME)_SOURCES += HAL_TLS_mbedtls.c HAL_DTLS_mbedtls.c
$(NAME)_COMPONENTS += security/imbedtls
$(NAME)_DEFINES += TLS_SAVE_TICKET
endif

View file

@ -0,0 +1,58 @@
src =Split('''
HAL_OS_rhino.c
HAL_TCP_rhino.c
HAL_PRODUCT_rhino.c
HAL_UDP_rhino.c
HAL_Crypt_rhino.c
HAL_TLS_mbedtls.c
HAL_DTLS_mbedtls.c
HAL_AWSS_rhino.c
''')
# HAL_TLS_mbedtls.c
# HAL_DTLS_mbedtls.c
component =aos_component('iotx-hal', src)
dependencis =Split('''
security/mbedtls
utility/digest_algorithm
''')
for i in dependencis:
component.add_comp_deps(i)
global_includes =Split('''
''')
for i in global_includes:
component.add_global_includes(i)
global_macros =Split('''
COAP_DTLS_SUPPORT
''')
for i in global_macros:
component.add_global_macros(i)
includes =Split('''
''')
for i in includes:
component.add_includes(i)
cflags =Split('''
''')
for i in cflags:
component.add_cflags(i)
component.add_global_macros('')
@post_config
def alink_ilop_post_config(component):
comp_names = [comp.name for comp in aos_global_config.components]
if 'ywss4linkkit' in comp_names:
component.add_sources('HAL_AWSS_rhino.c')
alink_ilop_post_config(component)

View file

@ -0,0 +1,41 @@
aos_board_conf.mk
*.so
*.exe
.settings/
*.cproject
*.project
*.o
*.d
*.lo
*.gcno
*.gcda
/INSTALL
cscope.*
*.swp
*.swo
ltmain.sh
*.kv
*.bak
/Default/
.O/
.config
output/
ota.bin
src/packages/*.git/hooks/*.sample
vs_build/
.vs/
doc/html/
compile.log
CMakeLists.txt.user
qt_build/
.vscode/
GPATH
GRTAGS
GTAGS
iotx-sdk-c-test/
sdk-c/examples/coapapp
sdk-c/examples/linkkit_gateway
sdk-c/examples/linkkit_newapi
sdk-c/examples/linkkitapp
sdk-c/examples/mqttapp

View file

@ -0,0 +1,103 @@
if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
MESSAGE (FATAL_ERROR "in-tree build not allowded")
endif(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
CMAKE_MINIMUM_REQUIRED (VERSION 2.8)
PROJECT (iotkit-embedded-V2.3.0 C)
SET (EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
SET (LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
SET (CMAKE_C_FLAGS " -Iexamples -Iexamples/linkkit -Itests -Os -Wall -fPIC")
IF (WIN32)
SET (CMAKE_EXE_LINKER_FLAGS "-L${PROJECT_SOURCE_DIR}/prebuilt/win7/libs")
ENDIF (WIN32)
MESSAGE ("---------------------------------------------------------------------")
MESSAGE ("Project Name : " ${PROJECT_NAME})
MESSAGE ("Source Dir : " ${PROJECT_SOURCE_DIR})
MESSAGE ("Binary Dir : " ${PROJECT_BINARY_DIR})
MESSAGE ("System Processor : " ${CMAKE_SYSTEM_PROCESSOR})
MESSAGE ("System Platform : " ${CMAKE_SYSTEM})
MESSAGE ("C Compiler : " ${CMAKE_C_COMPILER})
MESSAGE ("Executable Dir : " ${EXECUTABLE_OUTPUT_PATH})
MESSAGE ("Library Dir : " ${LIBRARY_OUTPUT_PATH})
MESSAGE ("SDK Version : " V2.3.0)
MESSAGE ("")
IF (WIN32)
MESSAGE ("Building on WINDOWS ...")
ELSE (WIN32)
MESSAGE ("Building on LINUX ...")
ENDIF (WIN32)
MESSAGE ("---------------------------------------------------------------------")
ADD_DEFINITIONS (-DDLL_IOT_EXPORTS)
ADD_DEFINITIONS (-DAWSS_DISABLE_ENROLLEE)
ADD_DEFINITIONS (-DAWSS_DISABLE_REGISTRAR)
ADD_DEFINITIONS (-DAWSS_SUPPORT_ADHA)
ADD_DEFINITIONS (-DAWSS_SUPPORT_AHA)
ADD_DEFINITIONS (-DAWSS_SUPPORT_APLIST)
ADD_DEFINITIONS (-DAWSS_SUPPORT_PHONEASAP)
ADD_DEFINITIONS (-DAWSS_SUPPORT_ROUTER)
ADD_DEFINITIONS (-DAWSS_SUPPORT_SMARTCONFIG)
ADD_DEFINITIONS (-DAWSS_SUPPORT_SMARTCONFIG_WPS)
ADD_DEFINITIONS (-DAWSS_SUPPORT_ZEROCONFIG)
ADD_DEFINITIONS (-DCOAP_SERV_MULTITHREAD)
ADD_DEFINITIONS (-DCONFIG_HTTP_AUTH_TIMEOUT=5000)
ADD_DEFINITIONS (-DCONFIG_MID_HTTP_TIMEOUT=5000)
ADD_DEFINITIONS (-DCONFIG_GUIDER_AUTH_TIMEOUT=10000)
ADD_DEFINITIONS (-DDEVICE_MODEL_ENABLED)
ADD_DEFINITIONS (-DDEV_BIND_ENABLED)
ADD_DEFINITIONS (-DFORCE_SSL_VERIFY)
ADD_DEFINITIONS (-DMQTT_COMM_ENABLED)
ADD_DEFINITIONS (-DMQTT_DIRECT)
ADD_DEFINITIONS (-DOTA_ENABLED)
ADD_DEFINITIONS (-DOTA_SIGNAL_CHANNEL=1)
ADD_DEFINITIONS (-DSUPPORT_TLS)
ADD_DEFINITIONS (-DWIFI_PROVISION_ENABLED)
ADD_DEFINITIONS (-D_PLATFORM_IS_HOST_)
ADD_SUBDIRECTORY (components/timer_service)
ADD_SUBDIRECTORY (src/infra/utils)
ADD_SUBDIRECTORY (src/infra/log)
ADD_SUBDIRECTORY (src/infra/system)
ADD_SUBDIRECTORY (src/sdk-impl)
ADD_SUBDIRECTORY (src/protocol/mqtt)
ADD_SUBDIRECTORY (src/services/ota)
ADD_SUBDIRECTORY (src/services/linkkit/cm)
ADD_SUBDIRECTORY (src/services/linkkit/dm)
ADD_SUBDIRECTORY (src/services/linkkit/dev_reset)
ADD_SUBDIRECTORY (src/protocol/coap/local)
ADD_SUBDIRECTORY (src/services/awss)
ADD_SUBDIRECTORY (src/services/dev_diagnosis)
ADD_SUBDIRECTORY (src/services/dev_bind)
ADD_SUBDIRECTORY (src/ref-impl/hal)
ADD_SUBDIRECTORY (examples)
ADD_SUBDIRECTORY (src/ref-impl/tls)
ADD_LIBRARY (iot_sdk SHARED
$<TARGET_OBJECTS:iot_timer_service>
$<TARGET_OBJECTS:iot_utils>
$<TARGET_OBJECTS:iot_log>
$<TARGET_OBJECTS:iot_system>
$<TARGET_OBJECTS:sdk_impl>
$<TARGET_OBJECTS:iot_mqtt>
$<TARGET_OBJECTS:iot_ota>
$<TARGET_OBJECTS:iot_cm>
$<TARGET_OBJECTS:iot_dm>
$<TARGET_OBJECTS:iot_reset>
$<TARGET_OBJECTS:iot_coap_local>
$<TARGET_OBJECTS:iot_awss>
$<TARGET_OBJECTS:iot_dev_diagnosis>
$<TARGET_OBJECTS:iot_bind>
)
if(WIN32)
TARGET_LINK_LIBRARIES (iot_sdk ws2_32)
endif(WIN32)
TARGET_LINK_LIBRARIES (iot_sdk iot_hal)
SET (LIBRARY_OUTPUT_PATH ./out)

View file

@ -0,0 +1,8 @@
mainmenu "Main Menu"
comment "Configure Link Kit SDK for IoT Embedded Devices"
config SRCPATH
string
default "."
source "Config.linkkit"

View file

@ -0,0 +1,9 @@
source "$SRCPATH/src/protocol/mqtt/Config.in"
source "$SRCPATH/src/services/linkkit/Config.in"
source "$SRCPATH/src/protocol/coap/Config.in"
source "$SRCPATH/src/services/ota/Config.in"
source "$SRCPATH/src/protocol/http2/Config.in"
source "$SRCPATH/src/protocol/http/Config.in"
source "$SRCPATH/src/sdk-impl/Config.in"
source "$SRCPATH/src/services/mdal/Config.in"
source "$SRCPATH/src/services/awss/Config.in"

View file

@ -0,0 +1,14 @@
Copyright (c) 2014-2016 Alibaba Group. All rights reserved.
License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License"); you may
not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -0,0 +1,18 @@
# Link Kit C-SDK 简介
设备厂商在设备上集成 `Link Kit C-SDK` 后, 可以将设备安全的接入到阿里云IoT物联网平台, 从而让设备可以被阿里云IoT物联网平台进行管理
设备需要支持TCP/IP协议栈才能集成SDK, zigbee/433/KNX这样的非IP设备需要通过网关设备接入到阿里云IoT物联网平台, 网关设备需要集成Link Kit SDK
# 快速开始
用户可以通过[在Ubuntu快速的体验Link Kit SDK](https://help.aliyun.com/document_detail/96624.html)感受如何将设备连接到阿里云物联网平台, 并如何将设备的数据发送到平台/以及如何从物联网平台接收数据
# 移植说明
Link Kit SDK是一个与OS/硬件平台无关的用C编写的代码, 定义了HAL层来对接与硬件相关的功能, 因此在使用Link Kit SDK时用户需要去实现相关的HAL函数
目前Link Kit SDK已实现了在Linux/Windows/AliOS上HAL的实现, 同时对于一些常见的OS或者模组也进行了适配, 可以[访问此处](https://help.aliyun.com/document_detail/97557.html)查看如何在相应平台上进行SDK的编译与集成
# 编程文档
SDK提供了一系列的编程文档来描述如何使用SDK提供的软件功能, 请[访问此处](https://help.aliyun.com/document_detail/96627.html)进行了解

View file

@ -0,0 +1,55 @@
.PHONY: comp-lib
ifdef COMP_LIB
ifeq (dynamic,$(CONFIG_LIB_EXPORT))
define Finalize_CompLib
( \
$(CC) -shared -Os -o $(2)/lib$(3).so $(1) $(LDFLAGS); \
)
endef
define Info_CompLib
( \
EXIST_OBJS="$$(ls $(2) 2>/dev/null)"; \
\
echo -ne "\033[1;32m"; \
printf "\r%-40s%s\n" "[AR] lib$(1).a" "<= "; \
for i in $${EXIST_OBJS}; do \
printf "%-40s%s\n" "" " $${i}"|$(SED) 's,$(LIBOBJ_TMPDIR)/,,g'; \
done; \
echo -ne "\033[0m"; \
)
endef
else
define Finalize_CompLib
( \
EXIST_OBJS="$$(ls $(1) 2>/dev/null)"; \
\
if [ "$${EXIST_OBJS}" != "" ]; then \
$(AR) -rcs $(2)/lib$(3).a $${EXIST_OBJS}; \
fi \
)
endef
define Info_CompLib
( \
EXIST_OBJS="$$(ls $(2) 2>/dev/null)"; \
\
echo -ne "\033[1;35m"; \
printf "\r%-40s%s\n" "[AR] lib$(1).a" "<= "; \
for i in $${EXIST_OBJS}; do \
printf "%-40s%s\n" "" " $${i}"|$(SED) 's,$(LIBOBJ_TMPDIR)/,,g'; \
done; \
echo -ne "\033[0m"; \
)
endef
endif # dynamic
endif # COMP_LIB
comp-lib: toolchain
ifdef COMP_LIB
$(TOP_Q)+( \
if [ -f $(STAMP_PRJ_CFG) ]; then true; else \
$(call Build_CompLib,FORCE) \
fi)
else
$(Q)true
endif

View file

@ -0,0 +1,26 @@
.PHONY: coverage lcov test
ifneq (,$(COVERAGE_LIST))
COVERAGE_PROGS := \(
COVERAGE_PROGS += $(COVERAGE_LIST)
COVERAGE_PROGS += \)
COVERAGE_CMD := $(RULE_DIR)/scripts/exe_coverage_progs.sh
endif
ifeq (,$(COVERAGE_CMD))
coverage lcov test:
@echo "COVERAGE_CMD not defined, skip"
else
coverage lcov test:
#
# SKIP --coverage existence in $(CFLAGS) checking for now
#
$(Q)$(MAKE) --no-print-directory WITH_LCOV=1
$(Q)OUTPUT_DIR=$(OUTPUT_DIR) bash <($(SED) '2iPROGS=$(COVERAGE_PROGS)' $(COVERAGE_CMD)) || true
$(Q)CFLAGS=$(CFLAGS) \
$(foreach V,$(INFO_ENV_VARS),$(V)="$($(V))") \
bash $(RULE_DIR)/scripts/gen_lcov_report.sh
endif

View file

@ -0,0 +1,51 @@
final-out: sub-mods
ifneq (1,$(WITH_LCOV))
ifneq (,$(COMP_LIB_NAME))
$(TOP_Q) \
if [ ! -f $(SYSROOT_LIB)/lib$(COMP_LIB_NAME).a ] && \
[ ! -f $(SYSROOT_LIB)/lib$(COMP_LIB_NAME).so ]; then \
$(call Build_CompLib, FORCE) \
fi;
endif
$(TOP_Q) \
if [ -f $(STAMP_PRJ_CFG) ]; then true; else \
rm -rf $(DIST_DIR); \
mkdir -p $(DIST_DIR) $(FINAL_DIR); \
for i in bin lib include; do \
if [ -d $(OUTPUT_DIR)/usr/$${i} ]; then \
cp -rf $(OUTPUT_DIR)/usr/$${i} $(FINAL_DIR); \
fi; \
done; \
VDR_NAME=$$(grep -m 1 "VENDOR *:" $(CONFIG_TPL) 2>/dev/null|awk '{ print $$NF }'); \
if [ "$$(ls $(IMPORT_DIR)/$${VDR_NAME}/$(PREBUILT_LIBDIR)/lib* 2>/dev/null)" != "" ]; then \
cp -f $(IMPORT_DIR)/$${VDR_NAME}/$(PREBUILT_LIBDIR)/lib* $(FINAL_DIR)/lib; \
fi; \
fi
$(TOP_Q) \
if [ "$$(ls $(FINAL_DIR)/lib/*.a 2>/dev/null)" != "" ]; then \
$(STRIP) $(STRIP_DBGOPT) $(FINAL_DIR)/lib/*.a 2>/dev/null || true; \
fi
$(TOP_Q) \
if [ "$$(ls $(FINAL_DIR)/bin/ 2>/dev/null)" != "" ]; then \
$(STRIP) $(FINAL_DIR)/bin/* 2>/dev/null || true; \
fi
$(TOP_Q) \
if [ "$$(ls $(FINAL_DIR)/lib/*.so 2>/dev/null)" != "" ]; then \
$(STRIP) $(STRIP_DBGOPT) $(FINAL_DIR)/lib/*.so 2>/dev/null || true; \
fi
ifeq ($(strip $(HAS_POST_HOOK)), 1)
$(TOP_Q)+$(call $(POST_FINAL_OUT_HOOK))
endif
ifneq (,$(filter all,$(strip $(MAKECMDGOALS))))
$(TOP_Q)+$(call $(POST_FINAL_OUT_HOOK))
endif
$(TOP_Q)$(foreach V,$(INFO_ENV_VARS),$(V)="$($(V))") \
CFLAGS=$(CFLAGS) SED=$(SED) \
bash $(RULE_DIR)/scripts/gen_rom_stats.sh
endif

View file

@ -0,0 +1,148 @@
ifneq ($(TOP_DIR),$(CURDIR))
INTERNAL_INCLUDES += -I$(SYSROOT_INC)
INTERNAL_INCLUDES += $(foreach d, $(shell find $(SYSROOT_INC) -type d), -I$(d))
INTERNAL_INCLUDES += -I$(TOP_DIR)
INTERNAL_INCLUDES += $(foreach d, $(shell find -L $(TOP_DIR)/$(EXPORT_DIR) -type d), -I$(d))
INTERNAL_INCLUDES += \
$(foreach d, \
$(shell [ -d $(IMPORT_DIR)/$(CONFIG_VENDOR)/include ] && find -L $(IMPORT_DIR)/$(CONFIG_VENDOR)/include -type d), \
-I$(d) \
)
INTERNAL_INCLUDES += $(foreach mod, $(MODULE_NAME) $(HDR_REFS), \
$(foreach d, \
$(shell [ -d $(TOP_DIR)/$(mod) ] && \
find -L $(TOP_DIR)/$(mod)/ -type d \
-a -name "[^.]*" \
-not -path "*.git*"), \
-I$(d) \
) \
)
# INTERNAL_INCLUDES += \
$(foreach d, \
$(shell find $(OUTPUT_DIR)/$(MODULE_NAME) -type d -a -name "[^.]*"), \
-I$(d) \
)
INTERNAL_INCLUDES := $(strip $(sort $(INTERNAL_INCLUDES)))
EXTERNAL_INCLUDES += $(foreach mod, $(DEPENDS), \
$(foreach d, \
$(shell $(SHELL_DBG) find \
$(SYSROOT_INC)/$(mod)/ -maxdepth 2 -type d 2>/dev/null) \
$(shell $(SHELL_DBG) find \
$(IMPORT_VDRDIR)/include/$(mod)/ -maxdepth 2 -type d 2>/dev/null), \
-I$(d) \
) \
)
EXTERNAL_INCLUDES := $(strip $(EXTERNAL_INCLUDES))
endif # ifneq ($(TOP_DIR),$(CURDIR))
ifeq (dynamic,$(strip $(CONFIG_LIB_EXPORT)))
CFLAGS += -fPIC
endif
#CFLAGS := $(sort $(strip $(CFLAGS)))
LDFLAGS += -L$(SYSROOT_LIB)
ifeq (y,$(shell [ -e $(TOP_DIR)/$(IMPORT_VDRDIR)/$(PREBUILT_LIBDIR) ] && echo y))
LDFLAGS += -L$(TOP_DIR)/$(IMPORT_VDRDIR)/$(PREBUILT_LIBDIR)
endif
LDFLAGS += $(foreach d,$(DEPENDS_$(MODULE_NAME)),$(REF_LDFLAGS_$(d)))
WATCHED_VARS = \
TARGET \
CFLAGS \
CC \
LDFLAGS \
CURDIR \
INTERNAL_INCLUDES \
DEPENDS \
MAKECMDGOALS \
EXTERNAL_INCLUDES \
LIBA_TARGET \
LIBSO_TARGET \
ALL_TARGETS := $(TARGET) $(LIBSO_TARGET) $(LIBA_TARGET) $(firstword $(KMOD_TARGET))
ifneq (,$(strip $(PKG_SWITCH)))
all: $(ALL_TARGETS)
else
all:
$(Q)true
endif
clean:
$(Q)rm -f \
$(strip \
$(ALL_TARGETS) $(OBJS) $(LIB_OBJS) \
$(OBJS:.o=.d) $(LIB_OBJS:.o=.d) \
$(LIB_OBJS:.o=.gcno) $(LIB_OBJS:.o=.gcda) \
) \
*.o.e *.d *.o *.a *.so *.log *.gc*
%.o: %.c $(HD_MAKEFILE)
@$(call Brief_Log,"CC")
$(call Inspect_Env,$(WATCHED_VARS))
$(Q) \
set -o pipefail; \
$(CC) -I$(CURDIR) \
$(INTERNAL_INCLUDES) \
$(EXTERNAL_INCLUDES) \
$(CFLAGS) \
-c -o $@ $<
ifneq (,$(OBJCOPY_FLAGS))
$(Q)$(OBJCOPY) $(OBJCOPY_FLAGS) $@
endif
NODEP_LIST = \
$(SYSROOT_INC)/git_version.h \
$(SYSROOT_INC)/platform.h \
$(SYSROOT_INC)/product.h \
$(SYSROOT_INC)/product_config.h \
ifneq (,$(findstring gcc,$(CC)))
ifeq (,$(filter modinfo,$(MAKECMDGOALS)))
%.d: %.c
@ \
( \
D=$$(dirname $<|$(SED) 's,$(TOP_DIR),$(OUTPUT_DIR),1'); \
F=$$(basename $<); \
mkdir -p $${D}; \
$(CC) -MM -I$(CURDIR) \
$(INTERNAL_INCLUDES) \
$(EXTERNAL_INCLUDES) \
$(CFLAGS) \
$< > $${D}/$${F}.$$$$; \
$(SED) -i 's!$(shell basename $*)\.o[ :]!$*.o:!1' $${D}/$${F}.$$$$; \
mv $${D}/$${F}.$$$$ $@; \
)
endif
endif
%.o: %.cpp
@$(call Brief_Log,"CC")
$(call Inspect_Env,$(WATCHED_VARS))
$(Q)$(CXX) -I$(CURDIR) \
$(INTERNAL_INCLUDES) \
$(EXTERNAL_INCLUDES) \
$(CFLAGS) \
-c -o $@ $<
ifneq (,$(findstring gcc,$(CC)))
%.d: %.cpp
@ \
$(CXX) -MM -I$(CURDIR) \
$(INTERNAL_INCLUDES) \
$(EXTERNAL_INCLUDES) \
$(CFLAGS) \
$< > $@.$$$$; \
$(foreach D,$(NODEP_LIST),$(SED) -i 's,$(D),,g' $@.$$$$;) \
$(SED) 's,\($*\)\.o[ :]*,\1.o $@: ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$;
endif
include $(RULE_DIR)/_rules-libs.mk
include $(RULE_DIR)/_rules-prog.mk
include $(RULE_DIR)/_rules-kmod.mk

View file

@ -0,0 +1,35 @@
ifdef KMOD_TARGET
KMOD_NAME := $(subst .o,,$(obj-m))
KMOD_OBJS := $(foreach mod, $(KMOD_NAME), $($(mod)-objs))
KMOD_SRCS := $(subst .o,.c,$(KMOD_OBJS))
KMOD_BUILD_DIR := $(CURDIR)/build-$(shell $(SHELL_DBG) basename $(CURDIR))-kmod
KMOD_MAKEFILE := $(KMOD_BUILD_DIR)/Makefile
$(firstword $(KMOD_TARGET)): $(KMOD_SRCS)
$(Q)rm -rf $(KMOD_BUILD_DIR) && mkdir -p $(KMOD_BUILD_DIR)
$(Q)cp -f $(KMOD_SRCS) $(KMOD_BUILD_DIR)
$(Q)echo "EXTRA_CFLAGS += " \
"-I$(CURDIR)" \
"$(INTERNAL_INCLUDES)" \
| $(SED) 's/-I/\\\n -I/g' \
>> $(KMOD_MAKEFILE)
$(Q)echo "" >> $(KMOD_MAKEFILE)
$(Q)echo "obj-m := $(obj-m)" >> $(KMOD_MAKEFILE)
$(Q)echo "" >> $(KMOD_MAKEFILE)
$(Q) \
$(foreach mod, $(KMOD_NAME), \
echo "$(mod)-objs := $($(mod)-objs)" \
| $(SED) 's/ [_a-z]*\.o/ \\\n &/g' \
>> $(KMOD_MAKEFILE); \
echo "" >> $(KMOD_MAKEFILE); \
)
@$(call Brief_Log,"CC",$(KMOD_TARGET))
$(Q) \
LDFLAGS=""; \
$(MAKE) -C $(KERNEL_DIR) M=$(KMOD_BUILD_DIR) CROSS_COMPILE=$(CROSS_PREFIX) modules
$(Q)cp -f $(KMOD_BUILD_DIR)/*.ko $(CURDIR)
$(Q)mkdir -p $(SYSROOT_LIB)
$(Q)install -m 0755 $(KMOD_BUILD_DIR)/*.ko $(SYSROOT_LIB)
endif # ifdef KMOD_TARGET

View file

@ -0,0 +1,96 @@
VPATH := $(TOP_DIR)/$(MODULE_NAME)
LIB_SRCS ?= $(foreach M,*.c */*.c */*/*.c,$(wildcard $(TOP_DIR)/$(MODULE_NAME)/$(M))) $(wildcard *.c)
.PHONY : cmake
cmake:
$(Q)$(foreach V,$(INFO_ENV_VARS),$(subst -,_,$(V))="$($(V))") \
$(foreach V,$(TARGET),$(subst -,_,SRCS_$(V))="$(SRCS_$(V))") \
bash $(if $(TOP_Q),,-x) $(RULE_DIR)/scripts/gen_sub_cmake.sh $(TOP_DIR)/${MODULE_NAME}/CMakeLists.txt
ifdef Extra_CMake_Head
@rm -f $(OUTPUT_DIR)/$(STAMP_CMAKE)
@$(call Extra_CMake_Head, >> $(OUTPUT_DIR)/$(STAMP_CMAKE))
@cat $(TOP_DIR)/${MODULE_NAME}/CMakeLists.txt >> $(OUTPUT_DIR)/$(STAMP_CMAKE)
@$(call Extra_CMake_Foot, >> $(OUTPUT_DIR)/$(STAMP_CMAKE))
@mv $(OUTPUT_DIR)/$(STAMP_CMAKE) $(TOP_DIR)/${MODULE_NAME}/CMakeLists.txt
endif
ifdef LIB_SRCS_PATTERN
SRC_LIST := $(foreach M,$(LIB_SRCS_PATTERN),$(shell ls $(TOP_DIR)/$(MODULE_NAME)/$(M) 2>/dev/null))
LIB_SRCS := $(SRC_LIST)
endif
LIB_SRCS := $(filter-out $(foreach M,$(LIB_SRCS_EXCLUDE),$(TOP_DIR)/$(MODULE_NAME)/$(M)),$(LIB_SRCS))
LIB_OBJS := $(LIB_SRCS:.c=.o)
LIB_OBJS := $(subst $(TOP_DIR)/$(MODULE_NAME)/,,$(LIB_OBJS))
sinclude $(LIB_OBJS:.o=.d)
ifdef LIBA_TARGET
.PHONY: StaticLib_Install
ifeq (1,$(words $(LIBA_TARGET)))
$(LIBA_TARGET) :: $(LIB_OBJS)
@$(call Brief_Log,"AR")
$(call Inspect_Env,$(WATCHED_VARS))
$(Q)rm -f $@
ifdef CONFIG_LIBOBJ_STRIP
@$(call Brief_Log,"ST")
$(TOP_Q)$(STRIP) $(STRIP_DBGOPT) $(LIB_OBJS)
endif
$(TOP_Q) \
if [ "$$(echo "$(LIB_OBJS)"|awk '{ print NF }')" != "0" ]; then \
$(AR) -rcs $@ $(LIB_OBJS); \
fi
$(LIBA_TARGET) :: StaticLib_Install
$(Q)mkdir -p $(LIBOBJ_TMPDIR)/$(MODULE_NAME)
ifneq (,$(strip $(LIB_OBJS)))
ifneq ($(LIBA_TARGET),$(LIBA_SKIP_COMBO))
$(Q)cp -f $(LIB_OBJS) $(LIBOBJ_TMPDIR)/$(MODULE_NAME) 2>/dev/null || true
endif
endif
$(Q)mkdir -p $(SYSROOT_LIB)
$(Q)if [ -f $@ ]; then cp -f $@ $(SYSROOT_LIB); fi
$(call Copy_Headers, $(LIB_HEADERS),$(SYSROOT_INC),$(LIB_HDRS_DIR))
else
$(foreach t,$(sort $(LIBA_TARGET)),$(t)): FORCE
$(Q) \
$(MAKE) LIBA_TARGET=$@ \
LIB_SRCS="$(LIB_SRCS_$(subst .a,,$(subst lib,,$@)))" \
LIB_SRCS_PATTERN="$(LIB_SRCS_PATTERN_$(subst .a,,$(subst lib,,$@)))" \
endif # ifeq (1,$(words $(LIBA_TARGET)))
endif # ifdef LIBA_TARGET
ifdef LIBSO_TARGET
.PHONY: DynamicLib_Install
$(LIBSO_TARGET) :: SELF_LIBNAME = $(subst lib,,$(subst .so,,$(LIBSO_TARGET)))
$(LIBSO_TARGET) :: LDFLAGS := $(filter-out -l$(SELF_LIBNAME), $(LDFLAGS))
$(LIBSO_TARGET) :: $(LIB_OBJS) $(foreach d,$(DEPENDS_$(MODULE_NAME)),$(SYSROOT_LIB)/$(LIBA_TARGET_$(d)))
@$(call Brief_Log,"CC")
$(call Inspect_Env,$(WATCHED_VARS))
$(Q)$(CC) -shared -Os \
$(CFLAGS) \
$(RPATH_CFLAGS) \
-o $@ \
$(LIB_OBJS) \
-Wl,--start-group $(LDFLAGS) -Wl,--end-group
$(LIBSO_TARGET) :: DynamicLib_Install
$(Q)mkdir -p $(LIBOBJ_TMPDIR)/$(shell $(SHELL_DBG) basename $(CURDIR))
$(Q)cp -f $(LIB_OBJS) $(LIBOBJ_TMPDIR)/$(shell $(SHELL_DBG) basename $(CURDIR))
$(Q)mkdir -p $(SYSROOT_LIB)
$(Q)install -m 0755 $@ $(SYSROOT_LIB)
$(call Copy_Headers, $(LIB_HEADERS),$(SYSROOT_INC),$(LIB_HDRS_DIR))
endif # ifdef LIBSO_TARGET

View file

@ -0,0 +1,58 @@
.PHONY: modinfo
modinfo:
@true
MODINFO_VARS := \
EXTRA_SRCS \
PKG_SWITCH \
ORIGIN \
PKG_SOURCE \
PKG_BRANCH \
PKG_REVISION \
PKG_UPSTREAM \
REF_CFLAGS \
REF_LDFLAGS \
LDFLAGS \
LIBA_TARGET \
LIB_OBJS \
TARGET \
LIBSO_TARGET \
ifneq (,$(CONFIG_$(MODULE_NAME)))
$(if $(filter modinfo,$(MAKECMDGOALS)), \
$(if $(strip $(DEPENDS)), \
$(info DEPENDS_$(MODULE_NAME) = $(strip $(DEPENDS))) \
$(info CONFIG_$(MODULE_NAME) = $(CONFIG_$(MODULE_NAME))) \
) \
)
$(if $(filter modinfo,$(MAKECMDGOALS)), \
$(foreach v, $(MODINFO_VARS), \
$(if $(strip $($(v))), \
$(info $(v)_$(MODULE_NAME) = $(strip $($(v)))) \
) \
) \
)
ifeq (0,$(words $(TARGET)))
else
ifeq (1,$(words $(TARGET)))
$(if $(filter modinfo,$(MAKECMDGOALS)), \
$(info SRCS_$(TARGET) = $(if $(SRCS_$(TARGET)), \
$(subst $(TOP_DIR)/,,$(SRCS_$(TARGET))), \
$(subst $(TOP_DIR)/$(MODULE_NAME)/,,$(SRCS)))) \
)
else
$(if $(filter modinfo,$(MAKECMDGOALS)), \
$(foreach v, $(TARGET), \
$(info SRCS_$(v) = $(SRCS_$(v))) \
) \
)
endif
endif
endif

View file

@ -0,0 +1,120 @@
CFLAGS := $(filter-out -Werror,$(CFLAGS))
LDFLAGS :=
.PHONY: config build install post-install
ORIGIN_Q ?= @
ifeq ($(strip $(PKG_SWITCH)),y)
all :
ifeq ($(PKG_SOURCE),)
$(error PKG_SOURCE for $(PKG_NAME) cannot be found!)
endif
$(ORIGIN_Q) \
MESSAGE=$(strip $(if $(filter 0 1,$(MAKELEVEL)), \
"\r$(PKG_NAME) already pre-built at $(IMPORT_VDRDIR)/$(PREBUILT_LIBDIR)\n","")); \
if [ "$(LIBA_TARGET)" != "" -a -f $(IMPORT_VDRDIR)/$(PREBUILT_LIBDIR)/$(LIBA_TARGET) ] || \
[ "$(LIBSO_TARGET)" != "" -a -f $(IMPORT_VDRDIR)/$(PREBUILT_LIBDIR)/$(LIBSO_TARGET) ]; then \
echo -ne $${MESSAGE}; \
cp -P -f $(IMPORT_VDRDIR)/$(PREBUILT_LIBDIR)/{$(LIBA_TARGET),$(LIBSO_TARGET)*} \
$(SYSROOT_LIB) 2>/dev/null; \
for t in $(TARGET); do \
cp -f $(IMPORT_VDRDIR)/$(PREBUILT_BINDIR)/$${t} $(SYSROOT_BIN); \
done; \
touch $(STAMP_SHIELD); \
fi
$(ORIGIN_Q) \
MESSAGE=$(if $(filter 0 1,$(MAKELEVEL)),"\r$(PKG_NAME) already unpacked\n",""); \
if [ -f $(STAMP_SHIELD) ]; then true; \
elif [ -f $(STAMP_UNPACK) ]; then \
echo -ne $${MESSAGE}; \
else \
rm -rf $(PKG_NAME)* && \
if [ -f $(PKG_SOURCE) ]; then \
tar xf $(PKG_SOURCE) -C . && \
for i in $(wildcard *.patch); do \
cd $(PKG_NAME)* && patch -d . -p 1 < ../$${i} && cd $${OLDPWD}; \
done \
fi \
&& touch $(STAMP_UNPACK); \
fi
$(ORIGIN_Q) \
MESSAGE=$(if $(filter 0 1,$(MAKELEVEL)),"\r$(PKG_NAME) already configured\n",""); \
if [ -f $(STAMP_SHIELD) ]; then true; \
elif [ -f $(STAMP_CONFIG) ]; then \
echo -ne $${MESSAGE}; \
else \
if grep -q 'config *:' $(HD_MAKEFILE); then \
export SHELL=$(SHELL); \
$(MAKE) config -f $(HD_MAKEFILE); \
else \
cd $(PKG_NAME)* && ( \
./configure \
--prefix=$(OUTPUT_DIR)/usr \
--host=$(HOST) \
--target=$(shell $(SHELL_DBG) basename $(CROSS_PREFIX) 2>/dev/null) \
--enable-static --enable-shared \
|| \
./configure \
--prefix=$(OUTPUT_DIR)/usr \
--host=$(HOST) \
--target=$(shell $(SHELL_DBG) basename $(CROSS_PREFIX) 2>/dev/null|cut -d'-' -f1) \
--enable-static --enable-shared \
) && cd $${OLDPWD}; \
fi \
&& touch $(STAMP_CONFIG); \
fi
$(ORIGIN_Q) \
MESSAGE=$(if $(filter 0 1,$(MAKELEVEL)),"\r$(PKG_NAME) already built\n",""); \
if [ -f $(STAMP_SHIELD) ]; then true; \
elif [ -f $(STAMP_BUILD) ]; then \
echo -ne $${MESSAGE}; \
else \
if grep -q 'build *:' $(HD_MAKEFILE); then \
$(MAKE) build -f $(HD_MAKEFILE); \
else \
if [ -d $(PKG_NAME)* ]; then \
cd $(PKG_NAME)* && $(MAKE) -j8 all && cd ..; \
fi \
fi \
&& touch $(STAMP_BUILD); \
fi
$(ORIGIN_Q) \
MESSAGE=$(if $(filter 0 1,$(MAKELEVEL)),"\r$(PKG_NAME) already installed\n",""); \
if [ -f $(STAMP_SHIELD) ]; then true; \
elif [ -f $(STAMP_INSTALL) ]; then \
echo -ne $${MESSAGE}; \
else \
if grep -q 'install *:' $(HD_MAKEFILE); then \
$(MAKE) install -f $(HD_MAKEFILE); \
else \
if [ -d $(PKG_NAME)* ]; then \
cd $(PKG_NAME)* && $(MAKE) install && cd ..; \
fi \
fi \
&& touch $(STAMP_INSTALL); \
fi
$(ORIGIN_Q) \
MESSAGE=$(if $(filter 0 1,$(MAKELEVEL)),"\r$(PKG_NAME) already post-installed\n",""); \
if [ -f $(STAMP_POSTINS) ]; then \
echo -ne $${MESSAGE}; \
else \
if grep -q 'post-install *:' $(HD_MAKEFILE); then \
$(MAKE) post-install -f $(HD_MAKEFILE); \
fi \
&& touch $(STAMP_POSTINS); \
fi
clean-prepare:
$(Q)rm -f $(STAMP_BUILD) $(STAMP_INSTALL) $(STAMP_POSTINS)
else
all:
$(Q)true
clean:
$(Q)true
endif # ifeq ($(strip $(PKG_SWITCH)),y)

View file

@ -0,0 +1,25 @@
ifeq (,$(findstring llvm,$(CC)))
CFLAGS := "$(sort $(CFLAGS) $(CONFIG_ENV_CFLAGS))"
else
CFLAGS := "$(CFLAGS) $(CONFIG_ENV_CFLAGS)"
endif
LDFLAGS := $(sort $(LDFLAGS) $(CONFIG_ENV_LDFLAGS))
ifeq (dynamic,$(CONFIG_LIB_EXPORT))
CFLAGS := $(filter-out --coverage,$(CFLAGS))
endif
MAKE_ENV_VARS := \
$(foreach v, \
$(shell grep -o 'CONFIG_ENV_[_A-Z]*' $(CONFIG_TPL) 2>/dev/null), \
$(subst CONFIG_ENV_,,$(v)) \
)
# $(eval ...) causes '$' in CFLAGS lost
MAKE_ENV_VARS := $(sort $(filter-out CFLAGS LDFLAGS,$(MAKE_ENV_VARS)))
$(foreach V, \
$(MAKE_ENV_VARS), \
$(eval export $(V) := $(sort $(CONFIG_ENV_$(V)))) \
)

View file

@ -0,0 +1,67 @@
VPATH := $(TOP_DIR)/$(MODULE_NAME)
SRCS ?= $(foreach M,*.c */*.c */*/*.c,$(wildcard $(TOP_DIR)/$(MODULE_NAME)/$(M))) $(wildcard *.c)
OBJS := $(SRCS:.c=.o)
OBJS := $(subst $(TOP_DIR)/$(MODULE_NAME)/,,$(OBJS))
ifdef SRCS_PATTERN
PROG_LIST := $(foreach M,$(SRCS_PATTERN),$(shell ls $(TOP_DIR)/$(MODULE_NAME)/$(M) 2>/dev/null))
SRCS := $(PROG_LIST)
OBJS := $(PROG_LIST:.c=.o)
OBJS := $(subst $(TOP_DIR)/$(MODULE_NAME)/,,$(OBJS))
endif
ifdef TARGET
ifneq (modinfo,$(MAKECMDGOALS))
ifneq (clean,$(MAKECMDGOALS))
sinclude $(OBJS:.o=.d)
endif
endif
ifdef LIBA_TARGET
$(TARGET): $(LIBA_TARGET)
LDFLAGS := -l$(subst .a,,$(subst lib,,$(LIBA_TARGET))) $(LDFLAGS)
endif
ifdef LIBSO_TARGET
$(TARGET): $(LIBSO_TARGET)
LDFLAGS := -l$(subst .so,,$(subst lib,,$(LIBSO_TARGET))) $(LDFLAGS)
endif
LDFLAGS += $(sort $(CONFIG_ENV_LDFLAGS))
ifneq (,$(filter %.cpp %.cc,$(SRCS)))
CCLD := $(CXX)
else
CCLD := $(CC)
endif
ifeq (1,$(words $(TARGET)))
$(TARGET): $(OBJS) FORCE
$(call Inspect_Env,$(WATCHED_VARS))
$(Q) \
( \
if [ "$(strip $(CC))" = "gcc" -o "$(strip $(CC))" = "i686-w64-mingw32-gcc" ] \
|| [ "$(filter -D_PLATFORM_IS_LINUX_,$(CFLAGS))" != "" ] \
|| [ "$(filter -D_PLATFORM_IS_WINDOWS_,$(CFLAGS))" != "" ]; then \
$(call Brief_Log,"LD"); \
mkdir -p $(OUTPUT_DIR)${bindir}; \
$(CCLD) $(CFLAGS) -o $@ \
$(RPATH_CFLAGS) \
$(OBJS) \
$(LDFLAGS) && \
cp -f $@ $(OUTPUT_DIR)${bindir}; \
fi; \
)
else
$(foreach t,$(sort $(TARGET)),$(t)): FORCE
$(Q)$(MAKE) TARGET=$@ OBJS="$(SRCS_$@:.c=.o)"
endif
endif # ifdef TARGET

View file

@ -0,0 +1,16 @@
OPS_CMDLINE_V := \
PACKAGE_DIR \
TOP_DIR \
STAMP_BLD_VAR \
OPS_SCRIPT := \
$(strip $(foreach V, $(OPS_CMDLINE_V), $(V)="$($(V))")) \
$(SHELL) \
$(RULE_DIR)/scripts/ops_repository.sh \
$(STAMP_BLD_VAR)
repo-list: config
$(TOP_Q)$(OPS_SCRIPT) list
repo-update: config
$(TOP_Q)$(OPS_SCRIPT) update

View file

@ -0,0 +1,161 @@
SUB_LOG_OPTION := $(if $(Q),,| tee -a $(OUTPUT_DIR)/$${i}/$(COMPILE_LOG))
ALL_LOG_OPTION := $(if $(Q),,| tee -a $(COMPILE_LOG))
sub-mods: toolchain
$(Q) \
if [ -f $(STAMP_ONE_MK) ] && [ "$(MAKECMDGOALS)" = "" ]; then \
CORE_NUM=$$(cat /proc/cpuinfo 2>/dev/null| grep processor | tail -1 | awk '{ print $$NF }'); \
JOBS_NUM=32; \
if [ "$${CORE_NUM}" != "" ]; then JOBS_NUM=$${CORE_NUM}; fi; \
rm -rf $(OUTPUT_DIR)${bindir}/* && \
if [ -f $(STAMP_LCOV) ] && [ "$(WITH_LCOV)" != "1" ]; then \
$(MAKE) --no-print-directory clean; \
fi && \
if ([ ! -f $(STAMP_LCOV) ] && [ "$(WITH_LCOV)" = "1" ]) || [ $(TOP_DIR)/make.settings -nt $(DIST_DIR) ]; then \
$(MAKE) --no-print-directory clean; \
fi && \
$(MAKE) --no-print-directory -j$$((JOBS_NUM + 1)) -f $(STAMP_ONE_MK) && \
TMPD=$$(mktemp -d) && \
rm -rf $(LIBOBJ_TMPDIR) $${TMPD} && \
cp -rf $(OUTPUT_DIR) $${TMPD} && \
rm -rf $${TMPD}/{usr,stamps} && \
mv $${TMPD} $(LIBOBJ_TMPDIR); \
else \
if [ -f $(STAMP_PRJ_CFG) ]; then true; else \
set -o pipefail; \
for i in \
$(SUBDIRS); do \
if [ ! -d $${i} ]; then continue; fi; \
$(MAKE) --no-print-directory Q=$(Q) $${i} 2>&1 $(SUB_LOG_OPTION); \
RETVAL=$$?; \
if [ $${RETVAL} != 0 ]; then exit $${RETVAL}; fi; \
done 2>&1 $(ALL_LOG_OPTION); \
fi; \
fi
TOP_BUILD_VARS := \
CC LD AR \
CFLAGS LDFLAGS \
PACKAGE_DIR \
IMPORT_DIR \
EXPORT_DIR \
TOP_DIR \
RULE_DIR \
CONFIG_VENDOR \
COMP_LIB \
COMP_LIB_COMPONENTS \
$(CROSS_CANDIDATES) \
$(MAKE_ENV_VARS) \
INSTALL_DIR \
INSTALL_LIB_DIR \
SYSROOT_INC \
KERNEL_DIR \
MAKE_ENV_VARS \
CROSS_PREFIX \
CROSS_CANDIDATES \
ALL_SUB_DIRS \
WIN32_CMAKE_SKIP \
NOEXEC_CMAKE_DIRS \
CMDLINE_VARS := \
HD_MAKEFILE \
MAKE_SEGMENT \
OUTPUT_DIR \
PACKAGE_DIR \
STAMP_BLD_ENV \
STAMP_UNPACK \
TOP_DIR \
RULE_DIR \
# When TOP_BUILD_VARS like $(CFLAGS) contains special character '$'
# simply echo its value into 'Makefile' will cause '$' lost when GNU make read in again
#
$(STAMP_BLD_ENV): $(TOP_DIR)/makefile $(shell ls $(CONFIG_TPL) 2>/dev/null) \
$(wildcard $(RULE_DIR)/*.mk) \
$(shell grep "^ *include" $(TOP_DIR)/$(TOP_MAKEFILE)|awk '{ print $$NF }'|$(SED) '/^\$$/d')
@rm -f $@
@$(foreach V, \
$(sort $(TOP_BUILD_VARS)), \
echo "$(V) := $(sort $($(V)))"|$(SED) 's:\$$:$$$$:g' >> $(STAMP_BLD_ENV); \
)
@echo "COMP_LIB_FILES := $(foreach V,$(COMP_LIB_COMPONENTS), $(LIBA_TARGET_$(V)))" >> $@
# note:
# $(SED) -i "/CONFIG_$${i//\//\\/}.*/d" $(CONFIG_TPL);
# above
# $(SED) -i "1iCONFIG_$${i} = y" $(CONFIG_TPL)
# was removed since modules will be skipped in some cases
$(STAMP_BLD_VAR): $(foreach d,$(ALL_SUB_DIRS),$(d)/$(MAKE_SEGMENT)) $(STAMP_BLD_ENV) $(wildcard $(RULE_DIR)/*.mk)
$(TOP_Q) \
( \
if [ ! -f $(STAMP_BLD_VAR) ]; then echo ""; VERBOSE=1; fi; \
rm -f $(STAMP_BLD_VAR); \
for i in $(shell echo "$(ALL_SUB_DIRS)"|tr ' ' '\n'|sort -u); do \
if [ "$${VERBOSE}" != "" ]; then \
if [ ! -L $${i} ]; then \
printf "CONFIGURE .............................. [%s]\n" $${i}; \
fi; \
$(SED) -i "1iCONFIG_$${i} = y" $(CONFIG_TPL); \
if ! grep -q "target-$${i}:" $(STAMP_POST_RULE) 2>/dev/null; then \
echo "target-$${i}:; @true" >> $(STAMP_POST_RULE); \
fi; \
fi; \
$(foreach V, $(CMDLINE_VARS), $(V)="$($(V))") \
bash $(RULE_DIR)/pre-build.sh $${i} makefile-only > /dev/null; \
if [ -d $(OUTPUT_DIR)/$${i} ]; then \
$(MAKE) -s -C $(OUTPUT_DIR)/$${i} modinfo > /dev/null; \
if [ $$? = 0 ]; then \
$(MAKE) --no-print-directory -s -C $(OUTPUT_DIR)/$${i} modinfo >> $(STAMP_BLD_VAR); \
else \
echo ""; \
echo "ERROR detected in '$${i}/$(MAKE_SEGMENT)'..."|grep --color '.*'; \
echo ""; \
rm -f $(STAMP_BLD_VAR) $(STAMP_PRJ_CFG); \
exit 13; \
fi \
fi \
done; \
sort -o $(STAMP_BLD_VAR) $(STAMP_BLD_VAR); \
if [ "$${VERBOSE}" != "" ]; then echo ""; fi; \
)
pre-build: MOD = $(subst target-,,$(filter-out $@,$(MAKECMDGOALS)))
pre-build: $(STAMP_BLD_ENV)
$(TOP_Q)rm -f $(OUTPUT_DIR)/$(MOD)/$(STAMP_UNPACK)
$(if $(filter 0,$(MAKELEVEL)),,@) \
$(strip $(foreach V, $(CMDLINE_VARS), $(V)="$($(V))") \
PKG_SOURCE="$(PKG_SOURCE_$(MOD))" \
PKG_BRANCH="$(PKG_BRANCH_$(MOD))" \
PKG_REVISION="$(PKG_REVISION_$(MOD))" \
PKG_UPSTREAM="$(PKG_UPSTREAM_$(MOD))" \
PKG_SWITCH="$(PKG_SWITCH_$(MOD))" \
) \
$(if $(filter 0,$(MAKELEVEL)),VERBOSE_PRE_BLD=1) \
bash $(RULE_DIR)/pre-build.sh $(subst target-,,$(filter-out $@,$(MAKECMDGOALS)))
.PHONY: $(ALL_SUB_DIRS)
$(ALL_SUB_DIRS): ALL_LOG_OPT = $(if $(Q),,2>&1|tee -a $(OUTPUT_DIR)/$(COMPILE_LOG))
$(ALL_SUB_DIRS): SUB_LOG_OPT = $(if $(Q),,2>&1|tee -a $(OUTPUT_DIR)/$@/$(COMPILE_LOG))
$(ALL_SUB_DIRS): $(if $(filter 0,$(MAKELEVEL)),toolchain) $(STAMP_BLD_VAR)
$(TOP_Q)rm -f $(STAMP_PRJ_CFG)
$(TOP_Q)$(MAKE) --no-print-directory pre-build target-$@
ifeq (0,$(MAKELEVEL))
$(Q)$(MAKE) --no-print-directory -C $(OUTPUT_DIR)/$@ clean
endif
$(Q) \
if [ "$$( $(call Require_Build,$@) )" = "TRUE" ]; then \
$(call Build_Depends,$@) && \
$(call Build_CompLib,$@) && \
$(call Update_Extra_Srcs,$(EXTRA_SRCS_$@),$@) && \
$(MAKE) --no-print-directory -C $(OUTPUT_DIR)/$@ all $(SUB_LOG_OPT) $(ALL_LOG_OPT) && \
if [ "$$(echo $(ORIGIN_$@))" != "" ]; then \
touch $(OUTPUT_DIR)/$@/{$(STAMP_UNPACK),$(STAMP_CONFIG),$(STAMP_BUILD),$(STAMP_INSTALL)}; \
fi \
else \
echo -ne "\r$$(printf '%40s' '')\r"; \
fi
@mkdir -p $(STAMP_DIR) && touch $(STAMP_DIR)/$$(echo "$@"|$(SED) 's:/:~:g').build.done

View file

@ -0,0 +1,212 @@
.PHONY: doc detect config reconfig toolchain sub-mods final-out env cmake one help
all: detect config toolchain sub-mods final-out
$(TOP_Q) \
if [ -f $(STAMP_PRJ_CFG) ]; then \
$(RECURSIVE_MAKE) toolchain; \
rm -f $(STAMP_PRJ_CFG); \
fi
@rm -rf $(STAMP_DIR)
RESET_ENV_VARS := \
CROSS_PREFIX \
CFLAGS \
HOST \
LDFLAGS \
help:
@echo -e "\033[1;37m[$(RULE_DIR)/docs]\e[0m"
@echo ""
@cat $(RULE_DIR)/docs/Help.md
@echo ""
doc:
$(TOP_Q)rm -rf $(DOXYGEN_DIR)/html; mkdir -p $(DOXYGEN_DIR)
$(TOP_Q) \
$(SED) \
-e 's:^PROJECT_NAME.*:PROJECT_NAME = $(PRJ_NAME):g;' \
-e 's:^PROJECT_NUMBER.*:PROJECT_NUMBER = $(PRJ_VERSION):g;' \
-e 's:^OUTPUT_DIRECTORY.*:OUTPUT_DIRECTORY = $(DOXYGEN_DIR):g;' \
build-rules/misc/Doxyfile.tpl > $(OUTPUT_DIR)/.doxygen.cfg
$(TOP_Q)doxygen $(OUTPUT_DIR)/.doxygen.cfg
detect:
@if [ -d .git ]; then \
mkdir -p .git/hooks; \
for i in $(RULE_DIR)/hooks/*; do \
cp -f $$i .git/hooks && chmod a+x .git/hooks/$$(basename $$i); \
done; \
fi
prune:
@echo "$(TOP_DIR).pkgs directory removed!"|grep --color ".*"
@rm -rf $(TOP_DIR).pkgs
@$(MAKE) --no-print-directory distclean
unzip: config $(STAMP_BLD_VAR)
@echo "Components: "
@echo ""
@for i in $(ALL_SUB_DIRS); do \
$(MAKE) --no-print-directory pre-build target-$${i} ; \
echo -ne "\r. $${i}"; \
echo -e " "; \
done
@echo ""
cmake:
$(TOP_Q)$(MAKE) -s distclean
$(TOP_Q)$(MAKE) -s DEFAULT_BLD=$(RULE_DIR)/misc/config.generic.cmake config
$(TOP_Q)$(foreach V,$(INFO_ENV_VARS),$(V)="$($(V))") CFLAGS=$(CFLAGS) \
SEP_LIBS="$$(grep -m 1 '^COMP_LIB_FILES' $(STAMP_BLD_ENV) | cut -d' ' -f3-)" \
bash $(if $(TOP_Q),,-x) $(RULE_DIR)/scripts/gen_top_cmake.sh $(TOP_DIR)/CMakeLists.txt
$(TOP_Q)for D in $(ALL_SUB_DIRS); do \
echo "+ $${D}"; \
$(MAKE) --no-print-directory -C $(OUTPUT_DIR)/$${D} cmake; \
done
$(TOP_Q)echo ""
one: COMP_LIB_OBJS = $(foreach V,$(COMP_LIB_COMPONENTS),$(foreach U,$(LIB_OBJS_$(V)),$(V)/$(U)))
one:
$(TOP_Q)$(foreach V,$(INFO_ENV_VARS),$(V)="$($(V))") \
CFLAGS="$(subst ",,$(CFLAGS))" \
ALL_LIBS="$(strip $(foreach V,$(SUBDIRS),$(LIBA_TARGET_$(V))))" \
ALL_PROG="$(strip $(foreach V,$(SUBDIRS),$(TARGET_$(V))))" \
COMP_LIB_OBJS="$(COMP_LIB_OBJS)" \
bash $(RULE_DIR)/scripts/gen_one_makefile.sh
config:
@mkdir -p $(OUTPUT_DIR) $(STAMP_DIR) $(INSTALL_DIR)
@mkdir -p $(SYSROOT_BIN) $(SYSROOT_INC) $(SYSROOT_LIB)
$(TOP_Q) \
if [ -f $(STAMP_BLD_VAR) ]; then \
if [ "$$($(SED) '/[-_/a-zA-Z0-9]* = *..*/d' $(STAMP_BLD_VAR)|wc -l|$(SED) 's:^ *::g')" != "0" ]; then \
rm -vf $(STAMP_BLD_VAR); \
fi \
fi
$(TOP_Q)+( \
if [ -f $(CONFIG_TPL) ]; then \
if [ "$(filter comp-lib,$(MAKECMDGOALS))" = "" ]; then \
printf "BUILDING WITH EXISTING CONFIGURATION:\n\n"; \
command grep -m 1 "VENDOR *:" $(CONFIG_TPL)|cut -c 3-; \
command grep -m 1 "MODEL *:" $(CONFIG_TPL)|cut -c 3-; \
echo ""; \
fi \
else \
if [ "$(DEFAULT_BLD)" != "" ] && [ -f $(DEFAULT_BLD) ] && \
([ "$(DEFAULT_BLD)" = "$(RULE_DIR)/misc/config.generic.default" ] \
|| [ "$(MAKECMDGOALS)" = "" ] || [ "$(MAKECMDGOALS)" = "config" ]); then \
printf "# Automatically Generated Section End\n\n" >> $(CONFIG_TPL); \
printf "# %-10s %s\n" "VENDOR :" $$(basename $(DEFAULT_BLD)|cut -d. -f2) >> $(CONFIG_TPL); \
printf "# %-10s %s\n" "MODEL :" $$(basename $(DEFAULT_BLD)|cut -d. -f3) >> $(CONFIG_TPL); \
cat $(DEFAULT_BLD) >> $(CONFIG_TPL); \
else \
printf "SELECT A CONFIGURATION:\n\n"; \
LIST=$$(for i in $(CONFIG_DIR)/config.*.*; do basename $${i}; done|sort); \
select V in $${LIST}; do \
echo ""; \
printf "# Automatically Generated Section End\n\n" >> $(CONFIG_TPL); \
printf "# %-10s %s\n" "VENDOR :" $$(echo $${V}|cut -d. -f2) >> $(CONFIG_TPL); \
printf "# %-10s %s\n" "MODEL :" $$(echo $${V}|cut -d. -f3) >> $(CONFIG_TPL); \
cp -f -P $(IMPORT_DIR)/$$(echo $${V}|cut -d. -f2)/$(PREBUILT_LIBDIR)/*.so* $(SYSROOT_LIB) 2>/dev/null; \
cat $(CONFIG_DIR)/$${V} >> $(CONFIG_TPL); \
break; \
done; \
fi && \
printf "SELECTED CONFIGURATION:\n\n" && \
command grep -m 1 "VENDOR *:" $(CONFIG_TPL)|cut -c 3- && \
command grep -m 1 "MODEL *:" $(CONFIG_TPL)|cut -c 3- && \
echo ""; \
if [ "$(MAKECMDGOALS)" = "config" ]; then true; else \
if [ "$(DEFAULT_BLD)" = "" ]; then \
touch $(STAMP_PRJ_CFG); \
fi; \
fi; \
for i in $(RESET_ENV_VARS); do unset $${i}; done; \
$(MAKE) --no-print-directory -f $(TOP_MAKEFILE) $(STAMP_BLD_VAR) unzip; \
fi)
@$(MAKE) --no-print-directory one
DL_TOOLCHAIN_VARS = \
TOOLCHAIN_DLDIR \
OUTPUT_DIR \
toolchain:
@$(foreach V,$(DL_TOOLCHAIN_VARS),$(V)=$($(V))) \
CC=$(shell basename $(CC)) \
AR=$(shell basename $(AR)) \
RELPATH=` $(call Relative_TcPath,$(shell basename $(CC))) ` \
GITPATH=` $(call Gitrepo_TcPath,$(shell basename $(CC))) ` \
bash $(RULE_DIR)/scripts/gen_cross_toolchain.sh
reconfig: distclean
$(TOP_Q)+( \
if [ -d $(CONFIG_DIR) ]; then \
$(RECURSIVE_MAKE) config DEFAULT_BLD=not-exist-actually; \
else \
$(RECURSIVE_MAKE) config; \
fi)
$(TOP_Q)rm -f $(STAMP_PRJ_CFG)
clean:
$(TOP_Q) \
$(TOP_Q) \
rm -rf \
$(LIBOBJ_TMPDIR) \
$(COMPILE_LOG) \
$(DIST_DIR)/* \
$(STAMP_DIR) \
$(STAMP_LCOV) \
$(SYSROOT_INC)/* $(SYSROOT_LIB)/* $(SYSROOT_LIB)/../bin/* \
$(shell $(SHELL_DBG) find $(OUTPUT_DIR) -name "$(COMPILE_LOG)" \
-or -name "$(WARNING_LOG)" \
-or -name "$(STAMP_BUILD)" \
-or -name "$(STAMP_INSTALL)" \
-or -name "$(STAMP_POSTINS)" \
-or -name "*.so" \
-or -name "*.a" \
-or -name "*.o" \
-or -name "*.d" \
-or -name "*.gc*" \
| grep -v '$(OUTPUT_DIR)/compiler' \
2>/dev/null)
distclean:
$(TOP_Q) \
rm -rf \
$(CONFIG_TPL) $(COMPILE_LOG) \
$(STAMP_PRJ_CFG) $(STAMP_BLD_ENV) $(STAMP_BLD_VAR) $(STAMP_POST_RULE) $(STAMP_LCOV) \
$(DIST_DIR) $(STAMP_DIR) *.gcda \
$(TOP_Q) \
if [ -d $(OUTPUT_DIR) ]; then \
cd $(OUTPUT_DIR); \
if [ "$(CONFIG_TOOLCHAIN_NAME)" = "" ]; then \
rm -rf *; \
else \
rm -rf $$(ls -I $(CONFIG_TOOLCHAIN_NAME)); \
fi \
fi
COMMON_CONFIG_ENV = \
KCONFIG_CONFIG=mconf.config \
KCONFIG_AUTOCONFIG=$(OUTPUT_DIR)/auto.conf \
KCONFIG_AUTOHEADER=$(OUTPUT_DIR)/autoconf.h \
menuconfig: prebuilt/ubuntu/bin/kconfig-mconf
$(TOP_Q)$(COMMON_CONFIG_ENV) $^ -s $(TOP_DIR)/Config.in $(if $(TOP_Q),2>/dev/null)
$(TOP_Q) \
( \
if [ ! -f mconf.config ]; then exit 0; fi; \
\
sed -i 's:^CONFIG_:FEATURE_:g' mconf.config; \
sed -i 's:^# CONFIG_:# FEATURE_:g' mconf.config; \
cp -Lf mconf.config make.settings; \
rm -f mconf.config*; \
)

View file

@ -0,0 +1,41 @@
# 构建系统配置
## 定制目录排布
默认情况下, 构建系统采用如下的目录排布:
CONFIG_DIR ?= $(TOP_DIR)/configs
DIST_DIR ?= $(TOP_DIR)/output
FINAL_DIR ?= $(DIST_DIR)/release
IMPORT_DIR ?= $(TOP_DIR)/import
LCOV_DIR ?= Coverage
MAKE_SEGMENT ?= iot.mk
OUTPUT_DIR ?= $(TOP_DIR)/.O
PACKAGE_DIR ?= $(TOP_DIR)/packages
RULE_DIR ?= $(TOP_DIR)/build-rules
TOP_DIR ?= $(CURDIR)
含义如下:
| 变量名 | 说明 |
|-------------------|-------------------------------------------|
| `CONFIG_DIR` | *硬件平台配置文件*的存放目录, 其中的文件需要以`config.XXX.YYY`形式命名, 其中`XXX`一般表示操作系统, `YYY`一般表示具体的硬件型号 |
| `DIST_DIR` | 最终的编译产物, 例如可执行程序, SDK的总库等, 存放的顶层目录 |
| `FINAL_DIR` | 最终的编译产物摆放时, 会放在`$(FINAL_DIR)`下, 这个变量可以指定最终摆放位置在顶层目录下的子目录路径 |
| `IMPORT_DIR` | 输入目录, 用于摆放预编译的二进制库, 以及使用这些预编译库对应的头文件 |
| `LCOV_DIR` | 覆盖率文件产生目录, 用于存放`lcov`软件产生的中间文件和最终的`HTML`格式图形化文件 |
| `MAKE_SEGMENT` | 构建单元中的片段文件, 开发者唯一需要编辑的文件, 指导构建系统如何编译该文件所在的构建单元 |
| `OUTPUT_DIR` | 编译树中间目录 |
| `PACKAGE_DIR` | 打包目录, 其中可以存放其它组件, 也可以存放压缩包形式的第三方软件, 例如`openssl-0.9.8.tar.gz`等 |
| `RULE_DIR` | 构建系统核心目录, 如果不喜欢`build-rules`存放在自己的工程里, 完全可以通过这个变量把它移出去 |
| `TOP_DIR` | 工程的顶级目录, 默认就是顶层`makefile`所在的路径, 极少改动 |
可以完全不对它们做任何改动, 依照上文的含义和默认值来排布自己工程
---
也可以通过顶层目录的`project.mk`, 可以改动它们, 例如:
$ cat project.mk
MAKE_SEGMENT := alink.mk
则表示在每个构建单元中, 指导构建过程的片段文件不再是默认的`iot.mk`, 而是`alink.mk`

View file

@ -0,0 +1,16 @@
# 构建系统调试
## 调试开关
* 在`make ...`命令行中, 设置`TOP_Q`变量为空, 可打印工程顶层的执行逻辑, 例如硬件平台的选择, SDK主库的生成等
make .... TOP_Q=
* 在`make ...`命令行中, 设置`Q`变量为空, 可打印模块内部的构建过程, 例如目标文件的生成, 头文件搜寻路径的组成等
make .... Q=
## 对单个构建单元调试
* 可以用`make foo/bar`单独对`foo/bar`进行构建, 不过, 这可能需要先执行`make reconfig`
* 可以进入`.O/foo/bar`路径, 看到完整的编译临时目录, 有makefile和全部源码, 所以在这里执行`make`, 效果和`make foo/bar`等同

View file

@ -0,0 +1,124 @@
# 如何获取
* 可访问样板组件`LITE-utils`的仓库: [*git@gitlab.alibaba-inc.com:iot-middleware/LITE-utils.git*](http://gitlab.alibaba-inc.com/iot-middleware/LITE-utils)
* 从`master`分支的`build-rules`目录复制得到构建系统的最新副本
* 也可以直接在`LITE-utils`中体验构建系统的工作方式和观察工作过程
# 常用命令
| 命令 | 解释 |
|-----------------------|-----------------------------------------------------------------------------------|
| `make distclean` | **清除一切构建过程产生的中间文件, 使当前目录仿佛和刚刚clone下来一样** |
| `make [all]` | **使用默认的平台配置文件开始编译** |
| `make reconfig` | **弹出多平台选择菜单, 用户可按数字键选择, 然后根据相应的硬件平台配置开始编译** |
| `make config` | **显示当前被选择的平台配置文件** |
| `make help` | **打印帮助文本** |
| `make <directory>` | **单独编译被<directory>指定的目录, 或者叫构建单元** |
# 如何开发
* 访问[**构建系统配置**](https://code.aliyun.com/edward.yangx/public-docs/wikis/build/build-system-config), 了解如何配置来影响构建系统的行为
* 访问[**构建工程说明**](https://code.aliyun.com/edward.yangx/public-docs/wikis/build/build-system-proj), 了解如何定制工程全局的编译
* 访问[**构建单元说明**](https://code.aliyun.com/edward.yangx/public-docs/wikis/build/build-system-units), 了解如何增删改查你自己的构建单元
* 访问[**构建系统调试**](https://code.aliyun.com/edward.yangx/public-docs/wikis/build/build-system-debug), 了解在定制构建单元时, 如何自己调试
# 高级命令
| 命令 | 解释 |
|-----------------------|-------------------------------------------------------------------------------------------|
| `make test` | **运行指定的测试集程序, 统计显示测试例的通过率和源代码的覆盖率** |
| `make doc` | **扫描源码目录中以`Doxygen`格式或者`Markdown`格式编写的注释, 在`html`目录产生帮助文档** |
| `make repo-list` | **列出当前工程引用的外部组件和它们的云端仓库地址** |
| `make repo-update` | **对所有引用到的外部组件, 用云端仓库更新本地仓库** |
# 组成部分
LITE-utils$ tree -A -L 1
.
+-- build-rules # 构建系统核心
+-- example
+-- external
+-- makefile # 工程的makefile
+-- packages
+-- project.mk # 工程设置文件
+-- src
+-- testsuites
> 以`LITE-utils`为例, 对整个构建过程需要知道的只有如上三个部分:
| 组成部分 | 说明 |
|---------------|-------------------------------------------------------------------------------|
| `project.mk` | 本工程的目录排布, 工程名称, 版本信息等, 可选 |
| `makefile` | 本工程的makefile, 基于`GNU Make`, 通常只含有极少的内容, 指定编译的范围, 必选 |
| `build-rules` | 构建系统核心, 指定编译的规则, 不需要关注 |
# 工作过程
可以从一个简单的`makefile`样例看起
1 sinclude project.mk
2 sinclude $(CONFIG_TPL)
3
4 SUBDIRS += \
5 external/cut \
6 src \
7 example \
8 testsuites \
9
10 include $(RULE_DIR)/rules.mk
0. 构建系统是基于`GNU Make`的简化系统, 所以工作过程的起点仍然是顶层的`makefile`
1. 读取`project.mk`, 如果当前工程的目录排布和默认的不一样, 则用当前设置, 可选
2. 读取`.config`文件, 这个文件其实是构建系统运行时所有输入的集合, 也称为*硬件平台配置文件*, 可选
3. 读取`SUBDIRS`变量, 这个变量指定了编译的范围, 必选
4. 读取`CFLAGS`或者`LDFLAGS`等变量, 顶层`makefile`的变量会被应用到每个构建单元的编译和链接, 可选
5. 读取`.../rules.mk`文件, 开始进入构建系统核心, 必选, 这又可以细分为如下过程
## 详细工作过程
* 产生*硬件平台配置文件*, 这个过程是为了产生顶层的`.config`文件, 也就是所谓的`$(CONFIG_TPL)`
* 识别构建单元, 所谓构建单元在构建系统看来就是一个又一个包含`iot.mk`的目录, 如果不希望用`iot.mk`作为每个单元的编译片段文件, 在`project.mk`中设置`MAKE_SEGMENT`变量即可
* 从`$(SUBDIRS)`变量从前往后逐个编译每个构建单元
* 构建单元如果有依赖到其它构建单元, 则先去编译被依赖的单元; 若后者又有依赖的其它的单元, 则同样, 递归的先去编译其依赖; 以此类推
# 高级命令示例
- **make test: 运行指定的测试集程序, 统计显示测试例的通过率和源代码的覆盖率**
![image](https://yuncodeweb.oss-cn-hangzhou.aliyuncs.com/uploads/edward.yangx/public-docs/52c806dd879f18cd7ea855a8549461f6/image.png)
- **make doc: 扫描源码目录中以`Doxygen`格式或者`Markdown`格式编写的注释, 在`html`目录产生帮助文档**
LITE-utils $ make doc
...
...
Patching output file 15/16
Patching output file 16/16
lookup cache used 256/65536 hits=882 misses=258
finished...
![image](https://yuncodeweb.oss-cn-hangzhou.aliyuncs.com/uploads/edward.yangx/public-docs/b9ea5662e866913efcaca28549d9f033/image.png)
- **make repo-list: 列出当前工程引用的外部组件和它们的云端仓库地址**
LITE-utils $ make repo-list
[external/log] git@gitlab.alibaba-inc.com:iot-middleware/LITE-log.git
> 以上输出表示在构建单元`external/log`, 引用了云端仓库位于`git@gitlab.alibaba-inc.com:iot-middleware/LITE-log.git`的外部组件`LITE-log`
- **make repo-update: 将所有引用的外部组件用云端仓库更新本地仓库**
LITE-utils $ make repo-update
[ LITE-log.git ] <= : git@gitlab.alibaba-inc.com:iot-middleware/LITE-log.git :: master
+ cd /home/edward/srcs/iot-middleware/LITE-utils/packages
+ rm -rf LITE-log.git
+ git clone -q --bare -b master --single-branch git@gitlab.alibaba-inc.com:iot-middleware/LITE-log.git LITE-log.git
+ rm -rf LITE-log.git/hooks/
+ mkdir -p LITE-log.git/hooks/
+ touch LITE-log.git/hooks/.gitkeep
+ touch LITE-log.git/refs/heads/.gitkeep LITE-log.git/refs/tags/.gitkeep
+ rm -rf /home/edward/srcs/iot-middleware/LITE-utils.pkgs/LITE-log
+ cd /home/edward/srcs/iot-middleware/LITE-utils
+ set +x
> 以上输出表示从`git@gitlab.alibaba-inc.com:iot-middleware/LITE-log.git`拉取最新的云端仓库, 更新到本地仓库`packages/LITE-log.git`

View file

@ -0,0 +1,39 @@
# 定制工程全局的编译行为
## 增加硬件平台配置文件
在默认的`configs`目录, 或者在指定的`$(CONFIG_DIR)`目录下, 文件名形式为`config.<VENDOR>.<MODEL>`的文本文件, 会被构建系统认为是硬件平台配置文件, 每个文件对应一个嵌入式软硬件平台
* 其中<VENDOR>部分, 一般是指明嵌入式平台的软件OS提供方, 如`mxchip`, `ubuntu`, `win7`等. 另外, 这也会导致构建系统到`$(IMPORT_DIR)/<VENDOR>`目录下寻找预编译库的二进制库文件和头文件
* 其中<MODEL>部分, 一般是标明嵌入式平台的具体硬件型号, 如`mtk7687`, `qcom4004`等, 不过也可以写上其它信息, 因为构建系统不会去理解它, 比如`mingw32`, `x86-64`
> 例如`config.mxchip.3080c`文件, 如果在`make reconfig`的时候被选择, 则会导致:
* 构建系统在`import/mxchip/`目录下寻找预编译库的二进制库文件和头文件
* 构建系统使用该文件内的变量指导编译行为, 具体来说, 可以根据说明使用如下变量
| 变量 | 说明 |
|-----------------------|-------------------------------------------|
| `CONFIG_ENV_CFLAGS` | 指定全局的`CFLAGS`编译选项, 传给`compiler`, 例如`CONFIG_ENV_CFLAGS += -DDEBUG` |
| `CONFIG_ENV_LDFLAGS` | 指定全局的`LDFLAGS`链接选项, 传给`linker`, 例如`CONFIG_ENV_LDFLAGS += -lcrypto` |
| `CROSS_PREFIX` | 指定交叉编译工具链共有的前缀, 例如`CROSS_PREFIX := arm-none-eabi-`, 会导致构建系统使用`arm-none-eabi-gcc``arm-none-eabi-ar`, 以及`arm-none-eabi-strip`等 |
| `OVERRIDE_CC` | 当交叉工具链没有共有的前缀或者前缀不符合`prefix+gcc|ar|strip`类型时, 例如`armcc`, 可用`OVERRIDE_CC = armcc`单独指定C编译器 |
| `OVERRIDE_AR` | 当交叉工具链没有共有的前缀或者前缀不符合`prefix+gcc|ar|strip`类型时, 例如`armar`, 可用`OVERRIDE_AR = armar`单独指定库压缩器 |
| `OVERRIDE_STRIP` | 当交叉工具链没有共有的前缀或者前缀不符合`prefix+gcc|ar|strip`类型时, 例如`armcc`没有对应的strip程序, 可用`OVERRIDE_STRIP = true`单独指定strip程序不执行 |
## 定制单元测试
如果你的工程含有配合构建系统的单元测试用例, 则可以在顶层`makefile`中添写类似如下语句, 告诉构建系统在`make test`命令中执行它们做单元测试, 并统计源码覆盖率
UTEST_PROG := utils-tests
> 以上面的`LITE-utils`为例, 其中的`utils-tests`就是它的单元测试程序, 这是在构建单元`testsuites`中产生的一个`Linux`下可执行程序
$ cat testsuites/iot.mk -n
1 TARGET := utils-tests
2 DEPENDS += external/cut src
3 HDR_REFS := src
4
5 LDFLAGS += -llite-utils -llite-log -llite-cut
为什么如上的一个简单`iot.mk`片段文件, 就能指导构建系统生成可执行程序`utils-tests`, 可以访问[**构建单元说明**](https://code.aliyun.com/edward.yangx/public-docs/wikis/build/build-system-units)

View file

@ -0,0 +1,130 @@
# 构建单元说明
## 定义
* 片段文件: 用来指导某个具体的文件夹下源码应如何获取和编译以及链接的makefile文本片段, 基本只包含变量的赋值
* 默认的片段文件是名为`iot.mk`的文本文件, 可以在工程顶层目录`project.mk`里, 用`MAKE_SEGMENT := <new>`更改片段文件名
* 从工程顶层目录以下, 每一个含有`iot.mk`的子目录, 都被构建系统认为是一个构建单元
> 举例来说:
> 假设在/path/to/project/project.mk文件中有
>
> MAKE_SEGEMENT := build.mk
> 那么, 如下的目录排布
>
> /path/to/project/bar/build.mk
> /path/to/project/foo/sub1/build.mk
> /path/to/project/foo/sub2/build.mk
> /path/to/project/mmm/nnn/ppp/qqq/build.mk
> 会导致
>
> bar
> foo/sub1
> foo/sub2
> mmm/nnn/ppp/qqq
> 都被认为是构建单元, 可以用类似`make bar`, `make foo/bar1`这样的命令单独编译, 也可以调试完成后通过修改顶层`makefile`集成到工程中
## 工作过程
对整个工程进行构建的过程基本是遍历每个构建单元逐个构建, 而对每个构建单元的构建过程是:
* 构造编译的临时目录, 例如 `.O/bar` 目录, 对应源码 `bar` 构建单元
* 在编译的临时目录中动态生成或更新`makefile`和源代码
* 切换到临时目录中, 编译源代码, 产生目标代码
## 开发过程
增加一个新的构建单元可以按如下步骤进行:
* 创建新单元对应的目录, 比如
mkdir foo/bar
* 创建该单元的片段文件, 比如
vi foo/bar/iot.mk
1 LIBA_TARGET := libfoobar.a
* 为该单元添加一些源码文件, 比如
cp .../*.c foo/bar/
* 这时, 在工程文件中运行`make reconfig`, 告诉构建系统新增了一个单元, 这个单元就可以被独立编译了
make reconfig
make foo/bar
* 单独的编译和运行没问题之后, 修改工程的`makefile`, 使这个新单元也加入到工程中
vi makefile
...
...
SUBDIRS += foo/bar
...
...
## 编写片段文件
**简化编译的设计思想就是使每一个模块的开发者, 基本只需要编写片段文件就能构建自己的功能模块**
**而片段文件之所以能够起到简化的效果, 是因为它基本上只是一些"变量赋值"语句的集合, 编写它, 几乎可以不需要学习任何语言的任何语法**
---
以下是在片段文件中可以使用的变量名:
### 输出相关
| 变量名 | 用处 |
|-------------------|-----------------------------------------------------------------------------------------------|
| ORIGIN | 如果你的模块希望按自己独特的方式编译, 比如`./configure ...; make; ...`, 需要设置此变量为1 |
| LIBSO_TARGET | 设置本单元被编译出的`Linux`动态库文件名, 对它赋值导致系统帮助你产生`*.so`共享库文件 |
| LIBA_TARGET | 设置本单元被编译出的静态库文件名, 对它赋值导致系统帮助你产生`*.a`静态库文件 |
| TARGET | 设置本单元被编译出的可执行程序文件名, 对它赋值导致系统帮助你产生`Linux`下的可执行程序 |
| KMOD_TARGET | 设置本单元被编译出的内核模块文件名, 对它赋值导致系统帮助你产生`Linux`下的`*.ko`内核模块 |
**以上变量至少要有一个被设置, 这样构建系统才知道构建的输出是什么, 至多则可以同时被设置, 例如同时产生静态库文件和可执行程序, 甚至内核模块等**
### 输入相关
| 变量名 | 用处 |
|-------------------|-----------------------------------------------------------------------------------------------|
| LIB_SRCS | 可选, 列出哪些`*.c`文件被编译成`*.a`或者`*.so` |
| SRCS | 可选, 列出哪些`*.c`文件被编译成可执行程序 |
| EXTRA_SRCS | 可选, 列出哪些源文件需要在开始编译之前被复制到临时的编译目录 |
| CFLAGS | 可选, 列出需要特别应用在本模块上的编译选项 |
| LDFLAGS | 可选, 列出需要特别应用在本模块上的链接选项 |
### 组合相关
| 变量名 | 用处 |
|-------------------|-----------------------------------------------------------------------------------------------|
| HDR_REFS | 可选, 如果你的模块引用了其它模块的头文件, 那么需要设置这个变量, 列出被引用模块在工程里的相对路径 |
| DEPENDS | 可选, 如果你的模块需要在其它模块构建完成后才能编译, 那么需要设置这个变量, 列出被依赖模块在工程里的相对路径 |
### 高级用法
| 变量名 | 用处 |
|-------------------|-----------------------------------------------------------------------------------------------|
| PKG_SOURCE | 可选, 表示源码来自`*.c`之外的形式, 例如压缩包文件, 或者独立的git仓库等 |
| PKG_BRANCH | 可选, 仅在`PKG_SOURCE`是git仓库的时候才有意义, 指定使用该仓库的哪个分支作为源码输入 |
| PKG_REVISION | 可选, 仅在`PKG_SOURCE`是git仓库的时候才有意义, 指定使用该仓库的哪个分支上的哪个`commit`或者`tag` |
| PKG_UPSTREAM | 可选, 仅在`PKG_SOURCE`是git仓库的时候才有意义, 指定使用哪个云端的git仓库地址来更新本地git仓库 |
### 其它
#### 产生多个可执行程序
* 如果你的模块希望产生单个的可执行程序, 那么对变量`TARGET``SRCS`赋值就可以了, 但如果希望产生多个可执行程序, 比如
TARGET = prog1 prog2 prog3
* 那么需要用`SRCS_<name>`变量对这多个可执行程序分别设定他们的源文件, 比如
SRCS_prog1 = prog1.c
SRCS_prog2 = prog2.c library_A.c
SRCS_prog3 = prog3.c library_A.c library_B.c

View file

@ -0,0 +1,24 @@
常用命令
---
| 命令 | 解释 |
|-----------------------|-----------------------------------------------------------------------------------|
| `make distclean` | **清除一切编译过程产生的中间文件, 使当前目录仿佛和刚刚clone下来一样** |
| `make [all]` | **使用默认的平台配置文件开始编译** |
| `make reconfig` | **弹出多平台选择菜单, 用户可按数字键选择, 然后根据相应的硬件平台配置开始编译** |
| `make config` | **显示当前被选择的平台配置文件** |
| `make menuconfig` | **图形化的编辑 make.settings 文件** |
| `make help` | **打印帮助文本** |
| `make env` | **打印当前编译的选项和它们的值** |
| `make <directory>` | **单独编译被 <directory> 指定的目录, 或者叫编译单元** |
高级命令
---
| 命令 | 解释 |
|-----------------------|-----------------------------------------------------------------------------------|
| `make repo-list` | 列出当前可以更新的组件列表, 所谓组件是跨项目的功能模块, 有独立的`git`仓库 |
| `make repo-update` | 根据输入更新所有组件或单个被选择的组件, 从线上获取其最新的`git`仓库 |
| `make test` | 如果当前项目有编写单元测试主程序和单元测试例, 则执行UT, 统计通过率和覆盖率 |
o 访问 https://code.aliyun.com/edward.yangx/public-docs/wikis/home 可获得编译系统线上最新和最全的帮助文档

View file

@ -0,0 +1,259 @@
define Append_Conditional
$(if $(strip $(foreach V,$(4),$(filter -D$(V),$(CFLAGS)))),, \
$(if \
$(findstring $(foreach U,$(3),-D$(U)),$(foreach U,$(3),$(filter -D$(U),$(CFLAGS)))), \
$(eval $(strip $(1)) += $(2)) \
) \
)
endef
define Dump_Var
NUM=`echo "$(strip $($(1)))"|awk '{ print NF }'`; \
if (( $${NUM} \> 1 )); then \
printf -- "-----------------------------------------------------------------\n"; \
printf "%-24s| %s\n" ". $(1)" `echo "$(strip $($(1)))"|cut -d' ' -f1|$(SED) 's/^ *//'`; \
for i in `echo "$(strip $($(1)))"|cut -d' ' -f2-`; do \
printf "%-24s| %s\n" "" "$${i}"; \
done; \
printf -- "-----------------------------------------------------------------\n"; \
else \
printf "%-24s| %s\n" ". $(1)" "$(strip $($(1)))"; \
fi;
endef
ifneq (,$(Q))
define Inspect_Env
endef
else
define Inspect_Env
@printf -- "-----------------------------------------------------------------\n"
@printf "%-20s| %s\n" ". BUILDING_TARGET" "$@"
@printf -- "-----------------------------------------------------------------\n"
@printf "%-20s| %s\n" ". BUILDING_DEPEND" "$(filter-out FORCE,$^)"
@printf -- "-----------------------------------------------------------------\n"
@$(foreach var,$(1),$(call Dump_Var,$(var)))
@printf -- "-----------------------------------------------------------------\n"
endef
endif
# 31, red. 32, green. 33, yellow. 34, blue. 35, magenta. 36, cyan. 37, white.
define Brief_Log
( \
if [ "$1" = "CC" ]; then \
if echo "$@"|grep -q "\.so$$"; then \
COLOR_MARK="\033[1;32m"; \
elif echo "$@"|grep -q "\.ko$$"; then \
COLOR_MARK="\033[1;35m"; \
else \
COLOR_MARK="\033[1;36m"; \
fi \
elif [ "$1" = "AR" ]; then \
COLOR_MARK="\033[1;33m"; \
elif [ "$1" = "LD" ]; then \
COLOR_MARK="\033[1;31m"; \
elif [ "$1" = "ST" ]; then \
COLOR_MARK="\033[0;33m"; \
fi; \
if [ "$(PLAIN_LOG)" != "1" ]; then \
echo -ne "$${COLOR_MARK}"; \
fi; \
if [ "$2" = "" ]; then \
FIRST_DEP="$(firstword $(filter-out FORCE,$?))"; \
SPACE_BAR=" "; \
if [ "$${FIRST_DEP}" != "" ]; then \
FIRST_DEP="$$(basename $${FIRST_DEP})"; \
fi; \
printf "\r%-40s%s%s$(3)\n" "[$1] $$(echo -n "$$(basename $@)" | cut -c1-28)" "<= $${FIRST_DEP} $${SPACE_BAR}"; \
else \
printf "\r%-40s%s%s$(3)\n" "[$1] $$(echo -n "$(2)" | cut -c1-28)" "<= $${FIRST_DEP} $${SPACE_BAR}"; \
fi; \
if [ "$3" != "..." ]; then \
for i in $(wordlist 2,150,$(filter-out FORCE,$?)); do \
if [ "$$(echo $${i}|cut -c1)" != "/" ]; then \
printf "%-40s%s$(3)\n" "" " $$(basename $${i})"; \
fi \
done; \
fi; \
if [ "$(PLAIN_LOG)" != "1" ]; then \
echo -ne "\033[0m"; \
fi; \
)
endef
define Copy_Headers
$(Q) \
if [ "$(strip $(1))" != "" ]; then \
mkdir -p $(2)/$(3); \
for hdr in $(1); do \
if [ ! -f $(2)/$(3)/$${hdr} ] || [ $${PWD}/$${hdr} -nt $(2)/$(3)/$${hdr} ]; then \
mkdir -p $(2)/$(3); \
cp -f $(TOP_DIR)/$(MODULE_NAME)/$${hdr} $(2)/$(3)/$$(basename $${hdr}); \
fi; \
done \
fi
endef
define Update_Extra_Srcs
( \
for ELEM in $(strip $(1)); do \
DST=$(OUTPUT_DIR)/$(2)/$$(basename $${ELEM}); \
if [ $${ELEM} -nt $${DST} ]; then \
cp -Lf $${ELEM} $${DST}; \
fi; \
done \
)
endef
define Require_Build
( \
SW=$$(grep -m 1 "^PKG_SWITCH_$(1) =" $(STAMP_BLD_VAR)|awk '{ print $$NF }'); \
[ "$${SW}" != "y" ] && \
echo "FALSE" && exit; set +x; \
\
[ "$(LIBA_TARGET_$(1))" != "" ] && \
$(foreach L,$(LIBA_TARGET_$(1)),[ -f $(IMPORT_VDRDIR)/$(PREBUILT_LIBDIR)/$(L) ] && ) \
echo "FALSE" && exit; \
\
[ "$(LIBSO_TARGET_$(1))" != "" ] && \
[ -f $(IMPORT_VDRDIR)/$(PREBUILT_LIBDIR)/$(LIBSO_TARGET_$(1)) ] && \
echo "FALSE" && exit; \
\
echo "TRUE"; \
)
endef
define Build_Depends
( \
set -o pipefail && \
for i in $(DEPENDS_$(1)); do \
STAMP=$(STAMP_DIR)/$$(echo $${i}|$(SED) 's:/:~:g').build.done; \
if [ -f $${STAMP} ]; then \
continue; \
fi; \
$(MAKE) --no-print-directory $${i} \
$(if $(Q),,2>&1|tee -a $(OUTPUT_DIR)/$${i}/$(COMPILE_LOG)) \
$(if $(Q),,2>&1|tee -a $(OUTPUT_DIR)/$(COMPILE_LOG)); \
RETVAL=$$?; \
if [ $${RETVAL} != 0 ]; then \
exit $${RETVAL}; \
fi; \
done \
\
)
endef
#
# ($(foreach d,$(COMP_LIB_COMPONENTS), \
#
# $(RECURSIVE_MAKE) pre-build target-$(d) && \
# $(MAKE) --no-print-directory -C $(OUTPUT_DIR)/$(d) $(LIBA_TARGET_$(d)) \
# $(if $(Q),,2>&1|tee -a $(OUTPUT_DIR)/$(d)/$(COMPILE_LOG)) \
# $(if $(Q),,2>&1|tee -a $(OUTPUT_DIR)/$(COMPILE_LOG)) \
# ; \
#
# if [ $$? != 0 ]; then \
#
# KEEP SEPA-LIBS:
#
# rm -f $(SYSROOT_LIB)/$(firstword $(LIBA_TARGET_$(d))) $(SYSROOT_LIB)/$(firstword $(LIBSO_TARGET_$(d))) 2>/dev/null; \
#
ifdef COMP_LIB
define Build_CompLib
( \
if [ "$(strip $(1))" = "FORCE" ] || \
[ "$$(echo $(LDFLAGS_$(strip $(1)))|grep -wo -- '-l$(COMP_LIB_NAME)')" != "" ]; then \
( \
$(foreach d,$(COMP_LIB_COMPONENTS), \
[ -f $(STAMP_DIR)/$(subst /,~,$(d)).build.done ] || \
set -o pipefail && \
$(MAKE) --no-print-directory -C $(OUTPUT_DIR)/$(d) $(firstword $(LIBA_TARGET_$(d))) $(firstword $(LIBSO_TARGET_$(d))) && set +x; \
RETVAL=$$?; \
if [ $${RETVAL} != 0 ]; then \
exit $${RETVAL}; \
fi; \
) \
); \
if [ ! -f $(SYSROOT_LIB)/$(COMP_LIB) ]; then \
$(call Info_CompLib,$(COMP_LIB_NAME),$(COMP_LIB_OBJS)); \
fi; \
$(call Finalize_CompLib,$(COMP_LIB_OBJS),$(SYSROOT_LIB),$(COMP_LIB_NAME)); \
fi \
)
endef
else
define Build_CompLib
true
endef
endif
define Relative_TcPath
( \
case $(1) in \
xtensa-lx106-elf-gcc ) \
echo "gcc-xtensa-lx106-linux/main/bin" ;; \
arm-none-eabi-gcc ) \
echo "gcc-arm-none-eabi-linux/main/bin" ;; \
esac \
)
endef
define Gitrepo_TcPath
( \
case $(1) in \
xtensa-lx106-elf-gcc ) \
echo "gcc-xtensa-lx106-linux" ;; \
arm-none-eabi-gcc ) \
echo "gcc-arm-none-eabi-linux" ;; \
esac \
)
endef
define CompLib_Map
$(eval \
COMP_LIB_COMPONENTS += \
$(if \
$(filter y,$($(strip $(1)))),$(foreach M,$(strip $(2)),$(if $(filter $(strip $(M)),$(COMP_LIB_COMPONENTS)),,$(strip $(M)))) \
) \
)
endef
OMIT_GOALS := distclean clean env help config reconfig menuconfig
ifeq (,$(filter $(OMIT_GOALS),$(MAKECMDGOALS)))
define Conflict_Relation
$(if $(filter y,$($(strip $(1)))), \
$(if $(filter y,$($(strip $(2)))), \
$(error INVALID CONFIG: '$(strip $(1)) = $($(strip $(1)))' conflicts with '$(strip $(2)) = $($(strip $(2)))' at same time!), \
), \
)
endef
define Present1_Relation
$(if $(filter n,$($(strip $(1)))), \
$(if $(filter n,$($(strip $(2)))), \
$(error INVALID CONFIG: '$(strip $(1)) = $($(strip $(1)))' conflicts with '$(strip $(2)) = $($(strip $(2)))' at same time!), \
), \
)
endef
define Requires_Relation
$(if $(filter y,$($(strip $(1)))), \
$(if $(filter y,$($(strip $(2)))),, \
$(error INVALID CONFIG: '$(strip $(2)) = $($(strip $(2)))' breaks dependency since '$(strip $(1)) = $($(strip $(1)))'!), \
), \
)
endef
else # ifeq (,$(filter $(OMIT_GOALS),$(MAKECMDGOALS)))
define Conflict_Relation
endef
define Present1_Relation
endef
define Requires_Relation
endef
endif # ifeq (,$(filter $(OMIT_GOALS),$(MAKECMDGOALS)))

View file

@ -0,0 +1,23 @@
#!/bin/sh
#
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-commit".
for i in `git status -s | awk '{ print $NF }'`; do
j=$(echo $(basename $i)|cut -d'.' -f2)
if [ "$j" = "c" -o "$j" = "h" -o "$j" = "md" -o "$j" = "mk" ] || [ "$i" = "makefile" -o "$i" = "make.settings" ]; then
if [ "$(find $i -perm /111 2>/dev/null)" != "" ]; then
chmod a-x $i
echo "[chmod] $i"
if [ "$(git status --short $i|cut -c1)" = "M" ]; then
git add $i
fi
fi
else
echo "[skip ] $i"
fi
done

View file

@ -0,0 +1,8 @@
CONFIG_ENV_CFLAGS += \
-Os -Wall \
-D_PLATFORM_IS_HOST_ \
-DCONFIG_HTTP_AUTH_TIMEOUT=5000 \
-DCONFIG_MID_HTTP_TIMEOUT=5000 \
-DCONFIG_GUIDER_AUTH_TIMEOUT=10000 \
LDFLAGS += -lpthread -lrt

View file

@ -0,0 +1,2 @@
CONFIG_ENV_CFLAGS += -Wall
CONFIG_ENV_CFLAGS += --coverage

View file

@ -0,0 +1,192 @@
#include "cut.h"
struct cut_runtime cut;
static char suite_pattern[64];
static char case_pattern[64];
static void _filter(int argc, char **argv)
{
int i = 0;
struct cut_case *c = NULL;
if (argc == 2 && 0 == strcmp(argv[1], "all")) {
return;
}
for (i = 0; i < cut.ccnt_total; i++) {
c = cut.clist[i];
if ((argc == 2 && (0 != strcmp(c->sname, argv[1]))) ||
(argc == 3 && (0 != strcmp(c->sname, argv[1]) || 0 != strcmp(c->cname, argv[2])))) {
if (!(argc == 2 && strlen(suite_pattern) && strstr(c->sname, suite_pattern))) {
cut.clist[i]->skip = 1;
cut.ccnt_skip++;
}
}
}
}
static void _usage(const char *me)
{
cut_printf("Usage: %s [OPTION] S-FILTER [C-FILTER]\n\n" \
"OPTION:\n" \
" --verbose: verbose when exec cases\n" \
" --list: list cases\n" \
" --count: print case count\n" \
"\n" \
"S-FILTER: suite name filter, e.g. '%s all' means run all suites\n" \
"C-FILTER: case name filter\n", me, me);
}
static int _verbose_opt = 0;
static int _parse_arg(int argc, char **argv)
{
if (argc >= 2) {
if (0 == strcmp(argv[1], "--list")) {
int i = 0;
int cnt = 0;
for (i = 0; i < cut.ccnt_total; i++) {
struct cut_case *c = cut.clist[i];
if (argc == 2 ||
(argc == 3 && 0 == strcmp(argv[2], "all")) ||
(argc == 3 && 0 == strcmp(c->sname, argv[2])) ||
(argc == 3 && strlen(suite_pattern) && strstr(c->sname, suite_pattern)) ||
(argc == 4 && strlen(suite_pattern) && strlen(case_pattern) && strstr(c->sname, suite_pattern)
&& strstr(c->cname, case_pattern)) ||
(argc == 4 && 0 == strcmp(c->sname, argv[2]) && 0 == strcmp(c->cname, argv[3]))) {
cut_printf(" [%02d] %s.%s\n", ++cnt, c->sname, c->cname);
}
}
cut_printf("\n");
cut_printf("In total %d case(s), matched %d case(s)\n", cut.ccnt_total, cnt);
cut_printf("\n");
return 0;
}
if (0 == strcmp(argv[1], "--count")) {
cut_printf("total %d case(s).\n", cut.ccnt_total);
return 0;
}
if (0 == strcmp(argv[1], "--help")) {
_usage(argv[0]);
return 0;
}
}
return 1;
}
int cut_main(int argc, char **argv)
{
int i = 0, j = 0, cnt = 0;
char tmpbuf[128];
char *pos;
if (argc >= 2) {
int idx = 1;
char *q = NULL;
if (!strcmp(argv[1], "--list") || !strncmp(argv[1], "--verbose", strlen("--verbose"))) {
idx += 1;
}
if (idx < argc) {
if ((q = strchr(argv[idx], '%')) != NULL) {
strncpy(suite_pattern, argv[idx], q - argv[idx]);
}
idx += 1;
if (idx < argc) {
if ((q = strchr(argv[idx], '%')) != NULL) {
strncpy(case_pattern, argv[idx], q - argv[idx]);
}
}
}
}
if (0 == _parse_arg(argc, argv)) {
return 0;
}
if (argc >= 2 && !strncmp(argv[1], "--verbose", strlen("--verbose"))) {
_verbose_opt = 1;
argc --;
argv ++;
}
_filter(argc, argv);
for (; i < cut.ccnt_total; i++) {
pos = tmpbuf;
cut.ccur = cut.clist[i];
if (cut.ccur->skip) {
continue;
}
memset(tmpbuf, 0, sizeof(tmpbuf));
pos += cut_snprintf(pos,
sizeof(tmpbuf),
"TEST [%02d/%02d] %s.%s ",
++cnt,
cut.ccnt_total - cut.ccnt_skip,
cut.ccur->sname,
cut.ccur->cname);
for (j = 80 - strlen(tmpbuf); j >= 0; --j) {
pos += sprintf(pos, "%s", ".");
}
if (_verbose_opt) {
pos += sprintf(pos, " [%sEXEC%s]\n", COL_YEL, COL_DEF);
cut_printf("%s", tmpbuf);
pos -= 19;
}
TRY {
if (cut.ccur->setup)
{
cut.ccur->setup(cut.ccur->data, cut.ccur);
}
cut.ccur->run(cut.ccur->data, (struct cut_case *)cut.ccur);
if (cut.ccur->teardown)
{
cut.ccur->teardown(cut.ccur->data);
}
pos += sprintf(pos, " [%sSUCC%s]\n", COL_GRE, COL_DEF);
cut_printf("%s", tmpbuf);
cut.ccnt_pass++;
continue;
}
EXCEPT {
pos += sprintf(pos, " [%sFAIL%s]\n", COL_RED, COL_DEF);
cut_printf("%s", tmpbuf);
cut.ccnt_fail++;
continue;
}
}
cut_printf("\n");
cut_printf("===========================================================================\n");
if (cut.ccnt_fail > 0) {
cut_printf("FAIL LIST:\n");
for (i = 0; i < cut.ccnt_fail; i++) {
cut_printf(" [%02d] %s\n", i + 1, cut.cerrmsg[i]);
cut_free(cut.cerrmsg[i]);
}
cut_printf("---------------------------------------------------------------------------\n");
}
cut_printf("SUMMARY:\n" \
" TOTAL: %d\n" \
" SKIPPED: %d\n" \
" MATCHED: %d\n" \
" PASS: %d\n" \
" FAILED: %d\n", cut.ccnt_total, cut.ccnt_skip,
cut.ccnt_total - cut.ccnt_skip, cut.ccnt_pass, cut.ccnt_fail);
cut_printf("===========================================================================\n");
return cut.ccnt_fail;
}

View file

@ -0,0 +1,249 @@
#ifndef __CUT_H__
#define __CUT_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <setjmp.h>
#include <string.h>
#include <assert.h>
#define CUT_CASE_MAX_CNT (1024)
#define CUT_MSG_MAX_LEN (512)
#define cut_printf printf
#define cut_snprintf snprintf
#define cut_malloc malloc
#define cut_free free
#define CASE2 CASEs
extern int cut_main(int argc, char **argv);
extern struct cut_runtime cut;
struct cut_case {
const char *sname;
const char *cname;
void *data;
void (*run)(void *, void *);
void (*setup)(void *, void *);
void (*teardown)(void *);
int skip;
};
struct cut_runtime {
jmp_buf jmpbuf;
int scnt_total;
int ccnt_total;
int ccnt_pass;
int ccnt_fail;
int ccnt_skip;
struct cut_case *clist[CUT_CASE_MAX_CNT];
struct cut_case *ccur;
char *cerrmsg[CUT_CASE_MAX_CNT];
};
#define CUT_CASE_RUNNER(sname, cname) cut_##sname##_##cname##_run
#define CUT_CASE_NAME(sname, cname) cut_##sname##_##cname
#define CUT_CASE_DATA(sname) cut_##sname##_data
#define CUT_CASE_SETUP(sname) cut_##sname##_setup
#define CUT_CASE_TEARDOWN(sname) cut_##sname##_teardown
#define DATA(sname) \
struct CUT_CASE_DATA(sname)
#define SETUP(sname) \
static void CUT_CASE_SETUP(sname)(struct CUT_CASE_DATA(sname) *data, struct cut_case *case_data)
#define TEARDOWN(sname) \
static void CUT_CASE_TEARDOWN(sname)(struct CUT_CASE_DATA(sname) *data)
/*
* @brief: construct a test case structor and a test case runner
* @sname: suite name
* @cname: case name
* e.g.
CASE(mysuite, mycase1) {
// do something here
ASSERT_TRUE(1);
}
*/
#define CASE(sname, cname) \
static void CUT_CASE_RUNNER(sname, cname)(void *null, struct cut_case *case_data); \
static struct cut_case CUT_CASE_NAME(sname, cname) = \
{ \
#sname, #cname, NULL, (void(*)(void*,void*))CUT_CASE_RUNNER(sname, cname), NULL, NULL, 0}; \
static void CUT_CASE_RUNNER(sname, cname)(void *null, struct cut_case *case_data)
/*
* @brief: construct a test case structor and a test case runner
* with case_data/setup/teardown for each case.
* @sname: suite name
* @cname: case name
* e.g.
CASE_DATA(mysuite) {
int errmsg;
char *errcode;
};
CASE_SETUP(mysuite) {
data->errcode = 0;
data->errmsg = (char*)malloc(100);
}
CASE_TEARDOWN(mysuite) {
if(data->errmsg) {
free(data->errmsg);
data->errmsg = NULL;
}
}
CASEs(mysuite, mycase1) {
data->errcode = 1;
strcpy(data->errmsg, "timeout error");
ASSERT_TRUE(1);
}
*/
#define CASEs(sname, cname) \
static struct CUT_CASE_DATA(sname) CUT_CASE_DATA(sname); \
static void CUT_CASE_RUNNER(sname, cname)(struct CUT_CASE_DATA(sname) * data,struct cut_case *case_data); \
static struct cut_case CUT_CASE_NAME(sname, cname) = \
{ \
#sname, #cname, &CUT_CASE_DATA(sname), (void(*)(void*,void*))CUT_CASE_RUNNER(sname, cname), \
(void(*)(void*,void*))CUT_CASE_SETUP(sname), (void(*)(void*))CUT_CASE_TEARDOWN(sname), 0}; \
\
static void CUT_CASE_RUNNER(sname, cname)(struct CUT_CASE_DATA(sname) * data, struct cut_case *case_data)
/*
* @brief: construct a test suite by adding test case(s)
* @sname: suite name
* e.g.
SUITE(mysuite) = {
ADD_CASE(mysuite, mycase1),
ADD_CASE(mysuite, mycase2),
ADD_CASE_NULL
};
*/
#define SUITE(sname) struct cut_case *cut_suite_##sname[]
/*
* @brief: add a test case into a test suite
* @sname: suite name
* @cname: case name
*/
#define ADD_CASE(sname, cname) &CUT_CASE_NAME(sname, cname)
#define ADD_CASE_NULL (struct cut_case*)(NULL)
/*
* @brief: add a test suite into case list
* @sname: suite name
*/
#define ADD_SUITE(sname) \
do { \
int i = 0; \
extern struct cut_case *cut_suite_##sname[]; \
struct cut_case *c = cut_suite_##sname[i]; \
if (cut.ccnt_total >= CUT_CASE_MAX_CNT) { \
cut_printf("reaches maximum case count:%d\n", \
CUT_CASE_MAX_CNT); \
break; \
} \
while (c) { \
*(cut.clist + cut.ccnt_total++) = c; \
c = *(cut_suite_##sname + (++i)); \
} \
} while (0)
#define TRY if (0 == setjmp(cut.jmpbuf))
#define EXCEPT else
#define RAISE_EXCEPTION_WITH_MSG(msg) \
do { \
int ret = 0, i = cut.ccnt_fail; \
cut.cerrmsg[i] = (char*)cut_malloc(CUT_MSG_MAX_LEN); \
assert(cut.cerrmsg[i] != NULL); \
memset(cut.cerrmsg[i], 0, CUT_MSG_MAX_LEN); \
ret = cut_snprintf(cut.cerrmsg[i], \
CUT_MSG_MAX_LEN - 1, \
"%s.%s in %s(%d) expected %s", \
cut.ccur->sname, cut.ccur->cname, \
__FILE__, __LINE__, msg); \
if (ret >= CUT_MSG_MAX_LEN) \
cut_snprintf(cut.cerrmsg[i] + CUT_MSG_MAX_LEN - 4, \
4, "..."); \
longjmp(cut.jmpbuf, 1); \
} while (0)
#define ASSERT_TRUE(cond) \
do { \
if (!(cond)) \
RAISE_EXCEPTION_WITH_MSG("[True]"); \
} while (0)
#define ASSERT_INT(expected, compare, actual) \
do { \
if (!((expected)compare(actual))) \
RAISE_EXCEPTION_WITH_MSG("[" #expected " " #compare " " #actual "]"); \
} while (0)
#define ASSERT_STR(expected, compare, actual) \
do { \
if (!(strcmp((expected), (actual)) compare 0)) \
RAISE_EXCEPTION_WITH_MSG("[" #expected " " #compare " " #actual "]"); \
} while (0)
#define ASSERT_IN(expected1, actual, expected2) \
do { \
if ((actual) < (expected1) || (actual) > (expected2)) \
RAISE_EXCEPTION_WITH_MSG("[" #expected1 " <= " #actual " <= " #expected2 "]"); \
} while (0)
#define ASSERT_NSTR(expected, compare, actual, len) \
do { \
if (!(strncmp((expected), (actual), (len)) compare 0)) \
RAISE_EXCEPTION_WITH_MSG("[" #expected " " #compare " " #actual "]"); \
} while (0)
#define ASSERT_FAIL() RAISE_EXCEPTION_WITH_MSG("[should not be here]")
#define ASSERT_FALSE(cond) ASSERT_TRUE(!(cond))
#define ASSERT_NULL(ptr) ASSERT_INT(ptr, ==, NULL)
#define ASSERT_NOT_NULL(ptr) ASSERT_INT(ptr, !=, NULL)
#define ASSERT_EQ(actual, expected) ASSERT_INT(actual, ==, expected)
#define ASSERT_NE(actual, expected) ASSERT_INT(actual, !=, expected)
#define ASSERT_GT(actual, expected) ASSERT_INT(actual, >, expected)
#define ASSERT_GE(actual, expected) ASSERT_INT(actual, >=, expected)
#define ASSERT_LT(actual, expected) ASSERT_INT(actual, <, expected)
#define ASSERT_LE(actual, expected) ASSERT_INT(actual, <=, expected)
#define ASSERT_STR_EQ(actual, expected) ASSERT_STR(actual, ==, expected)
#define ASSERT_STR_NE(actual, expected) ASSERT_STR(actual, !=, expected)
#define ASSERT_STR_GT(actual, expected) ASSERT_STR(actual, >, expected)
#define ASSERT_STR_LT(actual, expected) ASSERT_STR(actual, <, expected)
#define ASSERT_NSTR_EQ(actual, expected, len) ASSERT_NSTR(actual, ==, expected, len)
#define ASSERT_NSTR_NE(actual, expected, len) ASSERT_NSTR(actual, !=, expected, len)
#define ASSERT_NSTR_GT(actual, expected, len) ASSERT_NSTR(actual, >, expected, len)
#define ASSERT_NSTR_LT(actual, expected, len) ASSERT_NSTR(actual, <, expected, len)
/*
* see http://stackoverflow.com/questions/3585846/color-text-in-terminal-applications-in-unix
*/
#define COL_DEF "\x1B[0m"
#define COL_RED "\x1B[1;31m"
#define COL_GRE "\x1B[1;32m"
#define COL_YEL "\x1B[1;33m"
#define COL_BLU "\x1B[1;34m"
#define COL_MAG "\x1B[1;35m"
#define COL_CYN "\x1B[1;36m"
#define COL_WHE "\x1B[1;37m"
#ifdef __cplusplus
}
#endif
#endif /* __CUT_H__ */

View file

@ -0,0 +1,194 @@
#! /bin/bash
if [ "$(uname)" = "Darwin" ]; then
SED=gsed
else
SED=sed
fi
function Trace()
{
if [ "${VERBOSE_PRE_BLD}" != "" ]; then
echo "$1" 1>&2
fi
}
function Update_Sources()
{
if [ -f ${BLD_DIR}/${STAMP_UNPACK} ]; then
Trace "Skipped @ ${BLD_DIR}/${STAMP_UNPACK}"
return 0
fi
if [ "${PKG_SWITCH}" = "" ]; then
Trace "Warning @ CONFIG_${MODULE} = '${PKG_SWITCH}'"
fi
Trace "MODULE_NAME: [${MODULE}]"
Trace "SRC_DIR: [${SRC_DIR}]"
Trace "BLD_DIR: [${BLD_DIR}]"
Trace "PACKAGE_DIR: [${PACKAGE_DIR}]"
Trace "PKG_SOURCE: [${PKG_SOURCE}]"
Trace "PKG_BRANCH: [${PKG_BRANCH}]"
Trace "PKG_REVISION: [${PKG_REVISION}]"
Trace "PKG_UPSTREAM: [${PKG_UPSTREAM}]"
for i in $(find -L ${MODULE} -type d -not -path "*.git*"|${SED} "s,${MODULE}/*,,1"|${SED} '/^$/d'); do
mkdir -p ${BLD_DIR}/${i}
done
if [ "${PKG_SOURCE}" != "" ] && [ -d ${PACKAGE_DIR}/${PKG_SOURCE} ]; then
GIT_BASENAME=$(basename ${PKG_SOURCE})
GIT_NAME_LEN=$(echo -n "${GIT_BASENAME}"|wc -c|awk '{ print $1 }')
GIT_OFFSET=$(( GIT_NAME_LEN - 3 ))
GIT_MOD_NAME=$(echo "${GIT_BASENAME}" | cut -c"1-$(( GIT_OFFSET-1 ))"|awk '{ print $1 }')
GIT_POSTFIX=$(echo "${GIT_BASENAME}" | cut -c"${GIT_OFFSET}-${GIT_NAME_LEN}"|awk '{ print $1 }')
Trace "GIT_POSTFIX: [${GIT_POSTFIX}]"
Trace "GIT_MOD_NAME: [${GIT_MOD_NAME}]"
fi
set +x
if [ "${GIT_POSTFIX}" = ".git" ]; then
GIT_COPY=${MODULE}/${GIT_MOD_NAME}
DEV_COPY_BASE=${TOP_DIR}.pkgs
Trace "GIT_COPY: [${GIT_COPY}]"
Trace "DEV_COPY_BASE: [${DEV_COPY_BASE}]"
eval "${CMDSET_X}"
mkdir -p ${DEV_COPY_BASE}
cd ${DEV_COPY_BASE}
if [ ! -d ${GIT_MOD_NAME} ]; then
git clone ${OPTION_Q} ${PACKAGE_DIR}/${PKG_SOURCE} ${GIT_MOD_NAME} \
$([ "${PKG_BRANCH}" = "" ] || echo "-b ${PKG_BRANCH}")
if [ "${PKG_UPSTREAM}" != "" ]; then
cd ${GIT_MOD_NAME};
git remote add upstream ${PKG_UPSTREAM}
cd ${OLDPWD};
fi
fi
if [ "${PKG_REVISION}" != "" ]; then
cd ${GIT_MOD_NAME} && git reset ${OPTION_Q} --hard ${PKG_REVISION} && cd ${OLDPWD}
else
cd ${GIT_MOD_NAME}
git pull ${OPTION_Q} origin ${PKG_BRANCH} || exit 1
fi
cd ${TOP_DIR}
rm -fr ${SRC_DIR}/${GIT_MOD_NAME}
ln -sf ${DEV_COPY_BASE}/${GIT_MOD_NAME} ${SRC_DIR}/${GIT_MOD_NAME}
touch ${BLD_DIR}/${STAMP_UNPACK}
PKG_SOURCE=""
set +x
SRC_ELEM=$(ls ${SRC_DIR}|grep -v ${HD_MAKEFILE}|grep -v ${MAKE_SEGMENT})
BLD_ELEM=$(ls ${BLD_DIR}|grep -v ${HD_MAKEFILE}|grep -v ${MAKE_SEGMENT})
if [ "${BLD_ELEM}" = "" ]; then
for iter in ${SRC_ELEM}; do
Trace "Bulk [${SRC_DIR}/${iter} => ${BLD_DIR}"
# cp -Lrf ${SRC_DIR}/${iter} ${BLD_DIR}
done
return 0
fi
fi
# for FILE in \
# $(find -L ${SRC_DIR}/ -type f -o -type l -name "*.[ch]" -o -name "*.mk" -o -name "*.cpp") \
# $(find ${SRC_DIR}/ -maxdepth 1 -name "*.patch" -o -name "lib*.a" -o -name "lib*.so") \
# $([ "" != "${PKG_SOURCE}" ] && [ -d ${PACKAGE_DIR}/${PKG_SOURCE} ] && find ${PACKAGE_DIR}/${PKG_SOURCE}/ -type f -o -type l) \
# ; \
# do
# if [ "" != "${PKG_SOURCE}" ] && \
# [ -d ${PKG_SOURCE} ] && \
# [ "$(dirname ${FILE})" != "${TOP_DIR}/${MODULE}" ]; then
# SUBD=$(echo $(dirname ${FILE})|${SED} "s:$(dirname ${PKG_SOURCE})::")
# SUBD=$(echo ${SUBD}|${SED} "s:${SRC_DIR}::")
# else
# SUBD=$(echo $(dirname ${FILE})|${SED} "s:${SRC_DIR}::")
# SUBD=$(echo ${SUBD}|${SED} "s:${PACKAGE_DIR}/*::")
# fi
#
# COPY_DIR=${OUTPUT_DIR}/${MODULE}/${SUBD}
# mkdir -p ${COPY_DIR}
# COPY_BASE=$(basename ${FILE})
# FILE_COPY=${COPY_DIR}/${COPY_BASE}
# # grep -q "\.git" <<< ${FILE} || Trace "Check: ${FILE}: ${FILE_COPY}"
#
# if [ ! -e ${FILE_COPY} -o \
# ${FILE} -nt ${FILE_COPY} ]; then
# mkdir -p ${BLD_DIR}/${FILE_DIR}
# cp -f ${FILE} ${FILE_COPY}
# fi
# done
}
function Update_Makefile()
{
BLD_MFILE=${BLD_DIR}/${HD_MAKEFILE}
if [ ${BLD_MFILE} -nt ${SRC_DIR}/${MAKE_SEGMENT} ] && \
[ ${BLD_MFILE} -nt ${STAMP_BLD_ENV} ]; then
return 0;
fi
rm -f ${BLD_MFILE}
echo "MODULE_NAME := ${MODULE}" >> ${BLD_MFILE}
cat ${STAMP_BLD_ENV} >> ${BLD_MFILE}
cat << EOB >> ${BLD_MFILE}
include \$(RULE_DIR)/settings.mk
include \$(CONFIG_TPL)
all:
EOB
cp -f ${SRC_DIR}/${MAKE_SEGMENT} ${BLD_DIR}/${MAKE_SEGMENT}
cat ${BLD_DIR}/${MAKE_SEGMENT} >> ${BLD_MFILE}
${SED} -i 's/clean:/clean : clean-prepare/g' ${BLD_MFILE}
cat << EOB >> ${BLD_MFILE}
env:
@echo ""
@printf -- "-----------------------------------------------------------------\n"
@\$(foreach var,\$(SHOW_ENV_VARS),\$(call Dump_Var,\$(var)))
@printf -- "-----------------------------------------------------------------\n"
@echo ""
include \$(RULE_DIR)/rules.mk
EOB
Trace "Updated: ${BLD_MFILE}"
}
if [ "$#" != "1" -a "$#" != "2" ]; then exit 12; fi
MODULE=${1}
BLD_DIR=${OUTPUT_DIR}/${MODULE}
SRC_DIR=${TOP_DIR}/${MODULE}
if [ ! -d ${SRC_DIR} ]; then
exit 0
fi
if [ "${VERBOSE_PRE_BLD}" != "" ]; then
OPTION_V="-v"
CMDSET_X="set -x"
else
OPTION_Q="-q"
fi
mkdir -p ${BLD_DIR}
MSG=$(printf "%-28s%s" "${MODULE}" "[..]")
echo -ne "\r "
echo -ne "\033[0;37;0;44m""\r[..] o ${MSG}""\033[0;m"
Trace ""
if [ "$#" = "1" ]; then
Update_Sources
fi
Update_Makefile

View file

@ -0,0 +1,197 @@
include $(RULE_DIR)/settings.mk
sinclude $(CONFIG_TPL)
export PATH := $(PATH):$(TOOLCHAIN_DLDIR)/main/bin
unexport VERBOSE
unexport DEBUG
TOPDIR_NAME := $(shell $(SHELL_DBG) basename $(TOP_DIR))
LIBOBJ_TMPDIR := $(OUTPUT_DIR)/lib$(TOPDIR_NAME).objs
SYSROOT_BIN := $(OUTPUT_DIR)${bindir}
SYSROOT_INC := $(OUTPUT_DIR)${incdir}
SYSROOT_LIB := $(OUTPUT_DIR)${libdir}
CONFIG_VENDOR := $(shell grep -m 1 "VENDOR *:" $(CONFIG_TPL) 2>/dev/null|awk '{ print $$NF }')
IMPORT_VDRDIR := $(IMPORT_DIR)/$(CONFIG_VENDOR)
HOST_ARCH_BITS := $(shell [ "$$(uname -m)" = "x86_64" ] && echo -n "64" || echo -n "32")
PREBUILT_LIBDIR := $(if $(strip $(filter 64,$(HOST_ARCH_BITS)) $(CROSS_PREFIX)),libs,32bit-libs)
PREBUILT_BINDIR := $(if $(strip $(filter 64,$(HOST_ARCH_BITS)) $(CROSS_PREFIX)),bin,32bit-bin)
CONFIG_VSP_WEBSITE ?= http://gitlab.alibaba-inc.com/yusheng.yx/alink-vendor-support-package
ifeq ($(shell uname), Linux)
RPATH_CFLAGS += -Wl,-rpath='$$''ORIGIN/../lib'
endif
# CFLAGS contains '$' causes ./configure failure in ORIGIN packages
#
# Instead of:
#
# ifeq ($(shell uname), Linux)
# CFLAGS += -Wl,-rpath='$$''ORIGIN/../lib'
# CFLAGS := $(sort $(CFLAGS))
# endif
#
# Write @ package's makefile:
#
# ./configure \
# CFLAGS='$(CFLAGS) -Wl,-rpath='\''$$$$'\''ORIGIN/../lib' \
# --prefix=...
#
# To pass in RPATH related link flags
COMP_LIB_NAME := $(subst lib,,$(subst .so,,$(subst .a,,$(COMP_LIB))))
COMP_LIB_OBJS = $(foreach d,$(COMP_LIB_COMPONENTS),$(LIBOBJ_TMPDIR)/$(d)/*.o)
RECURSIVE_MAKE := $(MAKE) $(if $(TOP_Q),-s) -C $(TOP_DIR) -f $(TOP_MAKEFILE)
ALL_SUB_DIRS := $(shell find -L $(TOP_DIR) \
! -path "$(OUTPUT_DIR)/*" \
! -path "$(TOP_DIR)/$(SHADOW_DIR)/*" \
-name "$(MAKE_SEGMENT)" 2>/dev/null \
| $(SED) 's,$(TOP_DIR)[/]*,,;s,[/]*$(MAKE_SEGMENT),,')
SHOW_ENV_VARS := \
MODULE_NAME SUBDIRS PKG_NAME PKG_RPATH PKG_SOURCE PKG_SWITCH_V PKG_SWITCH \
HOST_ARCH_BITS PREBUILT_LIBDIR RPATH_CFLAGS EXTRA_INCLUDE_DIRS \
CROSS_PREFIX DEPENDS CFLAGS CCLD LDFLAGS \
CC LD AR STRIP OBJCOPY COMP_LIB ALL_SUB_DIRS LIBOBJ_TMPDIR \
MAKE_ENV_VARS DEFAULT_BLD EXTRA_CFLAGS \
LIBA_TARGET LIBSO_TARGET TARGET KMOD_TARGET \
SRCS OBJS LIB_SRCS LIB_OBJS LIB_HDRS_DIR LIB_HEADERS EXTRA_SRCS \
$(foreach M,$(LIBA_TARGET),LIB_SRCS_$(subst .a,,$(subst lib,,$(M)))) \
INTERNAL_INCLUDES TOP_DIR PRJ_NAME PRJ_VERSION COMP_LIB_COMPONENTS \
IMPORT_DIR IMPORT_VDRDIR CONFIG_DIR PACKAGE_DIR EXTERNAL_INCLUDES \
CONFIG_LIB_EXPORT OBJCOPY_FLAGS CONFIG_VENDOR COVERAGE_PROGS COVERAGE_CMD \
INFO_ENV_VARS := $(SHOW_ENV_VARS) \
ALL_SUB_DIRS SED RULE_DIR OUTPUT_DIR MAKE_SEGMENT COMP_LIB_NAME LIBOBJ_TMPDIR \
COMP_LIB_FILES STAMP_BLD_ENV STAMP_BLD_VAR EXTRA_INSTALL_HDRS DIST_DIR \
WIN32_CMAKE_SKIP EXTRA_INCLUDE_DIRS NOEXEC_CMAKE_DIRS COMP_LIB \
WITH_LCOV LCOV_DIR UTEST_PROG COVERAGE_CMD STAMP_LCOV CMAKE_EXPORT_LIBS \
INFO_ENV_VARS := $(filter-out CFLAGS,$(INFO_ENV_VARS))
ifndef CONFIG_LIB_EXPORT
ifeq (y,$(strip $(CONFIG_EMB_GATEWAY_SDK)))
CONFIG_LIB_EXPORT := dynamic
else
ifeq (y,$(strip $(CONFIG_EMB_BASIC_SDK)))
CONFIG_LIB_EXPORT := static
else
ifeq (y,$(strip $(CONFIG_EMB_ROUTER_SDK)))
CONFIG_LIB_EXPORT := dynamic
endif # ROUTER
endif # BASIC
endif # GATEWAY
else
ifneq (static,$(CONFIG_LIB_EXPORT))
ifneq (dynamic,$(CONFIG_LIB_EXPORT))
$(error CONFIG_LIB_EXPORT($(CONFIG_LIB_EXPORT)) is neither 'static' or 'dynamic')
endif # dynamic
endif # static
endif # CONFIG_LIB_EXPORT
ifneq (,$(shell ls $(STAMP_BLD_VAR) 2>/dev/null))
ifeq (,$(filter reconfig distclean,$(MAKECMDGOALS)))
ifeq (0,$(strip $(shell $(SED) '/[-_/a-zA-Z0-9]* = *..*/d' $(STAMP_BLD_VAR)|wc -l)))
include $(STAMP_BLD_VAR)
endif
endif
endif
.PHONY: all clean FORCE
ifdef SUBDIRS
include $(RULE_DIR)/_rules-top.mk
include $(RULE_DIR)/_rules-prefix.mk
include $(RULE_DIR)/_rules-repo.mk
exist = $(shell if [ -f $(CONFIG_TPL) ];then echo "exist"; else echo "not exist"; fi;)
ifeq ($(exist),exist)
CROSS_CANDIDATES := CC CXX AR LD STRIP OBJCOPY
export CC := $(strip $(if $(OVERRIDE_CC), $(OVERRIDE_CC), $(CROSS_PREFIX)gcc))
export CXX := $(strip $(if $(OVERRIDE_CXX), $(OVERRIDE_CXX), $(CROSS_PREFIX)g++))
export AR := $(strip $(if $(OVERRIDE_AR), $(OVERRIDE_AR), $(CROSS_PREFIX)ar))
export LD := $(strip $(if $(OVERRIDE_LD), $(OVERRIDE_LD), $(CROSS_PREFIX)ld))
export OBJCOPY := $(strip $(if $(OVERRIDE_OBJCOPY),$(OVERRIDE_OBJCOPY),$(CROSS_PREFIX)objcopy))
ifneq (,$(OVERRIDE_STRIP))
export STRIP := $(OVERRIDE_STRIP)
else
ifneq (,$(CROSS_PREFIX))
export STRIP := $(CROSS_PREFIX)strip
else
export STRIP := true
endif
endif
ifeq (gcc,$(strip $(CC)))
export STRIP := strip
endif
endif #ifeq (exist, "exist" )
ifneq (,$(filter -m32,$(strip $(CFLAGS))))
PREBUILT_LIBDIR := 32bit-libs
PREBUILT_BINDIR := 32bit-bin
endif
include $(RULE_DIR)/_rules-dist.mk
include $(RULE_DIR)/_rules-complib.mk
include $(RULE_DIR)/_rules-submods.mk
env:
$(TOP_Q)echo ""
$(TOP_Q)printf -- "-----------------------------------------------------------------\n"
$(TOP_Q)$(foreach var,$(SHOW_ENV_VARS),$(call Dump_Var,$(var)))
$(TOP_Q)printf -- "-----------------------------------------------------------------\n"
$(TOP_Q)echo ""
$(TOP_Q)$(call $(POST_ENV_HOOK))
else # ifdef SUBDIRS
PKG_RPATH := $(shell echo $(CURDIR)|$(SED) 's,$(OUTPUT_DIR)/*,,g')
PKG_NAME ?= $(shell basename $(CURDIR))
PKG_SOURCE ?= $(shell [ -d $(PACKAGE_DIR) ] && find $(PACKAGE_DIR) -name "$(PKG_NAME)*" | head -1)
DEPENDS += $(DEPENDS_$(MODULE_NAME))
DEPENDS := $(sort $(strip $(DEPENDS)))
ifdef CONFIG_SWITCH
PKG_SWITCH_V = $(CONFIG_SWITCH)
else
PKG_SWITCH_V := CONFIG_$(PKG_RPATH)
endif
PKG_SWITCH = $($(PKG_SWITCH_V))
ifdef ORIGIN
include $(RULE_DIR)/_rules-origin.mk
else # ifdef ORIGIN
ifneq (,$(filter -m32,$(strip $(CFLAGS))))
PREBUILT_LIBDIR := 32bit-libs
PREBUILT_BINDIR := 32bit-bin
endif
include $(RULE_DIR)/_rules-flat.mk
endif # ifdef ORIGIN
include $(RULE_DIR)/_rules-modinfo.mk
endif # ifdef SUBDIRS
sinclude $(STAMP_POST_RULE)
ifdef UTEST_PROG
COVERAGE_LIST += \\\"./$(strip $(UTEST_PROG) --list)\\\"
COVERAGE_LIST += \\\"./$(strip $(UTEST_PROG) --verbose=4)\\\"
include $(RULE_DIR)/_rules-coverage.mk
endif

View file

@ -0,0 +1,40 @@
#! /bin/bash
TEXT=(
"Copyright (c) 2014-2016 Alibaba Group. All rights reserved."
"License-Identifier: Apache-2.0"
""
"Licensed under the Apache License, Version 2.0 (the \"License\"); you may"
"not use this file except in compliance with the License."
"You may obtain a copy of the License at"
""
"http://www.apache.org/licenses/LICENSE-2.0"
""
"Unless required by applicable law or agreed to in writing, software"
"distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT"
"WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied."
"See the License for the specific language governing permissions and"
"limitations under the License."
""
)
TOTAL_LINE=${#TEXT[@]}
i=$(( TOTAL_LINE - 1 ))
sed -i "1i\ */" $1
while (( i >= 0 )); do
j=$(eval echo '${TEXT['$i']}')
if [ "$j" = "" ]; then
sed -i "1i\ *" $1
else
if [ "$(echo $j|awk '{ print NF }')" = "1" ] && [ "$(echo $j | cut -c1-7)" = "http://" ]; then
sed -i "1i\ * $j" $1
else
sed -i "1i\ * $j" $1
fi
fi
i=$(( i - 1 ))
done
sed -i "1i\/*" $1

View file

@ -0,0 +1,10 @@
#! /bin/bash
START_LINE=$(head -3 $1|grep -n '^ *\/\*'|cut -d':' -f1)
END_LINE=$(grep -m 1 -n '^ *\*\/' $1|cut -d':' -f1)
echo "[${START_LINE},${END_LINE}]"
if [ "${START_LINE}" != "" ] && [ "${END_LINE}" != "" ]; then
sed -i "${START_LINE},${END_LINE}d" $1
echo "LICENSE REMOVED: $1"
fi

View file

@ -0,0 +1,25 @@
#! /bin/bash
set -e
if [ "${OUTPUT_DIR}" = "" ] || [ ! -d ${OUTPUT_DIR} ]; then exit 1; fi
cd ${OUTPUT_DIR}/usr/bin
echo ""
iter=0
while (( iter < ${#PROGS[@]} )); do
UT_CMD=$(eval echo '${PROGS['${iter}']}')
UT_PROG=$(echo ${UT_CMD}|cut -d' ' -f1)
echo "[${iter}] RUNNING '${UT_CMD}' with '${UT_PROG}'"|grep --color ".*"
echo ""
if [ -f ${UT_PROG} ]; then
${UT_CMD}
else
echo "${UT_CMD} SPECIFIED BUT ${UT_PROG} NOT FOUND"|grep --color ".*"
fi
iter=$(( iter + 1 ))
done

View file

@ -0,0 +1,62 @@
#! /bin/bash
procing() {
trap 'exit 0;' 6
while :; do
for j in '-' '\\' '|' '/'; do
tput sc
echo -ne "[$j]"
sleep 0.1
tput rc
done
done
}
waiting() {
local pid="$1"
echo -ne "\033[1;32m"
echo -n "$2 .................... "
procing &
local tmppid="$!"
wait $pid
tput rc
echo "done"
echo -ne "\033[0m"
echo ""
kill -6 $tmppid >/dev/null 1>&2
}
GIT_PREFIX="https://gitee.com/alios-things"
LOCAL_CC=${TOOLCHAIN_DLDIR}/${RELPATH}/${CC}
LOCAL_AR=${TOOLCHAIN_DLDIR}/${RELPATH}/${AR}
# echo "[RELPATH]: ${RELPATH}"
# echo "[GITPATH]: ${GITPATH}"
which ${CC} > /dev/null 2>&1
if [ $? != 0 ] && [ ! -f ${LOCAL_CC} ]; then
if [ "${GITPATH}" = "" ]; then
echo "Unable to find available toolchain of [${CC}] from local ENV or Internet. Abort!" | grep --color ".*"
echo ""
exit 1
fi
echo -n "${GIT_PREFIX}/${GITPATH} -> "
echo -n "$(basename ${OUTPUT_DIR})/$(basename ${TOOLCHAIN_DLDIR})/"
echo "$(dirname ${RELPATH})"
echo "---"
mkdir -p ${TOOLCHAIN_DLDIR}
cd ${TOOLCHAIN_DLDIR}
git clone -q ${GIT_PREFIX}/${GITPATH} &
waiting "$!" "downloading toolchain for ${CC}"
cd ${OLDPWD}
fi

View file

@ -0,0 +1,108 @@
#! /bin/bash
set -e
if [ "$(uname)" = "Darwin" ]; then
SED=gsed
else
SED=sed
fi
rm -rf ${OUTPUT_DIR}/${LCOV_DIR} ${DIST_DIR}/${LCOV_DIR}
lcov --quiet \
--capture --initial --directory ${OUTPUT_DIR}/ \
-o ${OUTPUT_DIR}/files.info
lcov --quiet \
--capture --directory ${OUTPUT_DIR} \
-o ${OUTPUT_DIR}/tests.info
lcov --quiet \
--add-tracefile ${OUTPUT_DIR}/files.info \
--add-tracefile ${OUTPUT_DIR}/tests.info \
-o ${OUTPUT_DIR}/all.info
lcov --quiet \
--remove ${OUTPUT_DIR}/all.info \
-o ${OUTPUT_DIR}/final.info '*.h'
genhtml --quiet \
--legend --no-branch-coverage \
-o ${OUTPUT_DIR}/${LCOV_DIR} ${OUTPUT_DIR}/final.info 2>/dev/null
cp -rf ${OUTPUT_DIR}/${LCOV_DIR} ${DIST_DIR}/${LCOV_DIR}
cd ${DIST_DIR}/${LCOV_DIR} && \
${SED} -i 's:\(coverFile.*\)>${OUTPUT_DIR}/:\1>:g' index.html
cd ${OLDPWD}
SRC_NAME_LENGTH=28
DIR_NAME_LENGTH=16
COVERAGE_HIGH=90
COVERAGE_MID=75
echo ""
echo "Processing [${DIST_DIR}/${LCOV_DIR}] for Coverage Brief"
echo ""
#
# sdk-example / example.c : [100.00%] (7/7) [100.00%] (1/1)
#
echo -ne "\033[1;36m"
printf "%${DIR_NAME_LENGTH}s %-${SRC_NAME_LENGTH}s: %-24s %-20s\n\n" \
"Directory" \
"Source File" \
"Line Coverage" \
"Function Coverage"
echo -ne "\033[0m"
REPORT_LIST=$(find ${DIST_DIR}/${LCOV_DIR} -mindepth 2 -name "index.html")
for R in ${REPORT_LIST}; do
SOURCE_LIST=$(grep "coverFile" ${R} | awk -F '<' '{ print $3 }' | cut -d'>' -f2)
for S in ${SOURCE_LIST}; do
STATS=$(grep -A 7 "${S}</a>" ${R} | ${SED} -n '6p;8p'|grep -o -E '[0-9]+')
DIR_NAME=$(echo "$(dirname ${R}|xargs basename)" | cut -c1-15)
SRC_NAME=$(echo "${S}" | cut -c"1-$(( SRC_NAME_LENGTH -1 ))")
COVER_LINE=$(echo ${STATS}|cut -d' ' -f1)
TOTAL_LINE=$(echo ${STATS}|cut -d' ' -f2)
COVER_FUNC=$(echo ${STATS}|cut -d' ' -f3)
TOTAL_FUNC=$(echo ${STATS}|cut -d' ' -f4)
LINE_PERCENT="$(echo "scale=2; ${COVER_LINE} * 100 / ${TOTAL_LINE}"|bc -l)%"
FUNC_PERCENT="$(echo "scale=2; ${COVER_FUNC} * 100 / ${TOTAL_FUNC}"|bc -l)%"
printf \
"%-8s %${DIR_NAME_LENGTH}s / %-${SRC_NAME_LENGTH}s: [ %s ] (%s/%s) \t [ %s ] (%s/%s)\n" \
${LINE_PERCENT} \
${DIR_NAME} \
${SRC_NAME} \
${LINE_PERCENT} \
${COVER_LINE} \
${TOTAL_LINE} \
${FUNC_PERCENT} \
${COVER_FUNC} \
${TOTAL_FUNC}
done
done \
| sort -nr \
| cut -d' ' -f2- \
| awk -v SRC_LEN=${SRC_NAME_LENGTH} -v DIR_LEN=${DIR_NAME_LENGTH} \
-v HIGH=${COVERAGE_HIGH} -v MID=${COVERAGE_MID} \
'{
split($6, arr, ".");
if (arr[1] >= HIGH)
printf("\033[1;32m");
else if (arr[1] >= MID)
printf("\033[1;35m");
else
printf("\033[1;31m");
printf("%" DIR_LEN "s / %-" SRC_LEN "s: [ %-8s] %-12s [ %-8s] %-12s\n",
$1, $3, $6, $8, $10, $12);
}'
#
# 1 2 3 4 5 6 7 8 9 10 11 12
# sdk-example / example.c : [ 100.00% ] (7/7) [ 100.00% ] (1/1)
#
rm -f ${OUTPUT_DIR}/{files,tests,all,final}.info
find ${OUTPUT_DIR} -name "*.gcno" -o -name "*.gcda" -exec rm -f {} \;
echo ""
exit 0

View file

@ -0,0 +1,195 @@
#! /bin/bash
TARGET_FILE=${OUTPUT_DIR}/.one_makefile
rm -f ${TARGET_FILE}
CONFIG_VERNDOR=$(grep -m 1 "VENDOR *:" .config|awk '{ print $NF }')
EXT_IFLAGS=$( \
for iter in \
$(find -L \
build-rules/misc \
include \
tests \
src/infra \
${IMPORT_DIR}/${CONFIG_VENDOR}/include \
-type d -not -path "*.git*" -not -path "*.O*" 2>/dev/null); do \
echo " -I${iter} \\"; \
done)
IFLAGS=$( \
for iter in \
$(find -L \
${COMP_LIB_COMPONENTS} \
${EXPORT_DIR} \
${EXTRA_INCLUDE_DIRS} \
${IMPORT_DIR}/${CONFIG_VENDOR}/include \
-type d -not -path "*.git*" -not -path "*.O*" 2>/dev/null); do \
echo " -I${iter} \\"; \
done)
if [ "${WITH_LCOV}" = "1" ]; then
CFLAGS=$( \
echo "${CFLAGS}" \
| xargs -n 1 \
| awk '{ printf(" %s \\\n", $0); }' \
)
else
CFLAGS=$( \
echo "${CFLAGS}" \
| xargs -n 1 \
| grep -v '\-\-coverage' \
| awk '{ printf(" %s \\\n", $0); }' \
)
fi
ETC_OBJS=$(
for i in ${ALL_LIBS}; do
j=$(grep "${i}$" ${STAMP_BLD_VAR} | cut -d' ' -f1 | ${SED} 's|LIBA_TARGET_|LIB_OBJS_|g')
k=$(grep "${j}" ${STAMP_BLD_VAR} | cut -d' ' -f3-)
for l in ${k}; do
echo "${j//LIB_OBJS_/}/${l}"
done
done)
ALL_LIBS=$(for iter in ${ALL_LIBS}; do echo -n "${OUTPUT_DIR}/usr/lib/${iter} "; done)
ALL_BINS=$(for iter in ${ALL_PROG}; do echo -n "${OUTPUT_DIR}/usr/bin/${iter} "; done)
OUTPUT_D=$(basename ${OUTPUT_DIR})
if [ "${CC}" != "gcc" ]; then
ALL_BINS=""
fi
cat << EOB >> ${TARGET_FILE}
include ${RULE_DIR}/funcs.mk
SHELL := bash
Q ?= @
VPATH := $(for iter in ${COMP_LIB_COMPONENTS}; do echo -n "${OUTPUT_DIR}/${iter} "; done)
EXT_IFLAGS := \\
${EXT_IFLAGS}
IFLAGS := \\
${IFLAGS}
CFLAGS := \\
${EXTRA_CFLAGS} \\
${CFLAGS}
STAMP_LCOV := ${STAMP_LCOV}
.PHONY: all
all: ${OUTPUT_DIR}/usr/lib/${COMP_LIB} ${ALL_LIBS} ${ALL_BINS}
\$(Q)cp -rf ${EXTRA_INSTALL_HDRS} ${OUTPUT_DIR}/usr/include 2>/dev/null || true
@rm -f *.gcda *.gcno \$\$(find ${RULE_DIR} -name "*.o")
@if [ "\$(WITH_LCOV)" = "1" ]; then \\
mkdir -p \$\$(dirname \$(STAMP_LCOV)); \\
touch \$(STAMP_LCOV); \\
else \\
rm -f \$(STAMP_LCOV); \\
fi
ifneq (,\$(findstring gcc,\$(CC)))
$(for iter in ${COMP_LIB_OBJS}; do
echo "sinclude ${OUTPUT_DIR}/${iter/.o/.d}"
done
)
endif
${OUTPUT_DIR}/usr/lib/${COMP_LIB}: \\
$(for iter in ${COMP_LIB_OBJS}; do
echo " ${OUTPUT_DIR}/${iter} \\"
done
)
\$(Q)mkdir -p \$\$(dirname \$@)
\$(Q)\$(call Brief_Log,"AR",\$\$(basename \$@),"...")
\$(Q)${AR} -rcs \$@ \$^ 2>/dev/null
%.o:
\$(Q)\$(call Brief_Log,"CC",\$\$(basename \$@),"...")
\$(Q)mkdir -p \$\$(dirname \$@)
\$(Q)S=\$\$(echo \$@|${SED} 's,${OUTPUT_DIR},${TOP_DIR},1'); \\
[ -f \$\${S//.o/.c} ] && ${CC} -c \\
-o \$@ \\
\$(CFLAGS) \\
\$(IFLAGS) \\
\$\${S//.o/.c}
ifneq (,\$(findstring gcc,\$(CC)))
%.d:
@\\
( \\
D=\$\$(dirname \$@|${SED} 's,${OUTPUT_DIR},${TOP_DIR},1'); \\
F=\$\$(basename \$@); \\
F=\$\${F/.d/.c}; \\
mkdir -p \$\$(dirname \$@); \\
${CC} -MM -I\$(CURDIR) \\
\$(IFLAGS) \\
\$(CFLAGS) \\
\$\${D}/\$\${F} > \$@.\$\$\$\$; \\
${SED} -i 's!\$(shell basename \$*)\.o[ :]!\$*.o:!1' \$@.\$\$\$\$; \\
mv \$@.\$\$\$\$ \$@; \\
)
endif
EOB
for i in ${ALL_LIBS}; do
n=$(basename ${i})
j=$(grep "${n}$" ${STAMP_BLD_VAR}|cut -d' ' -f1|${SED} 's:LIBA_TARGET_::1')
k=$(echo 'LIB_OBJS_'"${j}")
k=$(grep -m 1 "^${k}" ${STAMP_BLD_VAR}|cut -d' ' -f3-)
k=$(for l in ${k}; do echo -n "${OUTPUT_DIR}/${j}/${l} "; done)
for m in ${k}; do
echo "sinclude ${m/.o/.d}" >> ${TARGET_FILE}
done
echo "" >> ${TARGET_FILE}
cat << EOB >> ${TARGET_FILE}
${OUTPUT_DIR}/usr/lib/${n}: \\
$(for m in ${k}; do
echo " ${m} \\";
done)
\$(Q)mkdir -p \$\$(dirname \$@)
\$(Q)\$(call Brief_Log,"AR",\$\$(basename \$@),"...")
\$(Q)${AR} -rcs \$@ \$^ 2>/dev/null
EOB
done
for i in ${ALL_PROG}; do
j=$(grep -w -m 1 "^SRCS_${i}" ${STAMP_BLD_VAR}|cut -d' ' -f3-)
k=$(grep -m 1 "TARGET_.* = .*${i}" ${STAMP_BLD_VAR}|cut -d' ' -f1|${SED} 's:TARGET_::1')
q=${k}
if [ "$(grep -m 1 "^TARGET_${k}" ${STAMP_BLD_VAR}|cut -d' ' -f3-|awk '{ print NF }')" = "1" ]; then
k=""
fi
LFLAGS=$(grep -m 1 "^LDFLAGS_${k}" ${STAMP_BLD_VAR}|cut -d' ' -f3-)
if [ "${CC}" = "gcc" ]; then
if [ "$(uname)" != "Darwin" ]; then
LFLAGS="${LFLAGS} -lgcov"
fi
fi
j=$(for n in ${j}; do p=$(echo ${n}|cut -c1); [ "${p}" = "/" ] && echo -n "${n}" || echo -n "${TOP_DIR}/${q}/${n} "; done)
cat << EOB >> ${TARGET_FILE}
${OUTPUT_DIR}/usr/bin/${i}: \\
$(for m in ${j} ${OUTPUT_DIR}/usr/lib/${COMP_LIB} ${ALL_LIBS}; do
echo " ${m} \\"|${SED} 's!//*!/!g';
done)
\$(Q)\$(call Brief_Log,"LD",\$\$(basename \$@),"...")
\$(Q)${CC} \\
-o \$@ \\
$([ "$i" != "sdk-testsuites" ] && echo "\$(IFLAGS)" || echo "\$(EXT_IFLAGS)") \\
\$(CFLAGS) \\
\$(filter-out %.a,\$^) \\
$( if [ "${i}" = "sdk-testsuites" ] && uname -a|grep -qw Ubuntu; then echo "${TOP_DIR}/${IMPORT_VDRDIR}/${PREBUILT_LIBDIR}/libcurl.a"; fi ) \\
-L${OUTPUT_DIR}/usr/lib \\
${LFLAGS} $( if [ "${i}" = "sdk-testsuites" ] && ! uname -a|grep -qw Ubuntu; then echo "-lcurl"; fi )
EOB
done

View file

@ -0,0 +1,114 @@
#! /bin/bash
#echo "COMP_LIB = ${COMP_LIB}"
#echo "STRIP = ${STRIP}"
echo ""
printf " | %-5s | %-35s | %14s | %26s |\n" "RATE" "OBJ NAME" "BYTES/TOTAL" "MODULE NAME"
for iter in ${ALL_SUB_DIRS}; do
[ ! -d ${LIBOBJ_TMPDIR}/${iter} ] && continue
cd ${LIBOBJ_TMPDIR}/${iter}
ITER_OBJS=$(find . -name "*.o")
[ "${ITER_OBJS}" != "" ] || continue
${STRIP} ${ITER_OBJS} 2>/dev/null
printf " |-%-.5s-|-%-.35s-|-%.14s-|-%.26s-|\n" \
"-----------------------------------------" \
"-----------------------------------------" \
"-----------------------------------------" \
"-----------------------------------------"
ITER_SIZE=$(size ${ITER_OBJS} | ${SED} '1d' | awk '{ sum += $1 } END { print sum }')
for j in ${ITER_OBJS}; do
size $j | ${SED} '1d' \
| awk -v sum="${ITER_SIZE}" \
-v mod="${iter}" \
-v obj="$(basename ${j})" \
'{ if ($1 != 0) printf("%d %.4s%% %s %-d/%d %s\n", $1, ($1/sum)*100, obj, $1, sum, mod); }'
done \
| sort -nr \
| cut -d' ' -f2- \
| awk '{ printf(" | %-5s | %-35s | %14s | %26s |\n", $1, $2, $3, $4); }'
cd ${OLDPWD}
done
echo ""
echo ""
echo ""
printf " | %-5s | %-35s | %-9s | %-9s | %-10s | %-6s |\n" \
"RATE" "MODULE NAME" "ROM" "RAM" "BSS" "DATA"
printf " |-%-.5s-|-%-.35s-|-%-.9s-|-%-.9s-|-%-.10s-|-%-.6s-|\n" \
"-------------" \
"--------------------------------------------" \
"-------------" \
"-------------" \
"-------------" \
"-------------"
cd ${LIBOBJ_TMPDIR}
TOTAL_ROM=$(find $(for i in ${COMP_LIB_COMPONENTS}; do echo "${OUTPUT_DIR}/${i}"; done) -name "*.o" \
| xargs size \
| awk '{ sum += $1 } END { print sum }')
cd ${OLDPWD}
for iter in ${COMP_LIB_COMPONENTS}; do
[ ! -d ${LIBOBJ_TMPDIR}/${iter} ] && continue
cd ${LIBOBJ_TMPDIR}/${iter}
ITER_OBJS=$(find . -name "*.o")
[ "${ITER_OBJS}" != "" ] || continue
${STRIP} ${ITER_OBJS} 2>/dev/null
size ${ITER_OBJS} | ${SED} '1d' \
| awk -v name=${iter} -v total_rom=${TOTAL_ROM} '
BEGIN { sum_rom = sum_ram = sum_bss = sum_data = 0 }
{
sum_rom += $1 + $2;
sum_ram += $2 + $3;
sum_bss += $3;
sum_data += $2;
}
END {
rate = sum_rom / total_rom * 100;
printf("%d | %.4s%% | %-35s | %-9s | %-9s | %-10s | %-6s |\n",
sum_rom,
rate,
name,
sum_rom,
sum_ram,
sum_bss,
sum_data);
}
'
cd ${OLDPWD}
done \
| sort -nr \
| cut -d' ' -f2- \
| ${SED} 's!.*! &!g' \
| awk -v total_rom=${TOTAL_ROM} '
BEGIN { sum_rom = sum_ram = sum_bss = sum_data = 0 }
{
sum_rom += $6;
sum_ram += $8;
sum_bss += $10;
sum_data += $12;
print;
}
END {
rate = sum_rom / total_rom * 100;
printf(" |-------|-------------------------------------|-----------|-----------|------------|--------|\n");
if (rate < 100)
printf(" | %.4s%% | %-35s | %-9s | %-9s | %-10s | %-6s |\n", rate, "- IN TOTAL -", sum_rom, sum_ram, sum_bss, sum_data);
else
printf(" | %.3s%% | %-35s | %-9s | %-9s | %-10s | %-6s |\n", rate, "- IN TOTAL -", sum_rom, sum_ram, sum_bss, sum_data);
}
'
echo ""

View file

@ -0,0 +1,120 @@
#! /bin/bash
TARGET_FILE=$1
SRC_LIST=$(for i in ${LIB_SRCS}; do
echo ${i}|${SED} "s:${TOP_DIR}: \${PROJECT_SOURCE_DIR}:g"
done)
DIR_LIST=$(for i in ${LIB_SRCS}; do
dirname ${i}|sed "s:${TOP_DIR}/*::g"
done|sort -u)
MOD_NAME=$(echo ${MODULE_NAME}|sed 's:/:_:g')
rm -f ${TARGET_FILE}
cat << EOB >> ${TARGET_FILE}
$(for i in ${INTERNAL_INCLUDES} ${EXTERNAL_INCLUDES}; do
if grep -q "$(basename ${OUTPUT_DIR})/usr/include" <<< "${i}"; then
continue;
fi
echo $i \
| ${SED} "s:-I${TOP_DIR}\(.*\):INCLUDE_DIRECTORIES (\${PROJECT_SOURCE_DIR}\1):g"
done)
EOB
if echo ${CMAKE_EXPORT_LIBS} | grep -qw ${MODULE_NAME}; then
TYPE="SHARED"
else
TYPE="OBJECT"
fi
if [ "${LIBA_TARGET}" != "" ]; then
LNAME=${LIBA_TARGET#lib}
LNAME=${LNAME%.a}
cat << EOB >> ${TARGET_FILE}
FILE (GLOB ${MOD_NAME}_SRCS
$(for i in ${DIR_LIST}; do echo " \${PROJECT_SOURCE_DIR}/${i}/*.c"; done)
)
ADD_LIBRARY (${LNAME} ${TYPE}
\${${MOD_NAME}_SRCS}
\${EXTRA_C_SOURCES}
)
EOB
fi
#
# We do NOT compose ADD_TARGET and TARGET_LINK_LIBRARY segment for those
#
if grep -qw "${MODULE_NAME}" <<< "${NOEXEC_CMAKE_DIRS}"; then
exit 0
fi
TARGET_COUNT=$(echo "${TARGET}" | awk '{ print NF }')
if (( TARGET_COUNT == 1 )); then
if grep -qw ${TARGET} <<< ${WIN32_CMAKE_SKIP}; then
echo "IF (NOT WIN32)" >> ${TARGET_FILE}
fi
cat << EOB >> ${TARGET_FILE}
ADD_EXECUTABLE (${TARGET}
$(for i in ${SRCS}; do
echo ${i} | ${SED} "s:${TOP_DIR}: \${PROJECT_SOURCE_DIR}:g"
done)
)
$(for i in \
$(echo ${LDFLAGS} | grep -o '\-l[^ ]*' | sort -u | sed 's:^-l::g'); do
if [ "${i}" = "pthread" -o "${i}" = "rt" ]; then echo "IF (NOT MSVC)"; fi
echo "TARGET_LINK_LIBRARIES (${TARGET} ${i})"
if [ "${i}" = "pthread" -o "${i}" = "rt" ]; then echo "ENDIF (NOT MSVC)"; fi
done)
EOB
if grep -qw ${TARGET} <<< ${WIN32_CMAKE_SKIP}; then
echo "ENDIF (NOT WIN32)" >> ${TARGET_FILE}
fi
echo "" >> ${TARGET_FILE}
fi
if (( TARGET_COUNT > 1 )); then
cat << EOB >> ${TARGET_FILE}
$(for i in ${TARGET}; do
if echo ${WIN32_CMAKE_SKIP} | grep -qw ${i}; then
echo "IF (NOT WIN32)"
fi
echo "ADD_EXECUTABLE (${i}"
j=${i//-/_}
k=$(eval echo '${''SRCS_'"${j}"'}')
for v in ${k}; do
echo " ${v}"
done
echo ")"
if echo ${WIN32_CMAKE_SKIP} | grep -qw ${i}; then
echo "ENDIF (NOT WIN32)"
fi
done)
$(for i in ${TARGET}; do
if echo ${WIN32_CMAKE_SKIP} | grep -qw ${i}; then
echo "IF (NOT WIN32)"
fi
echo "TARGET_LINK_LIBRARIES (${i} ${COMP_LIB_NAME})"
for j in $(echo ${LDFLAGS} | grep -o '\-l[^ ]*' | sort -u | sed 's:^-l::g' | grep -vw ${COMP_LIB_NAME}); do
if [ "${j}" = "pthread" -o "${j}" = "rt" ]; then echo "IF (NOT MSVC)"; fi
echo "TARGET_LINK_LIBRARIES (${i} ${j})"
if [ "${j}" = "pthread" -o "${j}" = "rt" ]; then echo "ENDIF (NOT MSVC)"; fi
done
if echo ${WIN32_CMAKE_SKIP} | grep -qw ${i}; then
echo "ENDIF (NOT WIN32)"
fi
echo ""
done)
SET (EXECUTABLE_OUTPUT_PATH ../out)
EOB
fi

View file

@ -0,0 +1,117 @@
#! /bin/bash
TARGET_FILE=$1
PKG_RPATH=$(echo ${PACKAGE_DIR}|${SED} "s:${TOP_DIR}/*::g")
W32_LIBSD=$(echo ${IMPORT_DIR}/win7/${PREBUILT_LIBDIR}|${SED} "s:${TOP_DIR}/*::g")
rm -f ${TARGET_FILE}
ALL_CFLAGS="$(grep -m 1 '^CFLAGS\>' ${STAMP_BLD_ENV}|cut -d' ' -f3-)"
REM_CFLAGS=""
DEF_CFLAGS=""
for i in ${ALL_CFLAGS}; do
j=$(echo ${i}|cut -c1,2)
if [ "${j}" = "-D" ]; then
DEF_CFLAGS="${DEF_CFLAGS} ${i}"
else
REM_CFLAGS="${REM_CFLAGS} ${i}"
fi
done
cat << EOB >> ${TARGET_FILE}
if(\${CMAKE_SOURCE_DIR} STREQUAL \${CMAKE_BINARY_DIR})
MESSAGE (FATAL_ERROR "in-tree build not allowded")
endif(\${CMAKE_SOURCE_DIR} STREQUAL \${CMAKE_BINARY_DIR})
CMAKE_MINIMUM_REQUIRED (VERSION 2.8)
PROJECT (${PRJ_NAME}-${PRJ_VERSION} C)
SET (EXECUTABLE_OUTPUT_PATH \${PROJECT_BINARY_DIR}/bin)
SET (LIBRARY_OUTPUT_PATH \${PROJECT_BINARY_DIR}/lib)
SET (CMAKE_C_FLAGS "${REM_CFLAGS} -fPIC")
IF (WIN32)
SET (CMAKE_EXE_LINKER_FLAGS "-L\${PROJECT_SOURCE_DIR}/${W32_LIBSD}")
ENDIF (WIN32)
MESSAGE ("---------------------------------------------------------------------")
MESSAGE ("Project Name : " \${PROJECT_NAME})
MESSAGE ("Source Dir : " \${PROJECT_SOURCE_DIR})
MESSAGE ("Binary Dir : " \${PROJECT_BINARY_DIR})
MESSAGE ("System Processor : " \${CMAKE_SYSTEM_PROCESSOR})
MESSAGE ("System Platform : " \${CMAKE_SYSTEM})
MESSAGE ("C Compiler : " \${CMAKE_C_COMPILER})
MESSAGE ("Executable Dir : " \${EXECUTABLE_OUTPUT_PATH})
MESSAGE ("Library Dir : " \${LIBRARY_OUTPUT_PATH})
MESSAGE ("SDK Version : " ${PRJ_VERSION})
MESSAGE ("")
IF (WIN32)
MESSAGE ("Building on WINDOWS ...")
ELSE (WIN32)
MESSAGE ("Building on LINUX ...")
ENDIF (WIN32)
MESSAGE ("---------------------------------------------------------------------")
ADD_DEFINITIONS (-DDLL_IOT_EXPORTS)
$(for i in $(grep 'PKG_SOURCE' \
$(find ${TOP_DIR} -name ${MAKE_SEGMENT} -not -path "*.O*") \
| ${SED} "s:${TOP_DIR}/\(.*\)/${MAKE_SEGMENT}.*= *\(.*\):\1~\2:g"); do
UNZIP_DIR=${i%%~*}
GREPO_DIR=${i##*~}
GREPO_PRE=${GREPO_DIR%%.git}
echo "FILE (REMOVE_RECURSE \${PROJECT_SOURCE_DIR}/${UNZIP_DIR}/${GREPO_PRE})"
echo "EXECUTE_PROCESS (COMMAND git clone -q \${PROJECT_SOURCE_DIR}/${PKG_RPATH}/${GREPO_DIR} \${PROJECT_SOURCE_DIR}/${UNZIP_DIR}/${GREPO_PRE})"
echo ""
done)
EOB
cat << EOB >> ${TARGET_FILE}
$(for i in ${DEF_CFLAGS}; do
echo "ADD_DEFINITIONS (${i})"
done)
EOB
if [ "${COMP_LIB_NAME}" != "" ]; then
cat << EOB >> ${TARGET_FILE}
$(for i in ${COMP_LIB_COMPONENTS}; do
echo "ADD_SUBDIRECTORY (${i})"
done)
EOB
cat << EOB >> ${TARGET_FILE}
$(for i in ${SUBDIRS}; do
if [ ! -d ${TOP_DIR}/${i} ]; then
continue
fi
if echo ${COMP_LIB_COMPONENTS} | grep -qw ${i}; then
continue
fi
if [ "$i" = "tests" ]; then
continue
fi
echo "ADD_SUBDIRECTORY (${i})"
done)
EOB
cat << EOB >> ${TARGET_FILE}
ADD_LIBRARY (${COMP_LIB_NAME} SHARED
$(for i in ${SEP_LIBS}; do
j=${i%.a}
j=${j#lib}
echo " \$<TARGET_OBJECTS:${j}>"
done)
)
if(WIN32)
TARGET_LINK_LIBRARIES (${COMP_LIB_NAME} ws2_32)
endif(WIN32)
TARGET_LINK_LIBRARIES (${COMP_LIB_NAME} iot_hal)
SET (LIBRARY_OUTPUT_PATH ./out)
EOB
fi

View file

@ -0,0 +1,65 @@
#! /bin/bash
if [ $# != 2 ]; then echo "$# != 2"; exit 1; fi
if [ ! -f $1 ]; then echo "$1 not exist"; exit 2; fi
if [ "$(uname)" = "Darwin" ]; then
SED=gsed
else
SED=sed
fi
BLDV=$1
CMDV=$2
if [ "${CMDV}" = "list" ]; then
grep "^PKG_UPSTREAM_[-/_a-zA-Z0-9]*" ${BLDV} \
| ${SED} 's/^PKG_UPSTREAM_\([^ ]*\) = \(.*\)$/[\1] \2/g'
fi
REPO_LIST=$( \
grep "^PKG_UPSTREAM_[-/_a-zA-Z0-9]*" ${BLDV} \
| ${SED} 's/^PKG_UPSTREAM_\([^ ]*\) = \(.*\)$/[\1] \2/g' \
| cut -d' ' -f1 \
| ${SED} 's/\[//g;s/\]//g;' \
)
if [ "${CMDV}" = "update" ]; then
echo "Select repository to be updated, type 1 to update all repositories"|grep --color ".*"
echo ""
select O in "ALL REPOS" ${REPO_LIST}; do
echo ""
echo "Updating $O ..."|grep --color ".*"
echo ""
break
done
if [ "${O}" = "ALL REPOS" ]; then
O=""
fi
REPOS=$(grep -o "^PKG_UPSTREAM_[-/_a-zA-Z0-9]*" ${BLDV}|grep "${O}"|sort -u|${SED} 's:PKG_UPSTREAM_::')
for R in ${REPOS}; do
UPSTREAM=$(grep -m 1 "^PKG_UPSTREAM_${R}" ${BLDV}|awk '{ print $NF }')
SOURCE=$(grep -m 1 "^PKG_SOURCE_${R}" ${BLDV}|awk '{ print $NF }')
BRANCH=$(grep -m 1 "^PKG_BRANCH_${R}" ${BLDV}|awk '{ print $NF }')
[ "${BRANCH}" = "" ] && BRANCH="master"
echo "[ ${SOURCE} ] <= : ${UPSTREAM} :: ${BRANCH}"
set -x
cd ${PACKAGE_DIR}
rm -rf ${SOURCE}
# --single-branch might doesn't exist for git <= 1.7.9.5
#
# git clone -q --bare -b ${BRANCH} --single-branch ${UPSTREAM} ${SOURCE}
git clone -q --bare -b ${BRANCH} ${UPSTREAM} ${SOURCE}
rm -rf ${SOURCE}/hooks/
mkdir -p ${SOURCE}/hooks/
touch ${SOURCE}/hooks/.gitkeep
touch ${SOURCE}/refs/{heads,tags}/.gitkeep
rm -rf ${TOP_DIR}.pkgs/${SOURCE/.git}
cd ${OLDPWD}
set +x
done
fi

View file

@ -0,0 +1,98 @@
# Basic Settings
#
SHELL := /bin/bash
TOP_DIR ?= $(CURDIR)
ifeq (Darwin,$(strip $(shell uname)))
SED := gsed
STRIP_DBGOPT :=
else
SED := sed
STRIP_DBGOPT := --strip-debug
endif
# Settings of input directory and file
#
RULE_DIR ?= $(TOP_DIR)/build-rules
CONFIG_DIR ?= $(TOP_DIR)/configs
PACKAGE_DIR ?= $(TOP_DIR)/packages
IMPORT_DIR ?= $(TOP_DIR)/import
MAKE_SEGMENT ?= iot.mk
DOXYGEN_DIR ?= $(TOP_DIR)
ifeq ($(shell [ ! -d $(CONFIG_DIR) ] && echo y),y)
DEFAULT_BLD := $(RULE_DIR)/misc/config.generic.default
endif
# Settings of project information
PRJ_NAME ?= LITE-build.prj
PRJ_VERSION ?= LITE-build.ver
# Settings of output directory
#
CONFIG_TPL := $(TOP_DIR)/.config
OUTPUT_DIR ?= $(TOP_DIR)/.O
SHADOW_DIR ?= workspace output tests/kconf
DIST_DIR ?= $(TOP_DIR)/output
LCOV_DIR ?= Coverage
FINAL_DIR ?= $(DIST_DIR)/release
# Setting of directory for flat modules
#
bindir = /usr/bin
libdir = /usr/lib
incdir = /usr/include
# Setting of build process control
#
COMPILE_LOG := compile.log
WARNING_LOG := warnings.log
HD_MAKEFILE := makefile
TOP_MAKEFILE := makefile
STAMP_PRJ_CFG := $(OUTPUT_DIR)/.just.configured
STAMP_BLD_ENV := $(OUTPUT_DIR)/.sub-build.env
STAMP_BLD_VAR := $(OUTPUT_DIR)/.sub-build.vars
STAMP_LCOV := $(OUTPUT_DIR)/.coverage.done
STAMP_UNPACK := .unpack.done
STAMP_CONFIG := .config.done
STAMP_CMAKE := .cmake_section
STAMP_BUILD := .build.done
STAMP_INSTALL := .install.done
STAMP_POSTINS := .post.install.done
STAMP_SHIELD := .shield.done
STAMP_POST_RULE := $(OUTPUT_DIR)/.post-rules.mk
STAMP_DIR := $(OUTPUT_DIR)/stamps
STAMP_ONE_MK := $(OUTPUT_DIR)/.one_makefile
ifdef DEBUG
AUTO_HEADER_Q :=
ORIGIN_Q :=
SHELL_DBG := set -x;
Q :=
TOP_Q :=
else
Q := @
TOP_Q := @
endif
ifdef DEBUG_SHELL
SHELL_DBG := set -x;
endif
# Setting of downloading toolchains
TOOLCHAIN_DLDIR :=
# Setting of directory for origin modules
#
export INSTALL_DIR = $(OUTPUT_DIR)/usr
export INSTALL_BIN_DIR = $(INSTALL_DIR)/bin
export INSTALL_LIB_DIR = $(INSTALL_DIR)/lib
# Setting of cmake auto-generation
#
CMAKE_EXPORT_LIBS := \
src/ref-impl/hal \
src/ref-impl/tls \
include $(RULE_DIR)/funcs.mk

View file

@ -0,0 +1,3 @@
LIBA_TARGET := libiot_tick_notify.a
HDR_REFS += src/protocol/alcs

View file

@ -0,0 +1,495 @@
#ifdef ALCS_ENABLED
#include "cJSON.h"
#include "iot_import.h"
#include "CoAPExport.h"
#include "CoAPServer.h"
#include "iotx_alcs.h"
#include "alcs_api_internal.h"
#include "iotx_log.h"
#define TICK_NOTIFY_ADDR "255.255.255.255"
#define TICK_NOTIFY_PORT (5683)
#define TICK_NOTIFY_INTERVAL (1 * 60 * 1000)
#define ALCS_TICK_NOTIFY_URI "/dev/core/service/dev/tick_notify"
#define ALCS_TICK_NOTIFY_MSG_FMT "{\"id\":0,\"version\":\"1.0\",\"params\":{\"tick\":\"%s\",\"mode\":%d,\"seqnum\":%d,\"synced\":%d}}"
#define TICK_NOTIFY_MODE_BROADCAST (1)
#define TICK_NOTIFY_MODE_REQUEST (2)
#define TICK_NOTIFY_MODE_RESPONSE (3)
#define TICK_NOTIFY_MODE_SYNCED (4)
#define TICK_NOTIFY_MSG_MAX_LEN (90)
#define TICK_NOTIFY_MAX_DELAY (50)
#define TICK_NOTIFY_DEBUG_ENABLE
#ifdef TICK_NOTIFY_DEBUG_ENABLE
#define TICK_NOTIFY_DEBUG(...) log_debug("tick_notify", __VA_ARGS__)
#define TICK_NOTIFY_INFO(...) log_info("tick_notify", __VA_ARGS__)
#define TICK_NOTIFY_WRN(...) log_warning("tick_notify", __VA_ARGS__)
#define TICK_NOTIFY_ERR(...) log_err("tick_notify", __VA_ARGS__)
#else
#define TICK_NOTIFY_DEBUG(...)
#define TICK_NOTIFY_INFO(...)
#define TICK_NOTIFY_WRN(...)
#define TICK_NOTIFY_ERR(...)
#endif
typedef struct {
void *timer;
uint64_t tick_ms_base;//获取外部sync tick时本机的tick参考
uint64_t tick_ms_sync;//保存获取的外部syn tick
uint64_t tick_ms_send_request;//收到广播后对外发送的tick
uint64_t tick_ms_recv_request;//收到外部request时本地tick
uint64_t tick_ms_send_response;//收到request后对外发送后的本地tick
uint64_t tick_ms_received_resp;//保存获取resp的时间
int32_t local_seq_num;
int32_t remote_seq_num;
char inited;
char is_synced;//是否同步过外部tick
NetworkAddr remote;
int status;
char is_master;
int delay;
char tick_changing_flag;
} TickNotify_Context;
static uint64_t strtouint64(char *inputstr, uint64_t *intnum)
{
uint64_t i = 0, res = 0;
uint64_t val = 0;
for (i = 0;i < 21;i++){
if (inputstr[i] == '\0'){
*intnum = val;
res = SUCCESS_RETURN;
break;
}
else if ((inputstr[i] >= '0') && (inputstr[i] <= '9')){
val = val * 10 + (inputstr[i] - '0');
}
else{
res = FAIL_RETURN;
break;
}
}
if (i >= 21){
res = FAIL_RETURN;
}
return res;
}
static void* uint64toa(int64_t uint64num, char str[])
{
uint64_t i = 0, res = 0;
uint64_t val = 0;
uint64_t temp64 = 0;
uint8_t numlen = 0;
temp64 = uint64num;
do{
str[i++] = temp64 % 10;
}while((temp64/=10) > 0);
numlen = i;
temp64 = uint64num;
str[numlen] = '\0';
do{
str[--numlen] = temp64 % 10 + '0';
}while((temp64/=10) > 0);
return SUCCESS_RETURN;
}
static TickNotify_Context g_ticknotify_ctx;
void* iotx_tick_notify_get_context()
{
return &g_ticknotify_ctx;
}
int32_t iotx_tick_notify_new_local_seqnum()
{
TickNotify_Context *ctx = iotx_tick_notify_get_context();
return ++ctx->local_seq_num;
}
int iotx_get_notify_time(uint64_t *tick)
{
TickNotify_Context *ctx = iotx_tick_notify_get_context();
int ret = -1;
if(ctx->inited == 0){
return -1;
}
if(ctx == NULL){
ret = -1;
}else if(ctx->is_synced == 1){
if(ctx->tick_changing_flag == 1){
return -1;
}
*tick = ctx->tick_ms_sync + ((int)HAL_UptimeMs() - (int)ctx->tick_ms_base);
ret = 0;
}else if(ctx->is_synced == 0){
*tick = HAL_UptimeMs();
ret = -2;
}
return ret;
}
void iotx_tick_notify(void *ticknotify_ctx, NetworkAddr *remote, int mode, uint64_t tick, int seqnum)
{
int res = 0;
TickNotify_Context *tick_ctx = ticknotify_ctx;
iotx_alcs_msg_t alcs_msg;
char str[20] = {0};
if(tick_ctx == NULL){
return;
}
memset(&alcs_msg, 0, sizeof(iotx_alcs_msg_t));
alcs_msg.group_id = 0;
alcs_msg.ip = TICK_NOTIFY_ADDR;
alcs_msg.port = TICK_NOTIFY_PORT;
alcs_msg.msg_code = ITOX_ALCS_COAP_MSG_CODE_POST;
alcs_msg.msg_type = IOTX_ALCS_MESSAGE_TYPE_NON;
alcs_msg.uri = ALCS_TICK_NOTIFY_URI;
uint64toa(tick, str);
alcs_msg.payload = HAL_Malloc(TICK_NOTIFY_MSG_MAX_LEN);
if(alcs_msg.payload == NULL){
return;
}
memset(alcs_msg.payload, 0, TICK_NOTIFY_MSG_MAX_LEN);
HAL_Snprintf((char *)alcs_msg.payload, TICK_NOTIFY_MSG_MAX_LEN, ALCS_TICK_NOTIFY_MSG_FMT, str, mode, seqnum, tick_ctx->is_synced);
alcs_msg.payload_len = strlen((char *)alcs_msg.payload) + 1;
NetworkAddr notify_sa;
CoAPContext *coap_ctx = CoAPServer_init();
if(NULL == remote){
memset(&notify_sa, 0, sizeof(notify_sa));
memcpy(notify_sa.addr, TICK_NOTIFY_ADDR, strlen(TICK_NOTIFY_ADDR));
notify_sa.port = TICK_NOTIFY_PORT;
}else{
memcpy(&notify_sa, remote, sizeof(NetworkAddr));
}
CoAPServerMultiCast_send(coap_ctx, &notify_sa, alcs_msg.uri, (uint8_t *)alcs_msg.payload,
(uint16_t)alcs_msg.payload_len, NULL, NULL);
if(alcs_msg.payload){
HAL_Free(alcs_msg.payload);
}
}
void iotx_tick_notify_timer_change(int interval)
{
TickNotify_Context *tick_ctx = iotx_tick_notify_get_context();
if(tick_ctx == NULL){
return;
}
HAL_Timer_Stop(tick_ctx->timer);
HAL_Timer_Start(tick_ctx->timer, interval);
}
static int random_num(void)
{
HAL_Srandom(HAL_UptimeMs());
return HAL_Random(0xFF)%20 + 1;
}
void iotx_tick_notify_send_broadcast()
{
TickNotify_Context *ctx = iotx_tick_notify_get_context();
uint64_t tick = 0;
int32_t seqnum = 0;
iotx_get_notify_time(&tick);
seqnum = iotx_tick_notify_new_local_seqnum();
iotx_tick_notify((void *)ctx, NULL, TICK_NOTIFY_MODE_BROADCAST, tick, seqnum);
}
void iotx_tick_notify_send_request()
{
TickNotify_Context *ctx = iotx_tick_notify_get_context();
uint64_t tick = 0;
int32_t seqnum = 0;
iotx_get_notify_time(&tick);
seqnum = iotx_tick_notify_new_local_seqnum();
iotx_tick_notify((void *)ctx, &ctx->remote, TICK_NOTIFY_MODE_REQUEST, tick, seqnum);
ctx->tick_ms_send_request = HAL_UptimeMs();
ctx->is_master = 0;
}
void iotx_tick_notify_send_response()
{
TickNotify_Context *ctx = iotx_tick_notify_get_context();
uint64_t tick = 0;
iotx_get_notify_time(&tick);
iotx_tick_notify((void *)ctx, &ctx->remote, TICK_NOTIFY_MODE_RESPONSE, tick, ctx->remote_seq_num);
ctx->tick_ms_send_response = HAL_UptimeMs();
ctx->is_master = 1;
}
void iotx_tick_notify_send_synced()
{
TickNotify_Context *ctx = iotx_tick_notify_get_context();
uint64_t tick = 0;
iotx_get_notify_time(&tick);
iotx_tick_notify((void *)ctx, &ctx->remote, TICK_NOTIFY_MODE_SYNCED, tick, ctx->remote_seq_num);
}
void tick_process_cycle(void *context)
{
TickNotify_Context *ctx = context;
if(ctx == NULL){
return;
}
switch(ctx->status){
case TICK_NOTIFY_MODE_BROADCAST:
iotx_tick_notify_send_broadcast();
iotx_tick_notify_timer_change(TICK_NOTIFY_INTERVAL + ctx->delay * 1000);
break;
case TICK_NOTIFY_MODE_REQUEST:
iotx_tick_notify_send_request();
iotx_tick_notify_timer_change(TICK_NOTIFY_INTERVAL * 2 + ctx->delay * 1000);
ctx->status = TICK_NOTIFY_MODE_BROADCAST;
break;
case TICK_NOTIFY_MODE_SYNCED:
iotx_tick_notify_send_synced();
iotx_tick_notify_timer_change(TICK_NOTIFY_INTERVAL * 2 + ctx->delay * 1000);
ctx->status = TICK_NOTIFY_MODE_BROADCAST;
default:
break;
}
}
void iotx_tick_notify_msg_handle(CoAPContext *context, const char *paths, NetworkAddr *remote,
CoAPMessage *message)
{
int res = 0;
TickNotify_Context *ctx = iotx_tick_notify_get_context();
cJSON *json_item_JSON = NULL;
cJSON *json_param = NULL;
cJSON *json_tick = NULL;
cJSON *json_mode = NULL;
cJSON *json_seq = NULL;
cJSON *json_synced = NULL;
uint64_t pasttime = 0;
json_item_JSON = cJSON_Parse((const char *)message->payload);
if (json_item_JSON == NULL) {
return;
}
if (!cJSON_IsObject(json_item_JSON)){
goto func_exit;
}
json_param = cJSON_GetObjectItem(json_item_JSON, "params");
if (json_param == NULL) {
goto func_exit;
}
json_tick = cJSON_GetObjectItem(json_param, "tick");
if (json_tick == NULL || !cJSON_IsString(json_tick)) {
goto func_exit;
}
json_mode = cJSON_GetObjectItem(json_param, "mode");
if (json_mode == NULL || !cJSON_IsNumber(json_mode)) {
goto func_exit;
}
json_seq = cJSON_GetObjectItem(json_param, "seqnum");
if (json_seq == NULL || !cJSON_IsNumber(json_seq)) {
goto func_exit;
}
json_synced = cJSON_GetObjectItem(json_param, "synced");
if (json_synced == NULL || !cJSON_IsNumber(json_synced)) {
goto func_exit;
}
switch(json_mode->valueint){
/* received broadcast */
case TICK_NOTIFY_MODE_BROADCAST:
TICK_NOTIFY_INFO("received broadcast.");
if(json_synced->valueint == 1){
//ctx->remote_seq_num = json_seq->valueint;
memcpy(&ctx->remote, remote, sizeof(NetworkAddr));
ctx->status = TICK_NOTIFY_MODE_REQUEST;
iotx_tick_notify_timer_change(random_num() * 1000);
TICK_NOTIFY_INFO("ready to send request.");
}else if(json_synced->valueint == 0 && ctx->is_synced == 0){
//ctx->remote_seq_num = json_seq->valueint;
memcpy(&ctx->remote, remote, sizeof(NetworkAddr));
ctx->status = TICK_NOTIFY_MODE_REQUEST;
iotx_tick_notify_timer_change(10000 + random_num() * 1000);
TICK_NOTIFY_INFO("ready to send request.");
}else if(json_synced->valueint == 0 && ctx->is_synced == 1 && ctx->is_master == 1){
ctx->status = TICK_NOTIFY_MODE_BROADCAST;
iotx_tick_notify_timer_change(2000);
TICK_NOTIFY_INFO("ready to send broadcast.");
}
break;
/* received request*/
case TICK_NOTIFY_MODE_REQUEST:
ctx->remote_seq_num = json_seq->valueint;
memcpy(&ctx->remote, remote, sizeof(NetworkAddr));
iotx_tick_notify_send_response();
break;
/* received response */
case TICK_NOTIFY_MODE_RESPONSE:
if(json_seq->valueint == ctx->local_seq_num && !memcmp(remote, &ctx->remote, sizeof(NetworkAddr))){
ctx->tick_ms_received_resp = message->timestamp;
ctx->delay = ((int)ctx->tick_ms_received_resp - (int)ctx->tick_ms_send_request)/2;
if(ctx->delay > TICK_NOTIFY_MAX_DELAY){
HAL_Printf("tick_notify:discard tick delay %d\n", ctx->delay);
ctx->delay = TICK_NOTIFY_MAX_DELAY;
break;
}
ctx->tick_changing_flag = 1;
ctx->tick_ms_base = ctx->tick_ms_received_resp;
strtouint64(json_tick->valuestring, &(ctx->tick_ms_sync));
ctx->tick_ms_sync = ctx->tick_ms_sync + ctx->delay + ((int)HAL_UptimeMs() - (int)ctx->tick_ms_base);
ctx->is_synced = 1;
ctx->tick_changing_flag = 0;
if(json_synced->valueint == 0){
ctx->status = TICK_NOTIFY_MODE_SYNCED;
iotx_tick_notify_timer_change(random_num() * 1000);
}else{
iotx_tick_notify_timer_change(TICK_NOTIFY_INTERVAL * 2 + ctx->delay * 1000);
}
HAL_Printf("tick_notify: tick synced, delay is %d\n", ctx->delay);
}
break;
case TICK_NOTIFY_MODE_SYNCED:
if(json_synced->valueint == 1){
ctx->is_synced = 1;
}
break;
default:
HAL_Printf("mode not support");
break;
}
func_exit:
cJSON_Delete(json_item_JSON);
}
void iotx_tick_notify_register_resource()
{
iotx_alcs_res_t alcs_res;
CoAPContext *coap_ctx = CoAPServer_init();
int res = 0;
memset(&alcs_res, 0, sizeof(iotx_alcs_res_t));
alcs_res.uri = ALCS_TICK_NOTIFY_URI;
alcs_res.msg_ct = IOTX_ALCS_MESSAGE_CT_APP_JSON;
alcs_res.msg_perm = IOTX_ALCS_MESSAGE_PERM_POST;
alcs_res.maxage = 60;
alcs_res.need_auth = 0;
alcs_res.callback = iotx_tick_notify_msg_handle;
alcs_resource_register(coap_ctx,
NULL,
NULL,
alcs_res.uri,
alcs_res.msg_perm,
alcs_res.msg_ct,
alcs_res.maxage,
alcs_res.need_auth,
alcs_res.callback);
}
void iotx_tick_get_register_resource()
{
iotx_alcs_res_t alcs_res;
CoAPContext *coap_ctx = CoAPServer_init();
int res = 0;
memset(&alcs_res, 0, sizeof(iotx_alcs_res_t));
alcs_res.uri = ALCS_TICK_NOTIFY_URI;
alcs_res.msg_ct = IOTX_ALCS_MESSAGE_CT_APP_JSON;
alcs_res.msg_perm = IOTX_ALCS_MESSAGE_PERM_GET;
alcs_res.maxage = 60;
alcs_res.need_auth = 0;
alcs_res.callback = iotx_tick_notify_msg_handle;
alcs_resource_register(coap_ctx,
NULL,
NULL,
alcs_res.uri,
alcs_res.msg_perm,
alcs_res.msg_ct,
alcs_res.maxage,
alcs_res.need_auth,
alcs_res.callback);
}
void *iotx_tick_notify_init()
{
if(g_ticknotify_ctx.inited == 1){
return &g_ticknotify_ctx;
}
memset(&g_ticknotify_ctx,0,sizeof(TickNotify_Context));
g_ticknotify_ctx.timer = HAL_Timer_Create("tick_notify", tick_process_cycle, &g_ticknotify_ctx);
g_ticknotify_ctx.status = TICK_NOTIFY_MODE_BROADCAST;
iotx_tick_notify_register_resource();
iotx_tick_get_register_resource();
iotx_tick_notify_send_broadcast();
iotx_tick_notify_timer_change(TICK_NOTIFY_INTERVAL + random_num() * 1000);
g_ticknotify_ctx.inited = 1;
return &g_ticknotify_ctx;
}
int iotx_tick_notify_deinit()
{
if(g_ticknotify_ctx.timer){
HAL_Timer_Stop(g_ticknotify_ctx.timer);
HAL_Timer_Delete(g_ticknotify_ctx.timer);
}
memset(&g_ticknotify_ctx,0,sizeof(TickNotify_Context));
return 0;
}
#endif

View file

@ -0,0 +1,18 @@
NAME := libiot_tick_notify
$(NAME)_MBINS_TYPE := kernel
$(NAME)_VERSION := 2.3.0
$(NAME)_SUMMARY :=
$(NAME)_INCLUDES := ../../src/protocol/alcs/
$(NAME)_SOURCES := tick_notify.c
ifeq ($(COMPILER),)
else ifeq ($(COMPILER),gcc)
$(NAME)_CFLAGS += -Wall -Werror -Wno-unused-variable -Wno-unused-parameter -Wno-implicit-function-declaration
$(NAME)_CFLAGS += -Wno-type-limits -Wno-sign-compare -Wno-pointer-sign -Wno-uninitialized
$(NAME)_CFLAGS += -Wno-return-type -Wno-unused-function -Wno-unused-but-set-variable
$(NAME)_CFLAGS += -Wno-unused-value -Wno-strict-aliasing
endif

View file

@ -0,0 +1,14 @@
INCLUDE_DIRECTORIES (${PROJECT_SOURCE_DIR})
INCLUDE_DIRECTORIES (${PROJECT_SOURCE_DIR}/include)
INCLUDE_DIRECTORIES (${PROJECT_SOURCE_DIR}/include/exports)
INCLUDE_DIRECTORIES (${PROJECT_SOURCE_DIR}/include/imports)
INCLUDE_DIRECTORIES (${PROJECT_SOURCE_DIR}/components/timer_service/)
FILE (GLOB src_services_timer_service_SRCS
${PROJECT_SOURCE_DIR}/components/timer_service/*.c
)
ADD_LIBRARY (iot_timer_service OBJECT
${src_services_timer_service_SRCS}
)

View file

@ -0,0 +1,98 @@
/*
* Copyright 2015, alex at staticlibs.net
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* File: ccronexpr.h
* Author: alex
*
* Created on February 24, 2015, 9:35 AM
*/
#ifndef CCRONEXPR_H
#define CCRONEXPR_H
#if defined(__cplusplus) && !defined(CRON_COMPILE_AS_CXX)
extern "C" {
#endif
#ifndef ANDROID
#include <time.h>
#else /* ANDROID */
#include <time64.h>
#endif /* ANDROID */
#include <stdint.h> /*added for use if uint*_t data types*/
/**
* Parsed cron expression
*/
typedef struct {
uint8_t seconds[8];
uint8_t minutes[8];
uint8_t hours[3];
uint8_t days_of_week[1];
uint8_t days_of_month[4];
uint8_t months[2];
} cron_expr;
/**
* Parses specified cron expression.
*
* @param expression cron expression as nul-terminated string,
* should be no longer that 256 bytes
* @param pointer to cron expression structure, it's client code responsibility
* to free/destroy it afterwards
* @param error output error message, will be set to string literal
* error message in case of error. Will be set to NULL on success.
* The error message should NOT be freed by client.
*/
void cron_parse_expr(const char* expression, cron_expr* target, const char** error);
/**
* Uses the specified expression to calculate the next 'fire' date after
* the specified date. All dates are processed as UTC (GMT) dates
* without timezones information. To use local dates (current system timezone)
* instead of GMT compile with '-DCRON_USE_LOCAL_TIME'
*
* @param expr parsed cron expression to use in next date calculation
* @param date start date to start calculation from
* @return next 'fire' date in case of success, '((time_t) -1)' in case of error.
*/
time_t cron_next(cron_expr* expr, time_t date);
/**
* Uses the specified expression to calculate the previous 'fire' date after
* the specified date. All dates are processed as UTC (GMT) dates
* without timezones information. To use local dates (current system timezone)
* instead of GMT compile with '-DCRON_USE_LOCAL_TIME'
*
* @param expr parsed cron expression to use in previous date calculation
* @param date start date to start calculation from
* @return previous 'fire' date in case of success, '((time_t) -1)' in case of error.
*/
time_t cron_prev(cron_expr* expr, time_t date);
uint8_t cron_get_bit(uint8_t* rbyte, int idx);
void cron_set_bit(uint8_t* rbyte, int idx);
#if defined(__cplusplus) && !defined(CRON_COMPILE_AS_CXX)
} /* extern "C"*/
#endif
#endif /* CCRONEXPR_H */

View file

@ -0,0 +1 @@
LIBA_TARGET := libiot_timer_service.a

View file

@ -0,0 +1,151 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef __TIMER_SERVICE_H__
#define __TIMER_SERVICE_H__
#if defined(__cplusplus)
extern "C" {
#endif
#include "iot_export_timer.h"
#include "iotx_log.h"
#define TS "timer_serv"
#define TS_ERR(...) log_err(TS, __VA_ARGS__)
#define TS_WRN(...) log_warning(TS, __VA_ARGS__)
#define TS_INFO(...) log_info(TS, __VA_ARGS__)
#define TS_DEBUG(...) log_debug(TS, __VA_ARGS__)
#define HOURS_OF_DAY 24
#define MINUTES_OF_HOUR 60
#define SECONDS_OF_MINUTE 60
#define MINUTES_OF_WEEK (60 * 24 * 7)
#define SUNDAY 1556956800 //2019/5/5 0:0:0 sunday
#define SECONDS_OF_DAY 86400
#define DEFAULT_TIMEZONEOFFSET 8 // BEIJING
#ifdef ENABLE_COUNTDOWN
#define NUM_OF_COUNTDOWN_TARGET 1
#define COUNTDOWN_TARGET_INIT() \
const char *countdown_target_list[NUM_OF_COUNTDOWN_TARGET] = { "PowerSwitch"}
#endif
typedef enum timer_service_type {
COUNT_DOWN,
#ifdef ENABLE_COUNTDOWN_LIST
COUNT_DOWN_LIST,
#endif
#ifdef ENABLE_LOCALTIMER
LOCAL_TIMER,
#endif
#ifdef ENABLE_PERIOD_TIMER
PERIOD_TIMER,
#endif
#ifdef ENABLE_RANDOM_TIMER
RANDOM_TIMER,
#endif
TYPE_MAX
} timer_service_type_t;
const char *str_prop_name[]={
"CountDown",
#ifdef ENABLE_COUNTDOWN_LIST
"CountDownList",
#endif
#ifdef ENABLE_LOCALTIMER
"LocalTimer",
#endif
#ifdef ENABLE_PERIOD_TIMER
"PeriodTimer",
#endif
#ifdef ENABLE_RANDOM_TIMER
"RandomTimer",
#endif
""};
#ifdef ENABLE_COUNTDOWN
typedef struct countdown {
int value_list[NUM_OF_COUNTDOWN_TARGET];
int time_left;
int duration;
int power_switch;
int is_running;
char timeStamp[20];
} countdown_t;
#endif
#ifdef ENABLE_COUNTDOWN_LIST
#define NUM_OF_COUNTDOWNLIST 10
#define NUM_OF_COUNTDOWN_LIST_TARGET 10
typedef struct countdown_list {
// int value_list[NUM_OF_COUNTDOWN_LIST_TARGET];
int time_left;
int duration;
int is_running;
char timeStamp[20];
int action;
} countdown_list_t;
#endif
#ifdef ENABLE_LOCALTIMER
#define NUM_OF_LOCALTIMER 5
#define NUM_OF_LOCAL_TIMER_TARGET 5
typedef struct local_timer {
int value_list[NUM_OF_LOCAL_TIMER_TARGET];
char cron_timer[32];
char targets[STRING_MAX_LEN];
int offset[DAYS_OF_WEEK];
int enable;
int action;
int is_valid;
int timezone_offset;
int repeat;
} local_timer_t;
#endif
#ifdef ENABLE_PERIOD_TIMER
#define NUM_OF_PERIOD_TIMER 1
typedef struct period_timer {
// int value_list[NUM_OF_PERIOD_TIMER_TARGET];
int offset_start[DAYS_OF_WEEK];
char start[8];
int offset_end[DAYS_OF_WEEK];
char end[8];
int timezoneOffset;
int repeat;
char repeat_raw[16];
int enable;
int run_time;
int sleep_time;
} period_timer_t;
#endif
#ifdef ENABLE_RANDOM_TIMER
#define NUM_OF_RANDOM_TIMER 1
#define RANDOM_MINUTE_LIMIT 30
typedef struct random_timer {
// int value_list[NUM_OF_RANDOM_TIMER_TARGET];
int offset_start[DAYS_OF_WEEK];
char start[8];
int offset_end[DAYS_OF_WEEK];
char end[8];
int timezoneOffset;
uint8_t repeat;
char repeat_raw[16];
int enable;
} random_timer_t;
#endif
// #define EXAMPLE_TRACE(...) \
// do { \
// HAL_Printf("\033[1;32;40m%s.%d: ", __func__, __LINE__); \
// HAL_Printf(__VA_ARGS__); \
// HAL_Printf("\033[0m\r\n"); \
// } while (0)
#if defined(__cplusplus)
} /* extern "C" */
#endif
#endif /* __TIMER_SERVICE_H__ */

View file

@ -0,0 +1,19 @@
NAME := libiot_timer_service
$(NAME)_MBINS_TYPE := kernel
$(NAME)_VERSION := 2.3.0
$(NAME)_SUMMARY :=
$(NAME)_INCLUDES += .
$(NAME)_SOURCES :=
$(NAME)_SOURCES += timer_service.c ccronexpr.c
ifeq ($(COMPILER),)
else ifeq ($(COMPILER),gcc)
$(NAME)_CFLAGS += -Wall -Werror -Wno-unused-variable -Wno-unused-parameter -Wno-implicit-function-declaration
$(NAME)_CFLAGS += -Wno-type-limits -Wno-sign-compare -Wno-pointer-sign -Wno-uninitialized
$(NAME)_CFLAGS += -Wno-return-type -Wno-unused-function -Wno-unused-but-set-variable
$(NAME)_CFLAGS += -Wno-unused-value -Wno-strict-aliasing
endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,247 @@
/*
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef cJSON__h
#define cJSON__h
#ifdef __cplusplus
extern "C"
{
#endif
/* project version */
#define CJSON_VERSION_MAJOR 1
#define CJSON_VERSION_MINOR 5
#define CJSON_VERSION_PATCH 3
#include <stdint.h>
#include <stddef.h>
/* cJSON Types: */
#define cJSON_Invalid (0)
#define cJSON_False (1 << 0)
#define cJSON_True (1 << 1)
#define cJSON_NULL (1 << 2)
#define cJSON_Number (1 << 3)
#define cJSON_String (1 << 4)
#define cJSON_Array (1 << 5)
#define cJSON_Object (1 << 6)
#define cJSON_Raw (1 << 7) /* raw json */
#define cJSON_IsReference 256
#define cJSON_StringIsConst 512
/* The cJSON structure: */
typedef struct cJSON
{
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *next;
struct cJSON *prev;
/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
struct cJSON *child;
/* The type of the item, as above. */
int type;
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
char *valuestring;
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
int valueint;
/* The item's number, if type==cJSON_Number */
double valuedouble;
/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
char *string;
} cJSON;
typedef int cJSON_bool;
#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
#define __WINDOWS__
#endif
#ifdef __WINDOWS__
/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 2 define options:
CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
For *nix builds that support visibility attribute, you can define similar behavior by
setting default visibility to hidden by adding
-fvisibility=hidden (for gcc)
or
-xldscope=hidden (for sun cc)
to CFLAGS
then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
*/
/* export symbols by default, this is necessary for copy pasting the C and header file */
#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_EXPORT_SYMBOLS
#endif
#if defined(CJSON_HIDE_SYMBOLS)
#define CJSON_PUBLIC(type) type __stdcall
#elif defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllexport) type __stdcall
#elif defined(CJSON_IMPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllimport) type __stdcall
#endif
#else /* !WIN32 */
#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
#else
#define CJSON_PUBLIC(type) type
#endif
#endif
/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
* This is to prevent stack overflows. */
#ifndef CJSON_NESTING_LIMIT
#define CJSON_NESTING_LIMIT 1000
#endif
/* returns the version of cJSON as a string */
CJSON_PUBLIC(const char*) cJSON_Version(void);
/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
/* Render a cJSON entity to text for transfer/storage. */
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. */
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
/* Delete a cJSON entity and all subentities. */
CJSON_PUBLIC(void) cJSON_Delete(cJSON *c);
/* Returns the number of items in an array (or object). */
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
/* Get item "string" from object. Case insensitive. */
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
/* These functions check the type of an item */
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
/* These calls create a cJSON item of the appropriate type. */
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
/* raw json */
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
/* These utilities create an Array of count items. */
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count);
/* Append item to the specified array/object. */
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
* WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
* writing to `item->string` */
CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
/* Remove/Detatch items from Arrays/Objects. */
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
/* Update array items. */
CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem);
CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem);
/* Duplicate a cJSON item */
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
need to be released. With recurse!=0, it will duplicate any children connected to the item.
The item->next and ->prev pointers are always zero on return from Duplicate. */
/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
* case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error. If not, then cJSON_GetErrorPtr() does the job. */
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
CJSON_PUBLIC(void) cJSON_Minify(char *json);
/* Macros for creating things quickly. */
#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
#define cJSON_AddRawToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateRaw(s))
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
/* helper for the cJSON_SetNumberValue macro */
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
/* Macro for iterating over an array or object */
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
CJSON_PUBLIC(void) cJSON_free(void *object);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,77 @@
DEPENDS := src/ref-impl/hal
DEPENDS += src/ref-impl/tls
HDR_REFS += src/infra
HDR_REFS += src/services
HDR_REFS += linkkit/gateway
HDR_REFS += linkkit/certification
HDR_REFS += linkkit/living_platform
HDR_REFS += linkkit/living_platform_rawdata
LDFLAGS := -Bstatic
LDFLAGS += -liot_sdk
LDFLAGS += -liot_hal
CFLAGS := $(filter-out -ansi,$(CFLAGS))
ifneq (,$(filter -D_PLATFORM_IS_WINDOWS_,$(CFLAGS)))
LDFLAGS += -lws2_32
CFLAGS := $(filter-out -DCOAP_COMM_ENABLED,$(CFLAGS))
endif
ifneq (,$(filter -DSUPPORT_ITLS,$(CFLAGS)))
LDFLAGS += -litls
else
LDFLAGS += -liot_tls
endif
ifneq (,$(filter -D_PLATFORM_IS_LINUX_, $(CFLAGS)))
LDFLAGS += -L$(TOP_DIR)/lib/linux
LDFLAGS += -lawss_security
endif
SRCS_gateway := cJSON.c linkkit/gateway/gateway_entry.c \
linkkit/gateway/gateway_main.c \
linkkit/gateway/gateway_api.c \
linkkit/gateway/gateway_ut.c
SRCS_certification := cJSON.c linkkit/certification/ct_entry.c \
linkkit/certification/ct_main.c \
linkkit/certification/ct_ut.c \
linkkit/certification/ct_ota.c
SRCS_living_platform := cJSON.c linkkit/living_platform/app_entry.c \
linkkit/living_platform/living_platform_main.c \
linkkit/living_platform/living_platform_ut.c
SRCS_living_platform_rawdata := cJSON.c linkkit/living_platform_rawdata/app_entry.c \
linkkit/living_platform_rawdata/living_platform_rawdata_main.c \
linkkit/living_platform_rawdata/living_platform_rawdata_ut.c
# Syntax of Append_Conditional
# ---
#
# $(call Append_Conditional, TARGET, \ <-- Operated Variable
# member1 member2 ... , \ <-- Appended Members
# switch1 switch2 ... , \ <-- All These Switches are Defined
# switch3 switch4 ...) <-- All These Switches are Not Defined (Optional)
$(call Append_Conditional, LDFLAGS, \
-litls \
-lid2client \
-lkm \
-lplat_gen \
-lalicrypto \
-lmbedcrypto \
, \
SUPPORT_ITLS, \
SUPPORT_TLS)
$(call Append_Conditional, TARGET, gateway, DEVICE_MODEL_ENABLED DEVICE_MODEL_GATEWAY)
$(call Append_Conditional, TARGET, certification, DEVICE_MODEL_ENABLED)
$(call Append_Conditional, TARGET, living_platform, DEVICE_MODEL_ENABLED, DEVICE_MODEL_RAWDATA_SOLO)
$(call Append_Conditional, TARGET, living_platform_rawdata, DEVICE_MODEL_ENABLED DEVICE_MODEL_RAWDATA_SOLO)
# Clear All Above when Build for Windows
#
ifneq (,$(filter -D_PLATFORM_IS_WINDOWS_,$(CFLAGS)))
TARGET := living_platform
endif

View file

@ -0,0 +1,84 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "iot_export.h"
#include "ct_entry.h"
#include "ct_main.h"
#include "ct_ut.h"
static void load_ct_meta_info(void)
{
int len = 0;
char key_buf[MAX_KEY_LEN];
char product_key[PRODUCT_KEY_LEN + 1] = {0};
char product_secret[PRODUCT_SECRET_LEN + 1] = {0};
char device_name[DEVICE_NAME_LEN + 1] = {0};
char device_secret[DEVICE_SECRET_LEN + 1] = {0};
len = PRODUCT_KEY_LEN + 1;
memset(key_buf, 0, MAX_KEY_LEN);
memset(product_key, 0, sizeof(product_key));
HAL_Snprintf(key_buf, MAX_KEY_LEN, "%s_%d", KV_KEY_PK, 0);
HAL_Kv_Get(key_buf, product_key, &len);
len = PRODUCT_SECRET_LEN + 1;
memset(key_buf, 0, MAX_KEY_LEN);
memset(product_secret, 0, sizeof(product_secret));
HAL_Snprintf(key_buf, MAX_KEY_LEN, "%s_%d", KV_KEY_PS, 0);
HAL_Kv_Get(key_buf, product_secret, &len);
len = DEVICE_NAME_LEN + 1;
memset(key_buf, 0, MAX_KEY_LEN);
memset(device_name, 0, sizeof(device_name));
HAL_Snprintf(key_buf, MAX_KEY_LEN, "%s_%d", KV_KEY_DN, 0);
HAL_Kv_Get(key_buf, device_name, &len);
len = DEVICE_SECRET_LEN + 1;
memset(key_buf, 0, MAX_KEY_LEN);
memset(device_secret, 0, sizeof(device_secret));
HAL_Snprintf(key_buf, MAX_KEY_LEN, "%s_%d", KV_KEY_DS, 0);
HAL_Kv_Get(key_buf, device_secret, &len);
if ((strlen(product_key) > 0) && (strlen(product_secret) > 0) && (strlen(device_name) > 0))
{
HAL_SetProductKey(product_key);
HAL_SetProductSecret(product_secret);
HAL_SetDeviceName(device_name);
HAL_SetDeviceSecret(device_secret);
printf("pk[%s]\r\n", product_key);
printf("dn[%s]\r\n", device_name);
}
else
{
HAL_SetProductKey(PRODUCT_KEY);
HAL_SetProductSecret(PRODUCT_SECRET);
HAL_SetDeviceName(DEVICE_NAME);
HAL_SetDeviceSecret(DEVICE_SECRET);
printf("pk[%s]\r\n", PRODUCT_KEY);
printf("dn[%s]\r\n", DEVICE_NAME);
}
}
int main(int argc, char **argv)
{
ct_main_params_t paras;
paras.argc = argc;
paras.argv = argv;
#ifdef LOG_LEVEL_DEBUG
IOT_SetLogLevel(IOT_LOG_DEBUG);
#else
IOT_SetLogLevel(IOT_LOG_INFO);
#endif
load_ct_meta_info();
ct_main((void *)&paras);
return 0;
}

View file

@ -0,0 +1,19 @@
#ifndef __CT_ENTRY_H__
#define __CT_ENTRY_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#define LOG_LEVEL_DEBUG
typedef struct
{
int argc;
char **argv;
} ct_main_params_t;
extern void user_event_monitor(int event);
#endif

View file

@ -0,0 +1,741 @@
/*
* Copyright (C) 2015-2019 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include "cJSON.h"
#include "iot_import.h"
#include "iot_export_linkkit.h"
#include "iotx_log.h"
#include "ct_main.h"
#include "ct_entry.h"
#include "ct_ut.h"
#include "ct_ota.h"
static ct_ctx_t g_ct_ctx;
ct_ctx_t *ct_get_ctx(void)
{
return &g_ct_ctx;
}
static int user_connected_event_handler(void)
{
ct_ctx_t *ct_ctx = ct_get_ctx();
ct_info("Cloud Connected");
ct_ctx->cloud_connected = 1;
if (ct_ctx->master_initialized == 1) //initialized
{
}
return 0;
}
static int user_disconnected_event_handler(void)
{
ct_ctx_t *ct_ctx = ct_get_ctx();
ct_info("Cloud Disconnected");
ct_ctx->cloud_connected = 0;
return 0;
}
static int user_down_raw_data_arrived_event_handler(const int devid, const unsigned char *payload,
const int payload_len)
{
ct_info("Down Raw Message, Devid: %d, Payload Length: %d", devid, payload_len);
if (payload[0] == 0x02 && payload_len == 6)
{
ct_ut_set_LightSwitch(payload[5]);
}
return 0;
}
static int user_service_request_event_handler(const int devid, const char *serviceid, const int serviceid_len,
const char *request, const int request_len,
char **response, int *response_len)
{
int transparency = 0;
cJSON *root = NULL, *item_transparency = NULL;
ct_info("Service Request Received, Devid: %d, Service ID: %.*s, Payload: %s", devid, serviceid_len,
serviceid,
request);
/* Parse Root */
root = cJSON_Parse(request);
if (root == NULL || !cJSON_IsObject(root))
{
ct_err("JSON Parse Error");
return -1;
}
if (strlen("Custom") == serviceid_len && memcmp("Custom", serviceid, serviceid_len) == 0)
{
/* Parse Item */
const char *response_fmt = "{\"transparency\":%d}";
item_transparency = cJSON_GetObjectItem(root, "transparency");
if (item_transparency == NULL || !cJSON_IsNumber(item_transparency))
{
cJSON_Delete(root);
return -1;
}
ct_info("transparency: %d", item_transparency->valueint);
transparency = item_transparency->valueint + 1;
if (transparency > 100)
{
transparency = 100;
}
/* Send Service Response To Cloud */
*response_len = strlen(response_fmt) + 10 + 1;
*response = (char *)HAL_Malloc(*response_len);
if (*response == NULL)
{
ct_err("Memory Not Enough");
return -1;
}
memset(*response, 0, *response_len);
HAL_Snprintf(*response, *response_len, response_fmt, transparency);
*response_len = strlen(*response);
}
else if (strlen("ToggleLightSwitch") == serviceid_len && memcmp("ToggleLightSwitch", serviceid, serviceid_len) == 0)
{
/* Parse Item */
const char *response_fmt = "{\"LightSwitch\":%d}";
/* Send Service Response To Cloud */
*response_len = strlen(response_fmt) + strlen("LightSwitch") + 10;
*response = (char *)HAL_Malloc(*response_len);
if (*response == NULL)
{
ct_err("Memory Not Enough");
return -1;
}
memset(*response, 0, *response_len);
if (ct_ut_get_LightSwitch() == 0)
{
ct_ut_set_LightSwitch(1);
}
else
{
ct_ut_set_LightSwitch(0);
}
HAL_Snprintf(*response, *response_len, response_fmt, ct_ut_get_LightSwitch());
*response_len = strlen(*response);
}
cJSON_Delete(root);
return 0;
}
#ifdef ALCS_ENABLED
//Just for reference,user have to change his owner properties
static int user_property_get_event_handler(const int devid, const char *request, const int request_len, char **response,
int *response_len)
{
int index = 0;
ct_tsl_t *p_ct_tsl_data = ct_ut_get_tsl_data();
cJSON *response_root = NULL;
cJSON *request_root = NULL, *item_propertyid = NULL;
ct_info("Property Get Received, Devid: %d, Request: %s", devid, request);
/* Parse Request */
request_root = cJSON_Parse(request);
if (request_root == NULL || !cJSON_IsArray(request_root))
{
ct_info("JSON Parse Error");
return -1;
}
/* Prepare Response */
response_root = cJSON_CreateObject();
if (response_root == NULL)
{
ct_info("No Enough Memory");
cJSON_Delete(request_root);
return -1;
}
for (index = 0; index < cJSON_GetArraySize(request_root); index++)
{
item_propertyid = cJSON_GetArrayItem(request_root, index);
if (item_propertyid == NULL || !cJSON_IsString(item_propertyid))
{
ct_info("JSON Parse Error");
cJSON_Delete(request_root);
cJSON_Delete(response_root);
return -1;
}
ct_info("Property ID, index: %d, Value: %s", index, item_propertyid->valuestring);
if (strcmp("WIFI_Band", item_propertyid->valuestring) == 0)
{
cJSON_AddStringToObject(response_root, "WIFI_Band", p_ct_tsl_data->wifi.band);
}
else if (strcmp("WIFI_AP_BSSID", item_propertyid->valuestring) == 0)
{
cJSON_AddStringToObject(response_root, "WIFI_AP_BSSID", p_ct_tsl_data->wifi.bssid);
}
else if (strcmp("WIFI_Channel", item_propertyid->valuestring) == 0)
{
cJSON_AddNumberToObject(response_root, "WIFI_Channel", p_ct_tsl_data->wifi.Channel);
}
else if (strcmp("WiFI_SNR", item_propertyid->valuestring) == 0)
{
cJSON_AddNumberToObject(response_root, "WiFI_SNR", p_ct_tsl_data->wifi.SNR);
}
else if (strcmp("WiFI_RSSI", item_propertyid->valuestring) == 0)
{
cJSON_AddNumberToObject(response_root, "WiFI_RSSI", p_ct_tsl_data->wifi.rssi);
}
else if (strcmp("LightSwitch", item_propertyid->valuestring) == 0)
{
cJSON_AddBoolToObject(response_root, "LightSwitch", p_ct_tsl_data->LightSwitch);
}
else if (strcmp("NightLightSwitch", item_propertyid->valuestring) == 0)
{
cJSON_AddBoolToObject(response_root, "NightLightSwitch", p_ct_tsl_data->NightLightSwitch);
}
else if (strcmp("WorkMode", item_propertyid->valuestring) == 0)
{
cJSON_AddNumberToObject(response_root, "WorkMode", p_ct_tsl_data->WorkMode);
}
else if (strcmp("worktime", item_propertyid->valuestring) == 0)
{
cJSON_AddStringToObject(response_root, "worktime", p_ct_tsl_data->WorkTime);
}
else if (strcmp("Brightness", item_propertyid->valuestring) == 0)
{
cJSON_AddNumberToObject(response_root, "Brightness", p_ct_tsl_data->Brightness);
}
else if (strcmp("onlyread", item_propertyid->valuestring) == 0)
{
cJSON_AddNumberToObject(response_root, "onlyread", p_ct_tsl_data->readonly);
}
else if (strcmp("floatid", item_propertyid->valuestring) == 0)
{
cJSON_AddNumberToObject(response_root, "floatid", p_ct_tsl_data->f);
}
else if (strcmp("doubleid", item_propertyid->valuestring) == 0)
{
cJSON_AddNumberToObject(response_root, "doubleid", p_ct_tsl_data->d);
}
else if (strcmp("PropertyString", item_propertyid->valuestring) == 0)
{
cJSON_AddStringToObject(response_root, "PropertyString", p_ct_tsl_data->PropertyString);
}
else if (strcmp("RGBColor", item_propertyid->valuestring) == 0)
{
cJSON *item_RGBColor = cJSON_CreateObject();
if (item_RGBColor == NULL)
{
cJSON_Delete(request_root);
cJSON_Delete(response_root);
return -1;
}
cJSON_AddNumberToObject(item_RGBColor, "Red", p_ct_tsl_data->RGB.R);
cJSON_AddNumberToObject(item_RGBColor, "Green", p_ct_tsl_data->RGB.G);
cJSON_AddNumberToObject(item_RGBColor, "Blue", p_ct_tsl_data->RGB.B);
cJSON_AddItemToObject(response_root, "RGBColor", item_RGBColor);
}
}
cJSON_Delete(request_root);
*response = cJSON_PrintUnformatted(response_root);
if (*response == NULL)
{
ct_info("No Enough Memory");
cJSON_Delete(response_root);
return -1;
}
cJSON_Delete(response_root);
*response_len = strlen(*response);
ct_info("Property Get Response: %s", *response);
return SUCCESS_RETURN;
}
#endif
//When code is not 200,maybe call this function
static int user_property_cloud_error_handler(const int code, const char *data, const char *detail)
{
ct_info("code =%d ,data=%s, detail=%s", code, data, detail);
return 0;
}
/**
* @brief
* @param request payload的指针
* @param request_len payload长度
* @return : 0, : <0
*/
int32_t app_parse_property(const char *request, uint32_t request_len)
{
cJSON *lightswitch = NULL;
cJSON *rgbcolor = NULL;
cJSON *nightlightswitch = NULL;
cJSON *workmode = NULL;
cJSON *brightness = NULL;
cJSON *worktime = NULL;
cJSON *floatid = NULL;
cJSON *doubleid = NULL;
cJSON *propertystring = NULL;
cJSON *req = cJSON_Parse(request);
if (req == NULL || !cJSON_IsObject(req))
{
return -0x911;
}
lightswitch = cJSON_GetObjectItem(req, "LightSwitch");
if (lightswitch != NULL && cJSON_IsNumber(lightswitch))
{
/* process property LightSwitch here */
ct_info("property id: LightSwitch, value: %d", lightswitch->valueint);
ct_ut_set_LightSwitch(lightswitch->valueint);
}
rgbcolor = cJSON_GetObjectItem(req, "RGBColor");
if (rgbcolor != NULL && cJSON_IsObject(rgbcolor))
{
/* process property RGBColor here */
cJSON *R = cJSON_GetObjectItem(rgbcolor, "Red");
cJSON *G = cJSON_GetObjectItem(rgbcolor, "Green");
cJSON *B = cJSON_GetObjectItem(rgbcolor, "Blue");
if ((R != NULL && cJSON_IsNumber(R)) &&
(G != NULL && cJSON_IsNumber(G)) &&
(B != NULL && cJSON_IsNumber(B)))
{
ct_info("struct property id: RGBColor R:%d G:%d B:%d", R->valueint, G->valueint, B->valueint);
ct_ut_set_RGB(R->valueint, G->valueint, B->valueint);
}
}
nightlightswitch = cJSON_GetObjectItem(req, "NightLightSwitch");
if (nightlightswitch != NULL && cJSON_IsNumber(nightlightswitch))
{
/* process property NightLightSwitch here */
ct_info("property id: NightLightSwitch, value: %d", nightlightswitch->valueint);
ct_ut_set_NightLightSwitch(nightlightswitch->valueint);
}
workmode = cJSON_GetObjectItem(req, "WorkMode");
if (workmode != NULL && cJSON_IsNumber(workmode))
{
/* process property WorkMode here */
ct_info("property id: WorkMode, value: %d", workmode->valueint);
ct_ut_set_WorkMode(workmode->valueint);
}
brightness = cJSON_GetObjectItem(req, "Brightness");
if (brightness != NULL && cJSON_IsNumber(brightness))
{
/* process property Brightness here */
ct_info("property id: Brightness, value: %d", brightness->valueint);
ct_ut_set_Brightness(brightness->valueint);
}
worktime = cJSON_GetObjectItem(req, "worktime");
if (worktime != NULL && cJSON_IsString(worktime))
{
/* process property worktime here */
ct_info("property id: worktime, value: %s", worktime->valuestring);
ct_ut_set_WorkTime(worktime->valuestring);
}
floatid = cJSON_GetObjectItem(req, "floatid");
if (floatid != NULL && cJSON_IsNumber(floatid))
{
/* process property float here */
ct_info("property id: float, value: %f", floatid->valuedouble);
ct_ut_set_Float(floatid->valuedouble);
}
doubleid = cJSON_GetObjectItem(req, "doubleid");
if (doubleid != NULL && cJSON_IsNumber(doubleid))
{
/* process property double here */
ct_info("property id: double, value: %f", doubleid->valuedouble);
ct_ut_set_Double(doubleid->valuedouble);
}
propertystring = cJSON_GetObjectItem(req, "PropertyString");
if (propertystring != NULL && cJSON_IsString(propertystring))
{
/* process property PropertyString here */
ct_info("property id: PropertyString, value: %s", propertystring->valuestring);
ct_ut_set_PropertyString(propertystring->valuestring);
}
cJSON_Delete(req);
return 0;
}
static int user_property_set_event_handler(const int devid, const char *request, const int request_len)
{
int res = 0;
ct_ctx_t *ct_ctx = ct_get_ctx();
ct_info("Property Set Received, Devid: %d, Request: %s", devid, request);
app_parse_property(request, request_len);
res = IOT_Linkkit_Report(ct_ctx->master_devid, ITM_MSG_POST_PROPERTY,
(unsigned char *)request, request_len);
ct_info("Post Property Message ID: %d", res);
return 0;
}
static int user_report_reply_event_handler(const int devid, const int msgid, const int code, const char *reply,
const int reply_len)
{
const char *reply_value = (reply == NULL) ? ("NULL") : (reply);
const int reply_value_len = (reply_len == 0) ? (strlen("NULL")) : (reply_len);
ct_info("Message Post Reply Received, Devid: %d, Message ID: %d, Code: %d, Reply: %.*s", devid, msgid, code,
reply_value_len,
reply_value);
return 0;
}
static int user_trigger_event_reply_event_handler(const int devid, const int msgid, const int code, const char *eventid,
const int eventid_len, const char *message, const int message_len)
{
ct_info("Trigger Event Reply Received, Devid: %d, Message ID: %d, Code: %d, EventID: %.*s, Message: %.*s", devid,
msgid, code,
eventid_len,
eventid, message_len, message);
return 0;
}
static int user_timestamp_reply_event_handler(const char *timestamp)
{
ct_info("Current Timestamp: %s", timestamp);
return 0;
}
static uint64_t user_update_sec(void)
{
static uint64_t time_start_ms = 0;
if (time_start_ms == 0)
{
time_start_ms = HAL_UptimeMs();
}
return (HAL_UptimeMs() - time_start_ms) / 1000;
}
static int ct_ut_query_timestamp(void)
{
ct_ctx_t *ct_ctx = ct_get_ctx();
ct_info("do query timestamp");
IOT_Linkkit_Query(ct_ctx->master_devid, ITM_MSG_QUERY_TIMESTAMP, NULL, 0);
return 0;
}
static int user_initialized(const int devid)
{
ct_ctx_t *ct_ctx = ct_get_ctx();
ct_info("Device Initialized, Devid: %d", devid);
if (ct_ctx->master_devid == devid)
{
ct_ctx->master_initialized = 1;
}
return 0;
}
static int user_master_dev_available(void)
{
ct_ctx_t *ct_ctx = ct_get_ctx();
if (ct_ctx->cloud_connected && ct_ctx->master_initialized)
{
return 1;
}
return 0;
}
#ifdef CT_FY_SDK_VERSION_1_3_OR_1_4
static int user_event_notify_handler(const int devid, const char *request, const int request_len)
{
int res = 0;
ct_ctx_t *ct_ctx = ct_get_ctx();
ct_info("Event notify Received, Devid: %d, Request: %s", devid, request);
res = IOT_Linkkit_Report(ct_ctx->master_devid, ITM_MSG_EVENT_NOTIFY_REPLY,
(unsigned char *)request, request_len);
ct_info("Post Property Message ID: %d", res);
return 0;
}
#endif
static int user_fota_event_handler(int type, const char *version)
{
char *p_fota_buffer = NULL;
ct_ctx_t *ct_ctx = ct_get_ctx();
p_fota_buffer = HAL_Malloc(CT_OTA_BUFFER_LEN);
if (!p_fota_buffer)
{
ct_err("no mem");
return -1;
}
if (type == 0)
{
ct_info("New Firmware Version: %s", version);
memset(p_fota_buffer, 0, CT_OTA_BUFFER_LEN);
IOT_Linkkit_Query(ct_ctx->master_devid, ITM_MSG_QUERY_FOTA_DATA, (unsigned char *)p_fota_buffer, CT_OTA_BUFFER_LEN);
}
if (p_fota_buffer)
HAL_Free(p_fota_buffer);
return 0;
}
static int user_cota_event_handler(int type, const char *config_id, int config_size, const char *get_type,
const char *sign, const char *sign_method, const char *url)
{
char *p_cota_buffer = NULL;
ct_ctx_t *ct_ctx = ct_get_ctx();
p_cota_buffer = HAL_Malloc(CT_OTA_BUFFER_LEN);
if (!p_cota_buffer)
{
ct_err("no mem");
return -1;
}
if (type == 0)
{
ct_info("New Config ID: %s", config_id);
ct_info("New Config Size: %d", config_size);
ct_info("New Config Type: %s", get_type);
ct_info("New Config Sign: %s", sign);
ct_info("New Config Sign Method: %s", sign_method);
ct_info("New Config URL: %s", url);
IOT_Linkkit_Query(ct_ctx->master_devid, ITM_MSG_QUERY_COTA_DATA, (unsigned char *)p_cota_buffer, CT_OTA_BUFFER_LEN);
}
if (p_cota_buffer)
HAL_Free(p_cota_buffer);
return 0;
}
#ifdef CT_FY_SDK_VERSION_1_5
static int user_offline_reset_handler(void)
{
ct_info("user callback user_offline_reset_handler called.");
return 0;
}
#endif
#ifdef CT_FY_SDK_VERSION_1_3_OR_1_4
static int user_dev_bind_event(const int state_code, const char *state_message)
{
ct_info("state_code: -0x%04x, str_msg= %s", -state_code, state_message == NULL ? "NULL" : state_message);
return 0;
}
#endif
#ifdef DM_UNIFIED_SERVICE_POST
static int user_unified_service_post_reply_handler(const int devid, const int id, const int code, const char *payload, const int payload_len)
{
ct_info("Receive unified service post reply, code:%d, payload:%s", code, payload);
return 0;
}
#endif
static iotx_linkkit_dev_meta_info_t *ct_main_init(ct_ctx_t *ct_ctx)
{
int register_type = 0;
int post_event_reply = 1;
iotx_linkkit_dev_meta_info_t *p_master_meta = NULL;
memset(ct_ctx, 0, sizeof(ct_ctx_t));
p_master_meta = HAL_Malloc(sizeof(iotx_linkkit_dev_meta_info_t));
if (p_master_meta == NULL)
{
ct_err("no mem");
return NULL;
}
memset(p_master_meta, 0, sizeof(iotx_linkkit_dev_meta_info_t));
HAL_GetProductKey(p_master_meta->product_key);
HAL_GetDeviceName(p_master_meta->device_name);
HAL_GetDeviceSecret(p_master_meta->device_secret);
HAL_GetProductSecret(p_master_meta->product_secret);
if ((0 == strlen(p_master_meta->product_key)) || (0 == strlen(p_master_meta->device_name)) ||
(0 == register_type && (0 == strlen(p_master_meta->device_secret))) || (0 == strlen(p_master_meta->product_secret)))
{
while (1)
{
printf("Master meta info is invalid...\r\n");
printf("pk[%s]\r\n", p_master_meta->product_key);
printf("ps[%s]\r\n", p_master_meta->product_secret);
printf("dn[%s]\r\n", p_master_meta->device_name);
printf("ds[%s]\r\n", p_master_meta->device_secret);
HAL_SleepMs(2000);
}
}
#ifdef CT_PRODUCT_DYNAMIC_REGISTER_AND_USE_RAWDATA
register_type = 1;
#endif
/* Register Callback */
IOT_RegisterCallback(ITE_INITIALIZE_COMPLETED, user_initialized);
IOT_RegisterCallback(ITE_CONNECT_SUCC, user_connected_event_handler);
IOT_RegisterCallback(ITE_DISCONNECTED, user_disconnected_event_handler);
IOT_RegisterCallback(ITE_RAWDATA_ARRIVED, user_down_raw_data_arrived_event_handler);
IOT_RegisterCallback(ITE_SERVICE_REQUEST, user_service_request_event_handler);
IOT_RegisterCallback(ITE_PROPERTY_SET, user_property_set_event_handler);
#ifdef ALCS_ENABLED
/*Only for local communication service(ALCS)*/
IOT_RegisterCallback(ITE_PROPERTY_GET, user_property_get_event_handler);
#endif
IOT_RegisterCallback(ITE_REPORT_REPLY, user_report_reply_event_handler);
IOT_RegisterCallback(ITE_TRIGGER_EVENT_REPLY, user_trigger_event_reply_event_handler);
IOT_RegisterCallback(ITE_TIMESTAMP_REPLY, user_timestamp_reply_event_handler);
IOT_RegisterCallback(ITE_CLOUD_ERROR, user_property_cloud_error_handler);
IOT_RegisterCallback(ITE_FOTA, user_fota_event_handler);
IOT_RegisterCallback(ITE_COTA, user_cota_event_handler);
#ifdef CT_FY_SDK_VERSION_1_3_OR_1_4
IOT_RegisterCallback(ITE_EVENT_NOTIFY, user_event_notify_handler);
IOT_RegisterCallback(ITE_STATE_DEV_BIND, user_dev_bind_event);
#endif
#ifdef CT_FY_SDK_VERSION_1_5
IOT_RegisterCallback(ITE_OFFLINE_RESET, user_offline_reset_handler);
#endif
#ifdef CT_FY_SDK_VERSION_1_3_OR_1_4
#ifdef DM_UNIFIED_SERVICE_POST
IOT_RegisterCallback(ITE_UNIFIED_SERVICE_POST, user_unified_service_post_reply_handler);
#endif
#endif
IOT_Ioctl(IOTX_IOCTL_SET_DYNAMIC_REGISTER, (void *)&register_type);
/* Choose Whether You Need Post Property/Event Reply */
IOT_Ioctl(IOTX_IOCTL_RECV_EVENT_REPLY, (void *)&post_event_reply);
ct_ut_init();
return p_master_meta;
}
int ct_main(void *paras)
{
int res = 0;
uint64_t time_prev_sec = 0, time_now_sec = 0;
ct_ctx_t *ct_ctx = ct_get_ctx();
iotx_linkkit_dev_meta_info_t *p_master_meta = NULL;
p_master_meta = ct_main_init(ct_ctx);
if (NULL == p_master_meta)
{
printf("OOPS:ct_main_init failed");
return -1;
}
/* Create Master Device Resources */
do
{
ct_ctx->master_devid = IOT_Linkkit_Open(IOTX_LINKKIT_DEV_TYPE_MASTER, p_master_meta);
if (ct_ctx->master_devid < 0)
{
printf("IOT_Linkkit_Open Failed, retry after 5s...\r\n");
HAL_SleepMs(5000);
}
} while (ct_ctx->master_devid < 0);
/* Start Connect Aliyun Server */
do
{
res = IOT_Linkkit_Connect(ct_ctx->master_devid);
if (res < 0)
{
printf("IOT_Linkkit_Connect Failed, retry after 5s...\r\n");
HAL_SleepMs(5000);
}
} while (res < 0);
ct_ut_query_timestamp();
while (1)
{
IOT_Linkkit_Yield(CT_YIELD_TIMEOUT_MS);
time_now_sec = user_update_sec();
if (time_prev_sec == time_now_sec)
{
continue;
}
if (user_master_dev_available())
{
ct_ut_misc_process(time_now_sec);
}
time_prev_sec = time_now_sec;
}
//Should never come here
ct_ctx->g_user_dispatch_thread_running = 0;
if (p_master_meta)
{
HAL_Free(p_master_meta);
}
IOT_DumpMemoryStats(IOT_LOG_DEBUG);
return 0;
}

View file

@ -0,0 +1,38 @@
#ifndef __CT_MAIN_H__
#define __CT_MAIN_H__
#include <iotx_log.h>
//#define CT_PRODUCT_DYNAMIC_REGISTER_AND_USE_RAWDATA
//if your fy sdk is V1.0.0 or V 1.1.0
//#define CT_FY_SDK_VERSION_1_0_OR_1_1
//if your fy sdk is V1.3.0 or V 1.4.0
#define CT_FY_SDK_VERSION_1_3_OR_1_4
//if your fy sdk is V1.5.0
//#define CT_FY_SDK_VERSION_1_5
#define ct_debug(...) log_debug("ct", __VA_ARGS__)
#define ct_info(...) log_info("ct", __VA_ARGS__)
#define ct_warn(...) log_warning("ct", __VA_ARGS__)
#define ct_err(...) log_err("ct", __VA_ARGS__)
#define ct_crit(...) log_crit("ct", __VA_ARGS__)
#define CT_YIELD_TIMEOUT_MS (200)
#define CT_OTA_BUFFER_LEN (512 + 1) //Have to +1 or else ota SHA256 will crash
typedef struct
{
int master_devid;
int cloud_connected;
int master_initialized;
void *g_user_dispatch_thread;
int g_user_dispatch_thread_running;
} ct_ctx_t;
extern int ct_main(void *paras);
extern ct_ctx_t *ct_get_ctx(void);
#endif

View file

@ -0,0 +1,184 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include "cJSON.h"
#include "iot_import.h"
#include "iotx_log.h"
#include "ct_main.h"
#include "ct_entry.h"
#include "ct_ut.h"
#ifdef OTA_ENABLED
#ifdef BUILD_AOS
#include "ota_service.h"
#else
#include "dm_ota.h"
#endif
#endif
#include "ct_ota.h"
#ifdef OTA_ENABLED
static int ota_get_kv_size(void)
{
int ret = 0;
char ota_size[OTA_DESC_KV_KEY_SIZE_LEN] = {0};
int len = OTA_DESC_KV_KEY_SIZE_LEN - 1;
ret = HAL_Kv_Get(OTA_DESC_KV_KEY_SIZE, ota_size, &len);
if (ret == 0)
{
return atoi(ota_size);
}
return -1;
}
static int ota_get_kv_version(char version[OTA_DESC_KV_KEY_VERSION_LEN])
{
int ret = 0;
char ota_ver[OTA_DESC_KV_KEY_VERSION_LEN] = {0};
int len = OTA_DESC_KV_KEY_VERSION_LEN - 1;
ret = HAL_Kv_Get(OTA_DESC_KV_KEY_VERSION, ota_ver, &len);
if (ret == 0)
{
memcpy(version, ota_ver, strlen(ota_ver));
}
return ret;
}
static int ota_get_kv_md5(char md5[OTA_DESC_KV_KEY_MD5_LEN])
{
int ret = 0;
char ota_md5[OTA_DESC_KV_KEY_MD5_LEN] = {0};
int len = OTA_DESC_KV_KEY_MD5_LEN - 1;
ret = HAL_Kv_Get(OTA_DESC_KV_KEY_MD5, ota_md5, &len);
if (ret == 0)
{
memcpy(md5, ota_md5, strlen(ota_md5));
}
return ret;
}
static int ota_get_kv_url(char url[OTA_DESC_KV_KEY_URL_LEN])
{
int ret = 0;
char ota_url[OTA_DESC_KV_KEY_URL_LEN] = {0};
int len = OTA_DESC_KV_KEY_URL_LEN - 1;
ret = HAL_Kv_Get(OTA_DESC_KV_KEY_URL, ota_url, &len);
if (ret == 0)
{
memcpy(url, ota_url, strlen(ota_url));
}
return ret;
}
#ifdef BUILD_AOS
int ct_ota_download(ota_service_t *p_ota_ctx)
{
int ret = 0;
char *p_ota_desc_data = NULL;
int size = 0;
char version[OTA_DESC_KV_KEY_VERSION_LEN] = {0};
char md5[OTA_DESC_KV_KEY_MD5_LEN] = {0};
char url[OTA_DESC_KV_KEY_URL_LEN] = {0};
if (p_ota_ctx == NULL)
{
ct_err("param err");
return -1;
}
size = ota_get_kv_size();
ota_get_kv_version(version);
ota_get_kv_md5(md5);
ota_get_kv_url(url);
if (strlen(md5) < 32 || strlen(version) < 1 ||
strlen(url) < 10 || size < 1)
{
ct_err("err ota:size(%d) version(%s) md5(%s) url(%s)", size, version, md5, url);
return -1;
}
ct_info("ct ota:size(%d) version(%s) md5(%s) url(%s)", size, version, md5, url);
p_ota_desc_data = HAL_Malloc(OTA_DESC_DATA_LEN);
if (!p_ota_desc_data)
{
ct_err("no mem");
return -1;
}
HAL_Snprintf(p_ota_desc_data, OTA_DESC_DATA_LEN,
OTA_DESC_DATA_FMT, size, md5,
version, url, md5);
ret = p_ota_ctx->upgrade_cb(p_ota_ctx, p_ota_desc_data);
if (p_ota_desc_data)
{
HAL_Free(p_ota_desc_data);
}
return ret;
}
#else
int ct_ota_download(void)
{
int ret = 0;
char *p_ota_desc_data = NULL;
int size = 0;
char version[OTA_DESC_KV_KEY_VERSION_LEN] = {0};
char md5[OTA_DESC_KV_KEY_MD5_LEN] = {0};
char url[OTA_DESC_KV_KEY_URL_LEN] = {0};
size = ota_get_kv_size();
ota_get_kv_version(version);
ota_get_kv_md5(md5);
ota_get_kv_url(url);
if (strlen(md5) < 32 || strlen(version) < 1 ||
strlen(url) < 10 || size < 1)
{
ct_err("param err");
return -1;
}
ct_info("ct ota:size(%d) version(%s) md5(%s) url(%s)", size, version, md5, url);
p_ota_desc_data = HAL_Malloc(OTA_DESC_DATA_LEN);
if (!p_ota_desc_data)
{
ct_err("no mem");
return -1;
}
HAL_Snprintf(p_ota_desc_data, OTA_DESC_DATA_LEN,
OTA_DESC_DATA_FMT, size, md5,
version, url, md5);
//If not fy 1.5.0 or larger version,please add dm_ota_download to dm_ota.c
#ifdef CT_FY_SDK_VERSION_1_5
ret = dm_ota_download(p_ota_desc_data, strlen(p_ota_desc_data));
#endif
if (p_ota_desc_data)
{
HAL_Free(p_ota_desc_data);
}
return ret;
}
#endif
#endif

View file

@ -0,0 +1,29 @@
#ifndef __CT_OTA_H__
#define __CT_OTA_H__
//#define CT_DOWNLOAD_OTA_WHEN_CONNECT_CLOUD
#ifdef OTA_ENABLED
#define OTA_DESC_DATA_LEN (1024)
#define OTA_DESC_DATA_FMT "{\"code\":\"1000\",\"data\":{\"size\":%d,\"sign\":\"%s\",\"version\":\"%s\",\"url\":\"%s\",\"signMethod\":\"Md5\",\"md5\":\"%s\"},\"id\":1583301049684,\"message\":\"success\"}"
#define OTA_DESC_KV_KEY_SIZE "ct_ota_size"
#define OTA_DESC_KV_KEY_VERSION "ct_ota_ver"
#define OTA_DESC_KV_KEY_MD5 "ct_ota_md5"
#define OTA_DESC_KV_KEY_URL "ct_ota_url"
#define OTA_DESC_KV_KEY_SIZE_LEN (16)
#define OTA_DESC_KV_KEY_VERSION_LEN (64)
#define OTA_DESC_KV_KEY_MD5_LEN (33)
#define OTA_DESC_KV_KEY_URL_LEN (1024)
#ifdef BUILD_AOS
#include "ota_service.h"
int ct_ota_download(ota_service_t *p_ota_ctx);
#else
int ct_ota_download(void);
#endif
#endif
#endif

View file

@ -0,0 +1,707 @@
/*
* Copyright (C) 2015-2019 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include "cJSON.h"
#include "iot_import.h"
#include "iot_export_linkkit.h"
#include "iotx_log.h"
#include "ct_main.h"
#include "ct_entry.h"
#include "ct_ut.h"
#include "ct_ota.h"
#if defined(CT_DOWNLOAD_OTA_WHEN_CONNECT_CLOUD) && defined(OTA_ENABLED)
static char do_only_once = 0;
#endif
static ct_tsl_t ct_tsl_data;
ct_tsl_t *ct_ut_get_tsl_data(void)
{
return &ct_tsl_data;
}
int ct_ut_set_LightSwitch(char LightSwitch)
{
ct_tsl_data.LightSwitch = LightSwitch;
ct_info("set LightSwitch:%s", (LightSwitch == 0) ? "off" : "on");
return 0;
}
int ct_ut_get_LightSwitch(void)
{
return ct_tsl_data.LightSwitch;
}
int ct_ut_set_NightLightSwitch(char NightLightSwitch)
{
ct_tsl_data.NightLightSwitch = NightLightSwitch;
return 0;
}
int ct_ut_set_WorkMode(unsigned char WorkMode)
{
ct_tsl_data.WorkMode = WorkMode;
return 0;
}
int ct_ut_set_Brightness(unsigned char Brightness)
{
ct_tsl_data.Brightness = Brightness;
return 0;
}
int ct_ut_set_RGB(unsigned char R, unsigned char G, unsigned char B)
{
ct_tsl_data.RGB.R = R;
ct_tsl_data.RGB.G = G;
ct_tsl_data.RGB.B = B;
return 0;
}
int ct_ut_set_Float(float f)
{
ct_tsl_data.f = f;
return 0;
}
int ct_ut_set_Double(double d)
{
ct_tsl_data.d = d;
return 0;
}
int ct_ut_set_PropertyString(char *PropertyString)
{
if (PropertyString)
{
HAL_Snprintf(ct_tsl_data.PropertyString, PROPERTY_STRING_MAX_LEN, "%s", PropertyString);
}
return 0;
}
int ct_ut_set_WorkTime(char *WorkTime)
{
if (WorkTime)
{
HAL_Snprintf(ct_tsl_data.WorkTime, WORKTIME_MAX_LEN, "%s", WorkTime);
}
return 0;
}
/**
* @brief LightSwitch到云端
* @param devid IOT_Linkkit_Open返回的设备标示符
* @param value LightSwitch的值uint8_t
* @return id:(>=1), : <0
*/
int32_t app_post_property_LightSwitch(uint32_t devid, uint8_t value)
{
int32_t res = -0x100;
char property_payload[64] = {0};
res = HAL_Snprintf(property_payload, sizeof(property_payload), "{\"LightSwitch\": %d}", value);
if (res < 0)
{
return -0x10E;
}
res = IOT_Linkkit_Report(devid, ITM_MSG_POST_PROPERTY,
(uint8_t *)property_payload, strlen(property_payload));
return res;
}
/**
* @brief WIFI_Band到云端
* @param devid IOT_Linkkit_Open返回的设备标示符
* @param value WIFI_Band的值char*
* @return id:(>=1), : <0
*/
int32_t app_post_property_WIFI_Band(uint32_t devid, char *value)
{
int32_t res = -0x100;
char *property_payload = NULL;
uint32_t property_payload_len = 0;
if (value == NULL)
{
return -0x101;
}
property_payload_len = strlen("WIFI_Band") + strlen(value) + 10;
property_payload = HAL_Malloc(property_payload_len);
if (property_payload == NULL)
{
return -0x201;
}
memset(property_payload, 0, property_payload_len);
res = HAL_Snprintf(property_payload, property_payload_len, "{\"WIFI_Band\": \"%s\"}", value);
if (res < 0)
{
return -0x10E;
}
res = IOT_Linkkit_Report(devid, ITM_MSG_POST_PROPERTY,
(uint8_t *)property_payload, strlen(property_payload));
HAL_Free(property_payload);
return res;
}
/**
* @brief WiFI_RSSI到云端
* @param devid IOT_Linkkit_Open返回的设备标示符
* @param value WiFI_RSSI的值int32_t
* @return id:(>=1), : <0
*/
int32_t app_post_property_WiFI_RSSI(uint32_t devid, int32_t value)
{
int32_t res = -0x100;
char property_payload[64] = {0};
res = HAL_Snprintf(property_payload, sizeof(property_payload), "{\"WiFI_RSSI\": %d}", value);
if (res < 0)
{
return -0x10E;
}
res = IOT_Linkkit_Report(devid, ITM_MSG_POST_PROPERTY,
(uint8_t *)property_payload, strlen(property_payload));
return res;
}
/**
* @brief WIFI_AP_BSSID到云端
* @param devid IOT_Linkkit_Open返回的设备标示符
* @param value WIFI_AP_BSSID的值char*
* @return id:(>=1), : <0
*/
int32_t app_post_property_WIFI_AP_BSSID(uint32_t devid, char *value)
{
int32_t res = -0x100;
char *property_payload = NULL;
uint32_t property_payload_len = 0;
if (value == NULL)
{
return -0x101;
}
property_payload_len = strlen("WIFI_AP_BSSID") + strlen(value) + 10;
property_payload = HAL_Malloc(property_payload_len);
if (property_payload == NULL)
{
return -0x201;
}
memset(property_payload, 0, property_payload_len);
res = HAL_Snprintf(property_payload, property_payload_len, "{\"WIFI_AP_BSSID\": \"%s\"}", value);
if (res < 0)
{
return -0x10E;
}
res = IOT_Linkkit_Report(devid, ITM_MSG_POST_PROPERTY,
(uint8_t *)property_payload, strlen(property_payload));
HAL_Free(property_payload);
return res;
}
/**
* @brief WIFI_Channel到云端
* @param devid IOT_Linkkit_Open返回的设备标示符
* @param value WIFI_Channel的值int32_t
* @return id:(>=1), : <0
*/
int32_t app_post_property_WIFI_Channel(uint32_t devid, int32_t value)
{
int32_t res = -0x100;
char property_payload[64] = {0};
res = HAL_Snprintf(property_payload, sizeof(property_payload), "{\"WIFI_Channel\": %d}", value);
if (res < 0)
{
return -0x10E;
}
res = IOT_Linkkit_Report(devid, ITM_MSG_POST_PROPERTY,
(uint8_t *)property_payload, strlen(property_payload));
return res;
}
/**
* @brief WiFI_SNR到云端
* @param devid IOT_Linkkit_Open返回的设备标示符
* @param value WiFI_SNR的值int32_t
* @return id:(>=1), : <0
*/
int32_t app_post_property_WiFI_SNR(uint32_t devid, int32_t value)
{
int32_t res = -0x100;
char property_payload[64] = {0};
res = HAL_Snprintf(property_payload, sizeof(property_payload), "{\"WiFI_SNR\": %d}", value);
if (res < 0)
{
return -0x10E;
}
res = IOT_Linkkit_Report(devid, ITM_MSG_POST_PROPERTY,
(uint8_t *)property_payload, strlen(property_payload));
return res;
}
/**
* @brief NightLightSwitch到云端
* @param devid IOT_Linkkit_Open返回的设备标示符
* @param value NightLightSwitch的值uint8_t
* @return id:(>=1), : <0
*/
int32_t app_post_property_NightLightSwitch(uint32_t devid, uint8_t value)
{
int32_t res = -0x100;
char property_payload[64] = {0};
res = HAL_Snprintf(property_payload, sizeof(property_payload), "{\"NightLightSwitch\": %d}", value);
if (res < 0)
{
return -0x10E;
}
res = IOT_Linkkit_Report(devid, ITM_MSG_POST_PROPERTY,
(uint8_t *)property_payload, strlen(property_payload));
return res;
}
/**
* @brief WorkMode到云端
* @param devid IOT_Linkkit_Open返回的设备标示符
* @param value WorkMode的值uint32_t
* @return id:(>=1), : <0
*/
int32_t app_post_property_WorkMode(uint32_t devid, uint32_t value)
{
int32_t res = -0x100;
char property_payload[64] = {0};
res = HAL_Snprintf(property_payload, sizeof(property_payload), "{\"WorkMode\": %d}", value);
if (res < 0)
{
return -0x10E;
}
res = IOT_Linkkit_Report(devid, ITM_MSG_POST_PROPERTY,
(uint8_t *)property_payload, strlen(property_payload));
return res;
}
/**
* @brief Brightness到云端
* @param devid IOT_Linkkit_Open返回的设备标示符
* @param value Brightness的值int32_t
* @return id:(>=1), : <0
*/
int32_t app_post_property_Brightness(uint32_t devid, int32_t value)
{
int32_t res = -0x100;
char property_payload[64] = {0};
res = HAL_Snprintf(property_payload, sizeof(property_payload), "{\"Brightness\": %d}", value);
if (res < 0)
{
return -0x10E;
}
res = IOT_Linkkit_Report(devid, ITM_MSG_POST_PROPERTY,
(uint8_t *)property_payload, strlen(property_payload));
return res;
}
/**
* @brief worktime到云端
* @param devid IOT_Linkkit_Open返回的设备标示符
* @param utc worktime的值${dataType}
* @return id:(>=1), : <0
*/
int32_t app_post_property_worktime(uint32_t devid, char *worktime)
{
int32_t res = -0x100;
char property_payload[64] = {0};
res = HAL_Snprintf(property_payload, sizeof(property_payload), "{\"worktime\": \"%s\"}", worktime);
if (res < 0)
{
return -0x10E;
}
res = IOT_Linkkit_Report(devid, ITM_MSG_POST_PROPERTY,
(uint8_t *)property_payload, strlen(property_payload));
return res;
}
int32_t app_post_property_RGB(uint32_t devid, unsigned char R, unsigned char G, unsigned char B)
{
int32_t res = -0x100;
char property_payload[64] = {0};
res = HAL_Snprintf(property_payload, sizeof(property_payload), "{\"RGBColor\": {\"Red\": %d, \"Green\": %d, \"Blue\": %d}}", R, G, B);
if (res < 0)
{
return -0x10E;
}
res = IOT_Linkkit_Report(devid, ITM_MSG_POST_PROPERTY,
(uint8_t *)property_payload, strlen(property_payload));
return res;
}
/**
* @brief onlyread到云端
* @param devid IOT_Linkkit_Open返回的设备标示符
* @param value onlyread的值int32_t
* @return id:(>=1), : <0
*/
int32_t app_post_property_onlyread(uint32_t devid, int32_t value)
{
int32_t res = -0x100;
char property_payload[64] = {0};
res = HAL_Snprintf(property_payload, sizeof(property_payload), "{\"onlyread\": %d}", value);
if (res < 0)
{
return -0x10E;
}
res = IOT_Linkkit_Report(devid, ITM_MSG_POST_PROPERTY,
(uint8_t *)property_payload, strlen(property_payload));
return res;
}
/**
* @brief float到云端
* @param devid IOT_Linkkit_Open返回的设备标示符
* @param value float的值float
* @return id:(>=1), : <0
*/
int32_t app_post_property_float(uint32_t devid, float value)
{
int32_t res = -0x100;
char property_payload[64] = {0};
res = HAL_Snprintf(property_payload, sizeof(property_payload), "{\"floatid\": %f}", value);
if (res < 0)
{
return -0x10E;
}
res = IOT_Linkkit_Report(devid, ITM_MSG_POST_PROPERTY,
(uint8_t *)property_payload, strlen(property_payload));
return res;
}
/**
* @brief double到云端
* @param devid IOT_Linkkit_Open返回的设备标示符
* @param value double的值double
* @return id:(>=1), : <0
*/
int32_t app_post_property_double(uint32_t devid, double value)
{
int32_t res = -0x100;
char property_payload[64] = {0};
res = HAL_Snprintf(property_payload, sizeof(property_payload), "{\"doubleid\": %f}", value);
if (res < 0)
{
return -0x10E;
}
res = IOT_Linkkit_Report(devid, ITM_MSG_POST_PROPERTY,
(uint8_t *)property_payload, strlen(property_payload));
return res;
}
/**
* @brief PropertyString到云端
* @param devid IOT_Linkkit_Open返回的设备标示符
* @param value PropertyString的值char*
* @return id:(>=1), : <0
*/
int32_t app_post_property_PropertyString(uint32_t devid, char *value)
{
int32_t res = -0x100;
char *property_payload = NULL;
uint32_t property_payload_len = 0;
if (value == NULL)
{
return -0x101;
}
property_payload_len = strlen("PropertyString") + strlen(value) + 10;
property_payload = HAL_Malloc(property_payload_len);
if (property_payload == NULL)
{
return -0x201;
}
memset(property_payload, 0, property_payload_len);
res = HAL_Snprintf(property_payload, property_payload_len, "{\"PropertyString\": \"%s\"}", value);
if (res < 0)
{
HAL_Free(property_payload);
return -0x10E;
}
res = IOT_Linkkit_Report(devid, ITM_MSG_POST_PROPERTY,
(uint8_t *)property_payload, strlen(property_payload));
HAL_Free(property_payload);
return res;
}
/**
* @brief Error到云端
* @param devid IOT_Linkkit_Open返回的设备标示符
* @param value Error的值uint32_t
* @return id:(>=1), : <0
*/
int32_t app_post_event_Error(uint32_t devid, uint32_t value)
{
int32_t res = -0x100;
char *event_id = "Error";
char event_payload[64] = {0};
res = HAL_Snprintf(event_payload, sizeof(event_payload), "{\"ErrorCode\": %d}", value);
if (res < 0)
{
return -0x10E;
}
res = IOT_Linkkit_TriggerEvent(EXAMPLE_MASTER_DEVID, event_id, strlen(event_id),
event_payload, strlen(event_payload));
return res;
}
/**
* @brief alarm到云端
* @param devid IOT_Linkkit_Open返回的设备标示符
* @param value alarm的值int32_t
* @return id:(>=1), : <0
*/
int32_t app_post_event_alarm(uint32_t devid, int32_t value)
{
int32_t res = -0x100;
char *event_id = "alarm";
char event_payload[64] = {0};
res = HAL_Snprintf(event_payload, sizeof(event_payload), "{\"alarm\": %d}", value);
if (res < 0)
{
return -0x10E;
}
res = IOT_Linkkit_TriggerEvent(EXAMPLE_MASTER_DEVID, event_id, strlen(event_id),
event_payload, strlen(event_payload));
return res;
}
/**
* @brief info到云端
* @param devid IOT_Linkkit_Open返回的设备标示符
* @param value info的值int32_t
* @return id:(>=1), : <0
*/
int32_t app_post_event_info(uint32_t devid, int32_t value)
{
int32_t res = -0x100;
char *event_id = "info";
char event_payload[64] = {0};
res = HAL_Snprintf(event_payload, sizeof(event_payload), "{\"info\": %d}", value);
if (res < 0)
{
return -0x10E;
}
res = IOT_Linkkit_TriggerEvent(EXAMPLE_MASTER_DEVID, event_id, strlen(event_id),
event_payload, strlen(event_payload));
return res;
}
//Just for reference
void user_post_property(void)
{
static int count = 0;
app_post_property_LightSwitch(EXAMPLE_MASTER_DEVID, ct_tsl_data.LightSwitch);
app_post_property_WIFI_Band(EXAMPLE_MASTER_DEVID, ct_tsl_data.wifi.band);
app_post_property_WiFI_RSSI(EXAMPLE_MASTER_DEVID, ct_tsl_data.wifi.rssi);
app_post_property_WIFI_AP_BSSID(EXAMPLE_MASTER_DEVID, ct_tsl_data.wifi.bssid);
app_post_property_WIFI_Channel(EXAMPLE_MASTER_DEVID, ct_tsl_data.wifi.Channel);
app_post_property_WiFI_SNR(EXAMPLE_MASTER_DEVID, ct_tsl_data.wifi.SNR);
app_post_property_NightLightSwitch(EXAMPLE_MASTER_DEVID, ct_tsl_data.NightLightSwitch);
app_post_property_WorkMode(EXAMPLE_MASTER_DEVID, ct_tsl_data.WorkMode);
app_post_property_Brightness(EXAMPLE_MASTER_DEVID, ct_tsl_data.Brightness);
app_post_property_worktime(EXAMPLE_MASTER_DEVID, ct_tsl_data.WorkTime);
app_post_property_RGB(EXAMPLE_MASTER_DEVID, ct_tsl_data.RGB.R, ct_tsl_data.RGB.G, ct_tsl_data.RGB.B);
app_post_property_onlyread(EXAMPLE_MASTER_DEVID, ct_tsl_data.readonly);
app_post_property_float(EXAMPLE_MASTER_DEVID, ct_tsl_data.f);
app_post_property_double(EXAMPLE_MASTER_DEVID, ct_tsl_data.d);
app_post_property_PropertyString(EXAMPLE_MASTER_DEVID, ct_tsl_data.PropertyString);
if (count == 0)
{
app_post_event_Error(EXAMPLE_MASTER_DEVID, count);
}
else if (count == 1)
{
app_post_event_alarm(EXAMPLE_MASTER_DEVID, count);
}
else if (count == 2)
{
app_post_event_info(EXAMPLE_MASTER_DEVID, count);
}
if (++count > 2)
{
count = 0;
}
}
//Just for reference
void user_post_raw_data(void)
{
static int id = 0;
int res = 0;
unsigned char payload[6] = {0};
ct_ctx_t *ct_ctx = ct_get_ctx();
id += 1;
payload[0] = 0x01;
payload[1] = (id >> 24) & 0xFF;
payload[2] = (id >> 16) & 0xFF;
payload[3] = (id >> 8) & 0xFF;
payload[4] = id & 0xFF;
payload[5] = ct_tsl_data.LightSwitch;
res = IOT_Linkkit_Report(ct_ctx->master_devid, ITM_MSG_POST_RAW_DATA,
payload, 6);
ct_info("Post Raw Data Message ID: %d", res);
}
//Just for reference
void user_deviceinfo_update(void)
{
int res = 0;
ct_ctx_t *ct_ctx = ct_get_ctx();
char *device_info_update = "[{\"attrKey\":\"ct\",\"attrValue\":\"I am a ct device\"},{\"attrKey\":\"ct2\",\"attrValue\":\"I am a ct2\"}]";
res = IOT_Linkkit_Report(ct_ctx->master_devid, ITM_MSG_DEVICEINFO_UPDATE,
(unsigned char *)device_info_update, strlen(device_info_update));
ct_info("Device Info Update Message ID: %d", res);
}
//Just for reference
void user_deviceinfo_delete(void)
{
int res = 0;
ct_ctx_t *ct_ctx = ct_get_ctx();
char *device_info_delete = "[{\"attrKey\":\"ct2\"}]";
res = IOT_Linkkit_Report(ct_ctx->master_devid, ITM_MSG_DEVICEINFO_DELETE,
(unsigned char *)device_info_delete, strlen(device_info_delete));
ct_info("Device Info Delete Message ID: %d", res);
}
void ct_ut_misc_process(uint64_t time_now_sec)
{
/* Post Proprety Example */
if (time_now_sec % 11 == 0)
{
#ifdef CT_PRODUCT_DYNAMIC_REGISTER_AND_USE_RAWDATA
user_post_raw_data();
#else
user_post_property();
#endif
}
#ifndef CT_PRODUCT_DYNAMIC_REGISTER_AND_USE_RAWDATA
/* Device Info Update Example */
if (time_now_sec % 23 == 0)
{
user_deviceinfo_update();
}
/* Device Info Delete Example */
if (time_now_sec % 29 == 0)
{
user_deviceinfo_delete();
}
#endif
#if defined(CT_DOWNLOAD_OTA_WHEN_CONNECT_CLOUD) && defined(OTA_ENABLED)
if (do_only_once == 0)
{
do_only_once = 1;
#ifdef BUILD_AOS
ct_ota_download((ota_service_t *)ct_entry_get_uota_ctx());
#else
ct_ota_download();
#endif
}
#endif
}
int ct_ut_init(void)
{
int ret = SUCCESS_RETURN;
memset(&ct_tsl_data, 0, sizeof(ct_tsl_t));
ct_tsl_data.PropertyString = (char *)HAL_Malloc(PROPERTY_STRING_MAX_LEN);
if (ct_tsl_data.PropertyString == NULL)
{
ct_err("no mem");
ret = FAIL_RETURN;
}
ct_tsl_data.LightSwitch = 1;
ct_tsl_data.NightLightSwitch = 0;
ct_tsl_data.Brightness = 88;
ct_tsl_data.WorkMode = 3;
HAL_Snprintf(ct_tsl_data.WorkTime, WORKTIME_MAX_LEN, "%s", "1582861307282");
HAL_Snprintf(ct_tsl_data.PropertyString, PROPERTY_STRING_MAX_LEN, "%s", "This is a testing property string!");
ct_tsl_data.f = 9.999999;
ct_tsl_data.d = 88.888888;
ct_tsl_data.RGB.R = 128;
ct_tsl_data.RGB.G = 128;
ct_tsl_data.RGB.B = 128;
ct_tsl_data.readonly = 38;
ct_tsl_data.wifi.Channel = 6;
ct_tsl_data.wifi.SNR = -127;
ct_tsl_data.wifi.rssi = -78;
HAL_Snprintf(ct_tsl_data.wifi.bssid, AP_BSSID_MAX_LEN, "%s", "11:22:33:44:55:66");
HAL_Snprintf(ct_tsl_data.wifi.band, WIFI_BAND_MAX_LEN, "%s", "2.4G");
return ret;
}

View file

@ -0,0 +1,67 @@
#ifndef __CT_UT_H__
#define __CT_UT_H__
#define KV_KEY_PK "pk"
#define KV_KEY_PS "ps"
#define KV_KEY_DN "dn"
#define KV_KEY_DS "ds"
#define MAX_KEY_LEN (6)
#define PRODUCT_KEY "PK_XXXXXX"
#define PRODUCT_SECRET "PS_XXXXXX"
#define DEVICE_NAME "DN_XXXXXX"
#define DEVICE_SECRET "DS_XXXXXX"
#define EXAMPLE_MASTER_DEVID (0)
#define PROPERTY_STRING_MAX_LEN (1024)
#define WORKTIME_MAX_LEN (64)
#define WIFI_BAND_MAX_LEN (64)
#define AP_BSSID_MAX_LEN (64)
typedef struct _RGBColor_s
{
unsigned char R;
unsigned char G;
unsigned char B;
} RGBColor_t;
typedef struct _WiFi_s
{
int Channel;
char SNR;
char bssid[AP_BSSID_MAX_LEN];
char band[WIFI_BAND_MAX_LEN];
char rssi;
} WiFi_t;
typedef struct _ct_tsl_s
{
char LightSwitch;
char NightLightSwitch;
RGBColor_t RGB;
unsigned char Brightness;
unsigned char WorkMode;
float f;
double d;
int readonly;
char *PropertyString;
char WorkTime[WORKTIME_MAX_LEN];
WiFi_t wifi;
} ct_tsl_t;
extern int ct_ut_init(void);
extern void ct_ut_misc_process(uint64_t time_now_sec);
extern ct_tsl_t* ct_ut_get_tsl_data(void);
extern int ct_ut_set_LightSwitch(char LightSwitch);
extern int ct_ut_get_LightSwitch(void);
extern int ct_ut_set_NightLightSwitch(char NightLightSwitch);
extern int ct_ut_set_WorkMode(unsigned char WorkMode);
extern int ct_ut_set_Brightness(unsigned char Brightness);
extern int ct_ut_set_RGB(unsigned char R, unsigned char G, unsigned char B);
extern int ct_ut_set_Float(float f);
extern int ct_ut_set_Double(double d);
extern int ct_ut_set_PropertyString(char *PropertyString);
extern int ct_ut_set_WorkTime(char *WorkTime);
#endif

View file

@ -0,0 +1,977 @@
{
"schema":"https://iotx-tsl.oss-ap-southeast-1.aliyuncs.com/schema.json",
"profile":{
"productKey":"a15mFJQoWM1"
},
"services":[
{
"outputData":[
],
"identifier":"set",
"inputData":[
{
"identifier":"LightSwitch",
"dataType":{
"specs":{
"0":"关闭",
"1":"开启"
},
"type":"bool"
},
"name":"主灯开关"
},
{
"identifier":"RGBColor",
"dataType":{
"specs":[
{
"identifier":"Red",
"dataType":{
"specs":{
"min":"0",
"unitName":"无",
"max":"255",
"step":"1"
},
"type":"int"
},
"name":"红色"
},
{
"identifier":"Green",
"dataType":{
"specs":{
"min":"0",
"unitName":"无",
"max":"255",
"step":"1"
},
"type":"int"
},
"name":"绿色"
},
{
"identifier":"Blue",
"dataType":{
"specs":{
"min":"0",
"unitName":"无",
"max":"255",
"step":"1"
},
"type":"int"
},
"name":"蓝色"
}
],
"type":"struct"
},
"name":"RGB调色"
},
{
"identifier":"NightLightSwitch",
"dataType":{
"specs":{
"0":"关闭",
"1":"开启"
},
"type":"bool"
},
"name":"夜灯开关"
},
{
"identifier":"WorkMode",
"dataType":{
"specs":{
"0":"手动",
"1":"阅读",
"2":"影院",
"3":"夜灯",
"4":"生活",
"5":"柔和"
},
"type":"enum"
},
"name":"工作模式"
},
{
"identifier":"Brightness",
"dataType":{
"specs":{
"unit":"%",
"min":"0",
"unitName":"百分比",
"max":"100",
"step":"1"
},
"type":"int"
},
"name":"明暗度"
},
{
"identifier":"worktime",
"dataType":{
"specs":{
},
"type":"date"
},
"name":"工作时间"
},
{
"identifier":"floatid",
"dataType":{
"specs":{
"min":"0",
"max":"10",
"step":"0.000001"
},
"type":"float"
},
"name":"单精度"
},
{
"identifier":"doubleid",
"dataType":{
"specs":{
"min":"0",
"max":"100",
"step":"0.000001"
},
"type":"double"
},
"name":"双精度"
},
{
"identifier":"PropertyString",
"dataType":{
"specs":{
"length":"1024"
},
"type":"text"
},
"name":"PropertyString"
}
],
"method":"thing.service.property.set",
"name":"set",
"required":true,
"callType":"async",
"desc":"属性设置"
},
{
"outputData":[
{
"identifier":"LightSwitch",
"dataType":{
"specs":{
"0":"关闭",
"1":"开启"
},
"type":"bool"
},
"name":"主灯开关"
},
{
"identifier":"WIFI_Band",
"dataType":{
"specs":{
"length":"255"
},
"type":"text"
},
"name":"频段"
},
{
"identifier":"WiFI_RSSI",
"dataType":{
"specs":{
"min":"-127",
"max":"-1",
"step":"1"
},
"type":"int"
},
"name":"信号强度"
},
{
"identifier":"WIFI_AP_BSSID",
"dataType":{
"specs":{
"length":"255"
},
"type":"text"
},
"name":"热点BSSID"
},
{
"identifier":"WIFI_Channel",
"dataType":{
"specs":{
"min":"1",
"max":"255",
"step":"1"
},
"type":"int"
},
"name":"信道"
},
{
"identifier":"WiFI_SNR",
"dataType":{
"specs":{
"min":"-127",
"max":"127",
"step":"1"
},
"type":"int"
},
"name":"信噪比"
},
{
"identifier":"RGBColor",
"dataType":{
"specs":[
{
"identifier":"Red",
"dataType":{
"specs":{
"min":"0",
"unitName":"无",
"max":"255",
"step":"1"
},
"type":"int"
},
"name":"红色"
},
{
"identifier":"Green",
"dataType":{
"specs":{
"min":"0",
"unitName":"无",
"max":"255",
"step":"1"
},
"type":"int"
},
"name":"绿色"
},
{
"identifier":"Blue",
"dataType":{
"specs":{
"min":"0",
"unitName":"无",
"max":"255",
"step":"1"
},
"type":"int"
},
"name":"蓝色"
}
],
"type":"struct"
},
"name":"RGB调色"
},
{
"identifier":"NightLightSwitch",
"dataType":{
"specs":{
"0":"关闭",
"1":"开启"
},
"type":"bool"
},
"name":"夜灯开关"
},
{
"identifier":"WorkMode",
"dataType":{
"specs":{
"0":"手动",
"1":"阅读",
"2":"影院",
"3":"夜灯",
"4":"生活",
"5":"柔和"
},
"type":"enum"
},
"name":"工作模式"
},
{
"identifier":"Brightness",
"dataType":{
"specs":{
"unit":"%",
"min":"0",
"unitName":"百分比",
"max":"100",
"step":"1"
},
"type":"int"
},
"name":"明暗度"
},
{
"identifier":"worktime",
"dataType":{
"specs":{
},
"type":"date"
},
"name":"工作时间"
},
{
"identifier":"onlyread",
"dataType":{
"specs":{
"min":"0",
"max":"50",
"step":"1"
},
"type":"int"
},
"name":"只读"
},
{
"identifier":"floatid",
"dataType":{
"specs":{
"min":"0",
"max":"10",
"step":"0.000001"
},
"type":"float"
},
"name":"单精度"
},
{
"identifier":"doubleid",
"dataType":{
"specs":{
"min":"0",
"max":"100",
"step":"0.000001"
},
"type":"double"
},
"name":"双精度"
},
{
"identifier":"PropertyString",
"dataType":{
"specs":{
"length":"1024"
},
"type":"text"
},
"name":"PropertyString"
}
],
"identifier":"get",
"inputData":[
"LightSwitch",
"WIFI_Band",
"WiFI_RSSI",
"WIFI_AP_BSSID",
"WIFI_Channel",
"WiFI_SNR",
"RGBColor",
"NightLightSwitch",
"WorkMode",
"Brightness",
"worktime",
"onlyread",
"floatid",
"doubleid",
"PropertyString"
],
"method":"thing.service.property.get",
"name":"get",
"required":true,
"callType":"async",
"desc":"属性获取"
},
{
"outputData":[
{
"identifier":"transparency",
"dataType":{
"specs":{
"min":"0",
"max":"100",
"step":"1"
},
"type":"int"
},
"name":"Contrastratio"
}
],
"identifier":"Custom",
"inputData":[
{
"identifier":"transparency",
"dataType":{
"specs":{
"min":"0",
"max":"100",
"step":"1"
},
"type":"int"
},
"name":"Contrastratio"
}
],
"method":"thing.service.Custom",
"name":"Custom",
"required":false,
"callType":"async"
},
{
"outputData":[
],
"identifier":"ToggleLightSwitch",
"inputData":[
],
"method":"thing.service.ToggleLightSwitch",
"name":"翻转主灯开关",
"required":false,
"callType":"sync"
}
],
"properties":[
{
"identifier":"LightSwitch",
"dataType":{
"specs":{
"0":"关闭",
"1":"开启"
},
"type":"bool"
},
"name":"主灯开关",
"accessMode":"rw",
"required":false
},
{
"identifier":"WIFI_Band",
"dataType":{
"specs":{
"length":"255"
},
"type":"text"
},
"name":"频段",
"accessMode":"r",
"required":false
},
{
"identifier":"WiFI_RSSI",
"dataType":{
"specs":{
"min":"-127",
"max":"-1",
"step":"1"
},
"type":"int"
},
"name":"信号强度",
"accessMode":"r",
"required":false
},
{
"identifier":"WIFI_AP_BSSID",
"dataType":{
"specs":{
"length":"255"
},
"type":"text"
},
"name":"热点BSSID",
"accessMode":"r",
"required":false
},
{
"identifier":"WIFI_Channel",
"dataType":{
"specs":{
"min":"1",
"max":"255",
"step":"1"
},
"type":"int"
},
"name":"信道",
"accessMode":"r",
"required":false
},
{
"identifier":"WiFI_SNR",
"dataType":{
"specs":{
"min":"-127",
"max":"127",
"step":"1"
},
"type":"int"
},
"name":"信噪比",
"accessMode":"r",
"required":false
},
{
"identifier":"RGBColor",
"dataType":{
"specs":[
{
"identifier":"Red",
"dataType":{
"specs":{
"min":"0",
"unitName":"无",
"max":"255",
"step":"1"
},
"type":"int"
},
"name":"红色"
},
{
"identifier":"Green",
"dataType":{
"specs":{
"min":"0",
"unitName":"无",
"max":"255",
"step":"1"
},
"type":"int"
},
"name":"绿色"
},
{
"identifier":"Blue",
"dataType":{
"specs":{
"min":"0",
"unitName":"无",
"max":"255",
"step":"1"
},
"type":"int"
},
"name":"蓝色"
}
],
"type":"struct"
},
"name":"RGB调色",
"accessMode":"rw",
"required":false
},
{
"identifier":"NightLightSwitch",
"dataType":{
"specs":{
"0":"关闭",
"1":"开启"
},
"type":"bool"
},
"name":"夜灯开关",
"accessMode":"rw",
"required":false
},
{
"identifier":"WorkMode",
"dataType":{
"specs":{
"0":"手动",
"1":"阅读",
"2":"影院",
"3":"夜灯",
"4":"生活",
"5":"柔和"
},
"type":"enum"
},
"name":"工作模式",
"accessMode":"rw",
"required":false
},
{
"identifier":"Brightness",
"dataType":{
"specs":{
"unit":"%",
"min":"0",
"unitName":"百分比",
"max":"100",
"step":"1"
},
"type":"int"
},
"name":"明暗度",
"accessMode":"rw",
"required":false
},
{
"identifier":"worktime",
"dataType":{
"specs":{
},
"type":"date"
},
"name":"工作时间",
"accessMode":"rw",
"required":false
},
{
"identifier":"onlyread",
"dataType":{
"specs":{
"min":"0",
"max":"50",
"step":"1"
},
"type":"int"
},
"name":"只读",
"accessMode":"r",
"required":false
},
{
"identifier":"floatid",
"dataType":{
"specs":{
"min":"0",
"max":"10",
"step":"0.000001"
},
"type":"float"
},
"name":"单精度",
"accessMode":"rw",
"required":false
},
{
"identifier":"doubleid",
"dataType":{
"specs":{
"min":"0",
"max":"100",
"step":"0.000001"
},
"type":"double"
},
"name":"双精度",
"accessMode":"rw",
"required":false
},
{
"identifier":"PropertyString",
"dataType":{
"specs":{
"length":"1024"
},
"type":"text"
},
"name":"PropertyString",
"accessMode":"rw",
"required":false
}
],
"events":[
{
"outputData":[
{
"identifier":"LightSwitch",
"dataType":{
"specs":{
"0":"关闭",
"1":"开启"
},
"type":"bool"
},
"name":"主灯开关"
},
{
"identifier":"WIFI_Band",
"dataType":{
"specs":{
"length":"255"
},
"type":"text"
},
"name":"频段"
},
{
"identifier":"WiFI_RSSI",
"dataType":{
"specs":{
"min":"-127",
"max":"-1",
"step":"1"
},
"type":"int"
},
"name":"信号强度"
},
{
"identifier":"WIFI_AP_BSSID",
"dataType":{
"specs":{
"length":"255"
},
"type":"text"
},
"name":"热点BSSID"
},
{
"identifier":"WIFI_Channel",
"dataType":{
"specs":{
"min":"1",
"max":"255",
"step":"1"
},
"type":"int"
},
"name":"信道"
},
{
"identifier":"WiFI_SNR",
"dataType":{
"specs":{
"min":"-127",
"max":"127",
"step":"1"
},
"type":"int"
},
"name":"信噪比"
},
{
"identifier":"RGBColor",
"dataType":{
"specs":[
{
"identifier":"Red",
"dataType":{
"specs":{
"min":"0",
"unitName":"无",
"max":"255",
"step":"1"
},
"type":"int"
},
"name":"红色"
},
{
"identifier":"Green",
"dataType":{
"specs":{
"min":"0",
"unitName":"无",
"max":"255",
"step":"1"
},
"type":"int"
},
"name":"绿色"
},
{
"identifier":"Blue",
"dataType":{
"specs":{
"min":"0",
"unitName":"无",
"max":"255",
"step":"1"
},
"type":"int"
},
"name":"蓝色"
}
],
"type":"struct"
},
"name":"RGB调色"
},
{
"identifier":"NightLightSwitch",
"dataType":{
"specs":{
"0":"关闭",
"1":"开启"
},
"type":"bool"
},
"name":"夜灯开关"
},
{
"identifier":"WorkMode",
"dataType":{
"specs":{
"0":"手动",
"1":"阅读",
"2":"影院",
"3":"夜灯",
"4":"生活",
"5":"柔和"
},
"type":"enum"
},
"name":"工作模式"
},
{
"identifier":"Brightness",
"dataType":{
"specs":{
"unit":"%",
"min":"0",
"unitName":"百分比",
"max":"100",
"step":"1"
},
"type":"int"
},
"name":"明暗度"
},
{
"identifier":"worktime",
"dataType":{
"specs":{
},
"type":"date"
},
"name":"工作时间"
},
{
"identifier":"onlyread",
"dataType":{
"specs":{
"min":"0",
"max":"50",
"step":"1"
},
"type":"int"
},
"name":"只读"
},
{
"identifier":"floatid",
"dataType":{
"specs":{
"min":"0",
"max":"10",
"step":"0.000001"
},
"type":"float"
},
"name":"单精度"
},
{
"identifier":"doubleid",
"dataType":{
"specs":{
"min":"0",
"max":"100",
"step":"0.000001"
},
"type":"double"
},
"name":"双精度"
},
{
"identifier":"PropertyString",
"dataType":{
"specs":{
"length":"1024"
},
"type":"text"
},
"name":"PropertyString"
}
],
"identifier":"post",
"method":"thing.event.property.post",
"name":"post",
"type":"info",
"required":true,
"desc":"属性上报"
},
{
"outputData":[
{
"identifier":"ErrorCode",
"dataType":{
"specs":{
"0":"恢复正常"
},
"type":"enum"
},
"name":"故障代码"
}
],
"identifier":"Error",
"method":"thing.event.Error.post",
"name":"故障上报",
"type":"error",
"required":false
},
{
"outputData":[
{
"identifier":"alarm",
"dataType":{
"specs":{
"min":"0",
"max":"10",
"step":"1"
},
"type":"int"
},
"name":"alarm"
}
],
"identifier":"alarm",
"method":"thing.event.alarm.post",
"name":"alarm",
"type":"alert",
"required":false
},
{
"outputData":[
{
"identifier":"info",
"dataType":{
"specs":{
"min":"0",
"max":"20",
"step":"1"
},
"type":"int"
},
"name":"info"
}
],
"identifier":"info",
"method":"thing.event.info.post",
"name":"info",
"type":"info",
"required":false
}
]
}

View file

@ -0,0 +1,96 @@
var COMMAND_REPORT = 0x01; //属性上报
var COMMAND_SET = 0x02; //属性设置
var ALINK_PROP_REPORT_METHOD = 'thing.event.property.post'; //标准ALink JSON格式topic 设备上传属性数据到云端
var ALINK_PROP_SET_METHOD = 'thing.service.property.set'; //标准ALink JSON格式topic 云端下发属性控制指令到设备端
var ALINK_PROP_SET_REPLY_METHOD = 'thing.service.property.set'; //标准ALink JSON格式topic, 设备上报属性设置的结果到云端
/*
示例数据:
设备上报数据
传入参数 ->
0x010000006400
输出结果 ->
{"method":"thing.event.property.post","id":"100","params":{"LightSwitch":0},"version":"1.0"}
*/
function rawDataToProtocol(bytes) {
var uint8Array = new Uint8Array(bytes.length);
for (var i = 0; i < bytes.length; i++) {
uint8Array[i] = bytes[i] & 0xff;
}
var dataView = new DataView(uint8Array.buffer, 0);
var jsonMap = new Object();
var fHead = uint8Array[0]; // command
if (fHead == COMMAND_REPORT) {
jsonMap['method'] = ALINK_PROP_REPORT_METHOD; //ALink JSON格式 - 属性上报topic
jsonMap['version'] = '1.0'; //ALink JSON格式 - 协议版本号固定字段
jsonMap['id'] = '' + dataView.getInt32(1); //ALink JSON格式 - 标示该次请求id值
var params = {};
params['LightSwitch'] = dataView.getInt8(5); //对应产品属性中 prop_int16
jsonMap['params'] = params; //ALink JSON格式 - params标准字段
}
return jsonMap;
}
/*
示例数据:
属性设置
传入参数 ->
{"method":"thing.service.property.set","id":"100","version":"1.0","params":{"LightSwitch":0}}
输出结果 ->
0x020000006400
*/
function protocolToRawData(json) {
var method = json['method'];
var id = json['id'];
var version = json['version'];
var payloadArray = [];
if (method == ALINK_PROP_SET_METHOD) // 属性设置
{
var params = json['params'];
var light_switch = params['LightSwitch'];
//按照自定义协议格式拼接 rawData
payloadArray = payloadArray.concat(buffer_uint8(COMMAND_SET)); // command字段
payloadArray = payloadArray.concat(buffer_int32(parseInt(id))); // ALink JSON格式 'id'
payloadArray = payloadArray.concat(buffer_uint8(light_switch)); // 属性'light_switch'的值
}
return payloadArray;
}
/**
* 将设备自定义topic数据转换为json格式数据, 设备上报数据到物联网平台时调用
* 入参topic 字符串设备上报消息的topic
* 入参rawData byte[]数组 不能为空
* 出参jsonObj 对象 不能为空
*/
function transformPayload(topic, rawData) {
jsonObj = {}
return jsonObj
}
//以下是部分辅助函数
function buffer_uint8(value) {
var uint8Array = new Uint8Array(1);
var dv = new DataView(uint8Array.buffer, 0);
dv.setUint8(0, value);
return [].slice.call(uint8Array);
}
function buffer_int16(value) {
var uint8Array = new Uint8Array(2);
var dv = new DataView(uint8Array.buffer, 0);
dv.setInt16(0, value);
return [].slice.call(uint8Array);
}
function buffer_int32(value) {
var uint8Array = new Uint8Array(4);
var dv = new DataView(uint8Array.buffer, 0);
dv.setInt32(0, value);
return [].slice.call(uint8Array);
}
function buffer_float32(value) {
var uint8Array = new Uint8Array(4);
var dv = new DataView(uint8Array.buffer, 0);
dv.setFloat32(0, value);
return [].slice.call(uint8Array);
}

View file

@ -0,0 +1,9 @@
工具名称log_extract.sh
工具功能:从一个或者多个日志文件中提取感兴趣的日志信息
使用方式:
1. 运行环境Linux运行环境
2. Linux环境下运行log_extract.sh脚本要求用户输入三个参数
- 日志文件夹名称例如logfiles
- 需要提取的关键信息例如disconnect
- 关键字前后的行数例如10
3. 脚本执行之后会自动生成一个类似这样的文件logfiles-20200304_183318.log如果抓取的日志文件比较多的时候使用这个工具可以提高分析效率

View file

@ -0,0 +1,46 @@
#!/bin/bash
#This script can extract some lines from some log files according some key words
#Date:2020-03-03
#Version:1.0
#Author:Liuese
#Contacts:TingTalk number:13826595824
#Changes:Create
read -p "Please input a folder which include some log files:" logfiles
test -e $logfiles || echo "Folder $logfiles is not exist" || exit 1
test -r $logfiles || echo "Folder $logfiles can not read" || exit 1
read -p "Please input a keyword that want be searched:" keyword
test -z $keyword && echo "You input is none" && exit 1
declare -i lines
read -p "Please input a number which is the lines around the keyword $keyword:" lines
if test $lines -lt 1
then
echo "Please input a number that must larger than 0"
exit 1
fi
if test $? -ne 0
then
echo "Please input a number"
exit 1
fi
time=$(date +%Y%m%d_%H%M%S)
savedfile=$logfiles-$time.log
files=$(ls $logfiles)
for file in $files
do
printf "+++++++++++++++File:$file +++++++++++++++\r\n" >> ./$savedfile
keylog=$(cat ./$logfiles/$file | grep -C $lines "$keyword")
echo $keylog >> ./$savedfile
printf "===============File:$file ===============\r\n" >> ./$savedfile
done
dir=$(pwd)
echo "Your input params log folder is:$logfiles keyword is:$keyword lines is:$lines"
echo "The parsed log saved to file:$dir/$savedfile"
exit 0

View file

@ -0,0 +1,204 @@
/*
* Copyright (C) 2015-2020 Alibaba Group Holding Limited
*/
#include "cJSON.h"
#include "iotx_log.h"
#include "iot_import.h"
#include "iot_export_linkkit.h"
#include "gateway_main.h"
#include "gateway_api.h"
/*
[params]
subdev_mate:one subdev meta info
[return]
SUCCESS_RETURN:success
FAIL_RETURN:failed
*/
GATEWAY_API int gateway_add_subdev(iotx_linkkit_dev_meta_info_t *subdev_mate)
{
int res = SUCCESS_RETURN;
int devid = -1;
devid = IOT_Linkkit_Open(IOTX_LINKKIT_DEV_TYPE_SLAVE, subdev_mate);
if (devid == FAIL_RETURN)
{
gateway_info("subdev open Failed");
return FAIL_RETURN;
}
gateway_info("subdev open susseed, devid = %d", devid);
res = IOT_Linkkit_Connect(devid);
if (res == FAIL_RETURN)
{
gateway_info("subdev connect Failed");
return res;
}
gateway_info("subdev connect success: devid = %d", devid);
res = IOT_Linkkit_Report(devid, ITM_MSG_LOGIN, NULL, 0);
if (res == FAIL_RETURN)
{
gateway_info("subdev login Failed");
return res;
}
return res;
}
/*
[params]
master_devid:master device id
subdev_list:one or more subdev meta info
subdev_num:subdev total
[return]
SUCCESS_RETURN:success
FAIL_RETURN:failed
*/
GATEWAY_API int gateway_add_multi_subdev(int master_devid, iotx_linkkit_dev_meta_info_t *subdev_list, int subdev_num)
{
int res = SUCCESS_RETURN;
int subdev_id = 0;
int index = 0;
int inner_index = 0;
int connect_times = 0;
int cur_subdev_num = 0;
iotx_linkkit_dev_meta_info_t *p_cur_subdev = NULL;
if (!subdev_list || subdev_num < 1)
{
gateway_err("add multi subdev Failed\n");
return FAIL_RETURN;
}
connect_times = subdev_num / GATEWAY_SUBDEV_ONE_TIME_CONNECT_MAX_NUM + (((subdev_num % GATEWAY_SUBDEV_ONE_TIME_CONNECT_MAX_NUM) == 0) ? 0 : 1);
for (index = 0; index < connect_times; index++)
{
p_cur_subdev = subdev_list + (index * GATEWAY_SUBDEV_ONE_TIME_CONNECT_MAX_NUM);
if ((index == (connect_times - 1)) && ((subdev_num % GATEWAY_SUBDEV_ONE_TIME_CONNECT_MAX_NUM) != 0))
{
cur_subdev_num = subdev_num - (index * GATEWAY_SUBDEV_ONE_TIME_CONNECT_MAX_NUM);
}
else
{
cur_subdev_num = GATEWAY_SUBDEV_ONE_TIME_CONNECT_MAX_NUM;
}
res = IOT_Linkkit_Report(master_devid, ITM_MSG_CONNECT_SUBDEV, (unsigned char *)p_cur_subdev, sizeof(iotx_linkkit_dev_meta_info_t) * cur_subdev_num);
if (res == FAIL_RETURN)
{
gateway_err("add multi subdev index:%d Failed\n", index);
}
else
{
gateway_info("add multi subdev index:%d success\n", index);
iotx_linkkit_dev_meta_info_t *p_subdev_mate = NULL;
for (inner_index = 0; inner_index < cur_subdev_num; inner_index++)
{
p_subdev_mate = p_cur_subdev + inner_index;
subdev_id = gateway_query_subdev_id(master_devid, p_subdev_mate);
if (subdev_id > 0)
{
res = IOT_Linkkit_Report(subdev_id, ITM_MSG_LOGIN, NULL, 0);
if (res == FAIL_RETURN)
{
gateway_err("login subdev dn:%s failed", p_subdev_mate->device_name);
}
else
{
gateway_debug("login subdev dn:%s success", p_subdev_mate->device_name);
}
}
else
{
gateway_err("connect subdev dn:%s failed", p_subdev_mate->device_name);
}
}
}
}
return res;
}
/*
[params]
subdev_mate:one subdev meta info
[return]
SUCCESS_RETURN:success
FAIL_RETURN:failed
*/
GATEWAY_API int gateway_del_subdev(iotx_linkkit_dev_meta_info_t *subdev_mate)
{
int subdev_id = 1000; //set an not exist subdev id
int ret = SUCCESS_RETURN;
gateway_info("do del subdev");
//Here pk and dn of subdev is priorior than subdev id
ret = IOT_Linkkit_Report(subdev_id, ITM_MSG_DELETE_TOPO, (unsigned char *)subdev_mate, sizeof(iotx_linkkit_dev_meta_info_t));
if (SUCCESS_RETURN != ret)
{
gateway_err("del subdev failed");
}
return 0;
}
/*
[params]
subdev_mate:one subdev meta info
[return]
SUCCESS_RETURN:success
FAIL_RETURN:failed
*/
GATEWAY_API int gateway_reset_subdev(iotx_linkkit_dev_meta_info_t *subdev_mate)
{
int subdev_id = 1000; //set an not exist subdev id
int ret = SUCCESS_RETURN;
gateway_info("do reset subdev");
//Here pk and dn of subdev is priorior than subdev id
ret = IOT_Linkkit_Report(subdev_id, ITM_MSG_SUBDEV_RESET, (unsigned char *)subdev_mate, sizeof(iotx_linkkit_dev_meta_info_t));
if (SUCCESS_RETURN != ret)
{
gateway_err("reset subdev failed");
}
return ret;
}
/*
[params]
master_devid:master device id
subdev_mate:one subdev meta info
[return]
subdev_id:>0 success <=0 failed
*/
GATEWAY_API int gateway_query_subdev_id(int master_devid, iotx_linkkit_dev_meta_info_t *subdev_mate)
{
int subdev_id = -1; //set an not exist subdev id
gateway_info("query subdev id");
subdev_id = IOT_Linkkit_Query(master_devid, ITM_MSG_QUERY_SUBDEV_ID, (unsigned char *)subdev_mate, sizeof(iotx_linkkit_dev_meta_info_t));
if (subdev_id < 0)
{
gateway_err("subdev not exist");
}
else
{
gateway_info("got subdev id is %d", subdev_id);
}
return subdev_id;
}

View file

@ -0,0 +1,62 @@
#ifndef __GATEWAY_API_H__
#define __GATEWAY_API_H__
#ifndef GATEWAY_API
#define GATEWAY_API
#endif
#define GATEWAY_SUBDEV_ONE_TIME_CONNECT_MAX_NUM (5)
/*
[params]
subdev_mate:one subdev meta info
[return]
SUCCESS_RETURN:success
FAIL_RETURN:failed
*/
extern GATEWAY_API int gateway_add_subdev(iotx_linkkit_dev_meta_info_t *subdev_mate);
/*
[params]
master_devid:master device id
subdev_list:one or more subdev meta info
subdev_num:subdev total
[return]
SUCCESS_RETURN:success
FAIL_RETURN:failed
*/
extern GATEWAY_API int gateway_add_multi_subdev(int master_devid, iotx_linkkit_dev_meta_info_t *subdev_list, int subdev_num);
/*
[params]
subdev_mate:one subdev meta info
[return]
SUCCESS_RETURN:success
FAIL_RETURN:failed
*/
extern GATEWAY_API int gateway_del_subdev(iotx_linkkit_dev_meta_info_t *subdev_mate);
/*
[params]
subdev_mate:one subdev meta info
[return]
SUCCESS_RETURN:success
FAIL_RETURN:failed
*/
extern GATEWAY_API int gateway_reset_subdev(iotx_linkkit_dev_meta_info_t *subdev_mate);
/*
[params]
master_devid:master device id
subdev_mate:one subdev meta info
[return]
subdev_id:>0 success <=0 failed
*/
extern GATEWAY_API int gateway_query_subdev_id(int master_devid, iotx_linkkit_dev_meta_info_t *subdev_mate);
#endif

View file

@ -0,0 +1,89 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "iot_export.h"
#include "gateway_entry.h"
#include "gateway_main.h"
#include "gateway_ut.h"
#ifdef GATEWAY_UT_TESTING
static void load_gateway_meta_info(void)
{
int len = 0;
char key_buf[MAX_KEY_LEN];
char product_key[PRODUCT_KEY_LEN + 1] = {0};
char product_secret[PRODUCT_SECRET_LEN + 1] = {0};
char device_name[DEVICE_NAME_LEN + 1] = {0};
char device_secret[DEVICE_SECRET_LEN + 1] = {0};
len = PRODUCT_KEY_LEN + 1;
memset(key_buf, 0, MAX_KEY_LEN);
memset(product_key, 0, sizeof(product_key));
HAL_Snprintf(key_buf, MAX_KEY_LEN, "%s_%d", KV_KEY_PK, 0);
HAL_Kv_Get(key_buf, product_key, &len);
len = PRODUCT_SECRET_LEN + 1;
memset(key_buf, 0, MAX_KEY_LEN);
memset(product_secret, 0, sizeof(product_secret));
HAL_Snprintf(key_buf, MAX_KEY_LEN, "%s_%d", KV_KEY_PS, 0);
HAL_Kv_Get(key_buf, product_secret, &len);
len = DEVICE_NAME_LEN + 1;
memset(key_buf, 0, MAX_KEY_LEN);
memset(device_name, 0, sizeof(device_name));
HAL_Snprintf(key_buf, MAX_KEY_LEN, "%s_%d", KV_KEY_DN, 0);
HAL_Kv_Get(key_buf, device_name, &len);
len = DEVICE_SECRET_LEN + 1;
memset(key_buf, 0, MAX_KEY_LEN);
memset(device_secret, 0, sizeof(device_secret));
HAL_Snprintf(key_buf, MAX_KEY_LEN, "%s_%d", KV_KEY_DS, 0);
HAL_Kv_Get(key_buf, device_secret, &len);
if ((strlen(product_key) > 0) && (strlen(product_secret) > 0) && (strlen(device_name) > 0) && (strlen(device_secret) > 0))
{
HAL_SetProductKey(product_key);
HAL_SetProductSecret(product_secret);
HAL_SetDeviceName(device_name);
HAL_SetDeviceSecret(device_secret);
printf("pk[%s]\r\n", product_key);
printf("dn[%s]\r\n", device_name);
}
else
{
HAL_SetProductKey(PRODUCT_KEY);
HAL_SetProductSecret(PRODUCT_SECRET);
HAL_SetDeviceName(DEVICE_NAME);
HAL_SetDeviceSecret(DEVICE_SECRET);
printf("pk[%s]\r\n", PRODUCT_KEY);
printf("dn[%s]\r\n", DEVICE_NAME);
}
}
#endif
int main(int argc, char **argv)
{
gateway_main_params_t paras;
paras.argc = argc;
paras.argv = argv;
#ifdef LOG_LEVEL_DEBUG
IOT_SetLogLevel(IOT_LOG_DEBUG);
#else
IOT_SetLogLevel(IOT_LOG_INFO);
#endif
#ifdef GATEWAY_UT_TESTING
load_gateway_meta_info();
#endif
gateway_main((void *)&paras);
return 0;
}

View file

@ -0,0 +1,20 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef __APP_ENTRY_H__
#define __APP_ENTRY_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#define LOG_LEVEL_DEBUG
typedef struct
{
int argc;
char **argv;
} gateway_main_params_t;
#endif

View file

@ -0,0 +1,790 @@
/*
* Copyright (C) 2015-2019 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include "cJSON.h"
#include "iot_import.h"
#include "iot_export_linkkit.h"
#include "iotx_log.h"
#include "gateway_main.h"
#include "gateway_api.h"
#include "gateway_ut.h"
static gateway_ctx_t g_gateway_ctx;
static void *permit_join_timer = NULL;
gateway_ctx_t *gateway_get_ctx(void)
{
return &g_gateway_ctx;
}
static int user_connected_event_handler(void)
{
gateway_ctx_t *gateway_ctx = gateway_get_ctx();
gateway_info("Cloud Connected");
gateway_ctx->cloud_connected = 1;
if (gateway_ctx->master_initialized == 1) //initialized
{
#ifdef GATEWAY_UT_TESTING
gateway_ut_update_subdev(GW_TOPO_GET_REASON_CONNECT_CLOUD);
#endif
}
return 0;
}
static int user_disconnected_event_handler(void)
{
gateway_ctx_t *gateway_ctx = gateway_get_ctx();
gateway_info("Cloud Disconnected");
gateway_ctx->cloud_connected = 0;
return 0;
}
static int user_down_raw_data_arrived_event_handler(const int devid, const unsigned char *payload,
const int payload_len)
{
gateway_info("Down Raw Message, Devid: %d, Payload Length: %d", devid, payload_len);
return 0;
}
static int user_service_request_event_handler(const int devid, const char *serviceid, const int serviceid_len,
const char *request, const int request_len,
char **response, int *response_len)
{
gateway_info("Service Request Received, Devid: %d, Service ID: %.*s, Payload: %s", devid, serviceid_len,
serviceid,
request);
return 0;
}
#ifdef ALCS_ENABLED
//Just for reference,user have to change his owner properties
static int user_property_get_event_handler(const int devid, const char *request, const int request_len, char **response,
int *response_len)
{
cJSON *request_root = NULL, *item_propertyid = NULL;
cJSON *response_root = NULL;
int index = 0;
gateway_info("Property Get Received, Devid: %d, Request: %s", devid, request);
/* Parse Request */
request_root = cJSON_Parse(request);
if (request_root == NULL || !cJSON_IsArray(request_root))
{
gateway_info("JSON Parse Error");
return -1;
}
/* Prepare Response */
response_root = cJSON_CreateObject();
if (response_root == NULL)
{
gateway_info("No Enough Memory");
cJSON_Delete(request_root);
return -1;
}
for (index = 0; index < cJSON_GetArraySize(request_root); index++)
{
item_propertyid = cJSON_GetArrayItem(request_root, index);
if (item_propertyid == NULL || !cJSON_IsString(item_propertyid))
{
gateway_info("JSON Parse Error");
cJSON_Delete(request_root);
cJSON_Delete(response_root);
return -1;
}
gateway_info("Property ID, index: %d, Value: %s", index, item_propertyid->valuestring);
if (strcmp("WIFI_Tx_Rate", item_propertyid->valuestring) == 0)
{
cJSON_AddNumberToObject(response_root, "WIFI_Tx_Rate", 1111);
}
else if (strcmp("WIFI_Rx_Rate", item_propertyid->valuestring) == 0)
{
cJSON_AddNumberToObject(response_root, "WIFI_Rx_Rate", 2222);
}
else if (strcmp("LocalTimer", item_propertyid->valuestring) == 0)
{
cJSON *array_localtimer = cJSON_CreateArray();
if (array_localtimer == NULL)
{
cJSON_Delete(request_root);
cJSON_Delete(response_root);
return -1;
}
cJSON *item_localtimer = cJSON_CreateObject();
if (item_localtimer == NULL)
{
cJSON_Delete(request_root);
cJSON_Delete(response_root);
cJSON_Delete(array_localtimer);
return -1;
}
cJSON_AddStringToObject(item_localtimer, "Timer", "10 11 * * * 1 2 3 4 5");
cJSON_AddNumberToObject(item_localtimer, "Enable", 1);
cJSON_AddNumberToObject(item_localtimer, "IsValid", 1);
cJSON_AddItemToArray(array_localtimer, item_localtimer);
cJSON_AddItemToObject(response_root, "LocalTimer", array_localtimer);
}
}
cJSON_Delete(request_root);
*response = cJSON_PrintUnformatted(response_root);
if (*response == NULL)
{
gateway_info("No Enough Memory");
cJSON_Delete(response_root);
return -1;
}
cJSON_Delete(response_root);
*response_len = strlen(*response);
gateway_info("Property Get Response: %s", *response);
return SUCCESS_RETURN;
}
#endif
//When code is not 200,maybe call this function
static int user_property_cloud_error_handler(const int code, const char *data, const char *detail)
{
gateway_info("code =%d ,data=%s, detail=%s", code, data, detail);
return 0;
}
static int user_property_set_event_handler(const int devid, const char *request, const int request_len)
{
int res = 0;
gateway_ctx_t *gateway_ctx = gateway_get_ctx();
gateway_info("Property Set Received, Devid: %d, Request: %s", devid, request);
res = IOT_Linkkit_Report(devid, ITM_MSG_POST_PROPERTY,
(unsigned char *)request, request_len);
gateway_info("Post Property Message ID: %d", res);
return 0;
}
static int user_report_reply_event_handler(const int devid, const int msgid, const int code, const char *reply,
const int reply_len)
{
const char *reply_value = (reply == NULL) ? ("NULL") : (reply);
const int reply_value_len = (reply_len == 0) ? (strlen("NULL")) : (reply_len);
gateway_info("Message Post Reply Received, Devid: %d, Message ID: %d, Code: %d, Reply: %.*s", devid, msgid, code,
reply_value_len,
reply_value);
return 0;
}
static int user_trigger_event_reply_event_handler(const int devid, const int msgid, const int code, const char *eventid,
const int eventid_len, const char *message, const int message_len)
{
gateway_info("Trigger Event Reply Received, Devid: %d, Message ID: %d, Code: %d, EventID: %.*s, Message: %.*s", devid,
msgid, code,
eventid_len,
eventid, message_len, message);
return 0;
}
static int user_timestamp_reply_event_handler(const char *timestamp)
{
gateway_info("Current Timestamp: %s", timestamp);
return 0;
}
static uint64_t user_update_sec(void)
{
static uint64_t time_start_ms = 0;
if (time_start_ms == 0)
{
time_start_ms = HAL_UptimeMs();
}
return (HAL_UptimeMs() - time_start_ms) / 1000;
}
static int user_initialized(const int devid)
{
gateway_ctx_t *gateway_ctx = gateway_get_ctx();
gateway_info("Device Initialized, Devid: %d", devid);
if (gateway_ctx->master_devid == devid)
{
gateway_ctx->master_initialized = 1;
}
return 0;
}
static int user_master_dev_available(void)
{
gateway_ctx_t *gateway_ctx = gateway_get_ctx();
if (gateway_ctx->cloud_connected && gateway_ctx->master_initialized)
{
return 1;
}
return 0;
}
static int gw_notify_msg_handle(int devid, const char *request, const int request_len)
{
int ret = 0;
cJSON *request_root = NULL;
cJSON *item = NULL;
gateway_msg_t gw_msg;
request_root = cJSON_Parse(request);
if (request_root == NULL)
{
gateway_info("JSON Parse Error");
return -1;
}
item = cJSON_GetObjectItem(request_root, "identifier");
if (item == NULL || !cJSON_IsString(item))
{
cJSON_Delete(request_root);
return -1;
}
if (!strcmp(item->valuestring, "awss.BindNotify"))
{
cJSON *value = cJSON_GetObjectItem(request_root, "value");
if (value == NULL || !cJSON_IsObject(value))
{
cJSON_Delete(request_root);
return -1;
}
cJSON *op = cJSON_GetObjectItem(value, "Operation");
if (op != NULL && cJSON_IsString(op))
{
if (!strcmp(op->valuestring, "Bind"))
{
gateway_info("Device Bind");
}
else if (!strcmp(op->valuestring, "Unbind"))
{
gateway_info("Device unBind");
if (devid > 0) //User unbind subdev
{
memset(&gw_msg, 0, sizeof(gateway_msg_t));
gw_msg.msg_type = GATEWAY_MSG_TYPE_DEL;
gw_msg.devid = devid;
ret = gateway_ut_send_msg(&gw_msg, sizeof(gateway_msg_t));
}
}
else if (!strcmp(op->valuestring, "Reset"))
{
gateway_info("Device reset");
if (devid > 0) //User reset subdev
{
memset(&gw_msg, 0, sizeof(gateway_msg_t));
gw_msg.msg_type = GATEWAY_MSG_TYPE_RESET;
gw_msg.devid = devid;
ret = gateway_ut_send_msg(&gw_msg, sizeof(gateway_msg_t));
}
}
}
}
cJSON_Delete(request_root);
return 0;
}
static int user_event_notify_handler(const int devid, const char *request, const int request_len)
{
int res = 0;
gateway_ctx_t *gateway_ctx = gateway_get_ctx();
gateway_info("Event notify Received, Devid: %d, Request: %s", devid, request);
gw_notify_msg_handle(devid, request, request_len);
res = IOT_Linkkit_Report(gateway_ctx->master_devid, ITM_MSG_EVENT_NOTIFY_REPLY,
(unsigned char *)request, request_len);
gateway_info("Post Property Message ID: %d", res);
return 0;
}
//get topo list reply
static int user_topolist_reply_handler(const int devid, const int id, const int code, const char *payload, const int payload_len)
{
gateway_info("Receive topolist reply, code:%d, payload:%s", code, payload);
#ifdef GATEWAY_UT_TESTING
if (code == 200 && payload && payload_len > 0)
{
gateway_ut_handle_topolist_reply(payload, payload_len);
}
#endif
return 0;
}
static int permit_join_timer_cb(void)
{
gateway_ctx_t *gateway_ctx = gateway_get_ctx();
if (permit_join_timer)
{
HAL_Timer_Stop(permit_join_timer);
HAL_Timer_Delete(permit_join_timer);
permit_join_timer = NULL;
gateway_ctx->permit_join = 0;
gateway_info("delete permit join timer");
}
return 0;
}
static int user_permit_join_event_handler(const char *product_key, const int time)
{
gateway_ctx_t *gateway_ctx = gateway_get_ctx();
gateway_info("Product Key: %s, Time: %dS", product_key, time);
memset(gateway_ctx->permit_join_pk, '\0', PRODUCT_KEY_MAXLEN);
if (strlen(product_key) > 0 && strlen(product_key) < PRODUCT_KEY_MAXLEN)
{
HAL_Snprintf(gateway_ctx->permit_join_pk, PRODUCT_KEY_MAXLEN, "%s", product_key);
}
gateway_ctx->permit_join = 1;
if (permit_join_timer) //Just restart this timer
{
HAL_Timer_Stop(permit_join_timer);
HAL_Timer_Start(permit_join_timer, time * 1000);
}
else if (time > 0)
{
permit_join_timer = HAL_Timer_Create("oll_upload", (void (*)(void *))permit_join_timer_cb, NULL);
if (permit_join_timer)
{
HAL_Timer_Stop(permit_join_timer);
HAL_Timer_Start(permit_join_timer, time * 1000);
}
}
#ifdef GATEWAY_UT_TESTING
gateway_ut_handle_permit_join();
#endif
return 0;
}
#ifdef GATEWAY_SUPPORT_TOPO_CHANGE
static int user_gateway_topo_change_handler(const int devid, const char *payload, const int payload_len)
{
int index = 0;
int subdev_id = -1;
cJSON *topo_change = NULL, *status = NULL, *subList = NULL;
cJSON *subdev, *pk = NULL, *dn = NULL;
gateway_ctx_t *gateway_ctx = gateway_get_ctx();
iotx_linkkit_dev_meta_info_t subdev_mate;
gateway_debug("Receive topo change, payload:%s", payload);
/* Parse Request */
topo_change = cJSON_Parse(payload);
if (topo_change == NULL)
{
gateway_err("topo change json format err");
return -1;
}
status = cJSON_GetObjectItem(topo_change, TOPO_CHANGE_STATUS);
if (!cJSON_IsNumber(status))
{
gateway_err("topo change status err");
cJSON_Delete(topo_change);
return -1;
}
subList = cJSON_GetObjectItem(topo_change, TOPO_CHANGE_SUBLIST);
if (!cJSON_IsArray(subList))
{
gateway_err("topo change subList err");
cJSON_Delete(topo_change);
return -1;
}
for (index = 0; index < cJSON_GetArraySize(subList); index++)
{
subdev = cJSON_GetArrayItem(subList, index);
if (subdev == NULL || !cJSON_IsObject(subdev))
{
gateway_err("subdev json err");
cJSON_Delete(topo_change);
return -1;
}
pk = cJSON_GetObjectItem(subdev, TOPO_LIST_PK);
dn = cJSON_GetObjectItem(subdev, TOPO_LIST_DN);
if (cJSON_IsString(pk) && cJSON_IsString(dn))
{
memset(&subdev_mate, 0, sizeof(iotx_linkkit_dev_meta_info_t));
HAL_Snprintf(subdev_mate.product_key, PRODUCT_KEY_MAXLEN, "%s", pk->valuestring);
HAL_Snprintf(subdev_mate.device_name, DEVICE_NAME_MAXLEN, "%s", dn->valuestring);
subdev_id = gateway_query_subdev_id(gateway_ctx->master_devid, &subdev_mate);
if (subdev_id > 0)
{
switch (status->valueint)
{
case GW_TOPO_CHANGE_STATUS_ADD:
{
}
break;
case GW_TOPO_CHANGE_STATUS_DELETE:
{
gateway_info("topo change del dn:%s", subdev_mate.device_name);
IOT_Linkkit_Close(subdev_id);
}
break;
case GW_TOPO_CHANGE_STATUS_ENABLE:
{
}
break;
case GW_TOPO_CHANGE_STATUS_DISABLE:
{
}
break;
default:
break;
}
}
}
}
cJSON_Delete(topo_change);
return 0;
}
#endif
static int user_subdev_misc_reply_handler(const int devid, const int event_id, const int code, const char *payload, const int payload_len)
{
gateway_info("Receive subdev misc reply, code:%d, payload:%s", code, payload);
switch (event_id)
{
case ITM_EVENT_TOPO_DELETE_REPLY:
{
gateway_info("ITM_EVENT_TOPO_DELETE_REPLY, devid:%d code:%d, payload:%s", devid, code, payload);
if (200 == code)
{
IOT_Linkkit_Close(devid); //remove subdev from dm(device manager)
}
}
break;
case ITM_EVENT_SUBDEV_RESET_REPLY:
{
gateway_info("ITM_EVENT_SUBDEV_RESET_REPLY, devid:%d code:%d, payload:%s", devid, code, payload);
}
break;
case ITM_EVENT_TOPO_ADD_REPLY:
{
gateway_info("ITM_EVENT_TOPO_ADD_REPLY, devid:%d code:%d, payload:%s", devid, code, payload);
}
break;
case ITM_EVENT_COMBINE_LOGIN_REPLY:
{
gateway_info("ITM_EVENT_COMBINE_LOGIN_REPLY, devid:%d code:%d, payload:%s", devid, code, payload);
}
break;
case ITM_EVENT_COMBINE_LOGOUT_REPLY:
{
gateway_info("ITM_EVENT_COMBINE_LOGOUT_REPLY, devid:%d code:%d, payload:%s", devid, code, payload);
}
break;
default:
break;
}
return 0;
}
static int user_fota_event_handler(int type, const char *version)
{
char *p_fota_buffer = NULL;
gateway_ctx_t *gateway_ctx = gateway_get_ctx();
p_fota_buffer = HAL_Malloc(GATEWAY_OTA_BUFFER_LEN);
if (!p_fota_buffer)
{
gateway_err("no mem");
return -1;
}
if (type == 0)
{
gateway_info("New Firmware Version: %s", version);
memset(p_fota_buffer, 0, GATEWAY_OTA_BUFFER_LEN);
IOT_Linkkit_Query(gateway_ctx->master_devid, ITM_MSG_QUERY_FOTA_DATA, (unsigned char *)p_fota_buffer, GATEWAY_OTA_BUFFER_LEN);
}
if (p_fota_buffer)
HAL_Free(p_fota_buffer);
return 0;
}
static int user_cota_event_handler(int type, const char *config_id, int config_size, const char *get_type,
const char *sign, const char *sign_method, const char *url)
{
char *p_cota_buffer = NULL;
gateway_ctx_t *gateway_ctx = gateway_get_ctx();
p_cota_buffer = HAL_Malloc(GATEWAY_OTA_BUFFER_LEN);
if (!p_cota_buffer)
{
gateway_err("no mem");
return -1;
}
if (type == 0)
{
gateway_info("New Config ID: %s", config_id);
gateway_info("New Config Size: %d", config_size);
gateway_info("New Config Type: %s", get_type);
gateway_info("New Config Sign: %s", sign);
gateway_info("New Config Sign Method: %s", sign_method);
gateway_info("New Config URL: %s", url);
IOT_Linkkit_Query(gateway_ctx->master_devid, ITM_MSG_QUERY_COTA_DATA, (unsigned char *)p_cota_buffer, GATEWAY_OTA_BUFFER_LEN);
}
if (p_cota_buffer)
HAL_Free(p_cota_buffer);
return 0;
}
static int user_offline_reset_handler(void)
{
gateway_info("user callback user_offline_reset_handler called.");
return 0;
}
static int user_dev_bind_event(const int state_code, const char *state_message)
{
gateway_info("state_code: -0x%04x, str_msg= %s", -state_code, state_message == NULL ? "NULL" : state_message);
return 0;
}
#ifdef DM_UNIFIED_SERVICE_POST
static int user_unified_service_post_reply_handler(const int devid, const int id, const int code, const char *payload, const int payload_len)
{
gateway_info("Receive unified service post reply, code:%d, payload:%s", code, payload);
return 0;
}
#endif
void *user_dispatch_yield(void *args)
{
gateway_ctx_t *gateway_ctx = gateway_get_ctx();
while (gateway_ctx->g_user_dispatch_thread_running)
{
IOT_Linkkit_Yield(GATEWAY_YIELD_TIMEOUT_MS);
}
return NULL;
}
static iotx_linkkit_dev_meta_info_t *gateway_main_init(gateway_ctx_t *gateway_ctx)
{
int ret = 0;
int dynamic_register = 0; //0:You have to burn DS for each devices,1:Request DS from cloud by https
int post_event_reply = 1;
iotx_linkkit_dev_meta_info_t *p_master_meta = NULL;
memset(gateway_ctx, 0, sizeof(gateway_ctx_t));
p_master_meta = HAL_Malloc(sizeof(iotx_linkkit_dev_meta_info_t));
if (p_master_meta == NULL)
{
gateway_err("no mem");
return NULL;
}
memset(p_master_meta, 0, sizeof(iotx_linkkit_dev_meta_info_t));
HAL_GetProductKey(p_master_meta->product_key);
HAL_GetDeviceName(p_master_meta->device_name);
HAL_GetDeviceSecret(p_master_meta->device_secret);
HAL_GetProductSecret(p_master_meta->product_secret);
if ((0 == strlen(p_master_meta->product_key)) || (0 == strlen(p_master_meta->device_name)) || (0 == dynamic_register && (0 == strlen(p_master_meta->device_secret))) || (0 == strlen(p_master_meta->product_secret)))
{
while (1)
{
printf("Master meta info is invalid...\r\n");
printf("pk[%s]\r\n", p_master_meta->product_key);
printf("ps[%s]\r\n", p_master_meta->product_secret);
printf("dn[%s]\r\n", p_master_meta->device_name);
printf("ds[%s]\r\n", p_master_meta->device_secret);
HAL_SleepMs(2000);
}
}
/* Register Callback */
IOT_RegisterCallback(ITE_INITIALIZE_COMPLETED, user_initialized);
IOT_RegisterCallback(ITE_CONNECT_SUCC, user_connected_event_handler);
IOT_RegisterCallback(ITE_DISCONNECTED, user_disconnected_event_handler);
IOT_RegisterCallback(ITE_RAWDATA_ARRIVED, user_down_raw_data_arrived_event_handler);
IOT_RegisterCallback(ITE_SERVICE_REQUEST, user_service_request_event_handler);
IOT_RegisterCallback(ITE_PROPERTY_SET, user_property_set_event_handler);
#ifdef ALCS_ENABLED
/*Only for local communication service(ALCS)*/
IOT_RegisterCallback(ITE_PROPERTY_GET, user_property_get_event_handler);
#endif
IOT_RegisterCallback(ITE_REPORT_REPLY, user_report_reply_event_handler);
IOT_RegisterCallback(ITE_TRIGGER_EVENT_REPLY, user_trigger_event_reply_event_handler);
IOT_RegisterCallback(ITE_TIMESTAMP_REPLY, user_timestamp_reply_event_handler);
IOT_RegisterCallback(ITE_PERMIT_JOIN, user_permit_join_event_handler);
IOT_RegisterCallback(ITE_CLOUD_ERROR, user_property_cloud_error_handler);
IOT_RegisterCallback(ITE_EVENT_NOTIFY, user_event_notify_handler);
IOT_RegisterCallback(ITE_TOPOLIST_REPLY, user_topolist_reply_handler);
IOT_RegisterCallback(ITE_SUBDEV_MISC_OPS, user_subdev_misc_reply_handler);
#ifdef GATEWAY_SUPPORT_TOPO_CHANGE
IOT_RegisterCallback(ITE_TOPO_CHANGE, user_gateway_topo_change_handler);
#endif
IOT_RegisterCallback(ITE_FOTA, user_fota_event_handler);
IOT_RegisterCallback(ITE_COTA, user_cota_event_handler);
IOT_RegisterCallback(ITE_STATE_DEV_BIND, user_dev_bind_event);
IOT_RegisterCallback(ITE_OFFLINE_RESET, user_offline_reset_handler);
#ifdef DM_UNIFIED_SERVICE_POST
IOT_RegisterCallback(ITE_UNIFIED_SERVICE_POST, user_unified_service_post_reply_handler);
#endif
IOT_Ioctl(IOTX_IOCTL_SET_DYNAMIC_REGISTER, (void *)&dynamic_register);
/* Choose Whether You Need Post Property/Event Reply */
IOT_Ioctl(IOTX_IOCTL_RECV_EVENT_REPLY, (void *)&post_event_reply);
#ifdef GATEWAY_UT_TESTING
gateway_ut_init();
#endif
return p_master_meta;
}
int gateway_main(void *paras)
{
int res = 0;
uint64_t time_prev_sec = 0, time_now_sec = 0, time_begin_sec = 0;
gateway_ctx_t *gateway_ctx = gateway_get_ctx();
iotx_linkkit_dev_meta_info_t *p_master_meta = NULL;
hal_os_thread_param_t hal_os_thread_param;
p_master_meta = gateway_main_init(gateway_ctx);
if (NULL == p_master_meta)
{
printf("OOPS:gateway_main_init failed");
return -1;
}
/* Create Master Device Resources */
do
{
gateway_ctx->master_devid = IOT_Linkkit_Open(IOTX_LINKKIT_DEV_TYPE_MASTER, p_master_meta);
if (gateway_ctx->master_devid < 0)
{
printf("IOT_Linkkit_Open Failed, retry after 5s...\r\n");
HAL_SleepMs(5000);
}
} while (gateway_ctx->master_devid < 0);
/* Start Connect Aliyun Server */
do
{
res = IOT_Linkkit_Connect(gateway_ctx->master_devid);
if (res < 0)
{
printf("IOT_Linkkit_Connect Failed, retry after 5s...\r\n");
HAL_SleepMs(5000);
}
} while (res < 0);
gateway_ctx->g_user_dispatch_thread_running = 1;
//Attation:please don't remove this thread,because sub dev operations is sync
memset(&hal_os_thread_param, 0, sizeof(hal_os_thread_param_t));
hal_os_thread_param.stack_size = GATEWAY_YIELD_THREAD_STACKSIZE;
hal_os_thread_param.name = GATEWAY_YIELD_THREAD_NAME;
res = HAL_ThreadCreate(&gateway_ctx->g_user_dispatch_thread, user_dispatch_yield, NULL, &hal_os_thread_param, NULL);
if (res < 0)
{
gateway_info("HAL_ThreadCreate Failed\n");
IOT_Linkkit_Close(gateway_ctx->master_devid);
return -1;
}
time_begin_sec = user_update_sec();
while (1)
{
time_now_sec = user_update_sec();
if (time_prev_sec == time_now_sec)
{
continue;
}
#ifdef GATEWAY_UT_TESTING
HAL_SleepMs(GATEWAY_YIELD_TIMEOUT_MS / 2);
if (user_master_dev_available())
{
gateway_ut_msg_process(gateway_ctx->master_devid, GATEWAY_YIELD_TIMEOUT_MS / 2);
gateway_ut_misc_process(time_now_sec);
}
#else
HAL_SleepMs(GATEWAY_YIELD_TIMEOUT_MS);
#endif
time_prev_sec = time_now_sec;
}
//Should never come here
gateway_ctx->g_user_dispatch_thread_running = 0;
if (p_master_meta)
{
HAL_Free(p_master_meta);
}
IOT_DumpMemoryStats(IOT_LOG_DEBUG);
return 0;
}

View file

@ -0,0 +1,33 @@
#ifndef __GATEWAY_MAIN_H__
#define __GATEWAY_MAIN_H__
#include <iotx_log.h>
#define gateway_debug(...) log_debug("gateway", __VA_ARGS__)
#define gateway_info(...) log_info("gateway", __VA_ARGS__)
#define gateway_warn(...) log_warning("gateway", __VA_ARGS__)
#define gateway_err(...) log_err("gateway", __VA_ARGS__)
#define gateway_crit(...) log_crit("gateway", __VA_ARGS__)
#define GATEWAY_YIELD_THREAD_NAME "linkkit_yield"
#define GATEWAY_YIELD_THREAD_STACKSIZE (8 * 1024)
#define GATEWAY_YIELD_TIMEOUT_MS (200)
#define GATEWAY_OTA_BUFFER_LEN (512)
//#define GATEWAY_SUPPORT_TOPO_CHANGE
typedef struct
{
int master_devid;
int cloud_connected;
int master_initialized;
int permit_join;
char permit_join_pk[PRODUCT_KEY_MAXLEN];
void *g_user_dispatch_thread;
int g_user_dispatch_thread_running;
} gateway_ctx_t;
extern int gateway_main(void *paras);
extern gateway_ctx_t *gateway_get_ctx(void);
#endif

View file

@ -0,0 +1,742 @@
/*
* Copyright (C) 2015-2019 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <poll.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "cJSON.h"
#include "iot_import.h"
#include "iot_export_linkkit.h"
#include "iotx_log.h"
#include "gateway_main.h"
#include "gateway_entry.h"
#include "gateway_api.h"
#include "gateway_ut.h"
#ifdef GATEWAY_UT_TESTING
static char is_forbidden_auto_add_subdev = 0;
static int subdev_index = 0;
static aos_queue_t gateway_queue_t;
static char gateway_queue_buf[MAX_QUEUE_SIZE];
static gw_topo_get_reason_e topo_get_reason = GW_TOPO_GET_REASON_MAX;
static int gateway_find_subdev_by_pk_dn(iotx_linkkit_dev_meta_info_t *subdev_meta);
static int aos_queue_new(aos_queue_t *queue, void *buf, unsigned int size, int max_msg)
{
ssize_t ret = 0;
struct queue *q = malloc(sizeof(*q));
ret = pipe(q->fds);
q->buf = buf;
q->size = size;
q->msg_size = max_msg;
queue->hdl = q;
return ret;
}
static int aos_queue_send(aos_queue_t *queue, void *msg, unsigned int size)
{
ssize_t ret = 0;
struct queue *q = queue->hdl;
ret = write(q->fds[1], msg, size);
return ret;
}
static int aos_queue_recv(aos_queue_t *queue, unsigned int ms, void *msg,
unsigned int *size)
{
struct queue *q = queue->hdl;
struct pollfd rfd = {
.fd = q->fds[0],
.events = POLLIN,
};
poll(&rfd, 1, ms);
if (rfd.revents & POLLIN)
{
int len = read(q->fds[0], msg, q->msg_size);
*size = len;
return len < 0 ? -1 : 0;
}
return -1;
}
//For cmds call send msg to linkkit_main
int gateway_ut_send_msg(gateway_msg_t *msg, int len)
{
if (msg && len == QUEUE_MSG_SIZE)
{
gateway_info("send msg type(%d)", msg->msg_type);
return aos_queue_send(&gateway_queue_t, msg, len);
}
gateway_err("param err");
return -1;
}
//This example sub dev mate mainly for CI
iotx_linkkit_dev_meta_info_t subdevArr[GATEWAY_SUBDEV_MAX_NUM] = {
#ifdef REGION_SINGAPORE
{"PK_XXXX",
"PS_XXXX",
"DN_XXXX",
"DS_XXXX"},
{"PK_XXXX",
"PS_XXXX",
"DN_XXXX",
"DS_XXXX"},
#else /* Mainland(Shanghai) for default */
{"PK_XXXX",
"PS_XXXX",
"DN_XXXX",
"DS_XXXX"},
{"PK_XXXX",
"PS_XXXX",
"DN_XXXX",
"DS_XXXX"},
#endif
};
static int gateway_connect_cloud(char *payload, int payload_len)
{
int index = 0;
int subdev_id = 0;
int subdev_total = 0;
int subdev_num = 0;
gateway_msg_t msg;
cJSON *topo_list = NULL, *subdev = NULL;
cJSON *pk = NULL, *dn = NULL;
gateway_ctx_t *p_gateway_ctx = gateway_get_ctx();
iotx_linkkit_dev_meta_info_t *p_subdev_mate = NULL;
iotx_linkkit_dev_meta_info_t *p_subdev_mate_index = NULL;
if (payload == NULL || payload_len < 1)
{
gateway_err("param err");
return -1;
}
/* Parse Request */
topo_list = cJSON_Parse(payload);
if (topo_list == NULL || !cJSON_IsArray(topo_list))
{
gateway_err("topo list json format err");
return -1;
}
subdev_total = cJSON_GetArraySize(topo_list);
if (subdev_total < 1)
{
gateway_err("topo is empty");
return -1;
}
p_subdev_mate = HAL_Malloc(sizeof(iotx_linkkit_dev_meta_info_t) * subdev_total);
if (p_subdev_mate == NULL)
{
gateway_err("no mem");
return -1;
}
memset(p_subdev_mate, 0, sizeof(iotx_linkkit_dev_meta_info_t) * subdev_total);
for (index = 0; index < subdev_total; index++)
{
subdev = cJSON_GetArrayItem(topo_list, index);
if (subdev == NULL || !cJSON_IsObject(subdev))
{
gateway_err("subdev json err");
continue;
}
pk = cJSON_GetObjectItem(subdev, TOPO_LIST_PK);
dn = cJSON_GetObjectItem(subdev, TOPO_LIST_DN);
if (cJSON_IsString(pk) && cJSON_IsString(dn))
{
p_subdev_mate_index = p_subdev_mate + subdev_num;
subdev_num++;
HAL_Snprintf(p_subdev_mate_index->product_key, PRODUCT_KEY_MAXLEN, "%s", pk->valuestring);
HAL_Snprintf(p_subdev_mate_index->device_name, DEVICE_NAME_MAXLEN, "%s", dn->valuestring);
}
}
cJSON_Delete(topo_list);
gateway_add_multi_subdev(p_gateway_ctx->master_devid, p_subdev_mate, subdev_num);
if (p_subdev_mate)
HAL_Free(p_subdev_mate);
return 0;
}
gw_device_type_e gateway_get_device_type(void)
{
int ret = 0;
char dev_type[GATEWAY_DEVICE_TYPE_LEN] = {0};
int len = GATEWAY_DEVICE_TYPE_LEN - 1;
ret = HAL_Kv_Get(GATEWAY_DEVICE_TYPE_KEY, dev_type, &len);
if (ret == 0)
{
if (!strcmp(dev_type, GATEWAY_DEVICE_TYPE_MASTER))
{
return GW_DEVICE_MASTER;
}
else if (!strcmp(dev_type, GATEWAY_DEVICE_TYPE_SLAVE))
{
return GW_DEVICE_SLAVE;
}
}
return GW_DEVICE_INVALID;
}
static int gateway_get_forbidden_auto_add_subdev_flag(void)
{
int ret = 0;
char forbidden_flag[GATEWAY_FORBIDDEN_AUTO_ADD_SUBDEV_FLAG_LEN] = {0};
int len = GATEWAY_FORBIDDEN_AUTO_ADD_SUBDEV_FLAG_LEN - 1;
ret = HAL_Kv_Get(GATEWAY_FORBIDDEN_AUTO_ADD_SUBDEV_FLAG_KEY, forbidden_flag, &len);
if (ret == 0)
{
if ((!strcmp(forbidden_flag, "Y")) || (!strcmp(forbidden_flag, "y")))
{
return 1;
}
}
return 0;
}
//Just for reference
static void user_post_property(void)
{
int res = 0;
gateway_ctx_t *gateway_ctx = gateway_get_ctx();
char *property_payload = "{\"LightSwitch\":1}";
res = IOT_Linkkit_Report(gateway_ctx->master_devid, ITM_MSG_POST_PROPERTY,
(unsigned char *)property_payload, strlen(property_payload));
gateway_info("Post Property Message ID: %d", res);
}
//Just for reference
static void user_post_sub_property(int subdev_id)
{
int res = 0;
gateway_ctx_t *gateway_ctx = gateway_get_ctx();
char *property_payload = "{\"LightSwitch\":1}";
res = IOT_Linkkit_Report(subdev_id, ITM_MSG_POST_PROPERTY,
(unsigned char *)property_payload, strlen(property_payload));
gateway_info("Post Property Message ID: %d", res);
}
//Just for reference
static void user_post_event(void)
{
int res = 0;
gateway_ctx_t *gateway_ctx = gateway_get_ctx();
char *event_id = "Error";
char *event_payload = "{\"ErrorCode\":0}";
res = IOT_Linkkit_TriggerEvent(gateway_ctx->master_devid, event_id, strlen(event_id),
event_payload, strlen(event_payload));
gateway_info("Post Event Message ID: %d", res);
}
//Just for reference
static void user_deviceinfo_update(void)
{
int res = 0;
gateway_ctx_t *gateway_ctx = gateway_get_ctx();
char *device_info_update = "[{\"attrKey\":\"gateway\",\"attrValue\":\"I am a gateway\"},{\"attrKey\":\"subdev\",\"attrValue\":\"I am a subdev\"}]";
res = IOT_Linkkit_Report(gateway_ctx->master_devid, ITM_MSG_DEVICEINFO_UPDATE,
(unsigned char *)device_info_update, strlen(device_info_update));
gateway_info("Device Info Update Message ID: %d", res);
}
//Just for reference
static void user_deviceinfo_delete(void)
{
int res = 0;
gateway_ctx_t *gateway_ctx = gateway_get_ctx();
char *device_info_delete = "[{\"attrKey\":\"subdev\"}]";
res = IOT_Linkkit_Report(gateway_ctx->master_devid, ITM_MSG_DEVICEINFO_DELETE,
(unsigned char *)device_info_delete, strlen(device_info_delete));
gateway_info("Device Info Delete Message ID: %d", res);
}
//Just for reference
static void user_post_raw_data(void)
{
int res = 0;
gateway_ctx_t *gateway_ctx = gateway_get_ctx();
//raw_data is ASCII of [This is raw data.]
unsigned char raw_data[] = {0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x72, 0x61, 0x77, 0x20, 0x64, 0x61, 0x74, 0x61, 0x2E};
res = IOT_Linkkit_Report(gateway_ctx->master_devid, ITM_MSG_POST_RAW_DATA,
raw_data, sizeof(raw_data));
gateway_info("Post Raw Data Message ID: %d", res);
}
int gateway_ut_handle_topolist_reply(const char *payload, const int payload_len)
{
gateway_msg_t msg;
if (topo_get_reason != GW_TOPO_GET_REASON_CONNECT_CLOUD)
{
return 0;
}
memset(&msg, 0, sizeof(gateway_msg_t));
msg.payload = HAL_Malloc(payload_len + 1);
if (msg.payload)
{
memset(msg.payload, '\0', payload_len + 1);
memcpy(msg.payload, payload, payload_len);
msg.msg_type = GATEWAY_MSG_TYPE_CLOUD_CONNECT;
msg.devid = 1;
msg.payload_len = payload_len;
gateway_ut_send_msg(&msg, sizeof(gateway_msg_t));
}
return 0;
}
int gateway_ut_handle_permit_join(void)
{
gateway_msg_t msg;
msg.msg_type = GATEWAY_MSG_TYPE_PERMIT_JOIN;
msg.devid = 1;
gateway_ut_send_msg(&msg, sizeof(gateway_msg_t));
return 0;
}
//get a sub dev mate info from KV,just for testing
static int get_one_device_mate(int devid, iotx_linkkit_dev_meta_info_t *p_subdev)
{
int len = 0;
char key_buf[MAX_KEY_LEN];
if (!p_subdev)
return -1;
len = PRODUCT_KEY_MAXLEN;
memset(key_buf, 0, MAX_KEY_LEN);
memset(p_subdev->product_key, 0, PRODUCT_KEY_MAXLEN);
HAL_Snprintf(key_buf, MAX_KEY_LEN, "%s_%d", KV_KEY_PK, devid);
HAL_Kv_Get(key_buf, p_subdev->product_key, &len);
len = PRODUCT_SECRET_MAXLEN;
memset(key_buf, 0, MAX_KEY_LEN);
memset(p_subdev->product_secret, 0, PRODUCT_SECRET_MAXLEN);
HAL_Snprintf(key_buf, MAX_KEY_LEN, "%s_%d", KV_KEY_PS, devid);
HAL_Kv_Get(key_buf, p_subdev->product_secret, &len);
len = DEVICE_NAME_MAXLEN;
memset(key_buf, 0, MAX_KEY_LEN);
memset(p_subdev->device_name, 0, DEVICE_NAME_MAXLEN);
HAL_Snprintf(key_buf, MAX_KEY_LEN, "%s_%d", KV_KEY_DN, devid);
HAL_Kv_Get(key_buf, p_subdev->device_name, &len);
len = DEVICE_SECRET_MAXLEN;
memset(key_buf, 0, MAX_KEY_LEN);
memset(p_subdev->device_secret, 0, DEVICE_SECRET_MAXLEN);
HAL_Snprintf(key_buf, MAX_KEY_LEN, "%s_%d", KV_KEY_DS, devid);
HAL_Kv_Get(key_buf, p_subdev->device_secret, &len);
gateway_info("DevNum(%d) DN:%s", devid, p_subdev->device_name);
return 0;
}
//Find sub device mate info from KV,just for testing
static int gateway_find_subdev_by_pk_dn(iotx_linkkit_dev_meta_info_t *subdev_meta)
{
int index = 0;
iotx_linkkit_dev_meta_info_t subdev;
if (!subdev_meta)
return -1;
for (index = 1; index < MAX_DEVICES_META_NUM; index++)
{
get_one_device_mate(index, &subdev);
if (!strcmp(subdev_meta->product_key, subdev.product_key) && !strcmp(subdev_meta->device_name, subdev.device_name))
{
return index;
}
}
return -1;
}
//get multi sub devices mate info from KV,just for testing
static int get_all_subdev_mate(iotx_linkkit_dev_meta_info_t *subdev_meta)
{
int index = 0;
iotx_linkkit_dev_meta_info_t *p_subdev = NULL;
if (!subdev_meta)
return -1;
for (index = 1; index < MAX_DEVICES_META_NUM; index++)
{
p_subdev = subdev_meta + (index - 1);
get_one_device_mate(index, p_subdev);
}
return 0;
}
//get multi sub devices mate info from KV,just for testing
static int get_range_subdev_mate(iotx_linkkit_dev_meta_info_t *subdev_meta, int devid_start, int devid_end)
{
int index = 0;
iotx_linkkit_dev_meta_info_t *p_subdev = NULL;
if (!subdev_meta)
return -1;
if (devid_start > 0 && devid_start < MAX_DEVICES_META_NUM &&
devid_end > 0 && devid_end < MAX_DEVICES_META_NUM &&
devid_start < devid_end)
{
for (index = devid_start; index <= devid_end; index++)
{
p_subdev = subdev_meta + (index - 1);
get_one_device_mate(index, p_subdev);
}
}
else
{
gateway_warn("devid err");
}
return 0;
}
//This is an example for get topolist info
//you can get topo list info in func:user_topolist_reply_handler
int gateway_ut_update_subdev(gw_topo_get_reason_e reason)
{
gateway_ctx_t *gateway_ctx = gateway_get_ctx();
gateway_info("do update subdev");
IOT_Linkkit_Query(gateway_ctx->master_devid, ITM_MSG_QUERY_TOPOLIST, NULL, 0);
topo_get_reason = reason;
return 0;
}
int gateway_ut_msg_process(int master_devid, int timeout)
{
int ret = 0;
unsigned int recv_size = 0;
int subdev_id = -1;
gateway_msg_t msg;
gateway_ctx_t *gateway_ctx = gateway_get_ctx();
ret = aos_queue_recv(&gateway_queue_t, timeout, &msg, &recv_size);
if (ret == 0 && recv_size == QUEUE_MSG_SIZE)
{
gateway_info("msg.type:%d, devid:%d", msg.msg_type, msg.devid);
if (msg.devid < 1 || msg.devid > MAX_DEVICES_META_NUM - 1)
{
gateway_warn("sub dev id(%d) err", msg.devid);
return -1;
}
switch (msg.msg_type)
{
case GATEWAY_MSG_TYPE_ADD:
{
iotx_linkkit_dev_meta_info_t subdev_mate;
memset(&subdev_mate, 0, sizeof(subdev_mate));
get_one_device_mate(msg.devid, &subdev_mate);
if (gateway_ctx->permit_join == 1 && strlen(gateway_ctx->permit_join_pk) > 0)
{
if (strcmp(subdev_mate.product_key, gateway_ctx->permit_join_pk))
{
gateway_warn("permit join pk:%s is not found", gateway_ctx->permit_join_pk);
ret = -1;
break;
}
}
ret = gateway_add_subdev(&subdev_mate);
}
break;
case GATEWAY_MSG_TYPE_ADDALL:
{
iotx_linkkit_dev_meta_info_t *p_meta_info = NULL;
p_meta_info = HAL_Malloc(sizeof(iotx_linkkit_dev_meta_info_t) * (MAX_DEVICES_META_NUM - 1));
if (!p_meta_info)
{
gateway_err("no mem");
return -1;
}
memset(p_meta_info, '\0', sizeof(iotx_linkkit_dev_meta_info_t) * (MAX_DEVICES_META_NUM - 1));
get_all_subdev_mate(p_meta_info);
ret = gateway_add_multi_subdev(master_devid, p_meta_info, MAX_DEVICES_META_NUM - 1);
HAL_Free(p_meta_info);
}
break;
case GATEWAY_MSG_TYPE_ADD_RANGE:
{
iotx_linkkit_dev_meta_info_t *p_meta_info = NULL;
int subdev_num = msg.devid_end - msg.devid + 1;
if (msg.devid < 1 || msg.devid >= MAX_DEVICES_META_NUM ||
msg.devid_end < 1 || msg.devid_end >= MAX_DEVICES_META_NUM ||
msg.devid >= msg.devid_end)
{
gateway_warn("sub dev id err");
return -1;
}
p_meta_info = HAL_Malloc(sizeof(iotx_linkkit_dev_meta_info_t) * subdev_num);
if (!p_meta_info)
{
gateway_err("no mem");
return -1;
}
memset(p_meta_info, '\0', sizeof(iotx_linkkit_dev_meta_info_t) * subdev_num);
get_range_subdev_mate(p_meta_info, msg.devid, msg.devid_end);
ret = gateway_add_multi_subdev(master_devid, p_meta_info, subdev_num);
HAL_Free(p_meta_info);
}
break;
case GATEWAY_MSG_TYPE_DELALL:
{
iotx_linkkit_dev_meta_info_t subdev_mate;
for (subdev_id = 1; subdev_id < MAX_DEVICES_META_NUM; subdev_id++)
{
memset(&subdev_mate, 0, sizeof(subdev_mate));
get_one_device_mate(subdev_id, &subdev_mate);
ret = gateway_del_subdev(&subdev_mate);
gateway_info("del subdev id(%d) ret = %d", subdev_id, ret);
}
}
break;
case GATEWAY_MSG_TYPE_DEL:
{
iotx_linkkit_dev_meta_info_t subdev_mate;
memset(&subdev_mate, 0, sizeof(subdev_mate));
get_one_device_mate(msg.devid, &subdev_mate);
ret = gateway_del_subdev(&subdev_mate);
}
break;
case GATEWAY_MSG_TYPE_DEL_RANGE:
{
iotx_linkkit_dev_meta_info_t subdev_mate;
if (msg.devid < 1 || msg.devid >= MAX_DEVICES_META_NUM ||
msg.devid_end < 1 || msg.devid_end >= MAX_DEVICES_META_NUM ||
msg.devid >= msg.devid_end)
{
gateway_warn("sub dev id err");
return -1;
}
for (subdev_id = msg.devid; subdev_id <= msg.devid_end; subdev_id++)
{
memset(&subdev_mate, 0, sizeof(subdev_mate));
get_one_device_mate(subdev_id, &subdev_mate);
ret = gateway_del_subdev(&subdev_mate);
gateway_info("del subdev id(%d) ret = %d", subdev_id, ret);
}
}
break;
case GATEWAY_MSG_TYPE_UPDATE:
{
ret = gateway_ut_update_subdev(GW_TOPO_GET_REASON_CLI_CMD);
}
break;
case GATEWAY_MSG_TYPE_RESET:
{
iotx_linkkit_dev_meta_info_t subdev_mate;
memset(&subdev_mate, 0, sizeof(subdev_mate));
get_one_device_mate(msg.devid, &subdev_mate);
ret = gateway_reset_subdev(&subdev_mate);
}
break;
case GATEWAY_MSG_TYPE_QUERY_SUBDEV_ID:
{
iotx_linkkit_dev_meta_info_t subdev_mate;
memset(&subdev_mate, 0, sizeof(subdev_mate));
get_one_device_mate(msg.devid, &subdev_mate);
ret = gateway_query_subdev_id(gateway_ctx->master_devid, &subdev_mate);
}
break;
case GATEWAY_MSG_TYPE_CLOUD_CONNECT:
{
if (msg.payload)
{
gateway_connect_cloud(msg.payload, msg.payload_len);
HAL_Free(msg.payload);
}
}
break;
case GATEWAY_MSG_TYPE_PERMIT_JOIN:
{
if (gateway_ctx->permit_join == 1)
{
int matched_subdev_num = 0;
iotx_linkkit_dev_meta_info_t subdev_mate = {0};
iotx_linkkit_dev_meta_info_t *p_subdev_mate = NULL;
p_subdev_mate = HAL_Malloc(sizeof(iotx_linkkit_dev_meta_info_t) * MAX_DEVICES_META_NUM);
if (p_subdev_mate == NULL)
{
gateway_err("no mem");
return -1;
}
memset(p_subdev_mate, 0, sizeof(iotx_linkkit_dev_meta_info_t) * MAX_DEVICES_META_NUM);
for (subdev_id = 1; subdev_id < MAX_DEVICES_META_NUM; subdev_id++)
{
memset(&subdev_mate, 0, sizeof(subdev_mate));
if (0 == get_one_device_mate(subdev_id, &subdev_mate) && 0 == strcmp(gateway_ctx->permit_join_pk, subdev_mate.product_key))
{
memcpy(p_subdev_mate + matched_subdev_num, &subdev_mate, sizeof(iotx_linkkit_dev_meta_info_t));
matched_subdev_num++;
}
else
{
gateway_warn("permit join pk:%s found pk:%s dn:%s", gateway_ctx->permit_join_pk, subdev_mate.product_key, subdev_mate.device_name);
}
}
gateway_add_multi_subdev(gateway_ctx->master_devid, p_subdev_mate, matched_subdev_num);
if (p_subdev_mate)
{
HAL_Free(p_subdev_mate);
}
}
}
break;
default:
gateway_warn("unKnow msg type(%d)", msg.msg_type);
return -1;
}
}
return ret;
}
void gateway_ut_misc_process(uint64_t time_now_sec)
{
/* Add subdev for CI*/
if (is_forbidden_auto_add_subdev == 0 && (subdev_index < GATEWAY_SUBDEV_MAX_NUM))
{
/* Add next subdev */
if (gateway_add_subdev(&subdevArr[subdev_index]) == SUCCESS_RETURN)
{
gateway_info("subdev DN:%s add succeed", subdevArr[subdev_index].device_name);
}
else
{
gateway_info("subdev DN:%s add failed", subdevArr[subdev_index].device_name);
}
subdev_index++;
}
/* Post Proprety Example */
if (time_now_sec % 11 == 0)
{
user_post_property();
user_post_sub_property(subdev_index);
}
/* Post Event Example */
if (time_now_sec % 17 == 0)
{
user_post_event();
}
/* Device Info Update Example */
if (time_now_sec % 23 == 0)
{
user_deviceinfo_update();
}
/* Device Info Delete Example */
if (time_now_sec % 29 == 0)
{
user_deviceinfo_delete();
}
/* Post Raw Example */
if (time_now_sec % 37 == 0)
{
user_post_raw_data();
}
}
int gateway_ut_init(void)
{
int ret = SUCCESS_RETURN;
ret = aos_queue_new(&gateway_queue_t, gateway_queue_buf, sizeof(gateway_queue_buf), QUEUE_MSG_SIZE);
if (FAIL_RETURN == ret)
{
gateway_info("aos_queue_new failed");
return ret;
}
if (gateway_get_forbidden_auto_add_subdev_flag())
{
gateway_info("gw forbiden auto add subdev");
is_forbidden_auto_add_subdev = 1;
}
return ret;
}
#endif

View file

@ -0,0 +1,115 @@
#ifndef __GATEWAY_UT_H__
#define __GATEWAY_UT_H__
// for demo only
#define KV_KEY_PK "pk"
#define KV_KEY_PS "ps"
#define KV_KEY_DN "dn"
#define KV_KEY_DS "ds"
#define MAX_KEY_LEN (6)
#define MAX_DEVICES_META_NUM (11) //support 10 sub devices
#define AOS_WAIT_FOREVER 0xffffffffu
#define AOS_NO_WAIT 0x0
#define PRODUCT_KEY "PK_XXXXX"
#define PRODUCT_SECRET "PS_XXXXX"
#define DEVICE_NAME "DN_XXXXX"
#define DEVICE_SECRET "DS_XXXXX"
#define TOPO_LIST_PK "productKey"
#define TOPO_LIST_DN "deviceName"
#define TOPO_CHANGE_STATUS "status"
#define TOPO_CHANGE_SUBLIST "subList"
#define GATEWAY_SUBDEV_MAX_NUM (2)
#define QUEUE_MSG_SIZE sizeof(gateway_msg_t)
#define MAX_QUEUE_SIZE 10 * QUEUE_MSG_SIZE
//You should undefine this Macro in your products
//#define GATEWAY_UT_TESTING
//KV config gw type,VALUE:master mean it is gateway,slave is subdev
#define GATEWAY_DEVICE_TYPE_KEY "gwtype"
#define GATEWAY_DEVICE_TYPE_MASTER "master"
#define GATEWAY_DEVICE_TYPE_SLAVE "slave"
#define GATEWAY_DEVICE_TYPE_LEN (7)
#define GATEWAY_FORBIDDEN_AUTO_ADD_SUBDEV_FLAG_KEY "gwf"
#define GATEWAY_FORBIDDEN_AUTO_ADD_SUBDEV_FLAG_LEN 2
typedef struct
{
void *hdl;
} aos_hdl_t;
typedef aos_hdl_t aos_queue_t;
struct queue
{
int fds[2];
void *buf;
int size;
int msg_size;
};
typedef enum _gw_topo_change_status_e
{
GW_TOPO_CHANGE_STATUS_ADD = 0,
GW_TOPO_CHANGE_STATUS_DELETE = 1,
GW_TOPO_CHANGE_STATUS_ENABLE = 2,
GW_TOPO_CHANGE_STATUS_DISABLE = 8,
GW_TOPO_CHANGE_STATUS_INVALID
} gw_topo_change_status_e;
typedef enum _gw_device_type_e
{
GW_DEVICE_MASTER = 0,
GW_DEVICE_SLAVE,
GW_DEVICE_INVALID
} gw_device_type_e;
typedef enum _gw_topo_get_reason_e
{
GW_TOPO_GET_REASON_CONNECT_CLOUD = 0,
GW_TOPO_GET_REASON_CLI_CMD,
GW_TOPO_GET_REASON_MAX
} gw_topo_get_reason_e;
typedef enum _gateway_msg_type_e
{
GATEWAY_MSG_TYPE_ADD,
GATEWAY_MSG_TYPE_ADD_RANGE,
GATEWAY_MSG_TYPE_DEL,
GATEWAY_MSG_TYPE_DEL_RANGE,
GATEWAY_MSG_TYPE_RESET,
GATEWAY_MSG_TYPE_UPDATE,
GATEWAY_MSG_TYPE_ADDALL,
GATEWAY_MSG_TYPE_DELALL,
GATEWAY_MSG_TYPE_QUERY_SUBDEV_ID,
GATEWAY_MSG_TYPE_CLOUD_CONNECT,
GATEWAY_MSG_TYPE_PERMIT_JOIN,
GATEWAY_MSG_TYPE_MAX
} gateway_msg_type_e;
typedef struct _gateway_msg_s
{
gateway_msg_type_e msg_type;
int devid;
int devid_end;
char *payload;
int payload_len;
} gateway_msg_t;
extern int gateway_ut_init(void);
extern int gateway_ut_handle_permit_join(void);
extern int gateway_ut_handle_topolist_reply(const char *payload, const int payload_len);
extern int gateway_ut_send_msg(gateway_msg_t *, int);
extern int gateway_ut_msg_process(int master_devid, int timeout);
extern void gateway_ut_misc_process(uint64_t time_now_sec);
extern int gateway_ut_update_subdev(gw_topo_get_reason_e reason);
#endif

View file

@ -0,0 +1,84 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "iot_export.h"
#include "app_entry.h"
#include "living_platform_main.h"
#include "living_platform_ut.h"
static void load_living_platform_meta_info(void)
{
int len = 0;
char key_buf[MAX_KEY_LEN];
char product_key[PRODUCT_KEY_LEN + 1] = {0};
char product_secret[PRODUCT_SECRET_LEN + 1] = {0};
char device_name[DEVICE_NAME_LEN + 1] = {0};
char device_secret[DEVICE_SECRET_LEN + 1] = {0};
len = PRODUCT_KEY_LEN + 1;
memset(key_buf, 0, MAX_KEY_LEN);
memset(product_key, 0, sizeof(product_key));
HAL_Snprintf(key_buf, MAX_KEY_LEN, "%s_%d", KV_KEY_PK, 0);
HAL_Kv_Get(key_buf, product_key, &len);
len = PRODUCT_SECRET_LEN + 1;
memset(key_buf, 0, MAX_KEY_LEN);
memset(product_secret, 0, sizeof(product_secret));
HAL_Snprintf(key_buf, MAX_KEY_LEN, "%s_%d", KV_KEY_PS, 0);
HAL_Kv_Get(key_buf, product_secret, &len);
len = DEVICE_NAME_LEN + 1;
memset(key_buf, 0, MAX_KEY_LEN);
memset(device_name, 0, sizeof(device_name));
HAL_Snprintf(key_buf, MAX_KEY_LEN, "%s_%d", KV_KEY_DN, 0);
HAL_Kv_Get(key_buf, device_name, &len);
len = DEVICE_SECRET_LEN + 1;
memset(key_buf, 0, MAX_KEY_LEN);
memset(device_secret, 0, sizeof(device_secret));
HAL_Snprintf(key_buf, MAX_KEY_LEN, "%s_%d", KV_KEY_DS, 0);
HAL_Kv_Get(key_buf, device_secret, &len);
if ((strlen(product_key) > 0) && (strlen(product_secret) > 0) && (strlen(device_name) > 0))
{
HAL_SetProductKey(product_key);
HAL_SetProductSecret(product_secret);
HAL_SetDeviceName(device_name);
HAL_SetDeviceSecret(device_secret);
printf("pk[%s]\r\n", product_key);
printf("dn[%s]\r\n", device_name);
}
else
{
HAL_SetProductKey(PRODUCT_KEY);
HAL_SetProductSecret(PRODUCT_SECRET);
HAL_SetDeviceName(DEVICE_NAME);
HAL_SetDeviceSecret(DEVICE_SECRET);
printf("pk[%s]\r\n", PRODUCT_KEY);
printf("dn[%s]\r\n", DEVICE_NAME);
}
}
int main(int argc, char **argv)
{
living_platform_main_params_t paras;
paras.argc = argc;
paras.argv = argv;
#ifdef LOG_LEVEL_DEBUG
IOT_SetLogLevel(IOT_LOG_DEBUG);
#else
IOT_SetLogLevel(IOT_LOG_INFO);
#endif
load_living_platform_meta_info();
living_platform_main((void *)&paras);
return 0;
}

Some files were not shown because too many files have changed in this diff Show more