【问题标题】:Bluetooth Serial Port (SPP) incoming port creation蓝牙串行端口 (SPP) 传入端口创建
【发布时间】:2018-11-13 12:26:27
【问题描述】:

我有一个定制的蓝牙设备,我可以使用 Windows 10 配对并连接它,它创建了 2 个 com 端口 - 一个列为传入,一个列为传出。

当我使用 32Feet C# 蓝牙库连接时,我能够发现并配对设备并启用 SPP 配置文件,但是,可惜我只有一个 COM 端口,它被列为“传出”。

我需要使用其他人的代码连接到设备,并且需要提供一个 com 端口号。不幸的是,它想连接到“传入”端口。

因此我的问题是创建这个传入的 com 端口需要什么魔法?我查看了 32Feet 代码和 BluetoothSetServiceState(...) 的底层 API 调用,它似乎没有任何参数来控制端口的创建方式。此功能是否还有其他配置文件?

【问题讨论】:

  • COM 端口(和蓝牙 SPP)是双向的。你在这里不需要任何魔法
  • 不幸的是,需要魔法 - 当 Windows 将设备配对时,我创建了两个端口,而“传入”端口提供了我需要的连接。当我通过 32Feet 使用 SPP 时,我只得到 1 个端口并且它不起作用。我知道这看起来很傻,但可惜我无法控制整个堆栈,所以我需要魔法。从我的阅读来看,“传入”和“传出”端口似乎都是双向的,但一个是由“客户端”创建的,一个是由“服务器”创建的

标签: c# .net bluetooth 32feet spp


【解决方案1】:

您必须使用 BluetoothAPIs.dll 中未记录的 InstallIncomingComPort 函数

【讨论】:

  • 嗨,迈克,所以当您说“无证”时,您是认真的!你碰巧知道它期望什么参数 - 我猜它需要一个本地无线电的句柄(我可能可以发送一个空指针),然后是远程设备的 BLUETOOTH_DEVICE_INFO,......但是还有什么其他的吗?也许是开/关状态?
  • 第一个参数是radio句柄。第二个是指向 FindNextOpenVCOMPort 函数返回值的指针。
  • 在谷歌上看起来 FindNextOpenVCOMPort 也可能是一个未记录的函数!它只需要无线电句柄还是无参数?
  • 是的,这也是未记录的功能。它需要无线电句柄并返回代表 vCOM 的内存块,您必须将此内存块传递给 InstallIncomingComPort。
  • 只记得其他解决方案:BluetoothSetLocalServiceInfo
【解决方案2】:
private const UInt16 BLUETOOTH_MAX_SERVICE_NAME_SIZE = 256;
private const UInt16 BLUETOOTH_DEVICE_NAME_SIZE  = 256;

private static Guid SerialPortServiceClass_UUID = new Guid("{00001101-0000-1000-8000-00805F9B34FB}");

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct BLUETOOTH_LOCAL_SERVICE_INFO
{
            public Boolean Enabled;
            public Int64 btAddr;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = BLUETOOTH_MAX_SERVICE_NAME_SIZE)]
            public String szName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = BLUETOOTH_DEVICE_NAME_SIZE)]
            public String szDeviceString;
};

[DllImport("BluetoothAPIs.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
private static extern UInt32 BluetoothSetLocalServiceInfo(IntPtr hRadioIn, ref Guid pClassGuid, UInt32 ulInstance, ref BLUETOOTH_LOCAL_SERVICE_INFO pServiceInfoIn);

private void CreateComPort(Boolean Create)
{
            BLUETOOTH_LOCAL_SERVICE_INFO s = new BLUETOOTH_LOCAL_SERVICE_INFO();
            s.btAddr = 0;
            s.Enabled = Create;
            s.szName = "MyComPort";
            s.szDeviceString = "COM10";

            UInt32 Res = BluetoothSetLocalServiceInfo(IntPtr.Zero,
                ref SerialPortServiceClass_UUID, 1, ref s);
            MessageBox.Show(Res.ToString());
}

【讨论】:

  • 对于所有关注我的人,请注意您可能希望将 s.btAddr 设置为您的蓝牙设备的地址。有关放入 32Feet 代码的代码,请参见下面的答案。
  • 接入服务不需要MAC地址。提供 MAC 应该只允许连接到特定设备,但是如果您查看它的实现(您可以尝试使用 IDA) - 它实际上什么都不做。顺便说一句,32 英尺:我想要求从您的库中删除您没有直接从我这里收到的所有代码。例如,在 MS 堆栈上更改本地无线电名称的代码。该代码已提供给我的一位客户,他与 32feet 共享该代码,违反 EULA。
【解决方案3】:

如果您希望使用 InTheHand BT 库并获取传入的 com 端口,您可以将以下代码添加到函数底部

public void SetServiceState(Guid service, bool state, bool throwOnError)

在 WindowsBlurtoothDeviceInfo.cs 中

if (service == BluetoothService.SerialPort)
{
    NativeMethods.BLUETOOTH_LOCAL_SERVICE_INFO s = new NativeMethods.BLUETOOTH_LOCAL_SERVICE_INFO();
    s.btAddr = deviceInfo.Address;
    s.Enabled = state;
    s.szName = "RemScan";
    s.szDeviceString = "COM10";
    UInt32 Res = NativeMethods.BluetoothSetLocalServiceInfo(IntPtr.Zero, ref NativeMethods.SerialPortServiceClass_UUID, 1, ref s);
}

【讨论】:

    猜你喜欢
    • 2016-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-10
    • 2013-07-21
    • 2011-07-31
    • 2014-12-22
    相关资源
    最近更新 更多