AC63_BT_SDK/apps/mesh/MshMDL/model_utils.c

141 lines
3.9 KiB
C
Raw Normal View History

2025-02-18 15:40:42 +08:00
/*
* Copyright (c) 2019 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/
#include "btstack/bluetooth.h"
#include "system/includes.h"
#include "bt_common.h"
#include "api/sig_mesh_api.h"
#include "model_types.h"
#include "adaptation.h"
#define LOG_TAG "[Gen_model_utils]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
#define CONFIG_BT_MESH_MOD_ACKD_TIMEOUT_BASE 3000
#define CONFIG_BT_MESH_MOD_ACKD_TIMEOUT_PER_HOP 50
/** Unknown encoded transition time value */
#define TRANSITION_TIME_UNKNOWN (0x3F)
/** Delay field step factor in milliseconds */
#define DELAY_TIME_STEP_MS (5)
#define SYS_FOREVER_MS (-1)
static const u32_t model_transition_res[] = {
100,
1 * MSEC_PER_SEC,
10 * MSEC_PER_SEC,
60 * 10 * MSEC_PER_SEC,
};
s32_t model_transition_decode(u8_t encoded_transition)
{
u8_t steps = (encoded_transition & 0x3f);
u8_t res = (encoded_transition >> 6);
return (steps == TRANSITION_TIME_UNKNOWN) ?
SYS_FOREVER_MS :
(model_transition_res[res] * steps);
}
u8_t model_transition_encode(s32_t transition_time)
{
if (transition_time == 0) {
return 0;
}
if (transition_time == SYS_FOREVER_MS) {
return TRANSITION_TIME_UNKNOWN;
}
/* Even though we're only able to encode values up to 6200 ms in
* 100 ms step resolution, values between 6200 and 6600 ms are closer
* to 6200 ms than 7000 ms, which would be the nearest 1-second step
* representation. Similar cases exist for the other step resolutions
* too, so we'll use these custom limits instead of checking against
* the max value of each step resolution. The formula for the limit is
* ((0x3e * res[i]) + (((0x3e * res[i]) / res[i+1]) + 1) * res[i+1])/2.
*/
const s32_t limits[] = {
6600,
66 * MSEC_PER_SEC,
910 * MSEC_PER_SEC,
60 * 620 * MSEC_PER_SEC,
};
for (u8_t i = 0; i < ARRAY_SIZE(model_transition_res); ++i) {
if (transition_time > limits[i]) {
continue;
}
u8_t steps = ((transition_time + model_transition_res[i] / 2) /
model_transition_res[i]);
steps = MAX(1, steps);
steps = MIN(0x3e, steps);
return (i << 6) | steps;
}
return TRANSITION_TIME_UNKNOWN;
}
u8_t model_delay_encode(u32_t delay)
{
return delay / DELAY_TIME_STEP_MS;
}
s32_t model_delay_decode(u8_t encoded_delay)
{
return encoded_delay * DELAY_TIME_STEP_MS;
}
static inline void
model_transition_buf_add(struct net_buf_simple *buf,
const struct bt_mesh_model_transition *transition)
{
net_buf_simple_add_u8(buf, model_transition_encode(transition->time));
net_buf_simple_add_u8(buf, model_delay_encode(transition->delay));
}
s32_t model_ackd_timeout_get(const struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx)
{
u8_t ttl = (ctx ? ctx->send_ttl : model->pub->ttl);
s32_t time = (CONFIG_BT_MESH_MOD_ACKD_TIMEOUT_BASE +
ttl * CONFIG_BT_MESH_MOD_ACKD_TIMEOUT_PER_HOP);
return time;
}
bool bt_mesh_model_pub_is_unicast(const struct bt_mesh_model *model)
{
return model->pub && BT_MESH_ADDR_IS_UNICAST(model->pub->addr);
}
int tid_check_and_update(struct bt_mesh_tid_ctx *prev_transaction, uint8_t tid,
const struct bt_mesh_msg_ctx *ctx)
{
/* This updates the timestamp in the progress: */
int64_t uptime_delta = k_uptime_delta(&prev_transaction->timestamp);
if (prev_transaction->src == ctx->addr &&
prev_transaction->dst == ctx->recv_dst &&
prev_transaction->tid == tid && uptime_delta < 6000) {
return -EALREADY;
}
prev_transaction->src = ctx->addr;
prev_transaction->dst = ctx->recv_dst;
prev_transaction->tid = tid;
return 0;
}