This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] CC2652R:蓝牙网状网络配置和消息发送:连接问题

Guru**** 2392095 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/1200980/cc2652r-bluetooth-mesh-provisioning-and-message-sending-connection-problem

器件型号:CC2652R

您好!

我正在使用简单的网状节点示例、我想实现一项配置器件并在不使用 UART 接口的情况下实现器件之间通信的任务。 回调函数除外、但当我尝试通过按下按钮来打开另一个设备的 LED 时、它会切换自己的 LED、 因此、我正在使用的两个器件之间没有通信、并且每个器件都在不同的网络上、这两个器件无法检测到异常。 使用 BLE 扫描仪可以检测到设备。  我还遵循了 BLE 网状网络基础教程、以便创建我自己的模型。 要启用设备之间的识别,缺少什么? 我已在两款器件上启用静态配置、就像在原始简单网状节点示例中一样。

此致、

Alexandra  

/******************************************************************************

@file  static_prov.c

@brief This file contains static provisioning configurations and performance.

Group: WCS, BTS
Target Device: cc13xx_cc26xx

******************************************************************************

 Copyright (c) 2013-2022, Texas Instruments Incorporated
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions
 are met:

 *  Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.

 *  Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.

 *  Neither the name of Texas Instruments Incorporated nor the names of
    its contributors may be used to endorse or promote products derived
    from this software without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

******************************************************************************


*****************************************************************************/

#ifdef USE_STATIC_PROVISIONING
/*********************************************************************
* INCLUDES
*/

#include "static_prov.h"
#include "mesh_erpc_wrapper.h"
#include "ti_device_composition.h"
#include <zephyr.h>
#include <sys/printk.h>
#include <settings/settings.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/mesh.h>

/*********************************************************************
 * MACROS
 */
#define MOD_LF 0x0000
#define GROUP_ADDR 0xc000

/*********************************************************************
* CONSTANTS
*/

/*********************************************************************
* TYPEDEFS
*/

/*********************************************************************
* GLOBAL VARIABLES
*/

/*********************************************************************
* LOCAL VARIABLES
*/
static const uint16_t net_idx;
static const uint32_t iv_index;
static uint8_t prov_flags = 0;
static const uint8_t net_key[16] = {
    0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
    0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
};
static const uint8_t dev_key[16] = {
    0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
    0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
};
static const uint8_t app_key[16] = {
    0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
    0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
};

/*********************************************************************
 * LOCAL FUNCTIONS
 */
static void MeshApp_provConfigure(uint16_t addr, uint16_t app_idx);

/*********************************************************************
 * EXTERN FUNCTIONS
*/

/*********************************************************************
 * PUBLIC FUNCTIONS
 */

/*********************************************************************
 * @fn      MeshApp_static_provisioning
 *
 * @brief   Perform Static Provisioning by calling bt_mesh_provision
 *          and MeshApp_provConfigure
 *
 * @param   addr
 * @param   app_idx
 */
int MeshApp_static_provisioning(uint16_t addr, uint16_t app_idx)
{
    int status;
    status = bt_mesh_provision(net_key, net_idx, prov_flags, iv_index, addr, dev_key);
    if (status)
    {
        return status;
    }

    MeshApp_provConfigure(addr, app_idx);

  return status;
}

/*********************************************************************
 * @fn      MeshApp_provConfigure
 *
 * @brief   Configure the Mesh Node
 *
 * @param   addr
 * @param   app_idx
 */
static void MeshApp_provConfigure(uint16_t addr, uint16_t app_idx)
{
  /* Add Application Key */
  bt_mesh_cfg_app_key_add_wrapper(net_idx, addr, net_idx, app_idx, app_key);

  /* Bind to vendor model */
  bt_mesh_cfg_mod_app_bind_vnd_wrapper(net_idx, addr, addr, app_idx,
                               MOD_LF, CONFIG_BT_COMPANY_ID);

  /* Bind to Health model */
  bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx,
                           BT_MESH_MODEL_ID_HEALTH_SRV);

  /* Bind to Generic OnOff server model */
  bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx,
                           BT_MESH_MODEL_ID_GEN_ONOFF_SRV);

  /* When using static provisioning, the loopback buffer is used
   * when the device sends messages.
   * The amount of the loopback buffers is determined by
   * CONFIG_BT_MESH_LOOPBACK_BUFS which is defined in autoconf.h.
   * Sleep is needed for the loopback buffers to be freed.
   */
  k_sleep(K_MSEC(100));

  /* Bind to vendor model

     bt_mesh_cfg_mod_app_bind_vnd Input Parameter Deep-dive

     net_idx: Pass in the network index
     addr: Address of the node
     elem_addr: Address of the element of the node. Here we refer to the second element, so we add 1.
     mod_app_idx: Application Key Index
     mod_id: Model ID. Here we set 0x1234 to match our Model ID in SysConfig.
     cid: Company ID
     status: Not needed
     */

     bt_mesh_cfg_mod_app_bind_vnd(net_idx, addr, addr+1, app_idx,
                                    0x1234, CONFIG_BT_COMPANY_ID, NULL);

  /* Bind to Generic OnOff client model */
  bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx,
                           BT_MESH_MODEL_ID_GEN_ONOFF_CLI);
  /* Bind to Generic Level server model */
  bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx,
                           BT_MESH_MODEL_ID_GEN_LEVEL_SRV);
  /* Bind to Generic Level client model */
  bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx,
                           BT_MESH_MODEL_ID_GEN_LEVEL_CLI);

  k_sleep(K_MSEC(100));

  /* Bind to Generic Transition Time server model */
  bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx,
                           BT_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_SRV);
  /* Bind to Generic Transition Time client model */
  bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx,
                           BT_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_CLI);
  /* Bind to Generic Power OnOff server model */
  bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx,
                           BT_MESH_MODEL_ID_GEN_POWER_ONOFF_SRV);

  k_sleep(K_MSEC(100));

  /* Bind to Generic Power OnOff client model */
  bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx,
                           BT_MESH_MODEL_ID_GEN_POWER_ONOFF_CLI);
  /* Bind to Generic Power OnOff Setup server model */
  bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx,
                           BT_MESH_MODEL_ID_GEN_POWER_ONOFF_SETUP_SRV);
  /* Bind to Generic Battery server model */
  bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx,
                           BT_MESH_MODEL_ID_GEN_BATTERY_SRV);

  k_sleep(K_MSEC(100));

  /* Bind to Generic Battery client model */
  bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx,
                           BT_MESH_MODEL_ID_GEN_BATTERY_CLI);
  /* Bind to Sensor server model */
  bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx,
                           BT_MESH_MODEL_ID_SENSOR_SRV);
  /* Bind to Sensor client model */
  bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx,
                           BT_MESH_MODEL_ID_SENSOR_CLI);

  k_sleep(K_MSEC(100));

  /* Bind to Sensor setup server model */
  bt_mesh_cfg_mod_app_bind_wrapper(net_idx, addr, addr, app_idx,
                           BT_MESH_MODEL_ID_SENSOR_SETUP_SRV);

  /* Add model subscription */
  bt_mesh_cfg_mod_sub_add_vnd_wrapper(net_idx, addr, addr, GROUP_ADDR,
                              MOD_LF, CONFIG_BT_COMPANY_ID);

  /* Add model subscription */
  bt_mesh_cfg_mod_sub_add_vnd(net_idx, addr, addr+1, GROUP_ADDR,
                              0x1234, CONFIG_BT_COMPANY_ID, NULL);
}

#endif // USE_STATIC_PROVISIONING

/******************************************************************************
 *
 *

@file  simple_mesh_node.c

@brief This file contains the simple_peripheral_and_mesh sample application for use
with the CC2652 Bluetooth Low Energy Protocol Stack.

Group: WCS, BTS
Target Device: cc13xx_cc26xx

******************************************************************************

 Copyright (c) 2013-2022, Texas Instruments Incorporated
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions
 are met:

 *  Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.

 *  Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.

 *  Neither the name of Texas Instruments Incorporated nor the names of
    its contributors may be used to endorse or promote products derived
    from this software without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

******************************************************************************


*****************************************************************************/

/*********************************************************************
* INCLUDES
*/
#include <string.h>

#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/knl/Event.h>
#include <ti/sysbios/knl/Queue.h>

#include <ti/display/Display.h>

#include "autoconf.h"

#define ADD_SENSOR_MODELS

#if !(defined __TI_COMPILER_VERSION__) && !(defined __GNUC__)
#include <intrinsics.h>
#endif

#include <ti/drivers/utils/List.h>

#include "util.h"
#include <bcomdef.h>
#include "ble_stack_api.h"

#include <devinfoservice.h>
#include <simple_gatt_profile.h>

#ifdef USE_RCOSC
#include <rcosc_calibration.h>
#endif //USE_RCOSC

#include <ti_drivers_config.h>
#include <board_key.h>

#include <menu/two_btn_menu.h>
#include "simple_mesh_node.h"
#include "simple_mesh_node_menu.h"
#include "ti_ble_config.h"
#include "ti_device_composition.h"
#if defined(OAD_SUPPORT)
#include "oad_app_support.h"
#endif
#include <zephyr.h>
#include <sys/printk.h>
#include <settings/settings.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/mesh.h>
#include <bt_le_porting_layer.h>

#ifdef USE_STATIC_PROVISIONING
#include "static_prov.h"
#endif

#include "generic_models.h"
#include "sensor_models.h"
#include "sensor_temperature8.h"

#include "mesh_erpc_wrapper.h"

/*********************************************************************
 * MACROS
 */

/*********************************************************************
* CONSTANTS
*/
// How often to perform periodic event (in ms)
#define BLEAPP_PERIODIC_EVT_PERIOD               2000


