123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478 |
- const readServiceID = '0000FFE0-0000-1000-8000-00805F9B34FB';
- const readID = '0000FFE4-0000-1000-8000-00805F9B34FB';
- const writeServiceID = '0000FFE5-0000-1000-8000-00805F9B34FB';
- const writeID = '0000FFE9-0000-1000-8000-00805F9B34FB';
- var readPart = '';
- function acceptDevice(device) {
- return device.btid ? true : false;
- }
- function isDevice(device, data) {
- const advertisData = new Uint8Array(data.advertisData);
- const mac = device.btid
- .split('')
- .map((p, i) => parseInt(p + device.btid[i + 1], 16))
- .filter((p, i) => i % 2 == 0);
- if (advertisData.slice(0, 2).toString() == [82, 83].toString() && advertisData.slice(4, 10).toString() == mac.toString()) {
- return true;
- }
- return false;
- }
- function readDataBP00(value, data) {
- if (value.split('HSO').length == 2) {
- data.imei = value.split('HSO')[0];
- value = value.split('HSO')[1];
- while (value != '') {
- switch (value[0]) {
- case 'P':
- data.quantity = parseInt(value.slice(1, 3));
- value = value.slice(3, value.length);
- break;
- case 'S':
- data.gpscount = parseInt(value.slice(1, 3), 16);
- value = value.slice(3, value.length);
- break;
- case 'G':
- data.gsmlevel = parseInt(value.slice(1, 3), 16);
- value = value.slice(3, value.length);
- break;
- case 'T':
- data.temp = parseInt(value.slice(1, 5), 16) < 32768 ? parseInt(value.slice(1, 5), 16) : parseInt(value.slice(1, 5), 16) - 65536;
- value = value.slice(5, value.length);
- break;
- case 'C':
- data.cycle = parseInt(value.slice(1, 5), 16);
- value = value.slice(5, value.length);
- break;
- case 'B':
- var state = parseInt(value.slice(1, 3), 16);
- data.lowTempProtectState = (state >> 0) & 1;
- data.highTempProtectState = (state >> 1) & 1;
- data.dischargeProtectState = (state >> 2) & 1;
- data.chargeProtectState = (state >> 3) & 1;
- data.lowVoltageState = (state >> 4) & 1;
- data.chargeState = (state >> 5) & 3;
- data.oilState = (state >> 7) & false ? 1 : 0;
- value = value.slice(3, value.length);
- break;
- case 'X':
- var state = parseInt(value.slice(1, 3), 16);
- data.autoProtectState = (state >> 0) & 1;
- data.elecState = (state >> 1) & false ? 1 : 0;
- data.factoryType = state >> 2;
- value = value.slice(3, value.length);
- break;
- default:
- if (['P', 'S', 'G', 'T', 'C', 'B', 'X'].indexOf(value[3]) == -1) {
- //data.voltage = parseInt(value.slice(0, 4), 16) / 100
- value = value.slice(4, value.length);
- } else {
- //data.voltage = parseInt(value.slice(0, 3), 16) / 100
- value = value.slice(3, value.length);
- }
- }
- }
- console.log(data);
- return data;
- }
- return false;
- }
- function readDataBS50(value, data) {
- const length = parseInt(value.slice(0, 4), 16);
- value = value.slice(4, value.length);
- if (value.length == length * 2) {
- console.log(value);
- return BMSReply(
- value
- .split('')
- .map((p, i) => parseInt(p + value[i + 1], 16))
- .filter((p, i) => i % 2 == 0),
- data
- );
- }
- return false;
- }
- function BMSReply(value, data) {
- if (value[0] == 78 && value[1] == 87) {
- //value = value.slice(2, value.length)
- const length = value[2] * 256 + value[3];
- if (value.length == length + 2) {
- data.bmsid = value
- .slice(4, 8)
- .map((p) => ('00' + p.toString(16)).substr(p.toString(16).length))
- .join('');
- if (
- value[8] == 6 &&
- value[value.length - 5] == 104 &&
- value.slice(0, value.length - 4).reduce((p, c) => p + c) == value[value.length - 2] * 256 + value[value.length - 1]
- ) {
- value = value.slice(11, value.length - 9);
- while (value.length != 0) {
- switch (value[0]) {
- case 121:
- const voltageLength = parseInt(value[1] / 3);
- data.voltageList = Array(voltageLength);
- let maxVoltage = -1;
- let minVoltage = 99999;
- let sumVoltage = 0;
- for (var i = 0; i < voltageLength; i++) {
- let _v = Math.round(value[i * 3 + 3] * 256 + value[i * 3 + 4]) / 1000;
- console.log('xxxxx');
- console.log(value[i * 3 + 2] - 1);
- data.voltageList[value[i * 3 + 2] - 1] = _v;
- sumVoltage += _v;
- if (_v > maxVoltage) {
- maxVoltage = _v;
- }
- if (_v < minVoltage) {
- minVoltage = _v;
- }
- }
- data.maxVoltage = maxVoltage;
- data.minVoltage = minVoltage;
- data.sumVoltage = sumVoltage;
- value = value.slice(voltageLength * 3 + 2, value.length);
- break;
- case 128:
- data.powerMOSTemp = value[1] * 256 + value[2];
- if (data.powerMOSTemp > 100) {
- data.powerMOSTemp = 100 - data.powerMOSTemp;
- }
- value = value.slice(3, value.length);
- break;
- case 129:
- data.batteryChamberTemp = value[1] * 256 + value[2];
- if (data.batteryChamberTemp > 100) {
- data.batteryChamberTemp = 100 - data.batteryChamberTemp;
- }
- value = value.slice(3, value.length);
- break;
- case 130:
- data.temp = value[1] * 256 + value[2];
- if (data.temp > 100) {
- data.temp = 100 - data.temp;
- }
- value = value.slice(3, value.length);
- break;
- case 131:
- data.voltage = Math.round(value[1] * 256 + value[2]) / 100;
- value = value.slice(3, value.length);
- break;
- case 132:
- data.chargeState = 0;
- let _value = value[1] * 256 + value[2];
- if (_value > 10000) {
- data.current = (_value - 10000) * 0.01 * -1;
- data.chargeState = 2;
- } else if (_value < 10000) {
- data.current = (10000 - _value) * 0.01;
- data.chargeState = 1;
- }
- value = value.slice(3, value.length);
- break;
- case 133:
- data.quantity = value[1];
- data.soc = value[1];
- value = value.slice(2, value.length);
- break;
- case 134:
- data.tempCount = value[1];
- value = value.slice(2, value.length);
- break;
- case 135:
- data.cycle = value[1] * 256 + value[2];
- value = value.slice(3, value.length);
- break;
- case 137:
- data.totalCirculatingCapacity = value[1] * 16777216 + value[2] * 65536 + value[3] * 256 + value[4];
- value = value.slice(5, value.length);
- break;
- case 138:
- data.count = value[1] * 256 + value[2];
- value = value.slice(3, value.length);
- break;
- case 139:
- data.alarmState = [];
- if (((value[2] >> 0) & 1) == 1) {
- data.alarmState.push('低容量报警');
- }
- if (((value[2] >> 1) & 1) == 1) {
- data.alarmState.push('MOS管超温报警');
- }
- if (((value[2] >> 2) & 1) == 1) {
- data.alarmState.push('充电过压报警');
- }
- if (((value[2] >> 3) & 1) == 1) {
- data.alarmState.push('放电欠压报警');
- }
- if (((value[2] >> 4) & 1) == 1) {
- data.alarmState.push('电池超温报警');
- }
- if (((value[2] >> 5) & 1) == 1) {
- data.alarmState.push('充电过流报警');
- }
- if (((value[2] >> 6) & 1) == 1) {
- data.alarmState.push('放电过流报警');
- }
- if (((value[2] >> 7) & 1) == 1) {
- data.alarmState.push('电芯压差报警');
- }
- if (((value[1] >> 0) & 1) == 1) {
- data.alarmState.push('电池箱内超温报警');
- }
- if (((value[1] >> 1) & 1) == 1) {
- data.alarmState.push('电池低温报警');
- }
- if (((value[1] >> 2) & 1) == 1) {
- data.alarmState.push('单体过压报警');
- }
- if (((value[1] >> 3) & 1) == 1) {
- data.alarmState.push('单体欠压报警');
- }
- if (((value[1] >> 4) & 1) == 1) {
- data.alarmState.push('309_A保护');
- }
- if (((value[1] >> 5) & 1) == 1) {
- data.alarmState.push('309_B保护');
- }
- value = value.slice(3, value.length);
- break;
- case 140:
- let _tmp = (value[1] << 8) | value[2];
- // data.chargeProtectState = (value[2] >> 0 & 1)
- // data.dischargeProtectState = (value[2] >> 1 & 1)
- // data.equilibrium = (value[2] >> 2 & 1)
- // data.disconnectState = (value[2] >> 3 & 1)
- data.chargeProtectState = (_tmp & 1) == 0 ? 0 : 1;
- data.dischargeProtectState = (_tmp & 2) == 0 ? 0 : 1;
- data.equilibrium = (_tmp & 4) == 0 ? 0 : 1;
- data.disconnectState = (_tmp & 8) == 0 ? 0 : 1;
- value = value.slice(3, value.length);
- //console.log(value[1] + " " . value[2] + " " + _tmp + " ;" + data.equilibrium)
- break;
- case 142:
- value = value.slice(3, value.length);
- break;
- case 143:
- value = value.slice(3, value.length);
- break;
- case 144:
- value = value.slice(3, value.length);
- break;
- case 145:
- case 146:
- case 147:
- case 148:
- case 149:
- case 150:
- case 151:
- case 152:
- case 153:
- case 154:
- case 155:
- case 156:
- value = value.slice(3, value.length);
- break;
- case 157:
- value = value.slice(2, value.length);
- break;
- case 158:
- case 159:
- case 160:
- case 161:
- case 162:
- case 163:
- case 164:
- case 165:
- case 166:
- case 167:
- case 168:
- value = value.slice(3, value.length);
- break;
- case 169:
- value = value.slice(2, value.length);
- break;
- case 170:
- // 电池容量
- data.capacity = (value[1] << 24) | (value[2] << 16) | (value[3] << 8) | value[4];
- value = value.slice(5, value.length);
- break;
- case 171:
- case 172:
- value = value.slice(2, value.length);
- break;
- case 173:
- value = value.slice(3, value.length);
- break;
- case 174:
- case 175:
- value = value.slice(2, value.length);
- break;
- case 176:
- value = value.slice(3, value.length);
- break;
- case 177:
- value = value.slice(2, value.length);
- break;
- case 178:
- value = value.slice(11, value.length);
- break;
- case 179:
- value = value.slice(2, value.length);
- break;
- case 180:
- value = value.slice(9, value.length);
- break;
- case 181:
- value = value.slice(5, value.length);
- break;
- case 182:
- value = value.slice(5, value.length);
- break;
- case 183:
- // 软件版本号 15bit
- data.firmware = '';
- for (let i = 1; i <= 15; i++) {
- let _value = 33;
- let hx = value[i];
- if (hx >= 33 && hx <= 126) {
- _value = hx;
- }
- data.firmware += String.fromCharCode(_value);
- }
- value = value.slice(16, value.length);
- break;
- case 184:
- value = value.slice(2, value.length);
- break;
- case 185:
- value = value.slice(5, value.length);
- break;
- case 186:
- value = value.slice(25, value.length);
- break;
- default:
- value = [];
- }
- }
- }
- return data;
- }
- }
- return false;
- }
- function readData(device, value, data) {
- value = Array.from(new Int8Array(value))
- .map((p) => String.fromCharCode(p))
- .join('');
- console.log(value);
- if (value[value.length - 1] == ')') {
- value = readPart.concat(value);
- readPart = '';
- } else if (value[0] == '(') {
- readPart = value;
- } else {
- readPart = readPart.concat(value);
- }
- console.log(value);
- if (value[0] == '(' && value[value.length - 1] == ')') {
- value = value.slice(1, value.length - 1);
- if (value.slice(0, 12) == device.mac_id) {
- value = value.slice(12, value.length);
- switch (value.slice(0, 4)) {
- case 'BP00':
- return readDataBP00(value.slice(4, value.length), data);
- case 'BS50':
- return readDataBS50(value.slice(4, value.length), data);
- }
- }
- }
- return false;
- }
- /**
- * cmd: 命令字 02:写
- */
- function BMSCommand(data, cmd, type = 0) {
- // 帧来源: 01
- // 传输类型: 00
- const length = data.length + 18;
- var data = [78, 87, parseInt(length / 256), parseInt(length % 256), 0, 0, 0, 0, cmd, 1, type].concat(data).concat([0, 0, 0, 0, 104]);
- const sum = data.reduce((p, c) => p + c);
- data.push(parseInt(sum / 16777216));
- data.push(parseInt((sum % 16777216) / 65536));
- data.push(parseInt((sum % 65536) / 256));
- data.push(parseInt(sum % 256));
- console.log('222222');
- console.log(data);
- return data;
- }
- function BMSRead() {
- return BMSCommand([0], 6, 0);
- }
- function BMSTurnOn() {
- return BMSCommand([172, 1], 2, 1);
- }
- function BMSTurnOff() {
- return BMSCommand([172, 0], 2, 1);
- }
- function bmsChargingMOS(value) {
- return BMSCommand([171, value], 2, 0);
- }
- function bmsDischargeMOS(value, device) {
- return BMSCommand([172, value], 2, 0);
- }
- function sendData(device, cmd, data = []) {
- return (
- '(' +
- device.mac_id +
- cmd +
- data
- .map((p) => ('00' + p.toString(16)).substr(p.toString(16).length))
- .join('')
- .toUpperCase() +
- ')'
- )
- .split('')
- .map((p) => p.charCodeAt(0));
- }
- function sendDataAE00(device, data) {
- return sendData(device, 'AE00', [data.length % 256, parseInt(data.length / 256)].concat(data));
- }
- function stateUpdate(device, deviceId) {
- return [sendData(device, 'AU20'), sendDataAE00(device, BMSRead())];
- }
- function turnOn(device, deviceId) {
- return [sendDataAE00(device, BMSTurnOn())];
- }
- function turnOff(device, deviceId) {
- return [sendDataAE00(device, BMSTurnOff())];
- }
- function bmsInfo(device, deviceId, info) {
- console.log('--------');
- console.log(info);
- return false;
- }
- function bmsSet(device) {
- return false;
- }
- module.exports = {
- readServiceID: readServiceID,
- readID: readID,
- writeServiceID: writeServiceID,
- writeID: writeID,
- acceptDevice: acceptDevice,
- isDevice: isDevice,
- readData: readData,
- stateUpdate: stateUpdate,
- turnOn: turnOn,
- turnOff: turnOff,
- bmsInfo: bmsInfo,
- bmsSet: bmsSet,
- BMSCommand: BMSCommand,
- BMSRead: BMSRead,
- BMSTurnOn: BMSTurnOn,
- BMSTurnOff: BMSTurnOff,
- BMSReply: BMSReply,
- bmsChargingMOS: bmsChargingMOS,
- bmsDischargeMOS: bmsDischargeMOS
- };
|