bumble 0.0.154__py3-none-any.whl → 0.0.156__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/rfcomm.py CHANGED
@@ -19,8 +19,9 @@ import logging
19
19
  import asyncio
20
20
 
21
21
  from pyee import EventEmitter
22
+ from typing import Optional, Tuple, Callable, Dict, Union
22
23
 
23
- from . import core
24
+ from . import core, l2cap
24
25
  from .colors import color
25
26
  from .core import BT_BR_EDR_TRANSPORT, InvalidStateError, ProtocolError
26
27
 
@@ -105,7 +106,7 @@ RFCOMM_DYNAMIC_CHANNEL_NUMBER_END = 30
105
106
 
106
107
 
107
108
  # -----------------------------------------------------------------------------
108
- def compute_fcs(buffer):
109
+ def compute_fcs(buffer: bytes) -> int:
109
110
  result = 0xFF
110
111
  for byte in buffer:
111
112
  result = CRC_TABLE[result ^ byte]
@@ -114,7 +115,15 @@ def compute_fcs(buffer):
114
115
 
115
116
  # -----------------------------------------------------------------------------
116
117
  class RFCOMM_Frame:
117
- def __init__(self, frame_type, c_r, dlci, p_f, information=b'', with_credits=False):
118
+ def __init__(
119
+ self,
120
+ frame_type: int,
121
+ c_r: int,
122
+ dlci: int,
123
+ p_f: int,
124
+ information: bytes = b'',
125
+ with_credits: bool = False,
126
+ ) -> None:
118
127
  self.type = frame_type
119
128
  self.c_r = c_r
120
129
  self.dlci = dlci
@@ -136,11 +145,11 @@ class RFCOMM_Frame:
136
145
  else:
137
146
  self.fcs = compute_fcs(bytes([self.address, self.control]) + self.length)
138
147
 
139
- def type_name(self):
148
+ def type_name(self) -> str:
140
149
  return RFCOMM_FRAME_TYPE_NAMES[self.type]
141
150
 
142
151
  @staticmethod
143
- def parse_mcc(data):
152
+ def parse_mcc(data) -> Tuple[int, int, bytes]:
144
153
  mcc_type = data[0] >> 2
145
154
  c_r = (data[0] >> 1) & 1
146
155
  length = data[1]
@@ -154,36 +163,36 @@ class RFCOMM_Frame:
154
163
  return (mcc_type, c_r, value)
155
164
 
156
165
  @staticmethod
157
- def make_mcc(mcc_type, c_r, data):
166
+ def make_mcc(mcc_type: int, c_r: int, data: bytes) -> bytes:
158
167
  return (
159
168
  bytes([(mcc_type << 2 | c_r << 1 | 1) & 0xFF, (len(data) & 0x7F) << 1 | 1])
160
169
  + data
161
170
  )
162
171
 
163
172
  @staticmethod
164
- def sabm(c_r, dlci):
173
+ def sabm(c_r: int, dlci: int):
165
174
  return RFCOMM_Frame(RFCOMM_SABM_FRAME, c_r, dlci, 1)
166
175
 
167
176
  @staticmethod
168
- def ua(c_r, dlci):
177
+ def ua(c_r: int, dlci: int):
169
178
  return RFCOMM_Frame(RFCOMM_UA_FRAME, c_r, dlci, 1)
170
179
 
171
180
  @staticmethod
172
- def dm(c_r, dlci):
181
+ def dm(c_r: int, dlci: int):
173
182
  return RFCOMM_Frame(RFCOMM_DM_FRAME, c_r, dlci, 1)
174
183
 
175
184
  @staticmethod
176
- def disc(c_r, dlci):
185
+ def disc(c_r: int, dlci: int):
177
186
  return RFCOMM_Frame(RFCOMM_DISC_FRAME, c_r, dlci, 1)
178
187
 
179
188
  @staticmethod
180
- def uih(c_r, dlci, information, p_f=0):
189
+ def uih(c_r: int, dlci: int, information: bytes, p_f: int = 0):
181
190
  return RFCOMM_Frame(
182
191
  RFCOMM_UIH_FRAME, c_r, dlci, p_f, information, with_credits=(p_f == 1)
183
192
  )
184
193
 
185
194
  @staticmethod
186
- def from_bytes(data):
195
+ def from_bytes(data: bytes):
187
196
  # Extract fields
188
197
  dlci = (data[0] >> 2) & 0x3F
189
198
  c_r = (data[0] >> 1) & 0x01
@@ -227,15 +236,23 @@ class RFCOMM_Frame:
227
236
 
228
237
  # -----------------------------------------------------------------------------
229
238
  class RFCOMM_MCC_PN:
239
+ dlci: int
240
+ cl: int
241
+ priority: int
242
+ ack_timer: int
243
+ max_frame_size: int
244
+ max_retransmissions: int
245
+ window_size: int
246
+
230
247
  def __init__(
231
248
  self,
232
- dlci,
233
- cl,
234
- priority,
235
- ack_timer,
236
- max_frame_size,
237
- max_retransmissions,
238
- window_size,
249
+ dlci: int,
250
+ cl: int,
251
+ priority: int,
252
+ ack_timer: int,
253
+ max_frame_size: int,
254
+ max_retransmissions: int,
255
+ window_size: int,
239
256
  ):
