BLE_TYQ_BJQ_CH584M/APP/multiCentral.c

1363 lines
47 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*********************************************************************
* INCLUDES
*/
#include "CONFIG.h"
#include "gattprofile.h"
#include "multiCentral.h"
#include "bsp_uart.h"
#include "log.h"
#include "bsp_flash.h"
#include "bsp_valve.h"
#undef LOG_ENABLE
#define LOG_ENABLE 1
#define MASTER_START_EVT (0X01 << 0)
#define MASTER_CONNECT_EVT (0X01 << 1)
#define MASTER_DISCONN_EVT (0X01 << 2)
#define MASTER_DETECT_EVT (0X01 << 3)
uint8_t MasterCtrTaskId;
/*********************************************************************
* MACROS
*/
// Length of bd addr as a string
#define B_ADDR_STR_LEN 15
/*********************************************************************
* CONSTANTS
*/
// Maximum number of scan responses
#define DEFAULT_MAX_SCAN_RES 1
// Scan duration in 0.625ms
#define DEFAULT_SCAN_DURATION 1600 * 3 // 2400*0.625 = 1500ms
// Connection min interval in 1.25ms
#define DEFAULT_MIN_CONNECTION_INTERVAL (80 * 4)
// Connection max interval in 1.25ms
#define DEFAULT_MAX_CONNECTION_INTERVAL 80 * 5
// Connection supervision timeout in 10ms
#define DEFAULT_CONNECTION_TIMEOUT (100 * 3)
// Discovey mode (limited, general, all)
#define DEFAULT_DISCOVERY_MODE DEVDISC_MODE_ALL
// TRUE to use active scan
#define DEFAULT_DISCOVERY_ACTIVE_SCAN TRUE
// TRUE to use white list during discovery
#define DEFAULT_DISCOVERY_WHITE_LIST FALSE
// TRUE to use high scan duty cycle when creating link
#define DEFAULT_LINK_HIGH_DUTY_CYCLE TRUE
// TRUE to use white list when creating link
#define DEFAULT_LINK_WHITE_LIST FALSE
// Default read RSSI period in 0.625ms
#define DEFAULT_RSSI_PERIOD 4800
// Minimum connection interval (units of 1.25ms)
#define DEFAULT_UPDATE_MIN_CONN_INTERVAL DEFAULT_MIN_CONNECTION_INTERVAL
// Maximum connection interval (units of 1.25ms)
#define DEFAULT_UPDATE_MAX_CONN_INTERVAL DEFAULT_MAX_CONNECTION_INTERVAL
// Slave latency to use parameter update
#define DEFAULT_UPDATE_SLAVE_LATENCY 0
// Supervision timeout value (units of 10ms)
#define DEFAULT_UPDATE_CONN_TIMEOUT 100 * 5
// Default passcode
#define DEFAULT_PASSCODE 0
// Default GAP pairing mode
#define DEFAULT_PAIRING_MODE GAPBOND_PAIRING_MODE_WAIT_FOR_REQ
// Default MITM mode (TRUE to require passcode or OOB when pairing)
#define DEFAULT_MITM_MODE TRUE
// Default bonding mode, TRUE to bond, max bonding 6 devices
#define DEFAULT_BONDING_MODE TRUE
// Default GAP bonding I/O capabilities
#define DEFAULT_IO_CAPABILITIES GAPBOND_IO_CAP_NO_INPUT_NO_OUTPUT
// Default service discovery timer delay in 0.625ms
#define DEFAULT_SVC_DISCOVERY_DELAY 10
// Default parameter update delay in 0.625ms
#define DEFAULT_PARAM_UPDATE_DELAY 1600
// Default read or write timer delay in 0.625ms
#define DEFAULT_READ_OR_WRITE_DELAY 1600
// Default write CCCD delay in 0.625ms
#define DEFAULT_WRITE_CCCD_DELAY 1600
// Establish link timeout in 0.625ms
#define ESTABLISH_LINK_TIMEOUT 1600 * 3
// Application states
enum
{
BLE_STATE_IDLE,
BLE_STATE_CONNECTING,
BLE_STATE_CONNECTED,
BLE_STATE_DISCONNECTING
};
// Discovery states
enum
{
BLE_DISC_STATE_IDLE, // Idle
BLE_DISC_STATE_SVC, // Service discovery
BLE_DISC_STATE_CHAR, // Characteristic discovery
BLE_DISC_STATE_CCCD, // client characteristic configuration discovery
};
/*********************************************************************
* TYPEDEFS
*/
/*********************************************************************
* GLOBAL VARIABLES
*/
/*********************************************************************
* EXTERNAL VARIABLES
*/
/*********************************************************************
* EXTERNAL FUNCTIONS
*/
/*********************************************************************
* LOCAL VARIABLES
*/
// Task ID for internal task/event processing
uint8_t centralTaskId;
// Number of scan results
static uint8_t centralScanRes;
// Scan result list
static gapDevRec_t centralDevList[DEFAULT_MAX_SCAN_RES];
// Peer device address
peerAddrDefItem_t PeerAddrDef[CENTRAL_MAX_CONNECTION] = {
// {0xb6, 0xb4, 0x8f, 0x10, 0x53, 0x5c},
};
// Connection item list
centralConnItem_t centralConnList[CENTRAL_MAX_CONNECTION];
// Value to write
static uint8_t centralCharVal = 0x01;
// Value read/write toggle
static uint8_t centralDoWrite = TRUE;
/*********************************************************************
* LOCAL FUNCTIONS
*/
static void centralProcessGATTMsg(gattMsgEvent_t *pMsg);
static void centralRssiCB(uint16_t connHandle, int8_t rssi);
static void centralEventCB(gapRoleEvent_t *pEvent);
static void centralHciMTUChangeCB(uint16_t connHandle, uint16_t maxTxOctets, uint16_t maxRxOctets);
static void centralPasscodeCB(uint8_t *deviceAddr, uint16_t connectionHandle,
uint8_t uiInputs, uint8_t uiOutputs);
static void centralPairStateCB(uint16_t connHandle, uint8_t state, uint8_t status);
static uint16_t connect0_ProcessEvent(uint8_t task_id, uint16_t events);
static void central_ProcessTMOSMsg(tmos_event_hdr_t *pMsg);
static void centralGATTDiscoveryEvent(uint8_t connItem, gattMsgEvent_t *pMsg);
static void centralConnIistStartDiscovery_0(void);
static void centralAddDeviceInfo(uint8_t *pAddr, uint8_t addrType);
static void centralInitConnItem(uint8_t task_id, centralConnItem_t *centralConnList);
static uint8_t centralAddrCmp(peerAddrDefItem_t *PeerAddrDef, uint8_t *addr);
int BSP_Master_Receive_Data(uint8_t task_id, uint8_t *data, uint16_t len);
uint16_t Master_ProcessEvent(uint8_t task_id, uint16_t events);
/*********************************************************************
* PROFILE CALLBACKS
*/
// GAP Role Callbacks
static gapCentralRoleCB_t centralRoleCB = {
centralRssiCB, // RSSI callback
centralEventCB, // Event callback
centralHciMTUChangeCB // MTU change callback
};
// Bond Manager Callbacks
static gapBondCBs_t centralBondCB = {
centralPasscodeCB,
centralPairStateCB};
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/*********************************************************************
* @fn Central_Init
*
* @brief Initialization function for the Central App Task.
* This is called during initialization and should contain
* any application specific initialization (ie. hardware
* initialization/setup, table initialization, power up
* notification).
*
* @param task_id - the ID assigned by TMOS. This ID should be
* used to send messages and set timers.
*
* @return none
*/
void Central_Init()
{
centralTaskId = TMOS_ProcessEventRegister(Central_ProcessEvent);
// Setup GAP
GAP_SetParamValue(TGAP_DISC_SCAN, DEFAULT_SCAN_DURATION);
GAP_SetParamValue(TGAP_CONN_EST_INT_MIN, DEFAULT_MIN_CONNECTION_INTERVAL);
GAP_SetParamValue(TGAP_CONN_EST_INT_MAX, DEFAULT_MAX_CONNECTION_INTERVAL);
GAP_SetParamValue(TGAP_CONN_EST_SUPERV_TIMEOUT, DEFAULT_CONNECTION_TIMEOUT);
// Setup the GAP Bond Manager
{
uint32_t passkey = DEFAULT_PASSCODE;
uint8_t pairMode = DEFAULT_PAIRING_MODE;
uint8_t mitm = DEFAULT_MITM_MODE;
uint8_t ioCap = DEFAULT_IO_CAPABILITIES;
uint8_t bonding = DEFAULT_BONDING_MODE;
GAPBondMgr_SetParameter(GAPBOND_CENT_DEFAULT_PASSCODE, sizeof(uint32_t), &passkey);
GAPBondMgr_SetParameter(GAPBOND_CENT_PAIRING_MODE, sizeof(uint8_t), &pairMode);
GAPBondMgr_SetParameter(GAPBOND_CENT_MITM_PROTECTION, sizeof(uint8_t), &mitm);
GAPBondMgr_SetParameter(GAPBOND_CENT_IO_CAPABILITIES, sizeof(uint8_t), &ioCap);
GAPBondMgr_SetParameter(GAPBOND_CENT_BONDING_ENABLED, sizeof(uint8_t), &bonding);
}
// Init Connection Item
centralInitConnItem(centralTaskId, centralConnList);
// Initialize GATT Client
GATT_InitClient();
// Register to receive incoming ATT Indications/Notifications
GATT_RegisterForInd(centralTaskId);
// Setup a delayed profile startup
tmos_set_event(centralTaskId, START_DEVICE_EVT);
//用户自定义
MasterCtrTaskId = TMOS_ProcessEventRegister(Master_ProcessEvent);
tmos_set_event(MasterCtrTaskId, MASTER_START_EVT);
}
/*********************************************************************
* @fn centralInitConnItem
*
* @brief Init Connection Item
*
* @param task_id -
* centralConnList -
*
* @return NULL
*/
static void centralInitConnItem(uint8_t task_id, centralConnItem_t *centralConnList)
{
uint8_t connItem;
for (connItem = 0; connItem < CENTRAL_MAX_CONNECTION; connItem++)
{
// 每个连接的任务通过taskID区分
centralConnList[connItem].taskID = TMOS_ProcessEventRegister(Central_ProcessEvent);
centralConnList[connItem].connHandle = GAP_CONNHANDLE_INIT;
centralConnList[connItem].state = BLE_STATE_IDLE;
centralConnList[connItem].discState = BLE_DISC_STATE_IDLE;
centralConnList[connItem].procedureInProgress = FALSE;
centralConnList[connItem].charHdl = 0;
centralConnList[connItem].svcStartHdl = 0;
centralConnList[connItem].svcEndHdl = 0;
centralConnList[connItem].cccHdl = 0;
}
}
/*********************************************************************
* @fn Central_ProcessEvent
*
* @brief Central Application Task event processor. This function
* is called to process all events for the task. Events
* include timers, messages and any other user defined events.
*
* @param task_id - The TMOS assigned task ID.
* @param events - events to process. This is a bit map and can
* contain more than one event.
*
* @return events not processed
*/
uint16_t Central_ProcessEvent(uint8_t task_id, uint16_t events)
{
if (events & SYS_EVENT_MSG)
{
uint8_t *pMsg;
if ((pMsg = tmos_msg_receive(centralTaskId)) != NULL)
{
central_ProcessTMOSMsg((tmos_event_hdr_t *)pMsg);
// Release the TMOS message
tmos_msg_deallocate(pMsg);
}
// return unprocessed events
return (events ^ SYS_EVENT_MSG);
}
if (events & START_DEVICE_EVT)
{
// Start the Device
GAPRole_CentralStartDevice(centralTaskId, &centralBondCB, &centralRoleCB);
return (events ^ START_DEVICE_EVT);
}
if (events & ESTABLISH_LINK_TIMEOUT_EVT)
{
GAPRole_TerminateLink(INVALID_CONNHANDLE);
return (events ^ ESTABLISH_LINK_TIMEOUT_EVT);
}
// 连接0的任务处理
if (task_id == centralConnList[CONNECT0_ITEM].taskID)
{
return connect0_ProcessEvent(task_id, events);
}
// 连接1的任务处理
else if (task_id == centralConnList[CONNECT1_ITEM].taskID)
{
}
// 连接2的任务处理
// else if(task_id == centralConnList[CONNECT2_ITEM].taskID)
// {
// }
// Discard unknown events
return 0;
}
/*********************************************************************
* @fn connect0_ProcessEvent
*
* @brief Process an incoming task message.
*
* @param pMsg - message to process
*
* @return none
*/
static uint16_t connect0_ProcessEvent(uint8_t task_id, uint16_t events)
{
// logDebug("connect0_ProcessEvent 0x%02x", events);
if (events & START_SVC_DISCOVERY_EVT)
{
// logDebug("START_SVC_DISCOVERY_EVT");
// start service discovery
// centralConnIistStartDiscovery_0();
logDebug("发现句柄配置\r\n");
centralConnList[CONNECT0_ITEM].charHdl = 0X23;
centralConnList[CONNECT0_ITEM].charHd2 = 0X26;
centralConnList[CONNECT0_ITEM].charHd3 = 0x29;
centralConnList[CONNECT0_ITEM].charHd4 = 0x2C;
centralConnList[CONNECT0_ITEM].procedureInProgress = FALSE;
return (events ^ START_SVC_DISCOVERY_EVT);
}
if (events & START_READ_OR_WRITE_EVT)
{
logDebug("START_READ_OR_WRITE_EVT");
if (centralConnList[CONNECT0_ITEM].procedureInProgress == FALSE)
{
if (centralDoWrite)
{
// Do a write
attWriteReq_t req;
req.cmd = FALSE;
req.sig = FALSE;
req.handle = centralConnList[CONNECT0_ITEM].charHdl;
req.len = 1;
req.pValue = GATT_bm_alloc(centralConnList[CONNECT0_ITEM].connHandle, ATT_WRITE_REQ, req.len, NULL, 0);
if (req.pValue != NULL)
{
*req.pValue = centralCharVal;
if (GATT_WriteCharValue(centralConnList[CONNECT0_ITEM].connHandle, &req, centralTaskId) == SUCCESS)
{
centralConnList[CONNECT0_ITEM].procedureInProgress = TRUE;
centralDoWrite = !centralDoWrite;
tmos_start_task(centralConnList[CONNECT0_ITEM].taskID, START_READ_OR_WRITE_EVT, DEFAULT_READ_OR_WRITE_DELAY);
}
else
{
GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ);
}
}
}
else
{
// Do a read
attReadReq_t req;
req.handle = centralConnList[CONNECT0_ITEM].charHdl;
if (GATT_ReadCharValue(centralConnList[CONNECT0_ITEM].connHandle, &req, centralTaskId) == SUCCESS)
{
centralConnList[CONNECT0_ITEM].procedureInProgress = TRUE;
centralDoWrite = !centralDoWrite;
}
}
}
return (events ^ START_READ_OR_WRITE_EVT);
}
if (events & CH2_READ_EVT)
{
logDebug("CH2_READ_EVT\r\n");
if (centralConnList[CONNECT0_ITEM].procedureInProgress == FALSE)
{
// read
attReadReq_t req;
req.handle = centralConnList[CONNECT0_ITEM].charHd2;
if (GATT_ReadCharValue(centralConnList[CONNECT0_ITEM].connHandle, &req, centralTaskId) == SUCCESS)
{
centralConnList[CONNECT0_ITEM].procedureInProgress = TRUE;
tmos_start_task(centralConnList[CONNECT0_ITEM].taskID, CH2_READ_EVT, 160000);
}
}
return (events ^ CH2_READ_EVT);
}
if (events & CH3_WRITE_EVT)
{
logDebug("CH3_WRITE_EVT\r\n");
if (centralConnList[CONNECT0_ITEM].procedureInProgress == FALSE)
{
// logDebug("centralConnList CH3_WRITE_EVT\n");
static uint8_t sendcnt = 0;
attWriteReq_t req;
req.cmd = FALSE;
req.sig = FALSE;
req.handle = centralConnList[CONNECT0_ITEM].charHd3;
// logDebug("handle:%x\r\n", req.handle);
req.len = 3;
req.pValue = GATT_bm_alloc(centralConnList[CONNECT0_ITEM].connHandle, ATT_WRITE_REQ, req.len, NULL, 0);
if (req.pValue != NULL)
{
logDebug("req.pValue != NULL\r\n");
req.pValue[0] = 0x11;
req.pValue[1] = 0x22;
req.pValue[2] = sendcnt++;
if (GATT_WriteCharValue(centralConnList[CONNECT0_ITEM].connHandle, &req, centralTaskId) == SUCCESS)
{
centralConnList[CONNECT0_ITEM].procedureInProgress = TRUE;
tmos_start_task(centralConnList[CONNECT0_ITEM].taskID, CH3_WRITE_EVT, 3200);
logDebug("GATT_WriteCharValue\r\n");
}
else
{
GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ);
}
}
}
return (events ^ CH3_WRITE_EVT);
}
if (events & CH4_NOTI_EVT)
{
// logDebug("CH4_NOTI_EVT\r\n");
if (centralConnList[CONNECT0_ITEM].procedureInProgress == FALSE)
{
// Do a write
attWriteReq_t req;
logDebug("CH4_NOTI_EVT handle:%x\r\n", req.handle + 1);
req.cmd = FALSE;
req.sig = FALSE;
req.handle = centralConnList[CONNECT0_ITEM].charHd4 + 1;
req.len = 2;
req.pValue = GATT_bm_alloc(centralConnList[CONNECT0_ITEM].connHandle, ATT_WRITE_REQ, req.len, NULL, 0); // 内存申请
if (req.pValue != NULL)
{
logDebug("CH4_NOTI_EVT req.pValue != NULL\r\n");
req.pValue[0] = 1;
req.pValue[1] = 0;
if (GATT_WriteCharValue(centralConnList[CONNECT0_ITEM].connHandle, &req, centralTaskId) == SUCCESS) // 发送
{
logDebug("GATT_WriteCharValue CH4_NOTI_EVT\r\n");
centralConnList[CONNECT0_ITEM].procedureInProgress = TRUE;
}
else
{
GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ); // 释放内存
}
}
}
return (events ^ CH4_NOTI_EVT);
}
// if (events & START_WRITE_CCCD_EVT)
// {
// if (centralConnList[CONNECT0_ITEM].procedureInProgress == FALSE)
// {
// // Do a write
// attWriteReq_t req;
// req.cmd = FALSE;
// req.sig = FALSE;
// req.handle = centralConnList[CONNECT0_ITEM].cccHdl;
// req.len = 2;
// req.pValue = GATT_bm_alloc(centralConnList[CONNECT0_ITEM].connHandle, ATT_WRITE_REQ, req.len, NULL, 0);
// if (req.pValue != NULL)
// {
// req.pValue[0] = 1;
// req.pValue[1] = 0;
// if (GATT_WriteCharValue(centralConnList[CONNECT0_ITEM].connHandle, &req, centralTaskId) == SUCCESS)
// {
// centralConnList[CONNECT0_ITEM].procedureInProgress = TRUE;
// }
// else
// {
// GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ);
// }
// }
// }
// return (events ^ START_WRITE_CCCD_EVT);
// }
if (events & START_READ_RSSI_EVT)
{
GAPRole_ReadRssiCmd(centralConnList[CONNECT0_ITEM].connHandle);
tmos_start_task(centralConnList[CONNECT0_ITEM].taskID, START_READ_RSSI_EVT, DEFAULT_RSSI_PERIOD);
return (events ^ START_READ_RSSI_EVT);
}
if (events & START_PARAM_UPDATE_EVT)
{
// start connect parameter update
GAPRole_UpdateLink(centralConnList[CONNECT0_ITEM].connHandle,
DEFAULT_UPDATE_MIN_CONN_INTERVAL,
DEFAULT_UPDATE_MAX_CONN_INTERVAL,
DEFAULT_UPDATE_SLAVE_LATENCY,
DEFAULT_UPDATE_CONN_TIMEOUT);
return (events ^ START_PARAM_UPDATE_EVT);
}
// Discard unknown events
return 0;
}
/*********************************************************************
* @fn central_ProcessTMOSMsg
*
* @brief Process an incoming task message.
*
* @param pMsg - message to process
*
* @return none
*/
static void central_ProcessTMOSMsg(tmos_event_hdr_t *pMsg)
{
switch (pMsg->event)
{
case GATT_MSG_EVENT:
centralProcessGATTMsg((gattMsgEvent_t *)pMsg);
break;
}
}
/*********************************************************************
* @fn centralProcessGATTMsg
*
* @brief Process GATT messages
*
* @return none
*/
static void centralProcessGATTMsg(gattMsgEvent_t *pMsg)
{
uint8_t connItem;
for (connItem = 0; connItem < CENTRAL_MAX_CONNECTION; connItem++)
{
if (centralConnList[connItem].connHandle == pMsg->connHandle)
break;
}
if (connItem == CENTRAL_MAX_CONNECTION)
{
return;
// Should not go there
}
if (centralConnList[connItem].state != BLE_STATE_CONNECTED)
{
// In case a GATT message came after a connection has dropped,
// ignore the message
GATT_bm_free(&pMsg->msg, pMsg->method);
return;
}
if ((pMsg->method == ATT_EXCHANGE_MTU_RSP) ||
((pMsg->method == ATT_ERROR_RSP) &&
(pMsg->msg.errorRsp.reqOpcode == ATT_EXCHANGE_MTU_REQ)))
{
if (pMsg->method == ATT_ERROR_RSP)
{
uint8_t status = pMsg->msg.errorRsp.errCode;
logDebug("Exchange MTU Error: %x\r\n", status);
}
centralConnList[connItem].procedureInProgress = FALSE;
}
if (pMsg->method == ATT_MTU_UPDATED_EVENT)
{
logDebug("MTU: %x\r\n", pMsg->msg.mtuEvt.MTU);
}
if ((pMsg->method == ATT_READ_RSP) || ((pMsg->method == ATT_ERROR_RSP) && (pMsg->msg.errorRsp.reqOpcode == ATT_READ_REQ)))
{
if (pMsg->method == ATT_ERROR_RSP)
{
uint8_t status = pMsg->msg.errorRsp.errCode;
logDebug("Read Error: %x\r\n", status);
}
else
{
// After a successful read, display the read value
logDebug("Read rsp: ");
// logHexDumpAll(pMsg->msg.readRsp.pValue, pMsg->msg.readRsp.len);
}
centralConnList[connItem].procedureInProgress = FALSE;
}
else if ((pMsg->method == ATT_WRITE_RSP) || ((pMsg->method == ATT_ERROR_RSP) && (pMsg->msg.errorRsp.reqOpcode == ATT_WRITE_REQ)))
{
if (pMsg->method == ATT_ERROR_RSP == ATT_ERROR_RSP)
{
uint8_t status = pMsg->msg.errorRsp.errCode;
logDebug("Write Error: %x\r\n", status);
}
else
{
// After a succesful write, display the value that was written and increment value
logDebug("Write sent: %x\r\n", centralCharVal);
}
centralConnList[connItem].procedureInProgress = FALSE;
}
else if (pMsg->method == ATT_HANDLE_VALUE_NOTI)
{
logDebug("Noti: ");
if (connItem == CONNECT0_ITEM)
{
BSP_Master_Receive_Data(CONNECT0_ITEM, pMsg->msg.handleValueNoti.pValue, pMsg->msg.handleValueNoti.len);
}
}
else if (centralConnList[connItem].discState != BLE_DISC_STATE_IDLE)
{
centralGATTDiscoveryEvent(connItem, pMsg);
centralConnList[connItem].discState = BLE_DISC_STATE_IDLE;
}
GATT_bm_free(&pMsg->msg, pMsg->method);
}
/*********************************************************************
* @fn centralRssiCB
*
* @brief RSSI callback.
*
* @param connHandle - connection handle
* @param rssi - RSSI
*
* @return none
*/
static void centralRssiCB(uint16_t connHandle, int8_t rssi)
{
logDebug("RSSI -%d dB Conn - %x \r\n", -rssi, connHandle);
}
/*********************************************************************
* @fn centralHciMTUChangeCB
*
* @brief MTU changed callback.
*
* @param maxTxOctets - Max tx octets
* @param maxRxOctets - Max rx octets
*
* @return none
*/
static void centralHciMTUChangeCB(uint16_t connHandle, uint16_t maxTxOctets, uint16_t maxRxOctets)
{
logDebug("MTU changed: %d, %d\r\n", maxTxOctets, maxRxOctets);
// centralConnList[CONNECT0_ITEM].procedureInProgress = FALSE;
// tmos_start_task(centralConnList[CONNECT0_ITEM].taskID, CH4_NOTI_EVT, 1600);
}
/*********************************************************************
* @fn centralEventCB
*
* @brief Central event callback function.
*
* @param pEvent - pointer to event structure
*
* @return none
*/
static void centralEventCB(gapRoleEvent_t *pEvent)
{
switch (pEvent->gap.opcode)
{
case GAP_DEVICE_INIT_DONE_EVENT:
{
GAPRole_CentralCancelDiscovery();
// logDebug("停止扫描,发起直连\r\n");
// tmos_start_task(MasterCtrTaskId, MASTER_CONNECT_EVT, 800);
}
break;
case GAP_DEVICE_INFO_EVENT:
{
// Add device to list
centralAddDeviceInfo(pEvent->deviceInfo.addr, pEvent->deviceInfo.addrType);
}
break;
case GAP_DEVICE_DISCOVERY_EVENT:
{
Master_Connect();
logDebug("Connecting...\r\n");
}
break;
case GAP_LINK_ESTABLISHED_EVENT:
{
tmos_stop_task(centralTaskId, ESTABLISH_LINK_TIMEOUT_EVT);
if (pEvent->gap.hdr.status == SUCCESS)
{
uint8_t connItem;
// 查询是否有空余连接条目
for (connItem = 0; connItem < CENTRAL_MAX_CONNECTION; connItem++)
{
if (centralConnList[connItem].connHandle == GAP_CONNHANDLE_INIT)
break;
}
if (connItem == CENTRAL_MAX_CONNECTION)
{
GAPRole_TerminateLink(pEvent->linkCmpl.connectionHandle);
logDebug("Connection max...\r\n");
}
else
{
centralConnList[connItem].state = BLE_STATE_CONNECTED;
centralConnList[connItem].connHandle = pEvent->linkCmpl.connectionHandle;
logDebug("Conn %x - Int %x \r\n", pEvent->linkCmpl.connectionHandle, pEvent->linkCmpl.connInterval);
// 连接0
if (connItem == CONNECT0_ITEM)
{
centralConnList[connItem].procedureInProgress = TRUE;
// update MTU
// attExchangeMTUReq_t req =
// {
// .clientRxMTU = BLE_BUFF_MAX_LEN - 4,
// };
// GATT_ExchangeMTU(pEvent->linkCmpl.connectionHandle, &req, centralTaskId);
// Initiate service discovery
tmos_start_task(centralConnList[connItem].taskID, START_SVC_DISCOVERY_EVT, DEFAULT_SVC_DISCOVERY_DELAY);
// Initiate connect parameter update
tmos_start_task(centralConnList[connItem].taskID, START_PARAM_UPDATE_EVT, DEFAULT_PARAM_UPDATE_DELAY);
// Start RSSI polling
tmos_start_task(centralConnList[connItem].taskID, START_READ_RSSI_EVT, DEFAULT_RSSI_PERIOD);
}
logDebug("Connected...\r\n");
// See if need discover again
for (connItem = 0; connItem < CENTRAL_MAX_CONNECTION; connItem++)
{
if (centralConnList[connItem].connHandle == GAP_CONNHANDLE_INIT)
break;
}
if (connItem < CENTRAL_MAX_CONNECTION)
{
logDebug("Discovering...\r\n");
centralScanRes = 0;
}
}
}
else
{
logDebug("Connect Failed...Reason:%X\r\n", pEvent->gap.hdr.status);
logDebug("Discovering...\r\n");
centralScanRes = 0;
}
}
break;
case GAP_LINK_TERMINATED_EVENT:
{
uint8_t connItem;
for (connItem = 0; connItem < CENTRAL_MAX_CONNECTION; connItem++)
{
if (centralConnList[connItem].connHandle == pEvent->linkTerminate.connectionHandle)
break;
}
if (connItem == CENTRAL_MAX_CONNECTION)
{
// Should not go there
}
logDebug(" %x Disconnected...Reason:%x\r\n", centralConnList[connItem].connHandle, pEvent->linkTerminate.reason);
centralConnList[connItem].state = BLE_STATE_IDLE;
centralConnList[connItem].connHandle = GAP_CONNHANDLE_INIT;
centralConnList[connItem].discState = BLE_DISC_STATE_IDLE;
centralConnList[connItem].charHdl = 0;
centralConnList[connItem].procedureInProgress = FALSE;
centralScanRes = 0;
tmos_stop_task(centralConnList[connItem].taskID, START_READ_RSSI_EVT);
logDebug("Discovering...\r\n");
//更新阀门状态信息
if (bt_connect_flag == 1)
{
bt_connect_flag = 0;
valve_list.valve_data[0].valve_connct_status = FALSE;
valve_list.valve_data[0].valve_switch_status = FALSE;
valve_list.valve_data[0].valve_temp = FALSE;
BSP_Bt_Valve_Resp(kValveConncetStatus, valve_list.valve_data[0].valve_id, valve_list.valve_data[0].valve_mac, FALSE);//表示连接成功
}
}
break;
case GAP_LINK_PARAM_UPDATE_EVENT:
{
logDebug("Update %x - Int %x \r\n", pEvent->linkUpdate.connectionHandle, pEvent->linkUpdate.connInterval);
}
break;
default:
break;
}
}
/*********************************************************************
* @fn pairStateCB
*
* @brief Pairing state callback.
*
* @return none
*/
static void centralPairStateCB(uint16_t connHandle, uint8_t state, uint8_t status)
{
if (state == GAPBOND_PAIRING_STATE_STARTED)
{
logDebug("Connection %04x - Pairing started:%d\r\n", connHandle, status);
}
else if (state == GAPBOND_PAIRING_STATE_COMPLETE)
{
if (status == SUCCESS)
{
logDebug("Connection %04x - Pairing success\r\n", connHandle);
}
else
{
logDebug("Connection %04x - Pairing fail\r\n", connHandle);
}
}
else if (state == GAPBOND_PAIRING_STATE_BONDED)
{
if (status == SUCCESS)
{
logDebug("Connection %04x - Bonding success\r\n", connHandle);
}
}
else if (state == GAPBOND_PAIRING_STATE_BOND_SAVED)
{
if (status == SUCCESS)
{
logDebug("Connection %04x - Bond save success\r\n", connHandle);
}
else
{
logDebug("Connection %04x - Bond save failed: %d\r\n", connHandle, status);
}
}
}
/*********************************************************************
* @fn centralPasscodeCB
*
* @brief Passcode callback.
*
* @return none
*/
static void centralPasscodeCB(uint8_t *deviceAddr, uint16_t connectionHandle,
uint8_t uiInputs, uint8_t uiOutputs)
{
uint32_t passcode;
// Create random passcode
passcode = tmos_rand();
passcode %= 1000000;
// Display passcode to user
if (uiOutputs != 0)
{
logDebug("Passcode:%06d\r\n", (int)passcode);
}
// Send passcode response
GAPBondMgr_PasscodeRsp(connectionHandle, SUCCESS, passcode);
}
/*********************************************************************
* @fn centralConnIistStartDiscovery_0
*
* @brief Start connection 0 service discovery.
*
* @return none
*/
static void centralConnIistStartDiscovery_0(void)
{
// uint8_t uuid[ATT_BT_UUID_SIZE] = {LO_UINT16(SIMPLEPROFILE_SERV_UUID),
// HI_UINT16(SIMPLEPROFILE_SERV_UUID)};
// // Initialize cached handles
// centralConnList[CONNECT0_ITEM].svcStartHdl = centralConnList[CONNECT0_ITEM].svcEndHdl = centralConnList[CONNECT0_ITEM].charHdl = 0;
// centralConnList[CONNECT0_ITEM].discState = BLE_DISC_STATE_SVC;
// GATT_DiscPrimaryServiceByUUID(centralConnList[CONNECT0_ITEM].connHandle,
// uuid,
// ATT_BT_UUID_SIZE,
// centralTaskId);
}
/*********************************************************************
* @fn centralGATTDiscoveryEvent
*
* @brief Process GATT discovery event
*
* @return none
*/
static void centralGATTDiscoveryEvent(uint8_t connItem, gattMsgEvent_t *pMsg)
{
attReadByTypeReq_t req;
// 连接0的枚举
if (connItem == CONNECT0_ITEM)
{
logDebug("发现句柄配置\r\n");
centralConnList[connItem].charHdl = 0X23;
centralConnList[connItem].charHd2 = 0X26;
centralConnList[connItem].charHd3 = 0x29;
centralConnList[connItem].charHd4 = 0x2C;
centralConnList[connItem].procedureInProgress = FALSE;
#if 0
if (centralConnList[connItem].discState == BLE_DISC_STATE_SVC)
{
// Service found, store handles
if (pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP &&
pMsg->msg.findByTypeValueRsp.numInfo > 0)
{
centralConnList[connItem].svcStartHdl = ATT_ATTR_HANDLE(pMsg->msg.findByTypeValueRsp.pHandlesInfo, 0);
centralConnList[connItem].svcEndHdl = ATT_GRP_END_HANDLE(pMsg->msg.findByTypeValueRsp.pHandlesInfo, 0);
// Display Profile Service handle range
logDebug("Found Profile Service handle : %x ~ %x \r\n", centralConnList[connItem].svcStartHdl, centralConnList[connItem].svcEndHdl);
#if 0
for (uint16_t i = 0; i < pMsg->msg.readByGrpTypeRsp.numGrps; i++)
{
// uuid
printf("uuid = %x", BUILD_UINT16(
pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i + 4],
pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i + 5]));
// Primary Service UUID Length
printf("%02d bit x", pMsg->msg.readByGrpTypeRsp.len - 4);
// printf("att len = %d\n", pMsg->msg.readByGrpTypeRsp.len);
printf("start handle:%04x", BUILD_UINT16(
pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i],
pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i + 1]));
// Attribute End Group Handle
printf("end handle:%04x\r\n", BUILD_UINT16(
pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i + 2],
pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i + 3]));
}
#endif
}
// If procedure complete
if ((pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP &&
pMsg->hdr.status == bleProcedureComplete) ||
(pMsg->method == ATT_ERROR_RSP))
{
// Discover characteristic
// centralConnList[connItem].discState = BLE_DISC_STATE_CHAR;
// uint8_t ret = GATT_DiscAllChars(centralConnList[connItem].connHandle, 0x01, 0xFFFF, centralTaskId);
// logDebug("GATT_DiscAllChars:%02x\r\n", ret);
}
}
else if (centralConnList[connItem].discState == BLE_DISC_STATE_CHAR)
{
// Characteristic found, store handle
if (pMsg->method == ATT_READ_BY_TYPE_RSP &&
pMsg->msg.readByTypeRsp.numPairs > 0)
{
#if 0
for (unsigned char i = 0; i < pMsg->msg.readByTypeRsp.numPairs; i++)
{
// characteristic properties
uint8_t char_properties = pMsg->msg.readByTypeRsp.pDataList[pMsg->msg.readByTypeRsp.len * i + 2];
uint16_t char_value_handle = BUILD_UINT16(pMsg->msg.readByTypeRsp.pDataList[pMsg->msg.readByTypeRsp.len * i + 3],
pMsg->msg.readByTypeRsp.pDataList[pMsg->msg.readByTypeRsp.len * i + 4]);
// characteristic uuid length
uint8_t char_uuid_length = pMsg->msg.readByGrpTypeRsp.len - 5;
// uuid
uint8_t *char_uuid = &(pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i + 5]);
logDebug("|-------------------------------------|");
logDebug("char_uuid\t:");
for (uint8_t i = 0; i < char_uuid_length; i++)
{
logDebug("%02x ", char_uuid[i]);
}
logDebug("char_value_handle\t:%04x\r\n", char_value_handle);
logDebug("char_uuid_length\t:%02d bit\r\n", char_uuid_length);
uint16_t char1uuid = SIMPLEPROFILE_CHAR1_UUID;
uint16_t char2uuid = SIMPLEPROFILE_CHAR2_UUID;
uint16_t char3uuid = SIMPLEPROFILE_CHAR3_UUID;
uint16_t char4uuid = SIMPLEPROFILE_CHAR4_UUID;
if (tmos_memcmp(char_uuid, &char1uuid, 2))
{
if (char_properties & (GATT_PROP_WRITE | GATT_PROP_WRITE_NO_RSP))
{
centralConnList[connItem].charHdl = char_value_handle;
logDebug("char1 Write handle\t:%04x\r\n", char_value_handle);
centralConnList[connItem].procedureInProgress = FALSE;
// tmos_start_task(centralConnList[CONNECT0_ITEM].taskID, START_READ_OR_WRITE_EVT, 1600);
}
}
else if (tmos_memcmp(char_uuid, &char2uuid, 2))
{
if (char_properties & (GATT_PROP_READ))
{
centralConnList[connItem].charHd2 = char_value_handle;
centralConnList[connItem].procedureInProgress = FALSE;
logDebug("char2 Write handle\t:%04x\r\n", char_value_handle);
// tmos_start_task(centralConnList[CONNECT0_ITEM].taskID, CH2_READ_EVT, 2400);
}
}
else if (tmos_memcmp(char_uuid, &char3uuid, 2))
{
if (char_properties & (GATT_PROP_WRITE | GATT_PROP_WRITE_NO_RSP))
{
centralConnList[connItem].charHd3 = char_value_handle;
logDebug("char3 Write handle\t:%04x\r\n", char_value_handle);
centralConnList[connItem].procedureInProgress = FALSE;
// tmos_start_task(centralConnList[CONNECT0_ITEM].taskID, CH3_WRITE_EVT, 3200);
}
}
else if (tmos_memcmp(char_uuid, &char4uuid, 2))
{
if (char_properties & (GATT_PROP_NOTIFY))
{
centralConnList[connItem].charHd4 = char_value_handle + 1;
centralConnList[connItem].procedureInProgress = FALSE;
logDebug("char4 Write handle\t:%04x\r\n", char_value_handle);
tmos_start_task(centralConnList[CONNECT0_ITEM].taskID, CH4_NOTI_EVT, 1600);
}
}
}
#endif
}
}
#endif
}
// 连接1的枚举
// else if (connItem == CONNECT1_ITEM)
// {
// }
// 连接2的枚举
// else if(connItem == CONNECT2_ITEM)
// {
// }
}
/*********************************************************************
* @fn centralAddDeviceInfo
*
* @brief Add a device to the device discovery result list
*
* @return none
*/
static void centralAddDeviceInfo(uint8_t *pAddr, uint8_t addrType)
{
uint8_t i;
// If result count not at max
if (centralScanRes < DEFAULT_MAX_SCAN_RES)
{
// Check if device is already in scan results
for (i = 0; i < centralScanRes; i++)
{
if (tmos_memcmp(pAddr, centralDevList[i].addr, B_ADDR_LEN))
{
return;
}
}
// Add addr to scan result list
tmos_memcpy(centralDevList[centralScanRes].addr, pAddr, B_ADDR_LEN);
centralDevList[centralScanRes].addrType = addrType;
// Increment scan result count
centralScanRes++;
// Display device addr
logDebug("Device %d - Addr %x %x %x %x %x %x \r\n", centralScanRes,
centralDevList[centralScanRes - 1].addr[0],
centralDevList[centralScanRes - 1].addr[1],
centralDevList[centralScanRes - 1].addr[2],
centralDevList[centralScanRes - 1].addr[3],
centralDevList[centralScanRes - 1].addr[4],
centralDevList[centralScanRes - 1].addr[5]);
}
}
/*********************************************************************
* @fn centralAddrCmp
*
* @brief none
*
* @return none
*/
static uint8_t centralAddrCmp(peerAddrDefItem_t *PeerAddrDef, uint8_t *addr)
{
uint8_t i;
for (i = 0; i < CENTRAL_MAX_CONNECTION; i++)
{
if (tmos_memcmp(PeerAddrDef[i].peerAddr, addr, B_ADDR_LEN))
break;
}
if (i == CENTRAL_MAX_CONNECTION)
{
return FALSE;
}
else
{
return TRUE;
}
}
/************************ endfile @ central **************************/
/*用户自定义文件*/
int BSP_Master_Send(centralConnItem_t *centralConnList, uint8_t id, uint8_t *Data, uint8_t Len)
{
int ret = 0;
attWriteReq_t req;
uint8_t res;
if (centralConnList[id].state == BLE_STATE_CONNECTED) // 检查连接状态是否为连接状态
{
if (centralConnList[id].procedureInProgress == FALSE)
{
req.cmd = FALSE;
req.sig = FALSE;
req.handle = centralConnList[id].charHd3;
req.len = Len;
req.pValue = GATT_bm_alloc(centralConnList[id].connHandle, ATT_WRITE_REQ, req.len, NULL, 0);
if (req.pValue != NULL)
{
tmos_memcpy(req.pValue, Data, Len);
res = GATT_WriteCharValue(centralConnList[id].connHandle, &req, centralTaskId);
if (res == SUCCESS)
{
logDebug("\n Master Write ok");
centralConnList[id].procedureInProgress = TRUE;
ret = 0;
}
else
{
logError("\n Master Write faild= %x", res);
GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ);
ret = 1;
}
}
else
{
logError("\n alloc Faild");
ret = 2;
}
}
else
{
logError("procedureInProgress");
ret = 3;
}
}
else
{
logError("没有连接成功");
ret = 4;
}
return ret;
}
int BSP_Master_Receive_Data(uint8_t task_id, uint8_t *data, uint16_t len)
{
int ret = 0;
uint16_t index = 0;
uint8_t data_buf[64] = {0};
// 解析接收到的数据帧先寻找AA开头然后再找AA下一个字节其代表命令然后找到代表长度的值的长度的下一位其为校验码校验码后为结束码0x55
// 如果数据正确,则提取数据,不正确,则不处理
if (len < 4)
{ // 至少需要 4 个字节:起始码、长度、校验码、结束码
logError("BT 数据帧长度不足");
logHexDumpAll(data, len);
return -1;
}
while (index < len && data[index] != 0xAA) // 寻找起始码 0xAA
{
index++;
}
if (index >= len - 3) // 不够空间容纳长度、校验码和结束码
{
logError("BT 数据帧起始码错误");
logHexDumpAll(data, len);
return -2;
}
uint16_t datalength = data[index + 2]; // 读取数据长度
if (index + 3 + datalength + 1 >= len) // 检查数据长度是否合理 数据长度 + 校验码 + 结束码
{
logError("BT 数据帧长度错误");
logHexDumpAll(data, len);
return -3; //
}
uint8_t rx_sum = data[index + 3 + datalength]; // 读取校验码
uint8_t calculated_sum = _CheckSum(&data[index], datalength + 3); // 计算校验码
if (rx_sum != calculated_sum)
{
logError("BT 数据帧校验码错误 rx_sum = %02X, calculated_sum = %02X", rx_sum, calculated_sum);
logHexDumpAll(data, len);
return -4;
}
if (data[index + 3 + datalength + 1] != 0x55) // 检查结束码
{
logError("BT 数据帧结束码错误");
logHexDumpAll(data, len);
return -5;
}
// //有效数据长度
size_t data_len = (datalength + 5);
ret = data_len;
if (data[index + 1] == kCmdCloseVavle) // 0x02 代表了其是控制阀门响应
{
// logDebug("BT 控制阀门响应包");
if (data[index + datalength + 2] == 1) // 响应数据位
{
logInfo("关闭阀门成功");
}
else
{
logError("BT 控制阀门失败");
}
}
else if (data[index + 1] == kValveCmdRep) // 这个是代表了其是心跳数据包
{
logDebug("蓝牙从机心跳数据包:");
logHexDumpAll(data, data_len);
}
// 到这一步说明数据没问题,将接收到的数据通过中心任务发送出去
uint8_t *p_data;
p_data = tmos_msg_allocate(data_len);
if (p_data)
{
tmos_memcpy(p_data, data, data_len);
tmos_msg_send(BtRxTaskId, p_data);
tmos_start_task(BtRxTaskId, SYS_EVENT_MSG, 0);
}
return ret;
}
void Master_Connect(void)
{
uint8_t def_mac[6] = {0xFF};
uint8_t cnt = Flash_Get_Valve_Num();
logDebug("cnt:%d\r\n", cnt);
for (uint8_t i = 0; i < cnt; i++)
{
if (valve_list.valve_data[i].valve_id != 0)
{
logDebug("valve_id:%d\r\n", valve_list.valve_data[i].valve_id);
logHexDumpAll(valve_list.valve_data[i].valve_mac, 6);
GAPRole_CentralEstablishLink(DEFAULT_LINK_HIGH_DUTY_CYCLE,
DEFAULT_LINK_WHITE_LIST,
ADDRTYPE_PUBLIC,
valve_list.valve_data[i].valve_mac);
tmos_start_task(centralTaskId, ESTABLISH_LINK_TIMEOUT_EVT, ESTABLISH_LINK_TIMEOUT);
logDebug("Connecting...\r\n");
}
}
}
void Master_DisConnect(void)
{
GAPRole_TerminateLink(centralConnList[0].connHandle);
centralConnList[0].state = BLE_STATE_IDLE;
logDebug("主动断开连接\r\n");
}
uint16_t Master_ProcessEvent(uint8_t task_id, uint16_t events)
{
int8_t ret = 0;
uint8_t *pMsg;
uint8_t master_buf[64] = {0};
if (events & MASTER_START_EVT)
{
if (centralConnList[0].state != BLE_STATE_CONNECTED)
{
if (Flash_Get_Valve_Num())//如果有设备,发起连接
{
tmos_start_task(task_id, MASTER_CONNECT_EVT, 1600);
}
}
tmos_start_task(task_id, MASTER_DETECT_EVT, 3200);
return (events ^ MASTER_START_EVT);
}
else if(events & MASTER_DETECT_EVT)
{
if (centralConnList[0].state != BLE_STATE_CONNECTED)
{
if (Flash_Get_Valve_Num())
{
logDebug("有设备,尝试连接\r\n");
tmos_start_task(task_id, MASTER_CONNECT_EVT, 1600);
}
}
tmos_start_task(task_id, MASTER_DETECT_EVT, 3200);
return (events ^ MASTER_DETECT_EVT);
}
else if (events & MASTER_CONNECT_EVT)
{
if (centralConnList[0].state != BLE_STATE_CONNECTED)
{
Master_Connect();
}
return (events ^ MASTER_CONNECT_EVT);
}
else if (events & MASTER_DISCONN_EVT)
{
Master_DisConnect();
return (events ^ MASTER_DISCONN_EVT);
}
return 0;
}