969 lines
30 KiB
Vue
969 lines
30 KiB
Vue
<template>
|
||
<view class="container">
|
||
<view v-if="!blueTooth.blueConn">
|
||
<uni-row>
|
||
<uni-col :span="24">
|
||
<uni-icons
|
||
type="info"
|
||
size="100"
|
||
color="#b4b4b4"
|
||
class="unconn-icon"
|
||
></uni-icons>
|
||
</uni-col>
|
||
<uni-col :span="24">
|
||
<text class="unconn-text">蓝牙未开启或未授权</text>
|
||
</uni-col>
|
||
</uni-row>
|
||
</view>
|
||
<view v-if="blueTooth.blueConn">
|
||
<uni-forms ref="bluetoothForm" :modelValue="blueTooth" labelWidth="100px">
|
||
<uni-forms-item label="车辆编号" name="bikeCode">
|
||
<bikeCodeScan
|
||
@scan-change="bikeCodeScanChange"
|
||
:codeValue="blueTooth.bikeCode"
|
||
ref="bikeCodeScanRef"
|
||
/>
|
||
</uni-forms-item>
|
||
<uni-forms-item label="中控编号" name="ecuCode">
|
||
<uni-easyinput v-model="blueTooth.ecuCode" placeholder="-" disabled />
|
||
</uni-forms-item>
|
||
<uni-forms-item label="蓝牙信号" name="blueSignal">
|
||
<uni-easyinput
|
||
v-model="blueTooth.blueSignal"
|
||
placeholder="-"
|
||
disabled
|
||
/>
|
||
</uni-forms-item>
|
||
</uni-forms>
|
||
<view>
|
||
<uni-list :border="true">
|
||
<view class="flex" style="padding: 10px 0 10px 0">
|
||
<view class="lt-title"> 蓝牙状态 </view>
|
||
<view class="lt-state">
|
||
<uni-load-more
|
||
v-if="blueTooth.blueState.load == 'loading'"
|
||
:status="blueTooth.blueState.load"
|
||
iconType="circle"
|
||
:icon-size="20"
|
||
:content-text="contentText"
|
||
/>
|
||
<view
|
||
class="cu-info"
|
||
v-if="blueTooth.blueState.detectionState == 'close'"
|
||
>
|
||
<text class="cuIcon-roundclosefill text-red"></text
|
||
>{{ blueTooth.blueState.msg }}
|
||
</view>
|
||
<view
|
||
class="cu-info"
|
||
v-if="blueTooth.blueState.detectionState == 'open'"
|
||
>
|
||
<text class="cuIcon-roundcheckfill text-green"></text
|
||
>{{ blueTooth.blueState.msg }}
|
||
</view>
|
||
</view>
|
||
<view class="lt-but">
|
||
<view style="bottom: 10rpx; width: 100%">
|
||
<button
|
||
v-if="blueTooth.blueState.detectionState != 'open'"
|
||
:disabled="blueTooth.blueState.btuDisabled"
|
||
style="width: 60px; height: 35px; font-size: 15px"
|
||
type="primary"
|
||
@click="getEbikeInfo"
|
||
>
|
||
连接
|
||
</button>
|
||
<button
|
||
v-if="blueTooth.blueState.detectionState == 'open'"
|
||
:disabled="blueTooth.blueState.btuDisabled"
|
||
style="width: 60px; height: 35px; font-size: 15px"
|
||
type="primary"
|
||
@click="closeConn"
|
||
>
|
||
断开
|
||
</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</uni-list>
|
||
<uni-list :border="true">
|
||
<view class="flex" style="padding: 10px 0 10px 0">
|
||
<view class="lt-title"> 车锁开 </view>
|
||
<view class="lt-state">
|
||
<uni-load-more
|
||
v-if="blueTooth.openLock.load == 'loading'"
|
||
:status="blueTooth.openLock.load"
|
||
iconType="circle"
|
||
:icon-size="20"
|
||
:content-text="contentText"
|
||
/>
|
||
<view class="cu-info">
|
||
<text
|
||
v-if="blueTooth.openLock.detectionState == 'error'"
|
||
class="cuIcon-roundclosefill text-red"
|
||
></text
|
||
>{{ blueTooth.openLock.msg }}
|
||
</view>
|
||
<view class="cu-info">
|
||
<text
|
||
v-if="blueTooth.openLock.detectionState == 'success'"
|
||
class="cuIcon-roundcheckfill text-green"
|
||
></text
|
||
>{{ blueTooth.openLock.msg }}
|
||
</view>
|
||
</view>
|
||
<view class="lt-but">
|
||
<view style="bottom: 10rpx; width: 100%">
|
||
<button
|
||
:disabled="blueTooth.openLock.btuDisabled"
|
||
style="width: 60px; height: 35px; font-size: 15px"
|
||
type="primary"
|
||
@click="execCommon('openLock')"
|
||
>
|
||
执行
|
||
</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</uni-list>
|
||
<uni-list :border="true">
|
||
<view class="flex" style="padding: 10px 0 10px 0">
|
||
<view class="lt-title"> 车锁关 </view>
|
||
<view class="lt-state">
|
||
<uni-load-more
|
||
v-if="blueTooth.closeLock.load == 'loading'"
|
||
:status="blueTooth.closeLock.load"
|
||
iconType="circle"
|
||
:icon-size="20"
|
||
:content-text="contentText"
|
||
/>
|
||
<view class="cu-info">
|
||
<text
|
||
v-if="blueTooth.closeLock.detectionState == 'error'"
|
||
class="cuIcon-roundclosefill text-red"
|
||
></text
|
||
>{{ blueTooth.closeLock.msg }}
|
||
</view>
|
||
<view class="cu-info">
|
||
<text
|
||
v-if="blueTooth.closeLock.detectionState == 'success'"
|
||
class="cuIcon-roundcheckfill text-green"
|
||
></text
|
||
>{{ blueTooth.closeLock.msg }}
|
||
</view>
|
||
</view>
|
||
<view class="lt-but">
|
||
<view style="bottom: 10rpx; width: 100%">
|
||
<button
|
||
:disabled="blueTooth.closeLock.btuDisabled"
|
||
style="width: 60px; height: 35px; font-size: 15px"
|
||
type="primary"
|
||
@click="execCommon('closeLock')"
|
||
>
|
||
执行
|
||
</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</uni-list>
|
||
<uni-list :border="true">
|
||
<view class="flex" style="padding: 10px 0 10px 0">
|
||
<view class="lt-title"> 打开电池仓 </view>
|
||
<view class="lt-state">
|
||
<uni-load-more
|
||
v-if="blueTooth.openBatteryHouse.load == 'loading'"
|
||
:status="blueTooth.openBatteryHouse.load"
|
||
iconType="circle"
|
||
:icon-size="20"
|
||
:content-text="contentText"
|
||
/>
|
||
<view class="cu-info">
|
||
<text
|
||
v-if="blueTooth.openBatteryHouse.detectionState == 'error'"
|
||
class="cuIcon-roundclosefill text-red"
|
||
></text
|
||
>{{ blueTooth.openBatteryHouse.msg }}
|
||
</view>
|
||
<view class="cu-info">
|
||
<text
|
||
v-if="blueTooth.openBatteryHouse.detectionState == 'success'"
|
||
class="cuIcon-roundcheckfill text-green"
|
||
></text
|
||
>{{ blueTooth.openBatteryHouse.msg }}
|
||
</view>
|
||
</view>
|
||
<view class="lt-but">
|
||
<view style="bottom: 10rpx; width: 100%">
|
||
<button
|
||
:disabled="blueTooth.openBatteryHouse.btuDisabled"
|
||
style="width: 60px; height: 35px; font-size: 15px"
|
||
type="primary"
|
||
@click="execCommon('openBatteryHouse')"
|
||
>
|
||
执行
|
||
</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</uni-list>
|
||
<uni-list :border="true">
|
||
<view class="flex" style="padding: 10px 0 10px 0">
|
||
<view class="lt-title"> 关闭电池仓 </view>
|
||
<view class="lt-state">
|
||
<uni-load-more
|
||
v-if="blueTooth.closeBatteryHouse.load == 'loading'"
|
||
:status="blueTooth.closeBatteryHouse.load"
|
||
iconType="circle"
|
||
:icon-size="20"
|
||
:content-text="contentText"
|
||
/>
|
||
<view class="cu-info">
|
||
<text
|
||
v-if="blueTooth.closeBatteryHouse.detectionState == 'error'"
|
||
class="cuIcon-roundclosefill text-red"
|
||
></text
|
||
>{{ blueTooth.closeBatteryHouse.msg }}
|
||
</view>
|
||
<view class="cu-info">
|
||
<text
|
||
v-if="blueTooth.closeBatteryHouse.detectionState == 'success'"
|
||
class="cuIcon-roundcheckfill text-green"
|
||
></text
|
||
>{{ blueTooth.closeBatteryHouse.msg }}
|
||
</view>
|
||
</view>
|
||
<view class="lt-but">
|
||
<view style="bottom: 10rpx; width: 100%">
|
||
<button
|
||
:disabled="blueTooth.openBatteryHouse.btuDisabled"
|
||
style="width: 60px; height: 35px; font-size: 15px"
|
||
type="primary"
|
||
@click="execCommon('closeBatteryHouse')"
|
||
>
|
||
执行
|
||
</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</uni-list>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, onMounted, reactive, onBeforeUnmount } from "vue";
|
||
import { showModelMessage } from "@/utils/tools.js";
|
||
import * as api from "@/utils/api.js";
|
||
import { AES128ECBEncrypt } from "@/utils/aes_util.js";
|
||
const bluetoothForm = ref(null);
|
||
const bikeCodeScanRef = ref(null);
|
||
// const serviceId = '0000FFF0-0000-1000-8000-00805F9B34FB';
|
||
// const characteristicId = '0000FFF6-0000-1000-8000-00805F9B34FB';
|
||
// 这里的 serviceId 和 characteristicId 需要根据实际设备的蓝牙服务和特征进行替换
|
||
const ids = {
|
||
serviceId: "",
|
||
characteristicId: "", //读取characteristicId
|
||
writeCharacteristicId: "", //写入characteristicId
|
||
};
|
||
|
||
const blueTooth = ref({
|
||
blueConn: false,
|
||
deviceId: "",
|
||
bikeCode: "",
|
||
ecuCode: "-",
|
||
ecuSn: "-",
|
||
blueSignal: "-",
|
||
autoBlueState: true,
|
||
blueState: {
|
||
load: "",
|
||
btuDisabled: true,
|
||
detectionState: "",
|
||
msg: "已断开",
|
||
},
|
||
openLock: {
|
||
load: "",
|
||
btuDisabled: true,
|
||
detectionState: "",
|
||
msg: "",
|
||
},
|
||
closeLock: {
|
||
load: "",
|
||
btuDisabled: true,
|
||
detectionState: "",
|
||
msg: "",
|
||
},
|
||
openBatteryHouse: {
|
||
load: "",
|
||
btuDisabled: true,
|
||
detectionState: "",
|
||
msg: "",
|
||
},
|
||
closeBatteryHouse: {
|
||
load: "",
|
||
btuDisabled: true,
|
||
detectionState: "",
|
||
msg: "",
|
||
},
|
||
});
|
||
|
||
const contentText = ref({
|
||
contentdown: "",
|
||
contentrefresh: "读取中",
|
||
contentnomore: "",
|
||
});
|
||
|
||
onMounted(() => {
|
||
uni.openBluetoothAdapter({
|
||
success(res) {
|
||
if (res.errno == 0) {
|
||
blueTooth.value.blueConn = true;
|
||
} else {
|
||
showModelMessage("蓝牙未就绪");
|
||
}
|
||
},
|
||
fail(err) {
|
||
let errmsg = err.errMsg;
|
||
if (err.errCode == 10001) {
|
||
}
|
||
errmsg = "蓝牙未就绪";
|
||
showModelMessage("蓝牙未就绪");
|
||
},
|
||
});
|
||
|
||
uni.onBluetoothAdapterStateChange(function (res) {
|
||
if (res["available"]) {
|
||
blueTooth.value.blueConn = true;
|
||
} else {
|
||
blueTooth.value.blueConn = false;
|
||
}
|
||
});
|
||
});
|
||
|
||
onBeforeUnmount(() => {
|
||
// 页面卸载时关闭蓝牙连接
|
||
if (blueTooth.value.deviceId != "") {
|
||
closeConn();
|
||
}
|
||
// 停止蓝牙设备搜索
|
||
stopBluetoothDevicesDiscovery();
|
||
// 关闭蓝牙适配器
|
||
uni.closeBluetoothAdapter({
|
||
success(res) {
|
||
console.log("closeBluetoothAdapter success", res);
|
||
},
|
||
fail(err) {
|
||
console.log("closeBluetoothAdapter err", err);
|
||
},
|
||
});
|
||
});
|
||
|
||
let timer;
|
||
const bikeCodeScanChange = (data) => {
|
||
clearTimeout(timer);
|
||
blueTooth.value.bikeCode = data;
|
||
if (data != "") {
|
||
timer = setTimeout(function () {
|
||
getEbikeInfo();
|
||
}, 5000);
|
||
}
|
||
};
|
||
|
||
const getEbikeInfo = () => {
|
||
if (blueTooth.value.deviceId != "") {
|
||
createBLEConnection();
|
||
} else {
|
||
api
|
||
.callEbikeInfo("getBikeINfoData?bikeCode=" + blueTooth.value.bikeCode)
|
||
.then((res) => {
|
||
console.log("EbikeInfo", res);
|
||
if (res.code == 200 && res.data) {
|
||
if (res.data.ecuCode != "") {
|
||
blueTooth.value.ecuCode = res.data.ecuCode;
|
||
blueTooth.value.ecuSn = res.data.ecuSn;
|
||
blueTooth.value.blueState.load == "loading";
|
||
setTimeout(function () {
|
||
startBluetoothDevicesDiscovery("ECU-" + res.data.ecuSn);
|
||
}, 2000);
|
||
} else {
|
||
showModelMessage("该车辆未绑定中控");
|
||
}
|
||
} else {
|
||
showModelMessage("该车辆未绑定中控");
|
||
}
|
||
})
|
||
.catch((err) => {
|
||
showModelMessage("该车辆未绑定中控");
|
||
});
|
||
}
|
||
};
|
||
|
||
const stopBluetoothDevicesDiscovery = () => {
|
||
uni.stopBluetoothDevicesDiscovery({
|
||
success(res) {},
|
||
});
|
||
};
|
||
|
||
const closeConn = () => {
|
||
uni.closeBLEConnection({
|
||
deviceId: blueTooth.value.deviceId,
|
||
success(res) {
|
||
blueTooth.value.autoBlueState = false;
|
||
},
|
||
});
|
||
};
|
||
|
||
const execCommon = (comm) => {
|
||
switch (comm) {
|
||
case "openLock": //开锁
|
||
var buffer = new ArrayBuffer(5);
|
||
var dataView = new DataView(buffer);
|
||
dataView.setUint32(0, 0x67740082);
|
||
dataView.setUint8(4, 0x82);
|
||
writeBLECharacteristicValueWithBuff(buffer);
|
||
break;
|
||
case "closeLock": //关锁
|
||
var buffer = new ArrayBuffer(5);
|
||
var dataView = new DataView(buffer);
|
||
dataView.setUint32(0, 0x67740081);
|
||
dataView.setUint8(4, 0x81);
|
||
writeBLECharacteristicValueWithBuff(buffer);
|
||
break;
|
||
case "openBatteryHouse": //打开电池仓
|
||
var buffer = new ArrayBuffer(6);
|
||
var dataView = new DataView(buffer);
|
||
dataView.setUint32(0, 0x67740189);
|
||
dataView.setUint8(4, 0);
|
||
var i;
|
||
var bcc;
|
||
for (i = 0; i < 2; i++) {
|
||
bcc ^= dataView.getInt8(i + 3);
|
||
}
|
||
dataView.setInt8(5, bcc);
|
||
writeBLECharacteristicValueWithBuff(buffer);
|
||
break;
|
||
case "closeBatteryHouse": //关闭电池仓
|
||
var buffer = new ArrayBuffer(6);
|
||
var dataView = new DataView(buffer);
|
||
dataView.setUint32(0, 0x67740189);
|
||
dataView.setUint8(4, 1);
|
||
var i;
|
||
var bcc;
|
||
for (i = 0; i < 2; i++) {
|
||
bcc ^= dataView.getInt8(i + 3);
|
||
}
|
||
dataView.setInt8(5, bcc);
|
||
writeBLECharacteristicValueWithBuff(buffer);
|
||
break;
|
||
}
|
||
};
|
||
|
||
const startBluetoothDevicesDiscovery = (sn) => {
|
||
uni.startBluetoothDevicesDiscovery({
|
||
success(res) {
|
||
if (res.errno == 0) {
|
||
uni.onBluetoothDeviceFound(function (res) {
|
||
console.log("onBluetoothDeviceFound", res);
|
||
const devices = res.devices;
|
||
for (let i = 0; i < devices.length; i++) {
|
||
if (devices[i].localName == sn) {
|
||
// 停止搜索
|
||
stopBluetoothDevicesDiscovery();
|
||
blueTooth.value.deviceId = devices[i].deviceId;
|
||
blueTooth.value.blueSignal = devices[i].RSSI;
|
||
createBLEConnection();
|
||
break;
|
||
}
|
||
}
|
||
});
|
||
setTimeout(function () {
|
||
showModelMessage("未发现蓝牙设备");
|
||
//停止搜索
|
||
stopBluetoothDevicesDiscovery();
|
||
}, 120000);
|
||
}
|
||
},
|
||
fail(err) {
|
||
showModelMessage("未发现蓝牙设备");
|
||
},
|
||
});
|
||
};
|
||
|
||
const createBLEConnection = () => {
|
||
blueTooth.value.autoBlueState = true;
|
||
uni.createBLEConnection({
|
||
deviceId: blueTooth.value.deviceId,
|
||
success(res) {
|
||
console.log("createBLEConnection success", res);
|
||
blueTooth.value.blueState.load == "";
|
||
blueTooth.value.blueState.detectionState = "open";
|
||
blueTooth.value.blueState.msg = "已连接";
|
||
blueTooth.value.blueState.btuDisabled = false;
|
||
blueTooth.value.openLock.btuDisabled = false;
|
||
blueTooth.value.closeLock.btuDisabled = false;
|
||
blueTooth.value.openBatteryHouse.btuDisabled = false;
|
||
blueTooth.value.closeBatteryHouse.btuDisabled = false;
|
||
uni.onBLEConnectionStateChange(function (res) {
|
||
console.log("onBLEConnectionStateChange", res);
|
||
if (!res.connected && blueTooth.value.autoBlueState) {
|
||
blueTooth.value.blueState.btuDisabled = false;
|
||
blueTooth.value.openLock.btuDisabled = true;
|
||
blueTooth.value.closeLock.btuDisabled = true;
|
||
blueTooth.value.openBatteryHouse.btuDisabled = true;
|
||
blueTooth.value.closeBatteryHouse.btuDisabled = true;
|
||
blueTooth.value.blueState.detectionState = "close";
|
||
blueTooth.value.blueState.msg = "已断开";
|
||
createBLEConnection();
|
||
}
|
||
});
|
||
getBLEDeviceServices();
|
||
},
|
||
fail(err) {
|
||
console.log("createBLEConnection err", err);
|
||
blueTooth.value.blueSignal = "-";
|
||
blueTooth.value.blueState.btuDisabled = false;
|
||
blueTooth.value.openLock.btuDisabled = true;
|
||
blueTooth.value.closeLock.btuDisabled = true;
|
||
blueTooth.value.openBatteryHouse.btuDisabled = true;
|
||
blueTooth.value.closeBatteryHouse.btuDisabled = true;
|
||
blueTooth.value.blueState.detectionState = "close";
|
||
blueTooth.value.blueState.msg = "已断开";
|
||
showModelMessage("蓝牙连接失败");
|
||
},
|
||
});
|
||
};
|
||
|
||
const getBLEDeviceServices = () => {
|
||
//获取蓝牙设备所有服务(service)。
|
||
uni.getBLEDeviceServices({
|
||
deviceId: blueTooth.value.deviceId,
|
||
success: function (res) {
|
||
console.log("蓝牙服务:", res.services);
|
||
for (var i = 0; i < res.services.length; i++) {
|
||
var serviceId = res.services[i].uuid;
|
||
var subServiceId = serviceId.substring(0, 8);
|
||
if (
|
||
subServiceId == "0000fff0" ||
|
||
subServiceId == "0000FFF0" ||
|
||
subServiceId == "6e400001" ||
|
||
subServiceId == "6E400001"
|
||
) {
|
||
console.log("符合的subServiceId =" + subServiceId);
|
||
|
||
ids.serviceId = serviceId;
|
||
//获取蓝牙设备某个服务中所有特征值(characteristic)。
|
||
uni.getBLEDeviceCharacteristics({
|
||
deviceId: blueTooth.value.deviceId,
|
||
serviceId: ids.serviceId,
|
||
success: function (res) {
|
||
console.log("获取到" + res.characteristics.length + "个特征值");
|
||
console.log("获取特征值:", res.characteristics);
|
||
for (var i = 0; i < res.characteristics.length; i++) {
|
||
var characteristicId = res.characteristics[i].uuid;
|
||
var subCharacteristic = characteristicId.substring(0, 8);
|
||
//读
|
||
if (
|
||
subCharacteristic == "0000fff6" ||
|
||
subCharacteristic == "0000FFF6" ||
|
||
subCharacteristic == "6e400003" ||
|
||
subCharacteristic == "6E400003"
|
||
) {
|
||
console.log("characteristicId =" + characteristicId);
|
||
ids.characteristicId = characteristicId;
|
||
}
|
||
//写
|
||
else if (
|
||
subCharacteristic == "6e400002" ||
|
||
subCharacteristic == "6E400002"
|
||
) {
|
||
console.log("writeCharacteristicId =" + characteristicId);
|
||
|
||
ids.writeCharacteristicId = characteristicId;
|
||
}
|
||
}
|
||
startNotify();
|
||
},
|
||
fail: function () {
|
||
console.log("获取特征值失败");
|
||
},
|
||
});
|
||
} else {
|
||
console.log("不符合的subServiceId =" + subServiceId);
|
||
}
|
||
}
|
||
},
|
||
fail: function (res) {
|
||
console.log("获取服务失败");
|
||
},
|
||
});
|
||
};
|
||
|
||
const startNotify = () => {
|
||
console.log("ids----------", ids);
|
||
uni.notifyBLECharacteristicValueChange({
|
||
state: true,
|
||
deviceId: blueTooth.value.deviceId,
|
||
serviceId: ids.serviceId,
|
||
characteristicId: ids.characteristicId,
|
||
success(res) {
|
||
console.log("notifyBLECharacteristicValueChange success", res);
|
||
//stopDiscovery();
|
||
uni.onBLECharacteristicValueChange(function (res) {
|
||
var hex = bufTohex(res.value);
|
||
//console.log("特征改变:", hex);
|
||
if (hex.length > 10) {
|
||
var header = hex.substring(0, 4);
|
||
if (header == "6774") {
|
||
var contentL1 = hex.substring(4, 6);
|
||
var contentL = parseInt(contentL1, 16);
|
||
//console.log('+++++++++++=', (contentL + 5), hex.length)
|
||
if ((contentL + 5) * 2 == hex.length) {
|
||
//console.log('完整的一条数据contentL=', contentL)
|
||
distributeCommandsWithDataStr(hex);
|
||
} else if ((contentL + 5) * 2 > hex.length) {
|
||
//需要分包接受数据
|
||
// 第一次接受分包数据
|
||
self.responseStr = hex;
|
||
//console.log('分包接受数据未实现', hex)
|
||
//console.log('第一次接受分包数据contentL2=', contentL)
|
||
} else {
|
||
//数据异常 ,查看
|
||
//console.log('数据异常 ,查看1', hex)
|
||
}
|
||
return;
|
||
}
|
||
} else {
|
||
//console.log('分包接受数据未实现', hex)
|
||
}
|
||
});
|
||
verification();
|
||
},
|
||
});
|
||
};
|
||
|
||
const verification = (mac, key1, key2) => {
|
||
if (mac && key1 && key2) {
|
||
//数据总长度为21,第一天长度20
|
||
var buffer = new ArrayBuffer(20);
|
||
var dataView = new DataView(buffer);
|
||
dataView.setUint32(0, 0x6774108a);
|
||
var sourceKey1 = mac + key1;
|
||
var AESEncrypt = AES128ECBEncrypt(sourceKey1, key2);
|
||
if (AESEncrypt.length != 32) {
|
||
return;
|
||
}
|
||
for (var i = 0; i < 4; i++) {
|
||
var subStr = AESEncrypt.substring(i * 8, i * 8 + 8, 16);
|
||
dataView.setUint32(i * 4 + 4, parseInt(subStr, 16)); //4字节01523947(16进制)-->>10进制数字-->放入dateView
|
||
}
|
||
var i;
|
||
var bcc; //17为数据长度16+1
|
||
for (i = 0; i < 17; i++) {
|
||
bcc ^= dataView.getInt8(i + 3);
|
||
}
|
||
var buffer2 = new ArrayBuffer(1);
|
||
var dataView2 = new DataView(buffer2);
|
||
dataView2.setUint8(0, bcc);
|
||
console.log("验证", bufTohex(buffer));
|
||
writeBLECharacteristicValueWithBuff(buffer);
|
||
setTimeout(() => {
|
||
writeBLECharacteristicValueWithBuff(buffer2);
|
||
}, 300);
|
||
} else {
|
||
var buffer = new ArrayBuffer(5);
|
||
var dataView = new DataView(buffer);
|
||
dataView.setUint32(0, 0x6774008a);
|
||
dataView.setUint8(4, 0x8a);
|
||
writeBLECharacteristicValueWithBuff(buffer);
|
||
}
|
||
};
|
||
|
||
const writeBLECharacteristicValueWithBuff = (buffer) => {
|
||
console.log("执行的命令--------", buffer);
|
||
console.log("characteristicId:" + ids.writeCharacteristicId);
|
||
|
||
uni.writeBLECharacteristicValue({
|
||
deviceId: blueTooth.value.deviceId,
|
||
serviceId: ids.serviceId,
|
||
characteristicId: ids.writeCharacteristicId,
|
||
value: buffer,
|
||
success: function (res) {
|
||
console.log("writeBLECharacteristicValue success", res.errMsg);
|
||
},
|
||
fail: function (res) {
|
||
console.log("writeBLECharacteristicValue fail", res.errMsg);
|
||
},
|
||
complete: function (res) {},
|
||
});
|
||
};
|
||
|
||
let verificationTimes = 0;
|
||
const distributeCommandsWithDataStr = (hex) => {
|
||
var cmd = hex.substring(6, 8);
|
||
var code = hex.substring(8, 10);
|
||
var errCode = code;
|
||
var desDic = {};
|
||
var des = "";
|
||
if (code == "00") {
|
||
des = "成功";
|
||
errCode = 0;
|
||
} else if (code == "ff") {
|
||
//-1
|
||
des = "锁已打开";
|
||
errCode = -1;
|
||
} else if (code == "fe") {
|
||
//-2
|
||
des = "电量不足";
|
||
errCode = -2;
|
||
} else if (code == "fd") {
|
||
//-3
|
||
des = "加密验证失败";
|
||
errCode = -3;
|
||
} else if (code == "fc") {
|
||
//-4
|
||
des = "内存空间不足";
|
||
errCode = -4;
|
||
} else if (code == "fb") {
|
||
//-5
|
||
des = "格式错误";
|
||
errCode = -5;
|
||
} else if (code == "fa") {
|
||
//-6
|
||
des = "没有验证或验证失败";
|
||
errCode = -6;
|
||
desDic["mac"] = hex.substring(10, 22);
|
||
desDic["key"] = hex.substring(22, 30);
|
||
} else if (code == "f9") {
|
||
//-7
|
||
des = "flash写入失败";
|
||
errCode = -7;
|
||
} else if (code == "f8") {
|
||
//-8
|
||
des = "数据空";
|
||
errCode = -8;
|
||
} else if (code == "f7") {
|
||
//-9
|
||
des = "操作失败";
|
||
errCode = -9;
|
||
} else if (code == "f6") {
|
||
//-10
|
||
des = "运输模式下无法执行该指令";
|
||
errCode = -10;
|
||
} else if (code == "f5") {
|
||
//-11
|
||
des = "锁车失败,车辆未停止";
|
||
errCode = -11;
|
||
} else if (code == "f4") {
|
||
//-12
|
||
des = "未检测到道钉信息";
|
||
errCode = -12;
|
||
} else if (parseInt(code, 16) == 149) {
|
||
//
|
||
des = "摄像头正在工作中";
|
||
errCode = parseInt(code, 16);
|
||
} else if (parseInt(code, 16) == 150) {
|
||
//
|
||
des = "摄像头离线";
|
||
errCode = parseInt(code, 16);
|
||
} else if (parseInt(code, 16) == 151) {
|
||
//
|
||
des = "车辆不在使用中(临时停车或是还车中)无法使用摄像头还车";
|
||
errCode = parseInt(code, 16);
|
||
} else if (parseInt(code, 16) == 152) {
|
||
//
|
||
des = "执行命令超时";
|
||
errCode = parseInt(code, 16);
|
||
} else if (parseInt(code, 16) == 153) {
|
||
//
|
||
des = "摄像头执行失败";
|
||
errCode = parseInt(code, 16);
|
||
} else if (parseInt(code, 16) == 154) {
|
||
//
|
||
des = "不在站点中或没有垂直停车";
|
||
errCode = parseInt(code, 16);
|
||
} else {
|
||
des = "未知错误码" + code;
|
||
errCode = code;
|
||
}
|
||
console.log("distributeCommandsWithDataStr", hex);
|
||
desDic["errCode"] = errCode;
|
||
desDic["des"] = des;
|
||
// if (cmd == '41') { //关锁指令
|
||
// if (!that.data.fortifiedDing) {
|
||
// if (that.BLESetUpDefences) {
|
||
// desDic['CMD'] = '81'
|
||
// that.BLESetUpDefences(desDic);
|
||
// } else {
|
||
// console.log('未找到BLESetUpDefences函数')
|
||
// }
|
||
// } else {
|
||
// if (that.BLEFortifiedDing) {
|
||
// // 6774108a
|
||
// if (hex.length > 22) {
|
||
// desDic['macDing'] = hex.substring(10, 22);
|
||
// }
|
||
// desDic['CMD'] = '81'
|
||
// that.BLEFortifiedDing(desDic);
|
||
// } else {
|
||
// console.log('未找到BLEFortifiedDing函数')
|
||
// }
|
||
// }
|
||
// }
|
||
// else if (cmd == '42') { //开锁指令
|
||
// if (that.BLEUnlock) {
|
||
// desDic['CMD'] = '82'
|
||
// that.BLEUnlock(desDic);
|
||
// } else {
|
||
// console.log('未找到BLEUnlock函数')
|
||
// }
|
||
// }
|
||
// else if (cmd == '44') { //重启设备
|
||
// if (that.BLEResetDevice) {
|
||
// desDic['CMD'] = '84'
|
||
// that.BLEResetDevice(desDic);
|
||
// } else {
|
||
// console.log('未找到BLEResetDevice函数')
|
||
// }
|
||
// }
|
||
// else if (cmd == '46') { //修改设备工作模式
|
||
// if (that.BLEUpdateDeviceMode) {
|
||
// desDic['CMD'] = '86'
|
||
// that.BLEUpdateDeviceMode(desDic);
|
||
// } else {
|
||
// console.log('未找到BLEUpdateDeviceMode函数')
|
||
// }
|
||
// }
|
||
// else if (cmd == '47') { //获取版本信息
|
||
// if (that.BLEGetVersionInfo) {
|
||
// var hardwareVersion = hex.substring(10, 12);
|
||
// var softwareVersion = hex.substring(12, 16);
|
||
// desDic['CMD'] = '87'
|
||
// desDic['hardwareVersion'] = hardwareVersion
|
||
// desDic['softwareVersion'] = softwareVersion
|
||
// that.BLEGetVersionInfo(desDic);
|
||
// } else {
|
||
// console.log('未找到BLEGetVersionInfo函数')
|
||
// }
|
||
// }
|
||
// else if (cmd == '49') { //打开电池仓
|
||
// if (that.BLEOpenTheBatteryCompartment) {
|
||
// desDic['CMD'] = '89'
|
||
// that.BLEOpenTheBatteryCompartment(desDic);
|
||
// } else {
|
||
// console.log('未找到BLEOpenTheBatteryCompartment函数')
|
||
// }
|
||
// }
|
||
// else
|
||
if (cmd == "4a") {
|
||
//验证
|
||
if (verificationTimes >= 1) {
|
||
verificationTimes = 0;
|
||
if (errCode == -6) {
|
||
verificationTimes = 1;
|
||
verification(desDic.mac, desDic.key, "6666660000888888");
|
||
return;
|
||
}
|
||
//验证成功
|
||
return;
|
||
} else {
|
||
verificationTimes += 1;
|
||
}
|
||
if (errCode == -6) {
|
||
verification(desDic.mac, desDic.key, "6666660000888888");
|
||
}
|
||
}
|
||
// else if (cmd == '4b') { //临时停车
|
||
// if (that.BLETemporaryParking) {
|
||
// desDic['CMD'] = '8b'
|
||
// that.BLETemporaryParking(desDic);
|
||
// } else {
|
||
// console.log('未找到BLETemporaryParking函数')
|
||
// }
|
||
// }
|
||
// else if (cmd == '4c') { //继续用车
|
||
// if (that.BLEContinueUnlocking) {
|
||
// desDic['CMD'] = '8c'
|
||
// that.BLEContinueUnlocking(desDic);
|
||
// } else {
|
||
// console.log('未找到BLEContinueUnlocking函数')
|
||
// }
|
||
// }
|
||
// else if (cmd == '4d') { //继续用车
|
||
// if (that.BLEOpenHelmetLock) {
|
||
// desDic['CMD'] = '8d'
|
||
// that.BLEOpenHelmetLock(desDic);
|
||
// } else {
|
||
// console.log('未找到BLEOpenHelmetLock函数')
|
||
// }
|
||
// }
|
||
// else if (cmd == '4e') { //摄像头还车 67740a 4e 95 00 000000ff 00000000 24
|
||
// if (that.BLELockBikeWithCamera) {
|
||
// desDic['CMD'] = '8e'
|
||
// //摄像头执行的错误码
|
||
// desDic['code'] = parseInt(hex.substring(10, 12),16)
|
||
// // (目标图像识别到的图像角度,标识报砂识别到的目标图片与车头方向顺时针的角度值,如果未识别到的角度则 255)
|
||
// desDic['angle'] = parseInt(hex.substring(12, 20),16)
|
||
// // 如示例 0x01 0x01 0x00 0x01 从左到右 第一位 byte:芯片型号。值 01 海思;02 联咏 03 富瀚微 第二位 byte :标志系列 值 01 黄白,02 黄蓝,04 预留 11 多颜色输入适配 第三、四位 byte 低字节递增 :版本号如 0001,0002,0003
|
||
// desDic['version'] = hex.substring(20, 28)
|
||
// that.BLELockBikeWithCamera(desDic);
|
||
// } else {
|
||
// console.log('未找到BLELockBikeWithCamera函数')
|
||
// }
|
||
// }
|
||
else {
|
||
console.log("未找到对应指令及函数");
|
||
}
|
||
};
|
||
|
||
const bufTohex = (buffer) => {
|
||
return Array.prototype.map
|
||
.call(new Uint8Array(buffer), (x) => ("00" + x.toString(16)).slice(-2))
|
||
.join("");
|
||
};
|
||
</script>
|
||
|
||
<style>
|
||
.container {
|
||
padding: 15px;
|
||
background-color: #fff;
|
||
}
|
||
|
||
.unconn-icon {
|
||
display: flex;
|
||
/* 启用 Flexbox 布局 */
|
||
justify-content: center;
|
||
/* 水平居中 */
|
||
align-items: center;
|
||
/* 垂直居中 */
|
||
}
|
||
|
||
.unconn-text {
|
||
width: 100%;
|
||
height: 80rpx;
|
||
display: flex;
|
||
/* 启用 Flexbox 布局 */
|
||
justify-content: center;
|
||
/* 水平居中 */
|
||
align-items: center;
|
||
/* 垂直居中 */
|
||
color: #b4b4b4;
|
||
}
|
||
|
||
.lt-title {
|
||
width: 30%;
|
||
padding: 8px 0 0 0;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.lt-state {
|
||
width: 50%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
}
|
||
|
||
.lt-but {
|
||
width: 20%;
|
||
}
|
||
</style>
|