WinCE: не удалось открыть созданный виртуальный COM-порт Bluetooth
Я пытаюсь заставить принтер Bluetooth работать на контроллере WinCE. Устройство уже установлено как доверенное в Control Panel\Bluetooth Device Property
, PIN-код аутентифицирован.
RegisterDevice
call возвращает дескриптор устройства без ошибок, но когда я пытаюсь открыть порт через CreateFileW
с OPEN_EXISTING я получил INVALID_HANDLE_VALUE
, с кодом системной ошибки 55 ERROR_DEV_NOT_EXIST
,
Я очень плохо знаком с WinCE API, также плохо знаком с C++. Я не вижу, где проблема.
Что не так с моими настройками? Есть ли какие-либо дополнительные шаги, прежде чем я смогу поговорить с принтером по этому bt-vcom?
Мое устройство - телефон HTC Diamond HTC WM5. в его Communication Manager
>Bluetooth
>COM Port
В разделе я не вижу ни одного порта, созданного мною (но кажется, что он действительно создан: указан в стороннем приложении, например TerminalCE
и сообщается как занятый при попытке создать виртуальный com-порт в графическом интерфейсе системы с этим портом.). Если я создам другой Outgoing Port
в системном графическом интерфейсе Python может программно общаться с принтером через новый порт. Разве я не использую тот же API в конце концов... почему мой не работает?
Мой код адаптирован с https://msdn.microsoft.com/en-us/library/ms881004.aspx следующим образом:
# -*- coding: utf-8 -*-
from time import sleep
import ctypes
from ctypes import POINTER, Structure
from ctypes import c_ulonglong, c_int, pointer, c_ulong, c_wchar, c_char, c_ushort
from ctypes import windll, cdll
from ctypes import memset, addressof, sizeof, byref
from comtypes import GUID
from ceserial import Serial
import wintypex as w
# in wintypex
# ULONGLONG = c_ulonglong
# bt_addr = ULONGLONG
# BT_ADDR = POINTER(bt_addr)
# BT_ADDR_PTR = POINTER(BT_ADDR)
# uiportflags
RFCOMM_PORT_FLAGS_REMOTE_DCB = 0x00000001
RFCOMM_PORT_FLAGS_KEEP_DCD = 0x00000002
RFCOMM_PORT_FLAGS_AUTHENTICATE = 0x00000004
RFCOMM_PORT_FLAGS_ENCRYPT = 0x00000008
core = windll.coredll # windll.kernel32
RegisterDevice = core.RegisterDevice # HANDLE RegisterDevice( LPCWSTR lpszType, DWORD dwIndex, LPCWSTR lpszLib, DWORD dwInfo );
RegisterDevice.restype = w.HANDLE
RegisterDevice.argtypes = [ w.LPCWSTR, w.DWORD, w.LPCWSTR, w.DWORD ]
DeregisterDevice = core.DeregisterDevice
GetLastError = core.GetLastError
SetLastError = core.SetLastError
# For BT_COM support.
class PORTEMUPortParams(Structure):
_fields_=[
( 'channel', w.INT),
( 'flocal', w.INT ),
( 'device', w.BT_ADDR),
( 'imtu', w.INT ),
( 'iminmtu', w.INT ),
( 'imaxmtu', w.INT ),
( 'isendquota', w.INT ),
( 'irecvquota', w.INT ),
( 'uuidService', GUID ),
( 'uiportflags', w.UINT)
]
def __init__( self, device_str=None,
flocal=False,
channel = None,
uuidService=None,
uiportflags=None ):
if device_str is None and not flocal:
raise Exception( 'device address missing in client mode.' )
memset( addressof(self), 0, sizeof(self) ) # memset (&pp, 0, sizeof(pp));
if not flocal:
bta = c_ulonglong( int(device_str, 16) )
print(bta)
bta_p = w.BT_ADDR( bta )
self.deivce = bta_p
self.flocal = w.INT( flocal )
# https://stackru.com/questions/27302060/how-to-check-if-an-paired-bluetooth-device-is-a-printer-or-a-scanner-android
# " Note: most common UUID (scanners, printers, Mice)
# have the generic UUID 0001101-0000-1000-8000-00805F9B34FB "
if uuidService:
self.uuidService = uuidService
else:
self.uuidService = GUID("{00001101-0000-1000-8000-00805F9B34FB}")
if uiportflags:
self.uiportflags = uiportflags
if channel:
self.channel = channel & 0xff # pp.channel = channel & 0xff;
print('class defined.')
print( "try uuidService" )
pp = PORTEMUPortParams('dc1d30428b19') # PORTEMUPortParams pp;
# pp.uiportflags = RFCOMM_PORT_FLAGS_AUTHENTICATE
# pp.uiportflags = RFCOMM_PORT_FLAGS_REMOTE_DCB
pp.uiportflags = RFCOMM_PORT_FLAGS_REMOTE_DCB | RFCOMM_PORT_FLAGS_AUTHENTICATE
#HANDLE h = RegisterDevice ("COM", index, "btd.dll", (DWORD)&pp );
for i in range (1,10):
index = i
SetLastError( w.DWORD(0) )
h = RegisterDevice(u"COM", index, u"btd.dll", w.DWORD( addressof(pp) ) )
if h :
try:
print( 'handle=', h )
print( "COM%s" % index )
s = Serial( port="COM%s:" % index, open_existing=True )
s.open()
s.write(u'HELLO\r\n')
s.flushOutput()
# s.write(u'HI\r\n')
# s.flushOutput()
s.close()
except:
pass
# sleep(2)
DeregisterDevice( h )
break
else:
print('failed', GetLastError())
sleep(1)
1 ответ
В Windows Mobile в библиотеке существует два метода для создания порта, первый - это класс BluetoothSerialPort, он сразу создает соединение, но используемый им базовый API довольно ненадежен и, похоже, совсем не работает на различных типах устройств. Вторым является BluetoothDeviceInfo.SetServiceState, как и для Win32, он вручную настраивает необходимые параметры реестра и является надежным, но может потребовать перезагрузки до того, как порт станет доступным, и снова имя нового порта не возвращается.
https://github.com/inthehand/32feet/wiki/Bluetooth-Serial-Ports
полная трата времени...
PS: для управления принтером bluetooth, упаковка функций winsock в ctypes и связь с принтером через разъем bluetooth работает без ошибок после проб и ошибок.