bleSDK_expansion_board/mesh/model/light/lights/mm_lights_hsl.c

2359 lines
86 KiB
C

/**
****************************************************************************************
* @file mm_lights_hsl.c
*
* @brief Mesh Model Light HSL Server Module
*
****************************************************************************************
*/
/**
****************************************************************************************
* @addtogroup MM_LIGHTS_HSL
* @{
****************************************************************************************
*/
/*
* INCLUDE FILES
****************************************************************************************
*/
#include "mm_itf.h"
#include "mm_gens.h"
#include "mm_lights.h"
/*
* DEFINES
****************************************************************************************
*/
/// Validity of information provided to the Replay Manager
#define MM_LIGHTS_HSL_REPLAY_MS (6000)
/*
* ENUMERATIONS
****************************************************************************************
*/
/// Bit field content for status_info value present in environment for Light HSL Server model
/// 8 7 6 5 4 3 2 1 0
/// +-----+-----------+-----------+----------+----------------+----------------+---------------+-------+
/// | RFU | Trans Sat | Trans Hue | Trans LN | Wait Sat Trans | Wait Hue Trans | Wait LN Trans | Relay |
/// +-----+-----------+-----------+----------+----------------+----------------+---------------+-------+
enum mm_lights_hsl_sinfo_bf
{
/// Relaying of sent status message is authorized
MM_LIGHTS_HSL_SINFO_RELAY_POS = 0,
MM_LIGHTS_HSL_SINFO_RELAY_BIT = (1 << MM_LIGHTS_HSL_SINFO_RELAY_POS),
/// Wait for transition event for Light HSL Lightness state
MM_LIGHTS_HSL_SINFO_WAIT_LN_POS = 1,
MM_LIGHTS_HSL_SINFO_WAIT_LN_BIT = (1 << MM_LIGHTS_HSL_SINFO_WAIT_LN_POS),
/// Wait for transition event for Light HSL Hue state
MM_LIGHTS_HSL_SINFO_WAIT_HUE_POS = 2,
MM_LIGHTS_HSL_SINFO_WAIT_HUE_BIT = (1 << MM_LIGHTS_HSL_SINFO_WAIT_HUE_POS),
/// Wait for transition event for Light HSL Saturation state
MM_LIGHTS_HSL_SINFO_WAIT_SAT_POS = 3,
MM_LIGHTS_HSL_SINFO_WAIT_SAT_BIT = (1 << MM_LIGHTS_HSL_SINFO_WAIT_SAT_POS),
/// Wait for transition start (either Light HSL Lightness or Light HSL Hue or Light HSL
/// Saturation)
MM_LIGHTS_HSL_SINFO_WAIT_LSB = 1,
MM_LIGHTS_HSL_SINFO_WAIT_MASK = 0x0E,
/// Transition for Light HSL Lightness state in progress
MM_LIGHTS_HSL_SINFO_TRANS_LN_POS = 4,
MM_LIGHTS_HSL_SINFO_TRANS_LN_BIT = (1 << MM_LIGHTS_HSL_SINFO_TRANS_LN_POS),
/// Transition for Light HSL Hue state in progress
MM_LIGHTS_HSL_SINFO_TRANS_HUE_POS = 5,
MM_LIGHTS_HSL_SINFO_TRANS_HUE_BIT = (1 << MM_LIGHTS_HSL_SINFO_TRANS_HUE_POS),
/// Transition for Light HSL Saturation state in progress
MM_LIGHTS_HSL_SINFO_TRANS_SAT_POS = 6,
MM_LIGHTS_HSL_SINFO_TRANS_SAT_BIT = (1 << MM_LIGHTS_HSL_SINFO_TRANS_SAT_POS),
/// Transition in progress mask
MM_LIGHTS_HSL_SINFO_TRANS_LSB = 4,
MM_LIGHTS_HSL_SINFO_TRANS_MASK = 0x70,
};
/// Bit field content for status_info value present in environment for Light HSL Hue Server
/// and Light HSL Saturation Server models
/// 7 1 0
/// +----------------------+-------+
/// | RFU | Relay |
/// +----------------------+-------+
enum mm_lights_hsl_sinfo_hs_bf
{
/// Relaying of sent status message is authorized
MM_LIGHTS_HSL_SINFO_HS_RELAY_POS = 0,
MM_LIGHTS_HSL_SINFO_HS_RELAY_BIT = (1 << MM_LIGHTS_HSL_SINFO_HS_RELAY_POS),
};
/*
* TYPE DEFINITIONS
****************************************************************************************
*/
typedef struct mm_lights_hsl_env mm_lights_hsl_env_t;
typedef struct mm_lights_hsls_env mm_lights_hsls_env_t;
typedef struct mm_lights_hslh_env mm_lights_hslh_env_t;
typedef struct mm_lights_hslsat_env mm_lights_hslsat_env_t;
/// Structure for Light HSL Server model environment
struct mm_lights_hsl_env
{
/// Basic model environment - Must be first element in the structure - DO NOT MOVE
mm_mdl_env_t env;
/// Timer for sending of publications
mesh_timer_t tmr_publi;
/// Publication period in milliseconds
uint32_t publi_period_ms;
/// Environment for replay protection mechanism
mm_replay_env_t replay_env;
/// Pointer to environment of associated Light HSL Hue model
mm_lights_hslh_env_t *p_env_hslh;
/// Pointer to environment of associated Light HSL Saturation model
mm_lights_hslsat_env_t *p_env_hslsat;
/// Delta value in case of move transition for Light HSL Lightness state value
int16_t move_delta;
/// Light HSL Lightness state value
uint16_t ln;
/// Target Light HSL Lightness state value
uint16_t ln_tgt;
/// Source address of set message that has triggered last or current transition
uint8_t status_dst_addr;
/// Application key local index to be used for transmission of Light HSL Status
/// or Light HSL Linear Status message
m_lid_t status_app_key_lid;
/// Status information bitfield (@see enum mm_lights_hsl_sinfo_bf)
uint8_t status_info;
};
/// Structure for Light HSL Setup Server model environment
struct mm_lights_hsls_env
{
/// Basic model environment - Must be first element in the structure - DO NOT MOVE
mm_mdl_env_t env;
/// Pointer to environment of associated Light HSL Server model
mm_lights_hsl_env_t *p_env_hsl;
};
/// Structure for Light HSL Hue Server model environment
struct mm_lights_hslh_env
{
/// Basic model environment - Must be first element in the structure - DO NOT MOVE
mm_mdl_env_t env;
/// Timer for sending of publications
mesh_timer_t tmr_publi;
/// Publication period in milliseconds
uint32_t publi_period_ms;
/// Pointer to environment of associated Light HSL model
mm_lights_hsl_env_t *p_env_hsl;
/// Delta value in case of move transition for Light HSL Hue state value
int16_t move_delta;
/// Light HSL Hue state value
uint16_t hue;
/// Target Light HSL Hue state value
uint16_t hue_tgt;
/// Light HSL Hue Min state value
uint16_t hue_min;
/// Light HSL Hue Max state value
uint16_t hue_max;
/// Light HSL Hue Default state value
uint16_t hue_dflt;
/// Source address of set message that has triggered last or current transition
uint8_t status_dst_addr;
/// Application key local index to be used for transmission of Light HSL Status
/// or Light HSL Linear Status message
m_lid_t status_app_key_lid;
/// Status information bitfield (@see enum mm_lights_hsl_sinfo_hs_bf)
uint8_t status_info;
};
/// Structure for Light HSL Saturation Server model environment
struct mm_lights_hslsat_env
{
/// Basic model environment - Must be first element in the structure - DO NOT MOVE
mm_mdl_env_t env;
/// Timer for sending of publications
mesh_timer_t tmr_publi;
/// Publication period in milliseconds
uint32_t publi_period_ms;
/// Pointer to environment of associated Light HSL model
mm_lights_hsl_env_t *p_env_hsl;
/// Delta value in case of move transition for Light HSL Hue state value
int16_t move_delta;
/// Light HSL Saturation state value
uint16_t sat;
/// Target Light HSL Saturation state value
uint16_t sat_tgt;
/// Light HSL Saturation Min state value
uint16_t sat_min;
/// Light HSL Saturation Max state value
uint16_t sat_max;
/// Light HSL Saturation Default state value
uint16_t sat_dflt;
/// Source address of set message that has triggered last or current transition
uint8_t status_dst_addr;
/// Application key local index to be used for transmission of Light HSL Status
/// or Light HSL Linear Status message
m_lid_t status_app_key_lid;
/// Status information bitfield (@see enum mm_lights_hsl_sinfo_hs_bf)
uint8_t status_info;
};
/*
* LOCAL FUNCTIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Prepare and send a Light HSL Status or Light HSL Target Status message.
* Note that both messages have the same content
*
* @param[in] p_env_hsl Pointer to Light HSL Server model environment
* @param[in] p_route_env Pointer to structure containing reception information provided
* by Mesh Profile for received request message
* @param[in] publish Indicate if message is sent as a publication (true) or as
* a response to a received request (false)
* @param[in] target True if Light HSL Target Status message, else false
****************************************************************************************
*/
__STATIC void mm_lights_hsl_send_status(mm_lights_hsl_env_t *p_env_hsl,
mm_route_env_t *p_route_env, bool publish, bool target)
{
// Get environment for Light Lightness HSL Hue Server model
mm_lights_hslh_env_t *p_env_hslh = p_env_hsl->p_env_hslh;
// Get environment for Light Lightness HSL Saturation Server model
mm_lights_hslsat_env_t *p_env_hslsat = p_env_hsl->p_env_hslsat;
// Pointer to the buffer that will contain the message
mesh_buf_t *p_buf_status;
// Remaining time
uint8_t ln_rem_time, hue_rem_time, sat_rem_time;
// Transition type
uint8_t ln_trans_type, hue_trans_type, sat_trans_type;
// Data length
uint8_t data_length;
// Check if a transition has been started and deduce data length
mm_bind_get_trans_info(p_env_hsl->env.grp_lid, &ln_trans_type, &ln_rem_time);
mm_bind_get_trans_info(p_env_hslh->env.grp_lid, &hue_trans_type, &hue_rem_time);
mm_bind_get_trans_info(p_env_hslsat->env.grp_lid, &sat_trans_type, &sat_rem_time);
// Deduce deduce data length
data_length = ((ln_trans_type != MM_TRANS_TYPE_NONE)
|| (hue_trans_type != MM_TRANS_TYPE_NONE)
|| (sat_trans_type != MM_TRANS_TYPE_NONE))
? MM_LIGHT_HSL_STATUS_LEN : MM_LIGHT_HSL_STATUS_MIN_LEN;
p_buf_status = mm_route_buf_alloc(data_length);
if (p_buf_status)
{
// Get pointer to data
uint8_t *p_data = MESH_BUF_DATA(p_buf_status);
// Get pointer to environment
mm_route_env_t *p_buf_env = (mm_route_env_t *)&p_buf_status->env;
// State value
uint16_t state;
// Remaining time
uint8_t rem_time = 0;
// Prepare environment
if (p_route_env)
{
memcpy(p_buf_env, p_route_env, sizeof(mm_route_env_t));
}
else if (!publish)
{
p_buf_env->app_key_lid = p_env_hsl->status_app_key_lid;
p_buf_env->u_addr.dst = p_env_hsl->status_dst_addr;
SETB(p_buf_env->info, MM_ROUTE_INFO_RELAY,
GETB(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_RELAY));
}
SETB(p_buf_env->info, MM_ROUTE_INFO_RX, 0);
SETB(p_buf_env->info, MM_ROUTE_INFO_PUBLISH, publish);
p_buf_env->mdl_lid = p_env_hsl->env.mdl_lid;
p_buf_env->opcode = (target) ? MM_MSG_LIGHT_HSL_TGT_STATUS
: MM_MSG_LIGHT_HSL_STATUS;
// Fill the message
if (target && (ln_trans_type != MM_TRANS_TYPE_NONE))
{
if (ln_trans_type == MM_TRANS_TYPE_MOVE)
{
state = (p_env_hsl->move_delta > 0)
? mm_lights_ln_get(p_env_hsl->env.elmt_idx, MM_STATE_LIGHT_LN_RANGE_MAX)
: mm_lights_ln_get(p_env_hsl->env.elmt_idx, MM_STATE_LIGHT_LN_RANGE_MIN);
rem_time = MM_TRANS_TIME_UNKNOWN;
}
else
{
state = p_env_hsl->ln_tgt;
}
}
else
{
state = p_env_hsl->ln;
}
write16p(p_data + MM_LIGHT_HSL_STATUS_LIGHTNESS_POS, state);
if (target && (hue_trans_type != MM_TRANS_TYPE_NONE))
{
if (hue_trans_type == MM_TRANS_TYPE_MOVE)
{
state = (p_env_hslh->move_delta > 0) ? p_env_hslh->hue_max : p_env_hslh->hue_min;
rem_time = MM_TRANS_TIME_UNKNOWN;
}
else
{
state = p_env_hslh->hue_tgt;
}
}
else
{
state = p_env_hslh->hue;
}
write16p(p_data + MM_LIGHT_HSL_STATUS_HUE_POS, state);
if (target && (sat_trans_type != MM_TRANS_TYPE_NONE))
{
if (sat_trans_type == MM_TRANS_TYPE_MOVE)
{
state = (p_env_hslsat->move_delta > 0) ? p_env_hslsat->sat_max : p_env_hslsat->sat_min;
rem_time = MM_TRANS_TIME_UNKNOWN;
}
else
{
state = p_env_hslsat->sat_tgt;
}
}
else
{
state = p_env_hslsat->sat;
}
write16p(p_data + MM_LIGHT_HSL_STATUS_SAT_POS, state);
if (data_length == MM_LIGHT_HSL_STATUS_LEN)
{
if (rem_time != MM_TRANS_TIME_UNKNOWN)
{
rem_time = co_max(co_max(ln_rem_time, hue_rem_time), sat_rem_time);
}
*(p_data + MM_LIGHT_HSL_STATUS_REM_TIME_POS) = rem_time;
}
// Send the message
mm_route_send(p_buf_status);
}
}
/**
****************************************************************************************
* @brief Prepare and send a Light HSL Hue Status message
*
* @param[in] p_env_hslsat Pointer to Light HSL Hue Server model environment
* @param[in] p_route_env Pointer to structure containing reception information provided
* by Mesh Profile for received request message
* @param[in] publish Indicate if message is sent as a publication (true) or as
* a response to a received request (false)
****************************************************************************************
*/
__STATIC void mm_lights_hsl_send_status_hue(mm_lights_hslh_env_t *p_env_hslh,
mm_route_env_t *p_route_env, bool publish)
{
// Pointer to the buffer that will contain the message
mesh_buf_t *p_buf_status;
// Remaining time
uint8_t rem_time;
// Transition type
uint8_t trans_type;
// Data length
uint8_t data_length;
// Check if a transition has been started
mm_bind_get_trans_info(p_env_hslh->env.grp_lid, &trans_type, &rem_time);
// Deduce deduce data length
data_length = (trans_type != MM_TRANS_TYPE_NONE)
? MM_LIGHT_HSL_HUE_STATUS_LEN : MM_LIGHT_HSL_HUE_STATUS_MIN_LEN;
p_buf_status = mm_route_buf_alloc(data_length);
if (p_buf_status)
{
// Get pointer to data
uint8_t *p_data = MESH_BUF_DATA(p_buf_status);
// Get pointer to environment
mm_route_env_t *p_buf_env = (mm_route_env_t *)&p_buf_status->env;
// Prepare environment
if (p_route_env)
{
memcpy(p_buf_env, p_route_env, sizeof(mm_route_env_t));
}
else if (!publish)
{
p_buf_env->app_key_lid = p_env_hslh->status_app_key_lid;
p_buf_env->u_addr.dst = p_env_hslh->status_dst_addr;
SETB(p_buf_env->info, MM_ROUTE_INFO_RELAY,
GETB(p_env_hslh->status_info, MM_LIGHTS_HSL_SINFO_RELAY));
}
SETB(p_buf_env->info, MM_ROUTE_INFO_RX, 0);
SETB(p_buf_env->info, MM_ROUTE_INFO_PUBLISH, publish);
p_buf_env->mdl_lid = p_env_hslh->env.mdl_lid;
p_buf_env->opcode = MM_MSG_LIGHT_HSL_HUE_STATUS;
// Fill the message
write16p(p_data + MM_LIGHT_HSL_HUE_STATUS_HUE_POS, p_env_hslh->hue);
if (data_length == MM_LIGHT_HSL_HUE_STATUS_LEN)
{
// Sent Target Light HSL Hue state values
uint16_t hue_tgt;
if (trans_type == MM_TRANS_TYPE_MOVE)
{
hue_tgt = (p_env_hslh->move_delta > 0) ? p_env_hslh->hue_max
: p_env_hslh->hue_min;
rem_time = MM_TRANS_TIME_UNKNOWN;
}
else
{
hue_tgt = p_env_hslh->hue_tgt;
}
write16p(p_data + MM_LIGHT_HSL_HUE_STATUS_TGT_HUE_POS, hue_tgt);
*(p_data + MM_LIGHT_HSL_HUE_STATUS_REM_TIME_POS) = rem_time;
}
// Send the message
mm_route_send(p_buf_status);
}
}
/**
****************************************************************************************
* @brief Prepare and send a Light HSL Saturation Status message
*
* @param[in] p_env_hslsat Pointer to Light HSL Saturation Server model environment
* @param[in] p_route_env Pointer to structure containing reception information provided
* by Mesh Profile for received request message
* @param[in] publish Indicate if message is sent as a publication (true) or as
* a response to a received request (false)
****************************************************************************************
*/
__STATIC void mm_lights_hsl_send_status_sat(mm_lights_hslsat_env_t *p_env_hslsat,
mm_route_env_t *p_route_env, bool publish)
{
// Pointer to the buffer that will contain the message
mesh_buf_t *p_buf_status;
// Remaining time
uint8_t rem_time;
// Transition type
uint8_t trans_type;
// Data length
uint8_t data_length;
// Check if a transition has been started
mm_bind_get_trans_info(p_env_hslsat->env.grp_lid, &trans_type, &rem_time);
// Deduce deduce data length
data_length = (trans_type != MM_TRANS_TYPE_NONE)
? MM_LIGHT_HSL_SAT_STATUS_LEN : MM_LIGHT_HSL_SAT_STATUS_MIN_LEN;
p_buf_status = mm_route_buf_alloc(data_length);
if (p_buf_status)
{
// Get pointer to data
uint8_t *p_data = MESH_BUF_DATA(p_buf_status);
// Get pointer to environment
mm_route_env_t *p_buf_env = (mm_route_env_t *)&p_buf_status->env;
// Prepare environment
if (p_route_env)
{
memcpy(p_buf_env, p_route_env, sizeof(mm_route_env_t));
}
else if (!publish)
{
p_buf_env->app_key_lid = p_env_hslsat->status_app_key_lid;
p_buf_env->u_addr.dst = p_env_hslsat->status_dst_addr;
SETB(p_buf_env->info, MM_ROUTE_INFO_RELAY,
GETB(p_env_hslsat->status_info, MM_LIGHTS_HSL_SINFO_RELAY));
}
SETB(p_buf_env->info, MM_ROUTE_INFO_RX, 0);
SETB(p_buf_env->info, MM_ROUTE_INFO_PUBLISH, publish);
p_buf_env->mdl_lid = p_env_hslsat->env.mdl_lid;
p_buf_env->opcode = MM_MSG_LIGHT_HSL_SAT_STATUS;
// Fill the message
write16p(p_data + MM_LIGHT_HSL_SAT_STATUS_SAT_POS, p_env_hslsat->sat);
if (data_length == MM_LIGHT_HSL_SAT_STATUS_LEN)
{
// Sent Target Light HSL Saturation state values
uint16_t sat_tgt;
if (trans_type == MM_TRANS_TYPE_MOVE)
{
sat_tgt = (p_env_hslsat->move_delta > 0) ? p_env_hslsat->sat_max
: p_env_hslsat->sat_min;
rem_time = MM_TRANS_TIME_UNKNOWN;
}
else
{
sat_tgt = p_env_hslsat->sat_tgt;
}
write16p(p_data + MM_LIGHT_HSL_SAT_STATUS_TGT_SAT_POS, sat_tgt);
*(p_data + MM_LIGHT_HSL_SAT_STATUS_REM_TIME_POS) = rem_time;
}
// Send the message
mm_route_send(p_buf_status);
}
}
/**
****************************************************************************************
* @brief Prepare and send a Light HSL Default Status message
*
* @param[in] p_env_hsl Pointer to Light HSL Server model environment
* @param[in] p_route_env Pointer to structure containing reception information provided
* by Mesh Profile for received request message
****************************************************************************************
*/
__STATIC void mm_lights_hsl_send_status_dflt(mm_lights_hsl_env_t *p_env_hsl,
mm_route_env_t *p_route_env)
{
// Pointer to the buffer that will contain the message
mesh_buf_t *p_buf_status = mm_route_buf_alloc_status(MM_LIGHT_HSL_DFLT_STATUS_LEN, p_route_env);
if (p_buf_status)
{
// Get environment for Light Lightness HSL Hue Server model
mm_lights_hslh_env_t *p_env_hslh = p_env_hsl->p_env_hslh;
// Get environment for Light Lightness HSL Saturation Server model
mm_lights_hslsat_env_t *p_env_hslsat = p_env_hsl->p_env_hslsat;
// Get pointer to data
uint8_t *p_data = MESH_BUF_DATA(p_buf_status);
// Get pointer to environment
mm_route_env_t *p_buf_env = (mm_route_env_t *)&p_buf_status->env;
// Prepare environment
p_buf_env->mdl_lid = p_env_hsl->env.mdl_lid;
p_buf_env->opcode = MM_MSG_LIGHT_HSL_DFLT_STATUS;
// Fill the message
write16p(p_data + MM_LIGHT_HSL_DFLT_STATUS_LIGHTNESS_POS,
mm_lights_ln_get(p_env_hsl->env.elmt_idx, MM_STATE_LIGHT_LN_DFLT));
write16p(p_data + MM_LIGHT_HSL_DFLT_STATUS_HUE_POS, p_env_hslh->hue_dflt);
write16p(p_data + MM_LIGHT_HSL_DFLT_STATUS_SAT_POS, p_env_hslsat->sat_dflt);
// Send the message
mm_route_send(p_buf_status);
}
}
/**
****************************************************************************************
* @brief Prepare and send a Light HSL Range Status message
*
* @param[in] p_env_hsl Pointer to Light HSL Server model environment
* @param[in] p_route_env Pointer to structure containing reception information provided
* by Mesh Profile for received request message
* @param[in] status Status sent in the Light HSL Status message
* (@see enum mm_status)
****************************************************************************************
*/
__STATIC void mm_lights_hsl_send_status_range(mm_lights_hsl_env_t *p_env_hsl,
mm_route_env_t *p_route_env,
uint8_t status)
{
// Pointer to the buffer that will contain the message
mesh_buf_t *p_buf_status = mm_route_buf_alloc_status(MM_LIGHT_HSL_RANGE_STATUS_LEN, p_route_env);
if (p_buf_status)
{
// Get environment for Light Lightness HSL Hue Server model
mm_lights_hslh_env_t *p_env_hslh = p_env_hsl->p_env_hslh;
// Get environment for Light Lightness HSL Saturation Server model
mm_lights_hslsat_env_t *p_env_hslsat = p_env_hsl->p_env_hslsat;
// Get pointer to data
uint8_t *p_data = MESH_BUF_DATA(p_buf_status);
// Get pointer to environment
mm_route_env_t *p_buf_env = (mm_route_env_t *)&p_buf_status->env;
// Prepare environment
p_buf_env->mdl_lid = p_env_hsl->env.mdl_lid;
p_buf_env->opcode = MM_MSG_LIGHT_HSL_RANGE_STATUS;
// Fill the message
*(p_data + MM_LIGHT_HSL_RANGE_STATUS_CODE_POS) = status;
write16p(p_data + MM_LIGHT_HSL_RANGE_STATUS_HUE_MIN_POS, p_env_hslh->hue_min);
write16p(p_data + MM_LIGHT_HSL_RANGE_STATUS_HUE_MAX_POS, p_env_hslh->hue_max);
write16p(p_data + MM_LIGHT_HSL_RANGE_STATUS_SAT_MIN_POS, p_env_hslsat->sat_min);
write16p(p_data + MM_LIGHT_HSL_RANGE_STATUS_SAT_MAX_POS, p_env_hslsat->sat_max);
// Send the message
mm_route_send(p_buf_status);
}
}
/**
****************************************************************************************
* @brief Publish Light HSL state value if sending of publications is enabled
*
* @param[in] p_env_hsl Pointer to Light HSL Server model environment
* @param[in] target Publish current state or target state
****************************************************************************************
*/
__STATIC void mm_lights_hsl_publish(mm_lights_hsl_env_t *p_env_hsl, bool target)
{
// Check if sending of publication is enabled
if (GETB(p_env_hsl->env.info, MM_INFO_PUBLI))
{
mm_lights_hsl_send_status(p_env_hsl, NULL, true, target);
}
}
/**
****************************************************************************************
* @brief Publish Light HSL Hue or Light HSL Saturation state value if sending of publications
* is enabled
*
* @param[in] p_env Pointer to Light HSL Hue/Saturation Server model environment
****************************************************************************************
*/
__STATIC void mm_lights_hsl_publish_hue_sat(mm_mdl_env_t *p_env)
{
// Check if sending of publication is enabled
if (GETB(p_env->info, MM_INFO_PUBLI))
{
if (p_env->model_id == MM_ID_LIGHTS_HSLH)
{
mm_lights_hsl_send_status_hue((mm_lights_hslh_env_t *)p_env, NULL, true);
}
else // (p_env->model_id == MM_ID_LIGHTS_HSLSAT)
{
mm_lights_hsl_send_status_sat((mm_lights_hslsat_env_t *)p_env, NULL, true);
}
}
}
/**
****************************************************************************************
* @brief Check if a Light HSL Status message must be sent and send it if it is the case
*
* @param[in] p_env_hsl Pointer to Light HSL Server model environment
* @param[in] event
****************************************************************************************
*/
__STATIC void mm_lights_hsl_check_status(mm_lights_hsl_env_t *p_env_hsl, uint8_t event)
{
if (!GETF(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_WAIT))
{
if (p_env_hsl->status_dst_addr != MESH_UNASSIGNED_ADDR)
{
// Send a response to the node that has required the transition
mm_lights_hsl_send_status(p_env_hsl, NULL, false, false);
p_env_hsl->status_dst_addr = MESH_UNASSIGNED_ADDR;
}
// Send a publication
mm_lights_hsl_publish(p_env_hsl, (event == MM_GRP_EVENT_TRANS_STARTED));
if (event == MM_GRP_EVENT_TRANS_STARTED)
{
SETF(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_WAIT,
GETF(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_TRANS));
}
else
{
SETF(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_WAIT, 0);
SETF(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_TRANS, 0);
}
}
}
/**
****************************************************************************************
* @brief Check if a Light HSL Hue Status message or a Light HSL Saturation Status message
* must be sent and send it if it is the case
*
* @param[in] p_env Pointer to Light HSL Hue/Saturation Server model environment
****************************************************************************************
*/
__STATIC void mm_lights_hsl_check_status_rsp_hue_sat(mm_mdl_env_t *p_env)
{
if (p_env->model_id == MM_ID_LIGHTS_HSLH)
{
// Get environment allocated for Light HSL Hue Server model
mm_lights_hslh_env_t *p_env_hslh = (mm_lights_hslh_env_t *)p_env;
if (p_env_hslh->status_dst_addr != MESH_UNASSIGNED_ADDR)
{
// Send a response to the node that has required the transition
mm_lights_hsl_send_status_hue(p_env_hslh, NULL, false);
p_env_hslh->status_dst_addr = MESH_UNASSIGNED_ADDR;
}
}
else
{
// Get environment allocated for Light HSL Saturation Server model
mm_lights_hslsat_env_t *p_env_hslsat = (mm_lights_hslsat_env_t *)p_env;
if (p_env_hslsat->status_dst_addr != MESH_UNASSIGNED_ADDR)
{
// Send a response to the node that has required the transition
mm_lights_hsl_send_status_sat(p_env_hslsat, NULL, false);
p_env_hslsat->status_dst_addr = MESH_UNASSIGNED_ADDR;
}
}
}
/*
* MESSAGE HANDLERS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Handler for Light HSL Set/Set Unacknowledged message
*
* @param[in] p_env Pointer to environment of model for which message has been received
* @param[in] p_buf Pointer to buffer containing the received message
* @param[in] p_route_env Pointer to routing information for the received buffer
****************************************************************************************
*/
__STATIC void mm_lights_hsl_handler_set(mm_lights_hsl_env_t *p_env_hsl, mesh_buf_t *p_buf,
mm_route_env_t *p_route_env)
{
do
{
// Get environment for Light Lightness HSL Hue Server model
mm_lights_hslh_env_t *p_env_hslh = p_env_hsl->p_env_hslh;
// Get environment for Light Lightness HSL Saturation Server model
mm_lights_hslsat_env_t *p_env_hslsat = p_env_hsl->p_env_hslsat;
// Check if a status message must be sent
bool send_status = (p_route_env->opcode == MM_MSG_LIGHT_HSL_SET);
// Get pointer to data
uint8_t *p_data = MESH_BUF_DATA(p_buf);
// TID value
uint8_t tid;
// Light HSL Lightness, Light HSL Hue and Light HSL Saturation value
uint16_t ln = read16p(p_data + MM_LIGHT_HSL_SET_LIGHTNESS_POS);
uint16_t hue = read16p(p_data + MM_LIGHT_HSL_SET_HUE_POS);
uint16_t sat = read16p(p_data + MM_LIGHT_HSL_SET_SAT_POS);
// Transition time
uint8_t trans_time;
// Delay
uint8_t delay;
// Check if Light CTL Hue and Light CTL Saturation state values are within the defined ranges
if ((hue > p_env_hslh->hue_max)
|| (hue < p_env_hslh->hue_min)
|| (sat > p_env_hslsat->sat_max)
|| (sat < p_env_hslsat->sat_min))
{
break;
}
tid = *(p_data + MM_LIGHT_CTL_SET_TID_POS);
// Check if request can be processed
if ((p_env_hsl->status_dst_addr != MESH_UNASSIGNED_ADDR)
|| (p_env_hslh->status_dst_addr != MESH_UNASSIGNED_ADDR)
|| (p_env_hslsat->status_dst_addr != MESH_UNASSIGNED_ADDR)
|| (mm_replay_is_retx(&p_env_hsl->replay_env, p_route_env->u_addr.src, tid)))
{
// Send a Light HSL Status message
if (send_status)
{
mm_lights_hsl_send_status(p_env_hsl, p_route_env, false, false);
}
break;
}
// Extract and check optional parameters if present
if (p_buf->data_len == MM_LIGHT_HSL_SET_LEN)
{
trans_time = (uint16_t)(*(p_data + MM_LIGHT_HSL_SET_TRANS_TIME_POS));
// Check received value
if (GETF(trans_time, MM_TRANS_TIME_STEP_NB) > MM_TRANS_TIME_STEPS_MAX)
{
// Drop the message
break;
}
delay = *(p_data + MM_LIGHT_HSL_SET_DELAY_POS);
}
else
{
trans_time = MM_TRANS_TIME_UNKNOWN;
delay = 0;
}
// Check if at least one of the states is modified
if ((ln == p_env_hsl->ln)
&& (hue == p_env_hslh->hue)
&& (sat == p_env_hslsat->sat))
{
// Send a Light HSL Status message
if (send_status)
{
mm_lights_hsl_send_status(p_env_hsl, p_route_env, false, false);
}
break;
};
if (send_status)
{
// Keep information for transmission of status
p_env_hsl->status_dst_addr = p_route_env->u_addr.src;
p_env_hsl->status_app_key_lid = p_route_env->app_key_lid;
SETB(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_RELAY,
GETB(p_route_env->info, MM_ROUTE_INFO_RELAY));
}
SETB(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_TRANS_LN, (ln != p_env_hsl->ln));
SETB(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_TRANS_HUE, (hue != p_env_hslh->hue));
SETB(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_TRANS_SAT, (sat != p_env_hslsat->sat));
SETF(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_WAIT,
GETF(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_TRANS));
if (ln != p_env_hsl->ln)
{
// Update target state
p_env_hsl->ln_tgt = ln;
// Inform the Binding Manager about new transition
mm_bind_trans_new(p_env_hsl->env.grp_lid, MM_TRANS_TYPE_CLASSIC, trans_time, delay);
}
if (hue != p_env_hslh->hue)
{
// Update target state
p_env_hslh->hue_tgt = hue;
// Inform the Binding Manager about new transition
mm_bind_trans_new(p_env_hslh->env.grp_lid, MM_TRANS_TYPE_CLASSIC, trans_time, delay);
}
if (sat != p_env_hslsat->sat)
{
// Update target state
p_env_hslsat->sat_tgt = sat;
// Inform the Binding Manager about new transition
mm_bind_trans_new(p_env_hslsat->env.grp_lid, MM_TRANS_TYPE_CLASSIC, trans_time, delay);
}
} while (0);
}
/**
****************************************************************************************
* @brief Handler for Light HSL Hue Set/Set Unacknowledged message
*
* @param[in] p_env Pointer to environment of model for which message has been received
* @param[in] p_buf Pointer to buffer containing the received message
* @param[in] p_route_env Pointer to routing information for the received buffer
****************************************************************************************
*/
__STATIC void mm_lights_hsl_handler_set_hue(mm_lights_hslh_env_t *p_env_hslh, mesh_buf_t *p_buf,
mm_route_env_t *p_route_env)
{
do
{
// Get pointer to environment for Light HSL Server model
mm_lights_hsl_env_t *p_env_hsl = p_env_hslh->p_env_hsl;
// Check if a status message must be sent
bool send_status = (p_route_env->opcode == MM_MSG_LIGHT_HSL_HUE_SET);
// Get pointer to data
uint8_t *p_data = MESH_BUF_DATA(p_buf);
// TID value
uint8_t tid;
// Received Light CTL Hue state values
uint16_t hue = read16p(p_data + MM_LIGHT_HSL_HUE_SET_HUE_POS);
// Transition time
uint8_t trans_time;
// Delay
uint8_t delay = 0;
// Check if Light CTL Hue state value is within the defined range
if ((hue > p_env_hslh->hue_max)
|| (hue < p_env_hslh->hue_min))
{
break;
}
tid = *(p_data + MM_LIGHT_HSL_HUE_SET_TID_POS);
// Check if request can be processed
if ((p_env_hsl->status_dst_addr != MESH_UNASSIGNED_ADDR)
|| (mm_replay_is_retx(&p_env_hsl->replay_env, p_route_env->u_addr.src, tid)))
{
// Send a Light HSL Hue Status message
if (send_status)
{
mm_lights_hsl_send_status_hue(p_env_hslh, p_route_env, false);
}
break;
}
// Extract and check optional parameters if present
if (p_buf->data_len == MM_LIGHT_HSL_HUE_SET_LEN)
{
trans_time = (uint16_t)(*(p_data + MM_LIGHT_HSL_HUE_SET_TRANS_TIME_POS));
// Check received value
if (GETF(trans_time, MM_TRANS_TIME_STEP_NB) > MM_TRANS_TIME_STEPS_MAX)
{
// Drop the message
break;
}
delay = *(p_data + MM_LIGHT_HSL_HUE_SET_DELAY_POS);
}
else
{
delay = 0;
trans_time = MM_TRANS_TIME_UNKNOWN;
}
// Check if state is modified
if (hue == p_env_hslh->hue)
{
// Send a Light HSL Hue Status message
if (send_status)
{
mm_lights_hsl_send_status_hue(p_env_hslh, p_route_env, false);
}
break;
};
if (send_status)
{
// Keep information for transmission of status
p_env_hslh->status_dst_addr = p_route_env->u_addr.src;
p_env_hslh->status_app_key_lid = p_route_env->app_key_lid;
SETB(p_env_hslh->status_info, MM_LIGHTS_HSL_SINFO_HS_RELAY,
GETB(p_route_env->info, MM_ROUTE_INFO_RELAY));
}
SETB(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_TRANS_LN, 0);
SETB(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_TRANS_HUE, 1);
SETB(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_TRANS_SAT, 0);
SETF(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_TRANS,
GETF(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_WAIT));
// Update target state
p_env_hslh->hue_tgt = hue;
// Inform the Binding Manager about new transition
mm_bind_trans_new(p_env_hslh->env.grp_lid, MM_TRANS_TYPE_CLASSIC, trans_time, delay);
} while (0);
}
/**
****************************************************************************************
* @brief Handler for Light HSL Saturation Set/Set Unacknowledged message
*
* @param[in] p_env Pointer to environment of model for which message has been received
* @param[in] p_buf Pointer to buffer containing the received message
* @param[in] p_route_env Pointer to routing information for the received buffer
****************************************************************************************
*/
__STATIC void mm_lights_hsl_handler_set_sat(mm_lights_hslsat_env_t *p_env_hslsat, mesh_buf_t *p_buf,
mm_route_env_t *p_route_env)
{
do
{
// Get pointer to environment for Light HSL Server model
mm_lights_hsl_env_t *p_env_hsl = p_env_hslsat->p_env_hsl;
// Check if a status message must be sent
bool send_status = (p_route_env->opcode == MM_MSG_LIGHT_HSL_SAT_SET);
// Get pointer to data
uint8_t *p_data = MESH_BUF_DATA(p_buf);
// TID value
uint8_t tid;
// Received Light CTL Saturation state values
uint16_t sat = read16p(p_data + MM_LIGHT_HSL_SAT_SET_SAT_POS);
// Transition time
uint8_t trans_time;
// Delay
uint8_t delay;
// Check if Light CTL Saturation state value is within the defined range
if ((sat > p_env_hslsat->sat_max)
|| (sat < p_env_hslsat->sat_min))
{
break;
}
tid = *(p_data + MM_LIGHT_HSL_SAT_SET_TID_POS);
// Check if request can be processed
if ((p_env_hsl->status_dst_addr != MESH_UNASSIGNED_ADDR)
|| (mm_replay_is_retx(&p_env_hsl->replay_env, p_route_env->u_addr.src, tid)))
{
// Send a Light HSL Saturation Status message
if (send_status)
{
mm_lights_hsl_send_status_sat(p_env_hslsat, p_route_env, false);
}
break;
}
// Extract and check optional parameters if present
if (p_buf->data_len == MM_LIGHT_HSL_SAT_SET_LEN)
{
trans_time = (uint16_t)(*(p_data + MM_LIGHT_HSL_SAT_SET_TRANS_TIME_POS));
// Check received value
if (GETF(trans_time, MM_TRANS_TIME_STEP_NB) > MM_TRANS_TIME_STEPS_MAX)
{
// Drop the message
break;
}
delay = *(p_data + MM_LIGHT_HSL_SAT_SET_DELAY_POS);
}
else
{
delay = 0;
trans_time = MM_TRANS_TIME_UNKNOWN;
}
// Check if state is modified
if (sat == p_env_hslsat->sat)
{
// Send a Light HSL Saturation Status message
if (send_status)
{
mm_lights_hsl_send_status_sat(p_env_hslsat, p_route_env, false);
}
break;
};
if (send_status)
{
// Keep information for transmission of status
p_env_hslsat->status_dst_addr = p_route_env->u_addr.src;
p_env_hslsat->status_app_key_lid = p_route_env->app_key_lid;
SETB(p_env_hslsat->status_info, MM_LIGHTS_HSL_SINFO_HS_RELAY,
GETB(p_route_env->info, MM_ROUTE_INFO_RELAY));
}
SETB(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_TRANS_LN, 0);
SETB(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_TRANS_HUE, 0);
SETB(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_TRANS_SAT, 1);
SETF(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_TRANS,
GETF(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_WAIT));
// Update target state
p_env_hslsat->sat_tgt = sat;
// Inform the Binding Manager about new transition
mm_bind_trans_new(p_env_hslsat->env.grp_lid, MM_TRANS_TYPE_CLASSIC, trans_time, delay);
} while (0);
}
/**
****************************************************************************************
* @brief Handler for Light HSL Default Set/Set Unacknowledged message
*
* @param[in] p_env Pointer to environment of model for which message has been received
* @param[in] p_buf Pointer to buffer containing the received message
* @param[in] p_route_env Pointer to routing information for the received buffer
****************************************************************************************
*/
__STATIC void mm_lights_hsl_handler_set_dflt(mm_lights_hsl_env_t *p_env_hsl,
mesh_buf_t *p_buf, mm_route_env_t *p_route_env)
{
do
{
// Get pointer to data
uint8_t *p_data = MESH_BUF_DATA(p_buf);
// Get environment for Light Lightness HSL Hue Server model
mm_lights_hslh_env_t *p_env_hslh = p_env_hsl->p_env_hslh;
// Get environment for Light Lightness HSL Saturation Server model
mm_lights_hslsat_env_t *p_env_hslsat = p_env_hsl->p_env_hslsat;
// Extract Light HSL Lightness Default state value
uint16_t ln_dflt = read16p(p_data + MM_LIGHT_HSL_DFLT_SET_LIGHTNESS_POS);
// Extract Light HSL Hue Default state value
uint16_t hue_dflt = read16p(p_data + MM_LIGHT_HSL_DFLT_SET_HUE_POS);
// Extract Light HSL Saturation Default state value
uint16_t sat_dflt = read16p(p_data + MM_LIGHT_HSL_DFLT_SET_SAT_POS);
// Check if Light CTL Hue and Light CTL Saturation state values are within the defined ranges
if ((hue_dflt > p_env_hslh->hue_max)
|| (hue_dflt < p_env_hslh->hue_min)
|| (sat_dflt > p_env_hslsat->sat_max)
|| (sat_dflt < p_env_hslsat->sat_min))
{
break;
}
// Inform Light Lightness Server model about received Light Lightness Default state value
mm_lights_ln_set_dflt(p_env_hsl->env.elmt_idx, ln_dflt);
if (hue_dflt != p_env_hslh->hue_dflt)
{
// Keep received value
p_env_hslh->hue_dflt = hue_dflt;
// Inform application about received value
mm_srv_state_upd_ind_send(MM_STATE_LIGHT_HSL_DFLT_HUE,
p_env_hslh->env.elmt_idx, hue_dflt, 0);
}
if (sat_dflt != p_env_hslsat->sat_dflt)
{
// Keep received value
p_env_hslsat->sat_dflt = sat_dflt;
// Inform application about received value
mm_srv_state_upd_ind_send(MM_STATE_LIGHT_HSL_DFLT_SAT,
p_env_hslsat->env.elmt_idx, sat_dflt, 0);
}
// If needed, send a Light HSL Default Status message to the requester
if (p_route_env->opcode == MM_MSG_LIGHT_HSL_DFLT_SET)
{
mm_lights_hsl_send_status_dflt(p_env_hsl, p_route_env);
}
} while (0);
}
/**
****************************************************************************************
* @brief Handler for Light HSL Range Set/Set Unacknowledged message
*
* @param[in] p_env Pointer to environment of model for which message has been received
* @param[in] p_buf Pointer to buffer containing the received message
* @param[in] p_route_env Pointer to routing information for the received buffer
****************************************************************************************
*/
__STATIC void mm_lights_hsl_handler_set_range(mm_lights_hsl_env_t *p_env_hsl,
mesh_buf_t *p_buf, mm_route_env_t *p_route_env)
{
do
{
// Get pointer to data
uint8_t *p_data = MESH_BUF_DATA(p_buf);
// Get environment for Light Lightness HSL Hue Server model
mm_lights_hslh_env_t *p_env_hslh = p_env_hsl->p_env_hslh;
// Get environment for Light Lightness HSL Saturation Server model
mm_lights_hslsat_env_t *p_env_hslsat = p_env_hsl->p_env_hslsat;
// Extract Light HSL Hue Min state value
uint16_t hue_min = read16p(p_data + MM_LIGHT_HSL_RANGE_SET_HUE_MIN_POS);
// Extract Light HSL Hue Max state value
uint16_t hue_max = read16p(p_data + MM_LIGHT_HSL_RANGE_SET_HUE_MAX_POS);
// Extract Light HSL Saturation Min state value
uint16_t sat_min = read16p(p_data + MM_LIGHT_HSL_RANGE_SET_SAT_MIN_POS);
// Extract Light HSL Saturation Max state value
uint16_t sat_max = read16p(p_data + MM_LIGHT_HSL_RANGE_SET_SAT_MAX_POS);
// Check provided values
if ((hue_min > hue_max)
|| (sat_min > sat_max))
{
// Drop the message
break;
}
if ((p_env_hslh->hue_min != hue_min)
|| (p_env_hslh->hue_max != hue_max))
{
p_env_hslh->hue_min = hue_min;
p_env_hslh->hue_max = hue_max;
// Inform application about received value
mm_srv_state_upd_ind_send(MM_STATE_LIGHT_HSL_RANGE_HUE, p_env_hslh->env.elmt_idx,
(uint32_t)hue_min | ((uint32_t)hue_max << 16), 0);
}
if ((p_env_hslsat->sat_min != sat_min)
|| (p_env_hslsat->sat_max != sat_max))
{
p_env_hslsat->sat_min = sat_min;
p_env_hslsat->sat_max = sat_max;
// Inform application about received value
mm_srv_state_upd_ind_send(MM_STATE_LIGHT_HSL_RANGE_SAT, p_env_hslsat->env.elmt_idx,
(uint32_t)sat_min | ((uint32_t)sat_max << 16), 0);
}
// If needed, send a Light HSL Range Status message to the requester
if (p_route_env->opcode == MM_MSG_LIGHT_HSL_RANGE_SET)
{
mm_lights_hsl_send_status_range(p_env_hsl, p_route_env, MM_STATUS_SUCCESS);
}
} while (0);
}
/*
* INTERNAL CALLBACK FUNCTIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Callback function called when timer monitoring publication duration for
* Light HSL Server model or for Light HSL Hue Server model or for Light HSL Saturation
* Server model expires
*
* @param[in] p_env Pointer to model environment for Light HSL Server or Light HSL
* Hue Server or Light HSL Saturation Server model
****************************************************************************************
*/
__STATIC void mm_lights_hsl_cb_tmr_publi(void *p_tmr)
{
mm_lights_hsl_env_t *p_env = MESH_TMR2ENV(p_tmr, mm_lights_hsl_env_t, tmr_publi);
// Get allocated environment
mm_mdl_publi_env_t *p_env_publi = (mm_mdl_publi_env_t *)p_env;
if (p_env_publi->publi_period_ms)
{
if (p_env_publi->env.model_id == MM_ID_LIGHTS_HSL)
{
// Publish a Light HSL Status message
mm_lights_hsl_publish((mm_lights_hsl_env_t *)p_env, false);
}
else
{
// Publish a Light HSL Hue Status message
mm_lights_hsl_publish_hue_sat(&p_env_publi->env);
}
// Restart the timer
mesh_timer_set(&p_env_publi->tmr_publi, p_env_publi->publi_period_ms);
}
}
/**
****************************************************************************************
* @brief Inform Light HSL Server model about a received message
*
* @param[in] p_env Pointer to the environment allocated for the Light HSL
* Server model
* @param[in] p_buf Pointer to the buffer containing the received message
* @param[in] p_route_env Pointer to structure containing reception parameters provided
* by the Mesh Profile block
****************************************************************************************
*/
__STATIC void mm_lights_hsl_cb_rx(mm_mdl_env_t *p_env, mesh_buf_t *p_buf,
mm_route_env_t *p_route_env)
{
do
{
mm_lights_hsl_env_t *p_env_hsl;
if (p_env->model_id == MM_ID_LIGHTS_HSL)
{
// Get Environment for Light HSL Server model
p_env_hsl = (mm_lights_hsl_env_t *)p_env;
switch (p_route_env->opcode)
{
case (MM_MSG_LIGHT_HSL_GET):
case (MM_MSG_LIGHT_HSL_TGT_GET):
{
// Send a Light HSL Status message
mm_lights_hsl_send_status(p_env_hsl, p_route_env, false,
(p_route_env->opcode == MM_MSG_LIGHT_HSL_TGT_GET));
} break;
case (MM_MSG_LIGHT_HSL_SET):
case (MM_MSG_LIGHT_HSL_SET_UNACK):
{
// Handle the message
mm_lights_hsl_handler_set(p_env_hsl, p_buf, p_route_env);
} break;
case (MM_MSG_LIGHT_HSL_DFLT_GET):
{
// Send a Light HSL Default Status message
mm_lights_hsl_send_status_dflt(p_env_hsl, p_route_env);
} break;
case (MM_MSG_LIGHT_HSL_RANGE_GET):
{
// Send a Light HSL Range Status message
mm_lights_hsl_send_status_range(p_env_hsl, p_route_env, MM_STATUS_SUCCESS);
} break;
default:
{
} break;
}
}
else if (p_env->model_id == MM_ID_LIGHTS_HSLS)
{
// Get Environment for Light HSL Setup Server model
mm_lights_hsls_env_t *p_env_hsls = (mm_lights_hsls_env_t *)p_env;
// Get environment for Light HSL Server model
p_env_hsl = p_env_hsls->p_env_hsl;
switch (p_route_env->opcode)
{
case (MM_MSG_LIGHT_HSL_DFLT_SET):
case (MM_MSG_LIGHT_HSL_DFLT_SET_UNACK):
{
// Handle the message
mm_lights_hsl_handler_set_dflt(p_env_hsl, p_buf, p_route_env);
} break;
case (MM_MSG_LIGHT_HSL_RANGE_SET):
case (MM_MSG_LIGHT_HSL_RANGE_SET_UNACK):
{
// Handle the message
mm_lights_hsl_handler_set_range(p_env_hsl, p_buf, p_route_env);
} break;
default:
{
} break;
}
}
else if (p_env->model_id == MM_ID_LIGHTS_HSLH)
{
// Get environment for Light HSL Hue model
mm_lights_hslh_env_t *p_env_hslh = (mm_lights_hslh_env_t *)p_env;
switch (p_route_env->opcode)
{
case (MM_MSG_LIGHT_HSL_HUE_GET):
{
// Send a Light HSL Hue Status message
mm_lights_hsl_send_status_hue(p_env_hslh, p_route_env, false);
} break;
case (MM_MSG_LIGHT_HSL_HUE_SET):
case (MM_MSG_LIGHT_HSL_HUE_SET_UNACK):
{
// Handle the message
mm_lights_hsl_handler_set_hue(p_env_hslh, p_buf, p_route_env);
} break;
default:
{
} break;
}
}
else // (p_env->model_id == MM_ID_LIGHTS_HSLSAT)
{
// Get environment for Light HSL Saturation model
mm_lights_hslsat_env_t *p_env_hslsat = (mm_lights_hslsat_env_t *)p_env;
switch (p_route_env->opcode)
{
case (MM_MSG_LIGHT_HSL_SAT_GET):
{
// Send a Light HSL Saturation Status message
mm_lights_hsl_send_status_sat(p_env_hslsat, p_route_env, false);
} break;
case (MM_MSG_LIGHT_HSL_SAT_SET):
case (MM_MSG_LIGHT_HSL_SAT_SET_UNACK):
{
// Handle the message
mm_lights_hsl_handler_set_sat(p_env_hslsat, p_buf, p_route_env);
} break;
default:
{
} break;
}
}
} while (0);
}
/**
****************************************************************************************
* @brief Check if a given opcode is handled by the Light HSL Server model
*
* @param[in] p_env Pointer to the environment allocated for the Light HSL
* Server model
* @param[in] opcode Opcode to check
*
* @return An error status (@see enum mesh_err)
****************************************************************************************
*/
__STATIC uint8_t mm_lights_hsl_cb_opcode_check(mm_mdl_env_t *p_env, uint32_t opcode)
{
uint8_t status = MESH_ERR_MDL_INVALID_OPCODE;
if (p_env->model_id == MM_ID_LIGHTS_HSL)
{
if ((opcode == MM_MSG_LIGHT_HSL_GET)
|| (opcode == MM_MSG_LIGHT_HSL_SET)
|| (opcode == MM_MSG_LIGHT_HSL_SET_UNACK)
|| (opcode == MM_MSG_LIGHT_HSL_TGT_GET)
|| (opcode == MM_MSG_LIGHT_HSL_RANGE_GET)
|| (opcode == MM_MSG_LIGHT_HSL_DFLT_GET))
{
status = MESH_ERR_NO_ERROR;
}
}
else if (p_env->model_id == MM_ID_LIGHTS_HSLS)
{
if ((opcode == MM_MSG_LIGHT_HSL_DFLT_SET)
|| (opcode == MM_MSG_LIGHT_HSL_DFLT_SET_UNACK)
|| (opcode == MM_MSG_LIGHT_HSL_RANGE_SET)
|| (opcode == MM_MSG_LIGHT_HSL_RANGE_SET_UNACK))
{
status = MESH_ERR_NO_ERROR;
}
}
else if (p_env->model_id == MM_ID_LIGHTS_HSLH)
{
if ((opcode == MM_MSG_LIGHT_HSL_HUE_GET)
|| (opcode == MM_MSG_LIGHT_HSL_HUE_SET)
|| (opcode == MM_MSG_LIGHT_HSL_HUE_SET_UNACK))
{
status = MESH_ERR_NO_ERROR;
}
}
else if (p_env->model_id == MM_ID_LIGHTS_HSLSAT)
{
if ((opcode == MM_MSG_LIGHT_HSL_SAT_GET)
|| (opcode == MM_MSG_LIGHT_HSL_SAT_SET)
|| (opcode == MM_MSG_LIGHT_HSL_SAT_SET_UNACK))
{
status = MESH_ERR_NO_ERROR;
}
}
return (status);
}
/**
****************************************************************************************
* @brief Callback function called upon reception of application request to set a Light
* HSL state value
*
* @param[in] p_env Pointer the the environment allocated for model
* @param[in] state_id State identifier
* @param[in] state State value
*
* @return An error status (@see enum mesh_err)
****************************************************************************************
*/
__STATIC uint8_t mm_lights_hsl_cb_set(mm_mdl_env_t *p_env, uint16_t state_id,
uint32_t state)
{
// Returned status
uint8_t status = MESH_ERR_NO_ERROR;
if (state_id == MM_STATE_LIGHT_HSL_LN)
{
// Get environment for the Light HSL Server model
mm_lights_hsl_env_t *p_env_hsl = (mm_lights_hsl_env_t *)p_env;
// Keep the provided state value
p_env_hsl->ln = state;
// Set the Light Lightness state value
mm_bind_set_state(p_env_hsl->env.grp_lid, MM_STATE_TYPE_CURRENT,
MM_ID_LIGHTS_LN, state);
}
else
{
status = MESH_ERR_INVALID_PARAM;
}
return (status);
}
/**
****************************************************************************************
* @brief Callback function called upon reception of application request to set a Light
* HSL Hue state value
*
* @param[in] p_env Pointer the the environment allocated for model
* @param[in] state_id State identifier
* @param[in] state State value
*
* @return An error status (@see enum mesh_err)
****************************************************************************************
*/
__STATIC uint8_t mm_lights_hsl_cb_set_hue(mm_mdl_env_t *p_env, uint16_t state_id,
uint32_t state)
{
// Returned status
uint8_t status = MESH_ERR_NO_ERROR;
// Get environment for the Light HSL Hue Server model
mm_lights_hslh_env_t *p_env_hslh = (mm_lights_hslh_env_t *)p_env;
switch (state_id)
{
case (MM_STATE_LIGHT_HSL_HUE):
{
// Keep the provided state value
p_env_hslh->hue = state;
// Set the Generic Level state value
mm_bind_set_state(p_env_hslh->env.grp_lid, MM_STATE_TYPE_CURRENT,
MM_ID_GENS_LVL, state - 32768);
} break;
case (MM_STATE_LIGHT_HSL_DFLT_HUE):
{
// Keep the provided state value
p_env_hslh->hue_dflt = state;
} break;
case (MM_STATE_LIGHT_HSL_RANGE_HUE):
{
// Keep the provided state value
p_env_hslh->hue_min = state;
p_env_hslh->hue_max = (state >> 16);
} break;
default:
{
status = MESH_ERR_INVALID_PARAM;
} break;
}
return (status);
}
/**
****************************************************************************************
* @brief Callback function called upon reception of application request to set a Light
* HSL Saturation state value
*
* @param[in] p_env Pointer the the environment allocated for model
* @param[in] state_id State identifier
* @param[in] state State value
*
* @return An error status (@see enum mesh_err)
****************************************************************************************
*/
__STATIC uint8_t mm_lights_hsl_cb_set_sat(mm_mdl_env_t *p_env, uint16_t state_id, uint32_t state)
{
// Returned status
uint8_t status = MESH_ERR_NO_ERROR;
// Get environment for the Light HSL Saturation Server model
mm_lights_hslsat_env_t *p_env_hslsat = (mm_lights_hslsat_env_t *)p_env;
switch (state_id)
{
case (MM_STATE_LIGHT_HSL_SAT):
{
// Keep the provided state value
p_env_hslsat->sat = state;
// Set the Generic Level state value
mm_bind_set_state(p_env_hslsat->env.grp_lid, MM_STATE_TYPE_CURRENT,
MM_ID_GENS_LVL, state - 32768);
} break;
case (MM_STATE_LIGHT_HSL_DFLT_SAT):
{
// Keep the provided state value
p_env_hslsat->sat_dflt = state;
} break;
case (MM_STATE_LIGHT_HSL_RANGE_SAT):
{
// Keep the provided state value
p_env_hslsat->sat_min = state;
p_env_hslsat->sat_max = (state >> 16);
} break;
default:
{
status = MESH_ERR_INVALID_PARAM;
} break;
}
return (status);
}
/*
* REGISTRATION FUNCTIONS
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Register Light HSL Server model
*
* @param[in] elmt_idx Index of element on which the model must be registered
* @param[out] p_mdl_lid Address at which allocated model local index must be returned
*
* @return An handling status (@see enum mesh_err)
****************************************************************************************
*/
__STATIC uint8_t mm_lights_hsl_register_hsl(uint8_t elmt_idx)
{
// Register Light HSL Server model
m_lid_t mdl_lid = ms_register_model(MM_ID_LIGHTS_HSL, elmt_idx, MM_CFG_PUBLI_AUTH_BIT);
if (mdl_lid != MESH_INVALID_LID)
{
// Inform the Model State Manager about registered model
mm_lights_hsl_env_t *p_env_hsl = (mm_lights_hsl_env_t *)mm_state_register(elmt_idx, MM_ID_LIGHTS_HSL, mdl_lid,
MM_ROLE_SRV_PUBLI, sizeof(mm_lights_hsl_env_t));
if (p_env_hsl)
{
// Pointer to server-specific callback functions
//mm_srv_cb_t *p_cb_srv = p_env_hsl->env.cb.u.p_cb_srv;
// Prepare environment for Replay Manager
p_env_hsl->replay_env.delay_ms = MM_LIGHTS_HSL_REPLAY_MS;
// Prepare timer for publications
p_env_hsl->tmr_publi.cb = mm_lights_hsl_cb_tmr_publi;
//p_env_hsl->tmr_publi.p_env = (void *)p_env_hsl;
// Set internal callback functions
p_env_hsl->env.mdl_cb.cb_rx = mm_lights_hsl_cb_rx;
p_env_hsl->env.mdl_cb.cb_opcode_check = mm_lights_hsl_cb_opcode_check;
//p_env_hsl->env.mdl_cb.cb_publish_param = mm_lights_hsl_cb_publish_param;
//p_cb_srv->cb_set = mm_lights_hsl_cb_set;
p_env_hsl->env.mdl_cb.cb_srv_set = mm_lights_hsl_cb_set;
// Inform application about registered model
mm_register_ind_send(MM_ID_LIGHTS_HSL, elmt_idx, mdl_lid);
}
}
return (mdl_lid);
}
/**
****************************************************************************************
* @brief Register Light HSL Setup Server model
*
* @param[in] elmt_idx Index of element on which the model must be registered
* @param[out] p_mdl_lid Address at which allocated model local index must be returned
*
* @return An handling status (@see enum mesh_err)
****************************************************************************************
*/
__STATIC uint8_t mm_lights_hsl_register_hsls(uint8_t elmt_idx)
{
// Register Light HSL Setup Server model
m_lid_t mdl_lid = ms_register_model(MM_ID_LIGHTS_HSLS, elmt_idx, MM_CFG_PUBLI_AUTH_BIT);
if (mdl_lid != MESH_INVALID_LID)
{
// Inform the Model State Manager about registered model
mm_lights_hsls_env_t *p_env_hsls
= (mm_lights_hsls_env_t *)mm_state_register(elmt_idx, MM_ID_LIGHTS_HSLS, mdl_lid,
MM_ROLE_SRV, sizeof(mm_lights_hsls_env_t));
if (p_env_hsls)
{
// Set internal callback functions
p_env_hsls->env.mdl_cb.cb_rx = mm_lights_hsl_cb_rx;
p_env_hsls->env.mdl_cb.cb_opcode_check = mm_lights_hsl_cb_opcode_check;
// Inform application about registered model
mm_register_ind_send(MM_ID_LIGHTS_HSLS, elmt_idx, mdl_lid);
}
}
return (mdl_lid);
}
/**
****************************************************************************************
* @brief Register Light HSL Hue Server model
*
* @param[in] elmt_idx Index of element on which the model must be registered
* @param[out] p_mdl_lid Address at which allocated model local index must be returned
*
* @return An handling status (@see enum mesh_err)
****************************************************************************************
*/
__STATIC uint8_t mm_lights_hsl_register_hslh(uint8_t elmt_idx)
{
// Register Light HSL Hue Server model
m_lid_t mdl_lid = ms_register_model(MM_ID_LIGHTS_HSLH, elmt_idx, MM_CFG_PUBLI_AUTH_BIT);
if (mdl_lid != MESH_INVALID_LID)
{
// Inform the Model State Manager about registered model
mm_lights_hslh_env_t *p_env_hslh = (mm_lights_hslh_env_t *)mm_state_register(elmt_idx, MM_ID_LIGHTS_HSLH, mdl_lid,
MM_ROLE_SRV_PUBLI, sizeof(mm_lights_hslh_env_t));
if (p_env_hslh)
{
// Pointer to server-specific callback functions
//mm_srv_cb_t *p_cb_srv = p_env_hslh->env.cb.u.p_cb_srv;
// Prepare timer for publications
p_env_hslh->tmr_publi.cb = mm_lights_hsl_cb_tmr_publi;
//p_env_hslh->tmr_publi.p_env = (void *)p_env_hslh;
// Set internal callback functions
p_env_hslh->env.mdl_cb.cb_rx = mm_lights_hsl_cb_rx;
p_env_hslh->env.mdl_cb.cb_opcode_check = mm_lights_hsl_cb_opcode_check;
//p_env_hslh->env.mdl_cb.cb_publish_param = mm_lights_hsl_cb_publish_param;
//p_cb_srv->cb_set = mm_lights_hsl_cb_set_hue;
p_env_hslh->env.mdl_cb.cb_srv_set = mm_lights_hsl_cb_set_hue;
// Set range value
p_env_hslh->hue_max = 0xFFFF;
// Inform application about registered model
mm_register_ind_send(MM_ID_LIGHTS_HSLH, elmt_idx, mdl_lid);
}
}
return (mdl_lid);
}
/**
****************************************************************************************
* @brief Register Light HSL Saturation Server model
*
* @param[in] elmt_idx Index of element on which the model must be registered
* @param[out] p_mdl_lid Address at which allocated model local index must be returned
*
* @return An handling status (@see enum mesh_err)
****************************************************************************************
*/
__STATIC uint8_t mm_lights_hsl_register_hslsat(uint8_t elmt_idx)
{
// Register Light HSL Server model
m_lid_t mdl_lid = ms_register_model(MM_ID_LIGHTS_HSLSAT, elmt_idx, MM_CFG_PUBLI_AUTH_BIT);
if ( mdl_lid != MESH_INVALID_LID)
{
// Inform the Model State Manager about registered model
mm_lights_hslsat_env_t *p_env_hslsat
= (mm_lights_hslsat_env_t *)mm_state_register(elmt_idx, MM_ID_LIGHTS_HSLSAT, mdl_lid,
MM_ROLE_SRV_PUBLI, sizeof(mm_lights_hslsat_env_t));
if (p_env_hslsat)
{
// Pointer to server-specific callback functions
//mm_srv_cb_t *p_cb_srv = p_env_hslsat->env.cb.u.p_cb_srv;
// Prepare timer for publications
p_env_hslsat->tmr_publi.cb = mm_lights_hsl_cb_tmr_publi;
//p_env_hslsat->tmr_publi.p_env = (void *)p_env_hslsat;
// Set internal callback functions
p_env_hslsat->env.mdl_cb.cb_rx = mm_lights_hsl_cb_rx;
p_env_hslsat->env.mdl_cb.cb_opcode_check = mm_lights_hsl_cb_opcode_check;
//p_env_hslsat->env.mdl_cb.cb_publish_param = mm_lights_hsl_cb_publish_param;
//p_cb_srv->cb_set = mm_lights_hsl_cb_set_sat;
p_env_hslsat->env.mdl_cb.cb_srv_set = mm_lights_hsl_cb_set_sat;
// Set range value
p_env_hslsat->sat_max = 0xFFFF;
// Inform application about registered model
mm_register_ind_send(MM_ID_LIGHTS_HSLSAT, elmt_idx, mdl_lid);
}
}
return (mdl_lid);
}
/**
****************************************************************************************
* @brief Bind the Light HSL Server, the Light HSL Setup Server, the Light HSL Hue Server
* and the Light HSL Saturation Server models together
*
* @param[in] mdl_lid Model local index for the Light HSL Server model
* @param[in] mdl_lid_setup Model local index for the Light HSL Setup Server model
* @param[in] mdl_lid_hue Model local index for the Light HSL Hue Server model
* @param[in] mdl_lid_sat Model local index for the Light HSL Saturation Server model
****************************************************************************************
*/
__STATIC void mm_lights_hsl_bind(m_lid_t mdl_lid, m_lid_t mdl_lid_setup, m_lid_t mdl_lid_hue,
m_lid_t mdl_lid_sat)
{
// Pointer to environment for the Light HSL Server model
mm_lights_hsl_env_t *p_env_hsl = (mm_lights_hsl_env_t *)mm_state_get_env(mdl_lid);
// Pointer to environment for the Light HSL Setup Server model
mm_lights_hsls_env_t *p_env_hsls = (mm_lights_hsls_env_t *)mm_state_get_env(mdl_lid_setup);
// Pointer to environment for the Light HSL Hue Server model
mm_lights_hslh_env_t *p_env_hslh = (mm_lights_hslh_env_t *)mm_state_get_env(mdl_lid_hue);
// Pointer to environment for the Light HSL Saturation Server model
mm_lights_hslsat_env_t *p_env_hslsat = (mm_lights_hslsat_env_t *)mm_state_get_env(mdl_lid_sat);
// Bind environment together
p_env_hsl->p_env_hslh = p_env_hslh;
p_env_hsl->p_env_hslsat = p_env_hslsat;
p_env_hsls->p_env_hsl = p_env_hsl;
p_env_hslh->p_env_hsl = p_env_hsl;
p_env_hslsat->p_env_hsl = p_env_hsl;
}
/*
* CALLBACK FUNCTIONS FOR BINDING MANAGER
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Callback function provided to the Binding Manager so that Light HSL Server
* model can be informed about group event
*
* @param[in] mdl_lid Model Local Index
* @param[in] event Event
* @param[in] info Information (depends on the event type)
****************************************************************************************
*/
__STATIC void mm_lights_hsl_cb_grp_event(m_lid_t mdl_lid, uint8_t event, uint8_t info)
{
// Get environment for Light HSL Server model
mm_lights_hsl_env_t *p_env_hsl = (mm_lights_hsl_env_t *)mm_state_get_env(mdl_lid);
switch (event)
{
case (MM_GRP_EVENT_TRANS_DELAY_EXPIRED):
{
// Set the targeted Light Lightness state value
mm_bind_set_state(p_env_hsl->env.grp_lid, MM_STATE_TYPE_TARGET, MM_ID_LIGHTS_LN,
p_env_hsl->ln_tgt);
// Start the transition
mm_bind_trans_start(p_env_hsl->env.grp_lid);
} break;
case (MM_GRP_EVENT_TRANS_IMMEDIATE):
{
p_env_hsl->ln = p_env_hsl->ln_tgt;
} // no break;
case (MM_GRP_EVENT_TRANS_STARTED):
{
uint8_t trans_time = info;
// Transition has been started
SETB(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_WAIT_LN, 0);
// Inform application about state update
mm_srv_state_upd_ind_send(MM_STATE_LIGHT_HSL_LN, p_env_hsl->env.elmt_idx,
p_env_hsl->ln_tgt,
(trans_time) ? mm_get_trans_time_ms(trans_time) : 0);
// Check if Light HSL Status message must be sent
mm_lights_hsl_check_status(p_env_hsl, event);
} break;
case (MM_GRP_EVENT_TRANS_END):
{
p_env_hsl->ln = p_env_hsl->ln_tgt;
// Inform application about state update
mm_srv_state_upd_ind_send(MM_STATE_LIGHT_HSL_LN,
p_env_hsl->env.elmt_idx, p_env_hsl->ln, 0);
// Check if Light HSL Status message must be sent
mm_lights_hsl_check_status(p_env_hsl, event);
} break;
case (MM_GRP_EVENT_GROUP_FULL):
{
// Set the current Light Lightness state value
mm_bind_set_state(p_env_hsl->env.grp_lid, MM_STATE_TYPE_CURRENT, MM_ID_LIGHTS_LN,
p_env_hsl->ln);
} break;
//case (MM_GRP_EVENT_TRANS_ABORTED):
default:
{
} break;
}
}
/**
****************************************************************************************
* @brief Callback function provided to the Binding Manager so that Light HSL Hue or
* Saturation Server model can be informed about group event
*
* @param[in] mdl_lid Model Local Index
* @param[in] event Event
* @param[in] info Information (depends on the event type)
****************************************************************************************
*/
__STATIC void mm_lights_hsl_cb_grp_event_hue_sat(m_lid_t mdl_lid, uint8_t event, uint8_t info)
{
// Pointer to environment for the main model
mm_mdl_env_t *p_env = (mm_mdl_env_t *)mm_state_get_env(mdl_lid);
// Pointer to the environment allocated for the Light HSL Server model
mm_lights_hsl_env_t *p_env_hsl;
// Pointer to the needed value in the main model environment
uint16_t *p_tgt_state, *p_state;
// State identifier
uint32_t state_id;
if (p_env->model_id == MM_ID_LIGHTS_HSLH)
{
// Pointer to environment for the Light HSL Hue Server model
mm_lights_hslh_env_t *p_env_hslh = (mm_lights_hslh_env_t *)p_env;
p_tgt_state = &p_env_hslh->hue_tgt;
p_state = &p_env_hslh->hue;
p_env_hsl = p_env_hslh->p_env_hsl;
state_id = MM_STATE_LIGHT_HSL_HUE;
}
else // (p_env->model_id == MM_ID_LIGHTS_HSLSAT)
{
// Pointer to environment for the Light HSL Saturation Server model
mm_lights_hslsat_env_t *p_env_hslsat = (mm_lights_hslsat_env_t *)p_env;
p_tgt_state = &p_env_hslsat->sat_tgt;
p_state = &p_env_hslsat->sat;
p_env_hsl = p_env_hslsat->p_env_hsl;
state_id = MM_STATE_LIGHT_HSL_SAT;
}
switch (event)
{
case (MM_GRP_EVENT_TRANS_DELAY_EXPIRED):
{
// Generic Level = Light HSL Hue/Saturation - 32768
int16_t lvl = ((int32_t)*p_tgt_state) - 32768;
// Set the targeted Generic Level state value
mm_bind_set_state(p_env->grp_lid, MM_STATE_TYPE_TARGET, MM_ID_GENS_LVL, lvl);
// Start the transition
mm_bind_trans_start(p_env->grp_lid);
} break;
case (MM_GRP_EVENT_TRANS_IMMEDIATE):
{
*p_state = *p_tgt_state;
} // no break;
case (MM_GRP_EVENT_TRANS_STARTED):
{
uint8_t trans_time = info;
// Transition has been started
if (p_env->model_id == MM_ID_LIGHTS_HSLH)
{
SETB(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_WAIT_HUE, 0);
}
else
{
SETB(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_WAIT_SAT, 0);
}
// Inform application about state update
mm_srv_state_upd_ind_send(state_id, p_env->elmt_idx, *p_tgt_state,
(trans_time) ? mm_get_trans_time_ms(trans_time) : 0);
// Check if a status message must be sent
mm_lights_hsl_check_status_rsp_hue_sat(p_env);
// Send a publication
mm_lights_hsl_publish_hue_sat(p_env);
// Check if Light HSL Status message must be sent
mm_lights_hsl_check_status(p_env_hsl, event);
} break;
case (MM_GRP_EVENT_TRANS_END):
{
*p_state = *p_tgt_state;
// Inform application about state update
mm_srv_state_upd_ind_send(state_id, p_env->elmt_idx, *p_state, 0);
// Check if a status message must be sent
mm_lights_hsl_check_status_rsp_hue_sat(p_env);
// Send a publication
mm_lights_hsl_publish_hue_sat(p_env);
// Check if Light HSL Status message must be sent
mm_lights_hsl_check_status(p_env_hsl, event);
} break;
case (MM_GRP_EVENT_GROUP_FULL):
{
// Generic Level = Light HSL Hue/Saturation - 32768
int16_t lvl = ((int32_t)*p_state) - 32768;
// Set the current Generic Level state value
mm_bind_set_state(p_env->grp_lid, MM_STATE_TYPE_CURRENT, MM_ID_GENS_LVL, lvl);
} break;
//case (MM_GRP_EVENT_TRANS_ABORTED):
default:
{
} break;
}
}
/**
****************************************************************************************
* @brief Callback function provided to the Binding Manager so that Light HSL Hue or Light
* HSL Saturation state value can be set by main model of the group
*
* @param[in] main_mdl_lid Model Local Index
* @param[in] req_model_id Model ID of model that has requested the transition
* @param[in] trans_type Transition type
* @param[in] state_delta State value or delta value
****************************************************************************************
*/
__STATIC void mm_lights_hsl_cb_trans_req(m_lid_t main_mdl_lid, uint32_t req_model_id, uint8_t trans_type,
uint32_t state_delta)
{
// Get environment for Light HSL Server model
mm_lights_hsl_env_t *p_env_hsl = (mm_lights_hsl_env_t *)mm_state_get_env(main_mdl_lid);
// Targeted Light HSL Lightness state value
uint16_t ln_tgt;
if (req_model_id == MM_ID_LIGHTS_LN)
{
// Light HSL Lightness = Light Lightness Actual
ln_tgt = (uint16_t)state_delta;
}
else
{
if (req_model_id == MM_ID_GENS_OO)
{
// Requested Generic OnOff state value
uint8_t onoff = (uint8_t)state_delta;
// Deduce Target Light HSL Lightness state value
ln_tgt = (onoff == 0) ? 0 : mm_lights_ln_get(p_env_hsl->env.elmt_idx,
MM_STATE_LIGHT_LN_DFLT);
}
else // (req_model_id == MM_ID_GENS_LVL)
{
if (trans_type == MM_TRANS_TYPE_CLASSIC)
{
// Requested Generic Level state value
int16_t level = (int16_t)state_delta;
// Light HSL Lightness = Generic Level + 32768
ln_tgt = 32768 + level;
}
else // ((trans_type == MM_TRANS_TYPE_DELTA) || trans_type == MM_TRANS_TYPE_MOVE))
{
// Delta value
int32_t delta;
if (trans_type == MM_TRANS_TYPE_MOVE)
{
delta = (int16_t)state_delta;
// Keep the provided delta value
p_env_hsl->move_delta = (int16_t)state_delta;
}
else
{
delta = (int32_t)state_delta;
}
// Add the Light HSL Lightness state value to the received delta value
delta += p_env_hsl->ln;
// The Light HSL Actual state value cannot wrap
if (delta < 0)
{
ln_tgt = 0;
}
else
{
ln_tgt = (delta > 0xFFFF) ? 0xFFFF : (uint16_t)delta;
}
}
}
if (ln_tgt != 0)
{
// Get range value
uint16_t ln_min = mm_lights_ln_get(p_env_hsl->env.elmt_idx, MM_STATE_LIGHT_LN_RANGE_MIN);
uint16_t ln_max = mm_lights_ln_get(p_env_hsl->env.elmt_idx, MM_STATE_LIGHT_LN_RANGE_MAX);
// Ensure that Light HSL Lightness state value is between Light HSL Lightness Range
// Min and Max values
if (ln_tgt > ln_max)
{
ln_tgt = ln_max;
}
else if (ln_tgt < ln_min)
{
ln_tgt = ln_min;
}
}
}
// Check if Light HSL Actual state value is modified
if (ln_tgt != p_env_hsl->ln)
{
SETB(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_TRANS_LN, 1);
SETB(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_TRANS_HUE, 0);
SETB(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_TRANS_SAT, 0);
SETF(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_TRANS,
GETF(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_WAIT));
p_env_hsl->ln_tgt = ln_tgt;
// Start a new transition
mm_bind_trans_new(p_env_hsl->env.grp_lid, trans_type, 0, 0);
}
else
{
// Reject the transition
mm_bind_trans_reject(p_env_hsl->env.grp_lid);
}
}
/**
****************************************************************************************
* @brief Callback function provided to the Binding Manager so that Light HSL Hue or Light
* HSL Saturation state value can be set by main model of the group
*
* @param[in] main_mdl_lid Model Local Index
* @param[in] req_model_id Model ID of model that has requested the transition
* @param[in] trans_type Transition type
* @param[in] state_delta State value or delta value
****************************************************************************************
*/
void mm_lights_hsl_cb_trans_req_hue_sat(m_lid_t main_mdl_lid, uint32_t req_model_id, uint8_t trans_type,
uint32_t state_delta)
{
// Pointer to environment for the main model
mm_mdl_env_t *p_env = (mm_mdl_env_t *)mm_state_get_env(main_mdl_lid);
// Pointer to the needed value in the main model environment
uint16_t *p_range_min, *p_range_max, *p_tgt_state, *p_state;
int16_t *p_move_delta;
// Target Light HSL Hue or Light HSL Saturation state value
uint16_t tgt_state;
if (p_env->model_id == MM_ID_LIGHTS_HSLH)
{
// Pointer to environment for the Light HSL Hue Server model
mm_lights_hslh_env_t *p_env_hslh = (mm_lights_hslh_env_t *)p_env;
p_range_min = &p_env_hslh->hue_min;
p_range_max = &p_env_hslh->hue_max;
p_tgt_state = &p_env_hslh->hue_tgt;
p_state = &p_env_hslh->hue;
p_move_delta = &p_env_hslh->move_delta;
}
else // (p_env->model_id == MM_ID_LIGHTS_HSLSAT)
{
// Pointer to environment for the Light HSL Saturation Server model
mm_lights_hslsat_env_t *p_env_hslsat = (mm_lights_hslsat_env_t *)p_env;
p_range_min = &p_env_hslsat->sat_min;
p_range_max = &p_env_hslsat->sat_max;
p_tgt_state = &p_env_hslsat->sat_tgt;
p_state = &p_env_hslsat->sat;
p_move_delta = &p_env_hslsat->move_delta;
}
if (trans_type == MM_TRANS_TYPE_CLASSIC)
{
// Light HSL Hue/Saturation = Generic Level + 32768
tgt_state = 32768 + (int16_t)state_delta;
}
else // ((trans_type == MM_TRANS_TYPE_DELTA) || trans_type == MM_TRANS_TYPE_MOVE))
{
// Delta value
int32_t delta;
if (trans_type == MM_TRANS_TYPE_MOVE)
{
delta = (int16_t)state_delta;
// Keep the provided delta value
*p_move_delta = (int16_t)state_delta;
}
else
{
delta = (int32_t)state_delta;
}
// Add the current state value to the received delta value
delta += *p_state;;
// The state value cannot wrap
if (delta < 0)
{
tgt_state = 0;
}
else
{
tgt_state = (delta > 0xFFFF) ? 0xFFFF : (uint16_t)delta;
}
}
// Check that new targeted Light HSL Hue/Saturation state value is well within the set Light HSL
// Hue/Saturation state min and max values
if (tgt_state > *p_range_max)
{
tgt_state = *p_range_max;
}
else if (tgt_state < *p_range_min)
{
tgt_state = *p_range_min;
}
// Check if state value is modified
if (tgt_state != *p_tgt_state)
{
// Pointer to environment for the Light HSL Server model
mm_lights_hsl_env_t *p_env_hsl = (mm_lights_hsl_env_t *)p_env;
SETB(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_TRANS_LN, 0);
SETB(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_TRANS_HUE, p_env->model_id == MM_ID_LIGHTS_HSLH);
SETB(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_TRANS_SAT, p_env->model_id == MM_ID_LIGHTS_HSLSAT);
SETF(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_TRANS,
GETF(p_env_hsl->status_info, MM_LIGHTS_HSL_SINFO_WAIT));
*p_tgt_state = tgt_state;
// Start a new transition
mm_bind_trans_new(p_env->grp_lid, trans_type, 0, 0);
}
else
{
// Reject the transition
mm_bind_trans_reject(p_env->grp_lid);
}
}
/*
* GLOBAL FUNCTIONS
****************************************************************************************
*/
uint8_t mm_lights_hsl_register(uint8_t elmt_idx, bool main)
{
m_lid_t mdl_lid = MESH_INVALID_LID;
do
{
// Model local index for Light CTL Server model, for Light CTL Hue Server model
// for Light CTL Saturation Server model and for Light Lightness Server model
m_lid_t ln_lid, lvl1_lid, lvl2_lid;
m_lid_t hsl_lid, hsls_lid, hslh_lid, hslsat_lid;
// Register Light Lightness Server model and associated models
ln_lid = mm_lights_ln_register(elmt_idx, false);
if (ln_lid == MESH_INVALID_LID)
{
break;
}
// Register Generic Level Server model
lvl1_lid = mm_gens_lvl_register(elmt_idx + 1, false);
if (lvl1_lid == MESH_INVALID_LID)
{
break;
}
// Register Generic Level Server model
lvl2_lid = mm_gens_lvl_register(elmt_idx + 2, false);
if (lvl2_lid == MESH_INVALID_LID)
{
break;
}
// Register the Light HSL Server model and associated models
// 1. Register Light HSL Server model
hsl_lid = mm_lights_hsl_register_hsl(elmt_idx);
if (hsl_lid == MESH_INVALID_LID)
{
break;
}
// 2. Register Light HSL Setup Server model
hsls_lid = mm_lights_hsl_register_hsls(elmt_idx);
if (hsls_lid == MESH_INVALID_LID)
{
break;
}
// 3. Register Light HSL Hue Server model
hslh_lid = mm_lights_hsl_register_hslh(elmt_idx + 1);
if (hslh_lid == MESH_INVALID_LID)
{
break;
}
// 4. Register Light HSL Saturation Server model
hslsat_lid = mm_lights_hsl_register_hslsat(elmt_idx + 2);
if (hslsat_lid == MESH_INVALID_LID)
{
break;
}
// 5. Bound models together
mm_lights_hsl_bind(hsl_lid, hsls_lid, hslh_lid, hslsat_lid);
mdl_lid = hsl_lid;
if (main)
{
// Create group and set Light HSL Server model as main model
m_lid_t grp_lid = grp_lid = mm_bind_add_group(3, elmt_idx, hsl_lid,
mm_lights_hsl_cb_grp_event, mm_lights_hsl_cb_trans_req);
// Add Generic Level Server model to the group
mm_gens_lvl_bind_group(grp_lid, mm_state_get_lid(elmt_idx, MM_ID_GENS_LVL));
// Add Generic OnOff Server model to the group
mm_gens_oo_bind_group(grp_lid, mm_state_get_lid(elmt_idx, MM_ID_GENS_OO));
// Add Light Lightness Server model to the group
mm_lights_ln_bind_group(grp_lid, ln_lid);
// Create group and set Light HSL Hue Server model as main model
grp_lid = mm_bind_add_group(1, elmt_idx + 1, hslh_lid,
mm_lights_hsl_cb_grp_event_hue_sat,
mm_lights_hsl_cb_trans_req_hue_sat);
// Add Generic Level Server model to the group
mm_gens_lvl_bind_group(grp_lid, lvl1_lid);
// Create group and set Light HSL Saturation Server model as main model
grp_lid = mm_bind_add_group(1, elmt_idx + 2, hslsat_lid,
mm_lights_hsl_cb_grp_event_hue_sat,
mm_lights_hsl_cb_trans_req_hue_sat);
// Add Generic Level Server model to the group
mm_gens_lvl_bind_group(grp_lid, lvl2_lid);
}
} while (0);
return (mdl_lid);
}
/// @} end of group