huangyongcong il y a 1 an
Parent
commit
567d08dc7a
43 fichiers modifiés avec 2519 ajouts et 193 suppressions
  1. 1 0
      .gitignore
  2. 9 3
      App.vue
  3. 1 0
      css/btn.scss
  4. 0 1
      main.js
  5. 146 140
      manifest.json
  6. 14 10
      manifestTemp.json
  7. 2 1
      package.json
  8. 3 2
      pages.json
  9. 124 12
      pages/index/index.vue
  10. 1 1
      static/iconfont/iconfont.css
  11. 0 3
      store/useUserStore.js
  12. 2 0
      uni_modules/uv-datetime-picker/changelog.md
  13. 6 3
      uni_modules/uv-datetime-picker/components/uv-datetime-picker/uv-datetime-picker.vue
  14. 1 1
      uni_modules/uv-datetime-picker/package.json
  15. 35 0
      uni_modules/wrs-js-modbusCRCHex/changelog.md
  16. 233 0
      uni_modules/wrs-js-modbusCRCHex/js_sdk/wrs-ASCIIUtils.js
  17. 18 0
      uni_modules/wrs-js-modbusCRCHex/js_sdk/wrs-Base64Utils.js
  18. 92 0
      uni_modules/wrs-js-modbusCRCHex/js_sdk/wrs-ByteUtils.js
  19. 154 0
      uni_modules/wrs-js-modbusCRCHex/js_sdk/wrs-CRCUtils.js
  20. 102 0
      uni_modules/wrs-js-modbusCRCHex/js_sdk/wrs-HexUtils.js
  21. 50 0
      uni_modules/wrs-js-modbusCRCHex/js_sdk/wrs-ISType.js
  22. 114 0
      uni_modules/wrs-js-modbusCRCHex/js_sdk/wrs-IntUtils.js
  23. 132 0
      uni_modules/wrs-js-modbusCRCHex/js_sdk/wrs-ModbusUtils.js
  24. 86 0
      uni_modules/wrs-js-modbusCRCHex/package.json
  25. 355 0
      uni_modules/wrs-js-modbusCRCHex/readme.md
  26. 12 0
      uni_modules/wrs-uts-usbmanager/changelog.md
  27. 2 0
      uni_modules/wrs-uts-usbmanager/encrypt
  28. 84 0
      uni_modules/wrs-uts-usbmanager/package.json
  29. 92 0
      uni_modules/wrs-uts-usbmanager/readme.md
  30. 3 0
      uni_modules/wrs-uts-usbmanager/utssdk/app-android/config.json
  31. BIN
      uni_modules/wrs-uts-usbmanager/utssdk/app-android/index.uts
  32. BIN
      uni_modules/wrs-uts-usbmanager/utssdk/app-ios/index.uts
  33. 9 2
      utils/app.js
  34. 13 1
      utils/ble/hex.js
  35. 1 1
      utils/bootstrap.js
  36. 59 0
      utils/machine/bmiMachine.js
  37. 6 0
      utils/machine/config.js
  38. 243 0
      utils/machine/index.js
  39. 34 0
      utils/machine/scanMachine.js
  40. 234 0
      utils/usbSerial/base.js
  41. 15 0
      utils/usbSerial/readme.md
  42. 21 9
      utils/util.js
  43. 10 3
      vite.config.js

+ 1 - 0
.gitignore

@@ -2,3 +2,4 @@
 /unpackage/
 /node_modules/
 /package-lock.json
+manifest.json

+ 9 - 3
App.vue

@@ -1,13 +1,19 @@
 <script>
+import {Machine} from "@/utils/machine";
+import {provide} from "vue";
+
 export default {
   onLaunch: function () {
-    console.log('App Launch')
+    const $machine = new Machine()
+    provide('$machine', $machine);
+
+    // console.log('App Launch')
   },
   onShow: function () {
-    console.log('App Show')
+    // console.log('App Show')
   },
   onHide: function () {
-    console.log('App Hide')
+    // console.log('App Hide')
   }
 }
 </script>

+ 1 - 0
css/btn.scss

@@ -19,6 +19,7 @@
   vertical-align: middle;
   font-size: 27rpx;
   border-radius: 5px;
