home.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. //注意,注意,""../"表示退回上一级目录
  2. import { userMobileLogin } from '../../api/wxlogin.js'
  3. import { getMobileBtsParamList } from '../../api/btsparam.js'
  4. import sysconfig from '../../sysconfig/sysconfig.js'
  5. const app = getApp()
  6. Page({
  7. data: {
  8. bestFrame: 0,
  9. bestMultiFrame: 0,
  10. bleDataList: [],//蓝牙设备队列,包括mac和rssi项
  11. btsParamList: [],//基站参数列表
  12. btsDataList: [],//基站数据列表
  13. btsMinCoordX: 0,
  14. btsMaxCoordX: 0,
  15. btsMinCoordY: 0,
  16. btsMaxCoordY: 0,
  17. canvasCtx: null, //画布
  18. canvasWidth: 0, //画布宽度
  19. canvasHeight: 0, //画布高度
  20. canvasPixelRatio: 1,//画布像素比例
  21. coordDataList: [],//定位坐标数据队列(所有定位坐标)
  22. },
  23. /**
  24. * 生命周期函数--监听页面加载
  25. */
  26. onLoad(options) {
  27. if (!app.data.loginFlag) {
  28. const myTimer = setInterval(() => {
  29. if (app.data.loginFlag) {
  30. clearInterval(myTimer) // 停止定时器
  31. this.init()//初始化
  32. }
  33. }, 500); // 每500毫秒检查一次
  34. } else {
  35. this.init()//初始化
  36. }
  37. },
  38. /**
  39. * 生命周期函数--监听页面初次渲染完成
  40. */
  41. onReady() {
  42. },
  43. /**
  44. * 生命周期函数--监听页面显示
  45. */
  46. onShow() {
  47. },
  48. /**
  49. * 生命周期函数--监听页面隐藏
  50. */
  51. onHide() {
  52. },
  53. /**
  54. * 生命周期函数--监听页面卸载
  55. */
  56. onUnload() {
  57. //页面关闭时释放wasm模块内存
  58. if (app.data.worker != null) {
  59. app.data.worker.postMessage({
  60. message: 'MAIN_WORKER_FREE_MEMORY',
  61. data: ''
  62. })
  63. }
  64. },
  65. /**
  66. * 页面相关事件处理函数--监听用户下拉动作
  67. */
  68. onPullDownRefresh() {
  69. },
  70. /**
  71. * 页面上拉触底事件的处理函数
  72. */
  73. onReachBottom() {
  74. },
  75. /**
  76. * 用户点击右上角分享
  77. */
  78. onShareAppMessage() {
  79. },
  80. //初始化
  81. init() {
  82. //创建线程
  83. app.createWorker(this.workerMessageListenerHome)
  84. //创建录音设备
  85. app.createRecorder()
  86. //拉取基站参数(注意:需要在用户登录成功后才拉取参数)
  87. this.getBtsParamList()
  88. //启动三轴加速计
  89. app.startImu()
  90. },
  91. //线程监听服务程序
  92. workerMessageListenerHome(res) {
  93. switch (res.message) {
  94. case 'WORKER_MAIN_START_MONITOR_BLE_BTS':
  95. app.openBleAdapter()//打开蓝牙设备
  96. break
  97. case 'WORKER_MAIN_ORGANIZE_INSTALL_BTS_DATA':
  98. this.organizeBtsDataForWasm()//组织基站数据
  99. break
  100. case 'WORKER_MAIN_START_REC':
  101. app.startRecord()//开始录音
  102. break
  103. case 'WORKER_MAIN_CURRENT_LOCATION_COORD'://当前定位坐标
  104. this.saveLocateCoord(res.data)
  105. break
  106. case 'WORKER_MAIN_NOTICE_DOWNLOAD_AUDIO_FILE':
  107. this.downloadAudioFile()
  108. break
  109. case 'WORKER_MAIN_NOTICE_READ_AUDIO_FILE':
  110. this.readAudioFile()
  111. break
  112. case 'WORKER_MAIN_SAVE_AUDIO_DATA':
  113. app.saveAduioDataToBin(res.data)
  114. break
  115. default:
  116. break
  117. }
  118. },
  119. //用户登录,登录成功后拉取基站参数
  120. userLogin() {
  121. // 用户登录登录(发送登录凭证[res.code]到后台换取openId、sessionKey和unionId)
  122. wx.login({
  123. success: (res) => {
  124. var paramData = {};
  125. paramData.code = res.code; //登录凭证
  126. paramData.domain_name = sysconfig.domanName; //系统二级域名(用二级域名换取项目编号)
  127. userMobileLogin(paramData).then((resp) => {
  128. //保存token
  129. const tokenKey = sysconfig.user.tokenKey
  130. wx.setStorageSync(tokenKey, resp.data.data.token)
  131. //保存用户数据
  132. const userInfoKey = sysconfig.user.userInfoKey
  133. wx.setStorageSync(userInfoKey, resp.data.data)
  134. //拉取基站参数(注意:需要在用户登录成功后才拉取参数)
  135. this.getBtsParamList()
  136. }).catch((err) => {
  137. console.log("用户登录失败", err)
  138. })
  139. }
  140. })
  141. },
  142. //拉取基站参数(注意:需要在用户登录成功后才拉取参数)
  143. getBtsParamList() {
  144. //拉取基站参数
  145. getMobileBtsParamList().then((resBtsPram) => {
  146. this.data.btsParamList = resBtsPram.data.data
  147. //组织基站数据队列
  148. this.data.btsDataList = this.generateBtsDataList(this.data.btsParamList)
  149. //初始化画布
  150. this.initCanvas()
  151. }).catch((err) => {
  152. console.log("查询基站参数失败", err)
  153. })
  154. },
  155. //初始化画布
  156. initCanvas() {
  157. //获得屏幕数据
  158. let self = this
  159. wx.getSystemInfo({
  160. success: (res) => {
  161. self.data.canvasPixelRatio = res.pixelRatio
  162. let myCanvasWidth = res.windowWidth - 5
  163. self.setData({
  164. canvasWidth: myCanvasWidth,
  165. canvasHeight: myCanvasWidth
  166. })
  167. }
  168. })
  169. //为画布选择一个容器
  170. wx.createSelectorQuery().select('#homeCanvas').fields({ node: true, size: true }).exec((res) => {
  171. let canvas = res[0].node
  172. if (canvas) {
  173. this.data.canvasCtx = canvas.getContext('2d')
  174. canvas.width = res[0].width * this.data.canvasPixelRatio
  175. canvas.height = res[0].height * this.data.canvasPixelRatio
  176. this.data.canvasCtx.scale(this.data.canvasPixelRatio, this.data.canvasPixelRatio)
  177. //画网格
  178. this.drawLocateTrack(0, 0, 0, 0)
  179. //画基站坐标
  180. this.calMaxMinCoordXY(this.data.btsDataList)
  181. }
  182. })
  183. },
  184. //为wasm模块组织基站数据
  185. organizeBtsDataForWasm() {
  186. let dataList = []//数据队列
  187. let oneItem = {}
  188. let dataListLen = this.data.btsDataList.length
  189. //按照wasm模块要求的数据格式组织数据
  190. dataList.push(dataListLen)
  191. for (let i = 0; i < dataListLen; i++) {
  192. oneItem = this.data.btsDataList[i]
  193. dataList.push(oneItem.dwBuildId)
  194. dataList.push(oneItem.dwLayerId)
  195. dataList.push(oneItem.dwBtsId)
  196. dataList.push(oneItem.dwFreqIndex)
  197. dataList.push(oneItem.dwSlot)
  198. dataList.push(oneItem.dwCoordX)
  199. dataList.push(oneItem.dwCoordY)
  200. dataList.push(oneItem.dwCoordZ)
  201. //一维定位数据
  202. dataList.push(oneItem.dwLctType)
  203. dataList.push(oneItem.dwTwoBtsNum)
  204. for (let i = 0; i < oneItem.dwTwoBtsNum; i++) {
  205. dataList.push(oneItem.adwTwoBtsList[i])
  206. }
  207. for (let i = oneItem.dwTwoBtsNum; i < 6; i++) {//补零占位
  208. dataList.push(0)
  209. }
  210. //蓝牙mac
  211. for (let j = 0; j < 12; j++) {
  212. dataList.push(oneItem.adwBluetoothMac[j])
  213. }
  214. //wifi mac
  215. for (let k = 0; k < 12; k++) {
  216. dataList.push(oneItem.adwWifiMac[k])
  217. }
  218. }
  219. //将基站数据发送给worker
  220. if (app.data.worker != null && dataListLen > 0) {
  221. app.data.worker.postMessage({
  222. message: 'MAIN_WORKER_INSTALL_BTS_DATA',
  223. data: dataList//安装基站数据
  224. })
  225. }
  226. },
  227. //生成基站数据队列
  228. generateBtsDataList(btsParamList) {
  229. let dataList = []
  230. ////组织基站数据
  231. let btsNum = btsParamList.length;//基站数量
  232. for (let i = 0; i < btsNum; i++) {
  233. let btsParam = btsParamList[i]
  234. let oneItem = this.generateOneBtsData(btsParam.bts_id, btsParam.carrier_id, btsParam.timeslot, btsParam.coord_x, btsParam.coord_y, btsParam.coord_z, btsParam.ble_name, btsParam.location_type, btsParam.two_bts_num, btsParam.two_bts_list)
  235. dataList.push(oneItem)
  236. }
  237. return dataList
  238. },
  239. //生成一个基站数据
  240. //基站ID,频率ID(0 - 8),时隙ID(0 - 3),X坐标(单位厘米),Y坐标(单位厘米),Z坐标(单位厘米),蓝牙MAC地址,定位类型,1维定位基站数,1维定位基站ID队列
  241. generateOneBtsData(dwBtsId, dwFreqIndex, dwSlot, dwCoordX, dwCoordY, dwCoordZ, macAddressList, dwLctType, dwTwoBtsNum, adwTwoBtsList) {
  242. let installBts = {}
  243. let oneCharHex = ''
  244. let oneCharHexValue = 0
  245. installBts.dwBuildId = 1
  246. installBts.dwLayerId = 1
  247. installBts.dwBtsId = dwBtsId
  248. installBts.dwFreqIndex = dwFreqIndex - 1
  249. installBts.dwSlot = dwSlot - 1
  250. installBts.dwCoordX = dwCoordX
  251. installBts.dwCoordY = dwCoordY
  252. installBts.dwCoordZ = dwCoordZ
  253. //定位类型,1:一维定位,2:二维定位,3:既支持一维定位也支持二维定位
  254. installBts.dwLctType = dwLctType
  255. //一维定位基站数量
  256. installBts.dwTwoBtsNum = dwTwoBtsNum;
  257. //一维定位基站ID队列
  258. installBts.adwTwoBtsList = []
  259. let btsIdList = adwTwoBtsList.split(",")
  260. let btsId = 0
  261. for (let k = 0; k < dwTwoBtsNum; k++) {
  262. btsId = parseInt(btsIdList[k])
  263. installBts.adwTwoBtsList.push(btsId)
  264. }
  265. //蓝牙mac
  266. installBts.adwBluetoothMac = []
  267. for (let i = 0; i < 12; i++) {
  268. oneCharHex = macAddressList[i]
  269. oneCharHexValue = app.hexCharToValue(oneCharHex)
  270. installBts.adwBluetoothMac.push(oneCharHexValue)
  271. }
  272. //wifi mac
  273. installBts.adwWifiMac = []
  274. for (let j = 0; j < 12; j++) {
  275. oneCharHex = macAddressList[j]
  276. oneCharHexValue = app.hexCharToValue(oneCharHex)
  277. installBts.adwWifiMac.push(oneCharHexValue)
  278. }
  279. return installBts
  280. },
  281. //计算基站围成的多边形最大最小坐标
  282. calMaxMinCoordXY(btsDataList) {
  283. let maxTmpX = -10000000
  284. let minTmpX = 10000000
  285. let maxTmpY = -10000000
  286. let minTmpY = 10000000
  287. let xTmp = 0
  288. let yTmp = 0
  289. let btsNum = btsDataList.length
  290. //计算基站围成的多边形坐标最大最小值
  291. for (let i = 0; i < btsNum; i++) {
  292. xTmp = btsDataList[i].dwCoordX
  293. if (xTmp > maxTmpX) {
  294. maxTmpX = xTmp
  295. }
  296. if (xTmp < minTmpX) {
  297. minTmpX = xTmp
  298. }
  299. yTmp = btsDataList[i].dwCoordY
  300. if (yTmp > maxTmpY) {
  301. maxTmpY = yTmp
  302. }
  303. if (yTmp < minTmpY) {
  304. minTmpY = yTmp
  305. }
  306. }
  307. //保存值
  308. this.setData({
  309. btsMinCoordX: minTmpX,
  310. btsMaxCoordX: maxTmpX,
  311. btsMinCoordY: minTmpY,
  312. btsMaxCoordY: maxTmpY
  313. })
  314. //画基站坐标
  315. this.drawLocateTrack(1, 0, 0, this.data.coordDataList)
  316. },
  317. //保存定位坐标
  318. saveLocateCoord(coord) {
  319. //保存定位坐标
  320. this.data.coordDataList.push(coord)
  321. //画定位轨迹
  322. this.drawLocateTrack(2, coord.x, coord.y, this.data.coordDataList)
  323. },
  324. //画定位轨迹,包括网格线、基站信息、定位轨迹和当前位置
  325. drawLocateTrack(type, coordinateX, coordinateY, coordDataList) {
  326. let i = 0
  327. let pos = 0
  328. let space = 10
  329. let lineCount = 40
  330. let ctxMinX = this.data.btsMinCoordX - 500
  331. let ctxMaxX = this.data.btsMaxCoordX + 500
  332. let ctxMinY = this.data.btsMinCoordY - 500
  333. let ctxMaxY = this.data.btsMaxCoordY + 500
  334. let ctxWidth = ctxMaxX - ctxMinX
  335. let ctxHeight = ctxMaxY - ctxMinY
  336. let radio = this.data.canvasWidth / ctxWidth
  337. let radioHeight = this.data.canvasHeight / ctxHeight
  338. if (radioHeight < radio) {
  339. radio = radioHeight
  340. }
  341. //发布已经初始化
  342. if (this.data.canvasCtx === null) {
  343. return
  344. }
  345. let positionCtx = this.data.canvasCtx
  346. positionCtx.fillStyle = "#0066FF"
  347. positionCtx.clearRect(0, 0, this.data.canvasWidth, this.data.canvasHeight)
  348. positionCtx.lineWidth = 0.5
  349. //// 画网格
  350. positionCtx.beginPath()
  351. positionCtx.strokeStyle = '#CCCCCC'
  352. //1、画网格横线
  353. space = parseFloat(this.data.canvasWidth) / lineCount
  354. for (i = 0; i < lineCount; i++) {
  355. pos = i * space
  356. positionCtx.moveTo(0, pos)
  357. positionCtx.lineTo(this.data.canvasWidth, pos)
  358. }
  359. //2、画网格竖线
  360. space = parseFloat(this.data.canvasHeight) / lineCount
  361. for (i = 0; i < lineCount; i++) {
  362. pos = i * space
  363. positionCtx.moveTo(pos, 0)
  364. positionCtx.lineTo(pos, this.data.canvasHeight)
  365. }
  366. positionCtx.stroke()
  367. if (type === 0) { //仅画网格
  368. return
  369. }
  370. //// 画基站
  371. positionCtx.beginPath()
  372. positionCtx.fillStyle = "#FF0000"
  373. positionCtx.strokeStyle = '#FF0000'
  374. for (i = 0; i < this.data.btsDataList.length; i++) {
  375. let x = (this.data.btsDataList[i].dwCoordX - ctxMinX) * radio
  376. let y = this.data.canvasHeight - (this.data.btsDataList[i].dwCoordY - ctxMinY) * radio
  377. const btsId = this.data.btsDataList[i].dwBtsId
  378. const freqIndex = this.data.btsDataList[i].dwFreqIndex
  379. const slot = this.data.btsDataList[i].dwSlot
  380. const coord = "[" + this.data.btsDataList[i].dwCoordX / 100 + "," + this.data.btsDataList[i].dwCoordY / 100 + "," + this.data.btsDataList[i].dwCoordZ / 100 + "]"
  381. positionCtx.fillStyle = "#FF0000"
  382. positionCtx.fillRect(x - 5, y - 5, 6, 6);//基站标识符
  383. positionCtx.fillStyle = "#000000"
  384. positionCtx.fillText(btsId, x + 5, y - 15)//画基站ID
  385. positionCtx.fillText("f: " + freqIndex, x + 5, y - 5)//画频率
  386. positionCtx.fillText("t: " + slot, x + 5, y + 5)//时隙
  387. positionCtx.fillText(coord, x + 5, y + 15)//坐标
  388. }
  389. if (type === 1) {//仅画基站
  390. return
  391. }
  392. //// 画轨迹线
  393. positionCtx.lineWidth = 1.2
  394. positionCtx.beginPath()
  395. positionCtx.strokeStyle = '#0A0A0A'
  396. for (i = 2; i < coordDataList.length; i++) {
  397. let point = coordDataList[i - 1]
  398. let x = (point.x - ctxMinX) * radio
  399. let y = this.data.canvasHeight - (point.y - ctxMinY) * radio
  400. positionCtx.moveTo(x, y)
  401. point = coordDataList[i]
  402. x = (point.x - ctxMinX) * radio
  403. y = this.data.canvasHeight - (point.y - ctxMinY) * radio
  404. positionCtx.lineTo(x, y)
  405. }
  406. positionCtx.stroke()
  407. //// 画当前位置
  408. positionCtx.beginPath()
  409. positionCtx.fillStyle = "#0000FF"
  410. positionCtx.strokeStyle = '#0000FF'
  411. let x = (coordinateX - ctxMinX) * radio
  412. let y = this.data.canvasHeight - (coordinateY - ctxMinY) * radio
  413. positionCtx.arc(x, y, 3, 0, 2 * Math.PI);
  414. positionCtx.fill()
  415. },
  416. //////////////////////////////////////////////////////////////////////////////////
  417. //////////////////////////////////下面是测试接口,已舍弃////////////////////////////
  418. //////////////////////////////////////////////////////////////////////////////////
  419. //生成蓝牙基站数据
  420. generateBleBtsData() {
  421. let mac = "123456789ABC"
  422. let rssi = -58
  423. let item = {}
  424. item['mac'] = mac;
  425. item['rssi'] = rssi
  426. let dataList = []
  427. dataList.push(item)
  428. app.data.worker.postMessage({
  429. message: 'MAIN_WORKER_BLE_BTS_DATA',
  430. code: 100,
  431. data: dataList
  432. })
  433. },
  434. //从服务器上下载文件
  435. downloadAudioFile() {
  436. const url = "https://www.stp.intourism.cn/tdsadmin/line390-zt.wav"
  437. wx.downloadFile({
  438. url: url,
  439. success: (res) => {
  440. if (res.statusCode == 200) {
  441. app.data.wavFilePath = res.tempFilePath
  442. this.readAudioFile();
  443. }
  444. }
  445. })
  446. },
  447. // 读取音频文件
  448. readAudioFile() {
  449. let filePath = app.data.wavFilePath
  450. if (app.data.readFileTimes == null) {
  451. return
  452. }
  453. //90秒数据
  454. if (app.data.readFileTimes >= 360) {
  455. app.data.readFileTimes = 0
  456. return
  457. }
  458. const times = app.data.readFileTimes
  459. const fs = wx.getFileSystemManager();
  460. fs.readFile({
  461. filePath: `${filePath}`,
  462. position: 44 + times * 12000 * 2,
  463. length: 12000 * 2,//12000点,每点2个字节
  464. success: (res) => {
  465. app.data.readFileTimes++
  466. app.data.worker.postMessage({
  467. message: 'MAIN_WORKER_AUDIO_DATA',
  468. data: res.data
  469. })
  470. },
  471. fail(res) {
  472. console.log(res);
  473. }
  474. })
  475. },
  476. })