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.
Files changed (54) hide show
  1. bumble/_version.py +2 -2
  2. bumble/apps/auracast.py +692 -0
  3. bumble/apps/bench.py +77 -23
  4. bumble/apps/console.py +5 -20
  5. bumble/apps/controller_info.py +3 -3
  6. bumble/apps/device_info.py +230 -0
  7. bumble/apps/gatt_dump.py +4 -0
  8. bumble/apps/lea_unicast/app.py +16 -17
  9. bumble/at.py +12 -6
  10. bumble/avc.py +8 -5
  11. bumble/avctp.py +3 -2
  12. bumble/avdtp.py +5 -1
  13. bumble/avrcp.py +2 -1
  14. bumble/codecs.py +17 -13
  15. bumble/colors.py +6 -2
  16. bumble/core.py +726 -122
  17. bumble/device.py +817 -117
  18. bumble/drivers/rtk.py +13 -8
  19. bumble/gatt.py +6 -1
  20. bumble/gatt_client.py +10 -4
  21. bumble/hci.py +283 -20
  22. bumble/hid.py +24 -28
  23. bumble/host.py +29 -0
  24. bumble/l2cap.py +24 -17
  25. bumble/link.py +8 -3
  26. bumble/pandora/host.py +3 -2
  27. bumble/profiles/ascs.py +739 -0
  28. bumble/profiles/bap.py +85 -862
  29. bumble/profiles/bass.py +440 -0
  30. bumble/profiles/csip.py +4 -4
  31. bumble/profiles/gap.py +110 -0
  32. bumble/profiles/heart_rate_service.py +4 -3
  33. bumble/profiles/le_audio.py +83 -0
  34. bumble/profiles/mcp.py +448 -0
  35. bumble/profiles/pacs.py +210 -0
  36. bumble/profiles/pbp.py +46 -0
  37. bumble/profiles/tmap.py +89 -0
  38. bumble/rfcomm.py +14 -3
  39. bumble/sdp.py +13 -11
  40. bumble/smp.py +20 -8
  41. bumble/snoop.py +5 -4
  42. bumble/transport/__init__.py +8 -2
  43. bumble/transport/android_emulator.py +9 -3
  44. bumble/transport/android_netsim.py +9 -7
  45. bumble/transport/common.py +46 -18
  46. bumble/transport/pyusb.py +2 -2
  47. bumble/transport/unix.py +56 -0
  48. bumble/transport/usb.py +57 -46
  49. {bumble-0.0.194.dist-info → bumble-0.0.198.dist-info}/METADATA +41 -41
  50. {bumble-0.0.194.dist-info → bumble-0.0.198.dist-info}/RECORD +54 -43
  51. {bumble-0.0.194.dist-info → bumble-0.0.198.dist-info}/WHEEL +1 -1
  52. {bumble-0.0.194.dist-info → bumble-0.0.198.dist-info}/LICENSE +0 -0
  53. {bumble-0.0.194.dist-info → bumble-0.0.198.dist-info}/entry_points.txt +0 -0
  54. {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
- class BaseError(Exception):
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(Exception): # pylint: disable=redefined-builtin
127
+ class TimeoutError(BaseBumbleError): # pylint: disable=redefined-builtin
119
128
  """Timeout Error"""
120
129
 
121
130
 
122
- class CommandTimeoutError(Exception):
131
+ class CommandTimeoutError(BaseBumbleError):
123
132
  """Command Timeout Error"""
124
133
 
125
134
 
126
- class InvalidStateError(Exception):
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 ValueError('invalid UUID format')
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 ValueError(f"invalid UUID format: {uuid_str}")
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 ValueError('only 2, 4 and 16 bytes are allowed')
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
- AdvertisingObject = Union[
699
- List[UUID], Tuple[UUID, bytes], bytes, str, int, Tuple[int, int], Tuple[int, bytes]
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
- # This list is only partial, it still needs to be filled in from the spec
708
- FLAGS = 0x01
709
- INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS = 0x02
710
- COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS = 0x03
711
- INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS = 0x04
712
- COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS = 0x05
713
- INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS = 0x06
714
- COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS = 0x07
715
- SHORTENED_LOCAL_NAME = 0x08
716
- COMPLETE_LOCAL_NAME = 0x09
717
- TX_POWER_LEVEL = 0x0A
718
- CLASS_OF_DEVICE = 0x0D
719
- SIMPLE_PAIRING_HASH_C = 0x0E
720
- SIMPLE_PAIRING_HASH_C_192 = 0x0E
721
- SIMPLE_PAIRING_RANDOMIZER_R = 0x0F
722
- SIMPLE_PAIRING_RANDOMIZER_R_192 = 0x0F
723
- DEVICE_ID = 0x10
724
- SECURITY_MANAGER_TK_VALUE = 0x10
725
- SECURITY_MANAGER_OUT_OF_BAND_FLAGS = 0x11
726
- PERIPHERAL_CONNECTION_INTERVAL_RANGE = 0x12
727
- LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS = 0x14
728
- LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS = 0x15
729
- SERVICE_DATA = 0x16
730
- SERVICE_DATA_16_BIT_UUID = 0x16
731
- PUBLIC_TARGET_ADDRESS = 0x17
732
- RANDOM_TARGET_ADDRESS = 0x18
733
- APPEARANCE = 0x19
734
- ADVERTISING_INTERVAL = 0x1A
735
- LE_BLUETOOTH_DEVICE_ADDRESS = 0x1B
736
- LE_ROLE = 0x1C
737
- SIMPLE_PAIRING_HASH_C_256 = 0x1D
738
- SIMPLE_PAIRING_RANDOMIZER_R_256 = 0x1E
739
- LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS = 0x1F
740
- SERVICE_DATA_32_BIT_UUID = 0x20
741
- SERVICE_DATA_128_BIT_UUID = 0x21
742
- LE_SECURE_CONNECTIONS_CONFIRMATION_VALUE = 0x22
743
- LE_SECURE_CONNECTIONS_RANDOM_VALUE = 0x23
744
- URI = 0x24
745
- INDOOR_POSITIONING = 0x25
746
- TRANSPORT_DISCOVERY_DATA = 0x26
747
- LE_SUPPORTED_FEATURES = 0x27
748
- CHANNEL_MAP_UPDATE_INDICATION = 0x28
749
- PB_ADV = 0x29
750
- MESH_MESSAGE = 0x2A
751
- MESH_BEACON = 0x2B
752
- BIGINFO = 0x2C
753
- BROADCAST_CODE = 0x2D
754
- RESOLVABLE_SET_IDENTIFIER = 0x2E
755
- ADVERTISING_INTERVAL_LONG = 0x2F
756
- THREE_D_INFORMATION_DATA = 0x3D
757
- MANUFACTURER_SPECIFIC_DATA = 0xFF
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: 'FLAGS',
761
- INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS: 'INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS',
762
- COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS: 'COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS',
763
- INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS: 'INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS',
764
- COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS: 'COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS',
765
- INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS: 'INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS',
766
- COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS: 'COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS',
767
- SHORTENED_LOCAL_NAME: 'SHORTENED_LOCAL_NAME',
768
- COMPLETE_LOCAL_NAME: 'COMPLETE_LOCAL_NAME',
769
- TX_POWER_LEVEL: 'TX_POWER_LEVEL',
770
- CLASS_OF_DEVICE: 'CLASS_OF_DEVICE',
771
- SIMPLE_PAIRING_HASH_C: 'SIMPLE_PAIRING_HASH_C',
772
- SIMPLE_PAIRING_HASH_C_192: 'SIMPLE_PAIRING_HASH_C_192',
773
- SIMPLE_PAIRING_RANDOMIZER_R: 'SIMPLE_PAIRING_RANDOMIZER_R',
774
- SIMPLE_PAIRING_RANDOMIZER_R_192: 'SIMPLE_PAIRING_RANDOMIZER_R_192',
775
- DEVICE_ID: 'DEVICE_ID',
776
- SECURITY_MANAGER_TK_VALUE: 'SECURITY_MANAGER_TK_VALUE',
777
- SECURITY_MANAGER_OUT_OF_BAND_FLAGS: 'SECURITY_MANAGER_OUT_OF_BAND_FLAGS',
778
- PERIPHERAL_CONNECTION_INTERVAL_RANGE: 'PERIPHERAL_CONNECTION_INTERVAL_RANGE',
779
- LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS: 'LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS',
780
- LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS: 'LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS',
781
- SERVICE_DATA: 'SERVICE_DATA',
782
- SERVICE_DATA_16_BIT_UUID: 'SERVICE_DATA_16_BIT_UUID',
783
- PUBLIC_TARGET_ADDRESS: 'PUBLIC_TARGET_ADDRESS',
784
- RANDOM_TARGET_ADDRESS: 'RANDOM_TARGET_ADDRESS',
785
- APPEARANCE: 'APPEARANCE',
786
- ADVERTISING_INTERVAL: 'ADVERTISING_INTERVAL',
787
- LE_BLUETOOTH_DEVICE_ADDRESS: 'LE_BLUETOOTH_DEVICE_ADDRESS',
788
- LE_ROLE: 'LE_ROLE',
789
- SIMPLE_PAIRING_HASH_C_256: 'SIMPLE_PAIRING_HASH_C_256',
790
- SIMPLE_PAIRING_RANDOMIZER_R_256: 'SIMPLE_PAIRING_RANDOMIZER_R_256',
791
- LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS: 'LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS',
792
- SERVICE_DATA_32_BIT_UUID: 'SERVICE_DATA_32_BIT_UUID',
793
- SERVICE_DATA_128_BIT_UUID: 'SERVICE_DATA_128_BIT_UUID',
794
- LE_SECURE_CONNECTIONS_CONFIRMATION_VALUE: 'LE_SECURE_CONNECTIONS_CONFIRMATION_VALUE',
795
- LE_SECURE_CONNECTIONS_RANDOM_VALUE: 'LE_SECURE_CONNECTIONS_RANDOM_VALUE',
796
- URI: 'URI',
797
- INDOOR_POSITIONING: 'INDOOR_POSITIONING',
798
- TRANSPORT_DISCOVERY_DATA: 'TRANSPORT_DISCOVERY_DATA',
799
- LE_SUPPORTED_FEATURES: 'LE_SUPPORTED_FEATURES',
800
- CHANNEL_MAP_UPDATE_INDICATION: 'CHANNEL_MAP_UPDATE_INDICATION',
801
- PB_ADV: 'PB_ADV',
802
- MESH_MESSAGE: 'MESH_MESSAGE',
803
- MESH_BEACON: 'MESH_BEACON',
804
- BIGINFO: 'BIGINFO',
805
- BROADCAST_CODE: 'BROADCAST_CODE',
806
- RESOLVABLE_SET_IDENTIFIER: 'RESOLVABLE_SET_IDENTIFIER',
807
- ADVERTISING_INTERVAL_LONG: 'ADVERTISING_INTERVAL_LONG',
808
- THREE_D_INFORMATION_DATA: 'THREE_D_INFORMATION_DATA',
809
- MANUFACTURER_SPECIFIC_DATA: 'MANUFACTURER_SPECIFIC_DATA'
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
- ad_data_str = ad_data.hex()
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) -> AdvertisingObject:
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[AdvertisingObject]:
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) -> AdvertisingObject:
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[AdvertisingObject]:
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
- all = self.get_all(type_id, raw=raw)
1016
- return all[0] if all else None
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(