diff --git a/.eslintrc.cjs b/.eslintrc.cjs
index 2e0c9c9..3128e38 100644
--- a/.eslintrc.cjs
+++ b/.eslintrc.cjs
@@ -8,7 +8,8 @@ module.exports = {
globals: {
uni: 'writable',
getApp: 'writable',
- wx: 'writable'
+ wx: 'writable',
+ getCurrentPages: 'writable'
},
// 指定如何解析语法
parser: 'vue-eslint-parser',
@@ -41,17 +42,15 @@ module.exports = {
'no-var': 'error', // 要求使用 let 或 const 而不是 var
'no-multiple-empty-lines': ['error', { max: 1 }], // 不允许多个空行
'prefer-const': 'off', // 使用 let 关键字声明但在初始分配后从未重新分配的变量,要求使用 const
- 'no-use-before-define': 'error', // 禁止在 函数/类/变量 定义之前使用它们
+ 'no-use-before-define': 'off', // 禁止在 函数/类/变量 定义之前使用它们
'no-irregular-whitespace': 'off', // 禁止不规则的空白
'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-properties': [
- 'error',
- {
- ignore: ['getDeviceInfo', 'getBluetoothDevices', 'stopGetBluetoothDevices']
- }
- ], // 忽略特定方法的未定义检查
+ 'vue/no-undef-properties': 'off', // 关闭属性未定义的检查
+ 'vue/no-unused-vars': 'error', // 禁止Vue组件中出现未使用的变量
+ 'import/no-unused-modules': 'off', // 关闭模块导出检查
'import/no-cycle': 0,
'no-nested-ternary': 0,
'import/prefer-default-export': 0,
diff --git a/App.vue b/App.vue
index b2795b5..6b24e74 100644
--- a/App.vue
+++ b/App.vue
@@ -39,6 +39,8 @@
this.updateMiniProgram()
// 监听蓝牙开关状态
this.onBluetoothState()
+ // 设置voip配置
+ this.setVoipConfig()
// 检查蓝牙权限
const checkResult = await this.checkSetting()
console.log(checkResult)
@@ -65,6 +67,24 @@
'initAndListenBluetooth'
]),
...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() {
const updateManager = uni.getUpdateManager()
diff --git a/api/p2p.js b/api/p2p.js
deleted file mode 100644
index 7f6d4a4..0000000
--- a/api/p2p.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import request from '../utils/request'
-
-// p2p 模块
-
-// 获取p2pInfo
-export function getP2pInfo(data) {
- return request({
- url: '/v1/tencentYun/getDeviceDetail',
- method: 'POST',
- data
- })
-}
diff --git a/api/sdk.js b/api/sdk.js
new file mode 100644
index 0000000..5ec215c
--- /dev/null
+++ b/api/sdk.js
@@ -0,0 +1,12 @@
+import request from '../utils/request'
+
+// sdk 模块
+
+// 透传
+export function passthrough(data) {
+ return request({
+ url: '/passthrough',
+ method: 'POST',
+ data
+ })
+}
diff --git a/config/env.js b/config/env.js
index d64d6c6..75636f8 100644
--- a/config/env.js
+++ b/config/env.js
@@ -9,14 +9,17 @@ uni.getSystemInfo({
const DEV = {
name: 'dev',
- baseUrl: 'https://dev.lock.star-lock.cn/api',
- webviewBaseUrl: 'https://dev.lock.star-lock.cn',
+ appName: '星星锁Lite',
+ baseUrl: 'https://lock.dev.star-lock.cn/api',
+ webviewBaseUrl: 'https://lock.dev.star-lock.cn',
version,
buildNumber
}
+
const 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',
version,
buildNumber
@@ -24,6 +27,7 @@ const PRE = {
const XHJ = {
name: 'xhj',
+ appName: '星星锁Lite',
baseUrl: 'https://lock.xhjcn.ltd/api',
webviewBaseUrl: 'https://lock.xhjcn.ltd',
version,
@@ -32,6 +36,7 @@ const XHJ = {
const SKY = {
name: 'sky',
+ appName: '星星锁Lite',
baseUrl: 'https://lock.skychip.top/api',
webviewBaseUrl: 'https://lock.skychip.top',
version,
@@ -40,6 +45,7 @@ const SKY = {
const GE = {
name: 'ge',
+ appName: '星星锁Lite',
baseUrl: 'http://lock.ge.star-lock.cn/api',
webviewBaseUrl: 'http://lock.ge.star-lock.cn',
version,
diff --git a/jsconfig.json b/jsconfig.json
new file mode 100644
index 0000000..eb0cdc9
--- /dev/null
+++ b/jsconfig.json
@@ -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"
+ ]
+}
\ No newline at end of file
diff --git a/manifest.json b/manifest.json
index 715ce32..fdb5525 100644
--- a/manifest.json
+++ b/manifest.json
@@ -30,14 +30,14 @@
"provider": "wx1319af22356934bf",
"export": "exportForXp2pPlugin.js"
},
- "wechat-p2p-player": {
- "version": "latest",
- "provider": "wx9e8fbc98ceac2628",
- "export": "exportForPlayerPlugin.js"
- },
"wmpf-voip": {
"version": "latest",
- "provider": "wxf830863afde621eb"
+ "provider": "wxf830863afde621eb",
+ "genericsImplementation": {
+ "call-page-plugin": {
+ "custombox": "pages/main/customBox"
+ }
+ }
}
}
},
diff --git a/pages.json b/pages.json
index b85c5ba..fbe944f 100644
--- a/pages.json
+++ b/pages.json
@@ -16,6 +16,7 @@
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "监控",
+ "disableScroll": true,
"mp-weixin": {
"usingComponents": {
"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",
@@ -560,6 +575,9 @@
{
"path": "pages/main/mine"
},
+ {
+ "path": "pages/main/customBox"
+ },
{
"path": "pages/main/notificationList",
"style": {
diff --git a/pages/addDevice/addLockGuid.vue b/pages/addDevice/addLockGuid.vue
index 1f0c932..b3accef 100644
--- a/pages/addDevice/addLockGuid.vue
+++ b/pages/addDevice/addLockGuid.vue
@@ -12,10 +12,10 @@
-
-
diff --git a/pages/addDevice/searchDevice.vue b/pages/addDevice/searchDevice.vue
index c1a7c66..abdb58f 100644
--- a/pages/addDevice/searchDevice.vue
+++ b/pages/addDevice/searchDevice.vue
@@ -139,7 +139,7 @@
}
this.routeJump({
type: 'redirectTo',
- name: 'selectAddress'
+ name: false ? 'selectAddress' : 'distributionNetwork'
})
} else {
uni.hideLoading()
diff --git a/pages/feature/recordList.vue b/pages/feature/recordList.vue
index 4ffef70..5bc9a95 100644
--- a/pages/feature/recordList.vue
+++ b/pages/feature/recordList.vue
@@ -384,36 +384,36 @@
diff --git a/pages/main/lockDetail.vue b/pages/main/lockDetail.vue
index b4de880..b2a3cee 100644
--- a/pages/main/lockDetail.vue
+++ b/pages/main/lockDetail.vue
@@ -221,6 +221,16 @@
>
消息提醒
+
+
+ 微信呼叫
+
diff --git a/pages/p2p/authorizeWechat.vue b/pages/p2p/authorizeWechat.vue
new file mode 100644
index 0000000..5c957bb
--- /dev/null
+++ b/pages/p2p/authorizeWechat.vue
@@ -0,0 +1,148 @@
+
+
+ 授权后,设备可呼叫该微信
+
+
+ 授权
+
+
+ 您已授权
+
+ 您已拒绝授权,请去设置中
+ 打开语音、视频通话提醒开关
+
+ 打开设置
+
+
+
+
+
+
+
+
diff --git a/pages/p2p/p2pPlayer.vue b/pages/p2p/p2pPlayer.vue
index 6afe085..0a07bbc 100644
--- a/pages/p2p/p2pPlayer.vue
+++ b/pages/p2p/p2pPlayer.vue
@@ -1,20 +1,50 @@
+
+
+
+
+
+
@@ -72,21 +103,39 @@
+
+
+
diff --git a/pages/p2p/utils.js b/pages/p2p/utils.js
deleted file mode 100644
index 6d7d0c3..0000000
--- a/pages/p2p/utils.js
+++ /dev/null
@@ -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
-}
diff --git a/pages/p2p/xp2pManager.js b/pages/p2p/xp2pManager.js
deleted file mode 100644
index 6eefc30..0000000
--- a/pages/p2p/xp2pManager.js
+++ /dev/null
@@ -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
-}
diff --git a/pages/setting/catEye.vue b/pages/setting/catEye.vue
index 66d25a5..780ef06 100644
--- a/pages/setting/catEye.vue
+++ b/pages/setting/catEye.vue
@@ -9,7 +9,7 @@
? catEyeMode[
$bluetooth.currentLockSetting.lockSettingInfo.catEyeConfig[0]?.catEyeMode
].name
- : ""
+ : ''
}}
diff --git a/stores/basic.js b/stores/basic.js
index f62d83e..f74cac8 100644
--- a/stores/basic.js
+++ b/stores/basic.js
@@ -391,6 +391,11 @@ const pages = [
name: 'p2pPlayer',
path: '/pages/p2p/p2pPlayer',
tabBar: false
+ },
+ {
+ name: 'authorizeWechat',
+ path: '/pages/p2p/authorizeWechat',
+ tabBar: false
}
]
diff --git a/stores/bluetooth.js b/stores/bluetooth.js
index 66c2baa..1302e11 100644
--- a/stores/bluetooth.js
+++ b/stores/bluetooth.js
@@ -56,7 +56,15 @@ const cmdIds = {
// 锁遥控列表
lockRemoteList: 0x3026,
// 锁设置列表
- lockSettingList: 0x302a
+ lockSettingList: 0x302a,
+ // 获取Wi-Fi列表
+ getWifiList: 0x30f6,
+ // Wi-Fi列表
+ wifiList: 0x30f7,
+ // 配网
+ distributionNetwork: 0x30f4,
+ // 配网结果
+ distributionNetworkResult: 0x30f5
}
// 子命令ID
@@ -396,6 +404,34 @@ export const useBluetoothStore = defineStore('ble', {
})
}
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:
that.updateCurrentLockInfo({
...that.currentLockInfo,
@@ -1558,6 +1594,123 @@ export const useBluetoothStore = defineStore('ble', {
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) {
const array = new Uint8Array(4)
@@ -2732,12 +2885,12 @@ export const useBluetoothStore = defineStore('ble', {
const md5Array = this.md5Encrypte(
uid + keyId,
this.currentLockInfo.token || new Uint8Array([0, 0, 0, 0]),
- this.currentLockInfo.bluetooth.publicKey
+ this.currentLockInfo.publicKey
)
contentArray.set(md5Array, 75)
- const cebArray = sm4.encrypt(contentArray, this.currentLockInfo.bluetooth.privateKey, {
+ const cebArray = sm4.encrypt(contentArray, this.currentLockInfo.commKey, {
mode: 'ecb',
output: 'array'
})
diff --git a/utils/request.js b/utils/request.js
index a1a0a1d..dabfeba 100644
--- a/utils/request.js
+++ b/utils/request.js
@@ -29,13 +29,13 @@ const request = config => {
const timestamp = new Date().getTime()
timer = setTimeout(() => {
resolve({ code: -1, message: '网络访问失败,请检查网络是否正常' })
- }, 7200)
+ }, 30200)
uni.request({
url: URL,
method,
header,
data,
- timeout: 7000,
+ timeout: 30000,
async success(res) {
const { statusCode, data } = res
if (timer) {