mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-02-25 06:40:10 +00:00
mesh: generic on/off + level server - move transition logic to mesh_access
This commit is contained in:
parent
8245767ef9
commit
332b525621
@ -70,9 +70,6 @@ static btstack_timer_source_t mesh_access_acknowledged_timer;
|
||||
static int mesh_access_acknowledged_timer_active;
|
||||
|
||||
// Transitions
|
||||
static btstack_linked_list_t transitions;
|
||||
static btstack_timer_source_t transitions_timer;
|
||||
static uint32_t transition_step_min_ms;
|
||||
static uint8_t mesh_transaction_id_counter = 0;
|
||||
|
||||
void mesh_access_init(void){
|
||||
@ -249,29 +246,11 @@ static void mesh_access_upper_transport_handler(mesh_transport_callback_type_t c
|
||||
|
||||
// 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;
|
||||
}
|
||||
uint32_t mesh_access_time_gdtt2ms(uint8_t time_gdtt){
|
||||
uint8_t num_steps = mesh_access_transitions_num_steps_from_gdtt(time_gdtt);
|
||||
if (num_steps > 0x3E) return 0;
|
||||
|
||||
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;
|
||||
return mesh_access_transitions_step_ms_from_gdtt(time_gdtt) * num_steps;
|
||||
}
|
||||
|
||||
uint8_t mesh_access_transitions_num_steps_from_gdtt(uint8_t time_gdtt){
|
||||
@ -294,115 +273,6 @@ uint32_t mesh_access_transitions_step_ms_from_gdtt(uint8_t time_gdtt){
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t mesh_access_time_gdtt2ms(uint8_t time_gdtt){
|
||||
uint8_t num_steps = mesh_access_transitions_num_steps_from_gdtt(time_gdtt);
|
||||
if (num_steps > 0x3E) return 0;
|
||||
|
||||
return mesh_access_transitions_step_ms_from_gdtt(time_gdtt) * num_steps;
|
||||
}
|
||||
|
||||
uint8_t mesh_access_time_as_gdtt(uint32_t step_resolution_ms, uint32_t time_ms){
|
||||
uint8_t resolution;
|
||||
switch (step_resolution_ms){
|
||||
case 100:
|
||||
resolution = MESH_DEFAULT_TRANSITION_STEP_RESOLUTION_100ms;
|
||||
break;
|
||||
case 1000:
|
||||
resolution = MESH_DEFAULT_TRANSITION_STEP_RESOLUTION_1s;
|
||||
break;
|
||||
case 10000:
|
||||
resolution = MESH_DEFAULT_TRANSITION_STEP_RESOLUTION_10s;
|
||||
break;
|
||||
case 600000:
|
||||
resolution = MESH_DEFAULT_TRANSITION_STEP_RESOLUTION_10min;
|
||||
break;
|
||||
default:
|
||||
resolution = MESH_DEFAULT_TRANSITION_STEP_RESOLUTION_100ms;
|
||||
break;
|
||||
}
|
||||
uint8_t num_steps = time_ms / step_resolution_ms;
|
||||
return (resolution << 6) | num_steps;
|
||||
}
|
||||
|
||||
static void mesh_access_transitions_timeout_handler(btstack_timer_source_t * timer){
|
||||
btstack_linked_list_iterator_t it;
|
||||
btstack_linked_list_iterator_init(&it, &transitions);
|
||||
while (btstack_linked_list_iterator_has_next(&it)){
|
||||
mesh_transition_t * transition = (mesh_transition_t *)btstack_linked_list_iterator_next(&it);
|
||||
(transition->transition_callback)(transition, TRANSITION_UPDATE, btstack_run_loop_get_time_ms());
|
||||
}
|
||||
if (btstack_linked_list_empty(&transitions)) return;
|
||||
|
||||
btstack_run_loop_set_timer(timer, transition_step_min_ms);
|
||||
btstack_run_loop_add_timer(timer);
|
||||
}
|
||||
|
||||
static void mesh_access_transitions_timer_start(void){
|
||||
btstack_run_loop_remove_timer(&transitions_timer);
|
||||
btstack_run_loop_set_timer_handler(&transitions_timer, mesh_access_transitions_timeout_handler);
|
||||
btstack_run_loop_set_timer(&transitions_timer, transition_step_min_ms);
|
||||
btstack_run_loop_add_timer(&transitions_timer);
|
||||
}
|
||||
|
||||
static void mesh_access_transitions_timer_stop(void){
|
||||
btstack_run_loop_remove_timer(&transitions_timer);
|
||||
}
|
||||
|
||||
static uint32_t mesh_access_transitions_get_step_min_ms(void){
|
||||
uint32_t min_timeout_ms = 0;
|
||||
|
||||
btstack_linked_list_iterator_t it;
|
||||
btstack_linked_list_iterator_init(&it, &transitions);
|
||||
while (btstack_linked_list_iterator_has_next(&it)){
|
||||
mesh_transition_t * transition = (mesh_transition_t *)btstack_linked_list_iterator_next(&it);
|
||||
if (min_timeout_ms == 0 || transition->step_duration_ms < min_timeout_ms){
|
||||
min_timeout_ms = transition->step_duration_ms;
|
||||
}
|
||||
}
|
||||
return min_timeout_ms;
|
||||
}
|
||||
|
||||
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)){
|
||||
|
||||
// Only values of 0x00 through 0x3E shall be used to specify the value of the Transition Number of Steps field
|
||||
uint8_t num_steps = mesh_access_transitions_num_steps_from_gdtt(transition_time_gdtt);
|
||||
if (num_steps >= MESH_TRANSITION_NUM_STEPS_INFINITE) return;
|
||||
|
||||
transition->state = MESH_TRANSITION_STATE_IDLE;
|
||||
transition->phase_start_ms = 0;
|
||||
|
||||
transition->mesh_model = mesh_model;
|
||||
transition->transition_callback = transition_callback;
|
||||
transition->step_duration_ms = mesh_access_transitions_step_ms_from_gdtt(transition_time_gdtt);
|
||||
transition->remaining_delay_time_ms = delay_gdtt * 5;
|
||||
transition->remaining_transition_time_ms = num_steps * transition->step_duration_ms;
|
||||
transition->num_steps = num_steps;
|
||||
}
|
||||
|
||||
void mesh_access_transitions_add(mesh_transition_t * transition){
|
||||
if (transition->step_duration_ms == 0) return;
|
||||
|
||||
if (btstack_linked_list_empty(&transitions) || transition->step_duration_ms < transition_step_min_ms){
|
||||
transition_step_min_ms = transition->step_duration_ms;
|
||||
}
|
||||
mesh_access_transitions_timer_start();
|
||||
btstack_linked_list_add(&transitions, (btstack_linked_item_t *) transition);
|
||||
(transition->transition_callback)(transition, TRANSITION_START, btstack_run_loop_get_time_ms());
|
||||
}
|
||||
|
||||
void mesh_access_transitions_remove(mesh_transition_t * transition){
|
||||
mesh_access_transitions_setup(transition, NULL, 0, 0, NULL);
|
||||
btstack_linked_list_remove(&transitions, (btstack_linked_item_t *) transition);
|
||||
|
||||
if (btstack_linked_list_empty(&transitions)){
|
||||
mesh_access_transitions_timer_stop();
|
||||
} else {
|
||||
transition_step_min_ms = mesh_access_transitions_get_step_min_ms();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t mesh_access_transactions_get_next_transaction_id(void){
|
||||
mesh_transaction_id_counter++;
|
||||
if (mesh_transaction_id_counter == 0){
|
||||
@ -411,6 +281,95 @@ uint8_t mesh_access_transactions_get_next_transaction_id(void){
|
||||
return mesh_transaction_id_counter;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void mesh_access_transitions_init_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;
|
||||
}
|
||||
|
||||
static void mesh_server_transition_timeout(btstack_timer_source_t * ts){
|
||||
mesh_transition_t * base_transition = (mesh_transition_t*) btstack_run_loop_get_timer_context(ts);
|
||||
switch (base_transition->state){
|
||||
case MESH_TRANSITION_STATE_DELAYED:
|
||||
base_transition->state = MESH_TRANSITION_STATE_ACTIVE;
|
||||
(*base_transition->transition_callback)(base_transition, MODEL_STATE_UPDATE_REASON_TRANSITION_START);
|
||||
if (base_transition->num_steps > 0){
|
||||
btstack_run_loop_set_timer(&base_transition->timer, base_transition->step_duration_ms);
|
||||
btstack_run_loop_add_timer(&base_transition->timer);
|
||||
return;
|
||||
}
|
||||
base_transition->state = MESH_TRANSITION_STATE_IDLE;
|
||||
(*base_transition->transition_callback)(base_transition, MODEL_STATE_UPDATE_REASON_TRANSITION_END);
|
||||
break;
|
||||
case MESH_TRANSITION_STATE_ACTIVE:
|
||||
if (base_transition->num_steps < MESH_TRANSITION_NUM_STEPS_INFINITE){
|
||||
base_transition->num_steps--;
|
||||
}
|
||||
(*base_transition->transition_callback)(base_transition, MODEL_STATE_UPDATE_REASON_TRANSITION_ACTIVE);
|
||||
if (base_transition->num_steps > 0){
|
||||
btstack_run_loop_set_timer(&base_transition->timer, base_transition->step_duration_ms);
|
||||
btstack_run_loop_add_timer(&base_transition->timer);
|
||||
return;
|
||||
}
|
||||
base_transition->state = MESH_TRANSITION_STATE_IDLE;
|
||||
(*base_transition->transition_callback)(base_transition, MODEL_STATE_UPDATE_REASON_TRANSITION_END);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void mesh_access_transition_setup(mesh_model_t *mesh_model, mesh_transition_t * base_transition, uint8_t transition_time_gdtt, uint8_t delay_time_gdtt, void (*transition_callback)(mesh_transition_t * base_transition, model_state_update_reason_t event)){
|
||||
|
||||
base_transition->mesh_model = mesh_model;
|
||||
base_transition->num_steps = mesh_access_transitions_num_steps_from_gdtt(transition_time_gdtt);
|
||||
base_transition->step_resolution = (mesh_default_transition_step_resolution_t) (transition_time_gdtt >> 6);
|
||||
base_transition->step_duration_ms = mesh_access_transitions_step_ms_from_gdtt(transition_time_gdtt);
|
||||
base_transition->transition_callback = transition_callback;
|
||||
|
||||
btstack_run_loop_set_timer_context(&base_transition->timer, base_transition);
|
||||
btstack_run_loop_set_timer_handler(&base_transition->timer, &mesh_server_transition_timeout);
|
||||
|
||||
// delayed
|
||||
if (delay_time_gdtt > 0){
|
||||
base_transition->state = MESH_TRANSITION_STATE_DELAYED;
|
||||
btstack_run_loop_set_timer(&base_transition->timer, delay_time_gdtt * 5);
|
||||
btstack_run_loop_add_timer(&base_transition->timer);
|
||||
return;
|
||||
}
|
||||
|
||||
// started
|
||||
if (base_transition->num_steps > 0){
|
||||
base_transition->state = MESH_TRANSITION_STATE_ACTIVE;
|
||||
btstack_run_loop_set_timer(&base_transition->timer, base_transition->step_duration_ms);
|
||||
btstack_run_loop_add_timer(&base_transition->timer);
|
||||
return;
|
||||
}
|
||||
|
||||
// instanteneous update
|
||||
base_transition->state = MESH_TRANSITION_STATE_IDLE;
|
||||
(*transition_callback)(base_transition, MODEL_STATE_UPDATE_REASON_SET);
|
||||
return;
|
||||
}
|
||||
|
||||
void mesh_access_transitions_abort_transaction(mesh_transition_t * base_transition){
|
||||
btstack_run_loop_add_timer(&base_transition->timer);
|
||||
}
|
||||
|
||||
uint16_t mesh_pdu_ctl(mesh_pdu_t * pdu){
|
||||
switch (pdu->pdu_type){
|
||||
case MESH_PDU_TYPE_TRANSPORT:
|
||||
|
@ -127,7 +127,6 @@ typedef enum {
|
||||
} mesh_transaction_status_t;
|
||||
|
||||
typedef struct mesh_transition {
|
||||
btstack_linked_item_t item;
|
||||
btstack_timer_source_t timer;
|
||||
|
||||
mesh_transition_state_t state;
|
||||
@ -138,16 +137,14 @@ typedef struct mesh_transition {
|
||||
uint16_t dst_address;
|
||||
|
||||
uint8_t num_steps;
|
||||
|
||||
mesh_default_transition_step_resolution_t step_resolution;
|
||||
uint32_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;
|
||||
|
||||
// to execute transition
|
||||
void (* transition_callback)(struct mesh_transition * transition, transition_event_t event, uint32_t current_timestamp);
|
||||
void (* transition_callback)(struct mesh_transition * transition, model_state_update_reason_t event);
|
||||
} mesh_transition_t;
|
||||
|
||||
/**
|
||||
@ -185,29 +182,23 @@ void mesh_access_send_unacknowledged_pdu(mesh_pdu_t * pdu);
|
||||
*/
|
||||
void mesh_access_send_acknowledged_pdu(mesh_pdu_t * pdu, uint8_t retransmissions, uint32_t ack_opcode);
|
||||
|
||||
|
||||
// Mesh Model Transitions
|
||||
uint32_t mesh_access_transitions_step_ms_from_gdtt(uint8_t time_gdtt);
|
||||
uint8_t mesh_access_transitions_num_steps_from_gdtt(uint8_t time_gdtt);
|
||||
uint32_t mesh_access_time_gdtt2ms(uint8_t time_gdtt);
|
||||
uint8_t mesh_access_time_as_gdtt(uint32_t step_resolution_ms, uint32_t time_ms);
|
||||
void mesh_access_transitions_init_transaction(mesh_transition_t * transition, uint8_t transaction_identifier, uint16_t src_address, uint16_t dst_address);
|
||||
void mesh_access_transition_setup(mesh_model_t *mesh_model, mesh_transition_t * base_transition, uint8_t transition_time_gdtt, uint8_t delay_time_gdtt, void (*transition_callback)(mesh_transition_t * base_transition, model_state_update_reason_t event));
|
||||
void mesh_access_transitions_abort_transaction(mesh_transition_t * transition);
|
||||
uint8_t mesh_access_transactions_get_next_transaction_id(void);
|
||||
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_emit_state_update_bool(btstack_packet_handler_t event_handler, uint8_t element_index, uint32_t model_identifier,
|
||||
model_state_id_t state_identifier, model_state_update_reason_t reason, uint8_t value);
|
||||
|
||||
void mesh_access_emit_state_update_int16(btstack_packet_handler_t event_handler, uint8_t element_index, uint32_t model_identifier,
|
||||
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));
|
||||
|
||||
void mesh_access_transitions_add(mesh_transition_t * transition);
|
||||
void mesh_access_transitions_remove(mesh_transition_t * transition);
|
||||
uint8_t mesh_access_transactions_get_next_transaction_id(void);
|
||||
|
||||
// Mesh Model Publicaation
|
||||
|
||||
/**
|
||||
|
@ -76,133 +76,33 @@ static mesh_transition_t * generic_level_server_get_base_transition(mesh_model_t
|
||||
return &generic_level_server_state->transition_data.base_transition;
|
||||
}
|
||||
|
||||
static void mesh_server_transition_state_emit_change(mesh_transition_int16_t * transition, model_state_update_reason_t reason){
|
||||
mesh_model_t * generic_level_server_model = transition->base_transition.mesh_model;
|
||||
mesh_access_emit_state_update_int16(generic_level_server_model->model_packet_handler,
|
||||
mesh_access_get_element_index(generic_level_server_model),
|
||||
generic_level_server_model->model_identifier,
|
||||
MODEL_STATE_ID_GENERIC_LEVEL,
|
||||
reason,
|
||||
transition->current_value);
|
||||
}
|
||||
|
||||
static void mesh_server_transition_state_started(mesh_transition_int16_t * transition, uint32_t current_timestamp_ms){
|
||||
transition->base_transition.state = MESH_TRANSITION_STATE_ACTIVE;
|
||||
transition->base_transition.remaining_delay_time_ms = 0;
|
||||
transition->base_transition.phase_start_ms = current_timestamp_ms;
|
||||
|
||||
// notify transition completed
|
||||
mesh_server_transition_state_emit_change(transition, MODEL_STATE_UPDATE_REASON_TRANSITION_START);
|
||||
}
|
||||
|
||||
static void mesh_server_transition_state_update_stepwise_value(mesh_transition_int16_t * transition){
|
||||
transition->current_value = add_and_clip_int16(transition->current_value, transition->stepwise_value_increment);
|
||||
|
||||
// publish new value
|
||||
mesh_access_state_changed(transition->base_transition.mesh_model);
|
||||
|
||||
// notify transition update
|
||||
mesh_server_transition_state_emit_change(transition, MODEL_STATE_UPDATE_REASON_TRANSITION_ACTIVE);
|
||||
}
|
||||
|
||||
static void mesh_server_transition_state_done(mesh_transition_int16_t * transition, uint32_t current_timestamp_ms){
|
||||
transition->base_transition.state = MESH_TRANSITION_STATE_IDLE;
|
||||
transition->base_transition.remaining_transition_time_ms = 0;
|
||||
transition->current_value = transition->target_value;
|
||||
|
||||
// publish new value
|
||||
mesh_access_state_changed(transition->base_transition.mesh_model);
|
||||
|
||||
// notify transition completed
|
||||
mesh_server_transition_state_emit_change(transition, MODEL_STATE_UPDATE_REASON_TRANSITION_END);
|
||||
|
||||
// done, stop transition
|
||||
mesh_access_transitions_remove((mesh_transition_t *)transition);
|
||||
}
|
||||
|
||||
static void mesh_server_transition_state_set(mesh_transition_int16_t * transition, uint32_t current_timestamp_ms){
|
||||
UNUSED(current_timestamp_ms);
|
||||
|
||||
transition->base_transition.state = MESH_TRANSITION_STATE_IDLE;
|
||||
transition->base_transition.remaining_transition_time_ms = 0;
|
||||
transition->current_value = transition->target_value;
|
||||
|
||||
// publish new value
|
||||
mesh_access_state_changed(transition->base_transition.mesh_model);
|
||||
|
||||
// instantaneous update
|
||||
mesh_server_transition_state_emit_change(transition, MODEL_STATE_UPDATE_REASON_SET);
|
||||
}
|
||||
|
||||
static void mesh_server_transition_handler(mesh_transition_t * base_transition, model_state_update_reason_t event){
|
||||
mesh_transition_int16_t * transition = (mesh_transition_int16_t*) base_transition;
|
||||
uint32_t current_timestamp_ms = btstack_run_loop_get_time_ms();
|
||||
printf("Transition: event %x, current %x, target %x, increment %x, time %u\n", (int) event, transition->current_value, transition->target_value, transition->stepwise_value_increment, btstack_run_loop_get_time_ms());
|
||||
switch (event){
|
||||
case MODEL_STATE_UPDATE_REASON_SET:
|
||||
mesh_server_transition_state_set(transition, current_timestamp_ms);
|
||||
break;
|
||||
case MODEL_STATE_UPDATE_REASON_TRANSITION_START:
|
||||
mesh_server_transition_state_started(transition, current_timestamp_ms);
|
||||
break;
|
||||
case MODEL_STATE_UPDATE_REASON_TRANSITION_ACTIVE:
|
||||
mesh_server_transition_state_update_stepwise_value(transition);
|
||||
transition->current_value = add_and_clip_int16(transition->current_value, transition->stepwise_value_increment);
|
||||
mesh_access_state_changed(transition->base_transition.mesh_model);
|
||||
break;
|
||||
case MODEL_STATE_UPDATE_REASON_SET:
|
||||
case MODEL_STATE_UPDATE_REASON_TRANSITION_END:
|
||||
mesh_server_transition_state_done(transition, current_timestamp_ms);
|
||||
transition->current_value = transition->target_value;
|
||||
mesh_access_state_changed(transition->base_transition.mesh_model);
|
||||
break;
|
||||
case MODEL_STATE_UPDATE_REASON_TRANSITION_ABORT:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void mesh_server_transition_step(mesh_transition_t * base_transition, transition_event_t event, uint32_t current_timestamp_ms){
|
||||
uint32_t time_step_ms;
|
||||
|
||||
mesh_transition_int16_t * transition = (mesh_transition_int16_t*) base_transition;
|
||||
|
||||
switch (transition->base_transition.state){
|
||||
case MESH_TRANSITION_STATE_IDLE:
|
||||
if (event != TRANSITION_START) break;
|
||||
transition->base_transition.state = MESH_TRANSITION_STATE_DELAYED;
|
||||
transition->base_transition.phase_start_ms = current_timestamp_ms;
|
||||
if (transition->base_transition.remaining_delay_time_ms != 0) break;
|
||||
mesh_server_transition_handler(base_transition, MODEL_STATE_UPDATE_REASON_TRANSITION_START);
|
||||
if (transition->base_transition.remaining_transition_time_ms != 0) break;
|
||||
mesh_server_transition_handler(base_transition, MODEL_STATE_UPDATE_REASON_TRANSITION_END);
|
||||
break;
|
||||
|
||||
case MESH_TRANSITION_STATE_DELAYED:
|
||||
if (event != TRANSITION_UPDATE) break;
|
||||
time_step_ms = current_timestamp_ms - transition->base_transition.phase_start_ms;
|
||||
if (transition->base_transition.remaining_delay_time_ms > time_step_ms){
|
||||
transition->base_transition.remaining_delay_time_ms -= time_step_ms;
|
||||
transition->base_transition.phase_start_ms += time_step_ms;
|
||||
break;
|
||||
}
|
||||
mesh_server_transition_handler(base_transition, MODEL_STATE_UPDATE_REASON_TRANSITION_START);
|
||||
if (transition->base_transition.remaining_transition_time_ms != 0) break;
|
||||
mesh_server_transition_handler(base_transition, MODEL_STATE_UPDATE_REASON_TRANSITION_END);
|
||||
break;
|
||||
case MESH_TRANSITION_STATE_ACTIVE:
|
||||
if (event != TRANSITION_UPDATE) break;
|
||||
time_step_ms = current_timestamp_ms - transition->base_transition.phase_start_ms;
|
||||
if (transition->base_transition.num_steps == MESH_TRANSITION_NUM_STEPS_INFINITE){
|
||||
mesh_server_transition_handler(base_transition, MODEL_STATE_UPDATE_REASON_TRANSITION_ACTIVE);
|
||||
// done when max value reached
|
||||
if (transition->current_value > - 32768 && transition->current_value < 32767) break;
|
||||
} else if (transition->base_transition.remaining_transition_time_ms > time_step_ms){
|
||||
transition->base_transition.remaining_transition_time_ms -= time_step_ms;
|
||||
transition->base_transition.phase_start_ms += time_step_ms;
|
||||
mesh_server_transition_handler(base_transition, MODEL_STATE_UPDATE_REASON_TRANSITION_ACTIVE);
|
||||
break;
|
||||
}
|
||||
mesh_server_transition_handler(base_transition, MODEL_STATE_UPDATE_REASON_TRANSITION_END);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// notify app
|
||||
mesh_model_t * generic_level_server_model = transition->base_transition.mesh_model;
|
||||
mesh_access_emit_state_update_int16(generic_level_server_model->model_packet_handler,
|
||||
mesh_access_get_element_index(generic_level_server_model),
|
||||
generic_level_server_model->model_identifier,
|
||||
MODEL_STATE_ID_GENERIC_LEVEL,
|
||||
event,
|
||||
transition->current_value);
|
||||
}
|
||||
|
||||
static void mesh_server_transition_setup_transition_or_instantaneous_update_int16(mesh_model_t *mesh_model, uint8_t transition_time_gdtt, uint8_t delay_time_gdtt, uint32_t delta_value){
|
||||
@ -217,15 +117,9 @@ static void mesh_server_transition_setup_transition_or_instantaneous_update_int1
|
||||
generic_level_server_state->transition_data.stepwise_value_increment = 0;
|
||||
}
|
||||
|
||||
if (transition_time_gdtt != 0 || delay_time_gdtt != 0) {
|
||||
// transition
|
||||
mesh_access_transitions_setup(transition, mesh_model, transition_time_gdtt, delay_time_gdtt, &mesh_server_transition_step);
|
||||
mesh_access_transitions_add(transition);
|
||||
} else {
|
||||
// instantaneous update
|
||||
mesh_server_transition_handler(transition, MODEL_STATE_UPDATE_REASON_SET);
|
||||
}
|
||||
mesh_access_transition_setup(mesh_model, transition, transition_time_gdtt, delay_time_gdtt, &mesh_server_transition_handler);
|
||||
}
|
||||
|
||||
// Generic Level State
|
||||
|
||||
void mesh_generic_level_server_register_packet_handler(mesh_model_t *generic_level_server_model, btstack_packet_handler_t transition_events_packet_handler){
|
||||
@ -248,13 +142,8 @@ static mesh_pdu_t * mesh_generic_level_status_message(mesh_model_t *generic_leve
|
||||
|
||||
// setup message
|
||||
mesh_transport_pdu_t * transport_pdu = NULL;
|
||||
if (state->transition_data.base_transition.remaining_transition_time_ms != 0) {
|
||||
uint8_t remaining_time;
|
||||
if (state->transition_data.base_transition.num_steps == MESH_TRANSITION_NUM_STEPS_INFINITE){
|
||||
remaining_time = MESH_TRANSITION_NUM_STEPS_INFINITE;
|
||||
} else {
|
||||
remaining_time = mesh_access_time_as_gdtt(state->transition_data.base_transition.step_duration_ms, state->transition_data.base_transition.remaining_transition_time_ms);
|
||||
}
|
||||
if (state->transition_data.base_transition.num_steps > 0) {
|
||||
uint8_t remaining_time = (((uint8_t)state->transition_data.base_transition.step_resolution) << 6) | (state->transition_data.base_transition.num_steps);
|
||||
transport_pdu = mesh_access_setup_segmented_message(&mesh_generic_level_status_transition, state->transition_data.current_value,
|
||||
state->transition_data.target_value, remaining_time);
|
||||
} else {
|
||||
@ -289,7 +178,7 @@ static void generic_level_handle_set_target_level_message(mesh_model_t *mesh_mod
|
||||
// ignore
|
||||
break;
|
||||
default:
|
||||
mesh_access_transitions_setup_transaction(base_transition, tid, mesh_pdu_src(pdu), mesh_pdu_dst(pdu));
|
||||
mesh_access_transitions_init_transaction(base_transition, tid, mesh_pdu_src(pdu), mesh_pdu_dst(pdu));
|
||||
|
||||
generic_level_server_state->transition_data.initial_value = generic_level_server_state->transition_data.current_value;
|
||||
generic_level_server_state->transition_data.target_value = level_value;
|
||||
@ -334,7 +223,7 @@ static void generic_level_handle_set_delta_message(mesh_model_t *mesh_model, mes
|
||||
break;
|
||||
case MESH_TRANSACTION_STATUS_NEW:
|
||||
// start transaction with current value
|
||||
mesh_access_transitions_setup_transaction(base_transition, tid, mesh_pdu_src(pdu), mesh_pdu_dst(pdu));
|
||||
mesh_access_transitions_init_transaction(base_transition, tid, mesh_pdu_src(pdu), mesh_pdu_dst(pdu));
|
||||
generic_level_server_state->transition_data.initial_value = generic_level_server_state->transition_data.current_value;
|
||||
generic_level_server_state->transition_data.target_value = add_and_clip_int16(generic_level_server_state->transition_data.initial_value, delta_value);
|
||||
printf("Transaction %u, new, init %x, target %x\n", tid, generic_level_server_state->transition_data.initial_value, generic_level_server_state->transition_data.target_value);
|
||||
@ -343,7 +232,7 @@ static void generic_level_handle_set_delta_message(mesh_model_t *mesh_model, mes
|
||||
break;
|
||||
case MESH_TRANSACTION_STATUS_RETRANSMISSION:
|
||||
// replace last delta message
|
||||
mesh_access_transitions_setup_transaction(base_transition, tid, mesh_pdu_src(pdu), mesh_pdu_dst(pdu));
|
||||
mesh_access_transitions_init_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.initial_value, delta_value);
|
||||
printf("Transaction %u, retransmission, init %x, target %x\n", tid, generic_level_server_state->transition_data.initial_value, generic_level_server_state->transition_data.target_value);
|
||||
mesh_server_transition_setup_transition_or_instantaneous_update_int16(mesh_model, transition_time_gdtt, delay_time_gdtt, delta_value);
|
||||
@ -384,7 +273,7 @@ static void generic_level_handle_set_move_message(mesh_model_t *mesh_model, mesh
|
||||
// ignore retransmission
|
||||
break;
|
||||
default:
|
||||
mesh_access_transitions_setup_transaction(base_transition, tid, mesh_pdu_src(pdu), mesh_pdu_dst(pdu));
|
||||
mesh_access_transitions_init_transaction(base_transition, tid, mesh_pdu_src(pdu), mesh_pdu_dst(pdu));
|
||||
|
||||
generic_level_server_state->transition_data.initial_value = generic_level_server_state->transition_data.current_value;
|
||||
generic_level_server_state->transition_data.target_value = add_and_clip_int16(generic_level_server_state->transition_data.current_value, delta_value);
|
||||
|
@ -54,8 +54,6 @@
|
||||
#include "mesh/mesh_network.h"
|
||||
#include "mesh/mesh_upper_transport.h"
|
||||
|
||||
static void mesh_server_transition_step_bool(mesh_transition_t * transition, transition_event_t event, uint32_t current_timestamp);
|
||||
|
||||
static void generic_server_send_message(uint16_t src, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, mesh_pdu_t *pdu){
|
||||
uint8_t ttl = mesh_foundation_default_ttl_get();
|
||||
mesh_upper_transport_setup_access_pdu_header(pdu, netkey_index, appkey_index, ttl, src, dest, 0);
|
||||
@ -69,137 +67,39 @@ static mesh_transition_t * generic_on_off_server_get_base_transition(mesh_model_
|
||||
return &generic_on_off_server_state->transition_data.base_transition;
|
||||
}
|
||||
|
||||
static void mesh_server_transition_state_emit_change(mesh_transition_bool_t * transition, uint32_t current_timestamp_ms, model_state_update_reason_t reason){
|
||||
static void mesh_server_transition_handler(mesh_transition_t * base_transition, model_state_update_reason_t event){
|
||||
mesh_transition_bool_t * transition = (mesh_transition_bool_t*) base_transition;
|
||||
switch (event){
|
||||
case MODEL_STATE_UPDATE_REASON_TRANSITION_START:
|
||||
if (transition->target_value == 1){
|
||||
transition->current_value = 1;
|
||||
mesh_access_state_changed(transition->base_transition.mesh_model);
|
||||
}
|
||||
break;
|
||||
case MODEL_STATE_UPDATE_REASON_SET:
|
||||
case MODEL_STATE_UPDATE_REASON_TRANSITION_END:
|
||||
transition->current_value = transition->target_value;
|
||||
mesh_access_state_changed(transition->base_transition.mesh_model);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// notify app
|
||||
mesh_model_t * generic_on_off_server_model = transition->base_transition.mesh_model;
|
||||
mesh_access_emit_state_update_bool(generic_on_off_server_model->model_packet_handler,
|
||||
mesh_access_get_element_index(generic_on_off_server_model),
|
||||
generic_on_off_server_model->model_identifier,
|
||||
MODEL_STATE_ID_GENERIC_ON_OFF,
|
||||
reason,
|
||||
event,
|
||||
transition->current_value);
|
||||
}
|
||||
|
||||
static void mesh_server_transition_state_started(mesh_transition_bool_t * transition, uint32_t current_timestamp_ms){
|
||||
transition->base_transition.state = MESH_TRANSITION_STATE_ACTIVE;
|
||||
transition->base_transition.remaining_delay_time_ms = 0;
|
||||
transition->base_transition.phase_start_ms = current_timestamp_ms;
|
||||
if (transition->target_value == 1){
|
||||
transition->current_value = 1;
|
||||
|
||||
// publish new value
|
||||
mesh_access_state_changed(transition->base_transition.mesh_model);
|
||||
|
||||
// notify app
|
||||
mesh_server_transition_state_emit_change(transition, current_timestamp_ms, MODEL_STATE_UPDATE_REASON_TRANSITION_START);
|
||||
}
|
||||
}
|
||||
|
||||
static void mesh_server_transition_state_done(mesh_transition_bool_t * transition, uint32_t current_timestamp_ms){
|
||||
transition->base_transition.state = MESH_TRANSITION_STATE_IDLE;
|
||||
transition->base_transition.remaining_transition_time_ms = 0;
|
||||
transition->current_value = transition->target_value;
|
||||
|
||||
// publish new value
|
||||
mesh_access_state_changed(transition->base_transition.mesh_model);
|
||||
|
||||
// notify transition completed
|
||||
mesh_server_transition_state_emit_change(transition, current_timestamp_ms, MODEL_STATE_UPDATE_REASON_TRANSITION_END);
|
||||
|
||||
// done, stop transition
|
||||
mesh_access_transitions_remove((mesh_transition_t *)transition);
|
||||
}
|
||||
|
||||
static void mesh_server_transition_state_set(mesh_transition_bool_t * transition, uint32_t current_timestamp_ms){
|
||||
UNUSED(current_timestamp_ms);
|
||||
|
||||
transition->base_transition.state = MESH_TRANSITION_STATE_IDLE;
|
||||
transition->base_transition.remaining_delay_time_ms = 0;
|
||||
transition->base_transition.remaining_transition_time_ms = 0;
|
||||
transition->base_transition.phase_start_ms = 0;
|
||||
transition->current_value = transition->target_value;
|
||||
|
||||
// publish new value
|
||||
mesh_access_state_changed(transition->base_transition.mesh_model);
|
||||
|
||||
// notify transition completed
|
||||
mesh_server_transition_state_emit_change(transition, current_timestamp_ms, MODEL_STATE_UPDATE_REASON_SET);
|
||||
}
|
||||
|
||||
static void mesh_server_transition_handler(mesh_transition_t * base_transition, model_state_update_reason_t event){
|
||||
mesh_transition_bool_t * transition = (mesh_transition_bool_t*) base_transition;
|
||||
uint32_t current_timestamp_ms = btstack_run_loop_get_time_ms();
|
||||
switch (event){
|
||||
case MODEL_STATE_UPDATE_REASON_SET:
|
||||
mesh_server_transition_state_set(transition, current_timestamp_ms);
|
||||
break;
|
||||
case MODEL_STATE_UPDATE_REASON_TRANSITION_START:
|
||||
mesh_server_transition_state_started(transition, current_timestamp_ms);
|
||||
break;
|
||||
case MODEL_STATE_UPDATE_REASON_TRANSITION_END:
|
||||
mesh_server_transition_state_done(transition, current_timestamp_ms);
|
||||
break;
|
||||
case MODEL_STATE_UPDATE_REASON_TRANSITION_ABORT:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void mesh_server_transition_step_bool(mesh_transition_t * base_transition, transition_event_t event, uint32_t current_timestamp_ms){
|
||||
uint32_t time_step_ms;
|
||||
mesh_transition_bool_t * transition = (mesh_transition_bool_t*) base_transition;
|
||||
log_info("Transition: state %x, current timestamp %u, remaining delay %u ms, remaining transition %u ms",
|
||||
transition->base_transition.state, current_timestamp_ms, transition->base_transition.remaining_delay_time_ms, transition->base_transition.remaining_transition_time_ms);
|
||||
switch (transition->base_transition.state){
|
||||
case MESH_TRANSITION_STATE_IDLE:
|
||||
if (event != TRANSITION_START) break;
|
||||
transition->base_transition.state = MESH_TRANSITION_STATE_DELAYED;
|
||||
transition->base_transition.phase_start_ms = current_timestamp_ms;
|
||||
if (transition->base_transition.remaining_delay_time_ms != 0) break;
|
||||
mesh_server_transition_handler(base_transition, MODEL_STATE_UPDATE_REASON_TRANSITION_START);
|
||||
if (transition->base_transition.remaining_transition_time_ms != 0) break;
|
||||
mesh_server_transition_handler(base_transition, MODEL_STATE_UPDATE_REASON_TRANSITION_END);
|
||||
break;
|
||||
case MESH_TRANSITION_STATE_DELAYED:
|
||||
if (event != TRANSITION_UPDATE) break;
|
||||
time_step_ms = current_timestamp_ms - transition->base_transition.phase_start_ms;
|
||||
if (transition->base_transition.remaining_delay_time_ms > time_step_ms){
|
||||
transition->base_transition.remaining_delay_time_ms -= time_step_ms;
|
||||
transition->base_transition.phase_start_ms += time_step_ms;
|
||||
break;
|
||||
}
|
||||
mesh_server_transition_handler(base_transition, MODEL_STATE_UPDATE_REASON_TRANSITION_START);
|
||||
if (transition->base_transition.remaining_transition_time_ms != 0) break;
|
||||
mesh_server_transition_handler(base_transition, MODEL_STATE_UPDATE_REASON_TRANSITION_END);
|
||||
break;
|
||||
case MESH_TRANSITION_STATE_ACTIVE:
|
||||
if (event != TRANSITION_UPDATE) break;
|
||||
time_step_ms = current_timestamp_ms - transition->base_transition.phase_start_ms;
|
||||
if (transition->base_transition.remaining_transition_time_ms > time_step_ms){
|
||||
transition->base_transition.remaining_transition_time_ms -= time_step_ms;
|
||||
transition->base_transition.phase_start_ms += time_step_ms;
|
||||
break;
|
||||
}
|
||||
mesh_server_transition_handler(base_transition, MODEL_STATE_UPDATE_REASON_TRANSITION_END);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void mesh_server_transition_setup_transition_or_instantaneous_update(mesh_model_t *mesh_model, uint8_t transition_time_gdtt, uint8_t delay_time_gdtt){
|
||||
mesh_generic_on_off_state_t * generic_on_off_server_state = (mesh_generic_on_off_state_t *)mesh_model->model_data;
|
||||
mesh_transition_t * transition = &generic_on_off_server_state->transition_data.base_transition;
|
||||
|
||||
if ((transition_time_gdtt == 0) && (delay_time_gdtt == 0)){
|
||||
// instanteneous update
|
||||
mesh_server_transition_handler(transition, MODEL_STATE_UPDATE_REASON_SET);
|
||||
} else {
|
||||
// transaction
|
||||
mesh_access_transitions_setup(transition, (mesh_model_t *) mesh_model, transition_time_gdtt, delay_time_gdtt, &mesh_server_transition_step_bool);
|
||||
mesh_access_transitions_add(transition);
|
||||
mesh_access_transition_setup(mesh_model, transition, transition_time_gdtt, delay_time_gdtt, &mesh_server_transition_handler);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Generic On Off State
|
||||
|
||||
@ -223,9 +123,8 @@ static mesh_pdu_t * mesh_generic_on_off_status_message(mesh_model_t *generic_on_
|
||||
mesh_generic_on_off_state_t * state = (mesh_generic_on_off_state_t *) generic_on_off_server_model->model_data;
|
||||
// setup message
|
||||
mesh_transport_pdu_t * transport_pdu = NULL;
|
||||
if (state->transition_data.base_transition.remaining_transition_time_ms != 0) {
|
||||
log_info("On/Off Status: value %u, remaining time %u ms", state->transition_data.current_value, state->transition_data.base_transition.remaining_transition_time_ms);
|
||||
uint8_t remaining_time = mesh_access_time_as_gdtt(state->transition_data.base_transition.step_duration_ms, state->transition_data.base_transition.remaining_transition_time_ms);
|
||||
if (state->transition_data.base_transition.num_steps > 0) {
|
||||
uint8_t remaining_time = (((uint8_t)state->transition_data.base_transition.step_resolution) << 6) | (state->transition_data.base_transition.num_steps);
|
||||
transport_pdu = mesh_access_setup_segmented_message(&mesh_generic_on_off_status_transition, state->transition_data.current_value,
|
||||
state->transition_data.target_value, remaining_time);
|
||||
} else {
|
||||
@ -267,7 +166,7 @@ static bool generic_on_off_handle_set_message(mesh_model_t *mesh_model, mesh_pdu
|
||||
// ignore on retransmission
|
||||
break;
|
||||
default:
|
||||
mesh_access_transitions_setup_transaction(base_transition, tid, mesh_pdu_src(pdu), mesh_pdu_dst(pdu));
|
||||
mesh_access_transitions_init_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){
|
||||
|
Loading…
x
Reference in New Issue
Block a user