From 584bbe7d59efa1c2a1cd2066ed6c23700d212751 Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Fri, 19 Jul 2019 14:40:50 +0200 Subject: [PATCH] mesh: health server events and handlers: period and attention get/set/set_unacknowledged --- src/btstack_defines.h | 13 +++ src/btstack_event.h | 29 +++++ src/mesh/mesh_foundation.h | 8 +- src/mesh/mesh_health_server.c | 205 ++++++++++++++++++++++++++-------- src/mesh/mesh_health_server.h | 2 + src/mesh/mesh_node.h | 2 - 6 files changed, 204 insertions(+), 55 deletions(-) diff --git a/src/btstack_defines.h b/src/btstack_defines.h index f8ccc64cb..5ad09b871 100644 --- a/src/btstack_defines.h +++ b/src/btstack_defines.h @@ -2577,6 +2577,19 @@ typedef uint8_t sm_key_t[16]; */ #define MESH_SUBEVENT_HEALTH_PERFORM_TEST 0x34 +/** + * @format 111 + * @param subevent_code + * @param element_index + * @param fast_period_divisor + */ +#define MESH_SUBEVENT_HEALTH_FAST_PERIOD_DIVISOR_CHANGED 0x35 +/** + * @format 11 + * @param subevent_code + * @param element_index + */ +#define MESH_SUBEVENT_HEALTH_ATTENTION_TIMER_CHANGED 0x36 #endif diff --git a/src/btstack_event.h b/src/btstack_event.h index 84bca379f..f6e3ab378 100644 --- a/src/btstack_event.h +++ b/src/btstack_event.h @@ -7867,6 +7867,35 @@ static inline uint8_t mesh_subevent_health_perform_test_get_test_id(const uint8_ return event[16]; } +/** + * @brief Get field element_index from event MESH_SUBEVENT_HEALTH_FAST_PERIOD_DIVISOR_CHANGED + * @param event packet + * @return element_index + * @note: btstack_type 1 + */ +static inline uint8_t mesh_subevent_health_fast_period_divisor_changed_get_element_index(const uint8_t * event){ + return event[3]; +} +/** + * @brief Get field fast_period_divisor from event MESH_SUBEVENT_HEALTH_FAST_PERIOD_DIVISOR_CHANGED + * @param event packet + * @return fast_period_divisor + * @note: btstack_type 1 + */ +static inline uint8_t mesh_subevent_health_fast_period_divisor_changed_get_fast_period_divisor(const uint8_t * event){ + return event[4]; +} + +/** + * @brief Get field element_index from event MESH_SUBEVENT_HEALTH_ATTENTION_TIMER_CHANGED + * @param event packet + * @return element_index + * @note: btstack_type 1 + */ +static inline uint8_t mesh_subevent_health_attention_timer_changed_get_element_index(const uint8_t * event){ + return event[3]; +} + /* API_END */ diff --git a/src/mesh/mesh_foundation.h b/src/mesh/mesh_foundation.h index 1f7165186..60f1bf1bc 100644 --- a/src/mesh/mesh_foundation.h +++ b/src/mesh/mesh_foundation.h @@ -70,10 +70,10 @@ extern "C" #define MESH_FOUNDATION_OPERATION_APPKEY_GET 0x8001 #define MESH_FOUNDATION_OPERATION_APPKEY_LIST 0x8002 #define MESH_FOUNDATION_OPERATION_APPKEY_STATUS 0x8003 -#define MESH_FOUNDATION_OPERATION_ATTENTION_GET 0x8004 -#define MESH_FOUNDATION_OPERATION_ATTENTION_SET 0x8005 -#define MESH_FOUNDATION_OPERATION_ATTENTION_SET_UNACKNOWLEDGED 0x8006 -#define MESH_FOUNDATION_OPERATION_ATTENTION_STATUS 0x8007 +#define MESH_FOUNDATION_OPERATION_HEALTH_ATTENTION_GET 0x8004 +#define MESH_FOUNDATION_OPERATION_HEALTH_ATTENTION_SET 0x8005 +#define MESH_FOUNDATION_OPERATION_HEALTH_ATTENTION_SET_UNACKNOWLEDGED 0x8006 +#define MESH_FOUNDATION_OPERATION_HEALTH_ATTENTION_STATUS 0x8007 #define MESH_FOUNDATION_OPERATION_COMPOSITION_DATA_GET 0x8008 #define MESH_FOUNDATION_OPERATION_BEACON_GET 0x8009 #define MESH_FOUNDATION_OPERATION_BEACON_SET 0x800a diff --git a/src/mesh/mesh_health_server.c b/src/mesh/mesh_health_server.c index f73f42e4c..0c72450ac 100644 --- a/src/mesh/mesh_health_server.c +++ b/src/mesh/mesh_health_server.c @@ -47,6 +47,7 @@ #include "btstack_memory.h" #include "btstack_util.h" +#include "mesh/mesh.h" #include "mesh/mesh_access.h" #include "mesh/mesh_node.h" #include "mesh/mesh_foundation.h" @@ -56,6 +57,9 @@ #include "mesh/mesh_network.h" #include "mesh/mesh_upper_transport.h" +// used for asynchronous calls in the done command to unblock the message queue +static mesh_pdu_t * processed_pdu; + static void health_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); @@ -67,16 +71,37 @@ const mesh_access_message_t mesh_foundation_health_period_status = { }; const mesh_access_message_t mesh_foundation_health_attention_status = { - MESH_FOUNDATION_OPERATION_ATTENTION_STATUS, "1" + MESH_FOUNDATION_OPERATION_HEALTH_ATTENTION_STATUS, "1" }; +static mesh_pdu_t * health_period_status(mesh_model_t * mesh_model, uint32_t opcode){ + mesh_health_state_t * state = (mesh_health_state_t *) mesh_model->model_data; + if (state == NULL){ + log_error("health_period_status state == NULL"); + } + // setup message + mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_foundation_health_period_status, state->fast_period_divisor); + return (mesh_pdu_t *) transport_pdu; +} + +static mesh_pdu_t * health_attention_status(mesh_model_t * mesh_model, uint32_t opcode){ + // setup message + mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_foundation_health_attention_status, mesh_attention_timer_get()); + return (mesh_pdu_t *) transport_pdu; +} + // dynamic -static mesh_pdu_t * health_current_status(btstack_linked_list_t * faults, uint32_t opcode, uint16_t company_id){ +static mesh_pdu_t * health_current_status(mesh_model_t * mesh_model, uint32_t opcode, uint16_t company_id){ mesh_transport_pdu_t * transport_pdu = mesh_access_transport_init(opcode); if (!transport_pdu) return NULL; + + mesh_health_state_t * state = (mesh_health_state_t *) mesh_model->model_data; + if (state == NULL){ + log_error("health_current_status state == NULL"); + } btstack_linked_list_iterator_t it; - btstack_linked_list_iterator_init(&it, faults); + btstack_linked_list_iterator_init(&it, &state->registered_faults); while (btstack_linked_list_iterator_has_next(&it)){ mesh_fault_t * fault = (mesh_fault_t *) btstack_linked_list_iterator_next(&it); if (fault->company_id != company_id) continue; @@ -119,64 +144,55 @@ static mesh_pdu_t * health_fault_status(btstack_linked_list_t * faults, uint32_t return (mesh_pdu_t *) transport_pdu; } -// dynamic -static mesh_pdu_t * health_period_status(mesh_model_t * mesh_model, uint32_t opcode){ - mesh_health_state_t * state = (mesh_health_state_t *) mesh_model->model_data; - if (state == NULL){ - log_error("health_fault_status state == NULL"); - } - // setup message - mesh_transport_pdu_t * transport_pdu = mesh_access_setup_segmented_message(&mesh_foundation_health_period_status, state->fast_period_divisor); - return (mesh_pdu_t *) transport_pdu; -} static void health_fault_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ mesh_access_parser_state_t parser; mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); uint16_t company_id = mesh_access_parser_get_u16(&parser); - mesh_health_state_t * state = (mesh_health_state_t *) mesh_model->model_data; - mesh_transport_pdu_t * transport_pdu = (mesh_transport_pdu_t *) health_current_status(&state->registered_faults, MESH_FOUNDATION_OPERATION_HEALTH_FAULT_STATUS, company_id); + mesh_transport_pdu_t * transport_pdu = (mesh_transport_pdu_t *) health_current_status(mesh_model, MESH_FOUNDATION_OPERATION_HEALTH_FAULT_STATUS, company_id); if (!transport_pdu) return; health_server_send_message(mesh_access_get_element_address(mesh_model), mesh_pdu_src(pdu), mesh_pdu_netkey_index(pdu), mesh_pdu_appkey_index(pdu),(mesh_pdu_t *) transport_pdu); mesh_access_message_processed(pdu); } -static void clear_faults(btstack_linked_list_t * faults, uint16_t company_id){ - btstack_linked_list_iterator_t it; - btstack_linked_list_iterator_init(&it, faults); - while (btstack_linked_list_iterator_has_next(&it)){ - mesh_fault_t * fault = (mesh_fault_t *) btstack_linked_list_iterator_next(&it); - if (fault->company_id != company_id) continue; - memset(fault->faults, 0, sizeof(fault->faults)); - return; - } -} - -static void health_fault_clear_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ +static uint16_t process_message_fault_clear(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ mesh_access_parser_state_t parser; mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); uint16_t company_id = mesh_access_parser_get_u16(&parser); mesh_health_state_t * state = (mesh_health_state_t *) mesh_model->model_data; - - clear_faults(&state->registered_faults, company_id); - mesh_transport_pdu_t * transport_pdu = (mesh_transport_pdu_t *) health_current_status(&state->registered_faults, MESH_FOUNDATION_OPERATION_HEALTH_FAULT_STATUS, company_id); - if (!transport_pdu) return; + if (state == NULL){ + log_error("health_fault_status state == NULL"); + } + + uint8_t event[6]; + int pos = 0; + event[pos++] = HCI_EVENT_MESH_META; + // reserve for size + pos++; + event[pos++] = MESH_SUBEVENT_HEALTH_CLEAR_REGISTERED_FAULTS; + // element index + event[pos++] = mesh_model->element->element_index; + little_endian_store_16(event, pos, company_id); + pos += 2; + event[1] = pos - 2; + (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos); + + return company_id; +} + +static void health_fault_clear_handler(mesh_model_t * mesh_model, mesh_pdu_t * pdu){ + uint16_t company_id = process_message_fault_clear(mesh_model, pdu); + + mesh_transport_pdu_t * transport_pdu = (mesh_transport_pdu_t *) health_current_status(mesh_model, MESH_FOUNDATION_OPERATION_HEALTH_FAULT_STATUS, company_id); + if (!transport_pdu) return; health_server_send_message(mesh_access_get_element_address(mesh_model), mesh_pdu_src(pdu), mesh_pdu_netkey_index(pdu), mesh_pdu_appkey_index(pdu),(mesh_pdu_t *) transport_pdu); mesh_access_message_processed(pdu); } static void health_fault_clear_unacknowledged_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ - mesh_access_parser_state_t parser; - mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); - uint16_t company_id = mesh_access_parser_get_u16(&parser); - - mesh_health_state_t * state = (mesh_health_state_t *) mesh_model->model_data; - if (state == NULL){ - log_error("mesh_health_state == NULL"); - } - clear_faults(&state->registered_faults, company_id); + process_message_fault_clear(mesh_model, pdu); mesh_access_message_processed(pdu); } @@ -191,9 +207,9 @@ static void health_fault_test_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu if (state == NULL){ log_error("mesh_health_state == NULL"); } - mesh_model->processed_pdu = pdu; + processed_pdu = pdu; - uint8_t event[17 ]; + uint8_t event[17]; int pos = 0; event[pos++] = HCI_EVENT_MESH_META; // reserve for size @@ -230,7 +246,7 @@ void mesh_health_server_report_test_done(uint16_t element_index, uint16_t dest, mesh_transport_pdu_t * transport_pdu = (mesh_transport_pdu_t *) health_fault_status(&state->registered_faults, MESH_FOUNDATION_OPERATION_HEALTH_FAULT_STATUS, test_id, company_id); if (!transport_pdu) return; health_server_send_message(element_index, dest, netkey_index, appkey_index, (mesh_pdu_t *) transport_pdu); - mesh_access_message_processed(mesh_model->processed_pdu); + mesh_access_message_processed(processed_pdu); } static void health_fault_test_unacknowledged_handler(mesh_model_t * mesh_model, mesh_pdu_t * pdu){ @@ -245,6 +261,86 @@ static void health_period_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu mesh_access_message_processed(pdu); } +static void process_message_period_set(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ + mesh_access_parser_state_t parser; + mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); + uint8_t fast_period_divisor = mesh_access_parser_get_u8(&parser); + + mesh_health_state_t * state = (mesh_health_state_t *) mesh_model->model_data; + if (state == NULL){ + log_error("health_fault_status state == NULL"); + } + + if (state->fast_period_divisor != fast_period_divisor){ + state->fast_period_divisor = fast_period_divisor; + uint8_t event[5]; + int pos = 0; + event[pos++] = HCI_EVENT_MESH_META; + // reserve for size + pos++; + event[pos++] = MESH_SUBEVENT_HEALTH_FAST_PERIOD_DIVISOR_CHANGED; + // element index + event[pos++] = mesh_model->element->element_index; + // element index + event[pos++] = fast_period_divisor; + event[1] = pos - 2; + (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos); + } +} + +static void health_period_set_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ + process_message_period_set(mesh_model, pdu); + + mesh_transport_pdu_t * transport_pdu = (mesh_transport_pdu_t *) health_period_status(mesh_model, MESH_FOUNDATION_OPERATION_HEALTH_PERIOD_STATUS); + if (!transport_pdu) return; + health_server_send_message(mesh_access_get_element_address(mesh_model), mesh_pdu_src(pdu), mesh_pdu_netkey_index(pdu), mesh_pdu_appkey_index(pdu),(mesh_pdu_t *) transport_pdu); + mesh_access_message_processed(pdu); +} + +static void health_period_set_unacknowledged_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ + process_message_period_set(mesh_model, pdu); + mesh_access_message_processed(pdu); +} + +static void health_attention_get_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ + mesh_transport_pdu_t * transport_pdu = (mesh_transport_pdu_t *) health_attention_status(mesh_model, MESH_FOUNDATION_OPERATION_HEALTH_ATTENTION_STATUS); + if (!transport_pdu) return; + health_server_send_message(mesh_access_get_element_address(mesh_model), mesh_pdu_src(pdu), mesh_pdu_netkey_index(pdu), mesh_pdu_appkey_index(pdu),(mesh_pdu_t *) transport_pdu); + mesh_access_message_processed(pdu); +} + +static void process_message_attention_set(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ + mesh_access_parser_state_t parser; + mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu); + uint8_t timer_s = mesh_access_parser_get_u8(&parser); + mesh_attention_timer_set(timer_s); + + uint8_t event[4]; + int pos = 0; + event[pos++] = HCI_EVENT_MESH_META; + // reserve for size + pos++; + event[pos++] = MESH_SUBEVENT_HEALTH_ATTENTION_TIMER_CHANGED; + // element index + event[pos++] = mesh_model->element->element_index; + // element index + event[1] = pos - 2; + (*mesh_model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, pos); +} + +static void health_attention_set_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ + process_message_attention_set(mesh_model, pdu); + + mesh_transport_pdu_t * transport_pdu = (mesh_transport_pdu_t *) health_attention_status(mesh_model, MESH_FOUNDATION_OPERATION_HEALTH_ATTENTION_STATUS); + if (!transport_pdu) return; + health_server_send_message(mesh_access_get_element_address(mesh_model), mesh_pdu_src(pdu), mesh_pdu_netkey_index(pdu), mesh_pdu_appkey_index(pdu),(mesh_pdu_t *) transport_pdu); + mesh_access_message_processed(pdu); +} + +static void health_attention_set_unacknowledged_handler(mesh_model_t *mesh_model, mesh_pdu_t * pdu){ + process_message_attention_set(mesh_model, pdu); + mesh_access_message_processed(pdu); +} // Health Message const static mesh_operation_t mesh_health_model_operations[] = { @@ -254,11 +350,11 @@ const static mesh_operation_t mesh_health_model_operations[] = { { MESH_FOUNDATION_OPERATION_HEALTH_FAULT_TEST, 3, health_fault_test_handler }, { MESH_FOUNDATION_OPERATION_HEALTH_FAULT_TEST_UNACKNOWLEDGED, 3, health_fault_test_unacknowledged_handler }, { MESH_FOUNDATION_OPERATION_HEALTH_PERIOD_GET, 0, health_period_get_handler }, - // { MESH_FOUNDATION_OPERATION_HEALTH_PERIOD_SET, 2, health_period_set_handler }, - // { MESH_FOUNDATION_OPERATION_HEALTH_PERIOD_SET_UNACKNOWLEDGED, 2, health_period_set_unacknowledged_handler }, - // { MESH_FOUNDATION_OPERATION_HEALTH_ATTENTION_GET, 2, health_attention_get_handler }, - // { MESH_FOUNDATION_OPERATION_HEALTH_ATTENTION_SET, 2, health_attention_set_handler }, - // { MESH_FOUNDATION_OPERATION_HEALTH_ATTENTION_SET_UNACKNOWLEDGED, 2, health_attention_set_unacknowledged_handler }, + { MESH_FOUNDATION_OPERATION_HEALTH_PERIOD_SET, 1, health_period_set_handler }, + { MESH_FOUNDATION_OPERATION_HEALTH_PERIOD_SET_UNACKNOWLEDGED, 1, health_period_set_unacknowledged_handler }, + { MESH_FOUNDATION_OPERATION_HEALTH_ATTENTION_GET, 0, health_attention_get_handler }, + { MESH_FOUNDATION_OPERATION_HEALTH_ATTENTION_SET, 1, health_attention_set_handler }, + { MESH_FOUNDATION_OPERATION_HEALTH_ATTENTION_SET_UNACKNOWLEDGED, 1, health_attention_set_unacknowledged_handler }, { 0, 0, NULL } }; @@ -266,7 +362,7 @@ const mesh_operation_t * mesh_health_server_get_operations(void){ return mesh_health_model_operations; } -void mesh_health_server_register_packet_handler(mesh_model_t *mesh_model, btstack_packet_handler_t events_packet_handler){ +void mesh_health_server_register_packet_handler(mesh_model_t *mesh_model, btstack_packet_handler_t events_packet_handler){ if (events_packet_handler == NULL){ log_error(" mesh_health_server_register_packet_handler called with NULL callback"); return; @@ -277,3 +373,14 @@ void mesh_health_server_register_packet_handler(mesh_model_t *mesh_model, btsta } mesh_model->model_packet_handler = events_packet_handler; } + +void health_server_clear_faults(btstack_linked_list_t * faults, uint16_t company_id){ + btstack_linked_list_iterator_t it; + btstack_linked_list_iterator_init(&it, faults); + while (btstack_linked_list_iterator_has_next(&it)){ + mesh_fault_t * fault = (mesh_fault_t *) btstack_linked_list_iterator_next(&it); + if (fault->company_id != company_id) continue; + memset(fault->faults, 0, sizeof(fault->faults)); + return; + } +} diff --git a/src/mesh/mesh_health_server.h b/src/mesh/mesh_health_server.h index 9f5823e8d..7d1e35254 100644 --- a/src/mesh/mesh_health_server.h +++ b/src/mesh/mesh_health_server.h @@ -58,6 +58,8 @@ void mesh_health_server_register_packet_handler(mesh_model_t *mesh_model, btstac void mesh_health_server_report_test_done(uint16_t element_index, uint16_t dest, uint16_t netkey_index, uint16_t appkey_index, uint8_t test_id, uint16_t company_id); +void health_server_clear_faults(btstack_linked_list_t * faults, uint16_t company_id); + #ifdef __cplusplus } /* end of extern "C" */ #endif diff --git a/src/mesh/mesh_node.h b/src/mesh/mesh_node.h index d4c4766b4..f7798da75 100644 --- a/src/mesh/mesh_node.h +++ b/src/mesh/mesh_node.h @@ -121,8 +121,6 @@ typedef struct mesh_model { // packet handler for transition events in server, event callback handler in client btstack_packet_handler_t model_packet_handler; - // used for asynchronous calls in the done command to unblock the message queue - mesh_pdu_t * processed_pdu; } mesh_model_t; typedef struct {