HI,
I've noticed a few issues with the example app_level.c.
1: The g_set_transition() was updated in the 3.0.0 release to avoid a division by zero, however, this fix introduced a bug. Notice that line 9 below uses params.move.required_move instead of the correct params.set.required_delta. This is easy to fix, simply remove line 9 as the check is the same for both TRANSITION_SET and TRANSITION_DELTA_SET.
static bool g_set_transition(void * p_data)
{
app_level_server_t * p_server = (app_level_server_t *) p_data;
switch (p_server->state.transition_type)
{
/* Requirement: If transition time is not within valid range, do not start the transition. */
case TRANSITION_SET:
return (p_server->state.transition_time_ms > 0 && p_server->state.params.move.required_move != 0);
case TRANSITION_DELTA_SET:
return (p_server->state.transition_time_ms > 0 && p_server->state.params.set.required_delta != 0);
/* Requirement: If transition time is not within valid range, or given move level (delta level)
is zero, do not start the transition. */
case TRANSITION_MOVE_SET:
return (p_server->state.transition_time_ms > 0 &&
p_server->state.transition_time_ms != MODEL_TRANSITION_TIME_INVALID &&
p_server->state.params.move.required_move != 0);
default:
return false;
}
}
While looking at this code, line 17 should either be removed or introduced for TRANSITION_(DELTA)_SET as well. The only time this can happen is if the user set a bad value in p_server->p_dtt_ms. The generic_level_server.c implementation ensures that the transition time is always valid when app_level.c receives it.
2: The transition "parsing" in generic_level_state_move_set_cb() contain some redundant code.
* Line 22 should be removed as the target_level is correctly set later.
* Line 28 to 35 should also be removed as the validation of the transition time has already been done by generic_level_server.c. This matches the behavior of the other two _set callbacks. The TRANSITION_TIME_STEP_100MS_MAX is also wrong, but that doesn't matter as it should be removed all together.
static void generic_level_state_move_set_cb(const generic_level_server_t * p_self,
const access_message_rx_meta_t * p_meta,
const generic_level_move_set_params_t * p_in,
const model_transition_t * p_in_transition,
generic_level_status_params_t * p_out)
{
app_level_server_t * p_server = PARENT_BY_FIELD_GET(app_level_server_t, server, p_self);
/* Update internal representation of Level value, process timing. */
if (p_in_transition == NULL)
{
p_server->state.delay_ms = 0;
if (p_server->p_dtt_ms == NULL)
{
p_server->state.transition_time_ms = 0;
}
else
{
p_server->state.transition_time_ms = *p_server->p_dtt_ms;
}
p_server->state.target_level = p_server->state.present_level;
}
else
{
p_server->state.delay_ms = p_in_transition->delay_ms;
/* Requirement: If transition time is out of range, transition cannot be started. However
this must be stored to respond correctly to the get messages. */
if (p_in_transition->transition_time_ms > TRANSITION_TIME_STEP_100MS_MAX)
{
p_server->state.transition_time_ms = MODEL_TRANSITION_TIME_INVALID;
}
else
{
p_server->state.transition_time_ms = p_in_transition->transition_time_ms;
}
}
3: Generic Move Set with a Delta Level (called move_level in the SDK for some reason) of 0 doesn't work properly. From the standard, "When a Generic Level Server receives the message with a value of the Delta Level field equal to 0, it shall stop changing the Generic Level state.". The current implementation doesn't handle this properly.
Since g_set_delay and g_set_transition both will return false, the only outcome in the transition state table is FSM_NO_ACTION. This is wrong and the correct action should be A_TRANSITION_COMPLETE.
FSM_TRANSITION(E_MOVE_SET, G_SET_DELAY, A_DELAY_START, S_IN_DELAY),
FSM_TRANSITION(E_MOVE_SET, G_SET_TRANSITION, A_TRANSITION_START, S_IN_TRANSITION),
FSM_TRANSITION(E_MOVE_SET, FSM_OTHERWISE, FSM_NO_ACTION, S_IDLE)
4: The function a_transition_complete() doesn't work properly for Generic Move Set. The assignment `p_server->state.present_level = p_server->state.target_level;` should only be done for all TRANSITION_MOVE_SET otherwise the present_level would be set to either INT16_MIN or INT16_MAX.
5: From section 7.4.1.3 "It is recommended than an additional status message is published within 1 second after a state transition starts if the transition time is 2 seconds or longer.". The implementation doesn't currently seem to follow this recommendation.
I'm using SDK For Mesh v3.1.0.
Thanks