AC63_BT_SDK/apps/mesh/MshMDL/sensor_cli.c
2025-02-18 15:40:42 +08:00

1085 lines
30 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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