Esempio n. 1
0
void mesh_gatt_sd_ble_event_handle(ble_evt_t* p_ble_evt) {
	switch (p_ble_evt->header.evt_id) {
	case BLE_GATTS_EVT_WRITE: {
		if (p_ble_evt->evt.gatts_evt.params.write.handle
				== m_mesh_service.ble_val_char_handles.value_handle) {
			mesh_gatt_evt_t* p_gatt_evt =
					(mesh_gatt_evt_t*) p_ble_evt->evt.gatts_evt.params.write.data;
			switch ((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode) {
			case MESH_GATT_EVT_OPCODE_DATA: {
				if (p_gatt_evt->param.data_update.handle
						== RBC_MESH_INVALID_HANDLE) {
					mesh_gatt_cmd_rsp_push(
							(mesh_gatt_evt_opcode_t) p_gatt_evt->opcode,
							MESH_GATT_RESULT_ERROR_INVALID_HANDLE);
					break;
				}
				vh_data_status_t vh_data_status = vh_local_update(
						p_gatt_evt->param.data_update.handle,
						p_gatt_evt->param.data_update.data,
						p_gatt_evt->param.data_update.data_len);

				rbc_mesh_event_t mesh_evt;
				mesh_evt.data = p_gatt_evt->param.data_update.data;
				mesh_evt.data_len = p_gatt_evt->param.data_update.data_len;
				mesh_evt.value_handle = p_gatt_evt->param.data_update.handle;
				mesh_evt.version_delta = 1;
				bool send_event = true;
				switch (vh_data_status) {
				case VH_DATA_STATUS_CONFLICTING:
					mesh_evt.event_type = RBC_MESH_EVENT_TYPE_CONFLICTING_VAL;
					break;
				case VH_DATA_STATUS_NEW:
					mesh_evt.event_type = RBC_MESH_EVENT_TYPE_NEW_VAL;
					break;
				case VH_DATA_STATUS_UPDATED:
					mesh_evt.event_type = RBC_MESH_EVENT_TYPE_UPDATE_VAL;
					break;
				default:
					mesh_gatt_cmd_rsp_push(
							(mesh_gatt_evt_opcode_t) p_gatt_evt->opcode,
							MESH_GATT_RESULT_ERROR_BUSY);
					send_event = false;
				}
				if (send_event) {
					APP_ERROR_CHECK(rbc_mesh_event_push(&mesh_evt));
					mesh_gatt_cmd_rsp_push(
							(mesh_gatt_evt_opcode_t) p_gatt_evt->opcode,
							MESH_GATT_RESULT_SUCCESS);
				}
			}
				break;

			case MESH_GATT_EVT_OPCODE_FLAG_SET:
				switch ((mesh_gatt_evt_flag_t) p_gatt_evt->param.flag_update.flag) {
				case MESH_GATT_EVT_FLAG_PERSISTENT:
					if (vh_value_persistence_set(
							p_gatt_evt->param.flag_update.handle,
							!!(p_gatt_evt->param.flag_update.value)) != NRF_SUCCESS) {
						mesh_gatt_cmd_rsp_push(
								(mesh_gatt_evt_opcode_t) p_gatt_evt->opcode,
								MESH_GATT_RESULT_ERROR_INVALID_HANDLE);
						break;
					}
					mesh_gatt_cmd_rsp_push(
							(mesh_gatt_evt_opcode_t) p_gatt_evt->opcode,
							MESH_GATT_RESULT_SUCCESS);
					break;

				case MESH_GATT_EVT_FLAG_DO_TX:
					if (p_gatt_evt->param.flag_update.value) {
						if (vh_value_enable(
								p_gatt_evt->param.flag_update.handle) != NRF_SUCCESS) {
							mesh_gatt_cmd_rsp_push(
									(mesh_gatt_evt_opcode_t) p_gatt_evt->opcode,
									MESH_GATT_RESULT_ERROR_INVALID_HANDLE);
							break;
						}
						mesh_gatt_cmd_rsp_push(
								(mesh_gatt_evt_opcode_t) p_gatt_evt->opcode,
								MESH_GATT_RESULT_SUCCESS);
					} else {
						if (vh_value_disable(
								p_gatt_evt->param.flag_update.handle) != NRF_SUCCESS) {
							mesh_gatt_cmd_rsp_push(
									(mesh_gatt_evt_opcode_t) p_gatt_evt->opcode,
									MESH_GATT_RESULT_ERROR_INVALID_HANDLE);
							break;
						}
						mesh_gatt_cmd_rsp_push(
								(mesh_gatt_evt_opcode_t) p_gatt_evt->opcode,
								MESH_GATT_RESULT_SUCCESS);
					}
					break;

				default:
					mesh_gatt_cmd_rsp_push(
							(mesh_gatt_evt_opcode_t) p_gatt_evt->opcode,
							MESH_GATT_RESULT_ERROR_UNKNOWN_FLAG);
				}
				break;

			case MESH_GATT_EVT_OPCODE_FLAG_REQ:
				switch ((mesh_gatt_evt_flag_t) p_gatt_evt->param.flag_update.flag) {
				case MESH_GATT_EVT_FLAG_PERSISTENT: {
					if (p_gatt_evt->param.flag_update.handle
							== RBC_MESH_INVALID_HANDLE) {
						mesh_gatt_cmd_rsp_push(
								(mesh_gatt_evt_opcode_t) p_gatt_evt->opcode,
								MESH_GATT_RESULT_ERROR_INVALID_HANDLE);
						break;
					}

					bool is_persistent = false;
					if (vh_value_persistence_get(
							p_gatt_evt->param.flag_update.handle,
							&is_persistent) != NRF_SUCCESS) {
						mesh_gatt_cmd_rsp_push(
								(mesh_gatt_evt_opcode_t) p_gatt_evt->opcode,
								MESH_GATT_RESULT_ERROR_NOT_FOUND);
						break;
					}

					mesh_gatt_evt_t rsp_evt;
					rsp_evt.opcode = MESH_GATT_EVT_OPCODE_FLAG_RSP;
					rsp_evt.param.flag_update.handle =
							p_gatt_evt->param.flag_update.handle;
					rsp_evt.param.flag_update.flag =
							p_gatt_evt->param.flag_update.flag;
					rsp_evt.param.flag_update.value = (uint8_t) is_persistent;
					mesh_gatt_evt_push(&rsp_evt);
				}
					break;

				case MESH_GATT_EVT_FLAG_DO_TX: {
					bool is_enabled;
					if (vh_value_is_enabled(
							p_gatt_evt->param.flag_update.handle,
							&is_enabled) != NRF_SUCCESS) {
						mesh_gatt_cmd_rsp_push(
								(mesh_gatt_evt_opcode_t) p_gatt_evt->opcode,
								MESH_GATT_RESULT_ERROR_INVALID_HANDLE);
						break;
					}

					mesh_gatt_evt_t rsp_evt;
					rsp_evt.opcode = MESH_GATT_EVT_OPCODE_FLAG_RSP;
					rsp_evt.param.flag_update.handle =
							p_gatt_evt->param.flag_update.handle;
					rsp_evt.param.flag_update.flag =
							p_gatt_evt->param.flag_update.flag;
					rsp_evt.param.flag_update.value = (uint8_t) is_enabled;
					mesh_gatt_evt_push(&rsp_evt);
				}
					break;

				default:
					mesh_gatt_cmd_rsp_push(
							(mesh_gatt_evt_opcode_t) p_gatt_evt->opcode,
							MESH_GATT_RESULT_ERROR_UNKNOWN_FLAG);
				}
				break;

			default:
				mesh_gatt_cmd_rsp_push(
						(mesh_gatt_evt_opcode_t) p_gatt_evt->opcode,
						MESH_GATT_RESULT_ERROR_INVALID_OPCODE);
			}
		} else if (p_ble_evt->evt.gatts_evt.params.write.handle
				== m_mesh_service.ble_md_char_handles.value_handle) {
			mesh_metadata_char_t* p_md =
					(mesh_metadata_char_t*) p_ble_evt->evt.gatts_evt.params.write.data;
			tc_radio_params_set(p_md->mesh_access_addr, p_md->mesh_channel);
			vh_min_interval_set(p_md->mesh_interval_min_ms);
		} else if (p_ble_evt->evt.gatts_evt.params.write.handle
				== m_mesh_service.ble_val_char_handles.cccd_handle) {
			m_mesh_service.notification_enabled =
					(p_ble_evt->evt.gatts_evt.params.write.data[0] != 0);
		}
		break;
	}
	case BLE_GAP_EVT_CONNECTED: {
		m_active_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
		break;
	}
	case BLE_GAP_EVT_DISCONNECTED: {
		m_active_conn_handle = CONN_HANDLE_INVALID;

		// clear notification buffer on disconnect
		notifactionsPending = false;
		nb_clear();
		break;
	}
	case BLE_EVT_TX_COMPLETE: {
		if (notifactionsPending) {
			resume_notifications();
		}
		break;
	}
	}
}
void mesh_gatt_sd_ble_event_handle(ble_evt_t* p_ble_evt)
{
    if (p_ble_evt->header.evt_id == BLE_GATTS_EVT_WRITE)
    {
        if (p_ble_evt->evt.gatts_evt.params.write.handle == m_mesh_service.ble_val_char_handles.value_handle)
        {
            mesh_gatt_evt_t* p_gatt_evt = (mesh_gatt_evt_t*) p_ble_evt->evt.gatts_evt.params.write.data;
            switch ((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode)
            {
                case MESH_GATT_EVT_OPCODE_DATA:
                    {
                        if (p_gatt_evt->param.data_update.handle == RBC_MESH_INVALID_HANDLE)
                        {
                            mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_INVALID_HANDLE);
                            break;
                        }
                        uint32_t error_code = vh_local_update(
                                p_gatt_evt->param.data_update.handle,
                                p_gatt_evt->param.data_update.data,
                                p_gatt_evt->param.data_update.data_len);

                        if (error_code == NRF_SUCCESS)
                        {
                            rbc_mesh_event_t mesh_evt;
                            mesh_evt.type = RBC_MESH_EVENT_TYPE_UPDATE_VAL;
                            mesh_evt.params.rx.p_data        = p_gatt_evt->param.data_update.data;
                            mesh_evt.params.rx.data_len      = p_gatt_evt->param.data_update.data_len;
                            mesh_evt.params.rx.value_handle  = p_gatt_evt->param.data_update.handle;
                            mesh_evt.params.rx.version_delta = 1;
                            mesh_evt.params.rx.timestamp_us  = timer_now();
                            if (rbc_mesh_event_push(&mesh_evt) != NRF_SUCCESS)
                            {
                                mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_BUSY);
                            }
                            else
                            {
                                mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_SUCCESS);
                            }
                        }
                        else
                        {
                            mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_BUSY);
                        }

                    }
                    break;

                case MESH_GATT_EVT_OPCODE_FLAG_SET:
                    switch ((mesh_gatt_evt_flag_t) p_gatt_evt->param.flag_update.flag)
                    {
                        case MESH_GATT_EVT_FLAG_PERSISTENT:
                            if (vh_value_persistence_set(p_gatt_evt->param.flag_update.handle,
                                        !!(p_gatt_evt->param.flag_update.value))
                                    != NRF_SUCCESS)
                            {
                                mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_INVALID_HANDLE);
                                break;
                            }
                            mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_SUCCESS);
                            break;

                        case MESH_GATT_EVT_FLAG_DO_TX:
                            if (p_gatt_evt->param.flag_update.value)
                            {
                                if (vh_value_enable(p_gatt_evt->param.flag_update.handle)
                                        != NRF_SUCCESS)
                                {
                                    mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_INVALID_HANDLE);
                                    break;
                                }
                                mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_SUCCESS);
                            }
                            else
                            {
                                if (vh_value_disable(p_gatt_evt->param.flag_update.handle)
                                        != NRF_SUCCESS)
                                {
                                    mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_INVALID_HANDLE);
                                    break;
                                }
                                mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_SUCCESS);
                            }
                            break;

                        default:
                            mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_UNKNOWN_FLAG);
                    }
                    break;

                case MESH_GATT_EVT_OPCODE_FLAG_REQ:
                    switch ((mesh_gatt_evt_flag_t) p_gatt_evt->param.flag_update.flag)
                    {
                        case MESH_GATT_EVT_FLAG_PERSISTENT:
                            {
                                if (p_gatt_evt->param.flag_update.handle == RBC_MESH_INVALID_HANDLE)
                                {
                                    mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_INVALID_HANDLE);
                                    break;
                                }

                                bool is_persistent = false;
                                if (vh_value_persistence_get(p_gatt_evt->param.flag_update.handle, &is_persistent)
                                        != NRF_SUCCESS)
                                {
                                    mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_NOT_FOUND);
                                    break;
                                }

                                mesh_gatt_evt_t rsp_evt;
                                rsp_evt.opcode = MESH_GATT_EVT_OPCODE_FLAG_RSP;
                                rsp_evt.param.flag_update.handle = p_gatt_evt->param.flag_update.handle;
                                rsp_evt.param.flag_update.flag = p_gatt_evt->param.flag_update.flag;
                                rsp_evt.param.flag_update.value = (uint8_t) is_persistent;
                                mesh_gatt_evt_push(&rsp_evt);
                            }
                            break;

                        case MESH_GATT_EVT_FLAG_DO_TX:
                            {
                                bool is_enabled;
                                if (vh_value_is_enabled(p_gatt_evt->param.flag_update.handle, &is_enabled)
                                        != NRF_SUCCESS)
                                {
                                    mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_INVALID_HANDLE);
                                    break;
                                }

                                mesh_gatt_evt_t rsp_evt;
                                rsp_evt.opcode = MESH_GATT_EVT_OPCODE_FLAG_RSP;
                                rsp_evt.param.flag_update.handle = p_gatt_evt->param.flag_update.handle;
                                rsp_evt.param.flag_update.flag = p_gatt_evt->param.flag_update.flag;
                                rsp_evt.param.flag_update.value = (uint8_t) is_enabled;
                                mesh_gatt_evt_push(&rsp_evt);
                            }
                            break;

                        default:
                            mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_UNKNOWN_FLAG);
                    }
                    break;

                default:
                    mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_INVALID_OPCODE);
            }
        }
        else if (p_ble_evt->evt.gatts_evt.params.write.handle == m_mesh_service.ble_md_char_handles.value_handle)
        {
            mesh_metadata_char_t* p_md = (mesh_metadata_char_t*) p_ble_evt->evt.gatts_evt.params.write.data;
            tc_radio_params_set(p_md->mesh_access_addr, p_md->mesh_channel);
            vh_min_interval_set(p_md->mesh_interval_min_ms);
        }
        else if (p_ble_evt->evt.gatts_evt.params.write.handle == m_mesh_service.ble_val_char_handles.cccd_handle)
        {
            m_mesh_service.notification_enabled = (p_ble_evt->evt.gatts_evt.params.write.data[0] != 0);
        }
    }
    else if (p_ble_evt->header.evt_id == BLE_GAP_EVT_CONNECTED)
    {
        m_active_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
    }
    else if (p_ble_evt->header.evt_id == BLE_GAP_EVT_DISCONNECTED)
    {
        m_active_conn_handle = CONN_HANDLE_INVALID;
    }
}