|
@@ -0,0 +1,341 @@
|
|
|
+// components/map-sense.js
|
|
|
+
|
|
|
+const innerAudioContext = wx.createInnerAudioContext();
|
|
|
+import http from '../../utils/http';
|
|
|
+import {promisify,BeaconUtils} from '../../utils/util';
|
|
|
+let openBluetoothAdapter = promisify(wx.openBluetoothAdapter)
|
|
|
+let startBeaconDiscovery = promisify(wx.startBeaconDiscovery)
|
|
|
+
|
|
|
+import { CDN_URL, CONNECT_STATUS, STATUS_TEXT, API_BASE_URL } from '../../config/index';
|
|
|
+const STATUS_PIC = {
|
|
|
+ '0': 'default',
|
|
|
+ '1': 'loading',
|
|
|
+ '2': 'success',
|
|
|
+ '3': 'fail'
|
|
|
+};
|
|
|
+
|
|
|
+// 选择6档
|
|
|
+const TXPOWER = 0
|
|
|
+
|
|
|
+// 距离经验值(调试所得)
|
|
|
+const N = 14
|
|
|
+
|
|
|
+
|
|
|
+let AveLength = 10
|
|
|
+
|
|
|
+Component({
|
|
|
+ /**
|
|
|
+ * 组件的属性列表
|
|
|
+ */
|
|
|
+ properties: {
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 组件的初始数据
|
|
|
+ */
|
|
|
+ data: {
|
|
|
+ status: "0",
|
|
|
+ cdn_url: CDN_URL,
|
|
|
+ connect_status: CONNECT_STATUS,
|
|
|
+ status_text: STATUS_TEXT,
|
|
|
+ status_pic: STATUS_PIC,
|
|
|
+ targetObj: {},
|
|
|
+ audio_address: {},
|
|
|
+ api_base_url: API_BASE_URL,
|
|
|
+ // 是否是扫码播放
|
|
|
+ isScanPlay: false,
|
|
|
+ cdn_url:CDN_URL,
|
|
|
+ classfiy:{}
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 组件的方法列表
|
|
|
+ */
|
|
|
+ methods: {
|
|
|
+ openBluetooth(cb) {
|
|
|
+ openBluetoothAdapter().then(res=>{
|
|
|
+ cb(res)
|
|
|
+ },()=>{
|
|
|
+ wx.showToast({
|
|
|
+ title: '请打开蓝牙',
|
|
|
+ icon: 'error',
|
|
|
+ duration: 2000
|
|
|
+ })
|
|
|
+ })
|
|
|
+ },
|
|
|
+ toHandle() {
|
|
|
+ let aveArr = []
|
|
|
+
|
|
|
+
|
|
|
+ this.openBluetooth(()=>{
|
|
|
+ startBeaconDiscovery({uuids: ['FDA50693-A4E2-4FB1-AFCF-C6EB07647825']}).then((res)=>{
|
|
|
+
|
|
|
+ wx.onBeaconUpdate(data=>{
|
|
|
+
|
|
|
+ //打印最新收集到的信号
|
|
|
+ console.log('beacon',data.beacons)
|
|
|
+ // 需要收集十组数据,索引号最大的组是最旧的
|
|
|
+ if (aveArr.length > AveLength) {
|
|
|
+ // aveArr[0] = data.beacons
|
|
|
+ //当超过十组时,应该将索引号大的组淘汰掉
|
|
|
+ aveArr.pop()
|
|
|
+ }
|
|
|
+
|
|
|
+ aveArr.unshift(data.beacons) //在队列前面插入
|
|
|
+
|
|
|
+ // console.log('aveArr',aveArr);
|
|
|
+ let all = []
|
|
|
+ aveArr.forEach(item => {
|
|
|
+ // console.log(aveArr.length,item)
|
|
|
+ all = all.concat(item)
|
|
|
+ });
|
|
|
+ // classfiy = {10003:[{},{},···],10002:[{},{},···],10001:[{},{},···]}
|
|
|
+ // console.log('all',all)
|
|
|
+ let classfiy = BeaconUtils.classification(all,'major')
|
|
|
+ let accuracyList = {} // 存放处理后的accuary
|
|
|
+ // let dataArr = [] //记录各信标的信号收集数目
|
|
|
+ Object.keys(classfiy).forEach(key=>{
|
|
|
+ //每个major的AveLength个元素数组,元素为rssi
|
|
|
+ let arr = classfiy[key].map(item=>{
|
|
|
+ return item.rssi
|
|
|
+ })
|
|
|
+ //每个major的rssi平均值
|
|
|
+ // console.log(key,'rssi',arr)
|
|
|
+ let ave = BeaconUtils.arrayAverage(arr)
|
|
|
+ // console.log('ave',ave)
|
|
|
+ //计算平均差
|
|
|
+ let meanDeviation = BeaconUtils.getMeanDeviation(arr,ave);
|
|
|
+ // console.log('meanDeviation',meanDeviation)
|
|
|
+ //计算各rssi的高斯模糊权重
|
|
|
+ let guassionArr = [];
|
|
|
+ for(let i = 0; i < arr.length; ++i){
|
|
|
+ // console.log('guassionArr ele',BeaconUtils.getOneGuassionArray(arr.length,i,meanDeviation))
|
|
|
+ // 返回的可能是空数组
|
|
|
+ guassionArr.push(BeaconUtils.getOneGuassionArray(arr.length,i,meanDeviation));
|
|
|
+ }
|
|
|
+ // console.log('guassionArr',guassionArr)
|
|
|
+ //计算高斯模糊后的rssi值
|
|
|
+ let rssiArr = []; //模糊后的rssi数组
|
|
|
+ for(let i = 0; i < arr.length; ++i){
|
|
|
+ let sum = 0;
|
|
|
+ for(let j = 0; j <arr.length; ++j){
|
|
|
+ sum += guassionArr[i][j] * arr[j]
|
|
|
+ }
|
|
|
+ rssiArr.push(sum);
|
|
|
+ // console.log('sum',sum)
|
|
|
+ }
|
|
|
+ // console.log('rssiArr',rssiArr);
|
|
|
+ //时间加权后求rssi平均值
|
|
|
+ let aveOnTime = BeaconUtils.arrayAverage(rssiArr.slice(Math.floor(0,1)).concat(rssiArr));
|
|
|
+ // console.log('aveOnTime',aveOnTime)
|
|
|
+ //测距
|
|
|
+
|
|
|
+ classfiy[key].forEach(item=>{
|
|
|
+ item.accuracy = BeaconUtils.calculateAccuracy(TXPOWER,aveOnTime,N)
|
|
|
+ if(!accuracyList[key]){
|
|
|
+ //如果还没有对应的“信标号”
|
|
|
+ accuracyList[key] = [item.accuracy]
|
|
|
+ }
|
|
|
+ accuracyList[key].push(item.accuracy)
|
|
|
+ // console.log('item',item)
|
|
|
+ })
|
|
|
+
|
|
|
+ // dataArr.push(classfiy[key].length)
|
|
|
+
|
|
|
+ })
|
|
|
+ // console.log(classfiy['10001'])
|
|
|
+ // console.log(classfiy['10002'])
|
|
|
+ // console.log(classfiy['10003'])
|
|
|
+ console.log(classfiy)
|
|
|
+
|
|
|
+ // 筛选器,筛选出配对的一组信标
|
|
|
+ let aveAccuracys = new Map() //信标的平均距离,用于判断是否在范围内
|
|
|
+ let matchSigns = [] //匹配的信号
|
|
|
+ let prologue = ['1000110002'] //序厅
|
|
|
+ let annexHall = ['1000310004'] //附厅
|
|
|
+ let mainHall = ['1000510006'] //主厅
|
|
|
+ let area = [prologue,annexHall,mainHall]
|
|
|
+ const R = 3.8 //设定范围半径
|
|
|
+ Object.keys(accuracyList).forEach(key=>{
|
|
|
+ let aveAccuracy = BeaconUtils.arrayAverage(accuracyList[key])
|
|
|
+ if(aveAccuracy < R){
|
|
|
+ aveAccuracys.set(key,aveAccuracy)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ //理想情况下只有两个信标的信号,刚好匹配为一组
|
|
|
+ //判断编号是奇数偶数
|
|
|
+ let result = ''
|
|
|
+ for(let key of aveAccuracys.keys()){
|
|
|
+ let num = parseInt(key)
|
|
|
+ if(num % 2 == 0){
|
|
|
+ if(aveAccuracys.has(String(num - 1))){
|
|
|
+ num--
|
|
|
+ result = key + num
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }else if(aveAccuracys.has(String(num + 1))){
|
|
|
+ num++
|
|
|
+ result = key + num
|
|
|
+ break
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ console.log('result',result);
|
|
|
+ for(let i = 0; i < area.length; ++i){
|
|
|
+ if(area[i].includes(result)){
|
|
|
+ console.log(i)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // 计算方差
|
|
|
+ //计算平均数
|
|
|
+ // let x = BeaconUtils.arrayAverage(dataArr)
|
|
|
+ // let variance = BeaconUtils.getVariance(dataArr,x)
|
|
|
+ //打印收集到各种信号数目的方差
|
|
|
+ // console.log('txPower=',TXPOWER," 方差:",BeaconUtils.repeat('--',Math.floor(variance)))
|
|
|
+
|
|
|
+ // 定位
|
|
|
+ // 将三个信标构成直角三角形,其中10002号信标为直角,10001号为基点
|
|
|
+ // 根据挡位设定相邻顶点信标的距离,5档,设边长为10m
|
|
|
+ // let sideLength = 5
|
|
|
+ // let distance1,distance2,distance3 //分别对应游客到信标10001,1002,10003的距离
|
|
|
+ // distance1 = BeaconUtils.arrayAverage(accuracyList['10001'])
|
|
|
+ // distance2 = BeaconUtils.arrayAverage(accuracyList['10002'])
|
|
|
+ // distance3 = BeaconUtils.arrayAverage(accuracyList['10003'])
|
|
|
+ // let px = (Math.pow(2.8,2) - Math.pow(distance2,2) + Math.pow(distance1,2)) / (2.8 * 2)
|
|
|
+ // let py = (Math.pow(5.6,2) - Math.pow(distance3,2) + Math.pow(distance2,2)) / (5.6 * 2)
|
|
|
+ // console.log('px',px,' py',py)
|
|
|
+
|
|
|
+ this.setData({
|
|
|
+ classfiy,
|
|
|
+ status:'2'
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }).catch(()=>{
|
|
|
+ wx.showToast({
|
|
|
+ title: '连接失败',
|
|
|
+ icon: 'error',
|
|
|
+ duration: 500
|
|
|
+ })
|
|
|
+ })
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ stopBeaconDiscovery() {
|
|
|
+ var that = this;
|
|
|
+ console.log('这是取消连接')
|
|
|
+ wx.showToast({
|
|
|
+ title: '取消连接成功',
|
|
|
+ icon: 'error',
|
|
|
+ duration: 1000
|
|
|
+ })
|
|
|
+ wx.stopBeaconDiscovery({})
|
|
|
+ // 取消连接 停止播放音乐 目标对象置为{} 设置为第一次进入
|
|
|
+ innerAudioContext.stop();
|
|
|
+ that.setData({
|
|
|
+ status: '0',
|
|
|
+ targetObj: {}
|
|
|
+ })
|
|
|
+ },
|
|
|
+ // 扫一扫
|
|
|
+ toScanCode() {
|
|
|
+ var that = this;
|
|
|
+ that.setData({
|
|
|
+ isScanPlay: true
|
|
|
+ })
|
|
|
+ wx.scanCode({
|
|
|
+ success(res) {
|
|
|
+ console.log('success', res)
|
|
|
+ console.log('result', res['result'])
|
|
|
+ console.log('innerAudioContext', innerAudioContext)
|
|
|
+ that.setData({ targetObj: {} })
|
|
|
+ innerAudioContext.autoplay = true;
|
|
|
+ innerAudioContext.src = res['result']
|
|
|
+ innerAudioContext.loop = true;
|
|
|
+ innerAudioContext.play();
|
|
|
+ },
|
|
|
+ fail: function (res) {
|
|
|
+ console.log('fail innerAudioContext', innerAudioContext)
|
|
|
+ that.setData({
|
|
|
+ isScanPlay: false
|
|
|
+ })
|
|
|
+ innerAudioContext.play();
|
|
|
+ return;
|
|
|
+ },
|
|
|
+ complete(){
|
|
|
+ // console.log()
|
|
|
+ that.setData({
|
|
|
+ isScanPlay: false
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ getAudios() {
|
|
|
+ http.get('/api/web/getAudioIndex')
|
|
|
+ .then(res => {
|
|
|
+ let { data } = res,target = {};
|
|
|
+ data.forEach(item => {
|
|
|
+ switch (item.type) {
|
|
|
+ case 1:
|
|
|
+ target['10001'] = `${this.data.api_base_url}/data/${item.audio}`;
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ target['10002'] = `${this.data.api_base_url}/data/${item.audio}`;
|
|
|
+ break;
|
|
|
+ case 3:
|
|
|
+ target['10003'] = `${this.data.api_base_url}/data/${item.audio}`;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break
|
|
|
+ }
|
|
|
+ })
|
|
|
+ this.setData({
|
|
|
+ audio_address: target
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
+ },
|
|
|
+ lifetimes:{
|
|
|
+ attached: function () {
|
|
|
+ innerAudioContext.stop();
|
|
|
+ //获取语音
|
|
|
+ this.getAudios();
|
|
|
+
|
|
|
+ var that = this;
|
|
|
+ // wx.onAccelerometerChange(function (e) {
|
|
|
+ // console.log('手机咚咚咚给')
|
|
|
+ // if (Math.abs(e.x) > 1.1 && Math.abs(e.y) > 1.1) {
|
|
|
+ // // wx.showToast({ title: "摇一摇" })
|
|
|
+ // } else if (Math.abs(e.x) > 0.07 && Math.abs(e.y) > 0.02 && that.data.status === '2') {
|
|
|
+ // // 扫一扫播放的话 移动无效
|
|
|
+ // if (that.data.isScanPlay) return;
|
|
|
+
|
|
|
+ // that.startBeaconDiscovery()
|
|
|
+ // } else {
|
|
|
+ // // wx.showToast({ title: "静止" })
|
|
|
+ // }
|
|
|
+ // }),
|
|
|
+ innerAudioContext.onEnded(() => {
|
|
|
+ console.log('播放结束了')
|
|
|
+ if (this.data.isScanPlay) {
|
|
|
+ innerAudioContext.stop()
|
|
|
+ this.setData({ isScanPlay: false })
|
|
|
+ this.targetObj = {}
|
|
|
+ console.log('innerAudioContext', innerAudioContext)
|
|
|
+ if (this.data.status == 2) {
|
|
|
+ console.log(2222222222222222)
|
|
|
+ this.startBeaconDiscovery()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ detached: function () {
|
|
|
+ innerAudioContext.stop();
|
|
|
+ innerAudioContext.destroy();
|
|
|
+ wx.stopBeaconDiscovery({})
|
|
|
+ this.setData({status:"0"})
|
|
|
+ }
|
|
|
+ }
|
|
|
+})
|