Windows Moible, Wince 使用.NET Compact Framework的进行蓝牙(Bluetooth)开发 之 蓝牙虚拟串口 (Bluetooth Virtual Serial Port)

简介:

在之前的两篇文章分别讲述了在.NET Compact Framework下使用Windows Embedded Source Tools for Bluetooth和32feet.NET进行Bluetooth的开发,链接如下:
.NET Compact Framework下的Bluetooth开发 之 Windows Embedded Source Tools for Bluetooth 
.NET Compact Framework下的Bluetooth开发 之 32feet.NET 
在这篇文章讲述Bluetooth Virtual Serial Port的开发,所谓Bluetooth Virtual Serial Port,其实是从软件的角度看,把Bluetooth的通信转化成Serial Port(串口)。经过这样的转换后,使用Bluetooth的Client程序可以像使用串口一样操作Bluetooth。这个应用方式的出现是为了支持现有应用(Legacy system,遗产应用)。举个例子,在Bluetooth出现以前,大部分移动设备都是通过串口连接的GPS receiver的,基于GPS应用程序的开发也就通过的串口通信取出NMEA data。关于GPS NMEA data的开发可以参考 .NET Compact Framework下的GPS NMEA data数据分析 。串口的开发可以参考.NET Compact Framework下的串口通信。随着Bluetooth的普及,移动设备可以通过Bluetooth来连接GPS receiver了,那么原先基于GPS的应用程序需要重新开发通信部分去读取NMEA data,这为现有应用带来很多麻烦,所有的现有应用都需要重写通信部分,因此人们想出解决方法,把Bluetooth的通信转化成Serial Port(串口)。硬件上使用Bluetooth来进行通信,在软件上虚拟一个串口给应用程序,应用程序不需要任何的修改就可以支持Bluetooth的GPS Receiver了。这就像设计模式里面的Adapter模式,但是这里是为新设备提供原有的接口,使得原先的Client不需要更改。

由于Bluetooth Virtual Serial Port的出现基于对现有系统(Legacy System)支持的需求,所以对于新的系统,MS不推荐使用Bluetooth Virtual Serial Port,而是直接使用Winsock进行通信。在使用Winsock进行Bluetooth通信需要指定服务,因此可以指定使用串口服务进行通信。Bluetooth Virtual Serial Port和Winsock的Bluetooth通信都是使用RFCOMM协议,所以两者等同。使用Winsock的Bluetooth通信比Bluetooth Virtual Serial Port更简单,不需要配置。而且更强壮(robust),因为使用Winsock的Bluetooth通信可以直接监听到蓝牙设备关闭或者离开通信范围,而Bluetooth Virtual Serial Port只能通过Timeout来检查。

由于支持现有系统(Legacy System),Bluetooth Virtual Serial Port还是有存在的价值,下面讲述Bluetooth Virtual Serial Port的开发。在Windows Mobile下有两种方法可以建立Bluetooth Virtual Serial Port:调用API建立Bluetooth Virtual Serial Port和修改注册表建立Bluetooth Virtual Serial Port

调用API建立Bluetooth Virtual Serial Port

调用API建立Bluetooth Virtual Serial Port可以调用RegisterDevice

HANDLE h  =  RegisterDevice (L " COM " , index, L " btd.dll " , (DWORD) & pp);

 

建立服务端口,需要配置以下参数

PORTEMUPortParams pp;
memset (
& pp,  0 sizeof (pp));
pp.flocal 
=  TRUE;
pp.channel 
=  channel  &   0xff ;

服务端口flocal为true。channel可以使用RFCOMM_CHANNEL_MULTIPLE (0xfe),这样RFCOMM 会自动分配可用的信道。

建立客户端口,需要配置以下参数

 

PORTEMUPortParams pp;
memset (
& pp,  0 sizeof (pp));
pp.device 
=  ba;
pp.channel 
=  channel  &   0xff ;

服务端口flocal为false。device为服务端地址。

反注册端口使用以下API

DeregisterDevice (h);

详细可以参考MSDN文章 Creating a Connection to a Remote Device Using a Virtual COM Port,链接见参考文献。

在32feet.net里面,这些API封装在InTheHand.Net.Ports.BluetoothSerialPort,可以直接使用。但是32feet.net的作者提醒这些API是不是可信赖的(unreliable),所以在使用之前请要谨慎考虑和详细测试。我在wince 5下测试过,不能成功建立Bluetooth Virtual Serial Port。

使用32feet.net建立服务端口

