From Mesh Model Specification 1.0.1.
"3.3.2.2.2 Receiving Generic Level Set / Generic Level Set Unacknowledged messages
If the Transition Time field is included, the Delay field is included and indicates a delay 5-millisecond steps that the server shall wait before executing any state-changing behavior for this message."
"7.4.1.2 State change on receiving an acknowledged state-changing message
When a state is changed as a result of an acknowledged Set message, a corresponding unacknowledged unicast Status acknowledgment message is sent back to the originator. Additionally, a second unacknowledged status message is published to the model’s Publish Address to inform potential subscribers about the state change."
Reading the above it's clear that the Status message sent as a response to an acknowledged Set message (and the additional unacknowledged Status message) shouldn't be sent until the state is changed, which according to 3.2.2.2.2 doesn't happen until after the delay parameter.
However, the way the current Mesh SDK is designed this is not very easy.
When a message is received by the Access layer a access_message_rx_t is allocated on the stack and populate with information from lower layers. The access layer will eventually call the op_code handler that have the option to call access_model_reply() with appropriate content in order to generate a response. This design work fine for all message that doesn't require a Delay. However, if the received message includes a Delay the reply shouldn't be sent directly but rather delay. The function access_model_reply() is currently always called in all models supported in the models/model_spec/ provided by Nordic.
It's fairly obvious that the examples have implemented a bad hack around this issue in an attempt to be compliant, the response is sent to early with information which is thought to be correct in the future. From line 309 in app_level.c
/* Prepare response */
if (p_out != NULL)
{
p_out->present_level = p_app->state.present_level;
p_out->target_level = p_app->state.target_snapshot;
p_out->remaining_time_ms = p_params->transition_time_ms;
}
The response here contain target_snapshort and requested transition_time_ms which likely are different from the Status message generated in response to a Get request (received before delay timer expires) if the Set message included a delay parameter.
The only way I can see to fix this without messing with the internals of the Mesh Stack would be to change all the models in model_spec to ignore p_out and not send a reply if the received message included a Delay. In addition, the application level part of the model would need to keep a copy of the provided access_message_rx_meta_t * p_meta and when the delay has finished generate a reply using this information and a fake access_message_rx_t struct.
Using SDK For Mesh v5.0.0.
Thanks.