Samples: Bluetooth: Add ST BLE Demo sample

This sample demonstrates BLE peripheral for ST BLE Sensor.
You can test button notification and LED service using
ST BLE Sensor Android application

Signed-off-by: Marcio Montenegro <mtuxpe@gmail.com>
This commit is contained in:
Marcio Montenegro 2019-09-20 10:01:18 -03:00 committed by Johan Hedberg
parent 0297e7ec15
commit dd5d2e37f5
9 changed files with 430 additions and 0 deletions

View file

@ -0,0 +1,12 @@
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.13.1)
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
project(st_ble_sensor)
FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE
${app_sources}
)
zephyr_library_include_directories($ENV{ZEPHYR_BASE}/samples/bluetooth)

View file

@ -0,0 +1,41 @@
.. _bluetooth-st_ble_sensor:
Bluetooth: ST BLE Sensor Demo
#############################
Overview
********
This application demonstrates BLE peripheral by exposing vendor-specific
GATT services. Currently only button notification and LED service are
implemented. Other BLE sensor services can easily be added.
See `BlueST protocol`_ document for details of how to add a new service.
Requirements
************
* `ST BLE Sensor Android app <ST BLE Sensor app>`_
* A board with BLE support
Building and Running
********************
This sample can be found under :zephyr_file:`samples/bluetooth/st_ble_sensor` in the
Zephyr tree.
See :ref:`bluetooth samples section <bluetooth-samples>` for details.
.. _ST BLE Sensor app:
https://play.google.com/store/apps/details?id=com.st.bluems
.. _ST Nucleo WB55RG:
https://www.st.com/en/microcontrollers-microprocessors/stm32wb55rg.html
.. _STM32CubeProgrammer:
https://www.st.com/en/development-tools/stm32cubeprog.html
.. _BlueST protocol:
https://www.st.com/resource/en/user_manual/dm00550659.pdf
.. _STM32WB github:
https://github.com/STMicroelectronics/STM32CubeWB/tree/master/Projects/STM32WB_Copro_Wireless_Binaries

View file

@ -0,0 +1,8 @@
CONFIG_BT=y
CONFIG_BT_DEBUG_LOG=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_DEVICE_NAME="P2PSRV1"
CONFIG_BT_GATT_CLIENT=y
CONFIG_BT_DEBUG=y
CONFIG_LOG=y
CONFIG_LOG_BUFFER_SIZE=2048

View file

@ -0,0 +1,8 @@
sample:
description: TBD
name: TBD
tests:
sample.bluetooth.st_ble_sensor:
harness: bluetooth
platform_whitelist: nucleo_wb55rg
tags: bluetooth

View file

