IoT_SCV_CH584M/APP/peripheral.c

865 lines
28 KiB
C

/********************************** (C) COPYRIGHT *******************************
* File Name : peripheral.C
* Author : WCH
* Version : V1.0
* Date : 2018/12/10
* Description : 外设从机多连接应用程序,初始化广播连接参数,然后广播,连接主机后,
* 请求更新连接参数,通过自定义服务传输数据
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
/*********************************************************************
* INCLUDES
*/
#include "CONFIG.h"
#include "devinfoservice.h"
#include "gattprofile.h"
#include "peripheral.h"
#include "bsp_iwdg.h"
#include "bsp_valve.h"
#include "bsp_uart.h"
#include "log.h"
#include "bsp_adc.h"
#include "bsp_led.h"
#include "SLEEP.h"
#include <stdbool.h>
#undef LOG_ENABLE
#define LOG_ENABLE 1
#undef LOG_TAG
#define LOG_TAG "peripheral"
/*********************************************************************
* MACROS
*/
/*********************************************************************
* CONSTANTS
*/
// How often to perform periodic event
#define SBP_PERIODIC_EVT_PERIOD 1600
// How often to perform read rssi event
#define SBP_READ_RSSI_EVT_PERIOD 3200
// Parameter update delay
#define SBP_PARAM_UPDATE_DELAY 6400
// PHY update delay
#define SBP_PHY_UPDATE_DELAY 2400
// What is the advertising interval when device is discoverable (units of 625us, 80=50ms)
#define DEFAULT_ADVERTISING_INTERVAL (160 * 15) //160 * 10
// Limited discoverable mode advertises for 30.72s, and then stops
// General discoverable mode advertises indefinitely
#define DEFAULT_DISCOVERABLE_MODE GAP_ADTYPE_FLAGS_GENERAL
// Minimum connection interval (units of 1.25ms, 6=7.5ms)
#define DEFAULT_DESIRED_MIN_CONN_INTERVAL (200) //100
// Maximum connection interval (units of 1.25ms, 100=125ms)
#define DEFAULT_DESIRED_MAX_CONN_INTERVAL (800) //400
// Slave latency to use parameter update
#define DEFAULT_DESIRED_SLAVE_LATENCY 10 //5
// Supervision timeout value (units of 10ms, 100=1s)
#define DEFAULT_DESIRED_CONN_TIMEOUT 400 //200
// Company Identifier: WCH
#define WCH_COMPANY_ID 0x07D7
#define MAC_NAME "ZBF-93:B4:8F:10:53:5C"
#define MAC_NAME_LEN 22
/*********************************************************************
* TYPEDEFS
*/
/*********************************************************************
* GLOBAL VARIABLES
*/
volatile uint8_t mtu_flag = 0;
static volatile bool periodic_upload_block_flag = false;
void BSP_NeeedReplyCMdFirst(void)
{
periodic_upload_block_flag = true;
}
void BSP_NoNeeedReplyCMd(void)
{
periodic_upload_block_flag = false;
}
/*********************************************************************
* EXTERNAL VARIABLES
*/
/*********************************************************************
* EXTERNAL FUNCTIONS
*/
/*********************************************************************
* LOCAL VARIABLES
*/
uint8_t Peripheral_TaskID = INVALID_TASK_ID; // ????/???????ID
// GAP - SCAN RSP data (max size = 31 bytes)
static uint8_t scanRspData[] = {
// complete name
0x12, // length of this data
GAP_ADTYPE_LOCAL_NAME_COMPLETE,
'I',
'o',
'T',
'z',
'b',
'f',
' ',
'P',
'e',
'r',
'i',
'p',
'h',
'e',
'r',
'a',
'l',
// connection interval range
0x05, // length of this data
GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE,
LO_UINT16(DEFAULT_DESIRED_MIN_CONN_INTERVAL), // 100ms
HI_UINT16(DEFAULT_DESIRED_MIN_CONN_INTERVAL),
LO_UINT16(DEFAULT_DESIRED_MAX_CONN_INTERVAL), // 1s
HI_UINT16(DEFAULT_DESIRED_MAX_CONN_INTERVAL),
// Tx power level
0x02, // length of this data
GAP_ADTYPE_POWER_LEVEL,
0 // 0dBm
};
// GAP - Advertisement data (max size = 31 bytes, though this is
// best kept short to conserve power while advertising)
static uint8_t advertData[] = {
// Flags; this sets the device to use limited discoverable
// mode (advertises for 30 seconds at a time) instead of general
// discoverable mode (advertises indefinitely)
0x02, // length of this data
GAP_ADTYPE_FLAGS,
DEFAULT_DISCOVERABLE_MODE | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,
// service UUID, to notify central devices what services are included
// in this peripheral
0x03, // length of this data
GAP_ADTYPE_16BIT_MORE, // some of the UUID's, but not all
LO_UINT16(SIMPLEPROFILE_SERV_UUID),
HI_UINT16(SIMPLEPROFILE_SERV_UUID)
};
// GAP GATT Attributes
static uint8_t attDeviceName[GAP_DEVICE_NAME_LEN] = "IoTzbf Peripheral";
// Connection item list
static peripheralConnItem_t peripheralConnList;
static uint16_t peripheralMTU = ATT_MTU_SIZE;
/*********************************************************************
* LOCAL FUNCTIONS
*/
static void Peripheral_ProcessTMOSMsg(tmos_event_hdr_t *pMsg);
static void peripheralStateNotificationCB(gapRole_States_t newState, gapRoleEvent_t *pEvent);
static void performPeriodicTask(void);
static void simpleProfileChangeCB(uint8_t paramID, uint8_t *pValue, uint16_t len);
static void peripheralParamUpdateCB(uint16_t connHandle, uint16_t connInterval,
uint16_t connSlaveLatency, uint16_t connTimeout);
static void peripheralInitConnItem(peripheralConnItem_t *peripheralConnList);
static void peripheralRssiCB(uint16_t connHandle, int8_t rssi);
static void peripheralChar4Notify(uint8_t *pValue, uint16_t len);
// 广播事件和连接事件回调函数声明
extern void BLE_AdvertiseEventCB(uint32_t timeUs);
extern void BLE_ConnectEventCB(uint32_t timeUs);
/*********************************************************************
* PROFILE CALLBACKS
*/
// GAP Role Callbacks
static gapRolesCBs_t Peripheral_PeripheralCBs = {
peripheralStateNotificationCB, // Profile State Change Callbacks
peripheralRssiCB, // When a valid RSSI is read from controller (not used by application)
peripheralParamUpdateCB
};
// Broadcast Callbacks
static gapRolesBroadcasterCBs_t Broadcaster_BroadcasterCBs = {
NULL, // Not used in peripheral role
NULL // Receive scan request callback
};
// GAP Bond Manager Callbacks
static gapBondCBs_t Peripheral_BondMgrCBs = {
NULL, // Passcode callback (not used by application)
NULL, // Pairing / Bonding state Callback (not used by application)
NULL // oob callback
};
// Simple GATT Profile Callbacks
static simpleProfileCBs_t Peripheral_SimpleProfileCBs = {
simpleProfileChangeCB // Characteristic value change callback
};
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/*********************************************************************
* @fn Peripheral_Init
*
* @brief Initialization function for the Peripheral App Task.
* This is called during initialization and should contain
* any application specific initialization (ie. hardware
* initialization/setup, table initialization, power up
* notificaiton ... ).
*
* @param task_id - the ID assigned by TMOS. This ID should be
* used to send messages and set timers.
*
* @return none
*/
void Peripheral_Init()
{
Peripheral_TaskID = TMOS_ProcessEventRegister(Peripheral_ProcessEvent);
// Setup the GAP Peripheral Role Profile
{
uint8_t initial_advertising_enable = TRUE;
uint16_t desired_min_interval = DEFAULT_DESIRED_MIN_CONN_INTERVAL;
uint16_t desired_max_interval = DEFAULT_DESIRED_MAX_CONN_INTERVAL;
// Set the GAP Role Parameters
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &initial_advertising_enable);
GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof(scanRspData), scanRspData);
GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData);
GAPRole_SetParameter(GAPROLE_MIN_CONN_INTERVAL, sizeof(uint16_t), &desired_min_interval);
GAPRole_SetParameter(GAPROLE_MAX_CONN_INTERVAL, sizeof(uint16_t), &desired_max_interval);
}
{
uint16_t advInt = DEFAULT_ADVERTISING_INTERVAL;
// Set advertising interval
GAP_SetParamValue(TGAP_DISC_ADV_INT_MIN, advInt);
GAP_SetParamValue(TGAP_DISC_ADV_INT_MAX, advInt);
// Enable scan req notify
GAP_SetParamValue(TGAP_ADV_SCAN_REQ_NOTIFY, ENABLE);
}
// Setup the GAP Bond Manager
{
uint32_t passkey = 0; // passkey "000000"
uint8_t pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ;
uint8_t mitm = TRUE;
uint8_t bonding = TRUE;
uint8_t ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY;
GAPBondMgr_SetParameter(GAPBOND_PERI_DEFAULT_PASSCODE, sizeof(uint32_t), &passkey);
GAPBondMgr_SetParameter(GAPBOND_PERI_PAIRING_MODE, sizeof(uint8_t), &pairMode);
GAPBondMgr_SetParameter(GAPBOND_PERI_MITM_PROTECTION, sizeof(uint8_t), &mitm);
GAPBondMgr_SetParameter(GAPBOND_PERI_IO_CAPABILITIES, sizeof(uint8_t), &ioCap);
GAPBondMgr_SetParameter(GAPBOND_PERI_BONDING_ENABLED, sizeof(uint8_t), &bonding);
}
// Initialize GATT attributes
GGS_AddService(GATT_ALL_SERVICES); // GAP
GATTServApp_AddService(GATT_ALL_SERVICES); // GATT attributes
DevInfo_AddService(); // Device Information Service
SimpleProfile_AddService(GATT_ALL_SERVICES); // Simple GATT Profile
// Set the GAP Characteristics
GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName);
// Setup the SimpleProfile Characteristic Values
{
uint8_t charValue1[SIMPLEPROFILE_CHAR1_LEN] = {0};
uint8_t charValue2[SIMPLEPROFILE_CHAR2_LEN] = {0};
uint8_t charValue3[SIMPLEPROFILE_CHAR3_LEN] = {0};
uint8_t charValue4[SIMPLEPROFILE_CHAR4_LEN] = {0};
uint8_t charValue5[SIMPLEPROFILE_CHAR5_LEN] = {0, 0, 0, 0, 0};
SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR1, SIMPLEPROFILE_CHAR1_LEN, charValue1);
SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR2, SIMPLEPROFILE_CHAR2_LEN, charValue2);
SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR3, SIMPLEPROFILE_CHAR3_LEN, charValue3);
SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR4, SIMPLEPROFILE_CHAR4_LEN, charValue4);
SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR5, SIMPLEPROFILE_CHAR5_LEN, charValue5);
}
// Init Connection Item
peripheralInitConnItem(&peripheralConnList);
// Register callback with SimpleGATTprofile
SimpleProfile_RegisterAppCBs(&Peripheral_SimpleProfileCBs);
// Register receive scan request callback
GAPRole_BroadcasterSetCB(&Broadcaster_BroadcasterCBs);
// Setup a delayed profile startup
tmos_set_event(Peripheral_TaskID, SBP_START_DEVICE_EVT);
// 注册广播事件和连接事件回调函数
LL_AdvertiseEventRegister(BLE_AdvertiseEventCB);
LL_ConnectEventRegister(BLE_ConnectEventCB);
GATT_InitClient();
}
/*********************************************************************
* @fn peripheralInitConnItem
*
* @brief Init Connection Item
*
* @param peripheralConnList -
*
* @return NULL
*/
static void peripheralInitConnItem(peripheralConnItem_t *peripheralConnList)
{
peripheralConnList->connHandle = GAP_CONNHANDLE_INIT;
peripheralConnList->connInterval = 0;
peripheralConnList->connSlaveLatency = 0;
peripheralConnList->connTimeout = 0;
}
/*********************************************************************
* @fn Peripheral_ProcessEvent
*
* @brief Peripheral 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 Peripheral_ProcessEvent(uint8_t task_id, uint16_t events)
{
// VOID task_id; // TMOS required parameter that isn't used in this function
if(events & SYS_EVENT_MSG)
{
uint8_t *pMsg;
if((pMsg = tmos_msg_receive(Peripheral_TaskID)) != NULL)
{
Peripheral_ProcessTMOSMsg((tmos_event_hdr_t *)pMsg);
// Release the TMOS message
tmos_msg_deallocate(pMsg);
}
// return unprocessed events
return (events ^ SYS_EVENT_MSG);
}
if(events & SBP_START_DEVICE_EVT)
{
// Start the Device
GAPRole_PeripheralStartDevice(Peripheral_TaskID, &Peripheral_BondMgrCBs, &Peripheral_PeripheralCBs);
return (events ^ SBP_START_DEVICE_EVT);
}
if(events & SBP_REPLY_CMD_EVT)
{
logDebug("SBP_REPLY_CMD_EVT");
peripheralChar4Notify((uint8_t *)&RelyData.buf[0], RelyData.len);
BSP_NoNeeedReplyCMd();
return (events ^ SBP_REPLY_CMD_EVT);
}
if(events & SBP_PERIODIC_EVT)
{
// Restart timer
if(periodic_upload_block_flag == false && mtu_flag == 1)
{
performPeriodicTask();
tmos_start_task(Peripheral_TaskID, SBP_PERIODIC_EVT, SBP_PERIODIC_EVT_PERIOD);
}
else
{
tmos_start_task(Peripheral_TaskID, SBP_PERIODIC_EVT, 1600 * 1);
}
return (events ^ SBP_PERIODIC_EVT);
}
if(events & SBP_PARAM_UPDATE_EVT)
{
// Send connect param update request
GAPRole_PeripheralConnParamUpdateReq(peripheralConnList.connHandle,
DEFAULT_DESIRED_MIN_CONN_INTERVAL,
DEFAULT_DESIRED_MAX_CONN_INTERVAL,
DEFAULT_DESIRED_SLAVE_LATENCY,
DEFAULT_DESIRED_CONN_TIMEOUT,
Peripheral_TaskID);
return (events ^ SBP_PARAM_UPDATE_EVT);
}
if(events & SBP_PHY_UPDATE_EVT)
{
// start phy update
PRINT("PHY Update %x...\n", GAPRole_UpdatePHY(peripheralConnList.connHandle, 0,
GAP_PHY_BIT_LE_2M, GAP_PHY_BIT_LE_2M, 0));
return (events ^ SBP_PHY_UPDATE_EVT);
}
if(events & SBP_READ_RSSI_EVT)
{
GAPRole_ReadRssiCmd(peripheralConnList.connHandle);
tmos_start_task(Peripheral_TaskID, SBP_READ_RSSI_EVT, SBP_READ_RSSI_EVT_PERIOD);
return (events ^ SBP_READ_RSSI_EVT);
}
// Discard unknown events
return 0;
}
/*********************************************************************
* @fn Peripheral_ProcessGAPMsg
*
* @brief Process an incoming task message.
*
* @param pMsg - message to process
*
* @return none
*/
static void Peripheral_ProcessGAPMsg(gapRoleEvent_t *pEvent)
{
switch(pEvent->gap.opcode)
{
case GAP_SCAN_REQUEST_EVENT:
{
// PRINT("Receive scan req from %x %x %x %x %x %x ..\n", pEvent->scanReqEvt.scannerAddr[0],
// pEvent->scanReqEvt.scannerAddr[1], pEvent->scanReqEvt.scannerAddr[2], pEvent->scanReqEvt.scannerAddr[3],
// pEvent->scanReqEvt.scannerAddr[4], pEvent->scanReqEvt.scannerAddr[5]);
break;
}
case GAP_PHY_UPDATE_EVENT:
{
PRINT("Phy update Rx:%x Tx:%x ..\n", pEvent->linkPhyUpdate.connRxPHYS, pEvent->linkPhyUpdate.connTxPHYS);
break;
}
default:
break;
}
}
/*********************************************************************
* @fn Peripheral_ProcessTMOSMsg
*
* @brief Process an incoming task message.
*
* @param pMsg - message to process
*
* @return none
*/
static void Peripheral_ProcessTMOSMsg(tmos_event_hdr_t *pMsg)
{
switch(pMsg->event)
{
case GAP_MSG_EVENT:
{
Peripheral_ProcessGAPMsg((gapRoleEvent_t *)pMsg);
break;
}
case GATT_MSG_EVENT:
{
gattMsgEvent_t *pMsgEvent;
pMsgEvent = (gattMsgEvent_t *)pMsg;
if(pMsgEvent->method == ATT_MTU_UPDATED_EVENT)
{
peripheralMTU = pMsgEvent->msg.exchangeMTUReq.clientRxMTU;
mtu_flag = 1;
logDebug("****mtu exchange: %d****", pMsgEvent->msg.exchangeMTUReq.clientRxMTU);
}
break;
}
default:
break;
}
}
/*********************************************************************
* @fn Peripheral_LinkEstablished
*
* @brief Process link established.
*
* @param pEvent - event to process
*
* @return none
*/
static void Peripheral_LinkEstablished(gapRoleEvent_t *pEvent)
{
gapEstLinkReqEvent_t *event = (gapEstLinkReqEvent_t *)pEvent;
// See if already connected
if(peripheralConnList.connHandle != GAP_CONNHANDLE_INIT)
{
GAPRole_TerminateLink(pEvent->linkCmpl.connectionHandle);
PRINT("Connection max...\n");
}
else
{
peripheralConnList.connHandle = event->connectionHandle;
peripheralConnList.connInterval = event->connInterval;
peripheralConnList.connSlaveLatency = event->connLatency;
peripheralConnList.connTimeout = event->connTimeout;
peripheralMTU = ATT_MTU_SIZE;
// Set timer for periodic event
tmos_start_task(Peripheral_TaskID, SBP_PERIODIC_EVT, SBP_PERIODIC_EVT_PERIOD);
// Set timer for param update event
tmos_start_task(Peripheral_TaskID, SBP_PARAM_UPDATE_EVT, SBP_PARAM_UPDATE_DELAY);
// Start read rssi
tmos_start_task(Peripheral_TaskID, SBP_READ_RSSI_EVT, SBP_READ_RSSI_EVT_PERIOD);
attExchangeMTUReq_t req = {
.clientRxMTU = BLE_BUFF_MAX_LEN - 4,
};
GATT_ExchangeMTU(peripheralConnList.connHandle, &req, Peripheral_TaskID);
enable_notify(peripheralConnList.connHandle, ENABLE);
logDebug("Conn %x - Int %x= %.1fms", event->connectionHandle, event->connInterval, event->connInterval * 1.25);
}
}
/*********************************************************************
* @fn Peripheral_LinkTerminated
*
* @brief Process link terminated.
*
* @param pEvent - event to process
*
* @return none
*/
static void Peripheral_LinkTerminated(gapRoleEvent_t *pEvent)
{
gapTerminateLinkEvent_t *event = (gapTerminateLinkEvent_t *)pEvent;
if(event->connectionHandle == peripheralConnList.connHandle)
{
peripheralConnList.connHandle = GAP_CONNHANDLE_INIT;
peripheralConnList.connInterval = 0;
peripheralConnList.connSlaveLatency = 0;
peripheralConnList.connTimeout = 0;
tmos_stop_task(Peripheral_TaskID, SBP_PERIODIC_EVT);
tmos_stop_task(Peripheral_TaskID, SBP_READ_RSSI_EVT);
mtu_flag = 0;
// Restart advertising
{
uint8_t advertising_enable = TRUE;
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &advertising_enable);
}
}
else
{
logError("ERR..");
}
}
/*********************************************************************
* @fn peripheralRssiCB
*
* @brief RSSI callback.
*
* @param connHandle - connection handle
* @param rssi - RSSI
*
* @return none
*/
static void peripheralRssiCB(uint16_t connHandle, int8_t rssi)
{
gValveData.rssi = rssi;
logDebug("RSSI %d dB Conn %x ", gValveData.rssi, connHandle);
}
/*********************************************************************
* @fn peripheralParamUpdateCB
*
* @brief Parameter update complete callback
*
* @param connHandle - connect handle
* connInterval - connect interval
* connSlaveLatency - connect slave latency
* connTimeout - connect timeout
*
* @return none
*/
static void peripheralParamUpdateCB(uint16_t connHandle, uint16_t connInterval,
uint16_t connSlaveLatency, uint16_t connTimeout)
{
if(connHandle == peripheralConnList.connHandle)
{
peripheralConnList.connInterval = connInterval;
peripheralConnList.connSlaveLatency = connSlaveLatency;
peripheralConnList.connTimeout = connTimeout;
logDebug("ParamUpdateCB (Handle)%x - (connInt 0x%x=%.1fms) - (connSlaveLatency) %x - (connTimeout 0x%x=%dms)",
connHandle, connInterval, connInterval * 1.25, connSlaveLatency, connTimeout * 10, connTimeout * 10);
}
else
{
logError("ERR..");
}
}
/*********************************************************************
* @fn peripheralStateNotificationCB
*
* @brief Notification from the profile of a state change.
*
* @param newState - new state
*
* @return none
*/
static void peripheralStateNotificationCB(gapRole_States_t newState, gapRoleEvent_t *pEvent)
{
switch(newState & GAPROLE_STATE_ADV_MASK)
{
case GAPROLE_STARTED:
PRINT("Initialized..\n");
break;
case GAPROLE_ADVERTISING:
if(pEvent->gap.opcode == GAP_LINK_TERMINATED_EVENT)
{
Peripheral_LinkTerminated(pEvent);
PRINT("Disconnected.. Reason:%x\n", pEvent->linkTerminate.reason);
PRINT("Advertising..\n");
}
else if(pEvent->gap.opcode == GAP_MAKE_DISCOVERABLE_DONE_EVENT)
{
PRINT("Advertising..\n");
}
break;
case GAPROLE_CONNECTED:
if(pEvent->gap.opcode == GAP_LINK_ESTABLISHED_EVENT)
{
Peripheral_LinkEstablished(pEvent);
PRINT("Connected..\n");
}
break;
case GAPROLE_CONNECTED_ADV:
if(pEvent->gap.opcode == GAP_MAKE_DISCOVERABLE_DONE_EVENT)
{
PRINT("Connected Advertising..\n");
}
break;
case GAPROLE_WAITING:
if(pEvent->gap.opcode == GAP_END_DISCOVERABLE_DONE_EVENT)
{
PRINT("Waiting for advertising..\n");
}
else if(pEvent->gap.opcode == GAP_LINK_TERMINATED_EVENT)
{
Peripheral_LinkTerminated(pEvent);
PRINT("Disconnected.. Reason:%x\n", pEvent->linkTerminate.reason);
}
else if(pEvent->gap.opcode == GAP_LINK_ESTABLISHED_EVENT)
{
if(pEvent->gap.hdr.status != SUCCESS)
{
PRINT("Waiting for advertising..\n");
}
else
{
PRINT("Error..\n");
}
}
else
{
PRINT("Error..%x\n", pEvent->gap.opcode);
}
break;
case GAPROLE_ERROR:
PRINT("Error..\n");
break;
default:
break;
}
}
/*********************************************************************
* @fn performPeriodicTask
*
* @brief Perform a periodic application task. This function gets
* called every five seconds as a result of the SBP_PERIODIC_EVT
* TMOS event. In this example, the value of the third
* characteristic in the SimpleGATTProfile service is retrieved
* from the profile, and then copied into the value of the
* the fourth characteristic.
*
* @param none
*
* @return none
*/
static void performPeriodicTask(void)
{
// ??????
gValveData.bat = BSP_ReadVbat();
if (gValveData.bat <= LOW_VABAT_CLOSE_VALUE)
{
gValveData.switch_status = kClosed;
tmos_set_event(vavle_task_id, VAVLE_CLOSE_START_EVT);
}
else if (gValveData.bat <= LOW_VABAT_ALARM_VALUE)
{
tmos_set_event(vavle_task_id, VAVLE_LOW_VBAT_ALARM_EVT);
}
logDebug("switch_status:%d Temp:%d Bat:%d Humi:%d%% RSSI: %d",
gValveData.switch_status, gValveData.temp, gValveData.bat, gValveData.humi, gValveData.rssi);
TsRawFrameData RawData;
BSP_VALVE_Generate_UploadData(&RawData);
peripheralChar4Notify(&RawData.buf[0], RawData.len);
}
/*********************************************************************
* @fn peripheralChar4Notify
*
* @brief Prepare and send simpleProfileChar4 notification
*
* @param pValue - data to notify
* len - length of data
*
* @return none
*/
static void peripheralChar4Notify(uint8_t *pValue, uint16_t len)
{
attHandleValueNoti_t noti;
if(len > (peripheralMTU - 3))
{
PRINT("Too large noti\n");
return;
}
noti.len = len;
noti.pValue = GATT_bm_alloc(peripheralConnList.connHandle, ATT_HANDLE_VALUE_NOTI, noti.len, NULL, 0);
if(noti.pValue)
{
tmos_memcpy(noti.pValue, pValue, noti.len);
if(simpleProfile_Notify(peripheralConnList.connHandle, &noti) != SUCCESS)
{
GATT_bm_free((gattMsg_t *)&noti, ATT_HANDLE_VALUE_NOTI);
}
}
}
/*********************************************************************
* @fn simpleProfileChangeCB
*
* @brief Callback from SimpleBLEProfile indicating a value change
*
* @param paramID - parameter ID of the value that was changed.
* pValue - pointer to data that was changed
* len - length of data
*
* @return none
*/
static void simpleProfileChangeCB(uint8_t paramID, uint8_t *pValue, uint16_t len)
{
BSP_NeeedReplyCMdFirst();
switch(paramID)
{
case SIMPLEPROFILE_CHAR1:
{
uint8_t newValue[SIMPLEPROFILE_CHAR1_LEN];
tmos_memcpy(newValue, pValue, len);
logDebug("profile ChangeCB CHAR1.. Start");
for (uint8_t i = 0; i < len; i++)
{
logDebug("%02x ", newValue[i]);
}
logDebug("\n profile ChangeCB CHAR1.. End");
break;
}
case SIMPLEPROFILE_CHAR3:
{
logDebug("CHAR3 Start");
uint8_t *p_rev_msg;
p_rev_msg = tmos_msg_allocate(len + 1);
if (p_rev_msg)
{
p_rev_msg[0] = len;
tmos_memcpy(&p_rev_msg[1], pValue, len);
logDebug("rece data len: %d", len);
for (uint8_t i = 0; i < len; i++) {
logDebug("pValue%d: 0x%02X", i, pValue[i]);
}
int ret = tmos_msg_send(vavle_task_id, p_rev_msg);
if (ret == SUCCESS)
{
logDebug("p_rev_msg send ret = %d", ret);
}
else
{
logError("p_rev_msg send ret = %d", ret);
}
}
else
{
logError("????");
}
logDebug("profile ChangeCB CHAR3.. End");
break;
}
default:
// should not reach here!
break;
}
}
/*********************************************************************
* @fn BLE_AdvertiseEventCB
*
* @brief 广播事件回调函数,在每次广播间隔到来时调用
*
* @param timeUs - 当前事件的时间戳(微秒)
*
* @return none
*/
void BLE_AdvertiseEventCB(uint32_t timeUs)
{
FEED_IWDG();
// PRINT("BLE_AdvertiseEventCB\n");
}
/*********************************************************************
* @fn BLE_ConnectEventCB
*
* @brief 连接事件回调函数,在每次连接间隔到来时调用
*
* @param timeUs - 当前事件的时间戳(微秒)
*
* @return none
*/
void BLE_ConnectEventCB(uint32_t timeUs)
{
FEED_IWDG();
// PRINT("BLE_ConnectEventCB\n");
}
/*********************************************************************
*********************************************************************/