Skip to content

Commit 54323cc

Browse files
committed
mac - add strategy for adding / removing attribute ID's
1 parent 13ce04e commit 54323cc

File tree

2 files changed

+82
-20
lines changed

2 files changed

+82
-20
lines changed

examples/pizza/peripheral.js

+11-14
Original file line numberDiff line numberDiff line change
@@ -54,19 +54,16 @@ bleno.on('advertisingStart', function(err) {
5454
// Once we are advertising, it's time to set up our services,
5555
// along with our characteristics.
5656
//
57-
bleno.setServices([
58-
pizzaService
59-
]);
60-
61-
var flip = false;
62-
setInterval(function (){
63-
if(flip){
64-
bleno.removeService(pizzaService2);
65-
} else {
66-
bleno.addService(pizzaService2);
67-
}
68-
flip = !flip;
69-
}, 1500);
70-
57+
bleno.setServices([ pizzaService ], function (){
58+
var flip = false;
59+
setInterval(function (){
60+
if(flip){
61+
bleno.removeService(pizzaService2);
62+
} else {
63+
bleno.addService(pizzaService2);
64+
}
65+
flip = !flip;
66+
}, 1500);
67+
});
7168
}
7269
});

lib/mac/bindings.js

+71-6
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,64 @@ blenoBindings.on('kCBMsgId17', function(args) {
150150
});
151151

152152
blenoBindings.addService = function AddGATTService(service) {
153-
var attributeId = this._attributes.length ? this._attributes.length - 1 : 1;
153+
var attributeId;
154+
var attributeCount = 1 + service.characteristics.length;
155+
var attributes = this._attributes;
156+
157+
/**
158+
* The goal is to find an attribute range that can host the full service, which in most cases will be the next available push
159+
* position. In the edge case, where our attribute consumes more Id's than the standard permits (0xFFFF), we must find
160+
* a place within our attributes array that has been vacated or throw an error.
161+
*/
162+
if(!attributes.length){
163+
attributeId = 1;
164+
} else if((attributes.length - 1 + attributeCount) >= 0xFFFF){
165+
// perform search to find somewhere within our attributes array that contains a hole that can host the attributeCount
166+
var consecutiveCount = 0;
167+
var groupedOpenings = {};
168+
for(var i = 0, ii = attributes.length; i < ii; i++){
169+
var attribute = attributes[i];
170+
if(!attribute.kCBMsgArgAttributeID){
171+
consecutiveCount++;
172+
} else if(attribute.kCBMsgArgAttributeID && consecutiveCount){
173+
174+
// If we have found this amount of openings before, don't mark in our group so we use the first available.
175+
if(!groupedOpenings[consecutiveCount].start){
176+
var previousIndex = i - 1;
177+
178+
// PreviousIndex - Attribute Openings
179+
var start = previousIndex - consecutiveCount;
180+
181+
// Previous Index
182+
var end = previousIndex;
183+
groupedOpenings[consecutiveCount] = { start: start, end: end};
184+
185+
if(consecutiveCount === attributeCount){
186+
break;
187+
}
188+
}
189+
consecutiveCount = 0;
190+
}
191+
}
192+
193+
if(groupedOpenings[attributeCount].start){
194+
attributeId = groupedOpenings[attributeCount].start;
195+
} else {
196+
for(var openingCount in groupedOpenings){
197+
if(parseInt(openingCount, 10) > attributeCount){
198+
attributeId = groupedOpenings[openingCount].start;
199+
break;
200+
}
201+
}
202+
}
203+
204+
if(!attributeId){
205+
throw new Error('Not enough space to add service.');
206+
}
207+
} else {
208+
attributeId = attributes.length;
209+
}
210+
154211
var arg = {
155212
kCBMsgArgAttributeID: attributeId,
156213
kCBMsgArgAttributeIDs: [],
@@ -225,6 +282,7 @@ blenoBindings.addService = function AddGATTService(service) {
225282
kCBMsgArgUUID: new Buffer(characteristic.uuid, 'hex')
226283
};
227284
this._attributes[attributeId] = characteristic;
285+
characteristic.attributeId = attributeId;
228286

229287
for (var k = 0; k < characteristic.descriptors.length; k++) {
230288
var descriptor = characteristic.descriptors[k];
@@ -241,17 +299,24 @@ blenoBindings.addService = function AddGATTService(service) {
241299
};
242300

243301
blenoBindings.removeService = function RemoveGATTService(service){
244-
var attributeId = this._attributes[service.attributeId];
302+
var attributes = this._attributes;
303+
var attributeId = service.attributeId;
304+
var attribute = attributes[attributeId];
305+
for(var i = 0, ii = attribute.characteristics.length; i < ii; i++){
306+
var characteristic = attribute.characteristics[i];
307+
attributes[characteristic.attributeId] = {};
308+
}
309+
attributes[attributeId] = {};
245310
var messageBody = {
246311
kCBMsgArgAttributeID: attributeId
247312
};
248-
this._attributes[service.attributeId] = {};
249-
this.sendCBMsg(11, attributeId);
250-
}
313+
this.sendCBMsg(11, messageBody);
314+
};
251315

252316
blenoBindings.removeAllServices = function RemoveAllGATTServices(){
317+
this._attributes = [];
253318
this.sendCBMsg(12, null);
254-
}
319+
};
255320

256321
blenoBindings.setServices = function SetGATTServices(services) {
257322
this.sendCBMsg(12, null);

0 commit comments

Comments
 (0)