Metadata-Version: 2.4
Name: ha-maison-protegee2-api
Version: 0.1.0
Summary: Python client for Orange Maison Protégée (reverse-engineered gRPC API)
Author: Identity Labs
License: MIT
Project-URL: Homepage, https://github.com/Identity-labs/ha-maison-protegee2-api
Project-URL: Repository, https://github.com/Identity-labs/ha-maison-protegee2-api
Project-URL: Home Assistant, https://github.com/Identity-labs/ha-maison-protegee2
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: grpcio>=1.62.0
Requires-Dist: protobuf<7,>=6.31.0
Provides-Extra: dev
Requires-Dist: grpcio-tools<1.76,>=1.70.0; extra == "dev"
Dynamic: license-file

# ha-maison-protegee2-api

Python client for **Orange Maison Protégée** (`com.orange.fr.protegee2` v5.9), reverse-engineered from the Android APK.

No official public API exists — this project talks to the same gRPC backend as the mobile app.

The Home Assistant integration lives in [ha-maison-protegee2](https://github.com/Identity-labs/ha-maison-protegee2) and will depend on this package once it is published.

## API overview

| Item | Value |
|------|-------|
| Endpoint | `maison-protegee.orange.fr:443` (TLS) |
| Protocol | gRPC / protobuf |
| Service | `com.orange.erable.services.LsService` |
| Auth | `authenticate` → JWT tokens in protobuf messages |
| Alarm | `getGatewayStatus`, `gatewayCommand` |

### Alarm commands

| Action | `mode` | `status` |
|--------|--------|----------|
| Arm total | `total` | `active` |
| Arm partial | `partial` | `active` |
| Disarm | `` (empty) | `inactive` |

## Setup

```bash
cd ha-maison-protegee2-api
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
```

## Usage

### Python

```python
from maison_protegee import MaisonProtegeeClient

with MaisonProtegeeClient("your_customer_id", "your_password") as client:
    client.login()
    print(client.get_gateway_status())
    client.arm_total()
    client.disarm()
    print(client.list_equipment())
```

### CLI

```bash
export MAISON_PROTEGEE_USERNAME="..."
export MAISON_PROTEGEE_PASSWORD="..."

maison-protegee login
maison-protegee status
maison-protegee arm-total
maison-protegee disarm
maison-protegee equipment
maison-protegee events
```

## Project layout

```
ha-maison-protegee2-api/
├── src/maison_protegee/      # Python package
│   ├── client.py             # Main gRPC client
│   ├── models.py             # AlarmMode, GatewayState, …
│   ├── cli.py                # Command-line interface
│   ├── proto/erable.proto    # Reverse-engineered protobuf
│   └── generated/            # protoc output (erable_pb2*.py)
├── scripts/
│   ├── generate_proto.sh     # Regenerate stubs after proto edits
│   ├── extract_apk_urls.py   # Static APK string extraction
│   ├── parse_mitm_flows.py   # Parse mitmproxy captures
│   ├── capture_maison_protegee.sh
│   ├── intercept_maison_protegee_android.sh
│   ├── intercept_maison_protegee_ios.sh
│   └── frida/                # Certificate unpinning helpers
└── reverse/                  # RE notes & APK metadata
```

## Regenerate protobuf stubs

After editing `src/maison_protegee/proto/erable.proto`:

```bash
pip install -e ".[dev]"
./scripts/generate_proto.sh
```

## Reverse engineering

Protobuf field numbers were extracted from decompiled Java classes in:

- `com.orange.erable.services.*` (gRPC service)
- `ne/a.java` → host `maison-protegee.orange.fr`
- `com.orange.fr.protegee2.data.base.a` → gRPC metadata headers

The full decompiled APK (~200 MB) can stay in a sibling `ha/` workspace folder and is gitignored here.

Capture / decompile helpers:

```bash
./scripts/extract_apk_urls.py /path/to/app.apk
./scripts/capture_maison_protegee.sh
./scripts/intercept_maison_protegee_android.sh run
./scripts/parse_mitm_flows.py captures/maison_protegee/flows_….mitm
```

See `reverse/NOTES.md` for the RE summary.

## Implemented RPC methods

- `authenticate`
- `getDefaultContract`
- `getGatewayStatus`
- `gatewayCommand`
- `equipmentQueryList`
- `eventQueryList`

67 RPC methods exist in the app; extend `erable.proto` + `client.py` as needed.

## Home Assistant

The custom component is [ha-maison-protegee2](https://github.com/Identity-labs/ha-maison-protegee2). Until this package is on PyPI, that repo vendors a copy via `scripts/sync_ha_lib.sh`. After publish, add `ha-maison-protegee2-api` to the integration `manifest.json` requirements.

## Releasing

Bump `version` in `pyproject.toml`, then push a matching tag:

```bash
git tag v0.1.0
git push origin v0.1.0
```

The [publish](.github/workflows/publish.yml) workflow builds the wheel and sdist, creates a GitHub Release with those artifacts, and uploads them to PyPI.

### First-time PyPI setup

Trusted publishing needs no API token:

1. Create a GitHub Environment named `pypi` (recommended: required reviewers).
2. On [PyPI trusted publishers](https://pypi.org/manage/account/publishing/), add a **pending** publisher:
   - Project name: `ha-maison-protegee2-api`
   - Owner: `Identity-labs`
   - Repository: `ha-maison-protegee2-api`
   - Workflow: `publish.yml`
   - Environment: `pypi`

The first tagged release creates the PyPI project.

## Limitations

- Unofficial API — may break on app updates
- Token refresh re-logs in when JWT is near expiry
- Cameras use a separate WebRTC/signaling stack (`protectline.fr`)
- Use at your own risk; respect Orange ToS
