From f649fbc8b3c5131d6d457efc51b3de477b8df6dc Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Fri, 21 Jun 2019 14:53:50 +0200 Subject: [PATCH] mesh: introduce transaction status --- test/mesh/mesh_access.c | 27 ++++ test/mesh/mesh_access.h | 16 ++- test/mesh/mesh_generic_level_server.c | 177 +++++++++++++++----------- test/mesh/mesh_generic_level_server.h | 9 +- test/mesh/mesh_generic_server.c | 139 ++++++++++---------- test/mesh/mesh_generic_server.h | 3 +- 6 files changed, 222 insertions(+), 149 deletions(-) diff --git a/test/mesh/mesh_access.c b/test/mesh/mesh_access.c index 2370c9592..96db4c57c 100644 --- a/test/mesh/mesh_access.c +++ b/test/mesh/mesh_access.c @@ -47,6 +47,8 @@ #include "mesh_foundation.h" #include "btstack_tlv.h" +#define MEST_TRANSACTION_TIMEOUT_MS 6000 + static void mesh_access_message_process_handler(mesh_pdu_t * pdu); static uint16_t primary_element_address; @@ -111,6 +113,31 @@ void mesh_access_emit_state_update_int16(btstack_packet_handler_t * event_handle // Mesh Model Transitions +void mesh_access_transitions_setup_transaction(mesh_transition_t * transition, uint8_t transaction_identifier, uint16_t src_address, uint16_t dst_address){ + transition->transaction_timestamp_ms = btstack_run_loop_get_time_ms(); + transition->transaction_identifier = transaction_identifier; + transition->src_address = src_address; + transition->dst_address = dst_address; +} + +void mesh_access_transitions_abort_transaction(mesh_transition_t * transition){ + mesh_access_transitions_remove(transition); +} + + +static int mesh_access_transitions_transaction_is_expired(mesh_transition_t * transition){ + return (btstack_run_loop_get_time_ms() - transition->transaction_timestamp_ms) > MEST_TRANSACTION_TIMEOUT_MS; +} + +mesh_transaction_status_t mesh_access_transitions_transaction_status(mesh_transition_t * transition, uint8_t transaction_identifier, uint16_t src_address, uint16_t dst_address){ + if (transition->src_address != src_address || transition->dst_address != dst_address) return MESH_TRANSACTION_STATUS_DIFFERENT_DST_OR_SRC; + + if (transition->transaction_identifier == transaction_identifier && !mesh_access_transitions_transaction_is_expired(transition)){ + return MESH_TRANSACTION_STATUS_RETRANSMISSION; + } + return MESH_TRANSACTION_STATUS_NEW; +} + uint8_t mesh_access_transitions_num_steps_from_gdtt(uint8_t transition_time_gdtt){ return transition_time_gdtt >> 2; } diff --git a/test/mesh/mesh_access.h b/test/mesh/mesh_access.h index 3b9a5997f..abf0fef8a 100644 --- a/test/mesh/mesh_access.h +++ b/test/mesh/mesh_access.h @@ -173,16 +173,26 @@ typedef struct { const char * format; } mesh_access_message_t; +typedef enum { + MESH_TRANSACTION_STATUS_NEW = 0, + MESH_TRANSACTION_STATUS_RETRANSMISSION, + MESH_TRANSACTION_STATUS_DIFFERENT_DST_OR_SRC +} mesh_transaction_status_t; + typedef struct mesh_transition { btstack_linked_item_t item; mesh_transition_state_t state; + uint8_t transaction_identifier; + uint32_t transaction_timestamp_ms; + uint16_t src_address; + uint16_t dst_address; + mesh_default_transition_step_resolution_t step_duration_ms; uint32_t phase_start_ms; uint32_t remaining_delay_time_ms; uint32_t remaining_transition_time_ms; - // to send events and/or publish changes mesh_model_t * mesh_model; @@ -257,6 +267,10 @@ void mesh_access_emit_state_update_int16(btstack_packet_handler_t * event_handle model_state_id_t state_identifier, model_state_update_reason_t reason, int16_t value); // Mesh Model Transitions +void mesh_access_transitions_setup_transaction(mesh_transition_t * transition, uint8_t transaction_identifier, uint16_t src_address, uint16_t dst_address); +void mesh_access_transitions_abort_transaction(mesh_transition_t * transition); +mesh_transaction_status_t mesh_access_transitions_transaction_status(mesh_transition_t * transition, uint8_t transaction_identifier, uint16_t src_address, uint16_t dst_address); + void mesh_access_transitions_setup(mesh_transition_t * transition, mesh_model_t * mesh_model, uint8_t transition_time_gdtt, uint8_t delay_gdtt, void (* transition_callback)(struct mesh_transition * transition, transition_event_t event, uint32_t current_timestamp)); diff --git a/test/mesh/mesh_generic_level_server.c b/test/mesh/mesh_generic_level_server.c index 066f88896..bb8f40d7f 100644 --- a/test/mesh/mesh_generic_level_server.c +++ b/test/mesh/mesh_generic_level_server.c @@ -68,7 +68,12 @@ static int16_t add_and_clip_int16(int16_t current_value, int16_t increment){ return (int16_t) value; } -static void mesh_server_transition_state_update_stepwise_value(mesh_transition_uint16_t * transition){ +static mesh_transition_t * generic_level_server_get_base_transition(mesh_model_t * mesh_model) { + mesh_generic_level_state_t * generic_level_server_state = (mesh_generic_level_state_t *)mesh_model->model_data; + return &generic_level_server_state->transition_data.base_transition; +} + +static void mesh_server_transition_state_update_stepwise_value(mesh_transition_int16_t * transition){ mesh_model_t * generic_level_server_model = transition->base_transition.mesh_model; transition->current_value = add_and_clip_int16(transition->current_value, transition->stepwise_value_increment); @@ -81,7 +86,7 @@ static void mesh_server_transition_state_update_stepwise_value(mesh_transition_u transition->current_value); } -static void mesh_server_transition_state_update(mesh_transition_uint16_t * transition, uint32_t current_timestamp_ms){ +static void mesh_server_transition_state_update(mesh_transition_int16_t * transition, uint32_t current_timestamp_ms){ if (transition->base_transition.remaining_delay_time_ms != 0){ transition->base_transition.state = MESH_TRANSITION_STATE_DELAYED; transition->base_transition.remaining_delay_time_ms = 0; @@ -115,7 +120,7 @@ static void mesh_server_transition_state_update(mesh_transition_uint16_t * trans static void mesh_server_transition_step(mesh_transition_t * base_transition, transition_event_t event, uint32_t current_timestamp){ uint32_t time_step_ms; - mesh_transition_uint16_t * transition = (mesh_transition_uint16_t*) base_transition; + mesh_transition_int16_t * transition = (mesh_transition_int16_t*) base_transition; switch (transition->base_transition.state){ case MESH_TRANSITION_STATE_IDLE: @@ -219,11 +224,11 @@ static void mesh_generic_level_status_message(mesh_model_t *generic_level_server } -static void generic_level_handle_set_target_level_message(mesh_model_t *generic_level_server_model, mesh_pdu_t * pdu){ - if (generic_level_server_model == NULL){ - log_error("generic_level_server_model == NULL"); +static void generic_level_handle_set_target_level_message(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ + if (mesh_model == NULL){ + log_error("mesh_model == NULL"); } - mesh_generic_level_state_t * generic_level_server_state = (mesh_generic_level_state_t *)generic_level_server_model->model_data; + mesh_generic_level_state_t * generic_level_server_state = (mesh_generic_level_state_t *)mesh_model->model_data; if (generic_level_server_state == NULL){ log_error("generic_level_server_state == NULL"); @@ -235,38 +240,42 @@ static void generic_level_handle_set_target_level_message(mesh_model_t *generic_ // The TID field is a transaction identifier indicating whether the message is // a new message or a retransmission of a previously sent message uint8_t tid = mesh_access_parser_get_u8(&parser); - - if (tid == generic_level_server_state->transaction_identifier){ - printf("retransmission\n"); - return; - } - - generic_level_server_state->transition_data.target_value = level_value; - generic_level_server_state->transition_data.stepwise_value_increment = 0; - generic_level_server_state->transaction_identifier = tid; - + uint8_t transition_time_gdtt = 0; uint8_t delay_time_gdtt = 0; - if (mesh_access_parser_available(&parser) == 2){ - // Generic Default Transition Time format - num_steps (higher 6 bits), step_resolution (lower 2 bits) - transition_time_gdtt = mesh_access_parser_get_u8(&parser); - delay_time_gdtt = mesh_access_parser_get_u8(&parser); - int num_steps = mesh_access_transitions_num_steps_from_gdtt(transition_time_gdtt); - if (num_steps > 0){ - // TODO: remove division - generic_level_server_state->transition_data.stepwise_value_increment = (level_value - generic_level_server_state->transition_data.current_value)/num_steps; - } - } + mesh_transition_t * base_transition = generic_level_server_get_base_transition(mesh_model); - mesh_server_transition_setup_transition_or_instantaneous_update_int16(generic_level_server_model, transition_time_gdtt, delay_time_gdtt, MODEL_STATE_UPDATE_REASON_SET); + switch (mesh_access_transitions_transaction_status(base_transition, tid, mesh_pdu_src(pdu), mesh_pdu_dst(pdu))){ + case MESH_TRANSACTION_STATUS_RETRANSMISSION: + // ignore + break; + default: + mesh_access_transitions_setup_transaction(base_transition, tid, mesh_pdu_src(pdu), mesh_pdu_dst(pdu)); + + generic_level_server_state->transition_data.target_value = level_value; + generic_level_server_state->transition_data.stepwise_value_increment = 0; + + if (mesh_access_parser_available(&parser) == 2){ + // Generic Default Transition Time format - num_steps (higher 6 bits), step_resolution (lower 2 bits) + transition_time_gdtt = mesh_access_parser_get_u8(&parser); + delay_time_gdtt = mesh_access_parser_get_u8(&parser); + int num_steps = mesh_access_transitions_num_steps_from_gdtt(transition_time_gdtt); + if (num_steps > 0){ + // TODO: remove division + generic_level_server_state->transition_data.stepwise_value_increment = (level_value - generic_level_server_state->transition_data.current_value)/num_steps; + } + } + mesh_server_transition_setup_transition_or_instantaneous_update_int16(mesh_model, transition_time_gdtt, delay_time_gdtt, MODEL_STATE_UPDATE_REASON_SET); + break; + } + } - -static void generic_level_handle_set_move_message(mesh_model_t *generic_level_server_model, mesh_pdu_t * pdu){ - if (generic_level_server_model == NULL){ - log_error("generic_level_server_model == NULL"); +static void generic_level_handle_set_move_message(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ + if (mesh_model == NULL){ + log_error("mesh_model == NULL"); } - mesh_generic_level_state_t * generic_level_server_state = (mesh_generic_level_state_t *)generic_level_server_model->model_data; + mesh_generic_level_state_t * generic_level_server_state = (mesh_generic_level_state_t *)mesh_model->model_data; if (generic_level_server_state == NULL){ log_error("generic_level_server_state == NULL"); @@ -275,42 +284,46 @@ static void generic_level_handle_set_move_message(mesh_model_t *generic_level_se mesh_access_parser_state_t parser; mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); int16_t increment_value = (int16_t)mesh_access_parser_get_u16(&parser); + // The TID field is a transaction identifier indicating whether the message is // a new message or a retransmission of a previously sent message uint8_t tid = mesh_access_parser_get_u8(&parser); - // uint16_t src = mesh_pdu_src(pdu); - // uint16_t dst = mesh_pdu_dst(pdu); - - if (tid == generic_level_server_state->transaction_identifier){ - printf("retransmission\n"); - return; - } - - generic_level_server_state->transition_data.target_value = add_and_clip_int16(generic_level_server_state->transition_data.current_value, increment_value); - generic_level_server_state->transition_data.stepwise_value_increment = increment_value; - generic_level_server_state->transaction_identifier = tid; - + uint8_t transition_time_gdtt = 0; uint8_t delay_time_gdtt = 0; - if (mesh_access_parser_available(&parser) == 2){ - // Generic Default Transition Time format - num_steps (higher 6 bits), step_resolution (lower 2 bits) - transition_time_gdtt = mesh_access_parser_get_u8(&parser); - delay_time_gdtt = mesh_access_parser_get_u8(&parser); - int num_steps = mesh_access_transitions_num_steps_from_gdtt(transition_time_gdtt); - if (num_steps > 0){ - // TODO: remove division - generic_level_server_state->transition_data.target_value = add_and_clip_int16(generic_level_server_state->transition_data.current_value, increment_value * num_steps); - } - } - mesh_server_transition_setup_transition_or_instantaneous_update_int16(generic_level_server_model, transition_time_gdtt, delay_time_gdtt, MODEL_STATE_UPDATE_REASON_SET); + mesh_transition_t * base_transition = generic_level_server_get_base_transition(mesh_model); + + switch (mesh_access_transitions_transaction_status(base_transition, tid, mesh_pdu_src(pdu), mesh_pdu_dst(pdu))){ + case MESH_TRANSACTION_STATUS_RETRANSMISSION: + // ignore retransmission + break; + default: + mesh_access_transitions_setup_transaction(base_transition, tid, mesh_pdu_src(pdu), mesh_pdu_dst(pdu)); + + generic_level_server_state->transition_data.target_value = add_and_clip_int16(generic_level_server_state->transition_data.current_value, increment_value); + generic_level_server_state->transition_data.stepwise_value_increment = increment_value; + + if (mesh_access_parser_available(&parser) == 2){ + // Generic Default Transition Time format - num_steps (higher 6 bits), step_resolution (lower 2 bits) + transition_time_gdtt = mesh_access_parser_get_u8(&parser); + delay_time_gdtt = mesh_access_parser_get_u8(&parser); + int num_steps = mesh_access_transitions_num_steps_from_gdtt(transition_time_gdtt); + if (num_steps > 0){ + // TODO: remove division + generic_level_server_state->transition_data.target_value = add_and_clip_int16(generic_level_server_state->transition_data.current_value, increment_value * num_steps); + } + } + mesh_server_transition_setup_transition_or_instantaneous_update_int16(mesh_model, transition_time_gdtt, delay_time_gdtt, MODEL_STATE_UPDATE_REASON_SET); + break; + } } -static void generic_level_handle_set_delta_message(mesh_model_t *generic_level_server_model, mesh_pdu_t * pdu){ - if (generic_level_server_model == NULL){ - log_error("generic_level_server_model == NULL"); +static void generic_level_handle_set_delta_message(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ + if (mesh_model == NULL){ + log_error("mesh_model == NULL"); } - mesh_generic_level_state_t * generic_level_server_state = (mesh_generic_level_state_t *)generic_level_server_model->model_data; + mesh_generic_level_state_t * generic_level_server_state = (mesh_generic_level_state_t *)mesh_model->model_data; if (generic_level_server_state == NULL){ log_error("generic_level_server_state == NULL"); @@ -319,27 +332,39 @@ static void generic_level_handle_set_delta_message(mesh_model_t *generic_level_s mesh_access_parser_state_t parser; mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); int16_t delta_value = (int16_t) mesh_access_parser_get_u16(&parser); + // The TID field is a transaction identifier indicating whether the message is // a new message or a retransmission of a previously sent message uint8_t tid = mesh_access_parser_get_u8(&parser); - - if (tid != generic_level_server_state->transaction_identifier){ - printf("retransmission\n"); - return; - } - - generic_level_server_state->transition_data.target_value = add_and_clip_int16(generic_level_server_state->transition_data.current_value, delta_value); - generic_level_server_state->transition_data.stepwise_value_increment = delta_value; - generic_level_server_state->transaction_identifier = tid; - uint8_t transition_time_gdtt = 0; uint8_t delay_time_gdtt = 0; - if (mesh_access_parser_available(&parser) == 2){ - // Generic Default Transition Time format - num_steps (higher 6 bits), step_resolution (lower 2 bits) - transition_time_gdtt = mesh_access_parser_get_u8(&parser); - delay_time_gdtt = mesh_access_parser_get_u8(&parser); - } - mesh_server_transition_setup_transition_or_instantaneous_update_int16(generic_level_server_model, transition_time_gdtt, delay_time_gdtt, MODEL_STATE_UPDATE_REASON_SET); + + mesh_transition_t * base_transition = generic_level_server_get_base_transition(mesh_model); + + switch (mesh_access_transitions_transaction_status(base_transition, tid, mesh_pdu_src(pdu), mesh_pdu_dst(pdu))){ + case MESH_TRANSACTION_STATUS_DIFFERENT_DST_OR_SRC: + // abort transaction + mesh_access_transitions_abort_transaction(base_transition); + break; + case MESH_TRANSACTION_STATUS_RETRANSMISSION: + // ignore + break; + case MESH_TRANSACTION_STATUS_NEW: + mesh_access_transitions_setup_transaction(base_transition, tid, mesh_pdu_src(pdu), mesh_pdu_dst(pdu)); + + generic_level_server_state->transition_data.target_value = add_and_clip_int16(generic_level_server_state->transition_data.current_value, delta_value); + generic_level_server_state->transition_data.stepwise_value_increment = delta_value; + + if (mesh_access_parser_available(&parser) == 2){ + // Generic Default Transition Time format - num_steps (higher 6 bits), step_resolution (lower 2 bits) + transition_time_gdtt = mesh_access_parser_get_u8(&parser); + delay_time_gdtt = mesh_access_parser_get_u8(&parser); + } + mesh_server_transition_setup_transition_or_instantaneous_update_int16(mesh_model, transition_time_gdtt, delay_time_gdtt, MODEL_STATE_UPDATE_REASON_SET); + break; + default: + break; + } } diff --git a/test/mesh/mesh_generic_level_server.h b/test/mesh/mesh_generic_level_server.h index a30188182..c8878c8a0 100644 --- a/test/mesh/mesh_generic_level_server.h +++ b/test/mesh/mesh_generic_level_server.h @@ -59,19 +59,16 @@ extern "C" typedef struct { mesh_transition_t base_transition; + int16_t initial_value; int16_t current_value; int16_t target_value; int16_t stepwise_value_increment; - int16_t delta_from_initial_value; int16_t transition_speed; -} mesh_transition_uint16_t; +} mesh_transition_int16_t; typedef struct { - mesh_transition_uint16_t transition_data; - uint8_t transaction_identifier; - uint16_t src_address; - uint16_t dst_address; + mesh_transition_int16_t transition_data; } mesh_generic_level_state_t; const mesh_operation_t * mesh_generic_level_server_get_operations(void); diff --git a/test/mesh/mesh_generic_server.c b/test/mesh/mesh_generic_server.c index 157a218b1..78db1b286 100644 --- a/test/mesh/mesh_generic_server.c +++ b/test/mesh/mesh_generic_server.c @@ -58,51 +58,11 @@ static void generic_server_send_message(uint16_t src, uint16_t dest, uint16_t ne mesh_upper_transport_send_access_pdu(pdu); } -// Generic On Off State +// Transaction management -void mesh_generic_on_off_server_register_packet_handler(mesh_model_t *generic_on_off_server_model, btstack_packet_handler_t transition_events_packet_handler){ - if (transition_events_packet_handler == NULL){ - log_error("mesh_generic_on_off_server_register_packet_handler called with NULL callback"); - return; - } - if (generic_on_off_server_model == NULL){ - log_error("mesh_generic_on_off_server_register_packet_handler called with NULL generic_on_off_server_model"); - return; - } - generic_on_off_server_model->transition_events_packet_handler = &transition_events_packet_handler; -} - -const mesh_access_message_t mesh_generic_on_off_status_transition = { - MESH_GENERIC_ON_OFF_STATUS, "111" -}; - -const mesh_access_message_t mesh_generic_on_off_status_instantaneous = { - MESH_GENERIC_ON_OFF_STATUS, "1" -}; - -static void mesh_generic_on_off_status_message(mesh_model_t *generic_on_off_server_model, uint16_t netkey_index, uint16_t dest, uint16_t appkey_index){ - if (generic_on_off_server_model->element == NULL){ - log_error("generic_on_off_server_model->element == NULL"); - } - - mesh_generic_on_off_state_t * state = (mesh_generic_on_off_state_t *) generic_on_off_server_model->model_data; - if (state == NULL){ - log_error("generic_on_off_status == NULL"); - } - // setup message - mesh_transport_pdu_t * transport_pdu = NULL; - - - if (state->transition_data.base_transition.remaining_transition_time_ms != 0) { - transport_pdu = mesh_access_setup_segmented_message(&mesh_generic_on_off_status_transition, state->transition_data.current_value, - state->transition_data.target_value, state->transition_data.base_transition.remaining_transition_time_ms); - } else { - transport_pdu = mesh_access_setup_segmented_message(&mesh_generic_on_off_status_instantaneous, state->transition_data.current_value); - } - if (!transport_pdu) return; - - // send as segmented access pdu - generic_server_send_message(mesh_access_get_element_address(generic_on_off_server_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu); +static mesh_transition_t * generic_on_off_server_get_base_transition(mesh_model_t * mesh_model) { + mesh_generic_on_off_state_t * generic_on_off_server_state = (mesh_generic_on_off_state_t *)mesh_model->model_data; + return &generic_on_off_server_state->transition_data.base_transition; } static void mesh_server_transition_state_update(mesh_transition_bool_t * transition, uint32_t current_timestamp_ms){ @@ -204,16 +164,63 @@ static void mesh_server_transition_setup_transition_or_instantaneous_update(mesh } +// Generic On Off State + +void mesh_generic_on_off_server_register_packet_handler(mesh_model_t *generic_on_off_server_model, btstack_packet_handler_t transition_events_packet_handler){ + if (transition_events_packet_handler == NULL){ + log_error("mesh_generic_on_off_server_register_packet_handler called with NULL callback"); + return; + } + if (generic_on_off_server_model == NULL){ + log_error("mesh_generic_on_off_server_register_packet_handler called with NULL generic_on_off_server_model"); + return; + } + generic_on_off_server_model->transition_events_packet_handler = &transition_events_packet_handler; +} + +const mesh_access_message_t mesh_generic_on_off_status_transition = { + MESH_GENERIC_ON_OFF_STATUS, "111" +}; + +const mesh_access_message_t mesh_generic_on_off_status_instantaneous = { + MESH_GENERIC_ON_OFF_STATUS, "1" +}; + +static void mesh_generic_on_off_status_message(mesh_model_t *generic_on_off_server_model, uint16_t netkey_index, uint16_t dest, uint16_t appkey_index){ + if (generic_on_off_server_model->element == NULL){ + log_error("generic_on_off_server_model->element == NULL"); + } + + mesh_generic_on_off_state_t * state = (mesh_generic_on_off_state_t *) generic_on_off_server_model->model_data; + if (state == NULL){ + log_error("generic_on_off_status == NULL"); + } + // setup message + mesh_transport_pdu_t * transport_pdu = NULL; + + + if (state->transition_data.base_transition.remaining_transition_time_ms != 0) { + transport_pdu = mesh_access_setup_segmented_message(&mesh_generic_on_off_status_transition, state->transition_data.current_value, + state->transition_data.target_value, state->transition_data.base_transition.remaining_transition_time_ms); + } else { + transport_pdu = mesh_access_setup_segmented_message(&mesh_generic_on_off_status_instantaneous, state->transition_data.current_value); + } + if (!transport_pdu) return; + + // send as segmented access pdu + generic_server_send_message(mesh_access_get_element_address(generic_on_off_server_model), dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu); +} + static void generic_on_off_get_handler(mesh_model_t *generic_on_off_server_model, mesh_pdu_t * pdu){ mesh_generic_on_off_status_message(generic_on_off_server_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), mesh_pdu_appkey_index(pdu)); mesh_access_message_processed(pdu); } -static void generic_on_off_handle_set_message(mesh_model_t *generic_on_off_server_model, mesh_pdu_t * pdu){ - if (generic_on_off_server_model == NULL){ - log_error("generic_on_off_server_model == NULL"); +static void generic_on_off_handle_set_message(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ + if (mesh_model == NULL){ + log_error("mesh_model == NULL"); } - mesh_generic_on_off_state_t * generic_on_off_server_state = (mesh_generic_on_off_state_t *)generic_on_off_server_model->model_data; + mesh_generic_on_off_state_t * generic_on_off_server_state = (mesh_generic_on_off_state_t *)mesh_model->model_data; if (generic_on_off_server_state == NULL){ log_error("generic_on_off_server_state == NULL"); @@ -222,27 +229,31 @@ static void generic_on_off_handle_set_message(mesh_model_t *generic_on_off_serve mesh_access_parser_state_t parser; mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); uint8_t on_off_value = mesh_access_parser_get_u8(&parser); + // The TID field is a transaction identifier indicating whether the message is // a new message or a retransmission of a previously sent message uint8_t tid = mesh_access_parser_get_u8(&parser); - - if (tid == generic_on_off_server_state->transaction_identifier){ - printf("retransmission\n"); - return; - } - - generic_on_off_server_state->transition_data.target_value = on_off_value; - generic_on_off_server_state->transaction_identifier = tid; - uint8_t transition_time_gdtt = 0; uint8_t delay_time_gdtt = 0; - if (mesh_access_parser_available(&parser) == 2){ - // Generic Default Transition Time format - num_steps (higher 6 bits), step_resolution (lower 2 bits) - transition_time_gdtt = mesh_access_parser_get_u8(&parser); - delay_time_gdtt = mesh_access_parser_get_u8(&parser); - } - - mesh_server_transition_setup_transition_or_instantaneous_update(generic_on_off_server_model, transition_time_gdtt, delay_time_gdtt, MODEL_STATE_UPDATE_REASON_SET); + + mesh_transition_t * base_transition = generic_on_off_server_get_base_transition(mesh_model); + + switch (mesh_access_transitions_transaction_status(base_transition, tid, mesh_pdu_src(pdu), mesh_pdu_dst(pdu))){ + case MESH_TRANSACTION_STATUS_RETRANSMISSION: + // ignore on retransmission + break; + default: + mesh_access_transitions_setup_transaction(base_transition, tid, mesh_pdu_src(pdu), mesh_pdu_dst(pdu)); + generic_on_off_server_state->transition_data.target_value = on_off_value; + + if (mesh_access_parser_available(&parser) == 2){ + // Generic Default Transition Time format - num_steps (higher 6 bits), step_resolution (lower 2 bits) + transition_time_gdtt = mesh_access_parser_get_u8(&parser); + delay_time_gdtt = mesh_access_parser_get_u8(&parser); + } + mesh_server_transition_setup_transition_or_instantaneous_update(mesh_model, transition_time_gdtt, delay_time_gdtt, MODEL_STATE_UPDATE_REASON_SET); + break; + } } static void generic_on_off_set_handler(mesh_model_t *generic_on_off_server_model, mesh_pdu_t * pdu){ diff --git a/test/mesh/mesh_generic_server.h b/test/mesh/mesh_generic_server.h index 8b446656a..a0280f900 100644 --- a/test/mesh/mesh_generic_server.h +++ b/test/mesh/mesh_generic_server.h @@ -59,8 +59,7 @@ typedef struct { } mesh_transition_bool_t; typedef struct { - mesh_transition_bool_t transition_data; - uint8_t transaction_identifier; + mesh_transition_bool_t transition_data; } mesh_generic_on_off_state_t; const mesh_operation_t * mesh_generic_on_off_server_get_operations(void);