📄 bluetooth_wm.cpp
字号:
#include "StdAfx.h"
#include "BlueTooth_WM.h"
// for PORTEMUPortParams
#include <bt_api.h>
DEFINE_GUID(SerialPortServiceClass_UUID, 0x00001101, 0x0000, 0x1000, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB);
DWORD WINAPI ThreadProc_ScanNearbyBthDev(
LPVOID lpParameter // thread data
)
{
CBlueTooth_WM *pBlueTooth_WM = reinterpret_cast<CBlueTooth_WM*>(lpParameter);
if ( pBlueTooth_WM )
pBlueTooth_WM->ThreadProc_ScanNearbyBthDev ();
return TRUE;
}
CBlueTooth_WM::CBlueTooth_WM(void)
: m_hThread_ScanNearbyBthDev ( NULL )
, m_dwThreadID_ScanNearbyBthDev ( 0 )
, m_hEvtEndModule ( NULL )
, m_hEvt_Notify_ScanNearbyBthDev ( NULL )
, m_hWnd_Noify_ScanNearbyBthDev ( NULL )
, m_socketClient ( INVALID_SOCKET )
{
m_Ary_RemoteBthDevInfo.SetSize ( 0, 10*sizeof(t_RemoteBthDevInfo) );
}
CBlueTooth_WM::~CBlueTooth_WM(void)
{
if ( HANDLE_IS_VALID(m_hEvtEndModule) )
::SetEvent ( m_hEvtEndModule );
WaitForThreadEnd ( &m_hThread_ScanNearbyBthDev, 10*1000 );
SAFE_CLOSE_HANDLE ( m_hEvtEndModule );
if ( m_socketClient != INVALID_SOCKET )
closesocket ( m_socketClient );
RemoveAll_RemoteBthDevInfo ();
}
//
// 调用该类中任何函数之前必须先调用该函数来初始化
//
BOOL CBlueTooth_WM::Init ( LPCTSTR lpszCurDir )
{
m_hEvtEndModule = ::CreateEvent ( NULL, TRUE, FALSE, NULL );
if ( !HANDLE_IS_VALID(m_hEvtEndModule) )
return FALSE;
m_csCurDir = GET_SAFE_STRING(lpszCurDir);
Read_RemoteBthDevInfo_FromFile ( m_csCurDir );
return TRUE;
}
void CBlueTooth_WM::ThreadProc_ScanNearbyBthDev ()
{
int nRetValue = ScanNearbyBthDev_Direct ();
if ( HANDLE_IS_VALID(m_hEvt_Notify_ScanNearbyBthDev) )
SetEvent ( m_hEvt_Notify_ScanNearbyBthDev );
if ( IsWindow(m_hWnd_Noify_ScanNearbyBthDev) )
PostMessage ( m_hWnd_Noify_ScanNearbyBthDev, WM_SCAN_BLUETOOTH_DEVICE_FINISHED, nRetValue, 0 );
SAFE_CLOSE_HANDLE ( m_hThread_ScanNearbyBthDev );
TRACE ( L"ThreadProc_ScanNearbyBthDev END\n" );
}
//
// 搜索附近的蓝牙设备,如果指定 hEvt_Notify 或 hWnd_Noify 参数,表示异步查找,完成后以这两个参数中的一个通知调用者
// 如果这两个参数都未指定,表示同步查找,即完成后才会返回
//
BOOL CBlueTooth_WM::ScanNearbyBthDev ( HANDLE hEvt_Notify/*=NULL*/, HWND hWnd_Noify/*=NULL*/ )
{
if ( HANDLE_IS_VALID(m_hThread_ScanNearbyBthDev) ) return TRUE;
// 异步查找蓝牙设备,启动查找函数
if ( hEvt_Notify || IsWindow(hWnd_Noify) )
{
m_hEvt_Notify_ScanNearbyBthDev = hEvt_Notify;
m_hWnd_Noify_ScanNearbyBthDev = hWnd_Noify;
m_hThread_ScanNearbyBthDev = ::CreateThread ( NULL, 0, ::ThreadProc_ScanNearbyBthDev, this, 0, &m_dwThreadID_ScanNearbyBthDev );
return HANDLE_IS_VALID(m_hThread_ScanNearbyBthDev);
}
return ( ScanNearbyBthDev_Direct() >= 0 );
}
//
// 用 Socket 函数搜索附近的蓝牙设备,成功时返回设备数,否则返回-1
//
int CBlueTooth_WM::ScanNearbyBthDev_Direct ()
{
m_Ary_RemoteBthDevInfo.RemoveAll ();
SetWaitCursor ();
WSAQUERYSET querySet;
HANDLE hLookup;
DWORD flags = LUP_RETURN_NAME | LUP_RETURN_ADDR;
union
{
CHAR buf[5000];
double __unused; // ensure proper alignment
};
LPWSAQUERYSET pwsaResults = (LPWSAQUERYSET) buf;
DWORD dwSize = sizeof(buf);
BOOL bHaveName;
ZeroMemory(&querySet, sizeof(querySet));
querySet.dwSize = sizeof(querySet);
querySet.dwNameSpace = NS_BTH;
if ( ::WaitForSingleObject ( m_hEvtEndModule, 0 ) == WAIT_OBJECT_0 )
return -1;
if (ERROR_SUCCESS != WSALookupServiceBegin (&querySet, LUP_CONTAINERS, &hLookup))
{
ResotreCursor ();
MsgBoxErr ( _T("WSALookupServiceBegin failed") );
return (-1);
}
ZeroMemory(pwsaResults, sizeof(WSAQUERYSET));
pwsaResults->dwSize = sizeof(WSAQUERYSET);
pwsaResults->dwNameSpace = NS_BTH;
pwsaResults->lpBlob = NULL;
BOOL bError = FALSE;
while ( TRUE )
{
if ( ::WaitForSingleObject ( m_hEvtEndModule, 0 ) == WAIT_OBJECT_0 )
break;
if ( ERROR_SUCCESS == WSALookupServiceNext (hLookup, flags, &dwSize, pwsaResults) )
{
ASSERT (pwsaResults->dwNumberOfCsAddrs == 1);
BT_ADDR b = ((SOCKADDR_BTH *)pwsaResults->lpcsaBuffer->RemoteAddr.lpSockaddr)->btAddr;
bHaveName = pwsaResults->lpszServiceInstanceName && *(pwsaResults->lpszServiceInstanceName);
t_RemoteBthDevInfo RemoteBthDevInfo;
if ( bHaveName )
{
hwSnprintf ( RemoteBthDevInfo.szName, sizeof(RemoteBthDevInfo.szName), _T("%s"),
pwsaResults->lpszServiceInstanceName );
}
RemoteBthDevInfo.RemoteAddr = b;
CSADDR_INFO* pCSAddr = (CSADDR_INFO *)pwsaResults->lpcsaBuffer;
RemoteBthDevInfo.LocalAddr = ((SOCKADDR_BTH *)pCSAddr->LocalAddr.lpSockaddr)->btAddr;
TRACE (L"%s ( %04x%08x )\n", RemoteBthDevInfo.szName, GET_NAP(b), GET_SAP(b) );
Add_RemoteBthDevInfo ( RemoteBthDevInfo );
}
else
{
if ( WSAGetLastError() != WSA_E_NO_MORE )
{
bError = TRUE;
ResotreCursor ();
MsgBoxErr ( L"Lookup bluetooth device failed" );
}
break;
}
}
WSALookupServiceEnd(hLookup);
ResotreCursor ();
if ( bError ) return (-1);
return (int)m_Ary_RemoteBthDevInfo.GetSize();
}
CString CBlueTooth_WM::FormatBthAddress(BT_ADDR BthAddress)
{
ASSERT ( BthAddress );
BLUETOOTH_ADDRESS Address;
BYTE *pAddress = (BYTE*)&BthAddress;
CString csBthAddress;
for ( int i=0; i<LENGTH(Address.rgBytes); i++ )
{
CString csNode;
csNode.Format ( _T("%.2x"), pAddress[LENGTH(Address.rgBytes)-i-1] );
if ( !csBthAddress.IsEmpty() ) csBthAddress += ":";
csBthAddress += csNode;
}
return csBthAddress;
}
int CBlueTooth_WM::Find_RemoteBthDevInfo ( LPCTSTR lpszName_Found, t_RemoteBthDevInfo *pRemoteBthDevInfo/*=NULL*/ )
{
if ( !lpszName_Found || strlen_s(lpszName_Found) < 1 ) return -1;
for ( int i=0; i<m_Ary_RemoteBthDevInfo.GetSize(); i++ )
{
t_RemoteBthDevInfo &RemoteBthDevInfoRef = m_Ary_RemoteBthDevInfo.GetAt(i);
if ( stricmp_s ( RemoteBthDevInfoRef.szName, lpszName_Found ) == 0 )
{
if ( pRemoteBthDevInfo )
{
memcpy ( pRemoteBthDevInfo, &RemoteBthDevInfoRef, sizeof(t_RemoteBthDevInfo) );
}
return i;
}
}
return -1;
}
int CBlueTooth_WM::Find_RemoteBthDevInfo ( BT_ADDR Addr_Found, t_RemoteBthDevInfo *pRemoteBthDevInfo/*=NULL*/ )
{
for ( int i=0; i<m_Ary_RemoteBthDevInfo.GetSize(); i++ )
{
t_RemoteBthDevInfo &RemoteBthDevInfoRef = m_Ary_RemoteBthDevInfo.GetAt(i);
if ( RemoteBthDevInfoRef.RemoteAddr == Addr_Found )
{
if ( pRemoteBthDevInfo )
{
memcpy ( pRemoteBthDevInfo, &RemoteBthDevInfoRef, sizeof(t_RemoteBthDevInfo) );
}
return i;
}
}
return -1;
}
int CBlueTooth_WM::Add_RemoteBthDevInfo ( t_RemoteBthDevInfo &RemoteBthDevInfo )
{
if ( Find_RemoteBthDevInfo ( RemoteBthDevInfo.RemoteAddr ) >= 0 )
return TRUE;
m_Ary_RemoteBthDevInfo.Add ( RemoteBthDevInfo );
}
void CBlueTooth_WM::RemoveAll_RemoteBthDevInfo(void)
{
Save_RemoteBthDevInfo_ToFile ( m_csCurDir );
for ( int i=0; i<m_Ary_RemoteBthDevInfo.GetSize(); i++ )
{
t_RemoteBthDevInfo &RemoteBthDevInfo = m_Ary_RemoteBthDevInfo.GetAt(i);
}
m_Ary_RemoteBthDevInfo.RemoveAll ();
}
//
// 将周边蓝牙设备信息保存到文件中,这样就可以不用每次都重新搜索蓝牙设备了,只要当连接蓝牙设备失败的时候再重新搜索
//
BOOL CBlueTooth_WM::Save_RemoteBthDevInfo_ToFile(LPCTSTR lpszPath)
{
CString csFileName;
csFileName.Format ( L"%sRemoteBthInfo.info", GET_SAFE_STRING(lpszPath) );
CFile file;
BOOL bRet = TRUE;
TRY
{
if ( file.Open ( csFileName, CFile::modeCreate|CFile::modeWrite) )
{
for ( int i=0; i<m_Ary_RemoteBthDevInfo.GetSize(); i++ )
{
t_RemoteBthDevInfo &RemoteBthDevInfo = m_Ary_RemoteBthDevInfo.GetAt(i);
file.Write ( &RemoteBthDevInfo, sizeof(RemoteBthDevInfo) );
}
}
}
CATCH( CFileException, e )
{
e->Delete ();
bRet = FALSE;
}
END_CATCH
if ( HANDLE_IS_VALID ( file.m_hFile ) )
file.Close ();
return bRet;
}
//
// 从文件中读取上次保存的周边蓝牙设备信息,结果保存到 m_Ary_RemoteBthDevInfo 数组中
//
BOOL CBlueTooth_WM::Read_RemoteBthDevInfo_FromFile(LPCTSTR lpszPath)
{
CString csFileName;
csFileName.Format ( L"%sRemoteBthInfo.info", GET_SAFE_STRING(lpszPath) );
CFile file;
BOOL bRet = TRUE;
TRY
{
if ( file.Open ( csFileName, CFile::modeRead) )
{
while ( TRUE )
{
t_RemoteBthDevInfo RemoteBthDevInfo;
if ( file.Read ( &RemoteBthDevInfo, sizeof(t_RemoteBthDevInfo) ) != sizeof(t_RemoteBthDevInfo) )
break;
else
{
Add_RemoteBthDevInfo ( RemoteBthDevInfo );
}
}
}
}
CATCH( CFileException, e )
{
e->Delete ();
bRet = FALSE;
}
END_CATCH
if ( HANDLE_IS_VALID ( file.m_hFile ) )
file.Close ();
return bRet;
}
BOOL CBlueTooth_WM::StringToGUID ( LPCTSTR lpszGUID, GUID *pGUID)
{
if ( !lpszGUID ) return FALSE;
int data1, data2, data3;
int data4[8];
if (11 == sscanf_s(lpszGUID, L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
&data1, &data2, &data3,
&data4[0], &data4[1], &data4[2], &data4[3],
&data4[4], &data4[5], &data4[6], &data4[7])) {
pGUID->Data1 = data1;
pGUID->Data2 = data2 & 0xffff;
pGUID->Data3 = data3 & 0xffff;
for (int i = 0 ; i < 8 ; ++i)
pGUID->Data4[i] = data4[i] & 0xff;
return TRUE;
}
return FALSE;
}
//
// 连接到蓝牙服务器中的某一个服务,成功返回0,失败返回错误代码
//
int CBlueTooth_WM::ConnectToBlueToothServer ( BT_ADDR ServerAddress, LPCTSTR lpszServiceGUID )
{
if ( m_socketClient==INVALID_SOCKET )
{
GUID ServerGuid;
if ( !StringToGUID(lpszServiceGUID, &ServerGuid) )
return -1;
m_socketClient = socket (AF_BT, SOCK_STREAM, BTHPROTO_RFCOMM);
if (m_socketClient == INVALID_SOCKET)
{
return WSAGetLastError();
}
SOCKADDR_BTH sa;
memset (&sa, 0, sizeof(sa));
sa.addressFamily = AF_BT;
sa.serviceClassId = ServerGuid;
sa.btAddr = ServerAddress;
if (connect (m_socketClient, (SOCKADDR *)&sa, sizeof(sa)) == SOCKET_ERROR)
{
m_socketClient = INVALID_SOCKET;
return WSAGetLastError();
}
}
// Set nonblocking of socket
/* long cmd = FIONBIO;
u_long argp = 1; // 0 表示阻塞, 非0 表示非阻塞
BOOL err = ioctlsocket ( m_socketClient, cmd, (u_long*)&argp );
if ( err )
{
TRACE ( L"Set main socket to(#1) nonblocking failed!\n" );
}
*/
return 0;
}
//
// 断开连接
//
void CBlueTooth_WM::Disconnect ()
{
if ( m_socketClient==INVALID_SOCKET ) return;
shutdown ( m_socketClient, SD_BOTH );
closesocket ( m_socketClient );
m_socketClient = INVALID_SOCKET;
}
//
// 数据传输(收/发)
// 返回成功传输的字节数。失败时返回 -1;连接已经断开,返回 -2;处理不能立即完成,返回-3
//
int CBlueTooth_WM::Transmite ( LPVOID lpData, int nSize, BOOL bSend )
{
if ( m_socketClient==INVALID_SOCKET ) return -1;
if ( !lpData ) return -1;
if ( nSize < 1 ) return 0;
int iBytesTransmited = 0;
if ( bSend )
iBytesTransmited = send (m_socketClient, (char *)lpData, nSize, 0);
else
iBytesTransmited = recv (m_socketClient, (char *)lpData, nSize, 0);
if ( iBytesTransmited > 0 ) return iBytesTransmited;
int nLastError = WSAGetLastError ();
if ( nLastError == WSAENETDOWN || nLastError == WSAENOTCONN || nLastError == WSAENOTSOCK || nLastError == WSAESHUTDOWN ||
nLastError == WSAETIMEDOUT )
{
Disconnect ();
return -2;
}
if ( nLastError == WSAEWOULDBLOCK )
return -3;
return -1;
}
//
// 发送数据
// 返回成功发送的字节数。失败时返回 -1;连接已经断开,返回 -2;处理不能立即完成,返回-3
//
int CBlueTooth_WM::Send ( LPVOID lpData, int nSize )
{
return Transmite ( lpData, nSize, TRUE );
}
//
// 接收数据
// 返回接受到的字节数。失败时返回 -1;连接已经断开,返回 -2;处理不能立即完成,返回-3
//
int CBlueTooth_WM::Recv ( LPVOID lpData, int nSize )
{
// 得到可读的数据长度
long cmd = FIONREAD;
u_long argp = 0;
BOOL err = ioctlsocket ( m_socketClient, cmd, (u_long*)&argp );
if ( err || argp < 1 )
{
return 0;
}
return Transmite ( lpData, nSize, FALSE );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -