app.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. import { userMobileLogin } from './api/wxlogin.js'
  2. import sysconfig from './sysconfig/sysconfig.js'
  3. // app.js
  4. App({
  5. data: {//数据
  6. worker: null,//线程句柄
  7. recorder: null,//录音设备句柄
  8. wavFilePath: '',//wav文件路径
  9. readFileTimes: 0,//读取本地文件次数
  10. imuStartTimestamp: 0,//IMU开始时间戳
  11. loginFlag: false,//登录标识符
  12. },
  13. //初始化全局参数,在小程序存活期间onLaunch只执行一次
  14. onLaunch() {
  15. // 用户登录登录(发送登录凭证[res.code]到后台换取openId、sessionKey和unionId)
  16. wx.login({
  17. success: (res) => {
  18. var paramData = {};
  19. paramData.code = res.code; //登录凭证
  20. paramData.domain_name = sysconfig.domanName; //系统二级域名(用二级域名换取项目编号)
  21. userMobileLogin(paramData).then((resp) => {
  22. //保存token
  23. const tokenKey = sysconfig.user.tokenKey
  24. wx.setStorageSync(tokenKey, resp.data.data.token)
  25. //保存用户数据
  26. const userInfoKey = sysconfig.user.userInfoKey
  27. wx.setStorageSync(userInfoKey, resp.data.data)
  28. this.data.loginFlag = true//登录成功
  29. }).catch((err) => {
  30. this.data.loginFlag = false//登录失败
  31. console.log("%%%%%%%%", err.message)
  32. wx.showToast({
  33. title: '用户登录失败' + err.message,
  34. icon: 'error',
  35. duration: 10000
  36. })
  37. })
  38. }
  39. })
  40. },
  41. //创建线程(listener:线程监听服务程序)
  42. createWorker(listener) {
  43. if (this.data.worker == null) {
  44. this.data.worker = wx.createWorker("worker/worker.js", {
  45. useExperimentalWorker: true//使用实验worker,提升ios下js运行效率
  46. })
  47. // 监听worker被系统回收事件
  48. this.data.worker.onProcessKilled(() => {
  49. this.createNewWorker()// 重新创建一个worker
  50. })
  51. //设置线程监听服务程序
  52. if (typeof (listener) === 'function') {
  53. this.setWorkerListener(listener)
  54. //发消息给worker,加载wasm
  55. this.data.worker.postMessage({
  56. message: 'MAIN_WORKER_LOAD_WX_WASM',
  57. data: ''
  58. })
  59. }
  60. }
  61. },
  62. //设置线程监听服务程序
  63. setWorkerListener(listener) {
  64. if (this.data.worker != null) {
  65. this.data.worker.onMessage(listener)
  66. }
  67. },
  68. //创建录音设备,并监听录音完成事件
  69. createRecorder() {
  70. const self = this
  71. //获得录音机句柄
  72. this.data.recorder = wx.getRecorderManager()
  73. //注册录音回调函数(录音长度达到设定值后执行)
  74. this.data.recorder.onFrameRecorded((res) => {
  75. //从返回参数res中解构isLastFrame和frameBuffer变量
  76. //其中frameBuffer是二进制数据数组,不能直接读写
  77. const { isLastFrame, frameBuffer } = res
  78. //录音时长达到最大值,则重新开始录音
  79. //微信小程序录音时长最长为10分钟
  80. if (isLastFrame) {
  81. self.startRecord()
  82. }
  83. //将录音数据发送给worker
  84. self.data.worker.postMessage({
  85. message: 'MAIN_WORKER_AUDIO_DATA',
  86. data: frameBuffer
  87. })
  88. })
  89. //注册录音被打断回调函数
  90. this.data.recorder.onInterruptionBegin(() => {
  91. console.log("录音被打断")
  92. })
  93. //注册监听录音中断结束事件
  94. this.data.recorder.onInterruptionEnd(() => {
  95. this.resumeRecord()//恢复录音
  96. })
  97. },
  98. //开始录音
  99. startRecord() {
  100. if (this.data.recorder != null) {
  101. let options = {}
  102. //组织录音参数
  103. options.duration = 600000 //最长连续录音10分钟
  104. options.sampleRate = 48000 //采样频率
  105. options.encodeBitRate = 320000 //编码率,与采样率配对适用,参照腾讯文档要求设置具体值
  106. options.numberOfChannels = 1 //单通道采样
  107. options.format = "pcm"
  108. options.frameSize = "22" //单位kB(数据不会太准确,因此需要缓存数据以实施成帧操作)
  109. options.audioSource = "auto"//录音源,默认使用手机麦克风,插上耳麦后自动切换使用耳机麦克风,所有平台适用。
  110. //开始录音
  111. this.data.recorder.start(options)
  112. }
  113. },
  114. //恢复录音
  115. resumeRecord() {
  116. if (this.data.recorder != null) {
  117. this.data.recorder.resume()
  118. }
  119. },
  120. //打开蓝牙适配器
  121. openBleAdapter() {
  122. let self = this
  123. wx.openBluetoothAdapter({
  124. mode: "central",//主机模式
  125. //打开成功,开始扫描周边设备
  126. success: function (res) {
  127. wx.startBluetoothDevicesDiscovery({
  128. allowDuplicatesKey: true,//允许重复上报同一设备,每次上报RSSI值会有不同
  129. interval: 2000,//2秒扫描一次
  130. powerLevel: "medium",
  131. success() {
  132. self.monitorBleBtsScanResult()
  133. }
  134. })
  135. },
  136. //打开失败
  137. fail: function (err) {
  138. console.log("open ble fail", err)
  139. setTimeout(() => {
  140. self.openBleAdapter()
  141. }, 3000)
  142. }
  143. })
  144. },
  145. //监听蓝牙基站扫描结果
  146. monitorBleBtsScanResult() {
  147. let self = this
  148. wx.onBluetoothDeviceFound((res) => {
  149. let findFlag = 0//发现系统基站标识符
  150. let bleBtsDataList = []//蓝牙基站数据队列
  151. //遍历蓝牙设备队列
  152. res.devices.forEach((element) => {
  153. if (element.name && element.name.length == 23) {
  154. let bleName = element.name//蓝牙名称
  155. let subName = bleName.slice(-10)//蓝牙项目标识符
  156. //该设备为本系统设备
  157. if (subName === "IPS8000BLE") {
  158. if (!findFlag) {
  159. findFlag = 1//发现系统基站
  160. }
  161. let macAddress = bleName.substring(0, 12);//BLE的mac地址
  162. let rssi = -10000;
  163. if (element.RSSI) {
  164. rssi = element.RSSI//接收电平强度
  165. }
  166. //保存扫描结果
  167. let item = {}
  168. item['mac'] = macAddress;
  169. item['rssi'] = rssi
  170. bleBtsDataList.push(item)
  171. }
  172. }
  173. })
  174. //成功监听到本系统蓝牙设备
  175. if (findFlag) {
  176. //组织本次监听到的蓝牙基站数据
  177. self.organizeBleBtsData(bleBtsDataList)
  178. }
  179. })
  180. },
  181. //按照wasm模块所需格式组织蓝牙基站数据
  182. organizeBleBtsData(bleBtsList) {
  183. let listLen = 0
  184. let bleBtsDataList = []//蓝牙基站数据队列
  185. let rssi = 0
  186. let strMac = ""
  187. let macLen = 0
  188. let oneHexChar = ""
  189. let oneHexCharValue = 0
  190. //没有蓝牙基站
  191. if (!bleBtsList || bleBtsList.length <= 0) {
  192. return
  193. }
  194. //队列长度
  195. listLen = bleBtsList.length
  196. if (listLen > 9) {
  197. listLen = 9//最多9个蓝牙基站
  198. }
  199. ////按照WASM模块所需数据格式组织蓝牙基站数据
  200. bleBtsDataList.push(1)//蓝牙基站有效标识符置1
  201. bleBtsDataList.push(listLen)//蓝牙基站个数
  202. //组织RSSI和MAC
  203. for (let i = 0; i < listLen; i++) {
  204. rssi = bleBtsList[i].rssi
  205. bleBtsDataList.push(rssi)//RSSI
  206. strMac = bleBtsList[i].mac//mac地址16进制字符串
  207. macLen = strMac.length
  208. if (macLen == 12) {
  209. for (let j = 0; j < macLen; j++) {
  210. oneHexChar = strMac[j]
  211. oneHexCharValue = this.hexCharToValue(oneHexChar)
  212. bleBtsDataList.push(oneHexCharValue)//MAC
  213. }
  214. } else {
  215. console.log("长度错误")
  216. }
  217. }
  218. //把数据发送给worker
  219. if (bleBtsDataList.length > 3) {
  220. if (this.data.worker != null) {
  221. this.data.worker.postMessage({
  222. message: 'MAIN_WORKER_BLE_BTS_DATA',
  223. data: bleBtsDataList
  224. })
  225. }
  226. }
  227. },
  228. hexCharToValue(char) {
  229. // 定义16进制字符到数值的映射
  230. const hexValues = {
  231. '0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7,
  232. '8': 8, '9': 9, 'A': 10, 'B': 11, 'C': 12, 'D': 13, 'E': 14, 'F': 15,
  233. 'a': 10, 'b': 11, 'c': 12, 'd': 13, 'e': 14, 'f': 15
  234. };
  235. // 查找字符对应的值
  236. return hexValues[char];
  237. },
  238. //停止扫描蓝牙设备
  239. stopScanNearbyBle() {
  240. let self = this
  241. wx.stopBluetoothDevicesDiscovery({
  242. success: function () {
  243. wx.offBluetoothDeviceFound(function () { })
  244. },
  245. fail: function () {
  246. console.log("没有扫描到基站")
  247. setTimeout(self.stopScanNearbyBle, 3000)
  248. }
  249. })
  250. },
  251. //启动加速度计
  252. startImu() {
  253. wx.stopAccelerometer()//停止加速度传感器
  254. //启动加速度传感器,20毫秒采集一次加速度
  255. wx.startAccelerometer({ interval: "game" })
  256. //监听加速度传感器
  257. wx.onAccelerometerChange(this.onAccelerometerChange)
  258. //生成IMU开始时间戳
  259. this.data.imuStartTimestamp = new Date().getTime()
  260. },
  261. //监测三轴加速度计的变化
  262. onAccelerometerChange(res) {
  263. let timestamp = new Date().getTime() - this.data.imuStartTimestamp; //生成时间戳
  264. let item = {}
  265. item.timestamp = timestamp
  266. item.x = res.x
  267. item.y = res.y
  268. item.z = res.z
  269. //把数据发送给线程
  270. if (this.data.worker != null) {
  271. this.data.worker.postMessage({
  272. message: 'MAIN_WORKER_ONE_ACC_DATA',//加速度数据
  273. data: item
  274. })
  275. }
  276. },
  277. ////////////////////////////////////////////////////////////////////////////
  278. ///////////////////////////以下未测试接口,已舍弃/////////////////////////////
  279. ////////////////////////////////////////////////////////////////////////////
  280. //保存音频文件
  281. //buffer:录音数据,为二进制单字节数据数组(byte)
  282. saveAduioDataToBin(buffer) {
  283. console.log("收到保存消息")
  284. let fileSystemManager = wx.getFileSystemManager()
  285. try {
  286. fileSystemManager.appendFileSync(wx.env.USER_DATA_PATH + "/IPS8000.bin", buffer, 'binary')
  287. return { code: 1, data: 'ok' }
  288. } catch (e) {
  289. return { code: 0, data: e }
  290. }
  291. },
  292. //开始扫描周边蓝牙设备
  293. startScanNearbyBleBts() {
  294. let self = this
  295. //扫描周边设备
  296. wx.startBluetoothDevicesDiscovery({
  297. allowDuplicatesKey: true,//允许重复上报已扫描到的设备
  298. interval: 3000,//3秒扫描一次
  299. powerLevel: "medium",
  300. success: function () {
  301. self.monitorBleBtsScanResult()//监听蓝牙基站扫描结果
  302. },
  303. fail: function () {
  304. //500毫秒之后重新扫描
  305. setTimeout(self.startScanNearbyBleBts, 500)
  306. }
  307. })
  308. },
  309. })