123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507 |
- // components/map-sense.js
- let innerAudioContext = wx.createInnerAudioContext({
- useWebAudioImplement: true,
- });
- import { promisify, BeaconUtils } from "../../utils/util";
- let openBluetoothAdapter = promisify(wx.openBluetoothAdapter);
- let startBeaconDiscovery = promisify(wx.startBeaconDiscovery);
- let stopBeaconDiscovery = promisify(wx.stopBeaconDiscovery);
- let app = getApp();
- import {
- CDN_URL,
- CONNECT_STATUS,
- STATUS_TEXT,
- API_BASE_URL,
- DISTRIBUTION,
- AudioAddress,
- } from "../../config/index";
- const STATUS_PIC = {
- 0: "default",
- 1: "loading",
- 2: "success",
- 3: "fail",
- };
- let audioInterruptionCb = () => {};
- let bluetoothAdapterStateChangeCb = () => {};
- let isCollect = false;
- let hadshowModal = false
- let checkCollect = null
- let checkTimeout = null
- let updateingBeacon = false
- let updateTO = null
- let changeTO = null;
- // 选择6档
- const TXPOWER = -55;
- var result = 0,
- oldResult = -1;
- // 距离经验值(调试所得)
- const N = 3.3;
- const R = 3.4; //设定感应范围半径
- const RSSIVAL = 70; //rssi信号过滤临界点
- let AveLength = 10;
- let group = [
- ["10001", "10002"],
- ["10003"],
- ["10004"],
- ["10005", "10006"],
- ["10007"],
- ["10008"],
- ["10009"],
- ["10010"],
- ["10011"],
- ["10012", "10013"],
- ["10014"],
- ["10015"],
- ["10016"],
- ["10017"],
- ["10018"],
- ["10019"],
- ["10020", "10021"],
- ["10022"],
- ["10023"],
- ["10024"],
- ];
- // 1:['10001','10002'],2:['10003'],
- // 3:['10004'],4:['10005'],5:['10006'],
- // 6:['10007'],7:['10008'],8:['10009'],
- // 9:['10010'],10:['10011'],11:['10012','10013'],
- // 12:['10014'],13:['10015'],14:['10016'],
- // 15:['10017'],16:['10018'],17:['10019'],
- // 18:['10020','10021'],19:['10022'],
- // 20:['10023'],21:['10024']
- Component({
- /**
- * 组件的属性列表
- */
- properties: {},
- /**
- * 组件的初始数据
- */
- data: {
- status: "0",
- isAndroid:app.globalData.userInfo.system.toLowerCase().indexOf("android")>-1,
- 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) {
- wx.showLoading({
- title: "正在打开蓝牙…",
- mask: true,
- });
- openBluetoothAdapter().then(
- (res) => {
- wx.hideLoading({ fail() {} });
- cb(res);
- // if (app.globalData.userInfo.system.toLowerCase().indexOf("android")>-1) {
- // wx.getLocation({
- // type: "gcj02", //返回可以用于wx.openLocation的经纬度
- // success: () => {
- // cb(res);
- // },
- // fail: (err) => {
- // console.log(err);
- // wx.showToast({
- // title: "请打开手机定位服务",
- // icon: "error",
- // duration: 500,
- // });
- // },
- // });
- // } else {
- // cb(res);
- // }
- },
- () => {
- wx.hideLoading({ fail() {} });
- wx.showToast({
- title: "请打开蓝牙",
- icon: "error",
- duration: 2000,
- });
- }
- );
- },
- toHandle() {
- if (this.data.status == "2") {
- this.stopBeaconDiscovery();
- return;
- }
- let aveArr = [];
- this.openBluetooth(() => {
- wx.showLoading({
- title: "正在连接…",
- mask: true,
- });
- startBeaconDiscovery({
- uuids: ["FDA50693-A4E2-4FB1-AFCF-C6EB07647825"],
- })
- .then(() => {
- wx.hideLoading({ fail() {} });
- this.setData({
- status: "2",
- });
- isCollect = true;
- updateingBeacon = false
- if (this.data.isAndroid) {
- checkCollect && clearInterval(checkCollect)
- checkTimeout && clearTimeout(checkTimeout)
- checkTimeout = setTimeout(() => {
- checkCollect = setInterval(() => {
- if (!updateingBeacon) {
- if (!hadshowModal) {
- hadshowModal = true
- wx.showModal({
- title: "请检查手机定位服务、蓝牙和网络是否保持打开状态",
- showCancel: false,
- success:()=>{
- this.resetPage()
- checkCollect && clearInterval(checkCollect)
- checkTimeout && clearTimeout(checkTimeout)
- hadshowModal = false
- }
- });
- }
- }
- }, 1000)
- }, 2000);
- }
- wx.onBeaconUpdate((data) => {
- console.log(data, "onBeaconUpdate");
- if (!isCollect) {
- return;
- }
- if (this.data.isAndroid) {
- updateTO && clearTimeout(updateTO)
- updateTO = setTimeout(() => {
- console.log('重置updateingBeacon');
- updateingBeacon = false
- }, 3000);
- updateingBeacon = true
- }
- console.log("还在收集…………");
- // 需要收集十组数据,索引号最大的组是最旧的
- if (!aveArr.includes(data.beacons)) {
- if (aveArr.length >= AveLength) {
- //当超过十组时,应该将索引号大的组淘汰掉
- aveArr.pop();
- }
- aveArr.unshift(BeaconUtils.clone(data.beacons)); //在队列前面插入
- }
- let all = []; //获取所有data.beacons数据
- for (let i = 0; i < aveArr.length; i++) {
- let ele = aveArr[i];
- for (let j = 0; j < ele.length; j++) {
- let item = ele[j];
- //过滤信号弱的数据
- if (!(item.proximity === 0 && item.rssi === 0)) {
- if (Math.abs(item.rssi) < RSSIVAL) {
- // console.log(item.proximity,item.rssi);
- if (!all.includes(item)) {
- all.push(BeaconUtils.clone(item));
- }
- }
- }
- }
- }
- let accuracyList = {};
- // classfiy = {10003:[{},{},···],10002:[{},{},···],10001:[{},{},···]}
- let classfiy = BeaconUtils.classification(all, "major");
- // console.log(classfiy,'classfiy');
- Object.keys(classfiy).forEach((key) => {
- //每个major的AveLength个元素数组,元素为rssi
- let arr = classfiy[key].map((item) => {
- return item.rssi;
- });
- //每个major的rssi平均值
- let ave = BeaconUtils.arrayAverage(arr);
- //计算平均差
- let meanDeviation = BeaconUtils.getMeanDeviation(arr, ave);
- //计算各rssi的高斯模糊权重
- let guassionArr = []; //存放权重数组
- for (let i = 0; i < arr.length; ++i) {
- guassionArr.push(
- BeaconUtils.getOneGuassionArray(
- arr.length,
- i,
- meanDeviation
- )
- );
- }
- //计算高斯模糊后的rssi值
- let rssiArr = []; //模糊后的rssi数组
- for (let i = 0; i < arr.length; ++i) {
- let sum = 0;
- for (let j = 0; j < arr.length; ++j) {
- if (guassionArr[i].length == 0) {
- sum = arr[j];
- break;
- }
- sum += guassionArr[i][j] * arr[j];
- }
- rssiArr.push(sum);
- }
- //时间加权后求rssi平均值
- let aveOnTime = BeaconUtils.arrayAverage(
- rssiArr
- .slice(0, Math.floor(rssiArr.length / 3))
- .concat(rssiArr)
- );
- //测距,根据时间加权后的rssi计算距离
- // classfiy[key].forEach((item) => {
- let tmp = BeaconUtils.calculateAccuracy(TXPOWER, aveOnTime, N);
- if (!accuracyList[key]) {
- //如果还没有对应的“信标号”
- accuracyList[key] = [tmp];
- } else {
- accuracyList[key].push(tmp);
- }
- // });
- });
- Object.keys(accuracyList).forEach((item) => {
- console.log(accuracyList[item] + "---------" + item);
- });
- console.log("--------分隔--------");
- // 筛选器,筛选出配对的一组信标
- let signSelect = new Array(21).fill(0); //记录各组的信标出现数量,投票选择最多的,依次是prologue,annexHall,mainHall
- // const prologue = ['10001','10002'] //序厅
- // const annexHall = ['10003','10004','10005','10006','10007'] //附厅
- // const mainHall = ['10008'] //主厅
- Object.keys(accuracyList).forEach((key) => {
- let aveAccuracy = BeaconUtils.arrayAverage(accuracyList[key]);
- if (aveAccuracy < R) {
- for (let i = 0; i < group.length; i++) {
- if (group[i].includes(key)) {
- signSelect[i] += 1 / (aveAccuracy + 0.01); //取距离的反比例函数值,距离越近,值越大,+0.01是为了防止除数为0
- }
- }
- }
- });
- console.log(signSelect);
- //对小于预设半径的信号进行数量投票
- result = BeaconUtils.maxIndex(signSelect);
- console.log("result", result);
- if (result != null && result !== oldResult) {
- wx.hideLoading({ fail() {} });
- this.playAudio(AudioAddress[result]);
- oldResult = result;
- }
- if (result === null && oldResult != -1) {
- wx.showLoading({
- title: "音频切换中…",
- mask: true,
- });
- changeTO && clearTimeout(changeTO);
- changeTO = setTimeout(() => {
- wx.hideLoading({ fail() {} });
- }, 4000);
- this.stopAndDestroyAudio();
- }
- let temp = DISTRIBUTION.find((item) => {
- return item.position.some((sub) => sub == result);
- });
- this.setData({
- classfiy,
- targetObj: temp || {},
- result,
- });
- });
- })
- .catch((err) => {
- console.log(err,'1111');
- if (err.errCode == 11002) {
- wx.showToast({
- title: "请打开手机定位服务",
- icon: "error",
- duration: 500,
- });
- } else {
- wx.showToast({
- title: "连接失败",
- icon: "error",
- duration: 500,
- });
- }
- });
- });
- },
- stopAndDestroyAudio() {
- oldResult = -1;
- if (!innerAudioContext) {
- return;
- }
- innerAudioContext.pause();
- innerAudioContext.stop();
- innerAudioContext.src = null;
- innerAudioContext.destroy();
- innerAudioContext = null;
- },
- playAudio(src) {
- if (!innerAudioContext) {
- innerAudioContext = wx.createInnerAudioContext({
- useWebAudioImplement: true,
- });
- }
- innerAudioContext.src = src;
- innerAudioContext.loop = true;
- innerAudioContext.onCanplay(() => {
- innerAudioContext.play();
- });
- // innerAudioContext.play();
- },
- stopBeaconDiscovery(notips = null) {
- console.log("这是取消连接");
- // 取消连接 停止播放音乐 目标对象置为{} 设置为第一次进入
- checkCollect && clearInterval(checkCollect)
- checkTimeout && clearTimeout(checkTimeout)
- updateTO && clearTimeout(updateTO)
- this.stopAndDestroyAudio();
- this.reset();
- isCollect = false;
- stopBeaconDiscovery()
- .then(() => {
- !notips &&
- wx.showToast({
- title: "取消连接成功",
- icon: "error",
- duration: 1000,
- });
- })
- .catch((err) => {
- console.log(err);
- });
- },
- reset() {
- this.setData({
- status: "0",
- targetObj: {},
- });
- },
- // 扫一扫
- toScanCode() {
- this.setData({
- isScanPlay: true,
- });
- wx.scanCode({
- success: (res) => {
- this.stopBeaconDiscovery(true);
- this.playAudio(res["result"]);
- },
- fail: () => {
- console.log("fail innerAudioContext", innerAudioContext);
- this.setData({
- isScanPlay: false,
- });
- return;
- },
- complete() {
- this.setData({
- isScanPlay: false,
- });
- },
- });
- },
- resetPage() {
- this.stopBeaconDiscovery(true);
- },
- },
- lifetimes: {
- attached: function () {
- audioInterruptionCb = () => {
- console.log(innerAudioContext);
- if (innerAudioContext) {
- this.resetPage();
- }
- };
- bluetoothAdapterStateChangeCb = (res) => {
- if (!Boolean(res.available)) {
- this.resetPage();
- }
- };
- wx.onAudioInterruptionEnd(audioInterruptionCb);
- wx.onBluetoothAdapterStateChange(bluetoothAdapterStateChangeCb);
- wx.onAppShow(audioInterruptionCb);
- app.events.on('network', this, (data) =>{
- if (!data) {
- this.resetPage();
- }
- })
- },
- detached: function () {
- this.resetPage();
- wx.offAudioInterruptionEnd(audioInterruptionCb);
- wx.offBluetoothAdapterStateChange(bluetoothAdapterStateChangeCb);
- wx.offAppShow(audioInterruptionCb);
- app.events.remove('network',this)
- },
- },
- });
|