// Task configuration
#define BLEAPP_TASK_PRIORITY                     3

#ifndef BLEAPP_TASK_STACK_SIZE
#define BLEAPP_TASK_STACK_SIZE                   2248
#endif

// Application events
#define BLEAPP_EVT_CHAR_CHANGE         1
#define BLEAPP_EVT_KEY_CHANGE          2
#define BLEAPP_EVT_ADV                 3
#define BLEAPP_EVT_PAIRING_STATE       4
#define BLEAPP_EVT_PASSCODE_NEEDED     5
#define BLEAPP_EVT_PERIODIC            6
#define BLEAPP_EVT_READ_RPA            7
#define BLEAPP_EVT_SEND_PARAM_UPDATE   8
#define BLEAPP_EVT_CONN                9
#define BLEAPP_EVT_INSUFFICIENT_MEM    10
#define BLEAPP_EVT_ADV_REPORT          11
#define BLEAPP_EVT_SCAN_ENABLED        12
#define BLEAPP_EVT_SCAN_DISABLED       13
#define MESHAPP_EVT_ADV                14
#define MESHAPP_EVT_GATT_WRT           15
#define BLEAPP_EVT_STACK_CALLBACK      16
#define OADAPP_EVT_CALLBACK            17
#define OADAPP_EVT_RESET               18

// For storing the active connections
#define SP_RSSI_TRACK_CHNLS        1            // Max possible channels can be GAP_BONDINGS_MAX
#define SP_MAX_RSSI_STORE_DEPTH    5
#define SP_INVALID_HANDLE          0xFFFF
#define RSSI_2M_THRSHLD           -30
#define RSSI_1M_THRSHLD           -40
#define RSSI_S2_THRSHLD           -50
#define RSSI_S8_THRSHLD           -60
#define SP_PHY_NONE                LL_PHY_NONE  // No PHY set
#define AUTO_PHY_UPDATE            0xFF

// Spin if the expression is not true
#define BLEAPP_ASSERT(expr) if (!(expr)) bleApp_spin();

// address string length is an ascii character for each digit +
#define SMN_ADDR_STR_SIZE     15
#define APP_QUEUE_EVT         UTIL_QUEUE_EVENT_ID // Event_Id_30
#define EVENT_PEND_FOREVER    0xfffffffful

/*********************************************************************
* TYPEDEFS
*/

// App event passed from stack modules. This type is defined by the application
// since it can queue events to itself however it wants.
typedef struct
{
  uint8_t event;                // event type
  void    *pData;               // pointer to message
} appEvt_t;

// Container to store passcode data when passing from gapbondmgr callback
// to app event. See the pfnPairStateCB_t documentation from the gapbondmgr.h
// header file for more information on each parameter.
typedef struct
{
  uint8_t state;
  uint16_t connHandle;
  uint8_t status;
} appPairStateData_t;

// Container to store passcode data when passing from gapbondmgr callback
// to app event. See the pfnPasscodeCB_t documentation from the gapbondmgr.h
// header file for more information on each parameter.
typedef struct
{
  uint8_t deviceAddr[B_ADDR_LEN];
  uint16_t connHandle;
  uint8_t uiInputs;
  uint8_t uiOutputs;
  uint32_t numComparison;
} appPasscodeData_t;

// Container to store advertising event data when passing from advertising
// callback to app event. See the respective event in GapAdvScan_Event_IDs
// in gap_advertiser.h for the type that pBuf should be cast to.
typedef struct
{
  uint32_t event;
  void *pBuf;
} appGapAdvEventData_t;

// Container to store information from clock expiration using a flexible array
// since data is not always needed
typedef struct
{
  uint8_t event;
  uint8_t data[];
} appClockEventData_t;

// Scanned device information record
typedef struct
{
  uint8_t addrType;         // Peer Device's Address Type
  uint8_t addr[B_ADDR_LEN]; // Peer Device Address
} scanRec_t;

// Container to store all scan callback params
typedef struct
{
  uint32_t evt;
  void* pMsg;
  uintptr_t arg;
} scanCbData_t;

#ifdef ADD_SIMPLE_PERIPHERAL

// List element for parameter update and PHY command status lists
typedef struct
{
  List_Elem elem;
  uint16_t  connHandle;
} spConnHandleEntry_t;

// Connected device information
typedef struct
{
  uint16_t              connHandle;                        // Connection Handle
  appClockEventData_t*   pParamUpdateEventData;
  Clock_Struct*         pUpdateClock;                      // pointer to clock struct
  int8_t                rssiArr[SP_MAX_RSSI_STORE_DEPTH];
  uint8_t               rssiCntr;
  int8_t                rssiAvg;
  bool                  phyCngRq;                          // Set to true if PHY change request is in progress
  uint8_t               currPhy;
  uint8_t               rqPhy;
  uint8_t               phyRqFailCnt;                      // PHY change request count
  bool                  isAutoPHYEnable;                   // Flag to indicate auto phy change
} spConnRec_t;
#endif // ADD_SIMPLE_PERIPHERAL

/*********************************************************************
* GLOBAL VARIABLES
*/
// Display Interface
Display_Handle dispHandle = NULL;

// Task configuration
Task_Struct appTask;
#if defined __TI_COMPILER_VERSION__
#pragma DATA_ALIGN(appTaskStack, 8)
#else
#pragma data_alignment=8
#endif
uint8_t appTaskStack[BLEAPP_TASK_STACK_SIZE];


#define BLEAPP_EVT_EVENT_MAX  19
char *appEventStrings[] = {
  "BLEAPP_ZERO                 ",
  "BLEAPP_EVT_CHAR_CHANGE      ",
  "BLEAPP_EVT_KEY_CHANGE       ",
  "BLEAPP_EVT_ADV              ",
  "BLEAPP_EVT_PAIRING_STATE    ",
  "BLEAPP_EVT_PASSCODE_NEEDED  ",
  "BLEAPP_EVT_PERIODIC         ",
  "BLEAPP_EVT_READ_RPA         ",
  "BLEAPP_EVT_SEND_PARAM_UPDATE",
  "BLEAPP_EVT_CONN             ",
  "BLEAPP_EVT_INSUFFICIENT_MEM ",
  "BLEAPP_EVT_ADV_REPORT       ",
  "BLEAPP_EVT_SCAN_ENABLED     ",
  "BLEAPP_EVT_SCAN_DISABLED    ",
  "MESHAPP_EVT_ADV             ",
  "MESHAPP_EVT_GATT_WRT        ",
  "BLEAPP_EVT_STACK_CALLBACK   ",
  "OADAPP_EVT_CALLBACK         ",
  "OADAPP_EVT_RESET            ",
};

/*********************************************************************
* LOCAL VARIABLES
*/

// Entity ID globally used to check for source and/or destination of messages
bleStack_entityId_t appSelfEntity;
bleStack_entityId_t meshAppSelfEntity;  //extern in bt.c
static Event_Handle appSyncEvent;

// Queue object used for app messages
static Queue_Struct appMsgQueue;
static Queue_Handle appMsgQueueHandle;

// Clock instance for internal periodic events. Only one is needed since
// GattServApp will handle notifying all connected GATT clients
static Clock_Struct clkPeriodic;
// Clock instance for RPA read events.
static Clock_Struct clkRpaRead;

// Memory to pass periodic event ID to clock handler
appClockEventData_t argPeriodic =
{ .event = BLEAPP_EVT_PERIODIC };

// Memory to pass RPA read event ID to clock handler
appClockEventData_t argRpaRead =
{ .event = BLEAPP_EVT_READ_RPA };

#ifdef ADD_SIMPLE_PERIPHERAL
// Per-handle connection info
spConnRec_t connList[MAX_NUM_BLE_CONNS];

// Current connection handle as chosen by menu
static uint16_t menuConnHandle = LINKDB_CONNHANDLE_INVALID;

// List to store connection handles for set phy command status's
static List_List setPhyCommStatList;

// List to store connection handles for queued param updates
static List_List paramUpdateList;

// Auto connect Disabled/Enabled {0 - Disabled, 1- Group A , 2-Group B, ...}
uint8_t autoConnect = AUTOCONNECT_DISABLE;

// Advertising handles
static uint8 advHandle1;
#ifdef SECOND_ADV_SET
static uint8 advHandle2;
#endif /* SECOND_ADV_SET */
#endif // ADD_SIMPLE_PERIPHERAL

// Address mode
static GAP_Addr_Modes_t addrMode = ADDRMODE_PUBLIC;//DEFAULT_ADDRESS_MODE;

#ifdef ADD_SIMPLE_PERIPHERAL
// Current Random Private Address
static uint8 rpa[B_ADDR_LEN] = {0};
#endif // ADD_SIMPLE_PERIPHERAL

#ifdef USE_STATIC_PROVISIONING
uint16_t mesh_own_addr = DEVICE_OWN_ADDRESS;
#else
uint16_t mesh_own_addr = 1;
#endif
int advCb_count = 0;
int scanCb_count = 0;
int scanCb_beaconCount = 0;
int scanCb_msgCount = 0;
int scanCb_provCount = 0;
#ifdef CONFIG_BT_MESH_PROXY
static uint8_t meshScanData[] = "SimpleMeshNode";
#endif

// Used for save and restore the default device UUID
uint8_t defaultUUID[UUID_MAX_LEN];

/*********************************************************************
 * LOCAL FUNCTIONS
 */

