AC63_BT_SDK/apps/mesh/MshMDL/gen_onoff_srv.c

242 lines
6.7 KiB
C
Raw Permalink Normal View History

2025-02-18 15:40:42 +08:00
#include "system/includes.h"
#include "bt_common.h"
#include "api/sig_mesh_api.h"
#include "api/gen_onoff.h"
#include "api/gen_onoff_srv.h"
#include "api/gen_onoff_internal.h"
#include "model_api.h"
#include "model_utils.h"
#define LOG_TAG "[Gen_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)
static void encode_status(struct net_buf_simple *buf,
const struct bt_mesh_onoff_status *status)
{
bt_mesh_model_msg_init(buf, BT_MESH_ONOFF_OP_STATUS);
net_buf_simple_add_u8(buf, !!status->present_on_off);
if (status->remaining_time != 0) {
net_buf_simple_add_u8(buf, status->target_on_off);
net_buf_simple_add_u8(
buf, model_transition_encode(status->remaining_time));
}
}
static void rsp_status(struct bt_mesh_model *model,
struct bt_mesh_msg_ctx *rx_ctx,
const struct bt_mesh_onoff_status *status)
{
BT_MESH_MODEL_BUF_DEFINE(msg, BT_MESH_ONOFF_OP_STATUS,
BT_MESH_ONOFF_MSG_MAXLEN_STATUS);
encode_status(&msg, status);
(void)bt_mesh_model_send(model, rx_ctx, &msg, NULL, NULL);
}
static int handle_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
struct bt_mesh_onoff_srv *srv = model->rt->user_data;
struct bt_mesh_onoff_status status = { 0 };
srv->handlers->get(srv, ctx, &status);
rsp_status(model, ctx, &status);
return 0;
}
static int onoff_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf, bool ack)
{
if (buf->len != BT_MESH_ONOFF_MSG_MINLEN_SET &&
buf->len != BT_MESH_ONOFF_MSG_MAXLEN_SET) {
return -EMSGSIZE;
}
struct bt_mesh_onoff_srv *srv = model->rt->user_data;
struct bt_mesh_onoff_status status = { 0 };
struct bt_mesh_model_transition transition;
struct bt_mesh_onoff_set set;
uint8_t on_off = net_buf_simple_pull_u8(buf);
uint8_t tid = net_buf_simple_pull_u8(buf);
if (on_off > 1) {
return -EINVAL;
}
set.on_off = on_off;
if (tid_check_and_update(&srv->prev_transaction, tid, ctx) != 0) {
/* If this is the same transaction, we don't need to send it
* to the app, but we still have to respond with a status.
*/
srv->handlers->get(srv, NULL, &status);
goto respond;
}
if (buf->len == 2) {
model_transition_buf_pull(buf, &transition);
set.transition = &transition;
} else if (!atomic_test_bit(&srv->flags, GEN_ONOFF_SRV_NO_DTT)) {
bt_mesh_dtt_srv_transition_get(srv->model, &transition);
set.transition = &transition;
} else {
set.transition = NULL;
}
srv->handlers->set(srv, ctx, &set, &status);
if (IS_ENABLED(CONFIG_BT_MESH_SCENE_SRV)) {
bt_mesh_scene_invalidate(srv->model);
}
(void)bt_mesh_onoff_srv_pub(srv, NULL, &status);
respond:
if (ack) {
rsp_status(model, ctx, &status);
}
return 0;
}
static int handle_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
return onoff_set(model, ctx, buf, true);
}
static int handle_set_unack(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
return onoff_set(model, ctx, buf, false);
}
const struct bt_mesh_model_op _bt_mesh_onoff_srv_op[] = {
{
BT_MESH_ONOFF_OP_GET,
BT_MESH_LEN_EXACT(BT_MESH_ONOFF_MSG_LEN_GET),
handle_get,
},
{
BT_MESH_ONOFF_OP_SET,
BT_MESH_LEN_MIN(BT_MESH_ONOFF_MSG_MINLEN_SET),
handle_set,
},
{
BT_MESH_ONOFF_OP_SET_UNACK,
BT_MESH_LEN_MIN(BT_MESH_ONOFF_MSG_MINLEN_SET),
handle_set_unack,
},
BT_MESH_MODEL_OP_END,
};
/* .. include_startingpoint_scene_srv_rst_1 */
static ssize_t scene_store(struct bt_mesh_model *model, uint8_t data[])
{
struct bt_mesh_onoff_srv *srv = model->rt->user_data;
struct bt_mesh_onoff_status status = { 0 };
/* Only store the next stable on_off state: */
srv->handlers->get(srv, NULL, &status);
data[0] = status.remaining_time ? status.target_on_off :
status.present_on_off;
return 1;
}
static void scene_recall(struct bt_mesh_model *model, const uint8_t data[],
size_t len, struct bt_mesh_model_transition *transition)
{
struct bt_mesh_onoff_srv *srv = model->rt->user_data;
struct bt_mesh_onoff_status status = { 0 };
struct bt_mesh_onoff_set set = {
.on_off = data[0],
.transition = transition,
};
srv->handlers->set(srv, NULL, &set, &status);
}
static void scene_recall_complete(struct bt_mesh_model *model)
{
struct bt_mesh_onoff_srv *srv = model->rt->user_data;
struct bt_mesh_onoff_status status = { 0 };
srv->handlers->get(srv, NULL, &status);
(void)bt_mesh_onoff_srv_pub(srv, NULL, &status);
}
// BT_MESH_SCENE_ENTRY_SIG(onoff) = {
// .id.sig = BT_MESH_MODEL_ID_GEN_ONOFF_SRV,
// .maxlen = 1,
// .store = scene_store,
// .recall = scene_recall,
// .recall_complete = scene_recall_complete,
// };
const struct bt_mesh_scene_entry bt_mesh_scene_entry_sig_onoff = {
.id.sig = BT_MESH_MODEL_ID_GEN_ONOFF_SRV,
.maxlen = 1,
.store = scene_store,
.recall = scene_recall,
.recall_complete = scene_recall_complete,
};
static int update_handler(struct bt_mesh_model *model)
{
struct bt_mesh_onoff_srv *srv = model->rt->user_data;
struct bt_mesh_onoff_status status = { 0 };
srv->handlers->get(srv, NULL, &status);
encode_status(model->pub->msg, &status);
return 0;
}
static int bt_mesh_onoff_srv_init(struct bt_mesh_model *model)
{
struct bt_mesh_onoff_srv *srv = model->rt->user_data;
srv->model = model;
srv->pub.msg = &srv->pub_buf;
srv->pub.update = update_handler;
net_buf_simple_init_with_data(&srv->pub_buf, srv->pub_data,
sizeof(srv->pub_data));
return 0;
}
static void bt_mesh_onoff_srv_reset(struct bt_mesh_model *model)
{
net_buf_simple_reset(model->pub->msg);
}
const struct bt_mesh_model_cb _bt_mesh_onoff_srv_cb = {
.init = bt_mesh_onoff_srv_init,
.reset = bt_mesh_onoff_srv_reset,
};
int bt_mesh_onoff_srv_pub(struct bt_mesh_onoff_srv *srv,
struct bt_mesh_msg_ctx *ctx,
const struct bt_mesh_onoff_status *status)
{
BT_MESH_MODEL_BUF_DEFINE(msg, BT_MESH_ONOFF_OP_STATUS,
BT_MESH_ONOFF_MSG_MAXLEN_STATUS);
encode_status(&msg, status);
return bt_mesh_msg_send(srv->model, ctx, &msg);
}
#endif