+  padding: 0 20rpx;
 
   &-small {
     padding: 12rpx 21rpx;

+ 0 - 1
main.js

@@ -29,6 +29,5 @@ export function createApp() {
 
   return {
     app,
-    Pinia,
   }
 }

+ 146 - 140
manifest.json

@@ -1,147 +1,153 @@
 {
-  "name": "bmi-app",
-  "appid": "__UNI__1E3B7BA",
-  "description": "",
-  "versionName": "1.0.0",
-  "versionCode": "100",
-  "transformPx": false,
-  /* 5+App特有相关 */
-  "app-plus": {
-    "usingComponents": true,
-    "nvueStyleCompiler": "uni-app",
-    "compilerVersion": 3,
-    "splashscreen": {
-      "alwaysShowBeforeRender": true,
-      "waiting": true,
-      "autoclose": true,
-      "delay": 0
-    },
-    /* 模块配置 */
-    "modules": {
-      "Bluetooth": {},
-      "Camera": {},
-      "VideoPlayer": {},
-      "SQLite": {}
-    },
-    /* 应用发布信息 */
-    "distribute": {
-      /* android打包配置 */
-      "android": {
-        "permissions": [
-          "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
-          "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
-          "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
-          "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
-          "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
-          "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
-          "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
-          "<uses-permission android:name=\"android.permission.CAMERA\"/>",
-          "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
-          "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
-          "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
-          "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
-          "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
-          "<uses-feature android:name=\"android.hardware.camera\"/>",
-          "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
-        ]
-      },
-      /* ios打包配置 */
-      "ios": {},
-      /* SDK配置 */
-      "sdkConfigs": {},
-      "icons": {
-        "android": {
-          "ldpi": "unpackage/res/icons/48x48.png",
-          "mdpi": "unpackage/res/icons/48x48.png",
-          "hdpi": "unpackage/res/icons/72x72.png",
-          "xhdpi": "unpackage/res/icons/96x96.png",
-          "xxhdpi": "unpackage/res/icons/144x144.png",
-          "xxxhdpi": "unpackage/res/icons/192x192.png"
+    "name" : "bmi-app",
+    "appid" : "__UNI__1E3B7BA",
+    "description" : "",
+    "versionName" : "1.0.0",
+    "versionCode" : 100,
+    "transformPx" : false,
+    /* 5+App特有相关 */
+    "app-plus" : {
+        "usingComponents" : true,
+        "nvueStyleCompiler" : "uni-app",
+        "compilerVersion" : 3,
+        "splashscreen" : {
+            "alwaysShowBeforeRender" : true,
+            "waiting" : true,
+            "autoclose" : true,
+            "delay" : 0
+        },
+        /* 模块配置 */
+        "modules" : {
+            "Bluetooth" : {},
+            "Camera" : {},
+            "VideoPlayer" : {},
+            "SQLite" : {}
+        },
+        /* 应用发布信息 */
+        "distribute" : {
+            /* android打包配置 */
+            "android" : {
+                "permissions" : [
+                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+                    "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
+                    "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+                    "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera\"/>",
+                    "<uses-feature android:name=\"android.hardware.usb.host\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>",
+                    "<uses-permission android:name=\"android.permission.USB_PERMISSION\"/>"
+                ]
+            },
+            /* ios打包配置 */
+            "ios" : {
+                "dSYMs" : false
+            },
+            /* SDK配置 */
+            "sdkConfigs" : {
+                "ad" : {}
+            },
+            "icons" : {
+                "android" : {
+                    "ldpi" : "unpackage/res/icons/48x48.png",
+                    "mdpi" : "unpackage/res/icons/48x48.png",
+                    "hdpi" : "unpackage/res/icons/72x72.png",
+                    "xhdpi" : "unpackage/res/icons/96x96.png",
+                    "xxhdpi" : "unpackage/res/icons/144x144.png",
+                    "xxxhdpi" : "unpackage/res/icons/192x192.png"
+                },
+                "ios" : {
+                    "appstore" : "unpackage/res/icons/1024x1024.png",
+                    "ipad" : {
+                        "app" : "unpackage/res/icons/76x76.png",
+                        "app@2x" : "unpackage/res/icons/152x152.png",
+                        "notification" : "unpackage/res/icons/20x20.png",
+                        "notification@2x" : "unpackage/res/icons/40x40.png",
+                        "proapp@2x" : "unpackage/res/icons/167x167.png",
+                        "settings" : "unpackage/res/icons/29x29.png",
+                        "settings@2x" : "unpackage/res/icons/58x58.png",
+                        "spotlight" : "unpackage/res/icons/40x40.png",
+                        "spotlight@2x" : "unpackage/res/icons/80x80.png"
+                    },
+                    "iphone" : {
+                        "app@2x" : "unpackage/res/icons/120x120.png",
+                        "app@3x" : "unpackage/res/icons/180x180.png",
+                        "notification@2x" : "unpackage/res/icons/40x40.png",
+                        "notification@3x" : "unpackage/res/icons/60x60.png",
+                        "settings@2x" : "unpackage/res/icons/58x58.png",
+                        "settings@3x" : "unpackage/res/icons/87x87.png",
+                        "spotlight@2x" : "unpackage/res/icons/80x80.png",
+                        "spotlight@3x" : "unpackage/res/icons/120x120.png"
+                    }
+                }
+            }
         },
-        "ios": {
-          "appstore": "unpackage/res/icons/1024x1024.png",
-          "ipad": {
-            "app": "unpackage/res/icons/76x76.png",
-            "app@2x": "unpackage/res/icons/152x152.png",
-            "notification": "unpackage/res/icons/20x20.png",
-            "notification@2x": "unpackage/res/icons/40x40.png",
-            "proapp@2x": "unpackage/res/icons/167x167.png",
-            "settings": "unpackage/res/icons/29x29.png",
-            "settings@2x": "unpackage/res/icons/58x58.png",
-            "spotlight": "unpackage/res/icons/40x40.png",
-            "spotlight@2x": "unpackage/res/icons/80x80.png"
-          },
-          "iphone": {
-            "app@2x": "unpackage/res/icons/120x120.png",
-            "app@3x": "unpackage/res/icons/180x180.png",
-            "notification@2x": "unpackage/res/icons/40x40.png",
-            "notification@3x": "unpackage/res/icons/60x60.png",
-            "settings@2x": "unpackage/res/icons/58x58.png",
-            "settings@3x": "unpackage/res/icons/87x87.png",
-            "spotlight@2x": "unpackage/res/icons/80x80.png",
-            "spotlight@3x": "unpackage/res/icons/120x120.png"
-          }
+        "nativePlugins" : {
+            "Aq-ChooseFile" : {
+                "__plugin_info__" : {
+                    "name" : "文件选择,支持自定义路径,自定义筛选类型,多选",
+                    "description" : "支持android 11(30)文件选择,支持自定义路径",
+                    "platforms" : "Android",
+                    "url" : "https://ext.dcloud.net.cn/plugin?id=5263",
+                    "android_package_name" : "",
+                    "ios_bundle_id" : "",
+                    "isCloud" : true,
+                    "bought" : 1,
+                    "pid" : "5263",
+                    "parameters" : {}
+                }
+            },
+            "wrs-usbSerial" : {
+                "__plugin_info__" : {
+                    "name" : "OTG USB串口、CP210X、CDC、FTDI、PL2303、CH34X等 - [试用版,仅用于自定义调试基座]",
+                    "description" : "android OTG USB串口通讯,无需root权限系统,串口参数支持波特率、数据位、校验位、停止位、流控,支持CP210X、CDC、FTDI、PL2303、CH34X、CP2130 SPI-US",
+                    "platforms" : "Android",
+                    "url" : "https://ext.dcloud.net.cn/plugin?id=12157",
+                    "android_package_name" : "",
+                    "ios_bundle_id" : "",
+                    "isCloud" : true,
+                    "bought" : 0,
+                    "pid" : "12157",
+                    "parameters" : {}
+                }
+            }
         }
-      }
     },
-    "nativePlugins": {
-      "Aq-ChooseFile": {
-        "__plugin_info__": {
-          "name": "文件选择,支持自定义路径,自定义筛选类型,多选",
-          "description": "支持android 11(30)文件选择,支持自定义路径",
-          "platforms": "Android",
-          "url": "https://ext.dcloud.net.cn/plugin?id=5263",
-          "android_package_name": "",
-          "ios_bundle_id": "",
-          "isCloud": true,
-          "bought": 1,
-          "pid": "5263",
-          "parameters": {}
-        }
-      },
-      "Fvv-UniSerialPort": {
-        "__plugin_info__": {
-          "name": "安卓串口通信 Fvv-UniSerialPort",
-          "description": "Android平台串口通信插件,支持串口号、波特率、数据位、校验位、停止位、流控等参数设置",
-          "platforms": "Android",
-          "url": "https://ext.dcloud.net.cn/plugin?id=1787",
-          "android_package_name": "",
-          "ios_bundle_id": "",
-          "isCloud": true,
-          "bought": 1,
-          "pid": "1787",
-          "parameters": {}
-        }
-      }
-    }
-  },
-  /* 快应用特有相关 */
-  "quickapp": {},
-  /* 小程序特有相关 */
-  "mp-weixin": {
-    "appid": "",
-    "setting": {
-      "urlCheck": false
+    /* 快应用特有相关 */
+    "quickapp" : {},
+    /* 小程序特有相关 */
+    "mp-weixin" : {
+        "appid" : "",
+        "setting" : {
+            "urlCheck" : false
+        },
+        "usingComponents" : true
+    },
+    "mp-alipay" : {
+        "usingComponents" : true
+    },
+    "mp-baidu" : {
+        "usingComponents" : true
     },
-    "usingComponents": true
-  },
-  "mp-alipay": {
-    "usingComponents": true
-  },
-  "mp-baidu": {
-    "usingComponents": true
-  },
-  "mp-toutiao": {
-    "usingComponents": true
-  },
-  "uniStatistics": {
-    "enable": false
-  },
-  "vueVersion": "3",
-  "h5": {
-    "title": "BMI",
-    "devServer": {
-      "disableHostCheck": true
+    "mp-toutiao" : {
+        "usingComponents" : true
+    },
+    "uniStatistics" : {
+        "enable" : false
+    },
+    "vueVersion" : "3",
+    "h5" : {
+        "title" : "BMI",
+        "devServer" : {
+            "disableHostCheck" : true
+        }
     }
-  }
 }

+ 14 - 10
manifestTemp.json

@@ -2,8 +2,8 @@
   "name": "bmi-app",
   "appid": "__UNI__1E3B7BA",
   "description": "",
-  "versionName": "1.0.0",
-  "versionCode": "100",
+  "versionName": "1.0.1",
+  "versionCode": 101,
   "transformPx": false,
   /* 5+App特有相关 */
   "app-plus": {
@@ -46,9 +46,13 @@
         ]
       },
       /* ios打包配置 */
-      "ios": {},
+      "ios": {
+        "dSYMs": false
+      },
       /* SDK配置 */
-      "sdkConfigs": {},
+      "sdkConfigs": {
+        "ad": {}
+      },
       "icons": {
         "android": {
           "ldpi": "unpackage/res/icons/48x48.png",
@@ -99,17 +103,17 @@
           "parameters": {}
         }
       },
-      "Fvv-UniSerialPort": {
+      "wrs-usbSerial": {
         "__plugin_info__": {
-          "name": "安卓串口通信 Fvv-UniSerialPort",
-          "description": "Android平台串口通信插件,支持串口号、波特率、数据位、校验位、停止位、流控等参数设置",
+          "name": "OTG USB串口、CP210X、CDC、FTDI、PL2303、CH34X等 - [试用版,仅用于自定义调试基座]",
+          "description": "android OTG USB串口通讯,无需root权限系统,串口参数支持波特率、数据位、校验位、停止位、流控,支持CP210X、CDC、FTDI、PL2303、CH34X、CP2130 SPI-US",
           "platforms": "Android",
-          "url": "https://ext.dcloud.net.cn/plugin?id=1787",
+          "url": "https://ext.dcloud.net.cn/plugin?id=12157",
           "android_package_name": "",
           "ios_bundle_id": "",
           "isCloud": true,
-          "bought": 1,
-          "pid": "1787",
+          "bought": 0,
+          "pid": "12157",
           "parameters": {}
         }
       }

+ 2 - 1
package.json

@@ -24,6 +24,7 @@
     }
   },
   "devDependencies": {
-    "pinia": "^2.1.7"
+    "pinia": "^2.1.7",
+    "vue": "^3.4.21"
   }
 }

+ 3 - 2
pages.json

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

+ 124 - 12
pages/index/index.vue

@@ -1,31 +1,83 @@
 <template>
   <view class="window-box">
     <ly-back :showBack="false"/>
-    <view class="search w100 h100 flex-center-center main">
-      <view class="w60 h60 bg2 flex-center-center flex-wrap flex-dir-column">
-        <view>请将卡片放入感应区</view>
-        <view >
-          <uv-image :src="pD.imgUrl+ '/index-card.png'" width="500px" height="306px"></uv-image>
+    <view class="search w100 h100 flex-center-center main flex-dir-column">
+      <view class="" @click="getListHandle">测验机器</view>
+      <br>
+      <br>
+      <br>
+      <view class="flex-between-center w50">
+        <view class="w50 flex-center-center">
+          <view :class="[machine.scan?'btn-primary':'btn-info']" class="btn">
+            扫码器
+            <uv-icon v-if="machine.scan" color="#FFF" name="checkbox-mark" size="28"/>
+          </view>
         </view>
+        <view class="w50 flex-center-center">
+          <view :class="[machine.bmi?'btn-primary':'btn-info']" class="btn">
+            体重秤
+            <uv-icon v-if="machine.bmi" color="#FFF" name="checkbox-mark" size="28"/>
+          </view>
+        </view>
+      </view>
+      <br>
+      <br>
+      <view class="flex-start-center">
+        卡号:
+        <view class="col-checked">{{ pD.value1 || '--' }}</view>
+      </view>
+      <br>
+      <view class="flex-start-center">
+        身高:
+        <view class="col-checked">{{ pD.value3 || '0' }}</view>
+        cm
       </view>
-      <view class="btn btn-primary" @click="search">扫码</view>
-      <view class="btn btn-primary" @click="next">下一页</view>
+      <view class="flex-start-center">
+        体重:
+        <view class="col-checked">{{ pD.value2 || '0' }}</view>
+        kg
+      </view>
+
+
+      <!--      <view class="" :class="{'col-green':}"></view>-->
+
+      <!--      <view class="w60 h60 bg2 flex-center-center flex-wrap flex-dir-column">-->
+      <!--        <view>请将卡片放入感应区</view>-->
+      <!--        <view >-->
+      <!--          <uv-image :src="pD.imgUrl+ '/index-card.png'" width="500px" height="306px"></uv-image>-->
+      <!--        </view>-->
+      <!--      </view>-->
+      <!--      <view class="btn btn-primary" @click="search">扫码</view>-->
+      <!--      <view class="btn btn-primary" @click="next">下一页</view>-->
       <!--      <view class="btn btn-primary" @click="toSelect">手动选择</view>-->
     </view>
   </view>
 </template>
 
 <script setup>
-import {reactive} from "vue";
+import {getCurrentInstance, inject, onActivated, onBeforeUnmount, onMounted, reactive} from "vue";
+import {onShow, onHide} from "@dcloudio/uni-app";
 import {navTo, showToast} from "@/utils/app";
 import {cradToStudentInfo} from "@/api/student";
 import storage from "@/utils/storage";
+import {getAllMethods, logs, sleep} from "@/utils/util";
+import * as ASCIIUtils from "@/uni_modules/wrs-js-modbusCRCHex/js_sdk/wrs-ASCIIUtils";
+import * as HexUtils from "@/uni_modules/wrs-js-modbusCRCHex/js_sdk/wrs-HexUtils";
+import {orderToData} from "@/utils/ble/hex";
+
+const $machine = inject('$machine')
 
 const pD = reactive({
   title: '学生未激活',
   select: 0,
   selectMax: 1,
-  imgUrl:'/static',
+  imgUrl: '/static',
+  value1: '',
+  value2: '',
+})
+const machine = reactive({
+  scan: false,
+  bmi: false,
 })
 const queryForm = reactive({
   student_id: 0,
@@ -45,18 +97,76 @@ const search = async () => {
   }
   // navTo('pages/task/info')
 }
-const next = ()=>{
+
+const next = () => {
   navTo('pages/task/info', {
     id: queryForm.student_id,
   })
 }
+
 const toSelect = () => {
   navTo('pages/classes/select')
 }
+
+const getListHandle = () => {
+  // console.log('getListHandle')
+  $machine.getUsbList(true)
+}
+
+const scanWatch = (res) => {
+  console.log('scanWatch123', res)
+  pD.value1 = res.value
+}
+
+const bmiWatch = (res) => {
+  console.log('bmiWatch123', res)
+  pD.value2 = res.kg
+  pD.value3 = res.cm
+}
+
+const notifyMachineUsb = ({id, up}) => {
+  machine[id] = up
+}
+
+const setWatch = (open = false) => {
+  if (open) {
+    $machine.scan().setWatch(scanWatch)
+    $machine.bmi().setWatch(bmiWatch)
+  } else {
+    $machine.scan().setWatch(null)
+    $machine.bmi().setWatch(null)
+  }
+}
+
+
+// 挂载完成之后
+onMounted(async (r) => {
+  // console.log('index onMounted')
+  uni.$on('machineUsb', notifyMachineUsb)
+  // getListHandle()
+})
+
+onShow(async () => {
+  setWatch(true)
+})
+
+onHide(async () => {
+  setWatch()
+})
+// 页面卸载前
+onBeforeUnmount(() => {
+  setWatch()
+  uni.$off('machineUsb', notifyMachineUsb)
+})
+defineExpose({})
+
+// 激活页面时
+onActivated(async () => {
+})
 </script>
 
 <style lang="scss" scoped>
-.main{
+.main {
   background-image: url('static/image/index-bg.png');
   width: 100%;
   height: 100%;
@@ -64,7 +174,8 @@ const toSelect = () => {
   background-size: 100%;
   background-repeat: no-repeat;
 }
-.bg2{
+
+.bg2 {
   background-image: url('static/image/index-bg2.png');
   width: 80%;
   height: 80%;
@@ -72,6 +183,7 @@ const toSelect = () => {
   background-size: 100%;
   background-repeat: no-repeat;
 }
+
 .info-item {
   display: flex;
   align-items: center;

+ 1 - 1
static/iconfont/iconfont.css

@@ -1,6 +1,6 @@
 @font-face {
   font-family: "icon"; /* Project id 4463540 */
-  src: url('/static/iconfont/iconfont.ttf?t=1710230317828') format('truetype');
+  src: url('./iconfont.ttf?t=1710230317828') format('truetype');
 }
 
 .icon {

+ 0 - 3
store/useUserStore.js

@@ -10,7 +10,6 @@ export const useUserStore = defineStore({
   getters: {},
   actions: {
     _init() {
-      console.log('user _init')
       this.checkLogin()
       this.getMachineInfo()
     },
@@ -25,9 +24,7 @@ export const useUserStore = defineStore({
       this.token = null
     },
     getMachineInfo() {
-      console.log('132')
       this.mac = '123'
-      console.log('456')
     },
   }
 })

+ 2 - 0
uni_modules/uv-datetime-picker/changelog.md

@@ -1,3 +1,5 @@
+## 1.0.13(2024-03-22)
+1. 修复VUE3中出现的BUG
 ## 1.0.12(2023-11-27)
 1. 增加round圆角属性
 ## 1.0.11(2023-10-11)

+ 6 - 3
uni_modules/uv-datetime-picker/components/uv-datetime-picker/uv-datetime-picker.vue

@@ -13,11 +13,11 @@
 		:confirmText="confirmText"
 		:cancelColor="cancelColor"
 		:confirmColor="confirmColor"
+		:round="round"
 		@close="close"
 		@cancel="cancel"
 		@confirm="confirm"
 		@change="change"
-		:round="round"
 	>
 	</uv-picker>
 </template>
@@ -106,8 +106,11 @@
 			},
 			open() {
 				this.$refs.picker.open();
-				this.getValue();
-				this.updateColumnValue(this.innerValue);
+				// 解决打开的前一次和当前日期错乱的BUG
+				setTimeout(()=>{
+					this.getValue();
+					this.updateColumnValue(this.innerValue);
+				},10)
 			},
 			close() {
 				this.$emit('close');

+ 1 - 1
uni_modules/uv-datetime-picker/package.json

@@ -1,7 +1,7 @@
 {
   "id": "uv-datetime-picker",
   "displayName": "uv-datetime-picker 时间选择器 全面兼容vue3+2、app、h5、小程序等多端",
-  "version": "1.0.12",
+  "version": "1.0.13",
   "description": "时间选择器组件用于时间日期,主要用于年月日时分的选择,具体选择的精确度由参数控制。",
   "keywords": [
     "datetime-picker",

+ 35 - 0
uni_modules/wrs-js-modbusCRCHex/changelog.md

@@ -0,0 +1,35 @@
+## 1.0.21(2024-04-02)
+1. 十进制转二进制时,不够8位前面补0
+## 1.0.20(2023-10-11)
+1. utf8增加兼容性
+## 1.0.19(2023-10-11)
+优化
+## 1.0.18(2023-09-26)
+1. 增加CRC32
+## 1.0.17(2023-09-12)
+1. 修复ASCII解码时某些特殊中文错误问题
+## 1.0.16(2023-07-26)
+1. 增加十六进制字符串与Uint8Array之间的转换
+## 1.0.13(2023-07-10)
+1. 统一整型与高低位的入口
+2. 增加大小端数据的字节转换
+3. 增加十进制与二进制的转换
+
+## 1.0.12(2023-07-07)
+1. 增加Modbus协议,CRC校验高低位在前的参数
+## 1.0.11(2023-07-05)
+1. 优化内部算法
+## 1.0.10(2023-07-05)
+1. 兼容Vue3, 导入导出方式统一改成import/export
+## 1.0.9(2023-07-02)
+1. 修复十六进制问题
+## 1.0.8(2023-07-02)
+优化逻辑
+## 1.0.7(2023-06-08)
+1. 修复整型转高低位时,高位太大问题
+## 1.0.3(2023-06-02)
+1. 增加ASCII转换方法
+## 1.0.2(2023-06-02)
+十六进制转换/ArrayBuffer转换/modbus/crc/高低位
+## 1.0.0(2023-06-02)
+集成字节工具类

+ 233 - 0
uni_modules/wrs-js-modbusCRCHex/js_sdk/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
uni_modules/wrs-js-modbusCRCHex/js_sdk/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
uni_modules/wrs-js-modbusCRCHex/js_sdk/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
uni_modules/wrs-js-modbusCRCHex/js_sdk/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
uni_modules/wrs-js-modbusCRCHex/js_sdk/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
uni_modules/wrs-js-modbusCRCHex/js_sdk/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
uni_modules/wrs-js-modbusCRCHex/js_sdk/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
uni_modules/wrs-js-modbusCRCHex/js_sdk/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
+// }

+ 86 - 0
uni_modules/wrs-js-modbusCRCHex/package.json

@@ -0,0 +1,86 @@
+{
+  "id": "wrs-js-modbusCRCHex",
+  "displayName": "十六进制-ArrayBuffer-ASCII-modbus-crc-高低位-大小端-二进制",
+  "version": "1.0.21",
+  "description": "十六进制/ArrayBuffer/ASCII/modbus/crc/高低位/大小端/二进制等转换,常用于串口、蓝牙、socket等字节数据转换",
+  "keywords": [
+    "十六进制二进制",
+    "ASCIIArrayBuffer",
+    "modbuscrc",
+    "高低位",
+    "大小端大端小端"
+],
+  "repository": "",
+  "engines": {
+    "HBuilderX": "^3.1.0"
+  },
+  "dcloudext": {
+    "type": "sdk-js",
+    "sale": {
+      "regular": {
+        "price": "9.99"
+      },
+      "sourcecode": {
+        "price": "999.00"
+      }
+    },
+    "contact": {
+      "qq": "252797991"
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "插件不采集任何数据",
+      "permissions": "无"
+    },
+    "npmurl": ""
+  },
+  "uni_modules": {
+    "dependencies": [],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y",
+        "alipay": "n"
+      },
+      "client": {
+        "Vue": {
+          "vue2": "y",
+          "vue3": "y"
+        },
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y",
+          "钉钉": "y",
+          "快手": "y",
+          "飞书": "y",
+          "京东": "y"
+        },
+        "快应用": {
+          "华为": "y",
+          "联盟": "y"
+        }
+      }
+    }
+  }
+}

+ 355 - 0
uni_modules/wrs-js-modbusCRCHex/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);
+
+
+```

+ 12 - 0
uni_modules/wrs-uts-usbmanager/changelog.md

@@ -0,0 +1,12 @@
+## 1.0.5(2023-11-01)
+1. 优化
+## 1.0.4(2023-11-01)
+1. 修复新基座uts语法兼容问题
+## 1.0.3(2023-08-07)
+1. usb设备数据增加VID/PID
+## 1.0.2(2023-07-28)
+修改前缀
+## 1.0.1(2023-07-01)
+优化逻辑
+## 1.0.0(2023-07-01)
+监听USB插拔、获取所有USB设备、请求USB权限

+ 2 - 0
uni_modules/wrs-uts-usbmanager/encrypt

@@ -0,0 +1,2 @@
+<f	mŘm…µx¬­¬*ë"v†ďv{Ü�Z3ţ<~ť¤6ĚIY©y¶˘PЅѰ}šěą˙©®–h�[D�Ö—#Ků|3¦đ5ő÷ě¦
+ţ˙ÁĄÝĎźLîŐj…Aő^š3}°=9Ľrřb‘óNR"·şd/"ljş˙aŢČ�Ü&ęÖ5n‘zJR$×

+ 84 - 0
uni_modules/wrs-uts-usbmanager/package.json

@@ -0,0 +1,84 @@
+{
+  "id": "wrs-uts-usbmanager",
+  "displayName": "监听USB插拔获取所有USB设备请求USB权限",
+  "version": "1.0.5",
+  "description": "监听USB插拔、获取所有USB设备、请求USB权限",
+  "keywords": [
+    "监听USB插拔",
+    "获取所有USB设备",
+    "请求USB权限"
+],
+  "repository": "",
+"engines": {
+  },
+  "dcloudext": {
+    "type": "uts",
+    "sale": {
+      "regular": {
+        "price": "199.00"
+      },
+      "sourcecode": {
+        "price": "999.00"
+      }
+    },
+    "contact": {
+      "qq": "252797991"
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "插件不采集任何数据",
+      "permissions": "usb权限"
+    },
+    "npmurl": ""
+  },
+  "uni_modules": {
+    "dependencies": [],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "Vue": {
+          "vue2": "y",
+          "vue3": "y"
+        },
+        "App": {
+          "app-android": {
+            "minVersion": "19"
+        },
+          "app-ios": "u"
+        },
+        "H5-mobile": {
+          "Safari": "u",
+          "Android Browser": "u",
+          "微信浏览器(Android)": "u",
+          "QQ浏览器(Android)": "u"
+        },
+        "H5-pc": {
+          "Chrome": "u",
+          "IE": "u",
+          "Edge": "u",
+          "Firefox": "u",
+          "Safari": "u"
+        },
+        "小程序": {
+          "微信": "u",
+          "阿里": "u",
+          "百度": "u",
+          "字节跳动": "u",
+          "QQ": "u",
+          "钉钉": "u",
+          "快手": "u",
+          "飞书": "u",
+          "京东": "u"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        }
+      }
+    }
+  }
+}

+ 92 - 0
uni_modules/wrs-uts-usbmanager/readme.md

@@ -0,0 +1,92 @@
+# 监听USB设备的插拔,请求USB设备权限,获取当前连接的所有USB设备
+
+#### 定制或采购源码联系QQ252797991
+
+1. 下载demo,拷贝demo里的AndroidManifest.xml文件到uniapp项目根目录下
+2. 点击插件页面右上角的"试用"按钮,按照提示集成到uniapp项目
+3. 删除本地基座和手机app
+4. 重新自定义基座运行
+
+```
+
+	import {
+		UTSUsbManager,
+	} from "@/uni_modules/wrs-uts-usbmanager";
+
+
+```
+
+- 监听USB设备的插拔
+
+```
+
+				// 注册USB插拔监听
+				UTSUsbManager.registerReceiver(this.action, (resp) => {
+					let action = resp.action;
+					switch (action) {
+						// USB授权结果
+						case this.action: {
+							let granted = resp.granted
+							let action = resp.action
+							let device = resp.device
+							this.showMsg("有USB设备授权结果:" + JSON.stringify(resp));
+							if (granted) {
+								this.showMsg("有USB设备授权成功");
+							} else {
+								this.showMsg("有USB设备授权失败");
+							}
+						}
+						break;
+						// 监测到有USB拔出
+						case "android.hardware.usb.action.USB_DEVICE_DETACHED": {
+							this.showMsg("有USB设备拔出:" + JSON.stringify(resp));
+						}
+						break;
+						// 检测到有USB插入
+						case "android.hardware.usb.action.USB_DEVICE_ATTACHED": {
+							// USB插入时,有些设备会监听到USB插入-USB设备拔出-USB设备插入这么个过程,可能是系统或USB设备的bug
+							this.showMsg("有USB设备插入:" + JSON.stringify(resp));
+						}
+						break;
+						default:
+							break;
+					}
+				})
+
+```
+
+- 取消监听USB设备的插拔
+
+```
+
+UTSUsbManager.unregisterReceiver()
+
+```
+
+- 获取当前连接的所有USB设备
+
+
+```
+
+		UTSUsbManager.getDeviceList((resp) => {
+						this.showMsg(JSON.stringify(resp))
+						// {"devices":[{"deviceName":"/dev/bus/usb/001/017","interfaceCount":2,"interfaces":[{"id":0,"name":"Espressif CDC Device","interfaceProtocol":0,"interfaceClass":2},{"id":1,"interfaceProtocol":0,"interfaceClass":10}],"deviceId":1017,"deviceProtocol":0}]}
+				});
+
+```
+
+- 请求某个USB设备权限
+
+权限结果在registerReceiver里回调
+
+```
+
+let device = devices[index];
+							let deviceId = device.deviceId;
+							let requestCode = this.requestCode;
+							let action = this.action;
+							let flags = 0;
+							
+							UTSUsbManager.requestPermission(deviceId, requestCode, action, flags);
+
+```

+ 3 - 0
uni_modules/wrs-uts-usbmanager/utssdk/app-android/config.json

@@ -0,0 +1,3 @@
+{
+  "minSdkVersion": "19"
+}

BIN
uni_modules/wrs-uts-usbmanager/utssdk/app-android/index.uts


BIN
uni_modules/wrs-uts-usbmanager/utssdk/app-ios/index.uts


+ 9 - 2
utils/app.js

@@ -1,6 +1,7 @@
 import * as util from './util'
 import storage from "@/utils/storage";
 import {deletePageStyle, setPageStyle} from "@/utils/uniFunction";
+import {isObject} from "./util";
 
 /**
  * 显示成功提示框
@@ -66,11 +67,17 @@ export const confirmModal = (msg, options = {}) => {
  * 显示纯文字提示框
  */
 export const showToast = (msg, duration = 1500) => {
-  uni.showToast({
+  let data = {
     title: `${msg}`,
     icon: 'none',
     duration
-  })
+  }
+  if (!isObject(duration)) {
+    data.duration = duration
+  } else {
+    data = Object.assign(data, duration)
+  }
+  uni.showToast(data)
 }
 
 /**

+ 13 - 1
utils/ble/hex.js

@@ -1,5 +1,6 @@
 // ArrayBuffer转16进度字符串示例
 import {formatZero, isObject, sliceChunk} from "@/utils/util";
+import * as ASCIIUtils from "@/uni_modules/wrs-js-modbusCRCHex/js_sdk/wrs-ASCIIUtils";
 
 export const ab2hex = (buffer, join = '') => {
   const hexArr = Array.prototype.map.call(
@@ -91,6 +92,8 @@ export const stringToArrayBuffer = (str, type = 1) => {
  * @param arr(array)        按指定长度切割 不转换16进制[ type: 1 不转换10进制;   long:长度  ]
  * @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) => {
@@ -106,7 +109,8 @@ export const orderToData = (str, arr, mode = 1) => {
       t: itemArr.t || 0,
       l: itemArr.l || 2,
       c: itemArr.c || [],
-      d: itemArr.d || ''
+      d: itemArr.d || '',
+      fun: itemArr.fun || null,
     }
     let item = '';
     let save = !0
@@ -135,9 +139,15 @@ export const orderToData = (str, arr, mode = 1) => {
         item = sliceChunk(content, itOp.l)
         itOp.l = content.length
         break;
+      case 4:
+        item = str.slice(num, num + itOp.l);
+        item = parseInt(ASCIIUtils.decodeUtf8(item))
+        if (itOp.fun) item = itOp.fun(item)
+        break;
       default:
         item = str.slice(num, num + itOp.l);
         item = hexToDataHandle(item, mode, itOp.d)
+        if (itOp.fun) item = itOp.fun(item)
         break;
     }
     if (save) data[itOp.k] = item
@@ -166,6 +176,8 @@ export const dataToHexHandle = (str, len = 2) => {
 /**
  * 16进(低位)转成10进数据
  * @param str
+ * @param type
+ * @param def
  * @returns {string}
  */
 export const hexToDataHandle = (str, type = 1, def = '') => {

+ 1 - 1
utils/bootstrap.js

@@ -7,7 +7,7 @@ import {useConfigStore} from "@/store/useConfigStore";
 import {useUserStore} from "@/store/useUserStore";
 
 export default function Initializer() {
-  console.log('Initializer')
+  // console.log('Initializer')
   // 当前运行的终端
   // if (process.env.NODE_ENV === 'production') storage.clearOtherKey(config.get('clearOtherKey'))
   // store.commit('setting/setPlatform', platform)

+ 59 - 0
utils/machine/bmiMachine.js

@@ -0,0 +1,59 @@
+import {Base} from "@/utils/usbSerial/base";
+import {logs} from "@/utils/util";
+import {orderToData} from "@/utils/ble/hex";
+
+export class BmiMachine extends Base {
+
+  constructor(topClass, usbSerial) {
+    super(topClass, usbSerial)
+
+    this.id = 'bmi'
+    this.title = 'BMI体重秤'
+    this.config = {
+      baudRate: 9600,
+      dataBits: 8,
+      stopBits: 1,
+      parity: 0,
+      flowControl: 0,
+    }
+  }
+
+
+  read(resp) {
+    // resp.value = ASCIIUtils.decodeUtf8(resp.data)
+    // logs('bmi usbSerial.read', resp)
+    // 7.40kg   98.5cm   9???
+    // let str = '0240303037343030303938353030303030303030303030303030303030303030303030303030303037373030303030403503'
+    let resArr = this.packetManager(resp.data)
+    resArr.forEach(it => {
+      let code = it.substring(2, 4)
+      let orderContent = it.slice(4, -6)
+      let result = {}
+      let acceptOrder = this.getAcceptOrder(code)
+      if (acceptOrder) result = orderToData(orderContent, acceptOrder.c, 0)
+      if (this.notifyFun) this.notifyFun(result)
+    })
+  }
+
+
+  getAcceptOrder(cmd) {
+    let order = {
+      '40': {
+        l: 20,
+        c: [
+          {t: 4, k: 'kg', l: 10, fun: (it) => it ? it / 100 : 0},
+          {t: 4, k: 'cm', l: 10, fun: (it) => it / 10},
+          {t: 4, k: 'k3', l: 10, fun: (it) => it / 10},
+          {t: 4, k: 'k4', l: 10, fun: (it) => it / 10},
+          {t: 4, k: 'k5', l: 10, fun: (it) => it / 10},
+          {t: 4, k: 'k6', l: 10, fun: (it) => it / 10},
+          {t: 4, k: 'k7', l: 10},
+          {t: 4, k: 'k8', l: 10, fun: (it) => it / 10},
+          {t: 4, k: 'k9', l: 10, fun: (it) => it / 10},
+        ]
+      },
+    }
+    return order[cmd] || null
+  }
+
+}

+ 6 - 0
utils/machine/config.js

@@ -18,3 +18,9 @@ export const machineTypeList = [
     disabled: false,
   },
 ]
+
+export const usbConfigList = {
+  // 'vendorId_productId':'类型关键字'
+  '1155_22336': 'scan',
+  '6790_29987': 'bmi',
+}

+ 243 - 0
utils/machine/index.js

@@ -0,0 +1,243 @@
+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)
+
+  }
+
+  _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)
+  }
+
+}
+
+

+ 34 - 0
utils/machine/scanMachine.js

@@ -0,0 +1,34 @@
+import * as ASCIIUtils from "@/uni_modules/wrs-js-modbusCRCHex/js_sdk/wrs-ASCIIUtils";
+// import {logs} from "@/utils/util";
+import {Base} from "@/utils/usbSerial/base";
+import {logs} from "@/utils/util";
+
+export class ScanMachine extends Base {
+
+  constructor(topClass, usbSerial) {
+    super(topClass, usbSerial)
+
+    this.id = 'scan'
+    this.title = '扫码器'
+    this.config = {
+      baudRate: 115200,
+      dataBits: 8,
+      stopBits: 1,
+    }
+  }
+
+
+  read(resp) {
+    logs('read', this.id, resp)
+    if (!resp.data) return;
+    let data = resp.data
+    if (data.startsWith('02') && data.endsWith('03')) {
+      resp.value = data.substring(2, data.length - 2);
+    }
+    resp.value = ASCIIUtils.decodeUtf8(data)
+    // logs('scan usbSerial.read', resp)
+    if (this.notifyFun) this.notifyFun(resp)
+  }
+
+
+}

+ 234 - 0
utils/usbSerial/base.js

@@ -0,0 +1,234 @@
+import {getAllMethods, logs, sleep, sliceChunk} from "@/utils/util";
+
+/**
+ *
+ */
+export class Base {
+  constructor(topClass, usbSerial) {
+    this.topClass = topClass
+    this.usbSerial = usbSerial
+
+    this.title = '设备名'
+    this.id = null
+    this.k = null
+    this.key = null
+    this.open = false
+    this.auth = false
+    this.config = {
+      baudRate: 9600,
+      dataBits: 8,
+      stopBits: 1,// 停止位 1: STOP_BITS_1 2: STOP_BITS_2 3: STOP_BITS_15
+      parity: null, // 校验位 0: PARITY_NONE 1: PARITY_ODD 2: PARITY_EVEN 3: PARITY_MARK 4:PARITY_SPACE
+      flowControl: null, // 流控 0: FLOW_CONTROL_OFF 1: FLOW_CONTROL_RTS_CTS 2: FLOW_CONTROL_DSR_DTR 3: FLOW_CONTROL_XON_XOFF
+    }
+
+    this.notifyFun = null
+
+    this.startChar = 0x02;
+    this.endChar = 0x03;
+    this.buffer = new Uint8Array(0); // 初始化空的Uint8Array作为缓冲区
+  }
+
+  setWatch(fun = null) {
+    this.notifyFun = fun
+  }
+
+  async _init(k, key) {
+    // logs('ScanMachine init')
+    if (!key) {
+      return;
+    }
+    if (this.key && this.open) {
+      await this.close()
+      await sleep(800)
+    }
+    this.k = k
+    this.key = key
+    await this.connect()
+    // logs('ScanMachine init2')
+  }
+
+
+  async connect() {
+    // logs('base connect', this.key || '-', this.open || '-')
+    return new Promise(async (resolve, reject) => {
+      if (!this.key || (this.key && this.open)) return reject('设备已启动')
+      try {
+        let option = Object.assign(this.config, {
+          key: this.key,
+          open: () => {
+            this.openHandle()
+            // logs('扫码器开始监听')
+            resolve()
+          },
+          read: this.read.bind(this)
+        })
+        await this.usbSerialHandle(option)
+      } catch (e) {
+        reject(e)
+        console.error('bmiMachine error', e)
+      }
+    })
+  }
+
+
+  read(resp) {
+  }
+
+
+  openHandle() {
+    this.open = true
+  }
+
+
+  async close() {
+    if (!this.open) return;
+    await this.usbSerial.syncClose({
+      key: this.key
+    });
+    this.auth = false
+    this.key = null
+    this.open = false
+
+    uni.$emit('machineUsb', {
+      id: this.id,
+      up: false,
+    })
+  }
+
+
+  async usbSerialHandle(option = {}) {
+    let op = {
+      key: option.key || null,
+      baudRate: option.baudRate || 9600,
+      dataBits: option.dataBits || 8,
+      stopBits: option.stopBits || 1,
+      open: option.open || null,
+      read: option.read || null,
+    }
+    if (!op.key) throw '无法监听,请确认参数key'
+    if (!this.auth) throw '未授权无法监听'
+    try {
+      // await this.usbSerial.requestPermission({
+      //   key: op.key,
+      // });
+      // logs('start requestPermission')
+      // await sleep(5000)
+      // logs('start 1')
+      this.usbSerial.open({
+        key: op.key,
+      })
+      await sleep(100)
+      // logs('start 2')
+      this.usbSerial.setBaudRate({
+        key: op.key,
+        value: op.baudRate,
+      });
+      // await sleep(100)
+      // logs('start 3')
+
+      this.usbSerial.setDataBits({
+        key: op.key,
+        value: op.dataBits,
+      });
+      // await sleep(100)
+      // logs('start 4')
+
+      this.usbSerial.setStopBits({
+        key: op.key,
+        value: op.stopBits,
+      });
+      // await sleep(100)
+      // logs('start 5')
+
+      if (op.parity) this.usbSerial.setParity({
+        key: op.key,
+        value: op.parity,
+      });
+      // await sleep(100)
+      // logs('start 5')
+
+      if (op.parity) this.usbSerial.setFlowControl({
+        key: op.key,
+        value: op.flowControl,
+      });
+      await sleep(500)
+      // logs('start 6')
+
+      this.usbSerial.read({
+        key: op.key
+      }, (resp) => {
+        if (!resp.data) return;
+        op.read(resp)
+      });
+      if (op.open) op.open()
+      logs('开始监听', this.id, this.key, this.title)
+    } catch (e) {
+      // console.error('start error', e)
+      throw e
+    }
+  }
+
+
+  setPacket(startChar = 0x02, endChar = 0x03) {
+    this.startChar = startChar
+    this.endChar = endChar
+  }
+
+  packetManager(data) {
+    if (!data) return;
+    if (typeof data === 'string') {
+      // 如果输入是字符串,将其转换为ASCII码数组
+      data = sliceChunk(data, 2)
+    }
+    // logs('data', data)
+    // 将新接收到的数据追加到现有缓冲区
+    let tempBuffer = new Uint8Array(this.buffer.length + data.length);
+    tempBuffer.set(this.buffer, 0);
+    tempBuffer.set(data, this.buffer.length);
+    this.buffer = tempBuffer;
+    // logs('this.buffer', this.buffer)
+
+    let packets = [];
+    let start = 0;
+    let end = 0;
+
+    // 循环查找完整的数据包
+    while ((start = this.buffer.indexOf(this.startChar, end)) !== -1 && (end = this.buffer.indexOf(this.endChar, start + 1)) !== -1) {
+      // 提取从开始字符到结束字符的数据包
+      const packet = this.buffer.slice(start, end + 1);
+      // logs('packet', packet)
+      packets.push(this.bufferTOString(packet));
+
+      // 更新处理后的缓冲区内容
+      this.buffer = this.buffer.slice(end + 1);
+    }
+    // logs('packets', packets)
+    if (!packets) return false
+    // logs('packets2', packets)
+
+    // 返回所有找到的完整数据包
+    return packets;
+  }
+
+  bufferTOString(buffer) {
+    const hexArr = Array.prototype.map.call(
+      new Uint8Array(buffer),
+      function (bit) {
+        return ('00' + bit).slice(-2).toUpperCase()
+      }
+    )
+    return hexArr.join('')
+  }
+
+  parsePacket(packet) {
+    if (packet[0] === this.startChar && packet[packet.length - 1] === this.endChar) {
+      // 解析数据包内容,这里仅返回去除开始和结束字符的内容
+      const content = packet.slice(1, -1);
+      return content; // 返回解析后的内容
+    } else {
+      throw new Error('Invalid packet format.');
+    }
+  }
+
+}

+ 15 - 0
utils/usbSerial/readme.md

@@ -0,0 +1,15 @@
+0: PARITY_NONE
+
+## 校验位 setParity
+
+```
+无校验(None):不使用奇偶校验位。这意味着数据传输不会添加额外的校验位来检查错误。这种模式适用于错误率较低或者在其他层面上已经有错误检测机制的情况。
+1: PARITY_ODD
+奇校验(Odd):设置校验位,使得包括校验位在内的总位数为奇数。如果数据位的总和是偶数,则校验位设置为1,以确保总位数为奇数。
+2: PARITY_EVEN
+偶校验(Even):设置校验位,使得包括校验位在内的总位数为偶数。如果数据位的总和是奇数,则校验位设置为1,以确保总位数为偶数。
+3: PARITY_MARK
+标记校验(Mark):校验位始终设置为1,不论数据位。这种模式可以用来在数据流中标记特定的数据包或帧的开始和结束,但不用于错误检测。
+4: PARITY_SPACE
+空格校验(Space):校验位始终设置为0,与标记校验相反。同样,这种模式不用于错误检测,而是用于数据标记或其他特殊通信需求。
+```

+ 21 - 9
utils/util.js

@@ -192,17 +192,12 @@ export function formatZero(num, len) {
 /**
  * 字符串按指定长度切割
  * @param str
- * @param long
+ * @param size
  * @returns {*[]}
  */
-export function sliceChunk(str, long = 2) {
-  let arr = [];
-  for (let i = 0; i < str.length;) {
-    arr.push(str.slice(i, i + long))
-
-    i += long
-  }
-  return arr
+export function sliceChunk(str, size = 2) {
+  const reg = new RegExp(`.{1,${size}}`, 'g');
+  return str.match(reg);
 }
 
 
@@ -359,3 +354,20 @@ export const pxTorpx = (px) => {
   let rpx = (750 / deviceWidth) * Number(px)
   return Math.floor(rpx);
 }
+
+
+export const getAllMethods = (obj) => {
+  let methods = new Set();
+  let currentObj = obj;
+
+  do {
+    Object.getOwnPropertyNames(currentObj).forEach(prop => {
+      if (typeof obj[prop] === 'function') {
+        methods.add(prop);
+      }
+    });
+    currentObj = Object.getPrototypeOf(currentObj);
+  } while (currentObj && currentObj !== Object.prototype); // 避免添加Object的默认方法
+
+  return Array.from(methods).filter(method => method !== 'constructor');
+}

+ 10 - 3
vite.config.js

@@ -5,17 +5,24 @@ import uni from '@dcloudio/vite-plugin-uni';
 const envs = require('./config/env');
 
 export default ({mode}) => {
-  const context = JSON.parse(process.env.UNI_CUSTOM_CONTEXT)
+
+  let IS_TEST = true
+
+  let json = process.env.UNI_CUSTOM_CONTEXT
+  if (json) {
+    const context = JSON.parse(json)
+    IS_TEST = context.IS_TEST
+  }
 
   // 默认测试服
   let config = envs.test
-  if (!context.IS_TEST) {
+  if (!IS_TEST) {
     config = envs.prod
   }
 
   // 默认正式服
   // let config = envs.prod
-  // if (!context.IS_TEST) {
+  // if (!IS_TEST) {
   //   config = envs.test
   // }