@ -0,0 +1,81 @@
/** @file
* @brief Button Service sample
*/
/*
* Copyright (c) 2019 Marcio Montenegro <mtuxpe@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/types.h>
#include <stddef.h>
#include <string.h>
#include <errno.h>
#include <sys/printk.h>
#include <sys/byteorder.h>
#include <zephyr.h>
#include <drivers/gpio.h>
#include <logging/log.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/conn.h>
#include <bluetooth/uuid.h>
#include <bluetooth/gatt.h>
#include "button_svc.h"
LOG_MODULE_REGISTER(button_svc);
#define BUT_PORT DT_ALIAS_SW0_GPIOS_CONTROLLER
#define BUT_PIN DT_ALIAS_SW0_GPIOS_PIN
extern struct bt_conn *conn;
extern struct bt_gatt_service_static stsensor_svc[];
extern volatile bool notify_enable;
static struct device *button_dev;
static struct gpio_callback gpio_cb;
u16_t but_val;
void button_pressed(struct device *gpiob, struct gpio_callback *cb,
u32_t pins)
{
int err;
LOG_INF("Button SW1 pressed");
if (conn) {
if (notify_enable) {
err = bt_gatt_notify(NULL, &stsensor_svc->attrs[2],
&but_val, sizeof(but_val));
if (err) {
LOG_ERR("Notify error: %d", err);
} else {
LOG_INF("Send notify ok");
but_val = (but_val == 0) ? 0x100 : 0;
}
} else {
LOG_INF("Notify not enabled");
}
} else {
LOG_INF("BLE not connected");
}
}
int button_init(void)
{
button_dev = device_get_binding(BUT_PORT);
if (!button_dev) {
return (-EOPNOTSUPP);
}
gpio_pin_configure(button_dev, BUT_PIN,
GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE |
GPIO_PUD_PULL_UP | GPIO_INT_DEBOUNCE |
GPIO_INT_ACTIVE_LOW);
gpio_init_callback(&gpio_cb, button_pressed, BIT(BUT_PIN));
gpio_add_callback(button_dev, &gpio_cb);
gpio_pin_enable_callback(button_dev, BUT_PIN);
but_val = 0;
return 0;
}

View file

@ -0,0 +1,19 @@
/** @file
* @brief Button Service
*/
/*
* Copyright (c) 2019 Marcio Montenegro <mtuxpe@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifdef __cplusplus
extern "C" {
#endif
int button_init(void);
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,49 @@
/** @file
* @brief Button Service sample
*/
/*
* Copyright (c) 2019 Marcio Montenegro <mtuxpe@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/types.h>
#include <stddef.h>
#include <string.h>
#include <errno.h>
#include <sys/printk.h>
#include <sys/byteorder.h>
#include <zephyr.h>
#include <drivers/gpio.h>
#include <logging/log.h>
LOG_MODULE_REGISTER(led_svc);
#define LED_PORT DT_ALIAS_LED0_GPIOS_CONTROLLER
#define LED DT_ALIAS_LED0_GPIOS_PIN
struct device *led_dev;
bool led_state;
void led_on_off(u32_t led_state)
{
if (led_dev) {
gpio_pin_write(led_dev, LED, led_state);
}
}
int led_init(void)
{
led_dev = device_get_binding(LED_PORT);
if (!led_dev) {
return (-EOPNOTSUPP);
}
/* Set LED pin as output */
gpio_pin_configure(led_dev, LED, GPIO_DIR_OUT);
led_state = false;
gpio_pin_write(led_dev, LED, 0);
led_on_off(0);
return 0;
}

View file