static void     bleApp_init( void );
static void     bleApp_taskFxn(UArg a0, UArg a1);
static void     bleApp_processAppMsg(appEvt_t *pMsg);
static uint8_t  bleApp_processStackMsg(bleStack_msgHdt_t *pMsg);
static uint8_t  bleApp_processGATTMsg(gattMsgEvent_t *pMsg);
static void     bleApp_processGapMessage(gapEventHdr_t *pMsg);
#ifdef USE_APP_MENU
static void     bleApp_handleKeys(uint8_t keys);
#endif
static void     bleApp_keyChangeHandler(uint8_t keys);
static status_t bleApp_enqueueMsg(uint8_t event, void *pData);
static void     bleApp_performPeriodicTask(void);
static void     bleApp_clockHandler(UArg arg);
static void     bleApp_passcodeCB(uint8_t *pDeviceAddr, uint16_t connHandle,
                                            uint8_t uiInputs, uint8_t uiOutputs,
                                            uint32_t numComparison);
static void     bleApp_pairStateCb(uint16_t connHandle, uint8_t state,
                                             uint8_t status);
static void     meshApp_processAdvEvent(appGapAdvEventData_t *pEventData);

#ifdef ADD_SIMPLE_PERIPHERAL
static void bleApp_processAdvEvent(appGapAdvEventData_t *pEventData);
static void bleApp_charValueChangeCB(uint8_t paramId);
static void bleApp_processCharValueChangeEvt(uint8_t paramId);
static void SimplePeripheral_advCallback(uint32_t event, void *pBuf, uintptr_t arg);
static void SimplePeripheral_updateRPA(void);
static void bleApp_processPairState(appPairStateData_t *pPairState);
static void bleApp_processPasscode(appPasscodeData_t *pPasscodeData);
static void bleApp_processCmdCompleteEvt(hciEvt_CmdComplete_t *pMsg);
static void SimplePeripheral_initPHYRSSIArray(void);
static void SimplePeripheral_updatePHYStat(uint16_t eventCode, uint8_t *pMsg);
static uint8_t SimplePeripheral_addConn(uint16_t connHandle);
static uint8_t SimplePeripheral_getConnIndex(uint16_t connHandle);
static uint8_t SimplePeripheral_removeConn(uint16_t connHandle);
static void bleApp_processParamUpdate(uint16_t connHandle);
static status_t SimplePeripheral_startAutoPhyChange(uint16_t connHandle);
static status_t SimplePeripheral_stopAutoPhyChange(uint16_t connHandle);
static status_t SimplePeripheral_setPhy(uint16_t connHandle, uint8_t allPhys,
                                        uint8_t txPhy, uint8_t rxPhy,
                                        uint16_t phyOpts);
static uint8_t SimplePeripheral_clearConnListEntry(uint16_t connHandle);
void SimplePeripheral_connEvtCB(Gap_ConnEventRpt_t *pReport);
static void bleApp_processConnEvt(Gap_ConnEventRpt_t *pReport);
static bStatus_t SimplePeripheral_initAdvSet(pfnGapCB_t advCallback,
                                             uint8_t * const advHandle, GapAdv_params_t * const advParams,
                                             uint8_t advData[], const int advDataLen,
                                             uint8_t scanRespData[], const int scanRespDataLen);
#ifdef PTM_MODE
void PTM_init(bleStack_entityId_t appSelfEntity);
void PTM_handle_hci_event(uint8_t *pMsg);
#endif // PTM_MODE
#endif // ADD_SIMPLE_PERIPHERAL

uint8_t bleApp_processStackMsgCB(uint8_t event, uint8_t *pMsg);

/* Mesh profile */
int generic_models_extensions(void);
int MeshApp_init(uint16_t addr, uint8_t prov_type);
int MeshApp_unprovisioned_beacon(void);

/* Mesh Callbacks */
#ifdef USE_APP_MENU

#ifdef CONFIG_BT_MESH_LOW_POWER
static void meshApp_lpn_friendshipEstablished(uint16_t net_idx, uint16_t friend_addr,
		    uint8_t queue_size, uint8_t recv_window);
static void meshApp_lpn_friendshipTerminated(uint16_t net_idx, uint16_t friend_addr);
static void meshApp_lpnPolled(uint16_t net_idx, uint16_t friend_addr, bool retry);
#endif /* CONFIG_BT_MESH_LOW_POWER */

static void meshApp_hbRecv(const struct bt_mesh_hb_sub *sub, uint8_t hops,
	     uint16_t feat);
static void meshApp_hb_subEnd(const struct bt_mesh_hb_sub *sub);

#ifdef CONFIG_BT_MESH_FRIEND
static void meshApp_friend_friendshipEstablished(uint16_t net_idx, uint16_t lpn_addr,
			    uint8_t recv_delay, uint32_t polltimeout);
static void meshApp_friend_friendshipTerminated(uint16_t net_idx, uint16_t lpn_addr);
#endif /* CONFIG_BT_MESH_FRIEND */

#endif /* USE_APP_MENU */


/*********************************************************************
 * EXTERN FUNCTIONS
*/
extern void AssertHandler(uint8 assertCause, uint8 assertSubcause);
extern void mesh_portingLayer_scanCB(uint32_t evt, void* pMsg, uintptr_t arg);
extern void mesh_portingLayer_advCB(uint32_t event, void *pBuf);
extern int k_sys_work_q_init(void *dev);

#ifdef CONFIG_BT_MESH_PROXY
extern Event_Handle workQThreadSyncEvent;
#endif
#ifdef MESH_ERPC
extern void eRpcMesh_createTask();
// ERPC thread entity ID globally used to check for source and/or
// destination of messages
bleStack_entityId_t erpcThreadSelfEntity;    // eRPC thread
// ERPC thread event globally used to post local events and pend on
// system and local events
Event_Handle erpcThreadSyncEvent;    // eRPC thread
#endif

/*********************************************************************
 * PROFILE CALLBACKS
 */

// GAP Bond Manager Callbacks
static gapBondCBs_t bleApp_bondMgrCBs =
{
  bleApp_passcodeCB,       // Passcode callback
  bleApp_pairStateCb       // Pairing/Bonding state Callback
};

#ifdef ADD_SIMPLE_PERIPHERAL
// Simple GATT Profile Callbacks
static simpleProfileCBs_t bleApp_simpleProfileCBs =
{
  bleApp_charValueChangeCB // Simple GATT Characteristic value change callback
};
#endif

/*********************************************************************
 * Mesh Callbacks Global Variables
 */
#ifdef USE_APP_MENU

BT_MESH_HB_CB_DEFINE(meshApp_hb_cb) = {
  .recv    = meshApp_hbRecv,
  .sub_end = meshApp_hb_subEnd,
};

#ifdef CONFIG_BT_MESH_FRIEND
BT_MESH_FRIEND_CB_DEFINE(meshApp_friend_cb) = {
  .established = meshApp_friend_friendshipEstablished,
  .terminated  = meshApp_friend_friendshipTerminated,
};
#endif /* CONFIG_BT_MESH_FRIEND */

#ifdef CONFIG_BT_MESH_LOW_POWER
BT_MESH_LPN_CB_DEFINE(meshApp_lpn_cb) = {
  .established = meshApp_lpn_friendshipEstablished,
  .terminated  = meshApp_lpn_friendshipTerminated,
  .polled      = meshApp_lpnPolled,
};
#endif /* CONFIG_BT_MESH_LOW_POWER */
#endif /* USE_APP_MENU */

/*********************************************************************
 * PUBLIC FUNCTIONS
 */

/*********************************************************************
 * @fn      bleApp_spin
 *
 * @brief   Spin forever
 *
 * @param   none
 */
static void bleApp_spin(void)
{
  volatile uint8_t x = 0;

  while(1)
  {
    x++;
  }
}

#ifdef MESH_ERPC
/*********************************************************************
 * @fn      mesh_erpc_register
 *
 * @brief   Register to ble stack from the eRPC context.
 *
 * @return  none
 */
void mesh_erpc_register(void)
{
    bleStack_errno_t err;

    // When eRPC is enabled, need to register to the ble stack from the eRPC context
    err = bleStack_register(&erpcThreadSelfEntity, 0);
    BLEAPP_ASSERT(BLE_STACK_ERRNO_SUCCESS == err);
}
#endif


#ifdef ADD_SIMPLE_PERIPHERAL
/*********************************************************************
 * @fn      SimplePeripheral_initProfiles
 *
 * @brief   Init simple peripheral profiles
 */
int SimplePeripheral_initProfiles(void)
{
  DevInfo_AddService();                        // Device Information Service

  SimpleProfile_AddService(GATT_ALL_SERVICES); // Simple GATT Profile
#if defined(OAD_SUPPORT_ONCHIP)
  // OAD profile for reset action
  OadApp_addService();
#endif
  // Setup the SimpleProfile Characteristic Values
  // For more information, see the GATT and GATTServApp sections in the User's Guide:
  // software-dl.ti.com/.../
  {
    uint8_t charValue1 = 1;
    uint8_t charValue2 = 2;
    uint8_t charValue3 = 3;
    uint8_t charValue4 = 4;
    uint8_t charValue5[SIMPLEPROFILE_CHAR5_LEN] = { 1, 2, 3, 4, 5 };

    SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR1, sizeof(uint8_t),
                               &charValue1);
    SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR2, sizeof(uint8_t),
                               &charValue2);
    SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR3, sizeof(uint8_t),
                               &charValue3);
    SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR4, sizeof(uint8_t),
                               &charValue4);
    SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR5, SIMPLEPROFILE_CHAR5_LEN,
                               charValue5);
  }

  // Register callback with SimpleGATTprofile
  SimpleProfile_RegisterAppCBs(&bleApp_simpleProfileCBs);

  return 0;
}
#endif // ADD_SIMPLE_PERIPHERAL

/*********************************************************************
 * @fn      bleApp_stackInit
 *
 * @brief   Called during initialization and contains application
 *          specific initialization (ie. hardware initialization/setup,
 *          table initialization, power up notification, etc), and
 *          profile initialization/setup.
 */
