<template>
	<view>
		<h2 class='hTitle'>匹配蓝牙设备</h2>
		<view class="bottomBox">
			<button @click="refreshBlue" class="refreshBlueTooth">刷新蓝牙设备</button>
			<view class="equipmentTitle">
				设备名称
			</view>
			<!-- 连接蓝牙列表 -->
			<view class="blueListBox">
				<scroll-view scroll-y class="box">
					<view class="item" v-for="item in blueDeviceList" @click="connect(item)">
						<view>
							<text>id: {{ item.deviceId }}</text>
						</view>
						<view>
							<text>name: {{ item.name }}</text>
						</view>
					</view>
				</scroll-view>
			</view>
			<view class="equipmentTitle">
				已配对的设备
			</view>
			<view class="alreadyBlue">
				{{deviceId}}
			</view>
			<view class="bottom-btn">
				<button :loading='characteristicId==""' @click="confirmEdit" class="refreshBlueToothNot"
					:class="{refreshBlueTooth:characteristicId?true:false}">{{characteristicId?'确定编辑设备':'获取服务中'}}</button>
			</view>
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				blueDeviceList: [], //蓝牙设备
				deviceId: '', //蓝牙设备ID
				serviceId: '', //服务UUID
				characteristicId: '', //特征值
			};
		},
		created() {
			// 初始化蓝牙
			this.openBlue()
			// 获取蓝牙监听
			this.stateChange()
		},
		methods: {
			// 蓝牙报错提示
			blueError(code) {
				switch (code) {
					case 10000:
						this.errorToast('未初始化蓝牙适配器')
						break
					case 10001:
						this.errorToast('当前蓝牙适配器不可用')
						break
					case 10002:
						this.errorToast('没有找到指定设备')
						break
					case 10003:
						this.errorToast('连接失败')
						break
					case 10004:
						this.errorToast('没有找到指定服务')
						break
					case 10005:
						this.errorToast('没有找到指定特征值')
						break
					case 10006:
						this.errorToast('当前连接已断开')
						break
					case 10007:
						this.errorToast('当前特征值不支持此操作')
						break
					case 10008:
						this.errorToast('其余所有系统上报的异常')
						break
					case 10009:
						this.errorToast('Android 系统特有，系统版本低于 4.3 不支持 BLE')
						break
					case 100010:
						this.errorToast('已连接')
						break
					case 100011:
						this.errorToast('配对设备需要配对码')
						break
					case 100012:
						this.errorToast('连接超时')
						break
					case 100013:
						this.errorToast('连接 deviceld 为空或者是格式不正确')
						break
				}
			},
			// 统一错误封装
			errorToast(err) {
				uni.showToast({
					title: `${err}`,
					icon: 'none',
					duration: 2500
				})
			},
			// 刷新蓝牙设备列表
			refreshBlue() {
				uni.showLoading({
					title: '正在刷新',
					mask: true
				})
				this.discovery('refresh')
			},
			// 确定编辑
			confirmEdit() {
				if (!this.characteristicId) {
					return
				}
				uni.navigateTo({
					url: `/pages/edit/edit?deviceId=${this.deviceId}&serviceId=${this.serviceId}&characteristicId=${this.characteristicId}`
				})
			},
			// 初始化蓝牙
			openBlue() {
				let that = this
				uni.showLoading({
					title: '初始化中',
					mask: true
				})
				uni.openBluetoothAdapter({
					success(res) {
						uni.hideLoading()
						uni.showToast({
							title: '初始化成功',
							duration: 2500
						})
						that.discovery()
					},
					fail(err) {
						uni.hideLoading()
						that.blueError(err.errCode)
						console.log('初始化蓝牙失败')
						console.error(err)
					}
				})
			},
			// 搜索蓝牙设备
			discovery(msg) {
				let that = this
				that.blueDeviceList = []
				uni.startBluetoothDevicesDiscovery({
					success(res) {
						if (msg = 'refresh') {
							uni.hideLoading()
						}
						// 开启监听回调
						uni.onBluetoothDeviceFound((res) => {
							if (res.devices[0].name) {
								that.found(res)
							}
						})
					},
					fail(err) {
						console.log('搜索失败')
						console.error(err)
					}
				})
			},
			// 找到新设备就触发该方法
			found(res) {
				if (res.devices[0].name.includes('BT24')) {
					this.blueDeviceList.push(res.devices[0])
				}
				// 检查本地是否有id
				let deviceId = uni.getStorageSync('deviceId')
				if(deviceId){
					// 重置deviceId
					this.deviceId = ''
					let data = {
						deviceId
					}
					this.connect(data)   
				}
			},
			//监听蓝牙状态
			stateChange() {
				uni.onBLEConnectionStateChange(function(res) {
					// 该方法回调中可以用于处理连接意外断开等异常情况
					console.log(`device ${res.deviceId} state has changed, connected: ${res.connected}`,
						'监听到蓝牙设备变化')
					if (!res.connected) {
						console.log(111111, '断开重连操作');
						let data = {
							deviceId: this.deviceId
						}
						// 重置deviceId
						this.deviceId = ''
						this.connect(data)
					}
				})
			},
			// 断开蓝牙设备
			closeBLEConnection(deviceId) {
				console.log(deviceId, '断开蓝牙设备ID');
				uni.closeBLEConnection({
					deviceId,
					success(res) {
						console.log('断开蓝牙成功', res)
					},
					fail(err) {
						console.log('断开蓝牙失败', err);
					}
				})
			},
			// 连接设备
			connect(data) {
				// 判断是否是连接当前的蓝牙
				if (data.deviceId == this.deviceId) {
					uni.showToast({
						title: '您已经连接该蓝牙',
						duration: 2500,
						icon: 'none'
					})
					return
				} else if (this.deviceId) {
					this.closeBLEConnection(this.deviceId)
				}
				wx.showLoading({
					title: '正在连接',
					mask: true
				})
				let that = this
				that.deviceId = data.deviceId
				uni.createBLEConnection({
					deviceId: that.deviceId,
					timeout: 30000,
					success(res) {
						wx.hideLoading()
						uni.showToast({
							title: '连接成功',
							duration: 2500
						})
						console.log('连接成功');
						// 把deviceId保存到本地
						uni.setStorageSync('deviceId', that.deviceId);
						// 停止搜索
						that.stopDiscovery()
						//获取蓝牙服务
						setTimeout(() => {
							//需要延迟获取
							that.getLyService(that.deviceId)
						}, 1000)
					},
					fail(err) {
						wx.hideLoading()
						switch (err.errMsg) {
							default:
								that.blueError(err.errCode)
						}
						console.log('连接失败')
						console.error(err)
					}
				})
			},
			// 停止搜索
			stopDiscovery() {
				uni.stopBluetoothDevicesDiscovery({
					success(res) {
						console.log('停止成功')
						console.log(res)
					},
					fail(err) {
						console.log('停止失败')
						console.error(err)
					}
				})
			},
			//获取蓝牙可用服务
			getLyService(deviceId) {
				uni.getBLEDeviceServices({
					deviceId: deviceId,
					success: async (res) => {
						console.log('蓝牙服务', JSON.stringify(res))
						if (res.services.length < 1) {
							setTimeout(() => {
								this.getLyService(deviceId)
							}, 1000)
							return;
						}
						for (var i = 0; i < res.services.length; i++) {
							//获取蓝牙特征值
							var characteristic = await this.getLyCharacteristic(deviceId, res.services[i].uuid)
							if (!characteristic) continue;
							this.serviceId = res.services[i].uuid
							this.characteristicId = characteristic
							console.log('ok:', this.serviceId + ',' + this.characteristicId)
							this.notifyLy();
							break;
						}
					},
					fail: (err) => {
						console.error(JSON.stringify(err))
					}
				})
			},
			//获取蓝牙可用特征值
			getLyCharacteristic(deviceId, serviceId) {
				return new Promise((resolve, reject) => {
					uni.getBLEDeviceCharacteristics({
						deviceId: deviceId,
						serviceId: serviceId,
						success: (res) => {
							var result = '';
							for (var i = 0; i < res.characteristics.length; i++) {
								var properties = res.characteristics[i].properties;
								if (properties.read && properties.write && properties.notify) {
									console.log('可用特征值', JSON.stringify(res.characteristics[i].uuid))
									result = res.characteristics[i].uuid;
									break;
								}
							}
							resolve(result)
						},
						fail: (err) => {
							console.log('特征值', JSON.stringify(err))
							reject('')
						}
					})
				})
			},
		}
	}
</script>

<style lang="less" scoped>
	.hTitle {
		margin-left: 10px;
	}

	.bottomBox {
		margin-left: 40px;
		margin-top: 50px;

		// 蓝牙按钮
		.refreshBlueTooth {
			width: 140px;
			background-color: #1e98d7;
			color: #fff;
			margin: 0;
		}

		.refreshBlueToothNot {
			width: 140px;
			margin: 0;
		}

		.equipmentTitle {
			font-size: 18px;
			margin-top: 20px;
		}

		.blueListBox {
			margin-top: 20px;
			width: 90%;
			height: 300px;
			border: 1px solid #1e98d7;
			border-radius: 12px;
			padding: 8px;
			background-color: #eee;

			.box {
				margin-bottom: 20px;
				height: 100%;
				width: 100%;
			}

			.item:nth-child(2n) {
				background-color: aqua;
			}
		}

		.alreadyBlue {
			margin-top: 16px;
			font-size: 16px;
		}

		.bottom-btn {
			width: 90%;
			margin-top: 20px;
			display: flex;
			justify-content: flex-end;
		}
	}
</style>
