diff options
Diffstat (limited to 'src/libs/mynewt-nimble/apps/blehr/src/main.c')
-rw-r--r-- | src/libs/mynewt-nimble/apps/blehr/src/main.c | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/src/libs/mynewt-nimble/apps/blehr/src/main.c b/src/libs/mynewt-nimble/apps/blehr/src/main.c new file mode 100644 index 00000000..bf0f3f30 --- /dev/null +++ b/src/libs/mynewt-nimble/apps/blehr/src/main.c @@ -0,0 +1,261 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include <assert.h> +#include <string.h> +#include <stdio.h> +#include <errno.h> + +#include "os/mynewt.h" +#include "console/console.h" +#include "config/config.h" +#include "nimble/ble.h" +#include "host/ble_hs.h" +#include "services/gap/ble_svc_gap.h" +#include "blehr_sens.h" + +static bool notify_state; + +/* Connection handle */ +static uint16_t conn_handle; + +static const char *device_name = "blehr_sensor"; + +static int blehr_gap_event(struct ble_gap_event *event, void *arg); + +static uint8_t blehr_addr_type; + +/* Sending notify data timer */ +static struct os_callout blehr_tx_timer; + +/* Variable to simulate heart beats */ +static uint8_t heartrate = 90; + +/* + * Enables advertising with parameters: + * o General discoverable mode + * o Undirected connectable mode + */ +static void +blehr_advertise(void) +{ + struct ble_gap_adv_params adv_params; + struct ble_hs_adv_fields fields; + int rc; + + /* + * Set the advertisement data included in our advertisements: + * o Flags (indicates advertisement type and other general info) + * o Advertising tx power + * o Device name + */ + memset(&fields, 0, sizeof(fields)); + + /* + * Advertise two flags: + * o Discoverability in forthcoming advertisement (general) + * o BLE-only (BR/EDR unsupported) + */ + fields.flags = BLE_HS_ADV_F_DISC_GEN | + BLE_HS_ADV_F_BREDR_UNSUP; + + /* + * Indicate that the TX power level field should be included; have the + * stack fill this value automatically. This is done by assigning the + * special value BLE_HS_ADV_TX_PWR_LVL_AUTO. + */ + fields.tx_pwr_lvl_is_present = 1; + fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO; + + fields.name = (uint8_t *)device_name; + fields.name_len = strlen(device_name); + fields.name_is_complete = 1; + + rc = ble_gap_adv_set_fields(&fields); + if (rc != 0) { + MODLOG_DFLT(ERROR, "error setting advertisement data; rc=%d\n", rc); + return; + } + + /* Begin advertising */ + memset(&adv_params, 0, sizeof(adv_params)); + adv_params.conn_mode = BLE_GAP_CONN_MODE_UND; + adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN; + rc = ble_gap_adv_start(blehr_addr_type, NULL, BLE_HS_FOREVER, + &adv_params, blehr_gap_event, NULL); + if (rc != 0) { + MODLOG_DFLT(ERROR, "error enabling advertisement; rc=%d\n", rc); + return; + } +} + +static void +blehr_tx_hrate_stop(void) +{ + os_callout_stop(&blehr_tx_timer); +} + +/* Reset heartrate measurment */ +static void +blehr_tx_hrate_reset(void) +{ + int rc; + + rc = os_callout_reset(&blehr_tx_timer, OS_TICKS_PER_SEC); + assert(rc == 0); +} + +/* This functions simulates heart beat and notifies it to the client */ +static void +blehr_tx_hrate(struct os_event *ev) +{ + static uint8_t hrm[2]; + int rc; + struct os_mbuf *om; + + if (!notify_state) { + blehr_tx_hrate_stop(); + heartrate = 90; + return; + } + + hrm[0] = 0x06; /* contact of a sensor */ + hrm[1] = heartrate; /* storing dummy data */ + + /* Simulation of heart beats */ + heartrate++; + if (heartrate == 160) { + heartrate = 90; + } + + om = ble_hs_mbuf_from_flat(hrm, sizeof(hrm)); + + rc = ble_gattc_notify_custom(conn_handle, hrs_hrm_handle, om); + + assert(rc == 0); + blehr_tx_hrate_reset(); +} + +static int +blehr_gap_event(struct ble_gap_event *event, void *arg) +{ + switch (event->type) { + case BLE_GAP_EVENT_CONNECT: + /* A new connection was established or a connection attempt failed */ + MODLOG_DFLT(INFO, "connection %s; status=%d\n", + event->connect.status == 0 ? "established" : "failed", + event->connect.status); + + if (event->connect.status != 0) { + /* Connection failed; resume advertising */ + blehr_advertise(); + conn_handle = 0; + } + else { + conn_handle = event->connect.conn_handle; + } + + break; + + case BLE_GAP_EVENT_DISCONNECT: + MODLOG_DFLT(INFO, "disconnect; reason=%d\n", event->disconnect.reason); + conn_handle = BLE_HS_CONN_HANDLE_NONE; /* reset conn_handle */ + + /* Connection terminated; resume advertising */ + blehr_advertise(); + break; + + case BLE_GAP_EVENT_ADV_COMPLETE: + MODLOG_DFLT(INFO, "adv complete\n"); + blehr_advertise(); + break; + + case BLE_GAP_EVENT_SUBSCRIBE: + MODLOG_DFLT(INFO, "subscribe event; cur_notify=%d\n value handle; " + "val_handle=%d\n", + event->subscribe.cur_notify, hrs_hrm_handle); + if (event->subscribe.attr_handle == hrs_hrm_handle) { + notify_state = event->subscribe.cur_notify; + blehr_tx_hrate_reset(); + } else if (event->subscribe.attr_handle != hrs_hrm_handle) { + notify_state = event->subscribe.cur_notify; + blehr_tx_hrate_stop(); + } + break; + + case BLE_GAP_EVENT_MTU: + MODLOG_DFLT(INFO, "mtu update event; conn_handle=%d mtu=%d\n", + event->mtu.conn_handle, + event->mtu.value); + break; + + } + + return 0; +} + +static void +blehr_on_sync(void) +{ + int rc; + + /* Use privacy */ + rc = ble_hs_id_infer_auto(0, &blehr_addr_type); + assert(rc == 0); + + /* Begin advertising */ + blehr_advertise(); +} + +/* + * main + * + * The main task for the project. This function initializes the packages, + * then starts serving events from default event queue. + * + * @return int NOTE: this function should never return! + */ +int +main(void) +{ + int rc; + + /* Initialize OS */ + sysinit(); + + /* Initialize the NimBLE host configuration */ + ble_hs_cfg.sync_cb = blehr_on_sync; + + os_callout_init(&blehr_tx_timer, os_eventq_dflt_get(), + blehr_tx_hrate, NULL); + + rc = gatt_svr_init(); + assert(rc == 0); + + /* Set the default device name */ + rc = ble_svc_gap_device_name_set(device_name); + assert(rc == 0); + + /* As the last thing, process events from default event queue */ + while (1) { + os_eventq_run(os_eventq_dflt_get()); + } + return 0; +} + |