AC63_BT_SDK/apps/mesh/MshMDL/generic_onoff_srv.c

178 lines
5.6 KiB
C
Raw Normal View History

2025-02-18 15:40:42 +08:00
#include "btstack/bluetooth.h"
#include "system/includes.h"
#include "bt_common.h"
#include "api/sig_mesh_api.h"
#include "model_api.h"
#define LOG_TAG "[Mesh-OnOff_srv]"
#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_BT_MESH_GEN_ONOFF_SRV)
extern uint32_t btctler_get_rand_from_assign_range(uint32_t rand, uint32_t min, uint32_t max);
extern void pseudo_random_genrate(uint8_t *dest, unsigned size);
extern void gpio_pin_write(u8_t led_index, u8_t onoff);
/*
* 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);
/* 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)
#define LED0_GPIO_PIN 0
static struct onoff_state {
u8_t current;
u8_t previous;
u8_t led_gpio_pin;
};
struct onoff_state dev_onoff_state[] = {
{ .led_gpio_pin = LED0_GPIO_PIN },
};
const u8 led_use_port[] = {
IO_PORTA_01,
};
/*
* 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;
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,
};
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);
if (bt_mesh_model_send(model, ctx, &msg, &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);
#if 0
/*
* If a server has a publish address, it is required to
* publish status on a state change
*
* See Mesh Profile Specification 3.7.6.1.2
*
* Only publish if there is an assigned address
*/
if (onoff_state->previous != onoff_state->current &&
model->pub->addr != BT_MESH_ADDR_UNASSIGNED) {
log_info("publish last 0x%02x cur 0x%02x\n",
onoff_state->previous, onoff_state->current);
onoff_state->previous = 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);
err = bt_mesh_model_publish(model);
if (err) {
log_info("bt_mesh_model_publish err %d\n", err);
}
}
#endif /* */
}
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);
}
/*
* OnOff Model Server Op Dispatch Table
*
*/
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,
};
#endif