/* radio callback, executed in STACK_LOW */ static void tx_cb(uint8_t* data) { rbc_mesh_event_t tx_event; mesh_adv_data_t* p_adv_data = mesh_packet_adv_data_get((mesh_packet_t*) data); bool doing_tx_event = false; if (p_adv_data != NULL && vh_tx_event_flag_get(p_adv_data->handle, &doing_tx_event) == NRF_SUCCESS && doing_tx_event ) { tx_event.event_type = RBC_MESH_EVENT_TYPE_TX; tx_event.value_handle = p_adv_data->handle; tx_event.data = p_adv_data->data; tx_event.data_len = p_adv_data->adv_data_length - MESH_PACKET_ADV_OVERHEAD; tx_event.version_delta = 0; APP_ERROR_CHECK(rbc_mesh_event_push(&tx_event)); #if RBC_MESH_SERIAL mesh_aci_rbc_event_handler(&tx_event); #endif } mesh_packet_ref_count_dec((mesh_packet_t*) data); /* radio ref removed (pushed in tc_tx) */ vh_order_update(timer_get_timestamp()); /* tell the vh, so that it can push more updates */ }
uint32_t mesh_srv_packet_process(packet_t* packet) { if (!is_initialized) { return NRF_ERROR_INVALID_STATE; } uint32_t error_code; uint8_t handle = packet->data[MESH_PACKET_HANDLE_OFFSET]; uint16_t version = (packet->data[MESH_PACKET_VERSION_OFFSET] | (((uint16_t) packet->data[MESH_PACKET_VERSION_OFFSET + 1]) << 8)); uint8_t* data = &packet->data[MESH_PACKET_DATA_OFFSET]; uint16_t data_len = packet->length - MESH_PACKET_DATA_OFFSET; if (data_len > MAX_VALUE_LENGTH) { return NRF_ERROR_INVALID_LENGTH; } if (handle > g_mesh_service.value_count || handle == 0) { return NRF_ERROR_INVALID_ADDR; } mesh_char_metadata_t* ch_md = &g_mesh_service.char_metadata[handle - 1]; bool uninitialized = !(ch_md->flags & (1 << MESH_MD_FLAGS_INITIALIZED_POS)); if (uninitialized) { trickle_init(&ch_md->trickle); } if (ch_md->version_number != version) { trickle_rx_inconsistent(&ch_md->trickle); } /* new version */ uint16_t separation = (version >= ch_md->version_number)? (version - ch_md->version_number) : (-(ch_md->version_number - MESH_VALUE_LOLLIPOP_LIMIT) + (version - MESH_VALUE_LOLLIPOP_LIMIT) - MESH_VALUE_LOLLIPOP_LIMIT); if ((ch_md->version_number < MESH_VALUE_LOLLIPOP_LIMIT && version >= ch_md->version_number) || (ch_md->version_number >= MESH_VALUE_LOLLIPOP_LIMIT && separation < (UINT16_MAX - MESH_VALUE_LOLLIPOP_LIMIT)/2) || uninitialized) { /* update value */ mesh_srv_char_val_set(handle, data, data_len, false); ch_md->flags |= (1 << MESH_MD_FLAGS_INITIALIZED_POS); ch_md->flags &= ~(1 << MESH_MD_FLAGS_IS_ORIGIN_POS); ch_md->version_number = version; /* Manually set originator address */ memcpy(&ch_md->last_sender_addr, &packet->sender, sizeof(ble_gap_addr_t)); rbc_mesh_event_t update_evt; update_evt.event_type = ((uninitialized)? RBC_MESH_EVENT_TYPE_NEW_VAL : RBC_MESH_EVENT_TYPE_UPDATE_VAL); update_evt.data_len = data_len; update_evt.value_handle = handle; update_evt.data = data; memcpy(&update_evt.originator_address, &packet->sender, sizeof(ble_gap_addr_t)); rbc_mesh_event_handler(&update_evt); #ifdef RBC_MESH_SERIAL mesh_aci_rbc_event_handler(&update_evt); #endif } else if (version == ch_md->version_number) { /* check for conflicting data */ uint16_t old_len = MAX_VALUE_LENGTH; error_code = mesh_srv_char_val_get(handle, NULL, &old_len, NULL); if (error_code != NRF_SUCCESS) { return error_code; } volatile bool conflicting = false; if (packet->rx_crc != ch_md->crc && !(ch_md->flags & (1 << MESH_MD_FLAGS_IS_ORIGIN_POS))) { conflicting = true; } else if (old_len != data_len) { conflicting = true; } if (conflicting) { TICK_PIN(7); rbc_mesh_event_t conflicting_evt; conflicting_evt.event_type = RBC_MESH_EVENT_TYPE_CONFLICTING_VAL; conflicting_evt.data_len = data_len; conflicting_evt.value_handle = handle; conflicting_evt.data = data; memcpy(&conflicting_evt.originator_address, &packet->sender, sizeof(ble_gap_addr_t)); trickle_rx_inconsistent(&ch_md->trickle); rbc_mesh_event_handler(&conflicting_evt); #ifdef RBC_MESH_SERIAL mesh_aci_rbc_event_handler(&conflicting_evt); #endif } else { trickle_rx_consistent(&ch_md->trickle); } } ch_md->crc = packet->rx_crc; return NRF_SUCCESS; }
static void mesh_app_packet_handle(mesh_adv_data_t* p_mesh_adv_data, uint64_t timestamp) { // LOGi("_1"); int16_t delta = vh_get_version_delta(p_mesh_adv_data->handle, p_mesh_adv_data->version); vh_data_status_t data_status = vh_rx_register(p_mesh_adv_data, timestamp); /* prepare app event */ rbc_mesh_event_t evt; evt.version_delta = delta; switch (data_status) { case VH_DATA_STATUS_NEW: /* notify application */ prepare_event(&evt, p_mesh_adv_data); evt.event_type = RBC_MESH_EVENT_TYPE_NEW_VAL; if (rbc_mesh_event_push(&evt) == NRF_SUCCESS) { mesh_gatt_value_set(p_mesh_adv_data->handle, p_mesh_adv_data->data, p_mesh_adv_data->adv_data_length - MESH_PACKET_ADV_OVERHEAD); } #ifdef RBC_MESH_SERIAL mesh_aci_rbc_event_handler(&evt); #endif break; case VH_DATA_STATUS_UPDATED: /* notify application */ prepare_event(&evt, p_mesh_adv_data); evt.event_type = RBC_MESH_EVENT_TYPE_UPDATE_VAL; if (rbc_mesh_event_push(&evt) == NRF_SUCCESS) { mesh_gatt_value_set(p_mesh_adv_data->handle, p_mesh_adv_data->data, p_mesh_adv_data->adv_data_length - MESH_PACKET_ADV_OVERHEAD); } #ifdef RBC_MESH_SERIAL mesh_aci_rbc_event_handler(&evt); #endif break; case VH_DATA_STATUS_OLD: /* do nothing */ break; case VH_DATA_STATUS_SAME: /* do nothing */ break; case VH_DATA_STATUS_CONFLICTING: prepare_event(&evt, p_mesh_adv_data); evt.event_type = RBC_MESH_EVENT_TYPE_CONFLICTING_VAL; rbc_mesh_event_push(&evt); /* ignore error - will be a normal packet drop */ #ifdef RBC_MESH_SERIAL mesh_aci_rbc_event_handler(&evt); #endif break; case VH_DATA_STATUS_UNKNOWN: break; } }