AC63_BT_SDK/apps/mesh/MshMDL/sensor_cli.c

1085 lines
30 KiB
C
Raw Normal View History

2025-02-18 15:40:42 +08:00
#include "adaptation.h"
#include <string.h>
#include <stdlib.h>
#include "net.h"
#include "transport.h"
#include "api/sensor.h"
#include "api/sensor_cli.h"
#include "api/properties.h"
#include "api/sensor_types.h"
#include <access.h>
#include "msg.h"
#if (CONFIG_BT_MESH_SENSOR_CLI)
#define LOG_TAG "[Mesh-sensor_cli]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
struct list_rsp {
struct bt_mesh_sensor_info *sensors;
uint32_t count;
};
struct settings_rsp {
uint16_t id;
uint16_t *ids;
uint32_t count;
};
struct setting_rsp {
uint16_t id;
uint16_t setting_id;
struct bt_mesh_sensor_setting_status *setting;
};
struct sensor_data_list_rsp {
struct bt_mesh_sensor_data *sensors;
uint32_t count;
};
struct series_data_rsp {
struct bt_mesh_sensor_series_entry *entries;
const struct bt_mesh_sensor_column *col;
uint16_t id;
uint32_t count;
};
struct cadence_rsp {
uint16_t id;
struct bt_mesh_sensor_cadence_status *cadence;
};
const struct bt_mesh_sensor_type *bt_mesh_sensor_type_get(uint16_t id)
{
// 遍历传感器类型列表
for (size_t i = 0; i < SENSOR_TYPE_LIST_SIZE; i++) {
if (sensor_type_list[i]->id == id) {
return sensor_type_list[i];
}
}
// 如果找不到匹配的 ID返回 NULL
return NULL;
}
static void unknown_type(struct bt_mesh_sensor_cli *cli,
struct bt_mesh_msg_ctx *ctx, uint16_t id, uint32_t op)
{
if (cli->cb && cli->cb->unknown_type) {
cli->cb->unknown_type(cli, ctx, id, op);
}
}
static int handle_descriptor_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
if (buf->len != 2 && buf->len % 8) {
return -EMSGSIZE;
}
struct bt_mesh_sensor_cli *cli = model->rt->user_data;
struct list_rsp *ack_ctx = NULL;
uint32_t count = 0;
(void)bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, BT_MESH_SENSOR_OP_DESCRIPTOR_STATUS,
ctx->addr, (void **)&ack_ctx);
/* A packet with only the sensor ID means that the given sensor doesn't
* exist on the sensor server.
*/
if (buf->len == 2) {
goto yield_ack;
}
struct bt_mesh_sensor_info sensor;
while (buf->len >= 8) {
sensor_descriptor_decode(buf, &sensor);
if (cli->cb && cli->cb->sensor) {
cli->cb->sensor(cli, ctx, &sensor);
}
if (ack_ctx && count < ack_ctx->count) {
ack_ctx->sensors[count++] = sensor;
}
}
yield_ack:
if (ack_ctx) {
ack_ctx->count = count;
bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx);
}
return 0;
}
static int handle_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
struct bt_mesh_sensor_cli *cli = model->rt->user_data;
struct sensor_data_list_rsp *rsp = NULL;
uint32_t count = 0;
int err;
(void)bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, BT_MESH_SENSOR_OP_STATUS, ctx->addr,
(void **)&rsp);
log_debug_hexdump(buf->data, buf->len);
while (buf->len) {
const struct bt_mesh_sensor_type *type;
uint8_t length;
uint16_t id;
sensor_status_id_decode(buf, &length, &id);
if (length == 0) {
if (rsp && rsp->count == 1 && rsp->sensors[0].type &&
rsp->sensors[0].type->id == id) {
rsp->sensors[0].type = NULL;
bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx);
rsp = NULL;
}
continue;
}
type = bt_mesh_sensor_type_get(id);
if (!type) {
if (buf->len < length) {
log_error("Invalid length for 0x%04x: %u", id,
length);
return -EMSGSIZE;
}
net_buf_simple_pull(buf, length);
unknown_type(cli, ctx, id, BT_MESH_SENSOR_OP_STATUS);
continue;
}
uint8_t expected_len = sensor_value_len(type);
if (length != expected_len) {
log_error("Invalid length for 0x%04x: %u (expected %u)",
id, length, expected_len);
return -EMSGSIZE;
}
struct sensor_value value[CONFIG_BT_MESH_SENSOR_CHANNELS_MAX];
err = sensor_value_decode(buf, type, value);
if (err) {
log_error("Invalid format, err=%d", err);
return err; /* Invalid format, should ignore message */
}
if (cli->cb && cli->cb->data) {
cli->cb->data(cli, ctx, type, value);
}
if (rsp && count <= rsp->count) {
memcpy(rsp->sensors[count].value, value,
sizeof(struct sensor_value) *
type->channel_count);
rsp->sensors[count].type = type;
++count;
}
}
if (rsp) {
rsp->count = count;
bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx);
}
return 0;
}
static int parse_series_entry(const struct bt_mesh_sensor_type *type,
const struct bt_mesh_sensor_format *col_format,
struct net_buf_simple *buf,
struct bt_mesh_sensor_series_entry *entry)
{
if (col_format == NULL) {
// Indexed column, decode only value
memset(entry, 0, sizeof(struct bt_mesh_sensor_series_entry));
return sensor_value_decode(buf, type, entry->value);
}
return sensor_column_decode(buf, type, &entry->column, entry->value);
}
static int handle_column_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
struct bt_mesh_sensor_cli *cli = model->rt->user_data;
struct series_data_rsp *rsp;
const struct bt_mesh_sensor_format *col_format;
const struct bt_mesh_sensor_type *type;
int err;
uint16_t id = net_buf_simple_pull_le16(buf);
type = bt_mesh_sensor_type_get(id);
if (!type) {
unknown_type(cli, ctx, id, BT_MESH_SENSOR_OP_COLUMN_STATUS);
return -ENOENT;
}
struct bt_mesh_sensor_series_entry entry;
col_format = bt_mesh_sensor_column_format_get(type);
err = parse_series_entry(type, col_format, buf, &entry);
if (err == -ENOENT) {
/* The entry doesn't exist */
goto yield_ack;
}
if (err) {
return err; /* Invalid format, should ignore message */
}
if (cli->cb && cli->cb->series_entry) {
cli->cb->series_entry(cli, ctx, type, 0, 1, &entry);
}
yield_ack:
if (bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, BT_MESH_SENSOR_OP_COLUMN_STATUS, ctx->addr,
(void **)&rsp)) {
/* If column format exists verify Raw Value A */
if (col_format &&
(rsp->col->start.val1 != entry.column.start.val1 ||
rsp->col->start.val2 != entry.column.start.val2)) {
return 0;
}
if (err) {
rsp->count = 0;
} else {
rsp->entries[0] = entry;
rsp->count = 1;
}
bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx);
}
return 0;
}
static int handle_series_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
struct bt_mesh_sensor_cli *cli = model->rt->user_data;
const struct bt_mesh_sensor_format *col_format;
const struct bt_mesh_sensor_type *type;
struct series_data_rsp *rsp = NULL;
uint16_t id = net_buf_simple_pull_le16(buf);
type = bt_mesh_sensor_type_get(id);
if (!type) {
unknown_type(cli, ctx, id, BT_MESH_SENSOR_OP_SERIES_STATUS);
return -ENOENT;
}
if (bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, BT_MESH_SENSOR_OP_SERIES_STATUS, ctx->addr,
(void **)&rsp)) {
if (rsp->id != id) {
rsp = NULL;
}
}
size_t val_len = sensor_value_len(type);
col_format = bt_mesh_sensor_column_format_get(type);
if (col_format != NULL) {
val_len += (col_format->size * 2);
}
if (!val_len) {
return -ENOTSUP;
}
uint8_t count = buf->len / val_len;
for (uint8_t i = 0; i < count; i++) {
struct bt_mesh_sensor_series_entry entry;
int err;
err = parse_series_entry(type, col_format, buf, &entry);
if (err) {
log_error("Failed parsing column %u (err: %d)", i, err);
return err;
}
if (cli->cb && cli->cb->series_entry) {
cli->cb->series_entry(cli, ctx, type, i, count, &entry);
}
if (rsp && i < rsp->count) {
rsp->entries[i] = entry;
}
}
if (rsp) {
rsp->count = count;
bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx);
}
return 0;
}
static int handle_cadence_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
struct bt_mesh_sensor_cli *cli = model->rt->user_data;
struct cadence_rsp *rsp;
int err;
uint16_t id = net_buf_simple_pull_le16(buf);
const struct bt_mesh_sensor_type *type = bt_mesh_sensor_type_get(id);
if (!type) {
unknown_type(cli, ctx, id, BT_MESH_SENSOR_OP_CADENCE_STATUS);
return -ENOENT;
}
if (buf->len == 0 || type->channel_count != 1) {
log_error("Type 0x%04x doesn't support cadence", id);
err = -ENOTSUP;
goto yield_ack;
}
struct bt_mesh_sensor_cadence_status cadence;
err = sensor_cadence_decode(buf, type, &cadence.fast_period_div,
&cadence.min_int, &cadence.threshold);
if (err) {
return err;
}
if (cli->cb && cli->cb->cadence) {
cli->cb->cadence(cli, ctx, type, &cadence);
}
yield_ack:
if (bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, BT_MESH_SENSOR_OP_CADENCE_STATUS, ctx->addr,
(void **)&rsp) &&
rsp->id == id) {
if (err) {
rsp->cadence = NULL;
} else {
*rsp->cadence = cadence;
}
bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx);
}
return 0;
}
static int handle_settings_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
struct bt_mesh_sensor_cli *cli = model->rt->user_data;
struct settings_rsp *rsp;
if (buf->len % 2) {
return -EMSGSIZE;
}
uint16_t id = net_buf_simple_pull_le16(buf);
const struct bt_mesh_sensor_type *type = bt_mesh_sensor_type_get(id);
if (!type) {
unknown_type(cli, ctx, id, BT_MESH_SENSOR_OP_SETTINGS_STATUS);
return -ENOENT;
}
/* The list may be unaligned: */
uint16_t ids[(BT_MESH_RX_SDU_MAX -
BT_MESH_MODEL_OP_LEN(BT_MESH_SENSOR_OP_SETTINGS_STATUS) -
2) /
sizeof(uint16_t)];
uint32_t count = buf->len / 2;
memcpy(ids, net_buf_simple_pull_mem(buf, buf->len),
count * sizeof(uint16_t));
if (cli->cb && cli->cb->settings) {
cli->cb->settings(cli, ctx, type, ids, count);
}
if (bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, BT_MESH_SENSOR_OP_SETTINGS_STATUS, ctx->addr,
(void **)&rsp) &&
rsp->id == id) {
memcpy(rsp->ids, ids, sizeof(uint16_t) * MIN(count, rsp->count));
rsp->count = count;
bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx);
}
return 0;
}
static int handle_setting_status(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
struct net_buf_simple *buf)
{
struct bt_mesh_sensor_cli *cli = model->rt->user_data;
struct setting_rsp *rsp;
int err;
uint16_t id = net_buf_simple_pull_le16(buf);
uint16_t setting_id = net_buf_simple_pull_le16(buf);
struct bt_mesh_sensor_setting_status setting = { 0 };
uint8_t access;
if (buf->len == 0) {
goto yield_ack;
}
access = net_buf_simple_pull_u8(buf);
if (access != 0x01 && access != 0x03) {
return -EINVAL;
}
const struct bt_mesh_sensor_type *type = bt_mesh_sensor_type_get(id);
if (!type) {
unknown_type(cli, ctx, id, BT_MESH_SENSOR_OP_SETTING_STATUS);
return -ENOENT;
}
setting.type = bt_mesh_sensor_type_get(setting_id);
if (!setting.type) {
unknown_type(
cli, ctx, setting_id, BT_MESH_SENSOR_OP_SETTING_STATUS);
return -ENOENT;
}
setting.writable = (access == 0x03);
/* If we attempted setting an unwritable value, the server omits the
* setting value. This is a legal response, but it should make the set()
* function return -EACCES.
*/
if (buf->len == 0 && !setting.writable) {
goto yield_ack;
}
err = sensor_value_decode(buf, setting.type, setting.value);
if (err) {
return err;
}
if (cli->cb && cli->cb->setting_status) {
cli->cb->setting_status(cli, ctx, type, &setting);
}
yield_ack:
if (bt_mesh_msg_ack_ctx_match(&cli->ack_ctx, BT_MESH_SENSOR_OP_SETTING_STATUS, ctx->addr,
(void **)&rsp) &&
rsp->id == id && rsp->setting_id == setting_id) {
*rsp->setting = setting;
bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx);
}
return 0;
}
const struct bt_mesh_model_op _bt_mesh_sensor_cli_op[] = {
{
BT_MESH_SENSOR_OP_DESCRIPTOR_STATUS,
BT_MESH_LEN_MIN(BT_MESH_SENSOR_MSG_MINLEN_DESCRIPTOR_STATUS),
handle_descriptor_status,
},
{
BT_MESH_SENSOR_OP_STATUS,
BT_MESH_LEN_MIN(BT_MESH_SENSOR_MSG_MINLEN_STATUS),
handle_status,
},
{
BT_MESH_SENSOR_OP_COLUMN_STATUS,
BT_MESH_LEN_MIN(BT_MESH_SENSOR_MSG_MINLEN_COLUMN_STATUS),
handle_column_status,
},
{
BT_MESH_SENSOR_OP_SERIES_STATUS,
BT_MESH_LEN_MIN(BT_MESH_SENSOR_MSG_MINLEN_SERIES_STATUS),
handle_series_status,
},
{
BT_MESH_SENSOR_OP_CADENCE_STATUS,
BT_MESH_LEN_MIN(BT_MESH_SENSOR_MSG_MINLEN_CADENCE_STATUS),
handle_cadence_status,
},
{
BT_MESH_SENSOR_OP_SETTINGS_STATUS,
BT_MESH_LEN_MIN(BT_MESH_SENSOR_MSG_MINLEN_SETTINGS_STATUS),
handle_settings_status,
},
{
BT_MESH_SENSOR_OP_SETTING_STATUS,
BT_MESH_LEN_MIN(BT_MESH_SENSOR_MSG_MINLEN_SETTING_STATUS),
handle_setting_status,
},
BT_MESH_MODEL_OP_END,
};
static int sensor_cli_init(struct bt_mesh_model *model)
{
struct bt_mesh_sensor_cli *cli = model->rt->user_data;
cli->model = model;
cli->pub.msg = &cli->pub_buf;
net_buf_simple_init_with_data(&cli->pub_buf, cli->pub_data,
sizeof(cli->pub_data));
bt_mesh_msg_ack_ctx_init(&cli->ack_ctx);
return 0;
}
static void sensor_cli_reset(struct bt_mesh_model *model)
{
struct bt_mesh_sensor_cli *cli = model->rt->user_data;
net_buf_simple_reset(cli->pub.msg);
bt_mesh_msg_ack_ctx_reset(&cli->ack_ctx);
}
const struct bt_mesh_model_cb _bt_mesh_sensor_cli_cb = {
.init = sensor_cli_init,
.reset = sensor_cli_reset,
};
int bt_mesh_sensor_cli_desc_all_get(struct bt_mesh_sensor_cli *cli,
struct bt_mesh_msg_ctx *ctx,
struct bt_mesh_sensor_info *sensors,
uint32_t *count)
{
int err;
BT_MESH_MODEL_BUF_DEFINE(msg, BT_MESH_SENSOR_OP_DESCRIPTOR_GET,
BT_MESH_SENSOR_MSG_MINLEN_DESCRIPTOR_GET);
bt_mesh_model_msg_init(&msg, BT_MESH_SENSOR_OP_DESCRIPTOR_GET);
struct list_rsp list_rsp = {
.sensors = sensors,
.count = count ? *count : 0,
};
struct bt_mesh_msg_rsp_ctx rsp_ctx = {
.ack = &cli->ack_ctx,
.op = BT_MESH_SENSOR_OP_DESCRIPTOR_STATUS,
.user_data = &list_rsp,
.timeout = model_ackd_timeout_get(cli->model, ctx),
};
err = bt_mesh_msg_ackd_send(cli->model, ctx, &msg, sensors ? &rsp_ctx : NULL);
if (count && !err) {
*count = list_rsp.count;
}
return err;
}
int bt_mesh_sensor_cli_desc_get(struct bt_mesh_sensor_cli *cli,
struct bt_mesh_msg_ctx *ctx,
const struct bt_mesh_sensor_type *sensor,
struct bt_mesh_sensor_descriptor *rsp)
{
int err;
BT_MESH_MODEL_BUF_DEFINE(msg, BT_MESH_SENSOR_OP_DESCRIPTOR_GET,
BT_MESH_SENSOR_MSG_MAXLEN_DESCRIPTOR_GET);
bt_mesh_model_msg_init(&msg, BT_MESH_SENSOR_OP_DESCRIPTOR_GET);
net_buf_simple_add_le16(&msg, sensor->id);
struct bt_mesh_sensor_info info = {
sensor->id,
};
struct list_rsp list_rsp = {
.sensors = &info,
.count = 1,
};
struct bt_mesh_msg_rsp_ctx rsp_ctx = {
.ack = &cli->ack_ctx,
.op = BT_MESH_SENSOR_OP_DESCRIPTOR_STATUS,
.user_data = &list_rsp,
.timeout = model_ackd_timeout_get(cli->model, ctx),
};
err = bt_mesh_msg_ackd_send(cli->model, ctx, &msg, rsp ? &rsp_ctx : NULL);
if (!rsp || err) {
return err;
}
if (list_rsp.count == 0) {
return -ENOTSUP;
}
*rsp = info.descriptor;
return 0;
}
int bt_mesh_sensor_cli_cadence_get(struct bt_mesh_sensor_cli *cli,
struct bt_mesh_msg_ctx *ctx,
const struct bt_mesh_sensor_type *sensor,
struct bt_mesh_sensor_cadence_status *rsp)
{
if (sensor->channel_count != 1) {
return -ENOTSUP;
}
int err;
BT_MESH_MODEL_BUF_DEFINE(msg, BT_MESH_SENSOR_OP_CADENCE_GET, 2);
bt_mesh_model_msg_init(&msg, BT_MESH_SENSOR_OP_CADENCE_GET);
net_buf_simple_add_le16(&msg, sensor->id);
struct cadence_rsp rsp_data = {
.id = sensor->id,
.cadence = rsp,
};
struct bt_mesh_msg_rsp_ctx rsp_ctx = {
.ack = &cli->ack_ctx,
.op = BT_MESH_SENSOR_OP_CADENCE_STATUS,
.user_data = &rsp_data,
.timeout = model_ackd_timeout_get(cli->model, ctx),
};
err = bt_mesh_msg_ackd_send(cli->model, ctx, &msg, rsp ? &rsp_ctx : NULL);
if (!rsp || err) {
return err;
}
/* Status handler clears the cadence member if server indicates that
* cadence isn't supported.
*/
if (!rsp_data.cadence) {
return -ENOTSUP;
}
return 0;
}
int bt_mesh_sensor_cli_cadence_set(
struct bt_mesh_sensor_cli *cli, struct bt_mesh_msg_ctx *ctx,
const struct bt_mesh_sensor_type *sensor,
const struct bt_mesh_sensor_cadence_status *cadence,
struct bt_mesh_sensor_cadence_status *rsp)
{
if (sensor->channel_count != 1) {
return -ENOTSUP;
}
int err;
BT_MESH_MODEL_BUF_DEFINE(msg, BT_MESH_SENSOR_OP_CADENCE_SET,
BT_MESH_SENSOR_MSG_MAXLEN_CADENCE_SET);
bt_mesh_model_msg_init(&msg, BT_MESH_SENSOR_OP_CADENCE_SET);
net_buf_simple_add_le16(&msg, sensor->id);
struct cadence_rsp rsp_data = {
.id = sensor->id,
.cadence = rsp,
};
err = sensor_cadence_encode(&msg, sensor, cadence->fast_period_div,
cadence->min_int, &cadence->threshold);
if (err) {
return err;
}
struct bt_mesh_msg_rsp_ctx rsp_ctx = {
.ack = &cli->ack_ctx,
.op = BT_MESH_SENSOR_OP_CADENCE_STATUS,
.user_data = &rsp_data,
.timeout = model_ackd_timeout_get(cli->model, ctx),
};
err = bt_mesh_msg_ackd_send(cli->model, ctx, &msg, rsp ? &rsp_ctx : NULL);
if (!rsp || err) {
return err;
}
/* Status handler clears the cadence member if server indicates that
* cadence isn't supported.
*/
if (!rsp_data.cadence) {
return -ENOTSUP;
}
return 0;
}
int bt_mesh_sensor_cli_cadence_set_unack(
struct bt_mesh_sensor_cli *cli, struct bt_mesh_msg_ctx *ctx,
const struct bt_mesh_sensor_type *sensor,
const struct bt_mesh_sensor_cadence_status *cadence)
{
if (sensor->channel_count != 1) {
return -ENOTSUP;
}
int err;
BT_MESH_MODEL_BUF_DEFINE(msg,
BT_MESH_SENSOR_OP_CADENCE_SET_UNACKNOWLEDGED,
BT_MESH_SENSOR_MSG_MAXLEN_CADENCE_SET);
bt_mesh_model_msg_init(&msg,
BT_MESH_SENSOR_OP_CADENCE_SET_UNACKNOWLEDGED);
net_buf_simple_add_le16(&msg, sensor->id);
err = sensor_cadence_encode(&msg, sensor, cadence->fast_period_div,
cadence->min_int, &cadence->threshold);
if (err) {
return err;
}
return bt_mesh_msg_send(cli->model, ctx, &msg);
}
int bt_mesh_sensor_cli_settings_get(struct bt_mesh_sensor_cli *cli,
struct bt_mesh_msg_ctx *ctx,
const struct bt_mesh_sensor_type *sensor,
uint16_t *ids, uint32_t *count)
{
int err;
BT_MESH_MODEL_BUF_DEFINE(msg, BT_MESH_SENSOR_OP_SETTINGS_GET,
BT_MESH_SENSOR_MSG_LEN_SETTINGS_GET);
bt_mesh_model_msg_init(&msg, BT_MESH_SENSOR_OP_SETTINGS_GET);
net_buf_simple_add_le16(&msg, sensor->id);
struct settings_rsp rsp = {
.id = sensor->id,
.ids = ids,
.count = count ? *count : 0,
};
struct bt_mesh_msg_rsp_ctx rsp_ctx = {
.ack = &cli->ack_ctx,
.op = BT_MESH_SENSOR_OP_SETTINGS_STATUS,
.user_data = &rsp,
.timeout = model_ackd_timeout_get(cli->model, ctx),
};
err = bt_mesh_msg_ackd_send(cli->model, ctx, &msg, ids ? &rsp_ctx : NULL);
if (!count || err) {
return err;
}
*count = rsp.count;
return err;
}
int bt_mesh_sensor_cli_setting_get(struct bt_mesh_sensor_cli *cli,
struct bt_mesh_msg_ctx *ctx,
const struct bt_mesh_sensor_type *sensor,
const struct bt_mesh_sensor_type *setting,
struct bt_mesh_sensor_setting_status *rsp)
{
int err;
BT_MESH_MODEL_BUF_DEFINE(msg, BT_MESH_SENSOR_OP_SETTING_GET,
BT_MESH_SENSOR_MSG_LEN_SETTING_GET);
bt_mesh_model_msg_init(&msg, BT_MESH_SENSOR_OP_SETTING_GET);
net_buf_simple_add_le16(&msg, sensor->id);
net_buf_simple_add_le16(&msg, setting->id);
struct setting_rsp rsp_data = {
.id = sensor->id,
.setting_id = setting->id,
.setting = rsp,
};
struct bt_mesh_msg_rsp_ctx rsp_ctx = {
.ack = &cli->ack_ctx,
.op = BT_MESH_SENSOR_OP_SETTING_STATUS,
.user_data = &rsp_data,
.timeout = model_ackd_timeout_get(cli->model, ctx),
};
err = bt_mesh_msg_ackd_send(cli->model, ctx, &msg, rsp ? &rsp_ctx : NULL);
if (!rsp || err) {
return err;
}
if (!rsp->type) {
return -ENOENT;
}
return 0;
}
int bt_mesh_sensor_cli_setting_set(struct bt_mesh_sensor_cli *cli,
struct bt_mesh_msg_ctx *ctx,
const struct bt_mesh_sensor_type *sensor,
const struct bt_mesh_sensor_type *setting,
const struct sensor_value *value,
struct bt_mesh_sensor_setting_status *rsp)
{
int err;
BT_MESH_MODEL_BUF_DEFINE(msg, BT_MESH_SENSOR_OP_SETTING_SET,
BT_MESH_SENSOR_MSG_MAXLEN_SETTING_SET);
bt_mesh_model_msg_init(&msg, BT_MESH_SENSOR_OP_SETTING_SET);
net_buf_simple_add_le16(&msg, sensor->id);
net_buf_simple_add_le16(&msg, setting->id);
err = sensor_value_encode(&msg, setting, value);
if (err) {
return err;
}
struct setting_rsp rsp_data = {
.id = sensor->id,
.setting_id = setting->id,
.setting = rsp,
};
struct bt_mesh_msg_rsp_ctx rsp_ctx = {
.ack = &cli->ack_ctx,
.op = BT_MESH_SENSOR_OP_SETTING_STATUS,
.user_data = &rsp_data,
.timeout = model_ackd_timeout_get(cli->model, ctx),
};
err = bt_mesh_msg_ackd_send(cli->model, ctx, &msg, rsp ? &rsp_ctx : NULL);
if (!rsp || err) {
return err;
}
if (!rsp->type) {
return -ENOENT;
}
if (!rsp->writable) {
return -EACCES;
}
return 0;
}
int bt_mesh_sensor_cli_setting_set_unack(
struct bt_mesh_sensor_cli *cli, struct bt_mesh_msg_ctx *ctx,
const struct bt_mesh_sensor_type *sensor,
const struct bt_mesh_sensor_type *setting,
const struct sensor_value *value)
{
int err;
BT_MESH_MODEL_BUF_DEFINE(msg, BT_MESH_SENSOR_OP_SETTING_SET_UNACKNOWLEDGED,
BT_MESH_SENSOR_MSG_MAXLEN_SETTING_SET);
bt_mesh_model_msg_init(&msg, BT_MESH_SENSOR_OP_SETTING_SET_UNACKNOWLEDGED);
net_buf_simple_add_le16(&msg, sensor->id);
net_buf_simple_add_le16(&msg, setting->id);
err = sensor_value_encode(&msg, setting, value);
if (err) {
return err;
}
return bt_mesh_msg_send(cli->model, ctx, &msg);
}
int bt_mesh_sensor_cli_all_get(struct bt_mesh_sensor_cli *cli,
struct bt_mesh_msg_ctx *ctx,
struct bt_mesh_sensor_data *sensors,
uint32_t *count)
{
int err;
BT_MESH_MODEL_BUF_DEFINE(msg, BT_MESH_SENSOR_OP_GET,
BT_MESH_SENSOR_MSG_MINLEN_GET);
bt_mesh_model_msg_init(&msg, BT_MESH_SENSOR_OP_GET);
struct sensor_data_list_rsp rsp_data = { .count = count ? *count : 0,
.sensors = sensors
};
if (sensors && count) {
memset(sensors, 0, sizeof(*sensors) * (*count));
}
struct bt_mesh_msg_rsp_ctx rsp_ctx = {
.ack = &cli->ack_ctx,
.op = BT_MESH_SENSOR_OP_STATUS,
.user_data = &rsp_data,
.timeout = model_ackd_timeout_get(cli->model, ctx),
};
err = bt_mesh_msg_ackd_send(cli->model, ctx, &msg, sensors ? &rsp_ctx : NULL);
if (!count || err) {
return err;
}
if (rsp_data.count == 0) {
return -ENODEV;
}
*count = rsp_data.count;
return 0;
}
int bt_mesh_sensor_cli_get(struct bt_mesh_sensor_cli *cli,
struct bt_mesh_msg_ctx *ctx,
const struct bt_mesh_sensor_type *sensor,
struct sensor_value *rsp)
{
int err;
BT_MESH_MODEL_BUF_DEFINE(msg, BT_MESH_SENSOR_OP_GET,
BT_MESH_SENSOR_MSG_MAXLEN_GET);
bt_mesh_model_msg_init(&msg, BT_MESH_SENSOR_OP_GET);
net_buf_simple_add_le16(&msg, sensor->id);
struct bt_mesh_sensor_data sensor_data = {
.type = sensor,
};
struct sensor_data_list_rsp rsp_data = { .count = 1,
.sensors = &sensor_data
};
struct bt_mesh_msg_rsp_ctx rsp_ctx = {
.ack = &cli->ack_ctx,
.op = BT_MESH_SENSOR_OP_STATUS,
.user_data = &rsp_data,
.timeout = model_ackd_timeout_get(cli->model, ctx),
};
err = bt_mesh_msg_ackd_send(cli->model, ctx, &msg, rsp ? &rsp_ctx : NULL);
if (!rsp || err) {
return err;
}
if (!sensor_data.type) {
return -ENODEV;
}
memcpy(rsp, sensor_data.value, sizeof(struct sensor_value) * sensor->channel_count);
return 0;
}
int bt_mesh_sensor_cli_series_entry_get(
struct bt_mesh_sensor_cli *cli, struct bt_mesh_msg_ctx *ctx,
const struct bt_mesh_sensor_type *sensor,
const struct bt_mesh_sensor_column *column,
struct bt_mesh_sensor_series_entry *rsp)
{
const struct bt_mesh_sensor_format *col_format;
int err;
BT_MESH_MODEL_BUF_DEFINE(msg, BT_MESH_SENSOR_OP_COLUMN_GET,
BT_MESH_SENSOR_MSG_MAXLEN_COLUMN_GET);
bt_mesh_model_msg_init(&msg, BT_MESH_SENSOR_OP_COLUMN_GET);
net_buf_simple_add_le16(&msg, sensor->id);
col_format = bt_mesh_sensor_column_format_get(sensor);
if (col_format == NULL) {
net_buf_simple_add_le16(&msg, column->start.val1);
} else {
err = sensor_ch_encode(&msg, col_format, &column->start);
if (err) {
return err;
}
}
struct series_data_rsp rsp_data = {
.entries = rsp,
.id = sensor->id,
.count = 1,
.col = column,
};
struct bt_mesh_msg_rsp_ctx rsp_ctx = {
.ack = &cli->ack_ctx,
.op = BT_MESH_SENSOR_OP_COLUMN_STATUS,
.user_data = &rsp_data,
.timeout = model_ackd_timeout_get(cli->model, ctx),
};
err = bt_mesh_msg_ackd_send(cli->model, ctx, &msg, rsp ? &rsp_ctx : NULL);
if (!rsp || err) {
return err;
}
if (rsp_data.count == 0) {
return -ENOENT;
}
return 0;
}
int bt_mesh_sensor_cli_series_entries_get(
struct bt_mesh_sensor_cli *cli, struct bt_mesh_msg_ctx *ctx,
const struct bt_mesh_sensor_type *sensor,
const struct bt_mesh_sensor_column *range,
struct bt_mesh_sensor_series_entry *rsp, uint32_t *count)
{
int err;
BT_MESH_MODEL_BUF_DEFINE(msg, BT_MESH_SENSOR_OP_SERIES_GET,
BT_MESH_SENSOR_MSG_MAXLEN_SERIES_GET);
bt_mesh_model_msg_init(&msg, BT_MESH_SENSOR_OP_SERIES_GET);
net_buf_simple_add_le16(&msg, sensor->id);
if (range) {
const struct bt_mesh_sensor_format *col_format;
col_format = bt_mesh_sensor_column_format_get(sensor);
if (!col_format) {
net_buf_simple_add_le16(&msg, range->start.val1);
net_buf_simple_add_le16(&msg, range->end.val1);
} else {
err = sensor_ch_encode(&msg, col_format, &range->start);
if (err) {
return err;
}
err = sensor_ch_encode(&msg, col_format, &range->end);
if (err) {
return err;
}
}
}
struct series_data_rsp rsp_data = {
.entries = rsp,
.id = sensor->id,
.count = count ? *count : 0,
};
struct bt_mesh_msg_rsp_ctx rsp_ctx = {
.ack = &cli->ack_ctx,
.op = BT_MESH_SENSOR_OP_SERIES_STATUS,
.user_data = &rsp_data,
.timeout = model_ackd_timeout_get(cli->model, ctx),
};
err = bt_mesh_msg_ackd_send(cli->model, ctx, &msg, rsp ? &rsp_ctx : NULL);
if (!count || err) {
return err;
}
*count = rsp_data.count;
return 0;
}
#endif