@@ -116,31 +116,24 @@ class AdvertisingFlags(AdvertisingDataField):
116
116
def __init__ (self , advertisement , advertising_data_type ):
117
117
self ._advertisement = advertisement
118
118
self ._adt = advertising_data_type
119
- self .flags = None
119
+ self .flags = 0
120
120
if self ._adt in self ._advertisement .data_dict :
121
121
self .flags = self ._advertisement .data_dict [self ._adt ][0 ]
122
- elif self ._advertisement .mutable :
123
- self .flags = 0b110 # Default to General discovery and LE Only
124
- else :
125
- self .flags = 0
126
122
127
123
def __len__ (self ):
128
124
return 1
129
125
130
126
def __bytes__ (self ):
131
- encoded = bytearray (1 )
132
- encoded [0 ] = self .flags
133
- return encoded
127
+ return bytes ([self .flags ])
134
128
135
129
def __str__ (self ):
136
- parts = ["<AdvertisingFlags" ]
130
+ parts = []
137
131
for attr in dir (self .__class__ ):
138
132
attribute_instance = getattr (self .__class__ , attr )
139
133
if issubclass (attribute_instance .__class__ , AdvertisingFlag ):
140
134
if getattr (self , attr ):
141
135
parts .append (attr )
142
- parts .append (">" )
143
- return " " .join (parts )
136
+ return "<AdvertisingFlags {} >" .format (" " .join (parts ))
144
137
145
138
class String (AdvertisingDataField ):
146
139
"""UTF-8 encoded string in an Advertisement.
@@ -172,7 +165,7 @@ def __set__(self, obj, value):
172
165
obj .data_dict [self ._adt ] = struct .pack (self ._format , value )
173
166
174
167
175
- class LazyField (AdvertisingDataField ):
168
+ class LazyObjectField (AdvertisingDataField ):
176
169
"""Non-data descriptor useful for lazily binding a complex object to an advertisement object."""
177
170
def __init__ (self , cls , attribute_name , * , advertising_data_type , ** kwargs ):
178
171
self ._cls = cls
@@ -184,18 +177,24 @@ def __get__(self, obj, cls):
184
177
# Return None if our object is immutable and the data is not present.
185
178
if not obj .mutable and self ._adt not in obj .data_dict :
186
179
return None
187
- bound_class = self ._cls (obj , advertising_data_type = self ._adt , ** self ._kwargs )
188
- setattr (obj , self ._attribute_name , bound_class )
189
- obj .data_dict [self ._adt ] = bound_class
190
- return bound_class
180
+ # Instantiate the object.
181
+ bound_obj = self ._cls (obj , advertising_data_type = self ._adt , ** self ._kwargs )
182
+ setattr (obj , self ._attribute_name , bound_obj )
183
+ obj .data_dict [self ._adt ] = bound_obj
184
+ return bound_obj
185
+
186
+ @property
187
+ def advertising_data_type (self ):
188
+ """Return the data type value used to indicate this field."""
189
+ return self ._adt
191
190
192
191
# TODO: Add __set_name__ support to CircuitPython so that we automatically tell the descriptor
193
192
# instance the attribute name it has and the class it is on.
194
193
195
194
class Advertisement :
196
195
"""Core Advertisement type"""
197
196
prefix = b"\x00 " # This is an empty prefix and will match everything.
198
- flags = LazyField (AdvertisingFlags , "flags" , advertising_data_type = 0x01 )
197
+ flags = LazyObjectField (AdvertisingFlags , "flags" , advertising_data_type = 0x01 )
199
198
short_name = String (advertising_data_type = 0x08 )
200
199
"""Short local device name (shortened to fit)."""
201
200
complete_name = String (advertising_data_type = 0x09 )
@@ -263,15 +262,19 @@ def __bytes__(self):
263
262
return encode_data (self .data_dict )
264
263
265
264
def __str__ (self ):
266
- parts = ["<" + self . __class__ . __name__ ]
265
+ parts = []
267
266
for attr in dir (self .__class__ ):
268
267
attribute_instance = getattr (self .__class__ , attr )
269
268
if issubclass (attribute_instance .__class__ , AdvertisingDataField ):
269
+ if (issubclass (attribute_instance .__class__ , LazyObjectField ) and
270
+ not attribute_instance .advertising_data_type in self .data_dict ):
271
+ # Skip uninstantiated lazy objects; if we get
272
+ # their value, they will be be instantiated.
273
+ continue
270
274
value = getattr (self , attr )
271
275
if value is not None :
272
- parts .append (attr + "=" + str (value ))
273
- parts .append (">" )
274
- return " " .join (parts )
276
+ parts .append ("{}={}" .format (attr , str (value )))
277
+ return "<{} {} >" .format (self .__class__ .__name__ , " " .join (parts ))
275
278
276
279
def __len__ (self ):
277
280
return compute_length (self .data_dict )
0 commit comments