bt-sensors-plugin-sk 1.3.6-beta4 → 1.3.6-beta5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BTSensor.js +17 -16
- package/README.md +2 -1
- package/package.json +1 -1
- package/public/124.js +1 -0
- package/public/159.js +1 -1
- package/public/540.js +1 -1
- package/public/598.js +8 -0
- package/public/{834.js.LICENSE.txt → 598.js.LICENSE.txt} +2 -0
- package/public/images/bm6.webp +0 -0
- package/public/main.js +1 -1
- package/public/remoteEntry.js +1 -1
- package/sensor_classes/BMBatteryMonitor.js +221 -0
- package/sensor_classes/FeasyComBeacon.js +1 -1
- package/sensor_classes/JBDBMS.js +357 -220
- package/sensor_classes/TestData/Jikong.json +36 -0
- package/sensor_classes/testxiaomi.js +45 -0
- package/temp.html +0 -0
- package/testxiaomi.js +27 -0
- package/.vscode/settings.json +0 -2
- package/Screenshot 2025-06-12 at 9.33.57/342/200/257AM.png +0 -0
- package/bt-sensors-plugin-sk copy.json +0 -170
- package/bt-sensors-plugin-sk.json.bak +0 -121
- package/development/TestData/Jikong.json +0 -14
- package/diff.txt +0 -2860
- package/public/143.js +0 -1
- package/public/834.js +0 -14
- package/test.txt +0 -805
- package/testGATT.js +0 -24
- package/vsl_patch_17_06_25.patch +0 -13
package/sensor_classes/JBDBMS.js
CHANGED
|
@@ -1,255 +1,392 @@
|
|
|
1
1
|
const BTSensor = require("../BTSensor");
|
|
2
|
+
|
|
2
3
|
function sumByteArray(byteArray) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
function checkSum(buffer){
|
|
11
|
-
if (buffer.length<5) {
|
|
12
|
-
console.log
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
sum = sumByteArray(
|
|
19
|
-
|
|
4
|
+
let sum = 0;
|
|
5
|
+
for (let i = 0; i < byteArray.length; i++) {
|
|
6
|
+
sum += byteArray[i];
|
|
7
|
+
}
|
|
8
|
+
return sum;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function checkSum(buffer) {
|
|
12
|
+
if (buffer.length < 5) {
|
|
13
|
+
console.log(
|
|
14
|
+
`Can't checksum ${buffer}. Invalid buffer. Buffer must be at least 5 bytes long.`
|
|
15
|
+
);
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
const checksum = buffer.readUInt16BE(buffer.length - 3);
|
|
19
|
+
let sum = sumByteArray(
|
|
20
|
+
Uint8Array.prototype.slice.call(buffer, 2, buffer.length - 3)
|
|
21
|
+
);
|
|
22
|
+
if (0xffff - sum + 1 == checksum) return true;
|
|
23
|
+
sum = sumByteArray(
|
|
24
|
+
Uint8Array.prototype.slice.call(buffer, 2, buffer.length - 2)
|
|
25
|
+
);
|
|
26
|
+
return 0xffff - sum + 1 == checksum;
|
|
20
27
|
}
|
|
21
28
|
|
|
22
29
|
class JBDBMS extends BTSensor {
|
|
23
|
-
|
|
30
|
+
static Domain = BTSensor.SensorDomains.electrical;
|
|
24
31
|
|
|
25
|
-
static TX_RX_SERVICE = "0000ff00-0000-1000-8000-00805f9b34fb"
|
|
26
|
-
static NOTIFY_CHAR_UUID = "0000ff01-0000-1000-8000-00805f9b34fb"
|
|
27
|
-
static WRITE_CHAR_UUID
|
|
28
|
-
|
|
29
|
-
static identify(device){
|
|
30
|
-
return null
|
|
32
|
+
static TX_RX_SERVICE = "0000ff00-0000-1000-8000-00805f9b34fb";
|
|
33
|
+
static NOTIFY_CHAR_UUID = "0000ff01-0000-1000-8000-00805f9b34fb";
|
|
34
|
+
static WRITE_CHAR_UUID = "0000ff02-0000-1000-8000-00805f9b34fb";
|
|
35
|
+
|
|
36
|
+
static identify(device) {
|
|
37
|
+
return null;
|
|
31
38
|
}
|
|
32
|
-
static ImageFile = "JBDBMS.webp"
|
|
39
|
+
static ImageFile = "JBDBMS.webp";
|
|
33
40
|
|
|
34
41
|
jbdCommand(command) {
|
|
35
|
-
return [
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
async sendReadFunctionRequest(
|
|
39
|
-
this.debug(
|
|
40
|
-
return await this.txChar.writeValueWithoutResponse(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
42
|
+
return [0xdd, 0xa5, command, 0x00, 0xff, 0xff - (command - 1), 0x77];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async sendReadFunctionRequest(command) {
|
|
46
|
+
this.debug(`${this.getName()}::sendReadFunctionRequest sending ${command}`);
|
|
47
|
+
return await this.txChar.writeValueWithoutResponse(
|
|
48
|
+
Buffer.from(this.jbdCommand(command))
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async initSchema() {
|
|
53
|
+
this.debug(`${this.getName()}::initSchema`);
|
|
54
|
+
|
|
55
|
+
super.initSchema();
|
|
56
|
+
this.addDefaultParam("batteryID");
|
|
57
|
+
|
|
58
|
+
this.addDefaultPath("voltage", "electrical.batteries.voltage").read = (
|
|
59
|
+
buffer
|
|
60
|
+
) => {
|
|
61
|
+
return buffer.readUInt16BE(4) / 100;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
this.addDefaultPath("current", "electrical.batteries.current").read = (
|
|
65
|
+
buffer
|
|
66
|
+
) => {
|
|
67
|
+
return buffer.readInt16BE(6) / 100;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
this.addDefaultPath(
|
|
71
|
+
"remainingCapacity",
|
|
72
|
+
"electrical.batteries.capacity.remaining"
|
|
73
|
+
).read = (buffer) => {
|
|
74
|
+
return (buffer.readUInt16BE(8) / 100) * 3600;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
this.addDefaultPath(
|
|
78
|
+
"capacity",
|
|
79
|
+
"electrical.batteries.capacity.actual"
|
|
80
|
+
).read = (buffer) => {
|
|
81
|
+
return (buffer.readUInt16BE(10) / 100) * 3600;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
this.addDefaultPath("cycles", "electrical.batteries.cycles").read = (
|
|
85
|
+
buffer
|
|
86
|
+
) => {
|
|
87
|
+
return buffer.readUInt16BE(12);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
this.addMetadatum("protectionStatus", "", "Protection Status", (buffer) => {
|
|
91
|
+
const bits = buffer.readUInt16BE(20).toString(2);
|
|
92
|
+
return {
|
|
93
|
+
singleCellOvervolt: bits[0] == "1",
|
|
94
|
+
singleCellUndervolt: bits[1] == "1",
|
|
95
|
+
packOvervolt: bits[2] == "1",
|
|
96
|
+
packUndervolt: bits[3] == "1",
|
|
97
|
+
chargeOvertemp: bits[4] == "1",
|
|
98
|
+
chargeUndertemp: bits[5] == "1",
|
|
99
|
+
dischargeOvertemp: bits[6] == "1",
|
|
100
|
+
dischargeUndertemp: bits[7] == "1",
|
|
101
|
+
chargeOvercurrent: bits[8] == "1",
|
|
102
|
+
dischargeOvercurrent: bits[9] == "1",
|
|
103
|
+
shortCircut: bits[10] == "1",
|
|
104
|
+
frontEndDetectionICError: bits[11] == "1",
|
|
105
|
+
softwareLockMOS: bits[12] == "1",
|
|
106
|
+
};
|
|
107
|
+
}).default = "electrical.batteries.{batteryID}.protectionStatus";
|
|
108
|
+
|
|
109
|
+
this.addDefaultPath(
|
|
110
|
+
"SOC",
|
|
111
|
+
"electrical.batteries.capacity.stateOfCharge"
|
|
112
|
+
).read = (buffer) => {
|
|
113
|
+
return buffer.readUInt8(23) / 100;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
this.addMetadatum("FET", "", "FET On/Off Status", (buffer) => {
|
|
117
|
+
return buffer.readUInt8(24) != 0;
|
|
118
|
+
}).default = "electrical.batteries.{batteryID}.FETStatus";
|
|
119
|
+
|
|
120
|
+
this.addMetadatum("FETCharging", "", "FET Status Charging", (buffer) => {
|
|
121
|
+
return (buffer.readUInt8(24) & 0x1) != 0;
|
|
122
|
+
}).default = "electrical.batteries.{batteryID}.FETStatus.charging";
|
|
123
|
+
|
|
124
|
+
this.addMetadatum(
|
|
125
|
+
"FETDischarging",
|
|
126
|
+
"",
|
|
127
|
+
"FET Status Discharging",
|
|
128
|
+
(buffer) => {
|
|
129
|
+
return (buffer.readUInt8(24) & 0x2) != 0;
|
|
118
130
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
131
|
+
).default = "electrical.batteries.{batteryID}.FETStatus.discharging";
|
|
132
|
+
|
|
133
|
+
if (this.numberOfCells == undefined || this.numberOfTemps == undefined) {
|
|
134
|
+
try {
|
|
135
|
+
this.debug(
|
|
136
|
+
`${this.getName()}::initSchema Getting number of cells and temps...`
|
|
137
|
+
);
|
|
138
|
+
// NOTE gatt conn initiated here, in init
|
|
139
|
+
await this.initGATTConnection();
|
|
140
|
+
const cellsAndTemps = await this.getNumberOfCellsAndTemps();
|
|
141
|
+
this.numberOfCells = cellsAndTemps.cells;
|
|
142
|
+
this.numberOfTemps = cellsAndTemps.temps;
|
|
143
|
+
} catch (e) {
|
|
144
|
+
console.error(e);
|
|
145
|
+
this.numberOfCells = 4;
|
|
146
|
+
this.numberOfTemps = 2;
|
|
127
147
|
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
for (let i = 0; i < this.numberOfTemps; i++) {
|
|
151
|
+
this.addMetadatum(
|
|
152
|
+
`temp${i}`,
|
|
153
|
+
"K",
|
|
154
|
+
`Temperature${i + 1} reading`,
|
|
155
|
+
(buffer) => {
|
|
156
|
+
return buffer.readUInt16BE(27 + i * 2) / 10;
|
|
157
|
+
}
|
|
158
|
+
).default = `electrical.batteries.{batteryID}.Temperature${i + 1}`;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
for (let i = 0; i < this.numberOfCells; i++) {
|
|
162
|
+
this.addMetadatum(
|
|
163
|
+
`cell${i}Voltage`,
|
|
164
|
+
"V",
|
|
165
|
+
`Cell ${i + 1} voltage`,
|
|
166
|
+
(buffer) => {
|
|
167
|
+
return buffer.readUInt16BE(4 + i * 2) / 1000;
|
|
168
|
+
}
|
|
169
|
+
).default = `electrical.batteries.{batteryID}.cell${i}.voltage`;
|
|
170
|
+
this.addMetadatum(
|
|
171
|
+
`cell${i}Balance`,
|
|
172
|
+
"",
|
|
173
|
+
`Cell ${i + 1} balance`
|
|
174
|
+
).default = `electrical.batteries.{batteryID}.cell${i}.balance`;
|
|
175
|
+
}
|
|
128
176
|
}
|
|
129
177
|
|
|
130
|
-
hasGATT(){
|
|
131
|
-
|
|
178
|
+
hasGATT() {
|
|
179
|
+
this.debug(`${this.getName()}::hasGATT`);
|
|
180
|
+
return true;
|
|
132
181
|
}
|
|
133
|
-
|
|
134
|
-
|
|
182
|
+
|
|
183
|
+
usingGATT() {
|
|
184
|
+
this.debug(`${this.getName()}::usingGATT`);
|
|
185
|
+
return true;
|
|
135
186
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}, 1000*(this?.pollFreq??60) )
|
|
187
|
+
// FIXME not really needed:
|
|
188
|
+
async initGATTNotifications() {
|
|
189
|
+
this.debug(`${this.getName()}::initGATTNotifications`);
|
|
140
190
|
}
|
|
141
191
|
|
|
142
|
-
async emitGATT(){
|
|
192
|
+
async emitGATT() {
|
|
193
|
+
this.debug(`${this.getName()}::emitGATT`);
|
|
143
194
|
try {
|
|
144
|
-
|
|
195
|
+
this.debug(`${this.getName()}::emitGATT calling getAndEmitBatteryInfo`);
|
|
196
|
+
await this.getAndEmitBatteryInfo();
|
|
197
|
+
this.debug(
|
|
198
|
+
`${this.getName()}::emitGATT returned from getAndEmitBatteryInfo`
|
|
199
|
+
);
|
|
200
|
+
} catch (e) {
|
|
201
|
+
console.error(e);
|
|
202
|
+
this.debug(
|
|
203
|
+
`${this.getName()}::emitGATT Failed to emit battery info for ${this.getName()}: ${e}`
|
|
204
|
+
);
|
|
145
205
|
}
|
|
146
|
-
|
|
147
|
-
|
|
206
|
+
// setTimeout(async () => {
|
|
207
|
+
try {
|
|
208
|
+
this.debug(`${this.getName()}::emitGATT calling getAndEmitCellVoltages`);
|
|
209
|
+
await this.getAndEmitCellVoltages();
|
|
210
|
+
this.debug(
|
|
211
|
+
`${this.getName()}::emitGATT returned from getAndEmitCellVoltages`
|
|
212
|
+
);
|
|
213
|
+
} catch (e) {
|
|
214
|
+
console.error(e);
|
|
215
|
+
this.debug(
|
|
216
|
+
`${this.getName()}::emitGATT Failed to emit Cell Voltages for ${this.getName()}: ${e}`
|
|
217
|
+
);
|
|
148
218
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
catch (e) {
|
|
152
|
-
this.debug(`Failed to emit Cell Voltages for ${this.getName()}: ${e}`)
|
|
153
|
-
}
|
|
154
|
-
}, 10000)
|
|
155
|
-
}
|
|
219
|
+
// }, 10000);
|
|
220
|
+
}
|
|
156
221
|
|
|
157
|
-
async getNumberOfCellsAndTemps(){
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
getBuffer
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
result = Uint8Array.prototype.slice.call(result, 0, offset+buffer.length)
|
|
186
|
-
this.rxChar.removeAllListeners()
|
|
187
|
-
clearTimeout(timer)
|
|
188
|
-
if (!checkSum(result))
|
|
189
|
-
reject(`Invalid checksum from ${this.getName()}, not processing.`)
|
|
190
|
-
|
|
191
|
-
resolve(result)
|
|
192
|
-
}
|
|
193
|
-
offset+=buffer.length
|
|
222
|
+
async getNumberOfCellsAndTemps() {
|
|
223
|
+
this.debug(`${this.getName()}::getNumberOfCellsAndTemps`);
|
|
224
|
+
const b = await this.getBuffer(0x3);
|
|
225
|
+
return { cells: b[25], temps: b[26] };
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
getBuffer(command) {
|
|
229
|
+
return new Promise(async (resolve, reject) => {
|
|
230
|
+
const r = await this.sendReadFunctionRequest(command);
|
|
231
|
+
let result = Buffer.alloc(256);
|
|
232
|
+
let offset = 0;
|
|
233
|
+
let datasize = -1;
|
|
234
|
+
const timer = setTimeout(() => {
|
|
235
|
+
clearTimeout(timer);
|
|
236
|
+
reject(
|
|
237
|
+
new Error(
|
|
238
|
+
`Response timed out (+30s) from JBDBMS device ${this.getName()}. `
|
|
239
|
+
)
|
|
240
|
+
);
|
|
241
|
+
}, 30000);
|
|
242
|
+
|
|
243
|
+
const valChanged = async (buffer) => {
|
|
244
|
+
if (offset == 0) {
|
|
245
|
+
//first packet
|
|
246
|
+
if (buffer[0] !== 0xdd || buffer.length < 5 || buffer[1] !== command)
|
|
247
|
+
reject(`Invalid buffer from ${this.getName()}, not processing.`);
|
|
248
|
+
else datasize = buffer[3];
|
|
194
249
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
250
|
+
buffer.copy(result, offset);
|
|
251
|
+
if (
|
|
252
|
+
buffer[buffer.length - 1] == 0x77 &&
|
|
253
|
+
offset + buffer.length - 7 == datasize
|
|
254
|
+
) {
|
|
255
|
+
result = Uint8Array.prototype.slice.call(
|
|
256
|
+
result,
|
|
257
|
+
0,
|
|
258
|
+
offset + buffer.length
|
|
259
|
+
);
|
|
260
|
+
this.rxChar.removeAllListeners();
|
|
261
|
+
clearTimeout(timer);
|
|
262
|
+
if (!checkSum(result))
|
|
263
|
+
reject(`Invalid checksum from ${this.getName()}, not processing.`);
|
|
198
264
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
}
|
|
265
|
+
resolve(result);
|
|
266
|
+
}
|
|
267
|
+
offset += buffer.length;
|
|
268
|
+
};
|
|
269
|
+
this.rxChar.on("valuechanged", valChanged);
|
|
270
|
+
});
|
|
271
|
+
}
|
|
203
272
|
|
|
204
|
-
async
|
|
205
|
-
|
|
206
|
-
(["current", "voltage", "remainingCapacity", "capacity","cycles", "protectionStatus", "SOC","FET",]).forEach((tag) =>
|
|
207
|
-
this.emitData( tag, buffer )
|
|
208
|
-
)
|
|
209
|
-
for (let i = 0; i<this.numberOfTemps; i++){
|
|
210
|
-
this.emitData(`temp${i}`,buffer)
|
|
211
|
-
}
|
|
212
|
-
const balances = buffer.readUInt32BE(16)
|
|
273
|
+
async initGATTConnection(isReconnecting = false) {
|
|
274
|
+
this.debug(`${this.getName()}::initGATTConnection`);
|
|
213
275
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
276
|
+
if (this.rxChar)
|
|
277
|
+
try {
|
|
278
|
+
this.rxChar.removeAllListeners();
|
|
279
|
+
await this.rxChar.stopNotifications();
|
|
280
|
+
} catch (e) {
|
|
281
|
+
console.error(e);
|
|
282
|
+
this.debug(`error while stopping notifications`);
|
|
283
|
+
this.debug(e);
|
|
284
|
+
}
|
|
217
285
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
this.
|
|
286
|
+
try {
|
|
287
|
+
await super.initGATTConnection(isReconnecting);
|
|
288
|
+
const gattServer = await this.getGATTServer();
|
|
289
|
+
|
|
290
|
+
this.txRxService = await gattServer.getPrimaryService(
|
|
291
|
+
this.constructor.TX_RX_SERVICE
|
|
292
|
+
);
|
|
293
|
+
this.rxChar = await this.txRxService.getCharacteristic(
|
|
294
|
+
this.constructor.NOTIFY_CHAR_UUID
|
|
295
|
+
);
|
|
296
|
+
this.txChar = await this.txRxService.getCharacteristic(
|
|
297
|
+
this.constructor.WRITE_CHAR_UUID
|
|
298
|
+
);
|
|
299
|
+
await this.rxChar.startNotifications();
|
|
300
|
+
} catch (e) {
|
|
301
|
+
console.error(e);
|
|
302
|
+
this.setError(e.message);
|
|
223
303
|
}
|
|
224
304
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
305
|
+
try {
|
|
306
|
+
// FIXME not really needed?
|
|
307
|
+
this.debug(`${this.getName()}::initGATTConnection sending a test poll`);
|
|
308
|
+
await this.getBuffer(0x03);
|
|
309
|
+
} catch (e) {
|
|
310
|
+
console.error(e);
|
|
311
|
+
this.debug(`Error encountered calling getBuffer(0x03)`);
|
|
230
312
|
}
|
|
231
|
-
|
|
232
|
-
}
|
|
313
|
+
//this.debug(`(${this.getName()}) Connections: ${this.connections++}`)
|
|
314
|
+
}
|
|
233
315
|
|
|
234
|
-
async
|
|
235
|
-
|
|
316
|
+
async getAndEmitBatteryInfo() {
|
|
317
|
+
return this.getBuffer(0x03).then((buffer) => {
|
|
318
|
+
[
|
|
319
|
+
"current",
|
|
320
|
+
"voltage",
|
|
321
|
+
"remainingCapacity",
|
|
322
|
+
"capacity",
|
|
323
|
+
"cycles",
|
|
324
|
+
"protectionStatus",
|
|
325
|
+
"SOC",
|
|
326
|
+
"FET",
|
|
327
|
+
].forEach((tag) => this.emitData(tag, buffer));
|
|
328
|
+
for (let i = 0; i < this.numberOfTemps; i++) {
|
|
329
|
+
this.emitData(`temp${i}`, buffer);
|
|
330
|
+
}
|
|
236
331
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
332
|
+
// cells 0-15 - read bits right to left
|
|
333
|
+
let balanceCells0to15 = buffer.readUInt16BE(16);
|
|
334
|
+
for (let i = 0; i < Math.min(16, this.numberOfCells); i++) {
|
|
335
|
+
const bit = (balanceCells0to15 >> i) & 1; // right-to-left
|
|
336
|
+
this.emit(`cell${i}Balance`, bit);
|
|
337
|
+
}
|
|
241
338
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}
|
|
339
|
+
// cells 16-31 - read bits right to left
|
|
340
|
+
let balanceCells16to31 = buffer.readUInt16BE(18);
|
|
341
|
+
for (let i = 0; i < Math.min(16, this.numberOfCells - 16); i++) {
|
|
342
|
+
const bit = (balanceCells16to31 >> i) & 1; // right-to-left
|
|
343
|
+
this.emit(`cell${16 + i}Balance`, bit);
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
}
|
|
247
347
|
|
|
248
|
-
async
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
}
|
|
252
|
-
|
|
348
|
+
async getAndEmitCellVoltages() {
|
|
349
|
+
return this.getBuffer(0x4).then((buffer) => {
|
|
350
|
+
for (let i = 0; i < this.numberOfCells; i++) {
|
|
351
|
+
this.emitData(`cell${i}Voltage`, buffer);
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
async initGATTInterval() {
|
|
357
|
+
this.debug(
|
|
358
|
+
`${this.getName()}::initGATTInterval pollFreq=${this?.pollFreq}`
|
|
359
|
+
);
|
|
360
|
+
this.intervalID = setInterval(
|
|
361
|
+
async () => {
|
|
362
|
+
this._error = false;
|
|
363
|
+
if (!(await this.device.isConnected())) {
|
|
364
|
+
await this.initGATTConnection(true);
|
|
365
|
+
}
|
|
366
|
+
await this.emitGATT();
|
|
367
|
+
},
|
|
368
|
+
(this?.pollFreq ?? 40) * 1000
|
|
369
|
+
);
|
|
370
|
+
|
|
371
|
+
try {
|
|
372
|
+
await this.emitGATT();
|
|
373
|
+
} catch (e) {
|
|
374
|
+
console.error(e);
|
|
375
|
+
this.setError(e.message);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
async deactivateGATT() {
|
|
380
|
+
this.debug(`${this.getName()}::deactivateGATT`);
|
|
381
|
+
|
|
382
|
+
// FIXME added this. needed any more?
|
|
383
|
+
if (this.intervalID) {
|
|
384
|
+
clearInterval(this.intervalID);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
await this.stopGATTNotifications(this.rxChar);
|
|
388
|
+
await super.deactivateGATT();
|
|
389
|
+
}
|
|
253
390
|
}
|
|
254
391
|
|
|
255
|
-
module.exports = JBDBMS;
|
|
392
|
+
module.exports = JBDBMS;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"delay":100,
|
|
3
|
+
"data":
|
|
4
|
+
{
|
|
5
|
+
"0x96": [
|
|
6
|
+
"55 aa eb 90 01 de 58 02 00 00 f0 0a 00 00 54 0b 00 00 10 0e 00 00 de 0d 00 00 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f6 09 00 00 f0 49 02 00 1e 00 00 00 3c 00 00 00 40 0d 03 00 1e 00 00 00 3c 00 00 00 3c 00 00 00 d0 07 00 00 f4 01 00 00 c2 01 00 00 f4 01 00 00 c2 01 00 00 00 00 00 00 1e 00 00 00 84 03 00 00 20 03 00 00 04 00 00 00 01 00 00 00 01 00 00 00 01 00",
|
|
7
|
+
"00 00 e0 93 04 00 dc 05 00 00 48 0d 00 00 00 00 00 00 00 00 00 00",
|
|
8
|
+
"00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00",
|
|
9
|
+
"b0 71 0b 00 08 00 00 00 00 7c f8 ff ff 1f 0d 00 00 00 00 00 00 2a",
|
|
10
|
+
"55 aa eb 90 02 de 02 0d 02 0d 02 0d 02 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0f 00 00 00 02 0d 00 00 00 00 2e 00 31 00 34 00 28 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
|
|
11
|
+
"00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 cb 00 00 00 00 00",
|
|
12
|
+
"06 34 00 00 e9 1d 00 00 c1 fd ff ff ac 00 ac 00 00 00 00 00 00 00 00 2a 5b f4 01 00 e0 93 04 00 40 00 00 00 bd 30 29 01 64 00 00 00 19 95 c1 03 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff 00 01 00 00 00 bf 03 01 00 03 00 12 5b 3f 40 00 00 00 00 33 05 39 1b 00 01 00 01 00 05 00 00 c0 2c df 00 00 00 00 00 cb 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
|
|
13
|
+
"00 00 00 00 00 00 00 00 00 fe ff 7f dc 0f 01 00 00 00 00 00 00 f1",
|
|
14
|
+
"55 aa eb 90 02 de 02 0d 02 0d 02 0d 02 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0f 00 00 00 02 0d 00 00 00 00 2e 00 31 00 34 00 28 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
|
|
15
|
+
"00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 cb 00 00 00 00 00",
|
|
16
|
+
"06 34 00 00 e9 1d 00 00 c1 fd ff ff ac 00 ac 00 00 00 00 00 00 00 00 2a 5b f4 01 00 e0 93 04 00 40 00 00 00 bd 30 29 01 64 00 00 00 19 95 c1 03 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff 00 01 00 00 00 bf 03 01 00 03 00 12 5b 3f 40 00 00 00 00 33 05 39 1b 00 01 00 01 00 05 00 00 c0 2c df 00 00 00 00 00 cb 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
|
|
17
|
+
"00 00 00 00 00 00 00 00 00 fe ff 7f dc 0f 01 00 00 00 00 00 00 f1",
|
|
18
|
+
"55 aa eb 90 01 de 58 02 00 00 f0 0a 00 00 54 0b 00 00 10 0e 00 00 de 0d 00 00 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f6 09 00 00 f0 49 02 00 1e 00 00 00 3c 00 00 00 40 0d 03 00 1e 00 00 00 3c 00 00 00 3c 00 00 00 d0 07 00 00 f4 01 00 00 c2 01 00 00 f4 01 00 00 c2 01 00 00 00 00 00 00 1e 00 00 00 84 03 00 00 20 03 00 00 04 00 00 00 01 00 00 00 01 00 00 00 01 00",
|
|
19
|
+
"00 00 e0 93 04 00 dc 05 00 00 48 0d 00 00 00 00 00 00 00 00 00 00",
|
|
20
|
+
"00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00",
|
|
21
|
+
"b0 71 0b 00 08 00 00 00 00 7c f8 ff ff 1f 0d 00 00 00 00 00 00 2a",
|
|
22
|
+
"aa bb cc dd ee ff",
|
|
23
|
+
"aa bb cc",
|
|
24
|
+
"55 aa eb 90 02 de 02 0d 02 0d 02 0d 02 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0f 00 00 00 02 0d 00 00 00 00 2e 00 31 00 34 00 28 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
|
|
25
|
+
"00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 cb 00 00 00 00 00",
|
|
26
|
+
"06 34 00 00 e9 1d 00 00 c1 fd ff ff ac 00 ac 00 00 00 00 00 00 00 00 2a 5b f4 01 00 e0 93 04 00 40 00 00 00 bd 30 29 01 64 00 00 00 19 95 c1 03 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff 00 01 00 00 00 bf 03 01 00 03 00 12 5b 3f 40 00 00 00 00 33 05 39 1b 00 01 00 01 00 05 00 00 c0 2c df 00 00 00 00 00 cb 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
|
|
27
|
+
"00 00 00 00 00 00 00 00 00 fe ff 7f dc 0f 01 00 00 00 00 00 00 f1"
|
|
28
|
+
],
|
|
29
|
+
"0x97":[
|
|
30
|
+
"55 aa eb 90 03 c4 4a 4b 5f 42 32 41 38 53 32 30 50 00 00 00 00 00 31 31 2e 58 57 00 00 00 31 31 2e 32 36 31 00 00 68 96 c1 03 18 00 00 00 48 42 31 5f 42 34 00 00 00 00 00 00 00 00 00 00 31 32 33 34 00 00 00 00 00 00 00 00 00 00 00 00 32 33 30 38 31 34 00 00 33 30 32 32 38 34 34 32 36 37 00 30 30 30 30 00 49 6e 70 75 74 20 55 73 65 72 64 61 74 61 00 00 31 32 33 33 32 31 00 00 00 00",
|
|
31
|
+
"00 00 00 00 00 00 49 6e 70 75 74 20 55 73 65 72 64 61 74 61 00 00",
|
|
32
|
+
"7c f8 ff ff 1f 0d 00 00 00 00 00 00 90 0f 00 00 00 00 c0 d8 03 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00",
|
|
33
|
+
"00 00 00 00 00 00 00 00 00 fe 2f 00 00 00 00 00 00 00 00 00 00 bf"
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
}
|