casambi-bt-revamped 0.3.12.dev11__py3-none-any.whl → 0.3.12.dev13__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.
- CasambiBt/_client.py +66 -7
- CasambiBt/_network.py +44 -25
- CasambiBt/_version.py +1 -1
- {casambi_bt_revamped-0.3.12.dev11.dist-info → casambi_bt_revamped-0.3.12.dev13.dist-info}/METADATA +1 -1
- {casambi_bt_revamped-0.3.12.dev11.dist-info → casambi_bt_revamped-0.3.12.dev13.dist-info}/RECORD +8 -8
- {casambi_bt_revamped-0.3.12.dev11.dist-info → casambi_bt_revamped-0.3.12.dev13.dist-info}/WHEEL +0 -0
- {casambi_bt_revamped-0.3.12.dev11.dist-info → casambi_bt_revamped-0.3.12.dev13.dist-info}/licenses/LICENSE +0 -0
- {casambi_bt_revamped-0.3.12.dev11.dist-info → casambi_bt_revamped-0.3.12.dev13.dist-info}/top_level.txt +0 -0
CasambiBt/_client.py
CHANGED
|
@@ -438,6 +438,7 @@ class CasambiClient:
|
|
|
438
438
|
self._network.classicManagerKey() is not None,
|
|
439
439
|
getattr(self._network, "isManager", lambda: False)(),
|
|
440
440
|
)
|
|
441
|
+
await self._classicEnumerateAndSubscribeGatt(notify_kwargs)
|
|
441
442
|
_log_probe_summary("CLASSIC", classic_variant="ca52_legacy")
|
|
442
443
|
# Emit a warning if we never see Classic RX frames; this is a common failure mode.
|
|
443
444
|
self._classicNoRxTask = asyncio.create_task(self._classic_no_rx_watchdog(30.0))
|
|
@@ -593,6 +594,7 @@ class CasambiClient:
|
|
|
593
594
|
self._network.classicManagerKey() is not None,
|
|
594
595
|
getattr(self._network, "isManager", lambda: False)(),
|
|
595
596
|
)
|
|
597
|
+
await self._classicEnumerateAndSubscribeGatt(notify_kwargs)
|
|
596
598
|
_log_probe_summary("CLASSIC", classic_variant="auth_uuid_conformant")
|
|
597
599
|
self._classicNoRxTask = asyncio.create_task(self._classic_no_rx_watchdog(30.0))
|
|
598
600
|
return
|
|
@@ -1223,6 +1225,58 @@ class CasambiClient:
|
|
|
1223
1225
|
len(pkt),
|
|
1224
1226
|
)
|
|
1225
1227
|
|
|
1228
|
+
async def _classicEnumerateAndSubscribeGatt(
|
|
1229
|
+
self, notify_kwargs: dict[str, Any]
|
|
1230
|
+
) -> None:
|
|
1231
|
+
"""Enumerate all GATT characteristics and subscribe to any notifiable ones.
|
|
1232
|
+
|
|
1233
|
+
This discovers characteristics beyond the manually-probed CA51/CA52/CA53
|
|
1234
|
+
UUIDs and subscribes to any that support notify or indicate, which may be
|
|
1235
|
+
needed for receiving Classic state/config notifications.
|
|
1236
|
+
"""
|
|
1237
|
+
try:
|
|
1238
|
+
total_chars = 0
|
|
1239
|
+
for svc in self._gattClient.services:
|
|
1240
|
+
for char in svc.characteristics:
|
|
1241
|
+
total_chars += 1
|
|
1242
|
+
char_uuid = str(char.uuid).lower()
|
|
1243
|
+
props = char.properties
|
|
1244
|
+
self._logger.warning(
|
|
1245
|
+
"[CASAMBI_CLASSIC_GATT_CHAR] uuid=%s props=%s handle=%d",
|
|
1246
|
+
char_uuid,
|
|
1247
|
+
props,
|
|
1248
|
+
char.handle,
|
|
1249
|
+
)
|
|
1250
|
+
if char_uuid not in self._classicNotifyCharUuids:
|
|
1251
|
+
if "notify" in props or "indicate" in props:
|
|
1252
|
+
try:
|
|
1253
|
+
await self._gattClient.start_notify(
|
|
1254
|
+
char.uuid,
|
|
1255
|
+
self._queueCallback,
|
|
1256
|
+
**notify_kwargs,
|
|
1257
|
+
)
|
|
1258
|
+
self._classicNotifyCharUuids.add(char_uuid)
|
|
1259
|
+
self._logger.warning(
|
|
1260
|
+
"[CASAMBI_CLASSIC_GATT_SUB] subscribed uuid=%s",
|
|
1261
|
+
char_uuid,
|
|
1262
|
+
)
|
|
1263
|
+
except Exception as e:
|
|
1264
|
+
self._logger.warning(
|
|
1265
|
+
"[CASAMBI_CLASSIC_GATT_SUB] failed uuid=%s err=%s",
|
|
1266
|
+
char_uuid,
|
|
1267
|
+
type(e).__name__,
|
|
1268
|
+
)
|
|
1269
|
+
self._logger.warning(
|
|
1270
|
+
"[CASAMBI_CLASSIC_GATT_ENUM] total_chars=%d subscribed_uuids=%s",
|
|
1271
|
+
total_chars,
|
|
1272
|
+
sorted(self._classicNotifyCharUuids),
|
|
1273
|
+
)
|
|
1274
|
+
except Exception as e:
|
|
1275
|
+
self._logger.warning(
|
|
1276
|
+
"[CASAMBI_CLASSIC_GATT_ENUM] services enumeration unavailable: %s",
|
|
1277
|
+
type(e).__name__,
|
|
1278
|
+
)
|
|
1279
|
+
|
|
1226
1280
|
async def classicSendInit(self) -> None:
|
|
1227
1281
|
"""Send Classic post-connection initialization (time-sync).
|
|
1228
1282
|
|
|
@@ -1253,7 +1307,7 @@ class CasambiClient:
|
|
|
1253
1307
|
# Build the time-sync payload.
|
|
1254
1308
|
# Format: [10][year:2BE][month:1][day:1][hour:1][min:1][sec:1]
|
|
1255
1309
|
# [tz_offset:2BE signed][dst_transition:4BE][dst_change:1]
|
|
1256
|
-
# [timestamp1:
|
|
1310
|
+
# [timestamp1:3BE][timestamp2:3BE][zero:2][millis:3BE][extra:1]
|
|
1257
1311
|
payload = bytearray()
|
|
1258
1312
|
payload.append(10) # Classic time-sync command byte
|
|
1259
1313
|
payload.extend(struct.pack(">H", now.year))
|
|
@@ -1266,16 +1320,21 @@ class CasambiClient:
|
|
|
1266
1320
|
# DST transition data and change minutes (0 = no DST info).
|
|
1267
1321
|
payload.extend(struct.pack(">I", 0))
|
|
1268
1322
|
payload.append(0)
|
|
1269
|
-
# Classic extra bytes: timestamps, zero short, millis.
|
|
1270
|
-
#
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1323
|
+
# Classic extra bytes: timestamps, zero short, millis, trailing byte.
|
|
1324
|
+
# Android AbstractC1717h.X() lines 323-328: j() = 3-byte big-endian write
|
|
1325
|
+
# (Q2.t.java:59-63), NOT 4-byte. Plus trailing writeByte(iK0 >> 24).
|
|
1326
|
+
ts1 = 0 # Q2.r.K0(network.V) — start with 0
|
|
1327
|
+
ts2 = 0 # Q2.r.K0(network.W) — start with 0
|
|
1328
|
+
for ts in (ts1, ts2):
|
|
1329
|
+
payload.append((ts >> 16) & 0xFF)
|
|
1330
|
+
payload.append((ts >> 8) & 0xFF)
|
|
1331
|
+
payload.append(ts & 0xFF)
|
|
1332
|
+
payload.extend(struct.pack(">H", 0)) # writeShort(0)
|
|
1275
1333
|
millis_val = now.microsecond // 1000 * 1000
|
|
1276
1334
|
payload.append((millis_val >> 16) & 0xFF)
|
|
1277
1335
|
payload.append((millis_val >> 8) & 0xFF)
|
|
1278
1336
|
payload.append(millis_val & 0xFF)
|
|
1337
|
+
payload.append((ts1 >> 24) & 0xFF) # writeByte(iK0 >> 24)
|
|
1279
1338
|
|
|
1280
1339
|
self._logger.warning(
|
|
1281
1340
|
"[CASAMBI_CLASSIC_INIT] sending time-sync len=%d hex=%s",
|
CasambiBt/_network.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import logging
|
|
3
|
-
import platform
|
|
4
3
|
import pickle
|
|
4
|
+
import random
|
|
5
5
|
from dataclasses import dataclass
|
|
6
6
|
from datetime import datetime, timedelta
|
|
7
7
|
from typing import Any, Final, cast
|
|
@@ -13,7 +13,6 @@ from ._cache import Cache
|
|
|
13
13
|
from ._constants import DEVICE_NAME
|
|
14
14
|
from ._keystore import KeyStore
|
|
15
15
|
from ._unit import Group, Scene, Unit, UnitControl, UnitControlType, UnitType
|
|
16
|
-
from ._version import __version__
|
|
17
16
|
from .errors import (
|
|
18
17
|
AuthenticationError,
|
|
19
18
|
NetworkNotFoundError,
|
|
@@ -66,29 +65,49 @@ class Network:
|
|
|
66
65
|
|
|
67
66
|
self._cache = cache
|
|
68
67
|
|
|
69
|
-
# Android
|
|
70
|
-
#
|
|
71
|
-
self._token: str =
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
"
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
|
|
68
|
+
# Android sends "fb:<FCM_token>" — we have no push token, use empty string
|
|
69
|
+
# to match the field type without leaking platform info.
|
|
70
|
+
self._token: str = ""
|
|
71
|
+
# Android: "{flavor}/{version} {manufacturer}_{model}/{os_release}"
|
|
72
|
+
_app_version = random.choice((
|
|
73
|
+
"3.19.0", "3.18.2", "3.18.1", "3.18.0",
|
|
74
|
+
"3.17.4", "3.17.3", "3.17.2", "3.17.1", "3.17.0",
|
|
75
|
+
"3.16.5", "3.16.4", "3.16.3", "3.16.1", "3.16.0",
|
|
76
|
+
"3.15.3", "3.15.2", "3.15.1", "3.15.0",
|
|
77
|
+
"3.14.2", "3.14.1", "3.14.0",
|
|
78
|
+
"3.13.2", "3.13.1", "3.13.0",
|
|
79
|
+
"3.12.4", "3.12.3", "3.12.1", "3.12.0",
|
|
80
|
+
"3.11.2", "3.11.1",
|
|
81
|
+
))
|
|
82
|
+
_device = random.choice((
|
|
83
|
+
# Samsung Galaxy S series
|
|
84
|
+
"samsung_SM-S928B/15", # S24 Ultra
|
|
85
|
+
"samsung_SM-S926B/15", # S24+
|
|
86
|
+
"samsung_SM-S921B/15", # S24
|
|
87
|
+
"samsung_SM-S918B/14", # S23 Ultra
|
|
88
|
+
"samsung_SM-S916B/14", # S23+
|
|
89
|
+
"samsung_SM-S911B/14", # S23
|
|
90
|
+
"samsung_SM-S908B/14", # S22 Ultra
|
|
91
|
+
"samsung_SM-S906B/14", # S22+
|
|
92
|
+
"samsung_SM-S901B/14", # S22
|
|
93
|
+
"samsung_SM-G998B/13", # S21 Ultra
|
|
94
|
+
"samsung_SM-G996B/13", # S21+
|
|
95
|
+
"samsung_SM-G991B/13", # S21
|
|
96
|
+
# Samsung Galaxy A series
|
|
97
|
+
"samsung_SM-A556B/14", # A55
|
|
98
|
+
"samsung_SM-A546B/14", # A54
|
|
99
|
+
"samsung_SM-A346B/14", # A34
|
|
100
|
+
"samsung_SM-A536B/13", # A53
|
|
101
|
+
# Google Pixel
|
|
102
|
+
"Google_Pixel 8 Pro/14",
|
|
103
|
+
"Google_Pixel 8/14",
|
|
104
|
+
"Google_Pixel 7 Pro/14",
|
|
105
|
+
"Google_Pixel 7/14",
|
|
106
|
+
# OnePlus
|
|
107
|
+
"OnePlus_IN2023/14", # 12
|
|
108
|
+
"OnePlus_CPH2449/14", # 11
|
|
109
|
+
))
|
|
110
|
+
self._clientInfo: str = f"Casambi/{_app_version} {_device}"
|
|
92
111
|
|
|
93
112
|
async def load(self) -> None:
|
|
94
113
|
self._keystore = KeyStore(self._cache)
|
CasambiBt/_version.py
CHANGED
{casambi_bt_revamped-0.3.12.dev11.dist-info → casambi_bt_revamped-0.3.12.dev13.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: casambi-bt-revamped
|
|
3
|
-
Version: 0.3.12.
|
|
3
|
+
Version: 0.3.12.dev13
|
|
4
4
|
Summary: Forked Casambi Bluetooth client library with switch event support, use original if no special need. https://github.com/lkempf/casambi-bt
|
|
5
5
|
Home-page: https://github.com/rankjie/casambi-bt
|
|
6
6
|
Author: rankjie
|
{casambi_bt_revamped-0.3.12.dev11.dist-info → casambi_bt_revamped-0.3.12.dev13.dist-info}/RECORD
RENAMED
|
@@ -2,21 +2,21 @@ CasambiBt/__init__.py,sha256=iJdTF4oeXfj5d5gfGxQkacqUjtnQo0IW-zFPJvFjWWk,336
|
|
|
2
2
|
CasambiBt/_cache.py,sha256=3bQil8vhSy4f4sf9JusMfEdQC7d3cJuva9qHhyKro-0,3808
|
|
3
3
|
CasambiBt/_casambi.py,sha256=dAZZ0S2-t2ShLbW78AE9lOLBzOmhBOTTXJky-6khdkE,41981
|
|
4
4
|
CasambiBt/_classic_crypto.py,sha256=XIp3JBaeY8hIUv5kB0ygVG_eRx9AgHHF4ts2--CFm78,4973
|
|
5
|
-
CasambiBt/_client.py,sha256
|
|
5
|
+
CasambiBt/_client.py,sha256=a257JmcbYvdP0gSy-W1t3oqunA78dvhXMx-L_TMhr8o,95405
|
|
6
6
|
CasambiBt/_constants.py,sha256=86heoDdb5iPaRrPmK2DIIl-4uSxbFFcnCo9zlCvTLww,1290
|
|
7
7
|
CasambiBt/_discover.py,sha256=jLc6H69JddrCURgtANZEjws6_UbSzXJtvJkbKTaIUHY,1849
|
|
8
8
|
CasambiBt/_encryption.py,sha256=CLcoOOrggQqhJbnr_emBnEnkizpWDvb_0yFnitq4_FM,3831
|
|
9
9
|
CasambiBt/_invocation.py,sha256=fkG4R0Gv5_amFfD_P6DKuIEe3oKWZW0v8RSU8zDjPdI,2985
|
|
10
10
|
CasambiBt/_keystore.py,sha256=Jdiq0zMPDmhfpheSojKY6sTUpmVrvX_qOyO7yCYd3kw,2788
|
|
11
|
-
CasambiBt/_network.py,sha256=
|
|
11
|
+
CasambiBt/_network.py,sha256=3ZUedQlHzzuHHiG5KxDLnK0AIz0TjzG1_vwg0UGsO9U,22132
|
|
12
12
|
CasambiBt/_operation.py,sha256=Q5UccsrtNp_B_wWqwH_3eLFW_yF6A55FMmfUKDk2WrI,1059
|
|
13
13
|
CasambiBt/_switch_events.py,sha256=S8OD0dBcw5T4J2C7qfmOQMnTJ7omIXRUYv4PqDOB87E,13137
|
|
14
14
|
CasambiBt/_unit.py,sha256=nxbg_8UCCVB9WI8dUS21g2JrGyPKcefqKMSusMOhLOo,18721
|
|
15
|
-
CasambiBt/_version.py,sha256=
|
|
15
|
+
CasambiBt/_version.py,sha256=kFYpR3yK4UmQAWNKE7Jrv9E0CGPotgTEUKIRF5GnzU8,338
|
|
16
16
|
CasambiBt/errors.py,sha256=1L_Q8og_N_BRYEKizghAQXr6tihlHykFgtcCHUDcBas,1961
|
|
17
17
|
CasambiBt/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
|
-
casambi_bt_revamped-0.3.12.
|
|
19
|
-
casambi_bt_revamped-0.3.12.
|
|
20
|
-
casambi_bt_revamped-0.3.12.
|
|
21
|
-
casambi_bt_revamped-0.3.12.
|
|
22
|
-
casambi_bt_revamped-0.3.12.
|
|
18
|
+
casambi_bt_revamped-0.3.12.dev13.dist-info/licenses/LICENSE,sha256=TAIIitFxpxEDi6Iju7foW4TDQmWvC-IhLVLhl67jKmQ,11341
|
|
19
|
+
casambi_bt_revamped-0.3.12.dev13.dist-info/METADATA,sha256=9LeLoHYkt4Hp8qzq6MzABk_ww_369Gmky5-FZtEKhe0,5878
|
|
20
|
+
casambi_bt_revamped-0.3.12.dev13.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
21
|
+
casambi_bt_revamped-0.3.12.dev13.dist-info/top_level.txt,sha256=uNbqLjtecFosoFzpGAC89-5icikWODKI8rOjbi8v_sA,10
|
|
22
|
+
casambi_bt_revamped-0.3.12.dev13.dist-info/RECORD,,
|
{casambi_bt_revamped-0.3.12.dev11.dist-info → casambi_bt_revamped-0.3.12.dev13.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|