casambi-bt-revamped 0.3.7.dev12__tar.gz → 0.3.7.dev14__tar.gz

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 (23) hide show
  1. {casambi_bt_revamped-0.3.7.dev12/src/casambi_bt_revamped.egg-info → casambi_bt_revamped-0.3.7.dev14}/PKG-INFO +1 -1
  2. {casambi_bt_revamped-0.3.7.dev12 → casambi_bt_revamped-0.3.7.dev14}/setup.cfg +1 -1
  3. {casambi_bt_revamped-0.3.7.dev12 → casambi_bt_revamped-0.3.7.dev14}/src/CasambiBt/_casambi.py +13 -0
  4. {casambi_bt_revamped-0.3.7.dev12 → casambi_bt_revamped-0.3.7.dev14}/src/CasambiBt/_client.py +42 -18
  5. {casambi_bt_revamped-0.3.7.dev12 → casambi_bt_revamped-0.3.7.dev14/src/casambi_bt_revamped.egg-info}/PKG-INFO +1 -1
  6. {casambi_bt_revamped-0.3.7.dev12 → casambi_bt_revamped-0.3.7.dev14}/LICENSE +0 -0
  7. {casambi_bt_revamped-0.3.7.dev12 → casambi_bt_revamped-0.3.7.dev14}/README.md +0 -0
  8. {casambi_bt_revamped-0.3.7.dev12 → casambi_bt_revamped-0.3.7.dev14}/pyproject.toml +0 -0
  9. {casambi_bt_revamped-0.3.7.dev12 → casambi_bt_revamped-0.3.7.dev14}/src/CasambiBt/__init__.py +0 -0
  10. {casambi_bt_revamped-0.3.7.dev12 → casambi_bt_revamped-0.3.7.dev14}/src/CasambiBt/_cache.py +0 -0
  11. {casambi_bt_revamped-0.3.7.dev12 → casambi_bt_revamped-0.3.7.dev14}/src/CasambiBt/_constants.py +0 -0
  12. {casambi_bt_revamped-0.3.7.dev12 → casambi_bt_revamped-0.3.7.dev14}/src/CasambiBt/_discover.py +0 -0
  13. {casambi_bt_revamped-0.3.7.dev12 → casambi_bt_revamped-0.3.7.dev14}/src/CasambiBt/_encryption.py +0 -0
  14. {casambi_bt_revamped-0.3.7.dev12 → casambi_bt_revamped-0.3.7.dev14}/src/CasambiBt/_keystore.py +0 -0
  15. {casambi_bt_revamped-0.3.7.dev12 → casambi_bt_revamped-0.3.7.dev14}/src/CasambiBt/_network.py +0 -0
  16. {casambi_bt_revamped-0.3.7.dev12 → casambi_bt_revamped-0.3.7.dev14}/src/CasambiBt/_operation.py +0 -0
  17. {casambi_bt_revamped-0.3.7.dev12 → casambi_bt_revamped-0.3.7.dev14}/src/CasambiBt/_unit.py +0 -0
  18. {casambi_bt_revamped-0.3.7.dev12 → casambi_bt_revamped-0.3.7.dev14}/src/CasambiBt/errors.py +0 -0
  19. {casambi_bt_revamped-0.3.7.dev12 → casambi_bt_revamped-0.3.7.dev14}/src/CasambiBt/py.typed +0 -0
  20. {casambi_bt_revamped-0.3.7.dev12 → casambi_bt_revamped-0.3.7.dev14}/src/casambi_bt_revamped.egg-info/SOURCES.txt +0 -0
  21. {casambi_bt_revamped-0.3.7.dev12 → casambi_bt_revamped-0.3.7.dev14}/src/casambi_bt_revamped.egg-info/dependency_links.txt +0 -0
  22. {casambi_bt_revamped-0.3.7.dev12 → casambi_bt_revamped-0.3.7.dev14}/src/casambi_bt_revamped.egg-info/requires.txt +0 -0
  23. {casambi_bt_revamped-0.3.7.dev12 → casambi_bt_revamped-0.3.7.dev14}/src/casambi_bt_revamped.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: casambi-bt-revamped
3
- Version: 0.3.7.dev12
3
+ Version: 0.3.7.dev14
4
4
  Summary: Enhanced Casambi Bluetooth client library with switch event support
5
5
  Home-page: https://github.com/rankjie/casambi-bt
6
6
  Author: rankjie
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = casambi-bt-revamped
3
- version = 0.3.7.dev12
3
+ version = 0.3.7.dev14
4
4
  author = rankjie
5
5
  author_email = rankjie@gmail.com
6
6
  description = Enhanced Casambi Bluetooth client library with switch event support
@@ -683,6 +683,19 @@ class Casambi:
683
683
  import json
684
684
  data = json.dumps(switch_config, separators=(",", ":")).encode("utf-8")
685
685
 
686
+ # Attempt to start a switch session before sending chunks. Some devices
687
+ # expect an AcquireSwitchSession (opcode 42) handshake prior to ExtPacketSend.
688
+ try:
689
+ await self.start_switch_session(unit_id)
690
+ self._logger.info("Started switch session (AcquireSwitchSession) for unit %s", unit_id)
691
+ except Exception as e:
692
+ # Non-fatal: proceed without session if device doesn't require it.
693
+ self._logger.info(
694
+ "AcquireSwitchSession not acknowledged or unsupported for unit %s (%s); proceeding with ExtPacketSend only.",
695
+ unit_id,
696
+ e,
697
+ )
698
+
686
699
  # Chunk into 61-byte pieces (ExtPacket payload allows 63 total minus 2-byte header)
