This commit is contained in:
parent
cfe0381610
commit
2354da0722
@ -9,4 +9,5 @@ find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
|||||||
|
|
||||||
project(app LANGUAGES C)
|
project(app LANGUAGES C)
|
||||||
|
|
||||||
target_sources(app PRIVATE src/main.c)
|
FILE(GLOB app_sources src/*.c)
|
||||||
|
target_sources(app PRIVATE ${app_sources})
|
@ -6,9 +6,6 @@
|
|||||||
#include <zephyr/kernel.h>
|
#include <zephyr/kernel.h>
|
||||||
#include <app_version.h>
|
#include <app_version.h>
|
||||||
|
|
||||||
#include <zephyr/logging/log.h>
|
|
||||||
LOG_MODULE_REGISTER(main, CONFIG_APP_LOG_LEVEL);
|
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
printk("Zephyr Example Application %s\n", APP_VERSION_STRING);
|
printk("Zephyr Example Application %s\n", APP_VERSION_STRING);
|
||||||
|
26
script.sh
26
script.sh
@ -124,7 +124,18 @@ connectivity_dialog() {
|
|||||||
# TODO
|
# TODO
|
||||||
;;
|
;;
|
||||||
2 ) # Bluetooth
|
2 ) # Bluetooth
|
||||||
# TODO
|
sed -i '/int main(void)/e cat snippets/ble_gatt/code1.txt' /workdir/app/src/main.c
|
||||||
|
|
||||||
|
code2=$(cat snippets/ble_gatt/code2.txt)
|
||||||
|
echo "$code2" >> /workdir/app/src/peripheral_gatt_write.c
|
||||||
|
|
||||||
|
code3=$(cat snippets/ble_gatt/code3.txt)
|
||||||
|
echo "$code3" >> /workdir/app/src/gatt_write_common.c
|
||||||
|
|
||||||
|
config=$(cat snippets/ble_gatt/config.txt)
|
||||||
|
echo "$config" >> /workdir/app/prj.conf
|
||||||
|
|
||||||
|
display_result 'Added functionality' "Added functionality successfully at the end of main.c.\nYou have to call the function like in the example manually."
|
||||||
;;
|
;;
|
||||||
3 ) # LoRaWAN
|
3 ) # LoRaWAN
|
||||||
# TODO
|
# TODO
|
||||||
@ -188,8 +199,7 @@ sensors_dialog() {
|
|||||||
|
|
||||||
case $sensors in
|
case $sensors in
|
||||||
1 ) # Button
|
1 ) # Button
|
||||||
code=$(cat snippets/button/code.txt)
|
sed -i '/int main(void)/e cat snippets/button/code.txt' /workdir/app/src/main.c
|
||||||
echo "$code" >> /workdir/app/src/main.c
|
|
||||||
|
|
||||||
config=$(cat snippets/button/config.txt)
|
config=$(cat snippets/button/config.txt)
|
||||||
echo "$config" >> /workdir/app/prj.conf
|
echo "$config" >> /workdir/app/prj.conf
|
||||||
@ -217,8 +227,7 @@ actuators_dialog() {
|
|||||||
|
|
||||||
case $actuators in
|
case $actuators in
|
||||||
1 ) # LED
|
1 ) # LED
|
||||||
code=$(cat snippets/led/code.txt)
|
sed -i '/int main(void)/e cat snippets/led/code.txt' /workdir/app/src/main.c
|
||||||
echo "$code" >> /workdir/app/src/main.c
|
|
||||||
|
|
||||||
config=$(cat snippets/led/config.txt)
|
config=$(cat snippets/led/config.txt)
|
||||||
echo "$config" >> /workdir/app/prj.conf
|
echo "$config" >> /workdir/app/prj.conf
|
||||||
@ -258,7 +267,12 @@ init_project() {
|
|||||||
build_project() {
|
build_project() {
|
||||||
plattform_dialog
|
plattform_dialog
|
||||||
|
|
||||||
{ cd /workdir/app/; west build -b $PLATTFORM; } 2>&1 | dialog --programbox -1 -1
|
clear
|
||||||
|
|
||||||
|
cd /workdir/app/
|
||||||
|
west build -b $PLATTFORM
|
||||||
|
|
||||||
|
read -p "Press any key to continue... " -n1 -s
|
||||||
}
|
}
|
||||||
|
|
||||||
flash_project() {
|
flash_project() {
|
||||||
|
26
snippets/ble_gatt/code1.txt
Normal file
26
snippets/ble_gatt/code1.txt
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
|
||||||
|
/* --------------------------- */
|
||||||
|
/* BLE */
|
||||||
|
/* --------------------------- */
|
||||||
|
|
||||||
|
/* Imports / Declarations */
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* Functions */
|
||||||
|
extern uint32_t peripheral_gatt_write(uint32_t count);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Example:
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
(void)peripheral_gatt_write(0U);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* --------------------------- */
|
||||||
|
/* BLE End */
|
||||||
|
/* --------------------------- */
|
||||||
|
|
106
snippets/ble_gatt/code2.txt
Normal file
106
snippets/ble_gatt/code2.txt
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022 Nordic Semiconductor ASA
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/sys/printk.h>
|
||||||
|
|
||||||
|
#include <zephyr/bluetooth/bluetooth.h>
|
||||||
|
#include <zephyr/bluetooth/conn.h>
|
||||||
|
#include <zephyr/bluetooth/gatt.h>
|
||||||
|
|
||||||
|
extern int mtu_exchange(struct bt_conn *conn);
|
||||||
|
extern int write_cmd(struct bt_conn *conn);
|
||||||
|
extern struct bt_conn *conn_connected;
|
||||||
|
extern uint32_t last_write_rate;
|
||||||
|
|
||||||
|
static const struct bt_data ad[] = {
|
||||||
|
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
|
||||||
|
};
|
||||||
|
|
||||||
|
static void mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx)
|
||||||
|
{
|
||||||
|
printk("Updated MTU: TX: %d RX: %d bytes\n", tx, rx);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_SMP)
|
||||||
|
static void auth_cancel(struct bt_conn *conn)
|
||||||
|
{
|
||||||
|
char addr[BT_ADDR_LE_STR_LEN];
|
||||||
|
|
||||||
|
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||||
|
|
||||||
|
printk("Pairing cancelled: %s\n", addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct bt_conn_auth_cb auth_callbacks = {
|
||||||
|
.cancel = auth_cancel,
|
||||||
|
};
|
||||||
|
#endif /* CONFIG_BT_SMP */
|
||||||
|
|
||||||
|
static struct bt_gatt_cb gatt_callbacks = {
|
||||||
|
.att_mtu_updated = mtu_updated
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t peripheral_gatt_write(uint32_t count)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = bt_enable(NULL);
|
||||||
|
if (err) {
|
||||||
|
printk("Bluetooth init failed (err %d)\n", err);
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
printk("Bluetooth initialized\n");
|
||||||
|
|
||||||
|
bt_gatt_cb_register(&gatt_callbacks);
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_SMP)
|
||||||
|
(void)bt_conn_auth_cb_register(&auth_callbacks);
|
||||||
|
#endif /* CONFIG_BT_SMP */
|
||||||
|
|
||||||
|
err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, ad, ARRAY_SIZE(ad), NULL, 0);
|
||||||
|
if (err) {
|
||||||
|
printk("Advertising failed to start (err %d)\n", err);
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
printk("Advertising successfully started\n");
|
||||||
|
|
||||||
|
conn_connected = NULL;
|
||||||
|
last_write_rate = 0U;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
struct bt_conn *conn = NULL;
|
||||||
|
|
||||||
|
if (conn_connected) {
|
||||||
|
/* Get a connection reference to ensure that a
|
||||||
|
* reference is maintained in case disconnected
|
||||||
|
* callback is called while we perform GATT Write
|
||||||
|
* command.
|
||||||
|
*/
|
||||||
|
conn = bt_conn_ref(conn_connected);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conn) {
|
||||||
|
write_cmd(conn);
|
||||||
|
bt_conn_unref(conn);
|
||||||
|
|
||||||
|
if (count) {
|
||||||
|
count--;
|
||||||
|
if (!count) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
k_yield();
|
||||||
|
} else {
|
||||||
|
k_sleep(K_SECONDS(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return last_write_rate;
|
||||||
|
}
|
226
snippets/ble_gatt/code3.txt
Normal file
226
snippets/ble_gatt/code3.txt
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022 Nordic Semiconductor ASA
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/sys/printk.h>
|
||||||
|
|
||||||
|
#include <zephyr/bluetooth/bluetooth.h>
|
||||||
|
#include <zephyr/bluetooth/conn.h>
|
||||||
|
#include <zephyr/bluetooth/gatt.h>
|
||||||
|
|
||||||
|
static struct bt_gatt_exchange_params mtu_exchange_params;
|
||||||
|
static uint32_t write_count;
|
||||||
|
static uint32_t write_len;
|
||||||
|
static uint32_t write_rate;
|
||||||
|
struct bt_conn *conn_connected;
|
||||||
|
uint32_t last_write_rate;
|
||||||
|
void (*start_scan_func)(void);
|
||||||
|
|
||||||
|
static void write_cmd_cb(struct bt_conn *conn, void *user_data)
|
||||||
|
{
|
||||||
|
static uint32_t cycle_stamp;
|
||||||
|
uint64_t delta;
|
||||||
|
|
||||||
|
delta = k_cycle_get_32() - cycle_stamp;
|
||||||
|
delta = k_cyc_to_ns_floor64(delta);
|
||||||
|
|
||||||
|
/* if last data rx-ed was greater than 1 second in the past,
|
||||||
|
* reset the metrics.
|
||||||
|
*/
|
||||||
|
if (delta > (1U * NSEC_PER_SEC)) {
|
||||||
|
printk("%s: count= %u, len= %u, rate= %u bps.\n", __func__,
|
||||||
|
write_count, write_len, write_rate);
|
||||||
|
|
||||||
|
last_write_rate = write_rate;
|
||||||
|
|
||||||
|
write_count = 0U;
|
||||||
|
write_len = 0U;
|
||||||
|
write_rate = 0U;
|
||||||
|
cycle_stamp = k_cycle_get_32();
|
||||||
|
} else {
|
||||||
|
uint16_t len;
|
||||||
|
|
||||||
|
write_count++;
|
||||||
|
|
||||||
|
/* Extract the 16-bit data length stored in user_data */
|
||||||
|
len = (uint32_t)user_data & 0xFFFF;
|
||||||
|
|
||||||
|
write_len += len;
|
||||||
|
write_rate = ((uint64_t)write_len << 3) * (1U * NSEC_PER_SEC) /
|
||||||
|
delta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mtu_exchange_cb(struct bt_conn *conn, uint8_t err,
|
||||||
|
struct bt_gatt_exchange_params *params)
|
||||||
|
{
|
||||||
|
printk("%s: MTU exchange %s (%u)\n", __func__,
|
||||||
|
err == 0U ? "successful" : "failed",
|
||||||
|
bt_gatt_get_mtu(conn));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mtu_exchange(struct bt_conn *conn)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
printk("%s: Current MTU = %u\n", __func__, bt_gatt_get_mtu(conn));
|
||||||
|
|
||||||
|
mtu_exchange_params.func = mtu_exchange_cb;
|
||||||
|
|
||||||
|
printk("%s: Exchange MTU...\n", __func__);
|
||||||
|
err = bt_gatt_exchange_mtu(conn, &mtu_exchange_params);
|
||||||
|
if (err) {
|
||||||
|
printk("%s: MTU exchange failed (err %d)", __func__, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void connected(struct bt_conn *conn, uint8_t conn_err)
|
||||||
|
{
|
||||||
|
struct bt_conn_info conn_info;
|
||||||
|
char addr[BT_ADDR_LE_STR_LEN];
|
||||||
|
int err;
|
||||||
|
|
||||||
|
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||||
|
|
||||||
|
if (conn_err) {
|
||||||
|
printk("%s: Failed to connect to %s (%u)\n", __func__, addr,
|
||||||
|
conn_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bt_conn_get_info(conn, &conn_info);
|
||||||
|
if (err) {
|
||||||
|
printk("Failed to get connection info (%d).\n", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printk("%s: %s role %u\n", __func__, addr, conn_info.role);
|
||||||
|
|
||||||
|
conn_connected = bt_conn_ref(conn);
|
||||||
|
|
||||||
|
(void)mtu_exchange(conn);
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_SMP)
|
||||||
|
if (conn_info.role == BT_CONN_ROLE_CENTRAL) {
|
||||||
|
err = bt_conn_set_security(conn, BT_SECURITY_L2);
|
||||||
|
if (err) {
|
||||||
|
printk("Failed to set security (%d).\n", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void disconnected(struct bt_conn *conn, uint8_t reason)
|
||||||
|
{
|
||||||
|
struct bt_conn_info conn_info;
|
||||||
|
char addr[BT_ADDR_LE_STR_LEN];
|
||||||
|
int err;
|
||||||
|
|
||||||
|
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||||
|
|
||||||
|
err = bt_conn_get_info(conn, &conn_info);
|
||||||
|
if (err) {
|
||||||
|
printk("Failed to get connection info (%d).\n", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printk("%s: %s role %u (reason %u)\n", __func__, addr, conn_info.role,
|
||||||
|
reason);
|
||||||
|
|
||||||
|
conn_connected = NULL;
|
||||||
|
|
||||||
|
bt_conn_unref(conn);
|
||||||
|
|
||||||
|
if (conn_info.role == BT_CONN_ROLE_CENTRAL) {
|
||||||
|
start_scan_func();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param)
|
||||||
|
{
|
||||||
|
printk("%s: int (0x%04x, 0x%04x) lat %u to %u\n", __func__,
|
||||||
|
param->interval_min, param->interval_max, param->latency,
|
||||||
|
param->timeout);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void le_param_updated(struct bt_conn *conn, uint16_t interval,
|
||||||
|
uint16_t latency, uint16_t timeout)
|
||||||
|
{
|
||||||
|
printk("%s: int 0x%04x lat %u to %u\n", __func__, interval,
|
||||||
|
latency, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_SMP)
|
||||||
|
static void security_changed(struct bt_conn *conn, bt_security_t level,
|
||||||
|
enum bt_security_err err)
|
||||||
|
{
|
||||||
|
printk("%s: to level %u (err %u)\n", __func__, level, err);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
BT_CONN_CB_DEFINE(conn_callbacks) = {
|
||||||
|
.connected = connected,
|
||||||
|
.disconnected = disconnected,
|
||||||
|
.le_param_req = le_param_req,
|
||||||
|
.le_param_updated = le_param_updated,
|
||||||
|
#if defined(CONFIG_BT_SMP)
|
||||||
|
.security_changed = security_changed,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
int write_cmd(struct bt_conn *conn)
|
||||||
|
{
|
||||||
|
static uint8_t data[BT_ATT_MAX_ATTRIBUTE_LEN] = {0, };
|
||||||
|
static uint16_t data_len;
|
||||||
|
uint16_t data_len_max;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
data_len_max = bt_gatt_get_mtu(conn) - 3;
|
||||||
|
if (data_len_max > BT_ATT_MAX_ATTRIBUTE_LEN) {
|
||||||
|
data_len_max = BT_ATT_MAX_ATTRIBUTE_LEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if TEST_FRAGMENTATION_WITH_VARIABLE_LENGTH_DATA
|
||||||
|
/* Use incremental length data for every write command */
|
||||||
|
/* TODO: Include test case in BabbleSim tests */
|
||||||
|
static bool decrement;
|
||||||
|
|
||||||
|
if (decrement) {
|
||||||
|
data_len--;
|
||||||
|
if (data_len <= 1) {
|
||||||
|
data_len = 1;
|
||||||
|
decrement = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data_len++;
|
||||||
|
if (data_len >= data_len_max) {
|
||||||
|
data_len = data_len_max;
|
||||||
|
decrement = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* Use fixed length data for every write command */
|
||||||
|
data_len = data_len_max;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Pass the 16-bit data length value (instead of reference) in
|
||||||
|
* user_data so that unique value is pass for each write callback.
|
||||||
|
* Using handle 0x0001, we do not care if it is writable, we just want
|
||||||
|
* to transmit the data across.
|
||||||
|
*/
|
||||||
|
err = bt_gatt_write_without_response_cb(conn, 0x0001, data, data_len,
|
||||||
|
false, write_cmd_cb,
|
||||||
|
(void *)((uint32_t)data_len));
|
||||||
|
if (err) {
|
||||||
|
printk("%s: Write cmd failed (%d).\n", __func__, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
14
snippets/ble_gatt/config.txt
Normal file
14
snippets/ble_gatt/config.txt
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
CONFIG_BT=y
|
||||||
|
CONFIG_BT_PERIPHERAL=y
|
||||||
|
CONFIG_BT_SMP=y
|
||||||
|
CONFIG_BT_GATT_CLIENT=y
|
||||||
|
CONFIG_BT_DEVICE_NAME="Zephyr GATT Write Example"
|
||||||
|
|
||||||
|
CONFIG_BT_BUF_ACL_RX_SIZE=255
|
||||||
|
CONFIG_BT_BUF_ACL_TX_SIZE=251
|
||||||
|
CONFIG_BT_BUF_CMD_TX_SIZE=255
|
||||||
|
CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE=255
|
||||||
|
|
||||||
|
CONFIG_BT_L2CAP_TX_MTU=247
|
||||||
|
|
||||||
|
CONFIG_LOG=y
|
@ -114,3 +114,8 @@ int main(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* --------------------------- */
|
||||||
|
/* Buttons End */
|
||||||
|
/* --------------------------- */
|
||||||
|
|
||||||
|
@ -56,3 +56,8 @@ int main(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* --------------------------- */
|
||||||
|
/* LED End */
|
||||||
|
/* --------------------------- */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user