<template>
	<view class="content">
		<button type="default" v-show="!shows" @click="initBle">
			初始化蓝牙模块
		</button>
		<scroll-view scroll-y="true" show-scrollbar="true">
			<radio-group>
				<view v-for="(item, index) in bleDevs" :key="index" v-show="item.name.length > 0 && !shows"
					style="padding: 10rpx 20rpx; border-bottom: 1rpx solid #ececec"
					v-if="Math.max(100 + item.RSSI, 0) >= 30">
					<view style="font-size: 32rpx; color: #333">
						<checkbox-group @change="checkboxChange" :data-name="item.name" :data-deviceId="item.deviceId">
							<label>
								<checkbox :value="item.deviceId">
									{{ item.name }}
								</checkbox>
							</label>
						</checkbox-group>
					</view>
					<view style="font-size: 20rpx; padding: 10rpx 0">
						deviceId: {{ item.deviceId }} 信号强度: {{ item.RSSI }}dBm ({{
              Math.max(100 + item.RSSI, 0)
            }}%)
					</view>
				</view>
				<view class="dis">
					<view @tap="connectBle" v-if="!shows" class="pl"> 连接 </view>
					<view @tap="close" v-if="shows" class="pl"> 断开 </view>
				</view>
			</radio-group>
		</scroll-view>

		<view class="appItems">
			<viwe :class="[item.status ? 'item bakBlue' : 'item']" v-for="(item, index) in totalList" :key="index">
				<view class="name p_hide">蓝牙名称：{{ item.name }}</view>
				<view class="txt">蓝牙数据：{{ item.text }}</view>
			</viwe>
		</view>

		<view class="items" v-if="shows">
			<view class="item" v-for="(item, index) in getData" :key="index">
				{{ item.name }}：{{ item.txt }}
			</view>
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				config: {
					color: "#333",
					backgroundColor: [1, "#fff"],
					title: "多设备蓝牙连接",
					back: false,
				},
				title: "Hello",
				bleDevs: [],
				status: -2, //-2未连接  -1已连接  0连接成功
				deviceId: "",
				serviceId: "",
				characteristicId: "",

				sendData: "",
				getData: [],

				deviceIds: [],
				totalList: [], // 全部已连接的设备

				timeIndex: 0, // 默认是列表的第一个

				timeout: null,
				shows: false,

				titleTime: "00:00:00",
				timer: "",

				hour: 0,
				minutes: 0,
				seconds: 0,

				input1: "B",
				input2: "",
			};
		},
		destroyed() {
			clearInterval(this.timer);
		},
		onLoad() {},
		mounted() {
			this.onBLEConnectionStateChange();
		},
		methods: {
			checkboxChange(e) {
				if (e.target.value[0] && e.target.dataset.name) {
					let item = {
						deviceId: e.target.value[0],
						name: e.target.dataset.name,
					};
					this.deviceIds.push(item);
				} else {
					for (let index = 0; index < this.deviceIds.length; index++) {
						let item = this.deviceIds[index];
						if (item.deviceId == e.target.dataset.deviceid) {
							this.deviceIds.splice(index, 1);
						}
					}
				}
			},
			onBLEConnectionStateChange() {
				uni.onBLEConnectionStateChange((res) => {
					// 该方法回调中可以用于处理连接意外断开等异常情况
					if (res.connected == false) {
						uni.hideLoading();
						for (let i = 0; i < this.deviceIds.length; i++) {
							if (res.deviceId == this.deviceIds[i].deviceId) {
								uni.showToast({
									title: this.deviceIds[i].name + " 蓝牙设备断开连接",
									icon: "none",
								});
							}
						}
					}
				});
			},
			//初始化蓝牙
			initBle() {
				this.bleDevs = [];
				this.deviceIds = [];
				uni.openBluetoothAdapter({
					success: (res) => {
						//已打开
						uni.getBluetoothAdapterState({
							//蓝牙的匹配状态
							success: (res1) => {
								this.startBluetoothDeviceDiscovery();
							},
							fail(error) {
								uni.showToast({
									icon: "none",
									title: "查看手机蓝牙是否打开"
								});
							},
						});
					},
					fail: (err) => {
						//未打开
						uni.showToast({
							icon: "none",
							title: "查看手机蓝牙是否打开"
						});
					},
				});
			},
			// 开始搜索蓝牙设备
			startBluetoothDeviceDiscovery() {
				uni.startBluetoothDevicesDiscovery({
					success: (res) => {
						// console.log("启动成功", res);
						// 发现外围设备
						this.onBluetoothDeviceFound();
					},
					fail: (err) => {
						// console.log(err, "错误信息");
					},
				});
			},
			// 发现外围设备
			onBluetoothDeviceFound() {
				// console.log("执行到这--发现外围设备")
				let that = this
				uni.onBluetoothDeviceFound((res) => {
					res.devices.forEach(device => {
						console.log("name", device.name)
						if (device.name.indexOf('PC-C02Pro') != -1|| (device.localName && device.localName.indexOf('PC-C02Pro') != -1) || device.name.indexOf('G02') != -1) {
							that.Bluetoothfilter(device)
						}
					})
					// 吧搜索到的设备存储起来，方便我们在页面上展示
					// if (this.bleDevs.indexOf(res.devices[0].deviceId) == -1) {
					// 	this.bleDevs.push(res.devices[0]);
					// }
					// console.log("蓝牙列表", res);
				});
			},
			Bluetoothfilter(item) {
				let that = this
				const foundDevices = that.bleDevs
				const idx = that.inArray(foundDevices, "deviceId", item.deviceId)
				if (idx === -1) {
					that.bleDevs.push(item);
				}
			},
			inArray(arr, key, val) {
				if (!arr || !arr.length || typeof arr != 'object' || !Array.isArray(arr)) {
					return -1
				}
				for (let i = 0; i < arr.length; i++) {
					if (!key) {
						if (arr[i] == val) {
							return i
						}
					} else if (arr[i][key] === val) {
						return i
					}
				}
				return -1;
			},

			// 多选然后连接
			connectBle() {
				if (this.deviceIds.length == 0) {
					uni.showToast({
						title: "请选择连接的设备",
						icon: "none"
					});
					return;
				}
				this.getData = [];
				for (let i = 0; i < this.deviceIds.length; i++) {
					this.createBLEConnection(this.deviceIds[i]);
					// this.nowLinkLis(this.deviceIds[i]);
				}
				// this.deviceIds.forEach((item) => {
				// 	// this.createBLEConnection(item);
				// 	this.nowLinkLis(item);
				// });
			},

			//选择设备连接吧deviceId传进来
			createBLEConnection(item) {
				uni.showLoading({
					title: "连接中，请稍等",
					mask: true,
				});
				let that = this;
				//连接蓝牙
				uni.createBLEConnection({
					deviceId: item.deviceId,
					success(res) {
						that.shows = true;
						that.stopBluetoothDevicesDiscovery();
						that.getBLEDeviceServices(2, item);
					},
					fail(res) {
						console.log("蓝牙连接失败", res);
						uni.showToast({
							title: items.name + "蓝牙连接失败",
							icon: "none",
						});
					},
				});
			},
			// 停止搜寻蓝牙设备
			stopBluetoothDevicesDiscovery() {
				uni.stopBluetoothDevicesDiscovery({
					success: (e) => {
						this.loading = false;
						// console.log("停止搜索蓝牙设备:" + e.errMsg);
					},
					fail: (e) => {
						console.log("停止搜索蓝牙设备失败，错误码：" + e.errCode);
					},
				});
			},

			//获取蓝牙的所有服务
			getBLEDeviceServices(index, items) {
				setTimeout(() => {
					uni.getBLEDeviceServices({
						// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
						deviceId: items.deviceId,
						success: (res) => {
							// console.log("成功",res)
							// console.log("device services:", res);
							//这里会获取到好多个services  uuid  我们只存储我们需要用到的就行，这个uuid一般硬件厂家会给我们提供
							console.log("services", res.services);
							res.services.forEach((item) => {
								if (item.uuid.indexOf("FFF0") != -1) {
									items["serviceId"] = item.uuid;
									this.getBLEDeviceCharacteristics(index, items);
								}
							});
						},
					});
				}, 1000);
			},
			//获取蓝牙特征
			getBLEDeviceCharacteristics(index, items) {
				// console.log("进入特征");
				setTimeout(() => {
					uni.getBLEDeviceCharacteristics({
						// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
						deviceId: items.deviceId,
						// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
						serviceId: items.serviceId,
						success: (res) => {
							console.log("characteristics", res);
							res.characteristics.forEach((item) => {
								if (
									// 2 支持监听   1 支持写入
									item.uuid.indexOf(
										index == 1 ?
										"0000FFF2" :
										"0000FFF1"
									) != -1
								) {
									items["characteristicId"] = item.uuid;
									if (index == 2) {
										this.notifyBLECharacteristicValueChange(items);
									}
								}
							});
							if (index == 1) {
								this.writeString(this.sendData, items);
							}
						},
						fail: (res) => {
							console.log(res);
						},
					});
				}, 0);
			},
			// 启用 notify 功能
			notifyBLECharacteristicValueChange(items) {
				let that = this;
				uni.notifyBLECharacteristicValueChange({
					state: true, // 启用 notify 功能
					// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
					deviceId: items.deviceId,
					// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
					serviceId: items.serviceId,
					// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
					characteristicId: items.characteristicId,
					success: (res) => {
						console.log("启用 notify 功能成功", res);
						uni.hideLoading();
						// uni.showToast({
						//   title: items.name + "连接成功",
						//   icon: "none",
						// });
						items["status"] = true;
						items["text"] = "";
						that.totalList.push(items);
						uni.onBLECharacteristicValueChange((res) => {

							for (let i = 0; i < that.deviceIds.length; i++) {
								if (res.deviceId == that.deviceIds[i].deviceId) {
									let item = {
										name: that.deviceIds[i].name,
										txt: "接收到：" + that.ab2hex(res.value),
									};
									that.getData.unshift(item);
								}
							}
							for (let i = 0; i < that.totalList.length; i++) {
								if (res.deviceId == that.totalList[i].deviceId) {
									that.totalList[i].text = that.ab2hex(res.value)
								}
							}
							that.totalList = JSON.stringify(that.totalList);
							that.totalList = JSON.parse(that.totalList);
						});
					},
					fail: (res) => {
						console.log("启用 notify 功能失败", res);
					},
				});
			},
			ab2hex(buffer, split) {
				var hexArr = Array.prototype.map.call(
					new Uint8Array(buffer),
					function(bit) {
						return ('00' + bit.toString(16)).slice(-2)
					}
				)
				return hexArr.join(split);
			},
			close() {
				let that = this;
				uni.showModal({
					title: "提示",
					content: "将断开全部蓝牙连接",
					success: function(res) {
						if (res.confirm) {
							for (let index = 0; index < that.deviceIds.length; index++) {
								let item = that.deviceIds[index];
								uni.closeBLEConnection({
									deviceId: item.deviceId,
									success(res) {
										console.log("断开蓝牙成功", res);
										that.shows = false;
										that.totalList = [];
										uni.showToast({
											title: "断开蓝牙成功",
										});
									},
									fail(res) {
										console.log("断开蓝牙失败", res);
									},
								});
							}
						}
					},
				});
			},

			// 向蓝牙设备发送字符串数据 writeBLECharacteristicValueString
			writeString(str, items) {
				let that = this;
				// console.log("发送字符串数据", str);
				// 发送方式一
				let buffer = new ArrayBuffer(str.length);
				let dataView = new DataView(buffer);
				for (let i in str) {
					dataView.setUint8(i, str[i].charCodeAt() | 0);
					//打印二进制字节
					// console.log("dataView.getUint8(i)>>", dataView.getUint8(i));
				}
				//延迟发送指令
				setTimeout(() => {
					uni.writeBLECharacteristicValue({
						deviceId: items.deviceId,
						serviceId: items.serviceId,
						characteristicId: items.characteristicId,
						value: buffer,
						writeType: "write",
						success: function(res) {
							uni.hideLoading();
							// uni.showToast({
							//   title: "已成功发送",
							// });
							let item = {
								name: items.name,
								txt: "已发送：" + str,
							};
							that.getData.unshift(item);
						},
						fail: function(res) {
							uni.hideLoading();
							uni.showToast({
								title: "发送失败，可能蓝牙目前不支持写入",
								icon: "none",
							});
						},
					});
				}, 0);
			},
		},
	};
