diff options
| author | Electric-Blue <Electric-Blue@users.noreply.github.com> | 2016-01-26 02:03:48 +0300 |
|---|---|---|
| committer | Electric-Blue <Electric-Blue@users.noreply.github.com> | 2016-01-26 02:03:48 +0300 |
| commit | 0c4a1cc1c2083a871562364de5df4f9d88ec321e (patch) | |
| tree | ddb8428845b663c078359eda4ec81bdcc157414f /nimbluez/bluetoothmsbt.nim | |
| parent | 27a7a2a18a6db8b67cbe0e86c37cb174de2a1295 (diff) | |
| download | NimBluez-0c4a1cc1c2083a871562364de5df4f9d88ec321e.tar.gz NimBluez-0c4a1cc1c2083a871562364de5df4f9d88ec321e.zip | |
First version.
Diffstat (limited to 'nimbluez/bluetoothmsbt.nim')
| -rw-r--r-- | nimbluez/bluetoothmsbt.nim | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/nimbluez/bluetoothmsbt.nim b/nimbluez/bluetoothmsbt.nim new file mode 100644 index 0000000..4d10392 --- /dev/null +++ b/nimbluez/bluetoothmsbt.nim @@ -0,0 +1,222 @@ +# Copyright (c) 2016, Maxim V. Abramov +# All rights reserved. +# Look at license.txt for more info. + +## This module is used for discovery and managing Bluetooth devices and +## services. It is based on Microsoft Bluetooth protocol stack implementation +## for Windows. + +import os, strutils, algorithm, sequtils, winlean +import msbt/ms_bluetoothapis, msbt/ms_bthsdpdef, msbt/ms_bthdef + +export BLUETOOTH_ADDRESS, BLUETOOTH_RADIO_INFO, BLUETOOTH_DEVICE_INFO + +const + ERROR_NO_MORE_ITEMS* = OSErrorCode(259) + +type + BluetoothDeviceLocalImpl* = object of RootObj ## Local Bluetooth device - + ## radio adapter. + fRadioInfo*: BLUETOOTH_RADIO_INFO + + BluetoothDeviceLocal* = ref BluetoothDeviceLocalImpl ## Local Bluetooth + ## device - radio + ## adapter reference. + + BluetoothDeviceRemoteImpl* = object of RootObj ## Remote Bluetooth device. + fDeviceInfo*: BLUETOOTH_DEVICE_INFO + + BluetoothDeviceRemote* = ref BluetoothDeviceRemoteImpl ## Remote Bluetooth + ## device reference. + + +proc CloseHandle(hObject: HANDLE): WINBOOL{.stdcall, dynlib: "kernel32", + importc: "CloseHandle".} + + +proc `$`*(ba: BLUETOOTH_ADDRESS): string = + ## Returns Bluetooth device address as a string. + let ab = map(ba.ano_116103095.rgBytes, + proc(b: byte): string = toHex(BiggestInt(b), 2)) + result = ab.reversed.join(":") + + +proc parseBluetoothAddress*(str: string): BLUETOOTH_ADDRESS = + ## Converts a string to a Bluetooth device address. + var intVals = map(str.split(':'), + proc(s: string): int = parseHexInt(s)).reversed() + for i in 0..5: + result.ano_116103095.rgBytes[i] = byte(intVals[i]) + + +proc `==`*(x, y: BLUETOOTH_ADDRESS): bool = + ## Converts a string to a Bluetooth device address. + x.ano_116103095.ullLong == y.ano_116103095.ullLong + + +iterator localDeviceHandles*(): + tuple[handle: int , info: BLUETOOTH_RADIO_INFO] {.inline.} = + ## Iterates through the local Bluetooth devices. Closes current device + ## ''handle'' at the end of the each iteration. + var + findRadioParams: BLUETOOTH_FIND_RADIO_PARAMS + findRadioHandle: HBLUETOOTH_RADIO_FIND + radioHandle: int + errorCode: OSErrorCode + + findRadioParams.dwSize = DWORD(sizeof(findRadioParams)) + try: + findRadioHandle = BluetoothFindFirstRadio(addr(findRadioParams), + addr(radioHandle)) + if findRadioHandle == 0: + errorCode = osLastError() + if errorCode != ERROR_NO_MORE_ITEMS: + raiseOSError(errorCode) + else: + while true: + var radioInfo: BLUETOOTH_RADIO_INFO + radioInfo.dwSize = DWORD(sizeof(radioInfo)) + + errorCode = BluetoothGetRadioInfo(radioHandle, addr(radioInfo)) + .OSErrorCode + if errorCode != OSErrorCode(NO_ERROR): + raiseOSError(errorCode) + + yield (handle: radioHandle, info: radioInfo) + + if CloseHandle(radioHandle) == 0: + raiseOSError(osLastError()) + radioHandle = 0; + + if BluetoothFindNextRadio(findRadioHandle, addr(radioHandle)) == 0: + errorCode = osLastError() + if errorCode != ERROR_NO_MORE_ITEMS: + raiseOSError(errorCode) + break + finally: + if findRadioHandle != 0: + if radioHandle != 0: + if CloseHandle(radioHandle) == 0: + raiseOSError(osLastError()) + if BluetoothFindRadioClose(findRadioHandle) == 0: + raiseOSError(osLastError()) + + +iterator getLocalDevices*(): BluetoothDeviceLocal {.inline.} = + ## Returns all local Blutooth radio devices. + for item in localDeviceHandles(): + yield BluetoothDeviceLocal(fRadioInfo: item.info) + + +proc getLocalDevice*(): BluetoothDeviceLocal = + ## Returns default local Bluetooth radio device. + for item in getLocalDevices(): + return item + raiseOSError(ERROR_NO_MORE_ITEMS) + + +proc getLocalDevice*(address: string): BluetoothDeviceLocal = + ## Returns local Bluetooth radio device with a specified address. + let ba = parseBluetoothAddress(address) + for item in getLocalDevices(): + if item.fRadioInfo.address == ba: + return item + raiseOSError(ERROR_NO_MORE_ITEMS) + + +proc getRemoteDevice*(address: string): BluetoothDeviceRemote = + ## Returns remote Bluetooth device with a specified address. + new(result) + result.fDeviceInfo.Address = address.parseBluetoothAddress + + +iterator remoteDeviceInfos*(radioHandle: HANDLE; + timeoutMultiplier: UCHAR; + issueInquiry: BOOL): + BLUETOOTH_DEVICE_INFO {.inline.} = + ## Iterates through the all remote Bluetooth devices visible for the + ## specified local Bluetooth radio device. + var + deviceSearchParams: BLUETOOTH_DEVICE_SEARCH_PARAMS + deviceFindHandle: HBLUETOOTH_DEVICE_FIND + errorCode: OSErrorCode + deviceInfo: BLUETOOTH_DEVICE_INFO + + deviceSearchParams.dwSize = DWORD(sizeof(deviceSearchParams)) + deviceSearchParams.fReturnAuthenticated = BOOL(true) + deviceSearchParams.fReturnRemembered = BOOL(true) + deviceSearchParams.fReturnUnknown = BOOL(true) + deviceSearchParams.fReturnConnected = BOOL(true) + deviceSearchParams.fIssueInquiry = issueInquiry + deviceSearchParams.cTimeoutMultiplier = timeoutMultiplier + deviceSearchParams.hRadio = radioHandle + + deviceInfo.dwSize = DWORD(sizeof(deviceInfo)) + + try: + deviceFindHandle = BluetoothFindFirstDevice(addr(deviceSearchParams), + addr(deviceInfo)) + if deviceFindHandle == 0: + errorCode = osLastError() + if errorCode != ERROR_NO_MORE_ITEMS: + raiseOSError(errorCode) + else: + yield deviceInfo + + while true: + var deviceInfoLoop: BLUETOOTH_DEVICE_INFO + deviceInfoLoop.dwSize = DWORD(sizeof(deviceInfoLoop)) + + if BluetoothFindNextDevice(deviceFindHandle, addr(deviceInfoLoop)) == 0: + errorCode = osLastError() + if errorCode != ERROR_NO_MORE_ITEMS: + raiseOSError(errorCode) + break + + yield deviceInfoLoop + finally: + if deviceFindHandle != 0: + if BluetoothFindDeviceClose(deviceFindHandle) == 0: + raiseOSError(errorCode) + + +proc getRemoteDevices*(device: BluetoothDeviceLocal = nil; + duration: int = 8; + flushCache: bool = true): seq[BluetoothDeviceRemote] = + ## Returns all remote Bluetooth devices visible for the specified or default + ## local Bluetooth radio device. + result = @[] + + if device != nil: + for item in localDeviceHandles(): + if item.info.address == device.fRadioInfo.address: + for deviceInfo in remoteDeviceInfos(item.handle, UCHAR(duration), + BOOL(flushCache)): + result.add(BluetoothDeviceRemote(fDeviceInfo: deviceInfo)) + else: + for deviceInfo in remoteDeviceInfos(0, UCHAR(duration), BOOL(flushCache)): + result.add(BluetoothDeviceRemote(fDeviceInfo: deviceInfo)) + + +proc address*(device: BluetoothDeviceLocal): string = + ## Returns local Bluetooth device address as a string. + $device.fRadioInfo.address + + +proc address*(device: BluetoothDeviceRemote): string = + ## Returns remote Bluetooth device address as a string. + $device.fDeviceInfo.Address + + +proc name*(device: BluetoothDeviceLocal): string = + ## Returns local Bluetooth device name. + var buf: array[BLUETOOTH_MAX_NAME_SIZE + 1, WCHAR] + copyMem(addr(buf), addr(device.fRadioInfo.szName), BLUETOOTH_MAX_NAME_SIZE) + return cast[WideCString](addr(buf)) $ BLUETOOTH_MAX_NAME_SIZE + + +proc name*(device: BluetoothDeviceRemote): string = + ## Returns remote Bluetooth device name. + var buf: array[BLUETOOTH_MAX_NAME_SIZE + 1, WCHAR] + copyMem(addr(buf), addr(device.fDeviceInfo.szName), BLUETOOTH_MAX_NAME_SIZE) + return cast[WideCString](addr(buf)) $ BLUETOOTH_MAX_NAME_SIZE |
