map-sense.js 8.7 KB

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