一、Master工程框架
/------------------------------ rtls_master.c -------------------------------------------/
static void RTLSMaster_taskFxn(uintptr_t a0, uintptr_t a1)
{
safeToDealloc = RTLSMaster_processStackMsg((ICall_Hdr *)pMsg); //1、处理蓝牙协议栈事件
RTLSMaster_processAppMsg(pMsg); //处理应用层数据
}
/-------------------------------------------- rtls_master.c --------------------------------------------------/
static void RTLSMaster_processAppMsg(rmEvt_t *pMsg)//1、处理蓝牙协议栈事件
{
switch (pMsg->hdr.event)
{
case RM_EVT_RTLS_CTRL_MSG_EVT:
{
RTLSMaster_processRtlsCtrlMsg((uint8_t *)pMsg->pData); //RTLS控制消息处理
}
break;
case RM_EVT_RTLS_SRV_MSG_EVT:
{
RTLSMaster_processRtlsSrvMsg((rtlsSrv_evt_t *)pMsg->pData); //RTLS服务消息处理
}
break;
}
}
/---------------------------------------------- rtls_master.c ----------------------------------------------------/
static void RTLSMaster_processRtlsCtrlMsg(uint8_t *pMsg)
{
case RTLS_REQ_ENABLE_SYNC:
{
RTLSMaster_enableRtlsSync((rtlsEnableSync_t *)pReq->pData); //使能RTLS同步
}
break;
case RTLS_REQ_SEND_DATA:
{
RTLSMaster_sendRTLSData((rtlsPacket_t *)pReq->pData); //发送RTLS数据
}
break;
case RTLS_REQ_SET_AOA_PARAMS:
{
RTLSMaster_setAoaParamsReq((rtlsAoaConfigReq_t *)pReq->pData); //设置AOA参数
}
break;
case RTLS_REQ_AOA_ENABLE:
{
RTLSMaster_enableAoaReq((rtlsAoaEnableReq_t *)pReq->pData); //使能AOA
}
break;
case RTLS_REQ_UPDATE_CONN_INTERVAL:
{
RTLSMaster_processRTLSUpdateConnInterval((rtlsUpdateConnIntReq_t *)pReq->pData); //更新连接间隔
}
break;
}
/----------------------------------------- rtls_master.c ------------------------------------------------------------/
static void RTLSMaster_processRtlsSrvMsg(rtlsSrv_evt_t *pEvt)
{
switch (pEvt->evtType)
{
case RTLSSRV_CONNECTION_CTE_IQ_REPORT_EVT:
{
rtlsSrv_connectionIQReport_t *pReport = (rtlsSrv_connectionIQReport_t *)pEvt->evtData;
RTLSAoa_processAoaResults(pReport->connHandle, //AOA数据处理
pReport->rssi,
pReport->dataChIndex,
pReport->sampleCount,
pReport->sampleRate,
pReport->sampleSize,
pReport->sampleCtrl,
pReport->slotDuration,
pReport->numAnt,
pReport->iqSamples);
}
break;
case RTLSSRV_ANTENNA_INFORMATION_EVT:
{
// This is for demonstration purposes - we could either use RTLSCtrl_sendDebugEvent
// Or read the information by using a debugger
// rtlsSrv_antennaInfo_t *pAntInfo = (rtlsSrv_antennaInfo_t)pEvt->evtData;
}
break;
case RTLSSRV_CTE_REQUEST_FAILED_EVT:
{
RTLSCtrl_sendDebugEvt("RTLS Services CTE Req Fail", (uint32_t)pReqFail->status);
}
break;
case RTLSSRV_ERROR_EVT:
{
RTLSCtrl_sendDebugEvt("RTLS Services Error", (uint32_t)pError->errCause);
}
break;
default:
break;
}
}
1、Master怎样发送、接收数据?
Master如何把采集到的AoA数据到PC:
RTLSHost_sendMsg(RTLS_CMD_AOA_RESULT_ANGLE, HOST_ASYNC_RSP, (uint8_t *)&aoaResult, sizeof(rtlsAoaResultAngle_t));
uint8_t NPITask_sendToHost(_npiFrame_t *pMsg);
NPIUtil_enqueueMsg(npiTxQueue, syncEvent, NPITASK_TX_READY_EVENT,(unsigned char *) pMsg);
if (NPITask_events & NPITASK_TX_READY_EVENT)
{
NPITask_ProcessTXQ();
NPITL_writeTL(lastQueuedTxMsg, pMsg->dataLen + NPI_MSG_HDR_LENGTH);
transportWrite(npiTxBufLen);
NPITLUART_writeTransport();
UART_write(uartHandle, npiTxBuf, TransportTxLen);
}
Master如何接收PC端数据:(接收AoA参数设置)
void RTLSCtrl_processMessage(rtlsEvt_t *pMsg) //rtls_ctrl.c
void RTLSCtrl_processHostMessage(rtlsHostMsg_t *pHostMsg);
RTLSCtrl_setAoaParamsCmd(pHostMsg->pData); //Master接收到AoA参数设置命令
// Request RTLS App to set it's own AoA parameters
RTLSCtrl_callRtlsApp(RTLS_REQ_SET_AOA_PARAMS, (uint8_t *)pSetAoaConfigReq);
gRtlsData.appCb((uint8_t *)appReq); //调用回调下面的函数
void RTLSMaster_rtlsCtrlMsgCb(uint8_t *cmd)
{
// Enqueue the message to switch context
RTLSMaster_enqueueMsg(RM_EVT_RTLS_CTRL_MSG_EVT, SUCCESS, (uint8_t *)cmd);
}
static void RTLSMaster_processAppMsg(rmEvt_t *pMsg) //rtls_master.c
case RM_EVT_RTLS_CTRL_MSG_EVT:
{
RTLSMaster_processRtlsCtrlMsg((uint8_t *)pMsg->pData);
RTLSMaster_setAoaParamsReq((rtlsAoaConfigReq_t *)pReq->pData);
// Configure AoA receiver parameters
RTLSSrv_setConnCteReceiveParams(pConfig->connHandle,pConfig->samplingEnable,pConfig->slotDurations,pConfig->numAnt,pConfig->pAntPattern);
// Configure sample accuracy
RTLSSrv_setCteSampleAccuracy(pConfig->connHandle,pConfig->sampleRate,pConfig->sampleSize,pConfig->sampleRate,pConfig->sampleSize,pConfig->sampleCtrl);
}
2、PC是怎样接收、发送数据的?
PC接收数据:
devices = [{"com_port": "COM15", "baud_rate": 460800, "name": "CC26x2 Master"}]
master_node, passive_nodes, all_nodes = rtlsUtil.set_devices(devices)
def set_devices(self, devices_setting):
self._start_message_receiver()
def _start_message_receiver(self):
self._message_receiver_th = threading.Thread(target=self._message_receiver)
def _message_receiver(self):
while not self._message_receiver_stop:
# Get messages from manager
try:
identifier, msg_pri, msg = self._rtls_manager_subscriber.pend(block=True, timeout=0.05).as_tuple()
self._log_incoming_msg(msg, identifier)
if msg.command == 'RTLS_CMD_AOA_SET_PARAMS' and msg.payload.status == 'RTLS_SUCCESS':
sending_node.aoa_initialized = True
if msg.command in ["RTLS_CMD_AOA_RESULT_ANGLE",
"RTLS_CMD_AOA_RESULT_RAW",
"RTLS_CMD_AOA_RESULT_PAIR_ANGLES"] and msg.type == "AsyncReq":
self.aoa_results_queue.put({
"name": sending_node.name,
"type": "aoa",
"identifier": identifier,
"payload": msg.payload
})
PC发送数据:
rtlsUtil.aoa_set_params(aoa_params) //PC发送设置AoA参数给Master(调用rtlsUtiil类的aoa_set_params方法)
二、AoA采集流程梳理
第1步:
PC通过UART给Master设置AoA参数
rtlsUtil.aoa_set_params(aoa_params)
Master接收到AoA参数后进行解析,设置参数到本地
static void RTLSMaster_setAoaParamsReq(rtlsAoaConfigReq_t *pConfig)
{
...
...
// Configure AoA receiver parameters
RTLSSrv_setConnCteReceiveParams(pConfig->connHandle,
pConfig->samplingEnable,
pConfig->slotDurations,
pConfig->numAnt,
pConfig->pAntPattern);
// Configure sample accuracy
RTLSSrv_setCteSampleAccuracy(pConfig->connHandle,
pConfig->sampleRate,
pConfig->sampleSize,
pConfig->sampleRate,
pConfig->sampleSize,
pConfig->sampleCtrl);
}
第2步:
PC端发送启动AoA采集命令给Master
rtlsUtil.aoa_start(cte_length=20, cte_interval=1)
Master接收到命令后,启动AoA采集
static void RTLSMaster_enableAoaReq(rtlsAoaEnableReq_t *pReq)
{
...
// Request CTE from our peer
RTLSSrv_setConnCteRequestEnableCmd(pReq->connHandle,
pReq->enableAoa,
pReq->cteInterval,
pReq->cteLength,
RTLSSRV_CTE_TYPE_AOA);
}
第3步:
运行AoA采集任务
/-------------------------- rtls_master.c ------------------------/
// Initialize RTLS Services
RTLSSrv_init(MAX_NUM_BLE_CONNS);
RTLSSrv_register(RTLSMaster_rtlsSrvlMsgCb); //注册回调函数
/-------------------------- rtls_master.c ------------------------/
void RTLSMaster_rtlsSrvlMsgCb(rtlsSrv_evt_t *pRtlsSrvEvt)
{
// Enqueue the message to switch context
RTLSMaster_enqueueMsg(RM_EVT_RTLS_SRV_MSG_EVT, SUCCESS, (uint8_t *)pRtlsSrvEvt);
}
/-------------------------- rtls_master.c ------------------------/
static status_t RTLSMaster_enqueueMsg((uint8_t event, uint8_t state,uint8_t *pData)
{
success = Util_enqueueMsg(appMsgQueue, syncEvent, (uint8_t *)pMsg);
}
/-------------------------- util.c ------------------------/
uint8_t Util_enqueueMsg(Queue_Handle msgQueue,Event_Handle event,uint8_t *pMsg)
{
if (event)
{
Event_post(event, UTIL_QUEUE_EVENT_ID);
}
}
/-------------------------- rtls_master.c ------------------------/
#define RM_QUEUE_EVT UTIL_QUEUE_EVENT_ID // Event_Id_30
// If RTOS queue is not empty, process app message
if (events & RM_QUEUE_EVT)
{
RTLSMaster_processAppMsg(pMsg);
}
/-------------------------- rtls_master.c ------------------------/
static void RTLSMaster_processAppMsg(rmEvt_t *pMsg)
{
case RM_EVT_RTLS_SRV_MSG_EVT:
{
RTLSMaster_processRtlsSrvMsg((rtlsSrv_evt_t *)pMsg->pData);
}
break;
}
/-------------------------- rtls_master.c ------------------------/
static void RTLSMaster_processRtlsSrvMsg(rtlsSrv_evt_t *pEvt)
{
switch (pEvt->evtType)
{
case RTLSSRV_CONNECTION_CTE_IQ_REPORT_EVT:
{
rtlsSrv_connectionIQReport_t *pReport = (rtlsSrv_connectionIQReport_t *)pEvt->evtData;
RTLSAoa_processAoaResults(pReport->connHandle,
pReport->rssi,
pReport->dataChIndex,
pReport->sampleCount,
pReport->sampleRate,
pReport->sampleSize,
pReport->sampleCtrl,
pReport->slotDuration,
pReport->numAnt,
pReport->iqSamples);
}
}
}
/-------------------------- rtls_aoa.c ------------------------/
void RTLSAoa_processAoaResults(uint16_t connHandle, int8_t rssi, uint8_t channel, uint16_t numIqSamples, uint8_t sampleRate, uint8_t sampleSize, uint8_t sampleCtrl, uint8_t slotDuration, uint8_t numAnt, int8_t *pIQ)
{
RTLSCtrl_aoaResultEvt(connHandle, rssi, channel, numIqSamples, sampleRate, sampleSize, sampleCtrl, slotDuration, numAnt, pIQ);
}
/-------------------------- rtls_ctrl.c ------------------------/
void RTLSCtrl_aoaResultEvt(uint16_t connHandle, int8_t rssi, uint8_t channel, uint16_t numIqSamples,
uint8_t sampleRate, uint8_t sampleSize, uint8_t sampleCtrl, uint8_t slotDuration,
uint8_t numAnt, int8_t *pIQ)
{
// Copy data
pEvt->connHandle = connHandle;
pEvt->rssi = rssi;
pEvt->channel = channel;
pEvt->numIqSamples = numIqSamples;
pEvt->sampleCtrl = sampleCtrl;
pEvt->sampleRate = sampleRate;
pEvt->sampleSize = sampleSize;
pEvt->slotDuration = slotDuration;
pEvt->numAnt = numAnt;
pEvt->pIQ = pIQ;
// Enqueue the event
RTLSCtrl_enqueueMsg(AOA_RESULTS_EVENT, (uint8_t *)pEvt);
}
/-------------------------- rtls_ctrl.c ------------------------/
void RTLSCtrl_processMessage(rtlsEvt_t *pMsg)
{
case AOA_RESULTS_EVENT:
{
RTLSCtrl_postProcessAoa((rtlsAoaIqEvt_t *)pMsg->pData);
}
}
/-------------------------- rtls_ctrl_aoa.c ------------------------/
void RTLSCtrl_postProcessAoa(rtlsAoaIqEvt_t *pEvt)
{
aoaTempResult = RTLSCtrl_estimateAngle(connHandle, sampleCtrl);
RTLSHost_sendMsg(RTLS_CMD_AOA_RESULT_PAIR_ANGLES, HOST_ASYNC_RSP, (uint8_t *)&aoaResult, sizeof(rtlsAoaResultPairAngles_t));
}
/------------------------------ rtls_ctrl_aoa.c ------------------------/
AoA_Sample_t RTLSCtrl_estimateAngle(uint16_t connHandle, uint8_t sampleCtrl)
{
// Return results
AoA.angle = gAoaCb.connResInfo[connHandle].AoA_ma.AoA;
AoA.rssi = gAoaCb.connResInfo[connHandle].AoA_ma.currentRssi;
AoA.channel = gAoaCb.connResInfo[connHandle].AoA_ma.currentCh;
AoA.antenna = gAoaCb.connResInfo[connHandle].AoA_ma.currentAntennaArray;
return AoA;
}
第4步:
通过UART发送AoA采集数据到PC端:
RTLSHost_sendMsg(RTLS_CMD_AOA_RESULT_PAIR_ANGLES, HOST_ASYNC_RSP, (uint8_t *)&aoaResult, sizeof(rtlsAoaResultPairAngles_t));
PC端接收并进行数据解析:
# Setup thread to pull out received data from devices on screen
th_aoa_results_parsing = threading.Thread(target=results_parsing, args=(rtlsUtil.aoa_results_queue,))
## User function to proces
def results_parsing(q):
while True:
try:
data = q.get(block=True, timeout=0.5)
if isinstance(data, dict):
data_time = datetime.datetime.now().strftime("[%m:%d:%Y %H:%M:%S:%f] :")
print(f"{data_time} {json.dumps(data)}")