hyc 10 hónapja
szülő
commit
a357b9f885

+ 1 - 1
App.vue

@@ -5,9 +5,9 @@ import {provide} from "vue";
 export default {
   onLaunch: function () {
     const $machine = new Machine()
+    console.log('App Launch')
     provide('$machine', $machine);
 
-    // console.log('App Launch')
   },
   onShow: function () {
     // console.log('App Show')

+ 10 - 0
api/common.js

@@ -0,0 +1,10 @@
+import request from "@/utils/request";
+
+
+export function login(data) {
+  return request.post('equipment/common/login', data)
+}
+
+export function getInfo(data) {
+  return request.get('equipment/work/getInfo', data)
+}

+ 12 - 6
pages.json

@@ -8,12 +8,18 @@
   },
   "pages": [
     //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
-       {
-         "path": "pages/index/init",
-         "style": {
-           "navigationStyle": "custom"
-         }
-       },
+    {
+      "path": "pages/index/load",
+      "style": {
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/index/init",
+      "style": {
+        "navigationStyle": "custom"
+      }
+    },
     {
       "path": "pages/index/index",
       "style": {

+ 77 - 53
pages/classes/select.vue

@@ -1,26 +1,29 @@
 <template>
   <view class="container-box">
-    <image src="/static/image/bmi/manual_icon_arrow.png" alt="" class="back-class" @click="goBcak()"></image>
+    <image alt="" class="back-class" src="/static/image/bmi/manual_icon_arrow.png" @click="goBcak()"></image>
     <text class="countdown">倒计时{{ countdown }}s</text>
     <view class="select-box">
       <view class="select-tab">
-        <view v-for="(item, index) in tabs" :key="index" class="tab-item"
-          :class="item.type == activeTab ? `tab-active-item${index}` : `tab-item${index}`" @click="changeTab(item)">
-          <image class="tab-img" :src="item.type == activeTab ? item.actImg : item.img" alt=""></image>
+        <view v-for="(item, index) in tabs" :key="index" :class="item.type == activeTab ? `tab-active-item${index}` : `tab-item${index}`"
+              class="tab-item" @click="changeTab(item)">
+          <image :src="item.type == activeTab ? item.actImg : item.img" alt="" class="tab-img"></image>
           <text>{{ item.title }}</text>
         </view>
       </view>
-      <view class="select-info" v-if="activeTab == 'grade'">
-        <view v-for="(item, index) in totalList" class="info-item" @click="changeGrade(item)"
-          :class="item.active == true ? `info-active-item0` : `info-item0`">{{ item.name }}</view>
+      <view v-if="activeTab == 'grade'" class="select-info">
+        <view v-for="(item, index) in totalList" :class="item.active == true ? `info-active-item0` : `info-item0`" class="info-item"
+              @click="changeGrade(item)">{{ item.name }}
+        </view>
       </view>
-      <view class="select-info" v-else-if="activeTab == 'class'">
-        <view v-for="(item, index) in classList" class="info-item" @click="changeClass(item)"
-          :class="item.active == true ? `info-active-item1` : `info-item1`">{{ item.class_name }}</view>
+      <view v-else-if="activeTab == 'class'" class="select-info">
+        <view v-for="(item, index) in classList" :class="item.active == true ? `info-active-item1` : `info-item1`" class="info-item"
+              @click="changeClass(item)">{{ item.class_name }}
+        </view>
       </view>
-      <view class="select-info" v-else-if="activeTab == 'student'">
-        <view v-for="(item, index) in studentList" class="info-item" @click="changeStudent(item)"
-          :class="item.active == true ? `info-active-item2` : `info-item2`">{{ item.jname }}</view>
+      <view v-else-if="activeTab == 'student'" class="select-info">
+        <view v-for="(item, index) in studentList" :class="item.active == true ? `info-active-item2` : `info-item2`" class="info-item"
+              @click="changeStudent(item)">{{ item.jname }}
+        </view>
       </view>
     </view>
     <view class="selected-box">
@@ -37,44 +40,59 @@
 </template>
 
 <script setup>
-import { onActivated, onUnmounted, watch, ref, computed } from "vue";
-import { onLoad, onUnload, onHide } from '@dcloudio/uni-app';
-import { navTo, showToast } from "@/utils/app";
-import { getTaskClassList, getTaskStudentList } from "@/api/student";
+import {onActivated, onUnmounted, watch, ref, computed} from "vue";
+import {onLoad, onUnload, onHide} from '@dcloudio/uni-app';
+import {navTo, showToast} from "@/utils/app";
+import {getTaskClassList, getTaskStudentList} from "@/api/student";
 
 const title = ref('学生未激活')
 const select = ref(0)
 const selectMax = ref(1)
 const totalList = ref([])
 const activeTab = ref('grade')
-const countdown = ref(5)
+const countdown = ref(60)
 const interval = ref()
 const queryForm = ref({
   student_id: 0,
 })
 const tabs = ref([
-  { title: '选择年级', type: 'grade', img: '/static/image/bmi/manual_icon_grade.png', actImg: '/static/image/bmi/manual_icon_grade_selected.png' },
-  { title: '选择班级', type: 'class', img: '/static/image/bmi/manual_icon_class.png', actImg: '/static/image/bmi/manual_icon_class_selected.png' },
-  { title: '选择学生', type: 'student', img: '/static/image/bmi/manual_icon_student.png', actImg: '/static/image/bmi/manual_icon_student_selected.png' }
+  {
+    title: '选择年级',
+    type: 'grade',
+    img: '/static/image/bmi/manual_icon_grade.png',
+    actImg: '/static/image/bmi/manual_icon_grade_selected.png'
+  },
+  {
+    title: '选择班级',
+    type: 'class',
+    img: '/static/image/bmi/manual_icon_class.png',
+    actImg: '/static/image/bmi/manual_icon_class_selected.png'
+  },
+  {
+    title: '选择学生',
+    type: 'student',
+    img: '/static/image/bmi/manual_icon_student.png',
+    actImg: '/static/image/bmi/manual_icon_student_selected.png'
+  }
 ])
 const selectedArr = ref([
-  { name: '三年级', id: 1 },
-  { name: '1班', id: 2 },
-  { name: '11', id: 3 },
+  {name: '三年级', id: 1},
+  {name: '1班', id: 2},
+  {name: '11', id: 3},
 ])
 
-const setCountdown = ()=>{
-  interval.value = setInterval(()=>{
-    countdown.value -=1
-  } , 1000);
-  if(countdown.value == 0){
+const setCountdown = () => {
+  interval.value = setInterval(() => {
+    countdown.value -= 1
+  }, 1000);
+  if (countdown.value == 0) {
     clearInterval(interval)
     goBcak()
   }
 }
 
-watch(countdown, (newVal, oldVal)=>{
-  if(newVal <= 0){
+watch(countdown, (newVal, oldVal) => {
+  if (newVal <= 0) {
     clearInterval(interval.value)
     goBcak()
   }
@@ -102,7 +120,7 @@ const curSelected = computed(() => {
     let activeClass = classList.value.find(item => item.active == true)
     if (activeClass) {
       arr.push(activeClass)
-      if(studentList.value && studentList.value.length > 0){
+      if (studentList.value && studentList.value.length > 0) {
         let activeStudent = studentList.value.find(item => item.active == true)
         if (activeStudent) arr.push(activeStudent)
       }
@@ -114,7 +132,7 @@ const curSelected = computed(() => {
 const getGradeList = async () => {
   const res = await getTaskClassList()
   const list = []
-  if(res.code == 1){
+  if (res.code == 1) {
     res.data.grades.forEach(el => {
       if (!list.some(e => e.id == el.id)) {
         list.push(el);
@@ -124,8 +142,8 @@ const getGradeList = async () => {
   totalList.value = list
 
   const classList = []
-  for(let item of res.data.list){
-    for(let task of item.task){
+  for (let item of res.data.list) {
+    for (let task of item.task) {
       classList.push({
         ...item,
         ...task,
@@ -134,15 +152,15 @@ const getGradeList = async () => {
     }
   }
 
-  for(let gradeItem of totalList.value){
+  for (let gradeItem of totalList.value) {
 
     let arr = []
-    for(let classItem of classList){
-      if(gradeItem.id == classItem.grade){
+    for (let classItem of classList) {
+      if (gradeItem.id == classItem.grade) {
         arr.push(classItem)
       }
     }
-    if(arr.length > 0)gradeItem.class = arr
+    if (arr.length > 0) gradeItem.class = arr
   }
 }
 
@@ -150,15 +168,15 @@ const getStudent = async (item) => {
   const res = await getTaskStudentList({
     task_id: item.task_id
   })
-  if(res.code == 1){
-    let list = res.data.list.map(i=>{
-      return {...i,name: i.jname}
+  if (res.code == 1) {
+    let list = res.data.list.map(i => {
+      return {...i, name: i.jname}
     })
     totalList.value.find(item => item.active == true).class
-    .find(item => item.active == true).student = list
+      .find(item => item.active == true).student = list
   }
 
-  
+
 }
 
 const changeTab = (item) => {
@@ -167,17 +185,23 @@ const changeTab = (item) => {
 
 const changeGrade = (item) => {
   activeTab.value = 'class'
-  for (let i of totalList.value) { i.active = false }
+  for (let i of totalList.value) {
+    i.active = false
+  }
   item.active = true
   let classList = totalList.value.find(i => i.active == true).class
-  for (let i of classList) { i.active = false }
+  for (let i of classList) {
+    i.active = false
+  }
   // getClassList()
 }
 
 const changeClass = (item) => {
   activeTab.value = 'student'
   let classList = totalList.value.find(i => i.active == true).class
-  for (let i of classList) { i.active = false }
+  for (let i of classList) {
+    i.active = false
+  }
   item.active = true
   getStudent(item)
 }
@@ -185,14 +209,14 @@ const changeClass = (item) => {
 const changeStudent = (item) => {
   let classList = totalList.value.find(i => i.active == true).class
   let studentList = classList.find(i => i.active == true).student
-  for (let i of studentList) { i.active = false }
+  for (let i of studentList) {
+    i.active = false
+  }
   item.active = true
 }
 
 const goBcak = () => {
-  navTo('pages/index/index', {
-
-  })
+  navTo('pages/index/index', {})
 }
 
 const navToTest = () => {
@@ -210,10 +234,10 @@ onLoad(() => {
   setCountdown()
 })
 
-onHide(()=>{
+onHide(() => {
   clearInterval(interval.value)
 })
-onUnload(()=>{
+onUnload(() => {
   clearInterval(interval.value)
 })
 </script>

+ 18 - 10
pages/index/index.vue

@@ -22,7 +22,7 @@
       <!--      <view class="btn btn-primary" @click="next">下一页</view>-->
       <view class="img-saoma-box">
         <text class="img-saoma-text">请将卡片放进感应区</text>
-        <image src="@/static/image/bmi/img_saoma.png" alt="" class="img-saoma"></image>
+        <image alt="" class="img-saoma" src="@/static/image/bmi/img_saoma.png"></image>
       </view>
       <view class="btn btn-primary hand-select" @click="toSelect">手动选择</view>
     </view>
@@ -97,16 +97,21 @@ const scanWatch = (value) => {
 }
 
 const setWatch = (open = false) => {
-  if (open) {
-    $machine.scan().setWatch(scanWatch)
-  } else {
-    $machine.scan().setWatch(null)
-  }
+  // if (open) {
+  //   $machine.scan().setWatch(scanWatch)
+  // } else {
+  //   $machine.scan().setWatch(null)
+  // }
 }
 
 
 // 挂载完成之后
 onMounted(async (r) => {
+  // const machine = $machine[`machine0${}`]
+  setTimeout(() => {
+    // $machine.machine03().getList()
+
+  }, 5000)
 })
 
 onShow(async () => {
@@ -155,11 +160,12 @@ onActivated(async () => {
   }
 }
 
-.img-saoma-box{
+.img-saoma-box {
   display: flex;
   flex-direction: column;
 }
-.img-saoma-text{
+
+.img-saoma-text {
   text-align: center;
   font-weight: bold;
   font-size: 35upx;
@@ -167,11 +173,13 @@ onActivated(async () => {
   line-height: 41upx;
   margin-bottom: 40upx;
 }
-.img-saoma{
+
+.img-saoma {
   width: 520upx;
   height: 400upx;
 }
-.hand-select{
+
+.hand-select {
   width: 480upx;
   border-radius: 21upx;
 }

+ 66 - 0
pages/index/load.vue

@@ -0,0 +1,66 @@
+<template>
+  <view class="window-box">
+    <view class="dis-flex flex-dir-column flex-x-center flex-y-center">
+      <view class="logo">
+        <image class="logo-image" src="/static/logo.png"/>
+      </view>
+      <view class="m-t-20 f-w-b p-b-50">{{ pD.name }}</view>
+    </view>
+  </view>
+</template>
+
+<script setup>
+import {getCurrentInstance, inject, onActivated, onBeforeUnmount, onMounted, reactive, ref} from "vue";
+import {onShow, onHide} from "@dcloudio/uni-app";
+import {checkLogin, redirectTo} from "@/utils/app";
+
+const pD = reactive({
+  name: '体训助手',
+})
+
+// 挂载完成之后
+onMounted(async (r) => {
+  setTimeout(() => {
+    let a = checkLogin(true)
+    if (!a) {
+      redirectTo('pages/index/init')
+    } else {
+      redirectTo('pages/index/index')
+    }
+  }, 2000)
+})
+// 激活页面时
+onActivated(async () => {
+})
+</script>
+
+<style lang="scss" scoped>
+.window-box {
+  background-color: #006bff;
+  background-size: 100% auto;
+  background-repeat: no-repeat;
+  width: 100vw;
+  height: 100vh;
+  color: #fff;
+  font-size: 43upx;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+
+  .logo {
+    width: 140upx;
+    height: 140upx;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    background: #cccccc50;
+    border-radius: 50%;
+
+    &-image {
+      width: 90%;
+      height: 90%;
+      border-radius: 50%;
+    }
+  }
+}
+</style>

+ 3 - 3
plugins/ly-back.vue

@@ -85,12 +85,12 @@ const toSetting = () => {
 
 // 挂载完成之后
 onMounted(async (r) => {
-  machineFun.setUsbNotify(true)
-  machineFun.getOnlineUsb($machine)
+  // machineFun.setUsbNotify(true)
+  // machineFun.getOnlineUsb($machine)
 })
 // 页面卸载前
 onBeforeUnmount(() => {
-  machineFun.setUsbNotify(false)
+  // machineFun.setUsbNotify(false)
 })
 </script>
 

BIN
static/logo.png


+ 7 - 95
store/useConfigStore.js

@@ -1,105 +1,17 @@
 import {defineStore} from "pinia";
-import storage from "@/utils/storage";
-import platform from "@/utils/platform";
-import {getSystemDeviceInfo} from "@/utils/getSystemDeviceInfo";
-import {FileStorage} from "@/utils/fileStorage";
-import {confirmModal, showToast} from "@/utils/app";
-import * as dayjs from "@/utils/dayjs"
-import {logs} from "@/utils/util";
-import {calcStrHash} from "@/utils/machine/function";
-
-const configUrl = '/storage/emulated/0/.TXZNMac.txt'
-const fileStorage = new FileStorage()
 
 export const useConfigStore = defineStore('config', {
   state: () => ({
-    mac: null,
-    mType: 7, // 7 BMI(默认);8 肺活量;9 视力;
-    mName: '',
-    platform,
+    all: {},
+    mac: [],
+    mType: 3, // 3 BMI(默认);4 肺活量;5 坐位体前屈;
   }),
   getters: {},
   actions: {
-    _init() {
-      // this.platform = ()
-      this.getMachineType()
-      this.mType = 7
-    },
-    setMachineType(item) {
-      storage.setKey('machineType', {
-        name: item.name,
-        type: item.type,
-      })
-    },
-    getMachineType() {
-      let info = storage.getKey('machineType')
-      console.log('getMachineType', info)
-      if (info) {
-        this.mType = info.type
-        this.mName = info.name
-      }
+    clear() {
+      this.all = {}
+      this.mac = []
+      this.mType = -1
     },
-
-    async getMac() {
-      return new Promise(async (resolve, reject) => {
-        let config = await this.getConfig()
-        console.log('config', config)
-        let mac = config.mac ?? await this.createMac()
-        console.log('config2', mac)
-        if (mac) {
-          resolve(mac)
-        } else {
-          reject(false)
-        }
-      })
-    },
-
-    async createMac() {
-      let {imei} = await getSystemDeviceInfo()
-      try {
-        if (!imei) {
-          // #ifdef APP-PLUS
-          await confirmModal('无法获取设备imei,请联系管理员!', {
-            showCancel: false,
-          })
-          plus.runtime.quit()
-          // #endif
-          // #ifdef H5
-          showToast('无法获取设备imei,请联系管理员!')
-          return false
-          // #endif
-        }
-      } catch (e) {
-        console.error('createMac 获取设备码失败')
-        return false
-      }
-      let timestamp = dayjs().valueOf()
-      let data = await this.getConfig()
-      let a = calcStrHash(imei, 5)
-      let b = calcStrHash(timestamp, 4)
-      data.mac = `BMI${a}${b}`
-      data.timestamp = timestamp
-      data.imei = imei
-      await this.getConfig(data)
-      this.mac = data.mac
-      return data.mac
-    },
-
-
-    async getConfig(data = false) {
-      if (data) {
-        fileStorage.storage(configUrl, (data || {}))
-        return data
-      }
-      data = {}
-      try {
-        let info = await fileStorage.read(configUrl)
-        if (info) data = info
-      } catch (e) {
-        fileStorage.storage(configUrl, {})
-      }
-      return data
-    },
-
   }
 })

+ 26 - 13
store/useUserStore.js

@@ -1,19 +1,35 @@
 import {defineStore} from "pinia";
 import storage from "@/utils/storage";
 import {useConfigStore} from "@/store/useConfigStore";
-import {login} from "@/api/student";
-import { showToast } from "@/utils/app";
+import {getInfo, login} from "@/api/common";
+import {showToast} from "@/utils/app";
 
 export const useUserStore = defineStore({
   id: 'user',
   state: () => ({
     token: null,
-    userInfo: {}
+    userInfo: {},
+    userName: '',
   }),
   getters: {},
   actions: {
-    _init() {
-      this.checkLogin()
+    async _init() {
+      try {
+        this.checkLogin()
+        if (this.token) {
+          const {list} = await getInfo()
+          this.userInfo = list
+          this.userName = list.mac
+
+          const configStore = useConfigStore()
+          configStore.mType = list.type
+          configStore.all = list.config
+        } else {
+
+        }
+      } catch (e) {
+
+      }
     },
     checkLogin() {
       let token = storage.getKey('LOGIN_TEACHER_TOKEN')
@@ -22,18 +38,15 @@ export const useUserStore = defineStore({
       }
     },
     async login(loginForm) {
-      const configStore = useConfigStore()
-      // let mac = configStore.getMac()
       return new Promise(async (resolve, reject) => {
         const res = await login({
           username: loginForm.mac,
           password: loginForm.pwd,
         })
-        if(res.code == 1 && res.data.token){
+        if (res.code == 1 && res.data.token) {
           this.setToken(res.data)
           resolve(res.data)
-        }
-        else{
+        } else {
           showToast(res.msg)
           reject(res.msg)
         }
@@ -42,14 +55,14 @@ export const useUserStore = defineStore({
     logout() {
       this.token = null
       this.userInfo = {}
+      const configStore = useConfigStore()
+      configStore.clear()
       storage.remove("LOGIN_TEACHER_TOKEN")
-      storage.remove("userInfo")
     },
-    setToken(data){
+    setToken(data) {
       this.token = data.token
       this.userInfo = data.info
       storage.setKey('LOGIN_TEACHER_TOKEN', data.token)
-      storage.setKey('userInfo', data.info)
     }
     // getMachineInfo() {
     //   this.mac = '123'

+ 2 - 2
utils/app.js

@@ -199,7 +199,7 @@ export const checkLogin = (isLogin = false, is_confirm = false) => {
         success: res => {
           if (res.confirm) {
             uni.navigateTo({
-              url: "/pages/auth/index"
+              url: "/pages/index/init"
             })
           }
           if (res.cancel && getCurrentPages().length > 1) {
@@ -208,7 +208,7 @@ export const checkLogin = (isLogin = false, is_confirm = false) => {
         }
       })
     } else {
-      redirectTo('/pages/auth/index')
+      redirectTo('/pages/index/init')
     }
   } else {
     // 无需登录

+ 40 - 14
utils/ble/error.js

@@ -1,31 +1,57 @@
 export default function (err) {
   if (err && err.errCode) {
+    let code = err.errCode
+
+    if (err.errCode == -1 && err.errno) code = err.errno
     // 微信BLE蓝牙错误码
-    switch (err.errCode) {
+    switch (code) {
+      case 10000:
+        let msg = ''
+        // #ifdef MP
+        msg = code + ":蓝牙未初始化,请右上角重新进入小程序"
+        // #endif
+
+        // #ifdef APP-PLUS
+        msg = code + ":蓝牙未初始化,请重启程序"
+        // #endif
+
+        return msg
       case 10001:
-        return err.errCode + ":当前蓝牙适配器不可用"
+        return code + ":当前蓝牙适配器不可用"
       case 10002:
-        return err.errCode + ":没有找到指定设备"
+        return code + ":没有找到指定设备"
       case 10003:
-        return err.errCode + ":连接失败,请重试"
+        return code + ":连接失败,请重试"
       case 10004:
-        return err.errCode + ":没有找到指定服务"
+        return code + ":没有找到指定服务"
       case 10005:
-        return err.errCode + ":没有找到指定特征值"
+        return code + ":没有找到指定特征值"
       case 10006:
-        return err.errCode + ":当前连接已断开"
+        return code + ":当前连接已断开"
       case 10007:
-        return err.errCode + ":当前特征值不支持此操作"
+        return code + ":当前特征值不支持此操作"
       case 10008:
-        return err.errCode + ":其余所有系统上报的异常"
+        return code + ":其余所有系统上报的异常"
       case 10009:
-        return err.errCode + ":Android 系统特有,系统版本低于 4.3 不支持 BLE"
+        return code + ":Android 系统特有,系统版本低于 4.3 不支持 BLE"
       case 10012:
-        return err.errCode + ":连接超时,请重试"
+        return code + ":连接超时,请重试"
       case 10013:
-        return err.errCode + ":连接 deviceId 为空或者是格式不正确"
+        return code + ":连接 deviceId 为空或者是格式不正确"
+      case 1509001:
+        return code + ":连接BLE设备失败"
+      case 1509003:
+        return code + ":未连接上该BLE设备"
+      case 1509005:
+        return code + ":蓝牙连接超时"
+      case 1509008:
+        return code + ":系统微信定位功能未授权"
+      case 1500103:
+        return code + ":当前BLE设备获取不到Service/获取不到对应UUID的Service"
+      case 1500105:
+        return code + ":系统不支持蓝牙功能"
       default:
-        return `蓝牙功能暂不支持${err.errCode}`
+        return `${err.errCode} - ${err.errno}${JSON.stringify(err)}`
     }
   } else {
     // 自定义错误码
@@ -37,7 +63,7 @@ export default function (err) {
           break;
       }
     } else {
-      return `蓝牙功能暂不支持${err.errCode}`
+      return `${err.errCode} - ${err.errno}${JSON.stringify(err)}`
     }
   }
 

+ 21 - 17
utils/ble/hex.js

@@ -1,15 +1,15 @@
 // ArrayBuffer转16进度字符串示例
 import {formatZero, isObject, sliceChunk} from "@/utils/util";
-import * as ASCIIUtils from "@/uni_modules/wrs-js-modbusCRCHex/js_sdk/wrs-ASCIIUtils";
+import * as ASCIIUtils from "@/utils/common/wrs-ASCIIUtils";
 
 export const ab2hex = (buffer, join = '') => {
   const hexArr = Array.prototype.map.call(
     new Uint8Array(buffer),
     function (bit) {
-      return ('00' + bit.toString(16)).slice(-2).toUpperCase()
+      return ('00' + bit.toString(16)).slice(-2)
     }
   )
-  return hexArr.join(join)
+  return hexArr.join(join).toUpperCase()
 }
 
 
@@ -22,12 +22,20 @@ export const orderToStr = (head, payload = []) => {
 /**
  * 获取命令码
  * @param str
- * @param sNum
- * @param eNum
+ * @param format
  * @returns {*}
  */
-export const getOrderCode = (str, sNum = 2, eNum = 4) => {
-  return str.slice(2, 4)
+export const orderSplit = (str, format = []) => {
+  let result = {}
+  for (let i = 0; i < format.length; i++) {
+    let item = format[i]
+    if ('e' in item) {
+      result[item.k] = str.slice(item.s, item.e);
+    } else {
+      result[item.k] = str.slice(item.s);
+    }
+  }
+  return result
 }
 
 
@@ -39,6 +47,7 @@ export const getOrderCode = (str, sNum = 2, eNum = 4) => {
  */
 export const stringToSplit = (str, endNum) => {
   let data = [];
+  let header = str.slice(2)
   let hex = ''
   hex = str.slice(-4) // 校验码
   if (endNum) str = str.slice(0, -endNum)
@@ -48,7 +57,7 @@ export const stringToSplit = (str, endNum) => {
     data.push(item)
     num += 2
   }
-  return {data, hex}
+  return {header, data, hex}
 }
 
 
@@ -60,7 +69,7 @@ export const stringToArrayBuffer = (str, type = 1) => {
   let result = null
   switch (type) {
     case 2:
-      result = new ArrayBuffer(str.length * 2);
+      result = new ArrayBuffer(str.length);
       const view = new Uint8Array(result);
       for (let i = 0; i < str.length; i++) {
         view[i] = str.charCodeAt(i);
@@ -93,7 +102,6 @@ export const stringToArrayBuffer = (str, type = 1) => {
  * @param arr(array)        按指定长度切割 转换为2进制[ type: 2 转为2进制;   long:长度 , places:补0长度  ]
  * @param arr(array)        字串从指定位数开始按指定长度分割成数组,不转换进制[ type: 3 按指定长分割   long:长度  ]
  * @param arr(array)        字串从指定位数开始按指定长度分割成数组,不转换进制[ type: 4 ASCii转10进   long:长度  ]
- * @param mode
  * @returns {*[]}
  */
 export const orderToData = (str, arr, mode = 1) => {
@@ -163,11 +171,10 @@ export const orderToData = (str, arr, mode = 1) => {
  * @returns {string}
  */
 export const dataToHexHandle = (str, len = 2) => {
-  str = formatZero(str.toString(16), len)
+  str = formatZero(parseInt(str).toString(16), len)
   let result = [];
-  for (let i = 0; i < str.length;) {
+  for (let i = 0; i < str.length; i += 2) {
     result.push(str.slice(i, i + 2))
-    i += 2
   }
   return result.reverse().join('')
 }
@@ -176,17 +183,14 @@ export const dataToHexHandle = (str, len = 2) => {
 /**
  * 16进(低位)转成10进数据
  * @param str
- * @param type
- * @param def
  * @returns {string}
  */
 export const hexToDataHandle = (str, type = 1, def = '') => {
   let result = [];
   let strLength = str.length
   if (strLength > 2) {
-    for (let i = 0; i < strLength;) {
+    for (let i = 0; i < strLength; i += 2) {
       result.push(str.slice(i, i + 2))
-      i += 2
     }
   } else {
     result.push(str)

+ 136 - 27
utils/ble/index.js

@@ -2,9 +2,8 @@ import * as tools from "./tools"
 import {inArray, isObject, logs, sleep} from "../util";
 import {showToast} from "../app";
 import {checkBleAuth} from "../uniFunction";
-import {ab2hex, stringToArrayBuffer} from "./hex";
+import {ab2hex, orderSplit, stringToArrayBuffer} from "./hex";
 import {isH5} from "@/utils/platform";
-import Vue from "vue";
 
 /**
  * 蓝牙工具类
@@ -21,6 +20,10 @@ export class bleBase {
     this.serviceId = null
     this.writeId = null // 写入id
     this.characteristicId = null// 接收id
+    this.conSevInterval = 2000
+
+    this.sList = []
+    this.OSList = []
   }
 
   /**
@@ -34,26 +37,37 @@ export class bleBase {
     let option = {
       second: 5000,
       type: 1,
+      start: null,
       fun: null,
+      fail: null,
     }
     option = Object.assign(option, op)
     return new Promise(async (resolve, reject) => {
       logs('进入 searchBle')
       try {
         await this.topClass.init()
-        if (isH5) throw 'H5不支持蓝牙功能'
+        console.error('getList init')
         await checkBleAuth() // 检查用户蓝牙授权是否通过
+        if (isH5) throw 'H5不支持蓝牙功能'
         if (showLoad) uni.showLoading({title: '搜索设备中。。。'})
         await tools._startSearch(Object.assign({
-          allowDuplicatesKey: true
+          allowDuplicatesKey: true,
+          // services: [],
+          // powerLevel: 'high',
         }, data))
+        if (option.type == 3 && option.start) option.start()
         let list = await this.bluetoothDeviceFound(option.second, option.type, option.fun)
         if (showLoad) uni.hideLoading()
         resolve(Object.values(list))
       } catch (msg) {
+        console.error('getList err', msg)
         if (showLoad) uni.hideLoading()
         showToast(msg, 4000)
-        resolve(new Object())
+        if (option.type == 3 && option.fail) {
+          option.fail(msg)
+        } else {
+          reject()
+        }
       }
     })
   }
@@ -71,8 +85,17 @@ export class bleBase {
     } else {
       item.ok = true
     }
-    if (item.ok && this.option.macSlice) item.mac = item.manufacturerData.slice(...this.option.macSlice)
-    if (this.option.search && !inArray(item.mac, this.option.machine)) item.ok = !1
+    if (item.ok) {
+      if (this.option.macSlice) item.mac = item.manufacturerData.slice(...this.option.macSlice)
+      if (this.option.order) {
+        let res = orderSplit(item.manufacturerData, this.option.order)
+        for (const resKey in res) {
+          item[resKey] = res[resKey]
+        }
+      }
+      if (this.option.judge) item.ok = this.option.judge(item)
+    }
+    if (this.option.search && !inArray(item.mac, this.option.machine)) item.ok = false
     return item
   }
 
@@ -88,14 +111,22 @@ export class bleBase {
   bluetoothDeviceFound(second = 5000, type = 1, fun = null) {
     let list = {}
     return new Promise(async (resolve, reject) => {
+      console.log('bleDeviceFound run')
       try {
         this.topClass.bleDeviceFound((res) => {
           res.devices.forEach((item) => {
             item.manufacturerData = ab2hex(item.advertisData)
+            // console.log('res.devices.forEach', item)
+            if (item.localName != '') {
+              // console.log(`bleDeviceFound forEach localName:${item.localName} deviceId:${item.deviceId} manufacturerData:${item.manufacturerData} advertisData:${item.advertisData}`)
+              // console.log('res.devices.forEach', item)
+            }
             item = this.filter(item)
+            // console.log('res.devices.forEach after', item)
             if (item.ok) {
               list[item.deviceId] = item
               if (type == 2) {
+                // console.log('type2 stop')
                 tools._stopSearchBluetooth();
                 throw '已找到设备'
               } else if (type == 3 && fun) {
@@ -109,11 +140,13 @@ export class bleBase {
         })
         if (second > 0) {
           await sleep(second)
+          // console.log('sleep stop')
           throw '搜索结束'
         }
       } catch (error) {
+        // console.log('catch stop')
+        await tools._stopSearchBluetooth();
         if (type != 3) {
-          await tools._stopSearchBluetooth();
         } else if (type == 3 && fun) {
           fun({
             run: false,
@@ -133,6 +166,7 @@ export class bleBase {
 
   stopSearch() {
     /* #ifndef H5 */
+    // console.log('stopSearch stop')
     tools._stopSearchBluetooth();
     /* #endif */
   }
@@ -152,36 +186,92 @@ export class bleBase {
         await this.closeConnection() // 结束前一台
         await sleep(500)
       }
+      await checkBleAuth() // 检查用户蓝牙授权是否通过
       this.topClass.addConnect(deviceId, this.typeKey)
       this.deviceId = deviceId
       logs('connectBle --- ' + this.deviceId)
       await tools._connectBlue(this.deviceId)
-      await sleep(2000);
-      await this.getBLEServices(this.option.serviceKey)
-      await this.getCharacteristics(this.option.channelKey)
+      // await sleep(this.conSevInterval);
+      this.serviceId = await this.getBLEServices(this.option.serviceKey)
+      await sleep(500)
+      const main = await this.getCharacteristics(this.option.channelKey)
+      this.writeId = main.writeId // 写入id
+      this.characteristicId = main.characteristicId // 写入id
       await tools._notifyBLECharacteristicValueChange(this.deviceId, this.serviceId, this.characteristicId)
       return Promise.resolve()
     } catch (e) {
       await this.closeConnection()
-      console.log('connectionBle catch', e)
+      console.error('connectionBle catch', e)
       return Promise.reject('连接失败')
     }
   }
 
-  async getBLEServices(serviceKey) {
-    logs('开始蓝牙获取服务')
+  async getBLEServices_old(serviceKey) {
+    if (!this.deviceId) console.error('获取服务错误,没有deviceId')
     let servicesList = await tools._getBLEServices(this.deviceId)
+
     if (!servicesList) throw '链接失败,蓝牙未找到服务号'
     logs('开始蓝牙获取服务', servicesList)
+    this.sList = servicesList.services
+    let uuid = null
     for (let i = 0; i < servicesList.services.length; i++) {
-      if (servicesList.services[i].isPrimary && (servicesList.services[i].uuid.indexOf(serviceKey) != -1)) {
-        this.serviceId = servicesList.services[i].uuid
-        return;
+      if (servicesList.services[i].uuid.indexOf(serviceKey) != -1) {
+        // this.serviceId = servicesList.services[i].uuid
+        uuid = servicesList.services[i].uuid
+        return uuid;
       }
     }
+    return uuid;
   }
 
-  async getCharacteristics(channelKey = '') {
+  async getBLEServices(serviceKey) {
+    if (!this.deviceId) console.error('获取服务错误,没有deviceId');
+
+    const timeout = new Promise((_, reject) => {
+      setTimeout(() => {
+        reject(new Error('超时,未能在5秒内获取到服务'));
+      }, 5000);
+    });
+
+    const getService = async () => {
+      let uuid = null;
+      for (let i = 0; i < 5; i++) {
+        try {
+          const servicesList = await tools._getBLEServices(this.deviceId);
+          if (servicesList) {
+            logs('getService', servicesList);
+            this.sList = servicesList.services;
+            for (let j = 0; j < servicesList.services.length; j++) {
+              if (servicesList.services[j].uuid.indexOf(serviceKey) !== -1) {
+                uuid = servicesList.services[j].uuid;
+                break; // 找到匹配的 uuid 后退出内层循环
+              }
+            }
+            if (uuid) break; // 找到匹配的 uuid 后退出外层循环
+          }
+        } catch (error) {
+          // 如果获取失败,继续下一次尝试
+          console.error('获取服务失败,重试中...');
+        }
+        await new Promise(resolve => setTimeout(resolve, 1000)); // 等待1秒后重试
+      }
+      if (uuid) {
+        return uuid;
+      } else {
+        throw new Error('未能在5秒内获取到服务');
+      }
+    };
+
+    try {
+      const uuid = await Promise.race([getService(), timeout]);
+      return uuid;
+    } catch (error) {
+      throw error;
+    }
+  }
+
+
+  async getCharacteristics(channelKey = '', obj = {}) {
     logs('开始蓝牙通道信息')
     // 获取通道信息(读、写、监听)
     let writeKey = ''
@@ -192,19 +282,28 @@ export class bleBase {
     } else {
       writeKey = notifyKey = channelKey
     }
-    let {characteristics} = await tools._getCharacteristics(this.deviceId, this.serviceId)
+    let op = {
+      deviceId: this.deviceId,
+      serviceId: this.serviceId,
+      ...obj
+    }
+    let {characteristics} = await tools._getCharacteristics(op.deviceId, op.serviceId)
     logs(`开始蓝牙通道信息 writeKey:${writeKey} notifyKey:${notifyKey} characteristics:${characteristics}`)
-
+    let d = {
+      writeId: null,
+      characteristicId: null,
+    }
     for (let i = 0; i < characteristics.length; i++) {
       let item = characteristics[i];
       if (item.uuid.search(writeKey) != -1) {
-        this.writeId = item.uuid // 写入id
+        d.writeId = item.uuid // 写入id
       }
       if (item.uuid.search(notifyKey) != -1) {
-        this.characteristicId = item.uuid // 写入id
+        d.characteristicId = item.uuid // 写入id
       }
     }
-    logs(`开始蓝牙通道信息 writeId:${this.writeId} characteristicId:${this.characteristicId}`)
+    logs(`开始蓝牙通道信息 writeId:${d.writeId} characteristicId:${d.characteristicId}`)
+    return d
   }
 
 
@@ -213,8 +312,8 @@ export class bleBase {
    * @param deviceId
    * @returns {Promise<void>}
    */
-  async closeConnection(deviceId = '') {
-    if (!deviceId) deviceId = this.deviceId
+  async closeConnection(deviceId = null) {
+    if (deviceId == null) deviceId = this.deviceId
     // 断开已连接的连接
     try {
       if (this.deviceId) await tools._closeBLEConnection(deviceId);
@@ -224,22 +323,32 @@ export class bleBase {
     this.serviceId = null
     this.writeId = null
     this.characteristicId = null
+    this.sList = []
+    this.OSList = []
     this.topClass.delConnect(deviceId)
   }
 
 
-  async sentOrder(str, type = 1) {
+  async sentOrder(str, type = 1, obj = {}) {
     let buffer = type != 0 ? stringToArrayBuffer(str, type) : str
     logs("-- 发送数据: ", ab2hex(buffer, ' '))
+    let op = {
+      deviceId: this.deviceId,
+      serviceId: this.serviceId,
+      writeId: this.writeId,
+      ...obj
+    }
     try {
       /* #ifndef H5 */
-      if (this.deviceId) await tools._writeBLECharacteristicValue(this.deviceId, this.serviceId, this.writeId, buffer)
+      if (this.deviceId) await tools._writeBLECharacteristicValue(op.deviceId, op.serviceId, op.writeId, buffer)
       /* #endif */
+      if (op.suc) op.suc()
       return true
     } catch (error) {
       if (error.errCode == 10006) {
         this.topClass.delConnect(this.deviceId, this.typeKey)
       }
+      if (op.err) op.err()
       console.error(error)
       logs(`发送出错 基本信息 deviceId:${this.deviceId}, serviceId:${this.serviceId}, writeId:${this.writeId}`)
       logs(error)

+ 30 - 90
utils/ble/tools.js

@@ -1,8 +1,9 @@
 import errToString from "./error";
-import {logs, promisify} from '../util'
+import {logs} from '../util'
+import {promisify} from '../uniFunction'
 import {ab2hex} from "@/utils/ble/hex";
 
-function _onBluetoothAdapterStateChange(callback) {
+export const _onBluetoothAdapterStateChange = (callback) => {
   /* #ifndef H5 */
   uni.onBluetoothAdapterStateChange(res => {
     // 处理蓝牙开启与关闭问题
@@ -11,7 +12,7 @@ function _onBluetoothAdapterStateChange(callback) {
   /* #endif */
 }
 
-function _onBLEConnectionStateChange(callback) {
+export const _onBLEConnectionStateChange = (callback) => {
   /* #ifndef H5 */
   uni.onBLEConnectionStateChange(res => {
     // 该方法回调中可以用于处理连接意外断开等异常情况
@@ -20,7 +21,7 @@ function _onBLEConnectionStateChange(callback) {
   /* #endif */
 }
 
-function _onBLECharacteristicValueChange(callback) {
+export const _onBLECharacteristicValueChange = (callback) => {
   /* #ifndef H5 */
   uni.onBLECharacteristicValueChange(res => {
     res.str = ab2hex(res.value)
@@ -29,31 +30,27 @@ function _onBLECharacteristicValueChange(callback) {
   /* #endif */
 }
 
-function _openAdapter() {
+export const _openAdapter = () => {
   logs(`准备初始化蓝牙适配器...`);
-  return uni.openBluetoothAdapter().then(
-    (res) => {
-      logs(`✔ 适配器初始化成功!`);
-      return res;
-    },
-    (err) => {
-      throw `初始化失败!${errToString(err)}`
-    }
-  );
+  return promisify(uni.openBluetoothAdapter).then((res) => {
+    logs(`✔ 适配器初始化成功!`, res);
+    return res;
+  }, (err) => {
+    throw `初始化失败!${errToString(err)}`
+  })
 }
 
 /**
- * @param {Array<string>} services
- * @param { Int } interval
+ * @param data
  */
-function _startSearch(data = {}) {
+export const _startSearch = (data = {}) => {
   logs(`准备搜寻附近的蓝牙外围设备...`);
   /* #ifndef H5 */
   return promisify(uni.startBluetoothDevicesDiscovery, Object.assign({
     interval: 10
   }, data)).then(
     (res) => {
-      logs(`✔ 搜索成功!`);
+      logs(`✔ 搜索成功!`, res);
       return res
     },
     (err) => {
@@ -63,57 +60,12 @@ function _startSearch(data = {}) {
   /* #endif */
 }
 
-/**
- * 获取已发现的蓝牙设备
- * @returns {Promise<[null, undefined] | [(string|string), Object]>}
- * @private
- */
-function _getBluetoothDevices() {
-  return promisify(uni.getBluetoothDevices).then(
-    ({devices}) => {
-      logs(`✔ 获取已发现的蓝牙设备成功!`);
-      let list = devices.filter(function (obj) {
-        return obj.advertisData; //这里过滤自己想要的设备
-      })
-      logs('已发现的蓝牙设备列表');
-      return list
-    },
-    (err) => {
-      throw `获取已发现的蓝牙设备失败!${errToString(err)}`
-    }
-  );
-}
-
-/**
- * @param {Array} devices 查找到设备数组
- * @param {int} count 计数器-嗅探2次
- */
-function _onBluetoothFound(maxCount = 3) {
-  let devices = []
-  let count = 0
-  /* #ifdef H5 */
-  return Promise.resolve(devices)
-  /* #endif */
-  return new Promise((resolve, reject) => {
-    uni.onBluetoothDeviceFound(res => {
-      devices.push(...res.devices)
-      count++
-      if (count > maxCount) {
-        resolve(devices)
-      }
-      logs(`已嗅探蓝牙设备数:${devices.length}...`)
-    }, err => {
-      reject(err)
-    })
-  })
-}
-
 /**
  * 停止蓝牙搜索
  * @returns {PromiseLike<[null, any] | [(string|string), null]> | Promise<[null, any] | [(string|string), null]>}
  * @private
  */
-function _stopSearchBluetooth() {
+export const _stopSearchBluetooth = () => {
   logs(`停止查找新设备...`);
   /* #ifdef H5 */
   throw `停止查询失败!H5不能操作`
@@ -135,7 +87,7 @@ function _stopSearchBluetooth() {
  * @returns {Promise<[null, unknown] | [null, any] | [(string|string), null]>}
  * @private
  */
-function _connectBlue(deviceId) {
+export const _connectBlue = (deviceId) => {
   logs(`准备连接设备...`);
   /* #ifndef H5 */
   return promisify(uni.createBLEConnection, {
@@ -163,7 +115,7 @@ function _connectBlue(deviceId) {
  * @returns {Promise<[null, unknown] | [(string|string), null]>}
  * @private
  */
-function _closeBLEConnection(deviceId) {
+export const _closeBLEConnection = (deviceId) => {
   logs(`断开蓝牙连接...`)
   /* #ifndef H5 */
   return promisify(uni.closeBLEConnection, {
@@ -185,7 +137,7 @@ function _closeBLEConnection(deviceId) {
  * @returns {Promise<[null, unknown] | [(string|string), null]>}
  * @private
  */
-function _closeBLEAdapter() {
+export const _closeBLEAdapter = () => {
   logs(`释放蓝牙适配器...`)
   return promisify(uni.closeBluetoothAdapter).then(
     (res) => {
@@ -204,7 +156,7 @@ function _closeBLEAdapter() {
  * @returns {Promise<[null, unknown] | [(string|string), null]>}
  * @private
  */
-function _getBLEServices(deviceId) {
+export const _getBLEServices = (deviceId) => {
   logs(`获取蓝牙设备所有服务...`)
   return promisify(uni.getBLEDeviceServices, {
     deviceId
@@ -223,7 +175,14 @@ function _getBLEServices(deviceId) {
  * @returns {Promise<[null, unknown] | [(string|string), null]>}
  * @private
  */
-function _getCharacteristics(deviceId, serviceId) {
+export const _getCharacteristics = (deviceId, serviceId) => {
+  let msg = null
+  if (!deviceId) msg = `服务通道错误!deviceId为空`
+  if (!serviceId) msg = `服务通道错误!serviceId为空`
+  if (msg != null) {
+    console.error(`获取特征失败,${msg}`)
+    throw msg
+  }
   logs(`开始获取特征值...`);
   return promisify(uni.getBLEDeviceCharacteristics, {
     deviceId,
@@ -240,7 +199,7 @@ function _getCharacteristics(deviceId, serviceId) {
 }
 
 // 订阅特征值
-function _notifyBLECharacteristicValueChange(deviceId, serviceId, characteristicId) {
+export const _notifyBLECharacteristicValueChange = (deviceId, serviceId, characteristicId) => {
   return promisify(uni.notifyBLECharacteristicValueChange, {
     deviceId,
     serviceId,
@@ -254,8 +213,7 @@ function _notifyBLECharacteristicValueChange(deviceId, serviceId, characteristic
   })
 }
 
-
-function _writeBLECharacteristicValue(deviceId, serviceId, characteristicId, buffer) {
+export const _writeBLECharacteristicValue = (deviceId, serviceId, characteristicId, buffer) => {
   return promisify(uni.writeBLECharacteristicValue, {
     deviceId,
     serviceId,
@@ -270,21 +228,3 @@ function _writeBLECharacteristicValue(deviceId, serviceId, characteristicId, buf
     }
   })
 }
-
-export {
-  _onBLEConnectionStateChange,
-  _onBluetoothAdapterStateChange,
-  _openAdapter,
-  _getCharacteristics,
-  _connectBlue,
-  _getBLEServices,
-  _closeBLEConnection,
-  _closeBLEAdapter,
-  _stopSearchBluetooth,
-  _getBluetoothDevices,
-  _notifyBLECharacteristicValueChange,
-  _onBluetoothFound,
-  _startSearch,
-  _writeBLECharacteristicValue,
-  _onBLECharacteristicValueChange,
-};

+ 2 - 2
utils/bootstrap.js

@@ -17,8 +17,8 @@ export default function Initializer() {
   // store.commit('user/setLoginToken', storage.getKey('LOGIN_TEACHER_TOKEN'))
   // store.dispatch('user/getUserInfo')
   // store.dispatch('machine/getConfig')
-  const configStore = useConfigStore()
-  configStore._init()
+  // const configStore = useConfigStore()
+  // configStore._init()
   const userStore = useUserStore()
   userStore._init()
 }

+ 355 - 0
utils/common/readme.md

@@ -0,0 +1,355 @@
+# 十六进制/ArrayBuffer/ASCII/modbus/crc/高低位,常用于串口、蓝牙、socket、UDP等字节数据转换
+
+## 业务定制需求可加Q252797991
+
+## 您的好评就是插件更新的动力,麻烦亲动动手指给个好评!!!!
+
+## byte字节工具类
+
+```
+
+import * as ByteUtils from '@/uni_modules/wrs-js-modbusCRCHex/js_sdk/wrs-ByteUtils.js';
+
+```
+
+- 整型转字节
+
+```
+
+				let intValue = 500;
+				let byteValue = ByteUtils.intToByte(intValue);
+
+```
+
+- 字节转整型
+
+```
+
+				let byteValue = 100;
+				let intValue = ByteUtils.byteToInt(byteValue);
+
+```
+
+## hex十六进制工具类
+
+```
+
+import * as HexUtils from '@/uni_modules/wrs-js-modbusCRCHex/js_sdk/wrs-HexUtils.js';
+
+```
+
+- 十进制数组转十六进制字符串
+
+```
+
+				let intArray = [];
+				intArray.push(0x01);
+				intArray.push(355);
+				let hex = HexUtils.intArrayToHex(intArray);
+
+```
+
+- 字节数组转十六进制字符串
+
+```
+
+				let byteArray = [];
+				byteArray.push(0x01);
+				byteArray.push(35);
+				let hex = HexUtils.byteArrayToHex(byteArray);
+
+```
+
+- 十六进制字符串转整型数组
+
+```
+
+	let hex = "030610aabb"
+				let intArray = HexUtils.hexToIntArray(hex);
+
+```
+
+- 十六进制字符串转字节数组
+
+```
+
+				let hex = "ffbb02"
+				let byteArray = HexUtils.hexToByteArray(hex);
+
+```
+
+- 十六进制字符串转arrayBuffer
+
+```
+
+				let hex = "ffbb02"
+				let arrayBuffer = HexUtils.hexToArrayBuffer(hex);
+
+```
+
+- arrayBuffer转十六进制字符串
+
+```
+
+				let byteArrayBuffer = new Uint8Array([0x05, 0x02, 0xff]);
+				let arrayBuffer = byteArrayBuffer.buffer;
+				let hex = HexUtils.arrayBufferToHex(arrayBuffer);
+
+```
+
+- 十六进制字符串转Uint8Array
+
+```
+
+				let hex = "030610aabb"
+				let uint8Array = HexUtils.hexToUint8Array(hex);
+				let msg = "hexToUint8Array\n" + "hex:" + hex + "\nintArray:" + uint8Array;
+				this.showMsg(msg);
+
+```
+
+- Uint8Array转十六进制字符串
+
+```
+
+				var uint8 = new Uint8Array(4);
+				uint8[0] = 0x1f;
+				uint8[1] = 0x2f;
+				uint8[2] = 0x3f;
+				uint8[3] = 0x4f;
+				let hex = HexUtils.uint8ArrayToHex(uint8);
+				let msg = "uint8ArrayToHex:" + uint8 + " uint8ArrayToHex hex:" + hex;
+				this.showMsg(msg);
+
+```
+
+## CRC校验工具类
+
+```
+
+import * as CRCUtils from '@/uni_modules/wrs-js-modbusCRCHex/js_sdk/wrs-CRCUtils.js';
+
+```
+
+- 获取CRC16_MODBUS
+
+```
+
+				let hex = "05060A";
+				let data = HexUtils.hexToByteArray(hex);
+				var crc = CRCUtils.getCRC16_MODBUS(data);
+				// CRC十六进制
+				var crcHex = IntUtils.intToHex(crc)
+				var obj = CRCUtils.intToHighLow(crc);
+				// CRC低位
+				let low = obj.low;
+				// CRC高位
+				let high = obj.high
+
+```
+
+- 获取CRC16_CCITT_FALSE
+
+```
+
+			let hex = "05060A";	
+			let data = HexUtils.hexToByteArray(hex);
+			var crc = CRCUtils.getCRC16_CCITT_FALSE(data);
+			// CRC十六进制
+			var crcHex = IntUtils.intToHex(crc)
+			var obj = CRCUtils.intToHighLow(crc);
+			// CRC低位
+			let low = obj.low;
+			// CRC高位
+			let high = obj.high
+
+```
+
+- 获取CRC32
+
+```
+
+				let data = [0x05, 0x06, 0x0a];
+				let initialCrc = 0xFFFFFFFF;
+				let polynom = 0x04C11DB7;
+				let xor = 0xFFFFFFFF;
+				let refIn = true;
+				let refOut = true;
+				var crc = CRCUtils.getCRC32(data);
+				this.showMsg("CRC32:" + crc)
+
+
+```
+
+## modubs工具类
+
+```
+
+import * as ModbusUtils from '@/uni_modules/wrs-js-modbusCRCHex/js_sdk/wrs-ModbusUtils.js';
+
+```
+- 写指令
+
+```
+
+				// 设备地址
+				let address = 0x25;
+				// 寄存器起始地址
+				let start = 20;
+				// 寄存器个数
+				let count = 3;
+				let byteArray = ModbusUtils.getReadModbus(address, start, count);
+				let hex = HexUtils.byteArrayToHex(byteArray);
+				
+				// 如果CRC高位在前
+				let crcLowFront = false; // CRC是否低位在前
+				let byteArray1 = ModbusUtils.getReadModbusCRCLowFront(address, start, count, crcLowFront);
+				let hex1 = HexUtils.byteArrayToHex(byteArray1);
+
+```
+
+- 读指令
+
+```
+
+				// 设备地址
+				let address = 0x25;
+				// 寄存器起始地址
+				let start = 20;
+				// 数据
+				let data = [];
+				data.push(0x02);
+				data.push(0x0A);
+				let byteArray = ModbusUtils.getWriteModbus(address, start, data);
+				let hex = HexUtils.byteArrayToHex(byteArray);
+
+				// 如果CRC高位在前
+				let crcLowFront = false; // CRC是否低位在前
+				let byteArray1 = ModbusUtils.getWriteModbusCRCLowFront(address, start, data, crcLowFront);
+				let hex1 = HexUtils.byteArrayToHex(byteArray1);
+
+```
+
+## ASCII工具类
+
+```
+
+import * as ASCIIUtils from '@/uni_modules/wrs-js-modbusCRCHex/js_sdk/wrs-ASCIIUtils.js';
+
+```
+
+- 字符串转ASCII
+
+```
+
+				let str = "Get_ID占三";
+				// byteArray为字节数组
+				let byteArray = ASCIIUtils.encodeUtf8(str);
+				// hex为十六进制字符串
+				let hex = HexUtils.byteArrayToHex(byteArray);
+
+```
+
+- ASCII转字符串
+
+```
+
+let hex = "4765745f4944e58da0e4b889"
+let decodeStr = ASCIIUtils.decodeUtf8(hex);
+
+```
+
+## 整型工具类
+
+```
+
+import * as IntUtils from '@/uni_modules/wrs-js-modbusCRCHex/js_sdk/wrs-IntUtils.js';
+
+```
+
+- 高低位转整型
+
+```
+
+				// 低位
+				let low = 226;
+				// 高位
+				let high = 102;
+				// 26338
+				let value = IntUtils.highLowToInt({
+					low: low,
+					high: high
+				})
+				
+```
+
+- 整型转高低位
+
+```
+
+				// 整型
+				let value = 26338;
+				// 26338
+				let obj = IntUtils.intToHighLow(value)
+				// 低位
+				let low = obj.low;
+				// 高位
+				let high = obj.high;
+
+```
+
+- 大端序-字节数组转整型
+
+```
+
+var byteArray = [0x01, 0x02, 0x03, 0x04]
+var intValue = IntUtils.bigEndianToInt(byteArray)
+
+```
+
+- 大端序 int转字节数组
+
+```
+
+	var intValue = 2461;
+	var byteArray = IntUtils.bigEndianToByteArray(intValue)
+
+```
+
+- 小端序-字节数组转整型
+
+```
+
+			var byteArray = [0x01, 0x02, 0x03, 0x04]
+			var intValue = IntUtils.littleEndianToInt(byteArray)
+
+```
+
+- 小端序-整型转字节数组
+
+```
+
+var intValue = 2461;
+var byteArray = IntUtils.littleEndianToByteArray(intValue)
+				
+
+```
+
+- 十进制转二进制
+
+```
+
+			var intValue = 20;
+			var bitStr = IntUtils.intToBit(intValue);
+
+```
+
+- 二进制转十进制
+
+```
+
+				var bit = "00001001";
+				var intValue = IntUtils.bitToInt(bit);
+
+
+```

+ 233 - 0
utils/common/wrs-ASCIIUtils.js

@@ -0,0 +1,233 @@
+import * as HexUtils from './wrs-HexUtils.js';
+
+export function encodeUtf8(str) {
+	// 方法1:
+	// const utf8 = [];
+	// for (let ii = 0; ii < str.length; ii++) {
+	// 	let charCode = str.charCodeAt(ii);
+	// 	if (charCode < 0x80){ 
+	// 		utf8.push(charCode);
+	// 	} else if (charCode < 0x800) {
+	// 		utf8.push(0xc0 | (charCode >> 6), 0x80 | (charCode & 0x3f));
+	// 	} else if (charCode < 0xd800 || charCode >= 0xe000) {
+	// 		utf8.push(0xe0 | (charCode >> 12), 0x80 | ((charCode >> 6) & 0x3f), 0x80 | (charCode & 0x3f));
+	// 	} else {
+	// 		ii++;
+	// 		// Surrogate pair:
+	// 		// UTF-16 encodes 0x10000-0x10FFFF by subtracting 0x10000 and
+	// 		// splitting the 20 bits of 0x0-0xFFFFF into two halves
+	// 		charCode = 0x10000 + (((charCode & 0x3ff) << 10) | (str.charCodeAt(ii) & 0x3ff));
+	// 		utf8.push(
+	// 			0xf0 | (charCode >> 18),
+	// 			0x80 | ((charCode >> 12) & 0x3f),
+	// 			0x80 | ((charCode >> 6) & 0x3f),
+	// 			0x80 | (charCode & 0x3f),
+	// 		);
+	// 	}
+	// }
+	// return utf8;
+	// 方法2:
+	// var bytes = []
+	// for (let ii = 0; ii < str.length; ii++) {
+	//   // for...of循环,能正确识别 32 位的 UTF-16 字符, 可以查阅资料了解。
+	//   	let code = str.charCodeAt(ii);
+	//   // let code = ch.codePointAt(0)
+	//   if (code >= 65536 && code <= 1114111) {// 位运算, 补齐8位
+	//     bytes.push((code >> 18) | 0xf0)
+	//     bytes.push(((code >> 12) & 0x3f) | 0x80)
+	//     bytes.push(((code >> 6) & 0x3f) | 0x80)
+	//     bytes.push((code & 0x3f) | 0x80)
+	//   } else if (code >= 2048 && code <= 65535) {
+	//     bytes.push((code >> 12) | 0xe0)
+	//     bytes.push(((code >> 6) & 0x3f) | 0x80)
+	//     bytes.push((code & 0x3f) | 0x80)
+	//   } else if (code >= 128 && code <= 2047) {
+	//     bytes.push((code >> 6) | 0xc0)
+	//     bytes.push((code & 0x3f) | 0x80)
+	//   } else {
+	//     bytes.push(code)
+	//   }
+	// }
+	// return bytes
+
+	// 方法3,android不支持TextEncoder
+	// let encoder = new TextEncoder();
+	// let utf8 = encoder.encode(str);  // UTF-8编码后的二进制数据
+
+	// return utf8
+	const encoded = encodeURIComponent(str);
+	const charCodes = [];
+	let i = 0;
+	while (encoded[i]) {
+		if (encoded[i] === '%') {
+			const substr = encoded.slice(i, i + 3);
+			charCodes.push(parseInt(substr.slice(-2), 16));
+			i += 3;
+		} else {
+			charCodes.push(encoded[i].charCodeAt(0));
+			i++;
+		}
+	}
+	return charCodes
+	// return Uint8Array.from(charCodes).buffer;
+}
+export function decodeUtf8(str) {
+
+
+	let arr = HexUtils.hexToUint8Array(str);
+
+	const REPL_CHAR = 0xFFFD;
+	const hex = x => x.toString(16).padStart(2, '0');
+	const xs = Array.from(arr);
+	const res = [];
+	let i = 0;
+	while (i < xs.length && i < 3 && xs[i] && (xs[i] & 0xC0) === 0x80) {
+		res.push(REPL_CHAR); // replacement for continuation byte
+		i++;
+	}
+	if (i >= xs.length) return String.fromCodePoint(...res);
+	if (!(
+			((xs[i] & 0x80) === 0) || // 1 byte
+			((xs[i] & 0xE0) === 0xC0) || // 2 byte
+			((xs[i] & 0xF0) === 0xE0) || // 3 byte
+			((xs[i] & 0xF8) === 0xF0) // 4 byte
+		)) {
+		throw new Error(`invalid utf-8. Expected a leading byte at index ${i} actual ${hex(xs[i])}`);
+	}
+	for (; i < xs.length; i++) {
+		const x = xs[i];
+		if ((x & 0x80) === 0) {
+			// 1 byte
+			res.push(x);
+			continue;
+		}
+		if ((x & 0xE0) === 0xC0) {
+			// 2 byte
+			if (i + 1 >= xs.length) {
+				res.push(REPL_CHAR); // replacement for 1st byte, 2nd byte is past end of string
+				break;
+			}
+			const x1 = xs[i + 1];
+			if ((x1 & 0xC0) !== 0x80) {
+				throw new Error(`invalid utf-8. Expected a continuation byte at index ${i + 1} actual ${hex(x1)}`);
+			}
+			const c = ((x & 0x1F) << 6) | (x1 & 0x3F);
+			if (c < 0x80 || c >= 0x800) {
+				throw new Error(`invalid utf-8. Expected an integer between 0x80 and 0x800 at index ${i} actual ${c}`);
+			}
+			res.push(c);
+			i++;
+			continue;
+		}
+		if ((x & 0xF0) === 0xE0) {
+			// 3 byte
+			if (i + 2 >= xs.length) {
+				res.push(REPL_CHAR); // replacement for 1st byte
+				if (i + 1 < xs.length) res.push(REPL_CHAR); // replacement for 2nd byte, 3rd byte is past end of string
+				break;
+			}
+			const x1 = xs[i + 1];
+			if ((x1 & 0xC0) !== 0x80) {
+				throw new Error(`invalid utf-8. Expected a continuation byte at index ${i + 1} actual ${hex(x1)}`);
+			}
+			const x2 = xs[i + 2];
+			if ((x2 & 0xC0) !== 0x80) {
+				throw new Error(`invalid utf-8. Expected a continuation byte at index ${i + 2} actual ${hex(x2)}`);
+			}
+			const c = ((x & 0x0F) << 12) | ((x1 & 0x3F) << 6) | (x2 & 0x3F);
+			if (c < 0x800 || c >= 0x10000) {
+				throw new Error(
+					`invalid utf-8. Expected an integer between 0x800 and 0x10000 at index ${i} actual ${c}`);
+			}
+			res.push(c);
+			i += 2;
+			continue;
+		}
+		if ((x & 0xF8) === 0xF0) {
+			// 4 byte
+			if (i + 3 >= xs.length) {
+				res.push(REPL_CHAR); // replacement for 1st byte
+				if (i + 1 < xs.length) res.push(REPL_CHAR); // replacement for 2nd byte
+				if (i + 2 < xs.length) res.push(REPL_CHAR); // replacement for 3rd byte, 4th byte is past end of string
+				break;
+			}
+			const x1 = xs[i + 1];
+			if ((x1 & 0xC0) !== 0x80) {
+				throw new Error(`invalid utf-8. Expected a continuation byte at index ${i + 1} actual ${hex(x1)}`);
+			}
+			const x2 = xs[i + 2];
+			if ((x2 & 0xC0) !== 0x80) {
+				throw new Error(`invalid utf-8. Expected a continuation byte at index ${i + 2} actual ${hex(x2)}`);
+			}
+			const x3 = xs[i + 3];
+			if ((x3 & 0xC0) !== 0x80) {
+				throw new Error(`invalid utf-8. Expected a continuation byte at index ${i + 3} actual ${hex(x3)}`);
+			}
+			const c = ((x & 0x07) << 18) | ((x1 & 0x3F) << 12) | ((x2 & 0x3F) << 6) | (x3 & 0x3F);
+			if (c < 0x10000) {
+				throw new Error(`invalid utf-8. Expected an integer above 0x10000 at index ${i} actual ${c}`);
+			}
+			res.push(c);
+			i += 3;
+			continue;
+		}
+		throw new Error(`invalid utf-8. Expected a leading byte at index ${i} actual ${hex(x)}`);
+	}
+	return String.fromCodePoint(...res);
+
+
+	// const u8 = new Uint8Array(buffer);
+	// const oneByteChars = String.fromCharCode(...u8);
+	// return btoa(oneByteChars);
+
+	// let uint8Array = HexUtils.hexToUint8Array(str);
+	// let decoder = new TextDecoder();
+	// let result = decoder.decode(uint8Array); // 解码后的字符串
+	// return result
+
+	// let strValue = ''
+	// let obStr = [...str].map((ch) => {
+	// 	return padStart(parseInt(ch, 16).toString(2), 4, 0)
+	// }).join('').match(/\d{8}/g).map((item) => parseInt(item, 2))
+	// for (var i = 0; i < obStr.length;) {
+
+	// 	let code = obStr[i]
+	// 	let code1, code2, code3, code4, hex
+	// 	if ((code & 240) == 240) {
+	// 		code1 = (code & 0x03).toString(2)
+	// 		code2 = padStart((obStr[i + 1] & 0x3f).toString(2), 6, '0')
+	// 		code3 = padStart((obStr[i + 2] & 0x3f).toString(2), 6, '0')
+	// 		code4 = padStart((obStr[i + 3] & 0x3f).toString(2), 6, '0')
+	// 		hex = parseInt((code1 + code2 + code3 + code4), 2)
+	// 		strValue = strValue + String.fromCodePoint(hex)
+	// 		i = i + 4
+	// 	} else if ((code & 224) == 224) {
+	// 		code1 = (code & 0x07).toString(2)
+	// 		code2 = padStart((obStr[i + 1] & 0x3f).toString(2), 6, '0')
+	// 		code3 = padStart((obStr[i + 2] & 0x3f).toString(2), 6, '0')
+	// 		hex = parseInt((code1 + code2 + code3), 2)
+	// 		strValue = strValue + String.fromCodePoint(hex)
+	// 		i = i + 3
+	// 	} else if ((code & 192) == 192) {
+	// 		code1 = (code & 0x0f).toString(2)
+	// 		code2 = padStart((obStr[i + 1] & 0x3f).toString(2), 6, '0')
+	// 		hex = parseInt((obStr + code2), 2)
+	// 		strValue = strValue + String.fromCodePoint(hex)
+	// 		i = i + 2
+	// 	} else {
+	// 		hex = code
+	// 		strValue = strValue + String.fromCodePoint(code)
+	// 		i = i + 1
+	// 	}
+	// }
+	// return strValue
+}
+// module.exports = {
+// 	encodeUtf8: encodeUtf8,
+// 	decodeUtf8: decodeUtf8
+// }
+
+
+function padStart(str, len, prefix) {
+	return ((new Array(len + 1).join(prefix)) + str).slice(-len) //  也可用 new Array(len+1).fill(0)
+}

+ 18 - 0
utils/common/wrs-Base64Utils.js

@@ -0,0 +1,18 @@
+
+export function encodeBase64(str) {
+	// let base64 = btoa(str)
+	// return base64
+	return new Buffer(str).toString('base64');
+}
+
+export function decodeBase64(str) {
+ //   let originStr = atob(base64)  // 解码后的字符串
+	// return originStr
+	return Buffer(str, 'base64').toString();
+}
+
+// https://blog.csdn.net/qq_42961150/article/details/121922216
+//编码
+// new Buffer(String, 'base64').toString('hex');
+// //解码
+// new Buffer(base64Str, 'hex').toString('utf8');

+ 92 - 0
utils/common/wrs-ByteUtils.js

@@ -0,0 +1,92 @@
+const HEX_CHAR_TABLE =  ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
+
+ export function intToByte(intValue){
+        var byteValue = intValue & 0xff;
+        return byteValue;
+ }
+
+ export function byteToInt(byteValue){
+    var intValue = byteValue & 0xff;
+    return intValue;
+}
+ 
+export function intArrayToHex(intArray) {
+	 var byteArray = []
+	 for(var i = 0; i < intArray.length; i ++) {
+		 byteArray.push(intToByte(intArray[i]));
+	 }
+	 return byteArrayToHex(byteArray);
+ }
+ 
+ export function byteArrayToHex(byteArray) {
+ 	 var hex = ""
+ 	 for(var i = 0; i < byteArray.length; i ++) {
+		 var byteValue = byteArray[i];
+		 hex = hex + HEX_CHAR_TABLE[(byteValue & 0xf0) >> 4];
+		 hex = hex + HEX_CHAR_TABLE[byteValue & 0x0f]; 
+ 	 }
+	 return hex;
+ }
+ 
+ export function hexToIntArray(hex) {
+	  var len = hex.length/2;
+	  var intArray = [];
+	  for(var i = 0; i< len; i ++) {
+		  var start = i * 2;
+		  var hexStr = hex.substring(start, start + 2);
+		   var intValue = parseInt(hexStr,16);
+		   intArray.push(intValue);
+	  }
+	  return intArray;
+ }
+ 
+ export function hexToByteArray(hex) {
+	 var len = hex.length;
+	 var intArray = hexToIntArray(hex);
+	 var byteArray = [];
+	 for(var i = 0; i < intArray.length; i ++) {
+		 var intValue = intArray[i];
+		 var byteValue = intToByte(intValue);
+		 byteArray.push(byteValue);
+	 }
+	 return byteArray;
+ }
+ 
+ export function intToHex(intValue) {
+	 return intValue.toString(16);
+ }
+ 
+
+ /**
+  * 16进制字符串转ArrayBuffer
+  * @param {*} hex String
+  */
+export function hexToArrayBuffer(hex) {
+   var typedArray = new Uint8Array(hex.match(/[\da-f]{2}/gi).map(function (h) {
+     return parseInt(h, 16)
+   }));
+   var buffer = typedArray.buffer;
+   return buffer;
+ }
+ 
+ /**
+  * ArrayButter转16进制字符串
+  * @param {*} buffer ArrayBuffer
+  */
+ export function arrayBufferToHex(buffer) { // buffer is an ArrayBuffer
+   return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
+ }
+ 
+ // module.exports = {
+ //   intToByte: intToByte,
+ //   byteToInt: byteToInt,
+ //   intArrayToHex: intArrayToHex,
+ //   byteArrayToHex: byteArrayToHex,
+ //   highLowToInt: highLowToInt,
+ //   intToHighLow: intToHighLow,
+ //   intToHex: intToHex,
+ //   hexToIntArray: hexToIntArray,
+ //   hexToByteArray: hexToByteArray,
+ //   hexToArrayBuffer: hexToArrayBuffer,
+ //   arrayBufferToHex: arrayBufferToHex
+ // }

+ 154 - 0
utils/common/wrs-CRCUtils.js

@@ -0,0 +1,154 @@
+import * as IntUtils from './wrs-IntUtils.js';
+
+/* 
+ *  http://www.metools.info/code/c15.html
+ *  采用的是CRC-16/MODBUS
+ *  ios swift: https://github.com/ivanesik/CrcSwift
+ */
+export function getCRC16_MODBUS(bytes) {
+	var CRC = 0x0000ffff;
+	var POLYNOMIAL = 0x0000a001;
+	var i;
+	var j;
+	for (i = 0; i < bytes.length; i++) {
+		CRC ^= (bytes[i] & 0x000000ff);
+		for (j = 0; j < 8; j++) {
+			if ((CRC & 0x00000001) != 0) {
+				CRC >>= 1;
+				CRC ^= POLYNOMIAL;
+			} else {
+				CRC >>= 1;
+			}
+		}
+	}
+	return CRC;
+}
+
+export function getCRC16_CCITT_FALSE(bytes) {
+	var crc = 0xffff; // initial value
+	var polynomial = 0x1021; // poly value
+	for (var index = 0; index < bytes.length; index++) {
+		var b = bytes[index];
+		for (var i = 0; i < 8; i++) {
+			var bit = ((b >> (7 - i) & 1) == 1);
+			var c15 = ((crc >> 15 & 1) == 1);
+			crc <<= 1;
+			if (c15 ^ bit) {
+				crc ^= polynomial;
+			}
+		}
+	}
+	crc &= 0xffff;
+	return crc;
+}
+
+export function getCRC32(data) {
+	var table = [
+		0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+		0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+		0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+		0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+		0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+		0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+		0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+		0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+		0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+		0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+		0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+		0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+		0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+		0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+		0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+		0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+		0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+		0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+		0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+		0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+		0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+		0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+		0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+		0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+		0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+		0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+		0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+		0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+		0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+		0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+		0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+		0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+	];
+	var crc = 0xffffffff;
+	var length = data.length;
+	for (var i = 0; i < length; i++) {
+        var b = data[i];
+		crc = (crc >>> 8 ^ table[(crc ^ b) & 0xff]);
+	}
+	crc = crc ^ 0xffffffff;
+	return crc;
+}
+
+
+export function getCRC3200(data, initialCrc, polynom, xor, refIn, refOut) {
+	var crcArray = Uint32Array.from([initialCrc]);
+	var length = data.length;
+	for (var i = 0; i < length; i++) {
+		var byte = data[i];
+		if (refIn) {
+			var reverBit = reverseBits(byte)
+			var reverBitArray = Uint32Array.from([reverBit])
+			crcArray[0] = (reverBitArray[0] << 24) ^ crcArray[0]
+		} else {
+			crcArray[0] = (byte << 24) ^ crcArray[0]
+		}
+		for (var j = 0; j < 8; j++) {
+			let check = crcArray[0] & 0x80000000
+			crcArray[0] = crcArray[0] << 1
+
+			if (check != 0) {
+				crcArray[0] = crcArray[0] ^ polynom
+			}
+		}
+	}
+
+	if (refOut) {
+		reverseBits(crcArray[0])
+	}
+	return (crcArray[0] ^ xor)
+}
+
+function reverseBits(value) {
+	var bitStr = IntUtils.intToBit(value);
+	if (bitStr.length < 8) {
+		let count = 8 - bitStr.length
+		for (var i = 0; i < count; i++) {
+			bitStr = "0" + bitStr;
+		}
+	}
+	var reverBitStr = reverseString(bitStr);
+	var intValue = IntUtils.bitToInt(reverBitStr);
+	return intValue
+}
+
+function reverseString(str) {
+	let reversedStr = '';
+	for (let i = str.length - 1; i >= 0; i--) {
+		reversedStr += str[i];
+	}
+	return reversedStr;
+}
+
+
+// 	if refOut {
+// 		crc = DataHelper.reverseBits(crc)
+// 	}
+
+// 	return crc ^ xor
+// }
+
+
+// module.exports = {
+// 	getCRC16_MODBUS: getCRC16_MODBUS,
+// 	getCRC16_CCITT_FALSE: getCRC16_CCITT_FALSE,
+// 	highLowToInt: highLowToInt,
+// 	intToHighLow: intToHighLow
+// }

+ 102 - 0
utils/common/wrs-HexUtils.js

@@ -0,0 +1,102 @@
+const HEX_CHAR_TABLE =  ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
+
+ export function intToByte(intValue){
+        var byteValue = intValue & 0xff;
+        return byteValue;
+ }
+
+ export function byteToInt(byteValue){
+    var intValue = byteValue & 0xff;
+    return intValue;
+}
+ 
+ export function intArrayToHex(intArray) {
+	 var byteArray = []
+	 for(var i = 0; i < intArray.length; i ++) {
+		 byteArray.push(intToByte(intArray[i]));
+	 }
+	 return byteArrayToHex(byteArray);
+ }
+ 
+ export function byteArrayToHex(byteArray) {
+	 // 方法1:
+ 	 var hex = ""
+ 	 for(var i = 0; i < byteArray.length; i ++) {
+		 var byteValue = byteArray[i];
+		 hex = hex + HEX_CHAR_TABLE[(byteValue & 0xf0) >> 4];
+		 hex = hex + HEX_CHAR_TABLE[byteValue & 0x0f]; 
+ 	 }
+	 return hex;
+	
+ }
+ 
+ export function hexToIntArray(hex) {
+	  var len = hex.length/2;
+	  var intArray = [];
+	  for(var i = 0; i< len; i ++) {
+		  var start = i * 2;
+		  var hexStr = hex.substring(start, start + 2);
+		   var intValue = parseInt(hexStr,16);
+		   intArray.push(intValue);
+	  }
+	  return intArray;
+ }
+ 
+ export function hexToByteArray(hex) {
+	 var len = hex.length;
+	 var intArray = hexToIntArray(hex);
+	 var byteArray = [];
+	 for(var i = 0; i < intArray.length; i ++) {
+		 var intValue = intArray[i];
+		 var byteValue = intToByte(intValue);
+		 byteArray.push(byteValue);
+	 }
+	 return byteArray;
+ }
+ 
+ export function intToHex(intValue) {
+	 return intValue.toString(16);
+ }
+ 
+ /**
+  * 16进制字符串转ArrayBuffer
+  * @param {*} hex String
+  */
+ export function hexToArrayBuffer(hex) {
+   var typedArray = new Uint8Array(hex.match(/[\da-f]{2}/gi).map(function (h) {
+     return parseInt(h, 16)
+   }));
+   var buffer = typedArray.buffer;
+   return buffer;
+ }
+ 
+ /**
+  * ArrayButter转16进制字符串
+  * @param {*} buffer ArrayBuffer
+  */
+ export function arrayBufferToHex(buffer) { // buffer is an ArrayBuffer
+   return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
+ }
+ 
+ export function hexToUint8Array(hex) {
+   var typedArray = new Uint8Array(hex.match(/[\da-f]{2}/gi).map(function (h) {
+     return parseInt(h, 16)
+   }));
+   return typedArray;
+ }
+ 
+ export function uint8ArrayToHex(uint8Array) {
+   return Array.prototype.map
+           .call(uint8Array, (x) => ('00' + x.toString(16)).slice(-2))
+           .join('');
+ }
+ 
+ // module.exports = {
+ //   intArrayToHex: intArrayToHex,
+ //   byteArrayToHex: byteArrayToHex,
+ //   intToHex: intToHex,
+ //   hexToIntArray: hexToIntArray,
+ //   hexToByteArray: hexToByteArray,
+ //   hexToArrayBuffer: hexToArrayBuffer,
+ //   arrayBufferToHex: arrayBufferToHex
+ // }

+ 50 - 0
utils/common/wrs-ISType.js

@@ -0,0 +1,50 @@
+const isType = type => (/^\[object\s(.*)\]$/.exec(Object.prototype.toString.call(type)))[1];
+export const isArray = function(a) {
+	return isType(a) == 'Array';
+}; // 注意首字母大写
+export const isSymbol = function(a) {
+	return isType(a) == 'Symbol';
+};
+export const isBoolean = function(a) {
+	return isType() == 'Boolean';
+};
+
+export const isNumber = function(a) {
+	return isType(a) == 'Number';
+};
+export const isUndefined = function(a) {
+	return isType(a) == 'Undefined';
+};
+export const isNull = function(a) {
+	return isType(a) == 'Null';
+};
+export const isObject = function(a) {
+	return isType(a) == 'Object';
+};
+export const isString = function(a) {
+	return isType(a) == 'String';
+};
+export const isFunction = function(a) {
+	return isType(a) == 'Function';
+};
+export const isDate = function(a) {
+	return isType(a) == 'Date';
+};
+export const isRegExp = function(a) {
+	return isType(a) == 'RegExp';
+};
+
+// module.exports = {
+// 	isType: isType,
+// 	isArray: isArray,
+// 	isSymbol: isSymbol,
+// 	isBoolean: isBoolean,
+// 	isString: isString,
+// 	isNumber: isNumber,
+// 	isUndefined: isUndefined,
+// 	isNull: isNull,
+// 	isObject: isObject,
+// 	isFunction: isFunction,
+// 	isDate: isDate,
+// 	isRegExp:isRegExp
+// }

+ 114 - 0
utils/common/wrs-IntUtils.js

@@ -0,0 +1,114 @@
+export function intToHex(intValue) {
+	return intValue.toString(16);
+}
+
+
+export function highLowToInt(obj) {
+	var value = ((obj.high & 0xFF) << 8) | (obj.low & 0xFF);
+	return value;
+}
+
+
+export function intToHighLow(intValue) {
+	var low = intValue & 0xFF;
+	var high = (intValue & 0xFFFF) >>> 8;
+	return {
+		low: low,
+		high: high
+	}
+}
+
+    /**
+     * 大端序 字节数组转int
+     *
+     * @param bytes
+     * @return
+     */
+export function bigEndianToInt(bytes) {
+	var byte0 = bytes[3] & 0XFF;
+	var byte1 = (bytes[2] & 0XFF) << 8;
+	var byte2 = (bytes[1] & 0XFF) << 16;
+	var byte3 = (bytes[0] & 0XFF) << 24;
+	var value = byte0 | byte1 | byte2 | byte3;
+        return value;
+}
+
+ /**
+     * 小端序 字节数组转int
+     *
+     * @param bytes
+     * @return
+     */
+export function littleEndianToInt(bytes) {
+        return (bytes[0]&0XFF)
+                | ((bytes[1]&0XFF) << 8)
+                | ((bytes[2]&0XFF) << 16)
+                | ((bytes[3]&0XFF) << 24);
+    }
+  
+
+// 大端序 int转字节数组
+export function bigEndianToByteArray(i) {
+	var byte1 = i & 0XFF;
+	var byte2 = (i & 0XFFFF) >>> 8;
+	var byte3 = (i & 0XFFFFFF) >>> 16;
+	var byte4 = (i & 0XFFFFFFFF) >>> 24;
+	var byteArray = [];
+	byteArray.push(byte1);
+	byteArray.push(byte2);
+	byteArray.push(byte3);
+	byteArray.push(byte4);
+	return byteArray;
+}
+
+/**
+ * 小端序 int转字节数组
+ *
+ * @param i
+ * @return
+ */
+export function littleEndianToByteArray(i) {
+	var byte1 = i & 0XFF;
+	var byte2 = (i & 0XFF << 8) >> 8;
+	var byte3 = (i & 0XFF << 16) >> 16;
+	var byte4 = (i & 0XFF << 24) >> 24;
+	var byteArray = []
+	byteArray.push(byte1)
+	byteArray.push(byte2)
+	byteArray.push(byte3)
+	byteArray.push(byte4)
+	return byteArray;
+}
+
+
+export function bitToInt(bitStr) {
+      return  parseInt(bitStr, 2)
+ }
+
+export function intToBit(by){
+    //    var bit0 = (by>>7) & 0x1;
+	   // var bit1 = (by>>6) & 0x1;
+	   // var bit2 = (by>>5) & 0x1;
+	   // var bit3 = (by>>4) & 0x1;
+	   // var bit4 = (by>>3) & 0x1;
+	   // var bit5 = (by>>2) & 0x1;
+	   // var bit6 = (by>>1) & 0x1;
+	   // var bit7 = (by>>1) & 0x1;
+	   // return "" + bit0 + bit1 + bit2 + bit3 + bit4 + bit5 + bit6 + bit7; 
+	  // return by.toString(2)
+	  var value = by.toString(2)
+	  if(value.length < 8) {
+	  		 var count = 8 - value.length
+	  		 for(var i = 0; i < count; i ++) {
+	  			 value = "0" + value
+	  		 }
+	  }
+	   return value
+}
+
+
+// module.exports = {
+// intToHex: intToHex,
+//   highLowToInt: highLowToInt,
+//   intToHighLow: intToHighLow
+// }

+ 132 - 0
utils/common/wrs-ModbusUtils.js

@@ -0,0 +1,132 @@
+// import {
+// 	getCRC
+// } from './CRCUtils.js'
+
+// var CRCUtils = require('./wrs-CRCUtils.js');
+import * as CRCUtils from './wrs-CRCUtils.js';
+import * as IntUtils from './wrs-IntUtils.js';
+/**
+ * 读指令
+ * @param address 设备地址, int
+ * @param address 寄存器起始地址, int
+ * @param count 寄存器个数, int
+ * @return byte[]
+ */
+export function getReadModbus(address, start, count) {
+	return getReadModbusCRCLowFront(address, start, count, true);
+}
+
+export function getReadModbusCRCLowFront(address, start, count, crcLowFront) {
+	var registerObj = IntUtils.intToHighLow(start)
+	var registerLow = registerObj.low; // int
+	var registerHigh = registerObj.high; // int
+	var countLow = count & 0xFF; // int
+	var countHigh = count >>> 8; // int
+	var data = [registerHigh, registerLow, countHigh, countLow]; // int[]
+	var sendData = getModbusDataCRCLowFront(address, 0x03, data, crcLowFront); // byte[]
+	return sendData;
+}
+
+
+/**
+ * 写指令
+ * @param address 设备地址 int
+ * @param start 寄存器起始地址 int
+ * @param writeData 寄存器个数 int[]
+ * @return byte[]
+ */
+export function getWriteModbus(address, start, writeData) {
+	return getWriteModbusCRCLowFront(address, start, writeData, true);
+}
+
+export function getWriteModbusCRCLowFront(address, start, writeData, crcLowFront) {
+	var registerObj = IntUtils.intToHighLow(start)
+	var registerLow = registerObj.low; // int
+	var registerHigh = registerObj.high; // int
+	var data = []; // int[]
+	data.push(registerHigh);
+	data.push(registerLow)
+	for (var i = 0; i < writeData.length; i++) {
+		data.push(writeData[i]);
+	}
+	var sendData = getModbusDataCRCLowFront(address, 0x06, data, crcLowFront);
+	return sendData;
+}
+
+// public static List<Byte> isValidModbusResponseData(List<Byte> list) {
+//     if (null != list && list.size() >= 4) {
+//         int size = list.size();
+//         int leng = ByteUtils.byteToInt(list.get(2));
+//         int totalSize = leng + 5;
+//         if (size < totalSize) {
+//             return null;
+//         }
+//         List tempList = list.subList(0, totalSize - 2);
+//         byte[] tempData = ArrayUtils.listTobyte(tempList);
+//         int crc = CRCUtils.getCRC(tempData);
+//         int low = crc & 0xFF;
+//         int high = crc >>> 8;
+//         byte lowData = list.get(totalSize - 2);
+//         byte hightData = list.get(totalSize - 1);
+//         if (low == ByteUtils.byteToInt(lowData) && high == ByteUtils.byteToInt(hightData)) {
+//             return list.subList(0, totalSize);
+//         } else {
+//             return null;
+//         }
+//     } else {
+//         return null;
+//     }
+// }
+
+/**
+ * 
+ * @param address 设备地址 int
+ * @param fun 功能值 int
+ * @param data 数据 int[]
+ * @return byte[]
+ */
+export function getModbusData(address, fun, data) {
+	return getModbusDataCRCLowFront(address, fun, data, true);
+}
+
+/**
+ * 
+ * @param address 设备地址 int
+ * @param fun 功能值 int
+ * @param data 数据 int[]
+ * @param crcLowFront CRC是否低位在前
+ * @return byte[]
+ */
+export function getModbusDataCRCLowFront(address, fun, data,crcLowFront) {
+	var leng = 2;
+	if (data) {
+		leng += data.length;
+	}
+	var tempData = []; // byte[]
+	tempData.push(address);
+	tempData.push(fun);
+	if (data) {
+		for (var i = 0; i < data.length; i++) {
+			tempData.push(data[i]);
+		}
+	}
+	var crc = CRCUtils.getCRC16_MODBUS(tempData); // int
+	var crcObj = IntUtils.intToHighLow(crc)
+	var low = crcObj.low; // int
+	var high = crcObj.high; // int
+	if(crcLowFront) {
+		tempData.push(low);
+		tempData.push(high);
+	} else {
+		tempData.push(high);
+		tempData.push(low);
+	}
+
+	return tempData;
+}
+
+// module.exports = {
+// 	getReadModbus: getReadModbus,
+// 	getWriteModbus: getWriteModbus,
+// 	getModbusData: getModbusData
+// }

+ 127 - 0
utils/machine/audioClass.js

@@ -0,0 +1,127 @@
+import {formatZero, logs} from "@/utils/util";
+import Config from "@/utils/config";
+
+export class audioClass {
+
+  constructor(topClass, op = null) {
+    this.topClass = topClass
+    this.audio = null
+    this.option = {
+      machine: 1,
+      version: 0,
+      model: 0,
+      sex: 1,
+    }
+    this.allFileList = {
+      // machine1: audioMachine1,
+    }
+    this.run = {
+      type: 0, // 0 手机播放;1 音箱播放;
+      list: {}
+    }
+    this.audio = null
+    this.init()
+    this.setOption(op)
+  }
+
+  init() {
+    this.audio = uni.createInnerAudioContext({
+      useWebAudioImplement: true,
+    }); //创建播放器对象
+    this.audio.onPlay(() => {
+      console.log('Audio', '开始播放');
+    })
+    this.audio.onError((res) => {
+      console.log('Audio err', res);
+    })
+    this.audio.onSeeking(() => {
+      console.log('Audio onSeeking');
+    })
+    this.audio.onSeeked(() => {
+      console.log('Audio onSeeked');
+    })
+    this.audio.onWaiting((res) => {
+      console.log('Audio onWaiting', res);
+    })
+    // this.audio.onPause(() => {
+    //   console.log('Audio', 'onPause');
+    // })
+    // this.audio.onStop(() => {
+    //   console.log('Audio', 'onStop');
+    // })
+    // this.audio.onCanplay((e) => {
+    //   console.log('Audio onCanplay', e);
+    // })
+    this.audio.onEnded((e) => {
+      console.log('Audio onEnded 自然结束', this.audio.duration);
+    })
+  }
+
+  async setOption(option) {
+    if (!option) return !1
+    this.option = Object.assign(this.option, option)
+    this.run.type = 0
+    this.run.list = {}
+
+    let modelList = this.allFileList[`machine${this.option.machine}`][`model${this.option.model}`]
+    this.run.type = 0
+    let defaultKey = 'default'
+    let loudspeakerKey = 'loudspeaker'
+    if (this.option.sex == 2) defaultKey = 'defaultGirl'
+    if (this.option.version > 0) {
+      if (this.option.sex == 2) loudspeakerKey = 'loudspeakerGirl'
+      if (this.option.version >= modelList[loudspeakerKey].version) this.run.type = 1
+    }
+    if (this.run.type == 0 && modelList[defaultKey]) {
+      this.run.list = modelList[defaultKey]
+      // for (const i in this.run.list) {
+      //   let it = this.run.list[i]
+      //   if (!it.file) return !0;
+      //   // it.file =it.file
+      // }
+      if (this.run.list) {
+        this.run.list.pause = {pause: !0, seek: 0}
+        this.run.list.stop = {stop: !0, seek: 0}
+      }
+    }
+    if (this.run.type == 1 && modelList[loudspeakerKey]) {
+      this.run.list = modelList[loudspeakerKey].list
+      this.run.list.pause = 'pause'
+      this.run.list.stop = 'pause'
+    }
+  }
+
+  play(seconds, queue = false) {
+    let item = this.run.list[seconds.toString()]
+    if (!item) return;
+    // logs('play item', item)
+    if (this.run.type == 0) {
+      if (item.file) {
+        let file = Config.get('imgUrl') + item.file
+        if (this.audio.src != file) {
+          this.audio.src = file
+        }
+        this.audio.startTime = 0
+      }
+      if (item.seek) this.audio.seek(item.seek)
+      if (item.pause) this.audio.pause()
+      if (item.stop) this.audio.stop()
+      if (item.play) this.audio.play()
+    } else {
+      let mKey = formatZero(this.option.machine, 2)
+      let machineClass = this.topClass[`Machine${mKey}Class`]
+      if (machineClass) {
+        // if (!queue) this.topClass[`machine${mKey}`]().sentOrder(item, 2)
+        // else {
+        logs(`audio type:${this.option.machine} data:${item}`)
+        this.topClass.queueAdd({
+          mT: this.option.machine,
+          t: 2,
+          p: item,
+        });
+        // }
+      }
+    }
+  }
+
+}

+ 13 - 0
utils/machine/config.js

@@ -24,3 +24,16 @@ export const usbConfigList = {
   '1155_22336': 'scan',
   '6790_29987': 'bmi',
 }
+export const equimentConnectConfig = {
+  3: {
+    // top: '0F0002',
+    // indexJudge: (index) => {
+    //   return index == 0
+    // },
+    order: [
+      {k: 'mac', s: 10, e: 22},
+    ],
+    serviceKey: 'FFE0',
+    channelKey: 'FFE1',
+  },
+}

+ 151 - 215
utils/machine/index.js

@@ -1,253 +1,189 @@
-import {array_column, logs, sleep} from "@/utils/util";
-import * as ASCIIUtils from "@/uni_modules/wrs-js-modbusCRCHex/js_sdk/wrs-ASCIIUtils";
-import {ScanMachine} from "@/utils/machine/scanMachine";
-import {showToast} from "@/utils/app";
-import {usbConfigList} from "@/utils/machine/config";
-import {BmiMachine} from "@/utils/machine/bmiMachine";
-import Debounce from "@/utils/debounce";
-
-let usbSerial = null
-// #ifdef APP-PLUS
-usbSerial = uni.requireNativePlugin("wrs-usbSerial")
-// logs('usbSerial', usbSerial)
-
-// #endif
+import {Machine03Class} from "./machine03Class";
+import * as tools from "@/utils/ble/tools";
+import {formatZero, logs, sleep} from "@/utils/util";
+import {showError, showToast} from "@/utils/app";
+import {isBluetoothEnabled} from "@/utils/uniFunction";
+import {isH5} from "@/utils/platform";
+import {audioClass} from "@/utils/machine/audioClass";
+import {ab2hex} from "@/utils/ble/hex";
 
 export class Machine {
 
-
   constructor() {
-    this.usbList = []
-    this.usbNum = 0
-
-
-    this.scanMachineClass = null
-    this.bmiMachineClass = null
-
-    this.permission = {
-      key: null,// usb地址
-      status: 0,
-      okList: [],// 已申请列表
-      list: {},// 记录列表
-    }
-
-
-    this.notify = false
-    this.notifyThis = null
-
-    // logs('Machine')
-    this.debounce = new Debounce()
-    this._init()
+    logs('machineV2 类加载')
+    this.isRunCreate = false
+    this.open = false
+    this.connectList = {};
+    this.foundRun = !1
+    this.foundCallback = null
+    this.notificationFun = {}
+    this.connectionStateFun = {}
+    this.audioClass = null
+
+    this.queueCreated = false
+    this.queueRun = false
+    this.queueInterval = null
+    this.queueLists = []
+    this.queueOutNum = 0
+
+    this.Machine03Class = null
+
+
+    /* #ifdef H5 */
+    window.$machine = this
+    /* #endif */
   }
 
   /**
-   * @returns {ScanMachine}
+   * @returns {Machine03Class}
    */
-  scan() {
-    if (!this.scanMachineClass) {
-      this.scanMachineClass = new ScanMachine(this, usbSerial)
+  machine03() {
+    if (!this.Machine03Class) {
+      this.Machine03Class = new Machine03Class(this)
     }
-    return this.scanMachineClass
+    return this.Machine03Class
   }
 
+
   /**
-   * @returns {BmiMachine}
+   *
+   * @returns {audioClass}
    */
-  bmi() {
-    if (!this.bmiMachineClass) {
-      this.bmiMachineClass = new BmiMachine(this, usbSerial)
-    }
-    return this.bmiMachineClass
+  audioHelper(obj = null) {
+    if (!this.audioClass) this.audioClass = new audioClass(this)
+    if (obj) this.audioClass.setOption(obj)
+    return this.audioClass
   }
 
-  async open(types = []) {
-    // logs('open')
-    for (const k in types) {
-      let it = types[k]
-      console.log('it', it)
-      if (it == 1) {
-        // await this.scans()._init()
-      }
+
+  async init() {
+    if (this.isRunCreate) return true;
+    logs('machineV2 init')
+    if (isH5) {
+      showToast('H5不支持蓝牙功能')
+      return false
     }
+
+    await tools._openAdapter();
     await sleep(1000)
-    this.getUsbList()
-  }
+    this.open = await isBluetoothEnabled()
 
-  /**
-   * @param open      插入usb 或 拔出usb
-   */
-  async getUsbList(open = true) {
-    this.debounce.do('getUsbList', () => {
-      // logs('getUsbList1')
-      this.usbList = {};
-      this.usbNum = 0
-      let that = this
-      // #ifdef APP-PLUS
-      this.permission.list = {}
-      usbSerial.findSerialPortDevice((resp) => {
-        logs('getUsbList2', resp)
-        if (resp.devices) {
-          that.usbList = resp.devices;
-          that.usbNum = resp.devices.length
-          for (const key in this.usbList) {
-            let it = this.usbList[key]
-            // logs('it', it)
-            const {vendorId, productId} = it.device
-            it.k = `${vendorId}_${productId}`
-            it.id = usbConfigList[it.k]
-            // logs('k', k, it.key, usbConfigList[k])
-            if (usbConfigList[it.k]) {
-              let data = {
-                id: it.id,
-                k: it.k,
-                key: it.key,
-                vendorId,
-                productId,
-              }
-              this.permission.list[data.key] = data
-            } else {
-              showToast(`未知设备:${key}`)
-            }
+    let that = this
+
+    this.bleDeviceFound(null)
+
+    /* #ifndef H5 */
+    uni.onBluetoothAdapterStateChange(({available}) => {
+      if (available == false && that.open == true) {
+        showError('请检查手机蓝牙是否已开启')
+        if (that.connectionStateFun.length > 0) {
+          for (const k in that.connectionStateFun) {
+            that.connectionStateFun[k]()
           }
         }
-        // logs('this.usbList', this.usbList)
-        // logs('this.permission.list', this.permission.list)
-        // logs('this.permission.okList', this.permission.okList)
-        if (open) {
-          this.getPermission()
-        } else {
-          this.closeUsb()
-        }
-      });
-      // #endif
-    }, 800)
-
+      } else if (available == true && that.open == false) {
+        // 是否需要再次init
+        tools._openAdapter();
+      }
+      if (that.open != available) {
+        console.log(`蓝牙状态被更新 原:${that.open}`)
+        that.open = available
+        console.log(`蓝牙状态被更新 现:${available}`)
+      }
+    })
+    /* #endif */
+
+    // 内容监听
+    /* #ifndef H5 */
+    uni.onBLECharacteristicValueChange(async (res) => {
+      res.str = ab2hex(res.value)
+      let key = this.connectList[res.deviceId]
+      if (!key) return
+      let fun = this.notificationFun[key]
+      if (fun) await fun(res)
+    })
+    /* #endif */
+
+    /* #ifndef H5 */
+    // 断线监听
+    uni.onBLEConnectionStateChange(async (res) => {
+      // 该方法回调中可以用于处理连接意外断开等异常情况
+      if (res.connected) return
+      let key = this.connectList[res.deviceId]
+      logs(`掉线 deviceId:${res.deviceId} key:${key}`)
+      if (!key) return
+      let fun = this.connectionStateFun[key]
+      if (fun) await fun(res)
+    })
+    /* #endif */
+
+    this.isRunCreate = true
+    return true
   }
 
 
-  getOnlineUsb(type = 1) {
-    let list = this.permission.okList
-    if (type === 1) {
-      list = array_column(list, 'id')
+  bleDeviceFound(callback = null) {
+    this.foundCallback = callback
+    if (!this.foundRun) {
+      this.foundRun = true
+      uni.onBluetoothDeviceFound((devices) => {
+        // console.log('onBluetoothDeviceFound', devices)
+        if (this.foundCallback) this.foundCallback(devices)
+      })
     }
-    return list
   }
 
+  addConnect(deviceId, key) {
+    this.connectList[deviceId] = key
+  }
 
-  _init() {
-    // logs('machine _init')
-    // #ifdef APP-PLUS
-    usbSerial.registerReceiver((resp) => {
-      const action = resp.action;
-      switch (action) {
-        // USB授权结果
-        case "com.android.wrs.USB_PERMISSION":
-          const granted = resp.granted;
-          // showToast("USB授权结果:" + granted);
-          // logs(1, granted)
-          this.getPermission(granted ? 1 : 2)
-          break;
-        case "android.hardware.usb.action.USB_DEVICE_ATTACHED":
-          // logs(2)
-          // showToast("有USB设备连接");
-          this.getUsbList(true)
-          break;
-        case "android.hardware.usb.action.USB_DEVICE_DETACHED":
-          // showToast("USB设备断开连接");
-          this.getUsbList(false)
-          // logs(3, resp)
-          break;
-        default:
-          break;
-      }
-    });
-    this.getUsbList()
-    // #endif
+  delConnect(deviceId) {
+    if (this.connectList[deviceId]) delete this.connectList[deviceId]
   }
 
-  async getPermission(type = 0) {
-    // logs('getPermission', type)
-    const l = Object.values(this.permission.list).length
-    // logs('getPermission', type)
-    if (l < 1) return false;
-    let key = this.permission.key
-    if (!key) {
-      key = Object.keys(this.permission.list)[0]
-      this.permission.key = key
-    }
-    // logs('key', key)
-    let item = this.permission.list[key]
-    // logs('getPermission2', this.permission.status, type, item)
-    let status = this.permission.status
-    // 已授权可跳出
-    if (this.permission.okList[item.key]) {
-      type = 3 // 已授权直接跳过
-      showToast(`已跳出 ${this[item.id]().title} 授权(重复)`, {
-        position: 'bottom'
-      })
-    }
 
-    if (type == 0 && status == 0) {
-      usbSerial.requestPermission({
-        key: item.key,
-      });
-      this[item.id]().key = item.key
-      this.permission.status = 1
-      return;
-    }
-    // 同意
-    if (type == 1) {
-      // logs('connect')
-      this[item.id]().auth = true
-      this[item.id]().connect()
-      // logs('connect1')
-      this.permission.okList.push({
-        key: item.key,
-        id: item.id,
-      })
-      // logs('connect2')
-      uni.$emit('machineUsb', {
-        id: item.id,
-        up: true,
-      })
-      // logs('connect3')
-    }
-    // 拒绝
-    if (type == 2) {
-      showToast(`拒绝了 ${this[item.id]().title} 授权,请重启软件再次授权`)
-      await sleep(1000)
-      uni.$emit('machineUsb', {
-        id: item.id,
-        up: false,
-      })
-    }
-    // logs('getPermissiongetPermission', type)
-    if (type != 0) {
-      delete this.permission.list[item.key]
-      this.permission.status = 0
-      this.permission.key = null
-      await this.getPermission(0)
+  queueAdd(task) {
+    this.queueLists.push(task)
+    if (!this.queueCreated) {
+      this.queueCreated = true
+      this.queueRunHandle()
+      this.queueInterval = setInterval(() => {
+        this.queueRunHandle()
+      }, 350);
     }
   }
 
-
-  closeUsb() {
-    // logs('closeUsb')
-    let newList = {}
-    if (this.usbList.length > 0) {
-      newList = array_column(this.usbList, 'id', 'key')
-    }
-    this.permission.okList = this.permission.okList.filter(it => {
-      if (!newList[it.key]) {
-        this[it.id]().close();
-        return false; // 过滤掉需要删除的元素
+  queueRunHandle() {
+    if (this.queueRun) return
+    this.queueRun = true
+    let l = this.queueLists.length || 0
+    if (l > 0) {
+      this.queueOutNum = 0
+      // 执行队列中的任务
+      const {mT, p, t = 1, o = {}} = this.queueLists.shift();
+      // console.log('queueRunHandle', mT, p, t)
+      // 执行任务的逻辑
+      let mKey = formatZero(mT, 2)
+      let machineClass = this[`Machine${mKey}Class`]
+      if (machineClass && machineClass.deviceId) {
+        machineClass.sentOrder(p, t, o)
       }
-      return true; // 保留不需要删除的元素
-    });
+    } else {
+      this.queueOutNum++
+      if (this.queueOutNum >= 400) this.clear()
+    }
+    this.queueRun = false
+  }
 
-    logs('closeUsb this.permission.okList', this.permission.okList)
+  // 清空队列
+  clear() {
+    this.queueLists = [];
+    if (this.queueInterval) {
+      clearInterval(this.queueInterval);
+      this.queueInterval = null;
+      this.queueCreated = false
+      this.queueRun = false
+    }
   }
 
 }
-
-

+ 253 - 0
utils/machine/index_old.js

@@ -0,0 +1,253 @@
+import {array_column, logs, sleep} from "@/utils/util";
+import * as ASCIIUtils from "@/uni_modules/wrs-js-modbusCRCHex/js_sdk/wrs-ASCIIUtils";
+import {ScanMachine} from "@/utils/machine/scanMachine";
+import {showToast} from "@/utils/app";
+import {usbConfigList} from "@/utils/machine/config";
+import {BmiMachine} from "@/utils/machine/bmiMachine";
+import Debounce from "@/utils/debounce";
+
+let usbSerial = null
+// #ifdef APP-PLUS
+usbSerial = uni.requireNativePlugin("wrs-usbSerial")
+// logs('usbSerial', usbSerial)
+
+// #endif
+
+export class Machine {
+
+
+  constructor() {
+    this.usbList = []
+    this.usbNum = 0
+
+
+    this.scanMachineClass = null
+    this.bmiMachineClass = null
+
+    this.permission = {
+      key: null,// usb地址
+      status: 0,
+      okList: [],// 已申请列表
+      list: {},// 记录列表
+    }
+
+
+    this.notify = false
+    this.notifyThis = null
+
+    // logs('Machine')
+    this.debounce = new Debounce()
+    this._init()
+  }
+
+  /**
+   * @returns {ScanMachine}
+   */
+  scan() {
+    if (!this.scanMachineClass) {
+      this.scanMachineClass = new ScanMachine(this, usbSerial)
+    }
+    return this.scanMachineClass
+  }
+
+  /**
+   * @returns {BmiMachine}
+   */
+  bmi() {
+    if (!this.bmiMachineClass) {
+      this.bmiMachineClass = new BmiMachine(this, usbSerial)
+    }
+    return this.bmiMachineClass
+  }
+
+  async open(types = []) {
+    // logs('open')
+    for (const k in types) {
+      let it = types[k]
+      console.log('it', it)
+      if (it == 1) {
+        // await this.scans()._init()
+      }
+    }
+    await sleep(1000)
+    this.getUsbList()
+  }
+
+  /**
+   * @param open      插入usb 或 拔出usb
+   */
+  async getUsbList(open = true) {
+    this.debounce.do('getUsbList', () => {
+      // logs('getUsbList1')
+      this.usbList = {};
+      this.usbNum = 0
+      let that = this
+      // #ifdef APP-PLUS
+      this.permission.list = {}
+      usbSerial.findSerialPortDevice((resp) => {
+        logs('getUsbList2', resp)
+        if (resp.devices) {
+          that.usbList = resp.devices;
+          that.usbNum = resp.devices.length
+          for (const key in this.usbList) {
+            let it = this.usbList[key]
+            // logs('it', it)
+            const {vendorId, productId} = it.device
+            it.k = `${vendorId}_${productId}`
+            it.id = usbConfigList[it.k]
+            // logs('k', k, it.key, usbConfigList[k])
+            if (usbConfigList[it.k]) {
+              let data = {
+                id: it.id,
+                k: it.k,
+                key: it.key,
+                vendorId,
+                productId,
+              }
+              this.permission.list[data.key] = data
+            } else {
+              showToast(`未知设备:${key}`)
+            }
+          }
+        }
+        // logs('this.usbList', this.usbList)
+        // logs('this.permission.list', this.permission.list)
+        // logs('this.permission.okList', this.permission.okList)
+        if (open) {
+          this.getPermission()
+        } else {
+          this.closeUsb()
+        }
+      });
+      // #endif
+    }, 800)
+
+  }
+
+
+  getOnlineUsb(type = 1) {
+    let list = this.permission.okList
+    if (type === 1) {
+      list = array_column(list, 'id')
+    }
+    return list
+  }
+
+
+  _init() {
+    // logs('machine _init')
+    // #ifdef APP-PLUS
+    usbSerial.registerReceiver((resp) => {
+      const action = resp.action;
+      switch (action) {
+        // USB授权结果
+        case "com.android.wrs.USB_PERMISSION":
+          const granted = resp.granted;
+          // showToast("USB授权结果:" + granted);
+          // logs(1, granted)
+          this.getPermission(granted ? 1 : 2)
+          break;
+        case "android.hardware.usb.action.USB_DEVICE_ATTACHED":
+          // logs(2)
+          // showToast("有USB设备连接");
+          this.getUsbList(true)
+          break;
+        case "android.hardware.usb.action.USB_DEVICE_DETACHED":
+          // showToast("USB设备断开连接");
+          this.getUsbList(false)
+          // logs(3, resp)
+          break;
+        default:
+          break;
+      }
+    });
+    this.getUsbList()
+    // #endif
+  }
+
+  async getPermission(type = 0) {
+    // logs('getPermission', type)
+    const l = Object.values(this.permission.list).length
+    // logs('getPermission', type)
+    if (l < 1) return false;
+    let key = this.permission.key
+    if (!key) {
+      key = Object.keys(this.permission.list)[0]
+      this.permission.key = key
+    }
+    // logs('key', key)
+    let item = this.permission.list[key]
+    // logs('getPermission2', this.permission.status, type, item)
+    let status = this.permission.status
+    // 已授权可跳出
+    if (this.permission.okList[item.key]) {
+      type = 3 // 已授权直接跳过
+      showToast(`已跳出 ${this[item.id]().title} 授权(重复)`, {
+        position: 'bottom'
+      })
+    }
+
+    if (type == 0 && status == 0) {
+      usbSerial.requestPermission({
+        key: item.key,
+      });
+      this[item.id]().key = item.key
+      this.permission.status = 1
+      return;
+    }
+    // 同意
+    if (type == 1) {
+      // logs('connect')
+      this[item.id]().auth = true
+      this[item.id]().connect()
+      // logs('connect1')
+      this.permission.okList.push({
+        key: item.key,
+        id: item.id,
+      })
+      // logs('connect2')
+      uni.$emit('machineUsb', {
+        id: item.id,
+        up: true,
+      })
+      // logs('connect3')
+    }
+    // 拒绝
+    if (type == 2) {
+      showToast(`拒绝了 ${this[item.id]().title} 授权,请重启软件再次授权`)
+      await sleep(1000)
+      uni.$emit('machineUsb', {
+        id: item.id,
+        up: false,
+      })
+    }
+    // logs('getPermissiongetPermission', type)
+    if (type != 0) {
+      delete this.permission.list[item.key]
+      this.permission.status = 0
+      this.permission.key = null
+      await this.getPermission(0)
+    }
+  }
+
+
+  closeUsb() {
+    // logs('closeUsb')
+    let newList = {}
+    if (this.usbList.length > 0) {
+      newList = array_column(this.usbList, 'id', 'key')
+    }
+    this.permission.okList = this.permission.okList.filter(it => {
+      if (!newList[it.key]) {
+        this[it.id]().close();
+        return false; // 过滤掉需要删除的元素
+      }
+      return true; // 保留不需要删除的元素
+    });
+
+    logs('closeUsb this.permission.okList', this.permission.okList)
+  }
+
+}
+
+

+ 184 - 0
utils/machine/machine03Class.js

@@ -0,0 +1,184 @@
+import {dataToHexHandle, orderSplit, orderToData} from '../ble/hex';
+import {logs, sleep} from "../util";
+import {showToast} from "../app";
+import {bleBase} from "@/utils/ble";
+import {ProtocolFormat03} from "@/utils/machine/manufacturerConfig";
+import {equimentConnectConfig} from "@/utils/machine/config";
+
+export class Machine03Class extends bleBase {
+
+  constructor(topClass) {
+    super(topClass)
+    /******************* 常规配置 *******************/
+    this.mType = 3
+    this.typeKey = 'machine03'
+    this.option = equimentConnectConfig[3]
+    /******************* 常规配置 *******************/
+    this.machine = {} // 设备蓝牙信息
+    this.machineInfo = {} // 网关信息
+
+    this.notify = false
+    this.notifyThis = null
+    this.init()
+
+    this.allMachine = {} // 所有设备地址
+    this.config = {
+      group: -1,
+      status: 0,
+      list: {
+        // init  0 未上线;1 已上线;2 错误;
+        // status   -1 未上线;0 待检测;1 被遮挡;2 触发;3 未安装;
+      },
+      track: {},
+    }
+    this.interval = 0
+  }
+
+  async watch(str) {
+    const {code, order} = orderSplit(str, ProtocolFormat03);
+    if (code != 'D1') logs('watch str', str)
+    // logs('code', code, order)
+    let result = order;
+    let acceptOrder = this.getAcceptOrder(code)
+    if (acceptOrder) result = orderToData(order, acceptOrder)
+    // logs('code', code)
+    // logs('acceptOrder', acceptOrder)
+    // logs('result', result)
+    let runThat = this.notify ? this.notifyThis : null
+    if (!runThat) return
+    switch (code) {
+
+
+      // 断线
+      case '99':
+        result = '设备断线了'
+        this.closeBle()
+        break
+
+      default:
+        console.log('未知内容', code, order)
+        break
+    }
+
+    return !0;
+  }
+
+
+  init() {
+    /* #ifdef H5 */
+    window.machine03 = async (str) => {
+      await this.watch(str)
+    }
+    /* #endif */
+
+    this.topClass.notificationFun[this.typeKey] = async ({str}) => {
+      await this.watch(str)
+    }
+    this.topClass.connectionStateFun[this.typeKey] = async () => {
+      await this.closeBle()
+      await this.watch('029900')
+    }
+  }
+
+
+  /**
+   * 连接机器
+   */
+  connectBle(machine) {
+    return new Promise(async (resolve, reject) => {
+      try {
+        if (!machine) throw '请确保设备 deviceId 不为空'
+        let {deviceId} = machine
+        uni.showLoading({
+          title: '正在连接',
+        })
+        await this.connectionBle(deviceId)
+        this.machine = machine
+        await sleep(1000)
+        // 连接并监听
+        logs('✔ 设备连接成功,可以开始监听')
+        uni.hideLoading()
+        return resolve()
+      } catch (error) {
+        console.error('connectBle', error)
+        await this.closeBle() // 失败断开并清除连接信息
+        uni.hideLoading()
+        showToast(error, 4000)
+        return reject()
+      }
+    })
+  }
+
+  async closeBle() {
+    await this.closeConnection()
+  }
+
+  /**
+   * @returns {string}
+   */
+  async sendCmd(cmd, data = null) {
+    const cmdMap = {
+      '07': '0207020000',
+      '14': () => {
+        return {
+          p: `02140500${dataToHexHandle(data.t, 8)}`,
+          o: data.o,
+        }
+      },
+    }
+    let result = cmdMap[cmd]
+    if (!result) return
+    if (typeof result === 'function') {
+      result = result(data);
+    }
+    // console.log('result', result)
+    if (!Array.isArray(result)) {
+      result = [result]
+    }
+    // 如果返回的是数组,则逐个加入队列
+    result.forEach(str => {
+      let d = {
+        t: 1,
+        p: '',
+        o: null,
+      }
+      if (typeof str == 'string') {
+        d.p = str
+      } else if (typeof str == 'object') {
+        d = Object.assign(d, str)
+      }
+      // this.sentOrder(d.p, d.t, d.o)
+      this.topClass.queueAdd({
+        mT: this.mType,
+        p: d.p,
+        o: d.o,
+      });
+    });
+    return true
+  }
+
+  getAcceptOrder(cmd) {
+    let order = {
+      '87': [
+        {k: 'battery'},
+        {k: 'k1'},
+        {k: 'group', l: 8},
+        {k: 'time', l: 8},
+      ],
+      '94': [
+        {k: 'time', l: 8},
+      ],
+      '97': [
+        {k: 'ok'},
+        {k: 'k1', l: 8},
+      ],
+      'D1': [
+        {k: 'k1'},
+        {k: 'time', l: 8},
+      ],
+    }
+    return order[cmd] || null
+  }
+
+
+}

+ 6 - 0
utils/machine/manufacturerConfig.js

@@ -0,0 +1,6 @@
+export const ProtocolFormat03 = [
+  {k: 'head', s: 0, e: 2},
+  {k: 'code', s: 2, e: 4},
+  {k: 'length', s: 4, e: 6},
+  {k: 'order', s: 6},
+]

+ 3 - 2
utils/request/index.js

@@ -154,9 +154,10 @@ $http.dataFactory = async res => {
     // 401也有可能是后端登录态到期, 所以要清空本地的登录状态
     useUserStore().logout()
     let beforePage = getBeforePage(0)
-    if (beforePage.route !== 'pages/index/init') {
+    console.log('beforePage', beforePage)
+    if (beforePage.route !== 'pages/index/load') {
       uni.redirectTo({
-        url: "pages/index/init"
+        url: "/pages/index/load"
       })
     }
   } else {

+ 34 - 7
utils/request/request.md

@@ -1,4 +1,5 @@
 # request请求、配置简单、批量上传图片、视频、超强适应性(支持多域名请求)
+
 1. 配置简单、源码清晰注释多、适用于一项目多域名请求、第三方请求、七牛云图片上传、本地服务器图片上传等等
 2. 支持请求`get`、`post`、`put`、`delete`
 3. 自动显示请求加载动画(可单个接口关闭)
@@ -13,18 +14,21 @@
 12. 支持上传文件进度监听
 13. 支持上传文件单张成功回调
 
-| `QQ交流群(607391225)`         | `微信交流群(加我好友备注"进群")`                  |
-| ----------------------------|--------------------------- |
-|![QQ交流群](http://qn.kemean.cn//upload/202004/14/15868301778472k7oubi6.png)|![微信交流群](https://qn.kemean.cn/upload/202010/13/weiXin_group_code.jpg)|
-| QQ群号:607391225 |微信号:zhou0612wei|
+| `QQ交流群(607391225)`                                                        | `微信交流群(加我好友备注"进群")`                                                   |
+|---------------------------------------------------------------------------|-----------------------------------------------------------------------|
+| ![QQ交流群](http://qn.kemean.cn//upload/202004/14/15868301778472k7oubi6.png) | ![微信交流群](https://qn.kemean.cn/upload/202010/13/weiXin_group_code.jpg) |
+| QQ群号:607391225                                                            | 微信号:zhou0612wei                                                       |
 
 ### [点击跳转-插件示例](https://ext.dcloud.net.cn/plugin?id=2009)
+
 ### [点击跳转-5年的web前端开源的uni-app快速开发模板-下载看文档](https://ext.dcloud.net.cn/plugin?id=2009)
 
 ### 常见问题
+
 1.接口请求成功了,没有返回数据或者数据是走的catch回调
 
-答:`requestConfig.js` 请求配置文件里面,有一个`$http.dataFactory`方法,里面写的只是参考示例,`此方法需要开发者根据各自的接口返回类型修改`
+答:`requestConfig.js` 请求配置文件里面,有一个`$http.dataFactory`
+方法,里面写的只是参考示例,`此方法需要开发者根据各自的接口返回类型修改`
 
 2.官方的方法有数据,本插件方法请求报错跨域问题
 
@@ -40,9 +44,11 @@
 
 5.接口请求成功了,一直提示“网络错误,请检查一下网络”?
 
-答:`requestConfig.js` 请求配置文件里面,有一个`$http.dataFactory`方法,里面写的只是参考示例,`此方法需要开发者根据各自的接口返回类型修改`
+答:`requestConfig.js` 请求配置文件里面,有一个`$http.dataFactory`
+方法,里面写的只是参考示例,`此方法需要开发者根据各自的接口返回类型修改`
 
 ### 本次更新注意事项
+
 1. 所有的headers都改成了header(和官方统一)
 2. 七牛云的获取token等信息提取到了`requestConfig.js`文件,参考如下
 
@@ -69,6 +75,7 @@ $http.getQnToken = function(callback){
 ```
 
 ### 文件说明
+
 1. `request => core` 请求方法的目录
 2. `request => core => request.js` 请求方法的class文件
 3. `request => core => utils.js` 请求方法的源码文件
@@ -76,16 +83,18 @@ $http.getQnToken = function(callback){
 5. `request => upload => upload.js` 上传方法的class文件
 6. `request => upload => utils.js` 上传方法源码文件
 7. `request => upload => qiniuUploader.js` 七牛云官方上传文件
-8. `request => index.js` 输出方法的文件
+8. `request => index_old.js` 输出方法的文件
 9. `requestConfig.js` 请求配置文件(具体看代码)
 
 ### 在main.js引入并挂在Vue上
+
 ```
 import $http from '@/zhouWei-request/requestConfig';
 Vue.prototype.$http = $http;
 ```
 
 ### `requestConfig.js`配置说明(requestConfig.js有配置示例)
+
 ```
 import request from "@/plugins/request";
 //可以new多个request来支持多个域名请求
@@ -232,6 +241,7 @@ $http.requestError = function (e) {
 ```
 
 ### 通用请求方法
+
 ```
 this.$http.request({
 	url: 'aid/region',
@@ -256,6 +266,7 @@ this.$http.request({
 ```
 
 ### get请求 正常写法
+
 ```
 this.$http.get('aid/region',{pid:0}).
 then(function (response) {
@@ -267,6 +278,7 @@ then(function (response) {
 ```
 
 ### post请求 async写法
+
 ```
 async request(){
 	let data = await this.$http.post('aid/region',{pid:0});
@@ -275,6 +287,7 @@ async request(){
 ```
 
 ### 其他功能配置项
+
 ```
 let data = await this.$http.post(
 	'http://www.aaa.com/aid/region', //可以直接放链接(将不启用全局定义域名)
@@ -293,6 +306,7 @@ let data = await this.$http.post(
 ```
 
 ### `requestConfig.js`可以设置服务器上传图片默认url
+
 ```
 //可以new多个request来支持多个域名请求
 let $http = new request({
@@ -302,6 +316,7 @@ let $http = new request({
 	defaultUploadUrl: "api/common/v1/upload_image",
 });
 ```
+
 ```
 // 上传可以不用传递url(使用全局的上传图片url)
 this.$http.urlImgUpload({
@@ -329,6 +344,7 @@ this.$http.urlFileUpload({
 ```
 
 ### 本地服务器图片上传(支持多张上传)
+
 ```
 this.$http.urlImgUpload('flie/upload',{
 	name:"后台接受文件key名称", //默认 file
@@ -356,7 +372,9 @@ this.$http.urlImgUpload('flie/upload',{
 	console.log("全部上传完返回结果:",res);
 });
 ```
+
 ### 本地服务器视频上传
+
 ```
 this.$http.urlVideoUpload('flie/upload',{
 	sourceType:"选择相机拍照或相册上传 默认两个都选",//默认 ['album','camera']
@@ -382,7 +400,9 @@ this.$http.urlVideoUpload('flie/upload',{
 	console.log("全部上传完返回结果:",res);
 });
 ```
+
 ### 本地服务器文件上传(支持多张上传)
+
 ```
 this.$http.urlFileUpload("flie/upload",{
 	files: [], // 必填 临时文件路径 格式: [{path: "图片地址"}]
@@ -407,6 +427,7 @@ this.$http.urlFileUpload("flie/upload",{
 ```
 
 ### 七牛云图片上传(支持多张上传)
+
 ```
 this.$http.qnImgUpload({
 	count:"最大选择数", // 默认 9
@@ -427,7 +448,9 @@ this.$http.qnImgUpload({
 	console.log("全部上传完返回结果:",res);
 });
 ```
+
 ### 七牛云视频上传
+
 ```
 this.$http.qnVideoUpload({
 	sourceType:"选择相机拍照或相册上传 默认两个都选",//默认 ['album','camera']
@@ -446,7 +469,9 @@ this.$http.qnVideoUpload({
 	console.log("全部上传完返回结果:",res);
 });
 ```
+
 ### 七牛云文件上传(支持多张上传)
+
 ```
 this.$http.qnFileUpload(
 {
@@ -463,7 +488,9 @@ this.$http.qnFileUpload(
 	console.log("全部上传完返回结果:",res);
 });
 ```
+
 ### jsonp 跨域请求(只支持H5)
+
 ```
 let data = await this.$http.jsonp('http://www.aaa.com/aid/region',{pid:0}, {
     isFactory: false, //(默认 true 说明:本接口是否调用公共的数据处理方法,设置false后isPrompt参数奖失去作用)

+ 120 - 94
utils/uniFunction.js

@@ -1,11 +1,15 @@
 import {confirmModal} from "./app";
-import {objectToStr, promisify, sleep, strToObject} from "@/utils/util";
+import {logs, objectToStr, strToObject} from "@/utils/util";
 import {_openAdapter} from "@/utils/ble/tools";
-import platfrom from "@/utils/platform";
+
+let isIos
+// #ifdef APP-PLUS
+isIos = (plus.os.name == "iOS")
+// #endif
 
 export const globalPageMeta = () => {
   return {
-    pageStyle: `--statusBarHeight:${uni.$u.sys().statusBarHeight}px;--status-bar-height:${uni.$u.sys().statusBarHeight}px !important;`,
+    pageStyle: `--statusBarHeight:${uni.$u.sys().statusBarHeight}px;--status-bar-height:${uni.$u.sys().statusBarHeight}px !important;min-height:100vh;`,
   }
 }
 
@@ -23,8 +27,20 @@ export const deletePageStyle = (str = '', keyArr = []) => {
   return objectToStr(arr)
 }
 
-export const getNetworkType = () => {
-  return promisify(uni.getNetworkType)
+
+/**
+ * 对微信接口的promise封装
+ * @param {function} fn
+ * @param {object} args
+ */
+export const promisify = (fn, args) => {
+  return new Promise((resolve, reject) => {
+    fn({
+      ...(args || {}),
+      success: (res) => resolve(res),
+      fail: (err) => reject(err),
+    });
+  });
 }
 
 /**
@@ -73,76 +89,82 @@ export function authorize(scope) {
     scope,
   }).then(() => {
     return true
-  }).catch((e) => {
-    throw '用户拒绝了授权'
+  }, (e) => {
+    console.error('authorize', e)
+    return false
   })
 }
 
-export const getBluetoothStatus = async (open = true) => {
-  let bluetoothEnabled = false
-  switch (platfrom) {
-    case "APP":
-      const BluetoothAdapter = plus.android.importClass('android.bluetooth.BluetoothAdapter'); // 引入Java 蓝牙类
-      const blueadapter = BluetoothAdapter.getDefaultAdapter(); //拿到默认蓝牙适配器方法
-      bluetoothEnabled = blueadapter.isEnabled()
-      if (!bluetoothEnabled && open) {
-        blueadapter.enable()
-        uni.showLoading('请稍等蓝牙初始化中~~~')
-        await sleep(2000)
-        await _openAdapter()
-        uni.hideLoading()
-      }
-      break;
-    default:
-      const res = await getSystemInfo()
-      bluetoothEnabled = res.bluetoothEnabled
-      if (!bluetoothEnabled && open) {
-        throw '请检查系统蓝牙是否已开启'
-      }
-      if (bluetoothEnabled) bluetoothEnabled = await checkWeiXinAuth('bluetooth', open, '蓝牙')
-      break;
+export const isBluetoothEnabled = async () => {
+  // #ifdef MP
+  let res = {
+    bluetoothEnabled: false
   }
-  return bluetoothEnabled
-}
-
-
-export const getLocationStatus = async (open = true, auth = false) => {
-  let locationEnabled = false
-  switch (platfrom) {
-    case "APP":
-      const context = plus.android.importClass("android.content.Context");
-      const locationManager = plus.android.importClass("android.location.LocationManager");
-      const main = plus.android.runtimeMainActivity();
-      const mainSvr = main.getSystemService(context.LOCATION_SERVICE);
-      locationEnabled = mainSvr.isProviderEnabled(locationManager.GPS_PROVIDER)
-      if (!locationEnabled && open) {
-        await confirmModal('请打开定位服务功能', {
-          showCancel: false, // 不显示取消按钮
-        }).then(() => {
-          if (!mainSvr.isProviderEnabled(locationManager.GPS_PROVIDER)) {
-            const Intent = plus.android.importClass('android.content.Intent');
-            const Settings = plus.android.importClass('android.provider.Settings');
-            const intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
-            main.startActivity(intent); // 打开系统设置GPS服务页面
-          }
-        }, () => {
-          throw '请打开定位服务功能'
-        })
-      }
-      break;
-    default:
-      const res = await getSystemInfo()
-      locationEnabled = res.locationEnabled
-      if (!res.locationEnabled && open) throw '请检查系统定位是否已开启'
-      break;
+
+  // #ifdef MP-WEIXIN
+  res = uni.getSystemSetting()
+  // #endif
+
+  // #ifndef MP-WEIXIN
+  res = uni.getSystemInfoSync()
+  // #endif
+
+  return res.bluetoothEnabled
+  // #endif
+
+  // #ifdef APP-PLUS
+  if (!isIos) {
+    const BluetoothAdapter = plus.android.importClass('android.bluetooth.BluetoothAdapter');
+    const bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+    if (bluetoothAdapter != null) { // 判断设备是否支持蓝牙
+      return bluetoothAdapter.isEnabled();
+    } else {
+      console.log('该设备不支持蓝牙');
+      return false;
+    }
   }
-  return locationEnabled
+  // #endif
+}
+
+async function checkBluetoothPermission() {
+  // #ifdef MP
+  return await checkWeiXinAuth('bluetooth', true, '蓝牙')
+  // #endif
+
+  // #ifdef APP-PLUS
+  if (!isIos) {
+    const Context = plus.android.importClass("android.content.Context");
+    const ActivityCompat = plus.android.importClass("androidx.core.app.ActivityCompat");
+    const PackageManager = plus.android.importClass("android.content.pm.PackageManager");
+    const activity = plus.android.runtimeMainActivity();
+
+    const hasPermission = ActivityCompat.checkSelfPermission(activity, "android.permission.ACCESS_FINE_LOCATION") === PackageManager.PERMISSION_GRANTED ||
+      ActivityCompat.checkSelfPermission(activity, "android.permission.ACCESS_COARSE_LOCATION") === PackageManager.PERMISSION_GRANTED;
+
+    if (!hasPermission) {
+      console.log('没有蓝牙权限,需要请求权限');
+      // 请求权限的代码
+      const permissions = ["android.permission.ACCESS_FINE_LOCATION", "android.permission.ACCESS_COARSE_LOCATION"];
+      ActivityCompat.requestPermissions(activity, permissions, 1); // 1是请求码,根据需要自定义
+      throw '未授权蓝牙,请前往授权'
+    } else {
+      return true;
+    }
+  }
+  // #endif
 }
 
 
 export const checkBleAuth = async () => {
-  await getBluetoothStatus(true)
-  await getLocationStatus(true)
+  // 蓝牙是否开启并授权
+  let bluetoothEnabled = await isBluetoothEnabled()
+  if (!bluetoothEnabled) throw '请检查系统蓝牙是否已开启'
+  await checkBluetoothPermission()
+
+  // 定位是否开启
+  let locationEnabled = await isLocationServiceEnabled()
+  if (!locationEnabled) throw '请检查系统定位是否已开启'
+  return true
 }
 
 
@@ -154,38 +176,40 @@ export const checkWeiXinAuth = async (auth, openSet = false, keyword = '') => {
     //'scope.*'属性存在,且为false
     result = settingData.authSetting[`scope.${auth}`]
   }
-  if (!result) {
-    if (openSet) {
-      await confirmModal(`请确认是否已开启${keyword}授权`, {
-        confirmText: '去授权',
-      }).then(async () => {
-        await openSetting()
-        await authorize(`scope.${auth}`)
-        if (auth == 'bluetooth') await _openAdapter()
-      }).catch(() => {
-        throw `用户拒绝了${keyword}授权`
-      })
-    } else {
-      return result
+  if (result || !openSet) return result
+  result = await authorize(`scope.${auth}`)
+  if (result) return result
+  await confirmModal(`请确认是否已开启${keyword}授权`, {
+    confirmText: '去授权',
+  }).then(async () => {
+    let res = await openSetting()
+    result = res.authSetting[`scope.${auth}`]
+    if (!result) {
+      throw `用户不同意${keyword}授权`
     }
-  }
+    if (auth == 'bluetooth') await _openAdapter()
+  }, () => {
+    throw `用户拒绝了${keyword}授权`
+  })
   return result
 }
 
-export const getLocation = async () => {
-  return new Promise(async (resolve, reject) => {
-    let result = {
-      lng: 0,
-      lat: 0,
-    }
-    promisify(uni.getLocation).then(({longitude, latitude}) => {
-      result.lng = longitude
-      result.lat = latitude
-      resolve(result)
-    }).catch(() => {
-      resolve(result)
-    })
-  })
+async function isLocationServiceEnabled() {
+  // #ifdef MP
+  const res = await getSystemInfo()
+  return res.locationEnabled
+  // #endif
+
+  // #ifdef APP-PLUS
+  if (!isIos) {
+    const context = plus.android.importClass("android.content.Context");
+    const LocationManager = plus.android.importClass("android.location.LocationManager");
+    const locationManager = plus.android.runtimeMainActivity().getSystemService(context.LOCATION_SERVICE);
+    const isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
+    const isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
+    return isGpsEnabled || isNetworkEnabled;
+  }
+  // #endif
 }
 
 export const makePhoneCall = (tel = '') => {
@@ -223,6 +247,8 @@ export const getDomInfo = (obj, selector, type = 1) => {
           resolve(res)
         }).exec()
         break
+      case 3:
+        resolve(div)
     }
   })
 }