nfcTools.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647
  1. const app = getApp();
  2. import {tools} from "../des3/nfcTool"
  3. Component({
  4. options: {
  5. addGlobalClass: true,
  6. multipleSlots: true,
  7. },
  8. properties: {
  9. scanType: {
  10. type: Number,
  11. value: 1,
  12. },
  13. scanTxt: {
  14. value: '',
  15. },
  16. },
  17. data: {
  18. reading:false,
  19. key:"",
  20. nfc:"",
  21. debug:1,
  22. keyA:[0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7],
  23. keyB:[0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF],
  24. },
  25. pageLifetimes:{
  26. async show() {
  27. //type值,1查看有源状态,2激活有源标签,3锁闭有源标签,4读取有源标签温度,6读取防伪标签,7读取uid
  28. this.initNfc(this.scanType)
  29. },
  30. hide() {
  31. var nfc = this.nfc
  32. if(nfc){
  33. nfc.offDiscovered(this.discoverHandler)
  34. }
  35. },
  36. },
  37. async ready(){
  38. console.log(this.data.scanType)
  39. },
  40. methods: {
  41. offNfc(){
  42. return new Promise((resolve, reject)=>{
  43. if(this.nfc){
  44. this.nfc.offDiscovered({
  45. complete:(r)=>{
  46. this.nfc.stopDiscovery({
  47. complete:(res)=>{
  48. console.log(res)
  49. resolve()
  50. }
  51. })
  52. }
  53. })
  54. }else{
  55. resolve()
  56. }
  57. })
  58. },
  59. async initNfc(type){//初始化NFC
  60. var that = this
  61. if(this.data.debug)console.log(this.nfcObj)
  62. if(this.nfc){
  63. await this.offNfc()
  64. }
  65. this.type = type
  66. this.type = this.data.scanType
  67. const nfc = wx.getNFCAdapter()
  68. this.nfc = nfc
  69. return new Promise(async (resolve, reject)=>{
  70. this.nfc.onDiscovered(res=>{//监听NFC接近
  71. this.type = this.data.scanType
  72. var techs = res.techs
  73. this.techTime = new Date().getTime()
  74. this.nfcObj = this.nfc.getIsoDep();
  75. //连接NFC
  76. this.nfcObj.connect({
  77. success:async (resc)=>{
  78. this.setData({reading:true})
  79. var temp = {}
  80. //ACCESS验证
  81. await this.COS_Access()
  82. //读取有源标签温度
  83. if(this.type==4)temp =await this.read_yy()
  84. //检查有源标签状态
  85. if(this.type==1)temp =await this.check_yy_status()
  86. //激活有源标签
  87. if(this.type==2)temp =await this.active_yy()
  88. //锁闭有源标签
  89. if(this.type==3)temp =await this.close_yy()
  90. //读取防伪标签
  91. if(this.type==6)temp =await this.read_fw()
  92. //读取uid
  93. if(this.type==7)temp =await this.read_uid()
  94. //读取自定义信息
  95. if(this.type==8)temp =await this.read_data()
  96. //写入自定义信息
  97. if(this.type==9)temp =await this.write_data(this.data.scanTxt)
  98. //读采温周期
  99. if(this.type==10)temp =await this.read_interval()
  100. //读采温周期
  101. if(this.type==11)temp =await this.write_interval(this.data.scanTxt)
  102. //x106读取自定义信息和温度数据
  103. if(this.type==101)temp =await this.x106_end()
  104. //x106读取自定义信息和温度数据
  105. if(this.type==102)temp =await this.x106_start(this.data.scanTxt)
  106. this.setData({reading:false})
  107. this.triggerEvent('setNfcRes', temp)
  108. resolve(temp)
  109. },
  110. fail:err=>{
  111. if(this.data.debug)console.log("connect",err)
  112. reject(err)
  113. }
  114. })
  115. })
  116. this.nfc.startDiscovery({
  117. fail(err) {
  118. //app.globalData?.nonfc = true
  119. reject(err)
  120. }
  121. })
  122. })
  123. },
  124. async COS_Access(){
  125. await this.authNfc()
  126. var trnd = await this.setApdu([0xA2, 0xB0, 0x00, 0x10, 0x10])
  127. await this.calcKey(trnd)
  128. },
  129. sleep(ms){
  130. return new Promise(resolve => setTimeout(resolve, ms))
  131. },
  132. authNfc(){
  133. return new Promise(async (resolve, reject)=>{
  134. var authRes = await this.setApdu([0xA2, 0xA4, 0x00, 0x0C, 0x02, 0xAC, 0x01])
  135. if(authRes.join("") == "99192"){//[99,192]
  136. if(this.data.debug)console.log("解锁标签")
  137. await this.sleep(20)
  138. authRes = await this.setApdu([0xA2, 0xA4, 0x00, 0x0C, 0x02, 0xAC, 0x01])
  139. }
  140. if(authRes.join("") == "1440"){//[144,0]
  141. resolve()
  142. }else{
  143. if(this.data.debug)console.log("解锁失败")
  144. reject()
  145. }
  146. })
  147. },
  148. async calcKey(data){
  149. var trnd_bytes = data.slice(0,8)
  150. var mid_bytes = data.slice(8,17)
  151. var des3_key_list = []
  152. for(var i=0;i<8;i++){
  153. des3_key_list[i] = trnd_bytes[i] ^ this.data.keyA[i]
  154. des3_key_list[i+8] = mid_bytes[i] ^ this.data.keyB[i]
  155. }
  156. var des3_key_bytes = tools.numArrToHex(des3_key_list)//numArrToBit(des3_key_list)//
  157. this.des3Key = des3_key_bytes
  158. // this.des3Key = "11223344556677889900AABBCCDDEEFF"
  159. //3des的KEY
  160. var random_key_bytes = tools.numArrToHex(trnd_bytes)//numArrToBit(trnd_bytes)//
  161. var trnd_encrpyt_bytes = tools.encode3des(random_key_bytes,des3_key_bytes)
  162. var command_bytes = [0xA2, 0xD6, 0x00, 0x10, 0x10]
  163. var rad = [1,2,3,4,5,6,7,8]//8位随机字节,直接写死试试
  164. //拼三段指令
  165. command_bytes= [...command_bytes,...tools.hexToNumArr(trnd_encrpyt_bytes),...rad]
  166. if(this.data.debug)console.log(command_bytes)
  167. rad = tools.numArrToHex(rad)//numArrToBit(rad)//
  168. trnd_encrpyt_bytes = tools.encode3des(rad,des3_key_bytes)
  169. if(this.data.debug)console.log(tools.hexToNumArr(trnd_encrpyt_bytes))
  170. var authRes = await this.setApdu(command_bytes)
  171. return new Promise(async (resolve, reject)=>{
  172. if(authRes.join("") == "99192"){//[99,192]
  173. if(this.data.debug)console.log("解锁标签")
  174. authRes = await this.setApdu(command_bytes)
  175. }
  176. if(authRes.join("") == "1440"){//[144,0]
  177. var trnd = await this.setApdu([0xA2, 0xB0, 0x00, 0x10, 0x10])
  178. if(this.data.debug)console.log(trnd)
  179. if(trnd.slice(0,8).join("") == tools.hexToNumArr(trnd_encrpyt_bytes).join("")){
  180. if(this.data.debug)console.log("验证通过1")
  181. resolve()
  182. }else{
  183. if(this.data.debug)console.log("验证不通过")
  184. reject()
  185. }
  186. }else{
  187. if(this.data.debug)console.log("设备异常")
  188. reject()
  189. }
  190. })
  191. },
  192. async read_yy(){
  193. var data_bytes = await this.COS_Analysis(data_bytes)
  194. if(this.data.debug)console.log(data_bytes)
  195. return {data_bytes,timeUsed:new Date().getTime() - this.techTime}
  196. },
  197. async COS_Analysis(){
  198. await this.setApdu([0xA2, 0xA4, 0x00, 0x0C, 0x02, 0xDA, 0x01])
  199. var data_bytes = await this.ISO14443_4A_ReadBinary(0xA2, 0, 80, 56)
  200. var data_bias = 24
  201. var uid = data_bytes.substring(data_bias + 0, data_bias + 52)
  202. var CID_bytes = data_bytes.substring(data_bias + 0, data_bias + 4)
  203. var TID_bytes = data_bytes.substring(data_bias + 4, data_bias + 16)
  204. var GTIN_bytes = data_bytes.substring(data_bias + 16, data_bias + 36)
  205. var VID_bytes = data_bytes.substring(data_bias + 36, data_bias + 52)
  206. var MID_bytes = data_bytes.substring(data_bias + 52, data_bias + 68)
  207. var MAC_bytes = data_bytes.substring(data_bias + 68, data_bias + 84)
  208. var TRNG_bytes = data_bytes.substring(data_bias + 84, data_bias + 100)
  209. var PAGE_bytes = data_bytes.substring(data_bias + 100, data_bias + 102)
  210. var RNUM_bytes = data_bytes.substring(data_bias + 102, data_bias + 110)
  211. //解析校准值
  212. var data_Nums = tools.hexToNumArr(data_bytes)
  213. var Cal_Data = [[],[],[]]
  214. Cal_Data[0][0] = ((data_Nums[data_bias/2 + 56] >> 4) + data_Nums[data_bias/2 + 55]) / 10
  215. Cal_Data[0][1] = data_Nums[data_bias/2 + 57] + (data_Nums[data_bias/2 + 56] & 0x0F) * 256
  216. Cal_Data[1][0] = ((data_Nums[data_bias/2 + 59] >> 4) + data_Nums[data_bias/2 + 58]) / 10
  217. Cal_Data[1][1] = data_Nums[data_bias/2 + 60] + (data_Nums[data_bias/2 + 59] & 0x0F) * 256
  218. Cal_Data[2][0] = tools.hex2int((data_Nums[data_bias/2 + 62] >> 4) + tools.numArrToHex([data_Nums[data_bias/2 + 61]])) / 10
  219. Cal_Data[2][1] = data_Nums[data_bias/2 + 63] + (data_Nums[data_bias/2 + 62] & 0x0F) * 256
  220. //计算温度长度
  221. var record_number_int = tools.hex2int(RNUM_bytes)
  222. var record_data_size_int = Math.ceil(record_number_int * 11 / 8)
  223. var record_data_size_mod_int = record_data_size_int % 8
  224. if(record_data_size_mod_int){
  225. record_data_size_int = record_data_size_int + (8 - record_data_size_mod_int)
  226. }
  227. //读取数据
  228. const NDEF_MAX_INT = 4032
  229. var start_address_int = 78
  230. if ((start_address_int + record_data_size_int) > NDEF_MAX_INT){
  231. record_data_size_int = record_data_size_int - 8
  232. record_number_int = Math.floor(record_data_size_int * 8 / 11)
  233. }
  234. data_bytes = await this.ISO14443_4A_ReadBinary(0xA2, start_address_int, record_data_size_int, 56)
  235. data_bytes = tools.hexToNumArr(data_bytes)
  236. // 解析adc
  237. var tempture_data = []
  238. var repeat_cnt = Math.floor(record_number_int / 8)
  239. var count_residue = record_number_int % 8
  240. if (count_residue > 0)
  241. repeat_cnt += 1
  242. var decode_count = 0
  243. var temp = {}
  244. for(var i=0;i<repeat_cnt;i++){
  245. for(var j=0;j<8;j++){
  246. if(decode_count >= record_number_int)break;
  247. else decode_count += 1
  248. var adc_data_int = null
  249. if(j==0){
  250. adc_data_int = data_bytes[i * 11] * 256 + data_bytes[i * 11 + 1]
  251. adc_data_int = (adc_data_int & 0x0000FFE0) >> 5
  252. }else if(j==1){
  253. adc_data_int = data_bytes[i * 11 + 1] * 256 + data_bytes[i * 11 + 2]
  254. adc_data_int = (adc_data_int & 0x00001FFC) >> 2
  255. }else if(j==2){
  256. adc_data_int = data_bytes[i * 11 + 2] * 65536 + data_bytes[i * 11 + 3] * 256 + data_bytes[
  257. i * 11 + 4]
  258. adc_data_int = (adc_data_int & 0x0003FF80) >> 7
  259. }else if(j==3){
  260. adc_data_int = data_bytes[i * 11 + 4] * 256 + data_bytes[i * 11 + 5]
  261. adc_data_int = (adc_data_int & 0x00007FF0) >> 4
  262. }else if(j==4){
  263. adc_data_int = data_bytes[i * 11 + 5] * 256 + data_bytes[i * 11 + 6]
  264. adc_data_int = (adc_data_int & 0x00000FFE) >> 1
  265. }else if(j==5){
  266. adc_data_int = data_bytes[i * 11 + 6] * 65536 + data_bytes[i * 11 + 7] * 256 + data_bytes[
  267. i * 11 + 8]
  268. adc_data_int = (adc_data_int & 0x0001FFC0) >> 6
  269. }else if(j==6){
  270. adc_data_int = data_bytes[i * 11 + 8] * 256 + data_bytes[i * 11 + 9]
  271. adc_data_int = (adc_data_int & 0x000003FF8) >> 3
  272. }else if(j==7){
  273. adc_data_int = data_bytes[i * 11 + 9] * 256 + data_bytes[i * 11 + 10]
  274. adc_data_int = (adc_data_int & 0x000007FF) >> 0
  275. }
  276. adc_data_int = Math.floor(adc_data_int)
  277. temp = {}
  278. // 温度小于第二个校准点,使用第一个点和第二个点计算KB值
  279. var tempture1,adc1,tempture2,adc2
  280. if (adc_data_int < Cal_Data[1][1]){
  281. tempture1 = Cal_Data[0][0]
  282. adc1 = Cal_Data[0][1]
  283. tempture2 = Cal_Data[1][0]
  284. adc2 = Cal_Data[1][1]
  285. }else{
  286. tempture1 = Cal_Data[1][0]
  287. adc1 = Cal_Data[1][1]
  288. tempture2 = Cal_Data[2][0]
  289. adc2 = Cal_Data[2][1]
  290. }
  291. if ((adc1 - adc2) != 0){
  292. var k = (tempture1 - tempture2) / (adc1 - adc2)
  293. var b = tempture1 - (k * adc1)
  294. var tempture_float = k * adc_data_int + b
  295. temp['temp'] = Math.round(tempture_float*10)/10
  296. temp['adc'] = adc_data_int
  297. }else{
  298. temp['adc'] = adc_data_int
  299. }
  300. tempture_data.push(temp)
  301. }
  302. }
  303. return {
  304. "CID": CID_bytes,
  305. "TID": TID_bytes,
  306. "GTIN": GTIN_bytes,
  307. "VID": VID_bytes,
  308. "MID": MID_bytes,
  309. "MAC": MAC_bytes,
  310. "TRNG": TRNG_bytes,
  311. "PAGE": PAGE_bytes,
  312. "RUNM": RNUM_bytes,
  313. "CAL1": {
  314. "TEMP": Cal_Data[0][0],
  315. "ADC": Cal_Data[0][1]
  316. },
  317. "CAL2": {
  318. "TEMP": Cal_Data[1][0],
  319. "ADC": Cal_Data[1][1]
  320. },
  321. "CAL3": {
  322. "TEMP": Cal_Data[2][0],
  323. "ADC": Cal_Data[2][1]
  324. },
  325. 'tempture_data':tempture_data,
  326. "uid":uid,
  327. }
  328. },
  329. async read_uid(){
  330. await this.setApdu([0xA2, 0xA4, 0x00, 0x0C, 0x02, 0xDA, 0x01])
  331. var data_bytes = await this.ISO14443_4A_ReadBinary(0xA2, 0, 80, 56)
  332. var data_bias = 24
  333. var uid = data_bytes.substr(data_bias,data_bias+52)
  334. return {uid,timeUsed:new Date().getTime() - this.techTime}
  335. },
  336. async read_fw(){
  337. var data_bytes = await this.ISO14443_4A_ReadBinary(0xA4, 8, 8, 8)
  338. if(data_bytes?.length == 16){
  339. //记录值
  340. var record_adc_int_list = [tools.hex2int(data_bytes.substr(0,4)),tools.hex2int(data_bytes.substr(4,4))]
  341. //当前值
  342. var current_adc_int_list = [tools.hex2int(data_bytes.substr(8,4)),tools.hex2int(data_bytes.substr(12,4))]
  343. if(this.data.debug)console.log('阻值为:',[record_adc_int_list,current_adc_int_list])
  344. if(current_adc_int_list[0] && current_adc_int_list[1]){
  345. if(record_adc_int_list[0] && record_adc_int_list[1]){
  346. var abs0 = Math.abs(current_adc_int_list[0]-record_adc_int_list[0]) < record_adc_int_list[0]*0.01
  347. var abs1 = Math.abs(current_adc_int_list[1]-record_adc_int_list[1]) < record_adc_int_list[0]*0.01
  348. if(abs0 && abs1){
  349. if(this.data.debug)console.log('标签验证通过')
  350. await this.setApdu([0xA2, 0xA4, 0x00, 0x0C, 0x02, 0xDA, 0x01])
  351. var data_bytes = await this.ISO14443_4A_ReadBinary(0xA2, 0, 80, 56)
  352. var data_bias = 24
  353. var uid = data_bytes.substr(data_bias,data_bias+110)
  354. return {res:'ok',uid,timeUsed:new Date().getTime() - this.techTime}
  355. }else{
  356. if(this.data.debug)console.log('标签验证不通过')
  357. return {res:'no',uid:null,timeUsed:new Date().getTime() - this.techTime}
  358. }
  359. }else{
  360. if(this.data.debug)console.log('标签初始化')
  361. return {res:'init',uid:null,timeUsed:new Date().getTime() - this.techTime}
  362. }
  363. }else{
  364. if(this.data.debug)console.log('标签未放置到位,请重试')
  365. return {res:'retry',uid:null,timeUsed:new Date().getTime() - this.techTime}
  366. }
  367. }else{
  368. if(this.data.debug)console.log('读取结果异常,请重试')
  369. return {res:'retry',uid:null,timeUsed:new Date().getTime() - this.techTime}
  370. }
  371. },
  372. async write_data(write_bytes){
  373. if(!write_bytes){
  374. wx.showToast({
  375. title: '数据写入不能为空',
  376. })
  377. return {sta:0,msg:"写入不能为空",timeUsed:new Date().getTime() - this.techTime}
  378. }
  379. write_bytes = tools.str2NumArr(write_bytes)
  380. var len = write_bytes.length
  381. for(var i=0;i<(8-len%8);i++){
  382. write_bytes.push(255)
  383. }
  384. if(this.data.debug)console.log(write_bytes)
  385. var data_bytes = await this.COS_Write_Config(49316, write_bytes.length,write_bytes, 56)
  386. if(data_bytes.join('') == '1440'){
  387. return {sta:1,msg:"写入成功",timeUsed:new Date().getTime() - this.techTime}
  388. }else{
  389. return {sta:0,msg:"写入失败,请重试",timeUsed:new Date().getTime() - this.techTime}
  390. }
  391. },
  392. async read_data(){
  393. const maxData = 128
  394. var data_bytes = await this.COS_Read_Config(49316,maxData,56)
  395. var data_bytes = tools.hexToNumArr(data_bytes)
  396. var index = data_bytes.indexOf(255)
  397. index = index==-1?maxData:index
  398. data_bytes = data_bytes.slice(0,index)
  399. return {data:tools.numArrToBit(data_bytes),timeUsed:new Date().getTime() - this.techTime}
  400. },
  401. async read_interval(){
  402. var data_bytes = await this.COS_Read_Config(49213,16,16)
  403. console.log(data_bytes)
  404. data_bytes = data_bytes.substr(0,4)
  405. data_bytes = tools.hex2int(data_bytes)
  406. return {data:data_bytes,timeUsed:new Date().getTime() - this.techTime}
  407. },
  408. async write_interval(idel_num){
  409. var data_bytes = await this.COS_Read_Config(49213,16,16)
  410. idel_num = ("0000" + (parseInt(idel_num)).toString(16)).substr(-4)
  411. var write_bytes = idel_num+data_bytes.substr(4)
  412. write_bytes = tools.hexToNumArr(write_bytes)
  413. if(this.data.debug)console.log(write_bytes)
  414. var data_bytes = await this.COS_Write_Config(49213, 16,write_bytes, 16)
  415. if(data_bytes.join('') == '1440'){
  416. return {sta:1,msg:"写入成功",timeUsed:new Date().getTime() - this.techTime}
  417. }else{
  418. return {sta:0,msg:"写入失败,请重试",timeUsed:new Date().getTime() - this.techTime}
  419. }
  420. },
  421. async check_yy_status(){//检查有源标签状态
  422. var data_bytes = await this.COS_Read_Config(49162,8,8)
  423. var stateVal = tools.hexToNumArr(data_bytes)[0]
  424. if(stateVal){
  425. stateVal = tools.num2bin(stateVal) || []
  426. //0b11111000 py取下标为6
  427. if(stateVal[4] == '1'){
  428. // wx.showToast({title: '芯片已激活',})
  429. return {sta:1,msg:"设备已激活",timeUsed:new Date().getTime() - this.techTime}
  430. }
  431. if(stateVal[4] == '0'){
  432. // wx.showToast({title: '芯片未激活',})
  433. return {sta:0,msg:"设备已锁闭",timeUsed:new Date().getTime() - this.techTime}
  434. }
  435. return {sta:null,msg:"读取失败",timeUsed:new Date().getTime() - this.techTime}
  436. }else{
  437. return {sta:null,msg:"读取失败",timeUsed:new Date().getTime() - this.techTime}
  438. }
  439. },
  440. async active_yy(){
  441. //("NFC激活")
  442. var data_bytes = await this.COS_Write_Config(49162, 8,[0xFC, 0x03, 0x00, 0x0F, 0x20, 0x00, 0xF6, 0x00], 8)
  443. if(data_bytes.join('') == '1440'){
  444. //NFC操作成功,开始读取并修改page
  445. var data = await this.COS_Read_Config(49458,16,16)
  446. if(this.data.debug)console.log(data)
  447. if(data&&data.length ==32){
  448. data = tools.hexToNumArr(data)
  449. data[12] = 1
  450. data = tools.numArrToHex(data)
  451. data_bytes = await this.COS_Write_Config(49458, 16, data, 16)
  452. if(data_bytes.join('') == '1440'){
  453. // wx.showToast({title: 'NFC激活成功',})
  454. if(this.data.debug)console.log("设备已激活")
  455. return {sta:1,msg:"设备已激活",timeUsed:new Date().getTime() - this.techTime}
  456. }else{
  457. if(this.data.debug)console.log("激活失败,请重试!")
  458. // wx.showToast({title: 'NFC激活失败',})
  459. return {sta:null,msg:"激活失败,请重试!",timeUsed:new Date().getTime() - this.techTime}
  460. }
  461. }else{
  462. wx.showToast({title: '激活失败,请重试!',})
  463. return {sta:null,msg:"激活失败,请重试!",timeUsed:new Date().getTime() - this.techTime}
  464. }
  465. }else{
  466. wx.showToast({title: '激活失败,请重试!',})
  467. return {sta:null,msg:"激活失败,请重试!",timeUsed:new Date().getTime() - this.techTime}
  468. }
  469. },
  470. async close_yy(){
  471. //("NFC锁闭")
  472. var data_bytes = await this.COS_Write_Config(49162, 8,[0xF0, 0x03, 0x00, 0x0F, 0x20, 0x00, 0xF6, 0x00], 8)
  473. if(data_bytes.join('') == '1440'){
  474. //NFC操作成功,开始读取并修改page
  475. var data = await this.COS_Read_Config(49458,16,16)
  476. if(this.data.debug)console.log(data)
  477. if(data&&data.length ==32){
  478. data = tools.hexToNumArr(data)
  479. data[12] = 0
  480. data = tools.numArrToHex(data)
  481. data_bytes = await this.COS_Write_Config(49458, 16, data, 16)
  482. if(data_bytes.join('') == '1440'){
  483. wx.showToast({title: '设备锁闭成功',})
  484. return {sta:1,msg:"设备锁闭成功",timeUsed:new Date().getTime() - this.techTime}
  485. }else{
  486. wx.showToast({title: '设备锁闭失败,请重试!',})
  487. return {sta:null,msg:"设备锁闭失败,请重试!",timeUsed:new Date().getTime() - this.techTime}
  488. }
  489. }else{
  490. wx.showToast({title: '设备锁闭失败,请重试!',})
  491. return {sta:null,msg:"设备锁闭失败,请重试!",timeUsed:new Date().getTime() - this.techTime}
  492. }
  493. }else{
  494. wx.showToast({title: '设备锁闭失败,请重试!',})
  495. return {sta:null,msg:"设备锁闭失败,请重试!",timeUsed:new Date().getTime() - this.techTime}
  496. }
  497. },
  498. async COS_Write_Config(address_int, length_int, write_bytes, package_size){
  499. //选中CONFIG
  500. var data_bytes = await this.setApdu([0xA2, 0xA4, 0x00, 0x0C, 0x02, 0xCF, 0x01])
  501. write_bytes = tools.numArrToHex(write_bytes)
  502. var data_write_bytes = tools.encode3des(write_bytes,this.des3Key)
  503. data_write_bytes = tools.hexToNumArr(data_write_bytes)
  504. data_bytes = await this.ISO14443_4A_UpdateBinary(0xA2, address_int, length_int, data_write_bytes, package_size)
  505. return new Promise(async (resolve)=>{
  506. resolve(data_bytes)
  507. })
  508. },
  509. async COS_Read_Config(address_int, length_int, package_size){
  510. //选中CONFIG
  511. var data_bytes = await this.setApdu([0xA2, 0xA4, 0x00, 0x0C, 0x02, 0xCF, 0x01])
  512. data_bytes = await this.ISO14443_4A_ReadBinary(0xA2, address_int, length_int, package_size)
  513. return new Promise(async (resolve)=>{
  514. resolve(data_bytes)
  515. })
  516. },
  517. async ISO14443_4A_ReadBinary(cla_bytes, address_start_int, length_int, package_size_int){
  518. var data_read_bytes = []
  519. var des3_key_int_list = []
  520. var package_number_int = Math.floor(length_int / package_size_int)
  521. var package_bytes_left_int = length_int % package_size_int
  522. var i = 0
  523. //读取整包数据
  524. for(;i<package_number_int;i++){
  525. var data_address_int = address_start_int + i * package_size_int
  526. des3_key_int_list[0] = Math.floor(data_address_int / 256)
  527. des3_key_int_list[1] = data_address_int % 256
  528. var data_address_bytes = des3_key_int_list
  529. var rf_command_bytes = [cla_bytes,0xB0]
  530. rf_command_bytes = [...rf_command_bytes,...data_address_bytes,package_size_int]
  531. var data = await this.setApdu(rf_command_bytes)
  532. data.pop()
  533. data.pop()
  534. data_read_bytes.push(...data)
  535. }
  536. // i--
  537. // 读取剩余数据
  538. if(package_bytes_left_int != 0){
  539. // if(package_number_int!=0){
  540. // i = i + 1
  541. // }
  542. var data_address_int = address_start_int + i * package_size_int
  543. des3_key_int_list[0] = Math.floor(data_address_int / 256)
  544. des3_key_int_list[1] = data_address_int % 256
  545. var data_address_bytes = des3_key_int_list
  546. var rf_command_bytes = [cla_bytes,0xB0]
  547. rf_command_bytes = [...rf_command_bytes,...data_address_bytes,package_size_int]
  548. console.log(rf_command_bytes)
  549. var data = await this.setApdu(rf_command_bytes)
  550. data.pop()
  551. data.pop()
  552. data_read_bytes.push(...data)
  553. }
  554. var dataList = tools.numArrToHex(data_read_bytes)
  555. var strTemp = ""
  556. strTemp = tools.decode3des(dataList,this.des3Key)
  557. // for(var i=0;i<dataList.length;){
  558. // var temp = dataList.substr(i,16)
  559. // console.log("截取:"+i,temp)
  560. // var res = tools.decode3des(temp,this.des3Key)
  561. // console.log("解密:"+i,res)
  562. // strTemp = strTemp+res
  563. // i+=16
  564. // }
  565. return new Promise(async (resolve)=>{
  566. if(strTemp.length != dataList.length){wx.showToast({title: '解密失败',})}
  567. resolve(strTemp)
  568. })
  569. },
  570. async ISO14443_4A_UpdateBinary(cla_bytes,address_start_int, length_int, data_write_bytes, RF_PACKAGE_SIZE){
  571. var des3_key_int_list = []
  572. var package_size_int = RF_PACKAGE_SIZE
  573. var package_number_int = Math.floor(length_int / package_size_int)
  574. var package_bytes_left_int = length_int % package_size_int
  575. var i = 0
  576. var data_bytes = ''
  577. // 写整包数据
  578. for(;i<package_number_int;i++){
  579. var data_address_int = address_start_int + i * package_size_int
  580. des3_key_int_list[0] = Math.floor(data_address_int / 256)
  581. des3_key_int_list[1] = data_address_int % 256
  582. var data_address_bytes = des3_key_int_list//int_list2bytes(des3_key_int_list)
  583. var rf_command_bytes = [cla_bytes, 0xD6,...data_address_bytes,package_size_int,...data_write_bytes.slice(i * package_size_int,(i + 1) * package_size_int)]
  584. data_bytes = await this.setApdu(rf_command_bytes)
  585. await this.sleep(10)
  586. }
  587. // 写剩余数据
  588. if (package_bytes_left_int != 0){
  589. // if (package_number_int != 0){
  590. // i = i + 1
  591. // }
  592. var data_address_int = address_start_int + i * package_size_int
  593. des3_key_int_list[0] = Math.floor(data_address_int / 256)
  594. des3_key_int_list[1] = data_address_int % 256
  595. var data_address_bytes = des3_key_int_list//int_list2bytes(des3_key_int_list)
  596. var rf_command_bytes = [cla_bytes, 0xD6,...data_address_bytes,package_bytes_left_int,...data_write_bytes.slice(i * package_size_int,i * package_size_int+package_bytes_left_int)]
  597. data_bytes = await this.setApdu(rf_command_bytes)
  598. }
  599. return new Promise(async (resolve)=>{
  600. resolve(data_bytes)
  601. })
  602. },
  603. setApdu(arr){
  604. var that = this
  605. return new Promise((resolve, reject)=>{
  606. const nfcObj = that.nfcObj
  607. var key = new Uint8Array(arr).buffer
  608. nfcObj.transceive({
  609. data: key,
  610. success: res => {
  611. var hexData = tools.ab2NumArr(res.data)
  612. resolve(hexData)
  613. },
  614. fail:res=>{
  615. if(that.data.debug)console.log("transceive",res)
  616. reject(res)
  617. }
  618. })
  619. })
  620. },
  621. async x106_end(){
  622. //读温度
  623. var data = await this.read_yy()
  624. data = data.data_bytes
  625. //读自定义信息
  626. var str = await this.read_data()
  627. data.data = str.data
  628. //锁闭
  629. var data = await this.close_yy()
  630. //数据汇总返回
  631. return {data,timeUsed:new Date().getTime() - this.techTime}
  632. },
  633. async x106_start(config){
  634. //写入采温周期
  635. var time = config.split(";")[1]
  636. this.write_interval(time)
  637. //写自定义信息
  638. this.read_data(config)
  639. //激活
  640. var data = await this.active_yy()
  641. //数据汇总返回
  642. return {data,timeUsed:new Date().getTime() - this.techTime}
  643. },
  644. }
  645. })