摘要
使用微信小程序扫描BLE设备,找到指定设备后弹窗.
平台信息
- 微信开发者工具Stable 1.06.2310080
原理
typescript+less开发模式
[https://developers.weixin.qq.com/miniprogram/dev/devtools/compilets.html]
[https://blog.csdn.net/Boale_H/article/details/121360082]
小程序代码包要求代码文件为 wxml / wxss / js / json / wxs。
如果我们希望使用 TypeScript 或 less 去开发小程序,就需要将 ts 文件或 less 文件编译成对应的 js 文件 或 wxss 文件,这个编译过程以前是需要开发者在工具外自行配置。
从开发者工具 1.05.2109101 以上开始,我们优化工具内置的编译模块,支持以编译插件的形式,扩展编译功能。
使用这种方式有两个好处:
项目内只需要创建 ts 文件即可,无需再生成同名的 js 文件。less 文件同理。
编译流程由开发者工具控制,按需编译,开发体验更好。
可在创建小程序项目时,选择对应的语言模板。 目前支持的语言模板有
- TypeScript
- TypeScript + Less
- TypeScript + Sass
typescript的类型
[https://typescript.p6p.net]
[https://www.typescriptlang.org/docs/handbook/intro.html]
[https://jkchao.github.io/typescript-book-chinese/]
TypeScript 代码最明显的特征,就是为 JavaScript 变量加上了类型声明。
TypeScript(简称 TS)是微软公司开发的一种基于 JavaScript (简称 JS)语言的编程语言。
它的目的并不是创造一种全新语言,而是增强 JavaScript 的功能,使其更适合多人合作的企业级项目。
TypeScript 可以看成是 JavaScript 的超集(superset),即它继承了后者的全部语法,所有 JavaScript 脚本都可以当作 TypeScript 脚本(但是可能会报错),此外它再增加了一些自己的语法。
TypeScript 对 JavaScript 添加的最主要部分,就是一个独立的类型系统。
静态类型有很多好处,这也是 TypeScript 想要达到的目的。
(1)有利于代码的静态分析。
有了静态类型,不必运行代码,就可以确定变量的类型,从而推断代码有没有错误。这就叫做代码的静态分析。
这对于大型项目非常重要,单单在开发阶段运行静态检查,就可以发现很多问题,避免交付有问题的代码,大大降低了线上风险。
(2)有利于发现错误。
由于每个值、每个变量、每个运算符都有严格的类型约束,TypeScript 就能轻松发现拼写错误、语义错误和方法调用错误,节省程序员的时间。
第三方库如果没有提供类型声明文件,社区往往会提供。TypeScript 社区主要使用 DefinitelyTyped 仓库,各种类型声明文件都会提交到那里,已经包含了几千个第三方库。
这些声明文件都会作为一个单独的库,发布到 npm 的@types名称空间之下。比如,jQuery 的类型声明文件就发布成@types/jquery这个库,使用时安装这个库就可以了。
TypeScript 会自动加载node_modules/@types目录下的模块,但可以使用编译选项typeRoots改变这种行为。
当前模块如果包含自己的类型声明文件,可以在 package.json 文件里面添加一个types字段或typings字段,指明类型声明文件的位置。
举例来说,入口文件是main.d.ts,里面的接口定义在interfaces.d.ts,函数定义在functions.d.ts。那么,main.d.ts里面可以用三斜杠命令,加载后面两个文件。
三斜杠命令(///)是一个 TypeScript 编译器命令,用来指定编译器行为。它只能用在文件的头部,如果用在其他地方,会被当作普通的注释。另外,若一个文件中使用了三斜线命令,那么在三斜线命令之前只允许使用单行注释、多行注释和其他三斜线命令,否则三斜杠命令也会被当作普通的注释。
实现
核心代码
app.json
{
"pages": [
"pages/index/index",
"pages/logs/logs",
"pages/about/about"
],
"window": {
"navigationBarTextStyle": "black",
"navigationStyle": "custom"
},
"style": "v2",
"rendererOptions": {
"skyline": {
"defaultDisplayBlock": true,
"disableABTest": true,
"sdkVersionBegin": "3.0.0",
"sdkVersionEnd": "15.255.255"
}
},
"componentFramework": "glass-easel",
"sitemapLocation": "sitemap.json",
"lazyCodeLoading": "requiredComponents"
}
index.wxml
<button bindtap="btn8Handler" style="margin-top:1vh;">连接蓝牙</button>
index.ts
// index.ts
// 引入mdui
// const mdui = require('mdui')
// 获取应用实例
const app = getApp<IAppOption>()
// 组件命名空间
Component({
data: {
imageList: [""], // 用于存储选中的图片的本地文件路径
is_ble_searching: false, // ble扫描状态
ble_device_list: [] as WechatMiniprogram.BlueToothDevice[], // ble设备列表
},// end data
methods: {
// 上传图片事件处理函数
chooseImage: function() {
var that = this; // 延伸this的作用域
// 这里是处理图片选择的代码
wx.chooseImage({
count: 1, // 默认9
sizeType: ['original'], // 可以指定是原图还是压缩图,默认二者都有
sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
success: function (res) {
// 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片
that.setData({
imageList: res.tempFilePaths, // 直接将选中的图片路径设置为imageList,而不是合并
});
that.setImageSrc(res.tempFilePaths[0]); // 设置选中的图片为originalImage元素的源
}
})
}, // end chooseImage
// 设置originalImage元素的源为选中的图片
setImageSrc(src: string) {
const query = wx.createSelectorQuery();
query.select('#originalImage').fields({ }).exec((res) => {
if (res[0]) {
res[0].src = src; // 设置选中的图片路径为originalImage元素的源
}
});
},// end setImageSrc
// 按钮8事件处理函数
btn8Handler: function(){
var that = this; // 延伸this的作用域
// 开始扫描蓝牙
console.log("开始扫描蓝牙")
wx.showToast({
title: "扫描ble设备",
icon: 'none',
})
that.BleSearch()
// TODO:连接蓝牙并保持连接
},// end btn8Handler
// 按钮9事件处理函数
btn9Handler: function(){
// 关闭蓝牙连接
},// end btn9Handler
// 蓝牙ble搜索
BleSearch: function () {
var that = this // 作用域不同,所以需要把Page.this重命名
// is_ble_searching变量为搜索状态
// 如果没有在搜索,则进行搜索
if (!that.data.is_ble_searching) {
// 关闭蓝牙
wx.closeBluetoothAdapter({
complete: function (res) {
console.log(res)
// 开启蓝牙
wx.openBluetoothAdapter({
success: function (res) {
console.log(res)
// 获取蓝牙适配器状态
wx.getBluetoothAdapterState({
success: function (res) {
console.log("蓝牙状态:"+res.available)
}
})
// 开始蓝牙设备发现
wx.startBluetoothDevicesDiscovery({
allowDuplicatesKey: false,
success: function (res) {
console.log(res)
that.setData({
is_ble_searching: true,
ble_device_list: []
})
}
})
},
fail: function (res) {
console.log(res)
wx.showModal({
title: '提示',
content: '请检查手机蓝牙是否打开',
showCancel: false,
success: function (res) {
that.setData({
is_ble_searching: false
})
}
})
} // end fail
}) // end openBluetoothAdapter
}, // end complete
fail: function (res) {
console.log(res)
wx.showModal({
title: '提示',
content: '请检查手机蓝牙是否打开',
showCancel: false,
success: function (res) {
that.setData({
is_ble_searching: false
})
}
})
} // end fail
}) // end closeBluetoothAdapter
}
// 如果在搜索,则停止搜索
else {
// 停止蓝牙设备发现
wx.stopBluetoothDevicesDiscovery({
success: function (res) {
console.log(res)
that.setData({
is_ble_searching: false
})
}
})
}
// 蓝牙搜索到设备
wx.onBluetoothDeviceFound(function (devices) {
//剔除重复设备,兼容不同设备API的不同返回值
var isnotexist = true
// 设备类型2的返回结果
if (devices.devices) {
console.log("设备类型2")
if (devices.devices[0].advertisData){
// devices.devices[0].advertisData = app.buf2hex(devices.devices[0].advertisData)
}
else{
// 清空数据
devices.devices[0].advertisData = new ArrayBuffer(0);
}
console.log(devices.devices[0])
for (var i = 0; i < that.data.ble_device_list.length; i++) {
if (devices.devices[0].deviceId == that.data.ble_device_list[i].deviceId) {
isnotexist = false
}
}
if (isnotexist) {
that.data.ble_device_list.push(devices.devices[0])
// 匹配名称
if(devices.devices[0].name == "sugardraw"){
console.log("找到设备surgardraw");
wx.showToast({
title: '找到设备surgardraw',
});
}
}
}
// 删除重复项后更新显示
that.setData({
ble_device_list: that.data.ble_device_list
})
})
}, // end BleSearch
// 隐藏小程序自动停止搜索
hide: function () {
console.log("进入hide")
var that = this
that.setData({
ble_device_list: []
})
if (this.data.is_ble_searching) {
wx.stopBluetoothDevicesDiscovery({
success: function (res) {
console.log(res)
that.setData({
is_ble_searching: false
})
}
})
}
},// end onHide
// 页面加载完成事件
ready: function (options:any) {
console.log("进入ready")
var that = this
that.setData({
})
wx.onBluetoothAdapterStateChange(function (res) {
console.log(res)
console.log("扫描状态:"+res.discovering)
that.setData({
is_ble_searching: res.discovering
})
if (!res.available) {
that.setData({
is_ble_searching: false
})
}
})
}, // end onl oad
},// end methods
})// end Component