ota.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. const { BtHelper } = require("../../devices/bt_helper");
  2. import { EnumCmdEvent, CmdEvent } from '../../devices/cmd_key_event';
  3. import EventManager, { addNotification } from '../../utils/event_bus'
  4. // pages/OTA/ota.js
  5. Page({
  6. /**
  7. * 页面的初始数据
  8. */
  9. data: {
  10. navbarData: {
  11. showCapsule: 1, //
  12. title: '固件信息',
  13. },
  14. device: {},
  15. otaData: {},
  16. btHelper: null,
  17. progress: 0, // 进度条初始值
  18. otaStatus: 0,
  19. buttonTips: "固件更新",
  20. _chunks: [],
  21. progressPercent: 0,
  22. progress: 0,
  23. progressTextLeft: "0%",
  24. _timer: null,
  25. },
  26. setOtaStatus(status) {
  27. switch (status) {
  28. case 0:
  29. this.setData({
  30. otaStatus: 0,
  31. buttonTips: "固件更新"
  32. });
  33. break;
  34. case 1:
  35. this.setData({
  36. otaStatus: 1,
  37. buttonTips: "下载升级包"
  38. });
  39. break;
  40. case 2:
  41. this.setData({
  42. otaStatus: 2,
  43. buttonTips: "开始更新"
  44. });
  45. break;
  46. case 3:
  47. this.setData({
  48. otaStatus: 3,
  49. buttonTips: "更新中..."
  50. });
  51. break;
  52. case 4:
  53. this.setData({
  54. otaStatus: 4,
  55. buttonTips: "更新失败,再试一次"
  56. });
  57. break;
  58. case 5:
  59. this.setData({
  60. otaStatus: 4,
  61. buttonTips: "更新完成"
  62. });
  63. break;
  64. default:
  65. break;
  66. }
  67. },
  68. startOtaTap() {
  69. let online = this.data.device.state === "online"
  70. if (!online) {
  71. wx.showToast({
  72. title: '设备已经掉线了',
  73. })
  74. return;
  75. }
  76. let hasNewVersion = this.data.otaData.hasNewVersion ?? false
  77. if (!hasNewVersion) {
  78. wx.showToast({
  79. title: '没有可升级的固件',
  80. })
  81. return;
  82. }
  83. if (this.data.otaStatus != 1 || this.data.otaStatus != 4) {
  84. return;
  85. }
  86. let _this = this
  87. wx.showModal({
  88. title: '有新固件可升级',
  89. content: _this.data.otaData.content ?? '提升体验,操作更流畅',
  90. cancelText: '以后再说',
  91. confirmText: '升级',
  92. complete: (res) => {
  93. if (res.cancel) {
  94. }
  95. if (res.confirm) {
  96. _this.startDownloadFile()
  97. // _this.downloadOtaFile(_this.data.otaData.url ?? "")
  98. }
  99. }
  100. })
  101. // const btHelper = BtHelper.getInstance();
  102. // btHelper.ota(this.data.otaData.file_url)
  103. },
  104. sendWiFiInfo(wifiName, pwd) {
  105. // [0x22, (wifiList.length + pwdList.length + 6), 0x33, (wifiList.length), (wifiList), 0x44, (pwdList)];
  106. if (!wifiName || !pwd) {
  107. wx.showToast({
  108. title: '请输入正确的账号密码',
  109. })
  110. wx.hideLoading()
  111. return;
  112. }
  113. let result = [];
  114. // 字母*6 +
  115. let wifiList = this.string2ListInt(wifiName);
  116. // 数字*3 +
  117. let pwdList = this.string2ListInt(pwd);
  118. // 16进制
  119. result.push(0x22);
  120. result.push(this.int2Hex(wifiList.length + pwdList.length + 6));
  121. // 账号
  122. result.push(0x33);
  123. result.push(this.int2Hex(wifiList.length));
  124. let p = result[3] + 4;
  125. let j = 0;
  126. for (let i = 4; i < p; i++) {
  127. result.splice(i, 0, wifiList[j++]);
  128. }
  129. // 密码
  130. result.splice(p, 0, 0x44);
  131. result.splice(++p, 0, this.int2Hex(pwdList.length));
  132. p++;
  133. j = 0;
  134. // for (let i = p; i < p + pwdList.length; i++) {
  135. // result.splice(i, 0, pwdList[j++]);
  136. // }
  137. // result.push(...pwdList);
  138. result.concat(pwdList)
  139. console.log("发送wifi账号密码:", result.toString());
  140. // _ble.send({ cmd: result });
  141. const btHelper = BtHelper.getInstance();
  142. btHelper.otaData(result)
  143. },
  144. int2Hex(num) {
  145. return parseInt(num, 16);
  146. },
  147. // string转换为List<int>
  148. string2ListInt(text) {
  149. let code = Array.from(text).map(char => char.charCodeAt(0));
  150. console.log("string转换为List<int>", code)
  151. return code
  152. },
  153. // List<int>转换为string
  154. listInt2String(data) {
  155. return String.fromCharCode(...data);
  156. },
  157. startDownloadFile() {
  158. var urlPath = this.data.otaData.url ?? "";
  159. var list = urlPath.split("/");
  160. // let cachePath = await PathUtil.getDownloadPath(fileName: list.last ?? 'OTAUpgrade.OTA');
  161. const fs = wx.getFileSystemManager();
  162. // 构建本地文件路径
  163. var localFilePath = list[list.length - 1];
  164. console.log(list, localFilePath)
  165. let _this = this;
  166. _this.setOtaStatus(2);
  167. let localPath = `${wx.env.USER_DATA_PATH}/` + localFilePath
  168. // 判断文件是否存在
  169. fs.access({
  170. path: localPath,
  171. success(res) {
  172. console.log('文件已存在:', res);
  173. if (res) {
  174. // 有文件
  175. _this.readFile(localPath);
  176. } else {
  177. _this.downloadOtaFile(urlPath, localPath)
  178. }
  179. }, fail(err) {
  180. // 文件不存在或其他错误
  181. console.log(err)
  182. // 文件不存在,开始下载
  183. _this.downloadOtaFile(urlPath, localPath)
  184. }
  185. }
  186. );
  187. },
  188. downloadOtaFile(urlPath, localPath) {
  189. let _this = this;
  190. // const fs = wx.getFileSystemManager();
  191. wx.downloadFile({
  192. url: urlPath, // 下载资源的URL
  193. success: (res) => {
  194. console.log('文件下载成功2', res);
  195. if (res.statusCode === 200) {
  196. // 下载成功,保存文件路径
  197. const filePath = res.tempFilePath;
  198. // _this.readFile(filePath);
  199. // 将下载的文件移动到本地路径
  200. fs.rename({
  201. oldPath: filePath,
  202. newPath: localPath,
  203. success: () => {
  204. wx.showToast({
  205. title: '文件下载成功',
  206. });
  207. _this.readFile(localPath);
  208. },
  209. fail: (err) => {
  210. _this.setOtaStatus(4);
  211. wx.showToast({
  212. title: '下载文件失败,检查下手机内存吧',
  213. });
  214. console.error('文件移动失败:', err);
  215. }
  216. });
  217. } else {
  218. _this.setOtaStatus(4);
  219. wx.showToast({
  220. title: '文件下载失败',
  221. });
  222. }
  223. },
  224. fail: (err) => {
  225. _this.setOtaStatus(4);
  226. wx.showToast({
  227. title: '文件下载失败',
  228. });
  229. console.error('下载文件失败:', err);
  230. }
  231. });
  232. },
  233. readFile(localFilePath) {
  234. if (!localFilePath) {
  235. wx.showToast({
  236. title: '下载文件为空',
  237. });
  238. return;
  239. }
  240. wx.showLoading({
  241. title: '开始传输文件',
  242. })
  243. const fs = wx.getFileSystemManager();
  244. let _this = this;
  245. fs.readFile({
  246. filePath: localFilePath,
  247. encoding: 'base64', // 可以选择 'utf8' 或 'base64'
  248. success: (res) => {
  249. // const btHelper = BtHelper.getInstance();
  250. // btHelper.ota(localFilePath);
  251. console.log('文件内容:', res.data.length);
  252. _this.startSend(res.data);
  253. },
  254. fail: (err) => {
  255. wx.showToast({
  256. title: 'OTA文件下载失败',
  257. });
  258. console.error('文件读取失败:', err);
  259. _this.setOtaStatus(4);
  260. }
  261. });
  262. },
  263. startSend(data) {
  264. const chunkSize = 20; // 每次发送的数据块大小
  265. const chunks = [];
  266. for (let i = 0; i < data.length; i += chunkSize) {
  267. chunks.push(data.slice(i, i + chunkSize));
  268. }
  269. this.data._chunks = chunks;
  270. this.endOta(1)
  271. // this.startSendOtaData()
  272. },
  273. startSendOtaData() {
  274. let _this = this
  275. let length = this.data._chunks.length
  276. if (length === 0) {
  277. wx.showToast({
  278. title: '下载文件失败',
  279. icon: 'none'
  280. })
  281. _this.endOta(2)
  282. return;
  283. }
  284. _this.sendOtaData(this.data._chunks, 0)
  285. // }
  286. }, sendOtaData(imageBuffer, index) {
  287. let _this = this
  288. if (index >= imageBuffer.length) {
  289. _this.endOta(0)
  290. return;
  291. }
  292. let chunkSize = 20;
  293. let total = imageBuffer.length
  294. let next = index + chunkSize;
  295. const chunk = imageBuffer.slice(index, next);
  296. // todo 改成设备wifi下载
  297. // BtHelper.getInstance().wallPaperData(chunk, function (res) {
  298. // console.log("发送OTA数据:", next)
  299. // if (res) {
  300. // _this.updateProgress(next, total);
  301. // _this.sendOtaData(imageBuffer)
  302. // } else {
  303. // wx.showModal({
  304. // title: 'OTA升级失败了',
  305. // showCancel: false
  306. // })
  307. // }
  308. // })
  309. },
  310. endOta(value) {
  311. BtHelper.getInstance().otaCmd(value)
  312. if (value == 0) {
  313. this.setOtaStatus(0);
  314. } else {
  315. this.setOtaStatus(4);
  316. }
  317. },
  318. startProgress() {
  319. this.setData({
  320. progress: 0,
  321. showProgress: true
  322. })
  323. },
  324. updateProgress(chunk, total) {
  325. let progress = chunk / total * 100;
  326. let _this = this
  327. if (progress >= 100) {
  328. _this.setData({
  329. progress: 0,
  330. showProgress: false,
  331. // showCropImg: false
  332. });
  333. wx.showToast({
  334. title: '图片上传成功',
  335. })
  336. } else {
  337. _this.setData({
  338. progress: progress,
  339. });
  340. }
  341. },
  342. addNotification() {
  343. let _this = this;
  344. EventManager.addNotification(CmdEvent.eventName, function (event) {
  345. let name = event.cmdEvent;
  346. console.log("OTA页0:", event)
  347. let kind = event.heiJiaoKind;
  348. switch (name) {
  349. case EnumCmdEvent.otaCmd:
  350. let otaCmd = event.otaCmd;
  351. console.log("OTA页:", otaCmd, kind)
  352. if (otaCmd === 1 && kind == 1) {
  353. wx.hideLoading();
  354. // 设备收到开启OTA的回复,开始发送wifi信息
  355. _this.sendWiFiInfo()
  356. } else if (otaCmd === 0 && kind == 1) {
  357. // 设备回收到url,OTA结束了
  358. // _this.endOta(0)
  359. wx.hideLoading()
  360. wx.showModal({
  361. title: '等待设备升级中',
  362. showCancel: false
  363. })
  364. } else if (kind == 0) {
  365. wx.hideLoading()
  366. wx.showModal({
  367. title: 'WIFI连接失败了',
  368. showCancel: false
  369. })
  370. }
  371. break;
  372. case EnumCmdEvent.otaUrl:
  373. let otaUrl = event.otaUrl;
  374. if (otaUrl === 1) {
  375. // 开始发送url
  376. BtHelper.getInstance().wifiUrl(_this.string2ListInt(_this.data.otaData.url))
  377. } else {
  378. wx.hideLoading()
  379. // wifi失败
  380. wx.showModal({
  381. title: 'OTA升级失败了',
  382. showCancel: false
  383. })
  384. }
  385. break;
  386. }
  387. }, _this)
  388. },
  389. /**
  390. * 生命周期函数--监听页面加载
  391. */
  392. onLoad(options) {
  393. let param = JSON.parse(options.param)
  394. console.log("OTA界面:", param)
  395. let otaData = param.otaData
  396. let device = param.device
  397. this.setData({
  398. otaData: otaData,
  399. device: device,
  400. isShowOta: device.clientType === 'MW-S2(BLE)' || device.clientType === 'MW-S2'
  401. })
  402. this.addNotification()
  403. },
  404. onUnload() {
  405. EventManager.removeNotification(CmdEvent.eventName, this)
  406. },
  407. })