mirror of
https://github.com/Ai-Thinker-Open/Ai-Thinker-Open_RTL8710BX_ALIOS_SDK.git
synced 2025-07-31 19:31:05 +00:00
rel_1.6.0 init
This commit is contained in:
commit
27b3e2883d
19359 changed files with 8093121 additions and 0 deletions
606
Living_SDK/framework/protocol/linkkit/hal/HAL_AWSS_rhino.c
Normal file
606
Living_SDK/framework/protocol/linkkit/hal/HAL_AWSS_rhino.c
Normal 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 推荐时长是200毫秒到400毫秒
|
||||
*/
|
||||
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:
|
||||
* 1)ssid和passwd都是以'\0'结尾的字符串,如果passwd字符串的
|
||||
* 长度为0,表示该热点采用Open模式(不加密);
|
||||
* 2)beacon_interval表示热点的Beacon广播间隔(或周期),单
|
||||
* 位为毫秒,一般会采用默认100ms;
|
||||
* 3)hide表示创建的热点是否是隐藏热点,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)如果当前设备已经开启热点,关闭当前热点,如果当前设备正
|
||||
* 在开热点,取消开热点的操作;
|
||||
* 2)如果当前设备不是以Station模式(包括Station+SoftAP模式和
|
||||
* SoftAP模式)工作,设备必须切换到Station模式;
|
||||
* 3)Wi-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
|
||||
218
Living_SDK/framework/protocol/linkkit/hal/HAL_Crypt_rhino.c
Normal file
218
Living_SDK/framework/protocol/linkkit/hal/HAL_Crypt_rhino.c
Normal 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
|
||||
560
Living_SDK/framework/protocol/linkkit/hal/HAL_DTLS_mbedtls.c
Executable file
560
Living_SDK/framework/protocol/linkkit/hal/HAL_DTLS_mbedtls.c
Executable 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
|
||||
35
Living_SDK/framework/protocol/linkkit/hal/HAL_FS_rhino.c
Normal file
35
Living_SDK/framework/protocol/linkkit/hal/HAL_FS_rhino.c
Normal 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;
|
||||
}
|
||||
564
Living_SDK/framework/protocol/linkkit/hal/HAL_OS_rhino.c
Executable file
564
Living_SDK/framework/protocol/linkkit/hal/HAL_OS_rhino.c
Executable 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);
|
||||
}
|
||||
200
Living_SDK/framework/protocol/linkkit/hal/HAL_PRODUCT_rhino.c
Executable file
200
Living_SDK/framework/protocol/linkkit/hal/HAL_PRODUCT_rhino.c
Executable 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);
|
||||
}
|
||||
273
Living_SDK/framework/protocol/linkkit/hal/HAL_TCP_rhino.c
Normal file
273
Living_SDK/framework/protocol/linkkit/hal/HAL_TCP_rhino.c
Normal 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
|
||||
434
Living_SDK/framework/protocol/linkkit/hal/HAL_TLS_itls.c
Executable file
434
Living_SDK/framework/protocol/linkkit/hal/HAL_TLS_itls.c
Executable 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);;
|
||||
}
|
||||
|
||||
936
Living_SDK/framework/protocol/linkkit/hal/HAL_TLS_mbedtls.c
Executable file
936
Living_SDK/framework/protocol/linkkit/hal/HAL_TLS_mbedtls.c
Executable 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;
|
||||
}
|
||||
378
Living_SDK/framework/protocol/linkkit/hal/HAL_UDP_rhino.c
Normal file
378
Living_SDK/framework/protocol/linkkit/hal/HAL_UDP_rhino.c
Normal 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);
|
||||
}
|
||||
34
Living_SDK/framework/protocol/linkkit/hal/hal.mk
Executable file
34
Living_SDK/framework/protocol/linkkit/hal/hal.mk
Executable 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
|
||||
58
Living_SDK/framework/protocol/linkkit/hal/ucube.py
Executable file
58
Living_SDK/framework/protocol/linkkit/hal/ucube.py
Executable 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)
|
||||
|
||||
41
Living_SDK/framework/protocol/linkkit/sdk/iotx-sdk-c_clone/.gitignore
vendored
Normal file
41
Living_SDK/framework/protocol/linkkit/sdk/iotx-sdk-c_clone/.gitignore
vendored
Normal 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
|
||||
|
|
@ -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)
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
mainmenu "Main Menu"
|
||||
comment "Configure Link Kit SDK for IoT Embedded Devices"
|
||||
|
||||
config SRCPATH
|
||||
string
|
||||
default "."
|
||||
|
||||
source "Config.linkkit"
|
||||
|
|
@ -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"
|
||||
|
|
@ -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.
|
||||
|
|
@ -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)进行了解
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
|
@ -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)))) \
|
||||
)
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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*; \
|
||||
)
|
||||
|
||||
|
|
@ -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`
|
||||
|
|
@ -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`等同
|
||||
|
|
@ -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: 运行指定的测试集程序, 统计显示测试例的通过率和源代码的覆盖率**
|
||||
|
||||

|
||||
|
||||
- **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...
|
||||
|
||||

|
||||
|
||||
- **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`
|
||||
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
|
|
@ -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 可获得编译系统线上最新和最全的帮助文档
|
||||
|
|
@ -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)))
|
||||
|
|
@ -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
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -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
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
CONFIG_ENV_CFLAGS += -Wall
|
||||
CONFIG_ENV_CFLAGS += --coverage
|
||||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -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__ */
|
||||
|
||||
|
|
@ -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
|
||||
197
Living_SDK/framework/protocol/linkkit/sdk/iotx-sdk-c_clone/build-rules/rules.mk
Executable file
197
Living_SDK/framework/protocol/linkkit/sdk/iotx-sdk-c_clone/build-rules/rules.mk
Executable 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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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 ""
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
LIBA_TARGET := libiot_tick_notify.a
|
||||
|
||||
HDR_REFS += src/protocol/alcs
|
||||
|
|
@ -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(¬ify_sa, 0, sizeof(notify_sa));
|
||||
memcpy(notify_sa.addr, TICK_NOTIFY_ADDR, strlen(TICK_NOTIFY_ADDR));
|
||||
notify_sa.port = TICK_NOTIFY_PORT;
|
||||
}else{
|
||||
memcpy(¬ify_sa, remote, sizeof(NetworkAddr));
|
||||
}
|
||||
|
||||
CoAPServerMultiCast_send(coap_ctx, ¬ify_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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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}
|
||||
)
|
||||
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -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 */
|
||||
|
||||
|
||||
|
|
@ -0,0 +1 @@
|
|||
LIBA_TARGET := libiot_timer_service.a
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -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__ */
|
||||
|
|
@ -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
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load diff
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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 *)¶s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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 *)®ister_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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
工具名称:log_extract.sh
|
||||
工具功能:从一个或者多个日志文件中提取感兴趣的日志信息
|
||||
使用方式:
|
||||
1. 运行环境:Linux运行环境
|
||||
2. Linux环境下运行log_extract.sh脚本,要求用户输入三个参数:
|
||||
- 日志文件夹名称,例如:logfiles
|
||||
- 需要提取的关键信息,例如:disconnect
|
||||
- 关键字前后的行数,例如:10
|
||||
3. 脚本执行之后会自动生成一个类似这样的文件:logfiles-20200304_183318.log,如果抓取的日志文件比较多的时候使用这个工具可以提高分析效率
|
||||
|
|
@ -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
|
||||
Binary file not shown.
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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 *)¶s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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 *)¶s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue