644 lines
20 KiB
C
644 lines
20 KiB
C
/*
|
|
* Copyright (c) 2020 Nordic Semiconductor ASA
|
|
*
|
|
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
|
|
*/
|
|
|
|
#include "adaptation.h"
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include "net.h"
|
|
#include "access.h"
|
|
#include "transport.h"
|
|
#include "api/properties.h"
|
|
#include "sensor.h"
|
|
|
|
#if (CONFIG_BT_MESH_SENSOR_SRV || CONFIG_BT_MESH_SENSOR_CLI)
|
|
|
|
#define LOG_TAG "[Mesh-sensor]"
|
|
#define LOG_ERROR_ENABLE
|
|
#define LOG_DEBUG_ENABLE
|
|
#define LOG_INFO_ENABLE
|
|
/* #define LOG_DUMP_ENABLE */
|
|
#define LOG_CLI_ENABLE
|
|
#include "debug.h"
|
|
|
|
/** Scale away the sensor_value fraction, to allow integer math */
|
|
#define SENSOR_MILL(_val) ((1000000LL * (_val)->val1) + (_val)->val2)
|
|
|
|
static enum bt_mesh_sensor_cadence
|
|
sensor_cadence(const struct bt_mesh_sensor_threshold *threshold,
|
|
const struct sensor_value *curr) {
|
|
int64_t high_mill = SENSOR_MILL(&threshold->range.high);
|
|
int64_t low_mill = SENSOR_MILL(&threshold->range.low);
|
|
|
|
if (high_mill == low_mill)
|
|
{
|
|
return BT_MESH_SENSOR_CADENCE_NORMAL;
|
|
}
|
|
|
|
int64_t curr_mill = SENSOR_MILL(curr);
|
|
bool in_range = (curr_mill >= MIN(low_mill, high_mill) &&
|
|
curr_mill <= MAX(low_mill, high_mill));
|
|
|
|
return in_range ? threshold->range.cadence : !threshold->range.cadence;
|
|
}
|
|
|
|
bool bt_mesh_sensor_delta_threshold(const struct bt_mesh_sensor *sensor,
|
|
const struct sensor_value *curr)
|
|
{
|
|
struct sensor_value delta = {
|
|
curr->val1 - sensor->state.prev.val1,
|
|
curr->val2 - sensor->state.prev.val2,
|
|
};
|
|
int64_t delta_mill = SENSOR_MILL(&delta);
|
|
int64_t thrsh_mill;
|
|
|
|
if (delta_mill < 0) {
|
|
delta_mill = -delta_mill;
|
|
thrsh_mill = SENSOR_MILL(&sensor->state.threshold.delta.down);
|
|
} else {
|
|
thrsh_mill = SENSOR_MILL(&sensor->state.threshold.delta.up);
|
|
}
|
|
|
|
/* If the threshold value is a perentage, we should calculate the actual
|
|
* threshold value relative to the previous value.
|
|
*/
|
|
if (sensor->state.threshold.delta.type ==
|
|
BT_MESH_SENSOR_DELTA_PERCENT) {
|
|
int64_t prev_mill = llabs(SENSOR_MILL(&sensor->state.prev));
|
|
|
|
thrsh_mill = (prev_mill * thrsh_mill) / (100LL * 1000000LL);
|
|
}
|
|
|
|
if (IS_ENABLED(CONFIG_BT_MESH_MODEL_LOG_LEVEL_DBG)) {
|
|
char delta_str[BT_MESH_SENSOR_CH_STR_LEN];
|
|
char curr_str[BT_MESH_SENSOR_CH_STR_LEN];
|
|
char prev_str[BT_MESH_SENSOR_CH_STR_LEN];
|
|
char thrsh_str[BT_MESH_SENSOR_CH_STR_LEN];
|
|
|
|
strcpy(delta_str, bt_mesh_sensor_ch_str(&delta));
|
|
strcpy(curr_str, bt_mesh_sensor_ch_str(curr));
|
|
strcpy(prev_str, bt_mesh_sensor_ch_str(&sensor->state.prev));
|
|
strcpy(thrsh_str,
|
|
delta_mill < 0 ? bt_mesh_sensor_ch_str(&sensor->state.threshold.delta.down) :
|
|
bt_mesh_sensor_ch_str(&sensor->state.threshold.delta.up));
|
|
|
|
log_debug("Delta: %s (%s - %s) thrsh: %s", delta_str, curr_str, prev_str, thrsh_str);
|
|
}
|
|
|
|
return (delta_mill > thrsh_mill);
|
|
}
|
|
|
|
void bt_mesh_sensor_cadence_set(struct bt_mesh_sensor *sensor,
|
|
enum bt_mesh_sensor_cadence cadence)
|
|
{
|
|
sensor->state.fast_pub = (cadence == BT_MESH_SENSOR_CADENCE_FAST);
|
|
}
|
|
|
|
int sensor_status_id_encode(struct net_buf_simple *buf, uint8_t len, uint16_t id)
|
|
{
|
|
if ((len > 0 && len <= 16) && id < 2048) {
|
|
if (net_buf_simple_tailroom(buf) < 2 + len) {
|
|
return -ENOMEM;
|
|
}
|
|
net_buf_simple_add_le16(buf, ((len - 1) << 1) | (id << 5));
|
|
log_debug_hexdump(buf->data, buf->len);
|
|
} else {
|
|
if (net_buf_simple_tailroom(buf) < 3 + len) {
|
|
return -ENOMEM;
|
|
}
|
|
net_buf_simple_add_u8(buf, BIT(0) | (((len - 1) & BIT_MASK(7))
|
|
<< 1));
|
|
net_buf_simple_add_le16(buf, id);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void sensor_status_id_decode(struct net_buf_simple *buf, uint8_t *len, uint16_t *id)
|
|
{
|
|
uint8_t first = net_buf_simple_pull_u8(buf);
|
|
if (first & BIT(0)) { /* long format */
|
|
if (buf->len < 2) {
|
|
*len = 0;
|
|
*id = BT_MESH_PROP_ID_PROHIBITED;
|
|
return;
|
|
}
|
|
*len = ((first >> 1) + 1) & 0x7f;
|
|
*id = net_buf_simple_pull_le16(buf);
|
|
} else if (buf->len < 1) {
|
|
*len = 0;
|
|
*id = BT_MESH_PROP_ID_PROHIBITED;
|
|
} else {
|
|
*len = ((first >> 1) & BIT_MASK(4)) + 1;
|
|
*id = (first >> 5) | (net_buf_simple_pull_u8(buf) << 3);
|
|
}
|
|
}
|
|
|
|
static void tolerance_decode(uint16_t encoded, struct sensor_value *tolerance)
|
|
{
|
|
uint32_t toll_mill = (encoded * 100ULL * 1000000ULL) / 4095ULL;
|
|
|
|
tolerance->val1 = toll_mill / 1000000ULL;
|
|
tolerance->val2 = toll_mill % 1000000ULL;
|
|
}
|
|
static uint16_t tolerance_encode(const struct sensor_value *tol)
|
|
{
|
|
uint64_t tol_mill = 1000000ULL * tol->val1 + tol->val2;
|
|
|
|
if (tol_mill > (1000000ULL * 100ULL)) {
|
|
return 0;
|
|
}
|
|
return (tol_mill * 4095ULL + (1000000ULL * 50ULL)) / (1000000ULL * 100ULL);
|
|
}
|
|
|
|
void sensor_descriptor_decode(struct net_buf_simple *buf,
|
|
struct bt_mesh_sensor_info *sensor)
|
|
{
|
|
uint32_t tolerances;
|
|
|
|
sensor->id = net_buf_simple_pull_le16(buf);
|
|
tolerances = net_buf_simple_pull_le24(buf);
|
|
tolerance_decode(tolerances & BIT_MASK(12),
|
|
&sensor->descriptor.tolerance.positive);
|
|
tolerance_decode(tolerances >> 12,
|
|
&sensor->descriptor.tolerance.negative);
|
|
sensor->descriptor.sampling_type = net_buf_simple_pull_u8(buf);
|
|
sensor->descriptor.period =
|
|
sensor_powtime_decode(net_buf_simple_pull_u8(buf));
|
|
sensor->descriptor.update_interval =
|
|
sensor_powtime_decode(net_buf_simple_pull_u8(buf));
|
|
}
|
|
|
|
void sensor_descriptor_encode(struct net_buf_simple *buf,
|
|
struct bt_mesh_sensor *sensor)
|
|
{
|
|
net_buf_simple_add_le16(buf, sensor->type->id);
|
|
|
|
const struct bt_mesh_sensor_descriptor dummy = { 0 };
|
|
const struct bt_mesh_sensor_descriptor *d =
|
|
sensor->descriptor ? sensor->descriptor : &dummy;
|
|
|
|
uint16_t tol_pos = tolerance_encode(&d->tolerance.positive);
|
|
uint16_t tol_neg = tolerance_encode(&d->tolerance.negative);
|
|
|
|
net_buf_simple_add_u8(buf, tol_pos & 0xff);
|
|
net_buf_simple_add_u8(buf,
|
|
((tol_pos >> 8) & BIT_MASK(4)) | (tol_neg << 4));
|
|
net_buf_simple_add_u8(buf, tol_neg >> 4);
|
|
net_buf_simple_add_u8(buf, d->sampling_type);
|
|
|
|
net_buf_simple_add_u8(buf, sensor_powtime_encode(d->period));
|
|
net_buf_simple_add_u8(buf, sensor_powtime_encode(d->update_interval));
|
|
}
|
|
|
|
int sensor_value_encode(struct net_buf_simple *buf,
|
|
const struct bt_mesh_sensor_type *type,
|
|
const struct sensor_value *values)
|
|
{
|
|
/* The API assumes that `values` array size is always CONFIG_BT_MESH_SENSOR_CHANNELS_MAX. */
|
|
__ASSERT_NO_MSG(type->channel_count <= CONFIG_BT_MESH_SENSOR_CHANNELS_MAX);
|
|
|
|
for (uint32_t i = 0; i < type->channel_count; ++i) {
|
|
int err;
|
|
|
|
err = sensor_ch_encode(buf, type->channels[i].format,
|
|
&values[i]);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sensor_value_decode(struct net_buf_simple *buf,
|
|
const struct bt_mesh_sensor_type *type,
|
|
struct sensor_value *values)
|
|
{
|
|
int err;
|
|
|
|
/* The API assumes that `values` array size is always CONFIG_BT_MESH_SENSOR_CHANNELS_MAX. */
|
|
__ASSERT_NO_MSG(type->channel_count <= CONFIG_BT_MESH_SENSOR_CHANNELS_MAX);
|
|
|
|
for (uint32_t i = 0; i < type->channel_count; ++i) {
|
|
err = sensor_ch_decode(buf, type->channels[i].format,
|
|
&values[i]);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sensor_ch_encode(struct net_buf_simple *buf,
|
|
const struct bt_mesh_sensor_format *format,
|
|
const struct sensor_value *value)
|
|
{
|
|
return format->encode(format, value, buf);
|
|
}
|
|
|
|
int sensor_ch_decode(struct net_buf_simple *buf,
|
|
const struct bt_mesh_sensor_format *format,
|
|
struct sensor_value *value)
|
|
{
|
|
return format->decode(format, buf, value);
|
|
}
|
|
|
|
int sensor_status_encode(struct net_buf_simple *buf,
|
|
const struct bt_mesh_sensor *sensor,
|
|
const struct sensor_value *values)
|
|
{
|
|
const struct bt_mesh_sensor_type *type = sensor->type;
|
|
size_t size = 0;
|
|
int err;
|
|
|
|
for (uint32_t i = 0; i < type->channel_count; ++i) {
|
|
size += type->channels[i].format->size;
|
|
}
|
|
err = sensor_status_id_encode(buf, size, type->id);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
return sensor_value_encode(buf, type, values);
|
|
}
|
|
|
|
const struct bt_mesh_sensor_format *
|
|
bt_mesh_sensor_column_format_get(const struct bt_mesh_sensor_type *type)
|
|
{
|
|
if (type->channel_count > 2) {
|
|
return type->channels[1].format;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int sensor_column_value_encode(struct net_buf_simple *buf,
|
|
struct bt_mesh_sensor_srv *srv,
|
|
struct bt_mesh_sensor *sensor,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
uint32_t column_index)
|
|
{
|
|
struct sensor_value values[CONFIG_BT_MESH_SENSOR_CHANNELS_MAX];
|
|
int err = sensor->series.get(srv, sensor, ctx, column_index, values);
|
|
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
return sensor_value_encode(buf, sensor->type, values);
|
|
}
|
|
|
|
int sensor_column_encode(struct net_buf_simple *buf,
|
|
struct bt_mesh_sensor_srv *srv,
|
|
struct bt_mesh_sensor *sensor,
|
|
struct bt_mesh_msg_ctx *ctx,
|
|
const struct bt_mesh_sensor_column *col)
|
|
{
|
|
int col_index = col - sensor->series.columns;
|
|
|
|
const struct bt_mesh_sensor_format *col_format;
|
|
const uint64_t width_million =
|
|
(col->end.val1 - col->start.val1) * 1000000ULL +
|
|
(col->end.val2 - col->start.val2);
|
|
const struct sensor_value width = {
|
|
.val1 = width_million / 1000000ULL,
|
|
.val2 = width_million % 1000000ULL,
|
|
};
|
|
int err;
|
|
|
|
log_debug("Column width: %s", bt_mesh_sensor_ch_str(&width));
|
|
|
|
col_format = bt_mesh_sensor_column_format_get(sensor->type);
|
|
if (!col_format) {
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
err = sensor_ch_encode(buf, col_format, &col->start);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
/* The sensor columns are transmitted as start+width, not start+end: */
|
|
err = sensor_ch_encode(buf, col_format, &width);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
return sensor_column_value_encode(buf, srv, sensor, ctx, col_index);
|
|
}
|
|
|
|
int sensor_column_decode(
|
|
struct net_buf_simple *buf, const struct bt_mesh_sensor_type *type,
|
|
struct bt_mesh_sensor_column *col,
|
|
struct sensor_value value[CONFIG_BT_MESH_SENSOR_CHANNELS_MAX])
|
|
{
|
|
const struct bt_mesh_sensor_format *col_format;
|
|
int err;
|
|
|
|
col_format = bt_mesh_sensor_column_format_get(type);
|
|
if (!col_format) {
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
err = sensor_ch_decode(buf, col_format, &col->start);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
if (buf->len == 0) {
|
|
log_error("The requested column didn't exist: %s",
|
|
bt_mesh_sensor_ch_str(&col->start));
|
|
return -ENOENT;
|
|
}
|
|
|
|
struct sensor_value width;
|
|
|
|
err = sensor_ch_decode(buf, col_format, &width);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
uint64_t end_mill = (col->start.val1 + width.val1) * 1000000ULL +
|
|
(col->start.val2 + width.val2);
|
|
|
|
col->end.val1 = end_mill / 1000000ULL;
|
|
col->end.val2 = end_mill % 1000000ULL;
|
|
|
|
return sensor_value_decode(buf, type, value);
|
|
}
|
|
|
|
uint8_t sensor_value_len(const struct bt_mesh_sensor_type *type)
|
|
{
|
|
uint8_t sum = 0;
|
|
|
|
for (int i = 0; i < type->channel_count; ++i) {
|
|
sum += type->channels[i].format->size;
|
|
}
|
|
|
|
return sum;
|
|
}
|
|
|
|
/* Several timer values in sensors are encoded in the following scheme:
|
|
*
|
|
* time = pow(1.1 seconds, encoded - 64)
|
|
*
|
|
* To keep the lookup table size and processing time down, this is implemented
|
|
* as a lookup table of the raw value corresponding to every 16th encoded value
|
|
* and a table of multiplicators. The values of the lookup table are
|
|
* pow(1.1, (index * 16) - 64) nanoseconds. The values of the multiplicator
|
|
* array are pow(1.1, index) * 100000. When multiplied by the values in
|
|
* the lookup, the result is pow(1.1, encoded - 64), because of the following
|
|
* property of powers:
|
|
*
|
|
* pow(A, B + C) = pow(A, B) * pow(A, C)
|
|
*
|
|
* Where in our case, A is 1.1, B is floor((encoded-64), 16) and C is
|
|
* (encoded % 16).
|
|
*/
|
|
static const uint64_t powtime_lookup[] = {
|
|
2243, 10307, 47362, 217629,
|
|
1000000, 4594972, 21113776, 97017233,
|
|
445791568, 2048400214, 9412343651, 43249464815,
|
|
198730122503, 913159544478, 4195943439113, 19280246755010,
|
|
};
|
|
|
|
static const uint32_t powtime_mul[] = {
|
|
100000, 110000, 121000, 133100, 146410, 161051, 177156, 194871,
|
|
214358, 235794, 259374, 285311, 313842, 345227, 379749, 417724,
|
|
};
|
|
|
|
uint8_t sensor_powtime_encode(uint64_t raw)
|
|
{
|
|
if (raw == 0) {
|
|
return 0;
|
|
}
|
|
|
|
/* Search through the lookup table to find the highest encoding lower
|
|
* than the raw value.
|
|
*/
|
|
uint64_t raw_us = raw * USEC_PER_MSEC;
|
|
|
|
if (raw_us < powtime_lookup[0]) {
|
|
return 1;
|
|
}
|
|
|
|
const uint64_t *seed = &powtime_lookup[ARRAY_SIZE(powtime_lookup) - 1];
|
|
|
|
for (int i = 1; i < ARRAY_SIZE(powtime_lookup); ++i) {
|
|
if (raw_us < powtime_lookup[i]) {
|
|
seed = &powtime_lookup[i - 1];
|
|
break;
|
|
}
|
|
}
|
|
|
|
int i;
|
|
|
|
for (i = 0; (i < ARRAY_SIZE(powtime_mul) &&
|
|
raw_us > (*seed * powtime_mul[i]) / 100000);
|
|
i++) {
|
|
}
|
|
|
|
uint8_t encoded = ARRAY_SIZE(powtime_mul) * (seed - &powtime_lookup[0]) + i;
|
|
|
|
return MIN(encoded, 253);
|
|
}
|
|
|
|
uint64_t sensor_powtime_decode_us(uint8_t val)
|
|
{
|
|
if (val == 0) {
|
|
return 0;
|
|
}
|
|
|
|
return (powtime_lookup[val / ARRAY_SIZE(powtime_mul)] *
|
|
powtime_mul[val % ARRAY_SIZE(powtime_mul)]) /
|
|
100000L;
|
|
}
|
|
|
|
uint64_t sensor_powtime_decode(uint8_t val)
|
|
{
|
|
return sensor_powtime_decode_us(val) / USEC_PER_MSEC;
|
|
}
|
|
|
|
int sensor_cadence_encode(struct net_buf_simple *buf,
|
|
const struct bt_mesh_sensor_type *sensor_type,
|
|
uint8_t fast_period_div, uint8_t min_int,
|
|
const struct bt_mesh_sensor_threshold *threshold)
|
|
{
|
|
net_buf_simple_add_u8(buf, ((!!threshold->delta.type) << 7) |
|
|
(BIT_MASK(7) & fast_period_div));
|
|
|
|
// for compiler, not used now.
|
|
// const struct bt_mesh_sensor_format *delta_format =
|
|
// (threshold->delta.type == BT_MESH_SENSOR_DELTA_PERCENT) ?
|
|
// &bt_mesh_sensor_format_percentage_delta_trigger :
|
|
// sensor_type->channels[0].format;
|
|
const struct bt_mesh_sensor_format *delta_format = sensor_type->channels[0].format;
|
|
int err;
|
|
|
|
err = sensor_ch_encode(buf, delta_format, &threshold->delta.down);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
err = sensor_ch_encode(buf, delta_format, &threshold->delta.up);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
if (min_int > BT_MESH_SENSOR_INTERVAL_MAX) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
net_buf_simple_add_u8(buf, min_int);
|
|
|
|
/* Flip the order if the cadence is fast outside. */
|
|
const struct sensor_value *first, *second;
|
|
|
|
if (threshold->range.cadence == BT_MESH_SENSOR_CADENCE_FAST) {
|
|
first = &threshold->range.low;
|
|
second = &threshold->range.high;
|
|
} else {
|
|
first = &threshold->range.high;
|
|
second = &threshold->range.low;
|
|
}
|
|
|
|
err = sensor_ch_encode(buf, sensor_type->channels[0].format, first);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
return sensor_ch_encode(buf, sensor_type->channels[0].format, second);
|
|
}
|
|
|
|
int sensor_cadence_decode(struct net_buf_simple *buf,
|
|
const struct bt_mesh_sensor_type *sensor_type,
|
|
uint8_t *fast_period_div, uint8_t *min_int,
|
|
struct bt_mesh_sensor_threshold *threshold)
|
|
{
|
|
const struct bt_mesh_sensor_format *delta_format;
|
|
uint8_t div_and_type;
|
|
int err;
|
|
|
|
div_and_type = net_buf_simple_pull_u8(buf);
|
|
threshold->delta.type = div_and_type >> 7;
|
|
*fast_period_div = div_and_type & BIT_MASK(7);
|
|
if (*fast_period_div > BT_MESH_SENSOR_PERIOD_DIV_MAX) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
// for compiler, not used now.
|
|
// delta_format = (threshold->delta.type == BT_MESH_SENSOR_DELTA_PERCENT) ?
|
|
// &bt_mesh_sensor_format_percentage_delta_trigger :
|
|
// sensor_type->channels[0].format;
|
|
|
|
delta_format = sensor_type->channels[0].format;
|
|
|
|
err = sensor_ch_decode(buf, delta_format, &threshold->delta.down);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
err = sensor_ch_decode(buf, delta_format, &threshold->delta.up);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
*min_int = net_buf_simple_pull_u8(buf);
|
|
if (*min_int > BT_MESH_SENSOR_INTERVAL_MAX) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
err = sensor_ch_decode(buf, sensor_type->channels[0].format,
|
|
&threshold->range.low);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
err = sensor_ch_decode(buf, sensor_type->channels[0].format,
|
|
&threshold->range.high);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
|
|
/* According to the Bluetooth Mesh Model Specification v1.0.1, Section
|
|
* 4.1.3.6, if range.high is lower than range.low, the cadence is fast
|
|
* outside the range. Swap the two in this case.
|
|
*/
|
|
if (threshold->range.high.val1 < threshold->range.low.val1 ||
|
|
(threshold->range.high.val1 == threshold->range.low.val1 &&
|
|
threshold->range.high.val2 < threshold->range.low.val2)) {
|
|
struct sensor_value temp;
|
|
|
|
temp = threshold->range.high;
|
|
threshold->range.high = threshold->range.low;
|
|
threshold->range.low = temp;
|
|
|
|
threshold->range.cadence = BT_MESH_SENSOR_CADENCE_NORMAL;
|
|
} else {
|
|
threshold->range.cadence = BT_MESH_SENSOR_CADENCE_FAST;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint8_t sensor_pub_div_get(const struct bt_mesh_sensor *s, uint32_t base_period)
|
|
{
|
|
uint8_t div = s->state.pub_div * s->state.fast_pub;
|
|
|
|
while (div != 0 && (base_period >> div) < (1 << s->state.min_int)) {
|
|
div--;
|
|
}
|
|
|
|
return div;
|
|
}
|
|
|
|
bool bt_mesh_sensor_value_in_column(const struct sensor_value *value,
|
|
const struct bt_mesh_sensor_column *col)
|
|
{
|
|
return (value->val1 > col->start.val1 ||
|
|
(value->val1 == col->start.val1 &&
|
|
value->val2 >= col->start.val2)) &&
|
|
(value->val1 < col->end.val1 ||
|
|
(value->val1 == col->end.val1 && value->val2 <= col->end.val2));
|
|
}
|
|
|
|
void sensor_cadence_update(struct bt_mesh_sensor *sensor,
|
|
const struct sensor_value *value)
|
|
{
|
|
enum bt_mesh_sensor_cadence new;
|
|
|
|
new = sensor_cadence(&sensor->state.threshold, value);
|
|
|
|
/** Use Fast Cadence Period Divisor when publishing when the change exceeds the delta,
|
|
* section 4.3.1.2.4.3, E15551 and E15886.
|
|
*/
|
|
if (new == BT_MESH_SENSOR_CADENCE_NORMAL) {
|
|
new = bt_mesh_sensor_delta_threshold(sensor, value) ?
|
|
BT_MESH_SENSOR_CADENCE_FAST : BT_MESH_SENSOR_CADENCE_NORMAL;
|
|
}
|
|
|
|
if (sensor->state.fast_pub != new) {
|
|
log_debug("0x%04x new cadence: %s", sensor->type->id,
|
|
(new == BT_MESH_SENSOR_CADENCE_FAST) ? "fast" :
|
|
"normal");
|
|
}
|
|
|
|
sensor->state.fast_pub = new;
|
|
}
|
|
|
|
const char *bt_mesh_sensor_ch_str(const struct sensor_value *ch)
|
|
{
|
|
static char str[BT_MESH_SENSOR_CH_STR_LEN];
|
|
|
|
if (bt_mesh_sensor_ch_to_str(ch, str, BT_MESH_SENSOR_CH_STR_LEN) <= 0) {
|
|
strcpy(str, "Unknown format");
|
|
}
|
|
|
|
return str;
|
|
}
|
|
|
|
#endif // CONFIG_BT_MESH_SENSOR_SRV
|