wzh 2 лет назад
Родитель
Сommit
0f897485c3
6 измененных файлов с 954 добавлено и 22 удалено
  1. 7 1
      pages.json
  2. 15 8
      pages/bluetooth/index/index.vue
  3. 4 11
      pages/login.vue
  4. 671 0
      pages/weitiandi/bluetooth/index.vue
  5. 2 2
      permission.js
  6. 255 0
      utils/weitiandi/device/device.js

+ 7 - 1
pages.json

@@ -1,11 +1,17 @@
 {
   "pages": [
-   
+
     {
       "path": "pages/login",
       "style": {
         "navigationBarTitleText": "登录"
       }
+    },
+    {
+      "path": "pages/weitiandi/bluetooth/index",
+      "style": {
+        "navigationBarTitleText": "蓝牙控制"
+      }
     },
 	{
 	  "path": "pages/bluetooth/index/index",

+ 15 - 8
pages/bluetooth/index/index.vue

@@ -5,7 +5,7 @@
 			hover-start-time="0" hover-stay-time="100" @click="listViewTap(item.id)">
 			<image v-if="item.manufacturer==='eciot'" src="/static/img/ecble.png" class="list-item-img"></image>
 			<image v-else src="/static/img/ble.png" class="list-item-img"></image>
-			<text class="list-item-name">{{item.name}}</text> 
+			<text class="list-item-name">{{item.name}}</text>
 			<image v-if="item.rssi >= -41" src="/static/img/s5.png" mode="aspectFit" class="list-item-rssi-img"></image>
 			<image v-else-if="item.rssi >= -55" src="/static/img/s4.png" mode="aspectFit" class="list-item-rssi-img"></image>
 			<image v-else-if="item.rssi >= -65" src="/static/img/s3.png" mode="aspectFit" class="list-item-rssi-img"></image>
@@ -19,18 +19,18 @@
 	</scroll-view>
 </template>
 
-<script> 
+<script>
 // #ifdef APP
 import ecUI from '@/utils/ecUI.js'
 import ecBLE from '@/utils/ecBLE/ecBLE.js'
-// #endif   
+// #endif
 // #ifdef MP
-const ecUI = require('@/utils/ecUI.js')     
+const ecUI = require('@/utils/ecUI.js')
 const ecBLE = require('@/utils/ecBLE/ecBLE.js')
 // #endif
 	let ctx
 	let deviceListData = []
-	export default {  
+	export default {
 		data() {
 			return {
         timer:"",
@@ -40,9 +40,15 @@ const ecBLE = require('@/utils/ecBLE/ecBLE.js')
 		onLoad() {
 			ctx = this
       clearInterval(this.timer);
-			this.timer = setInterval(() => {
-				ctx.deviceListDataShow = JSON.parse(JSON.stringify(deviceListData))
-			}, 800)
+      const blueid = uni.getStorageSync('blueid');
+      if(blueid){
+          this.listViewTap(blueid);
+      }else{
+        this.timer = setInterval(() => {
+          ctx.deviceListDataShow = JSON.parse(JSON.stringify(deviceListData))
+        }, 800)
+      }
+
 		},
 		onShow() {
 			setTimeout(() => {
@@ -55,6 +61,7 @@ const ecBLE = require('@/utils/ecBLE/ecBLE.js')
 				ecBLE.onBLEConnectionStateChange(res => {
 					ecUI.hideLoading()
 					if (res.ok) {
+            uni.setStorageSync('blueid', id);
 						ecBLE.stopBluetoothDevicesDiscovery()
 						uni.navigateTo({ url: '../device/device' })
 					} else {

+ 4 - 11
pages/login.vue

@@ -88,10 +88,10 @@
   </view>
     <view v-show="isLogin">
     <view class="img">
-	    <image @click="buleTeeth()" style="width: 31px;" :src="imgUrl+'/login/blueTeeth.png'" mode="widthFix"/>
+	    <image @click="buleTeeth" style="width: 31px;" :src="imgUrl+'/login/blueTeeth.png'" mode="widthFix"/>
 	</view>
 	<view class="blue-text">
-	    <text @click="buleTeeth()">蓝牙连接</text>
+	    <text @click="buleTeeth">蓝牙连接</text>
 	</view>
 	</view>
   </view>
@@ -129,19 +129,12 @@
 	  }
 	},
     created() {
+      debugger
       this.checkLogin();
     },
     methods: {
       buleTeeth(){
-        uni.navigateTo({
-          url: '/pages/buletooth/bluetooth',
-          complete:function (){
-            debugger;
-          },
-          fail:function (res){
-            console.log(res)
-          }
-        });
+        this.$tab.reLaunch('/pages/bluetooth/index/index')
       },
       checkLogin(){
         let token = getToken()

+ 671 - 0
pages/weitiandi/bluetooth/index.vue

@@ -0,0 +1,671 @@
+<template>
+  <view class="container">
+    <view class="header">
+      <view class="header-status chong-active" v-if="portDetail.portStatus == 1">
+        充电枪未连接
+      </view>
+
+      <view class="header-status chong-active" v-if="portDetail.portStatus == 0">
+        正在读取状态
+      </view>
+
+      <view class="header-status chong-active" v-if="portDetail.portStatus == 5">
+        充电枪已连接
+      </view>
+
+      <view class="header-status chong-active" v-if="portDetail.portStatus == 2">
+        充电枪已连接
+      </view>
+      <view class="header-img" v-if="portDetail.portStatus == 2">
+        <image :src="imgUrl+'/chargedetail/chonging.png'">
+
+        </image>
+      </view>
+
+      <view class="header-img" v-if="portDetail.portStatus != 2">
+        <image :src="imgUrl+'/chargedetail/chongoff.png'">
+
+        </image>
+      </view>
+      <view class="header-status-desc" v-if="portDetail.portStatus == 2">
+        充电中
+      </view>
+
+      <view class="header-status-desc" style="color: #B2B2B2" v-if="portDetail.portStatus != 2">
+        未充电
+      </view>
+    </view>
+    <view class="port"  @click="showPort = true">
+      <view class="port-image">
+        <image class="btn-image" :src="imgUrl+'/index/device.png'" >
+        </image>
+      </view>
+      <view class="port-text">
+        设备编号:{{ deviceInfo.qrcode }}
+      </view>
+
+      <view class="port-num">
+        <view>
+          {{portList[0][choosePort-1]["text"]}}
+        </view>
+
+      </view>
+      <view class="port-icon">
+        <image class="btn-image" :src="imgUrl+'/index/right.png'" >
+        </image>
+      </view>
+    </view>
+    <view class="plan" @click="planCharge">
+      <view class="port-image">
+        <image class="btn-image" :src="imgUrl+'/index/clock.png'" >
+        </image>
+      </view>
+      <view class="port-text" v-if="planInfo != null"  style="top:8px">
+        预约充电时间:
+      </view>
+      <view v-if="planInfo != null" class="port-text" style="top:30px;">
+        <text style="font-size: 10px">{{ planInfo.runTime }}</text>
+      </view>
+      <view class="port-text" style="top:24px" v-else>
+        点击预约充电
+      </view>
+      <view class="port-num" style="top:48px;font-size: 12px" v-if="planInfo != null">
+        点击取消预约
+      </view>
+      <view class="port-icon"  v-if="planInfo==null">
+        <image class="btn-image" :src="imgUrl+'/index/right.png'" >
+        </image>
+      </view>
+      <view class="port-icon" v-if="planInfo !=null" style="width: 18px;height: 18px;right:1px;">
+        <image class="btn-image"  :src="imgUrl+'/index/del.png'" >
+        </image>
+      </view>
+
+    </view>
+    <view class="info-body">
+     <view>
+       <view class="info-content">
+
+         <view class="info-content-value">{{ portDetail.voltage }}V</view>
+         <view class="info-content-text">
+           充电电压
+         </view>
+       </view>
+
+       <view class="info-content">
+
+         <view class="info-content-value" v-if="portDetail.voltage == 0">0A</view>
+         <view class="info-content-value" v-else>{{portDetail.POWER/portDetail.voltage}}A</view>
+
+         <view class="info-content-text">
+           充电电流
+         </view>
+       </view>
+
+       <view class="info-content">
+
+         <view class="info-content-value">{{portDetail.dev_temper}}℃</view>
+         <view class="info-content-text">
+           设备温度
+         </view>
+       </view>
+
+
+       <view class="info-content">
+
+         <view class="info-content-value">{{portDetail.wire_temper}}℃</view>
+         <view class="info-content-text">
+           线路温度
+         </view>
+       </view>
+     </view>
+
+      <view class="body-bottom">
+        <view class="info-content">
+
+          <view class="info-content-value">{{ portDetail.time }}分钟</view>
+          <view class="info-content-text">
+            已冲时间
+          </view>
+        </view>
+        <view class="info-content">
+
+          <view class="info-content-value">{{ portDetail.power }}W</view>
+          <view class="info-content-text">
+            充电功率
+          </view>
+        </view>
+        <view class="info-content">
+
+          <view class="info-content-value">{{ portDetail.elec }} 度</view>
+          <view class="info-content-text">
+            已冲电量
+          </view>
+        </view>
+      </view>
+
+    </view>
+    <u-picker @cancel="showPort=false" @confirm="confirmPort" :show="showPort" :columns="portList" keyName="text"></u-picker>
+
+
+    <view class="bottom-control">
+      <view class="control-btn" @click="trigger()" v-if="portDetail.portStatus == 2">
+        <image class="btn-image" :src="imgUrl+'/control/stop.png'" >
+        </image>
+        <view>停止充电</view>
+      </view>
+
+      <view class="control-btn" @click="trigger()" v-if="portDetail.portStatus != 2">
+        <image class="btn-image" :src="imgUrl+'/control/charge.png'" >
+        </image>
+        <view>立即充电</view>
+      </view>
+      <view class="control-btn" @click="getInfo">
+        <image class="btn-image" :src="imgUrl+'/control/getstatus.png'" >
+        </image>
+        <view>获取状态</view>
+      </view>
+      <view class="control-btn" @click="toSet">
+        <image class="btn-image" :src="imgUrl+'/control/control.png'" >
+        </image>
+        <view>设备控制</view>
+      </view>
+      <view class="control-btn">
+        <image class="btn-image" :src="imgUrl+'/control/record.png'" >
+        </image>
+        <view>使用记录</view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+import {getDeviceInfo,getPortDetail,startCharge,stopCharge,sendPortDetailCmd,checkStatusChange,getPlanInfo,cancelPlan} from "@/utils/weitiandi/device/device.js";
+// #ifdef APP
+import ecUI from '@/utils/ecUI.js'
+import ecBLE from '@/utils/ecBLE/ecBLE.js'
+// #endif
+// #ifdef MP
+const ecUI = require('@/utils/ecUI.js')
+const ecBLE = require('@/utils/ecBLE/ecBLE.js')
+// #endif
+let ctx
+let isCheckScroll = true
+let isCheckRevHex = false
+let isCheckSendHex = false
+let sendData = ''
+export default {
+ data() {
+   return {
+     deviceInfo:{},
+     visitTime:"",
+     timer:null,
+     showPort:false,
+     portDetail:{portStatus:0,POWER:0,voltage:0},
+     statusTimer:"",
+     connected:false,
+     scriptTask:null,
+     choosePort:1,
+     portList:[[{port:1,text:"端口一"}]],
+     planInfo:null,
+     days:["","周一","周二","周三","周四","周五","周六","周日"],
+     textRevData: '',
+   }
+ },
+ computed: {
+   imgUrl() {
+     return getApp().globalData.config.imgUrl;
+   }
+ },
+ onLoad(opt) {
+   this.deviceInfo.deviceId = opt.id;
+   this.deviceInfo.ccid = opt.ccid;
+   this.deviceInfo.qrcode = opt.qrcode;
+   this.buletooth();
+   this.checkPassword();
+ },
+  onShow(){
+    this.getInfo();
+  },
+  onUnload (){
+   this.closeSocket();
+  },
+  methods: {
+    checkPassword(){
+    },
+    buletooth(){
+      let self = this;
+      ctx = this
+      isCheckScroll = true
+      isCheckRevHex = false
+      isCheckSendHex = false
+      sendData = ''
+
+      //on disconnect
+      ecBLE.onBLEConnectionStateChange(() => {
+        ecUI.showModal('提示', '设备断开连接')
+      })
+      //receive data
+      ecBLE.onBLECharacteristicValueChange((str, strHex) => {
+        ctx.textRevData = str
+        console.log("收到消息:"+str);
+        let data = JSON.parse(str);
+        let type = data.type;
+        let real_data = data.real_data;
+        if(type == 103){
+          self.portDetail = real_data
+          self.portList = [[]];
+          let port_first_status = self.portDetail["port_first_status"];
+          let port_second_status = self.portDetail["port_second_status"]
+          if(port_first_status){
+            self.portList[0].push({port:1,text:"端口一"});
+          }
+          if(port_second_status){
+            self.portList[0].push({port:2,text:"端口二"});
+          }
+          let choosePort = self.choosePort
+          if(choosePort == 1){
+            self.portDetail.portStatus = port_first_status;
+          }else if(choosePort == 2){
+            self.portDetail.portStatus = port_second_status;
+          }
+
+          self.$modal.closeLoading();
+        }
+        if(type == 116){
+          self.$modal.closeLoading();
+          self.getInfo();
+        }
+        if(type == 113){
+          self.$modal.closeLoading();
+          self.getInfo();
+        }
+        if(type == 96){
+          self.mainBoardInfo = real_data;
+          self.formatMainboardData();
+          self.$modal.closeLoading();
+        }
+        self.$forceUpdate();
+        console.log('收到服务器内容:' + JSON.stringify(data));
+      })
+    },
+    planCharge(){
+      if(this.planInfo != null){
+        this.$modal.confirm("确认取消预约?").then(res=>{
+          this.cancelPlan();
+        })
+      }else{
+        this.toPlan()
+      }
+    },
+    sendBlueData(){
+      ecBLE.writeBLECharacteristicValue(tempSendData, false)
+    },
+    cancelPlan(){
+      cancelPlan(this.planInfo.id).then(res=>{
+        this.$modal.msg("取消成功");
+        this.planInfo = null;
+        this.getPlanInfo();
+      })
+    },
+    getPlanInfo(){
+      getPlanInfo(this.deviceInfo.deviceId,this.choosePort).then(res=>{
+        let data = res.data;
+        if(data != null){
+          let planType = data.planType;
+          if(planType == 1){//单次预约
+              let planInfo = {};
+              planInfo.runTime = data.runTime;
+              this.planInfo = planInfo;
+              this.planInfo.id = data.id;
+          }else{
+            let planInfo = {};
+            planInfo.runTime = data.runTime;
+            let repeatDays = data.repeatDays;
+            let days = repeatDays.split(",")
+            let strs = "";
+            for (let i = 0; i < days.length; i++) {
+                if(strs.length>0){
+                  strs+=",";
+                }
+                strs +=this.days[days[i]];
+            }
+            this.planInfo = planInfo;
+            this.planInfo.runTime = strs+" "+data.repeatTime;
+            this.planInfo.id = data.id;
+          }
+        }
+      })
+    },
+    confirmPort(e){
+      let value = e.value[0]
+      this.choosePort = value.port;
+      this.showPort = false;
+      this.getInfo()
+    },
+    initSocket(key){
+      let self = this;
+    },
+    toSet(){
+      this.closeSocket();
+      uni.navigateTo({
+        url: '/pages/weitiandi/device/setting?id='+this.deviceInfo.deviceId+"&ccid="+this.deviceInfo.ccid
+      });
+    },
+    toPlan(){
+      uni.navigateTo({
+        url: '/pages/weitiandi/device/plan?port='+this.choosePort+'&id='+this.deviceInfo.deviceId+"&ccid="+this.deviceInfo.ccid
+      });
+    },
+    trigger(){
+      let portStatus = this.portDetail.portStatus;
+      if(portStatus == 2){//需要停止充电
+        this.$modal.confirm("需要停止充电么?").then(res=>{
+              this.stopCharge();
+        })
+      }else{
+        if(portStatus == 1){
+          this.$modal.msg("请先将充电枪插入后再点击充电");
+        }
+        if(portStatus == 5){
+          this.$modal.confirm("确认开始充电么?").then(res=>{
+            this.startCharge();
+          })
+        }
+
+      }
+    },
+   getInfo() {
+    this.$modal.loading("正在获取状态,请稍等...");
+     sendPortDetailCmd().then(res => {
+       this.$modal.loading("正在获取状态,请稍等...");
+        this.visitTime = res.msg;
+        if(!this.visitTime){
+          this.$modal.msg("请重新进入页面");
+          return;
+        }
+        if(!this.scriptTask){
+          // this.initSocket(this.deviceInfo.deviceId);
+        }
+       // this.getPortInfo()
+    })
+  },
+    stopCharge(){
+      let self = this;
+      this.deviceInfo.port = this.choosePort;
+      stopCharge(this.deviceInfo).then(()=>{
+        self.$modal.loading("停止成功");
+        setTimeout((()=>{
+          self.getInfo();
+        }),1000);
+      })
+    },
+    startCharge(){
+      let self = this;
+      this.deviceInfo.port = this.choosePort;
+      startCharge(this.deviceInfo).then(res=>{
+        self.$modal.loading("启动成功");
+        setTimeout((()=>{
+          self.getInfo();
+        }),1000);
+      })
+    },
+    getPortInfo(){
+      this.startPortDetailTimer();
+    },
+    startPortDetailTimer(){
+     let self = this;
+      this.timer = setTimeout(function (){
+        getPortDetail(self.deviceInfo,self.visitTime).then(res=>{
+         let data = res.data;
+         if(data != null){
+           self.portDetail = data;
+           self.checkStatusCheck();
+           self.$modal.closeLoading();
+         }else{
+           self.startPortDetailTimer();
+         }
+        });
+      },1000);
+    },
+    checkStatusCheck(){
+      this.statusChangeTimer();
+    },
+    checkOnPage(){
+      var pages = getCurrentPages() // 获取栈实例
+      let currentRoute = pages[pages.length - 1].route; // 获取当前页面路由
+      if("pages/weitiandi/device/index" != currentRoute){
+        return false;
+      }
+      return  true;
+    },
+    closeSocket(){
+      ecBLE.onBLEConnectionStateChange(() => {})
+      ecBLE.onBLECharacteristicValueChange(() => {})
+      ecBLE.closeBLEConnection()
+    },
+    statusChangeTimer(){
+      let self = this;
+      this.statusTimer = setTimeout(function(){
+       if(!this.checkOnPage()){
+         return;
+       }
+        checkStatusChange(self.deviceInfo,self.visitTime).then(res=>{
+          let data = res.data;
+          if(data != null){
+            self.getInfo();
+          }else{
+            self.statusChangeTimer();
+          }
+        });
+      },3000);
+    }
+  }
+}
+</script>
+
+<style>
+.container {
+  background: rgb(249, 252, 255);
+  inset: 0;
+  position: absolute;
+}
+
+.header {
+  position: relative;
+  margin-top:4vw;
+}
+
+.header-status-desc {
+  position: absolute;
+  text-align: center;
+  width: 100%;
+  bottom:1vh;
+  font-size: 5vw;
+  font-weight: bold;
+  color: #0E9F9B;
+}
+
+.header-status {
+  font-weight: bold;
+  padding-left: 5vw;
+}
+
+.chong-active {
+  color: #0E9F9B
+}
+
+.header-img {
+  width: 100%;
+  padding: 5% 10%;
+  text-align: center;
+
+}
+
+.header-img image {
+  width: 100%;
+  height: 23vh;
+}
+.info-body{
+  background: #0E9F9B;
+  height: 20vh;
+  margin: 0 2%;
+  border-radius: 1vw;
+  margin-top:2vh;
+  color: #F8FCFF;
+  line-height: 3vh;
+}
+.info-content{
+  display: inline-block;
+  width: 23%;
+  text-align: center;
+  margin: 1%;
+  margin-top:2.5vh;
+}
+.info-content-value{
+  font-weight: bold;
+}
+.info-content-text{
+
+}
+.info-summary{
+  display: flex;
+  flex-direction: row;
+  text-align: center;
+  margin:3vh 0;
+}
+.summary{
+  width: 33%;
+  line-height: 2.5vh;
+}
+.charge-num{
+  color: #0E9F9B;
+  font-weight: bold;
+  font-size: 4.5vw;
+}
+.charge-title{
+  color: #B2B2B2;
+  font-weight: 400;
+}
+.btn-image{
+  width: 90%;
+  height: 100%;
+}
+.info-bottom-btn{
+  display: flex;
+  flex-direction: row;
+  text-align: center;
+  position: relative;
+  margin-top: 10vh
+;
+}
+.btn-area{
+  width: 50%;
+  height: 50px;
+}
+.left{
+  position: relative;
+  left: 10px;
+  text-align: right;
+}
+.right{
+  text-align: left;
+  position: relative;
+  right: 10px;
+}
+.info-plan{
+  text-align: center;
+  color: #0E9F9B;
+  margin-top:1vh;
+  font-weight: 400;
+}
+.setting{
+  position: fixed;
+  right: -1px;
+  top: 10vh;
+  z-index: 999;
+  background: rgb(227,243,245);
+  color: #0E9F9B;
+  font-size: 10px;
+  border-radius: 5px;
+  padding: 3px;
+}
+.port{
+  height: 70px;
+  background: #F8FCFF;
+  border: 0px solid #F8FCFF;
+  box-shadow: 0px 0px 6px 1px rgba(101,101,101,0.29);
+  border-radius: 4px;
+  margin:0 10px;
+  position: relative;
+  margin-top:10px;
+}
+
+.plan{
+  height: 70px;
+  background: #F8FCFF;
+  border: 0px solid #F8FCFF;
+  box-shadow: 0px 0px 6px 1px rgba(101,101,101,0.29);
+  border-radius: 4px;
+  margin:0 10px;
+  position: relative;
+  margin-top:15px;
+}
+.port-image{
+  height: 40px;
+  width: 40px;
+  position: absolute;
+  top:15px;
+  left:20px;
+}
+.port-text{
+  position: absolute;
+  top:13px;
+  left:75px;
+  font-weight: bold;
+}
+.port-num{
+  position: absolute;
+  top:38px;
+  left:75px;
+  color: #B2B2B2;
+}
+.port-icon{
+  position: absolute;
+  top:30px;
+  right:5px;
+  width: 10px;
+  height: 16px;
+}
+.port-icon image{
+  width: 90%;
+}
+.body-bottom{
+padding:0 22px;
+}
+.body-bottom .info-content{
+  width: 30%;
+}
+.bottom-control{
+  height: 20vh;
+  margin: 0 2%;
+  margin-top:2vh;
+  line-height: 3vh;
+  background: #F8FCFF;
+  border: 0px solid #F8FCFF;
+  box-shadow: 0px 0px 6px 1px rgba(101,101,101,0.29);
+  border-radius: 4px;
+  padding:3%;
+}
+.control-btn{
+  display: inline-block;;
+  height: 60px;
+  width: 25%;
+  padding:10px 20px;
+  text-align: center;
+  font-size: 12px;
+  color: black;
+}
+.control-btn .btn-image{
+}
+</style>

+ 2 - 2
permission.js

@@ -2,10 +2,10 @@ import { getToken } from '@/utils/auth'
 
 // 登录页面
 const loginPage = "/pages/login"
-  
+
 // 页面白名单
 const whiteList = [
-  '/pages/login', '/pages/common/webview/index'
+  '/pages/login', '/pages/common/webview/index','/pages/bluetooth/index/index','/pages/weitiandi/bluetooth/index'
 ]
 
 // 检查地址白名单

+ 255 - 0
utils/weitiandi/device/device.js

@@ -0,0 +1,255 @@
+// #ifdef APP
+import ecUI from '@/utils/ecUI.js'
+import ecBLE from '@/utils/ecBLE/ecBLE.js'
+// #endif
+// #ifdef MP
+const ecUI = require('@/utils/ecUI.js')
+const ecBLE = require('@/utils/ecBLE/ecBLE.js')
+// #endif
+const deviceTool = {
+    //
+    startCharge(port){
+        let arr = [85,104,3,1,80,195,127];
+        if(port == 2){
+            arr = [85,104,3,2,80,195,128];
+        }
+        sendData(arr)
+    },
+    stopCharge(port){
+        let arr = [85,105,1,1,107];
+        if(port == 2){
+            arr = [85,105,1,2,108];
+        }
+        sendData(arr)
+    },
+    sendPortDetailCmd(){
+        let arr = [85,103,1,0,104];
+        sendData(arr)
+    },
+
+    restart(){
+        let arr = [85,117,1,0,118];
+        sendData(arr)
+    },
+    plan(port,time){
+        let arr = [85,104,5,1,80,95,7,0,152];
+
+    }
+
+}
+
+function sendData(arr){
+    arr = changeArr(arr);
+    let str = arr.join(" ");
+    return str;
+}
+
+function changeArr(arr){
+    const hexArr = arr.map(num => {
+       let str = num.toString(16); // 将每个数字转换为16进制字符串
+        if(str.length == 1){
+            return "0"+str.toUpperCase();
+        }else{
+            return str.toUpperCase();
+        }
+    });
+    return hexArr;
+}
+
+const dataParser = {
+/**
+ *     "data":[170,96,33,1,8,244,1,231,3,1,208,32,7,9,5,22,8,0,0,0,5,128,12,0,0,0,0,12,15,18,8,7,8,7,8,7,120]
+ *     "real_data":{"card_avail":1,"peak_price":8,"cost":500,"time_limit":999,"fee_type":1,"max_power":8400,"peak_service_price":7,"volume":9,"bottom_price":5,"botton_end":22,"bottom_start":8,"qr_id_low":0,"qr_id_middle":0,"qr_id_high":0,"bottom_service_price":5,"max_current":3200,"cp_check_off":0,"fee_show_off":0,"time1_end":12,"time2_end":15,"time3_end":18,"time1_price":8,"time1_price_service":7,"time2_price":8,"time2_sercie_price":7,"time3_price":8,"time3_service_price":7},"type":96}
+ */
+    mainboard:'CARD_AVAIL\n' +
+        'PEAK_PRICE\n' +
+        'COST 2\n' +
+        'TIME_LIMIT 2\n' +
+        'FEE_TYPE\n' +
+        'MAX_POWER 2\n' +
+        'PEAK_SERVICE_PRICE\n' +
+        'VOLUME\n' +
+        'BOTTOM_PRICE\n' +
+        'BOTTON_END\n' +
+        'BOTTOM_START\n' +
+        'QR_ID_LOW\n' +
+        'QR_ID_MIDDLE\n' +
+        'QR_ID_HIGH\n' +
+        'BOTTOM_SERVICE_PRICE\n' +
+        'MAX_CURRENT 2\n' +
+        'XXX\n' +
+        'XXX\n' +
+        'CP_CHECK_OFF\n' +
+        'FEE_SHOW_OFF\n' +
+        'TIME1_END\n' +
+        'TIME2_END\n' +
+        'TIME3_END\n' +
+        'TIME1_PRICE\n' +
+        'TIME1_PRICE_SERVICE\n' +
+        'TIME2_PRICE\n' +
+        'TIME2_SERCIE_PRICE\n' +
+        'TIME3_PRICE\n' +
+        'TIME3_SERVICE_PRICE',
+    portdetail:{
+        single:'PORT_FIRST_STATUS\n' +
+            'POWER 2\n' +
+            'ELEC 2\n' +
+            'MONEY 2\n' +
+            'TIME 2',
+        morlsingle:'PORT_FIRST_STATUS\n' +
+            'POWER 2\n' +
+            'ELEC 2\n' +
+            'MONEY 2\n' +
+            'TIME 2\n' +
+            'VOLTAGE\n' +
+            'DEV_TEMPER\n' +
+            'WIRE_TEMPER',
+        double:'PORT_FIRST_STATUS\n' +
+            'POWER 2\n' +
+            'ELEC 2\n' +
+            'MONEY 2\n' +
+            'TIME 2\n' +
+            'PORT_SECOND_STATUS\n' +
+            'POWER 2\n' +
+            'ELEC 2\n' +
+            'MONEY 2\n' +
+            'TIME 2'
+    }
+}
+function parseData(arr){
+    if(!arr){
+        return
+    }
+    let type = arr[1];
+    let str = "";
+    if(type == 96){//主板
+         str = dataParser.mainboard;
+    }
+    if(type == 103){
+      let len =  arr[2];
+        if(len == 18){
+            str = dataParser.portdetail.double;
+        }
+        if(len == 9){
+            str = dataParser.portdetail.single;
+        }
+        if(len == 13){
+            str = dataParser.portdetail.morlsingle;
+        }
+    }
+   return parseProp(arr,str)
+}
+function parseProp(arr,str){
+    let obj = {};
+    let keys = str.split("\n")
+    let index = 3;
+    for (let i = 0; i < keys.length; i++) {
+        let key = keys[i];
+        let keyProps = key.split(" ");
+        let num = 1;
+        if(keyProps.length == 2){
+            num = parseInt(keyProps[1],10);
+        }
+        let integers = [index,index+num-1];
+        let datas = [];
+        for (let j = integers[0]; j <= integers[integers.length-1]; j++) {
+            datas.push(arr[j]);
+        }
+        let aLong = cmdToDec(datas);
+        obj[keyProps[0].toLowerCase()] =  aLong;
+        index+=num;
+    }
+    return obj;
+}
+/**
+ * 将命令字符串转成十进制
+ * @param cmds
+ * @return
+ */
+function cmdToDec(cmds) {
+  if (!cmds) {
+    return -1;
+  }
+  let len = cmds.length;
+  if (len === 1) {
+    return cmds[0];
+  } else if (len === 2) {
+    let first = cmds[0];
+    let second = cmds[1];
+    let firstStr = addZero(first.toString(2));
+    let secondStr = addZero(second.toString(2));
+    let allStr = secondStr + firstStr;
+    let i = parseInt(allStr, 2);
+    return i;
+  } else if (len === 4) {
+    let first = cmds[0];
+    let second = cmds[1];
+    let third = cmds[2];
+    let forth = cmds[3];
+    let firstStr = addZero(first.toString(2));
+    let secondStr = addZero(second.toString(2));
+    let thirdStr = addZero(third.toString(2));
+    let forthStr = addZero(forth.toString(2));
+    let allStr = forthStr + thirdStr + secondStr + firstStr;
+    let i = parseInt(allStr, 2);
+    return i;
+  }
+  return 0;
+}
+function sendBlueData(tempSendData){
+    ecBLE.writeBLECharacteristicValue(tempSendData, false)
+}
+/**
+ * 二进制补0
+ * @param value
+ * @return
+ */
+function addZero(value) {
+  let len = value.length;
+  if (len < 8) {
+    for (let i = 0; i < 8 - len; i++) {
+      value = "0" + value;
+    }
+  }
+  return value;
+}
+
+/**
+ * 将十进制值转成cmd格式
+ * @param value
+ * @return
+ */
+function decToCmd(value) {
+  let cmds = null;
+  if (value <= 255) { //两位
+    cmds = [value];
+  } else if (value <= 65535) {
+    cmds = new Array(2);
+    let valueStr = value.toString(2);
+    let len = valueStr.length;
+    let lastEight = valueStr.substring(len - 8, len);
+    let firstEight = valueStr.substring(0, len - 8);
+    cmds[0] = parseInt(lastEight, 2);
+    cmds[1] = parseInt(firstEight, 2);
+  } else {
+    cmds = new Array(4);
+    let valueStr = value.toString(2);
+    let len = valueStr.length;
+    let lastEight = valueStr.substring(len - 8, len);
+    let firstEight = valueStr.substring(len - 16, len - 8);
+    let secondEight = valueStr.substring(len - 24, len - 16);
+    let thirdEight = valueStr.substring(0, len - 24);
+    cmds[0] = parseInt(lastEight, 2);
+    cmds[1] = parseInt(firstEight, 2);
+    cmds[2] = parseInt(secondEight, 2);
+    cmds[3] = parseInt(thirdEight, 2);
+  }
+  return cmds;
+}
+//parseData([170,103,18,1,0,0,54,5,0,0,0,0,2,241,25,67,3,75,0,77,0,159])
+export function sendPortDetailCmd(){
+    return new Promise(resolve => {
+        resolve()
+    });
+}
+