240
257
  self.dlci = dlci
241
258
  self.cl = cl
@@ -246,7 +263,7 @@ class RFCOMM_MCC_PN:
246
263
  self.window_size = window_size
247
264
 
248
265
  @staticmethod
249
- def from_bytes(data):
266
+ def from_bytes(data: bytes):
250
267
  return RFCOMM_MCC_PN(
251
268
  dlci=data[0],
252
269
  cl=data[1],
@@ -285,7 +302,14 @@ class RFCOMM_MCC_PN:
285
302
 
286
303
  # -----------------------------------------------------------------------------
287
304
  class RFCOMM_MCC_MSC:
288
- def __init__(self, dlci, fc, rtc, rtr, ic, dv):
305
+ dlci: int
306
+ fc: int
307
+ rtc: int
308
+ rtr: int
309
+ ic: int
310
+ dv: int
311
+
312
+ def __init__(self, dlci: int, fc: int, rtc: int, rtr: int, ic: int, dv: int):
289
313
  self.dlci = dlci
290
314
  self.fc = fc
291
315
  self.rtc = rtc
@@ -294,7 +318,7 @@ class RFCOMM_MCC_MSC:
294
318
  self.dv = dv
295
319
 
296
320
  @staticmethod
297
- def from_bytes(data):
321
+ def from_bytes(data: bytes):
298
322
  return RFCOMM_MCC_MSC(
299
323
  dlci=data[0] >> 2,
300
324
  fc=data[1] >> 1 & 1,
@@ -347,7 +371,12 @@ class DLC(EventEmitter):
347
371
  RESET: 'RESET',
348
372
  }
349
373
 
350
- def __init__(self, multiplexer, dlci, max_frame_size, initial_tx_credits):
374
+ connection_result: Optional[asyncio.Future]
375
+ sink: Optional[Callable[[bytes], None]]
376
+
377
+ def __init__(
378
+ self, multiplexer, dlci: int, max_frame_size: int, initial_tx_credits: int
379
+ ):
351
380
  super().__init__()
352
381
  self.multiplexer = multiplexer
353
382
  self.dlci = dlci
@@ -368,23 +397,23 @@ class DLC(EventEmitter):
368
397
  )
369
398
 
370
399
  @staticmethod
371
- def state_name(state):
400
+ def state_name(state: int) -> str:
372
401
  return DLC.STATE_NAMES[state]
373
402
 
374
- def change_state(self, new_state):
403
+ def change_state(self, new_state: int) -> None:
375
404
  logger.debug(
376
405
  f'{self} state change -> {color(self.state_name(new_state), "magenta")}'
377
406
  )
378
407
  self.state = new_state
379
408
 
380
- def send_frame(self, frame):
409
+ def send_frame(self, frame: RFCOMM_Frame) -> None:
381
410
  self.multiplexer.send_frame(frame)
382
411
 
383
- def on_frame(self, frame):
412
+ def on_frame(self, frame: RFCOMM_Frame) -> None:
384
413
  handler = getattr(self, f'on_{frame.type_name()}_frame'.lower())
385
414
  handler(frame)
386
415
 
387
- def on_sabm_frame(self, _frame):
416
+ def on_sabm_frame(self, _frame) -> None:
388
417
  if self.state != DLC.CONNECTING:
389
418
  logger.warning(
390
419
  color('!!! received SABM when not in CONNECTING state', 'red')
@@ -404,7 +433,7 @@ class DLC(EventEmitter):
404
433
  self.change_state(DLC.CONNECTED)
405
434
  self.emit('open')
406
435
 
407
- def on_ua_frame(self, _frame):
436
+ def on_ua_frame(self, _frame) -> None:
408
437
  if self.state != DLC.CONNECTING:
409
438
  logger.warning(
410
439
  color('!!! received SABM when not in CONNECTING state', 'red')
@@ -422,15 +451,15 @@ class DLC(EventEmitter):
422
451
  self.change_state(DLC.CONNECTED)
423
452
  self.multiplexer.on_dlc_open_complete(self)
424
453
 
425
- def on_dm_frame(self, frame):
454
+ def on_dm_frame(self, frame) -> None:
426
455
  # TODO: handle all states
427
456
  pass
428
457
 
429
- def on_disc_frame(self, _frame):
458
+ def on_disc_frame(self, _frame) -> None:
430
459
  # TODO: handle all states
431
460
  self.send_frame(RFCOMM_Frame.ua(c_r=1 - self.c_r, dlci=self.dlci))
432
461
 
433
- def on_uih_frame(self, frame):
462
+ def on_uih_frame(self, frame: RFCOMM_Frame) -> None:
434
463
  data = frame.information
435
464
  if frame.p_f == 1:
436
465
  # With credits
@@ -460,10 +489,10 @@ class DLC(EventEmitter):
460
489
  # Check if there's anything to send (including credits)
461
490
  self.process_tx()
462
491
 
463
- def on_ui_frame(self, frame):
492
+ def on_ui_frame(self, frame) -> None:
464
493
  pass
465
494
 
466
- def on_mcc_msc(self, c_r, msc):
495
+ def on_mcc_msc(self, c_r, msc) -> None:
467
496
  if c_r:
468
497
  # Command
469
498
  logger.debug(f'<<< MCC MSC Command: {msc}')
@@ -477,7 +506,7 @@ class DLC(EventEmitter):
477
506
  # Response
478
507
  logger.debug(f'<<< MCC MSC Response: {msc}')
479
508
 
480
- def connect(self):
509
+ def connect(self) -> None:
481
510
  if self.state != DLC.INIT:
482
511
  raise InvalidStateError('invalid state')
483
512
 
@@ -485,7 +514,7 @@ class DLC(EventEmitter):
485
514
  self.connection_result = asyncio.get_running_loop().create_future()
486
515
  self.send_frame(RFCOMM_Frame.sabm(c_r=self.c_r, dlci=self.dlci))
487
516
 
488
- def accept(self):
517
+ def accept(self) -> None:
489
518
  if self.state != DLC.INIT:
490
519
  raise InvalidStateError('invalid state')
491
520
 
@@ -503,13 +532,13 @@ class DLC(EventEmitter):
503
532
  self.send_frame(RFCOMM_Frame.uih(c_r=self.c_r, dlci=0, information=mcc))
504
533
  self.change_state(DLC.CONNECTING)
505
534
 
506
- def rx_credits_needed(self):
535
+ def rx_credits_needed(self) -> int:
507
536
  if self.rx_credits <= self.rx_threshold:
508
537
  return RFCOMM_DEFAULT_INITIAL_RX_CREDITS - self.rx_credits
509
538
 
510
539
  return 0
511
540
 
512
- def process_tx(self):
541
+ def process_tx(self) -> None:
513
542
  # Send anything we can (or an empty frame if we need to send rx credits)
514
543
  rx_credits_needed = self.rx_credits_needed()
515
544
  while (self.tx_buffer and self.tx_credits > 0) or rx_credits_needed > 0:
@@ -547,7 +576,7 @@ class DLC(EventEmitter):
547
576
  rx_credits_needed = 0
548
577
 
549
578
  # Stream protocol
550
- def write(self, data):
579
+ def write(self, data: Union[bytes, str]) -> None:
551
580
  # We can only send bytes
552
581
  if not isinstance(data, bytes):
553
582
  if isinstance(data, str):
@@ -559,7 +588,7 @@ class DLC(EventEmitter):
559
588
  self.tx_buffer += data
560
589
  self.process_tx()
561
590
 
562
- def drain(self):
591
+ def drain(self) -> None:
563
592
  # TODO
564
593
  pass
565
594
 
@@ -592,7 +621,13 @@ class Multiplexer(EventEmitter):
592
621
  RESET: 'RESET',
593
622
  }
594
623
 
595
- def __init__(self, l2cap_channel, role):
624
+ connection_result: Optional[asyncio.Future]
625
+ disconnection_result: Optional[asyncio.Future]
626
+ open_result: Optional[asyncio.Future]
627
+ acceptor: Optional[Callable[[int], bool]]
628
+ dlcs: Dict[int, DLC]
629
+
630
+ def __init__(self, l2cap_channel: l2cap.Channel, role: int) -> None:
596
631
  super().__init__()
597
632
  self.role = role
598
633
  self.l2cap_channel = l2cap_channel
@@ -607,20 +642,20 @@ class Multiplexer(EventEmitter):
607
642
  l2cap_channel.sink = self.on_pdu
608
643
 
609
644
  @staticmethod
610
- def state_name(state):
645
+ def state_name(state: int):
611
646
  return Multiplexer.STATE_NAMES[state]
612
647
 
613
- def change_state(self, new_state):
648
+ def change_state(self, new_state: int) -> None:
614
649
  logger.debug(
615
650
  f'{self} state change -> {color(self.state_name(new_state), "cyan")}'
616
651
  )
617
652
  self.state = new_state
618
653
 
619
- def send_frame(self, frame):
654
+ def send_frame(self, frame: RFCOMM_Frame) -> None:
620
655
  logger.debug(f'>>> Multiplexer sending {frame}')
621
656
  self.l2cap_channel.send_pdu(frame)
622
657
 
623
- def on_pdu(self, pdu):
658
+ def on_pdu(self, pdu: bytes) -> None:
624
659
  frame = RFCOMM_Frame.from_bytes(pdu)
625
660
  logger.debug(f'<<< Multiplexer received {frame}')
626
661
 
@@ -640,18 +675,18 @@ class Multiplexer(EventEmitter):
640
675
  return
641
676
  dlc.on_frame(frame)
642
677
 
643
- def on_frame(self, frame):
678
+ def on_frame(self, frame: RFCOMM_Frame) -> None:
644
679
  handler = getattr(self, f'on_{frame.type_name()}_frame'.lower())
645
680
  handler(frame)
646
681
 
647
- def on_sabm_frame(self, _frame):
682
+ def on_sabm_frame(self, _frame) -> None:
648
683
  if self.state != Multiplexer.INIT:
649
684
  logger.debug('not in INIT state, ignoring SABM')
650
685
  return
651
686
  self.change_state(Multiplexer.CONNECTED)
652
687
  self.send_frame(RFCOMM_Frame.ua(c_r=1, dlci=0))
653
688
 
654
- def on_ua_frame(self, _frame):
689
+ def on_ua_frame(self, _frame) -> None:
655
690
  if self.state == Multiplexer.CONNECTING:
656
691
  self.change_state(Multiplexer.CONNECTED)
657
692
  if self.connection_result:
@@ -663,7 +698,7 @@ class Multiplexer(EventEmitter):
663
698
  self.disconnection_result.set_result(None)
664
699
  self.disconnection_result = None
665
700
 
666
- def on_dm_frame(self, _frame):
701
+ def on_dm_frame(self, _frame) -> None:
667
702
  if self.state == Multiplexer.OPENING:
668
703
  self.change_state(Multiplexer.CONNECTED)
669
704
  if self.open_result:
@@ -678,13 +713,13 @@ class Multiplexer(EventEmitter):
678
713
  else:
679
714
  logger.warning(f'unexpected state for DM: {self}')
680
715
 
681
- def on_disc_frame(self, _frame):
716
+ def on_disc_frame(self, _frame) -> None:
682
717
  self.change_state(Multiplexer.DISCONNECTED)
683
718
  self.send_frame(
684
719
  RFCOMM_Frame.ua(c_r=0 if self.role == Multiplexer.INITIATOR else 1, dlci=0)
685
720
  )
686
721
 
687
- def on_uih_frame(self, frame):
722
+ def on_uih_frame(self, frame: RFCOMM_Frame) -> None:
688
723
  (mcc_type, c_r, value) = RFCOMM_Frame.parse_mcc(frame.information)
689
724
 
690
725
  if mcc_type == RFCOMM_MCC_PN_TYPE:
@@ -694,10 +729,10 @@ class Multiplexer(EventEmitter):
694
729
  mcs = RFCOMM_MCC_MSC.from_bytes(value)
695
730
  self.on_mcc_msc(c_r, mcs)
696
731
 
697
- def on_ui_frame(self, frame):
732
+ def on_ui_frame(self, frame) -> None:
698
733
  pass
699
734
 
700
- def on_mcc_pn(self, c_r, pn):
735
+ def on_mcc_pn(self, c_r, pn) -> None:
701
736
  if c_r == 1:
702
737
  # Command
703
738
  logger.debug(f'<<< PN Command: {pn}')
@@ -736,14 +771,14 @@ class Multiplexer(EventEmitter):
736
771
  else:
737
772
  logger.warning('ignoring PN response')
738
773
 
739
- def on_mcc_msc(self, c_r, msc):
774
+ def on_mcc_msc(self, c_r, msc) -> None:
740
775
  dlc = self.dlcs.get(msc.dlci)
741
776
  if dlc is None:
742
777
  logger.warning(f'no dlc for DLCI {msc.dlci}')
743
778
  return
744
779
  dlc.on_mcc_msc(c_r, msc)
745
780
 
746
- async def connect(self):
781
+ async def connect(self) -> None:
747
782
  if self.state != Multiplexer.INIT:
748
783
  raise InvalidStateError('invalid state')
749
784
 
@@ -752,7 +787,7 @@ class Multiplexer(EventEmitter):
752
787
  self.send_frame(RFCOMM_Frame.sabm(c_r=1, dlci=0))
753
788
  return await self.connection_result
754
789
 
755
- async def disconnect(self):
790
+ async def disconnect(self) -> None:
756
791
  if self.state != Multiplexer.CONNECTED:
757
792
  return
758
793
 
@@ -765,7 +800,7 @@ class Multiplexer(EventEmitter):
765
800
  )
766
801
  await self.disconnection_result
767
802
 
768
- async def open_dlc(self, channel):
803
+ async def open_dlc(self, channel: int) -> DLC:
769
804
  if self.state != Multiplexer.CONNECTED:
770
805
  if self.state == Multiplexer.OPENING:
771
806
  raise InvalidStateError('open already in progress')
@@ -796,7 +831,7 @@ class Multiplexer(EventEmitter):
796
831
  self.open_result = None
797
832
  return result
798
833
 
799
- def on_dlc_open_complete(self, dlc):
834
+ def on_dlc_open_complete(self, dlc: DLC):
800
835
  logger.debug(f'DLC [{dlc.dlci}] open complete')
801
836
  self.change_state(Multiplexer.CONNECTED)
802
837
  if self.open_result:
@@ -808,13 +843,16 @@ class Multiplexer(EventEmitter):
808
843
 
809
844
  # -----------------------------------------------------------------------------
810
845
  class Client:
811
- def __init__(self, device, connection):
846
+ multiplexer: Optional[Multiplexer]
847
+ l2cap_channel: Optional[l2cap.Channel]
848
+
849
+ def __init__(self, device, connection) -> None:
812
850
  self.device = device
813
851
  self.connection = connection
814
852
  self.l2cap_channel = None
815
853
  self.multiplexer = None
816
854
 
817
- async def start(self):
855
+ async def start(self) -> Multiplexer:
818
856
  # Create a new L2CAP connection
819
857
  try:
820
858
  self.l2cap_channel = await self.device.l2cap_channel_manager.connect(
@@ -824,6 +862,7 @@ class Client:
824
862
  logger.warning(f'L2CAP connection failed: {error}')
825
863
  raise
826
864
 
865
+ assert self.l2cap_channel is not None
827
866
  # Create a mutliplexer to manage DLCs with the server
828
867
  self.multiplexer = Multiplexer(self.l2cap_channel, Multiplexer.INITIATOR)
829
868
 
@@ -832,7 +871,9 @@ class Client:
832
871
 
833
872
  return self.multiplexer
834
873
 
835
- async def shutdown(self):
874
+ async def shutdown(self) -> None:
875
+ if self.multiplexer is None:
876
+ return
836
877
  # Disconnect the multiplexer
837
878
  await self.multiplexer.disconnect()
838
879
  self.multiplexer = None
@@ -843,7 +884,9 @@ class Client:
843
884
 
844
885
  # -----------------------------------------------------------------------------
845
886
  class Server(EventEmitter):
846
- def __init__(self, device):
887
+ acceptors: Dict[int, Callable[[DLC], None]]
888
+
889
+ def __init__(self, device) -> None:
847
890
  super().__init__()
848
891
  self.device = device
849
892
  self.multiplexer = None
@@ -852,7 +895,7 @@ class Server(EventEmitter):
852
895
  # Register ourselves with the L2CAP channel manager
853
896
  device.register_l2cap_server(RFCOMM_PSM, self.on_connection)
854
897
 
855
- def listen(self, acceptor, channel=0):
898
+ def listen(self, acceptor: Callable[[DLC], None], channel: int = 0) -> int:
856
899
  if channel:
857
900
  if channel in self.acceptors:
858
901
  # Busy
@@ -874,11 +917,11 @@ class Server(EventEmitter):
874
917
  self.acceptors[channel] = acceptor
875
918
  return channel
876
919
 
877
- def on_connection(self, l2cap_channel):
920
+ def on_connection(self, l2cap_channel: l2cap.Channel) -> None:
878
921
  logger.debug(f'+++ new L2CAP connection: {l2cap_channel}')
879
922
  l2cap_channel.on('open', lambda: self.on_l2cap_channel_open(l2cap_channel))
880
923
 
881
- def on_l2cap_channel_open(self, l2cap_channel):
924
+ def on_l2cap_channel_open(self, l2cap_channel: l2cap.Channel) -> None:
882
925
  logger.debug(f'$$$ L2CAP channel open: {l2cap_channel}')
883
926
 
884
927
  # Create a new multiplexer for the channel
@@ -889,10 +932,10 @@ class Server(EventEmitter):
889
932
  # Notify
890
933
  self.emit('start', multiplexer)
891
934
 
892
- def accept_dlc(self, channel_number):
935
+ def accept_dlc(self, channel_number: int) -> bool:
893
936
  return channel_number in self.acceptors
894
937
 
895
- def on_dlc(self, dlc):
938
+ def on_dlc(self, dlc: DLC) -> None:
896
939
  logger.debug(f'@@@ new DLC connected: {dlc}')
897
940
 
898
941
  # Let the acceptor know
bumble/smp.py CHANGED
@@ -1805,7 +1805,7 @@ class Manager(EventEmitter):
1805
1805
  self.device.abort_on('flush', store_keys())
1806
1806
 
1807
1807
  # Notify the device
1808
- self.device.on_pairing(session.connection, keys, session.sc)
1808
+ self.device.on_pairing(session.connection, identity_address, keys, session.sc)
1809
1809
 
1810
1810
  def on_pairing_failure(self, session: Session, reason: int) -> None:
1811
1811
  self.device.on_pairing_failure(session.connection, reason)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: bumble
3
- Version: 0.0.154
3
+ Version: 0.0.156
4
4
  Summary: Bluetooth Stack for Apps, Emulation, Test and Experimentation
5
5
  Home-page: https://github.com/google/bumble
6
6
  Author: Google
@@ -9,11 +9,12 @@ Requires-Python: >=3.8
9
9
  Description-Content-Type: text/markdown
10
10
  License-File: LICENSE
11
11
  Requires-Dist: appdirs (>=1.4)
12
+ Requires-Dist: bt-test-interfaces (>=0.0.2)
13
+ Requires-Dist: humanize (>=4.6.0)
14
+ Requires-Dist: prettytable (>=3.6.0)
12
15
  Requires-Dist: protobuf (>=3.12.4)
13
16
  Requires-Dist: pyee (>=8.2.2)
14
- Requires-Dist: prettytable (>=3.6.0)
15
- Requires-Dist: humanize (>=4.6.0)
16
- Requires-Dist: bt-test-interfaces (>=0.0.2)
17
+ Requires-Dist: aiohttp (>=3.8.4) ; platform_system != "Emscripten"
17
18
  Requires-Dist: click (>=7.1.2) ; platform_system != "Emscripten"
18
19
  Requires-Dist: cryptography (==35) ; platform_system != "Emscripten"
19
20
  Requires-Dist: grpcio (==1.51.1) ; platform_system != "Emscripten"
@@ -1,32 +1,33 @@
1
1
  bumble/__init__.py,sha256=Q8jkz6rgl95IMAeInQVt_2GLoJl3DcEP2cxtrQ-ho5c,110
2
- bumble/_version.py,sha256=9Vv_lgvFJRfjAttDT6Es4opA6YKvorXng5gzUuteh-8,164
3
- bumble/a2dp.py,sha256=MyCieGd2rA--nwpEdi1PsMXxfcki06ut6x7RXZUcO-w,21904
2
+ bumble/_version.py,sha256=uN9kco0Y-N-7Tp48dZrOIxHFhGYovN79kmVBnZPMLR0,164
3
+ bumble/a2dp.py,sha256=vwnKknvSKPR7IdTz8JHHNvHGObjepVy1kFRWm0kNWEI,21923
4
4
  bumble/att.py,sha256=qXwC5gtC-4Bwjqul0sCm_bWA_BbK4NVf5xNlOCRE7LI,30231
5
- bumble/avdtp.py,sha256=LVX536sds4M5IJoN46pbX7wZIcJG5DzunZ55KPjquiQ,71471
5
+ bumble/avdtp.py,sha256=sT0mFeFvp9jTEP-dOp4_ibdtKX3mtw1Gyi-72tHfkiE,72268
6
6
  bumble/bridge.py,sha256=T6es5oS1dy8QgkxQ8iOD-YcZ0SWOv8jaqC7TGxqodk4,3003
7
+ bumble/codecs.py,sha256=Vc7FOo6d-6VCgDI0ibnLmX8vCZ4-jtX_-0vEUM-yOrI,15343
7
8
  bumble/colors.py,sha256=9H-qzGgMr-YoWdIFpcGPaiRvTvkCzz7FPIkpwqKyKug,3033
8
9
  bumble/company_ids.py,sha256=mHmG9mk_0lkjiRm-IMggDnuXzY2QlZzH9jugy_ijhDc,95931
9
10
  bumble/controller.py,sha256=YwOVfcsPD8BvzXqfswY-wUECym2BX7_8zEBjIjUnhWw,44266
10
11
  bumble/core.py,sha256=_BnrlhR4OcS0RJE3510CshdD5iQ1zQeoMrdCD0oDebQ,48167
11
12
  bumble/crypto.py,sha256=JX3wg6kd-aFMxkxJz2FYFvyXHOukD-z0QcGH9jpEYvk,8679
12
13
  bumble/decoder.py,sha256=N9nMvuVhuwpnfw7EDVuNe9uYY6B6c3RY2dh8RhRPC1U,9608
13
- bumble/device.py,sha256=lOV-a-h03ckE-2UmicXGvgrnGX4x80hv-Gvvyaq8TA0,121790
14
+ bumble/device.py,sha256=VmLZ9V_XQWjYQBO9KMURMye8UcYJLUgUkv0HJO-K5ag,122190
14
15
  bumble/gap.py,sha256=axlOZIv99357Ehq2vMokeioU85z81qdQvplGn0pF70Q,2137
15
16
  bumble/gatt.py,sha256=bq6-oR0qx2Vp05IxnAiDZEGv3WsWCiNtdjYHpi0A6Fg,28150
16
17
  bumble/gatt_client.py,sha256=0NrwW7Y3oy1HUWisIyBLwnBpYNnuI9jtbcNkS6CD__U,40297
17
18
  bumble/gatt_server.py,sha256=vi_-sofp5NjPWDYX5K_hldsAaoFuNlt8GFA-eVzFkb8,35277
18
- bumble/hci.py,sha256=NTLA7l5SI312Gp77yZNRsaduV95Az_UeUBnA4IH_NBE,209326
19
+ bumble/hci.py,sha256=ky1_4ettxVk-ALKxBxEoUdcRroKLibznh4Fdb-HRLqk,209492
19
20
  bumble/helpers.py,sha256=AgtOigAqQzzTEMMwHQJ2EO7dOTp77qhnyfHQ2LCDd-k,8896
20
- bumble/hfp.py,sha256=GUOkQ2_earE9IiLXWa8uKugpEIyavEgm1tCSm8naGnI,3187
21
- bumble/host.py,sha256=ZeKsZg0qwqb-DmIZu5ZY6eMOGby0kXbcQHKvQDPit9g,33678
22
- bumble/keys.py,sha256=Oe69rpPF8-Gi4y1MP7ZF17BlOI8-SFISrvbm_PYfIUU,10709
21
+ bumble/hfp.py,sha256=BQEuh7A9WkP2V-YuuveuI5W-k1-O1Ovq2DvRao_2psk,3434
22
+ bumble/host.py,sha256=mNdGRnHNqk6eMpSdE49UT2uLk3Wi9TNhchsXfpDtA_o,33877
23
+ bumble/keys.py,sha256=_ibaJ4CxM5zyxnTp7wnihIQSsEAEkCiPxx9qHsGA04Q,12601
23
24
  bumble/l2cap.py,sha256=Md_1af1jEP0dXlXpVkaXINnnmElq423o5m9OJFBaiYk,72106
24
25
  bumble/link.py,sha256=dvb3fdmV8689A4rLhFVHHKMR3u4wQbUapFi-GeheK0M,20220
25
26
  bumble/pairing.py,sha256=smMCrWdgtdLXKJ_Ix9e5x1SuvSs_49mKtwzJS94ygd4,7002
26
27
  bumble/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
- bumble/rfcomm.py,sha256=r8Sl76HY-rQpctz7QYAKoEvg8VPcOtJngWdLjmRcrsA,29883
28
+ bumble/rfcomm.py,sha256=LgcHvRelcToJy3PiPedqkrj4CRZjCg2zFVba-hTkZCY,31632
28
29
  bumble/sdp.py,sha256=h0DyXOYpQ5OLzwVZsE4b5YZq_jxxu7m_QSbFkaPy9mQ,42464
29
- bumble/smp.py,sha256=-tSKjhUD699a8aj2HRT9X9BmiBZY6B8Wr_iAjQ73ZPY,68749
30
+ bumble/smp.py,sha256=NxbAlbijmTy3V1Yc8bqn0MlK3qnyNqFomgO0R_Wedsc,68767
30
31
  bumble/snoop.py,sha256=_QfF36eylBW6Snd-_KYOwKaGiM8i_Ed-B5XoFIPt3Dg,5631
31
32
  bumble/utils.py,sha256=x7AKW6QD35Dl1OkROLJ6TX4dNN6ajwFjW8w_BZGGcA4,10195
32
33
  bumble/apps/README.md,sha256=XTwjRAY-EJWDXpl1V8K3Mw8B7kIqzUIUizRjVBVhoIE,1769
@@ -39,21 +40,27 @@ bumble/apps/gatt_dump.py,sha256=-dCvCgjuHAp0h1zxm-gmqB4lVlSdas1Kp4cpzzx4gGw,4245
39
40
  bumble/apps/gg_bridge.py,sha256=G32XdCqYzt8Kqv9jZZDY29-ENjOxDMX_7CPolA8Jm1U,14555
40
41
  bumble/apps/hci_bridge.py,sha256=KISv352tKnsQsoxjkDiCQbMFmhnPWdnug5wSFAAXxEs,4033
41
42
  bumble/apps/l2cap_bridge.py,sha256=9914J7UomNtdWyE3VPgvzfJvZ304OM9AW9jzO_zRwNY,12604
42
- bumble/apps/pair.py,sha256=vorcWV98u0ZRVVhh-lF2-QOuTutaJ94GO_jCgXdIJZc,14776
43
+ bumble/apps/pair.py,sha256=Tl-QeJwahK17_iQHHy7dZW9gk0f5ETQhJ21Cxoj4k40,14860
43
44
  bumble/apps/pandora_server.py,sha256=VK6FDGluUkiQKiHPxCI5sd6jkCFJuSXDCdt8bAHykpo,900
44
- bumble/apps/scan.py,sha256=TBjeEWkyLDDdIYeq2HRA9oZ2xv5-_Ja18Mt_nG9WkvA,7467
45
+ bumble/apps/scan.py,sha256=_fMG_1j1HZQ_8SrJ0ZOxJaWB1OR4mKBaZuQMgm8viYI,7439
45
46
  bumble/apps/show.py,sha256=qvCY0RcACws8iU5EKPQ3GcURJkykvVvBi8EMAu5GOus,4385
46
- bumble/apps/unbond.py,sha256=-PXf6Jk4v-CQiogxhol6CjJ4mMWCApLFkbNHDuclUNk,2096
47
+ bumble/apps/unbond.py,sha256=P_zqdK_WsQHReqnhcaeeG3Kg6LhGBzCrRAyhcewQ7lU,3175
47
48
  bumble/apps/usb_probe.py,sha256=zJqrqKSGVYcOntXzgONdluZDE6jfj3IwPNuLqmDPDsU,10351
48
49
  bumble/apps/link_relay/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
50
  bumble/apps/link_relay/link_relay.py,sha256=GOESYPzkMJFrz5VOI_BSmnmgz4Y8EdSLHMWgdA63aDg,10066
50
51
  bumble/apps/link_relay/logging.yml,sha256=t-P72RAHsTZOESw0M4I3CQPonymcjkd9SLE0eY_ZNiM,311
52
+ bumble/apps/speaker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
+ bumble/apps/speaker/logo.svg,sha256=SQ9XXIqhh07BnGaBZ653nJ7vOslm2Dogdqadhg2MdE4,4205
54
+ bumble/apps/speaker/speaker.css,sha256=KTyvN0r0Q0aXWG7SWSE904lODfPQJTxRsvbuRJg5OBg,1236
55
+ bumble/apps/speaker/speaker.html,sha256=CAYYRK7S-uAN5BYV4B5TbPkT5tisqNl3v_xCqtBwYgw,1211
56
+ bumble/apps/speaker/speaker.js,sha256=DrT831yg3oBXKZ5usnfZjRU9X6Nw3zjIWSkz6sIgVtw,9373
57
+ bumble/apps/speaker/speaker.py,sha256=FOVTbJePBSfd1lZaW7wDR7ExcJiUOjmrpYsCz4Lg-oM,24516
51
58
  bumble/pandora/__init__.py,sha256=5NBVmndeTulANawift0jPT9ISp562wyIHTZ-4uP34Mg,3283
52
59
  bumble/pandora/config.py,sha256=fxKSACOSpsu8kfiVh3b1M1u_JHEBAIlhO88V9-s4kOk,2010
53
60
  bumble/pandora/device.py,sha256=xT_3f3IAeg8k_AWDyN0MvnRxZQ4Qf7AnDWD8LT0x_pI,5154
54
- bumble/pandora/host.py,sha256=0al7-od1_kZIiZPaFtguiYB_oTisGpuzBDle78JMBzA,33337
61
+ bumble/pandora/host.py,sha256=6TGEGyDwd2Wlq9BSjiOdAQnOvXqiImlltIt2olpMaTA,33393
55
62
  bumble/pandora/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
56
- bumble/pandora/security.py,sha256=u-KxfSSFBYWlD6BsGIQ9RqKsNNgpLxWuFvefbJaPG8g,20517
63
+ bumble/pandora/security.py,sha256=dEyDC7YSgavQX-Oq1SOcEQNJd46DsOYt8pjyaMRXbgM,20545
57
64
  bumble/pandora/utils.py,sha256=2s2oZXbsVz16sYVyfiWE8ehOMHCIU5gIUAChSTULrW8,3914
58
65
  bumble/profiles/__init__.py,sha256=yBGC8Ti5LvZuoh1F42XtfrBilb39T77_yuxESZeX2yI,581
59
66
  bumble/profiles/asha_service.py,sha256=C7-xwG1DgdPbt6IKLglIP1VYAg1X5s61YPAiOzHHgVw,7089
@@ -106,9 +113,9 @@ bumble/transport/grpc_protobuf/packet_streamer_pb2_grpc.py,sha256=k4RDFvE5Y4QgGL
106
113
  bumble/transport/grpc_protobuf/startup_pb2.py,sha256=viPPlvFuRE1HoM3zg3Ayy5wfNnuSSAX80MNqtKVqv-o,1854
107
114
  bumble/transport/grpc_protobuf/startup_pb2.pyi,sha256=8bDHVKJ_PIZuPvXRVK7tJCPOY8E8ZKW-5xzqbRLEJcw,2140
108
115
  bumble/transport/grpc_protobuf/startup_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
109
- bumble-0.0.154.dist-info/LICENSE,sha256=FvaYh4NRWIGgS_OwoBs5gFgkCmAghZ-DYnIGBZPuw-s,12142
110
- bumble-0.0.154.dist-info/METADATA,sha256=NYn42wISu9TjQYTMzDzqWqxVICEqB3h0qGYp6_Wwj3g,5156
111
- bumble-0.0.154.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
112
- bumble-0.0.154.dist-info/entry_points.txt,sha256=TziHgqYkLlyw0DMNA8rV2DJPME08q7R2s8dQ6zjG_48,611
113
- bumble-0.0.154.dist-info/top_level.txt,sha256=tV6JJKaHPYMFiJYiBYFW24PCcfLxTJZdlu6BmH3Cb00,7
114
- bumble-0.0.154.dist-info/RECORD,,
116
+ bumble-0.0.156.dist-info/LICENSE,sha256=FvaYh4NRWIGgS_OwoBs5gFgkCmAghZ-DYnIGBZPuw-s,12142
117
+ bumble-0.0.156.dist-info/METADATA,sha256=DKqhKEprZCG3ypJRbuJbWkE3NGC7oPIf9bSzxmLCS-s,5223
118
+ bumble-0.0.156.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
119
+ bumble-0.0.156.dist-info/entry_points.txt,sha256=E4FgYbSefpIthFFC6S9l9PVJECQ-GvZBsEfcMTovM74,661
120
+ bumble-0.0.156.dist-info/top_level.txt,sha256=tV6JJKaHPYMFiJYiBYFW24PCcfLxTJZdlu6BmH3Cb00,7
121
+ bumble-0.0.156.dist-info/RECORD,,
@@ -10,5 +10,6 @@ bumble-pair = bumble.apps.pair:main
10
10
  bumble-pandora-server = bumble.apps.pandora_server:main
11
11
  bumble-scan = bumble.apps.scan:main
12
12
  bumble-show = bumble.apps.show:main
13
+ bumble-speaker = bumble.apps.speaker.speaker:main
13
14
  bumble-unbond = bumble.apps.unbond:main
14
15
  bumble-usb-probe = bumble.apps.usb_probe:main