`
zhhaogen
  • 浏览: 13524 次
  • 性别: Icon_minigender_1
  • 来自: 未知
社区版块
存档分类
最新评论

win10 uwp应用开发(JS)——蓝牙Rfcomm连接

 
阅读更多

1.环境

 

操作系统名称	Microsoft Windows 10 专业版
版本	10.0.15063 版本 15063

 

Microsoft Visual Studio Community 2017 
版本 15.3.3
VisualStudio.15.Release/15.3.3+26730.12
Microsoft .NET Framework
版本 4.7.02046

已安装的版本: Community

Visual Basic 2017   00369-60000-00001-AA520
Microsoft Visual Basic 2017

Visual C# 2017   00369-60000-00001-AA520
Microsoft Visual C# 2017

Visual C++ 2017   00369-60000-00001-AA520
Microsoft Visual C++ 2017

Application Insights Tools for Visual Studio 包   8.8.00712.1
Application Insights Tools for Visual Studio

ASP.NET and Web Tools 2017   15.0.30726.0
ASP.NET and Web Tools 2017

ASP.NET Core Razor Language Services   1.0
Provides languages services for ASP.NET Core Razor.

ASP.NET 模板引擎 2017   15.0.30726.0
ASP.NET 模板引擎 2017

JavaScript Project System   2.0
JavaScript Project System

JavaScript UWP 项目系统   2.0
JavaScript UWP 项目系统

JavaScript 语言服务   2.0
JavaScript 语言服务

Microsoft JVM Debugger   1.0
Provides support for connecting the Visual Studio debugger to JDWP compatible Java Virtual Machines

Microsoft MI-Based Debugger   1.0
Provides support for connecting Visual Studio to MI compatible debuggers

Microsoft Visual C++ 向导   1.0
Microsoft Visual C++ 向导

Microsoft Visual Studio VC 软件包   1.0
Microsoft Visual Studio VC 软件包

NuGet 包管理器   4.3.1
Visual Studio 中的 NuGet 包管理器。有关 NuGet 的详细信息,请访问 http://docs.nuget.org/。

TypeScript   2.3.4.0
用于 Visual Studio 的 TypeScript 工具

Visual Studio Code Debug Adapter Host Package   1.0
Interop layer for hosting Visual Studio Code debug adapters in Visual Studio

Visual Studio tools for CMake   1.0
Visual Studio tools for CMake

Visual Studio Tools for Universal Windows Apps   15.0.26730.08
Visual Studio Tools for Universal Windows Apps 让你能够构建一种通用的应用体验,运行 Windows 10 的每种设备都可以获得这种体验,如手机、平板电脑、PC 等。它包含 Microsoft Windows 10 软件开发工具包。

通用 Azure 工具   1.10
通过 Azure 移动服务和 Microsoft Azure Tools 提供通用服务。

 

2.参考资料和API

蓝牙开发MSDN资料 https://docs.microsoft.com/zh-cn/windows/uwp/devices-sensors/bluetooth

主要涉及的包

 

//导入包
let { BluetoothCacheMode, BluetoothDevice } = Windows.Devices.Bluetooth;
let { RfcommDeviceService, RfcommServiceId } = Windows.Devices.Bluetooth.Rfcomm;
let { DeviceInformation } = Windows.Devices.Enumeration;
let { StreamSocket, SocketProtectionLevel } = Windows.Networking.Sockets;
let { DataWriter, DataReader, UnicodeEncoding } = Windows.Storage.Streams;

 

/**
 * 一些常量
 */
const Constants = {
    RfcommServiceUuid: RfcommServiceId.fromUuid("58517d84-357d-c58a-0000-000000000000"),
    //  RfcommServiceUuid: RfcommServiceId.obexObjectPush,
    SdpServiceNameAttributeId: 0x100,
    SdpServiceNameAttributeType: (4 << 3) | 5,
    SdpServiceName: "My Win1o BLE"
};

 

 

 

3.Rfcomm服务监听

 创建RfcommServiceProvider

 

 provider = await RfcommServiceProvider.createAsync(Constants.RfcommServiceUuid);

 

使用StreamSocketListener监听socket连接,并且启动监听

 

    listener = new StreamSocketListener();
    listener.addEventListener("connectionreceived", onConnectionreceived);
  await listener.bindServiceNameAsync(provider.serviceId.asString(), SocketProtectionLevel.bluetoothEncryptionAllowNullAuthentication);

 

  provider.startAdvertising(listener, true);

 监听连接客户端的socket连接

 

 

/**
 * 监听客户端连接
 * @param {Windows.Networking.Sockets.StreamSocketListenerConnectionReceivedEventArgs} evt
 */
async function onConnectionreceived(evt)
{
    console.log(evt);
    let socket;
    try
    {
        socket = evt.socket;
    } catch (e)
    {
        console.log(e);
        disconnect();
        return;
    }

    console.log("socket连接", socket);
    let information = socket.information;
    info(information.remoteAddress + "  正在接入...");
    let remoteDevice = await BluetoothDevice.fromHostNameAsync(information.remoteHostName);//获取实际设备名
    console.log(remoteDevice);
    let holder = clients[information.remoteAddress];
    if (holder == null)//添加元素
    {
        holder = {};
        let ele = document.createElement("div");
        ele.className = "clientItem";
        ele.innerHTML = "<span>" + remoteDevice.name + "</span><span>" + information.remoteAddress + "</span><input  type=\"checkbox\" />";
        clientList.appendChild(ele);

        holder.socket = socket;
        holder.ele = ele;
        holder.name = remoteDevice.name;
        Object.defineProperty(holder, "isSelected", {
            get:
            function ()
            {
                return ele.querySelector("input").checked;
            }
        });
        holder.writer = new DataWriter(socket.outputStream);
        clients[information.remoteAddress] = holder;
    } else//更新元素
    {
        //do noting
    }
    let reader = new DataReader(socket.inputStream);
    //断开异常处理
    let errFun = function (igr)
    {
        console.log(igr);
        //断开连接
        info(holder.name + "断开连接..");
        delete clients[information.remoteAddress];
        clientList.removeChild(holder.ele);
    };
    //迭代循环读取
    function run()
    {
        reader.loadAsync(4).then(len =>
        {
            let size = reader.readInt32();//抛出异常处理 
            return size;
        }).then(size =>
        {
            console.log(size);
            return reader.loadAsync(size);
        }).then(textLen =>
        {
            console.log("文本长度:" + textLen);
            let str = reader.readString(textLen);
            return str;
        }).then(str =>
        {
            console.log(str);
            info(holder.name, str);
            run();
        }, errFun);
    }
    run();
}

 向连接的客户端发送消息

 

 

sendBtn.onclick = function ()
{
    let msg = sendText.value;
    console.log("发送文本", msg);
    info("服务器", msg);
    for (mac in clients)
    {
        let holder = clients[mac];
        if (holder.isSelected)
        {
            let writer = holder.writer;
            sendMsg(writer, msg);
        }
    }
}
/**
 * 
 * @param {Windows.Storage.Streams.DataWriter} writer
 * @param {string} msg
 */
function sendMsg(writer, msg)
{
    let textLen = writer.measureString(msg);
    console.log("写入长度:" + textLen);
    writer.writeInt32(textLen);
    writer.writeString(msg);
    writer.storeAsync();
}

 断开服务

 

 

function disconnect()
{
    startBtn.removeAttribute("disabled");
    startBtn.checked = false;

    for (mac in clients)
    {
        let holder = clients[mac];
        holder.socket.close();
    }
    if (listener != null)
    {
        info("服务已经断开");

        listener.close();
        listener = null;
    }
    if (provider != null)
    {
        provider.stopAdvertising();
        provider = null;
    }
}

 

 

4.Rfcomm连接服务

查找蓝牙设备

 

async function search()
{
    console.clear();
    connectBtn.setAttribute("disabled", true);

    //  RfcommDeviceService.getDeviceSelector.getDeviceSelector(Constants.RfcommServiceUuid);
    let selector = BluetoothDevice.getDeviceSelector();
    console.log("selector", selector);
    let devices = await DeviceInformation.findAllAsync(selector);
    console.log("devices", devices);
    info("正在搜索周边设备...");
    let bluetoothDevices = new Map();
    for (const device of devices)
    {
        let bluetoothDevice = await BluetoothDevice.fromIdAsync(device.id);
        if (bluetoothDevice != null)
        {
            //console.log(bluetoothDevice);
            bluetoothDevices.set(bluetoothDevice.deviceId, bluetoothDevice);
        }
    }
    console.log(bluetoothDevices);
    info("找到周边设备有" + bluetoothDevices.size + "个");

    notifyDataSetChanged(bluetoothDevices);

}

需要注意

DeviceInformation.findAllAsync(selector)

得到并一定全是BluetoothDevice或RfcommDeviceService,(至少js的api是这样,bug?),需要

let bluetoothDevice = await BluetoothDevice.fromIdAsync(device.id);

判断是否为蓝牙设备

检索蓝牙服务,通过bluetoothDevice.rfcommServices获取缓存结果

           bluetoothDevice.getRfcommServicesAsync(BluetoothCacheMode.uncached).then(result =>
            {
                console.log("返回服务", result);
                for (const rfcommService of bluetoothDevice.rfcommServices)
                {
                    let inputDiv = document.createElement("div");
                    inputDiv.className = "itemLabel";
                    let inputEle = document.createElement("label");
                    inputEle.innerHTML = rfcommService.serviceId.asString() + "<input name='rfcommService' type='radio' />";
                    inputDiv.appendChild(inputEle);
                    itemDiv.appendChild(inputDiv);

                    inputDiv.onclick = function ()
                    {
                        clientList.className = "left";
                        msgText.className = "right";
                        connect(rfcommService);
                    };
                }
            });

 连接指定的服务

/**
 * 连接到指定服务
 * @param {Windows.Devices.Bluetooth.Rfcomm.RfcommDeviceService} rfcommService
 */
async function connect(rfcommService)
{
    console.log(rfcommService);
    connectText.textContent = "已连接到" + rfcommService.device.name + rfcommService.device.hostName;
    info("正在连接到 " + rfcommService.serviceId.uuid + " ...");
    socket = new StreamSocket();
    try
    {
        await socket.connectAsync(rfcommService.connectionHostName, rfcommService.connectionServiceName, SocketProtectionLevel.bluetoothEncryptionAllowNullAuthentication);
        info("连接成功");
    } catch (e)
    {
        console.log(e);
        error("不能连接到服务端!");
        connectText.textContent = "搜索设备";
        connectBtn.checked = false;
        socket = null;
        return;
    }
    writer = new DataWriter(socket.outputStream);
    let reader = new DataReader(socket.inputStream);
    //迭代循环读取
    function run()
    {
        reader.loadAsync(4).then(len =>
        {
            let size = reader.readInt32();//抛出异常处理 
            return size;
        }).then(size =>
        {
            console.log(size);
            return reader.loadAsync(size);
        }).then(textLen =>
        {
            console.log("文本长度:" + textLen);
            let str = reader.readString(textLen);
            return str;
        }).then(str =>
        {
            console.log(str);
            info("服务器", str);
            run();
        }, err =>
            {
                console.log(err);
                disconnect();
            });
    }
    run();
}

 

5.win10与Android的Rfcomm蓝牙通信对接

在win10中,设置 -> 设备 -> 蓝牙和其他设备 -> 切换 蓝牙 开关, 点击 添加蓝牙或其他设备 -> 蓝牙 ,需要 匹配Android蓝牙设备 才能正常通信

使用Android作为客户端,win10服务端;

 

 

 

或者Android作为服务端,或者Win10为客户端

 

 

 

 

6.源码

win10 源码:https://github.com/zhhaogen/BuletoothTest-UWP.git

android 源码:https://github.com/zhhaogen/BuletoothTest-Android.git

 

  • 大小: 25.4 KB
  • 大小: 140 KB
  • 大小: 97.1 KB
  • 大小: 15.5 KB
分享到:
评论

相关推荐

    Win10下通过UWP刷新WIFI

    在Windows 10操作系统中,开发人员可以利用通用Windows平台(UWP)应用程序接口来实现对Wi-Fi网络的各种操作,包括刷新Wi-Fi列表、获取Wi-Fi信息以及连接到Wi-Fi网络。UWP提供了丰富的API集,使得开发者能够在安全且...

    Win10 UWP应用代理工具

    全选设置之后UWP即可访问localhost,可以走代理。

    Win10 UWP 开发教程 课程 资源

    Win10 UWP 开发教程 课程 资源 80课时 课程地址:http://blog.csdn.net/shanguuncle/article/details/78111649

    win10 uwp 轻量级 MVVM 框架入门 2.1.5.3199 例子

    在Windows 10平台上开发UWP(Universal Windows Platform)应用时,MVVM(Model-View-ViewModel)设计模式被广泛采用,它可以帮助开发者创建出松耦合、可测试且易于维护的代码。本文将深入介绍如何使用一个轻量级的...

    C#实现win10 uwp 右击浮出窗在点击位置

    在Windows 10 UWP应用开发中,常常需要创建一种用户友好的交互方式,即当用户右键点击某个元素时,能在一个特定的位置显示一个浮出菜单(MenuFlyout)。本篇文章将详细介绍如何使用C#实现这样的功能,使得MenuFlyout...

    UWP应用设计规范

    UWP(Universal Windows Platform,通用Windows平台)应用设计规范是微软为开发者提供的关于如何设计在所有基于Windows 10的设备上运行良好的用户界面的一套指导原则。这包括从手机、平板电脑到个人电脑和Surface ...

    WindowsStore_LTSC2019,LTSC 自动恢复 win10 应用商店

    但是LTSB/C也没了应用商店和UWP运行环境.,LTSC自动恢复win10应用商店,应用商店也是Win10的一大特色! Win10的应用商店也有一些优秀的应用可以代替臃肿的桌面程序. 使用该工具即可在 Windows10 LTSC(2019,1809) 上...

    hosxy#Settings#为UWP应用开启本地回环访问权限1

    1、什么是本地回环 2、开启本地回环访问权限 3、删除本地回环访问权限 4、查看可以拥有访问本地回环代理的应用列表 5、获取 UWP 应用的 SID 或者 Pa

    深入浅出Windows 10通用应用开发

    《深入浅出Windows 10通用应用开发》这本书籍,主要关注的是Windows 10平台上的通用Windows平台(Universal Windows Platform,简称UWP)应用的开发。UWP是一种跨设备的应用开发框架,允许开发者创建一次编写,多处...

    WindowsStore_LTSC2019,LTSC自动恢复win10应用商店

    但是LTSB/C也没了应用商店和UWP运行环境.,LTSC自动恢复win10应用商店,应用商店也是Win10的一大特色! Win10的应用商店也有一些优秀的应用可以代替臃肿的桌面程序. 使用该工具即可在 Windows10 LTSC(2019,1809) 上安装...

    uwp开发-demoHelloworld源码

    【标题】"uwp开发-demoHelloworld源码"是一个针对UWP(通用Windows平台)应用开发的示例项目,主要用于教学或快速理解UWP的基本结构和编程原理。这个源码可以无缝移植到任何运行Win10操作系统的设备上,包括PC、平板...

    UWP应用示例

    通用Windows平台(UWP)是微软为Windows 10操作系统推出的一种应用程序开发框架。UWP应用旨在提供跨设备兼容性,可以在各种Windows 10设备上运行,包括桌面、手机、平板电脑、Xbox、Hololens等。"UWP应用示例"是一个...

    win10 uwp 使用 asp dotnet core 做图床服务器客户端

    在本文中,我们将探讨如何利用Windows 10的UWP(通用Windows平台)应用程序与ASP.NET Core构建一个图床服务器的客户端。这是一个涉及到跨平台开发和云端图像存储管理的项目,旨在提供一种高效且灵活的方式来上传和...

    经典蓝牙+ble蓝牙(低功耗蓝牙)客户端\服务端开发

    同时,优化电池使用和提高连接稳定性是BLE应用开发的关键。此外,理解蓝牙的配对流程、安全性和数据包格式也有助于提升开发效率和应用质量。 在实际项目中,客户端和服务端的角色分配取决于应用需求。客户端通常...

    Windows10通用应用(UWP)开发详细教程, Windows10通用应用(UWP)代码大全

    即Windows通用应用平台,在Windows 10 Mobile/Surface(Windows平板电脑)/PC/Xbox/HoloLens等平台上运行,uwp不同于传统pc上的exe应用,也跟只适用于手机端的app有本质区别。它并不是为某一个终端而设计,而是可以...

    BleScan_连接_Windows编程_ble_win10ble开发_win10ble_

    标题"BleScan_连接_Windows编程_ble_win10ble开发_win10ble_"涉及的核心技术是Windows 10上的蓝牙低功耗(Bluetooth Low Energy, BLE)开发,具体包括BLE设备的扫描、连接以及属性查询。这个项目是在64位Windows 10...

    快捷将UWP应用添加到环回免除列表以使用代理加速访问.zip

    在IT行业中,UWP(Universal Windows Platform)应用是微软为Windows 10及更高版本操作系统设计的一种现代化应用程序框架。这些应用程序具有跨设备兼容性,并且能够利用Windows平台的各种特性和功能。然而,当涉及到...

    UWP程序开发200例

    《UWP程序开发200例》是针对Windows Universal Platform(UWP)应用程序...通过详尽研究这个压缩包中的每个示例,开发者不仅能获得丰富的实践经验,还能提升解决实际问题的能力,从而在UWP应用开发领域更加游刃有余。

    windows visual studio C++ 蓝牙BLE客户端(蓝牙调试工具)的完整源码和例子,可用于调试蓝牙BLE的开发

    Windows 10引入了通用Windows平台(UWP)蓝牙API,使得开发者可以方便地访问蓝牙功能。在这个示例中,可能会使用到如`Windows.Devices.Bluetooth`、`Windows.Devices.Bluetooth.GenericAttributeProfile`等命名空间...

    lindexi#lindexi#2020-10-28-win10-uwp-字符文本转语音声音文件方法1

    title: "win10 uwp 字符文本转语音声音文件方法"在 UWP 中,支持将传入的字符串文本内容转换为音频语音,可以将这个语音声音通过 MediaEl

Global site tag (gtag.js) - Google Analytics