687
700
  max_chunk = 61
688
701
  seq = 0
@@ -418,6 +418,13 @@ class CasambiClient:
418
418
  # Store raw encrypted packet for reference
419
419
  raw_encrypted_packet = data[:]
420
420
 
421
+ # Extract the device-provided 4-byte little-endian counter from the
422
+ # encrypted header. This is the true per-session packet sequence.
423
+ try:
424
+ device_sequence = int.from_bytes(data[:4], byteorder="little", signed=False)
425
+ except Exception:
426
+ device_sequence = None
427
+
421
428
  try:
422
429
  decrypted_data = self._encryptor.decryptAndVerify(
423
430
  data, data[:4] + self._nonce[4:]
@@ -433,8 +440,11 @@ class CasambiClient:
433
440
  if packetType == IncommingPacketType.UnitState:
434
441
  self._parseUnitStates(decrypted_data[1:])
435
442
  elif packetType == IncommingPacketType.SwitchEvent:
443
+ # Pass the device sequence as the packet sequence for consumers,
444
+ # and still include the raw encrypted packet for diagnostics.
445
+ seq_for_consumer = device_sequence if device_sequence is not None else self._inPacketCount
436
446
  self._parseSwitchEvent(
437
- decrypted_data[1:], self._inPacketCount, raw_encrypted_packet
447
+ decrypted_data[1:], seq_for_consumer, raw_encrypted_packet
438
448
  )
439
449
  elif packetType == IncommingPacketType.NetworkConfig:
440
450
  # We don't care about the config the network thinks it has.
@@ -552,21 +562,32 @@ class CasambiClient:
552
562
  # Process based on message type
553
563
  if message_type == 0x08 or message_type == 0x10: # Switch/button events
554
564
  switch_events_found += 1
555
- # Extract button ID - try both upper and lower nibbles
556
- button_lower = parameter & 0x0F
557
- button_upper = (parameter >> 4) & 0x0F
558
-
559
- # Use upper 4 bits if lower 4 bits are 0, otherwise use lower 4 bits
560
- if button_lower == 0 and button_upper != 0:
561
- button = button_upper
565
+
566
+ # Button extraction differs between type 0x08 and type 0x10
567
+ if message_type == 0x08:
568
+ # For type 0x08, the lower nibble is a code that maps to physical button id
569
+ # Using formula: ((code + 2) % 4) + 1 based on reverse engineering findings
570
+ code_nibble = parameter & 0x0F
571
+ button = ((code_nibble + 2) % 4) + 1
562
572
  self._logger.debug(
563
- f"EVO button extraction: parameter=0x{parameter:02x}, using upper nibble, button={button}"
573
+ f"Type 0x08 button extraction: parameter=0x{parameter:02x}, code={code_nibble}, button={button}"
564
574
  )
565
575
  else:
566
- button = button_lower
567
- self._logger.debug(
568
- f"EVO button extraction: parameter=0x{parameter:02x}, using lower nibble, button={button}"
569
- )
576
+ # For type 0x10, use existing logic
577
+ button_lower = parameter & 0x0F
578
+ button_upper = (parameter >> 4) & 0x0F
579
+
580
+ # Use upper 4 bits if lower 4 bits are 0, otherwise use lower 4 bits
581
+ if button_lower == 0 and button_upper != 0:
582
+ button = button_upper
583
+ self._logger.debug(
584
+ f"Type 0x10 button extraction: parameter=0x{parameter:02x}, using upper nibble, button={button}"
585
+ )
586
+ else:
587
+ button = button_lower
588
+ self._logger.debug(
589
+ f"Type 0x10 button extraction: parameter=0x{parameter:02x}, using lower nibble, button={button}"
590
+ )
570
591
 
571
592
  # For type 0x10 messages, we need to pass additional data beyond the declared payload
572
593
  if message_type == 0x10:
@@ -705,13 +726,12 @@ class CasambiClient:
705
726
  f"action={action_display} ({event_string}), flags=0x{flags:02x}"
706
727
  )
707
728
 
708
- # Filter out all type 0x08 messages
729
+ # Log detailed info about type 0x08 messages (now processed, not filtered)
709
730
  if message_type == 0x08:
710
- self._logger.debug(
711
- f"Filtering out type 0x08 event: button={button}, unit_id={unit_id}, "
712
- f"action={action_display}, flags=0x{flags:02x}"
731
+ self._logger.info(
732
+ f"Type 0x08 event processed: button={button}, unit_id={unit_id}, "
733
+ f"action={action_display}, event={event_string}, flags=0x{flags:02x}"
713
734
  )
714
- return
715
735
 
716
736
  self._dataCallback(
717
737
  IncommingPacketType.SwitchEvent,
@@ -723,7 +743,11 @@ class CasambiClient:
723
743
  "event": event_string,
724
744
  "flags": flags,
725
745
  "extra_data": extra_data,
746
+ # packet_sequence is the device-provided sequence number when available
747
+ # (true 32-bit counter from the BLE header), otherwise the local arrival index.
726
748
  "packet_sequence": packet_seq,
749
+ # Include the local arrival index for debugging and correlation.
750
+ "arrival_sequence": self._inPacketCount,
727
751
  "raw_packet": b2a(raw_packet) if raw_packet else None,
728
752
  "decrypted_data": b2a(full_data),
729
753
  "message_position": start_pos,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: casambi-bt-revamped
3
- Version: 0.3.7.dev12
3
+ Version: 0.3.7.dev14
4
4
  Summary: Enhanced Casambi Bluetooth client library with switch event support
5
5
  Home-page: https://github.com/rankjie/casambi-bt
6
6
  Author: rankjie