-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
343 lines (316 loc) · 11.6 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
var noble=require('noble');
require('jnode/setup.js');
var debug=$('debug')('jnode:noble:core');
$.bt={noble:noble, devices:{}};
var serviceMapping={
'1811':'Alert Notification Service',
'1815':'Automation IO',
'180f':'./services/battery.js',
'1810':'Blood Pressure',
'181B':'Body Composition',
'181E':'Bond Management',
'181F':'Continuous Glucose Monitoring',
'1805':'Current Time Service',
'1818':'Cycling Power',
'1816':'Cycling Speed and Cadence',
'180A':'Device Information',
'181A':'Environmental Sensing',
'1800':'Generic Access',
'1801':'Generic Attribute',
'1808':'Glucose',
'1809':'Health Thermometer',
'180D':'Heart Rate',
'1812':'Human Interface Device',
'1802':'Immediate Alet',
'1821':'Indoor Positioning',
'1820':'Internet Protocol Support',
'1803':'Link Loss',
'1819':':Location and Navigation',
'1807':'Next DST Change Service',
'180E':'Phone Alert Status Service',
'1822':'Pulse Oximeter',
'1806':'Reference Time Update Service',
'1814':'Running Speed and Cadence',
'1813':'Scan Parameters',
'1804':'Tx Power',
'181C':'User Data',
'181D':'Weight Scale',
};
var characteristicsMapping={
'2A7E':'Aerobic Heart Rate Lower Limit',
'2A84':'Aerobic Heart Rate Upper Limit',
'2A7F':'Aerobic Threshold',
'2A80':'Age',
'2A5A':'Aggregate',
'2A43':'Alert Category ID',
'2A42':'Alert Category ID Bit Mask',
'2A06':'Alert Level',
'2A44':'Alert Notification Control Point',
'2A3F':'Alert Status',
'2AB3':'Altitude',
'2A81':'Anaerobic Heart Rate Lower Limit',
'2A82':'Anaerobic Heart Rate Upper Limit',
'2A83':'Anaerobic Threshold',
'2A58':'Analog',
'2A73':'Apparent Wind Direction',
'2A72':'Apparent Wind Speed',
'2A01':'Appearance',
'2AA3':'Barometric Pressure Trend',
'2A19':'Battery Level',
'2A49':'Blood Pressure Feature',
'2A35':'Blood Pressure Measurement',
'2A9B':'Body Composition Feature',
'2A9C':'Body Composition Measurement',
'2A38':'Body Sensor Location',
'2AA4':'Bond Management Control Point',
'2AA5':'Bond Management Feature',
'2A22':'Boot Keyboard Input Report',
'2A32':'Boot Keyboard Output Report',
'2A33':'Boot Mouse Input Report',
'2AA6':'Central Address Resolution',
'2AA8':'CGM Feature',
'2AA7':'CGM Measurement',
'2AAB':'CGM Session Run Time',
'2AAA':'CGM Session Start Time',
'2AAC':'CGM Specific Ops Control Point',
'2AA9':'CGM Status',
'2A5C':'CSC Feature',
'2A5B':'CSC Measurement',
'2A2B':'Current Time',
'2A66':'Cycling Power Control Point',
'2A65':'Cycling Power Feature',
'2A63':'Cycling Power Measurement',
'2A64':'Cycling Power Vector',
'2A99':'Database Change Increment',
'2A85':'Date of Birth',
'2A86':'Date of Threshold Assessment',
'2A08':'Date Time',
'2A0A':'Day Date Time',
'2A09':'Day of Week',
'2A7D':'Descriptor Value Changed',
'2A00':'Device Name',
'2A7B':'Dew Point',
'2A56':'Digital',
'2A0D':'DST Offset',
'2A6C':'Elevation',
'2A87':'Email Address',
'2A0C':'Exact Time 256',
'2A88':'Fat Burn Heart Rate Lower Limit',
'2A89':'Fat Burn Heart Rate Upper Limit',
'2A26':'Firmware Revision String',
'2A8A':'First Name',
'2A8B':'Five Zone Heart Rate Limits',
'2AB2':'Floor Number',
'2A8C':'Gender',
'2A51':'Glucose Feature',
'2A18':'Glucose Measurement',
'2A34':'Glucose Measurement Context',
'2A74':'Gust Factor',
'2A27':'Hardware Revision String',
'2A39':'Heart Rate Control Point',
'2A8D':'Heart Rate Max',
'2A37':'Heart Rate Measurement',
'2A7A':'Heat Index',
'2A8E':'Height',
'2A4C':'HID Control Point',
'2A4A':'HID Information',
'2A8F':'Hip Circumference',
'2A6F':'Humidity',
'2A2A':'IEEE 11073-20601 Regulatory Certification Data List',
'2AAD':'Indoor Positioning Configuration',
'2A36':'Intermediate Cuff Pressure',
'2A1E':'Intermediate Temperature',
'2A77':'Irradiance',
'2AA2':'Language',
'2A90':'Last Name',
'2AAE':'Latitude',
'2A6B':'LN Control Point',
'2A6A':'LN Feature',
'2AB1':'Local East Coordinate',
'2AB0':'Local North Coordinate',
'2A0F':'Local Time Information',
'2A67':'Location and Speed',
'2AB5':'Location Name',
'2AAF':'Longitude',
'2A2C':'Magnetic Declination',
'2AA0':'Magnetic Flux Density - 2D',
'2AA1':'Magnetic Flux Density - 3D',
'2A29':'Manufacturer Name String',
'2A91':'Maximum Recommended Heart Rate',
'2A21':'Measurement Interval',
'2A24':'Model Number String',
'2A68':'Navigation',
'2A46':'New Alert',
'2A04':'Peripheral Preferred Connection Parameters',
'2A02':'Peripheral Privacy Flag',
'2A5F':'PLX Continuous Measurement',
'2A60':'PLX Features',
'2A5E':'PLX Spot-Check Measurement',
'2A50':'PnP ID',
'2A75':'Pollen Concentration',
'2A69':'Position Quality',
'2A6D':'Pressure',
'2A4E':'Protocol Mode',
'2A78':'Rainfall',
'2A03':'Reconnection Address',
'2A52':'Record Access Control Point',
'2A14':'Reference Time Information',
'2A4D':'Report',
'2A4B':'Report Map',
'2A92':'Resting Heart Rate',
'2A40':'Ringer Control Point',
'2A41':'Ringer Setting',
'2A54':'RSC Feature',
'2A53':'RSC Measurement',
'2A55':'SC Control Point',
'2A4F':'Scan Interval Window',
'2A31':'Scan Refresh',
'2A5D':'Sensor Location',
'2A25':'Serial Number String',
'2A05':'Service Changed',
'2A28':'Software Revision String',
'2A93':'Sport Type for Aerobic and Anaerobic Thresholds',
'2A47':'Supported New Alert Category',
'2A48':'Supported Unread Alert Category',
'2A23':'System ID',
'2A6E':'Temperature',
'2A1C':'Temperature Measurement',
'2A1D':'Temperature Type',
'2A94':'Three Zone Heart Rate Limits',
'2A12':'Time Accuracy',
'2A13':'Time Source',
'2A16':'Time Update Control Point',
'2A17':'Time Update State',
'2A11':'Time with DST',
'2A0E':'Time Zone',
'2A71':'True Wind Direction',
'2A70':'True Wind Speed',
'2A95':'Two Zone Heart Rate Limit',
'2A07':'Tx Power Level',
'2AB4':'Uncertainty',
'2A45':'Unread Alert Status',
'2A9F':'User Control Point',
'2A9A':'User Index',
'2A76':'UV Index',
'2A96':'VO2 Max',
'2A97':'Waist Circumference',
'2A98':'Weight',
'2A9D':'Weight Measurement',
'2A9E':'Weight Scale Feature',
'2A79':'Wind Chill',
};
noble.on('stateChange', function(state) {
console.log(state);
if (state === 'poweredOn') {
noble.startScanning([], true);
} else {
noble.stopScanning();
}
});
var connectedPeripherals=[];
noble.on('discover', function(peripheral) {
//debug('peripheral discovered (' + peripheral.uuid +
// ' with address <' + peripheral.address + ', ' + peripheral.addressType + '>, RSSI ' + peripheral.rssi + ':');
//var notified=false;
if(!$.bt.devices[peripheral.uuid])
{
peripheral.on('connect', function(){
console.log('connected to device '+peripheral.uuid);
peripheral.connected=true;
connectedPeripherals.push(peripheral);
});
peripheral.on('disconnect', function(){
console.log('disconnected from device '+peripheral.uuid);
peripheral.connected=false;
connectedPeripherals.splice(connectedPeripherals.indexOf(peripheral), 1);
/*if(!notified)
peripheral.connect(function(){
noble.write(peripheral.uuid, '1803', '2a06', new Buffer([0x01]), true);
});*/
if(connectedPeripherals.length==0)
noble.startScanning([], true);
});
}
else
peripheral.emit('update');
$.bt.devices[peripheral.uuid]=peripheral;
/*console.log('peripheral discovered (' + peripheral.uuid +
' with address <' + peripheral.address + ', ' + peripheral.addressType + '>, RSSI ' + peripheral.rssi + ':');
console.log('\thello my local name is:');
console.log('\t\t' + peripheral.advertisement.localName);
console.log('\tcan I interest you in any of the following advertised services:');
console.log('\t\t' + JSON.stringify($.map(peripheral.advertisement.serviceUuids, function(v){ return serviceMapping[v]; })));
var serviceData = peripheral.advertisement.serviceData;
if (serviceData && serviceData.length) {
console.log('\there is my service data:');
for (var i in serviceData) {
console.log('\t\t' + JSON.stringify(serviceData[i].uuid) + ': ' + JSON.stringify(serviceData[i].data.toString('hex')));
}
}*/
//console.log(peripheral.advertisement);
/*if (peripheral.advertisement.manufacturerData) {
console.log('\there is my manufacturer data:');
console.log('\t\t' + JSON.stringify(peripheral.advertisement.manufacturerData.toString('hex')));
}
if (peripheral.advertisement.txPowerLevel !== undefined) {
console.log('\tmy TX power level is:');
console.log('\t\t' + peripheral.advertisement.txPowerLevel);
}*/
/*peripheral.on('rssiUpdate', function(rssi)
{
console.log('RSSI for '+peripheral.advertisement.localName+' ('+peripheral.address+') : '+rssi);
});
peripheral.connect(function(error){
if(error)
{
console.log(error);
return;
}
peripheral.discoverServices([], function(error, services) {
$.each(services, function(i, service){
console.log('discovered '+service.name);
service.discoverCharacteristics([], function(error, characteristics) {
$.each(characteristics, function(i, characteristic){
console.log('discovered characteristic ('+ characteristic.properties.join(', ') +')'+ characteristic.name+' for '+service.name);
if(service.uuid=='1803' && characteristic.uuid=='2a06')
{
console.log('notifying peripheral');
var data=new Buffer(4);
data.writeUInt8(1, 0);
characteristic.write(data, true);
characteristic.on('data', function(data, isNotification){
console.log(arguments);
});
characteristic.notify(true, function(){
console.log(arguments);
});
}
/*if(service.uuid=='1802' && characteristic.uuid=='2a06')
{
console.log('notifying peripheral');
var data=new Buffer(4);
data.writeUInt8(1, 0);
characteristic.write(data, true);
}
if(characteristic.uuid=='2a19')
{
characteristic.on('data', function(data, isNotification) {
console.log('battery level is now: ', data.readUInt8(0) + '%');
});
// true to enable notify
characteristic.notify(true, function(error) {
console.log('battery level notification on');
});
}*//*
})
})
});
});
})*/
});
process.on('exit', function(){
noble.stopScanning();
$.each(connectedPeripherals, function(i, peripheral){
peripheral.disconnect();
});
});