mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-01-27 06:35:20 +00:00
mesh: introduce transaction status
This commit is contained in:
parent
4963ec13ad
commit
f649fbc8b3
@ -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;
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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){
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user