1107 lines
34 KiB
C
1107 lines
34 KiB
C
|
#include "btstack/bluetooth.h"
|
|||
|
#include "system/includes.h"
|
|||
|
#include "bt_common.h"
|
|||
|
#include "sha256.h"
|
|||
|
#include "api/sig_mesh_api.h"
|
|||
|
#include "model_api.h"
|
|||
|
#include "unix_timestamp.h"
|
|||
|
|
|||
|
#define LOG_TAG "[Mesh-AliSocket]"
|
|||
|
#define LOG_ERROR_ENABLE
|
|||
|
#define LOG_DEBUG_ENABLE
|
|||
|
#define LOG_INFO_ENABLE
|
|||
|
/* #define LOG_DUMP_ENABLE */
|
|||
|
#define LOG_CLI_ENABLE
|
|||
|
#include "debug.h"
|
|||
|
|
|||
|
#if (CONFIG_MESH_MODEL == SIG_MESH_ALIGENIE_SOCKET)
|
|||
|
/*
|
|||
|
* @brief Config current node features(Relay/Proxy/Friend/Low Power)
|
|||
|
*/
|
|||
|
/*-----------------------------------------------------------*/
|
|||
|
#define BT_MESH_FEAT_SUPPORTED_TEMP ( \
|
|||
|
BT_MESH_FEAT_RELAY | \
|
|||
|
BT_MESH_FEAT_PROXY | \
|
|||
|
0 \
|
|||
|
)
|
|||
|
#include "feature_correct.h"
|
|||
|
const int config_bt_mesh_features = BT_MESH_FEAT_SUPPORTED;
|
|||
|
|
|||
|
/*
|
|||
|
* @brief Config proxy connectable adv hardware param
|
|||
|
*/
|
|||
|
/*-----------------------------------------------------------*/
|
|||
|
#if BT_MESH_FEATURES_GET(BT_MESH_FEAT_LOW_POWER)
|
|||
|
const u16 config_bt_mesh_proxy_node_adv_interval = ADV_SCAN_UNIT(3000); // unit: ms
|
|||
|
#else
|
|||
|
const u16 config_bt_mesh_proxy_node_adv_interval = ADV_SCAN_UNIT(300); // unit: ms
|
|||
|
#endif /* BT_MESH_FEATURES_GET(BT_MESH_FEAT_LOW_POWER) */
|
|||
|
|
|||
|
/*
|
|||
|
* @brief Conifg complete local name
|
|||
|
*/
|
|||
|
/*-----------------------------------------------------------*/
|
|||
|
#define BLE_DEV_NAME 'A', 'G', '-', 'S', 'o', 'c', 'k', 'e', 't'
|
|||
|
|
|||
|
const uint8_t mesh_name[] = {
|
|||
|
// Name
|
|||
|
BYTE_LEN(BLE_DEV_NAME) + 1, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, BLE_DEV_NAME,
|
|||
|
};
|
|||
|
|
|||
|
void get_mesh_adv_name(u8 *len, u8 **data)
|
|||
|
{
|
|||
|
*len = sizeof(mesh_name);
|
|||
|
|
|||
|
*data = mesh_name;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* @brief Conifg AliGenie 三元组
|
|||
|
*
|
|||
|
* detail on https://www.aligenie.com/doc/357554/gtgprq
|
|||
|
*/
|
|||
|
/*-----------------------------------------------------------*/
|
|||
|
#define PID_TO_LITTLE_ENDIAN(x) \
|
|||
|
(x & 0xff), \
|
|||
|
((x >> 8) & 0xff), \
|
|||
|
((x >> 16) & 0xff), \
|
|||
|
((x >> 24) & 0xff)
|
|||
|
#define PID_TO_BIG_ENDIAN(x) \
|
|||
|
((x >> 24) & 0xff), \
|
|||
|
((x >> 16) & 0xff), \
|
|||
|
((x >> 8) & 0xff), \
|
|||
|
(x & 0xff)
|
|||
|
|
|||
|
#define PRODUCT_ID_STRING_SIZE (sizeof(Product_ID) * 2)
|
|||
|
#define MAC_ADDRESS_STRING_SIZE (sizeof(Mac_Address) * 2)
|
|||
|
#define SECRET_STRING_SIZE (sizeof(Secret) - 1)
|
|||
|
|
|||
|
#define CUR_DEVICE_MAC_ADDR 0x28fa7a42bf14
|
|||
|
#define PRODUCT_ID 6001957
|
|||
|
#define DEVICE_SECRET "e3a3d73b8ebf93619cdd56ce469d3cb9"
|
|||
|
|
|||
|
#define ALIGENIE_SUB_ADDR_1 0xc002
|
|||
|
#define ALIGENIE_SUB_ADDR_2 0xcfff
|
|||
|
|
|||
|
/*
|
|||
|
* @brief Publication Declarations
|
|||
|
*
|
|||
|
* The publication messages are initialized to the
|
|||
|
* the size of the opcode + content
|
|||
|
*
|
|||
|
* For publication, the message must be in static or global as
|
|||
|
* it is re-transmitted several times. This occurs
|
|||
|
* after the function that called bt_mesh_model_publish() has
|
|||
|
* exited and the stack is no longer valid.
|
|||
|
*
|
|||
|
* Note that the additional 4 bytes for the AppMIC is not needed
|
|||
|
* because it is added to a stack variable at the time a
|
|||
|
* transmission occurs.
|
|||
|
*
|
|||
|
*/
|
|||
|
/*-----------------------------------------------------------*/
|
|||
|
BT_MESH_MODEL_PUB_DEFINE(gen_onoff_pub_srv, NULL, 2 + 2);
|
|||
|
|
|||
|
/*
|
|||
|
* @brief Generic OnOff Model Operation Codes
|
|||
|
*/
|
|||
|
/*-----------------------------------------------------------*/
|
|||
|
#define BT_MESH_MODEL_OP_GEN_ONOFF_GET BT_MESH_MODEL_OP_2(0x82, 0x01)
|
|||
|
#define BT_MESH_MODEL_OP_GEN_ONOFF_SET BT_MESH_MODEL_OP_2(0x82, 0x02)
|
|||
|
#define BT_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK BT_MESH_MODEL_OP_2(0x82, 0x03)
|
|||
|
#define BT_MESH_MODEL_OP_GEN_ONOFF_STATUS BT_MESH_MODEL_OP_2(0x82, 0x04)
|
|||
|
|
|||
|
/*
|
|||
|
* @brief Vendor Model ID
|
|||
|
*
|
|||
|
* Company Identifiers (see Bluetooth Assigned Numbers)
|
|||
|
* detail on Mesh_v1.0 <3.7.2 Model identifier>
|
|||
|
* detail on https://www.aligenie.com/doc/357554/iv5it7
|
|||
|
*/
|
|||
|
/*-----------------------------------------------------------*/
|
|||
|
#define BT_COMP_ID_LF 0x01A8 // Alibaba
|
|||
|
#define BT_MESH_VENDOR_MODEL_ID_SRV 0x01A80000 //0x0000
|
|||
|
#define BT_MESH_VENDOR_MODEL_ID_CLI 0x01A80001 //0x0001
|
|||
|
|
|||
|
/*
|
|||
|
* @brief AliGenie Vendor Model Operation Codes
|
|||
|
*
|
|||
|
* detail on Mesh_v1.0 <3.7.3.1 Operation codes>
|
|||
|
* 扩展消息 detail on https://www.aligenie.com/doc/357554/iv5it7
|
|||
|
*/
|
|||
|
/*-----------------------------------------------------------*/
|
|||
|
#define VENDOR_MSG_ATTR_GET BT_MESH_MODEL_OP_3(0xD0, BT_COMP_ID_LF)
|
|||
|
#define VENDOR_MSG_ATTR_SET BT_MESH_MODEL_OP_3(0xD1, BT_COMP_ID_LF)
|
|||
|
#define VENDOR_MSG_ATTR_SET_UNACK BT_MESH_MODEL_OP_3(0xD2, BT_COMP_ID_LF)
|
|||
|
#define VENDOR_MSG_ATTR_STATUS BT_MESH_MODEL_OP_3(0xD3, BT_COMP_ID_LF)
|
|||
|
#define VENDOR_MSG_ATTR_INDICAT BT_MESH_MODEL_OP_3(0xD4, BT_COMP_ID_LF)
|
|||
|
#define VENDOR_MSG_ATTR_CONFIRM BT_MESH_MODEL_OP_3(0xD5, BT_COMP_ID_LF)
|
|||
|
#define VENDOR_MSG_ATTR_TRANSPARENT BT_MESH_MODEL_OP_3(0xCF, BT_COMP_ID_LF)
|
|||
|
|
|||
|
/*
|
|||
|
* @brief AliGenie Vendor Model Message Struct
|
|||
|
*
|
|||
|
* 定时功能 detail on https://www.aligenie.com/doc/357554/ovzn6v
|
|||
|
*/
|
|||
|
/*-----------------------------------------------------------*/
|
|||
|
#define ATTR_TYPE_UNIX_TIME 0xF01F
|
|||
|
#define ATTR_TYPE_SET_TIMEOUT 0xF010
|
|||
|
#define ATTR_TYPE_SET_PERIOD_TIMEOUT 0xF011
|
|||
|
#define ATTR_TYPE_DELETE_TIMEOUT 0xF012
|
|||
|
|
|||
|
struct __unix_time {
|
|||
|
u32 Opcode: 24,
|
|||
|
TID: 8;
|
|||
|
u16 Attr_Type;
|
|||
|
u32 time;
|
|||
|
} _GNU_PACKED_;
|
|||
|
|
|||
|
struct __set_timeout {
|
|||
|
u32 Opcode: 24,
|
|||
|
TID: 8;
|
|||
|
u16 Attr_Type;
|
|||
|
struct __param {
|
|||
|
u8 index;
|
|||
|
u32 time;
|
|||
|
u16 attr_type;
|
|||
|
u8 attr_para;
|
|||
|
} _GNU_PACKED_ param[1] ;
|
|||
|
} _GNU_PACKED_;
|
|||
|
|
|||
|
struct __set_period_timeout {
|
|||
|
u32 Opcode: 24,
|
|||
|
TID: 8;
|
|||
|
u16 Attr_Type;
|
|||
|
struct __period_param {
|
|||
|
u8 index;
|
|||
|
u16 _24h_timer;
|
|||
|
u8 schedule;
|
|||
|
u16 attr_type;
|
|||
|
u8 attr_para;
|
|||
|
} _GNU_PACKED_ period_param[1] ;
|
|||
|
} _GNU_PACKED_;
|
|||
|
|
|||
|
struct __delete_time {
|
|||
|
u32 Opcode: 24,
|
|||
|
TID: 8;
|
|||
|
u16 Attr_Type;
|
|||
|
u8 index;
|
|||
|
} _GNU_PACKED_;
|
|||
|
|
|||
|
struct __timer_success {
|
|||
|
u32 Opcode: 24,
|
|||
|
TID: 8;
|
|||
|
u16 Attr_Type;
|
|||
|
u8 event;
|
|||
|
u8 index;
|
|||
|
} _GNU_PACKED_;
|
|||
|
|
|||
|
struct __timer_param {
|
|||
|
u8 tid;
|
|||
|
u8 index;
|
|||
|
u8 timer_cnt;
|
|||
|
bool onoff;
|
|||
|
};
|
|||
|
|
|||
|
struct __onoff_repo {
|
|||
|
u32 Opcode: 24,
|
|||
|
TID: 8;
|
|||
|
u16 Attr_Type;
|
|||
|
bool OnOff;
|
|||
|
} _GNU_PACKED_;
|
|||
|
|
|||
|
struct __indicate_msg {
|
|||
|
u32 Opcode: 24,
|
|||
|
TID: 8;
|
|||
|
u16 Attr_Type;
|
|||
|
u8 Event;
|
|||
|
u8 EventParam;
|
|||
|
} _GNU_PACKED_;
|
|||
|
|
|||
|
struct __comfirm_check_param {
|
|||
|
u8 resend_cnt;
|
|||
|
u8 timer_cnt;
|
|||
|
u8 indicate_tid;
|
|||
|
void *buf;
|
|||
|
u16 len;
|
|||
|
};
|
|||
|
|
|||
|
static bool led_flag = 0;
|
|||
|
static u8 indicate_tid = 0x80;
|
|||
|
static u16 timer_index[20];
|
|||
|
static struct __timer_param timer_param[20];
|
|||
|
static struct __comfirm_check_param comfirm_check_param[20];
|
|||
|
static u8 timer_cnt = -1;
|
|||
|
static struct bt_mesh_model vendor_server_models[];
|
|||
|
static bool indicate_flag[256];
|
|||
|
|
|||
|
/*
|
|||
|
* @brief Access Payload Fields
|
|||
|
*
|
|||
|
* detail on Mesh_v1.0 <3.7.3 Access payload>
|
|||
|
*/
|
|||
|
/*-----------------------------------------------------------*/
|
|||
|
#define TRANSMIC_SIZE 4
|
|||
|
#define MAX_USEFUL_ACCESS_PAYLOAD_SIZE 11 // 32 bit TransMIC (unsegmented)
|
|||
|
#define ACCESS_OP_SIZE 3
|
|||
|
#define ACCESS_PARAM_SIZE (MAX_USEFUL_ACCESS_PAYLOAD_SIZE - ACCESS_OP_SIZE)
|
|||
|
|
|||
|
/*
|
|||
|
* @brief Generic OnOff State Set
|
|||
|
*/
|
|||
|
/*-----------------------------------------------------------*/
|
|||
|
#define LED0_GPIO_PIN 0
|
|||
|
#define LED1_GPIO_PIN 1
|
|||
|
|
|||
|
struct onoff_state {
|
|||
|
u8_t current;
|
|||
|
u8_t previous;
|
|||
|
u8_t led_gpio_pin;
|
|||
|
};
|
|||
|
|
|||
|
struct _switch {
|
|||
|
u8_t sw_num;
|
|||
|
u8_t onoff_state;
|
|||
|
};
|
|||
|
|
|||
|
static struct onoff_state onoff_state[] = {
|
|||
|
{ .led_gpio_pin = LED0_GPIO_PIN },
|
|||
|
};
|
|||
|
|
|||
|
const u8 led_use_port[] = {
|
|||
|
IO_PORTA_01,
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* @brief Generic OnOff Model Server Message Handlers
|
|||
|
*
|
|||
|
* Mesh Model Specification 3.1.1
|
|||
|
*/
|
|||
|
/*-----------------------------------------------------------*/
|
|||
|
static void respond_messsage_schedule(u16 *delay, u16 *duration, void *cb_data)
|
|||
|
{
|
|||
|
/* Mesh_v1.0 <3.7.4.1 Transmitting an access message>
|
|||
|
*
|
|||
|
* If the message is sent in response to a received message
|
|||
|
* that was sent to a unicast address, the node should transmit
|
|||
|
* the response message with a random delay between 20 and 50 milliseconds.
|
|||
|
*
|
|||
|
* If the message is sent in response to a received message
|
|||
|
* that was sent to a group address or a virtual address,
|
|||
|
* the node should transmit the response message with
|
|||
|
* a random delay between 20 and 500 milliseconds.
|
|||
|
*/
|
|||
|
u16 delay_ms;
|
|||
|
//struct bt_mesh_msg_ctx *ctx = cb_data;
|
|||
|
u16 dst_addr = (u16)cb_data;
|
|||
|
|
|||
|
pseudo_random_genrate((u8 *)&delay_ms, 2);
|
|||
|
if (BT_MESH_ADDR_IS_UNICAST(dst_addr)) {
|
|||
|
delay_ms = btctler_get_rand_from_assign_range(delay_ms, 20, 50);
|
|||
|
} else {
|
|||
|
delay_ms = btctler_get_rand_from_assign_range(delay_ms, 20, 200);
|
|||
|
}
|
|||
|
|
|||
|
*delay = delay_ms;
|
|||
|
log_info("respond_messsage delay =%u ms", delay_ms);
|
|||
|
}
|
|||
|
|
|||
|
// static const struct bt_mesh_send_cb rsp_msg_cb = {
|
|||
|
// .user_intercept = respond_messsage_schedule,
|
|||
|
// /* .user_intercept = NULL, */
|
|||
|
// };
|
|||
|
|
|||
|
/*
|
|||
|
* @brief AliGenie Vendor Model Message Handlers
|
|||
|
*
|
|||
|
* 定时功能 detail on https://www.aligenie.com/doc/357554/ovzn6v
|
|||
|
*/
|
|||
|
/*-----------------------------------------------------------*/
|
|||
|
static void vendor_attr_status_send(struct bt_mesh_model *model,
|
|||
|
struct bt_mesh_msg_ctx *ctx,
|
|||
|
void *buf, u16 len)
|
|||
|
{
|
|||
|
log_info("ready to send ATTR_TYPE_SET_TIMEOUT status");
|
|||
|
|
|||
|
NET_BUF_SIMPLE_DEFINE(msg, len + TRANSMIC_SIZE);
|
|||
|
|
|||
|
buffer_memcpy(&msg, buf, len);
|
|||
|
|
|||
|
log_info_hexdump(msg.data, msg.len);
|
|||
|
|
|||
|
if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) {
|
|||
|
log_error("Unable to send Status response\n");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void indicate_tid_get(u8 *indicate_tid)
|
|||
|
{
|
|||
|
if (*indicate_tid >= 0x80 && *indicate_tid <= 0xbf) {
|
|||
|
*indicate_tid += 1;
|
|||
|
} else {
|
|||
|
*indicate_tid = 0x80;
|
|||
|
}
|
|||
|
}
|
|||
|
void timer_cnt_get(u8 *timer_cnt)
|
|||
|
{
|
|||
|
if (*timer_cnt >= -1 && *timer_cnt <= 18) {
|
|||
|
*timer_cnt += 1;
|
|||
|
} else {
|
|||
|
*timer_cnt = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void comfirm_check(struct __comfirm_check_param *param)
|
|||
|
{
|
|||
|
struct bt_mesh_msg_ctx ctx = {
|
|||
|
.addr = 0xf000,
|
|||
|
};
|
|||
|
if (!indicate_flag[param->indicate_tid]) {
|
|||
|
param->resend_cnt += 1;
|
|||
|
if (param->resend_cnt >= 10) { //最多重传75次,即30秒重传时间
|
|||
|
sys_timer_remove(timer_index[param->timer_cnt]);
|
|||
|
log_info("resend msg more than 75 times\r\n");
|
|||
|
}
|
|||
|
log_info("indicate_flag[ %d ] = %d\r\n", param->indicate_tid, indicate_flag[param->indicate_tid]);
|
|||
|
log_info("\n param->buf.tid = %d, timer_cnt = %d \n", ((struct __onoff_repo *)(param->buf))->TID, param->timer_cnt);
|
|||
|
vendor_attr_status_send(&vendor_server_models[0], &ctx, param->buf, param->len);
|
|||
|
} else {
|
|||
|
sys_timer_remove(timer_index[param->timer_cnt]);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
static void gen_onoff_get(struct bt_mesh_model *model,
|
|||
|
struct bt_mesh_msg_ctx *ctx,
|
|||
|
struct net_buf_simple *buf)
|
|||
|
{
|
|||
|
NET_BUF_SIMPLE_DEFINE(msg, 2 + 1 + 4);
|
|||
|
struct onoff_state *onoff_state = model->rt->user_data;
|
|||
|
|
|||
|
log_info("addr 0x%04x onoff 0x%02x\n",
|
|||
|
bt_mesh_model_elem(model)->rt->addr, onoff_state->current);
|
|||
|
bt_mesh_model_msg_init(&msg, BT_MESH_MODEL_OP_GEN_ONOFF_STATUS);
|
|||
|
buffer_add_u8_at_tail(&msg, onoff_state->current);
|
|||
|
|
|||
|
/* delay for send msg because adv timer duration is 50ms. */
|
|||
|
os_time_dly(5);
|
|||
|
|
|||
|
if (bt_mesh_model_send(model, ctx, &msg, NULL/*&rsp_msg_cb*/, (void *)ctx->recv_dst)) {
|
|||
|
log_info("Unable to send On Off Status response\n");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
static void gen_onoff_set_unack(struct bt_mesh_model *model,
|
|||
|
struct bt_mesh_msg_ctx *ctx,
|
|||
|
struct net_buf_simple *buf)
|
|||
|
{
|
|||
|
struct net_buf_simple *msg = model->pub->msg;
|
|||
|
struct onoff_state *onoff_state = model->rt->user_data;
|
|||
|
int err;
|
|||
|
|
|||
|
onoff_state->current = buffer_pull_u8_from_head(buf);
|
|||
|
log_info("addr 0x%02x state 0x%02x\n",
|
|||
|
bt_mesh_model_elem(model)->rt->addr, onoff_state->current);
|
|||
|
/* log_info_hexdump((u8 *)onoff_state, sizeof(*onoff_state)); */
|
|||
|
|
|||
|
gpio_pin_write(onoff_state->led_gpio_pin,
|
|||
|
onoff_state->current);
|
|||
|
|
|||
|
led_flag = onoff_state->current;
|
|||
|
|
|||
|
log_info("\n tmall set led to %d \n", led_flag);
|
|||
|
|
|||
|
indicate_tid_get(&indicate_tid);
|
|||
|
timer_cnt_get(&timer_cnt);
|
|||
|
indicate_flag[indicate_tid] = 0;
|
|||
|
|
|||
|
static struct __onoff_repo onoff_repo_set[10];
|
|||
|
static u8 onoff_repo_set_cnt = 0;
|
|||
|
|
|||
|
if (onoff_repo_set_cnt < 9) {
|
|||
|
onoff_repo_set_cnt ++;
|
|||
|
} else {
|
|||
|
onoff_repo_set_cnt = 0;
|
|||
|
}
|
|||
|
|
|||
|
onoff_repo_set[onoff_repo_set_cnt].Opcode = buffer_head_init(VENDOR_MSG_ATTR_INDICAT);
|
|||
|
onoff_repo_set[onoff_repo_set_cnt].TID = indicate_tid;
|
|||
|
onoff_repo_set[onoff_repo_set_cnt].Attr_Type = 0x0100;
|
|||
|
onoff_repo_set[onoff_repo_set_cnt].OnOff = led_flag;
|
|||
|
|
|||
|
comfirm_check_param[timer_cnt].resend_cnt = 0;
|
|||
|
comfirm_check_param[timer_cnt].timer_cnt = timer_cnt;
|
|||
|
comfirm_check_param[timer_cnt].indicate_tid = onoff_repo_set[onoff_repo_set_cnt].TID;
|
|||
|
comfirm_check_param[timer_cnt].buf = &onoff_repo_set[onoff_repo_set_cnt];
|
|||
|
comfirm_check_param[timer_cnt].len = sizeof(onoff_repo_set[onoff_repo_set_cnt]);
|
|||
|
|
|||
|
log_info("\n set unack tid = %d, timer_cnt = %d, param.tid = %d \n", onoff_repo_set[onoff_repo_set_cnt].TID, timer_cnt, comfirm_check_param[timer_cnt].indicate_tid);
|
|||
|
|
|||
|
vendor_attr_status_send(&vendor_server_models[0], ctx, &onoff_repo_set[onoff_repo_set_cnt], sizeof(onoff_repo_set[onoff_repo_set_cnt]));
|
|||
|
timer_index[timer_cnt] = sys_timer_add(&comfirm_check_param[timer_cnt], comfirm_check, 400);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
static void gen_onoff_set(struct bt_mesh_model *model,
|
|||
|
struct bt_mesh_msg_ctx *ctx,
|
|||
|
struct net_buf_simple *buf)
|
|||
|
{
|
|||
|
log_info("gen_onoff_set\n");
|
|||
|
|
|||
|
gen_onoff_set_unack(model, ctx, buf);
|
|||
|
gen_onoff_get(model, ctx, buf);
|
|||
|
}
|
|||
|
|
|||
|
static void timer_handler(struct __timer_param *param)
|
|||
|
{
|
|||
|
indicate_tid_get(&indicate_tid);
|
|||
|
|
|||
|
static struct __timer_success timer_success;
|
|||
|
timer_success.Opcode = buffer_head_init(VENDOR_MSG_ATTR_INDICAT);
|
|||
|
timer_success.TID = indicate_tid;
|
|||
|
timer_success.Attr_Type = 0xf009;
|
|||
|
timer_success.event = 0x11;
|
|||
|
timer_success.index = param->index;
|
|||
|
|
|||
|
indicate_flag[timer_success.TID] = 0;
|
|||
|
|
|||
|
indicate_tid_get(&indicate_tid);
|
|||
|
static struct __onoff_repo onoff_repo_handle;
|
|||
|
onoff_repo_handle.Opcode = buffer_head_init(VENDOR_MSG_ATTR_INDICAT);
|
|||
|
onoff_repo_handle.TID = indicate_tid;
|
|||
|
onoff_repo_handle.Attr_Type = 0x0100;
|
|||
|
onoff_repo_handle.OnOff = param->onoff;
|
|||
|
|
|||
|
indicate_flag[onoff_repo_handle.TID] = 0;
|
|||
|
|
|||
|
struct bt_mesh_msg_ctx ctx = {
|
|||
|
.addr = 0xf000,
|
|||
|
};
|
|||
|
|
|||
|
gpio_pin_write(LED0_GPIO_PIN, param->onoff);
|
|||
|
led_flag = param->onoff;
|
|||
|
|
|||
|
log_info("timer_cnt = %d, timer_index = 0x%x, onoff = %d", param->timer_cnt, timer_index[param->timer_cnt], param->onoff);
|
|||
|
|
|||
|
sys_timer_remove(timer_index[param->timer_cnt]);
|
|||
|
|
|||
|
//timing success msg send and check comfirm
|
|||
|
timer_cnt_get(&timer_cnt);
|
|||
|
comfirm_check_param[timer_cnt].resend_cnt = 0;
|
|||
|
comfirm_check_param[timer_cnt].timer_cnt = timer_cnt;
|
|||
|
comfirm_check_param[timer_cnt].indicate_tid = indicate_tid;
|
|||
|
comfirm_check_param[timer_cnt].buf = &timer_success;
|
|||
|
comfirm_check_param[timer_cnt].len = sizeof(timer_success);
|
|||
|
vendor_attr_status_send(&vendor_server_models[0], &ctx, &timer_success, sizeof(timer_success));
|
|||
|
timer_index[timer_cnt] = sys_timer_add(&comfirm_check_param[timer_cnt], comfirm_check, 400);
|
|||
|
|
|||
|
//onoff_state msg send and check comfirm
|
|||
|
timer_cnt_get(&timer_cnt);
|
|||
|
comfirm_check_param[timer_cnt].resend_cnt = 0;
|
|||
|
comfirm_check_param[timer_cnt].timer_cnt = timer_cnt;
|
|||
|
comfirm_check_param[timer_cnt].indicate_tid = indicate_tid;
|
|||
|
comfirm_check_param[timer_cnt].buf = &onoff_repo_handle;
|
|||
|
comfirm_check_param[timer_cnt].len = sizeof(onoff_repo_handle);
|
|||
|
vendor_attr_status_send(&vendor_server_models[0], &ctx, &onoff_repo_handle, sizeof(onoff_repo_handle));
|
|||
|
timer_index[timer_cnt] = sys_timer_add(&comfirm_check_param[timer_cnt], comfirm_check, 400);
|
|||
|
}
|
|||
|
|
|||
|
static void set_timer_start(u8 tid,
|
|||
|
u32 delay_s,
|
|||
|
u8 index,
|
|||
|
bool onoff)
|
|||
|
{
|
|||
|
|
|||
|
timer_cnt_get(&timer_cnt);
|
|||
|
|
|||
|
timer_param[timer_cnt].tid = tid;
|
|||
|
timer_param[timer_cnt].index = index;
|
|||
|
timer_param[timer_cnt].onoff = onoff;
|
|||
|
timer_param[timer_cnt].timer_cnt = timer_cnt;
|
|||
|
|
|||
|
|
|||
|
log_info("time_cnt = %d\r\n", timer_cnt);
|
|||
|
timer_index[timer_cnt] = sys_timer_add(&timer_param[timer_cnt], timer_handler, delay_s * 1000);
|
|||
|
|
|||
|
log_info("timer set delay %d second\r\n", delay_s);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
static void vendor_attr_cfm(struct bt_mesh_model *model,
|
|||
|
struct bt_mesh_msg_ctx *ctx,
|
|||
|
struct net_buf_simple *buf)
|
|||
|
{
|
|||
|
u8 cfm_tid = buffer_pull_u8_from_head(buf);
|
|||
|
indicate_flag[cfm_tid] = 1;
|
|||
|
log_info("receice vendor_attr_confirm, indicate_tid = %d\r\n", cfm_tid);
|
|||
|
}
|
|||
|
|
|||
|
static void vendor_attr_get(struct bt_mesh_model *model,
|
|||
|
struct bt_mesh_msg_ctx *ctx,
|
|||
|
struct net_buf_simple *buf)
|
|||
|
{
|
|||
|
log_info("receive vendor_attr_get, len except opcode =0x%x", buf->len);
|
|||
|
log_info_hexdump(buf->data, buf->len);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
static void vendor_attr_set(struct bt_mesh_model *model,
|
|||
|
struct bt_mesh_msg_ctx *ctx,
|
|||
|
struct net_buf_simple *buf)
|
|||
|
{
|
|||
|
log_info("receive vendor_attr_set, len except opcode =0x%x", buf->len);
|
|||
|
log_info_hexdump(buf->data, buf->len);
|
|||
|
|
|||
|
static struct UTC_TIME cur_utc;
|
|||
|
u8 tid = buffer_pull_u8_from_head(buf);
|
|||
|
u16 Attr_Type = buffer_pull_le16_from_head(buf);
|
|||
|
switch (Attr_Type) {
|
|||
|
case ATTR_TYPE_UNIX_TIME: {
|
|||
|
u32 time = buffer_pull_le32_from_head(buf);
|
|||
|
|
|||
|
cur_utc = unix32_to_UTC_beijing(time);
|
|||
|
log_info("\n __unix_time BeiJing time: %d/%d/%d %02d:%02d:%02d, weekday %d \n",
|
|||
|
cur_utc.year, cur_utc.month, cur_utc.day,
|
|||
|
cur_utc.hour, cur_utc.minute, cur_utc.second,
|
|||
|
cur_utc.weekday);
|
|||
|
|
|||
|
struct __unix_time unix_time = {
|
|||
|
.Opcode = buffer_head_init(VENDOR_MSG_ATTR_STATUS),
|
|||
|
.TID = tid,
|
|||
|
.Attr_Type = Attr_Type,
|
|||
|
.time = time,
|
|||
|
};
|
|||
|
|
|||
|
vendor_attr_status_send(model, ctx, &unix_time, sizeof(unix_time));
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case ATTR_TYPE_SET_TIMEOUT: {
|
|||
|
u8 index = buffer_pull_u8_from_head(buf);
|
|||
|
u32 time = buffer_pull_le32_from_head(buf);
|
|||
|
u16 attr_type = buffer_pull_le16_from_head(buf);
|
|||
|
u8 attr_para = buffer_pull_u8_from_head(buf);
|
|||
|
|
|||
|
struct UTC_TIME set_cur_utc = unix32_to_UTC_beijing(time);
|
|||
|
log_info("\n __set_timeout BeiJinG time: %d/%d/%d %02d:%02d:%02d, weekday %d\n",
|
|||
|
set_cur_utc.year, set_cur_utc.month, set_cur_utc.day,
|
|||
|
set_cur_utc.hour, set_cur_utc.minute, set_cur_utc.second,
|
|||
|
set_cur_utc.weekday);
|
|||
|
|
|||
|
u32 delay_s = ((set_cur_utc.hour - cur_utc.hour) * 3600) + ((set_cur_utc.minute - cur_utc.minute) * 60) + (set_cur_utc.second - cur_utc.second);
|
|||
|
|
|||
|
log_info("\n delay_s = %d, switch set to %d\n", delay_s, attr_para);
|
|||
|
|
|||
|
set_timer_start(tid, delay_s, index, attr_para);
|
|||
|
|
|||
|
struct __set_timeout set_timeout = {
|
|||
|
.Opcode = buffer_head_init(VENDOR_MSG_ATTR_STATUS),
|
|||
|
.TID = tid,
|
|||
|
.Attr_Type = Attr_Type,
|
|||
|
.param[0] = {
|
|||
|
.index = index,
|
|||
|
.time = time,
|
|||
|
.attr_type = attr_type,
|
|||
|
.attr_para = attr_para,
|
|||
|
},
|
|||
|
};
|
|||
|
vendor_attr_status_send(model, ctx, &set_timeout, sizeof(set_timeout));
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case ATTR_TYPE_SET_PERIOD_TIMEOUT: {
|
|||
|
u8 index = buffer_pull_u8_from_head(buf);
|
|||
|
u16 _24h_timer = buffer_pull_le16_from_head(buf);
|
|||
|
u8 schedule = buffer_pull_u8_from_head(buf);
|
|||
|
u16 attr_type = buffer_pull_le16_from_head(buf);
|
|||
|
u8 attr_para = buffer_pull_u8_from_head(buf);
|
|||
|
|
|||
|
log_info("\n set_period_timeout BeiJinG time: %02d:%02d, weekday %d\n",
|
|||
|
(_24h_timer & 0x0fff) / 60, (_24h_timer & 0x0fff) % 60, schedule);
|
|||
|
|
|||
|
struct __set_period_timeout set_period_timeout = {
|
|||
|
.Opcode = buffer_head_init(VENDOR_MSG_ATTR_STATUS),
|
|||
|
.TID = tid,
|
|||
|
.Attr_Type = Attr_Type,
|
|||
|
.period_param[0] = {
|
|||
|
.index = index,
|
|||
|
._24h_timer = _24h_timer,
|
|||
|
.schedule = schedule,
|
|||
|
.attr_type = attr_type,
|
|||
|
.attr_para = attr_para,
|
|||
|
},
|
|||
|
};
|
|||
|
log_info("\n time = 0x%x\n", _24h_timer);
|
|||
|
log_info("\n set_period opcode = 0x%x, Attr_Type = 0x%x, para = 0x%x, index = 0x%x \n", set_period_timeout.Opcode, Attr_Type, attr_para, index);
|
|||
|
vendor_attr_status_send(model, ctx, &set_period_timeout, sizeof(set_period_timeout));
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case ATTR_TYPE_DELETE_TIMEOUT: {
|
|||
|
u8 index = buffer_pull_u8_from_head(buf);
|
|||
|
struct __delete_time delete_time = {
|
|||
|
.Opcode = buffer_head_init(VENDOR_MSG_ATTR_STATUS),
|
|||
|
.TID = tid,
|
|||
|
.Attr_Type = Attr_Type,
|
|||
|
.index = index,
|
|||
|
};
|
|||
|
log_info("delete timeout for index = 0x%x\r\n", index);
|
|||
|
vendor_attr_status_send(model, ctx, &delete_time, sizeof(delete_time));
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
default :
|
|||
|
log_info("\n\n\n\n default attr = 0x%x \n\n\n\n", Attr_Type);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* @brief OnOff Model Server Op Dispatch Table
|
|||
|
*/
|
|||
|
/*-----------------------------------------------------------*/
|
|||
|
static const struct bt_mesh_model_op gen_onoff_srv_op[] = {
|
|||
|
{ BT_MESH_MODEL_OP_GEN_ONOFF_GET, 0, gen_onoff_get },
|
|||
|
{ BT_MESH_MODEL_OP_GEN_ONOFF_SET, 2, gen_onoff_set },
|
|||
|
{ BT_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK, 2, gen_onoff_set_unack },
|
|||
|
BT_MESH_MODEL_OP_END,
|
|||
|
};
|
|||
|
|
|||
|
/*
|
|||
|
* @brief Vendor Model Server Op Dispatch Table
|
|||
|
*/
|
|||
|
/*-----------------------------------------------------------*/
|
|||
|
static const struct bt_mesh_model_op vendor_srv_op[] = {
|
|||
|
{ VENDOR_MSG_ATTR_GET, ACCESS_OP_SIZE, vendor_attr_get },
|
|||
|
{ VENDOR_MSG_ATTR_SET, ACCESS_OP_SIZE, vendor_attr_set },
|
|||
|
{ VENDOR_MSG_ATTR_CONFIRM, 1, vendor_attr_cfm },
|
|||
|
BT_MESH_MODEL_OP_END,
|
|||
|
};
|
|||
|
|
|||
|
/*
|
|||
|
* @brief Element Model Declarations
|
|||
|
*
|
|||
|
* Element 0 Root Models
|
|||
|
*/
|
|||
|
/*-----------------------------------------------------------*/
|
|||
|
static struct bt_mesh_model root_models[] = {
|
|||
|
BT_MESH_MODEL_CFG_SRV,
|
|||
|
BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_srv_op, &gen_onoff_pub_srv, &onoff_state[0]),
|
|||
|
};
|
|||
|
|
|||
|
static struct bt_mesh_model vendor_server_models[] = {
|
|||
|
BT_MESH_MODEL_VND(BT_COMP_ID_LF, BT_MESH_VENDOR_MODEL_ID_SRV, vendor_srv_op, NULL, &onoff_state[0]),
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* @brief LED to Server Model Assigmnents
|
|||
|
*/
|
|||
|
/*-----------------------------------------------------------*/
|
|||
|
static struct bt_mesh_model *mod_srv_sw[] = {
|
|||
|
&root_models[1],
|
|||
|
};
|
|||
|
|
|||
|
/*
|
|||
|
* @brief Root and Secondary Element Declarations
|
|||
|
*/
|
|||
|
/*-----------------------------------------------------------*/
|
|||
|
static struct bt_mesh_elem elements[] = {
|
|||
|
BT_MESH_ELEM(0, root_models, vendor_server_models),
|
|||
|
};
|
|||
|
|
|||
|
static const struct bt_mesh_comp composition = {
|
|||
|
.cid = BT_COMP_ID_LF,
|
|||
|
.elem = elements,
|
|||
|
.elem_count = ARRAY_SIZE(elements),
|
|||
|
};
|
|||
|
|
|||
|
/*
|
|||
|
* @brief AliGenie UUID格式
|
|||
|
*
|
|||
|
* detail on https://www.aligenie.com/doc/357554/gtgprq <表1:Device UUID格式>
|
|||
|
*/
|
|||
|
/*-----------------------------------------------------------*/
|
|||
|
static u8 dev_uuid[16] = {
|
|||
|
0xA8, 0x01, // CID
|
|||
|
0x01 | BIT(4) | BIT(6), // PID
|
|||
|
PID_TO_LITTLE_ENDIAN(PRODUCT_ID), // ProductID
|
|||
|
MAC_TO_LITTLE_ENDIAN(CUR_DEVICE_MAC_ADDR), // MAC
|
|||
|
BIT(1), //FeatureFlag
|
|||
|
0x00, 0x00 // RFU
|
|||
|
};
|
|||
|
|
|||
|
/*
|
|||
|
* @brief AliGenie 设备配网流程
|
|||
|
*
|
|||
|
* detail on https://www.aligenie.com/doc/357554/gtgprq
|
|||
|
*/
|
|||
|
/*-----------------------------------------------------------*/
|
|||
|
static u8 auth_data[16];
|
|||
|
|
|||
|
static void hex_to_string(void *in, int in_len, void *out, int out_len)
|
|||
|
{
|
|||
|
static const char hex[] = "0123456789abcdef";
|
|||
|
u8 *a = in;
|
|||
|
u8 *b = out;
|
|||
|
int i;
|
|||
|
|
|||
|
if (in_len > (out_len / 2)) {
|
|||
|
log_error("\"error: in_len > (out_len / 2)\"");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
for (i = 0; i < in_len; i++) {
|
|||
|
b[i * 2] = hex[a[i] >> 4];
|
|||
|
b[i * 2 + 1] = hex[a[i] & 0xf];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
static void static_auth_value_calculate(void)
|
|||
|
{
|
|||
|
log_info("--func=%s", __FUNCTION__);
|
|||
|
|
|||
|
const u8 Product_ID[] = {
|
|||
|
PID_TO_BIG_ENDIAN(PRODUCT_ID)
|
|||
|
};
|
|||
|
const u8 Mac_Address[] = {
|
|||
|
MAC_TO_BIG_ENDIAN(CUR_DEVICE_MAC_ADDR)
|
|||
|
};
|
|||
|
const u8 Secret[] = {
|
|||
|
DEVICE_SECRET
|
|||
|
};
|
|||
|
|
|||
|
u8 string_buf[PRODUCT_ID_STRING_SIZE + MAC_ADDRESS_STRING_SIZE + SECRET_STRING_SIZE + 2];
|
|||
|
u8 *string_p = string_buf;
|
|||
|
u8 digest[SHA256_DIGEST_SIZE];
|
|||
|
|
|||
|
//< Product ID
|
|||
|
hex_to_string(Product_ID, sizeof(Product_ID), string_p, PRODUCT_ID_STRING_SIZE);
|
|||
|
string_p += PRODUCT_ID_STRING_SIZE;
|
|||
|
*string_p++ = ',';
|
|||
|
//< Mac Address
|
|||
|
hex_to_string(Mac_Address, sizeof(Mac_Address), string_p, MAC_ADDRESS_STRING_SIZE);
|
|||
|
string_p += MAC_ADDRESS_STRING_SIZE;
|
|||
|
*string_p++ = ',';
|
|||
|
//< Secert
|
|||
|
memcpy(string_p, Secret, SECRET_STRING_SIZE);
|
|||
|
|
|||
|
sha256Compute(string_buf, sizeof(string_buf), digest);
|
|||
|
|
|||
|
memcpy(auth_data, digest, sizeof(auth_data));
|
|||
|
|
|||
|
log_info("string_buf : %s", string_buf);
|
|||
|
log_info_hexdump(string_buf, sizeof(string_buf));
|
|||
|
log_info_hexdump(auth_data, sizeof(auth_data));
|
|||
|
}
|
|||
|
|
|||
|
void auth_data_change(u8 *c_auth_data)
|
|||
|
{
|
|||
|
memcpy(auth_data, c_auth_data, sizeof(auth_data));
|
|||
|
}
|
|||
|
|
|||
|
static const struct bt_mesh_prov prov = {
|
|||
|
.uuid = dev_uuid,
|
|||
|
.static_val = auth_data,
|
|||
|
.static_val_len = sizeof(auth_data),
|
|||
|
.output_size = 0,
|
|||
|
.output_actions = 0,
|
|||
|
.output_number = 0,
|
|||
|
.complete = prov_complete,
|
|||
|
.reset = prov_reset,
|
|||
|
};
|
|||
|
|
|||
|
/*
|
|||
|
* @brief Button Pressed Worker Task
|
|||
|
*/
|
|||
|
/*-----------------------------------------------------------*/
|
|||
|
static bool server_publish(struct _switch *sw)
|
|||
|
{
|
|||
|
struct bt_mesh_model *mod_srv;
|
|||
|
struct bt_mesh_model_pub *pub_srv;
|
|||
|
|
|||
|
mod_srv = mod_srv_sw[sw->sw_num];
|
|||
|
pub_srv = mod_srv->pub;
|
|||
|
|
|||
|
/* If unprovisioned, just call the set function.
|
|||
|
* The intent is to have switch-like behavior
|
|||
|
* prior to provisioning. Once provisioned,
|
|||
|
* the button and its corresponding led are no longer
|
|||
|
* associated and act independently. So, if a button is to
|
|||
|
* control its associated led after provisioning, the button
|
|||
|
* must be configured to either publish to the led's unicast
|
|||
|
* address or a group to which the led is subscribed.
|
|||
|
*/
|
|||
|
u16 primary_addr = get_primary_addr();
|
|||
|
if (primary_addr == BT_MESH_ADDR_UNASSIGNED) {
|
|||
|
NET_BUF_SIMPLE_DEFINE(msg, 1);
|
|||
|
struct bt_mesh_msg_ctx ctx = {
|
|||
|
.addr = sw->sw_num + primary_addr,
|
|||
|
};
|
|||
|
|
|||
|
/* This is a dummy message sufficient
|
|||
|
* for the led server
|
|||
|
*/
|
|||
|
buffer_add_u8_at_tail(&msg, sw->onoff_state);
|
|||
|
gen_onoff_set_unack(mod_srv, &ctx, &msg);
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
static void button_pressed_worker(struct _switch *sw)
|
|||
|
{
|
|||
|
if (sw->sw_num >= composition.elem_count) {
|
|||
|
log_info("sw_num over elem_count");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (server_publish(sw)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void led_set(void)
|
|||
|
{
|
|||
|
led_flag = !led_flag;
|
|||
|
|
|||
|
indicate_tid_get(&indicate_tid);
|
|||
|
timer_cnt_get(&timer_cnt);
|
|||
|
|
|||
|
gpio_pin_write(LED0_GPIO_PIN, led_flag);
|
|||
|
log_info("state set to %d, indicate_tid now = %d\r\n", led_flag, indicate_tid);
|
|||
|
|
|||
|
if (!bt_mesh_is_provisioned()) {
|
|||
|
log_info("no provision, not send state indicate\r\n");
|
|||
|
return;
|
|||
|
}
|
|||
|
struct bt_mesh_msg_ctx ctx = {
|
|||
|
.addr = 0xf000,
|
|||
|
};
|
|||
|
|
|||
|
static struct __onoff_repo onoff_repo;
|
|||
|
onoff_repo.Opcode = buffer_head_init(VENDOR_MSG_ATTR_INDICAT);
|
|||
|
onoff_repo.TID = indicate_tid;
|
|||
|
onoff_repo.Attr_Type = 0x0100;
|
|||
|
onoff_repo.OnOff = led_flag;
|
|||
|
|
|||
|
indicate_flag[indicate_tid] = 0;
|
|||
|
|
|||
|
comfirm_check_param[timer_cnt].resend_cnt = 0;
|
|||
|
comfirm_check_param[timer_cnt].timer_cnt = timer_cnt;
|
|||
|
comfirm_check_param[timer_cnt].indicate_tid = indicate_tid;
|
|||
|
comfirm_check_param[timer_cnt].buf = &onoff_repo;
|
|||
|
comfirm_check_param[timer_cnt].len = sizeof(onoff_repo);
|
|||
|
|
|||
|
log_info(" vendor &model = 0x%x, vendor model = 0x%x", &vendor_server_models[0], vendor_server_models[0]);
|
|||
|
|
|||
|
vendor_attr_status_send(&vendor_server_models[0], &ctx, &onoff_repo, sizeof(onoff_repo));
|
|||
|
timer_index[timer_cnt] = sys_timer_add(&comfirm_check_param[timer_cnt], comfirm_check, 400);
|
|||
|
}
|
|||
|
|
|||
|
void iot_reset()
|
|||
|
{
|
|||
|
bt_mesh_reset();
|
|||
|
p33_soft_reset();
|
|||
|
}
|
|||
|
|
|||
|
static u16 blink_id;
|
|||
|
|
|||
|
void led_blink()
|
|||
|
{
|
|||
|
static bool blink_flag = 0;
|
|||
|
static blink_cnt = 0;
|
|||
|
blink_flag = ~blink_flag;
|
|||
|
blink_cnt += 1;
|
|||
|
gpio_pin_write(LED1_GPIO_PIN, blink_flag);
|
|||
|
if (blink_cnt == 6) {
|
|||
|
sys_timer_remove(blink_id);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void input_key_handler(u8 key_status, u8 key_number)
|
|||
|
{
|
|||
|
struct _switch press_switch;
|
|||
|
log_info("key_number=0x%x", key_number);
|
|||
|
|
|||
|
if ((key_number == 2) && (key_status == KEY_EVENT_CLICK)) {
|
|||
|
|
|||
|
log_info("\n <bt_mesh_reset> \n");
|
|||
|
struct __indicate_msg HardReset_msg = {
|
|||
|
.Opcode = buffer_head_init(VENDOR_MSG_ATTR_INDICAT),
|
|||
|
.TID = indicate_tid,
|
|||
|
.Attr_Type = 0xf009,
|
|||
|
.Event = 0x23,
|
|||
|
};
|
|||
|
struct bt_mesh_msg_ctx ctx = {
|
|||
|
.addr = 0xf000,
|
|||
|
};
|
|||
|
vendor_attr_status_send(&vendor_server_models[0], &ctx, &HardReset_msg, sizeof(HardReset_msg));
|
|||
|
blink_id = sys_timer_add(NULL, led_blink, 300);
|
|||
|
sys_timer_add(NULL, iot_reset, 1000 * 3);
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if ((key_number == 1) && (key_status == KEY_EVENT_LONG)) {
|
|||
|
power_set_soft_poweroff();
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if ((key_number == 0) && (key_status == KEY_EVENT_CLICK)) {
|
|||
|
led_set();
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
switch (key_status) {
|
|||
|
case KEY_EVENT_CLICK:
|
|||
|
log_info(" [KEY_EVENT_CLICK] ");
|
|||
|
press_switch.sw_num = key_number;
|
|||
|
press_switch.onoff_state = 1;
|
|||
|
button_pressed_worker(&press_switch);
|
|||
|
break;
|
|||
|
case KEY_EVENT_LONG:
|
|||
|
log_info(" [KEY_EVENT_LONG] ");
|
|||
|
press_switch.sw_num = key_number;
|
|||
|
press_switch.onoff_state = 0;
|
|||
|
button_pressed_worker(&press_switch);
|
|||
|
break;
|
|||
|
case KEY_EVENT_HOLD:
|
|||
|
log_info(" [KEY_EVENT_HOLD] ");
|
|||
|
break;
|
|||
|
default :
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
static void period_msg(void *empty)
|
|||
|
{
|
|||
|
struct bt_mesh_msg_ctx ctx = {
|
|||
|
.addr = 0xf000,
|
|||
|
};
|
|||
|
struct __onoff_repo period_indicat = {
|
|||
|
.Opcode = buffer_head_init(VENDOR_MSG_ATTR_INDICAT),
|
|||
|
.TID = indicate_tid,
|
|||
|
.Attr_Type = 0x0100, //设备开关状态,与generic onoff绑定
|
|||
|
.OnOff = led_flag,
|
|||
|
};
|
|||
|
|
|||
|
if (bt_mesh_is_provisioned()) {
|
|||
|
vendor_attr_status_send(&vendor_server_models[0], &ctx, &period_indicat, sizeof(period_indicat));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void iot_init()
|
|||
|
{
|
|||
|
if (bt_mesh_is_provisioned()) {
|
|||
|
indicate_tid_get(&indicate_tid);
|
|||
|
struct bt_mesh_msg_ctx ctx = {
|
|||
|
.addr = 0xf000,
|
|||
|
};
|
|||
|
struct __onoff_repo state_msg = {
|
|||
|
.Opcode = buffer_head_init(VENDOR_MSG_ATTR_INDICAT),
|
|||
|
.TID = indicate_tid,
|
|||
|
.Attr_Type = 0x0100, //设备开关状态,与generic onoff绑定
|
|||
|
.OnOff = led_flag,
|
|||
|
};
|
|||
|
vendor_attr_status_send(&vendor_server_models[0], &ctx, &state_msg, sizeof(state_msg));
|
|||
|
|
|||
|
indicate_tid_get(&indicate_tid);
|
|||
|
struct __indicate_msg indicate_msg = {
|
|||
|
.Opcode = buffer_head_init(VENDOR_MSG_ATTR_INDICAT),
|
|||
|
.TID = indicate_tid,
|
|||
|
.Attr_Type = 0xf009,
|
|||
|
.Event = 0x03,
|
|||
|
};
|
|||
|
vendor_attr_status_send(&vendor_server_models[0], &ctx, &indicate_msg, sizeof(indicate_msg));
|
|||
|
}
|
|||
|
sys_timer_add(NULL, period_msg, 180 * 1000);
|
|||
|
}
|
|||
|
|
|||
|
static void aligenie_app_key_set(u16_t app_key)
|
|||
|
{
|
|||
|
log_info("aligenie_app_key_set");
|
|||
|
mesh_mod_bind(root_models[1], app_key);
|
|||
|
mesh_mod_bind(vendor_server_models[0], app_key);
|
|||
|
}
|
|||
|
|
|||
|
static void aligenie_sub_set(struct bt_mesh_model *mod, u16_t sub_addr)
|
|||
|
{
|
|||
|
int i = 0;
|
|||
|
for (i = 0; i < ARRAY_SIZE(mod->groups); i++) {
|
|||
|
if (mod->groups[i] == BT_MESH_ADDR_UNASSIGNED) {
|
|||
|
mod->groups[i] = sub_addr;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (i != ARRAY_SIZE(mod->groups)) {
|
|||
|
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
|||
|
bt_mesh_model_sub_store(mod);
|
|||
|
}
|
|||
|
if (IS_ENABLED(CONFIG_BT_MESH_LOW_POWER)) {
|
|||
|
bt_mesh_lpn_group_add(sub_addr);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
static void aligenie_configuration()
|
|||
|
{
|
|||
|
aligenie_sub_set(&root_models[1], ALIGENIE_SUB_ADDR_1);
|
|||
|
aligenie_sub_set(&vendor_server_models[0], ALIGENIE_SUB_ADDR_1);
|
|||
|
aligenie_sub_set(&root_models[1], ALIGENIE_SUB_ADDR_2);
|
|||
|
aligenie_sub_set(&vendor_server_models[0], ALIGENIE_SUB_ADDR_2);
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* @brief Mesh Profile Setup
|
|||
|
*/
|
|||
|
/*-----------------------------------------------------------*/
|
|||
|
static void mesh_init(void)
|
|||
|
{
|
|||
|
log_info("--func=%s", __FUNCTION__);
|
|||
|
|
|||
|
#if (TMALL_UPDATE_TOOL == 0)
|
|||
|
static_auth_value_calculate();
|
|||
|
#endif
|
|||
|
|
|||
|
bt_conn_cb_register(bt_conn_get_callbacks());
|
|||
|
|
|||
|
int err = bt_mesh_init(&prov, &composition);
|
|||
|
if (err) {
|
|||
|
log_error("Initializing mesh failed (err %d)\n", err);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
|||
|
settings_load();
|
|||
|
}
|
|||
|
|
|||
|
bt_mesh_prov_enable(BT_MESH_PROV_GATT | BT_MESH_PROV_ADV);
|
|||
|
|
|||
|
mesh_app_key_add_callback_register(aligenie_app_key_set);
|
|||
|
|
|||
|
aligenie_configuration();
|
|||
|
|
|||
|
iot_init(); //indicate_state
|
|||
|
}
|
|||
|
|
|||
|
void bt_ble_init(void)
|
|||
|
{
|
|||
|
#if (TMALL_UPDATE_TOOL == 0)
|
|||
|
u8 bt_addr[6] = {MAC_TO_LITTLE_ENDIAN(CUR_DEVICE_MAC_ADDR)};
|
|||
|
|
|||
|
bt_mac_addr_set(bt_addr);
|
|||
|
#else
|
|||
|
void set_triad(u8 * uuid);
|
|||
|
set_triad(dev_uuid);
|
|||
|
#endif
|
|||
|
|
|||
|
mesh_setup(mesh_init);
|
|||
|
}
|
|||
|
|
|||
|
#endif /* (CONFIG_MESH_MODEL == SIG_MESH_ALIGENIE_SOCKET) */
|
|||
|
|