bumble 0.0.194__py3-none-any.whl → 0.0.198__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bumble/_version.py +2 -2
- bumble/apps/auracast.py +692 -0
- bumble/apps/bench.py +77 -23
- bumble/apps/console.py +5 -20
- bumble/apps/controller_info.py +3 -3
- bumble/apps/device_info.py +230 -0
- bumble/apps/gatt_dump.py +4 -0
- bumble/apps/lea_unicast/app.py +16 -17
- bumble/at.py +12 -6
- bumble/avc.py +8 -5
- bumble/avctp.py +3 -2
- bumble/avdtp.py +5 -1
- bumble/avrcp.py +2 -1
- bumble/codecs.py +17 -13
- bumble/colors.py +6 -2
- bumble/core.py +726 -122
- bumble/device.py +817 -117
- bumble/drivers/rtk.py +13 -8
- bumble/gatt.py +6 -1
- bumble/gatt_client.py +10 -4
- bumble/hci.py +283 -20
- bumble/hid.py +24 -28
- bumble/host.py +29 -0
- bumble/l2cap.py +24 -17
- bumble/link.py +8 -3
- bumble/pandora/host.py +3 -2
- bumble/profiles/ascs.py +739 -0
- bumble/profiles/bap.py +85 -862
- bumble/profiles/bass.py +440 -0
- bumble/profiles/csip.py +4 -4
- bumble/profiles/gap.py +110 -0
- bumble/profiles/heart_rate_service.py +4 -3
- bumble/profiles/le_audio.py +83 -0
- bumble/profiles/mcp.py +448 -0
- bumble/profiles/pacs.py +210 -0
- bumble/profiles/pbp.py +46 -0
- bumble/profiles/tmap.py +89 -0
- bumble/rfcomm.py +14 -3
- bumble/sdp.py +13 -11
- bumble/smp.py +20 -8
- bumble/snoop.py +5 -4
- bumble/transport/__init__.py +8 -2
- bumble/transport/android_emulator.py +9 -3
- bumble/transport/android_netsim.py +9 -7
- bumble/transport/common.py +46 -18
- bumble/transport/pyusb.py +2 -2
- bumble/transport/unix.py +56 -0
- bumble/transport/usb.py +57 -46
- {bumble-0.0.194.dist-info → bumble-0.0.198.dist-info}/METADATA +41 -41
- {bumble-0.0.194.dist-info → bumble-0.0.198.dist-info}/RECORD +54 -43
- {bumble-0.0.194.dist-info → bumble-0.0.198.dist-info}/WHEEL +1 -1
- {bumble-0.0.194.dist-info → bumble-0.0.198.dist-info}/LICENSE +0 -0
- {bumble-0.0.194.dist-info → bumble-0.0.198.dist-info}/entry_points.txt +0 -0
- {bumble-0.0.194.dist-info → bumble-0.0.198.dist-info}/top_level.txt +0 -0
bumble/core.py
CHANGED
|
@@ -16,11 +16,14 @@
|
|
|
16
16
|
# Imports
|
|
17
17
|
# -----------------------------------------------------------------------------
|
|
18
18
|
from __future__ import annotations
|
|
19
|
+
import dataclasses
|
|
19
20
|
import enum
|
|
20
21
|
import struct
|
|
21
22
|
from typing import List, Optional, Tuple, Union, cast, Dict
|
|
23
|
+
from typing_extensions import Self
|
|
22
24
|
|
|
23
|
-
from .company_ids import COMPANY_IDENTIFIERS
|
|
25
|
+
from bumble.company_ids import COMPANY_IDENTIFIERS
|
|
26
|
+
from bumble.utils import OpenIntEnum
|
|
24
27
|
|
|
25
28
|
|
|
26
29
|
# -----------------------------------------------------------------------------
|
|
@@ -76,7 +79,13 @@ def get_dict_key_by_value(dictionary, value):
|
|
|
76
79
|
# -----------------------------------------------------------------------------
|
|
77
80
|
# Exceptions
|
|
78
81
|
# -----------------------------------------------------------------------------
|
|
79
|
-
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class BaseBumbleError(Exception):
|
|
85
|
+
"""Base Error raised by Bumble."""
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class BaseError(BaseBumbleError):
|
|
80
89
|
"""Base class for errors with an error code, error name and namespace"""
|
|
81
90
|
|
|
82
91
|
def __init__(
|
|
@@ -115,18 +124,42 @@ class ProtocolError(BaseError):
|
|
|
115
124
|
"""Protocol Error"""
|
|
116
125
|
|
|
117
126
|
|
|
118
|
-
class TimeoutError(
|
|
127
|
+
class TimeoutError(BaseBumbleError): # pylint: disable=redefined-builtin
|
|
119
128
|
"""Timeout Error"""
|
|
120
129
|
|
|
121
130
|
|
|
122
|
-
class CommandTimeoutError(
|
|
131
|
+
class CommandTimeoutError(BaseBumbleError):
|
|
123
132
|
"""Command Timeout Error"""
|
|
124
133
|
|
|
125
134
|
|
|
126
|
-
class InvalidStateError(
|
|
135
|
+
class InvalidStateError(BaseBumbleError):
|
|
127
136
|
"""Invalid State Error"""
|
|
128
137
|
|
|
129
138
|
|
|
139
|
+
class InvalidArgumentError(BaseBumbleError, ValueError):
|
|
140
|
+
"""Invalid Argument Error"""
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class InvalidPacketError(BaseBumbleError, ValueError):
|
|
144
|
+
"""Invalid Packet Error"""
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class InvalidOperationError(BaseBumbleError, RuntimeError):
|
|
148
|
+
"""Invalid Operation Error"""
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class NotSupportedError(BaseBumbleError, RuntimeError):
|
|
152
|
+
"""Not Supported"""
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class OutOfResourcesError(BaseBumbleError, RuntimeError):
|
|
156
|
+
"""Out of Resources Error"""
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
class UnreachableError(BaseBumbleError):
|
|
160
|
+
"""The code path raising this error should be unreachable."""
|
|
161
|
+
|
|
162
|
+
|
|
130
163
|
class ConnectionError(BaseError): # pylint: disable=redefined-builtin
|
|
131
164
|
"""Connection Error"""
|
|
132
165
|
|
|
@@ -185,12 +218,12 @@ class UUID:
|
|
|
185
218
|
or uuid_str_or_int[18] != '-'
|
|
186
219
|
or uuid_str_or_int[23] != '-'
|
|
187
220
|
):
|
|
188
|
-
raise
|
|
221
|
+
raise InvalidArgumentError('invalid UUID format')
|
|
189
222
|
uuid_str = uuid_str_or_int.replace('-', '')
|
|
190
223
|
else:
|
|
191
224
|
uuid_str = uuid_str_or_int
|
|
192
225
|
if len(uuid_str) != 32 and len(uuid_str) != 8 and len(uuid_str) != 4:
|
|
193
|
-
raise
|
|
226
|
+
raise InvalidArgumentError(f"invalid UUID format: {uuid_str}")
|
|
194
227
|
self.uuid_bytes = bytes(reversed(bytes.fromhex(uuid_str)))
|
|
195
228
|
self.name = name
|
|
196
229
|
|
|
@@ -215,7 +248,7 @@ class UUID:
|
|
|
215
248
|
|
|
216
249
|
return self.register()
|
|
217
250
|
|
|
218
|
-
raise
|
|
251
|
+
raise InvalidArgumentError('only 2, 4 and 16 bytes are allowed')
|
|
219
252
|
|
|
220
253
|
@classmethod
|
|
221
254
|
def from_16_bits(cls, uuid_16: int, name: Optional[str] = None) -> UUID:
|
|
@@ -692,11 +725,569 @@ class DeviceClass:
|
|
|
692
725
|
return name_or_number(class_names, minor_device_class)
|
|
693
726
|
|
|
694
727
|
|
|
728
|
+
# -----------------------------------------------------------------------------
|
|
729
|
+
# Appearance
|
|
730
|
+
# -----------------------------------------------------------------------------
|
|
731
|
+
class Appearance:
|
|
732
|
+
class Category(OpenIntEnum):
|
|
733
|
+
UNKNOWN = 0x0000
|
|
734
|
+
PHONE = 0x0001
|
|
735
|
+
COMPUTER = 0x0002
|
|
736
|
+
WATCH = 0x0003
|
|
737
|
+
CLOCK = 0x0004
|
|
738
|
+
DISPLAY = 0x0005
|
|
739
|
+
REMOTE_CONTROL = 0x0006
|
|
740
|
+
EYE_GLASSES = 0x0007
|
|
741
|
+
TAG = 0x0008
|
|
742
|
+
KEYRING = 0x0009
|
|
743
|
+
MEDIA_PLAYER = 0x000A
|
|
744
|
+
BARCODE_SCANNER = 0x000B
|
|
745
|
+
THERMOMETER = 0x000C
|
|
746
|
+
HEART_RATE_SENSOR = 0x000D
|
|
747
|
+
BLOOD_PRESSURE = 0x000E
|
|
748
|
+
HUMAN_INTERFACE_DEVICE = 0x000F
|
|
749
|
+
GLUCOSE_METER = 0x0010
|
|
750
|
+
RUNNING_WALKING_SENSOR = 0x0011
|
|
751
|
+
CYCLING = 0x0012
|
|
752
|
+
CONTROL_DEVICE = 0x0013
|
|
753
|
+
NETWORK_DEVICE = 0x0014
|
|
754
|
+
SENSOR = 0x0015
|
|
755
|
+
LIGHT_FIXTURES = 0x0016
|
|
756
|
+
FAN = 0x0017
|
|
757
|
+
HVAC = 0x0018
|
|
758
|
+
AIR_CONDITIONING = 0x0019
|
|
759
|
+
HUMIDIFIER = 0x001A
|
|
760
|
+
HEATING = 0x001B
|
|
761
|
+
ACCESS_CONTROL = 0x001C
|
|
762
|
+
MOTORIZED_DEVICE = 0x001D
|
|
763
|
+
POWER_DEVICE = 0x001E
|
|
764
|
+
LIGHT_SOURCE = 0x001F
|
|
765
|
+
WINDOW_COVERING = 0x0020
|
|
766
|
+
AUDIO_SINK = 0x0021
|
|
767
|
+
AUDIO_SOURCE = 0x0022
|
|
768
|
+
MOTORIZED_VEHICLE = 0x0023
|
|
769
|
+
DOMESTIC_APPLIANCE = 0x0024
|
|
770
|
+
WEARABLE_AUDIO_DEVICE = 0x0025
|
|
771
|
+
AIRCRAFT = 0x0026
|
|
772
|
+
AV_EQUIPMENT = 0x0027
|
|
773
|
+
DISPLAY_EQUIPMENT = 0x0028
|
|
774
|
+
HEARING_AID = 0x0029
|
|
775
|
+
GAMING = 0x002A
|
|
776
|
+
SIGNAGE = 0x002B
|
|
777
|
+
PULSE_OXIMETER = 0x0031
|
|
778
|
+
WEIGHT_SCALE = 0x0032
|
|
779
|
+
PERSONAL_MOBILITY_DEVICE = 0x0033
|
|
780
|
+
CONTINUOUS_GLUCOSE_MONITOR = 0x0034
|
|
781
|
+
INSULIN_PUMP = 0x0035
|
|
782
|
+
MEDICATION_DELIVERY = 0x0036
|
|
783
|
+
SPIROMETER = 0x0037
|
|
784
|
+
OUTDOOR_SPORTS_ACTIVITY = 0x0051
|
|
785
|
+
|
|
786
|
+
class UnknownSubcategory(OpenIntEnum):
|
|
787
|
+
GENERIC_UNKNOWN = 0x00
|
|
788
|
+
|
|
789
|
+
class PhoneSubcategory(OpenIntEnum):
|
|
790
|
+
GENERIC_PHONE = 0x00
|
|
791
|
+
|
|
792
|
+
class ComputerSubcategory(OpenIntEnum):
|
|
793
|
+
GENERIC_COMPUTER = 0x00
|
|
794
|
+
DESKTOP_WORKSTATION = 0x01
|
|
795
|
+
SERVER_CLASS_COMPUTER = 0x02
|
|
796
|
+
LAPTOP = 0x03
|
|
797
|
+
HANDHELD_PC_PDA = 0x04
|
|
798
|
+
PALM_SIZE_PC_PDA = 0x05
|
|
799
|
+
WEARABLE_COMPUTER = 0x06
|
|
800
|
+
TABLET = 0x07
|
|
801
|
+
DOCKING_STATION = 0x08
|
|
802
|
+
ALL_IN_ONE = 0x09
|
|
803
|
+
BLADE_SERVER = 0x0A
|
|
804
|
+
CONVERTIBLE = 0x0B
|
|
805
|
+
DETACHABLE = 0x0C
|
|
806
|
+
IOT_GATEWAY = 0x0D
|
|
807
|
+
MINI_PC = 0x0E
|
|
808
|
+
STICK_PC = 0x0F
|
|
809
|
+
|
|
810
|
+
class WatchSubcategory(OpenIntEnum):
|
|
811
|
+
GENENERIC_WATCH = 0x00
|
|
812
|
+
SPORTS_WATCH = 0x01
|
|
813
|
+
SMARTWATCH = 0x02
|
|
814
|
+
|
|
815
|
+
class ClockSubcategory(OpenIntEnum):
|
|
816
|
+
GENERIC_CLOCK = 0x00
|
|
817
|
+
|
|
818
|
+
class DisplaySubcategory(OpenIntEnum):
|
|
819
|
+
GENERIC_DISPLAY = 0x00
|
|
820
|
+
|
|
821
|
+
class RemoteControlSubcategory(OpenIntEnum):
|
|
822
|
+
GENERIC_REMOTE_CONTROL = 0x00
|
|
823
|
+
|
|
824
|
+
class EyeglassesSubcategory(OpenIntEnum):
|
|
825
|
+
GENERIC_EYEGLASSES = 0x00
|
|
826
|
+
|
|
827
|
+
class TagSubcategory(OpenIntEnum):
|
|
828
|
+
GENERIC_TAG = 0x00
|
|
829
|
+
|
|
830
|
+
class KeyringSubcategory(OpenIntEnum):
|
|
831
|
+
GENERIC_KEYRING = 0x00
|
|
832
|
+
|
|
833
|
+
class MediaPlayerSubcategory(OpenIntEnum):
|
|
834
|
+
GENERIC_MEDIA_PLAYER = 0x00
|
|
835
|
+
|
|
836
|
+
class BarcodeScannerSubcategory(OpenIntEnum):
|
|
837
|
+
GENERIC_BARCODE_SCANNER = 0x00
|
|
838
|
+
|
|
839
|
+
class ThermometerSubcategory(OpenIntEnum):
|
|
840
|
+
GENERIC_THERMOMETER = 0x00
|
|
841
|
+
EAR_THERMOMETER = 0x01
|
|
842
|
+
|
|
843
|
+
class HeartRateSensorSubcategory(OpenIntEnum):
|
|
844
|
+
GENERIC_HEART_RATE_SENSOR = 0x00
|
|
845
|
+
HEART_RATE_BELT = 0x01
|
|
846
|
+
|
|
847
|
+
class BloodPressureSubcategory(OpenIntEnum):
|
|
848
|
+
GENERIC_BLOOD_PRESSURE = 0x00
|
|
849
|
+
ARM_BLOOD_PRESSURE = 0x01
|
|
850
|
+
WRIST_BLOOD_PRESSURE = 0x02
|
|
851
|
+
|
|
852
|
+
class HumanInterfaceDeviceSubcategory(OpenIntEnum):
|
|
853
|
+
GENERIC_HUMAN_INTERFACE_DEVICE = 0x00
|
|
854
|
+
KEYBOARD = 0x01
|
|
855
|
+
MOUSE = 0x02
|
|
856
|
+
JOYSTICK = 0x03
|
|
857
|
+
GAMEPAD = 0x04
|
|
858
|
+
DIGITIZER_TABLET = 0x05
|
|
859
|
+
CARD_READER = 0x06
|
|
860
|
+
DIGITAL_PEN = 0x07
|
|
861
|
+
BARCODE_SCANNER = 0x08
|
|
862
|
+
TOUCHPAD = 0x09
|
|
863
|
+
PRESENTATION_REMOTE = 0x0A
|
|
864
|
+
|
|
865
|
+
class GlucoseMeterSubcategory(OpenIntEnum):
|
|
866
|
+
GENERIC_GLUCOSE_METER = 0x00
|
|
867
|
+
|
|
868
|
+
class RunningWalkingSensorSubcategory(OpenIntEnum):
|
|
869
|
+
GENERIC_RUNNING_WALKING_SENSOR = 0x00
|
|
870
|
+
IN_SHOE_RUNNING_WALKING_SENSOR = 0x01
|
|
871
|
+
ON_SHOW_RUNNING_WALKING_SENSOR = 0x02
|
|
872
|
+
ON_HIP_RUNNING_WALKING_SENSOR = 0x03
|
|
873
|
+
|
|
874
|
+
class CyclingSubcategory(OpenIntEnum):
|
|
875
|
+
GENERIC_CYCLING = 0x00
|
|
876
|
+
CYCLING_COMPUTER = 0x01
|
|
877
|
+
SPEED_SENSOR = 0x02
|
|
878
|
+
CADENCE_SENSOR = 0x03
|
|
879
|
+
POWER_SENSOR = 0x04
|
|
880
|
+
SPEED_AND_CADENCE_SENSOR = 0x05
|
|
881
|
+
|
|
882
|
+
class ControlDeviceSubcategory(OpenIntEnum):
|
|
883
|
+
GENERIC_CONTROL_DEVICE = 0x00
|
|
884
|
+
SWITCH = 0x01
|
|
885
|
+
MULTI_SWITCH = 0x02
|
|
886
|
+
BUTTON = 0x03
|
|
887
|
+
SLIDER = 0x04
|
|
888
|
+
ROTARY_SWITCH = 0x05
|
|
889
|
+
TOUCH_PANEL = 0x06
|
|
890
|
+
SINGLE_SWITCH = 0x07
|
|
891
|
+
DOUBLE_SWITCH = 0x08
|
|
892
|
+
TRIPLE_SWITCH = 0x09
|
|
893
|
+
BATTERY_SWITCH = 0x0A
|
|
894
|
+
ENERGY_HARVESTING_SWITCH = 0x0B
|
|
895
|
+
PUSH_BUTTON = 0x0C
|
|
896
|
+
|
|
897
|
+
class NetworkDeviceSubcategory(OpenIntEnum):
|
|
898
|
+
GENERIC_NETWORK_DEVICE = 0x00
|
|
899
|
+
ACCESS_POINT = 0x01
|
|
900
|
+
MESH_DEVICE = 0x02
|
|
901
|
+
MESH_NETWORK_PROXY = 0x03
|
|
902
|
+
|
|
903
|
+
class SensorSubcategory(OpenIntEnum):
|
|
904
|
+
GENERIC_SENSOR = 0x00
|
|
905
|
+
MOTION_SENSOR = 0x01
|
|
906
|
+
AIR_QUALITY_SENSOR = 0x02
|
|
907
|
+
TEMPERATURE_SENSOR = 0x03
|
|
908
|
+
HUMIDITY_SENSOR = 0x04
|
|
909
|
+
LEAK_SENSOR = 0x05
|
|
910
|
+
SMOKE_SENSOR = 0x06
|
|
911
|
+
OCCUPANCY_SENSOR = 0x07
|
|
912
|
+
CONTACT_SENSOR = 0x08
|
|
913
|
+
CARBON_MONOXIDE_SENSOR = 0x09
|
|
914
|
+
CARBON_DIOXIDE_SENSOR = 0x0A
|
|
915
|
+
AMBIENT_LIGHT_SENSOR = 0x0B
|
|
916
|
+
ENERGY_SENSOR = 0x0C
|
|
917
|
+
COLOR_LIGHT_SENSOR = 0x0D
|
|
918
|
+
RAIN_SENSOR = 0x0E
|
|
919
|
+
FIRE_SENSOR = 0x0F
|
|
920
|
+
WIND_SENSOR = 0x10
|
|
921
|
+
PROXIMITY_SENSOR = 0x11
|
|
922
|
+
MULTI_SENSOR = 0x12
|
|
923
|
+
FLUSH_MOUNTED_SENSOR = 0x13
|
|
924
|
+
CEILING_MOUNTED_SENSOR = 0x14
|
|
925
|
+
WALL_MOUNTED_SENSOR = 0x15
|
|
926
|
+
MULTISENSOR = 0x16
|
|
927
|
+
ENERGY_METER = 0x17
|
|
928
|
+
FLAME_DETECTOR = 0x18
|
|
929
|
+
VEHICLE_TIRE_PRESSURE_SENSOR = 0x19
|
|
930
|
+
|
|
931
|
+
class LightFixturesSubcategory(OpenIntEnum):
|
|
932
|
+
GENERIC_LIGHT_FIXTURES = 0x00
|
|
933
|
+
WALL_LIGHT = 0x01
|
|
934
|
+
CEILING_LIGHT = 0x02
|
|
935
|
+
FLOOR_LIGHT = 0x03
|
|
936
|
+
CABINET_LIGHT = 0x04
|
|
937
|
+
DESK_LIGHT = 0x05
|
|
938
|
+
TROFFER_LIGHT = 0x06
|
|
939
|
+
PENDANT_LIGHT = 0x07
|
|
940
|
+
IN_GROUND_LIGHT = 0x08
|
|
941
|
+
FLOOD_LIGHT = 0x09
|
|
942
|
+
UNDERWATER_LIGHT = 0x0A
|
|
943
|
+
BOLLARD_WITH_LIGHT = 0x0B
|
|
944
|
+
PATHWAY_LIGHT = 0x0C
|
|
945
|
+
GARDEN_LIGHT = 0x0D
|
|
946
|
+
POLE_TOP_LIGHT = 0x0E
|
|
947
|
+
SPOTLIGHT = 0x0F
|
|
948
|
+
LINEAR_LIGHT = 0x10
|
|
949
|
+
STREET_LIGHT = 0x11
|
|
950
|
+
SHELVES_LIGHT = 0x12
|
|
951
|
+
BAY_LIGHT = 0x013
|
|
952
|
+
EMERGENCY_EXIT_LIGHT = 0x14
|
|
953
|
+
LIGHT_CONTROLLER = 0x15
|
|
954
|
+
LIGHT_DRIVER = 0x16
|
|
955
|
+
BULB = 0x17
|
|
956
|
+
LOW_BAY_LIGHT = 0x18
|
|
957
|
+
HIGH_BAY_LIGHT = 0x19
|
|
958
|
+
|
|
959
|
+
class FanSubcategory(OpenIntEnum):
|
|
960
|
+
GENERIC_FAN = 0x00
|
|
961
|
+
CEILING_FAN = 0x01
|
|
962
|
+
AXIAL_FAN = 0x02
|
|
963
|
+
EXHAUST_FAN = 0x03
|
|
964
|
+
PEDESTAL_FAN = 0x04
|
|
965
|
+
DESK_FAN = 0x05
|
|
966
|
+
WALL_FAN = 0x06
|
|
967
|
+
|
|
968
|
+
class HvacSubcategory(OpenIntEnum):
|
|
969
|
+
GENERIC_HVAC = 0x00
|
|
970
|
+
THERMOSTAT = 0x01
|
|
971
|
+
HUMIDIFIER = 0x02
|
|
972
|
+
DEHUMIDIFIER = 0x03
|
|
973
|
+
HEATER = 0x04
|
|
974
|
+
RADIATOR = 0x05
|
|
975
|
+
BOILER = 0x06
|
|
976
|
+
HEAT_PUMP = 0x07
|
|
977
|
+
INFRARED_HEATER = 0x08
|
|
978
|
+
RADIANT_PANEL_HEATER = 0x09
|
|
979
|
+
FAN_HEATER = 0x0A
|
|
980
|
+
AIR_CURTAIN = 0x0B
|
|
981
|
+
|
|
982
|
+
class AirConditioningSubcategory(OpenIntEnum):
|
|
983
|
+
GENERIC_AIR_CONDITIONING = 0x00
|
|
984
|
+
|
|
985
|
+
class HumidifierSubcategory(OpenIntEnum):
|
|
986
|
+
GENERIC_HUMIDIFIER = 0x00
|
|
987
|
+
|
|
988
|
+
class HeatingSubcategory(OpenIntEnum):
|
|
989
|
+
GENERIC_HEATING = 0x00
|
|
990
|
+
RADIATOR = 0x01
|
|
991
|
+
BOILER = 0x02
|
|
992
|
+
HEAT_PUMP = 0x03
|
|
993
|
+
INFRARED_HEATER = 0x04
|
|
994
|
+
RADIANT_PANEL_HEATER = 0x05
|
|
995
|
+
FAN_HEATER = 0x06
|
|
996
|
+
AIR_CURTAIN = 0x07
|
|
997
|
+
|
|
998
|
+
class AccessControlSubcategory(OpenIntEnum):
|
|
999
|
+
GENERIC_ACCESS_CONTROL = 0x00
|
|
1000
|
+
ACCESS_DOOR = 0x01
|
|
1001
|
+
GARAGE_DOOR = 0x02
|
|
1002
|
+
EMERGENCY_EXIT_DOOR = 0x03
|
|
1003
|
+
ACCESS_LOCK = 0x04
|
|
1004
|
+
ELEVATOR = 0x05
|
|
1005
|
+
WINDOW = 0x06
|
|
1006
|
+
ENTRANCE_GATE = 0x07
|
|
1007
|
+
DOOR_LOCK = 0x08
|
|
1008
|
+
LOCKER = 0x09
|
|
1009
|
+
|
|
1010
|
+
class MotorizedDeviceSubcategory(OpenIntEnum):
|
|
1011
|
+
GENERIC_MOTORIZED_DEVICE = 0x00
|
|
1012
|
+
MOTORIZED_GATE = 0x01
|
|
1013
|
+
AWNING = 0x02
|
|
1014
|
+
BLINDS_OR_SHADES = 0x03
|
|
1015
|
+
CURTAINS = 0x04
|
|
1016
|
+
SCREEN = 0x05
|
|
1017
|
+
|
|
1018
|
+
class PowerDeviceSubcategory(OpenIntEnum):
|
|
1019
|
+
GENERIC_POWER_DEVICE = 0x00
|
|
1020
|
+
POWER_OUTLET = 0x01
|
|
1021
|
+
POWER_STRIP = 0x02
|
|
1022
|
+
PLUG = 0x03
|
|
1023
|
+
POWER_SUPPLY = 0x04
|
|
1024
|
+
LED_DRIVER = 0x05
|
|
1025
|
+
FLUORESCENT_LAMP_GEAR = 0x06
|
|
1026
|
+
HID_LAMP_GEAR = 0x07
|
|
1027
|
+
CHARGE_CASE = 0x08
|
|
1028
|
+
POWER_BANK = 0x09
|
|
1029
|
+
|
|
1030
|
+
class LightSourceSubcategory(OpenIntEnum):
|
|
1031
|
+
GENERIC_LIGHT_SOURCE = 0x00
|
|
1032
|
+
INCANDESCENT_LIGHT_BULB = 0x01
|
|
1033
|
+
LED_LAMP = 0x02
|
|
1034
|
+
HID_LAMP = 0x03
|
|
1035
|
+
FLUORESCENT_LAMP = 0x04
|
|
1036
|
+
LED_ARRAY = 0x05
|
|
1037
|
+
MULTI_COLOR_LED_ARRAY = 0x06
|
|
1038
|
+
LOW_VOLTAGE_HALOGEN = 0x07
|
|
1039
|
+
ORGANIC_LIGHT_EMITTING_DIODE = 0x08
|
|
1040
|
+
|
|
1041
|
+
class WindowCoveringSubcategory(OpenIntEnum):
|
|
1042
|
+
GENERIC_WINDOW_COVERING = 0x00
|
|
1043
|
+
WINDOW_SHADES = 0x01
|
|
1044
|
+
WINDOW_BLINDS = 0x02
|
|
1045
|
+
WINDOW_AWNING = 0x03
|
|
1046
|
+
WINDOW_CURTAIN = 0x04
|
|
1047
|
+
EXTERIOR_SHUTTER = 0x05
|
|
1048
|
+
EXTERIOR_SCREEN = 0x06
|
|
1049
|
+
|
|
1050
|
+
class AudioSinkSubcategory(OpenIntEnum):
|
|
1051
|
+
GENERIC_AUDIO_SINK = 0x00
|
|
1052
|
+
STANDALONE_SPEAKER = 0x01
|
|
1053
|
+
SOUNDBAR = 0x02
|
|
1054
|
+
BOOKSHELF_SPEAKER = 0x03
|
|
1055
|
+
STANDMOUNTED_SPEAKER = 0x04
|
|
1056
|
+
SPEAKERPHONE = 0x05
|
|
1057
|
+
|
|
1058
|
+
class AudioSourceSubcategory(OpenIntEnum):
|
|
1059
|
+
GENERIC_AUDIO_SOURCE = 0x00
|
|
1060
|
+
MICROPHONE = 0x01
|
|
1061
|
+
ALARM = 0x02
|
|
1062
|
+
BELL = 0x03
|
|
1063
|
+
HORN = 0x04
|
|
1064
|
+
BROADCASTING_DEVICE = 0x05
|
|
1065
|
+
SERVICE_DESK = 0x06
|
|
1066
|
+
KIOSK = 0x07
|
|
1067
|
+
BROADCASTING_ROOM = 0x08
|
|
1068
|
+
AUDITORIUM = 0x09
|
|
1069
|
+
|
|
1070
|
+
class MotorizedVehicleSubcategory(OpenIntEnum):
|
|
1071
|
+
GENERIC_MOTORIZED_VEHICLE = 0x00
|
|
1072
|
+
CAR = 0x01
|
|
1073
|
+
LARGE_GOODS_VEHICLE = 0x02
|
|
1074
|
+
TWO_WHEELED_VEHICLE = 0x03
|
|
1075
|
+
MOTORBIKE = 0x04
|
|
1076
|
+
SCOOTER = 0x05
|
|
1077
|
+
MOPED = 0x06
|
|
1078
|
+
THREE_WHEELED_VEHICLE = 0x07
|
|
1079
|
+
LIGHT_VEHICLE = 0x08
|
|
1080
|
+
QUAD_BIKE = 0x09
|
|
1081
|
+
MINIBUS = 0x0A
|
|
1082
|
+
BUS = 0x0B
|
|
1083
|
+
TROLLEY = 0x0C
|
|
1084
|
+
AGRICULTURAL_VEHICLE = 0x0D
|
|
1085
|
+
CAMPER_CARAVAN = 0x0E
|
|
1086
|
+
RECREATIONAL_VEHICLE_MOTOR_HOME = 0x0F
|
|
1087
|
+
|
|
1088
|
+
class DomesticApplianceSubcategory(OpenIntEnum):
|
|
1089
|
+
GENERIC_DOMESTIC_APPLIANCE = 0x00
|
|
1090
|
+
REFRIGERATOR = 0x01
|
|
1091
|
+
FREEZER = 0x02
|
|
1092
|
+
OVEN = 0x03
|
|
1093
|
+
MICROWAVE = 0x04
|
|
1094
|
+
TOASTER = 0x05
|
|
1095
|
+
WASHING_MACHINE = 0x06
|
|
1096
|
+
DRYER = 0x07
|
|
1097
|
+
COFFEE_MAKER = 0x08
|
|
1098
|
+
CLOTHES_IRON = 0x09
|
|
1099
|
+
CURLING_IRON = 0x0A
|
|
1100
|
+
HAIR_DRYER = 0x0B
|
|
1101
|
+
VACUUM_CLEANER = 0x0C
|
|
1102
|
+
ROBOTIC_VACUUM_CLEANER = 0x0D
|
|
1103
|
+
RICE_COOKER = 0x0E
|
|
1104
|
+
CLOTHES_STEAMER = 0x0F
|
|
1105
|
+
|
|
1106
|
+
class WearableAudioDeviceSubcategory(OpenIntEnum):
|
|
1107
|
+
GENERIC_WEARABLE_AUDIO_DEVICE = 0x00
|
|
1108
|
+
EARBUD = 0x01
|
|
1109
|
+
HEADSET = 0x02
|
|
1110
|
+
HEADPHONES = 0x03
|
|
1111
|
+
NECK_BAND = 0x04
|
|
1112
|
+
|
|
1113
|
+
class AircraftSubcategory(OpenIntEnum):
|
|
1114
|
+
GENERIC_AIRCRAFT = 0x00
|
|
1115
|
+
LIGHT_AIRCRAFT = 0x01
|
|
1116
|
+
MICROLIGHT = 0x02
|
|
1117
|
+
PARAGLIDER = 0x03
|
|
1118
|
+
LARGE_PASSENGER_AIRCRAFT = 0x04
|
|
1119
|
+
|
|
1120
|
+
class AvEquipmentSubcategory(OpenIntEnum):
|
|
1121
|
+
GENERIC_AV_EQUIPMENT = 0x00
|
|
1122
|
+
AMPLIFIER = 0x01
|
|
1123
|
+
RECEIVER = 0x02
|
|
1124
|
+
RADIO = 0x03
|
|
1125
|
+
TUNER = 0x04
|
|
1126
|
+
TURNTABLE = 0x05
|
|
1127
|
+
CD_PLAYER = 0x06
|
|
1128
|
+
DVD_PLAYER = 0x07
|
|
1129
|
+
BLUERAY_PLAYER = 0x08
|
|
1130
|
+
OPTICAL_DISC_PLAYER = 0x09
|
|
1131
|
+
SET_TOP_BOX = 0x0A
|
|
1132
|
+
|
|
1133
|
+
class DisplayEquipmentSubcategory(OpenIntEnum):
|
|
1134
|
+
GENERIC_DISPLAY_EQUIPMENT = 0x00
|
|
1135
|
+
TELEVISION = 0x01
|
|
1136
|
+
MONITOR = 0x02
|
|
1137
|
+
PROJECTOR = 0x03
|
|
1138
|
+
|
|
1139
|
+
class HearingAidSubcategory(OpenIntEnum):
|
|
1140
|
+
GENERIC_HEARING_AID = 0x00
|
|
1141
|
+
IN_EAR_HEARING_AID = 0x01
|
|
1142
|
+
BEHIND_EAR_HEARING_AID = 0x02
|
|
1143
|
+
COCHLEAR_IMPLANT = 0x03
|
|
1144
|
+
|
|
1145
|
+
class GamingSubcategory(OpenIntEnum):
|
|
1146
|
+
GENERIC_GAMING = 0x00
|
|
1147
|
+
HOME_VIDEO_GAME_CONSOLE = 0x01
|
|
1148
|
+
PORTABLE_HANDHELD_CONSOLE = 0x02
|
|
1149
|
+
|
|
1150
|
+
class SignageSubcategory(OpenIntEnum):
|
|
1151
|
+
GENERIC_SIGNAGE = 0x00
|
|
1152
|
+
DIGITAL_SIGNAGE = 0x01
|
|
1153
|
+
ELECTRONIC_LABEL = 0x02
|
|
1154
|
+
|
|
1155
|
+
class PulseOximeterSubcategory(OpenIntEnum):
|
|
1156
|
+
GENERIC_PULSE_OXIMETER = 0x00
|
|
1157
|
+
FINGERTIP_PULSE_OXIMETER = 0x01
|
|
1158
|
+
WRIST_WORN_PULSE_OXIMETER = 0x02
|
|
1159
|
+
|
|
1160
|
+
class WeightScaleSubcategory(OpenIntEnum):
|
|
1161
|
+
GENERIC_WEIGHT_SCALE = 0x00
|
|
1162
|
+
|
|
1163
|
+
class PersonalMobilityDeviceSubcategory(OpenIntEnum):
|
|
1164
|
+
GENERIC_PERSONAL_MOBILITY_DEVICE = 0x00
|
|
1165
|
+
POWERED_WHEELCHAIR = 0x01
|
|
1166
|
+
MOBILITY_SCOOTER = 0x02
|
|
1167
|
+
|
|
1168
|
+
class ContinuousGlucoseMonitorSubcategory(OpenIntEnum):
|
|
1169
|
+
GENERIC_CONTINUOUS_GLUCOSE_MONITOR = 0x00
|
|
1170
|
+
|
|
1171
|
+
class InsulinPumpSubcategory(OpenIntEnum):
|
|
1172
|
+
GENERIC_INSULIN_PUMP = 0x00
|
|
1173
|
+
INSULIN_PUMP_DURABLE_PUMP = 0x01
|
|
1174
|
+
INSULIN_PUMP_PATCH_PUMP = 0x02
|
|
1175
|
+
INSULIN_PEN = 0x03
|
|
1176
|
+
|
|
1177
|
+
class MedicationDeliverySubcategory(OpenIntEnum):
|
|
1178
|
+
GENERIC_MEDICATION_DELIVERY = 0x00
|
|
1179
|
+
|
|
1180
|
+
class SpirometerSubcategory(OpenIntEnum):
|
|
1181
|
+
GENERIC_SPIROMETER = 0x00
|
|
1182
|
+
HANDHELD_SPIROMETER = 0x01
|
|
1183
|
+
|
|
1184
|
+
class OutdoorSportsActivitySubcategory(OpenIntEnum):
|
|
1185
|
+
GENERIC_OUTDOOR_SPORTS_ACTIVITY = 0x00
|
|
1186
|
+
LOCATION_DISPLAY = 0x01
|
|
1187
|
+
LOCATION_AND_NAVIGATION_DISPLAY = 0x02
|
|
1188
|
+
LOCATION_POD = 0x03
|
|
1189
|
+
LOCATION_AND_NAVIGATION_POD = 0x04
|
|
1190
|
+
|
|
1191
|
+
class _OpenSubcategory(OpenIntEnum):
|
|
1192
|
+
GENERIC = 0x00
|
|
1193
|
+
|
|
1194
|
+
SUBCATEGORY_CLASSES = {
|
|
1195
|
+
Category.UNKNOWN: UnknownSubcategory,
|
|
1196
|
+
Category.PHONE: PhoneSubcategory,
|
|
1197
|
+
Category.COMPUTER: ComputerSubcategory,
|
|
1198
|
+
Category.WATCH: WatchSubcategory,
|
|
1199
|
+
Category.CLOCK: ClockSubcategory,
|
|
1200
|
+
Category.DISPLAY: DisplaySubcategory,
|
|
1201
|
+
Category.REMOTE_CONTROL: RemoteControlSubcategory,
|
|
1202
|
+
Category.EYE_GLASSES: EyeglassesSubcategory,
|
|
1203
|
+
Category.TAG: TagSubcategory,
|
|
1204
|
+
Category.KEYRING: KeyringSubcategory,
|
|
1205
|
+
Category.MEDIA_PLAYER: MediaPlayerSubcategory,
|
|
1206
|
+
Category.BARCODE_SCANNER: BarcodeScannerSubcategory,
|
|
1207
|
+
Category.THERMOMETER: ThermometerSubcategory,
|
|
1208
|
+
Category.HEART_RATE_SENSOR: HeartRateSensorSubcategory,
|
|
1209
|
+
Category.BLOOD_PRESSURE: BloodPressureSubcategory,
|
|
1210
|
+
Category.HUMAN_INTERFACE_DEVICE: HumanInterfaceDeviceSubcategory,
|
|
1211
|
+
Category.GLUCOSE_METER: GlucoseMeterSubcategory,
|
|
1212
|
+
Category.RUNNING_WALKING_SENSOR: RunningWalkingSensorSubcategory,
|
|
1213
|
+
Category.CYCLING: CyclingSubcategory,
|
|
1214
|
+
Category.CONTROL_DEVICE: ControlDeviceSubcategory,
|
|
1215
|
+
Category.NETWORK_DEVICE: NetworkDeviceSubcategory,
|
|
1216
|
+
Category.SENSOR: SensorSubcategory,
|
|
1217
|
+
Category.LIGHT_FIXTURES: LightFixturesSubcategory,
|
|
1218
|
+
Category.FAN: FanSubcategory,
|
|
1219
|
+
Category.HVAC: HvacSubcategory,
|
|
1220
|
+
Category.AIR_CONDITIONING: AirConditioningSubcategory,
|
|
1221
|
+
Category.HUMIDIFIER: HumidifierSubcategory,
|
|
1222
|
+
Category.HEATING: HeatingSubcategory,
|
|
1223
|
+
Category.ACCESS_CONTROL: AccessControlSubcategory,
|
|
1224
|
+
Category.MOTORIZED_DEVICE: MotorizedDeviceSubcategory,
|
|
1225
|
+
Category.POWER_DEVICE: PowerDeviceSubcategory,
|
|
1226
|
+
Category.LIGHT_SOURCE: LightSourceSubcategory,
|
|
1227
|
+
Category.WINDOW_COVERING: WindowCoveringSubcategory,
|
|
1228
|
+
Category.AUDIO_SINK: AudioSinkSubcategory,
|
|
1229
|
+
Category.AUDIO_SOURCE: AudioSourceSubcategory,
|
|
1230
|
+
Category.MOTORIZED_VEHICLE: MotorizedVehicleSubcategory,
|
|
1231
|
+
Category.DOMESTIC_APPLIANCE: DomesticApplianceSubcategory,
|
|
1232
|
+
Category.WEARABLE_AUDIO_DEVICE: WearableAudioDeviceSubcategory,
|
|
1233
|
+
Category.AIRCRAFT: AircraftSubcategory,
|
|
1234
|
+
Category.AV_EQUIPMENT: AvEquipmentSubcategory,
|
|
1235
|
+
Category.DISPLAY_EQUIPMENT: DisplayEquipmentSubcategory,
|
|
1236
|
+
Category.HEARING_AID: HearingAidSubcategory,
|
|
1237
|
+
Category.GAMING: GamingSubcategory,
|
|
1238
|
+
Category.SIGNAGE: SignageSubcategory,
|
|
1239
|
+
Category.PULSE_OXIMETER: PulseOximeterSubcategory,
|
|
1240
|
+
Category.WEIGHT_SCALE: WeightScaleSubcategory,
|
|
1241
|
+
Category.PERSONAL_MOBILITY_DEVICE: PersonalMobilityDeviceSubcategory,
|
|
1242
|
+
Category.CONTINUOUS_GLUCOSE_MONITOR: ContinuousGlucoseMonitorSubcategory,
|
|
1243
|
+
Category.INSULIN_PUMP: InsulinPumpSubcategory,
|
|
1244
|
+
Category.MEDICATION_DELIVERY: MedicationDeliverySubcategory,
|
|
1245
|
+
Category.SPIROMETER: SpirometerSubcategory,
|
|
1246
|
+
Category.OUTDOOR_SPORTS_ACTIVITY: OutdoorSportsActivitySubcategory,
|
|
1247
|
+
}
|
|
1248
|
+
|
|
1249
|
+
category: Category
|
|
1250
|
+
subcategory: enum.IntEnum
|
|
1251
|
+
|
|
1252
|
+
@classmethod
|
|
1253
|
+
def from_int(cls, appearance: int) -> Self:
|
|
1254
|
+
category = cls.Category(appearance >> 6)
|
|
1255
|
+
return cls(category, appearance & 0x3F)
|
|
1256
|
+
|
|
1257
|
+
def __init__(self, category: Category, subcategory: int) -> None:
|
|
1258
|
+
self.category = category
|
|
1259
|
+
if subcategory_class := self.SUBCATEGORY_CLASSES.get(category):
|
|
1260
|
+
self.subcategory = subcategory_class(subcategory)
|
|
1261
|
+
else:
|
|
1262
|
+
self.subcategory = self._OpenSubcategory(subcategory)
|
|
1263
|
+
|
|
1264
|
+
def __int__(self) -> int:
|
|
1265
|
+
return self.category << 6 | self.subcategory
|
|
1266
|
+
|
|
1267
|
+
def __repr__(self) -> str:
|
|
1268
|
+
return (
|
|
1269
|
+
'Appearance('
|
|
1270
|
+
f'category={self.category.name}, '
|
|
1271
|
+
f'subcategory={self.subcategory.name}'
|
|
1272
|
+
')'
|
|
1273
|
+
)
|
|
1274
|
+
|
|
1275
|
+
def __str__(self) -> str:
|
|
1276
|
+
return f'{self.category.name}/{self.subcategory.name}'
|
|
1277
|
+
|
|
1278
|
+
|
|
695
1279
|
# -----------------------------------------------------------------------------
|
|
696
1280
|
# Advertising Data
|
|
697
1281
|
# -----------------------------------------------------------------------------
|
|
698
|
-
|
|
699
|
-
List[UUID],
|
|
1282
|
+
AdvertisingDataObject = Union[
|
|
1283
|
+
List[UUID],
|
|
1284
|
+
Tuple[UUID, bytes],
|
|
1285
|
+
bytes,
|
|
1286
|
+
str,
|
|
1287
|
+
int,
|
|
1288
|
+
Tuple[int, int],
|
|
1289
|
+
Tuple[int, bytes],
|
|
1290
|
+
Appearance,
|
|
700
1291
|
]
|
|
701
1292
|
|
|
702
1293
|
|
|
@@ -704,109 +1295,115 @@ class AdvertisingData:
|
|
|
704
1295
|
# fmt: off
|
|
705
1296
|
# pylint: disable=line-too-long
|
|
706
1297
|
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
1298
|
+
FLAGS = 0x01
|
|
1299
|
+
INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS = 0x02
|
|
1300
|
+
COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS = 0x03
|
|
1301
|
+
INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS = 0x04
|
|
1302
|
+
COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS = 0x05
|
|
1303
|
+
INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS = 0x06
|
|
1304
|
+
COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS = 0x07
|
|
1305
|
+
SHORTENED_LOCAL_NAME = 0x08
|
|
1306
|
+
COMPLETE_LOCAL_NAME = 0x09
|
|
1307
|
+
TX_POWER_LEVEL = 0x0A
|
|
1308
|
+
CLASS_OF_DEVICE = 0x0D
|
|
1309
|
+
SIMPLE_PAIRING_HASH_C = 0x0E
|
|
1310
|
+
SIMPLE_PAIRING_HASH_C_192 = 0x0E
|
|
1311
|
+
SIMPLE_PAIRING_RANDOMIZER_R = 0x0F
|
|
1312
|
+
SIMPLE_PAIRING_RANDOMIZER_R_192 = 0x0F
|
|
1313
|
+
DEVICE_ID = 0x10
|
|
1314
|
+
SECURITY_MANAGER_TK_VALUE = 0x10
|
|
1315
|
+
SECURITY_MANAGER_OUT_OF_BAND_FLAGS = 0x11
|
|
1316
|
+
PERIPHERAL_CONNECTION_INTERVAL_RANGE = 0x12
|
|
1317
|
+
LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS = 0x14
|
|
1318
|
+
LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS = 0x15
|
|
1319
|
+
SERVICE_DATA = 0x16
|
|
1320
|
+
SERVICE_DATA_16_BIT_UUID = 0x16
|
|
1321
|
+
PUBLIC_TARGET_ADDRESS = 0x17
|
|
1322
|
+
RANDOM_TARGET_ADDRESS = 0x18
|
|
1323
|
+
APPEARANCE = 0x19
|
|
1324
|
+
ADVERTISING_INTERVAL = 0x1A
|
|
1325
|
+
LE_BLUETOOTH_DEVICE_ADDRESS = 0x1B
|
|
1326
|
+
LE_ROLE = 0x1C
|
|
1327
|
+
SIMPLE_PAIRING_HASH_C_256 = 0x1D
|
|
1328
|
+
SIMPLE_PAIRING_RANDOMIZER_R_256 = 0x1E
|
|
1329
|
+
LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS = 0x1F
|
|
1330
|
+
SERVICE_DATA_32_BIT_UUID = 0x20
|
|
1331
|
+
SERVICE_DATA_128_BIT_UUID = 0x21
|
|
1332
|
+
LE_SECURE_CONNECTIONS_CONFIRMATION_VALUE = 0x22
|
|
1333
|
+
LE_SECURE_CONNECTIONS_RANDOM_VALUE = 0x23
|
|
1334
|
+
URI = 0x24
|
|
1335
|
+
INDOOR_POSITIONING = 0x25
|
|
1336
|
+
TRANSPORT_DISCOVERY_DATA = 0x26
|
|
1337
|
+
LE_SUPPORTED_FEATURES = 0x27
|
|
1338
|
+
CHANNEL_MAP_UPDATE_INDICATION = 0x28
|
|
1339
|
+
PB_ADV = 0x29
|
|
1340
|
+
MESH_MESSAGE = 0x2A
|
|
1341
|
+
MESH_BEACON = 0x2B
|
|
1342
|
+
BIGINFO = 0x2C
|
|
1343
|
+
BROADCAST_CODE = 0x2D
|
|
1344
|
+
RESOLVABLE_SET_IDENTIFIER = 0x2E
|
|
1345
|
+
ADVERTISING_INTERVAL_LONG = 0x2F
|
|
1346
|
+
BROADCAST_NAME = 0x30
|
|
1347
|
+
ENCRYPTED_ADVERTISING_DATA = 0X31
|
|
1348
|
+
PERIODIC_ADVERTISING_RESPONSE_TIMING_INFORMATION = 0X32
|
|
1349
|
+
ELECTRONIC_SHELF_LABEL = 0X34
|
|
1350
|
+
THREE_D_INFORMATION_DATA = 0x3D
|
|
1351
|
+
MANUFACTURER_SPECIFIC_DATA = 0xFF
|
|
758
1352
|
|
|
759
1353
|
AD_TYPE_NAMES = {
|
|
760
|
-
FLAGS:
|
|
761
|
-
INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS:
|
|
762
|
-
COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS:
|
|
763
|
-
INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS:
|
|
764
|
-
COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS:
|
|
765
|
-
INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS:
|
|
766
|
-
COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS:
|
|
767
|
-
SHORTENED_LOCAL_NAME:
|
|
768
|
-
COMPLETE_LOCAL_NAME:
|
|
769
|
-
TX_POWER_LEVEL:
|
|
770
|
-
CLASS_OF_DEVICE:
|
|
771
|
-
SIMPLE_PAIRING_HASH_C:
|
|
772
|
-
SIMPLE_PAIRING_HASH_C_192:
|
|
773
|
-
SIMPLE_PAIRING_RANDOMIZER_R:
|
|
774
|
-
SIMPLE_PAIRING_RANDOMIZER_R_192:
|
|
775
|
-
DEVICE_ID:
|
|
776
|
-
SECURITY_MANAGER_TK_VALUE:
|
|
777
|
-
SECURITY_MANAGER_OUT_OF_BAND_FLAGS:
|
|
778
|
-
PERIPHERAL_CONNECTION_INTERVAL_RANGE:
|
|
779
|
-
LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS:
|
|
780
|
-
LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS:
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
1354
|
+
FLAGS: 'FLAGS',
|
|
1355
|
+
INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS: 'INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS',
|
|
1356
|
+
COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS: 'COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS',
|
|
1357
|
+
INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS: 'INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS',
|
|
1358
|
+
COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS: 'COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS',
|
|
1359
|
+
INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS: 'INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS',
|
|
1360
|
+
COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS: 'COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS',
|
|
1361
|
+
SHORTENED_LOCAL_NAME: 'SHORTENED_LOCAL_NAME',
|
|
1362
|
+
COMPLETE_LOCAL_NAME: 'COMPLETE_LOCAL_NAME',
|
|
1363
|
+
TX_POWER_LEVEL: 'TX_POWER_LEVEL',
|
|
1364
|
+
CLASS_OF_DEVICE: 'CLASS_OF_DEVICE',
|
|
1365
|
+
SIMPLE_PAIRING_HASH_C: 'SIMPLE_PAIRING_HASH_C',
|
|
1366
|
+
SIMPLE_PAIRING_HASH_C_192: 'SIMPLE_PAIRING_HASH_C_192',
|
|
1367
|
+
SIMPLE_PAIRING_RANDOMIZER_R: 'SIMPLE_PAIRING_RANDOMIZER_R',
|
|
1368
|
+
SIMPLE_PAIRING_RANDOMIZER_R_192: 'SIMPLE_PAIRING_RANDOMIZER_R_192',
|
|
1369
|
+
DEVICE_ID: 'DEVICE_ID',
|
|
1370
|
+
SECURITY_MANAGER_TK_VALUE: 'SECURITY_MANAGER_TK_VALUE',
|
|
1371
|
+
SECURITY_MANAGER_OUT_OF_BAND_FLAGS: 'SECURITY_MANAGER_OUT_OF_BAND_FLAGS',
|
|
1372
|
+
PERIPHERAL_CONNECTION_INTERVAL_RANGE: 'PERIPHERAL_CONNECTION_INTERVAL_RANGE',
|
|
1373
|
+
LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS: 'LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS',
|
|
1374
|
+
LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS: 'LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS',
|
|
1375
|
+
SERVICE_DATA_16_BIT_UUID: 'SERVICE_DATA_16_BIT_UUID',
|
|
1376
|
+
PUBLIC_TARGET_ADDRESS: 'PUBLIC_TARGET_ADDRESS',
|
|
1377
|
+
RANDOM_TARGET_ADDRESS: 'RANDOM_TARGET_ADDRESS',
|
|
1378
|
+
APPEARANCE: 'APPEARANCE',
|
|
1379
|
+
ADVERTISING_INTERVAL: 'ADVERTISING_INTERVAL',
|
|
1380
|
+
LE_BLUETOOTH_DEVICE_ADDRESS: 'LE_BLUETOOTH_DEVICE_ADDRESS',
|
|
1381
|
+
LE_ROLE: 'LE_ROLE',
|
|
1382
|
+
SIMPLE_PAIRING_HASH_C_256: 'SIMPLE_PAIRING_HASH_C_256',
|
|
1383
|
+
SIMPLE_PAIRING_RANDOMIZER_R_256: 'SIMPLE_PAIRING_RANDOMIZER_R_256',
|
|
1384
|
+
LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS: 'LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS',
|
|
1385
|
+
SERVICE_DATA_32_BIT_UUID: 'SERVICE_DATA_32_BIT_UUID',
|
|
1386
|
+
SERVICE_DATA_128_BIT_UUID: 'SERVICE_DATA_128_BIT_UUID',
|
|
1387
|
+
LE_SECURE_CONNECTIONS_CONFIRMATION_VALUE: 'LE_SECURE_CONNECTIONS_CONFIRMATION_VALUE',
|
|
1388
|
+
LE_SECURE_CONNECTIONS_RANDOM_VALUE: 'LE_SECURE_CONNECTIONS_RANDOM_VALUE',
|
|
1389
|
+
URI: 'URI',
|
|
1390
|
+
INDOOR_POSITIONING: 'INDOOR_POSITIONING',
|
|
1391
|
+
TRANSPORT_DISCOVERY_DATA: 'TRANSPORT_DISCOVERY_DATA',
|
|
1392
|
+
LE_SUPPORTED_FEATURES: 'LE_SUPPORTED_FEATURES',
|
|
1393
|
+
CHANNEL_MAP_UPDATE_INDICATION: 'CHANNEL_MAP_UPDATE_INDICATION',
|
|
1394
|
+
PB_ADV: 'PB_ADV',
|
|
1395
|
+
MESH_MESSAGE: 'MESH_MESSAGE',
|
|
1396
|
+
MESH_BEACON: 'MESH_BEACON',
|
|
1397
|
+
BIGINFO: 'BIGINFO',
|
|
1398
|
+
BROADCAST_CODE: 'BROADCAST_CODE',
|
|
1399
|
+
RESOLVABLE_SET_IDENTIFIER: 'RESOLVABLE_SET_IDENTIFIER',
|
|
1400
|
+
ADVERTISING_INTERVAL_LONG: 'ADVERTISING_INTERVAL_LONG',
|
|
1401
|
+
BROADCAST_NAME: 'BROADCAST_NAME',
|
|
1402
|
+
ENCRYPTED_ADVERTISING_DATA: 'ENCRYPTED_ADVERTISING_DATA',
|
|
1403
|
+
PERIODIC_ADVERTISING_RESPONSE_TIMING_INFORMATION: 'PERIODIC_ADVERTISING_RESPONSE_TIMING_INFORMATION',
|
|
1404
|
+
ELECTRONIC_SHELF_LABEL: 'ELECTRONIC_SHELF_LABEL',
|
|
1405
|
+
THREE_D_INFORMATION_DATA: 'THREE_D_INFORMATION_DATA',
|
|
1406
|
+
MANUFACTURER_SPECIFIC_DATA: 'MANUFACTURER_SPECIFIC_DATA'
|
|
810
1407
|
}
|
|
811
1408
|
|
|
812
1409
|
LE_LIMITED_DISCOVERABLE_MODE_FLAG = 0x01
|
|
@@ -915,7 +1512,11 @@ class AdvertisingData:
|
|
|
915
1512
|
ad_data_str = f'company={company_name}, data={ad_data[2:].hex()}'
|
|
916
1513
|
elif ad_type == AdvertisingData.APPEARANCE:
|
|
917
1514
|
ad_type_str = 'Appearance'
|
|
918
|
-
|
|
1515
|
+
appearance = Appearance.from_int(struct.unpack_from('<H', ad_data, 0)[0])
|
|
1516
|
+
ad_data_str = str(appearance)
|
|
1517
|
+
elif ad_type == AdvertisingData.BROADCAST_NAME:
|
|
1518
|
+
ad_type_str = 'Broadcast Name'
|
|
1519
|
+
ad_data_str = ad_data.decode('utf-8')
|
|
919
1520
|
else:
|
|
920
1521
|
ad_type_str = AdvertisingData.AD_TYPE_NAMES.get(ad_type, f'0x{ad_type:02X}')
|
|
921
1522
|
ad_data_str = ad_data.hex()
|
|
@@ -924,7 +1525,7 @@ class AdvertisingData:
|
|
|
924
1525
|
|
|
925
1526
|
# pylint: disable=too-many-return-statements
|
|
926
1527
|
@staticmethod
|
|
927
|
-
def ad_data_to_object(ad_type: int, ad_data: bytes) ->
|
|
1528
|
+
def ad_data_to_object(ad_type: int, ad_data: bytes) -> AdvertisingDataObject:
|
|
928
1529
|
if ad_type in (
|
|
929
1530
|
AdvertisingData.COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS,
|
|
930
1531
|
AdvertisingData.INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS,
|
|
@@ -959,16 +1560,14 @@ class AdvertisingData:
|
|
|
959
1560
|
AdvertisingData.SHORTENED_LOCAL_NAME,
|
|
960
1561
|
AdvertisingData.COMPLETE_LOCAL_NAME,
|
|
961
1562
|
AdvertisingData.URI,
|
|
1563
|
+
AdvertisingData.BROADCAST_NAME,
|
|
962
1564
|
):
|
|
963
1565
|
return ad_data.decode("utf-8")
|
|
964
1566
|
|
|
965
1567
|
if ad_type in (AdvertisingData.TX_POWER_LEVEL, AdvertisingData.FLAGS):
|
|
966
1568
|
return cast(int, struct.unpack('B', ad_data)[0])
|
|
967
1569
|
|
|
968
|
-
if ad_type in (
|
|
969
|
-
AdvertisingData.APPEARANCE,
|
|
970
|
-
AdvertisingData.ADVERTISING_INTERVAL,
|
|
971
|
-
):
|
|
1570
|
+
if ad_type in (AdvertisingData.ADVERTISING_INTERVAL,):
|
|
972
1571
|
return cast(int, struct.unpack('<H', ad_data)[0])
|
|
973
1572
|
|
|
974
1573
|
if ad_type == AdvertisingData.CLASS_OF_DEVICE:
|
|
@@ -980,6 +1579,11 @@ class AdvertisingData:
|
|
|
980
1579
|
if ad_type == AdvertisingData.MANUFACTURER_SPECIFIC_DATA:
|
|
981
1580
|
return (cast(int, struct.unpack_from('<H', ad_data, 0)[0]), ad_data[2:])
|
|
982
1581
|
|
|
1582
|
+
if ad_type == AdvertisingData.APPEARANCE:
|
|
1583
|
+
return Appearance.from_int(
|
|
1584
|
+
cast(int, struct.unpack_from('<H', ad_data, 0)[0])
|
|
1585
|
+
)
|
|
1586
|
+
|
|
983
1587
|
return ad_data
|
|
984
1588
|
|
|
985
1589
|
def append(self, data: bytes) -> None:
|
|
@@ -993,27 +1597,27 @@ class AdvertisingData:
|
|
|
993
1597
|
self.ad_structures.append((ad_type, ad_data))
|
|
994
1598
|
offset += length
|
|
995
1599
|
|
|
996
|
-
def get_all(self, type_id: int, raw: bool = False) -> List[
|
|
1600
|
+
def get_all(self, type_id: int, raw: bool = False) -> List[AdvertisingDataObject]:
|
|
997
1601
|
'''
|
|
998
1602
|
Get Advertising Data Structure(s) with a given type
|
|
999
1603
|
|
|
1000
1604
|
Returns a (possibly empty) list of matches.
|
|
1001
1605
|
'''
|
|
1002
1606
|
|
|
1003
|
-
def process_ad_data(ad_data: bytes) ->
|
|
1607
|
+
def process_ad_data(ad_data: bytes) -> AdvertisingDataObject:
|
|
1004
1608
|
return ad_data if raw else self.ad_data_to_object(type_id, ad_data)
|
|
1005
1609
|
|
|
1006
1610
|
return [process_ad_data(ad[1]) for ad in self.ad_structures if ad[0] == type_id]
|
|
1007
1611
|
|
|
1008
|
-
def get(self, type_id: int, raw: bool = False) -> Optional[
|
|
1612
|
+
def get(self, type_id: int, raw: bool = False) -> Optional[AdvertisingDataObject]:
|
|
1009
1613
|
'''
|
|
1010
1614
|
Get Advertising Data Structure(s) with a given type
|
|
1011
1615
|
|
|
1012
1616
|
Returns the first entry, or None if no structure matches.
|
|
1013
1617
|
'''
|
|
1014
1618
|
|
|
1015
|
-
|
|
1016
|
-
return
|
|
1619
|
+
all_objects = self.get_all(type_id, raw=raw)
|
|
1620
|
+
return all_objects[0] if all_objects else None
|
|
1017
1621
|
|
|
1018
1622
|
def __bytes__(self):
|
|
1019
1623
|
return b''.join(
|