1# -*- coding: utf-8 -*-
2# Copyright 2019 Oticon A/S
3# SPDX-License-Identifier: Apache-2.0
4
5from enum import IntEnum;
6from .utils import *;
7
8class ADType(IntEnum):
9    FLAGS                   =   1 # «Flags» Bluetooth Core Specification : Vol. 3, Part C, section 8.1.3 (v2.1 + EDR, 3.0 + HS and 4.0) Vol. 3, Part C, sections 11.1.3 and 18.1 (v4.0) Core Specification Supplement, Part A, section 1.3
10    ILIST_UUIDS_16          =   2 # «Incomplete List of 16 - bit Service Class UUIDs» Bluetooth Core Specification : Vol. 3, Part C, section 8.1.1 (v2.1 + EDR, 3.0 + HS and 4.0) Vol. 3, Part C, sections 11.1.1 and 18.2 (v4.0) Core Specification Supplement, Part A, section 1.1
11    CLIST_UUIDS_16          =   3 # «Complete List of 16 - bit Service Class UUIDs» Bluetooth Core Specification : Vol. 3, Part C, section 8.1.1 (v2.1 + EDR, 3.0 + HS and 4.0) Vol. 3, Part C, sections 11.1.1 and 18.2 (v4.0) Core Specification Supplement, Part A, section 1.1
12    ILIST_UUIDS_32          =   4 # «Incomplete List of 32 - bit Service Class UUIDs» Bluetooth Core Specification : Vol. 3, Part C, section 8.1.1 (v2.1 + EDR, 3.0 + HS and 4.0) Vol. 3, Part C, section 18.2 (v4.0) Core Specification Supplement, Part A, section 1.1
13    CLIST_UUIDS_32          =   5 # «Complete List of 32 - bit Service Class UUIDs» Bluetooth Core Specification : Vol. 3, Part C, section 8.1.1 (v2.1 + EDR, 3.0 + HS and 4.0) Vol. 3, Part C, section 18.2 (v4.0) Core Specification Supplement, Part A, section 1.1
14    ILIST_UUIDS_128         =   6 # «Incomplete List of 128 - bit Service Class UUIDs» Bluetooth Core Specification : Vol. 3, Part C, section 8.1.1 (v2.1 + EDR, 3.0 + HS and 4.0) Vol. 3, Part C, sections 11.1.1 and 18.2 (v4.0) Core Specification Supplement, Part A, section 1.1
15    CLIST_UUIDS_128         =   7 # «Complete List of 128 - bit Service Class UUIDs» Bluetooth Core Specification : Vol. 3, Part C, section 8.1.1 (v2.1 + EDR, 3.0 + HS and 4.0) Vol. 3, Part C, sections 11.1.1 and 18.2 (v4.0) Core Specification Supplement, Part A, section 1.1
16    SHORTENED_LOCAL_NAME    =   8 # «Shortened Local Name» Bluetooth Core Specification : Vol. 3, Part C, section 8.1.2 (v2.1 + EDR, 3.0 + HS and 4.0) Vol. 3, Part C, sections 11.1.2 and 18.4 (v4.0) Core Specification Supplement, Part A, section 1.2
17    COMPLETE_LOCAL_NAME     =   9 # «Complete Local Name» Bluetooth Core Specification : Vol. 3, Part C, section 8.1.2 (v2.1 + EDR, 3.0 + HS and 4.0) Vol. 3, Part C, sections 11.1.2 and 18.4 (v4.0) Core Specification Supplement, Part A, section 1.2
18    TX_POWER_LEVEL          =  10 # «Tx Power Level» Bluetooth Core Specification : Vol. 3, Part C, section 8.1.5 (v2.1 + EDR, 3.0 + HS and 4.0) Vol. 3, Part C, sections 11.1.5 and 18.3 (v4.0) Core Specification Supplement, Part A, section 1.5
19    DEVICE_CLASS            =  13 # «Class of Device» Bluetooth Core Specification : Vol. 3, Part C, section 8.1.6 (v2.1 + EDR, 3.0 + HS and 4.0) Vol. 3, Part C, sections 11.1.5 and 18.5 (v4.0) Core Specification Supplement, Part A, section 1.6
20    PAIR_HASH_C             =  14 # «Simple Pairing Hash C» Bluetooth Core Specification : Vol. 3, Part C, section 8.1.6 (v2.1 + EDR, 3.0 + HS and 4.0) Vol. 3, Part C, sections 11.1.5 and 18.5 (v4.0) ​
21    PAIR_RANDOM_R           =  15 # «Simple Pairing Randomizer R» Bluetooth Core Specification : Vol. 3, Part C, section 8.1.6 (v2.1 + EDR, 3.0 + HS and 4.0) Vol. 3, Part C, sections 11.1.5 and 18.5 (v4.0)
22    SEC_MANAGER_TK          =  16 # «Security Manager TK Value» Bluetooth Core Specification : Vol. 3, Part C, sections 11.1.7 and 18.6 (v4.0) Core Specification Supplement, Part A, section 1.8
23    SEC_MANAGER_OBF         =  17 # «Security Manager Out of Band Flags» Bluetooth Core Specification : Vol. 3, Part C, sections 11.1.6 and 18.7 (v4.0) Core Specification Supplement, Part A, section 1.7
24    PERIPHERAL_CONNECT_INT       =  18 # «Peripheral Connection Interval Range» Bluetooth Core Specification : Vol. 3, Part C, sections 11.1.8 and 18.8 (v4.0) Core Specification Supplement, Part A, section 1.9
25    SS_UUIDS_16             =  20 # «List of 16 - bit Service Solicitation UUIDs» Bluetooth Core Specification : Vol. 3, Part C, sections 11.1.9 and 18.9 (v4.0) Core Specification Supplement, Part A, section 1.10
26    SS_UUIDS_128            =  21 # «List of 128 - bit Service Solicitation UUIDs» Bluetooth Core Specification : Vol. 3, Part C, sections 11.1.9 and 18.9 (v4.0) Core Specification Supplement, Part A, section 1.10
27    SERVICE_DATA_16         =  22 # «Service Data» Bluetooth Core Specification : Vol. 3, Part C, sections 11.1.10 and 18.10 (v4.0)
28    PUBLIC_ADDRESS          =  23 # «Public Target Address» Bluetooth Core Specification : Core Specification Supplement, Part A, section 1.13
29    RANDOM_ADDRESS          =  24 # «Random Target Address» Bluetooth Core Specification : Core Specification Supplement, Part A, section 1.14
30    APPEARANCE              =  25 # «Appearance» Bluetooth Core Specification : Core Specification Supplement, Part A, section 1.12
31    ADVERTISE_INT           =  26 # ​«Advertising Interval» ​Bluetooth Core Specification : Core Specification Supplement, Part A, section 1.15​​​​
32    DEVICE_ADDRESS          =  27 # «​LE Bluetooth Device Address» ​Core Specification Supplement, Part A, section 1.16
33    DEVICE_ROLE             =  28 # «​LE Role» ​Core Specification Supplement, Part A, section 1.17
34    PAIR_HASH_C256          =  29 # «​Simple Pairing Hash C - 256» ​Core Specification Supplement, Part A, section 1.6
35    PAIR_RANDOM_R256        =  30 # «​Simple Pairing Randomizer R - 256» ​Core Specification Supplement, Part A, section 1.6
36    SS_UUIDS_32             =  31 # ​«List of 32 - bit Service Solicitation UUIDs» ​Core Specification Supplement, Part A, section 1.10
37    SERVICE_DATA_32         =  32 # ​«Service Data - 32 - bit UUID» ​Core Specification Supplement, Part A, section 1.11
38    SERVICE_DATA_128        =  33 # ​«Service Data - 128 - bit UUID» ​Core Specification Supplement, Part A, section 1.11
39    SEC_CONNECT_CONFIRM     =  34 # ​«​LE Secure Connections Confirmation Value» ​Core Specification Supplement Part A, Section 1.6
40    SEC_CONNECT_RANDOM      =  35 # ​​«​LE Secure Connections Random Value» ​Core Specification Supplement Part A, Section 1.6​
41    URI                     =  36 # ​​​«​URI» ​Bluetooth Core Specification : Core Specification Supplement, Part A, section 1.18
42    INDOOR_POSITION         =  37 # ​«Indoor Positioning» ​Indoor Posiioning Service v1.0 or later
43    DISCOVERY_DATA          =  38 # ​«Transport Discovery Data» ​Transport Discovery Service v1.0 or later​
44    LE_SUPPORTED_FEATURES   =  39 # «LE Supported Features» Core Specification Supplement, Part A, Section 1.19
45    CHANNEL_MAP_UPDATE      =  40 # «Channel Map Update Indication» Core Specification Supplement, Part A, Section 1.20
46    INFO_DATA_3D            =  61 # ​​«3D Information Data» ​3D Synchronization Profile, v1.0 or later
47    MANUFACTURER_DATA       = 255 # «Manufacturer Specific Data» Bluetooth Core Specification : Vol. 3, Part C, section 8.1.4 (v2.1 + EDR, 3.0 + HS and 4.0) Vol. 3, Part C, sections 11.1.4 and 18.11 (v4.0) Core Specification Supplement, Part A, section 1.4​
48
49class ADRole(IntEnum):
50    ONLY_PERIPHERAL         =   0 # Only Peripheral Role supported
51    ONLY_CENTRAL            =   1 # Only Central Role supported
52    PERIPHERAL_PREFERRED    =   2 # Peripheral and Central Role supported, Peripheral Role preferred for connection establishment
53    CENTRAL_PREFERRED       =   3 # Peripheral and Central Role supported, Central Role preferred for connection establishment
54
55class ADFlag(IntEnum):
56    LE_LIMITED_DISCOVERABLE =   1 # LE Limited Discoverable Mode
57    LE_GENERAL_DISCOVERABLE =   2 # LE General Discoverable Mode
58    BR_EDR_NOT_SUPPORTED    =   4 # BR/EDR Not Supported. Bit 37 of LMP Feature Mask Definitions.
59    LE_BR_EDR_CAPABLE_CTRL  =   8 # Simultaneous LE and BR/EDR to Same Device Capable (Controller). Bit 49 of LMP Feature Mask Definitions.
60    LE_BR_EDR_CAPABLE_HOST  =  16 # Simultaneous LE and BR/EDR to Same Device Capable (Host).       Bit 66 of LMP Feature Mask Definitions.
61    LE_FLAGS_ALL            =  31 # All flags set
62
63"""
64    Appearance is a 16 bit number divided into a Category (most significant 10 bits) and a Sub-category (least significant 6 bits)
65
66    Category Category Name      Sub-category Sub-category Name                Appearance Value
67           0 Unknown                       0 Unknown                                         0
68           1 Phone                         0 Generic Phone                                  64
69           2 Computer                      0 Generic Computer                              128
70           3 Watch                         0 Generic Watch                                 192
71                                           1 Sports Watch                                  193
72           4 Clock                         0 Generic Clock                                 256
73           5 Display                       0 Generic Display                               320
74           6 Remote Control                0 Generic Remote Control                        384
75           7 Eye-glasses                   0 Generic Eye-glasses                           448
76           8 Tag                           0 Generic Tag                                   512
77           9 Keyring                       0 Generic Keyring                               576
78          10 Media Player                  0 Generic Media Player                          640
79          11 Barcode Scanner               0 Generic Barcode Scanner                       704
80          12 Thermometer                   0 Generic Thermometer                           768
81                                           1 Ear Thermometer                               769
82          13 Heart rate Sensor             0 Generic Heart rate Sensor                     832
83                                           1 Heart rate Belt                               833
84          14 Blood Pressure                0 Generic Blood Pressure                        896
85                                           1 Blood Pressure Arm                            897
86                                           2 Blood Pressure Wrist                          898
87          15 Human Interface Device (HID)  0 Generic Human Interface Device                960
88                                           1 Keyboard                                      961
89                                           2 Mouse                                         962
90                                           3 Joystick                                      963
91                                           4 Gamepad                                       964
92                                           5 Digitizer Tablet                              965
93                                           6 Card Reader                                   966
94                                           7 Digital Pen                                   967
95                                           8 Barcode Scanner                               968
96          16 Glucoose Meter                0 Generic Glucoose Meter                       1024
97          17 Running Walking Sensor        0 Generic Running Walking Sensor               1088
98                                           1 In-Shoe Running Walking Sensor               1089
99                                           2 On-Shoe Running Walking Sensor               1090
100                                           3 On-Hip  Running Walking Sensor               1091
101          18 Cycling                       0 Generic Cycling                              1152
102                                           1 Cycling Computer                             1153
103                                           2 Speed Sensor                                 1154
104                                           3 Cadence Sensor                               1155
105                                           4 Power Sensor                                 1156
106                                           5 Speed and Cadence Sensor                     1157
107          49 Pulse Oximeter                0 Generic Pulse Oximeter                       3136
108                                           1 Fingertip                                    3137
109                                           2 Wrist Worn                                   3138
110          50 Weight Scale                  0 Generic Weight Scale                         3200
111          51 Personal Mobility Device      0 Generic Personal Mobility Device             3264
112                                           1 Powered Weelchair                            3265
113                                           2 Mobility Scooter                             3266
114          52 Continuous Glucoose Monitor   0 Generic Continuous Glucoose Monitor          3328
115          53 Insulin Pump                  0 Generic Insulin Pump                         3392
116                                           1 Durable Insulin Pump                         3393
117                                           4 Patch   Insulin Pump                         3396
118                                           8 Insulin Pen                                  3400
119          54 Medication Delivery           0 Generic Medication Delivery                  3456
120          81 Outdoor Sports Activity       0 Generic Outdoor Sports Activity              5184
121                                           1 Location Display Device                      5185
122                                           2 Location and Navigation Display Device       5186
123                                           3 Location Pod                                 5187
124                                           4 Location and Navigation Pod                  5188
125"""
126
127__schemeNames__ = {
128    'aaa':                      [ 0X02 ],
129    'aaas':                     [ 0X03 ],
130    'about':                    [ 0X04 ],
131    'acap':                     [ 0X05 ],
132    'acct':                     [ 0X06 ],
133    'cap':                      [ 0X07 ],
134    'cid':                      [ 0X08 ],
135    'coap':                     [ 0X09 ],
136    'coaps':                    [ 0X0A ],
137    'crid':                     [ 0X0B ],
138    'data':                     [ 0X0C ],
139    'dav':                      [ 0X0D ],
140    'dict':                     [ 0X0E ],
141    'dns':                      [ 0X0F ],
142    'file':                     [ 0X10 ],
143    'ftp':                      [ 0X11 ],
144    'geo':                      [ 0X12 ],
145    'go':                       [ 0X13 ],
146    'gopher':                   [ 0X14 ],
147    'h323':                     [ 0X15 ],
148    'http':                     [ 0X16 ],
149    'https':                    [ 0X17 ],
150    'iax':                      [ 0X18 ],
151    'icap':                     [ 0X19 ],
152    'im':                       [ 0X1A ],
153    'imap':                     [ 0X1B ],
154    'info':                     [ 0X1C ],
155    'ipp':                      [ 0X1D ],
156    'ipps':                     [ 0X1E ],
157    'iris':                     [ 0X1F ],
158    'iris.beep':                [ 0X20 ],
159    'iris.xpc':                 [ 0X21 ],
160    'iris.xpcs':                [ 0X22 ],
161    'iris.lwz':                 [ 0X23 ],
162    'jabber':                   [ 0X24 ],
163    'ldap':                     [ 0X25 ],
164    'mailto':                   [ 0X26 ],
165    'mid':                      [ 0X27 ],
166    'msrp':                     [ 0X28 ],
167    'msrps':                    [ 0X29 ],
168    'mtqp':                     [ 0X2A ],
169    'mupdate':                  [ 0X2B ],
170    'news':                     [ 0X2C ],
171    'nfs':                      [ 0X2D ],
172    'ni':                       [ 0X2E ],
173    'nih':                      [ 0X2F ],
174    'nntp':                     [ 0X30 ],
175    'opaquelocktoken':          [ 0X31 ],
176    'pop':                      [ 0X32 ],
177    'pres':                     [ 0X33 ],
178    'reload':                   [ 0X34 ],
179    'rtsp':                     [ 0X35 ],
180    'rtsps':                    [ 0X36 ],
181    'rtspu':                    [ 0X37 ],
182    'service':                  [ 0X38 ],
183    'session':                  [ 0X39 ],
184    'shttp':                    [ 0X3A ],
185    'sieve':                    [ 0X3B ],
186    'sip':                      [ 0X3C ],
187    'sips':                     [ 0X3D ],
188    'sms':                      [ 0X3E ],
189    'snmp':                     [ 0X3F ],
190    'soap.beep':                [ 0X40 ],
191    'soap.beeps':               [ 0X41 ],
192    'stun':                     [ 0X42 ],
193    'stuns':                    [ 0X43 ],
194    'tag':                      [ 0X44 ],
195    'tel':                      [ 0X45 ],
196    'telnet':                   [ 0X46 ],
197    'tftp':                     [ 0X47 ],
198    'thismessage':              [ 0X48 ],
199    'tn3270':                   [ 0X49 ],
200    'tip':                      [ 0X4A ],
201    'turn':                     [ 0X4B ],
202    'turns':                    [ 0X4C ],
203    'tv':                       [ 0X4D ],
204    'urn':                      [ 0X4E ],
205    'vemmi':                    [ 0X4F ],
206    'ws':                       [ 0X50 ],
207    'wss':                      [ 0X51 ],
208    'xcon':                     [ 0X52 ],
209    'xcon-userid':              [ 0X53 ],
210    'xmlrpc.beep':              [ 0X54 ],
211    'xmlrpc.beeps':             [ 0X55 ],
212    'xmpp':                     [ 0X56 ],
213    'z39.50r':                  [ 0X57 ],
214    'z39.50s':                  [ 0X58 ],
215    'acr':                      [ 0X59 ],
216    'adiumxtra':                [ 0X5A ],
217    'afp':                      [ 0X5B ],
218    'afs':                      [ 0X5C ],
219    'aim':                      [ 0X5D ],
220    'apt':                      [ 0X5E ],
221    'attachment':               [ 0X5F ],
222    'aw':                       [ 0X60 ],
223    'barion':                   [ 0X61 ],
224    'beshare':                  [ 0X62 ],
225    'bitcoin':                  [ 0X63 ],
226    'bolo':                     [ 0X64 ],
227    'callto':                   [ 0X65 ],
228    'chrome':                   [ 0X66 ],
229    'chrome-extension':         [ 0X67 ],
230    'com-eventbrite-attendee':  [ 0X68 ],
231    'content':                  [ 0X69 ],
232    'cvs':                      [ 0X6A ],
233    'dlna-playsingle':          [ 0X6B ],
234    'dlna-playcontainer':       [ 0X6C ],
235    'dtn':                      [ 0X6D ],
236    'dvb':                      [ 0X6E ],
237    'ed2k':                     [ 0X6F ],
238    'facetime':                 [ 0X70 ],
239    'feed':                     [ 0X71 ],
240    'feedready':                [ 0X72 ],
241    'finger':                   [ 0X73 ],
242    'fish':                     [ 0X74 ],
243    'gg':                       [ 0X75 ],
244    'git':                      [ 0X76 ],
245    'gizmoproject':             [ 0X77 ],
246    'gtalk':                    [ 0X78 ],
247    'ham':                      [ 0X79 ],
248    'hcp':                      [ 0X7A ],
249    'icon':                     [ 0X7B ],
250    'ipn':                      [ 0X7C ],
251    'irc':                      [ 0X7D ],
252    'irc6':                     [ 0X7E ],
253    'ircs':                     [ 0X7F ],
254    'itms':                     [ 0XC2, 0X80 ],
255    'jar':                      [ 0XC2, 0X81 ],
256    'jms':                      [ 0XC2, 0X82 ],
257    'keyparc':                  [ 0XC2, 0X83 ],
258    'lastfm':                   [ 0XC2, 0X84 ],
259    'ldaps':                    [ 0XC2, 0X85 ],
260    'magnet':                   [ 0XC2, 0X86 ],
261    'maps':                     [ 0XC2, 0X87 ],
262    'market':                   [ 0XC2, 0X88 ],
263    'message':                  [ 0XC2, 0X89 ],
264    'mms':                      [ 0XC2, 0X8A ],
265    'ms-help':                  [ 0XC2, 0X8B ],
266    'ms-settings-power':        [ 0XC2, 0X8C ],
267    'msnim':                    [ 0XC2, 0X8D ],
268    'mumble':                   [ 0XC2, 0X8E ],
269    'mvn':                      [ 0XC2, 0X8F ],
270    'notes':                    [ 0XC2, 0X90 ],
271    'oid':                      [ 0XC2, 0X91 ],
272    'palm':                     [ 0XC2, 0X92 ],
273    'paparazzi':                [ 0XC2, 0X93 ],
274    'pkcs11':                   [ 0XC2, 0X94 ],
275    'platform':                 [ 0XC2, 0X95 ],
276    'proxy':                    [ 0XC2, 0X96 ],
277    'psyc':                     [ 0XC2, 0X97 ],
278    'query':                    [ 0XC2, 0X98 ],
279    'res':                      [ 0XC2, 0X99 ],
280    'resource':                 [ 0XC2, 0X9A ],
281    'rmi':                      [ 0XC2, 0X9B ],
282    'rsync':                    [ 0XC2, 0X9C ],
283    'rtmfp':                    [ 0XC2, 0X9D ],
284    'rtmp':                     [ 0XC2, 0X9E ],
285    'secondlife':               [ 0XC2, 0X9F ],
286    'sftp':                     [ 0XC2, 0XA0 ],
287    'sgn':                      [ 0XC2, 0XA1 ],
288    'skype':                    [ 0XC2, 0XA2 ],
289    'smb':                      [ 0XC2, 0XA3 ],
290    'smtp':                     [ 0XC2, 0XA4 ],
291    'soldat':                   [ 0XC2, 0XA5 ],
292    'spotify':                  [ 0XC2, 0XA6 ],
293    'ssh':                      [ 0XC2, 0XA7 ],
294    'steam':                    [ 0XC2, 0XA8 ],
295    'submit':                   [ 0XC2, 0XA9 ],
296    'svn':                      [ 0XC2, 0XAA ],
297    'teamspeak':                [ 0XC2, 0XAB ],
298    'teliaeid':                 [ 0XC2, 0XAC ],
299    'things':                   [ 0XC2, 0XAD ],
300    'udp':                      [ 0XC2, 0XAE ],
301    'unreal':                   [ 0XC2, 0XAF ],
302    'ut2004':                   [ 0XC2, 0XB0 ],
303    'ventrilo':                 [ 0XC2, 0XB1 ],
304    'view-source':              [ 0XC2, 0XB2 ],
305    'webcal':                   [ 0XC2, 0XB3 ],
306    'wtai':                     [ 0XC2, 0XB4 ],
307    'wyciwyg':                  [ 0XC2, 0XB5 ],
308    'xfire':                    [ 0XC2, 0XB6 ],
309    'xri':                      [ 0XC2, 0XB7 ],
310    'ymsgr':                    [ 0XC2, 0XB8 ],
311    'example':                  [ 0XC2, 0XB9 ],
312    'ms-settings-cloudstorage': [ 0XC2, 0XBA ]
313};
314
315class ADData:
316
317    def __init__(self):
318        self.data = [];
319
320    def encode(self, adType, *args):
321      #
322      # ADType.TX_POWER_LEVEL, <power_level>; where <power_level> [ -127, +127 ] dBm.
323      #
324        if ( adType == ADType.TX_POWER_LEVEL ):
325            self.data = [ 2, adType, args[0] if args[0] >= 0 else 256+args[0] ];
326      #
327      # ADType.FLAGS, <flags>           where <flags> [ 0, 31 ]
328      # ADType.SEC_MANAGER_OBF, <flags> where <flags> [ 0, 15 ]
329      # ADType.DEVICE_ROLE, <role>      where <role>  [ 0, 3 ]
330      #
331        elif ( adType == ADType.FLAGS or adType == ADType.SEC_MANAGER_OBF or adType == ADType.DEVICE_ROLE ):
332            self.data = [ 2, adType, args[0] ];
333      #
334      # ADType.ILIST_UUIDS_16, <uuid_A>, <uuid_B>, ...
335      # ADTYpe,CLIST_UUIDS_16, <uuid_A>, <uuid_B>, ...
336      # ADType.SS_UUIDS_16,    <uuid_A>, <uuid_B>, ...
337      #
338        elif ( adType == ADType.ILIST_UUIDS_16 or adType == ADType.CLIST_UUIDS_16 or adType == ADType.SS_UUIDS_16 ):
339            self.data = [ 1+2*len(args), adType ];
340            for arg in args:
341                self.data += toArray(arg, 2);
342      #
343      # ADType.ILIST_UUIDS_32, <uuid_A>, <uuid_B>, ...
344      # ADTYpe,CLIST_UUIDS_32, <uuid_A>, <uuid_B>, ...
345      # ADType.SS_UUIDS_32,    <uuid_A>, <uuid_B>, ...
346      #
347        elif ( adType == ADType.ILIST_UUIDS_32 or adType == ADType.CLIST_UUIDS_32 or adType == ADType.SS_UUIDS_32 ):
348            self.data = [ 1+4*len(args), adType ];
349            for arg in args:
350                self.data += toArray(arg, 4);
351      #
352      # ADType.ILIST_UUIDS_128, <uuid_A>, <uuid_B>, ...
353      # ADTYpe,CLIST_UUIDS_128, <uuid_A>, <uuid_B>, ...
354      # ADType.SS_UUIDS_128,    <uuid_A>, <uuid_B>, ...
355      #
356        elif ( adType == ADType.ILIST_UUIDS_128 or adType == ADType.CLIST_UUIDS_128 or adType == ADType.SS_UUIDS_128 ):
357            self.data = [ 1+16*len(args), adType ];
358            for arg in args:
359                self.data += toArray(arg, 16);
360      #
361      # ADType.SHORTENED_LOCAL_NAME, <unicode_name>
362      # ADType.COMPLETE_LOCAL_NAME,  <unicode_name>
363      #
364        elif ( adType == ADType.SHORTENED_LOCAL_NAME or adType == ADType.COMPLETE_LOCAL_NAME ):
365            name = args[0].encode('UTF-8');
366            if len(name) > 29:
367                name = name[:29];
368            self.data = [ 1+len(name), adType ] + [ _ for _ in name ];
369      #
370      # ADType.DEVICE_CLASS, <device_class>
371      #
372        elif ( adType == ADType.DEVICE_CLASS ):
373            self.data = [ 4, adType ] + toArray(args[0], 3);
374      #
375      # ADType.PAIR_HASH_C,    <hash_value>
376      # ADType.PAIR_RANDOM_R,  <random_value>
377      # ADType.SEC_MANAGER_TK, <tk_value>
378      #
379        elif ( adType == ADType.PAIR_HASH_C or adType == ADType.PAIR_RANDOM_R or adType == ADType.SEC_MANAGER_TK ):
380            self.data = [ 17, adType ] + toArray(args[0], 16);
381      #
382      # ADType.PERIPHERAL_CONNECT_INT, <min_interval>, <max_interval>
383      #
384        elif ( adType == ADType.PERIPHERAL_CONNECT_INT ):
385            self.data = [ 5, adType ] + toArray(args[0], 2) + toArray(args[1], 2);
386      #
387      # ADType.SERVICE_DATA_16, <service_uuid>, [<service_data>...]
388      #
389        elif ( adType == ADType.SERVICE_DATA_16 ):
390            self.data = [ 2+len(args), adType ] + toArray(args[0],2);
391            if len(args) > 1:
392                for arg in args[1:]:
393                    self.data += [ arg ];
394      #
395      # ADType.SERVICE_DATA_32, <service_uuid>, [<service_data>...]
396      #
397        elif ( adType == ADType.SERVICE_DATA_32 ):
398            self.data = [ 4+len(args), adType ] + toArray(args[0], 4);
399            if len(args) > 1:
400                for arg in args[1:]:
401                    self.data += [ arg ];
402      #
403      # ADType.SERVICE_DATA_128, <service_uuid>, [<service_data>...]
404      #
405        elif ( adType == ADType.SERVICE_DATA_128 ):
406            self.data = [ 16+len(args), adType ] + toArray(args[0], 16);
407            if len(args) > 1:
408                for arg in args[1:]:
409                    self.data += [ arg ];
410      #
411      # ADType.PUBLIC_ADDRESS, <address_A>, <address_B>, ...
412      # ADType.RANDOM_ADDRESS, <address_A>, <address_B>, ...
413      #
414        elif ( adType == ADType.PUBLIC_ADDRESS or adType == ADType.RANDOM_ADDRESS ):
415            self.data = [ 1+6*len(args), adType ];
416            for arg in args:
417                self.data += toArray(arg, 6);
418      #
419      # ADType.APPEARANCE,    <apperance>
420      # ADType.ADVERTISE_INT, <interval>
421      #
422        elif ( adType == ADType.APPEARANCE or adType == ADType.ADVERTISE_INT ):
423            self.data = [ 3, adType ] + toArray(args[0], 2);
424      #
425      # ADType.DEVICE_ADDRESS, <address>, <public_or_random>
426      #
427        elif ( adType == ADType.DEVICE_ADDRESS ):
428            self.data = [ 8, adType ] + toArray(args[0], 6) + [ args[1] and 1 ];
429      #
430      # ADType.LE_SUPPORTED_FEATURES, <features>
431      #
432        elif ( adType == ADType.LE_SUPPORTED_FEATURES ):
433            self.data = [ 4, adType ] + toArray(args[0], 3);
434      #
435      # ADType.CHANNEL_MAP_UPDATE, <channel_map>, <instant>
436      #
437        elif ( adType == ADType.CHANNEL_MAP_UPDATE ):
438            self.data = [ 8, adType ] + toArray(args[0], 5) + toArray(args[1], 2);
439      #
440      # ADType.MANUFACTURER_DATA, <manufacturer>, <data>...
441      #
442        elif ( adType == ADType.MANUFACTURER_DATA ):
443            self.data = [ 2+len(args), adType ] + toArray(args[0], 2);
444            if len(args) > 1:
445                for arg in args[1:]:
446                    self.data += [ arg ];
447      #
448      # ADType.URI, <unicode_uri>
449      #
450        elif ( adType == ADType.URI ):
451            nPos = args[0].find(':');
452            if nPos > -1 and args[0][:nPos] in __schemeNames__:
453                rest = args[0][(nPos+1):].encode('UTF-8');
454                self.data = [ 1+len(__schemeNames__[args[0][:nPos]])+len(rest),
455                        adType ] + __schemeNames__[args[0][:nPos]] + [ _ for _ in rest ];
456            else:
457                rest = args[0].encode('UTF-8');
458                self.data = [ 2+len(rest), adType ] + [ 1 ] + [ _ for _ in rest ];
459
460        return self.data;
461
462    def decode(self, data):
463        result = { };
464        size = len(data);
465
466        n = 0;
467        while n < size:
468            length = data[n];
469            length -= 1; n += 1
470            if length > 0:
471                if data[n] in ADType._value2member_map_:
472                    adType = ADType(data[n]);
473                    n += 1;
474                  #
475                  # ADType.TX_POWER_LEVEL, <power_level>; where <power_level> [ -127, +127 ] dBm.
476                  #
477                    if ( adType == ADType.TX_POWER_LEVEL ):
478                        result[adType] = data[n] if data[n] < 128 else data[n]-256;
479                  #
480                  # ADType.FLAGS, <flags>           where <flags> [ 0, 31 ]
481                  # ADType.SEC_MANAGER_OBF, <flags> where <flags> [ 0, 15 ]
482                  # ADType.DEVICE_ROLE, <role>      where <role>  [ 0, 3 ]
483                  #
484                    elif ( adType == ADType.FLAGS or adType == ADType.SEC_MANAGER_OBF or adType == ADType.DEVICE_ROLE ):
485                        result[adType] = data[n];
486                  #
487                  # ADType.ILIST_UUIDS_16, <uuid_A>, <uuid_B>, ...
488                  # ADTYpe,CLIST_UUIDS_16, <uuid_A>, <uuid_B>, ...
489                  # ADType.SS_UUIDS_16,    <uuid_A>, <uuid_B>, ...
490                  #
491                    elif ( adType == ADType.ILIST_UUIDS_16 or adType == ADType.CLIST_UUIDS_16 or adType == ADType.SS_UUIDS_16 ):
492                        result[adType] = [];
493                        for i in range(n, n+length, 2):
494                            result[adType] += [ toNumber( data[i:i+2] ) ];
495                  #
496                  # ADType.ILIST_UUIDS_32, <uuid_A>, <uuid_B>, ...
497                  # ADTYpe,CLIST_UUIDS_32, <uuid_A>, <uuid_B>, ...
498                  # ADType.SS_UUIDS_32,    <uuid_A>, <uuid_B>, ...
499                  #
500                    elif ( adType == ADType.ILIST_UUIDS_32 or adType == ADType.CLIST_UUIDS_32 or adType == ADType.SS_UUIDS_32 ):
501                        result[adType] = [];
502                        for i in range(n, n+length, 4):
503                            result[adType] += [ toNumber( data[i:i+4] ) ];
504                  #
505                  # ADType.ILIST_UUIDS_128, <uuid_A>, <uuid_B>, ...
506                  # ADTYpe,CLIST_UUIDS_128, <uuid_A>, <uuid_B>, ...
507                  # ADType.SS_UUIDS_128,    <uuid_A>, <uuid_B>, ...
508                  #
509                    elif ( adType == ADType.ILIST_UUIDS_128 or adType == ADType.CLIST_UUIDS_128 or adType == ADType.SS_UUIDS_128 ):
510                        result[adType] = [];
511                        for i in range(n, n+length, 16):
512                            result[adType] += [ toNumber( data[i:i+16] ) ];
513                  #
514                  # ADType.SHORTENED_LOCAL_NAME, <unicode_name>
515                  # ADType.COMPLETE_LOCAL_NAME,  <unicode_name>
516                  #
517                    elif ( adType == ADType.SHORTENED_LOCAL_NAME or adType == ADType.COMPLETE_LOCAL_NAME ):
518                        name = bytes(data[n:n+length])
519                        result[adType] = name.decode('utf-8');
520                  #
521                  # ADType.DEVICE_CLASS, <device_class>
522                  #
523                    elif ( adType == ADType.DEVICE_CLASS ):
524                        result[adType] = toNumber( data[n:n+length] );
525                  #
526                  # ADType.PAIR_HASH_C,    <hash_value>
527                  # ADType.PAIR_RANDOM_R,  <random_value>
528                  # ADType.SEC_MANAGER_TK, <tk_value>
529                  #
530                    elif ( adType == ADType.PAIR_HASH_C or adType == ADType.PAIR_RANDOM_R or adType == ADType.SEC_MANAGER_TK ):
531                        result[adType] = toNumber( data[n:n+length] );
532                  #
533                  # ADType.PERIPHERAL_CONNECT_INT, <min_interval>, <max_interval>
534                  #
535                    elif ( adType == ADType.PERIPHERAL_CONNECT_INT ):
536                        result[adType] = [];
537                        for i in range(n, n+length, 2):
538                            result[adType] += [ toNumber( data[i:i+2] ) ];
539                  #
540                  # ADType.SERVICE_DATA_16, <service_uuid>, [<service_data>...]
541                  #
542                    elif ( adType == ADType.SERVICE_DATA_16 ):
543                        result[adType] = { "uuid": toNumber( data[n:n+2] ), "data": data[n+2:n+length] };
544                  #
545                  # ADType.SERVICE_DATA_32, <service_uuid>, [<service_data>...]
546                  #
547                    elif ( adType == ADType.SERVICE_DATA_32 ):
548                        result[adType] = { "uuid": toNumber( data[n:n+4] ), "data": data[n+4:n+length] };
549                  #
550                  # ADType.SERVICE_DATA_128, <service_uuid>, [<service_data>...]
551                  #
552                    elif ( adType == ADType.SERVICE_DATA_128 ):
553                        result[adType] = { "uuid": toNumber( data[n:n+16] ), "data": data[n+16:n+length] };
554                  #
555                  # ADType.PUBLIC_ADDRESS, <address_A>, <address_B>, ...
556                  # ADType.RANDOM_ADDRESS, <address_A>, <address_B>, ...
557                  #
558                    elif ( adType == ADType.PUBLIC_ADDRESS or adType == ADType.RANDOM_ADDRESS ):
559                        result[adType] = [];
560                        for i in range(n, n+length, 6):
561                            result[adType] += [ toNumber( data[i:i+6] ) ];
562                  #
563                  # ADType.APPEARANCE,    <apperance>
564                  # ADType.ADVERTISE_INT, <interval>
565                  #
566                    elif ( adType == ADType.APPEARANCE or adType == ADType.ADVERTISE_INT ):
567                        result[adType] = toNumber( data[n:n+2] );
568                  #
569                  # ADType.DEVICE_ADDRESS, <address>, <public_or_random>
570                  #
571                    elif ( adType == ADType.DEVICE_ADDRESS ):
572                        result[adType] = { "address": toNumber( data[n:n+6] ), "type": data[n+6] };
573                  #
574                  # ADType.LE_SUPPORTED_FEATURES, <features>
575                  #
576                    elif ( adType == ADType.LE_SUPPORTED_FEATURES ):
577                        result[adType] = data[n:n+length];
578                  #
579                  # ADType.CHANNEL_MAP_UPDATE, <channel_map>, <instant>
580                  #
581                    elif ( adType == ADType.CHANNEL_MAP_UPDATE ):
582                        result[adType] = { "map": toNumber( data[n:n+5] ), "instant": toNumber( data[n+5:n+7] ) };
583                  #
584                  # ADType.MANUFACTURER_DATA, <manufacturer>, <data>...
585                  #
586                    elif ( adType == ADType.MANUFACTURER_DATA ):
587                        result[adType] = { "manufacturer": toNumber( data[n:n+2] ), "data": data[n+2:n+length] };
588                  #
589                  # ADType.URI, <unicode_uri>
590                  #
591                    elif ( adType == ADType.URI ):
592                        name = [ chr(_) for _ in data[n:n+length] ];
593                        name = ''.join(name).decode('utf-8');
594                        codePoint = ord(name[0]);
595                        name = name[1:];
596                        if codePoint > 1:
597                            for scheme, code in __schemeNames__.items():
598                                if codePoint == code[-1]:
599                                    name = scheme + ':' + name;
600                                    break;
601                        result[adType] = name;
602                    else:
603                        result[adType] = data[n:n+length];
604                    n += length;
605                else:
606                    adType = data[n];
607                    n += 1;
608                    result[adType] = data[n:n+length];
609                    n += length;
610
611        return result;
612
613    def asBytes(self):
614        return [int(_) for _ in self.data];
615