</script>
<style lang="scss" scoped>
	.input3 {
		display: flex;
		justify-content: space-around;

		input {
			border: 1rpx solid #ccc;
			margin: 20rpx;
			text-align: center;
			height: 60rpx;
			border-radius: 10rpx;
			font-size: 50rpx;
		}

		input:first-child,
		input:last-child {
			width: 200rpx;
		}
	}

	.bakBlue {
		background-color: #007aff !important;
	}

	.appItems {
		padding: 30rpx 0 30rpx 4rpx;
		display: flex;
		flex-wrap: wrap;

		.item {
			color: #333;
			width: 100%;
			height: 60px;
			margin: 10rpx 15rpx;
			position: relative;
			background: #dfdfdf;
			border-radius: 10px;
			padding: 0 10px;
			display: flex;
			flex-direction: column;
			justify-content: space-evenly;
		}
	}

	.timers {
		text-align: center;
		margin-top: 30rpx;

		.time {
			margin-bottom: 40rpx;
			width: 100%;
			font-size: 80rpx;
			font-weight: bold;
		}

		.btns {
			display: flex;
			justify-content: space-around;

			view {
				width: 200rpx;
				height: 60rpx;
				background-color: #007aff;
				color: #fff;
				line-height: 60rpx;
				border-radius: 10rpx;
			}

			view:active {
				background-color: #2990ff;
			}
		}
	}

	.items {
		width: 100%;
		font-size: 32rpx;
		overflow-y: scroll;
		height: 300rpx;
		background-color: #ccc;
		margin: 40rpx 0;

		.item {
			padding: 4rpx 20rpx 0 20rpx;
		}
	}

	.pl {
		margin: 20rpx;
		background-color: #007aff;
		padding: 10rpx;
	}

	.classText {
		width: 94%;
		padding: 10rpx;
		margin: 3%;
		border: 1rpx solid #ececec;
	}

	.send {
		background-color: #ff3e3e;
		color: #fff;
	}

	.dis {
		display: flex;
		justify-content: space-between;
		color: #fff;
		text-align: center;
		flex-wrap: wrap;

		view {
			width: 100%;
			border-radius: 8rpx;
			font-size: 32rpx;
		}
	}

	.barItems {
		width: 100%;

		.barItem {
			display: flex;
			justify-content: space-around;
			// border: 1rpx solid #ececec;
			height: 100rpx;
			padding-top: 20rpx;
			align-items: center;

			.bar {
				width: 300rpx;
				display: flex;
				justify-content: space-around;

				view {
					border: 1rpx solid #ececec;
					width: 50rpx;
					height: 50rpx;
					text-align: center;
				}

				input {
					width: 100rpx;
					text-align: center;
				}
			}
		}
	}
</style>