int bleApp_stackInit(void)
{
  uint8_t profileRole;

  // ******************************************************************
  // N0 STACK API CALLS CAN OCCUR BEFORE THIS CALL TO bleStack_register
  // ******************************************************************
  // Register the stack messages callback - see ble_stack_api.c - #ifdef ICALL_NO_APP_EVENTS
  bleStack_register(&appSelfEntity, bleApp_processStackMsgCB);
  meshAppSelfEntity = appSelfEntity; // used by bt.c
  // Create the application appSyncEvent
  appSyncEvent = Event_create(NULL, NULL);

  // Create an RTOS queue for message from profile to be sent to app.
  appMsgQueueHandle = Util_constructQueue(&appMsgQueue);

  // Create one-shot clock for internal periodic events.
  Util_constructClock(&clkPeriodic, bleApp_clockHandler,
                      BLEAPP_PERIODIC_EVT_PERIOD, 0, false, (UArg)&argPeriodic);

#if defined(CONFIG_BT_MESH_PROXY) || defined(ADD_SIMPLE_PERIPHERAL)
  profileRole = GAP_PROFILE_PERIPHERAL | GAP_PROFILE_OBSERVER;
  BLE_LOG_INT_TIME(0, BLE_LOG_MODULE_APP, "APP : ---- role PERIPHERAL+OBSERVER", profileRole);
#else
  profileRole = GAP_PROFILE_BROADCASTER | GAP_PROFILE_OBSERVER;
  BLE_LOG_INT_TIME(0, BLE_LOG_MODULE_APP, "APP : ---- role BROADCASTER+OBSERVER", profileRole);
#endif // CONFIG_BT_MESH_PROXY || ADD_SIMPLE_PERIPHERAL

#ifdef USE_RCOSC
  // Set device's Sleep Clock Accuracy
#if ( HOST_CONFIG & ( CENTRAL_CFG | PERIPHERAL_CFG ) )
  HCI_EXT_SetSCACmd(500);
#endif // (CENTRAL_CFG | PERIPHERAL_CFG)
  RCOSC_enableCalibration();
#endif // USE_RCOSC

#if defined(CONFIG_BT_MESH_PROXY) || defined(ADD_SIMPLE_PERIPHERAL)
  // init GAP
  bleStack_initGap(profileRole, appSelfEntity, DEFAULT_PARAM_UPDATE_REQ_DECISION);

  // init GapBond
  bleStack_initGapBond(0, &bleApp_bondMgrCBs);

  // init GATT
  bleStack_initGatt(profileRole, appSelfEntity, attDeviceName);
#else
  // init GAP
  bleStack_initGap(profileRole, appSelfEntity, 0);

  // init GapBond
  bleStack_initGapBond(0, &bleApp_bondMgrCBs);
#endif

#if defined ( GAP_BOND_MGR )
  // Setup the GAP Bond Manager. For more information see the GAP Bond Manager
  // section in the User's Guide
  // ToDo - remove implementation from SysConfig
  // ToDo - set one call _all instaead of many calls to GAPBondMgr_SetParameter
  setBondManagerParameters();
#endif

#ifdef ADD_SIMPLE_PERIPHERAL
  SimplePeripheral_initProfiles();
#endif

#ifdef ADD_SIMPLE_PERIPHERAL
  // Initialize Connection List
  SimplePeripheral_clearConnListEntry(LINKDB_CONNHANDLE_ALL);

  // Initialize array to store connection handle and RSSI values
  SimplePeripheral_initPHYRSSIArray();
#endif

  BLE_LOG_INT_TIME(0, BLE_LOG_MODULE_APP, "APP : ---- call GAP_DeviceInit", profileRole);
  //Initialize GAP layer for Peripheral and Central role and register to receive GAP events
  GAP_DeviceInit(profileRole, appSelfEntity, addrMode, &pRandomAddress);

#ifdef PTM_MODE
  PTM_init(appSelfEntity);
#endif

#ifdef OAD_SUPPORT
#ifdef OAD_DEBUG
  tbm_setItemStatus(&spMenuMain, SP_ITEM_SELECT_OAD_DBG, SP_ITEM_SELECT_CONN);
#endif
  OadApp_init();
#endif
  // Preempting Advertise over Scan
  BLEAPP_ASSERT(HCI_EXT_SetQOSDefaultParameters(LL_QOS_MEDIUM_PRIORITY,
      LL_QOS_TYPE_PRIORITY, LL_QOS_ADV_TASK_TYPE) == HCI_SUCCESS);

  return 0;
}

/*********************************************************************
 * @fn      bleApp_init
 *
 * @brief   Called during initialization and contains application
 *          specific initialization (ie. hardware initialization/setup,
 *          table initialization, power up notification, etc), and
 *          profile initialization/setup.
 */
static void bleApp_init(void)
{
  BLE_LOG_INT_TIME(0, BLE_LOG_MODULE_APP, "APP : ---- init ", BLEAPP_TASK_PRIORITY);

  /*
   * Init the menu with input keys and display
   */

  // Init key debouncer
  Board_initKeys(bleApp_keyChangeHandler);

#ifdef USE_APP_MENU
  // preprocessor definitions
  dispHandle = Display_open(Display_Type_ANY, NULL);

  // Create the menu
 // SimpleMeshMenu_init(dispHandle);
#endif

  /*
   * Init the ble stack
   */
  bleApp_stackInit();

  if (IS_ENABLED(CONFIG_BT_SETTINGS))
  {
    // Initialize settings submodule
    int err = settings_subsys_init();
    BLEAPP_ASSERT(err == SUCCESS);
    Display_printf(dispHandle, SMN_ROW_MENU_ST, 0, "NVS: settings_subsys_init() ret status: %d", err);
  }

  /*
   * Init the mesh stack
   */
#if defined (USE_APP_MENU) || defined (MESH_ERPC)
    // TBMenu will call MeshApp_init
    // eRpc will call bt_mesh_init + bt_mesh_provision
#else
    // bt_ready now, zephyr mesh stack can be initialized
    MeshApp_init(mesh_own_addr, UNPROVISIONED_BEACON);
#endif
}

/*********************************************************************
 * @fn      simple_mesh_and_peripheral_createTask
 *
 * @brief   Task creation function for simple_mesh_and_peripheral.
 */
void simple_mesh_and_peripheral_createTask(void)
{
  Task_Params taskParams;

  // Configure task
  Task_Params_init(&taskParams);
  taskParams.stack = appTaskStack;
  taskParams.stackSize = BLEAPP_TASK_STACK_SIZE;
  taskParams.priority = BLEAPP_TASK_PRIORITY;

  Task_construct(&appTask, bleApp_taskFxn, &taskParams, NULL);
}

/*********************************************************************
 * @fn      bleApp_createTasks
 *
 * @brief   Task creation function for this ble application.
 */
void bleApp_createTasks(void)
{
  // Init and create ble stack tasks
  bleStack_createTasks();

  // init zephyr mesh worker task
  k_sys_work_q_init(NULL);

#ifdef MESH_ERPC
  // create eRpc task
  eRpcMesh_createTask();
#endif

  // Create local app task
  simple_mesh_and_peripheral_createTask();
}

/*********************************************************************
 * @fn      bleApp_taskFxn
 *
 * @brief   Application task entry point for the Simple Mesh.
 *
 * @param   a0, a1 - not used.
 */
static void bleApp_taskFxn(UArg a0, UArg a1)
{
  // Initialize application
  bleApp_init();

  // Application main loop
  for (;;)
  {
    uint32_t events;

    appEvt_t *pMsg;

    // Waits for an event to be posted
    events = Event_pend(appSyncEvent, Event_Id_NONE, APP_QUEUE_EVT,
                          EVENT_PEND_FOREVER);
    if (events)
    {
      // Check if there are any messages in the queue
      while (!Queue_empty(appMsgQueueHandle))
      {
          pMsg = (appEvt_t *)Util_dequeueMsg(appMsgQueueHandle);

          if (pMsg)
          {
            if (BLEAPP_EVT_STACK_CALLBACK == pMsg->event)
            {
              // Process stack messages - changed from events to callback
              if (bleApp_processStackMsg((bleStack_msgHdt_t*)pMsg->pData))
              {
                bleStack_freeMsg((bleStack_msgHdt_t*)pMsg->pData);
              }
            }
#ifdef OAD_SUPPORT
            else if (OADAPP_EVT_CALLBACK == pMsg->event)
            {
                OadApp_processEvents((uint32_t)(*(uint8_t *)(pMsg->pData)));
                bleStack_free(pMsg->pData);
            }
#endif
            else
            {
              // Process application messages (callbacks after switch context)
              bleApp_processAppMsg(pMsg);
            }

            // Free the space from the message.
            bleStack_free(pMsg);
        }
      }
    }
  }
}

/*********************************************************************
 * @fn      bleApp_processStackMsg
 *
 * @brief   Process an incoming stack message.
 *
 * @param   pMsg - message to process
 *
 * @return  TRUE if safe to deallocate incoming message, FALSE otherwise.
 */
