Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

deviceUpgrade.js 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. // plugin/etc/pages/deviceUpgrade/deviceUpgrade.js
  2. import { starSearch, stopSearch } from "../../../utils/blue-related-tools/blue_tool.js"
  3. import { HOME_DIRECTORY, OBU_SYSTEM_FILE, RANDOM_NUMBER, APPLICATION_DIRECTORY, CMD_READBINARY, CMD_GETBALANCE } from '../../../utils/cmdConfig'
  4. import { transCmd, transCmdArrAfter, transCmdAfter } from '../../../utils/etc-sdk-tool/etc-sdk-tool'
  5. import { ActiveDevice, DisConnectDevice, EquipmentDetection } from "../../../utils/active-tools/active-device-tools.js"
  6. import { formatCardNumber } from "../../../utils/obj-tools.js"
  7. import { API } from '../../../network/etcApi'
  8. Page({
  9. /**
  10. * 页面的初始数据
  11. */
  12. data: {
  13. isLoading: false,
  14. showType: 1,
  15. showPopDevice: false,
  16. devList: [],
  17. searchFailMsg: "请检查手机蓝牙、ETC蓝牙是否均已打开,连接过程中将手机和ETC设备尽量靠近",
  18. searchFailTitle: "未检测到ETC设备",
  19. deviceInfo: "",
  20. cardIdStr: "",
  21. obuInfo: {
  22. version: '',
  23. obuId: '',
  24. chipSn: ''
  25. },
  26. cardInfo: {
  27. version: '',
  28. cardId: ''
  29. }
  30. },
  31. /**
  32. * 生命周期函数--监听页面加载
  33. */
  34. onLoad(options) {
  35. },
  36. // 设备升级
  37. devipdeUpgrade () {
  38. },
  39. // 点击开始搜索
  40. tapStar() {
  41. this.configNavTitle()
  42. this.setData({
  43. showPopDevice: false,
  44. devList: [],
  45. showType: 1,
  46. })
  47. wx.showLoading({
  48. title: '正在搜索设备...',
  49. })
  50. let self = this;
  51. starSearch((DevResult) => {
  52. console.log(DevResult);
  53. wx.hideLoading()
  54. if (DevResult.code == 0) {
  55. self.configNavTitle("验证设备")
  56. self.setData({
  57. devList: DevResult.data,
  58. showPopDevice: true,
  59. });
  60. } else {
  61. self.configSearchFail(DevResult.code)
  62. }
  63. }, false, "", false);
  64. },
  65. // 确认升级
  66. async tapOwner(e) {
  67. // stopSearch(false);
  68. let device = e.detail;
  69. this.data.deviceInfo = JSON.stringify(e)
  70. wx.showToast({
  71. title: '已选择设备',
  72. })
  73. const res = await this.configActive(device);
  74. },
  75. // 设备连接
  76. async configActive (device) {
  77. const that = this;
  78. const rt = await EquipmentDetection({
  79. device,
  80. disconnectCallback: () => {
  81. that.configSearchFail(250)
  82. },
  83. })
  84. if (rt.code !== 0) {
  85. return rt
  86. } else {
  87. this.getObjDetail()
  88. return res
  89. }
  90. },
  91. // 配置搜索失败
  92. configSearchFail(code) {
  93. let failMsg = "请检查手机蓝牙、ETC蓝牙是否均已打开,连接过程中将手机和ETC设备尽量靠近"
  94. let failTitle = "未检测到ETC设备"
  95. if (code == -111 || code == -112) {
  96. failMsg = code == -111 ? "手机蓝牙权限未授权,无法读取蓝牙是否开启状态,请打开蓝牙" : "手机定位权限获取失败,请前往手机系统设置开启手机定位服务"
  97. failTitle = "蓝牙状态异常"
  98. }
  99. this.setData({
  100. showType: 2,
  101. searchFailMsg: failMsg,
  102. searchFailTitle: failTitle,
  103. })
  104. },
  105. // 获取Obu设备详情
  106. async getObjDetail () {
  107. let cmdArr = [HOME_DIRECTORY, OBU_SYSTEM_FILE, RANDOM_NUMBER]
  108. let res = await transCmd(cmdArr, '20')
  109. console.log('设备卡签信息:1111')
  110. console.log(res)
  111. let cmdResult = res.cmdResult ? res.cmdResult.split(',') : []
  112. if (cmdResult && cmdResult.length) {
  113. var status = cmdResult[1].substring(cmdResult[1].length - 4, cmdResult[1].length);
  114. //第一次获取随机数
  115. if (status == "9000") {
  116. this.data.obuInfo.obuId = cmdResult[1].substring(20, 36);
  117. this.data.obuInfo.version = cmdResult[1].substring(18, 20);
  118. this.data.obuInfo.chipSn = cmdResult[1].substring(0, 8)
  119. console.log(this.data.obuInfo)
  120. this.getCardId()
  121. } else {
  122. wx.showToast('获取设备信息错误!')
  123. }
  124. } else {
  125. wx.showToast('获取设备信息错误!')
  126. }
  127. },
  128. // 获取卡信息
  129. async getCardId () {
  130. let cmdArr = [HOME_DIRECTORY, APPLICATION_DIRECTORY, CMD_READBINARY, CMD_GETBALANCE];
  131. let res = await transCmd(cmdArr, '10')
  132. let cmdResult = res.cmdResult ? res.cmdResult.split(',') : []
  133. let str = cmdResult[2].substring(cmdResult[2].length - 4, cmdResult[2].length); //判断是否为9000
  134. let str3 = cmdResult[3].substring(cmdResult[3].length - 4, cmdResult[3].length); //判断是否为9000
  135. if (str == "9000" || str3 == "9000") {
  136. if (cmdResult[2].length > 86 || cmdResult[3] >= 12) {
  137. this.data.cardInfo.cardId = cmdResult[2].substring(20, 40);
  138. this.data.cardInfo.version = cmdResult[2].substring(18, 20)
  139. console.log(this.data.cardInfo)
  140. this.devideUpgrade()
  141. } else {
  142. wx.showModal({
  143. title: '提示',
  144. content: "CMD_READBINARY指令长度不符" + cmdResult
  145. })
  146. }
  147. return;
  148. }
  149. },
  150. // 设备升级
  151. async devideUpgrade () {
  152. if (this.data.obuInfo.version == '48' || this.data.obuInfo.version == '49' || this.data.cardInfo.version == '48' || this.data.cardInfo.version == '49') {
  153. let params = {
  154. contractSN: this.data.obuInfo.obuId, //OBU合同序列号 16位
  155. chipSn: this.data.obuInfo.chipSn, //OBU晶片序列号 8位
  156. issueMode: 'UPG', //发行模式
  157. issueType: 'SCOBU', //发行发行类型
  158. cardVersion: this.data.cardInfo.version, //卡版本号
  159. obuVersion: this.data.obuInfo.version //OBU版本号
  160. }
  161. let applyData = await this.apply4Upgrade(params)
  162. if (!applyData || (applyData && applyData.code !== 200)) return false
  163. if (this.data.obuInfo.version == '48' || this.data.obuInfo.version == '49') {
  164. const updateEsDat = await this.updateEs('GEN_OBEIC_UPG', applyData);
  165. if (!updateEsDat) return false;
  166. }
  167. if (this.data.cardInfo.version == '48' || this.data.cardInfo.version == '49') {
  168. const updateEsDatTwo = await this.updateEs('GEN_OBESAM_UPG', applyData);
  169. if (!updateEsDatTwo) return false;
  170. }
  171. const upgradeDoneData = await API.ETC.vfjUpgradeDone({
  172. issueSerialNo: applyData.issueSerialNo, //发行订单号
  173. });
  174. if (!upgradeDoneData || (upgradeDoneData && upgradeDoneData.code !== 200)) return false;
  175. // 升级完成后完成后重新写入
  176. const cardres = await this.getCardIdAfter();
  177. if(!cardres || (cardres && cardres.code !== 200)) return;
  178. const obures = await this.getObuIdAfter();
  179. if(!obures || (obures && obures.code !== 200)) return;
  180. wx.showModal({
  181. title: '提示',
  182. content: '设备升级完成',
  183. showCancel: false,
  184. complete: (res) => {
  185. if (res.confirm) {
  186. wx.navigateBack()
  187. }
  188. }
  189. })
  190. } else {
  191. DisConnectDevice()
  192. wx.showModal({
  193. title: '提示',
  194. content: "设备版本暂时不需要升级",
  195. showCancel: false,
  196. success: () => {
  197. wx.navigateBack()
  198. }
  199. })
  200. }
  201. },
  202. // 获取发行指令脚本
  203. async updateEs (type, applyData) {
  204. wx.showLoading({
  205. title: '设备升级中'
  206. })
  207. let getCommanData = await API.ETC.getVfjGetCommands({
  208. cardNo: applyData.cardNo, //卡片序列号
  209. wareId: type, //OBU的物料代码 OBE-SAM通道 GEN_OBESAM_UPG OBE-IC通道 GEN_OBEIC_UPG
  210. issueSerialNo: applyData.issueSerialNo, //发行订单号
  211. })
  212. if (!getCommanData || (getCommanData && getCommanData.code !== 200)) return false;
  213. //指令解析
  214. const result = getCommanData.commands;
  215. const array = result.split('~');
  216. let cmdType = type == 'GEN_OBESAM_UPG' ? '20' : '10';
  217. for (const element of array) {
  218. console.log('updateEs', element, cmdType);
  219. // 让出主线程,确保UI更新
  220. await new Promise(resolve => setTimeout(resolve, 0));
  221. console.log("进来了", element.charAt(0), )
  222. if (element.charAt(0) === 'D' || element.charAt(0) === 'R') {
  223. await this.processDirectCommand(element, cmdType);
  224. } else if (element.charAt(0) === 'K') {
  225. await this.processKeyExchange(element, cmdType, applyData);
  226. } else if (element.charAt(0) === 'E') {
  227. await this.processExtAuth(element, cmdType, applyData);
  228. } else if (element === 'SESAM') {
  229. cmdType = '20';
  230. } else {
  231. cmdType = '10';
  232. }
  233. }
  234. return true;
  235. },
  236. processDirectCommand(element, cmdType) {
  237. // 添加随机延迟,避免连续请求
  238. return transCmdArrAfter(element.substring(1), cmdType);
  239. },
  240. async processKeyExchange(element, cmdType, applyData) {
  241. const ranData = await transCmdArrAfter('0084000004', cmdType);
  242. console.log("ranData", ranData)
  243. const exchangeKeyData = API.ETC.vfjExchangeKey({
  244. key: element.substring(1),
  245. random: ranData['0084000004'][0].substring(0, 8),
  246. issueSerialNo: applyData.issueSerialNo
  247. });
  248. if (!exchangeKeyData) throw new Error('密钥置换失败');
  249. console.log("exchangeKeyData", exchangeKeyData)
  250. return transCmdArrAfter(exchangeKeyData.apdu, cmdType);
  251. },
  252. async processExtAuth(element, cmdType, applyData) {
  253. const ranData = await transCmdArrAfter('0084000004', cmdType);
  254. const extAuth4IssData = API.ETC.vfjExtAuth4Iss({
  255. keyType: element.substring(1),
  256. random: ranData['0084000004'][0].substring(0, 8),
  257. issueSerialNo: applyData.issueSerialNo,
  258. });
  259. console.log("extAuth4IssData", extAuth4IssData)
  260. if (!extAuth4IssData) throw new Error('外部认证失败');
  261. return transCmdArrAfter(extAuth4IssData.apdu, cmdType);
  262. },
  263. // 获取设备升级指令
  264. apply4Upgrade(params) {
  265. return API.ETC.getVfjApply4Upgrade(params)
  266. },
  267. // 读卡
  268. async getCardIdAfter () {
  269. return new Promise(async (resolve, reject) =>{
  270. try{
  271. let cmdArr = [HOME_DIRECTORY, APPLICATION_DIRECTORY, CMD_READBINARY, CMD_GETBALANCE];
  272. const res = await transCmdAfter(cmdArr, "10");
  273. let cmdResult = res.cmdResult ? res.cmdResult.split(',') : []
  274. let str = cmdResult[2].substring(cmdResult[2].length - 4, cmdResult[2].length); //判断是否为9000
  275. let str3 = cmdResult[3].substring(cmdResult[3].length - 4, cmdResult[3].length); //判断是否为9000
  276. if (str == "9000" || str3 == "9000") {
  277. if (cmdResult[2].length > 86 || cmdResult[3] >= 12) {
  278. card.cardId = cmdResult[2].substring(20, 40);
  279. // card.cardId = '52012511110201724155';
  280. this.data.cardInfo.version = cmdResult[2].substring(18, 20),
  281. console.log(9999999)
  282. console.log(this.data.cardInfo)
  283. wx.hideLoading()
  284. resolve(true);
  285. return
  286. } else {
  287. console.log("CMD_READBINARY指令长度不符" + cmdResult[2]);
  288. this.showModals("CMD_READBINARY指令长度不符" + cmdResult[2])
  289. resolve(false);
  290. return
  291. }
  292. }
  293. console.log("CMD_READBINARY指令长度不符" + cmdResult[2]);
  294. this.showModals("CMD_READBINARY指令长度不符" + cmdResult[2])
  295. resolve(false);
  296. return
  297. } catch (e) {
  298. //TODO handle the exception
  299. console.log('错误错误', e);
  300. reject(e);
  301. }
  302. })
  303. },
  304. // 读取签
  305. getObuIdAfter(){
  306. return new Promise(async (resolve, reject) =>{
  307. try{
  308. let cmdArray = [HOME_DIRECTORY, OBU_SYSTEM_FILE, RANDOM_NUMBER];
  309. const res = await transCmdAfter(cmdArray, "20");
  310. let cmdResult = res.cmdResult ? res.cmdResult.split(',') : []
  311. var status = cmdResult[1].substring(cmdResult[1].length - 4, cmdResult[1].length);
  312. console.log('获取OBU号执行结果' + status, cmdResult)
  313. //第一次获取随机数
  314. if (status == "9000") {
  315. this.data.obuInfo.obuId = cmdResult[1].substring(20, 36);
  316. this.data.obuInfo.version = cmdResult[1].substring(18, 20);
  317. this.data.obuInfo.chipSn = cmdResult[1].substring(0, 8)
  318. resolve(true);
  319. console.log("success")
  320. return
  321. } else {
  322. this.showModals('获取设备信息错误!')
  323. resolve(false);
  324. return
  325. }
  326. } catch (e) {
  327. //TODO handle the exception
  328. console.log('错误错误', e);
  329. reject(e);
  330. }
  331. })
  332. },
  333. showModals (content) {
  334. wx.showModal({
  335. title: '提示',
  336. content: content,
  337. showCancel: false
  338. })
  339. },
  340. /// 配置导航栏标题
  341. configNavTitle(title = "设备搜索") {
  342. wx.setNavigationBarTitle({
  343. title: title,
  344. })
  345. },
  346. // 参数缺失处理
  347. paramsMiss (content) {
  348. wx.showModal({
  349. title: '参数缺失',
  350. content: content,
  351. showCancel: false,
  352. success: () => {
  353. wx.navigateBack()
  354. }
  355. })
  356. },
  357. /**
  358. * 生命周期函数--监听页面初次渲染完成
  359. */
  360. onReady() {
  361. },
  362. /**
  363. * 生命周期函数--监听页面显示
  364. */
  365. onShow() {
  366. },
  367. /**
  368. * 生命周期函数--监听页面隐藏
  369. */
  370. onHide() {
  371. },
  372. /**
  373. * 生命周期函数--监听页面卸载
  374. */
  375. onUnload() {
  376. },
  377. /**
  378. * 页面相关事件处理函数--监听用户下拉动作
  379. */
  380. onPullDownRefresh() {
  381. },
  382. /**
  383. * 页面上拉触底事件的处理函数
  384. */
  385. onReachBottom() {
  386. },
  387. /**
  388. * 用户点击右上角分享
  389. */
  390. onShareAppMessage() {
  391. }
  392. })