mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-08-07 10:37:54 +00:00
apps/mesh_badge: Port app to Mynewt
This commit is contained in:
@@ -1,5 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.8.2)
|
||||
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
|
||||
project(NONE)
|
||||
|
||||
target_sources(app PRIVATE src/main.c src/mesh.c src/${BOARD}.c)
|
||||
@@ -1,9 +1,7 @@
|
||||
.. _mesh_badge:
|
||||
### Mesh Badge
|
||||
|
||||
Mesh Badge
|
||||
##########
|
||||
|
||||
Overview
|
||||
##### Overview
|
||||
********
|
||||
|
||||
This sample app for the reel board showcases Bluetooth Mesh
|
||||
@@ -14,27 +12,27 @@ Android and iOS) to access the service that the app exposes. The service
|
||||
can also be accessed with any Bluetooth LE GATT client from your PC,
|
||||
however these instructions focus on the necessary steps for phones.
|
||||
|
||||
Steps to set up
|
||||
##### Steps to set up
|
||||
***************
|
||||
|
||||
#. On your phone, use the nRF Connect app to Scan for devices and look
|
||||
* On your phone, use the nRF Connect app to Scan for devices and look
|
||||
for "reel board"
|
||||
#. Connect to the device. You'll see a single service - select it
|
||||
#. Request to write to the characteristic by pressing on the upward pointing
|
||||
* Connect to the device. You'll see a single service - select it
|
||||
* Request to write to the characteristic by pressing on the upward pointing
|
||||
arrow symbol
|
||||
#. Select "Text" to enter text instead of hex
|
||||
#. Enter your name (or any other arbitrary text). Multiple words
|
||||
* Select "Text" to enter text instead of hex
|
||||
* Enter your name (or any other arbitrary text). Multiple words
|
||||
separated by spaces are possible. The font used on the reel display
|
||||
allows three rows of up to 12 characters
|
||||
wide text. You can force line breaks with a comma.
|
||||
#. Press "Send" - this will trigger pairing since this is a protected
|
||||
* Press "Send" - this will trigger pairing since this is a protected
|
||||
characteristic. The passkey for the pairing will be shown on the board's
|
||||
display. Enter the passkey in your phone.
|
||||
#. Once pairing is complete the board will show the text you sent. If
|
||||
* Once pairing is complete the board will show the text you sent. If
|
||||
you're not happy with it you can try writing something else.
|
||||
#. When you're happy with the text, disconnect from the board (exit the app or
|
||||
* When you're happy with the text, disconnect from the board (exit the app or
|
||||
go back to the device scan page)
|
||||
#. Once disconnected the board switches over to Bluetooth Mesh mode, and you
|
||||
* Once disconnected the board switches over to Bluetooth Mesh mode, and you
|
||||
can't connect to it anymore over GATT.
|
||||
|
||||
If you configure multiple boards like this they can communicate with
|
||||
@@ -45,6 +43,6 @@ the network and cause the other boards to display "<name> says hi!".
|
||||
To reset a board to its initial state (disable mesh, erase the stored
|
||||
text, and make it connectable over GATT):
|
||||
|
||||
#. Keep the user button pressed when powering on (or press the reset button
|
||||
* Keep the user button pressed when powering on (or press the reset button
|
||||
when powered)
|
||||
#. Wait until "Reseting Device" is shown
|
||||
* Wait until "Reseting Device" is shown
|
||||
@@ -0,0 +1,39 @@
|
||||
# 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.
|
||||
#
|
||||
pkg.name: apps/mesh_badge
|
||||
pkg.type: app
|
||||
pkg.description: Sample app for the reel board that showcases Bluetooth Mesh
|
||||
pkg.author: "Apache Mynewt <[email protected]>"
|
||||
pkg.homepage: "http://mynewt.apache.org/"
|
||||
pkg.keywords:
|
||||
|
||||
pkg.deps:
|
||||
- "@apache-mynewt-core/hw/drivers/display/cfb"
|
||||
- "@apache-mynewt-core/hw/drivers/display/ssd1673"
|
||||
- "@apache-mynewt-core/kernel/os"
|
||||
- "@apache-mynewt-core/sys/console/full"
|
||||
- "@apache-mynewt-core/sys/log/full"
|
||||
- "@apache-mynewt-core/sys/log/modlog"
|
||||
- "@apache-mynewt-core/sys/stats/full"
|
||||
- "@apache-mynewt-core/sys/shell"
|
||||
- nimble/controller
|
||||
- nimble/host
|
||||
- nimble/host/services/gap
|
||||
- nimble/host/services/gatt
|
||||
- nimble/host/store/config
|
||||
- nimble/transport/ram
|
||||
@@ -1,66 +0,0 @@
|
||||
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096
|
||||
CONFIG_BT_RX_STACK_SIZE=4096
|
||||
|
||||
CONFIG_BT_DEVICE_NAME_DYNAMIC=y
|
||||
CONFIG_BT_DEVICE_NAME_GATT_WRITABLE=y
|
||||
CONFIG_BT_SMP=y
|
||||
CONFIG_BT_PERIPHERAL=y
|
||||
CONFIG_BT_PRIVACY=y
|
||||
CONFIG_BT_DEVICE_NAME="reel board"
|
||||
CONFIG_BT_DEVICE_NAME_MAX=32
|
||||
|
||||
CONFIG_BT_DEBUG_LOG=y
|
||||
CONFIG_BT_MESH_DEBUG=y
|
||||
#CONFIG_BT_DEBUG_HCI_CORE=y
|
||||
#CONFIG_BT_MESH_DEBUG_ADV=y
|
||||
|
||||
CONFIG_BT_OBSERVER=y
|
||||
CONFIG_BT_BROADCASTER=y
|
||||
CONFIG_BT_RX_BUF_COUNT=30
|
||||
CONFIG_BT_L2CAP_RX_MTU=69
|
||||
CONFIG_BT_L2CAP_TX_MTU=69
|
||||
CONFIG_BT_L2CAP_TX_BUF_COUNT=8
|
||||
|
||||
CONFIG_BT_MESH=y
|
||||
CONFIG_BT_MESH_RELAY=y
|
||||
#CONFIG_BT_MESH_GATT_PROXY=y
|
||||
CONFIG_BT_MESH_PB_ADV=n
|
||||
CONFIG_BT_MESH_PB_GATT=n
|
||||
CONFIG_BT_MESH_ADV_BUF_COUNT=30
|
||||
CONFIG_BT_MESH_LABEL_COUNT=0
|
||||
CONFIG_BT_MESH_CFG_CLI=y
|
||||
CONFIG_BT_MESH_TX_SEG_MAX=6
|
||||
CONFIG_BT_MESH_TX_SEG_MSG_COUNT=3
|
||||
CONFIG_BT_MESH_RX_SEG_MSG_COUNT=3
|
||||
CONFIG_BT_MESH_CRPL=128
|
||||
CONFIG_BT_MESH_RPL_STORE_TIMEOUT=120
|
||||
|
||||
CONFIG_PRINTK=y
|
||||
CONFIG_SERIAL=y
|
||||
CONFIG_CONSOLE=y
|
||||
CONFIG_STDOUT_CONSOLE=y
|
||||
|
||||
CONFIG_I2C=y
|
||||
CONFIG_GPIO=y
|
||||
CONFIG_SENSOR=y
|
||||
|
||||
CONFIG_APDS9960=y
|
||||
|
||||
CONFIG_HDC1008=y
|
||||
|
||||
CONFIG_SPI=y
|
||||
CONFIG_SPI_ASYNC=y
|
||||
|
||||
CONFIG_HEAP_MEM_POOL_SIZE=16384
|
||||
CONFIG_DISPLAY=y
|
||||
CONFIG_SSD1673=y
|
||||
|
||||
CONFIG_CHARACTER_FRAMEBUFFER=y
|
||||
|
||||
CONFIG_BT_SETTINGS=y
|
||||
CONFIG_FLASH=y
|
||||
CONFIG_FLASH_PAGE_LAYOUT=y
|
||||
CONFIG_FLASH_MAP=y
|
||||
CONFIG_FCB=y
|
||||
CONFIG_SETTINGS=y
|
||||
CONFIG_SETTINGS_FCB=y
|
||||
@@ -1,8 +0,0 @@
|
||||
sample:
|
||||
description: reel board mesh badge sample
|
||||
name: mesh badge
|
||||
tests:
|
||||
test:
|
||||
platform_whitelist: reel_board
|
||||
tags: samples sensor
|
||||
harness: sensor
|
||||
@@ -5,7 +5,11 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "mesh/mesh.h"
|
||||
|
||||
void board_refresh_display(void);
|
||||
void board_show_text(const char *text, bool center, s32_t duration);
|
||||
void board_blink_leds(void);
|
||||
void board_add_hello(u16_t addr, const char *name);
|
||||
void board_add_heartbeat(u16_t addr, u8_t hops);
|
||||
int board_init(void);
|
||||
|
||||
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "services/gap/ble_svc_gap.h"
|
||||
#include "bsp/bsp.h"
|
||||
#include "host/ble_hs.h"
|
||||
#include "host/ble_uuid.h"
|
||||
|
||||
#include "mesh.h"
|
||||
#include "board.h"
|
||||
#include "mesh_badge.h"
|
||||
|
||||
static const ble_uuid16_t gatt_cud_uuid = BLE_UUID16_INIT(0x2901);
|
||||
static const ble_uuid16_t gatt_cpf_uuid = BLE_UUID16_INIT(0x2904);
|
||||
|
||||
/** @brief GATT Characteristic Presentation Format Attribute Value. */
|
||||
struct bt_gatt_cpf {
|
||||
/** Format of the value of the characteristic */
|
||||
u8_t format;
|
||||
/** Exponent field to determine how the value of this characteristic is further formatted */
|
||||
s8_t exponent;
|
||||
/** Unit of the characteristic */
|
||||
u16_t unit;
|
||||
/** Name space of the description */
|
||||
u8_t name_space;
|
||||
/** Description of the characteristic as defined in a higher layer profile */
|
||||
u16_t description;
|
||||
} __packed;
|
||||
|
||||
#define CPF_FORMAT_UTF8 0x19
|
||||
|
||||
static const struct bt_gatt_cpf name_cpf = {
|
||||
.format = CPF_FORMAT_UTF8,
|
||||
};
|
||||
|
||||
static const ble_uuid128_t name_uuid = BLE_UUID128_INIT(
|
||||
0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
|
||||
0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12);
|
||||
|
||||
static const ble_uuid128_t name_enc_uuid = BLE_UUID128_INIT(
|
||||
0xf1, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
|
||||
0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12);
|
||||
|
||||
static int
|
||||
gatt_svr_chr_access(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctxt,
|
||||
void *arg);
|
||||
|
||||
static const struct ble_gatt_svc_def gatt_svr_svcs[] = {
|
||||
{
|
||||
.type = BLE_GATT_SVC_TYPE_PRIMARY,
|
||||
.uuid = &name_uuid.u,
|
||||
.characteristics = (struct ble_gatt_chr_def[]) { {
|
||||
.uuid = &name_enc_uuid.u,
|
||||
.access_cb = gatt_svr_chr_access,
|
||||
.flags = BLE_GATT_CHR_F_READ |
|
||||
BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_ENC,
|
||||
.descriptors = (struct ble_gatt_dsc_def[]) { {
|
||||
.uuid = &gatt_cud_uuid.u,
|
||||
.access_cb = gatt_svr_chr_access,
|
||||
.att_flags = BLE_ATT_F_READ,
|
||||
}, {
|
||||
.uuid = &gatt_cpf_uuid.u,
|
||||
.access_cb = gatt_svr_chr_access,
|
||||
.att_flags = BLE_ATT_F_READ,
|
||||
}, {
|
||||
0, /* No more descriptors in this characteristic. */
|
||||
} }
|
||||
}, {
|
||||
0, /* No more characteristics in this service. */
|
||||
} },
|
||||
},
|
||||
|
||||
{
|
||||
0, /* No more services. */
|
||||
},
|
||||
};
|
||||
|
||||
static int read_name(struct os_mbuf *om)
|
||||
{
|
||||
const char *value = bt_get_name();
|
||||
int rc;
|
||||
|
||||
rc = os_mbuf_append(om, value, (uint16_t) strlen(value));
|
||||
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||
}
|
||||
|
||||
static int write_name(struct os_mbuf *om)
|
||||
{
|
||||
char name[MYNEWT_VAL(BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH)];
|
||||
uint16_t len;
|
||||
uint16_t om_len;
|
||||
int rc;
|
||||
|
||||
om_len = OS_MBUF_PKTLEN(om);
|
||||
if (om_len >= sizeof(name)) {
|
||||
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
|
||||
}
|
||||
|
||||
rc = ble_hs_mbuf_to_flat(om, name, sizeof(name) - 1, &len);
|
||||
if (rc != 0) {
|
||||
return BLE_ATT_ERR_UNLIKELY;
|
||||
}
|
||||
|
||||
name[len] = '\0';
|
||||
|
||||
rc = bt_set_name(name);
|
||||
if (rc) {
|
||||
return BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||
}
|
||||
|
||||
board_refresh_display();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
gatt_svr_chr_access(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctxt,
|
||||
void *arg)
|
||||
{
|
||||
const ble_uuid_t *uuid;
|
||||
int rc;
|
||||
|
||||
uuid = ctxt->chr->uuid;
|
||||
|
||||
if (ble_uuid_cmp(uuid, &name_enc_uuid.u) == 0) {
|
||||
switch (ctxt->op) {
|
||||
case BLE_GATT_ACCESS_OP_READ_CHR:
|
||||
rc = read_name(ctxt->om);
|
||||
return rc;
|
||||
|
||||
case BLE_GATT_ACCESS_OP_WRITE_CHR:
|
||||
rc = write_name(ctxt->om);
|
||||
return rc;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return BLE_ATT_ERR_UNLIKELY;
|
||||
}
|
||||
} else if (ble_uuid_cmp(uuid, &gatt_cud_uuid.u) == 0) {
|
||||
rc = os_mbuf_append(ctxt->om, "Badge Name",
|
||||
(uint16_t) strlen("Badge Name"));
|
||||
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||
} else if (ble_uuid_cmp(uuid, &gatt_cpf_uuid.u) == 0) {
|
||||
rc = os_mbuf_append(ctxt->om, &name_cpf,
|
||||
(uint16_t) sizeof(name_cpf));
|
||||
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||
}
|
||||
|
||||
/* Unknown characteristic; the nimble stack should not have called this
|
||||
* function.
|
||||
*/
|
||||
assert(0);
|
||||
return BLE_ATT_ERR_UNLIKELY;
|
||||
}
|
||||
|
||||
void
|
||||
gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg)
|
||||
{
|
||||
char buf[BLE_UUID_STR_LEN];
|
||||
|
||||
switch (ctxt->op) {
|
||||
case BLE_GATT_REGISTER_OP_SVC:
|
||||
MODLOG_DFLT(DEBUG, "registered service %s with handle=%d\n",
|
||||
ble_uuid_to_str(ctxt->svc.svc_def->uuid, buf),
|
||||
ctxt->svc.handle);
|
||||
break;
|
||||
|
||||
case BLE_GATT_REGISTER_OP_CHR:
|
||||
MODLOG_DFLT(DEBUG, "registering characteristic %s with "
|
||||
"def_handle=%d val_handle=%d\n",
|
||||
ble_uuid_to_str(ctxt->chr.chr_def->uuid, buf),
|
||||
ctxt->chr.def_handle,
|
||||
ctxt->chr.val_handle);
|
||||
break;
|
||||
|
||||
case BLE_GATT_REGISTER_OP_DSC:
|
||||
MODLOG_DFLT(DEBUG, "registering descriptor %s with handle=%d\n",
|
||||
ble_uuid_to_str(ctxt->dsc.dsc_def->uuid, buf),
|
||||
ctxt->dsc.handle);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
gatt_svr_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = ble_gatts_count_cfg(gatt_svr_svcs);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = ble_gatts_add_svcs(gatt_svr_svcs);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
+290
-132
@@ -4,140 +4,155 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <misc/printk.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <settings/settings.h>
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/gatt.h>
|
||||
#include "console/console.h"
|
||||
#include "host/ble_gap.h"
|
||||
#include "mesh/glue.h"
|
||||
#include "services/gap/ble_svc_gap.h"
|
||||
#include "base64/base64.h"
|
||||
|
||||
#include "mesh_badge.h"
|
||||
#include "mesh.h"
|
||||
#include "board.h"
|
||||
|
||||
static const struct bt_data ad[] = {
|
||||
BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_NO_BREDR),
|
||||
};
|
||||
static char badge_name[MYNEWT_VAL(BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH)];
|
||||
|
||||
static size_t first_name_len(const char *name)
|
||||
#define MESH_BADGE_NAME_ENCODE_SIZE \
|
||||
BASE64_ENCODE_SIZE(sizeof(badge_name))
|
||||
|
||||
static bool reset_mesh;
|
||||
|
||||
void print_addr(const void *addr)
|
||||
{
|
||||
size_t len;
|
||||
const uint8_t *u8p;
|
||||
|
||||
for (len = 0; *name; name++, len++) {
|
||||
switch (*name) {
|
||||
case ' ':
|
||||
case ',':
|
||||
case '\n':
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
u8p = addr;
|
||||
MODLOG_DFLT(INFO, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
u8p[5], u8p[4], u8p[3], u8p[2], u8p[1], u8p[0]);
|
||||
}
|
||||
|
||||
static ssize_t read_name(struct bt_conn *conn, const struct bt_gatt_attr *attr,
|
||||
void *buf, u16_t len, u16_t offset)
|
||||
static void
|
||||
print_conn_desc(struct ble_gap_conn_desc *desc)
|
||||
{
|
||||
const char *value = bt_get_name();
|
||||
|
||||
return bt_gatt_attr_read(conn, attr, buf, len, offset, value,
|
||||
strlen(value));
|
||||
MODLOG_DFLT(INFO, "handle=%d our_ota_addr_type=%d our_ota_addr=",
|
||||
desc->conn_handle, desc->our_ota_addr.type);
|
||||
print_addr(desc->our_ota_addr.val);
|
||||
MODLOG_DFLT(INFO, " our_id_addr_type=%d our_id_addr=",
|
||||
desc->our_id_addr.type);
|
||||
print_addr(desc->our_id_addr.val);
|
||||
MODLOG_DFLT(INFO, " peer_ota_addr_type=%d peer_ota_addr=",
|
||||
desc->peer_ota_addr.type);
|
||||
print_addr(desc->peer_ota_addr.val);
|
||||
MODLOG_DFLT(INFO, " peer_id_addr_type=%d peer_id_addr=",
|
||||
desc->peer_id_addr.type);
|
||||
print_addr(desc->peer_id_addr.val);
|
||||
MODLOG_DFLT(INFO, " conn_itvl=%d conn_latency=%d supervision_timeout=%d "
|
||||
"encrypted=%d authenticated=%d bonded=%d\n",
|
||||
desc->conn_itvl, desc->conn_latency,
|
||||
desc->supervision_timeout,
|
||||
desc->sec_state.encrypted,
|
||||
desc->sec_state.authenticated,
|
||||
desc->sec_state.bonded);
|
||||
}
|
||||
|
||||
static ssize_t write_name(struct bt_conn *conn, const struct bt_gatt_attr *attr,
|
||||
const void *buf, u16_t len, u16_t offset,
|
||||
u8_t flags)
|
||||
static int gap_event(struct ble_gap_event *event, void *arg);
|
||||
|
||||
static void advertise(void)
|
||||
{
|
||||
char name[CONFIG_BT_DEVICE_NAME_MAX];
|
||||
int err;
|
||||
uint8_t own_addr_type;
|
||||
struct ble_gap_adv_params adv_params;
|
||||
struct ble_hs_adv_fields fields;
|
||||
const char *name;
|
||||
int rc;
|
||||
|
||||
if (offset) {
|
||||
return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
|
||||
/* Figure out address to use while advertising (no privacy for now) */
|
||||
rc = ble_hs_id_infer_auto(0, &own_addr_type);
|
||||
if (rc != 0) {
|
||||
MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (len >= CONFIG_BT_DEVICE_NAME_MAX) {
|
||||
return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
|
||||
/**
|
||||
* Set the advertisement data included in our advertisements:
|
||||
* o Flags (indicates advertisement type and other general info).
|
||||
* o Advertising tx power.
|
||||
* o Device name.
|
||||
* o 16-bit service UUIDs (alert notifications).
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
#if 0
|
||||
/* Indicate that the TX power level field should be included; have the
|
||||
* stack fill this value automatically. This is done by assiging 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;
|
||||
#endif
|
||||
|
||||
name = ble_svc_gap_device_name();
|
||||
fields.name = (uint8_t *)name;
|
||||
fields.name_len = (uint8_t) strlen(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;
|
||||
}
|
||||
|
||||
memcpy(name, buf, len);
|
||||
name[len] = '\0';
|
||||
|
||||
err = bt_set_name(name);
|
||||
if (err) {
|
||||
return BT_GATT_ERR(BT_ATT_ERR_INSUFFICIENT_RESOURCES);
|
||||
/* 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(own_addr_type, NULL, BLE_HS_FOREVER,
|
||||
&adv_params, gap_event, NULL);
|
||||
if (rc != 0) {
|
||||
MODLOG_DFLT(ERROR, "error enabling advertisement; rc=%d\n", rc);
|
||||
return;
|
||||
}
|
||||
|
||||
mesh_set_name(name, first_name_len(name));
|
||||
board_refresh_display();
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static struct bt_uuid_128 name_uuid = BT_UUID_INIT_128(
|
||||
0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
|
||||
0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12);
|
||||
|
||||
static struct bt_uuid_128 name_enc_uuid = BT_UUID_INIT_128(
|
||||
0xf1, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
|
||||
0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12);
|
||||
|
||||
#define CPF_FORMAT_UTF8 0x19
|
||||
|
||||
static const struct bt_gatt_cpf name_cpf = {
|
||||
.format = CPF_FORMAT_UTF8,
|
||||
};
|
||||
|
||||
/* Vendor Primary Service Declaration */
|
||||
static struct bt_gatt_attr name_attrs[] = {
|
||||
/* Vendor Primary Service Declaration */
|
||||
BT_GATT_PRIMARY_SERVICE(&name_uuid),
|
||||
BT_GATT_CHARACTERISTIC(&name_enc_uuid.uuid,
|
||||
BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE,
|
||||
BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT,
|
||||
read_name, write_name, NULL),
|
||||
BT_GATT_CUD("Badge Name", BT_GATT_PERM_READ),
|
||||
BT_GATT_CPF(&name_cpf),
|
||||
};
|
||||
|
||||
static struct bt_gatt_service name_svc = BT_GATT_SERVICE(name_attrs);
|
||||
|
||||
static void passkey_display(struct bt_conn *conn, unsigned int passkey)
|
||||
static void passkey_display(uint16_t conn_handle)
|
||||
{
|
||||
char buf[20];
|
||||
struct ble_sm_io pk;
|
||||
int rc;
|
||||
|
||||
snprintk(buf, sizeof(buf), "Passkey:\n%06u", passkey);
|
||||
bt_rand(&pk.passkey, sizeof(pk.passkey));
|
||||
/* Max value is 999999 */
|
||||
pk.passkey %= 1000000;
|
||||
pk.action = BLE_SM_IOACT_DISP;
|
||||
|
||||
rc = ble_sm_inject_io(conn_handle, &pk);
|
||||
assert(rc == 0);
|
||||
|
||||
snprintk(buf, sizeof(buf), "Passkey:\n%06lu", pk.passkey);
|
||||
|
||||
printk("%s\n", buf);
|
||||
board_show_text(buf, false, K_FOREVER);
|
||||
}
|
||||
|
||||
static void passkey_cancel(struct bt_conn *conn)
|
||||
{
|
||||
printk("Cancel\n");
|
||||
}
|
||||
|
||||
static void pairing_complete(struct bt_conn *conn, bool bonded)
|
||||
static void pairing_complete(uint16_t conn_handle, bool bonded)
|
||||
{
|
||||
printk("Pairing Complete\n");
|
||||
board_show_text("Pairing Complete", false, K_SECONDS(2));
|
||||
}
|
||||
|
||||
static void pairing_failed(struct bt_conn *conn)
|
||||
static void pairing_failed(uint16_t conn_handle)
|
||||
{
|
||||
printk("Pairing Failed\n");
|
||||
board_show_text("Pairing Failed", false, K_SECONDS(2));
|
||||
}
|
||||
|
||||
const struct bt_conn_auth_cb auth_cb = {
|
||||
.passkey_display = passkey_display,
|
||||
.cancel = passkey_cancel,
|
||||
.pairing_complete = pairing_complete,
|
||||
.pairing_failed = pairing_failed,
|
||||
};
|
||||
|
||||
static void connected(struct bt_conn *conn, u8_t err)
|
||||
static void connected(uint16_t conn_handle, int err)
|
||||
{
|
||||
printk("Connected (err 0x%02x)\n", err);
|
||||
|
||||
@@ -148,35 +163,129 @@ static void connected(struct bt_conn *conn, u8_t err)
|
||||
}
|
||||
}
|
||||
|
||||
static void disconnected(struct bt_conn *conn, u8_t reason)
|
||||
static void disconnected(uint16_t conn_handle, int reason)
|
||||
{
|
||||
printk("Disconnected (reason 0x%02x)\n", reason);
|
||||
|
||||
if (strcmp(CONFIG_BT_DEVICE_NAME, bt_get_name()) &&
|
||||
if (strcmp(MYNEWT_VAL(BLE_SVC_GAP_DEVICE_NAME), bt_get_name()) != 0 &&
|
||||
!mesh_is_initialized()) {
|
||||
/* Mesh will take over advertising control */
|
||||
bt_le_adv_stop();
|
||||
ble_gap_adv_stop();
|
||||
mesh_start();
|
||||
} else {
|
||||
board_show_text("Disconnected", false, K_SECONDS(2));
|
||||
}
|
||||
}
|
||||
|
||||
static struct bt_conn_cb conn_cb = {
|
||||
.connected = connected,
|
||||
.disconnected = disconnected,
|
||||
};
|
||||
|
||||
static void bt_ready(int err)
|
||||
static int gap_event(struct ble_gap_event *event, void *arg)
|
||||
{
|
||||
if (err) {
|
||||
printk("Bluetooth init failed (err %d)\n", err);
|
||||
return;
|
||||
struct ble_gap_conn_desc desc;
|
||||
int rc;
|
||||
|
||||
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 ",
|
||||
event->connect.status == 0 ? "established" : "failed",
|
||||
event->connect.status);
|
||||
if (event->connect.status == 0) {
|
||||
rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
|
||||
assert(rc == 0);
|
||||
print_conn_desc(&desc);
|
||||
connected(event->connect.conn_handle,
|
||||
event->connect.status);
|
||||
}
|
||||
MODLOG_DFLT(INFO, "\n");
|
||||
|
||||
if (event->connect.status != 0) {
|
||||
/* Connection failed; resume advertising. */
|
||||
advertise();
|
||||
}
|
||||
return 0;
|
||||
|
||||
case BLE_GAP_EVENT_DISCONNECT:
|
||||
MODLOG_DFLT(INFO, "disconnect; reason=%d ", event->disconnect.reason);
|
||||
print_conn_desc(&event->disconnect.conn);
|
||||
MODLOG_DFLT(INFO, "\n");
|
||||
|
||||
/* Connection terminated; resume advertising. */
|
||||
advertise();
|
||||
|
||||
disconnected(event->disconnect.conn.conn_handle,
|
||||
event->disconnect.reason);
|
||||
return 0;
|
||||
|
||||
case BLE_GAP_EVENT_CONN_UPDATE:
|
||||
/* The central has updated the connection parameters. */
|
||||
MODLOG_DFLT(INFO, "connection updated; status=%d ",
|
||||
event->conn_update.status);
|
||||
rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
|
||||
assert(rc == 0);
|
||||
print_conn_desc(&desc);
|
||||
MODLOG_DFLT(INFO, "\n");
|
||||
return 0;
|
||||
|
||||
case BLE_GAP_EVENT_ENC_CHANGE:
|
||||
/* Encryption has been enabled or disabled for this connection. */
|
||||
MODLOG_DFLT(INFO, "encryption change event; status=%d ",
|
||||
event->enc_change.status);
|
||||
rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
|
||||
assert(rc == 0);
|
||||
print_conn_desc(&desc);
|
||||
MODLOG_DFLT(INFO, "\n");
|
||||
|
||||
if (desc.sec_state.bonded) {
|
||||
pairing_complete(event->enc_change.conn_handle, true);
|
||||
} else if(desc.sec_state.encrypted) {
|
||||
pairing_complete(event->enc_change.conn_handle, false);
|
||||
} else {
|
||||
pairing_failed(event->enc_change.conn_handle);
|
||||
}
|
||||
return 0;
|
||||
|
||||
case BLE_GAP_EVENT_PASSKEY_ACTION:
|
||||
MODLOG_DFLT(INFO, "passkey action event; conn_handle=%d action=%d numcmp=%d\n",
|
||||
event->passkey.conn_handle,
|
||||
event->passkey.params.action,
|
||||
event->passkey.params.numcmp);
|
||||
passkey_display(event->passkey.conn_handle);
|
||||
return 0;
|
||||
|
||||
case BLE_GAP_EVENT_REPEAT_PAIRING:
|
||||
/* We already have a bond with the peer, but it is attempting to
|
||||
* establish a new secure link. This app sacrifices security for
|
||||
* convenience: just throw away the old bond and accept the new link.
|
||||
*/
|
||||
|
||||
/* Delete the old bond. */
|
||||
rc = ble_gap_conn_find(event->repeat_pairing.conn_handle, &desc);
|
||||
assert(rc == 0);
|
||||
ble_store_util_delete_peer(&desc.peer_id_addr);
|
||||
|
||||
/* Return BLE_GAP_REPEAT_PAIRING_RETRY to indicate that the host should
|
||||
* continue with the pairing operation.
|
||||
*/
|
||||
return BLE_GAP_REPEAT_PAIRING_RETRY;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void on_sync(void)
|
||||
{
|
||||
int err;
|
||||
ble_addr_t addr;
|
||||
|
||||
/* Use NRPA */
|
||||
err = ble_hs_id_gen_rnd(1, &addr);
|
||||
assert(err == 0);
|
||||
err = ble_hs_id_set_rnd(addr.val);
|
||||
assert(err == 0);
|
||||
|
||||
printk("Bluetooth initialized\n");
|
||||
|
||||
err = mesh_init();
|
||||
err = mesh_init(addr.type);
|
||||
if (err) {
|
||||
printk("Initializing mesh failed (err %d)\n", err);
|
||||
return;
|
||||
@@ -184,29 +293,20 @@ static void bt_ready(int err)
|
||||
|
||||
printk("Mesh initialized\n");
|
||||
|
||||
bt_conn_cb_register(&conn_cb);
|
||||
bt_conn_auth_cb_register(&auth_cb);
|
||||
|
||||
bt_gatt_service_register(&name_svc);
|
||||
|
||||
if (IS_ENABLED(CONFIG_SETTINGS)) {
|
||||
settings_load();
|
||||
}
|
||||
|
||||
if (reset_mesh) {
|
||||
bt_mesh_reset();
|
||||
reset_mesh = false;
|
||||
}
|
||||
|
||||
if (!mesh_is_initialized()) {
|
||||
/* Start advertising */
|
||||
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;
|
||||
}
|
||||
advertise();
|
||||
} else {
|
||||
const char *name = bt_get_name();
|
||||
|
||||
printk("Already provisioned\n");
|
||||
|
||||
mesh_set_name(name, first_name_len(name));
|
||||
ble_svc_gap_device_name_set(bt_get_name());
|
||||
}
|
||||
|
||||
board_refresh_display();
|
||||
@@ -214,22 +314,80 @@ static void bt_ready(int err)
|
||||
printk("Board started\n");
|
||||
}
|
||||
|
||||
void main(void)
|
||||
void schedule_mesh_reset(void)
|
||||
{
|
||||
reset_mesh = true;
|
||||
}
|
||||
|
||||
static void on_reset(int reason)
|
||||
{
|
||||
MODLOG_DFLT(ERROR, "Resetting state; reason=%d\n", reason);
|
||||
}
|
||||
|
||||
const char *bt_get_name(void)
|
||||
{
|
||||
char buf[MESH_BADGE_NAME_ENCODE_SIZE];
|
||||
int rc, len;
|
||||
|
||||
rc = conf_get_stored_value("mesh_badge/badge_name",
|
||||
buf, sizeof(buf));
|
||||
if (rc == OS_ENOENT) {
|
||||
bt_set_name(MYNEWT_VAL(BLE_SVC_GAP_DEVICE_NAME));
|
||||
} else {
|
||||
assert(rc == 0);
|
||||
}
|
||||
|
||||
memset(badge_name, '\0', sizeof(badge_name));
|
||||
len = base64_decode(buf, badge_name);
|
||||
if (len < 0) {
|
||||
bt_set_name(MYNEWT_VAL(BLE_SVC_GAP_DEVICE_NAME));
|
||||
}
|
||||
|
||||
return badge_name;
|
||||
}
|
||||
|
||||
int bt_set_name(const char *name)
|
||||
{
|
||||
char buf[MESH_BADGE_NAME_ENCODE_SIZE];
|
||||
int rc;
|
||||
|
||||
memset(badge_name, '\0', sizeof(badge_name));
|
||||
memcpy(badge_name, name, strlen(name));
|
||||
base64_encode(badge_name, sizeof(badge_name), buf, 1);
|
||||
rc = conf_save_one("mesh_badge/badge_name", buf);
|
||||
assert(rc == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Initialize OS */
|
||||
sysinit();
|
||||
|
||||
err = board_init();
|
||||
if (err) {
|
||||
printk("board init failed (err %d)\n", err);
|
||||
return;
|
||||
assert(err == 0);
|
||||
}
|
||||
|
||||
printk("Starting Board Demo\n");
|
||||
/* Initialize the NimBLE host configuration. */
|
||||
ble_hs_cfg.reset_cb = on_reset;
|
||||
ble_hs_cfg.sync_cb = on_sync;
|
||||
ble_hs_cfg.gatts_register_cb = gatt_svr_register_cb;
|
||||
ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
|
||||
ble_hs_cfg.sm_io_cap = BLE_SM_IO_CAP_DISP_ONLY;
|
||||
|
||||
/* Initialize the Bluetooth Subsystem */
|
||||
err = bt_enable(bt_ready);
|
||||
if (err) {
|
||||
printk("Bluetooth init failed (err %d)\n", err);
|
||||
return;
|
||||
err = gatt_svr_init();
|
||||
assert(err == 0);
|
||||
|
||||
/*
|
||||
* As the last thing, process events from default event queue.
|
||||
*/
|
||||
while (1) {
|
||||
os_eventq_run(os_eventq_dflt_get());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
+115
-42
@@ -4,29 +4,28 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <string.h>
|
||||
#include <misc/printk.h>
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/mesh.h>
|
||||
#include <bluetooth/hci.h>
|
||||
#include "console/console.h"
|
||||
#include "mesh/mesh.h"
|
||||
|
||||
#include "mesh_badge.h"
|
||||
#include "mesh.h"
|
||||
#include "board.h"
|
||||
|
||||
#define MOD_LF 0x0000
|
||||
#define OP_LF 0xbb
|
||||
#define OP_VENDOR_MSG BT_MESH_MODEL_OP_3(OP_LF, BT_COMP_ID_LF)
|
||||
#define BT_COMP_ID_LF 0x05f1
|
||||
|
||||
#define DEFAULT_TTL 7
|
||||
#define GROUP_ADDR 0xc123
|
||||
#define NET_IDX 0x000
|
||||
#define APP_IDX 0x000
|
||||
#define FLAGS 0
|
||||
#define MOD_LF 0x0000
|
||||
#define OP_HELLO 0xbb
|
||||
#define OP_HEARTBEAT 0xbc
|
||||
#define OP_VND_HELLO BT_MESH_MODEL_OP_3(OP_HELLO, BT_COMP_ID_LF)
|
||||
#define OP_VND_HEARTBEAT BT_MESH_MODEL_OP_3(OP_HEARTBEAT, BT_COMP_ID_LF)
|
||||
|
||||
static struct k_work publish_work;
|
||||
static struct k_work mesh_start_work;
|
||||
#define DEFAULT_TTL 31
|
||||
#define GROUP_ADDR 0xc123
|
||||
#define NET_IDX 0x000
|
||||
#define APP_IDX 0x000
|
||||
#define FLAGS 0
|
||||
static struct ble_npl_callout hello_work;
|
||||
static struct ble_npl_callout mesh_start_work;
|
||||
|
||||
static void heartbeat(u8_t hops, u16_t feat)
|
||||
{
|
||||
@@ -67,7 +66,8 @@ static struct bt_mesh_health_srv health_srv = {
|
||||
.cb = &health_srv_cb,
|
||||
};
|
||||
|
||||
BT_MESH_HEALTH_PUB_DEFINE(health_pub, 0);
|
||||
static struct os_mbuf *bt_mesh_pub_msg_health_pub;
|
||||
static struct bt_mesh_model_pub health_pub;
|
||||
|
||||
static struct bt_mesh_model root_models[] = {
|
||||
BT_MESH_MODEL_CFG_SRV(&cfg_srv),
|
||||
@@ -75,22 +75,26 @@ static struct bt_mesh_model root_models[] = {
|
||||
BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
|
||||
};
|
||||
|
||||
static void vnd_message(struct bt_mesh_model *model,
|
||||
static void vnd_hello(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct net_buf_simple *buf)
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
char str[32];
|
||||
size_t len;
|
||||
|
||||
printk("Vendor message from 0x%04x\n", ctx->addr);
|
||||
printk("Hello message from 0x%04x\n", ctx->addr);
|
||||
|
||||
if (ctx->addr == bt_mesh_model_elem(model)->addr) {
|
||||
printk("Ignoring message from self\n");
|
||||
return;
|
||||
}
|
||||
|
||||
len = min(buf->len, 8);
|
||||
memcpy(str, buf->data, len);
|
||||
len = min(buf->om_len, 8);
|
||||
memcpy(str, buf->om_data, len);
|
||||
str[len] = '\0';
|
||||
|
||||
board_add_hello(ctx->addr, str);
|
||||
|
||||
strcpy(str + len, " says hi!");
|
||||
|
||||
board_show_text(str, false, K_SECONDS(3));
|
||||
@@ -98,13 +102,46 @@ static void vnd_message(struct bt_mesh_model *model,
|
||||
board_blink_leds();
|
||||
}
|
||||
|
||||
static void vnd_heartbeat(struct bt_mesh_model *model,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
struct os_mbuf *buf)
|
||||
{
|
||||
u8_t init_ttl, hops;
|
||||
|
||||
/* Ignore messages from self */
|
||||
if (ctx->addr == bt_mesh_model_elem(model)->addr) {
|
||||
return;
|
||||
}
|
||||
|
||||
init_ttl = net_buf_simple_pull_u8(buf);
|
||||
hops = init_ttl - ctx->recv_ttl + 1;
|
||||
|
||||
printk("Heartbeat from 0x%04x over %u hop%s\n", ctx->addr,
|
||||
hops, hops == 1 ? "" : "s");
|
||||
|
||||
board_add_heartbeat(ctx->addr, hops);
|
||||
}
|
||||
|
||||
static const struct bt_mesh_model_op vnd_ops[] = {
|
||||
{ OP_VENDOR_MSG, 1, vnd_message },
|
||||
{ OP_VND_HELLO, 1, vnd_hello },
|
||||
{ OP_VND_HEARTBEAT, 1, vnd_heartbeat },
|
||||
BT_MESH_MODEL_OP_END,
|
||||
};
|
||||
|
||||
/* Limit the payload to 11 bytes so that it doesn't get segmented */
|
||||
BT_MESH_MODEL_PUB_DEFINE(vnd_pub, NULL, 3 + 8);
|
||||
static int pub_update(struct bt_mesh_model *mod)
|
||||
{
|
||||
struct os_mbuf *msg = mod->pub->msg;
|
||||
|
||||
printk("Preparing to send heartbeat\n");
|
||||
|
||||
bt_mesh_model_msg_init(msg, OP_VND_HEARTBEAT);
|
||||
net_buf_simple_add_u8(msg, DEFAULT_TTL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct os_mbuf *bt_mesh_pub_msg_vnd_pub;
|
||||
static struct bt_mesh_model_pub vnd_pub;
|
||||
|
||||
static struct bt_mesh_model vnd_models[] = {
|
||||
BT_MESH_MODEL_VND(BT_COMP_ID_LF, MOD_LF, vnd_ops, &vnd_pub, NULL),
|
||||
@@ -120,19 +157,49 @@ static const struct bt_mesh_comp comp = {
|
||||
.elem_count = ARRAY_SIZE(elements),
|
||||
};
|
||||
|
||||
static void publish_message(struct k_work *work)
|
||||
static size_t first_name_len(const char *name)
|
||||
{
|
||||
if (bt_mesh_model_publish(&vnd_models[0]) == 0) {
|
||||
size_t len;
|
||||
|
||||
for (len = 0; *name; name++, len++) {
|
||||
switch (*name) {
|
||||
case ' ':
|
||||
case ',':
|
||||
case '\n':
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static void send_hello(struct ble_npl_event *work)
|
||||
{
|
||||
struct os_mbuf *msg = NET_BUF_SIMPLE(3 + 8 + 4);
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.net_idx = NET_IDX,
|
||||
.app_idx = APP_IDX,
|
||||
.addr = GROUP_ADDR,
|
||||
.send_ttl = DEFAULT_TTL,
|
||||
};
|
||||
const char *name = bt_get_name();
|
||||
|
||||
bt_mesh_model_msg_init(msg, OP_VND_HELLO);
|
||||
net_buf_simple_add_mem(msg, name, first_name_len(name));
|
||||
|
||||
if (bt_mesh_model_send(&vnd_models[0], &ctx, msg, NULL, NULL) == 0) {
|
||||
board_show_text("Saying \"hi!\" to everyone", false,
|
||||
K_SECONDS(2));
|
||||
} else {
|
||||
board_show_text("Sending Failed!", false, K_SECONDS(2));
|
||||
}
|
||||
|
||||
os_mbuf_free_chain(msg);
|
||||
}
|
||||
|
||||
void mesh_publish(void)
|
||||
void mesh_send_hello(void)
|
||||
{
|
||||
k_work_submit(&publish_work);
|
||||
k_work_submit(&hello_work);
|
||||
}
|
||||
|
||||
static int provision_and_configure(void)
|
||||
@@ -150,6 +217,7 @@ static int provision_and_configure(void)
|
||||
.addr = GROUP_ADDR,
|
||||
.app_idx = APP_IDX,
|
||||
.ttl = DEFAULT_TTL,
|
||||
.period = BT_MESH_PUB_PERIOD_SEC(10),
|
||||
};
|
||||
u8_t dev_key[16];
|
||||
u16_t addr;
|
||||
@@ -201,7 +269,7 @@ static int provision_and_configure(void)
|
||||
return addr;
|
||||
}
|
||||
|
||||
static void start_mesh(struct k_work *work)
|
||||
static void start_mesh(struct ble_npl_event *work)
|
||||
{
|
||||
int err;
|
||||
|
||||
@@ -223,27 +291,32 @@ void mesh_start(void)
|
||||
k_work_submit(&mesh_start_work);
|
||||
}
|
||||
|
||||
void mesh_set_name(const char *name, size_t len)
|
||||
{
|
||||
bt_mesh_model_msg_init(vnd_pub.msg, OP_VENDOR_MSG);
|
||||
len = min(len, net_buf_simple_tailroom(vnd_pub.msg));
|
||||
net_buf_simple_add_mem(vnd_pub.msg, name, len);
|
||||
}
|
||||
|
||||
bool mesh_is_initialized(void)
|
||||
{
|
||||
return elements[0].addr != BT_MESH_ADDR_UNASSIGNED;
|
||||
return bt_mesh_is_provisioned();
|
||||
}
|
||||
|
||||
int mesh_init(void)
|
||||
u16_t mesh_get_addr(void)
|
||||
{
|
||||
return elements[0].addr;
|
||||
}
|
||||
|
||||
int mesh_init(u8_t addr_type)
|
||||
{
|
||||
static const u8_t dev_uuid[16] = { 0xc0, 0xff, 0xee };
|
||||
static const struct bt_mesh_prov prov = {
|
||||
.uuid = dev_uuid,
|
||||
};
|
||||
|
||||
k_work_init(&publish_work, publish_message);
|
||||
bt_mesh_pub_msg_health_pub = NET_BUF_SIMPLE(0);
|
||||
health_pub.msg = bt_mesh_pub_msg_health_pub;
|
||||
|
||||
bt_mesh_pub_msg_vnd_pub = NET_BUF_SIMPLE(3 + 1);
|
||||
vnd_pub.msg = bt_mesh_pub_msg_vnd_pub;
|
||||
vnd_pub.update = pub_update;
|
||||
|
||||
k_work_init(&hello_work, send_hello);
|
||||
k_work_init(&mesh_start_work, start_mesh);
|
||||
|
||||
return bt_mesh_init(&prov, &comp);
|
||||
return bt_mesh_init(addr_type, &prov, &comp);
|
||||
}
|
||||
|
||||
@@ -4,9 +4,11 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
void mesh_publish(void);
|
||||
void mesh_set_name(const char *name, size_t len);
|
||||
#include "mesh/mesh.h"
|
||||
|
||||
void mesh_send_hello(void);
|
||||
|
||||
u16_t mesh_get_addr(void);
|
||||
bool mesh_is_initialized(void);
|
||||
void mesh_start(void);
|
||||
int mesh_init(void);
|
||||
int mesh_init(u8_t addr_type);
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
struct ble_gatt_register_ctxt;
|
||||
|
||||
void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg);
|
||||
int gatt_svr_init(void);
|
||||
|
||||
void schedule_mesh_reset(void);
|
||||
const char *bt_get_name(void);
|
||||
int bt_set_name(const char *);
|
||||
|
||||
@@ -5,20 +5,39 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <device.h>
|
||||
#include <gpio.h>
|
||||
#include <display/cfb.h>
|
||||
#include <misc/printk.h>
|
||||
#include <flash.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include "os/mynewt.h"
|
||||
#include "bsp/bsp.h"
|
||||
#include "console/console.h"
|
||||
#include "hal/hal_flash.h"
|
||||
#include "hal/hal_gpio.h"
|
||||
#include "mesh/glue.h"
|
||||
#include "services/gap/ble_svc_gap.h"
|
||||
|
||||
#include "mesh_badge.h"
|
||||
#include "display/cfb.h"
|
||||
#include "mesh.h"
|
||||
#include "board.h"
|
||||
|
||||
#define printk console_printf
|
||||
|
||||
enum font_size {
|
||||
FONT_BIG = 0,
|
||||
FONT_MEDIUM = 1,
|
||||
FONT_SMALL = 2,
|
||||
};
|
||||
|
||||
struct font_info {
|
||||
u8_t columns;
|
||||
} fonts[] = {
|
||||
[FONT_BIG] = { .columns = 12 },
|
||||
[FONT_MEDIUM] = { .columns = 16 },
|
||||
[FONT_SMALL] = { .columns = 25 },
|
||||
};
|
||||
|
||||
#define LONG_PRESS_TIMEOUT K_SECONDS(1)
|
||||
|
||||
#define STAT_COUNT 128
|
||||
|
||||
#define EDGE (GPIO_INT_EDGE | GPIO_INT_DOUBLE_EDGE)
|
||||
|
||||
#ifdef SW0_GPIO_FLAGS
|
||||
@@ -27,43 +46,43 @@
|
||||
#define PULL_UP 0
|
||||
#endif
|
||||
|
||||
#define LINE_MAX 12
|
||||
|
||||
static struct device *epd_dev;
|
||||
static struct os_dev *epd_dev;
|
||||
static bool pressed;
|
||||
static struct device *gpio;
|
||||
static bool stats_view;
|
||||
static struct k_delayed_work epd_work;
|
||||
static struct k_delayed_work long_press_work;
|
||||
|
||||
static struct {
|
||||
struct device *dev;
|
||||
const char *name;
|
||||
u32_t pin;
|
||||
int pin;
|
||||
} leds[] = {
|
||||
{ .name = LED0_GPIO_CONTROLLER, .pin = LED0_GPIO_PIN, },
|
||||
{ .name = LED1_GPIO_CONTROLLER, .pin = LED1_GPIO_PIN, },
|
||||
{ .name = LED2_GPIO_CONTROLLER, .pin = LED2_GPIO_PIN, },
|
||||
{ .name = LED3_GPIO_CONTROLLER, .pin = LED3_GPIO_PIN, },
|
||||
{ .pin = LED_1, },
|
||||
{ .pin = RGB_LED_RED, },
|
||||
{ .pin = RGB_LED_GRN, },
|
||||
{ .pin = RGB_LED_BLU, },
|
||||
};
|
||||
|
||||
struct k_delayed_work led_timer;
|
||||
|
||||
static size_t print_line(int row, const char *text, size_t len, bool center)
|
||||
static size_t print_line(enum font_size font_size, int row, const char *text,
|
||||
size_t len, bool center)
|
||||
{
|
||||
u8_t font_height, font_width;
|
||||
u8_t line[LINE_MAX + 1];
|
||||
char line[fonts[FONT_SMALL].columns + 1];
|
||||
int pad;
|
||||
|
||||
len = min(len, LINE_MAX);
|
||||
cfb_framebuffer_set_font(epd_dev, font_size);
|
||||
|
||||
len = min(len, fonts[font_size].columns);
|
||||
memcpy(line, text, len);
|
||||
line[len] = '\0';
|
||||
|
||||
if (center) {
|
||||
pad = (LINE_MAX - len) / 2;
|
||||
pad = (fonts[font_size].columns - len) / 2;
|
||||
} else {
|
||||
pad = 0;
|
||||
}
|
||||
|
||||
cfb_get_font_size(epd_dev, 0, &font_width, &font_height);
|
||||
cfb_get_font_size(epd_dev, font_size, &font_width, &font_height);
|
||||
|
||||
if (cfb_print(epd_dev, line, font_width * pad, font_height * row)) {
|
||||
printk("Failed to print a string\n");
|
||||
@@ -72,12 +91,12 @@ static size_t print_line(int row, const char *text, size_t len, bool center)
|
||||
return len;
|
||||
}
|
||||
|
||||
static size_t get_len(const char *text)
|
||||
static size_t get_len(enum font_size font, const char *text)
|
||||
{
|
||||
const char *space = NULL;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i <= LINE_MAX; i++) {
|
||||
for (i = 0; i <= fonts[font].columns; i++) {
|
||||
switch (text[i]) {
|
||||
case '\n':
|
||||
case '\0':
|
||||
@@ -97,7 +116,7 @@ static size_t get_len(const char *text)
|
||||
return space - text;
|
||||
}
|
||||
|
||||
return LINE_MAX;
|
||||
return fonts[font].columns;
|
||||
}
|
||||
|
||||
void board_blink_leds(void)
|
||||
@@ -109,7 +128,6 @@ void board_show_text(const char *text, bool center, s32_t duration)
|
||||
{
|
||||
int i;
|
||||
|
||||
cfb_framebuffer_set_font(epd_dev, 0);
|
||||
cfb_framebuffer_clear(epd_dev, false);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
@@ -119,12 +137,12 @@ void board_show_text(const char *text, bool center, s32_t duration)
|
||||
text++;
|
||||
}
|
||||
|
||||
len = get_len(text);
|
||||
len = get_len(FONT_BIG, text);
|
||||
if (!len) {
|
||||
break;
|
||||
}
|
||||
|
||||
text += print_line(i, text, len, center);
|
||||
text += print_line(FONT_BIG, i, text, len, center);
|
||||
if (!*text) {
|
||||
break;
|
||||
}
|
||||
@@ -137,11 +155,191 @@ void board_show_text(const char *text, bool center, s32_t duration)
|
||||
}
|
||||
}
|
||||
|
||||
static void epd_update(struct k_work *work)
|
||||
static struct stat {
|
||||
u16_t addr;
|
||||
char name[9];
|
||||
u8_t min_hops;
|
||||
u8_t max_hops;
|
||||
u16_t hello_count;
|
||||
u16_t heartbeat_count;
|
||||
} stats[STAT_COUNT] = {
|
||||
[0 ... (STAT_COUNT - 1)] = {
|
||||
.min_hops = BT_MESH_TTL_MAX,
|
||||
.max_hops = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static u32_t stat_count;
|
||||
|
||||
#define NO_UPDATE -1
|
||||
|
||||
static int add_hello(u16_t addr, const char *name)
|
||||
{
|
||||
char buf[CONFIG_BT_DEVICE_NAME_MAX];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(stats); i++) {
|
||||
struct stat *stat = &stats[i];
|
||||
|
||||
if (!stat->addr) {
|
||||
stat->addr = addr;
|
||||
strncpy(stat->name, name, sizeof(stat->name) - 1);
|
||||
stat->hello_count = 1;
|
||||
stat_count++;
|
||||
return i;
|
||||
}
|
||||
|
||||
if (stat->addr == addr) {
|
||||
/* Update name, incase it has changed */
|
||||
strncpy(stat->name, name, sizeof(stat->name) - 1);
|
||||
|
||||
if (stat->hello_count < 0xffff) {
|
||||
stat->hello_count++;
|
||||
return i;
|
||||
}
|
||||
|
||||
return NO_UPDATE;
|
||||
}
|
||||
}
|
||||
|
||||
return NO_UPDATE;
|
||||
}
|
||||
|
||||
static int add_heartbeat(u16_t addr, u8_t hops)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(stats); i++) {
|
||||
struct stat *stat = &stats[i];
|
||||
|
||||
if (!stat->addr) {
|
||||
stat->addr = addr;
|
||||
stat->heartbeat_count = 1;
|
||||
stat->min_hops = hops;
|
||||
stat->max_hops = hops;
|
||||
stat_count++;
|
||||
return i;
|
||||
}
|
||||
|
||||
if (stat->addr == addr) {
|
||||
if (hops < stat->min_hops) {
|
||||
stat->min_hops = hops;
|
||||
} else if (hops > stat->max_hops) {
|
||||
stat->max_hops = hops;
|
||||
}
|
||||
|
||||
if (stat->heartbeat_count < 0xffff) {
|
||||
stat->heartbeat_count++;
|
||||
return i;
|
||||
}
|
||||
|
||||
return NO_UPDATE;
|
||||
}
|
||||
}
|
||||
|
||||
return NO_UPDATE;
|
||||
}
|
||||
|
||||
void board_add_hello(u16_t addr, const char *name)
|
||||
{
|
||||
u32_t sort_i;
|
||||
|
||||
sort_i = add_hello(addr, name);
|
||||
if (sort_i != NO_UPDATE) {
|
||||
}
|
||||
}
|
||||
|
||||
void board_add_heartbeat(u16_t addr, u8_t hops)
|
||||
{
|
||||
u32_t sort_i;
|
||||
|
||||
sort_i = add_heartbeat(addr, hops);
|
||||
if (sort_i != NO_UPDATE) {
|
||||
}
|
||||
}
|
||||
|
||||
static void show_statistics(void)
|
||||
{
|
||||
int top[4] = { -1, -1, -1, -1 };
|
||||
int len, i, line = 0;
|
||||
struct stat *stat;
|
||||
char str[32];
|
||||
|
||||
cfb_framebuffer_clear(epd_dev, false);
|
||||
|
||||
len = snprintk(str, sizeof(str),
|
||||
"Own Address: 0x%04x", mesh_get_addr());
|
||||
print_line(FONT_SMALL, line++, str, len, false);
|
||||
|
||||
len = snprintk(str, sizeof(str),
|
||||
"Node Count: %lu", stat_count + 1);
|
||||
print_line(FONT_SMALL, line++, str, len, false);
|
||||
|
||||
/* Find the top sender */
|
||||
for (i = 0; i < ARRAY_SIZE(stats); i++) {
|
||||
int j;
|
||||
|
||||
stat = &stats[i];
|
||||
if (!stat->addr) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!stat->hello_count) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (j = 0; j < ARRAY_SIZE(top); j++) {
|
||||
if (top[j] < 0) {
|
||||
top[j] = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (stat->hello_count <= stats[top[j]].hello_count) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Move other elements down the list */
|
||||
if (j < ARRAY_SIZE(top) - 1) {
|
||||
memmove(&top[j + 1], &top[j],
|
||||
((ARRAY_SIZE(top) - j - 1) *
|
||||
sizeof(top[j])));
|
||||
}
|
||||
|
||||
top[j] = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (stat_count >= 0) {
|
||||
len = snprintk(str, sizeof(str), "Most messages from:");
|
||||
print_line(FONT_SMALL, line++, str, len, false);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(top); i++) {
|
||||
if (top[i] < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
stat = &stats[top[i]];
|
||||
|
||||
len = snprintk(str, sizeof(str), "%-3u 0x%04x %s",
|
||||
stat->hello_count, stat->addr,
|
||||
stat->name);
|
||||
print_line(FONT_SMALL, line++, str, len, false);
|
||||
}
|
||||
}
|
||||
|
||||
cfb_framebuffer_finalize(epd_dev);
|
||||
}
|
||||
|
||||
static void epd_update(struct ble_npl_event *work)
|
||||
{
|
||||
char buf[MYNEWT_VAL(BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH)];
|
||||
int i;
|
||||
|
||||
if (stats_view) {
|
||||
show_statistics();
|
||||
return;
|
||||
}
|
||||
|
||||
strncpy(buf, bt_get_name(), sizeof(buf));
|
||||
|
||||
/* Convert commas to newlines */
|
||||
@@ -154,18 +352,27 @@ static void epd_update(struct k_work *work)
|
||||
board_show_text(buf, true, K_FOREVER);
|
||||
}
|
||||
|
||||
static void long_press(struct ble_npl_event *work)
|
||||
{
|
||||
/* Treat as release so actual release doesn't send messages */
|
||||
pressed = false;
|
||||
stats_view = !stats_view;
|
||||
board_refresh_display();
|
||||
}
|
||||
|
||||
static bool button_is_pressed(void)
|
||||
{
|
||||
u32_t val;
|
||||
|
||||
gpio_pin_read(gpio, SW0_GPIO_PIN, &val);
|
||||
val = (uint32_t) hal_gpio_read(BUTTON_1);
|
||||
|
||||
return !val;
|
||||
}
|
||||
|
||||
static void button_interrupt(struct device *dev, struct gpio_callback *cb,
|
||||
u32_t pins)
|
||||
static void button_interrupt(struct os_event *ev)
|
||||
{
|
||||
int pin_pos = (int ) ev->ev_arg;
|
||||
|
||||
if (button_is_pressed() == pressed) {
|
||||
return;
|
||||
}
|
||||
@@ -173,48 +380,55 @@ static void button_interrupt(struct device *dev, struct gpio_callback *cb,
|
||||
pressed = !pressed;
|
||||
printk("Button %s\n", pressed ? "pressed" : "released");
|
||||
|
||||
/* We only care about button release for now */
|
||||
if (pressed) {
|
||||
k_delayed_work_submit(&long_press_work, LONG_PRESS_TIMEOUT);
|
||||
return;
|
||||
}
|
||||
|
||||
k_delayed_work_cancel(&long_press_work);
|
||||
|
||||
if (!mesh_is_initialized()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pins & BIT(SW0_GPIO_PIN)) {
|
||||
mesh_publish();
|
||||
/* Short press does currently nothing in statistics view */
|
||||
if (stats_view) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pin_pos == BUTTON_1) {
|
||||
mesh_send_hello();
|
||||
}
|
||||
}
|
||||
|
||||
static struct os_event button_event;
|
||||
|
||||
static void
|
||||
gpio_irq_handler(void *arg)
|
||||
{
|
||||
button_event.ev_arg = arg;
|
||||
os_eventq_put(os_eventq_dflt_get(), &button_event);
|
||||
}
|
||||
|
||||
static int configure_button(void)
|
||||
{
|
||||
static struct gpio_callback button_cb;
|
||||
button_event.ev_cb = button_interrupt;
|
||||
|
||||
gpio = device_get_binding(GPIO_KEYS_BUTTON_0_GPIO_CONTROLLER);
|
||||
if (!gpio) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
gpio_pin_configure(gpio, SW0_GPIO_PIN,
|
||||
(GPIO_DIR_IN | GPIO_INT | PULL_UP | EDGE));
|
||||
|
||||
gpio_init_callback(&button_cb, button_interrupt, BIT(SW0_GPIO_PIN));
|
||||
gpio_add_callback(gpio, &button_cb);
|
||||
|
||||
gpio_pin_enable_callback(gpio, SW0_GPIO_PIN);
|
||||
hal_gpio_irq_init(BUTTON_1, gpio_irq_handler, (void *) BUTTON_1,
|
||||
HAL_GPIO_TRIG_BOTH, HAL_GPIO_PULL_UP);
|
||||
hal_gpio_irq_enable(BUTTON_1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void led_timeout(struct k_work *work)
|
||||
static void led_timeout(struct ble_npl_event *work)
|
||||
{
|
||||
static int led_cntr;
|
||||
int i;
|
||||
|
||||
/* Disable all LEDs */
|
||||
for (i = 0; i < ARRAY_SIZE(leds); i++) {
|
||||
gpio_pin_write(leds[i].dev, leds[i].pin, 1);
|
||||
hal_gpio_write(leds[i].pin, 1);
|
||||
}
|
||||
|
||||
/* Stop after 5 iterations */
|
||||
@@ -225,7 +439,7 @@ static void led_timeout(struct k_work *work)
|
||||
|
||||
/* Select and enable current LED */
|
||||
i = led_cntr++ % ARRAY_SIZE(leds);
|
||||
gpio_pin_write(leds[i].dev, leds[i].pin, 0);
|
||||
hal_gpio_write(leds[i].pin, 0);
|
||||
|
||||
k_delayed_work_submit(&led_timer, K_MSEC(100));
|
||||
}
|
||||
@@ -235,15 +449,7 @@ static int configure_leds(void)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(leds); i++) {
|
||||
leds[i].dev = device_get_binding(leds[i].name);
|
||||
if (!leds[i].dev) {
|
||||
printk("Failed to get %s device\n", leds[i].name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
gpio_pin_configure(leds[i].dev, leds[i].pin, GPIO_DIR_OUT);
|
||||
gpio_pin_write(leds[i].dev, leds[i].pin, 1);
|
||||
|
||||
hal_gpio_init_out(leds[i].pin, 1);
|
||||
}
|
||||
|
||||
k_delayed_work_init(&led_timer, led_timeout);
|
||||
@@ -252,12 +458,10 @@ static int configure_leds(void)
|
||||
|
||||
static int erase_storage(void)
|
||||
{
|
||||
struct device *dev;
|
||||
|
||||
dev = device_get_binding(FLASH_DEV_NAME);
|
||||
|
||||
return flash_erase(dev, FLASH_AREA_STORAGE_OFFSET,
|
||||
FLASH_AREA_STORAGE_SIZE);
|
||||
bt_set_name(MYNEWT_VAL(BLE_SVC_GAP_DEVICE_NAME));
|
||||
ble_store_clear();
|
||||
schedule_mesh_reset();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void board_refresh_display(void)
|
||||
@@ -267,7 +471,7 @@ void board_refresh_display(void)
|
||||
|
||||
int board_init(void)
|
||||
{
|
||||
epd_dev = device_get_binding(CONFIG_SSD1673_DEV_NAME);
|
||||
epd_dev = os_dev_lookup(MYNEWT_VAL(SSD1673_OS_DEV_NAME));
|
||||
if (epd_dev == NULL) {
|
||||
printk("SSD1673 device not found\n");
|
||||
return -ENODEV;
|
||||
@@ -291,6 +495,7 @@ int board_init(void)
|
||||
}
|
||||
|
||||
k_delayed_work_init(&epd_work, epd_update);
|
||||
k_delayed_work_init(&long_press_work, long_press);
|
||||
|
||||
pressed = button_is_pressed();
|
||||
if (pressed) {
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
# 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.
|
||||
#
|
||||
|
||||
# Package: apps/mesh_badge
|
||||
|
||||
syscfg.vals:
|
||||
# Enable the shell task.
|
||||
SHELL_TASK: 1
|
||||
|
||||
# Set log level to info (disable debug logging).
|
||||
LOG_LEVEL: 1
|
||||
|
||||
# Default task settings
|
||||
OS_MAIN_STACK_SIZE: 768
|
||||
|
||||
# Newtmgr is not supported in this app, so disable newtmgr-over-shell.
|
||||
SHELL_NEWTMGR: 0
|
||||
|
||||
REEL_BOARD_ENABLE_ACTIVE_MODE: 1
|
||||
SPI_0_MASTER: 1
|
||||
|
||||
BLE_MESH: 1
|
||||
MSYS_1_BLOCK_COUNT: 48
|
||||
|
||||
BLE_SVC_GAP_DEVICE_NAME: '"reel board"'
|
||||
|
||||
BLE_SM_SC: 1
|
||||
BLE_SM_BONDING: 1
|
||||
BLE_MESH_RELAY: 1
|
||||
BLE_MESH_GATT_PROXY: 0
|
||||
BLE_MESH_PB_ADV: 0
|
||||
BLE_MESH_PB_GATT: 0
|
||||
BLE_MESH_ADV_BUF_COUNT: 30
|
||||
BLE_MESH_LABEL_COUNT: 0
|
||||
BLE_MESH_CFG_CLI: 1
|
||||
BLE_MESH_TX_SEG_MAX: 6
|
||||
BLE_MESH_TX_SEG_MSG_COUNT: 3
|
||||
BLE_MESH_RX_SEG_MSG_COUNT: 3
|
||||
BLE_MESH_CRPL: 128
|
||||
BLE_MESH_RPL_STORE_TIMEOUT: 120
|
||||
BLE_MESH_SETTINGS: 1
|
||||
CONFIG_NFFS: 1
|
||||
Reference in New Issue
Block a user