static uint8_t bleApp_processStackMsg(bleStack_msgHdt_t *pMsg)
{
  // Always dealloc pMsg unless set otherwise
  uint8_t safeToDealloc = TRUE;

  BLE_LOG_INT_INT(0, BLE_LOG_MODULE_APP, "APP : Stack msg status=%d, event=0x%x\n", pMsg->status, pMsg->event);

  switch (pMsg->event)
  {
    case GAP_MSG_EVENT:
      bleApp_processGapMessage((gapEventHdr_t*) pMsg);
      break;

    case GATT_MSG_EVENT:
      // Process GATT message
      safeToDealloc = bleApp_processGATTMsg((gattMsgEvent_t *)pMsg);
      break;

    case HCI_GAP_EVENT_EVENT:
    {
      // Process HCI message
      switch (pMsg->status)
      {
        case HCI_COMMAND_COMPLETE_EVENT_CODE:
        // Process HCI Command Complete Events here
        {
#ifdef ADD_SIMPLE_PERIPHERAL
          bleApp_processCmdCompleteEvt((hciEvt_CmdComplete_t *) pMsg);
#endif
          break;
        }

        case HCI_BLE_HARDWARE_ERROR_EVENT_CODE:
          AssertHandler(HAL_ASSERT_CAUSE_HARDWARE_ERROR,0);
          break;

#ifdef ADD_SIMPLE_PERIPHERAL
        // HCI Commands Events
        case HCI_COMMAND_STATUS_EVENT_CODE:
        {
          hciEvt_CommandStatus_t *pMyMsg = (hciEvt_CommandStatus_t *)pMsg;
          switch ( pMyMsg->cmdOpcode )
          {
            case HCI_LE_SET_PHY:
            {
              if (pMyMsg->cmdStatus == HCI_ERROR_CODE_UNSUPPORTED_REMOTE_FEATURE)
              {
                Display_printf(dispHandle, SP_ROW_STATUS_1, 0,
                        "PHY Change failure, peer does not support this");
              }
              else
              {
                Display_printf(dispHandle, SP_ROW_STATUS_1, 0,
                               "PHY Update Status Event: 0x%x",
                               pMyMsg->cmdStatus);
              }

              SimplePeripheral_updatePHYStat(HCI_LE_SET_PHY, (uint8_t *)pMsg);
              break;
            }

            default:
              break;
          }
          break;
        }

        // LE Events
        case HCI_LE_EVENT_CODE:
        {
          hciEvt_BLEPhyUpdateComplete_t *pPUC =
            (hciEvt_BLEPhyUpdateComplete_t*) pMsg;

          // A Phy Update Has Completed or Failed
          if (pPUC->BLEEventCode == HCI_BLE_PHY_UPDATE_COMPLETE_EVENT)
          {
            if (pPUC->status != SUCCESS)
            {
              Display_printf(dispHandle, SP_ROW_STATUS_1, 0,
                             "PHY Change failure");
            }
            else
            {
              // Only symmetrical PHY is supported.
              // rxPhy should be equal to txPhy.
              Display_printf(dispHandle, SP_ROW_STATUS_2, 0,
                             "PHY Updated to %s",
                             (pPUC->rxPhy == PHY_UPDATE_COMPLETE_EVENT_1M) ? "1M" :
                             (pPUC->rxPhy == PHY_UPDATE_COMPLETE_EVENT_2M) ? "2M" :
                             (pPUC->rxPhy == PHY_UPDATE_COMPLETE_EVENT_CODED) ? "CODED" : "Unexpected PHY Value");
            }

            SimplePeripheral_updatePHYStat(HCI_BLE_PHY_UPDATE_COMPLETE_EVENT, (uint8_t *)pMsg);
          }
          break;
        }

#endif // ADD_SIMPLE_PERIPHERAL
        default:
          break;
      }

      break;
    }

#ifdef OAD_SUPPORT
    case L2CAP_SIGNAL_EVENT:
      // Process L2CAP signal
      safeToDealloc = OadApp_processL2CAPMsg((l2capSignalEvent_t *)pMsg);
      break;
#endif

    default:
      // Do nothing
      break;
  }

#ifdef PTM_MODE
  // Check for NPI Messages
  PTM_handle_hci_event(pMsg);
#endif

  return (safeToDealloc);
}

/*********************************************************************
* @fn      bleApp_processGATTMsg
*
* @brief   Process GATT messages and events.
*
* @return  TRUE if safe to deallocate incoming message, FALSE otherwise.
*/
static uint8_t bleApp_processGATTMsg(gattMsgEvent_t *pMsg)
{
#ifdef ADD_SIMPLE_PERIPHERAL
  if (pMsg->method == ATT_FLOW_CTRL_VIOLATED_EVENT)
  {
    // ATT request-response or indication-confirmation flow control is
    // violated. All subsequent ATT requests or indications will be dropped.
    // The app is informed in case it wants to drop the connection.

    // Display the opcode of the message that caused the violation.
    Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "FC Violated: %d", pMsg->msg.flowCtrlEvt.opcode);
  }
  else if (pMsg->method == ATT_MTU_UPDATED_EVENT)
  {
    // MTU size updated
#ifdef OAD_SUPPORT
    OAD_setBlockSize(pMsg->msg.mtuEvt.MTU);
#endif
    Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "MTU Size: %d", pMsg->msg.mtuEvt.MTU);
  }
#endif // ADD_SIMPLE_PERIPHERAL

#ifdef CONFIG_BT_MESH_PROXY
  if (pMsg->method == ATT_MTU_UPDATED_EVENT)
  {
    mesh_portingLayer_updateLinkMTU(pMsg->msg.mtuEvt.MTU);
  }
#endif
  // Free message payload. Needed only for ATT Protocol messages
  GATT_bm_free(&pMsg->msg, pMsg->method);

  // It's safe to free the incoming message
  return (TRUE);
}

/*********************************************************************
 * @fn      bleApp_processAppMsg
 *
 * @brief   Process an incoming callback from a profile.
 *
 * @param   pMsg - message to process
 *
 * @return  None.
 */
static void bleApp_processAppMsg(appEvt_t *pMsg)
{
  bool dealloc = TRUE;

  if (pMsg->event <= BLEAPP_EVT_EVENT_MAX)
  {
    BLE_LOG_INT_STR(0, BLE_LOG_MODULE_APP, "APP : App msg status=%d, event=%s\n", 0, appEventStrings[pMsg->event]);
  }
  else
  {
    BLE_LOG_INT_INT(0, BLE_LOG_MODULE_APP, "APP : App msg status=%d, event=0x%x\n", 0, pMsg->event);
  }

  switch (pMsg->event)
  {
#ifdef ADD_SIMPLE_PERIPHERAL
    case BLEAPP_EVT_CHAR_CHANGE:
      bleApp_processCharValueChangeEvt(*(uint8_t*)(pMsg->pData));
      break;
#endif

#ifdef USE_APP_MENU
    case BLEAPP_EVT_KEY_CHANGE:
      bleApp_handleKeys(*(uint8_t *)(pMsg->pData));
      break;
#endif

#ifdef ADD_SIMPLE_PERIPHERAL
    case BLEAPP_EVT_ADV:
      advCb_count++;
      bleApp_processAdvEvent((appGapAdvEventData_t*)(pMsg->pData));
      break;
#endif

    case MESHAPP_EVT_ADV:
      advCb_count++;
      meshApp_processAdvEvent((appGapAdvEventData_t*)(pMsg->pData));
      break;

    case BLEAPP_EVT_PERIODIC:
      bleApp_performPeriodicTask();
      break;

#ifdef ADD_SIMPLE_PERIPHERAL
    case BLEAPP_EVT_PAIRING_STATE:
      bleApp_processPairState((appPairStateData_t*)(pMsg->pData));
      break;

    case BLEAPP_EVT_PASSCODE_NEEDED:
      bleApp_processPasscode((appPasscodeData_t*)(pMsg->pData));
      break;

    case BLEAPP_EVT_READ_RPA:
      SimplePeripheral_updateRPA();
      break;

    case BLEAPP_EVT_SEND_PARAM_UPDATE:
    {
      // Extract connection handle from data
      uint16_t connHandle = *(uint16_t *)(((appClockEventData_t *)pMsg->pData)->data);

      bleApp_processParamUpdate(connHandle);

      // This data is not dynamically allocated
      dealloc = FALSE;
      break;
    }

    case BLEAPP_EVT_CONN:
      bleApp_processConnEvt((Gap_ConnEventRpt_t *)(pMsg->pData));
      break;

#if defined(OAD_SUPPORT_ONCHIP)
    case OADAPP_EVT_RESET:
      OadApp_processOadResetEvt((oadResetWrite_t *)(pMsg->pData));
      break;
#endif
#endif // ADD_SIMPLE_PERIPHERAL

    case BLEAPP_EVT_ADV_REPORT:
    {
      scanCbData_t *pData = (scanCbData_t *)pMsg->pData;
      GapScan_Evt_AdvRpt_t* pAdvRpt = (GapScan_Evt_AdvRpt_t*) (pData->pMsg);

      mesh_portingLayer_scanCB(pData->evt, pData->pMsg, pData->arg);
#define BT_DATA_MESH_PROV               0x29 /* Mesh Provisioning PDU */
#define BT_DATA_MESH_MESSAGE            0x2a /* Mesh Networking PDU */
#define BT_DATA_MESH_BEACON             0x2b /* Mesh Beacon */

      scanCb_count++;
      if (pAdvRpt->pData[1] == BT_DATA_MESH_BEACON)
          scanCb_beaconCount++;
      else if (pAdvRpt->pData[1] == BT_DATA_MESH_MESSAGE)
          scanCb_msgCount++;
      else if (pAdvRpt->pData[1] == BT_DATA_MESH_PROV)
          scanCb_provCount++;

      // Free scan payload data
      if (pAdvRpt->pData != NULL)
      {
        bleStack_free(pAdvRpt->pData);
      }
      if (pAdvRpt != NULL)
      {
        bleStack_free(pAdvRpt);
      }
      break;
    }

    case BLEAPP_EVT_SCAN_ENABLED:
    case BLEAPP_EVT_SCAN_DISABLED:
    {
      scanCbData_t *pData = (scanCbData_t *)pMsg->pData;

      mesh_portingLayer_scanCB(pData->evt, pData->pMsg, pData->arg);

      break;
    }

    case BLEAPP_EVT_INSUFFICIENT_MEM:
    {
      // We are running out of memory.
#ifdef USE_APP_MENU
//      Display_printf(dispHandle, SMN_ROW_ANY_CONN, 0, "Insufficient Memory");
#endif
      BLEAPP_ASSERT(FAILURE);
      break;
    }

#ifdef CONFIG_BT_MESH_PROXY
    case MESHAPP_EVT_GATT_WRT:
    {
      writeCbParams_t *writeParams = (writeCbParams_t *)(pMsg->pData);
      // call real writeCB
      mesh_portingLayer_proxyProvAttWriteCB(writeParams);
      break;
    }
#endif

    default:
      // Do nothing.
      break;
  }

  // Free message data if it exists and we are to dealloc
  if ((dealloc == TRUE) && (pMsg->pData != NULL))
  {
    bleStack_free(pMsg->pData);
  }
}