@ -0,0 +1,20 @@
/** @file
* @brief LED Service sample
*/
/*
* Copyright (c) 2019 Marcio Montenegro <mtuxpe@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifdef __cplusplus
extern "C" {
#endif
void led_on_off(u32_t led_state);
int led_init(void);
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,192 @@
/* main.c - Application main entry point */
/*
* Copyright (c) 2015-2016 Intel Corporation
* Copyright (c) 2019 Marcio Montenegro <mtuxpe@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/types.h>
#include <stddef.h>
#include <string.h>
#include <errno.h>
#include <sys/printk.h>
#include <sys/byteorder.h>
#include <zephyr.h>
#include <drivers/gpio.h>
#include <logging/log.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/conn.h>
#include <bluetooth/uuid.h>
#include <bluetooth/gatt.h>
#include "button_svc.h"
#include "led_svc.h"
LOG_MODULE_REGISTER(main);
extern u16_t but_val;
extern struct device *led_dev;
extern bool led_state;
/* Prototype */
static ssize_t recv(struct bt_conn *conn,
const struct bt_gatt_attr *attr, const void *buf,
u16_t len, u16_t offset, u8_t flags);
/* ST Custom Service */
static struct bt_uuid_128 st_service_uuid = BT_UUID_INIT_128(
0x8f, 0xe5, 0xb3, 0xd5, 0x2e, 0x7f, 0x4a, 0x98,
0x2a, 0x48, 0x7a, 0xcc, 0x40, 0xfe, 0x00, 0x00);
/* ST LED service */
static struct bt_uuid_128 led_char_uuid = BT_UUID_INIT_128(
0x19, 0xed, 0x82, 0xae, 0xed, 0x21, 0x4c, 0x9d,
0x41, 0x45, 0x22, 0x8e, 0x41, 0xfe, 0x00, 0x00);
/* ST Notify button service */
static struct bt_uuid_128 but_notif_uuid = BT_UUID_INIT_128(
0x19, 0xed, 0x82, 0xae, 0xed, 0x21, 0x4c, 0x9d,
0x41, 0x45, 0x22, 0x8e, 0x42, 0xfe, 0x00, 0x00);
#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)
#define ADV_LEN 12
/* Advertising data */
static u8_t manuf_data[ADV_LEN] = {
0x01 /*SKD version */,
0x83 /* STM32WB - P2P Server 1 */,
0x00 /* GROUP A Feature */,
0x00 /* GROUP A Feature */,
0x00 /* GROUP B Feature */,
0x00 /* GROUP B Feature */,
0x00, /* BLE MAC start -MSB */
0x00,
0x00,
0x00,
0x00,
0x00, /* BLE MAC stop */
};
static const struct bt_data ad[] = {
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
BT_DATA(BT_DATA_MANUFACTURER_DATA, manuf_data, ADV_LEN)
};
/* BLE connection */
struct bt_conn *conn;
/* Notification state */
volatile bool notify_enable;
static void mpu_ccc_cfg_changed(const struct bt_gatt_attr *attr, u16_t value)
{
ARG_UNUSED(attr);
notify_enable = (value == BT_GATT_CCC_NOTIFY);
LOG_INF("Notification %s", notify_enable ? "enabled" : "disabled");
}
/* The embedded board is acting as GATT server.
* The ST BLE Android app is the BLE GATT client.
*/
/* ST BLE Sensor GATT services and characteristic */
BT_GATT_SERVICE_DEFINE(stsensor_svc,
BT_GATT_PRIMARY_SERVICE(&st_service_uuid),
BT_GATT_CHARACTERISTIC(&led_char_uuid.uuid,
BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE_WITHOUT_RESP,
BT_GATT_PERM_WRITE, NULL, recv, (void *)1),
BT_GATT_CHARACTERISTIC(&but_notif_uuid.uuid, BT_GATT_CHRC_NOTIFY,
BT_GATT_PERM_READ, NULL, NULL, &but_val),
BT_GATT_CCC(mpu_ccc_cfg_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
);
static ssize_t recv(struct bt_conn *conn,
const struct bt_gatt_attr *attr, const void *buf,
u16_t len, u16_t offset, u8_t flags)
{
if (led_dev) {
if (led_state == true) {
led_on_off(0);
LOG_INF("Turn off LED");
} else {
led_on_off(1);
LOG_INF("Turn on LED");
}
led_state = !led_state;
}
return 0;
}
static void bt_ready(int err)
{
if (err) {
LOG_ERR("Bluetooth init failed (err %d)", err);
return;
}
LOG_INF("Bluetooth initialized");
/* Start advertising */
err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0);
if (err) {
LOG_ERR("Advertising failed to start (err %d)", err);
return;
}
LOG_INF("Configuration mode: waiting connections...");
}
static void connected(struct bt_conn *connected, u8_t err)
{
if (err) {
LOG_ERR("Connection failed (err %u)", err);
} else {
LOG_INF("Connected");
if (!conn) {
conn = bt_conn_ref(connected);
}
}
}
static void disconnected(struct bt_conn *disconn, u8_t reason)
{
if (conn) {
bt_conn_unref(conn);
conn = NULL;
}
LOG_INF("Disconnected (reason %u)", reason);
}
static struct bt_conn_cb conn_callbacks = {
.connected = connected,
.disconnected = disconnected,
};
void main(void)
{
int err;
err = button_init();
if (err) {
LOG_ERR("Button init error: (err %d)", err);
}
led_init();
bt_conn_cb_register(&conn_callbacks);
/* Initialize the Bluetooth Subsystem */
err = bt_enable(bt_ready);
if (err) {
LOG_ERR("Bluetooth init failed (err %d)", err);
}
while (1) {
k_sleep(K_SECONDS(1));
}
}