复制代码
public   static   void  CreateIncomingPort()
{
    BluetoothSerialPort port 
=  BluetoothSerialPort.CreateServer(BluetoothService.SerialPort);
    Console.WriteLine(port.PortName);
}
复制代码

 

使用32feet.net建立客户端口

复制代码
public   static   void  CreateIncomingPort()
{
    BluetoothClient client 
=   new  BluetoothClient();
    BluetoothDeviceInfo[] devices 
=  client.DiscoverDevices();
    BluetoothDeviceInfo device 
=   null ;
    
foreach  (BluetoothDeviceInfo d  in  devices)
    {
        
if  (d.DeviceName  ==   " BLUETOOTH_DEVICE " )
        {
            device 
=  d;
            
break ;
        }
    }
    BluetoothEndPoint  endPoint 
=   new  BluetoothEndPoint(device.DeviceAddress, BluetoothService.SerialPort);
    BluetoothSerialPort port 
=  BluetoothSerialPort.CreateClient(endPoint);
    Console.WriteLine(port.PortName);
}
复制代码

 

修改注册表建立Bluetooth Virtual Serial Port

由于第一种方法不是很可靠,所以可以选择第二种方法,第二种方法其实就是修改注册表,把
HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Bluetooth\\Serial\\Ports的项进行修改。可是这个方法只是支持windows mobile5以上的系统,不支持wince5。同时,如果使用这个方法,需要重启系统。

这是Windows Mobile的注册表,可以通过程序修改注册表的项目,通过程序修改后需要重启Windows Mobile。

上图为Wince 5的注册表,结构不一样,在Wince5不能通过修改注册表的方式实现Bluetooth Virtual Serial Port。

下面的代码来源自32feet.net的BluetoothDeviceInfo类里面的SetServiceState()方法。这里演示了如何修改注册表。

复制代码
if  (state)
{
    
// write registry settings for WM5 Serial Port support

    
// get available ports
    Microsoft.Win32.RegistryKey rkPorts  =  Microsoft.Win32.Registry.LocalMachine.OpenSubKey( " SOFTWARE\\Microsoft\\Bluetooth\\Serial\\Ports " true );
    
string [] supportedPorts  =  ( string [])rkPorts.GetValue( " SupportedPorts " );
    System.Collections.ArrayList alPorts 
=   new  System.Collections.ArrayList(supportedPorts);

    
// check availability
     foreach  ( string  deviceid  in  rkPorts.GetSubKeyNames())
    {
        Microsoft.Win32.RegistryKey rkDevice 
=  rkPorts.OpenSubKey(deviceid);
        
// remove port from arraylist if unavailable
         string  port  =  rkDevice.GetValue( " Port " ).ToString();
        
int  nullPos  =  port.IndexOf( ' \0 ' );
        
if  (nullPos  >   - 1 )
        {
            port 
=  port.Substring( 0 , nullPos);
        }
        
if  (alPorts.Contains(port))
        {
            alPorts.Remove(port);
        }
        rkDevice.Close();
    }

    
if  (alPorts.Count  ==   0 )
    {
        
throw   new  InvalidOperationException( " No ports available " );
    }
    
// write port details to registry
    Microsoft.Win32.RegistryKey rkNewPort  =  rkPorts.CreateSubKey( this .DeviceAddress.ToString( " 8 " ));
    rkNewPort.SetValue(
" KeepDCB " 0 );
    rkNewPort.SetValue(
" RemoteDCB " 0 );
    rkNewPort.SetValue(
" Encryption " 0 );
    rkNewPort.SetValue(
" Authentication " 0 );
    rkNewPort.SetValue(
" Port " , alPorts[ 0 ]);
    rkNewPort.SetValue(
" Server " 0 );
    rkNewPort.Close();

    rkPorts.Close();

    
// try open port now
     try
    {
        InTheHand.Net.Ports.BluetoothSerialPort.CreateClient(alPorts[
0 ].ToString(),  new  BluetoothEndPoint( this .DeviceAddress, BluetoothService.SerialPort));
    }
    
catch
    {
    }
}
else
{
    
// find and remove registry entries
    Microsoft.Win32.RegistryKey rkPorts  =  Microsoft.Win32.Registry.LocalMachine.OpenSubKey( " SOFTWARE\\Microsoft\\Bluetooth\\Serial\\Ports " true );
    
foreach  ( string  deviceAddress  in  rkPorts.GetSubKeyNames())
    {
        
if  (deviceAddress  ==   this .DeviceAddress.ToString( " 8 " ))
        {
            rkPorts.DeleteSubKeyTree(deviceAddress);
            
break ;
        }
    }
    rkPorts.Close();
}
复制代码
当state为true时为注册,当state为false时为反注册。

 

