Merge branch 'fanpeng' into 'develop'
Fanpeng See merge request StarlockTeam/wx-starlock!36
This commit is contained in:
commit
1c5d8ed714
@ -8,7 +8,8 @@ module.exports = {
|
|||||||
globals: {
|
globals: {
|
||||||
uni: 'writable',
|
uni: 'writable',
|
||||||
getApp: 'writable',
|
getApp: 'writable',
|
||||||
wx: 'writable'
|
wx: 'writable',
|
||||||
|
getCurrentPages: 'writable'
|
||||||
},
|
},
|
||||||
// 指定如何解析语法
|
// 指定如何解析语法
|
||||||
parser: 'vue-eslint-parser',
|
parser: 'vue-eslint-parser',
|
||||||
@ -41,17 +42,15 @@ module.exports = {
|
|||||||
'no-var': 'error', // 要求使用 let 或 const 而不是 var
|
'no-var': 'error', // 要求使用 let 或 const 而不是 var
|
||||||
'no-multiple-empty-lines': ['error', { max: 1 }], // 不允许多个空行
|
'no-multiple-empty-lines': ['error', { max: 1 }], // 不允许多个空行
|
||||||
'prefer-const': 'off', // 使用 let 关键字声明但在初始分配后从未重新分配的变量,要求使用 const
|
'prefer-const': 'off', // 使用 let 关键字声明但在初始分配后从未重新分配的变量,要求使用 const
|
||||||
'no-use-before-define': 'error', // 禁止在 函数/类/变量 定义之前使用它们
|
'no-use-before-define': 'off', // 禁止在 函数/类/变量 定义之前使用它们
|
||||||
'no-irregular-whitespace': 'off', // 禁止不规则的空白
|
'no-irregular-whitespace': 'off', // 禁止不规则的空白
|
||||||
'no-undef': 'error', // 禁止使用未声明的变量
|
'no-undef': 'error', // 禁止使用未声明的变量
|
||||||
'vue/script-setup-uses-vars': 'off', // 关闭此规则,因为它可能会干扰no-undef的检测
|
'no-unused-vars': 'error', // 禁止出现未使用过的变量
|
||||||
|
'vue/script-setup-uses-vars': 'error', // 确保script setup中的变量必须正确定义
|
||||||
'vue/no-undef-components': 'off', // 关闭组件未定义的检查
|
'vue/no-undef-components': 'off', // 关闭组件未定义的检查
|
||||||
'vue/no-undef-properties': [
|
'vue/no-undef-properties': 'off', // 关闭属性未定义的检查
|
||||||
'error',
|
'vue/no-unused-vars': 'error', // 禁止Vue组件中出现未使用的变量
|
||||||
{
|
'import/no-unused-modules': 'off', // 关闭模块导出检查
|
||||||
ignore: ['getDeviceInfo', 'getBluetoothDevices', 'stopGetBluetoothDevices']
|
|
||||||
}
|
|
||||||
], // 忽略特定方法的未定义检查
|
|
||||||
'import/no-cycle': 0,
|
'import/no-cycle': 0,
|
||||||
'no-nested-ternary': 0,
|
'no-nested-ternary': 0,
|
||||||
'import/prefer-default-export': 0,
|
'import/prefer-default-export': 0,
|
||||||
|
|||||||
20
App.vue
20
App.vue
@ -39,6 +39,8 @@
|
|||||||
this.updateMiniProgram()
|
this.updateMiniProgram()
|
||||||
// 监听蓝牙开关状态
|
// 监听蓝牙开关状态
|
||||||
this.onBluetoothState()
|
this.onBluetoothState()
|
||||||
|
// 设置voip配置
|
||||||
|
this.setVoipConfig()
|
||||||
// 检查蓝牙权限
|
// 检查蓝牙权限
|
||||||
const checkResult = await this.checkSetting()
|
const checkResult = await this.checkSetting()
|
||||||
console.log(checkResult)
|
console.log(checkResult)
|
||||||
@ -65,6 +67,24 @@
|
|||||||
'initAndListenBluetooth'
|
'initAndListenBluetooth'
|
||||||
]),
|
]),
|
||||||
...mapActions(useUserStore, ['updateLoginStatus']),
|
...mapActions(useUserStore, ['updateLoginStatus']),
|
||||||
|
// voip设置
|
||||||
|
setVoipConfig() {
|
||||||
|
const wmpfVoip = requirePlugin('wmpf-voip').default
|
||||||
|
wmpfVoip.setUIConfig({
|
||||||
|
btnText: '去开门',
|
||||||
|
customBoxHeight: '75vh',
|
||||||
|
listenerUI: {
|
||||||
|
cameraRotation: 270,
|
||||||
|
objectFit: 'fill',
|
||||||
|
enableToggleCamera: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
wmpfVoip.setVoipEndPagePath({
|
||||||
|
url: '/pages/main/home',
|
||||||
|
key: 'Call',
|
||||||
|
routeType: 'switchTab'
|
||||||
|
})
|
||||||
|
},
|
||||||
// 强制升级
|
// 强制升级
|
||||||
updateMiniProgram() {
|
updateMiniProgram() {
|
||||||
const updateManager = uni.getUpdateManager()
|
const updateManager = uni.getUpdateManager()
|
||||||
|
|||||||
12
api/p2p.js
12
api/p2p.js
@ -1,12 +0,0 @@
|
|||||||
import request from '../utils/request'
|
|
||||||
|
|
||||||
// p2p 模块
|
|
||||||
|
|
||||||
// 获取p2pInfo
|
|
||||||
export function getP2pInfo(data) {
|
|
||||||
return request({
|
|
||||||
url: '/v1/tencentYun/getDeviceDetail',
|
|
||||||
method: 'POST',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
12
api/sdk.js
Normal file
12
api/sdk.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import request from '../utils/request'
|
||||||
|
|
||||||
|
// sdk 模块
|
||||||
|
|
||||||
|
// 透传
|
||||||
|
export function passthrough(data) {
|
||||||
|
return request({
|
||||||
|
url: '/passthrough',
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
@ -9,14 +9,17 @@ uni.getSystemInfo({
|
|||||||
|
|
||||||
const DEV = {
|
const DEV = {
|
||||||
name: 'dev',
|
name: 'dev',
|
||||||
baseUrl: 'https://dev.lock.star-lock.cn/api',
|
appName: '星星锁Lite',
|
||||||
webviewBaseUrl: 'https://dev.lock.star-lock.cn',
|
baseUrl: 'https://lock.dev.star-lock.cn/api',
|
||||||
|
webviewBaseUrl: 'https://lock.dev.star-lock.cn',
|
||||||
version,
|
version,
|
||||||
buildNumber
|
buildNumber
|
||||||
}
|
}
|
||||||
|
|
||||||
const PRE = {
|
const PRE = {
|
||||||
name: 'pre',
|
name: 'pre',
|
||||||
baseUrl: 'https://pre.lock.star-lock.cn/api',
|
appName: '星星锁Lite',
|
||||||
|
baseUrl: 'https://lock.pre.star-lock.cn/api',
|
||||||
webviewBaseUrl: 'https://lock.xhjcn.ltd',
|
webviewBaseUrl: 'https://lock.xhjcn.ltd',
|
||||||
version,
|
version,
|
||||||
buildNumber
|
buildNumber
|
||||||
@ -24,6 +27,7 @@ const PRE = {
|
|||||||
|
|
||||||
const XHJ = {
|
const XHJ = {
|
||||||
name: 'xhj',
|
name: 'xhj',
|
||||||
|
appName: '星星锁Lite',
|
||||||
baseUrl: 'https://lock.xhjcn.ltd/api',
|
baseUrl: 'https://lock.xhjcn.ltd/api',
|
||||||
webviewBaseUrl: 'https://lock.xhjcn.ltd',
|
webviewBaseUrl: 'https://lock.xhjcn.ltd',
|
||||||
version,
|
version,
|
||||||
@ -32,6 +36,7 @@ const XHJ = {
|
|||||||
|
|
||||||
const SKY = {
|
const SKY = {
|
||||||
name: 'sky',
|
name: 'sky',
|
||||||
|
appName: '星星锁Lite',
|
||||||
baseUrl: 'https://lock.skychip.top/api',
|
baseUrl: 'https://lock.skychip.top/api',
|
||||||
webviewBaseUrl: 'https://lock.skychip.top',
|
webviewBaseUrl: 'https://lock.skychip.top',
|
||||||
version,
|
version,
|
||||||
@ -40,6 +45,7 @@ const SKY = {
|
|||||||
|
|
||||||
const GE = {
|
const GE = {
|
||||||
name: 'ge',
|
name: 'ge',
|
||||||
|
appName: '星星锁Lite',
|
||||||
baseUrl: 'http://lock.ge.star-lock.cn/api',
|
baseUrl: 'http://lock.ge.star-lock.cn/api',
|
||||||
webviewBaseUrl: 'http://lock.ge.star-lock.cn',
|
webviewBaseUrl: 'http://lock.ge.star-lock.cn',
|
||||||
version,
|
version,
|
||||||
|
|||||||
28
jsconfig.json
Normal file
28
jsconfig.json
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@/*": [
|
||||||
|
"./*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"target": "es2020",
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"strict": true,
|
||||||
|
"skipLibCheck": true
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"**/*.js",
|
||||||
|
"**/*.jsx",
|
||||||
|
"**/*.vue"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules",
|
||||||
|
"unpackage",
|
||||||
|
"dist"
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -30,14 +30,14 @@
|
|||||||
"provider": "wx1319af22356934bf",
|
"provider": "wx1319af22356934bf",
|
||||||
"export": "exportForXp2pPlugin.js"
|
"export": "exportForXp2pPlugin.js"
|
||||||
},
|
},
|
||||||
"wechat-p2p-player": {
|
|
||||||
"version": "latest",
|
|
||||||
"provider": "wx9e8fbc98ceac2628",
|
|
||||||
"export": "exportForPlayerPlugin.js"
|
|
||||||
},
|
|
||||||
"wmpf-voip": {
|
"wmpf-voip": {
|
||||||
"version": "latest",
|
"version": "latest",
|
||||||
"provider": "wxf830863afde621eb"
|
"provider": "wxf830863afde621eb",
|
||||||
|
"genericsImplementation": {
|
||||||
|
"call-page-plugin": {
|
||||||
|
"custombox": "pages/main/customBox"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
20
pages.json
20
pages.json
@ -16,6 +16,7 @@
|
|||||||
"style": {
|
"style": {
|
||||||
"navigationStyle": "custom",
|
"navigationStyle": "custom",
|
||||||
"navigationBarTitleText": "监控",
|
"navigationBarTitleText": "监控",
|
||||||
|
"disableScroll": true,
|
||||||
"mp-weixin": {
|
"mp-weixin": {
|
||||||
"usingComponents": {
|
"usingComponents": {
|
||||||
"iot-p2p-player-with-mjpg": "plugin://xp2p/iot-p2p-player-with-mjpg",
|
"iot-p2p-player-with-mjpg": "plugin://xp2p/iot-p2p-player-with-mjpg",
|
||||||
@ -23,8 +24,22 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "authorizeWechat",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "微信授权",
|
||||||
|
"disableScroll": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"plugins": {
|
||||||
|
"wechat-p2p-player": {
|
||||||
|
"version": "latest",
|
||||||
|
"provider": "wx9e8fbc98ceac2628",
|
||||||
|
"export": "exportForPlayerPlugin.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"root": "pages/addDevice",
|
"root": "pages/addDevice",
|
||||||
@ -560,6 +575,9 @@
|
|||||||
{
|
{
|
||||||
"path": "pages/main/mine"
|
"path": "pages/main/mine"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/main/customBox"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/main/notificationList",
|
"path": "pages/main/notificationList",
|
||||||
"style": {
|
"style": {
|
||||||
|
|||||||
@ -12,10 +12,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useBluetoothStore } from '@/stores/bluetooth'
|
|
||||||
import { useBasicStore } from '@/stores/basic'
|
|
||||||
import { onLoad } from '@dcloudio/uni-app'
|
import { onLoad } from '@dcloudio/uni-app'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
import { useBluetoothStore } from '@/stores/bluetooth'
|
||||||
|
import { useBasicStore } from '@/stores/basic'
|
||||||
|
|
||||||
const bluetoothStore = useBluetoothStore()
|
const bluetoothStore = useBluetoothStore()
|
||||||
const basicStore = useBasicStore()
|
const basicStore = useBasicStore()
|
||||||
|
|||||||
@ -134,6 +134,9 @@
|
|||||||
address: this.currentLockInfo.position.address
|
address: this.currentLockInfo.position.address
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (this.currentLockInfo.tencentYunLock) {
|
||||||
|
params.tencentYunLock = this.currentLockInfo.tencentYunLock
|
||||||
|
}
|
||||||
const { code, message } = await bindLockAdmin(params)
|
const { code, message } = await bindLockAdmin(params)
|
||||||
console.log('添加锁返回', code, message)
|
console.log('添加锁返回', code, message)
|
||||||
if (code === 0) {
|
if (code === 0) {
|
||||||
|
|||||||
@ -1,212 +1,163 @@
|
|||||||
<template>
|
<template>
|
||||||
<view>
|
<view>
|
||||||
<view class="mt-4">
|
<view class="mt-4">
|
||||||
<up-steps :current="current" activeColor="#63b8af" class="custom-steps">
|
<view class="mt-18 mx-8 flex flex-col">
|
||||||
<up-steps-item title="设置WiFi" :itemStyle="{ fontSize: '48rpx' }"> </up-steps-item>
|
<view class="text-lg font-bold mb-4">请选择WiFi并输入密码</view>
|
||||||
<up-steps-item title="连接设备蓝牙" :itemStyle="{ fontSize: '48rpx' }"></up-steps-item>
|
<view class="pt-2 pb-3 border-b-2 border-b-solid border-gray-200">
|
||||||
<up-steps-item title="开始配网" :itemStyle="{ fontSize: '48rpx' }"></up-steps-item>
|
<picker
|
||||||
</up-steps>
|
mode="selector"
|
||||||
<view class="mt-8 mx-8 flex flex-col h-[calc(100vh-300rpx)]">
|
:range="wifiList"
|
||||||
<view v-if="current === 0">
|
:value="wifiIndex"
|
||||||
<view class="text-lg font-bold mb-4">请选择WiFi并输入密码</view>
|
@change="changeWifi"
|
||||||
<view class="pt-2 pb-3 border-b-2 border-b-solid border-gray-200">
|
range-key="SSID"
|
||||||
<picker
|
|
||||||
mode="selector"
|
|
||||||
:range="wifiList"
|
|
||||||
:value="wifiIndex"
|
|
||||||
@change="changeWifi"
|
|
||||||
range-key="SSID"
|
|
||||||
>
|
|
||||||
<view class="flex items-center">
|
|
||||||
<view class="mr-4">WiFi</view>
|
|
||||||
<view>{{ wifiList[wifiIndex]?.SSID ?? '加载中...' }}</view>
|
|
||||||
<view class="ml-a">
|
|
||||||
<up-icon name="arrow-right" size="24rpx"></up-icon>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</picker>
|
|
||||||
</view>
|
|
||||||
<view class="py-2 border-b-2 border-b-solid border-gray-200 flex items-center">
|
|
||||||
<view>密码</view>
|
|
||||||
<view class="flex-1">
|
|
||||||
<!-- <up-input
|
|
||||||
:customStyle="{
|
|
||||||
padding: '0 28rpx',
|
|
||||||
outline: 'none',
|
|
||||||
height: '80rpx',
|
|
||||||
backgroundColor: '#FFFFFF',
|
|
||||||
border: 0
|
|
||||||
}"
|
|
||||||
placeholder-class="!text-base !line-height-[80rpx]"
|
|
||||||
v-model="password"
|
|
||||||
placeholder="请输入密码"
|
|
||||||
:type="showPassword ? 'text' : 'password'"
|
|
||||||
>
|
|
||||||
<template #suffix>
|
|
||||||
<up-icon
|
|
||||||
:name="showPassword ? 'eye-fill' : 'eye-off'"
|
|
||||||
size="42rpx"
|
|
||||||
@click="togglePassword"
|
|
||||||
></up-icon>
|
|
||||||
</template>
|
|
||||||
</up-input> -->
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view v-if="current === 1" class="flex flex-col h-[calc(100vh-230rpx)]">
|
|
||||||
<view class="text-lg font-bold mb-2">请连接设备蓝牙</view>
|
|
||||||
<view class="text-[#999999]">已发现设备如下</view>
|
|
||||||
<scroll-view scroll-y class="flex-1 mt-4 overflow-hidden">
|
|
||||||
<view
|
|
||||||
v-for="item in deviceList"
|
|
||||||
:key="item.deviceId"
|
|
||||||
@click="connectDevice(item)"
|
|
||||||
class="bg-[#efedf1] rounded-xl py-4 px-3 mt-2 flex justify-between"
|
|
||||||
>
|
|
||||||
<view>{{ item.name }}</view>
|
|
||||||
<view class="text-[#63b8af]">连接</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
<view class="flex justify-center items-center mt-2">
|
|
||||||
<up-loading-icon
|
|
||||||
size="70rpx"
|
|
||||||
text="搜索中"
|
|
||||||
:vertical="true"
|
|
||||||
textSize="28rpx"
|
|
||||||
></up-loading-icon>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view v-if="current === 2">
|
|
||||||
<view class="flex justify-center mt-10">
|
|
||||||
<image
|
|
||||||
src="https://oss-lock.xhjcn.ltd/mp/cloud_server.png"
|
|
||||||
mode="aspectFill"
|
|
||||||
class="w-200rpx h-200rpx p-4"
|
|
||||||
></image>
|
|
||||||
</view>
|
|
||||||
<view
|
|
||||||
v-for="(item, index) in stepList"
|
|
||||||
:key="item"
|
|
||||||
class="flex items-center mt-4 justify-center w-full"
|
|
||||||
>
|
>
|
||||||
<view class="flex items-center justify-start w-400rpx">
|
<view class="flex items-center">
|
||||||
<up-loading-icon mode="circle" v-if="step < index + 1" size="36rpx"></up-loading-icon>
|
<view class="mr-4">WiFi</view>
|
||||||
<up-icon name="checkbox-mark" color="#63b8af" size="36rpx" v-else></up-icon>
|
<view>{{ wifiList[wifiIndex]?.SSID ?? '搜索中...' }}</view>
|
||||||
<view class="ml-3">{{ item }}</view>
|
<view class="ml-a">
|
||||||
|
<up-icon name="arrow-right" size="24rpx"></up-icon>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
<view class="py-2 border-b-2 border-b-solid border-gray-200 flex items-center">
|
||||||
|
<view>密码</view>
|
||||||
|
<view class="flex-1">
|
||||||
|
<up-input
|
||||||
|
:customStyle="{
|
||||||
|
padding: '0 28rpx',
|
||||||
|
outline: 'none',
|
||||||
|
height: '80rpx',
|
||||||
|
backgroundColor: '#FFFFFF',
|
||||||
|
border: 0
|
||||||
|
}"
|
||||||
|
:maxlength="20"
|
||||||
|
placeholder-class="!text-base !line-height-[80rpx]"
|
||||||
|
placeholder="请输入密码"
|
||||||
|
:type="showPassword ? 'text' : 'password'"
|
||||||
|
@change="handleInput"
|
||||||
|
>
|
||||||
|
<template #suffix>
|
||||||
|
<up-icon
|
||||||
|
:name="showPassword ? 'eye-fill' : 'eye-off'"
|
||||||
|
size="42rpx"
|
||||||
|
@click="togglePassword"
|
||||||
|
></up-icon>
|
||||||
|
</template>
|
||||||
|
</up-input>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view
|
<view
|
||||||
v-if="current === 0"
|
|
||||||
class="fixed bottom-[calc(env(safe-area-inset-bottom)+32rpx)] w-686rpx mx-4 h-88rpx text-center text-white bg-[#63b8af] leading-[88rpx] rounded-44rpx font-bold"
|
class="fixed bottom-[calc(env(safe-area-inset-bottom)+32rpx)] w-686rpx mx-4 h-88rpx text-center text-white bg-[#63b8af] leading-[88rpx] rounded-44rpx font-bold"
|
||||||
@click="handleNext"
|
@click="connectWifi"
|
||||||
>下一步</view
|
|
||||||
>
|
>
|
||||||
|
连接
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref } from 'vue'
|
import { onMounted, onUnmounted, ref } from 'vue'
|
||||||
|
import { useBluetoothStore } from '@/stores/bluetooth'
|
||||||
|
// import { useUserStore } from '@/stores/user'
|
||||||
import { useBasicStore } from '@/stores/basic'
|
import { useBasicStore } from '@/stores/basic'
|
||||||
|
import { passthrough } from '@/api/sdk'
|
||||||
|
|
||||||
|
const $bluetooth = useBluetoothStore()
|
||||||
|
// const $user = useUserStore()
|
||||||
const $basic = useBasicStore()
|
const $basic = useBasicStore()
|
||||||
|
|
||||||
const current = ref(0)
|
|
||||||
const wifiList = ref([])
|
const wifiList = ref([])
|
||||||
const wifiIndex = ref()
|
const wifiIndex = ref()
|
||||||
const password = ref('')
|
const password = ref('')
|
||||||
|
|
||||||
const step = ref(1)
|
|
||||||
|
|
||||||
const deviceList = ref([])
|
|
||||||
|
|
||||||
const showPassword = ref(false)
|
const showPassword = ref(false)
|
||||||
|
|
||||||
const stepList = ref([
|
const pending = ref(false)
|
||||||
'手机与设备连接成功',
|
|
||||||
'向设备发送信息成功',
|
|
||||||
'设备连接云端成功',
|
|
||||||
'初始化成功'
|
|
||||||
])
|
|
||||||
|
|
||||||
const wifiInfo = ref({
|
onMounted(async () => {
|
||||||
SSID: '',
|
uni.showLoading({
|
||||||
password: ''
|
title: '搜索中'
|
||||||
|
})
|
||||||
|
// const result = await $bluetooth.getWifiList({
|
||||||
|
// uid: $user.userInfo.uid.toString()
|
||||||
|
// })
|
||||||
|
// if (result.code !== 0) {
|
||||||
|
// uni.showModal({
|
||||||
|
// title: '提示',
|
||||||
|
// content: '搜索失败,请返回重试',
|
||||||
|
// showCancel: false,
|
||||||
|
// success: () => {
|
||||||
|
// uni.navigateBack()
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
listenEvent()
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.hideLoading()
|
||||||
|
wifiList.value = [
|
||||||
|
{
|
||||||
|
SSID: '测试1',
|
||||||
|
rssi: 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SSID: '测试2',
|
||||||
|
rssi: 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SSID: '测试3',
|
||||||
|
rssi: 30
|
||||||
|
}
|
||||||
|
]
|
||||||
|
wifiIndex.value = 0
|
||||||
|
}, 2000)
|
||||||
})
|
})
|
||||||
|
|
||||||
const deviceInfo = $basic.deviceInfo
|
onUnmounted(() => {
|
||||||
|
uni.$off('wifiList')
|
||||||
|
uni.$off('distributionNetworkResult')
|
||||||
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
const listenEvent = () => {
|
||||||
if (deviceInfo.platform !== 'android' && deviceInfo.platform !== 'ios') {
|
uni.$on('wifiList', async data => {
|
||||||
uni.showToast({
|
if (data.status === 0) {
|
||||||
title: '当前设备不支持WiFi功能',
|
wifiList.value = data.wifiList
|
||||||
icon: 'none'
|
uni.hideLoading()
|
||||||
})
|
} else {
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
uni.authorize({
|
|
||||||
scope: 'scope.userLocation',
|
|
||||||
success: () => {
|
|
||||||
const getWifiListFn = () => {
|
|
||||||
uni.getWifiList({
|
|
||||||
success: () => {
|
|
||||||
uni.onGetWifiList(res => {
|
|
||||||
const uniqueWifiList = res.wifiList
|
|
||||||
.filter(wifi => wifi.SSID && wifi.SSID.trim() !== '')
|
|
||||||
.reduce((acc, current) => {
|
|
||||||
const exists = acc.find(item => item.SSID === current.SSID)
|
|
||||||
if (!exists) {
|
|
||||||
acc.push(current)
|
|
||||||
}
|
|
||||||
return acc
|
|
||||||
}, [])
|
|
||||||
wifiList.value = uniqueWifiList
|
|
||||||
wifiIndex.value = 0
|
|
||||||
})
|
|
||||||
},
|
|
||||||
fail: err => {
|
|
||||||
console.error('获取WiFi列表失败:', err)
|
|
||||||
uni.showToast({
|
|
||||||
title: '获取WiFi列表失败',
|
|
||||||
icon: 'none'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (deviceInfo.platform === 'android') {
|
|
||||||
uni.startWifi({
|
|
||||||
success: () => {
|
|
||||||
getWifiListFn()
|
|
||||||
},
|
|
||||||
fail: err => {
|
|
||||||
console.error('初始化WiFi失败:', err)
|
|
||||||
uni.showToast({
|
|
||||||
title: '初始化WiFi失败',
|
|
||||||
icon: 'none'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
getWifiListFn()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fail: () => {
|
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
title: '提示',
|
title: '提示',
|
||||||
content: '需要获取位置权限才能使用WiFi功能',
|
content: '搜索失败,请返回重试',
|
||||||
success: res => {
|
showCancel: false,
|
||||||
if (res.confirm) {
|
success: () => {
|
||||||
uni.openSetting()
|
uni.navigateBack()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
uni.$on('distributionNetworkResult', async data => {
|
||||||
|
uni.hideLoading()
|
||||||
|
pending.value = false
|
||||||
|
if (data.status === 0) {
|
||||||
|
$basic.routeJump({
|
||||||
|
type: 'redirectTo',
|
||||||
|
name: 'selectAddress'
|
||||||
|
})
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.showToast({
|
||||||
|
title: '连接成功',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}, 1000)
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: '连接失败,请重试',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const togglePassword = () => {
|
const togglePassword = () => {
|
||||||
showPassword.value = !showPassword.value
|
showPassword.value = !showPassword.value
|
||||||
@ -216,62 +167,7 @@
|
|||||||
wifiIndex.value = e.detail.value
|
wifiIndex.value = e.detail.value
|
||||||
}
|
}
|
||||||
|
|
||||||
function bleComboConfigure() {}
|
const connectWifi = async () => {
|
||||||
|
|
||||||
const connectDevice = async device => {
|
|
||||||
// try {
|
|
||||||
// const deviceAdapter = await bluetoothAdapter.connectDevice(device)
|
|
||||||
// console.log(1111, deviceAdapter)
|
|
||||||
// bleComboConfigure({
|
|
||||||
// token: '1234567890',
|
|
||||||
// wifiInfo: wifiInfo.value,
|
|
||||||
// familyId: 'default',
|
|
||||||
// roomId: 'default',
|
|
||||||
// deviceAdapter
|
|
||||||
// })
|
|
||||||
// current.value++
|
|
||||||
// } catch (err) {
|
|
||||||
// console.error('连接设备出错', err)
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
const searchDevice = async () => {
|
|
||||||
// try {
|
|
||||||
// await bluetoothAdapter.startSearch({
|
|
||||||
// onError: error => {
|
|
||||||
// console.log('搜索设备出错', error)
|
|
||||||
// bluetoothAdapter.stopSearch()
|
|
||||||
// },
|
|
||||||
// onSearch: devices => {
|
|
||||||
// if (devices.length > 0) {
|
|
||||||
// console.log('搜索到设备', devices)
|
|
||||||
// deviceList.value = devices
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// timeout: 1.4 * 15 * 1000
|
|
||||||
// })
|
|
||||||
// } catch (error) {
|
|
||||||
// console.log('搜索设备出错1', error)
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleNext = () => {
|
|
||||||
current.value++
|
|
||||||
searchDevice()
|
|
||||||
if (wifiIndex.value === undefined) {
|
|
||||||
uni.showToast({
|
|
||||||
title: '请选择WiFi',
|
|
||||||
icon: 'none'
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (password.value === '') {
|
|
||||||
uni.showToast({
|
|
||||||
title: '请输入密码',
|
|
||||||
icon: 'none'
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (password.value.length < 8) {
|
if (password.value.length < 8) {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: '密码长度不能小于8位',
|
title: '密码长度不能小于8位',
|
||||||
@ -280,25 +176,59 @@
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
wifiInfo.value = {
|
if (pending.value) return
|
||||||
SSID: wifiList.value[wifiIndex.value].SSID,
|
pending.value = true
|
||||||
password: password.value
|
uni.showLoading({
|
||||||
}
|
title: '连接中...'
|
||||||
|
})
|
||||||
|
|
||||||
uni.offGetWifiList()
|
const result = await passthrough({
|
||||||
if (deviceInfo.platform === 'android') {
|
request_method: 'GET',
|
||||||
uni.stopWifi()
|
request_uri: '/api/v1/tencentYun/getTencentTriple',
|
||||||
}
|
post_args: {
|
||||||
current.value++
|
serialNum0: $bluetooth.currentLockInfo.lockConfig.serialNum0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (result.code === 0) {
|
||||||
|
$bluetooth.updateCurrentLockInfo({
|
||||||
|
...$bluetooth.currentLockInfo,
|
||||||
|
tencentYunLock: {
|
||||||
|
productId: result.data.productId,
|
||||||
|
deviceName: result.data.deviceName,
|
||||||
|
devicePsk: result.data.devicePsk
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// const result = await $bluetooth.distributionNetwork({
|
||||||
|
// SSID: wifiList.value[wifiIndex.value].SSID,
|
||||||
|
// password: password.value,
|
||||||
|
// json: JSON.stringify({
|
||||||
|
// productId: result.data.productId,
|
||||||
|
// deviceName: result.data.deviceName,
|
||||||
|
// devicePsk: result.data.devicePsk
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// if (result.code !== 0) {
|
||||||
|
// uni.showToast({
|
||||||
|
// title: '连接失败,请重试',
|
||||||
|
// icon: 'none'
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
searchDevice()
|
setTimeout(() => {
|
||||||
|
$basic.routeJump({
|
||||||
|
type: 'redirectTo',
|
||||||
|
name: 'selectAddress'
|
||||||
|
})
|
||||||
|
}, 3000)
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: result.message,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleInput = e => {
|
||||||
|
password.value = e
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.custom-steps {
|
|
||||||
:deep(.u-text__value) {
|
|
||||||
font-size: 28rpx !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@ -139,7 +139,7 @@
|
|||||||
}
|
}
|
||||||
this.routeJump({
|
this.routeJump({
|
||||||
type: 'redirectTo',
|
type: 'redirectTo',
|
||||||
name: 'selectAddress'
|
name: false ? 'selectAddress' : 'distributionNetwork'
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
uni.hideLoading()
|
uni.hideLoading()
|
||||||
|
|||||||
@ -384,36 +384,36 @@
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.search {
|
.search {
|
||||||
padding: 32rpx;
|
|
||||||
width: 686rpx !important;
|
width: 686rpx !important;
|
||||||
|
padding: 32rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: calc(env(safe-area-inset-bottom) + 20rpx);
|
bottom: calc(env(safe-area-inset-bottom) + 20rpx);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
|
||||||
.button-reset {
|
.button-reset {
|
||||||
margin-left: 50rpx;
|
|
||||||
width: 300rpx;
|
width: 300rpx;
|
||||||
height: 88rpx;
|
height: 88rpx;
|
||||||
background-color: #df282d;
|
margin-left: 50rpx;
|
||||||
|
line-height: 88rpx;
|
||||||
color: white;
|
color: white;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 88rpx;
|
background-color: #df282d;
|
||||||
border-radius: 44rpx;
|
border-radius: 44rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-create {
|
.button-create {
|
||||||
margin-left: 50rpx;
|
|
||||||
width: 300rpx;
|
width: 300rpx;
|
||||||
height: 88rpx;
|
height: 88rpx;
|
||||||
background-color: #63b8af;
|
margin-left: 50rpx;
|
||||||
|
line-height: 88rpx;
|
||||||
color: white;
|
color: white;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 88rpx;
|
background-color: #63b8af;
|
||||||
border-radius: 44rpx;
|
border-radius: 44rpx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -421,29 +421,29 @@
|
|||||||
.item {
|
.item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: #ffffff;
|
|
||||||
height: 120rpx;
|
|
||||||
width: 750rpx;
|
width: 750rpx;
|
||||||
|
height: 120rpx;
|
||||||
|
background-color: #ffffff;
|
||||||
|
|
||||||
.item-left {
|
.item-left {
|
||||||
margin-left: 32rpx;
|
|
||||||
width: 80rpx;
|
width: 80rpx;
|
||||||
height: 80rpx;
|
height: 80rpx;
|
||||||
|
margin-left: 32rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-right {
|
.item-right {
|
||||||
|
width: 574rpx;
|
||||||
margin-right: 32rpx;
|
margin-right: 32rpx;
|
||||||
margin-left: 32rpx;
|
margin-left: 32rpx;
|
||||||
width: 574rpx;
|
|
||||||
|
|
||||||
.item-right-top {
|
.item-right-top {
|
||||||
max-width: 400rpx;
|
max-width: 400rpx;
|
||||||
font-size: 32rpx;
|
|
||||||
font-weight: bold;
|
|
||||||
padding-bottom: 6rpx;
|
padding-bottom: 6rpx;
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-right-bottom {
|
.item-right-bottom {
|
||||||
@ -467,9 +467,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.empty-list-text {
|
.empty-list-text {
|
||||||
text-align: center;
|
|
||||||
font-size: 32rpx;
|
font-size: 32rpx;
|
||||||
color: #999999;
|
color: #999999;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status {
|
.status {
|
||||||
|
|||||||
191
pages/main/customBox.vue
Normal file
191
pages/main/customBox.vue
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
<template>
|
||||||
|
<view class="dialog">
|
||||||
|
<image
|
||||||
|
class="top-background"
|
||||||
|
src="https://oss-lock.xhjcn.ltd/mp/background_main.jpg"
|
||||||
|
mode="aspectFill"
|
||||||
|
></image>
|
||||||
|
<view class="switch" @click="openDoorOperate">
|
||||||
|
<SwitchLoading :size="220" ref="sLoading"></SwitchLoading>
|
||||||
|
</view>
|
||||||
|
<view class="switch-text">点击开锁</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
import SwitchLoading from '@/components/SwitchLoading/SwitchLoading.vue'
|
||||||
|
import { useBluetoothStore } from '@/stores/bluetooth'
|
||||||
|
import { useBasicStore } from '@/stores/basic'
|
||||||
|
import { useUserStore } from '@/stores/user'
|
||||||
|
import { getLockDetailRequest, getLockNetTokenRequest } from '@/api/lock'
|
||||||
|
|
||||||
|
const $bluetooth = useBluetoothStore()
|
||||||
|
const $basic = useBasicStore()
|
||||||
|
const $user = useUserStore()
|
||||||
|
|
||||||
|
const sLoading = ref(null)
|
||||||
|
|
||||||
|
const pending = ref(false)
|
||||||
|
|
||||||
|
const lockInfo = ref(null)
|
||||||
|
|
||||||
|
const onlineToken = ref('0')
|
||||||
|
|
||||||
|
const lockId = ref(2712)
|
||||||
|
|
||||||
|
const time = ref(0)
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
const { code, data, message } = await getLockDetailRequest({
|
||||||
|
lockId: lockId.value
|
||||||
|
})
|
||||||
|
if (code === 0) {
|
||||||
|
lockInfo.value = data
|
||||||
|
$bluetooth.updateCurrentLockInfo({
|
||||||
|
...lockInfo.value,
|
||||||
|
name: lockInfo.value.lockName,
|
||||||
|
deviceId: lockInfo.value.lockName,
|
||||||
|
commKey: lockInfo.value.privateKey
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: message,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
await getServeTime()
|
||||||
|
})
|
||||||
|
|
||||||
|
const getServeTime = async () => {
|
||||||
|
const { code, data } = await $bluetooth.updateServerTimestamp()
|
||||||
|
if (code === 0) {
|
||||||
|
time.value = parseInt((data.date - new Date().getTime()) / 1000, 10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const openDoorOperate = async () => {
|
||||||
|
const timestamp = new Date().getTime()
|
||||||
|
if (pending.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const netWork = await $basic.getNetworkType()
|
||||||
|
if (!netWork) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lockInfo.value.appUnlockOnline) {
|
||||||
|
const result = await getNetToken()
|
||||||
|
if (!result) {
|
||||||
|
sLoading.value.close()
|
||||||
|
pending.value = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uni.vibrateLong()
|
||||||
|
pending.value = true
|
||||||
|
sLoading.value.open()
|
||||||
|
const openMode = lockInfo.value.appUnlockOnline ? 1 : 0
|
||||||
|
|
||||||
|
const { code } = await $bluetooth.openDoor({
|
||||||
|
name: lockInfo.value.lockName,
|
||||||
|
uid: $user.userInfo.uid.toString(),
|
||||||
|
openMode,
|
||||||
|
openTime: parseInt(new Date().getTime() / 1000, 10) + time.value,
|
||||||
|
onlineToken: onlineToken.value
|
||||||
|
})
|
||||||
|
|
||||||
|
$bluetooth
|
||||||
|
.syncRecord({
|
||||||
|
keyId: lockInfo.value.keyId.toString(),
|
||||||
|
uid: $user.userInfo.uid.toString()
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
$bluetooth.closeBluetoothConnection()
|
||||||
|
})
|
||||||
|
|
||||||
|
uni.reportEvent('open_door', {
|
||||||
|
result: code,
|
||||||
|
duration: new Date().getTime() - timestamp
|
||||||
|
})
|
||||||
|
|
||||||
|
if (code === 0) {
|
||||||
|
uni.showToast({
|
||||||
|
title: `开门成功`,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
} else if (code === 7) {
|
||||||
|
uni.showToast({
|
||||||
|
title: `钥匙过期`,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
} else if (code === 13) {
|
||||||
|
uni.showToast({
|
||||||
|
title: `钥匙当前不可用`,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
} else if (code === -1) {
|
||||||
|
uni.showToast({
|
||||||
|
title: `开锁失败`,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
sLoading.value.close()
|
||||||
|
pending.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const getNetToken = async () => {
|
||||||
|
const { code, data, message } = await getLockNetTokenRequest({
|
||||||
|
lockId: lockId.value
|
||||||
|
})
|
||||||
|
if (code === 0) {
|
||||||
|
onlineToken.value = data.token
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
uni.showToast({
|
||||||
|
title: message,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.dialog {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 75vh;
|
||||||
|
background-color: #f3f3f3;
|
||||||
|
|
||||||
|
.top-background {
|
||||||
|
position: absolute;
|
||||||
|
width: 686rpx;
|
||||||
|
height: 464rpx;
|
||||||
|
border-radius: 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch {
|
||||||
|
z-index: 99;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 250rpx;
|
||||||
|
height: 250rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 50%;
|
||||||
|
box-shadow: 0 8rpx 36rpx 0 rgba(0, 0, 0, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-text {
|
||||||
|
z-index: 99;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -221,6 +221,16 @@
|
|||||||
></image>
|
></image>
|
||||||
<view>消息提醒</view>
|
<view>消息提醒</view>
|
||||||
</view>
|
</view>
|
||||||
|
<view
|
||||||
|
class="menu-main-view transform-scale-105"
|
||||||
|
@click="$basic.routeJump({ name: 'authorizeWechat' })"
|
||||||
|
>
|
||||||
|
<image
|
||||||
|
class="menu-main-image"
|
||||||
|
src="https://oss-lock.xhjcn.ltd/mp/icon_wechat_call.png"
|
||||||
|
></image>
|
||||||
|
<view>微信呼叫</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="setting" @click="$basic.routeJump({ name: 'setting' })">
|
<view class="setting" @click="$basic.routeJump({ name: 'setting' })">
|
||||||
|
|||||||
148
pages/p2p/authorizeWechat.vue
Normal file
148
pages/p2p/authorizeWechat.vue
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<view class="mt-10 text-center text-base font-bold text-[#999]">授权后,设备可呼叫该微信</view>
|
||||||
|
<view v-if="requestFinish">
|
||||||
|
<view
|
||||||
|
v-if="!isAuthorized"
|
||||||
|
class="bg-[#63b8af] text-white rounded-full text-center leading-88rpx h-88rpx w-686 mx-4 mt-10"
|
||||||
|
@click="handleAuthorize"
|
||||||
|
>
|
||||||
|
授权
|
||||||
|
</view>
|
||||||
|
<view v-else>
|
||||||
|
<view v-if="!reject" class="text-center text-lg font-bold mt-4">您已授权</view>
|
||||||
|
<view v-else>
|
||||||
|
<view class="text-center text-lg font-bold mt-4"> 您已拒绝授权,请去设置中 </view>
|
||||||
|
<view class="text-center text-lg font-bold mt-4"> 打开语音、视频通话提醒开关 </view>
|
||||||
|
<view
|
||||||
|
class="bg-[#63b8af] text-white rounded-full text-center leading-88rpx h-88rpx w-686 mx-4 mt-10"
|
||||||
|
@click="openSetting"
|
||||||
|
>
|
||||||
|
打开设置
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { onShow } from '@dcloudio/uni-app'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { passthrough } from '@/api/sdk'
|
||||||
|
import { useBluetoothStore } from '@/stores/bluetooth'
|
||||||
|
import env from '@/config/env'
|
||||||
|
|
||||||
|
const $bluetooth = useBluetoothStore()
|
||||||
|
|
||||||
|
const requestFinish = ref(false)
|
||||||
|
|
||||||
|
const isAuthorized = ref(false)
|
||||||
|
const list = ref([])
|
||||||
|
|
||||||
|
const reject = ref(false)
|
||||||
|
|
||||||
|
const pending = ref(false)
|
||||||
|
|
||||||
|
onShow(() => {
|
||||||
|
uni.showLoading({
|
||||||
|
title: '加载中...'
|
||||||
|
})
|
||||||
|
wx.getDeviceVoIPList({
|
||||||
|
async success(res) {
|
||||||
|
list.value = res.list
|
||||||
|
if (res.list.length > 0) {
|
||||||
|
const result = await getInfo()
|
||||||
|
if (result.code === 0) {
|
||||||
|
const data = list.value.find(item => item.sn === result.data.WXIoTDeviceInfo.SN)
|
||||||
|
if (data) {
|
||||||
|
if (data.status === 1) {
|
||||||
|
reject.value = false
|
||||||
|
} else if (data.status === 0) {
|
||||||
|
reject.value = true
|
||||||
|
}
|
||||||
|
isAuthorized.value = true
|
||||||
|
requestFinish.value = true
|
||||||
|
uni.hideLoading()
|
||||||
|
} else {
|
||||||
|
requestFinish.value = true
|
||||||
|
uni.hideLoading()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: result.message,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
requestFinish.value = true
|
||||||
|
uni.hideLoading()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
requestFinish.value = true
|
||||||
|
uni.hideLoading()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const openSetting = () => {
|
||||||
|
uni.openSetting({
|
||||||
|
success: res => {
|
||||||
|
console.log(res)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const getInfo = async () => {
|
||||||
|
const result = await passthrough({
|
||||||
|
request_method: 'GET',
|
||||||
|
request_uri: '/api/v1/tencentYun/getWechatDeviceTicket',
|
||||||
|
post_args: {
|
||||||
|
lockId: $bluetooth.currentLockInfo.lockId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAuthorize = async () => {
|
||||||
|
if (pending.value) return
|
||||||
|
pending.value = true
|
||||||
|
uni.showLoading({
|
||||||
|
title: '授权中...'
|
||||||
|
})
|
||||||
|
const result = await getInfo()
|
||||||
|
if (result.code === 0) {
|
||||||
|
wx.requestDeviceVoIP({
|
||||||
|
sn: result.data.WXIoTDeviceInfo.SN,
|
||||||
|
snTicket: result.data.WXIoTDeviceInfo.SNTicket,
|
||||||
|
modelId: result.data.WXIoTDeviceInfo.ModelId,
|
||||||
|
deviceName: await env[await getApp().globalData.getEnvConfig()].appName,
|
||||||
|
success() {
|
||||||
|
isAuthorized.value = true
|
||||||
|
uni.hideLoading()
|
||||||
|
pending.value = false
|
||||||
|
uni.showToast({
|
||||||
|
title: '授权成功',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
fail() {
|
||||||
|
isAuthorized.value = true
|
||||||
|
reject.value = true
|
||||||
|
uni.hideLoading()
|
||||||
|
pending.value = false
|
||||||
|
uni.showToast({
|
||||||
|
title: '授权失败',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
uni.hideLoading()
|
||||||
|
pending.value = false
|
||||||
|
uni.showToast({
|
||||||
|
title: result.message,
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@ -1,20 +1,50 @@
|
|||||||
<template>
|
<template>
|
||||||
<view>
|
<view>
|
||||||
<iot-p2p-player-with-mjpg
|
<iot-p2p-player-with-mjpg
|
||||||
|
v-if="deviceInfo"
|
||||||
id="playerRef"
|
id="playerRef"
|
||||||
:deviceInfo="deviceInfo"
|
:deviceInfo="deviceInfo"
|
||||||
:xp2pInfo="xp2pInfo"
|
:xp2pInfo="xp2pInfo"
|
||||||
:rotate="90"
|
:rotate="90"
|
||||||
:muted="isMute"
|
:muted="isMute"
|
||||||
streamQuality="high"
|
mode="RTC"
|
||||||
|
:acceptPlayerEvents="true"
|
||||||
|
soundMode="speaker"
|
||||||
|
sceneType="live"
|
||||||
|
:streamQuality="range[index].value"
|
||||||
:minCache="0.2"
|
:minCache="0.2"
|
||||||
:maxCache="0.8"
|
:maxCache="0.8"
|
||||||
:fill="true"
|
:fill="true"
|
||||||
orientation="horizontal"
|
orientation="horizontal"
|
||||||
@statechange="handleStateChange"
|
@playsuccess="handlePlaySuccess"
|
||||||
>
|
>
|
||||||
</iot-p2p-player-with-mjpg>
|
</iot-p2p-player-with-mjpg>
|
||||||
|
<view
|
||||||
|
v-if="buttonInfo"
|
||||||
|
:style="{
|
||||||
|
top: buttonInfo.bottom + 15 + 'px'
|
||||||
|
}"
|
||||||
|
class="bg-[rgba(0,0,0,0.35)] rounded-full px-2 py-1.5 fixed right-32"
|
||||||
|
>
|
||||||
|
<picker :value="index" mode="selector" :range="range" range-key="name" @change="changeEvent">
|
||||||
|
<up-icon
|
||||||
|
:label="range[index].name"
|
||||||
|
color="#ffffff"
|
||||||
|
label-color="#ffffff"
|
||||||
|
labelPos="left"
|
||||||
|
name="arrow-down-fill"
|
||||||
|
size="32rpx"
|
||||||
|
space="16rpx"
|
||||||
|
></up-icon>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
<image
|
||||||
|
v-if="!isVideoLoaded"
|
||||||
|
src="https://oss-lock.xhjcn.ltd/mp/background_monitor.png"
|
||||||
|
class="w-full h-full absolute top-0 left-0"
|
||||||
|
></image>
|
||||||
<iot-p2p-voice
|
<iot-p2p-voice
|
||||||
|
v-if="deviceInfo"
|
||||||
id="voiceComponent"
|
id="voiceComponent"
|
||||||
:deviceInfo="deviceInfo"
|
:deviceInfo="deviceInfo"
|
||||||
:xp2pInfo="xp2pInfo"
|
:xp2pInfo="xp2pInfo"
|
||||||
@ -23,6 +53,7 @@
|
|||||||
</iot-p2p-voice>
|
</iot-p2p-voice>
|
||||||
|
|
||||||
<view
|
<view
|
||||||
|
v-if="isVideoLoaded"
|
||||||
class="fixed bottom-[calc(32rpx+env(safe-area-inset-bottom))] bg-[rgba(0,0,0,0.3)] rounded-xl p-4 shadow-lg mx-4 w-622"
|
class="fixed bottom-[calc(32rpx+env(safe-area-inset-bottom))] bg-[rgba(0,0,0,0.3)] rounded-xl p-4 shadow-lg mx-4 w-622"
|
||||||
>
|
>
|
||||||
<view class="flex items-center justify-around mx-10">
|
<view class="flex items-center justify-around mx-10">
|
||||||
@ -72,21 +103,39 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<view
|
||||||
|
v-if="!isVideoLoaded"
|
||||||
|
class="fixed bottom-[calc(48rpx+env(safe-area-inset-bottom))] w-full flex justify-center"
|
||||||
|
>
|
||||||
|
<up-loading-icon
|
||||||
|
size="70rpx"
|
||||||
|
:vertical="true"
|
||||||
|
textSize="28rpx"
|
||||||
|
text="连接中"
|
||||||
|
mode="circle"
|
||||||
|
></up-loading-icon>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { getXp2pManager } from './xp2pManager'
|
|
||||||
import { useBluetoothStore } from '@/stores/bluetooth'
|
|
||||||
import { useBasicStore } from '@/stores/basic'
|
|
||||||
import { onMounted, ref } from 'vue'
|
import { onMounted, ref } from 'vue'
|
||||||
import { onUnload } from '@dcloudio/uni-app'
|
import { onUnload } from '@dcloudio/uni-app'
|
||||||
import { getP2pInfo } from '@/api/p2p'
|
import { useBluetoothStore } from '@/stores/bluetooth'
|
||||||
|
import { useBasicStore } from '@/stores/basic'
|
||||||
|
import { passthrough } from '@/api/sdk'
|
||||||
|
|
||||||
const $bluetooth = useBluetoothStore()
|
const $bluetooth = useBluetoothStore()
|
||||||
const $basic = useBasicStore()
|
const $basic = useBasicStore()
|
||||||
|
|
||||||
let xp2pManager = null
|
const buttonInfo = ref(null)
|
||||||
|
|
||||||
|
const index = ref(1)
|
||||||
|
const range = ref([
|
||||||
|
{ name: '标清', value: 'standard' },
|
||||||
|
{ name: '高清', value: 'high' },
|
||||||
|
{ name: '超清', value: 'super' }
|
||||||
|
])
|
||||||
|
|
||||||
const deviceInfo = ref()
|
const deviceInfo = ref()
|
||||||
const xp2pInfo = ref()
|
const xp2pInfo = ref()
|
||||||
@ -94,28 +143,26 @@
|
|||||||
const isVoice = ref(false)
|
const isVoice = ref(false)
|
||||||
|
|
||||||
const isMute = ref(false)
|
const isMute = ref(false)
|
||||||
|
const isVideoLoaded = ref(false)
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
if (!xp2pManager) {
|
buttonInfo.value = await $basic.getButtonInfo()
|
||||||
xp2pManager = getXp2pManager()
|
|
||||||
}
|
|
||||||
|
|
||||||
const { code, data, message } = await getP2pInfo({
|
const { code, data, message } = await passthrough({
|
||||||
lockId: $bluetooth.currentLockInfo.lockId
|
request_method: 'GET',
|
||||||
|
request_uri: '/api/v1/tencentYun/getDeviceDetailData',
|
||||||
|
post_args: {
|
||||||
|
lockId: $bluetooth.currentLockInfo.lockId
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if (code === 0) {
|
if (code === 0) {
|
||||||
deviceInfo.value = {
|
deviceInfo.value = {
|
||||||
deviceId: `${data.productId}/${data.deviceId}`,
|
deviceId: `${data.productId}/${data.deviceName}`,
|
||||||
productId: data.productId,
|
productId: data.productId,
|
||||||
deviceName: data.deviceName
|
deviceName: data.deviceName
|
||||||
}
|
}
|
||||||
xp2pInfo.value = data.xp2pInfo
|
xp2pInfo.value = data.xp2pInfo
|
||||||
await xp2pManager.startP2PService({
|
|
||||||
deviceInfo: deviceInfo.value,
|
|
||||||
xp2pInfo: xp2pInfo.value,
|
|
||||||
caller: 1
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
$basic.backAndToast(message)
|
$basic.backAndToast(message)
|
||||||
}
|
}
|
||||||
@ -129,6 +176,10 @@
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const changeEvent = e => {
|
||||||
|
index.value = e.detail.value
|
||||||
|
}
|
||||||
|
|
||||||
const handleScreenshot = () => {
|
const handleScreenshot = () => {
|
||||||
const page = getCurrentPages().pop()
|
const page = getCurrentPages().pop()
|
||||||
const player = page.selectComponent('#playerRef')
|
const player = page.selectComponent('#playerRef')
|
||||||
@ -180,8 +231,8 @@
|
|||||||
voice.stopVoice()
|
voice.stopVoice()
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleStateChange = state => {
|
const handlePlaySuccess = () => {
|
||||||
console.log(11111111, state)
|
isVideoLoaded.value = true
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -1,29 +0,0 @@
|
|||||||
export const getUserId = () => {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
export function compareVersion(ver1, ver2) {
|
|
||||||
const v1 = ver1.split('.')
|
|
||||||
const v2 = ver2.split('.')
|
|
||||||
const len = Math.max(v1.length, v2.length)
|
|
||||||
|
|
||||||
while (v1.length < len) {
|
|
||||||
v1.push('0')
|
|
||||||
}
|
|
||||||
while (v2.length < len) {
|
|
||||||
v2.push('0')
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < len; i++) {
|
|
||||||
const num1 = parseInt(v1[i])
|
|
||||||
const num2 = parseInt(v2[i])
|
|
||||||
|
|
||||||
if (num1 > num2) {
|
|
||||||
return 1
|
|
||||||
} else if (num1 < num2) {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
@ -1,118 +0,0 @@
|
|||||||
import { getUserId, compareVersion } from './utils'
|
|
||||||
|
|
||||||
let xp2pManager = null
|
|
||||||
export const getXp2pManager = () => {
|
|
||||||
if (!xp2pManager) {
|
|
||||||
let xp2pPlugin = requirePlugin('xp2p')
|
|
||||||
|
|
||||||
console.log(11111, xp2pPlugin)
|
|
||||||
|
|
||||||
const iotExports = xp2pPlugin.iot
|
|
||||||
const app = getApp()
|
|
||||||
|
|
||||||
// 用户id,微信用户在此小程序中的唯一标识
|
|
||||||
iotExports?.setUserId?.(getUserId() || 'demo')
|
|
||||||
|
|
||||||
// 开发版才打插件log
|
|
||||||
if (app.pluginLogger && uni.getAccountInfoSync().miniProgram.envVersion === 'develop') {
|
|
||||||
iotExports?.setPluginLogger?.(app.pluginLogger)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置优先使用的打洞协议
|
|
||||||
if (
|
|
||||||
compareVersion(uni.getSystemInfoSync().SDKVersion, '3.4.1') >= 0 &&
|
|
||||||
xp2pPlugin.p2p.setTcpFirst
|
|
||||||
) {
|
|
||||||
const tcpFirstKey = 'tcpFirst'
|
|
||||||
const tcpFirstTime = parseInt(uni.getStorageSync(tcpFirstKey), 10)
|
|
||||||
const tcpFirst = !!(tcpFirstTime && Date.now() - tcpFirstTime < 3600000 * 24) // 24小时内有效
|
|
||||||
console.log('tcpFirst', tcpFirst)
|
|
||||||
xp2pPlugin.p2p.setTcpFirst(tcpFirst)
|
|
||||||
|
|
||||||
// 给index页用,方便测试时调整tcpFirst
|
|
||||||
app.tcpFirst = tcpFirst
|
|
||||||
app.toggleTcpFirst = async () => {
|
|
||||||
const modalRes = await uni.showModal({
|
|
||||||
title: '确定切换 tcpFirst 吗?',
|
|
||||||
content: '切换后需要重新进入小程序'
|
|
||||||
})
|
|
||||||
if (!modalRes || !modalRes.confirm) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
uni.setStorageSync(tcpFirstKey, tcpFirst ? '' : Date.now())
|
|
||||||
app.restart()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置是否连接对端stun
|
|
||||||
if (xp2pPlugin.p2p.setCrossStunTurn) {
|
|
||||||
const crossStunTurnKey = 'crossStunTurn'
|
|
||||||
const crossStunTurnTime = parseInt(uni.getStorageSync(crossStunTurnKey), 10)
|
|
||||||
const crossStunTurn = !!(crossStunTurnTime && Date.now() - crossStunTurnTime < 3600000 * 24) // 24小时内有效
|
|
||||||
xp2pPlugin.p2p.setCrossStunTurn(crossStunTurn)
|
|
||||||
// 给index页用,方便测试时调整crossStunTurn
|
|
||||||
app.crossStunTurn = crossStunTurn
|
|
||||||
app.toggleCrossStunTurn = async () => {
|
|
||||||
const modalRes = await uni.showModal({
|
|
||||||
title: '确定切换 crossStunTurn 吗?',
|
|
||||||
content: '切换后需要重新进入小程序'
|
|
||||||
})
|
|
||||||
if (!modalRes || !modalRes.confirm) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
uni.setStorageSync(crossStunTurnKey, crossStunTurn ? '' : Date.now())
|
|
||||||
app.restart()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置切换端口
|
|
||||||
if (xp2pPlugin.p2p.updateStunPort) {
|
|
||||||
const portKey = 'STUN_PORT'
|
|
||||||
const stunPort = uni.getStorageSync(portKey) || 20002
|
|
||||||
xp2pPlugin.p2p.updateStunPort(stunPort)
|
|
||||||
app.stunPort = stunPort
|
|
||||||
app.togglePort = async port => {
|
|
||||||
const modalRes = await uni.showModal({
|
|
||||||
title: '确定切换 stunPort 吗?',
|
|
||||||
content: '切换后需要重新进入小程序'
|
|
||||||
})
|
|
||||||
if (!modalRes || !modalRes.confirm) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
uni.setStorageSync(portKey, port)
|
|
||||||
app.restart()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置切换配置跟随
|
|
||||||
if (xp2pPlugin.p2p.setUseDeliveryConfig) {
|
|
||||||
const useDeliveryConfigKey = 'useDeliveryConfig'
|
|
||||||
const useDeliveryConfigTime = parseInt(uni.getStorageSync(useDeliveryConfigKey), 10)
|
|
||||||
const useDeliveryConfig = !!(
|
|
||||||
useDeliveryConfigTime && Date.now() - useDeliveryConfigTime < 3600000 * 24
|
|
||||||
) // 24小时内有效
|
|
||||||
xp2pPlugin.p2p.setUseDeliveryConfig(useDeliveryConfig)
|
|
||||||
app.useDeliveryConfig = useDeliveryConfig
|
|
||||||
app.toggleUseDeliveryConfig = async () => {
|
|
||||||
const modalRes = await uni.showModal({
|
|
||||||
title: '确定切换 使用设备跟随 吗?',
|
|
||||||
content: '切换后需要重新进入小程序'
|
|
||||||
})
|
|
||||||
if (!modalRes || !modalRes.confirm) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
uni.setStorageSync(useDeliveryConfigKey, useDeliveryConfig ? '' : Date.now())
|
|
||||||
app.restart()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
xp2pManager = iotExports.getXp2pManager()
|
|
||||||
app.logger?.log('xp2pManager', {
|
|
||||||
P2PPlayerVersion: xp2pManager.P2PPlayerVersion,
|
|
||||||
XP2PVersion: xp2pManager.XP2PVersion,
|
|
||||||
// uuid,插件随机生成的id,存储在小程序本地,删除小程序后会重新生成
|
|
||||||
uuid: xp2pManager.uuid
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return xp2pManager
|
|
||||||
}
|
|
||||||
@ -9,7 +9,7 @@
|
|||||||
? catEyeMode[
|
? catEyeMode[
|
||||||
$bluetooth.currentLockSetting.lockSettingInfo.catEyeConfig[0]?.catEyeMode
|
$bluetooth.currentLockSetting.lockSettingInfo.catEyeConfig[0]?.catEyeMode
|
||||||
].name
|
].name
|
||||||
: ""
|
: ''
|
||||||
}}
|
}}
|
||||||
</view>
|
</view>
|
||||||
<up-icon name="arrow-right"></up-icon>
|
<up-icon name="arrow-right"></up-icon>
|
||||||
|
|||||||
@ -391,6 +391,11 @@ const pages = [
|
|||||||
name: 'p2pPlayer',
|
name: 'p2pPlayer',
|
||||||
path: '/pages/p2p/p2pPlayer',
|
path: '/pages/p2p/p2pPlayer',
|
||||||
tabBar: false
|
tabBar: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'authorizeWechat',
|
||||||
|
path: '/pages/p2p/authorizeWechat',
|
||||||
|
tabBar: false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@ -56,7 +56,15 @@ const cmdIds = {
|
|||||||
// 锁遥控列表
|
// 锁遥控列表
|
||||||
lockRemoteList: 0x3026,
|
lockRemoteList: 0x3026,
|
||||||
// 锁设置列表
|
// 锁设置列表
|
||||||
lockSettingList: 0x302a
|
lockSettingList: 0x302a,
|
||||||
|
// 获取Wi-Fi列表
|
||||||
|
getWifiList: 0x30f6,
|
||||||
|
// Wi-Fi列表
|
||||||
|
wifiList: 0x30f7,
|
||||||
|
// 配网
|
||||||
|
distributionNetwork: 0x30f4,
|
||||||
|
// 配网结果
|
||||||
|
distributionNetworkResult: 0x30f5
|
||||||
}
|
}
|
||||||
|
|
||||||
// 子命令ID
|
// 子命令ID
|
||||||
@ -396,6 +404,34 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
case cmdIds.getWifiList:
|
||||||
|
characteristicValueCallback({
|
||||||
|
code: decrypted[2]
|
||||||
|
})
|
||||||
|
break
|
||||||
|
case cmdIds.wifiList:
|
||||||
|
const wifiList = []
|
||||||
|
for (let i = 0; i < decrypted[3]; i++) {
|
||||||
|
wifiList.push({
|
||||||
|
SSID: that.uint8ArrayToString(decrypted.slice(4 + 33 * i, 4 + 33 * i + 32)),
|
||||||
|
rssi: decrypted[33 + 33 * i]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
uni.$emit('wifiList', {
|
||||||
|
status: decrypted[2],
|
||||||
|
wifiList
|
||||||
|
})
|
||||||
|
break
|
||||||
|
case cmdIds.distributionNetwork:
|
||||||
|
characteristicValueCallback({
|
||||||
|
code: decrypted[2]
|
||||||
|
})
|
||||||
|
break
|
||||||
|
case cmdIds.distributionNetworkResult:
|
||||||
|
uni.$emit('distributionNetworkResult', {
|
||||||
|
status: decrypted[2]
|
||||||
|
})
|
||||||
|
break
|
||||||
case cmdIds.addUser:
|
case cmdIds.addUser:
|
||||||
that.updateCurrentLockInfo({
|
that.updateCurrentLockInfo({
|
||||||
...that.currentLockInfo,
|
...that.currentLockInfo,
|
||||||
@ -1558,6 +1594,123 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
|
|
||||||
return this.getWriteResult(this.getLockStatus, data)
|
return this.getWriteResult(this.getLockStatus, data)
|
||||||
},
|
},
|
||||||
|
// 获取Wi-Fi列表
|
||||||
|
async getWifiList(data) {
|
||||||
|
// 确认蓝牙状态正常
|
||||||
|
if (this.bluetoothStatus !== 0) {
|
||||||
|
console.log('写入未执行', this.bluetoothStatus)
|
||||||
|
this.getBluetoothStatus()
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确认设备连接正常
|
||||||
|
if (!this.currentLockInfo.connected) {
|
||||||
|
const searchResult = await this.searchAndConnectDevice()
|
||||||
|
if (searchResult.code !== 0) {
|
||||||
|
return searchResult
|
||||||
|
}
|
||||||
|
this.updateCurrentLockInfo({
|
||||||
|
...this.currentLockInfo,
|
||||||
|
deviceId: searchResult.data.deviceId
|
||||||
|
})
|
||||||
|
console.log('设备ID:', this.currentLockInfo.deviceId)
|
||||||
|
const result = await this.connectBluetoothDevice()
|
||||||
|
console.log('连接结果', result)
|
||||||
|
if (!result) {
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { uid } = data
|
||||||
|
const length = 2 + 20
|
||||||
|
const headArray = this.createPackageHeader(3, length)
|
||||||
|
|
||||||
|
const contentArray = new Uint8Array(length)
|
||||||
|
contentArray[0] = cmdIds.getWifiList / 256
|
||||||
|
contentArray[1] = cmdIds.getWifiList % 256
|
||||||
|
for (let i = 0; i < uid.length; i++) {
|
||||||
|
contentArray[i + 2] = uid.charCodeAt(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
const cebArray = sm4.encrypt(contentArray, this.currentLockInfo.commKey, {
|
||||||
|
mode: 'ecb',
|
||||||
|
output: 'array'
|
||||||
|
})
|
||||||
|
|
||||||
|
const packageArray = this.createPackageEnd(headArray, cebArray)
|
||||||
|
|
||||||
|
await this.writeBLECharacteristicValue(packageArray)
|
||||||
|
|
||||||
|
return this.getWriteResult(this.getWifiList, data)
|
||||||
|
},
|
||||||
|
// 配网
|
||||||
|
async distributionNetwork(data) {
|
||||||
|
// 确认蓝牙状态正常
|
||||||
|
if (this.bluetoothStatus !== 0) {
|
||||||
|
console.log('写入未执行', this.bluetoothStatus)
|
||||||
|
this.getBluetoothStatus()
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确认设备连接正常
|
||||||
|
if (!this.currentLockInfo.connected) {
|
||||||
|
const searchResult = await this.searchAndConnectDevice()
|
||||||
|
if (searchResult.code !== 0) {
|
||||||
|
return searchResult
|
||||||
|
}
|
||||||
|
this.updateCurrentLockInfo({
|
||||||
|
...this.currentLockInfo,
|
||||||
|
deviceId: searchResult.data.deviceId
|
||||||
|
})
|
||||||
|
console.log('设备ID:', this.currentLockInfo.deviceId)
|
||||||
|
const result = await this.connectBluetoothDevice()
|
||||||
|
console.log('连接结果', result)
|
||||||
|
if (!result) {
|
||||||
|
return {
|
||||||
|
code: -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { SSID, password, json } = data
|
||||||
|
const length = 2 + 30 + 20 + json.length
|
||||||
|
const headArray = this.createPackageHeader(3, length)
|
||||||
|
|
||||||
|
const contentArray = new Uint8Array(length)
|
||||||
|
contentArray[0] = cmdIds.distributionNetwork / 256
|
||||||
|
contentArray[1] = cmdIds.distributionNetwork % 256
|
||||||
|
for (let i = 0; i < SSID.length; i++) {
|
||||||
|
contentArray[i + 2] = SSID.charCodeAt(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < password.length; i++) {
|
||||||
|
contentArray[i + 32] = password.charCodeAt(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
contentArray[52] = json.length / 256
|
||||||
|
contentArray[53] = json.length % 256
|
||||||
|
|
||||||
|
for (let i = 0; i < json.length; i++) {
|
||||||
|
contentArray[i + 54] = json.charCodeAt(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
const cebArray = sm4.encrypt(contentArray, this.currentLockInfo.commKey, {
|
||||||
|
mode: 'ecb',
|
||||||
|
output: 'array'
|
||||||
|
})
|
||||||
|
|
||||||
|
const packageArray = this.createPackageEnd(headArray, cebArray)
|
||||||
|
|
||||||
|
await this.writeBLECharacteristicValue(packageArray)
|
||||||
|
|
||||||
|
return this.getWriteResult(this.distributionNetwork, data)
|
||||||
|
},
|
||||||
// 时间戳转二进制
|
// 时间戳转二进制
|
||||||
timestampToArray(timestamp) {
|
timestampToArray(timestamp) {
|
||||||
const array = new Uint8Array(4)
|
const array = new Uint8Array(4)
|
||||||
@ -2732,12 +2885,12 @@ export const useBluetoothStore = defineStore('ble', {
|
|||||||
const md5Array = this.md5Encrypte(
|
const md5Array = this.md5Encrypte(
|
||||||
uid + keyId,
|
uid + keyId,
|
||||||
this.currentLockInfo.token || new Uint8Array([0, 0, 0, 0]),
|
this.currentLockInfo.token || new Uint8Array([0, 0, 0, 0]),
|
||||||
this.currentLockInfo.bluetooth.publicKey
|
this.currentLockInfo.publicKey
|
||||||
)
|
)
|
||||||
|
|
||||||
contentArray.set(md5Array, 75)
|
contentArray.set(md5Array, 75)
|
||||||
|
|
||||||
const cebArray = sm4.encrypt(contentArray, this.currentLockInfo.bluetooth.privateKey, {
|
const cebArray = sm4.encrypt(contentArray, this.currentLockInfo.commKey, {
|
||||||
mode: 'ecb',
|
mode: 'ecb',
|
||||||
output: 'array'
|
output: 'array'
|
||||||
})
|
})
|
||||||
|
|||||||
@ -29,13 +29,13 @@ const request = config => {
|
|||||||
const timestamp = new Date().getTime()
|
const timestamp = new Date().getTime()
|
||||||
timer = setTimeout(() => {
|
timer = setTimeout(() => {
|
||||||
resolve({ code: -1, message: '网络访问失败,请检查网络是否正常' })
|
resolve({ code: -1, message: '网络访问失败,请检查网络是否正常' })
|
||||||
}, 7200)
|
}, 30200)
|
||||||
uni.request({
|
uni.request({
|
||||||
url: URL,
|
url: URL,
|
||||||
method,
|
method,
|
||||||
header,
|
header,
|
||||||
data,
|
data,
|
||||||
timeout: 7000,
|
timeout: 30000,
|
||||||
async success(res) {
|
async success(res) {
|
||||||
const { statusCode, data } = res
|
const { statusCode, data } = res
|
||||||
if (timer) {
|
if (timer) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user