Bläddra i källkod

蓝牙逻辑开发

xiaohaizhao 11 månader sedan
förälder
incheckning
927fb99415

+ 16 - 99
Bluetooth/index/index.vue

@@ -40,7 +40,6 @@
           </view>
         </view>
         <view style="flex: 1" />
-
         <view
           class="but"
           hover-class="navigator-hover"
@@ -68,19 +67,13 @@ export default {
     return {
       beSearching: false, //搜索状态
       connected: "", //连接状态
-      device: {}, //连接的蓝牙设备
-      devices: [], //蓝牙设备表
-      serviceid: 0,
-      services: [], //蓝牙设备服务列表
-      characteristics: [], //特征列表
-      characteristic: {
-        uuid: null,
-      }, //选中的特征
-
       empty: true,
+      services: [],
+      devices: [],
     };
   },
   onLoad(options) {
+    this.services = JSON.parse(options.services);
     this.startBluetooth();
     this.$refs.List.setHeight();
   },
@@ -97,6 +90,7 @@ export default {
         that.empty = devices.length == 0;
       });
       uni.startBluetoothDevicesDiscovery({
+        services: this.services,
         success(res) {
           that.beSearching = true;
           that.$refs.List.setHeight();
@@ -127,6 +121,7 @@ export default {
       that.connected = item.deviceId;
       uni.createBLEConnection({
         deviceId: item.deviceId,
+        services: that.services || [],
         success(res) {
           if (res.errCode == 0) {
             uni.getBLEDeviceServices({
@@ -157,7 +152,7 @@ export default {
                         that.closeBLEConnection();
                       } else {
                         device.characteristic = res.characteristics[0];
-                        const { write, read } =
+                        const { write, notify } =
                           device.characteristic.properties;
                         return uni.showModal({
                           content: `${
@@ -174,7 +169,7 @@ export default {
                             }
                           },
                         });
-                        if (write && read) {
+                        if (write && notify) {
                           uni.showModal({
                             content: `${
                               item.name || item.deviceId
@@ -192,7 +187,7 @@ export default {
                           });
                         } else {
                           uni.showModal({
-                            content: "设备未开启read或write权限,已断开连接",
+                            content: "设备未开启notify或write权限,已断开连接",
                             showCancel: false,
                             confirmText: "确认",
                           });
@@ -223,84 +218,16 @@ export default {
         },
       });
     },
-    /* 发送 */
-    send() {
-      let msg = JSON.stringify({
-          password: "87sjy9",
-          msgid: "3c1dfed63972c4441b4f0f1a097f884a",
-          ts: 1695354434598,
-        }),
-        that = this;
-      const buffer = new ArrayBuffer(msg.length);
-      const dataView = new DataView(buffer);
-      for (var i = 0; i < msg.length; i++) {
-        dataView.setUint8(i, msg.charAt(i).charCodeAt());
-      }
-      uni.writeBLECharacteristicValue({
-        deviceId: that.device.deviceId,
-        serviceId: that.serviceid,
-        characteristicId: that.characteristic.uuid,
-        value: buffer,
-        success(res) {
-          console.log("发送信息", res);
-        },
-        fail(err) {
-          console.error("发送信息失败", err);
-        },
-      });
-    },
-
-    /* 开始监听 */
-    startNotice() {
+    /* 关闭连接 */
+    closeBLEConnection() {
       let that = this;
-      uni.notifyBLECharacteristicValueChange({
-        deviceId: that.device.deviceId,
-        serviceId: that.serviceid,
-        characteristicId: that.characteristic.uuid,
-        state: true,
-        success(res) {
-          uni.onBLECharacteristicValueChange((res) => {
-            // 结果
-            console.log("结果", res);
-            // 结果里有个value值,该值为 ArrayBuffer 类型,所以在控制台无法用肉眼观察到,必须将该值转换为16进制
-            let resHex = that.ab2hex(res.value);
-            console.log("16进制", resHex);
-            // 最后将16进制转换为,就能看到对应的结果
-            let result = that.hexCharCodeToStr(resHex);
-            console.log("ascii码", result);
-          });
-        },
-      });
-    },
-    ab2hex(buffer) {
-      const hexArr = Array.prototype.map.call(
-        new Uint8Array(buffer),
-        function (bit) {
-          return ("00" + bit.toString(16)).slice(-2);
-        }
-      );
-      return hexArr.join("");
-    },
-    hexCharCodeToStr(hexCharCodeStr) {
-      var trimedStr = hexCharCodeStr.trim();
-      var rawStr =
-        trimedStr.substr(0, 2).toLowerCase() === "0x"
-          ? trimedStr.substr(2)
-          : trimedStr;
-      var len = rawStr.length;
-      if (len % 2 !== 0) {
-        alert("存在非法字符!");
-        return "";
-      }
-      var curCharCode;
-      var resultStr = [];
-      for (var i = 0; i < len; i = i + 2) {
-        curCharCode = parseInt(rawStr.substr(i, 2), 16);
-        resultStr.push(String.fromCharCode(curCharCode));
-      }
-      return resultStr.join("");
+      if (this.connected)
+        uni.closeBLEConnection({
+          deviceId: that.connected,
+          success(res) {},
+        });
+      this.connected = "";
     },
-
     handleFail(fail) {
       const codes = {
         0: "ok",
@@ -328,16 +255,6 @@ export default {
       });
       this.closeBLEConnection();
     },
-    /* 关闭连接 */
-    closeBLEConnection() {
-      let that = this;
-      if (this.connected)
-        uni.closeBLEConnection({
-          deviceId: that.connected,
-          success(res) {},
-        });
-      this.connected = "";
-    },
     getRSSIText: function (rssi) {
       let text = "";
       if (rssi >= -70) {

+ 156 - 0
control/components/prodnum-FW01B/prodnum-FW01B.vue

@@ -0,0 +1,156 @@
+<template>
+  <view>
+    <connectingDevice ref="refCD" @onFeedback="onFeedback" />
+    <block v-for="(item, index) in list" :key="item.w_functionid">
+      <view
+        class="item"
+        :hover-class="item.inputType == 'switch' ? '' : 'navigator-hover'"
+        @click="item.inputType == 'switch' ? '' : onClick(item)"
+      >
+        <view class="label">
+          {{ item.funcname }}
+          <block v-if="item.inputType == 'radio'">
+            {{ radioName(item) }}
+          </block>
+          <block v-if="item.inputType != 'switch'">
+            :{{
+              item.inputType == "radio"
+                ? item.showValue || "未设置"
+                : item.params.lastvalue || "未设置"
+            }}
+            <text v-if="item.params.unit" style="margin-left: 2px"
+              >({{ item.params.unit }})</text
+            >
+          </block>
+        </view>
+        <view>
+          <block v-if="item.inputType == 'switch'">
+            <u-switch
+              :value="item.params.lastvalue == 1"
+              asyncChange
+              size="24"
+              :loading="item.loading"
+              @change="changeSwitch(item, index)"
+            />
+          </block>
+          <block v-else>
+            <u-loading-icon v-if="item.loading" />
+            <text
+              v-else
+              class="iconfont icon-a-wodetiaozhuan"
+              style="color: #fff"
+            />
+          </block>
+        </view>
+      </view>
+    </block>
+    <My_input mode="1" ref="MyInput" @sendMsg="onSendMsg" />
+  </view>
+</template>
+
+<script>
+export default {
+  name: "prodnum-FW01",
+  components: {},
+  props: {
+    control: Object,
+  },
+  data() {
+    return {
+      list: [],
+    };
+  },
+  watch: {
+    control: function (newVal) {
+      if (newVal) {
+        let names = [];
+        for (const key in newVal.function) {
+          names.push(key);
+        }
+        this.list = this.__proto__.getControlItem(names, newVal, {
+          安装位置: "radio",
+        });
+        this.$refs.refCD.init();
+      }
+    },
+  },
+  methods: {
+    onClick(item) {
+      this.$refs.MyInput.openInput(item);
+    },
+    radioName(item) {
+      try {
+        item.showValue =
+          item.params.options.find((v) => v.value == item.params.lastvalue)
+            .label || "";
+      } catch (error) {
+        item.showValue;
+      }
+      return "";
+    },
+    changeSwitch(item, index) {
+      const value = item.params.lastvalue == 1 ? 0 : 1;
+      let msg = {
+        d: {
+          [item.params.param]: value,
+        },
+      };
+      this.$refs.refCD.send(msg, item);
+      this.$set(this.list[index], "loading", true);
+    },
+    onSendMsg(w_functionid, d) {
+      const index = this.list.findIndex((v) => v.w_functionid == w_functionid);
+      let msg = {
+        d,
+      };
+      this.$refs.refCD.send(msg, this.list[index]);
+      this.$set(this.list[index], "loading", true);
+    },
+    onFeedback(res) {
+      const index = this.list.findIndex((v) => v.msgid == res.msgid);
+      if (index != -1) {
+        let item = this.list[index];
+        let MyInput = this.$refs.MyInput;
+        MyInput.loading = false;
+
+        if (res.status == 1) {
+          item.params.lastvalue = item.msg.d[item.params.param];
+          MyInput.show = false;
+          MyInput.stepIsCalculate = null;
+        } else if (res.status == 0) {
+          uni.showModal({
+            title: "失败",
+            content: `“${item.funcname}”设置失败`,
+            showCancel: false,
+          });
+        }
+        
+        MyInput.$refs.uModal.loading = false;
+        delete item.loading;
+        delete item.msgid;
+        delete item.msg;
+
+        this.$set(this.list, index, item);
+        console.log(item);
+      }
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.item {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin: 10px 0;
+  box-sizing: border-box;
+  padding: 16px 20px;
+  border-radius: 6px;
+  background: rgba($color: #ffffff, $alpha: 0.1);
+  .label {
+    color: #fff;
+    font-size: 14px;
+    width: 230px;
+  }
+}
+</style>

+ 20 - 9
control/modules/My_input.vue

@@ -188,6 +188,13 @@ export default {
     customMethod: {
       type: Function,
     },
+    mode: {
+      type: [Number || String],
+      default: 0,
+    },
+    sendMsg: {
+      type: Function,
+    },
   },
   data() {
     return {
@@ -439,16 +446,20 @@ export default {
         this.stagingMethod = false;
       }
       this.loading = true;
-      let res = await this.$Http.setControlItem(w_functionid, params);
-      this.loading = false;
-      if (res) {
-        this.show = false;
-        this.stepIsCalculate = null;
-        setTimeout(() => {
-          // this.item = null;
-        }, 200);
+      if (this.mode == 1) {
+        this.$emit("sendMsg", w_functionid, params);
       } else {
-        this.$refs.uModal.loading = false;
+        let res = await this.$Http.setControlItem(w_functionid, params);
+        this.loading = false;
+        if (res) {
+          this.show = false;
+          this.stepIsCalculate = null;
+          setTimeout(() => {
+            // this.item = null;
+          }, 200);
+        } else {
+          this.$refs.uModal.loading = false;
+        }
       }
     },
   },

+ 259 - 0
control/modules/connectingDevice.vue

@@ -0,0 +1,259 @@
+<template>
+  <view class="device">
+    <view class="rssi">
+      <view class="signal">
+        <view
+          class="cell"
+          v-for="h in [4, 6, 8, 10]"
+          :key="h"
+          :style="{
+                  height: h + 'px',
+                  background:
+                    h &lt;= getRSSIStyle(Bluetooth.device.RSSI).h
+                      ? getRSSIStyle(Bluetooth.device.RSSI).BC
+                      : '#BBBBBB',
+                }"
+        />
+      </view>
+    </view>
+    {{ Bluetooth.device.name || Bluetooth.device.deviceId }}
+  </view>
+</template>
+
+<script>
+import { hexMD5 } from "../../pages/login/modules/md5";
+
+export default {
+  props: {
+    onFeedback: {
+      type: Function,
+    },
+  },
+  data() {
+    return {
+      Bluetooth: {},
+      circulation: null,
+    };
+  },
+  beforeDestroy() {
+    clearInterval(this.circulation);
+  },
+  methods: {
+    init() {
+      let that = this;
+      this.Bluetooth = this.$Http.Bluetooth;
+      console.log("连接蓝牙设备详情", this.$Http.Bluetooth);
+      uni.onBLEConnectionStateChange(function (res) {
+        if (!res.connected && that.circulation) {
+          uni.showModal({
+            content: "蓝牙设备已断开连接",
+            showCancel: false,
+          });
+          that.$Http.setDetailMode(0);
+          clearInterval(that.circulation);
+          that.circulation = null;
+        }
+      });
+      this.circulation = setInterval(() => {
+        uni.getBLEDeviceRSSI({
+          deviceId: that.Bluetooth.device.deviceId,
+          success: (success) => {
+            console.log("监听信号强度", success);
+            if (success.errCode == 0) that.Bluetooth.device.RSSI = success.RSSI;
+          },
+        });
+      }, 3000);
+
+      this.startNotice();
+    },
+
+    /* 发送 */
+    send(content = {}, item) {
+      content.ts = Date.now();
+      content.msgid = hexMD5(
+        JSON.stringify({ w_functionid: item.w_functionid, ...msg })
+      );
+      item.msgid = content.msgid;
+      item.msg = content;
+      let msg = JSON.stringify(content);
+      let that = this;
+      const buffer = new ArrayBuffer(msg.length);
+      const dataView = new DataView(buffer);
+      for (var i = 0; i < msg.length; i++) {
+        dataView.setUint8(i, msg.charAt(i).charCodeAt());
+      }
+      uni.writeBLECharacteristicValue({
+        deviceId: that.Bluetooth.device.deviceId,
+        serviceId: that.Bluetooth.service.uuid,
+        characteristicId: that.Bluetooth.characteristic.uuid,
+        value: buffer,
+        success(res) {
+          console.log("发送信息", res);
+        },
+        fail(err) {
+          console.error("发送信息失败", err);
+          that.handleFail(err);
+        },
+      });
+    },
+
+    /* 模拟接收 */
+    fanhui(value) {
+      let resHex = this.ab2hex(value);
+      let result = JSON.parse(this.hexCharCodeToStr(resHex));
+      delete result.d;
+      result.status = 1;
+      this.$emit("onFeedback", result);
+    },
+    /* 开始监听 */
+    startNotice() {
+      let that = this;
+      uni.notifyBLECharacteristicValueChange({
+        deviceId: that.Bluetooth.device.deviceId,
+        serviceId: that.Bluetooth.service.uuid,
+        characteristicId: that.Bluetooth.characteristic.uuid,
+        state: true,
+        success(res) {
+          console.log("监听信息", res);
+          uni.onBLECharacteristicValueChange((res) => {
+            let resHex = that.ab2hex(res.value);
+            let result = that.hexCharCodeToStr(resHex);
+            console.log("Notice", result);
+            that.$emit("onFeedback", result);
+          });
+        },
+        fail(err) {
+          console.error("监听信息失败", err);
+          that.handleFail(err);
+        },
+      });
+    },
+
+    handleFail(fail) {
+      const codes = {
+        0: "ok",
+        "-1": "已连接 ",
+        10000: "未初始化蓝牙适配器",
+        10001: "当前蓝牙适配器不可用",
+        10002: "没有找到指定设备",
+        10003: "连接失败",
+        10004: "没有找到指定服务",
+        10005: "没有找到指定特征值",
+        10006: "当前连接已断开",
+        10007: "当前特征值不支持此操作",
+        10008: "其余所有系统上报的异常",
+        10009: "系统版本低于 4.3 不支持 BLE",
+        10010: "已连接",
+        10011: "配对设备需要配对码",
+        10012: "连接超时",
+        10013: "连接 deviceId 为空或者是格式不正确",
+      };
+      uni.showModal({
+        content: codes[fail.errCode] || fail.errMsg,
+        showCancel: false,
+        confirmText: "确认",
+      });
+      this.$emit("onFeedback", {
+        status: 999,
+        msgid: 23232323,
+      });
+    },
+    ab2hex(buffer) {
+      const hexArr = Array.prototype.map.call(
+        new Uint8Array(buffer),
+        function (bit) {
+          return ("00" + bit.toString(16)).slice(-2);
+        }
+      );
+      return hexArr.join("");
+    },
+    hexCharCodeToStr(hexCharCodeStr) {
+      var trimedStr = hexCharCodeStr.trim();
+      var rawStr =
+        trimedStr.substr(0, 2).toLowerCase() === "0x"
+          ? trimedStr.substr(2)
+          : trimedStr;
+      var len = rawStr.length;
+      if (len % 2 !== 0) {
+        alert("存在非法字符!");
+        return "";
+      }
+      var curCharCode;
+      var resultStr = [];
+      for (var i = 0; i < len; i = i + 2) {
+        curCharCode = parseInt(rawStr.substr(i, 2), 16);
+        resultStr.push(String.fromCharCode(curCharCode));
+      }
+      return resultStr.join("");
+    },
+
+    getRSSIText: function (rssi) {
+      let text = "";
+      if (rssi >= -70) {
+        text = "可连接";
+      } else if (rssi < -90) {
+        text = "不可连接";
+      } else {
+        text = "信号差";
+      }
+      return text + `(${rssi})`;
+    },
+    getRSSIStyle: function (rssi) {
+      let obj = {
+        h: 10,
+        BC: "#5AB73F",
+      };
+      if (rssi < -60 && rssi >= -69) {
+        obj.h = 8;
+      } else if (rssi <= -70 && rssi >= -79) {
+        obj.h = 6;
+        obj.BC = "#F29C37";
+      } else if (rssi <= -80 && rssi >= -89) {
+        obj.h = 4;
+        obj.BC = "#EB4B5C";
+      } else if (rssi <= -90) {
+        obj.h = 0;
+      }
+      return obj;
+    },
+  },
+};
+</script>
+
+<style lang="scss" scope>
+.device {
+  display: flex;
+  align-items: center;
+  margin-top: 15px;
+  font-size: 14px;
+  color: #fff;
+  font-weight: 700;
+  padding-left: 5px;
+  padding-bottom: 5px;
+
+  .rssi {
+    display: flex;
+    align-items: center;
+    height: 17px;
+    margin: 0 6px;
+    .text {
+      font-family: PingFang SC, PingFang SC;
+      font-size: 12px;
+      color: #666666;
+      margin-right: 18px;
+    }
+
+    .signal {
+      display: flex;
+      align-items: flex-end;
+      height: 12px;
+
+      .cell {
+        width: 3px;
+        border-radius: 1px;
+        margin-right: 1px;
+      }
+    }
+  }
+}
+</style>

+ 2 - 0
main.js

@@ -25,6 +25,8 @@ import My_form from './components/My_form';
 Vue.component('My_form', My_form);
 import My_Files from './components/My_Files';
 Vue.component('My_Files', My_Files);
+import connectingDevice from './control/modules/connectingDevice';
+Vue.component('connectingDevice', connectingDevice);
 
 //挂载接口
 let isDev = process.env.NODE_ENV === 'development';

+ 41 - 10
pages/facility/detail.vue

@@ -210,24 +210,37 @@ export default {
       }
     },
     changeMode(mode) {
-      if (this.mode == mode) return;
       const that = this;
+      if (this.mode == mode) return;
       switch (mode) {
         case 0:
           uni.showModal({
             content: "是否关闭蓝牙\n并切换至网络控制",
             success: function ({ confirm }) {
-              if (confirm) that.mode = mode;
+              if (confirm) {
+                that.mode = mode;
+                try {
+                  if (that.$Http.Bluetooth)
+                    uni.closeBLEConnection({
+                      deviceId: that.$Http.Bluetooth.device.deviceId,
+                    });
+                  delete that.$Http.Bluetooth;
+                } catch (error) {}
+              }
             },
           });
           break;
         case 1:
           uni.openBluetoothAdapter({
             success: (result) => {
-              console.log("蓝牙初始化success:", result);
               if (result.errno == 0) {
                 uni.navigateTo({
-                  url: "/Bluetooth/index/index",
+                  url:
+                    "/Bluetooth/index/index?services=" +
+                    JSON.stringify([
+                      that.detail.prodnum,
+                      that.detail.w_productid,
+                    ]),
                 });
                 this.$Http.setBluetooth = function (Bluetooth) {
                   this.mode = mode;
@@ -237,8 +250,11 @@ export default {
                     "Bluetooth/index/index"
                   )
                     uni.navigateBack();
+                  this.$Http.setDetailMode = function (mode1) {
+                    this.mode = mode1;
+                    delete this.$Http.setDetailMode;
+                  }.bind(this);
                   this.$Http.Bluetooth = Bluetooth;
-                  console.log(this.$Http.Bluetooth);
                   delete this.$Http.setBluetooth;
                 }.bind(this);
               } else {
@@ -268,13 +284,28 @@ export default {
                   },
                 });
               } else {
+                const codes = {
+                  0: "ok",
+                  "-1": "已连接 ",
+                  10000: "未初始化蓝牙适配器",
+                  10001: "当前蓝牙适配器不可用",
+                  10002: "没有找到指定设备",
+                  10003: "连接失败",
+                  10004: "没有找到指定服务",
+                  10005: "没有找到指定特征值",
+                  10006: "当前连接已断开",
+                  10007: "当前特征值不支持此操作",
+                  10008: "其余所有系统上报的异常",
+                  10009: "系统版本低于 4.3 不支持 BLE",
+                  10010: "已连接",
+                  10011: "配对设备需要配对码",
+                  10012: "连接超时",
+                  10013: "连接 deviceId 为空或者是格式不正确",
+                };
                 uni.showModal({
-                  title: fail.errno || "",
-                  content: fail.errno
-                    ? "请确认已开启蓝牙设备权限"
-                    : fail.errMsg,
+                  content: codes[fail.errCode] || fail.errMsg,
                   showCancel: false,
-                  confirmText: "确定",
+                  confirmText: "确认",
                 });
               }
             },

+ 6 - 4
pages/facility/modules/control.vue

@@ -17,10 +17,12 @@
       v-else-if="detail.miniapppath == 'prodnum-YK01'"
       :control="control"
     />
-    <prodnum-FW01
-      v-else-if="detail.miniapppath == 'prodnum-FW01'"
-      :control="control"
-    />
+
+    <block v-else-if="detail.miniapppath == 'prodnum-FW01'">
+      <prodnum-FW01 v-if="mode == 0" :control="control" />
+      <prodnum-FW01B v-else :control="control" />
+    </block>
+
     <block v-else>
       <view style="height: 50px" />
       <u-empty mode="data" />