参考文献

Bluetooth COM Ports On Windows CE 
Windows Mobile 5.0 Bluetooth Virtual Serial Ports 
Any Port in a Storm 
MSDN:Creating a Connection to a Remote Device Using a Virtual COM Port

 


    本文转自Jake Lin博客园博客,原文链接:http://www.cnblogs.com/procoder/archive/2009/05/15/Bluetooth_Virtual_Serial_Port.html,如需转载请自行联系原作者



相关文章
|
3月前
|
Windows
windows 电脑 连接蓝牙耳机没有麦克风
【8月更文挑战第31天】当Windows电脑连接蓝牙耳机后无法使用麦克风时,可尝试以下步骤解决:检查蓝牙设置,确保耳机正确连接并开启麦克风选项;检查音频设备设置,确认蓝牙耳机为默认播放和录制设备;更新蓝牙和音频驱动;确认耳机与系统的兼容性及正确设置。如问题未解,可重新配对耳机或联系客服。
3552 7
|
4月前
|
Linux C++ Windows
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
|
1天前
|
弹性计算 开发框架 安全
基于云效 Windows 构建环境和 Nuget 制品仓库进行 .Net 应用开发
本文将基于云效 Flow 流水线 Windows 构建环境和云效 Packages Nuget 制品仓库手把手教你如何开发并部署一个 .NET 应用,从环境搭建到实战应用发布的详细教程,帮助你掌握 .NET 开发的核心技能。
|
2月前
|
开发框架 .NET API
Windows Forms应用程序中集成一个ASP.NET API服务
Windows Forms应用程序中集成一个ASP.NET API服务
98 9
|
2月前
|
Windows
.NET 隐藏/自定义windows系统光标
【10月更文挑战第20天】在.NET中,可以使用`Cursor`类来控制光标。要隐藏光标,可将光标设置为`Cursors.None`。此外,还可以通过从文件或资源加载自定义光标来更改光标的样式。例如,在表单加载时设置`this.Cursor = Cursors.None`隐藏光标,或使用`Cursor.FromFile`方法加载自定义光标文件,也可以将光标文件添加到项目资源中并通过资源管理器加载。这些方法适用于整个表单或特定控件。
|
4月前
|
Linux iOS开发 开发者
跨平台开发不再难:.NET Core如何让你的应用在Windows、Linux、macOS上自如游走?
【8月更文挑战第28天】本文提供了一份详尽的.NET跨平台开发指南,涵盖.NET Core简介、环境配置、项目结构、代码编写、依赖管理、构建与测试、部署及容器化等多个方面,帮助开发者掌握关键技术与最佳实践,充分利用.NET Core实现高效、便捷的跨平台应用开发与部署。
298 3
|
4月前
|
网络安全 API 数据安全/隐私保护
【Azure App Service】.NET代码实验App Service应用中获取TLS/SSL 证书 (App Service Windows)
【Azure App Service】.NET代码实验App Service应用中获取TLS/SSL 证书 (App Service Windows)
|
4月前
|
Java 开发工具 Spring
【Azure Spring Cloud】使用azure-spring-boot-starter-storage来上传文件报错: java.net.UnknownHostException: xxxxxxxx.blob.core.windows.net: Name or service not known
【Azure Spring Cloud】使用azure-spring-boot-starter-storage来上传文件报错: java.net.UnknownHostException: xxxxxxxx.blob.core.windows.net: Name or service not known
|
20天前
|
网络安全 Windows
Windows server 2012R2系统安装远程桌面服务后无法多用户同时登录是什么原因?
【11月更文挑战第15天】本文介绍了在Windows Server 2012 R2中遇到的多用户无法同时登录远程桌面的问题及其解决方法,包括许可模式限制、组策略配置问题、远程桌面服务配置错误以及网络和防火墙问题四个方面的原因分析及对应的解决方案。
|
24天前
|
监控 安全 网络安全
使用EventLog Analyzer日志分析工具监测 Windows Server 安全威胁
Windows服务器面临多重威胁,包括勒索软件、DoS攻击、内部威胁、恶意软件感染、网络钓鱼、暴力破解、漏洞利用、Web应用攻击及配置错误等。这些威胁严重威胁服务器安全与业务连续性。EventLog Analyzer通过日志管理和威胁分析,有效检测并应对上述威胁,提升服务器安全性,确保服务稳定运行。