Metadata-Version: 2.5
Name: pydanalock-ble
Version: 0.9.0
Summary: Unofficial async client library for Danalock V3 smart locks over Bluetooth Low Energy
Project-URL: Homepage, https://github.com/buggy-shep/pydanalock-ble
Project-URL: Repository, https://github.com/buggy-shep/pydanalock-ble
Project-URL: Issues, https://github.com/buggy-shep/pydanalock-ble/issues
Project-URL: Changelog, https://github.com/buggy-shep/pydanalock-ble/releases
Author: The pydanalock-ble contributors
License-Expression: MIT
License-File: LICENSE
Keywords: ble,bluetooth,danalock,home-automation,smart-lock
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Home Automation
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: bleak>=3.0
Requires-Dist: cryptography>=44
Provides-Extra: dev
Requires-Dist: mypy>=1.11; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
Requires-Dist: pytest>=8.2; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Provides-Extra: release
Requires-Dist: build>=1.2; extra == 'release'
Requires-Dist: twine>=5; extra == 'release'
Description-Content-Type: text/markdown

# pydanalock-ble

[![PyPI version](https://img.shields.io/pypi/v/pydanalock-ble.svg)](https://pypi.org/project/pydanalock-ble/)
[![CI](https://github.com/buggy-shep/pydanalock-ble/actions/workflows/ci.yml/badge.svg)](https://github.com/buggy-shep/pydanalock-ble/actions/workflows/ci.yml)

Unofficial async Python client library for Danalock V3 smart locks over
Bluetooth Low Energy. Key material is obtained from the sibling cloud client
[pydanalock-cloud](https://github.com/buggy-shep/pydanalock-cloud) and passed
in as opaque bytes.

```python
from pydanalock.ble import DanalockLock

lock = DanalockLock(
    "AA:BB:CC:DD:EE:FF",
    serial=bytes.fromhex("010203040506"),
    login_token=blob_from_your_cloud_client,
    trust_anchor=anchor_der_bytes,
)
async with lock:
    print(await lock.state())
    print(await lock.battery())
```

`unlock()` and `lock()` are only ever called by your code — the library
never moves the lock implicitly.

> **Disclaimer.** This project is unofficial and is not affiliated with,
> endorsed by, or sponsored by Danalock AS or Poly-Control. It is built for
> interoperability with devices you own. Use it at your own risk; only control
> devices you are authorized to control.

## Install

```bash
pip install pydanalock-ble
```

## Status

Work in progress. Development is spec-first; see [`specs/`](specs/) for the
protocol specifications and their status.

Implemented:

- DMI frame codec (envelope, byte stuffing, CRC-16) —
  [spec 0001](specs/0001-dmi-frame-codec.md)
- Reliable delivery layer (sequence/acknowledgement, retransmissions) and
  GATT transport — [spec 0002](specs/0002-rpd-transport.md)
- TLS 1.2 session (ECDHE-ECDSA-AES-256-GCM-SHA384, extended master secret,
  lock certificate validation) — [spec 0003](specs/0003-tls-session.md)
- Application command layer and the public async `DanalockLock` API
  (connect/login/state/battery/unlock/lock) —
  [spec 0004](specs/0004-afi-api.md)
- Passive state from BLE advertisements —
  [spec 0005](specs/0005-advertising.md)
- Lock settings read and write (read 4.6, one-member writes with
  verification reads) — [spec 0006](specs/0006-settings-write.md)
- Device information read (product, hardware version, firmware version,
  firmware identifier) — [spec 0008](specs/0008-device-information.md)

## Requirements

- Python >= 3.11
- [bleak](https://pypi.org/project/bleak/) >= 3.0
- [cryptography](https://pypi.org/project/cryptography/) >= 44

## Development

```bash
python3 -m venv .venv
.venv/bin/pip install -e ".[dev]"
.venv/bin/ruff check .
.venv/bin/ruff format --check .
.venv/bin/mypy
.venv/bin/pytest -m "not live"
```

Synthetic protocol test vectors (shape mirrors observed frames; no real
device data) live in `tests/vectors/`. Live tests (real lock) stay behind
the `live` marker and are run manually only.

## License

[MIT](LICENSE)
