ZX16D.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. // <<信驰达低功耗蓝牙(BLE)模块及协议 v5.10u_(RS02A1-B)191230.pdf>>
  2. const common = require('../common.js');
  3. const readServiceID = '0000FEE7-0000-1000-8000-00805F9B34FB';
  4. const readID = '000036F6-0000-1000-8000-00805F9B34FB';
  5. const writeServiceID = '0000FEE7-0000-1000-8000-00805F9B34FB';
  6. const writeID = '000036F5-0000-1000-8000-00805F9B34FB';
  7. const FMBMS = require('./FMBMS.js');
  8. var curTime = 0;
  9. function acceptDevice(device) {
  10. return device.btid ? true : false;
  11. }
  12. function isSingleBt() {
  13. return true;
  14. }
  15. // function isDevice(device, data) {
  16. // const advertisData = new Uint8Array(data.advertisData)
  17. // const mac = device.btid.split('').map((p, i) => parseInt(p + device.btid[i + 1], 16)).filter((p, i) => i % 2 == 0)
  18. // console.log(advertisData.toString())
  19. // console.log(mac.toString())
  20. // console.log(advertisData.slice(0, 2).toString())
  21. // console.log(advertisData.slice(4, 10).toString() )
  22. // if (advertisData.slice(0, 2).toString() == [0x52, 0x53].toString() &&
  23. // advertisData.slice(4, 10).toString() == mac.toString()) {
  24. // return true
  25. // }
  26. // return false
  27. // }
  28. function isDevice(device, data) {
  29. const advertisData = new Uint8Array(data.advertisData);
  30. const mac = device.btid
  31. .split('')
  32. .map((p, i) => parseInt(p + device.btid[i + 1], 16))
  33. .filter((p, i) => i % 2 == 0);
  34. if (advertisData.slice(0, 4).toString() == [9, 255, 1, 2].toString() && advertisData.slice(4, 10).toString() == mac.toString()) {
  35. return true;
  36. }
  37. return false;
  38. }
  39. function readData(device, value, data) {
  40. var value = new Uint8Array(value);
  41. switch (value[0]) {
  42. case 68:
  43. if (value.length == 5) {
  44. console.log('xxxxx1');
  45. data.voltage = (((value[2] << 8) | value[3]) / 100).toFixed(2);
  46. }
  47. break;
  48. case 66:
  49. break;
  50. }
  51. var endTime = new Date().getTime();
  52. console.log('xxxxx2');
  53. if (endTime - curTime < 15000) {
  54. return;
  55. }
  56. console.log('xxxxx3');
  57. if (value[0] != 68 && value.length != 5) {
  58. return;
  59. }
  60. console.log('xxxxx4');
  61. if (endTime - curTime > 15000) {
  62. console.log('xxxxx5');
  63. if (value[0] == 68) {
  64. console.log('xxxxx7');
  65. curTime = new Date().getTime();
  66. }
  67. console.log('获取电压');
  68. console.log(data);
  69. return data;
  70. }
  71. }
  72. // function readData(device, value, data) {
  73. // value = Array.from(new Int8Array(value)).map(p => String.fromCharCode(p)).join('')
  74. // if (value[value.length - 1] == ')') {
  75. // value = readPart.concat(value)
  76. // readPart = ''
  77. // } else if (value[0] == '(') {
  78. // readPart = value
  79. // } else {
  80. // readPart = readPart.concat(value)
  81. // }
  82. // if (value[0] == '(' && value[value.length-1] == ')') {
  83. // value = value.slice(1, value.length-1)
  84. // if (value.slice(0, 12) == device.mac_id) {
  85. // console.log(value)
  86. // value = value.slice(12, value.length)
  87. // switch (value.slice(0, 4)) {
  88. // case 'BP00':
  89. // return readDataBP00(value.slice(4, value.length), data)
  90. // }
  91. // }
  92. // }
  93. // return false
  94. // }
  95. // function stateUpdate(device, deviceId) {
  96. // var data = '(' + device.mac_id + 'AU20)'
  97. // console.log(data)
  98. // return [data.split('').map(p => p.charCodeAt(0))]
  99. // }
  100. // function turnOn(device, deviceId) {
  101. // var data = '(' + device.mac_id + 'AV011)'
  102. // console.log(data)
  103. // console.log([data.split('').map(p => p.charCodeAt(0))])
  104. // return [data.split('').map(p => p.charCodeAt(0))]
  105. // }
  106. // function turnOff(device, deviceId) {
  107. // var data = '(' + device.mac_id + 'AV010)'
  108. // console.log(data)
  109. // return [data.split('').map(p => p.charCodeAt(0))]
  110. // }
  111. function stateUpdate(device, deviceId) {
  112. console.log('读电压');
  113. curTime = 0;
  114. return [sendCommand(4)];
  115. }
  116. function turnOn(device, deviceId) {
  117. console.log('通电');
  118. return [sendCommand(3, [170])];
  119. }
  120. function turnOff(device, deviceId) {
  121. console.log('断电');
  122. return [sendCommand(3, [187])];
  123. }
  124. // 鉴权
  125. function alterConnect(device, deviceId) {
  126. return [sendCommand(1, [171, 205, 171, 205])];
  127. }
  128. function sendCommand(cmd, data = []) {
  129. data = [cmd, data.length].concat(data);
  130. return common.completArrayCRC(data, data.length);
  131. }
  132. function bmsInfo(device, deviceId, info) {
  133. return {
  134. state: {
  135. soc: 0,
  136. voltageAll: info.voltage ? info.voltage : 0,
  137. tempCount: info.temp ? 1 : 0,
  138. temp: info.temp ? [info.temp] : []
  139. },
  140. state_v2: [
  141. {
  142. class: '',
  143. class_eng: '',
  144. icon: 0,
  145. vars: [
  146. {
  147. label: '总电压',
  148. label_eng: 'voltageAll',
  149. name: '',
  150. type: 'readonly',
  151. value: info.voltage || info.voltage == 0 ? info.voltage + 'V' : '未知'
  152. },
  153. {
  154. label: '充电保护',
  155. label_eng: '',
  156. name: '',
  157. type: 'readonly',
  158. value: info.chargeProtectState == 0 ? '正常' : info.chargeProtectState == 1 ? '异常' : '未知'
  159. },
  160. {
  161. label: '放电保护',
  162. label_eng: '',
  163. name: '',
  164. type: 'readonly',
  165. value: info.dischargeProtectState == 0 ? '正常' : info.dischargeProtectState == 1 ? '异常' : '未知'
  166. },
  167. {
  168. label: '电池超温',
  169. label_eng: '',
  170. name: '',
  171. type: 'readonly',
  172. value: info.highTempProtectState == 0 ? '正常' : info.highTempProtectState == 1 ? '异常' : '未知'
  173. },
  174. {
  175. label: '电池温度',
  176. label_eng: '',
  177. name: '',
  178. type: 'readonly',
  179. value: info.temp || info.temp == 0 ? info.temp + '°C' : '未知'
  180. },
  181. {
  182. label: '电池低温保护',
  183. label_eng: '',
  184. name: '',
  185. type: 'readonly',
  186. value: info.lowTempProtectState == 0 ? '正常' : info.lowTempProtectState == 1 ? '异常' : '未知'
  187. },
  188. {
  189. label: '充放电状态',
  190. label_eng: '',
  191. name: '',
  192. type: 'readonly',
  193. value: info.chargeState == 1 ? '充电' : info.chargeState == 2 ? '放电' : '静止'
  194. },
  195. {
  196. label: '循环次数',
  197. label_eng: '',
  198. name: '',
  199. type: 'readonly',
  200. value: info.cycle || info.cycle == 0 ? info.cycle + '次' : '未知'
  201. }
  202. ]
  203. }
  204. ],
  205. btsets: [
  206. {
  207. class: '高低温保护阀值',
  208. name: 'AU10',
  209. vars: [
  210. {
  211. label: '低温保护阀值',
  212. name: 'AU100',
  213. type: 'number',
  214. value: ''
  215. },
  216. {
  217. label: '高温保护阀值',
  218. name: 'AU101',
  219. type: 'number',
  220. value: ''
  221. }
  222. ]
  223. },
  224. {
  225. class: '充放电保护电压',
  226. name: 'AU12',
  227. vars: [
  228. {
  229. label: '充电保护电压',
  230. name: 'AU120',
  231. type: 'number',
  232. value: ''
  233. },
  234. {
  235. label: '放电保护电压',
  236. name: 'AU121',
  237. type: 'number',
  238. value: ''
  239. }
  240. ]
  241. },
  242. {
  243. class: '充放电保护开关',
  244. name: 'AU13',
  245. vars: [
  246. {
  247. label: '充电保护',
  248. name: 'AU130',
  249. type: 'radio',
  250. option: [
  251. {
  252. label: '关闭',
  253. value: '0'
  254. },
  255. {
  256. label: '开启',
  257. value: '1'
  258. }
  259. ],
  260. value: ''
  261. },
  262. {
  263. label: '放电保护',
  264. name: 'AU131',
  265. type: 'radio',
  266. option: [
  267. {
  268. label: '关闭',
  269. value: '0'
  270. },
  271. {
  272. label: '开启',
  273. value: '1'
  274. }
  275. ],
  276. value: ''
  277. }
  278. ]
  279. },
  280. {
  281. class: '充放电保护恢复电压',
  282. name: 'AU14',
  283. vars: [
  284. {
  285. label: '充电保护恢复电压',
  286. name: 'AU140',
  287. type: 'number',
  288. value: ''
  289. },
  290. {
  291. label: '放电保护恢复电压',
  292. name: 'AU141',
  293. type: 'number',
  294. value: ''
  295. }
  296. ]
  297. },
  298. {
  299. class: '高低温保护恢复值',
  300. name: 'AU15',
  301. vars: [
  302. {
  303. label: '低温保护恢复值',
  304. name: 'AU150',
  305. type: 'number',
  306. value: ''
  307. },
  308. {
  309. label: '高温保护恢复值',
  310. name: 'AU151',
  311. type: 'number',
  312. value: ''
  313. }
  314. ]
  315. },
  316. {
  317. class: '电池循环次数',
  318. name: 'AU16',
  319. vars: [
  320. {
  321. label: '循环次数',
  322. name: 'AU160',
  323. type: 'number',
  324. value: ''
  325. }
  326. ]
  327. },
  328. {
  329. class: 'BMS自动保护开关',
  330. name: 'AU17',
  331. vars: [
  332. {
  333. label: '自动保护',
  334. name: 'AU170',
  335. type: 'radio',
  336. option: [
  337. {
  338. label: '关闭',
  339. value: '0'
  340. },
  341. {
  342. label: '开启',
  343. value: '1'
  344. }
  345. ],
  346. value: ''
  347. }
  348. ]
  349. }
  350. ]
  351. };
  352. }
  353. function bmsSet(device, deviceId, name, vars) {
  354. var data = '';
  355. var name = device.name;
  356. switch (name) {
  357. case 'AU10':
  358. if (
  359. vars['AU100'] &&
  360. !isNaN(parseInt(vars['AU100'])) &&
  361. Math.abs(parseInt(vars['AU100'])) < 1000 &&
  362. vars['AU101'] &&
  363. !isNaN(parseInt(vars['AU101'])) &&
  364. Math.abs(parseInt(vars['AU101'])) < 1000
  365. ) {
  366. data =
  367. (parseInt(vars['AU100']) < 0 ? '-' : '+') +
  368. ('000' + Math.abs(parseInt(vars['AU100']))).substr(String(Math.abs(parseInt(vars['AU100']))).length) +
  369. (parseInt(vars['AU101']) < 0 ? '-' : '+') +
  370. ('000' + Math.abs(parseInt(vars['AU101']))).substr(String(Math.abs(parseInt(vars['AU101']))).length);
  371. }
  372. break;
  373. case 'AU12':
  374. if (
  375. vars['AU120'] &&
  376. !isNaN(parseFloat(vars['AU120'])) &&
  377. parseFloat(vars['AU120']) >= 0 &&
  378. parseInt(parseFloat(vars['AU120']) * 100) < 65536 &&
  379. vars['AU121'] &&
  380. !isNaN(parseFloat(vars['AU121'])) &&
  381. parseFloat(vars['AU121']) >= 0 &&
  382. parseInt(parseFloat(vars['AU121']) * 100) < 65536
  383. ) {
  384. data = (
  385. ('0000' + parseInt(parseFloat(vars['AU120']) * 100).toString(16)).substr(parseInt(parseFloat(vars['AU120']) * 100).toString(16).length) +
  386. ('0000' + parseInt(parseFloat(vars['AU121']) * 100).toString(16)).substr(parseInt(parseFloat(vars['AU121']) * 100).toString(16).length)
  387. ).toUpperCase();
  388. }
  389. break;
  390. case 'AU13':
  391. if (
  392. vars['AU130'] &&
  393. (parseInt(vars['AU130']) == 0 || parseInt(vars['AU130']) == 1) &&
  394. vars['AU131'] &&
  395. (parseInt(vars['AU131']) == 0 || parseInt(vars['AU131']) == 1)
  396. ) {
  397. data = parseInt(vars['AU130']).toString() + parseInt(vars['AU131']).toString();
  398. }
  399. break;
  400. case 'AU14':
  401. if (
  402. vars['AU140'] &&
  403. !isNaN(parseFloat(vars['AU140'])) &&
  404. parseFloat(vars['AU140']) >= 0 &&
  405. parseInt(parseFloat(vars['AU140']) * 100) < 65536 &&
  406. vars['AU141'] &&
  407. !isNaN(parseFloat(vars['AU141'])) &&
  408. parseFloat(vars['AU141']) >= 0 &&
  409. parseInt(parseFloat(vars['AU141']) * 100) < 65536
  410. ) {
  411. data = (
  412. ('0000' + parseInt(parseFloat(vars['AU140']) * 100).toString(16)).substr(parseInt(parseFloat(vars['AU140']) * 100).toString(16).length) +
  413. ('0000' + parseInt(parseFloat(vars['AU141']) * 100).toString(16)).substr(parseInt(parseFloat(vars['AU141']) * 100).toString(16).length)
  414. ).toUpperCase();
  415. }
  416. break;
  417. case 'AU15':
  418. if (
  419. vars['AU150'] &&
  420. !isNaN(parseInt(vars['AU150'])) &&
  421. Math.abs(parseInt(vars['AU150'])) < 1000 &&
  422. vars['AU151'] &&
  423. !isNaN(parseInt(vars['AU151'])) &&
  424. Math.abs(parseInt(vars['AU151'])) < 1000
  425. ) {
  426. data =
  427. (parseInt(vars['AU150']) < 0 ? '-' : '+') +
  428. ('000' + Math.abs(parseInt(vars['AU150']))).substr(String(Math.abs(parseInt(vars['AU150']))).length) +
  429. (parseInt(vars['AU151']) < 0 ? '-' : '+') +
  430. ('000' + Math.abs(parseInt(vars['AU151']))).substr(String(Math.abs(parseInt(vars['AU151']))).length);
  431. }
  432. break;
  433. case 'AU16':
  434. if (vars['AU160'] && !isNaN(parseInt(vars['AU160'])) && parseInt(vars['AU160']) >= 0 && parseInt(vars['AU160']) < 65536) {
  435. data = ('0000' + parseInt(vars['AU160']).toString(16)).substr(parseInt(vars['AU160']).toString(16).length).toUpperCase();
  436. }
  437. break;
  438. case 'AU17':
  439. if (vars['AU170'] && (parseInt(vars['AU170']) == 0 || parseInt(vars['AU170']) == 1)) {
  440. data = parseInt(vars['AU170']).toString() + parseInt(vars['AU170']).toString();
  441. }
  442. break;
  443. }
  444. if (data) {
  445. data = '(' + device.mac_id + name + data + ')';
  446. console.log(data);
  447. return [data.split('').map((p) => p.charCodeAt(0))];
  448. }
  449. if (device.type === 'FMBMS') {
  450. // FMBMS.setBMSParams("")
  451. }
  452. return false;
  453. }
  454. module.exports = {
  455. readServiceID: readServiceID,
  456. readID: readID,
  457. writeServiceID: writeServiceID,
  458. writeID: writeID,
  459. acceptDevice: acceptDevice,
  460. isDevice: isDevice,
  461. readData: readData,
  462. alterConnect: alterConnect,
  463. stateUpdate: stateUpdate,
  464. isSingleBt: isSingleBt,
  465. turnOn: turnOn,
  466. turnOff: turnOff,
  467. bmsInfo: bmsInfo,
  468. bmsSet: bmsSet
  469. };