📄 e32btclientengine.cpp
字号:
//system include
#include <BtExtNotifiers.h>
#include <BtManClient.h>
#include <E32Math.h>
#include <F32File.h>
//use include
#include "E32BtClientEngine.h"
#include "BtDataListener.h"
const TInt KSerialUUID = 0x1101; //GPS UID
_LIT( KRFCap, "RFCOMM" );
enum TState
{
EStateNotConnected,
EStateDiscovering,
EStateQuerying,
EStateQueried,
EStateConnecting,
EStateReadingData
};
CE32BtClientEngine * CE32BtClientEngine::NewL( void )
{
CE32BtClientEngine * self = new ( ELeave ) CE32BtClientEngine( );
CleanupStack::PushL( self );
self->ConstructL( );
CleanupStack::Pop( );
return( self );
}
CE32BtClientEngine::CE32BtClientEngine( void )
:CActive( EPriorityStandard )
{
iStateMachine = EStateNotConnected;
iRemoteChannel = 255;
}
CE32BtClientEngine::~CE32BtClientEngine( void )
{
Cancel();
iFs.Close();
iTimer.Close();
iSocket.Close();
delete( iSdpAgent );
}
void CE32BtClientEngine::ConstructL( void )
{
//连接到系统服务
User::LeaveIfError( iFs.Connect() );
User::LeaveIfError( iSocketServ.Connect() );
//定时器检测数据文件
iTimer.CreateLocal();
CActiveScheduler::Add( this );
//寻找GPS设备
DiscoverRemoteL();
}
void CE32BtClientEngine::RunL( void )
{
//状态机
switch( iStateMachine )
{
case EStateDiscovering:
DiscoveredRemoteL( );
QueryRemoteL( );
break;
case EStateQueried:
ConnectRemoteL( );
break;
case EStateConnecting:
ReadDataL( );
break;
case EStateReadingData:
NotifyListener( );
ReadDataL( );
break;
}
}
void CE32BtClientEngine::DoCancel( void )
{
iTimer.Cancel( );
}
void CE32BtClientEngine::DiscoverRemoteL( void )
{
// Connect to the RNotifier
User::LeaveIfError( iNotifier.Connect( ) );
// Look for devices with services with our UUID
TBTDeviceSelectionParams filterParams;
TBTDeviceSelectionParamsPckg fpPckg( filterParams );
TUUID targetServiceClass( KSerialUUID );
filterParams.SetUUID( targetServiceClass );
// Start the notifier. The response will be in iDiscoveryResponse
iNotifier.StartNotifierAndGetResponse( iStatus,
KDeviceSelectionNotifierUid, fpPckg, iDiscoveryResponse );
// Change the state
iStateMachine = EStateDiscovering;
SetActive();
}
void CE32BtClientEngine::DiscoveredRemoteL( void )
{
// Close the notifier
iNotifier.CancelNotifier( KDeviceSelectionNotifierUid );
iNotifier.Close( );
// If the result is not a valid Bluetooth address,
// leave with KErrGeneral. Otherwise copy the address
// of the remote device.
if( iDiscoveryResponse( ).IsValidBDAddr( ) )
iRemoteAddr.SetBTAddr( iDiscoveryResponse( ).BDAddr( ) );
else
User::Leave( KErrGeneral );
}
void CE32BtClientEngine::QueryRemoteL( void )
{
// Create agent.
iSdpAgent = CSdpAgent::NewL( *this, iRemoteAddr.BTAddr( ) );
// Create a search pattern and add a service classes to it
CSdpSearchPattern * list = CSdpSearchPattern::NewL( );
list->AddL( KSerialUUID );
// Set the search pattern on the agent
iSdpAgent->SetRecordFilterL( *list );
// Get first search result: results in call back to this
iSdpAgent->NextRecordRequestL( );
// Advance the state machine
iStateMachine = EStateQuerying;
}
void CE32BtClientEngine::QueriedRemote( void )
{
// Just advance the state machine
iStateMachine = EStateQueried;
// Continue immediately
SetActive();
TRequestStatus * status = &iStatus;
User::RequestComplete( status, KErrNone );
}
void CE32BtClientEngine::ConnectRemoteL( void )
{
// If we have a proper remote channel, connect to the remote.
if( iRemoteChannel != 255 ) {
TProtocolDesc protocolDesc;
// Get protocol information on RFCOMM
User::LeaveIfError( iSocketServ.FindProtocol( KRFCap( ), protocolDesc ) );
// Open socket
User::LeaveIfError( iSocket.Open( iSocketServ, protocolDesc.iAddrFamily,
protocolDesc.iSockType, protocolDesc.iProtocol ) );
// Connect to remote
iRemoteAddr.SetPort( iRemoteChannel );
iSocket.Connect( iRemoteAddr, iStatus );
// Advance state machine
iStateMachine = EStateConnecting;
SetActive( );
}
}
void CE32BtClientEngine::ReadDataL( void )
{
// If the connect went fine, iStatus will contain KErrNone.
if( iStatus == KErrNone )
{
// Allocate memory for the actual data and wait for it.
iSocket.RecvOneOrMore( iDataBuffer, 0, iStatus, iDataLength );
// Advance the state machine
iStateMachine = EStateReadingData;
SetActive();
}
}
void CE32BtClientEngine::NotifyListener( void )
{
// If the read went fine, iStatus will contain KErrNone.
if( iStatus == KErrNone )
iListener->DataUpdate( iDataBuffer );
}
void CE32BtClientEngine::CloseRemoteL( void )
{
// Close the remote channel.
// Also removes the data file.
iSocket.Close( );
}
void CE32BtClientEngine::NextRecordRequestComplete( TInt aError, TSdpServRecordHandle aHandle, TInt /*aTotalRecordsCount*/ )
{
// We got a service record.
if ( aError != KErrNone )
{
// Some error
QueriedRemote( );
}
else
{
// Ask for the contents of the record
// Create a match list
CSdpAttrIdMatchList * matchList = CSdpAttrIdMatchList::NewL( );
CleanupStack::PushL( matchList );
// Add an attribute ID to get
matchList->AddL( TAttrRange( KSdpAttrIdProtocolDescriptorList ) );
// Set the match list on the agent
iSdpAgent->AttributeRequestL( aHandle, KSdpAttrIdProtocolDescriptorList );
CleanupStack::PopAndDestroy( ); // matchList
}
}
void CE32BtClientEngine::AttributeRequestResult( TSdpServRecordHandle /*aHandle*/, TSdpAttributeID aAttrID, CSdpAttrValue * aAttrValue)
{
// We got the contents. Use an attribute visitor to parse the results.
if( aAttrID == KSdpAttrIdProtocolDescriptorList )
aAttrValue->AcceptVisitorL( *this );
}
void CE32BtClientEngine::AttributeRequestComplete( TSdpServRecordHandle /*aHandle*/, TInt /*aError*/ )
{
// Request complete. Announce that we're done
// to the state machine.
QueriedRemote( );
}
void CE32BtClientEngine::VisitAttributeValueL( CSdpAttrValue & aValue, TSdpElementType aType )
{
// This will be called for each attribute received. It just waits for attributes
// of certain type and parses them. All other attributes are ignored.
switch( aType )
{
case ETypeUUID:
iPreviousUUID = aValue.UUID();
break;
case ETypeUint:
if( iPreviousUUID == KRFCOMM )
iRemoteChannel = aValue.Uint();
break;
default:
break;
}
}
void CE32BtClientEngine::StartListL( CSdpAttrValueList & /*aList*/ )
{
// We don't need to know about lists
}
void CE32BtClientEngine::EndListL( )
{
// We don't need to know about lists
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -