OVMS3-idf/components/bt/esp_ble_mesh/mesh_models/server/state_transition.c

1021 lines
37 KiB
C
Raw Normal View History

/* Bluetooth: Mesh Generic OnOff, Generic Level, Lighting & Vendor Models
*
* Copyright (c) 2018 Vikrant More
* Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "btc_ble_mesh_generic_model.h"
#include "btc_ble_mesh_lighting_model.h"
#include "btc_ble_mesh_time_scene_model.h"
#include "btc_ble_mesh_sensor_model.h"
#include "model_opcode.h"
#include "state_transition.h"
/* Function to calculate Remaining Time (Start) */
void bt_mesh_server_calc_remain_time(struct bt_mesh_state_transition *transition)
{
ble_mesh: Miscellaneous modifications 1. Add an API to set Provisioner static oob value 2. Add an API to deinit BLE Mesh stack 3. Add an API to set Provisioner unicast address 4. Add an API to provision devices with fixed address 5. Add an API to store node composition data 6. Add an API to get node with device uuid 7. Add an API to get node with unicast address 8. Add an API to delete node with device uuid 9. Add an API to delete node with unicast address 10. Add an API for Provisioner to update local AppKey 11. Add an API for Provisioner to update local NetKey 12. Support Provisioner persistent functionality 13. Fix Provisioner entering IV Update procedure 14. Fix an issue which may cause client failing to send msg 15. Use bt_mesh.flags to indicate device role 16. Remove several useless macros 17. Callback RSSI of received mesh provisioning packets 18. Modify the Provisioner disable function 19. Change some log level from debug to info 20. Add parameters to Provisioner bind AppKey completion event 21. Fix node ignoring relay messages issue 22. Support using a specific partition for BLE Mesh 23. Fix compile warning when proxy related macros are disabled 24. Clean up BLE Mesh stack included header files 25. NULL can be input if client message needs no parameters 26. Fix compile warning when BT log is disabled 27. Initilize BLE Mesh stack local variables 28. Support using PSRAM for BLE Mesh mutex, queue and task 29. Add a menuconfig option to enable using memory from PSRAM 30. Clean up sdkconfig.defaults of BLE Mesh examples
2020-01-19 10:57:13 +00:00
u8_t steps = 0U, resolution = 0U;
s32_t duration_remainder = 0;
s64_t now = 0;
if (transition->just_started) {
transition->remain_time = transition->trans_time;
} else {
now = k_uptime_get();
duration_remainder = transition->total_duration -
(now - transition->start_timestamp);
if (duration_remainder > 620000) {
/* > 620 seconds -> resolution = 0b11 [10 minutes] */
resolution = 0x03;
steps = duration_remainder / 600000;
} else if (duration_remainder > 62000) {
/* > 62 seconds -> resolution = 0b10 [10 seconds] */
resolution = 0x02;
steps = duration_remainder / 10000;
} else if (duration_remainder > 6200) {
/* > 6.2 seconds -> resolution = 0b01 [1 seconds] */
resolution = 0x01;
steps = duration_remainder / 1000;
} else if (duration_remainder > 0) {
/* <= 6.2 seconds -> resolution = 0b00 [100 ms] */
resolution = 0x00;
steps = duration_remainder / 100;
} else {
resolution = 0x00;
steps = 0x00;
}
transition->remain_time = (resolution << 6) | steps;
}
}
/* Function to calculate Remaining Time (End) */
static void tt_values_calculator(struct bt_mesh_state_transition *transition)
{
ble_mesh: Miscellaneous modifications 1. Add an API to set Provisioner static oob value 2. Add an API to deinit BLE Mesh stack 3. Add an API to set Provisioner unicast address 4. Add an API to provision devices with fixed address 5. Add an API to store node composition data 6. Add an API to get node with device uuid 7. Add an API to get node with unicast address 8. Add an API to delete node with device uuid 9. Add an API to delete node with unicast address 10. Add an API for Provisioner to update local AppKey 11. Add an API for Provisioner to update local NetKey 12. Support Provisioner persistent functionality 13. Fix Provisioner entering IV Update procedure 14. Fix an issue which may cause client failing to send msg 15. Use bt_mesh.flags to indicate device role 16. Remove several useless macros 17. Callback RSSI of received mesh provisioning packets 18. Modify the Provisioner disable function 19. Change some log level from debug to info 20. Add parameters to Provisioner bind AppKey completion event 21. Fix node ignoring relay messages issue 22. Support using a specific partition for BLE Mesh 23. Fix compile warning when proxy related macros are disabled 24. Clean up BLE Mesh stack included header files 25. NULL can be input if client message needs no parameters 26. Fix compile warning when BT log is disabled 27. Initilize BLE Mesh stack local variables 28. Support using PSRAM for BLE Mesh mutex, queue and task 29. Add a menuconfig option to enable using memory from PSRAM 30. Clean up sdkconfig.defaults of BLE Mesh examples
2020-01-19 10:57:13 +00:00
u8_t steps_multiplier = 0U, resolution = 0U;
resolution = (transition->trans_time >> 6);
steps_multiplier = (transition->trans_time & 0x3F);
switch (resolution) {
case 0: /* 100ms */
transition->total_duration = steps_multiplier * 100;
break;
case 1: /* 1 second */
transition->total_duration = steps_multiplier * 1000;
break;
case 2: /* 10 seconds */
transition->total_duration = steps_multiplier * 10000;
break;
case 3: /* 10 minutes */
transition->total_duration = steps_multiplier * 600000;
break;
}
transition->counter = ((float) transition->total_duration / 100);
if (transition->counter > BLE_MESH_DEVICE_SPECIFIC_RESOLUTION) {
transition->counter = BLE_MESH_DEVICE_SPECIFIC_RESOLUTION;
}
}
static void transition_time_values(struct bt_mesh_state_transition *transition,
u8_t trans_time, u8_t delay)
{
transition->trans_time = trans_time;
transition->delay = delay;
if (trans_time == 0U) {
return;
}
tt_values_calculator(transition);
transition->quo_tt = transition->total_duration / transition->counter;
}
void generic_onoff_tt_values(struct bt_mesh_gen_onoff_srv *srv,
u8_t trans_time, u8_t delay)
{
return transition_time_values(&srv->transition, trans_time, delay);
}
void generic_level_tt_values(struct bt_mesh_gen_level_srv *srv,
u8_t trans_time, u8_t delay)
{
transition_time_values(&srv->transition, trans_time, delay);
srv->tt_delta_level =
((float) (srv->state.level - srv->state.target_level) / srv->transition.counter);
}
void generic_power_level_tt_values(struct bt_mesh_gen_power_level_srv *srv,
u8_t trans_time, u8_t delay)
{
transition_time_values(&srv->transition, trans_time, delay);
srv->tt_delta_level =
((float) (srv->state->power_actual - srv->state->target_power_actual) / srv->transition.counter);
}
void light_lightness_actual_tt_values(struct bt_mesh_light_lightness_srv *srv,
u8_t trans_time, u8_t delay)
{
transition_time_values(&srv->actual_transition, trans_time, delay);
srv->tt_delta_lightness_actual =
((float) (srv->state->lightness_actual - srv->state->target_lightness_actual) / srv->actual_transition.counter);
}
void light_lightness_linear_tt_values(struct bt_mesh_light_lightness_srv *srv,
u8_t trans_time, u8_t delay)
{
transition_time_values(&srv->linear_transition, trans_time, delay);
srv->tt_delta_lightness_linear =
((float) (srv->state->lightness_linear - srv->state->target_lightness_linear) / srv->linear_transition.counter);
}
void light_ctl_tt_values(struct bt_mesh_light_ctl_srv *srv,
u8_t trans_time, u8_t delay)
{
transition_time_values(&srv->transition, trans_time, delay);
srv->tt_delta_lightness =
((float) (srv->state->lightness - srv->state->target_lightness) / srv->transition.counter);
srv->tt_delta_temperature =
((float) (srv->state->temperature - srv->state->target_temperature) / srv->transition.counter);
srv->tt_delta_delta_uv =
((float) (srv->state->delta_uv - srv->state->target_delta_uv) / srv->transition.counter);
}
void light_ctl_temp_tt_values(struct bt_mesh_light_ctl_temp_srv *srv,
u8_t trans_time, u8_t delay)
{
transition_time_values(&srv->transition, trans_time, delay);
srv->tt_delta_temperature =
((float) (srv->state->temperature - srv->state->target_temperature) / srv->transition.counter);
srv->tt_delta_delta_uv =
((float) (srv->state->delta_uv - srv->state->target_delta_uv) / srv->transition.counter);
}
void light_hsl_tt_values(struct bt_mesh_light_hsl_srv *srv,
u8_t trans_time, u8_t delay)
{
transition_time_values(&srv->transition, trans_time, delay);
srv->tt_delta_lightness =
((float) (srv->state->lightness - srv->state->target_lightness) / srv->transition.counter);
srv->tt_delta_hue =
((float) (srv->state->hue - srv->state->target_hue) / srv->transition.counter);
srv->tt_delta_saturation =
((float) (srv->state->saturation - srv->state->target_saturation) / srv->transition.counter);
}
void light_hsl_hue_tt_values(struct bt_mesh_light_hsl_hue_srv *srv,
u8_t trans_time, u8_t delay)
{
transition_time_values(&srv->transition, trans_time, delay);
srv->tt_delta_hue =
((float) (srv->state->hue - srv->state->target_hue) / srv->transition.counter);
}
void light_hsl_sat_tt_values(struct bt_mesh_light_hsl_sat_srv *srv,
u8_t trans_time, u8_t delay)
{
transition_time_values(&srv->transition, trans_time, delay);
srv->tt_delta_saturation =
((float) (srv->state->saturation - srv->state->target_saturation) / srv->transition.counter);
}
void light_xyl_tt_values(struct bt_mesh_light_xyl_srv *srv,
u8_t trans_time, u8_t delay)
{
transition_time_values(&srv->transition, trans_time, delay);
srv->tt_delta_lightness =
((float) (srv->state->lightness - srv->state->target_lightness) / srv->transition.counter);
srv->tt_delta_x =
((float) (srv->state->x - srv->state->target_x) / srv->transition.counter);
srv->tt_delta_y =
((float) (srv->state->y - srv->state->target_y) / srv->transition.counter);
}
void light_lc_tt_values(struct bt_mesh_light_lc_srv *srv,
u8_t trans_time, u8_t delay)
{
transition_time_values(&srv->transition, trans_time, delay);
}
void scene_tt_values(struct bt_mesh_scene_srv *srv, u8_t trans_time, u8_t delay)
{
transition_time_values(&srv->transition, trans_time, delay);
}
static void transition_timer_start(struct bt_mesh_state_transition *transition)
{
transition->start_timestamp = k_uptime_get();
k_delayed_work_submit_periodic(&transition->timer, K_MSEC(transition->quo_tt));
bt_mesh_atomic_set_bit(transition->flag, BLE_MESH_TRANS_TIMER_START);
}
static void transition_timer_stop(struct bt_mesh_state_transition *transition)
{
k_delayed_work_cancel(&transition->timer);
bt_mesh_atomic_clear_bit(transition->flag, BLE_MESH_TRANS_TIMER_START);
}
/* Timers related handlers & threads (Start) */
void generic_onoff_work_handler(struct k_work *work)
{
struct bt_mesh_gen_onoff_srv *srv =
CONTAINER_OF(work, struct bt_mesh_gen_onoff_srv, transition.timer.work);
struct bt_mesh_msg_ctx *ctx = NULL;
bt_mesh_gen_server_state_change_t change = {0};
if (srv == NULL || srv->transition.timer.work._reserved == NULL) {
BT_ERR("%s, Invalid parameter", __func__);
return;
}
bt_mesh_generic_server_lock();
ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved;
if (srv->transition.just_started) {
srv->transition.just_started = false;
if (srv->transition.counter == 0U) {
change.gen_onoff_set.onoff = srv->state.onoff;
bt_mesh_generic_server_cb_evt_to_btc(
BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change));
bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START);
} else {
/**
* Because binary states cannot support transitions, when changing to
* 0x01 (On), the Generic OnOff state shall change immediately when
* the transition starts, and when changing to 0x00, the state shall
* change when the transition finishes.
*/
if (srv->state.target_onoff == BLE_MESH_STATE_ON) {
srv->state.onoff = BLE_MESH_STATE_ON;
change.gen_onoff_set.onoff = srv->state.onoff;
bt_mesh_generic_server_cb_evt_to_btc(
BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change));
}
transition_timer_start(&srv->transition);
}
bt_mesh_generic_server_unlock();
return;
}
if (srv->transition.counter != 0U) {
srv->transition.counter--;
}
if (srv->transition.counter == 0U) {
transition_timer_stop(&srv->transition);
srv->state.onoff = srv->state.target_onoff;
if (srv->state.target_onoff != BLE_MESH_STATE_ON) {
change.gen_onoff_set.onoff = srv->state.onoff;
bt_mesh_generic_server_cb_evt_to_btc(
BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change));
}
}
gen_onoff_publish(srv->model);
bt_mesh_generic_server_unlock();
return;
}
void generic_level_work_handler(struct k_work *work)
{
struct bt_mesh_gen_level_srv *srv =
CONTAINER_OF(work, struct bt_mesh_gen_level_srv, transition.timer.work);
struct bt_mesh_msg_ctx *ctx = NULL;
bt_mesh_gen_server_state_change_t change = {0};
if (srv == NULL || srv->transition.timer.work._reserved == NULL) {
BT_ERR("%s, Invalid parameter", __func__);
return;
}
bt_mesh_generic_server_lock();
ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved;
if (srv->transition.just_started) {
srv->transition.just_started = false;
if (srv->transition.counter == 0U) {
switch (ctx->recv_op) {
case BLE_MESH_MODEL_OP_GEN_LEVEL_SET:
case BLE_MESH_MODEL_OP_GEN_LEVEL_SET_UNACK:
change.gen_level_set.level = srv->state.level;
break;
case BLE_MESH_MODEL_OP_GEN_DELTA_SET:
case BLE_MESH_MODEL_OP_GEN_DELTA_SET_UNACK:
change.gen_delta_set.level = srv->state.level;
break;
case BLE_MESH_MODEL_OP_GEN_MOVE_SET:
case BLE_MESH_MODEL_OP_GEN_MOVE_SET_UNACK:
change.gen_move_set.level = srv->state.level;
break;
}
bt_mesh_generic_server_cb_evt_to_btc(
BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change));
bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START);
} else {
transition_timer_start(&srv->transition);
}
bt_mesh_generic_server_unlock();
return;
}
if (srv->transition.counter != 0U) {
srv->transition.counter--;
srv->state.level -= srv->tt_delta_level;
}
if (srv->transition.counter == 0U) {
transition_timer_stop(&srv->transition);
srv->state.level = srv->state.target_level;
}
switch (ctx->recv_op) {
case BLE_MESH_MODEL_OP_GEN_LEVEL_SET:
case BLE_MESH_MODEL_OP_GEN_LEVEL_SET_UNACK:
change.gen_level_set.level = srv->state.level;
break;
case BLE_MESH_MODEL_OP_GEN_DELTA_SET:
case BLE_MESH_MODEL_OP_GEN_DELTA_SET_UNACK:
change.gen_delta_set.level = srv->state.level;
break;
case BLE_MESH_MODEL_OP_GEN_MOVE_SET:
case BLE_MESH_MODEL_OP_GEN_MOVE_SET_UNACK:
change.gen_move_set.level = srv->state.level;
break;
}
bt_mesh_generic_server_cb_evt_to_btc(
BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change));
gen_level_publish(srv->model);
bt_mesh_generic_server_unlock();
return;
}
void generic_power_level_work_handler(struct k_work *work)
{
struct bt_mesh_gen_power_level_srv *srv =
CONTAINER_OF(work, struct bt_mesh_gen_power_level_srv, transition.timer.work);
struct bt_mesh_msg_ctx *ctx = NULL;
bt_mesh_gen_server_state_change_t change = {0};
if (srv == NULL || srv->state == NULL ||
srv->transition.timer.work._reserved == NULL) {
BT_ERR("%s, Invalid parameter", __func__);
return;
}
bt_mesh_generic_server_lock();
ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved;
if (srv->transition.just_started) {
srv->transition.just_started = false;
if (srv->transition.counter == 0U) {
change.gen_power_level_set.power = srv->state->power_actual;
bt_mesh_generic_server_cb_evt_to_btc(
BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change));
bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START);
} else {
transition_timer_start(&srv->transition);
}
bt_mesh_generic_server_unlock();
return;
}
if (srv->transition.counter != 0U) {
srv->transition.counter--;
srv->state->power_actual -= srv->tt_delta_level;
}
if (srv->transition.counter == 0U) {
transition_timer_stop(&srv->transition);
srv->state->power_actual = srv->state->target_power_actual;
/**
* Whenever the Generic Power Actual state is changed to a non-zero value
* as a result of a non-transactional message or a completed sequence of
* transactional messages, the value of the Generic Power Last state shall
* be set to the value of the Generic Power Actual state.
*/
if (srv->state->power_actual) {
srv->state->power_last = srv->state->power_actual;
}
}
change.gen_power_level_set.power = srv->state->power_actual;
bt_mesh_generic_server_cb_evt_to_btc(
BTC_BLE_MESH_EVT_GENERIC_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change));
gen_power_level_publish(srv->model, BLE_MESH_MODEL_OP_GEN_POWER_LEVEL_STATUS);
bt_mesh_generic_server_unlock();
return;
}
void light_lightness_actual_work_handler(struct k_work *work)
{
struct bt_mesh_light_lightness_srv *srv =
CONTAINER_OF(work, struct bt_mesh_light_lightness_srv, actual_transition.timer.work);
struct bt_mesh_msg_ctx *ctx = NULL;
bt_mesh_light_server_state_change_t change = {0};
if (srv == NULL || srv->state == NULL ||
srv->actual_transition.timer.work._reserved == NULL) {
BT_ERR("%s, Invalid parameter", __func__);
return;
}
bt_mesh_light_server_lock();
ctx = (struct bt_mesh_msg_ctx *)srv->actual_transition.timer.work._reserved;
if (srv->actual_transition.just_started) {
srv->actual_transition.just_started = false;
if (srv->actual_transition.counter == 0U) {
change.lightness_set.lightness = srv->state->lightness_actual;
bt_mesh_lighting_server_cb_evt_to_btc(
BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change));
bt_mesh_atomic_clear_bit(srv->actual_transition.flag, BLE_MESH_TRANS_TIMER_START);
} else {
transition_timer_start(&srv->actual_transition);
}
bt_mesh_light_server_unlock();
return;
}
if (srv->actual_transition.counter != 0U) {
srv->actual_transition.counter--;
srv->state->lightness_actual -= srv->tt_delta_lightness_actual;
}
if (srv->actual_transition.counter == 0U) {
transition_timer_stop(&srv->actual_transition);
srv->state->lightness_actual = srv->state->target_lightness_actual;
/**
* Whenever the Light Lightness Actual state is changed with a non-
* transactional message or a completed sequence of transactional
* messages to a non-zero value, the value of the Light Lightness
* Last shall be set to the value of the Light Lightness Actual.
*/
if (srv->state->lightness_actual) {
srv->state->lightness_last = srv->state->lightness_actual;
}
}
change.lightness_set.lightness = srv->state->lightness_actual;
bt_mesh_lighting_server_cb_evt_to_btc(
BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change));
light_lightness_publish(srv->model, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_STATUS);
bt_mesh_light_server_unlock();
return;
}
void light_lightness_linear_work_handler(struct k_work *work)
{
struct bt_mesh_light_lightness_srv *srv =
CONTAINER_OF(work, struct bt_mesh_light_lightness_srv, linear_transition.timer.work);
struct bt_mesh_msg_ctx *ctx = NULL;
bt_mesh_light_server_state_change_t change = {0};
if (srv == NULL || srv->state == NULL ||
srv->linear_transition.timer.work._reserved == NULL) {
BT_ERR("%s, Invalid parameter", __func__);
return;
}
bt_mesh_light_server_lock();
ctx = (struct bt_mesh_msg_ctx *)srv->linear_transition.timer.work._reserved;
if (srv->linear_transition.just_started) {
srv->linear_transition.just_started = false;
if (srv->linear_transition.counter == 0U) {
change.lightness_linear_set.lightness = srv->state->lightness_linear;
bt_mesh_lighting_server_cb_evt_to_btc(
BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change));
bt_mesh_atomic_clear_bit(srv->linear_transition.flag, BLE_MESH_TRANS_TIMER_START);
} else {
transition_timer_start(&srv->linear_transition);
}
bt_mesh_light_server_unlock();
return;
}
if (srv->linear_transition.counter != 0U) {
srv->linear_transition.counter--;
srv->state->lightness_linear -= srv->tt_delta_lightness_linear;
}
if (srv->linear_transition.counter == 0U) {
transition_timer_stop(&srv->linear_transition);
srv->state->lightness_linear = srv->state->target_lightness_linear;
}
change.lightness_linear_set.lightness = srv->state->lightness_linear;
bt_mesh_lighting_server_cb_evt_to_btc(
BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change));
light_lightness_publish(srv->model, BLE_MESH_MODEL_OP_LIGHT_LIGHTNESS_LINEAR_STATUS);
bt_mesh_light_server_unlock();
return;
}
void light_ctl_work_handler(struct k_work *work)
{
struct bt_mesh_light_ctl_srv *srv =
CONTAINER_OF(work, struct bt_mesh_light_ctl_srv, transition.timer.work);
struct bt_mesh_msg_ctx *ctx = NULL;
bt_mesh_light_server_state_change_t change = {0};
if (srv == NULL || srv->state == NULL ||
srv->transition.timer.work._reserved == NULL) {
BT_ERR("%s, Invalid parameter", __func__);
return;
}
bt_mesh_light_server_lock();
ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved;
if (srv->transition.just_started) {
srv->transition.just_started = false;
if (srv->transition.counter == 0U) {
change.ctl_set.lightness = srv->state->lightness;
change.ctl_set.temperature = srv->state->temperature;
change.ctl_set.delta_uv = srv->state->delta_uv;
bt_mesh_lighting_server_cb_evt_to_btc(
BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change));
bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START);
} else {
transition_timer_start(&srv->transition);
}
bt_mesh_light_server_unlock();
return;
}
if (srv->transition.counter != 0U) {
srv->transition.counter--;
srv->state->lightness -= srv->tt_delta_lightness;
srv->state->temperature -= srv->tt_delta_temperature;
srv->state->delta_uv -= srv->tt_delta_delta_uv;
}
if (srv->transition.counter == 0U) {
transition_timer_stop(&srv->transition);
srv->state->lightness = srv->state->target_lightness;
srv->state->temperature = srv->state->target_temperature;
srv->state->delta_uv = srv->state->target_delta_uv;
}
change.ctl_set.lightness = srv->state->lightness;
change.ctl_set.temperature = srv->state->temperature;
change.ctl_set.delta_uv = srv->state->delta_uv;
bt_mesh_lighting_server_cb_evt_to_btc(
BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change));
light_ctl_publish(srv->model, BLE_MESH_MODEL_OP_LIGHT_CTL_STATUS);
bt_mesh_light_server_unlock();
return;
}
void light_ctl_temp_work_handler(struct k_work *work)
{
struct bt_mesh_light_ctl_temp_srv *srv =
CONTAINER_OF(work, struct bt_mesh_light_ctl_temp_srv, transition.timer.work);
struct bt_mesh_msg_ctx *ctx = NULL;
bt_mesh_light_server_state_change_t change = {0};
if (srv == NULL || srv->state == NULL ||
srv->transition.timer.work._reserved == NULL) {
BT_ERR("%s, Invalid parameter", __func__);
return;
}
bt_mesh_light_server_lock();
ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved;
if (srv->transition.just_started) {
srv->transition.just_started = false;
if (srv->transition.counter == 0U) {
change.ctl_temp_set.temperature = srv->state->temperature;
change.ctl_temp_set.delta_uv = srv->state->delta_uv;
bt_mesh_lighting_server_cb_evt_to_btc(
BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change));
bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START);
} else {
transition_timer_start(&srv->transition);
}
bt_mesh_light_server_unlock();
return;
}
if (srv->transition.counter != 0U) {
srv->transition.counter--;
srv->state->temperature -= srv->tt_delta_temperature;
srv->state->delta_uv -= srv->tt_delta_delta_uv;
}
if (srv->transition.counter == 0U) {
transition_timer_stop(&srv->transition);
srv->state->temperature = srv->state->target_temperature;
srv->state->delta_uv = srv->state->target_delta_uv;
}
change.ctl_temp_set.temperature = srv->state->temperature;
change.ctl_temp_set.delta_uv = srv->state->delta_uv;
bt_mesh_lighting_server_cb_evt_to_btc(
BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change));
light_ctl_publish(srv->model, BLE_MESH_MODEL_OP_LIGHT_CTL_TEMPERATURE_STATUS);
bt_mesh_light_server_unlock();
return;
}
void light_hsl_work_handler(struct k_work *work)
{
struct bt_mesh_light_hsl_srv *srv =
CONTAINER_OF(work, struct bt_mesh_light_hsl_srv, transition.timer.work);
struct bt_mesh_msg_ctx *ctx = NULL;
bt_mesh_light_server_state_change_t change = {0};
if (srv == NULL || srv->state == NULL ||
srv->transition.timer.work._reserved == NULL) {
BT_ERR("%s, Invalid parameter", __func__);
return;
}
bt_mesh_light_server_lock();
ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved;
if (srv->transition.just_started) {
srv->transition.just_started = false;
if (srv->transition.counter == 0U) {
change.hsl_set.lightness = srv->state->lightness;
change.hsl_set.hue = srv->state->hue;
change.hsl_set.saturation = srv->state->saturation;
bt_mesh_lighting_server_cb_evt_to_btc(
BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change));
bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START);
} else {
transition_timer_start(&srv->transition);
}
bt_mesh_light_server_unlock();
return;
}
if (srv->transition.counter != 0U) {
srv->transition.counter--;
srv->state->lightness -= srv->tt_delta_lightness;
srv->state->hue -= srv->tt_delta_hue;
srv->state->saturation -= srv->tt_delta_saturation;
}
if (srv->transition.counter == 0U) {
transition_timer_stop(&srv->transition);
srv->state->lightness = srv->state->target_lightness;
srv->state->hue = srv->state->target_hue;
srv->state->saturation = srv->state->target_saturation;
}
change.hsl_set.lightness = srv->state->lightness;
change.hsl_set.hue = srv->state->hue;
change.hsl_set.saturation = srv->state->saturation;
bt_mesh_lighting_server_cb_evt_to_btc(
BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change));
light_hsl_publish(srv->model, BLE_MESH_MODEL_OP_LIGHT_HSL_STATUS);
bt_mesh_light_server_unlock();
return;
}
void light_hsl_hue_work_handler(struct k_work *work)
{
struct bt_mesh_light_hsl_hue_srv *srv =
CONTAINER_OF(work, struct bt_mesh_light_hsl_hue_srv, transition.timer.work);
struct bt_mesh_msg_ctx *ctx = NULL;
bt_mesh_light_server_state_change_t change = {0};
if (srv == NULL || srv->state == NULL ||
srv->transition.timer.work._reserved == NULL) {
BT_ERR("%s, Invalid parameter", __func__);
return;
}
bt_mesh_light_server_lock();
ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved;
if (srv->transition.just_started) {
srv->transition.just_started = false;
if (srv->transition.counter == 0U) {
change.hsl_hue_set.hue = srv->state->hue;
bt_mesh_lighting_server_cb_evt_to_btc(
BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change));
bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START);
} else {
transition_timer_start(&srv->transition);
}
bt_mesh_light_server_unlock();
return;
}
if (srv->transition.counter != 0U) {
srv->transition.counter--;
srv->state->hue -= srv->tt_delta_hue;
}
if (srv->transition.counter == 0U) {
transition_timer_stop(&srv->transition);
srv->state->hue = srv->state->target_hue;
}
change.hsl_hue_set.hue = srv->state->hue;
bt_mesh_lighting_server_cb_evt_to_btc(
BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change));
light_hsl_publish(srv->model, BLE_MESH_MODEL_OP_LIGHT_HSL_HUE_STATUS);
bt_mesh_light_server_unlock();
return;
}
void light_hsl_sat_work_handler(struct k_work *work)
{
struct bt_mesh_light_hsl_sat_srv *srv =
CONTAINER_OF(work, struct bt_mesh_light_hsl_sat_srv, transition.timer.work);
struct bt_mesh_msg_ctx *ctx = NULL;
bt_mesh_light_server_state_change_t change = {0};
if (srv == NULL || srv->state == NULL ||
srv->transition.timer.work._reserved == NULL) {
BT_ERR("%s, Invalid parameter", __func__);
return;
}
bt_mesh_light_server_lock();
ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved;
if (srv->transition.just_started) {
srv->transition.just_started = false;
if (srv->transition.counter == 0U) {
change.hsl_saturation_set.saturation = srv->state->saturation;
bt_mesh_lighting_server_cb_evt_to_btc(
BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change));
bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START);
} else {
transition_timer_start(&srv->transition);
}
bt_mesh_light_server_unlock();
return;
}
if (srv->transition.counter != 0U) {
srv->transition.counter--;
srv->state->saturation -= srv->tt_delta_saturation;
}
if (srv->transition.counter == 0U) {
transition_timer_stop(&srv->transition);
srv->state->saturation = srv->state->target_saturation;
}
change.hsl_saturation_set.saturation = srv->state->saturation;
bt_mesh_lighting_server_cb_evt_to_btc(
BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change));
light_hsl_publish(srv->model, BLE_MESH_MODEL_OP_LIGHT_HSL_SATURATION_STATUS);
bt_mesh_light_server_unlock();
return;
}
void light_xyl_work_handler(struct k_work *work)
{
struct bt_mesh_light_xyl_srv *srv =
CONTAINER_OF(work, struct bt_mesh_light_xyl_srv, transition.timer.work);
struct bt_mesh_msg_ctx *ctx = NULL;
bt_mesh_light_server_state_change_t change = {0};
if (srv == NULL || srv->state == NULL ||
srv->transition.timer.work._reserved == NULL) {
BT_ERR("%s, Invalid parameter", __func__);
return;
}
bt_mesh_light_server_lock();
ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved;
if (srv->transition.just_started) {
srv->transition.just_started = false;
if (srv->transition.counter == 0U) {
change.xyl_set.lightness = srv->state->lightness;
change.xyl_set.x = srv->state->x;
change.xyl_set.y = srv->state->y;
bt_mesh_lighting_server_cb_evt_to_btc(
BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change));
bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START);
} else {
transition_timer_start(&srv->transition);
}
bt_mesh_light_server_unlock();
return;
}
if (srv->transition.counter != 0U) {
srv->transition.counter--;
srv->state->lightness -= srv->tt_delta_lightness;
srv->state->x -= srv->tt_delta_x;
srv->state->y -= srv->tt_delta_y;
}
if (srv->transition.counter == 0U) {
transition_timer_stop(&srv->transition);
srv->state->lightness = srv->state->target_lightness;
srv->state->x = srv->state->target_x;
srv->state->y = srv->state->target_y;
}
change.xyl_set.lightness = srv->state->lightness;
change.xyl_set.x = srv->state->x;
change.xyl_set.y = srv->state->y;
bt_mesh_lighting_server_cb_evt_to_btc(
BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change));
light_xyl_publish(srv->model, BLE_MESH_MODEL_OP_LIGHT_XYL_STATUS);
bt_mesh_light_server_unlock();
return;
}
void light_lc_work_handler(struct k_work *work)
{
struct bt_mesh_light_lc_srv *srv =
CONTAINER_OF(work, struct bt_mesh_light_lc_srv, transition.timer.work);
struct bt_mesh_msg_ctx *ctx = NULL;
bt_mesh_light_server_state_change_t change = {0};
if (srv == NULL || srv->transition.timer.work._reserved == NULL) {
BT_ERR("%s, Invalid parameter", __func__);
return;
}
bt_mesh_light_server_lock();
ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved;
if (srv->transition.just_started) {
srv->transition.just_started = false;
if (srv->transition.counter == 0U) {
change.lc_light_onoff_set.onoff = srv->lc->state.light_onoff;
bt_mesh_lighting_server_cb_evt_to_btc(
BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change));
bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START);
} else {
/**
* Because binary states cannot support transitions, when changing to
* 0x01 (On), the Generic OnOff state shall change immediately when
* the transition starts, and when changing to 0x00, the state shall
* change when the transition finishes.
*/
if (srv->lc->state.target_light_onoff == BLE_MESH_STATE_ON) {
srv->lc->state.light_onoff = BLE_MESH_STATE_ON;
bt_mesh_light_server_state_change_t change = {
.lc_light_onoff_set.onoff = srv->lc->state.light_onoff,
};
bt_mesh_lighting_server_cb_evt_to_btc(
BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change));
}
transition_timer_start(&srv->transition);
}
bt_mesh_light_server_unlock();
return;
}
if (srv->transition.counter != 0U) {
srv->transition.counter--;
}
if (srv->transition.counter == 0U) {
transition_timer_stop(&srv->transition);
srv->lc->state.light_onoff = srv->lc->state.target_light_onoff;
if (srv->lc->state.light_onoff != BLE_MESH_STATE_ON) {
change.lc_light_onoff_set.onoff = srv->lc->state.light_onoff;
bt_mesh_lighting_server_cb_evt_to_btc(
BTC_BLE_MESH_EVT_LIGHTING_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change));
}
}
light_lc_publish(srv->model, BLE_MESH_MODEL_OP_LIGHT_LC_LIGHT_ONOFF_STATUS);
bt_mesh_light_server_unlock();
return;
}
void scene_recall_work_handler(struct k_work *work)
{
struct bt_mesh_scene_srv *srv =
CONTAINER_OF(work, struct bt_mesh_scene_srv, transition.timer.work);
struct bt_mesh_msg_ctx *ctx = NULL;
bt_mesh_time_scene_server_state_change_t change = {0};
if (srv == NULL || srv->state == NULL ||
srv->transition.timer.work._reserved == NULL) {
BT_ERR("%s, Invalid parameter", __func__);
return;
}
bt_mesh_time_scene_server_lock();
ctx = (struct bt_mesh_msg_ctx *)srv->transition.timer.work._reserved;
if (srv->transition.just_started) {
srv->transition.just_started = false;
if (srv->transition.counter == 0U) {
change.scene_recall.scene_number = srv->state->current_scene;
bt_mesh_time_scene_server_cb_evt_to_btc(
BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change));
bt_mesh_atomic_clear_bit(srv->transition.flag, BLE_MESH_TRANS_TIMER_START);
} else {
transition_timer_start(&srv->transition);
}
bt_mesh_time_scene_server_unlock();
return;
}
if (srv->transition.counter != 0U) {
srv->transition.counter--;
}
if (srv->transition.counter == 0U) {
transition_timer_stop(&srv->transition);
srv->state->current_scene = srv->state->target_scene;
srv->state->in_progress = false;
srv->state->target_scene = INVALID_SCENE_NUMBER;
}
change.scene_recall.scene_number = srv->state->current_scene;
bt_mesh_time_scene_server_cb_evt_to_btc(
BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_STATE_CHANGE, srv->model, ctx, (const u8_t *)&change, sizeof(change));
scene_publish(srv->model, ctx, BLE_MESH_MODEL_OP_SCENE_STATUS);
bt_mesh_time_scene_server_unlock();
return;
}
/* Timers related handlers & threads (End) */
void bt_mesh_server_stop_transition(struct bt_mesh_state_transition *transition)
{
memset(transition, 0x0, offsetof(struct bt_mesh_state_transition, flag));
if (bt_mesh_atomic_test_and_clear_bit(transition->flag, BLE_MESH_TRANS_TIMER_START)) {
k_delayed_work_cancel(&transition->timer);
}
}
void bt_mesh_server_start_transition(struct bt_mesh_state_transition *transition)
{
if (transition->delay) {
k_delayed_work_submit(&transition->timer, K_MSEC(5 * transition->delay));
bt_mesh_atomic_set_bit(transition->flag, BLE_MESH_TRANS_TIMER_START);
} else {
k_work_submit(&transition->timer.work);
}
}
/* Messages handlers (End) */