220 lines
5.8 KiB
C
220 lines
5.8 KiB
C
/*
|
|
* Copyright (c) 2019 Nordic Semiconductor ASA
|
|
*
|
|
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
|
|
*/
|
|
|
|
#include "api/gen_dtt_srv.h"
|
|
|
|
#if (CONFIG_BT_MESH_DTT_SRV)
|
|
|
|
#define LOG_TAG "[Gen_dtt_srv]"
|
|
#define LOG_ERROR_ENABLE
|
|
#define LOG_DEBUG_ENABLE
|
|
#define LOG_INFO_ENABLE
|
|
/* #define LOG_DUMP_ENABLE */
|
|
#define LOG_CLI_ENABLE
|
|
#include "debug.h"
|
|
|
|
static void encode_status(struct net_buf_simple *buf, uint32_t transition_time)
|
|
{
|
|
bt_mesh_model_msg_init(buf, BT_MESH_DTT_OP_STATUS);
|
|
net_buf_simple_add_u8(buf, model_transition_encode(transition_time));
|
|
}
|
|
|
|
static void rsp_status(struct bt_mesh_dtt_srv *srv,
|
|
struct bt_mesh_msg_ctx *rx_ctx)
|
|
{
|
|
BT_MESH_MODEL_BUF_DEFINE(msg, BT_MESH_DTT_OP_STATUS,
|
|
BT_MESH_DTT_MSG_LEN_STATUS);
|
|
encode_status(&msg, srv->transition_time);
|
|
|
|
(void)bt_mesh_model_send(srv->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_dtt_srv *srv = model->rt->user_data;
|
|
|
|
rsp_status(srv, ctx);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int set_dtt(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf, bool ack)
|
|
{
|
|
struct bt_mesh_dtt_srv *srv = model->rt->user_data;
|
|
uint32_t old_time = srv->transition_time;
|
|
uint32_t new_time = model_transition_decode(net_buf_simple_pull_u8(buf));
|
|
|
|
if (new_time == SYS_FOREVER_MS) {
|
|
/* Invalid parameter */
|
|
return -EINVAL;
|
|
}
|
|
|
|
srv->transition_time = new_time;
|
|
|
|
if (old_time != new_time && srv->update) {
|
|
srv->update(srv, ctx, old_time, srv->transition_time);
|
|
}
|
|
|
|
if (ack) {
|
|
rsp_status(srv, ctx);
|
|
}
|
|
|
|
if (IS_ENABLED(CONFIG_BT_MESH_DTT_SRV_PERSISTENT)) {
|
|
(void)bt_mesh_model_data_store(model, false, NULL,
|
|
&srv->transition_time,
|
|
sizeof(srv->transition_time));
|
|
}
|
|
|
|
(void)bt_mesh_dtt_srv_pub(srv, NULL);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int handle_set(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
|
|
struct net_buf_simple *buf)
|
|
{
|
|
return set_dtt(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 set_dtt(model, ctx, buf, false);
|
|
}
|
|
|
|
const struct bt_mesh_model_op _bt_mesh_dtt_srv_op[] = {
|
|
{
|
|
BT_MESH_DTT_OP_GET,
|
|
BT_MESH_LEN_EXACT(BT_MESH_DTT_MSG_LEN_GET),
|
|
handle_get,
|
|
},
|
|
{
|
|
BT_MESH_DTT_OP_SET,
|
|
BT_MESH_LEN_EXACT(BT_MESH_DTT_MSG_LEN_SET),
|
|
handle_set,
|
|
},
|
|
{
|
|
BT_MESH_DTT_OP_SET_UNACK,
|
|
BT_MESH_LEN_EXACT(BT_MESH_DTT_MSG_LEN_SET),
|
|
handle_set_unack,
|
|
},
|
|
BT_MESH_MODEL_OP_END,
|
|
};
|
|
|
|
static int update_handler(struct bt_mesh_model *model)
|
|
{
|
|
struct bt_mesh_dtt_srv *srv = model->rt->user_data;
|
|
|
|
encode_status(srv->model->pub->msg, srv->transition_time);
|
|
return 0;
|
|
}
|
|
|
|
static int bt_mesh_dtt_srv_init(struct bt_mesh_model *model)
|
|
{
|
|
struct bt_mesh_dtt_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_dtt_srv_reset(struct bt_mesh_model *model)
|
|
{
|
|
struct bt_mesh_dtt_srv *srv = model->rt->user_data;
|
|
|
|
srv->transition_time = 0;
|
|
|
|
if (IS_ENABLED(CONFIG_BT_MESH_DTT_SRV_PERSISTENT)) {
|
|
(void)bt_mesh_model_data_store(model, false, NULL, NULL, 0);
|
|
}
|
|
|
|
net_buf_simple_reset(model->pub->msg);
|
|
}
|
|
|
|
#ifdef CONFIG_BT_MESH_DTT_SRV_PERSISTENT
|
|
static int bt_mesh_dtt_srv_settings_set(struct bt_mesh_model *model,
|
|
const char *name,
|
|
size_t len_rd, settings_read_cb read_cb,
|
|
void *cb_arg)
|
|
{
|
|
struct bt_mesh_dtt_srv *srv = model->rt->user_data;
|
|
|
|
if (name) {
|
|
return -ENOENT;
|
|
}
|
|
|
|
ssize_t bytes = read_cb(cb_arg, &srv->transition_time,
|
|
sizeof(srv->transition_time));
|
|
if (bytes < 0) {
|
|
return bytes;
|
|
}
|
|
|
|
if (bytes != 0 && bytes != sizeof(srv->transition_time)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
const struct bt_mesh_model_cb _bt_mesh_dtt_srv_cb = {
|
|
.init = bt_mesh_dtt_srv_init,
|
|
.reset = bt_mesh_dtt_srv_reset,
|
|
#ifdef CONFIG_BT_MESH_DTT_SRV_PERSISTENT
|
|
.settings_set = bt_mesh_dtt_srv_settings_set,
|
|
#endif
|
|
};
|
|
|
|
void bt_mesh_dtt_srv_set(struct bt_mesh_dtt_srv *srv, uint32_t transition_time)
|
|
{
|
|
uint32_t old = srv->transition_time;
|
|
|
|
srv->transition_time = transition_time;
|
|
|
|
if (srv->update) {
|
|
srv->update(srv, NULL, old, srv->transition_time);
|
|
}
|
|
|
|
(void)bt_mesh_dtt_srv_pub(srv, NULL);
|
|
}
|
|
|
|
int bt_mesh_dtt_srv_pub(struct bt_mesh_dtt_srv *srv,
|
|
struct bt_mesh_msg_ctx *ctx)
|
|
{
|
|
BT_MESH_MODEL_BUF_DEFINE(msg, BT_MESH_DTT_OP_STATUS,
|
|
BT_MESH_DTT_MSG_LEN_STATUS);
|
|
encode_status(&msg, srv->transition_time);
|
|
|
|
return bt_mesh_msg_send(srv->model, ctx, &msg);
|
|
}
|
|
|
|
struct bt_mesh_dtt_srv *bt_mesh_dtt_srv_get(const struct bt_mesh_elem *elem)
|
|
{
|
|
const struct bt_mesh_comp *comp = bt_mesh_comp_get();
|
|
uint16_t index;
|
|
|
|
index = elem->rt->addr - comp->elem[0].rt->addr;
|
|
for (int i = index; i >= 0; --i) {
|
|
struct bt_mesh_elem *element = &comp->elem[i];
|
|
|
|
struct bt_mesh_model *model =
|
|
bt_mesh_model_find(element, BT_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_SRV);
|
|
|
|
if (model) {
|
|
return (struct bt_mesh_dtt_srv *)(model->rt->user_data);
|
|
}
|
|
};
|
|
|
|
return NULL;
|
|
}
|
|
|
|
#endif |