map-sense.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. // components/map-sense.js
  2. const innerAudioContext = wx.createInnerAudioContext();
  3. import http from '../../utils/http';
  4. import {promisify,BeaconUtils} from '../../utils/util';
  5. let openBluetoothAdapter = promisify(wx.openBluetoothAdapter)
  6. let startBeaconDiscovery = promisify(wx.startBeaconDiscovery)
  7. import { CDN_URL, CONNECT_STATUS, STATUS_TEXT, API_BASE_URL } from '../../config/index';
  8. const STATUS_PIC = {
  9. '0': 'default',
  10. '1': 'loading',
  11. '2': 'success',
  12. '3': 'fail'
  13. };
  14. // 选择6档
  15. const TXPOWER = -55
  16. var result = 0,oldResult = -1;
  17. // 距离经验值(调试所得)
  18. const N = 3.3
  19. let AveLength = 10
  20. let AudioAddress={
  21. 0:'https://culture.4dage.com/demo/audio/1.2.mp3',
  22. 1:'https://culture.4dage.com/demo/audio/3.mp3',
  23. 2:'https://culture.4dage.com/demo/audio/4.mp3',
  24. 3:'https://culture.4dage.com/demo/audio/5.mp3',
  25. 4:'https://culture.4dage.com/demo/audio/6.mp3',
  26. 5:'https://culture.4dage.com/demo/audio/7.mp3',
  27. 6:'https://culture.4dage.com/demo/audio/8.mp3',
  28. 7:'https://culture.4dage.com/demo/audio/9.mp3',
  29. 8:'https://culture.4dage.com/demo/audio/10.mp3',
  30. 9:'https://culture.4dage.com/demo/audio/11.mp3',
  31. 10:'https://culture.4dage.com/demo/audio/12.13.mp3',
  32. 11:'https://culture.4dage.com/demo/audio/14.mp3',
  33. 12:'https://culture.4dage.com/demo/audio/15.mp3',
  34. 13:'https://culture.4dage.com/demo/audio/16.mp3',
  35. 14:'https://culture.4dage.com/demo/audio/17.mp3',
  36. 15:'https://culture.4dage.com/demo/audio/18.mp3',
  37. 16:'https://culture.4dage.com/demo/audio/19.mp3',
  38. 17:'https://culture.4dage.com/demo/audio/20.21.mp3',
  39. 18:'https://culture.4dage.com/demo/audio/22.mp3',
  40. 19:'https://culture.4dage.com/demo/audio/23.mp3',
  41. 20:'https://culture.4dage.com/demo/audio/24.mp3',
  42. }
  43. Component({
  44. /**
  45. * 组件的属性列表
  46. */
  47. properties: {
  48. },
  49. /**
  50. * 组件的初始数据
  51. */
  52. data: {
  53. status: "0",
  54. cdn_url: CDN_URL,
  55. connect_status: CONNECT_STATUS,
  56. status_text: STATUS_TEXT,
  57. status_pic: STATUS_PIC,
  58. targetObj: {},
  59. audio_address: {},
  60. api_base_url: API_BASE_URL,
  61. // 是否是扫码播放
  62. isScanPlay: false,
  63. cdn_url:CDN_URL,
  64. classfiy:{}
  65. },
  66. /**
  67. * 组件的方法列表
  68. */
  69. methods: {
  70. openBluetooth(cb) {
  71. openBluetoothAdapter().then(res=>{
  72. cb(res)
  73. },()=>{
  74. wx.showToast({
  75. title: '请打开蓝牙',
  76. icon: 'error',
  77. duration: 2000
  78. })
  79. })
  80. },
  81. toHandle() {
  82. let aveArr = []
  83. this.openBluetooth(()=>{
  84. startBeaconDiscovery({uuids: ['FDA50693-A4E2-4FB1-AFCF-C6EB07647825']}).then((res)=>{
  85. wx.onBeaconUpdate(data=>{
  86. // 需要收集十组数据,索引号最大的组是最旧的
  87. if (aveArr.length > AveLength) {
  88. //当超过十组时,应该将索引号大的组淘汰掉
  89. aveArr.pop()
  90. }
  91. aveArr.unshift(data.beacons) //在队列前面插入
  92. let all = []
  93. aveArr.forEach(item => {
  94. all = all.concat(item)
  95. });
  96. // classfiy = {10003:[{},{},···],10002:[{},{},···],10001:[{},{},···]}
  97. let classfiy = BeaconUtils.classification(all,'major')
  98. let accuracyList = {} // 存放处理后的accuary
  99. Object.keys(classfiy).forEach(key=>{
  100. //每个major的AveLength个元素数组,元素为rssi
  101. let arr = classfiy[key].map(item=>{
  102. return item.rssi
  103. })
  104. //每个major的rssi平均值
  105. let ave = BeaconUtils.arrayAverage(arr)
  106. //计算方差
  107. let meanDeviation = BeaconUtils.getVariance(arr,ave);
  108. //计算各rssi的高斯模糊权重
  109. let guassionArr = []; //存放权重数组
  110. for(let i = 0; i < arr.length; ++i){
  111. guassionArr.push(BeaconUtils.getOneGuassionArray(arr.length,i,meanDeviation));
  112. }
  113. //计算高斯模糊后的rssi值
  114. let rssiArr = []; //模糊后的rssi数组
  115. for(let i = 0; i < arr.length; ++i){
  116. let sum = 0;
  117. for(let j = 0; j <arr.length; ++j){
  118. if(guassionArr[i].length == 0){
  119. sum = arr[j]
  120. break;
  121. }
  122. sum += guassionArr[i][j] * arr[j]
  123. }
  124. rssiArr.push(sum);
  125. }
  126. //时间加权后求rssi平均值
  127. let aveOnTime = BeaconUtils.arrayAverage(rssiArr.slice(0,Math.floor(rssiArr.length / 3)).concat(rssiArr));
  128. //测距,根据时间加权后的rssi计算距离
  129. classfiy[key].forEach(item=>{
  130. item.accuracy = BeaconUtils.calculateAccuracy(TXPOWER,aveOnTime,N)
  131. if(!accuracyList[key]){
  132. //如果还没有对应的“信标号”
  133. accuracyList[key] = [item.accuracy]
  134. }
  135. accuracyList[key].push(item.accuracy)
  136. })
  137. })
  138. // 筛选器,筛选出配对的一组信标
  139. let signSelect = new Array(21).fill(0); //记录各组的信标出现数量,投票选择最多的,依次是prologue,annexHall,mainHall
  140. // const prologue = ['10001','10002'] //序厅
  141. // const annexHall = ['10003','10004','10005','10006','10007'] //附厅
  142. // const mainHall = ['10008'] //主厅
  143. let group = [
  144. ['10001','10002'],['10003'],
  145. ['10004'],['10005'],['10006'],
  146. ['10007'],['10008'],['10009'],
  147. ['10010'],['10011'],['10012','10013'],
  148. ['10014'],['10015'],['10016'],
  149. ['10017'],['10018'],['10019'],
  150. ['10020','10021'],['10022'],
  151. ['10023'],['10024']
  152. ];
  153. // 1:['10001','10002'],2:['10003'],
  154. // 3:['10004'],4:['10005'],5:['10006'],
  155. // 6:['10007'],7:['10008'],8:['10009'],
  156. // 9:['10010'],10:['10011'],11:['10012','10013'],
  157. // 12:['10014'],13:['10015'],14:['10016'],
  158. // 15:['10017'],16:['10018'],17:['10019'],
  159. // 18:['10020','10021'],19:['10022'],
  160. // 20:['10023'],21:['10024']
  161. const R = 2.1 //设定范围半径
  162. // console.log(accuracyList);
  163. Object.keys(accuracyList).forEach(key=>{
  164. let aveAccuracy = BeaconUtils.arrayAverage(accuracyList[key])
  165. if(aveAccuracy < R){
  166. // if(prologue.includes(key)){
  167. // signSelect[0] += 1;
  168. // }else if(annexHall.includes(key)){
  169. // signSelect[1] += 1;
  170. // }else if(mainHall.includes(key)){
  171. // signSelect[2] += 1;
  172. // }
  173. for(let i = 0;i<group.length;i++){
  174. if(group[i].includes(key)){
  175. signSelect[i] += accuracyList[key].length;
  176. }
  177. }
  178. }
  179. })
  180. // console.log(signSelect);
  181. //对小于预设半径的信号进行数量投票
  182. result = BeaconUtils.maxIndex(signSelect);
  183. console.log('result',result);
  184. if(result!=null && result != oldResult){
  185. innerAudioContext.stop();
  186. innerAudioContext.destroy();
  187. innerAudioContext.autoplay = true;
  188. innerAudioContext.src = AudioAddress[result];
  189. // console.log(innerAudioContext.src);
  190. innerAudioContext.play();
  191. oldResult = result;
  192. }else{
  193. innerAudioContext.play();
  194. }
  195. innerAudioContext.stop();
  196. innerAudioContext.destroy();
  197. innerAudioContext.autoplay = true;
  198. innerAudioContext.src = AudioAddress[result]
  199. innerAudioContext.play();
  200. this.setData({
  201. classfiy,
  202. result,
  203. status:'2'
  204. })
  205. })
  206. }).catch(()=>{
  207. wx.showToast({
  208. title: '连接失败',
  209. icon: 'error',
  210. duration: 500
  211. })
  212. })
  213. })
  214. },
  215. stopBeaconDiscovery() {
  216. var that = this;
  217. console.log('这是取消连接')
  218. wx.showToast({
  219. title: '取消连接成功',
  220. icon: 'error',
  221. duration: 1000
  222. })
  223. wx.stopBeaconDiscovery({})
  224. // 取消连接 停止播放音乐 目标对象置为{} 设置为第一次进入
  225. innerAudioContext.stop();
  226. that.setData({
  227. status: '0',
  228. targetObj: {}
  229. })
  230. },
  231. // 扫一扫
  232. toScanCode() {
  233. var that = this;
  234. that.setData({
  235. isScanPlay: true
  236. })
  237. wx.scanCode({
  238. success(res) {
  239. console.log('success', res)
  240. console.log('result', res['result'])
  241. console.log('innerAudioContext', innerAudioContext)
  242. that.setData({ targetObj: {} })
  243. innerAudioContext.autoplay = true;
  244. innerAudioContext.src = res['result']
  245. innerAudioContext.loop = true;
  246. innerAudioContext.play();
  247. },
  248. fail: function (res) {
  249. console.log('fail innerAudioContext', innerAudioContext)
  250. that.setData({
  251. isScanPlay: false
  252. })
  253. innerAudioContext.play();
  254. return;
  255. },
  256. complete(){
  257. // console.log()
  258. that.setData({
  259. isScanPlay: false
  260. })
  261. }
  262. })
  263. },
  264. getAudios() {
  265. http.get('/api/web/getAudioIndex')
  266. .then(res => {
  267. console.log(res);
  268. let { data } = res,target = {};
  269. data.forEach(item => {
  270. switch (item.type) {
  271. case 1:
  272. target['10001'] = `${this.data.api_base_url}/data/${item.audio}`;
  273. break;
  274. case 2:
  275. target['10002'] = `${this.data.api_base_url}/data/${item.audio}`;
  276. break;
  277. case 3:
  278. target['10003'] = `${this.data.api_base_url}/data/${item.audio}`;
  279. break;
  280. default:
  281. break
  282. }
  283. })
  284. this.setData({
  285. audio_address: target,
  286. })
  287. })
  288. }
  289. },
  290. lifetimes:{
  291. attached: function () {
  292. innerAudioContext.stop();
  293. //获取语音
  294. // this.getAudios();
  295. var that = this;
  296. // wx.onAccelerometerChange(function (e) {
  297. // console.log('手机咚咚咚给')
  298. // if (Math.abs(e.x) > 1.1 && Math.abs(e.y) > 1.1) {
  299. // //         wx.showToast({ title: "摇一摇" })
  300. // } else if (Math.abs(e.x) > 0.07 && Math.abs(e.y) > 0.02 && that.data.status === '2') {
  301. // // 扫一扫播放的话 移动无效
  302. // if (that.data.isScanPlay) return;
  303. // that.startBeaconDiscovery()
  304. // } else {
  305. // //         wx.showToast({ title: "静止" })
  306. // }
  307. // }),
  308. innerAudioContext.onEnded(() => {
  309. console.log('播放结束了')
  310. if (this.data.isScanPlay) {
  311. innerAudioContext.stop()
  312. this.setData({ isScanPlay: false })
  313. this.targetObj = {}
  314. console.log('innerAudioContext', innerAudioContext)
  315. if (this.data.status == 2) {
  316. console.log(2222222222222222)
  317. this.startBeaconDiscovery()
  318. }
  319. }
  320. })
  321. },
  322. detached: function () {
  323. innerAudioContext.stop();
  324. innerAudioContext.destroy();
  325. wx.stopBeaconDiscovery({})
  326. this.setData({status:"0"})
  327. }
  328. }
  329. })