@@ -150,7 +150,64 @@ blenoBindings.on('kCBMsgId17', function(args) {
150
150
} ) ;
151
151
152
152
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
+
154
211
var arg = {
155
212
kCBMsgArgAttributeID : attributeId ,
156
213
kCBMsgArgAttributeIDs : [ ] ,
@@ -225,6 +282,7 @@ blenoBindings.addService = function AddGATTService(service) {
225
282
kCBMsgArgUUID : new Buffer ( characteristic . uuid , 'hex' )
226
283
} ;
227
284
this . _attributes [ attributeId ] = characteristic ;
285
+ characteristic . attributeId = attributeId ;
228
286
229
287
for ( var k = 0 ; k < characteristic . descriptors . length ; k ++ ) {
230
288
var descriptor = characteristic . descriptors [ k ] ;
@@ -241,17 +299,24 @@ blenoBindings.addService = function AddGATTService(service) {
241
299
} ;
242
300
243
301
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 ] = { } ;
245
310
var messageBody = {
246
311
kCBMsgArgAttributeID : attributeId
247
312
} ;
248
- this . _attributes [ service . attributeId ] = { } ;
249
- this . sendCBMsg ( 11 , attributeId ) ;
250
- }
313
+ this . sendCBMsg ( 11 , messageBody ) ;
314
+ } ;
251
315
252
316
blenoBindings . removeAllServices = function RemoveAllGATTServices ( ) {
317
+ this . _attributes = [ ] ;
253
318
this . sendCBMsg ( 12 , null ) ;
254
- }
319
+ } ;
255
320
256
321
blenoBindings . setServices = function SetGATTServices ( services ) {
257
322
this . sendCBMsg ( 12 , null ) ;
0 commit comments