Bluetooth Integration Building Bridges to Bluetooth Enabled Peripherals Ryan McMahan • Senior Software Engineer Shared Technology • Intermec Presentation Focus • Code • • • • Tight Integration with Your App Wireless Printing Wireless Scanning Microsoft APIs Multiblue • A sample application • Bluetooth Printing setup • • Switching printers Bluetooth Scanning setup • Scanner setup via ISCP (Intermec Scanner Control Protocol) • Device Discovery • • • Found device event Scanning Printing Multiblue – Application Flow 1. 2. 3. 4. 5. 6. 7. 8. Startup Scanner setup Printer setup Scan Print Switch printers Print Shutdown Multiblue - Startup • Turn the radio on • • Intermec Bluetooth Library • IBT_On() • Available in Intermec Developer Library (IDL) Why would you leave it off? • • • Power savings Security policies No radio zones Be a Good Radio Citizen • • • Try to maintain the previous radio state when exiting your app Knowing when not to turn off is easier than knowing when it is safe to turn off Intermec APIs for Bluetooth • • IBT_On IBT_Off Multiblue – Scanner Setup • Add to Data Collection – Handles all of the connection maintenance • • • Related session – “Accelerating Development with the Intermec Data Collection Engine” COM port connections are possible as well How do we know which scanner to connect to? • Device Address is the key for connections • Device Discovery • Barcode scan • Read from a file • Manually entry Avoiding Device Discovery • • Very powerful and useful Can take longer than you’d like, especially in populated areas • • • • Inquiry is traditionally fixed (approximately 10s) Device name lookup is variable (0-10s) and handled one device at a time You can skip name lookup, but results are less valuable Approximate total time in seconds • 10 + (num_devices * 3) Barcode Scan • • • Scanner – SF51 Route Printer – PB41 Depot Printer – PB42 Reading Local Device Address • 3 Steps • • • Initialize Winsock Create and bind a socket getsockname() Reading Local Device Address • Step 1: Initialize Winsock WSADATA wsaData; WORD wVer = MAKEWORD( 2, 2 ); if(WSAStartup(wVer, &wsaData) != 0) AfxMessageBox(_T("Could not initialize")); Reading Local Device Address • Step 2: Create and bind a socket SOCKET s = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM); SOCKADDR_BTH sab; memset(&sab, 0, sizeof(sab)); sab.addressFamily = AF_BTH; sab.port = 0; int len = sizeof(sab); bind(s, (sockaddr *)&sab,len); Reading Local Device Address • Step 3: getsockname if(0 == getsockname(s, (sockaddr *)&sab, &len)) code.Format(_T("%04x%08x"), GET_NAP(sab.btAddr), GET_SAP(sab.btAddr)); closesocket(s); code.MakeUpper(); m_cDeviceAddress.SetWindowText(code); Live Display • Bluetooth Scanner in Intermec Settings Multiblue – Printer Setup • • Prepare two printers – one COM port How do we know which printer to connect to? • Device Address is the key for connections • Device Discovery • Barcode scan – leverage our scanner connection • Read from a file • Manually entry Printer Self-test • • Contains useful setup information Newer products contain a Code 128 representation of the Bluetooth Device Address Device Address Separators • Common separator forms • • • • • • AA:BB:CC:11:22:33 AA.BB.CC.11.22.33 AA-BB-CC-11-22-33 AA BB CC 11 22 33 Good for humans, less interesting to computers Suggestion – include code to filter out device address separators Barcode Scan • • • Code Note: I modify the postamble Route Printer – PB41 Depot Printer – PB42 COM Port Registration • Things You Need • • • • • Could be on different COM ports • • Remote Device Address Port index – COM6 is a good choice Port prefix – COM or BSP Service UUID or RFCOMM channel We’ll make them share to illustrate deregistration The dreaded 2404 • • The device is in use by an active process and cannot be disconnected. Something is already registered on that port • Choose another port or deregister Registration Code PORTEMUPortParams pp; TCHAR prefix[3+1]; // COM or BSP pp.device = bdaddr; pp.channel = 0; // Let it auto-SDP memcpy(&pp.uuidService, &SerialPortServiceClass_UUID, sizeof(GUID)); tcscpy(prefix, L"COM"); int index = 6; hBluetoothPort = RegisterDevice(prefix, index, L"btd.dll", (DWORD)&pp); Deregistration Code DeregisterDevice(hBluetoothPort); COM Port APIs • Same as traditional COM Ports • • • • • • • CreateFile & CloseFile ReadFile & WriteFile GetCommMask & SetCommMask GetCommState & SetCommState WaitCommEvent DCB Structure Be careful with uiportflags parameter Confirmation Print • • Common technique to verify setup It can be bad • • Requires printer to be in range and turned on Could be wasteful depending on frequency of setup and app design Device Discovery • Background thread to detect location • • • Allows us to auto-switch the default printer Bluetooth GPS is perfect for this Multiblue will use this to recognize when our depot printer is ready Device Discovery Code iRet = WSALookupServiceBegin (&wsaq, LUP_CONTAINERS, phLookup); <loop on WSALookupServiceNext> iRet = WSALookupServiceNext(*phLookup, LUP_RETURN_ADDR, &dwSize, pwsaResults); if(iRet == ERROR_SUCCESS) { wsprintf(szDevice, _T("%04x%08x"), GET_NAP(((SOCKADDR_BTH *)pwsaResults->lpcsaBuffer>RemoteAddr.lpSockaddr)->btAddr), GET_SAP(((SOCKADDR_BTH *)pwsaResults->lpcsaBuffer>RemoteAddr.lpSockaddr)->btAddr)); RETAILMSG(1,(_T("\r\n %s"), szDevice)); if(_tcsicmp(szDevice, me->m_printer2) == 0) { found = TRUE; RETAILMSG(1,(_T("\r\n DING! Match on %s"), szDevice)); } } WSALookupServiceEnd(phLookup); Demo • Multiblue in action Learn More • Bluetooth Resource Kit in Intermec Developer Library • • Microsoft’s Sample Program • • • • Wp_sample2 Btsearch Installs as part of the Pocket PC 2003 SDK \Program Files\Windows CE Tools\wce420\Pocket PC 2003\Samples\Win32\Bluetooth Windows Embedded Source Tools for Bluetooth Technology • A Win32 API Wrapper that developers can expose in Visual Studio .NET or the .NET Compact Framework Questions? • Yes, I will make this code available