#ifdef ADD_SIMPLE_PERIPHERAL
/*********************************************************************
 * @fn      SimplePeripheral_initAdvSet
 *
 * @brief   Initialize and starts advertise set (legacy or extended)
 *
 * @param advCallback Function pointer to a callback for this advertising set
 * @param advHandle Output parameter to return the created advertising handle
 * @param advParams pointer to structure of adversing parameters
 * @param advData pointer to array containing the advertise data
 * @param advDataLen length (in bytes) of @ref advData
 * @param scanRespData pointer to array containing the scan response data
 * @param scanRespDataLen length (in bytes) of @ref scanRespDataLen
 *
 * @return @ref SUCCESS upon successful initialization,
 *         else, relevant error code upon failure
 */
static bStatus_t SimplePeripheral_initAdvSet(pfnGapCB_t advCallback,
                                             uint8_t * const advHandle, GapAdv_params_t * const advParams,
                                             uint8_t advData[], const int advDataLen,
                                             uint8_t scanRespData[], const int scanRespDataLen)
{
  bStatus_t status;

  BLE_LOG_INT_INT(0, BLE_LOG_MODULE_APP, "APP : ---- call GapAdv_create set=%d,%d\n", 0, 0);
  // Create Advertisement set and assign handle
  status = GapAdv_create(advCallback, advParams,
                         advHandle);
  if (status != SUCCESS)
  {
    return status;
  }


  // Load advertising data for set that is statically allocated by the app
  status = GapAdv_loadByHandle(*advHandle, GAP_ADV_DATA_TYPE_ADV,
                               advDataLen, advData);
  if (status != SUCCESS)
  {
    return status;
  }

  // Load scan response data for set that is statically allocated by the app
  if (scanRespData != NULL)
  {
    status = GapAdv_loadByHandle(*advHandle, GAP_ADV_DATA_TYPE_SCAN_RSP,
                                 scanRespDataLen, scanRespData);
    if (status != SUCCESS)
    {
      return status;
    }
  }

  // Set event mask for set
  status = GapAdv_setEventMask(*advHandle,
                               GAP_ADV_EVT_MASK_START_AFTER_ENABLE |
                               GAP_ADV_EVT_MASK_END_AFTER_DISABLE |
                               GAP_ADV_EVT_MASK_SET_TERMINATED);

  if (status != SUCCESS)
  {
    return status;
  }
  // Enable advertising for set
  status = GapAdv_enable(*advHandle, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0);

  return status;
}

/*********************************************************************
 * @fn      SimplePeripheral_startAdvertising
 *
 * @brief   start advertising - legacy and long range
 */
int SimplePeripheral_startAdvertising(uint8_t *devAddr)
{
    bStatus_t status;
    Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "Initialized");

    // Setup and start Advertising
    // For more information, see the GAP section in the User's Guide:
    // software-dl.ti.com/.../

    // Initialize advertisement handlers

    // In case of extended, initialize advertise set with advertising data,
    // else (Legacy), initialize advertise set with scan response data and advertising data
    // Note: In this example, the default adv set is extended. When changing the set to Legacy,
    // please un-comment the "else" section.
    if ( (advParams1.eventProps & GAP_ADV_PROP_LEGACY) == 0)
    {
      status = SimplePeripheral_initAdvSet(&SimplePeripheral_advCallback, &advHandle1, &advParams1,
                                           advData1, sizeof(advData1) ,NULL, 0);
      BLEAPP_ASSERT(status == SUCCESS);
    }
    // else
    // {
    //   status = SimplePeripheral_initAdvSet(&SimplePeripheral_advCallback, &advHandle1, &advParams1,
    //                                        advData1, sizeof(advData1) ,
    //                                        scanResData1, sizeof(scanResData1));
    //   BLEAPP_ASSERT(status == SUCCESS);
    // }

#ifdef SECOND_ADV_SET
    // In case of extended, initialize advertise set with advertising data,
    // else (Legacy), initialize advertise set with scan response data and advertising data
    // Note: In this example, the default adv set is extended. When changing the set to Legacy,
    // please un-comment the "else" section.
    if (advParams2.eventProps & GAP_ADV_PROP_LEGACY == 0)
    {
      status = SimplePeripheral_initAdvSet(&SimplePeripheral_advCallback, &advHandle2, &advParams2,
                                           advData2, sizeof(advData2) ,NULL, 0);
      BLEAPP_ASSERT(status == SUCCESS);
    }
    // else
    // {
    //   status = SimplePeripheral_initAdvSet(&SimplePeripheral_advCallback, &advHandle2, &advParams2,
    //                                        advData2, sizeof(advData2) ,
    //                                        scanResData2, sizeof(scanResData2));
    //   BLEAPP_ASSERT(status == SUCCESS);
    // }
#endif /* SECOND_ADV_SET */

    // Display device address
    Display_printf(dispHandle, SP_ROW_IDA, 0, "%s Addr: %s",
                   (addrMode <= ADDRMODE_RANDOM) ? "Dev" : "ID",
                   Util_convertBdAddr2Str(devAddr));

    if (addrMode > ADDRMODE_RANDOM)
    {
      SimplePeripheral_updateRPA();

      // Create one-shot clock for RPA check event.
      Util_constructClock(&clkRpaRead, bleApp_clockHandler,
                          READ_RPA_PERIOD, 0, true,
                          (UArg) &argRpaRead);
    }
    tbm_setItemStatus(&spMenuMain, SP_ITEM_AUTOCONNECT, TBM_ITEM_NONE);

    return 0;
}

/*********************************************************************
 * @fn      SimplePeripheral_connectIndication
 *
 * @brief   conection establish indication
 */
int SimplePeripheral_connectIndication(uint16_t connectionHandle, uint8 pkt_status)
{
      // Display the amount of current connections
      uint8_t numActive = linkDB_NumActive();
#ifdef USE_APP_MENU
      Display_printf(dispHandle, SP_ROW_STATUS_2, 0, "Num Conns: %d",
                     (uint16_t)numActive);
#endif

      if (pkt_status == SUCCESS)
      {
        // Add connection to list and start RSSI
        SimplePeripheral_addConn(connectionHandle);
        // Enable connection selection option
        tbm_setItemStatus(&spMenuMain, SP_ITEM_SELECT_CONN,SP_ITEM_AUTOCONNECT);

        // Start Periodic Clock.
        Util_startClock(&clkPeriodic);
      }

      if ((numActive < MAX_NUM_BLE_CONNS) && (autoConnect == AUTOCONNECT_DISABLE))
      {
        // Start advertising since there is room for more connections
        GapAdv_enable(advHandle1, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0);
#ifdef SECOND_ADV_SET
        GapAdv_enable(advHandle2, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0);
#endif /* SECOND_ADV_SET */
      }
      else
      {
        GapAdv_disable(advHandle1);
#ifdef SECOND_ADV_SET
        GapAdv_disable(advHandle2);
#endif /* SECOND_ADV_SET */
      }

      return 0;
}
/*********************************************************************
 * @fn      SimplePeripheral_disableAdvertising
 *
 * @brief   disable advertising - legacy and long range
 */
int SimplePeripheral_disconnectIndication(uint16_t connectionHandle)
{
      // Display the amount of current connections
      uint8_t numActive = linkDB_NumActive();
#ifdef USE_APP_MENU
      Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "Device Disconnected!");
      Display_printf(dispHandle, SP_ROW_STATUS_2, 0, "Num Conns: %d",
                     (uint16_t)numActive);
#endif

      // Remove the connection from the list and disable RSSI if needed
      SimplePeripheral_removeConn(connectionHandle);

      // If no active connections
      if (numActive == 0)
      {
        // Stop periodic clock
        Util_stopClock(&clkPeriodic);

        // Disable Connection Selection option
        tbm_setItemStatus(&spMenuMain, SP_ITEM_AUTOCONNECT, SP_ITEM_SELECT_CONN);
      }

      BLE_LOG_INT_STR(0, BLE_LOG_MODULE_APP, "APP : GAP msg: status=%d, opcode=%s\n", 0, "GAP_LINK_TERMINATED_EVENT");
      // Start advertising since there is room for more connections
      GapAdv_enable(advHandle1, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0);
#ifdef SECOND_ADV_SET
      GapAdv_enable(advHandle2, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0);
#endif /* SECOND_ADV_SET */

      // Clear remaining lines
      Display_clearLine(dispHandle, SP_ROW_CONNECTION);

#ifdef OAD_SUPPORT
      // Cancel the OAD if one is going on
      // A disconnect forces the peer to re-identify
      OadApp_cancel();
#endif
      return 0;
}
#endif // ADD_SIMPLE_PERIPHERAL
/*********************************************************************
 * @fn      bleApp_processGapMessage
 *
 * @brief   Process an incoming GAP event.
 *
 * @param   pMsg - message to process
 */
static void bleApp_processGapMessage(gapEventHdr_t *pMsg)
{
  switch (pMsg->opcode)
  {
    case GAP_DEVICE_INIT_DONE_EVENT:
    {
      gapDeviceInitDoneEvent_t *pPkt = (gapDeviceInitDoneEvent_t *)pMsg;

      BLE_LOG_INT_TIME(0, BLE_LOG_MODULE_APP, "APP : ---- got GAP_DEVICE_INIT_DONE_EVENT", 0);
      if(pPkt->hdr.status == SUCCESS)
      {
        // Store the system ID
        uint8_t systemId[DEVINFO_SYSTEM_ID_LEN];

        // use 6 bytes of device address for 8 bytes of system ID value
        systemId[0] = pPkt->devAddr[0];
        systemId[1] = pPkt->devAddr[1];
        systemId[2] = pPkt->devAddr[2];

        // set middle bytes to zero
        systemId[4] = 0x00;
        systemId[3] = 0x00;

        // shift three bytes up
        systemId[7] = pPkt->devAddr[5];
        systemId[6] = pPkt->devAddr[4];
        systemId[5] = pPkt->devAddr[3];

        // Set Device Info Service Parameter
        DevInfo_SetParameter(DEVINFO_SYSTEM_ID, DEVINFO_SYSTEM_ID_LEN, systemId);

        // Register callback to process Scanner events
        GapScan_registerCb(MeshApp_scanCB, NULL);

#ifdef CONFIG_BT_MESH_PROXY
        // Set the device's name in the mesh porting layer
        mesh_portingLayer_setDeviceName(meshScanData);
#endif

#ifdef ADD_SIMPLE_PERIPHERAL
        SimplePeripheral_startAdvertising(pPkt->devAddr);
#endif
      }

      break;
    }

    case GAP_LINK_ESTABLISHED_EVENT:
    {
#if defined(CONFIG_BT_MESH_PROXY) || defined(ADD_SIMPLE_PERIPHERAL)
      gapEstLinkReqEvent_t *pPkt = (gapEstLinkReqEvent_t *)pMsg;

      BLE_LOG_INT_TIME(0, BLE_LOG_MODULE_APP, "APP : ---- got GAP_LINK_ESTABLISHED_EVENT", 0);
#endif
#ifdef CONFIG_BT_MESH_PROXY
        // Call zephyr cb
        mesh_portingLayer_newConnectionCB(pPkt);
#endif

#ifdef ADD_SIMPLE_PERIPHERAL
        SimplePeripheral_connectIndication(pPkt->connectionHandle, pPkt->hdr.status);
#endif
      break;
    }

    case GAP_LINK_TERMINATED_EVENT:
    {
#if defined(CONFIG_BT_MESH_PROXY) || defined(ADD_SIMPLE_PERIPHERAL)
      gapTerminateLinkEvent_t *pPkt = (gapTerminateLinkEvent_t *)pMsg;
#endif

#ifdef CONFIG_BT_MESH_PROXY
      // Call zephyr cb
      mesh_portingLayer_disconnectCB(pPkt);
#endif

#ifdef ADD_SIMPLE_PERIPHERAL
        SimplePeripheral_disconnectIndication(pPkt->connectionHandle);
#endif
      break;
    }

#if defined(CONFIG_BT_MESH_PROXY) || defined(ADD_SIMPLE_PERIPHERAL)
    case GAP_UPDATE_LINK_PARAM_REQ_EVENT:
    {
      gapUpdateLinkParamReqReply_t rsp;

      gapUpdateLinkParamReqEvent_t *pReq = (gapUpdateLinkParamReqEvent_t *)pMsg;

      rsp.connectionHandle = pReq->req.connectionHandle;
      rsp.signalIdentifier = pReq->req.signalIdentifier;

      // Only accept connection intervals with slave latency of 0
      // This is just an example of how the application can send a response
      if(pReq->req.connLatency == 0)
      {
        rsp.intervalMin = pReq->req.intervalMin;
        rsp.intervalMax = pReq->req.intervalMax;
        rsp.connLatency = pReq->req.connLatency;
        rsp.connTimeout = pReq->req.connTimeout;
        rsp.accepted = TRUE;
      }
      else
      {
        rsp.accepted = FALSE;
      }

      // Send Reply
      VOID GAP_UpdateLinkParamReqReply(&rsp);

      break;
    }

    case GAP_LINK_PARAM_UPDATE_EVENT:
    {
      gapLinkUpdateEvent_t *pPkt = (gapLinkUpdateEvent_t *)pMsg;

      // Get the address from the connection handle
      linkDBInfo_t linkInfo;
      linkDB_GetInfo(pPkt->connectionHandle, &linkInfo);

#ifdef CONFIG_BT_MESH_PROXY
      mesh_portingLayer_updateLinkMTU(linkInfo.MTU);
#endif

#ifdef ADD_SIMPLE_PERIPHERAL
#ifdef USE_APP_MENU
      if(pPkt->status == SUCCESS)
      {
        // Display the address of the connection update
        Display_printf(dispHandle, SP_ROW_STATUS_2, 0, "Link Param Updated: %s",
                       Util_convertBdAddr2Str(linkInfo.addr));
      }
      else
      {
        // Display the address of the connection update failure
        Display_printf(dispHandle, SP_ROW_STATUS_2, 0,
                       "Link Param Update Failed 0x%x: %s", pPkt->opcode,
                       Util_convertBdAddr2Str(linkInfo.addr));
      }
#endif
      // Check if there are any queued parameter updates
      spConnHandleEntry_t *connHandleEntry = (spConnHandleEntry_t *)List_get(&paramUpdateList);
      if (connHandleEntry != NULL)
      {
        // Attempt to send queued update now
        bleApp_processParamUpdate(connHandleEntry->connHandle);

        // Free list element
        bleStack_free(connHandleEntry);
      }
#endif // ADD_SIMPLE_PERIPHERAL
      break;
    }

#if defined ( NOTIFY_PARAM_UPDATE_RJCT )
     case GAP_LINK_PARAM_UPDATE_REJECT_EVENT:
     {
       linkDBInfo_t linkInfo;
       gapLinkUpdateEvent_t *pPkt = (gapLinkUpdateEvent_t *)pMsg;

       // Get the address from the connection handle
       linkDB_GetInfo(pPkt->connectionHandle, &linkInfo);

       // Display the address of the connection update failure
       Display_printf(dispHandle, SP_ROW_CONNECTION, 0,
                      "Peer Device's Update Request Rejected 0x%h: %s", pPkt->opcode,
                      Util_convertBdAddr2Str(linkInfo.addr));

       break;
     }
#endif
#endif /* defined(CONFIG_BT_MESH_PROXY) || defined(ADD_SIMPLE_PERIPHERAL) */

    default:
#ifdef ADD_SIMPLE_PERIPHERAL
      Display_clearLines(dispHandle, SP_ROW_STATUS_1, SP_ROW_STATUS_2);
#endif // ADD_SIMPLE_PERIPHERAL
      break;
  }
}

/*********************************************************************
* @fn      bleApp_processStackMsgCB
*
* @brief   Callback for application from ble stack
*
* @param   pMessage - message from ble stack
*
* @return  None.
*/
uint8_t bleApp_processStackMsgCB(uint8_t event, uint8_t *pMessage)
{
  // ignore the event
  // Enqueue the msg in order to be excuted in the application context
  bleApp_enqueueMsg(BLEAPP_EVT_STACK_CALLBACK, pMessage);

  // not safe to dealloc, the application layer will free the msg
  return (false);
}

#ifdef OAD_SUPPORT
/*********************************************************************
* @fn      bleApp_processOadEventsInAppContext
*
* @brief   Callback from OAD to handle OAD events
*
* @param   event - event from OAD
*
* @return  None.
*/
uint8_t bleApp_processOadEventsInAppContext(uint8_t *pEventData)
{
  // Enqueue the msg in order to be excuted in the application context
  bleApp_enqueueMsg(OADAPP_EVT_CALLBACK, pEventData);

  // not safe to dealloc, the application layer will free the msg
  return (false);
}
#if defined(OAD_SUPPORT_ONCHIP)
/*********************************************************************
* @fn      bleApp_processOadResetInAppContext
*
* @brief   Callback from OAD to handle OAD reset
*
* @param   event - event from OAD
*
* @return  None.
*/
uint8_t bleApp_processOadResetInAppContext(uint8_t *pEventData)
{
  // Enqueue the msg in order to be excuted in the application context
  bleApp_enqueueMsg(OADAPP_EVT_RESET, pEventData);

  // not safe to dealloc, the application layer will free the msg
  return (false);
}
#endif // OAD_SUPPORT_ONCHIP
#endif // OAD_SUPPORT


#ifdef ADD_SIMPLE_PERIPHERAL
/*********************************************************************
* @fn      bleApp_charValueChangeCB
*
* @brief   Callback from Simple Profile indicating a characteristic
*          value change.
*
 * @param   paramId - parameter Id of the value that was changed.
*
* @return  None.
*/
static void bleApp_charValueChangeCB(uint8_t paramId)
{
  uint8_t *pValue = bleStack_malloc(sizeof(uint8_t));

  if (pValue)
  {
    *pValue = paramId;

    if(bleApp_enqueueMsg(BLEAPP_EVT_CHAR_CHANGE, pValue) != SUCCESS)
    {
      bleStack_free(pValue);
    }
  }
}
#endif // ADD_SIMPLE_PERIPHERAL

#ifdef ADD_SIMPLE_PERIPHERAL
/*********************************************************************
 * @fn      bleApp_processCharValueChangeEvt
 *
 * @brief   Process a pending Simple Profile characteristic value change
 *          event.
 *
 * @param   paramID - parameter ID of the value that was changed.
 */
static void bleApp_processCharValueChangeEvt(uint8_t paramId)
{
  uint8_t newValue;

  switch(paramId)
  {
    case SIMPLEPROFILE_CHAR1:
      SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR1, &newValue);

      Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "Char 1: %d", (uint16_t)newValue);
      break;

    case SIMPLEPROFILE_CHAR3:
      SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR3, &newValue);

      Display_printf(dispHandle, SP_ROW_STATUS_1, 0, "Char 3: %d", (uint16_t)newValue);
      break;

    default:
      // should not reach here!
      break;
  }
}
#endif // ADD_SIMPLE_PERIPHERAL

/*********************************************************************
 * @fn      bleApp_performPeriodicTask
 *
 * @brief   Perform a periodic application task. This function gets called
 *          every two seconds (BLEAPP_PERIODIC_EVT_PERIOD).
 *
 * @param   None.
 *
 * @return  None.
 */
static void bleApp_performPeriodicTask(void)
{
#if defined(USE_APP_MENU) && defined(DEBUG_MESH_APP)
  Display_printf(dispHandle, SMN_ROW_CBCK_ST, 0, "CBCK: advCb count=%04d, scanCb=%04d, beacon=%04x, msg=%04x, prov=%04x",
                                  advCb_count, scanCb_count, scanCb_beaconCount, scanCb_msgCount, scanCb_provCount);
#endif
#ifdef ADD_SIMPLE_PERIPHERAL
  uint8_t valueToCopy;

  // Call to retrieve the value of the third characteristic in the profile
  if (SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR3, &valueToCopy) == SUCCESS)
  {
    // Call to set that value of the fourth characteristic in the profile.
    // Note that if notifications of the fourth characteristic have been
    // enabled by a GATT client device, then a notification will be sent
    // every time this function is called.
    SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR4, sizeof(uint8_t),
                               &valueToCopy);
  }
#endif // ADD_SIMPLE_PERIPHERAL
}

#ifdef ADD_SIMPLE_PERIPHERAL
/*********************************************************************
 * @fn      SimplePeripheral_updateRPA
 *
 * @brief   Read the current RPA from the stack and update display
 *          if the RPA has changed.
 *
 * @param   None.
 *
 * @return  None.
 */
static void SimplePeripheral_updateRPA(void)
{
  uint8_t* pRpaNew;

  // Read the current RPA.
  pRpaNew = GAP_GetDevAddress(FALSE);

  if (memcmp(pRpaNew, rpa, B_ADDR_LEN))
  {
    // If the RPA has changed, update the display
    Display_printf(dispHandle, SP_ROW_RPA, 0, "RP Addr: %s",
                   Util_convertBdAddr2Str(pRpaNew));
    memcpy(rpa, pRpaNew, B_ADDR_LEN);
  }
}
#endif // ADD_SIMPLE_PERIPHERAL

/*********************************************************************
 * @fn      SimpleMeshNode_advCB
 *
 * @brief   GapAdv module callback, called from MESH stack
 *
 * @param   pMsg - message to process
 */
void SimpleMeshNode_advCB(uint32_t event, void *pBuf, uintptr_t arg)
{
  appGapAdvEventData_t *pData = bleStack_malloc(sizeof(appGapAdvEventData_t));

  if (pData)
  {
    pData->event = event;
    pData->pBuf = pBuf;

    if(bleApp_enqueueMsg(MESHAPP_EVT_ADV, pData) != SUCCESS)
    {
      bleStack_free(pData);
    }
  }
}
/*
 * start_provisioning.c
 *
 *  Created on: 19 janv. 2023
 *      Author: alexa
 */


#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <math.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/knl/Event.h>
#include <ti/sysbios/knl/Queue.h>
#include <ti/sysbios/knl/Semaphore.h>
#include <ti/sysbios/BIOS.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/mesh.h>
#include <bt_le_porting_layer.h>

#include <start_provisioning.h>


#include <ti/drivers/GPIO.h>
#include "ti_drivers_config.h"

#include <simple_mesh_node.h>
#include "ti_ble_mesh_config.h"
#include <simple_mesh_node_menu.h>
#include <net/buf.h>
#include <include/bluetooth/mesh/access.h>
#include "static_prov.h"

#define START_PROV_TASK_PRIORITY    3
#ifndef START_PROV_STACK_SIZE
#define START_PROV_STACK_SIZE      2248
#endif

#define GROUP_ADDR 0xc000
extern void start_prov_init(void);
uint8_t button_state = 0;
uint8_t led_state = 0;
uint16_t addr;
uint16_t mesh_device_own_addr = DEVICE_OWN_ADDRESS;
extern uint16_t mesh_btn_target_addr;
//static const uint16_t app_idx;
Task_Struct start_prov_Task;
uint8_t start_prov_Stack[START_PROV_STACK_SIZE];
Semaphore_Struct semstart_prov_Task_Struct;
Semaphore_Handle semstart_prov_Task_Handle;
Semaphore_Struct semstart_led_Task_Struct;
Semaphore_Handle semstart_led_Task_Handle;


void provision_done_cbk()
{

  GPIO_write(CONFIG_GPIO_LED_0,1);

    }

void btn1fxn_cbk(uint_least8_t index)
{
    Semaphore_post(semstart_prov_Task_Handle);
}

void btn2fxn_cbk(uint_least8_t index)
{
    Semaphore_post(semstart_led_Task_Handle);
}

void turnLed(uint8_t on_off)
{
  if (on_off)
  {
      GPIO_write(CONFIG_GPIO_LED_1,1);
  }
  else
  {
    GPIO_write(CONFIG_GPIO_LED_1,0);
  }
}

void Mesh_doButton(uint8_t index)
{


  if (index == 0) // turn LED on
  {
    MeshApp_button_pressed(1);
  }
  else if (index == 1) // turn LED off
  {
    MeshApp_button_pressed(0);
  }
}
void button_pressed_cb(struct bt_mesh_model *model,
                      struct bt_mesh_msg_ctx *ctx,
                      struct net_buf_simple *buf)
{
  // check own address

  if (ctx->addr == mesh_device_own_addr )
  {
     return;
  }

  uint8_t led_state = net_buf_simple_pull_u8(buf);
  //SimpleMeshMenu_turnLed(led_state);

  turnLed(led_state);

}

void start_prov_init(void)
{

    GPIO_init();
    GPIO_setConfig(CONFIG_GPIO_BTN1,
                   GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING);
    GPIO_setCallback(CONFIG_GPIO_BTN1,btn1fxn_cbk );
    GPIO_enableInt(CONFIG_GPIO_BTN1);

    GPIO_init();
    GPIO_setConfig(CONFIG_GPIO_BTN2,
                      GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING);
    GPIO_setCallback(CONFIG_GPIO_BTN2,btn2fxn_cbk );
    GPIO_enableInt(CONFIG_GPIO_BTN2);

    GPIO_setConfig(CONFIG_GPIO_LED_0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
    GPIO_setConfig(CONFIG_GPIO_LED_1, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
}

static void start_prov_taskFxn(UArg a0, UArg a1)
{

    start_prov_init();
    bleApp_stackInit();

   /* MeshApp_init(DEVICE_OWN_ADDRESS, UNPROVISIONED_BEACON);
    MeshApp_static_provisioning(DEVICE_OWN_ADDRESS, BT_MESH_KEY_UNUSED);*/

    for (;;)
    {

        Semaphore_pend(semstart_prov_Task_Handle, BIOS_WAIT_FOREVER);
        MeshApp_init(DEVICE_OWN_ADDRESS, UNPROVISIONED_BEACON);



        Semaphore_pend(semstart_led_Task_Handle, BIOS_WAIT_FOREVER);
        mesh_btn_target_addr = GROUP_ADDR;
        button_state = 0;
        Mesh_doButton(button_state);


   }
}

void start_prov_CreateTask(void)
{
    bleStack_createTasks();
    k_sys_work_q_init(NULL);
    Semaphore_Params semParams;
    Task_Params taskParams;

    Task_Params_init(&taskParams);
    taskParams.stack = start_prov_Stack;
    taskParams.stackSize = START_PROV_STACK_SIZE;
    taskParams.priority = START_PROV_TASK_PRIORITY;

    Task_construct(&start_prov_Task, start_prov_taskFxn, &taskParams, NULL);
    Semaphore_Params_init(&semParams);
    Semaphore_construct(&semstart_prov_Task_Struct, 0, &semParams);
    semstart_prov_Task_Handle = Semaphore_handle(
            &semstart_prov_Task_Struct);
    Semaphore_construct(&semstart_led_Task_Struct, 0, &semParams);
       semstart_led_Task_Handle = Semaphore_handle(
               &semstart_led_Task_Struct);

}

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    您能否共享蓝牙监听器日志、以便我们进行评论?

    您能否解释一下您为什么认为这两个设备会连接不同的网络? 您是否为两台设备提供了相同的凭据?

    网络中是否有其他设备? 它们是否按预期工作?

    此致、

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Clement:

    除了两个 CC2652开发套件外、我不希望其他器件相互连接。 我已通过为两者提供不同的地址和 UUID 来将它们配置为 SYSCFG、并且两者都使用静态配置。 我会尽快为您提供监听器日志。

    此致、

    Alexandra

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Alexandra:

    感谢您的评分

    如果网络仅限2个器件、则使用低功耗蓝牙比使用蓝牙网状网络更高效。

    此致、

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    由于不活动而关闭此线程。

    如果仍需要支持、请根据请求的信息打开一个新主题。

    此致、