qubopy 0.1.0__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.
- qubopy-0.1.0/LICENSE +21 -0
- qubopy-0.1.0/PKG-INFO +546 -0
- qubopy-0.1.0/README.md +519 -0
- qubopy-0.1.0/pyproject.toml +60 -0
- qubopy-0.1.0/qubopy/__init__.py +65 -0
- qubopy-0.1.0/qubopy/__main__.py +6 -0
- qubopy-0.1.0/qubopy/auth.py +486 -0
- qubopy-0.1.0/qubopy/cli.py +650 -0
- qubopy-0.1.0/qubopy/client.py +583 -0
- qubopy-0.1.0/qubopy/const.py +78 -0
- qubopy-0.1.0/qubopy/devices/__init__.py +114 -0
- qubopy-0.1.0/qubopy/devices/base.py +140 -0
- qubopy-0.1.0/qubopy/devices/camera.py +152 -0
- qubopy-0.1.0/qubopy/devices/dashcam.py +88 -0
- qubopy-0.1.0/qubopy/devices/light.py +78 -0
- qubopy-0.1.0/qubopy/devices/lock.py +148 -0
- qubopy-0.1.0/qubopy/devices/plug.py +59 -0
- qubopy-0.1.0/qubopy/devices/purifier.py +74 -0
- qubopy-0.1.0/qubopy/devices/sensor.py +52 -0
- qubopy-0.1.0/qubopy/exceptions.py +25 -0
- qubopy-0.1.0/qubopy/models.py +115 -0
- qubopy-0.1.0/qubopy/py.typed +1 -0
- qubopy-0.1.0/qubopy.egg-info/PKG-INFO +546 -0
- qubopy-0.1.0/qubopy.egg-info/SOURCES.txt +32 -0
- qubopy-0.1.0/qubopy.egg-info/dependency_links.txt +1 -0
- qubopy-0.1.0/qubopy.egg-info/entry_points.txt +2 -0
- qubopy-0.1.0/qubopy.egg-info/requires.txt +7 -0
- qubopy-0.1.0/qubopy.egg-info/top_level.txt +1 -0
- qubopy-0.1.0/setup.cfg +4 -0
- qubopy-0.1.0/tests/test_auth.py +416 -0
- qubopy-0.1.0/tests/test_cli.py +88 -0
- qubopy-0.1.0/tests/test_client.py +378 -0
- qubopy-0.1.0/tests/test_devices.py +591 -0
- qubopy-0.1.0/tests/test_lock_ble.py +145 -0
qubopy-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Selva Kumaran K
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
qubopy-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,546 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: qubopy
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Asynchronous Python client library and local BLE enabler for Qubo smart home devices
|
|
5
|
+
Author-email: Selva Kumaran K <selvakk2k@users.noreply.github.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Classifier: Development Status :: 3 - Alpha
|
|
8
|
+
Classifier: Intended Audience :: Developers
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Topic :: Home Automation
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Requires-Python: >=3.10
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Requires-Dist: aiohttp>=3.8.0
|
|
21
|
+
Requires-Dist: pydantic>=2.0.0
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
24
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
25
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
|
|
28
|
+
# Qubo Python Client Library & BLE Enabler (`qubopy`)
|
|
29
|
+
|
|
30
|
+
[](https://badge.fury.io/py/qubopy)
|
|
31
|
+
[](https://pypi.org/project/qubopy/)
|
|
32
|
+
[](https://github.com/selvakk2k/qubopy/releases)
|
|
33
|
+
[](https://github.com/selvakk2k)
|
|
34
|
+
[](https://aiattribution.github.io/interpret-attribution)
|
|
35
|
+
|
|
36
|
+
An asynchronous Python client library and local Bluetooth Low Energy (BLE) credential extraction utility for Qubo smart home devices.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Table of Contents
|
|
41
|
+
|
|
42
|
+
- [Overview](#overview)
|
|
43
|
+
- [Hardware Compatibility Matrix](#hardware-compatibility-matrix)
|
|
44
|
+
- [Installation & CLI Access](#installation--cli-access)
|
|
45
|
+
- [1. From PyPI (Recommended)](#1-from-pypi-recommended)
|
|
46
|
+
- [2. From Source or GitHub Release](#2-from-source-or-github-release)
|
|
47
|
+
- [Authentication & Account Guidelines](#authentication--account-guidelines)
|
|
48
|
+
- [Quick Start](#quick-start)
|
|
49
|
+
- [1. Authentication & Client Setup (Hardware Verified)](#1-authentication--client-setup--hardware-verified)
|
|
50
|
+
- [2. Smart Plugs - HSP Series (API Modeled)](#2-smart-plugs-hsp-series--api-modeled--untested)
|
|
51
|
+
- [3. Air Purifiers - HPH Series (API Modeled)](#3-air-purifiers-hph-series--api-modeled--untested)
|
|
52
|
+
- [4. Smart Lighting - HLB Series (API Modeled)](#4-smart-lighting-hlb-series--api-modeled--untested)
|
|
53
|
+
- [5. Cameras & Doorbells - HCP / HCD Series (Hardware Verified)](#5-cameras--doorbells-hcp--hcd-series--hardware-verified)
|
|
54
|
+
- [6. Dashcams - HCA Series (Hardware Verified)](#6-dashcams-hca-series--hardware-verified)
|
|
55
|
+
- [7. Smart Door Locks - HLM / HLW Series](#7-smart-door-locks-hlm--hlw-series)
|
|
56
|
+
- [Command Line Interface (CLI)](#command-line-interface-cli)
|
|
57
|
+
- [IP Camera & Media Streaming Architecture](#ip-camera--media-streaming-architecture)
|
|
58
|
+
- [Cloud MQTT Broker & Real-Time Telemetry](#cloud-mqtt-broker--real-time-telemetry)
|
|
59
|
+
- [Local BLE Architecture for Smart Locks](#local-ble-architecture-for-smart-locks)
|
|
60
|
+
- [GATT Services and Characteristics](#gatt-services-and-characteristics)
|
|
61
|
+
- [Experimental ESPHome Configuration](#experimental-esphome-configuration)
|
|
62
|
+
- [Contributing & Testing](#contributing--testing)
|
|
63
|
+
- [Credits & License](#credits--license)
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Overview
|
|
68
|
+
|
|
69
|
+
The Qubo smart home ecosystem consists of two distinct communication models:
|
|
70
|
+
|
|
71
|
+
1. **Wi-Fi Appliances (Cloud Managed)**: Smart Plugs, Air Purifiers, Smart Bulbs, and Security Cameras connect outbound to Qubo cloud services over TLS REST and MQTT. `qubopy` interacts with Qubo's cloud REST gateway (`srvcapp.platform.quboworld.com`) to discover units, retrieve shadow states, and dispatch control commands.
|
|
72
|
+
2. **Bluetooth Smart Locks (Dual-Path Control)**: Qubo smart door locks (`HLM`/`HLW` series) operate via Bluetooth Low Energy without an integrated Wi-Fi radio. They can be actuated remotely through an in-home Qubo gateway bridge (Video Doorbell Pro or Smart Camera) or integrated locally by extracting offline cryptographic credentials (`dbtauthkey`) for ESP32 Bluetooth Proxies.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Hardware Compatibility Matrix
|
|
77
|
+
|
|
78
|
+
| Series | Category | Example Models | Functions & Sensors | Integration Mode | Status |
|
|
79
|
+
| :--- | :--- | :--- | :--- | :--- | :--- |
|
|
80
|
+
| **Auth** | Cloud Session | N/A | Email + Password, Phone SMS OTP | Cloud REST (`/user/login?system=CS`, `/phone/verify`) | `✅ Hardware Verified` |
|
|
81
|
+
| `HCP` / `HCO` | Cameras | `HCP01`–`HCP19`, `HCO04`–`HCO07` | RTSP Stream Query, Privacy Mask, Siren, Motion Status | Cloud REST + Local RTSP / P2P | `✅ Hardware Verified` |
|
|
82
|
+
| `HCD` | Doorbells | `HCD01`, `HCD04` | Ring Event, Chime, RTSP Stream / LAN P2P | Cloud REST + Local RTSP / P2P | `✅ Hardware Verified` |
|
|
83
|
+
| `HCA` | Dashcams | `HCA08B`, Smart Dashcam Pro | In-Car Wi-Fi AP Credentials, Parking Mode, Speed Warning | Cloud REST | `✅ Hardware Verified` |
|
|
84
|
+
| `HLM` / `HLW` | Door Locks | `HLM01`–`HLM10`, `HLR01`, `HLW01` | Remote Unlock, Battery Level, Offline BLE Key Export | Cloud Gateway / Local BLE | Gateway: `✅ Hardware Verified`<br>BLE: `⚠️ Experimental` |
|
|
85
|
+
| `HSP` | Smart Plugs | `HSP01` (16A), `HSP02` (10A), `HSP10` | Switch, Voltage, Current, Active Power (W), Energy (kWh) | Cloud REST | `⚠️ API Modeled` |
|
|
86
|
+
| `HPH` | Air Purifiers | `HPH01`–`HPH08` (Q200 to Q1000) | Fan Speed, Auto/Sleep Presets, PM2.5, Filter Life, Child Lock | Cloud REST | `⚠️ API Modeled` |
|
|
87
|
+
| `HLB` | Smart Lighting | `HLB01`, `HLB10` | State, Brightness, RGB Color, White Temperature | Cloud REST | `⚠️ API Modeled` |
|
|
88
|
+
| `HDS` / `HGS` | Security | `HDS01` (Contact), `HGS01` (Gas), `HSA01` (Smoke) | Binary Alarms, Battery Telemetry | Cloud REST | `⚠️ API Modeled` |
|
|
89
|
+
| `HDT` | Climate | `HDT01` | Temperature (°C), Humidity (%) | Cloud REST | `⚠️ API Modeled` |
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Installation & CLI Access
|
|
94
|
+
|
|
95
|
+
### 1. From PyPI (Recommended)
|
|
96
|
+
|
|
97
|
+
Install the library directly using `pip`:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
pip install qubopy
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Once installed, the CLI is available as both a direct executable and a Python module:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
# Using the console entry point
|
|
107
|
+
qubopy --help
|
|
108
|
+
|
|
109
|
+
# Using the Python module runner
|
|
110
|
+
python -m qubopy --help
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### 2. From Source or GitHub Release
|
|
114
|
+
|
|
115
|
+
If building from source or testing a GitHub release archive:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
# Clone the repository
|
|
119
|
+
git clone https://github.com/selvakk2k/qubopy.git
|
|
120
|
+
cd qubopy
|
|
121
|
+
|
|
122
|
+
# Install in editable mode
|
|
123
|
+
pip install -e .
|
|
124
|
+
|
|
125
|
+
# Run the CLI
|
|
126
|
+
python -m qubopy --help
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Authentication & Account Guidelines
|
|
132
|
+
|
|
133
|
+
`qubopy` supports two distinct authentication pathways provided by Qubo cloud services:
|
|
134
|
+
|
|
135
|
+
### 1. Email and Password (Continuous Session with Refresh Tokens)
|
|
136
|
+
* **Session Lifecycle**: Continuous. Qubo returns an `accessToken` along with a valid server-issued `refreshToken`.
|
|
137
|
+
* **Automatic Renewal**: `qubopy` proactively refreshes the access token before expiration using `POST /auth/refresh`.
|
|
138
|
+
* **Target Use Case**: Recommended for permanent Home Assistant integrations and continuous 24/7 cloud polling.
|
|
139
|
+
|
|
140
|
+
### 2. Phone Number and SMS OTP (1-Hour Session / Provisioning Extractor)
|
|
141
|
+
* **Session Lifecycle**: Exactly 1 hour (`exp: 3600s`). Qubo cloud endpoints do not issue a `refreshToken` over the phone verification route.
|
|
142
|
+
* **Account Linkage & Multi-Account Selection**: A single phone number can have multiple profile accounts attached. `qubopy` detects multiple profiles and allows interactive selection or targeted selection via `--profile-index` or `--account-uuid`.
|
|
143
|
+
* **Target Use Case**: Designed as a **local credential and provisioning extractor**:
|
|
144
|
+
* Extracting offline BLE smart lock keys via `qubopy export-ble-keys` for 100% local ESPHome/BLE control without cloud dependence.
|
|
145
|
+
* Exporting in-car Wi-Fi AP SSID and passwords via `qubopy dashcam-wifi` for direct dashcam connectivity.
|
|
146
|
+
* Initial device discovery and stream testing.
|
|
147
|
+
* **Switching to Email for 24/7 Automation**: Accounts originally created via mobile phone in the Qubo mobile app are marked with `accountType: "MOBILE"`. If you require automated 24/7 cloud polling in Home Assistant without hourly SMS re-authentication, register a separate email-based Qubo account.
|
|
148
|
+
|
|
149
|
+
> [!IMPORTANT]
|
|
150
|
+
> **Email Account Registration Guidelines & Constraints**:
|
|
151
|
+
> - **Brand-New Email Address Required**: You **cannot** use an email address that was ever previously added or linked to any mobile phone account. It must be an email address that has **never been associated with any Qubo app or account**.
|
|
152
|
+
> - **Phone Number Re-use is Permitted**: When registering a new email account, the Qubo app will still prompt for a phone number for SMS verification during onboarding. You **can** safely provide the exact same mobile phone number that was used for your mobile account. Login will continue to work seamlessly with your email ID and password!
|
|
153
|
+
> - **Account Type Separation**: Qubo strictly routes authentication based on the registration method:
|
|
154
|
+
> - Accounts created via **email** authenticate using `qubopy login --email <email>` (continuous session with automatic refresh tokens).
|
|
155
|
+
> - Accounts created via **phone number** authenticate using `qubopy login-phone --phone <number>` (1-hour session without refresh tokens).
|
|
156
|
+
> - Attempting to use email and password credentials on an account registered with a phone number will be rejected by the cloud.
|
|
157
|
+
|
|
158
|
+
> [!WARNING]
|
|
159
|
+
> **Mobile App Session Revocation**: When you sign in via `qubopy`, the active session is visible in the official Qubo mobile app under **Account -> Logged In Devices** with the label `Qubopy` (or your custom `--device-name`).
|
|
160
|
+
> Tapping **[Logout]** next to this entry in the mobile app immediately revokes the session on Qubo servers, requiring you to re-authenticate.
|
|
161
|
+
|
|
162
|
+
> [!NOTE]
|
|
163
|
+
> **Operating System File Permissions**: On Linux and macOS, session cache files (`~/.qubopy_session.json`, `~/.qubopy_otp_pending.json`) and device identifiers are created with POSIX `0o600` mode (read/write by owner only). Because Windows NTFS does not enforce POSIX permission bits, Windows users should ensure these files remain within their private user profile directory (`%USERPROFILE%`).
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Quick Start
|
|
168
|
+
|
|
169
|
+
### 1. Authentication & Client Setup (`✅ Hardware Verified`)
|
|
170
|
+
|
|
171
|
+
Authenticate using either your email and password or phone SMS OTP. Developers can pass an optional `device_attribute` parameter to set the friendly device label shown in the official Qubo mobile app:
|
|
172
|
+
|
|
173
|
+
#### Method A: Email and Password Login
|
|
174
|
+
|
|
175
|
+
```python
|
|
176
|
+
import asyncio
|
|
177
|
+
from qubopy import QuboAuth, QuboClient
|
|
178
|
+
|
|
179
|
+
async def main():
|
|
180
|
+
auth = QuboAuth()
|
|
181
|
+
await auth.login_with_email(
|
|
182
|
+
"<email>",
|
|
183
|
+
"<password>",
|
|
184
|
+
device_attribute="Home Assistant", # Optional: custom label in Qubo app (default: "Qubopy")
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
async with QuboClient(auth) as client:
|
|
188
|
+
devices = await client.get_all_devices()
|
|
189
|
+
for dev in devices:
|
|
190
|
+
print(f"- {dev.name} ({dev.model}) [{dev.device_id}]")
|
|
191
|
+
|
|
192
|
+
asyncio.run(main())
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
#### Method B: Phone SMS OTP Login
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
import asyncio
|
|
199
|
+
from qubopy import QuboAuth, QuboClient
|
|
200
|
+
|
|
201
|
+
async def main():
|
|
202
|
+
auth = QuboAuth()
|
|
203
|
+
res = await auth.request_phone_otp(
|
|
204
|
+
"<phone_number>",
|
|
205
|
+
isd_code="+91",
|
|
206
|
+
device_attribute="Home Assistant",
|
|
207
|
+
)
|
|
208
|
+
await auth.verify_phone_otp(
|
|
209
|
+
"<phone_number>",
|
|
210
|
+
"<otp_code>",
|
|
211
|
+
session_uuid=res["uuid"],
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
async with QuboClient(auth) as client:
|
|
215
|
+
devices = await client.get_all_devices()
|
|
216
|
+
for dev in devices:
|
|
217
|
+
print(f"- {dev.name} ({dev.model}) [{dev.device_id}]")
|
|
218
|
+
|
|
219
|
+
asyncio.run(main())
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
### 2. Smart Plugs (HSP Series) (`⚠️ API Modeled / Untested`)
|
|
225
|
+
|
|
226
|
+
*Note: Telemetry fields and power controls are modeled from APK application metadata. Community testing with physical smart plugs is welcome.*
|
|
227
|
+
|
|
228
|
+
```python
|
|
229
|
+
from qubopy.devices import QuboPlug
|
|
230
|
+
|
|
231
|
+
# Assuming 'plug' is an instance of QuboPlug from get_all_devices()
|
|
232
|
+
async def operate_plug(plug: QuboPlug):
|
|
233
|
+
# Toggle power state (or use plug.turn_off())
|
|
234
|
+
await plug.turn_on()
|
|
235
|
+
|
|
236
|
+
# Fetch latest telemetry
|
|
237
|
+
await plug.refresh()
|
|
238
|
+
print(f"Status : {'ON' if plug.is_on else 'OFF'}")
|
|
239
|
+
print(f"Power : {plug.power_watts} W")
|
|
240
|
+
print(f"Voltage: {plug.voltage} V")
|
|
241
|
+
print(f"Current: {plug.current_amps} A")
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
### 3. Air Purifiers (HPH Series) (`⚠️ API Modeled / Untested`)
|
|
247
|
+
|
|
248
|
+
*Note: Speed controls, presets, and sensor readings are modeled from APK application metadata. Community testing with physical air purifiers is welcome.*
|
|
249
|
+
|
|
250
|
+
```python
|
|
251
|
+
from qubopy.devices import QuboAirPurifier
|
|
252
|
+
|
|
253
|
+
async def operate_purifier(purifier: QuboAirPurifier):
|
|
254
|
+
await purifier.turn_on()
|
|
255
|
+
|
|
256
|
+
# Set fan speed (1 to 3) or preset mode ('auto', 'sleep', 'manual')
|
|
257
|
+
await purifier.set_fan_speed(2)
|
|
258
|
+
await purifier.set_mode("auto")
|
|
259
|
+
|
|
260
|
+
# Read sensor values
|
|
261
|
+
await purifier.refresh()
|
|
262
|
+
print(f"PM2.5 : {purifier.pm25} ug/m3")
|
|
263
|
+
print(f"Filter Life : {purifier.filter_life_percent}%")
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
### 4. Smart Lighting (HLB Series) (`⚠️ API Modeled / Untested`)
|
|
269
|
+
|
|
270
|
+
*Note: Lighting state, dimmer, and RGB/CCT attributes are modeled from APK application metadata. Community testing with physical smart bulbs is welcome.*
|
|
271
|
+
|
|
272
|
+
```python
|
|
273
|
+
from qubopy.devices import QuboLight
|
|
274
|
+
|
|
275
|
+
async def operate_light(light: QuboLight):
|
|
276
|
+
# Turn on with custom brightness and color
|
|
277
|
+
await light.turn_on(brightness=80, rgb=(255, 140, 0))
|
|
278
|
+
|
|
279
|
+
# Tune white color temperature
|
|
280
|
+
await light.set_color_temp_kelvin(3000)
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
### 5. Cameras & Doorbells (HCP / HCD Series) (`✅ Hardware Verified`)
|
|
286
|
+
|
|
287
|
+
Query RTSP stream credentials, toggle privacy shutters, and sound deterrent sirens. Cloud RTSP URL minting and LAN P2P H.264 stream decryption are verified on physical hardware:
|
|
288
|
+
|
|
289
|
+
```python
|
|
290
|
+
from qubopy.devices import QuboCamera
|
|
291
|
+
|
|
292
|
+
async def operate_camera(camera: QuboCamera):
|
|
293
|
+
# Query streaming endpoint details
|
|
294
|
+
stream_info = await camera.get_rtsp_info()
|
|
295
|
+
if stream_info.is_supported:
|
|
296
|
+
print(f"RTSP Host : {stream_info.rtsp_url}")
|
|
297
|
+
print(f"Username : {stream_info.username}")
|
|
298
|
+
|
|
299
|
+
# Toggle privacy shutter mode
|
|
300
|
+
await camera.set_privacy_mode(True)
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
### 6. Dashcams (HCA Series) (`✅ Hardware Verified`)
|
|
306
|
+
|
|
307
|
+
Query in-car Wi-Fi AP credentials, parking monitoring status, and overspeed alerts directly from the cloud shadow (even while the vehicle is parked and unpowered):
|
|
308
|
+
|
|
309
|
+
```python
|
|
310
|
+
from qubopy.devices import QuboDashcam
|
|
311
|
+
|
|
312
|
+
# Assuming 'dashcam' is an instance of QuboDashcam from get_all_devices()
|
|
313
|
+
async def inspect_dashcam(dashcam: QuboDashcam):
|
|
314
|
+
await dashcam.refresh()
|
|
315
|
+
print(f"Dashcam Name : {dashcam.name} ({dashcam.model})")
|
|
316
|
+
print(f"Serial Number : {dashcam.serial_number}")
|
|
317
|
+
print(f"In-Car Wi-Fi AP: {dashcam.wifi_ap_ssid}")
|
|
318
|
+
print(f"WPA2 Password : {dashcam.wifi_ap_password}")
|
|
319
|
+
print(f"Parking Mode : {'Enabled' if dashcam.is_parking_monitoring_on else 'Disabled'}")
|
|
320
|
+
print(f"Speed Warning : {dashcam.overspeed_limit} {dashcam.speed_unit}")
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
### 7. Smart Door Locks (HLM / HLW Series)
|
|
326
|
+
|
|
327
|
+
Qubo smart door locks support two distinct integration strategies:
|
|
328
|
+
|
|
329
|
+
#### Method A: Cloud Gateway Unlock (`✅ Hardware Verified`)
|
|
330
|
+
Actuates the lock via an in-home Qubo gateway bridge (such as a Video Doorbell Pro or Smart Camera). Verified on physical hardware with live bolt movement:
|
|
331
|
+
|
|
332
|
+
```python
|
|
333
|
+
from qubopy.devices import QuboLock
|
|
334
|
+
|
|
335
|
+
async def unlock_door(lock: QuboLock):
|
|
336
|
+
# Check if an in-home RF/BLE gateway bridge is active
|
|
337
|
+
if lock.is_gateway_accessible:
|
|
338
|
+
print(f"Paired gateway ID: {lock.gateway_id}")
|
|
339
|
+
result = await lock.unlock()
|
|
340
|
+
print(f"Unlock result: {result}")
|
|
341
|
+
else:
|
|
342
|
+
print("Lock is in standalone Bluetooth mode; use local BLE key export.")
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
#### Method B: Local BLE Offline Credentials (`⚠️ Experimental`)
|
|
346
|
+
|
|
347
|
+
> [!CAUTION]
|
|
348
|
+
> **Untested / Experimental**: The BLE lock credential extraction and GATT definitions below were derived from reverse-engineering the official mobile application. They have **not been tested or verified on physical smart lock hardware**. Testing and contributions from community members with physical locks are welcome.
|
|
349
|
+
|
|
350
|
+
> [!WARNING]
|
|
351
|
+
> **Cryptographic Key Security**: The extracted Bluetooth authentication key (`dbtauthkey`), offline key seed (`dbtoffkey`), and master admin passcode grant physical authorization to actuate the lock bolt. Treat these exported credentials with the same confidentiality as physical keys. Never commit exported credentials to public source control or paste them into unredacted issue reports.
|
|
352
|
+
|
|
353
|
+
Extract offline cryptographic keys for experimental local use with Home Assistant Bluetooth Proxies or ESPHome:
|
|
354
|
+
|
|
355
|
+
```python
|
|
356
|
+
from qubopy.devices import QuboLock
|
|
357
|
+
|
|
358
|
+
async def export_lock_ble(lock: QuboLock):
|
|
359
|
+
keys = await lock.get_ble_lock_keys()
|
|
360
|
+
print("=== Qubo BLE Lock Credentials (Experimental) ===")
|
|
361
|
+
print(f"Device Name: {keys.device_name}")
|
|
362
|
+
print(f"Bluetooth MAC: {keys.mac_address}")
|
|
363
|
+
print(f"Auth Key: {keys.auth_key}")
|
|
364
|
+
print(f"Offline Key: {keys.offline_key}")
|
|
365
|
+
print(f"Admin PIN: {keys.admin_pass}")
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
## Command Line Interface (CLI)
|
|
371
|
+
|
|
372
|
+
`qubopy` provides a command-line interface for authenticating, testing, and inspecting device parameters:
|
|
373
|
+
|
|
374
|
+
```bash
|
|
375
|
+
# Authenticate using email and password (continuous session with refresh token)
|
|
376
|
+
python -m qubopy login --email <email> --password <password>
|
|
377
|
+
|
|
378
|
+
# Authenticate with a custom device label shown in the Qubo mobile app
|
|
379
|
+
python -m qubopy login --email <email> --password <password> --device-name <device_label>
|
|
380
|
+
|
|
381
|
+
# Authenticate using phone number and SMS OTP (interactive prompt with profile selector)
|
|
382
|
+
python -m qubopy login-phone --phone <phone_number> --isd +91
|
|
383
|
+
|
|
384
|
+
# Verify SMS OTP in a separate step (select profile by index or account UUID)
|
|
385
|
+
python -m qubopy verify-otp --otp <otp_code>
|
|
386
|
+
python -m qubopy verify-otp --otp <otp_code> --profile-index 1
|
|
387
|
+
python -m qubopy verify-otp --otp <otp_code> --account-uuid <user_uuid>
|
|
388
|
+
|
|
389
|
+
# List all units and paired devices (alias: 'devices')
|
|
390
|
+
python -m qubopy devices
|
|
391
|
+
python -m qubopy list-devices
|
|
392
|
+
|
|
393
|
+
# Mint live Wowza RTSPS stream URL for cameras (can open in VLC or go2rtc)
|
|
394
|
+
python -m qubopy stream
|
|
395
|
+
python -m qubopy stream --device-id <camera_uuid> --quality high
|
|
396
|
+
|
|
397
|
+
# Fetch in-car Wi-Fi AP credentials (SSID and WPA2 password) for dashcam
|
|
398
|
+
python -m qubopy dashcam-wifi
|
|
399
|
+
|
|
400
|
+
# Export offline BLE credentials (MAC, auth key, offline key) for smart locks
|
|
401
|
+
python -m qubopy export-ble-keys
|
|
402
|
+
python -m qubopy export-ble-keys --device-id <lock_uuid>
|
|
403
|
+
|
|
404
|
+
# Cloud unlock smart lock via paired in-home gateway
|
|
405
|
+
python -m qubopy unlock --device-id <lock_uuid>
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
---
|
|
409
|
+
|
|
410
|
+
## IP Camera & Media Streaming Architecture
|
|
411
|
+
|
|
412
|
+
Qubo security cameras (`HCP` / `HCO` series) and video doorbells (`HCD` series) handle streaming sessions as follows:
|
|
413
|
+
|
|
414
|
+
* **Session Exclusivity**: Streaming URLs minted by Qubo cloud are single-consumer sessions (each URL serves one active stream session).
|
|
415
|
+
* **Local Network Streaming**: The mobile app does not rely on open LAN RTSP ports. Instead, it negotiates direct peer-to-peer (P2P) UDP connections encrypted with AES-128-GCM over RTP.
|
|
416
|
+
* **Downstream Integration**: `qubopy` extracts device identifiers, unit IDs, live tokens, and streaming endpoints so that media engines (such as `go2rtc` and Home Assistant) can connect without third-party tools.
|
|
417
|
+
|
|
418
|
+
---
|
|
419
|
+
|
|
420
|
+
## Cloud MQTT Broker & Real-Time Telemetry
|
|
421
|
+
|
|
422
|
+
In addition to REST-based control, the Qubo ecosystem operates a cloud MQTT broker for real-time telemetry streaming and sub-second push notifications.
|
|
423
|
+
|
|
424
|
+
### 1. Broker Connection Parameters
|
|
425
|
+
|
|
426
|
+
* **Host**: `mqtt.platform.quboworld.com`
|
|
427
|
+
* **Port**: `8883`
|
|
428
|
+
* **Protocol**: TLS / SSL (`ssl://`)
|
|
429
|
+
* **Transport**: TCP over TLS with standard server certificate verification
|
|
430
|
+
|
|
431
|
+
### 2. Dynamic Credential Provisioning
|
|
432
|
+
|
|
433
|
+
The MQTT broker does not use static passwords. Clients provision dynamic MQTT credentials by calling the authenticated REST endpoint:
|
|
434
|
+
|
|
435
|
+
```http
|
|
436
|
+
GET /unit-entity-management/api/v1/sp/d10e4bfb0153496e8e8bb955f7ebe413/agent/device/mqtt/unit/{unit_uuid}/device/{device_uuid}
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
The response provides the dynamic broker credentials:
|
|
440
|
+
|
|
441
|
+
```json
|
|
442
|
+
{
|
|
443
|
+
"username": "<user_uuid>",
|
|
444
|
+
"password": "<dynamic_mqtt_session_secret>",
|
|
445
|
+
"clientId": "<client_or_device_uuid>",
|
|
446
|
+
"serverUrl": "ssl://mqtt.platform.quboworld.com:8883"
|
|
447
|
+
}
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
### 3. Topic Hierarchy & Subscriptions
|
|
451
|
+
|
|
452
|
+
Once authenticated over TLS, clients subscribe to specific event streams:
|
|
453
|
+
|
|
454
|
+
| Stream Type | Topic Pattern | Description |
|
|
455
|
+
| :--- | :--- | :--- |
|
|
456
|
+
| **User Push Events** | `/users/{user_uuid}/events` | Real-time push events for doorbell presses, motion detection, and security alarms. |
|
|
457
|
+
| **Device Telemetry** | `units/{unit_uuid}/devices/{device_uuid}/status` | Live attribute reports including plug power (W), air purifier PM2.5, and sensor metrics. |
|
|
458
|
+
| **Command Channel** | `units/{unit_uuid}/devices/{device_uuid}/command` | Asynchronous command publication channel for cloud-relayed actuation. |
|
|
459
|
+
|
|
460
|
+
---
|
|
461
|
+
|
|
462
|
+
## Local BLE Architecture for Smart Locks
|
|
463
|
+
|
|
464
|
+
> [!CAUTION]
|
|
465
|
+
> **Experimental & Hardware-Unverified**: All BLE lock definitions below were reverse-engineered from application binaries. They have not been validated against physical smart locks.
|
|
466
|
+
|
|
467
|
+
Qubo Bluetooth smart locks store offline parameters in the cloud. The parameters extracted from account metadata include:
|
|
468
|
+
|
|
469
|
+
* `dmac`: Physical Bluetooth MAC address.
|
|
470
|
+
* `dbtauthkey`: Cryptographic session key used during GATT handshake.
|
|
471
|
+
* `dbtoffkey`: Cryptographic seed for computing time-based offline passcodes.
|
|
472
|
+
* `dadminpass`: Master PIN code.
|
|
473
|
+
|
|
474
|
+
### GATT Services and Characteristics
|
|
475
|
+
|
|
476
|
+
* **Main GATT Service**: `0000fee0-0000-1000-8000-00805f9b34fb`
|
|
477
|
+
* **Auth / Write Characteristic**: `0000fee1-0000-1000-8000-00805f9b34fb`
|
|
478
|
+
* **Notify / State Characteristic**: `0000fee2-0000-1000-8000-00805f9b34fb`
|
|
479
|
+
|
|
480
|
+
### Experimental ESPHome Configuration
|
|
481
|
+
|
|
482
|
+
The following configuration demonstrates how an ESP32 board running ESPHome can listen to the lock's state characteristic and dispatch write commands:
|
|
483
|
+
|
|
484
|
+
```yaml
|
|
485
|
+
# Experimental ESPHome Configuration (Untested on Physical Lock Hardware)
|
|
486
|
+
# Requires an ESP32 board with Bluetooth Low Energy enabled
|
|
487
|
+
|
|
488
|
+
esp32_ble_tracker:
|
|
489
|
+
|
|
490
|
+
ble_client:
|
|
491
|
+
- mac_address: "XX:XX:XX:XX:XX:XX" # Replace with exported Bluetooth MAC (dmac)
|
|
492
|
+
id: qubo_lock_ble
|
|
493
|
+
|
|
494
|
+
sensor:
|
|
495
|
+
# Notify/State Characteristic for Lock Status & Battery Telemetry
|
|
496
|
+
- platform: ble_client
|
|
497
|
+
type: characteristic
|
|
498
|
+
ble_client_id: qubo_lock_ble
|
|
499
|
+
id: lock_state
|
|
500
|
+
name: "Qubo Lock State"
|
|
501
|
+
service_uuid: "0000fee0-0000-1000-8000-00805f9b34fb"
|
|
502
|
+
characteristic_uuid: "0000fee2-0000-1000-8000-00805f9b34fb"
|
|
503
|
+
notify: true
|
|
504
|
+
|
|
505
|
+
button:
|
|
506
|
+
# Auth/Write Characteristic for Dispatching Local Handshake Packets
|
|
507
|
+
- platform: template
|
|
508
|
+
name: "Qubo Unlock (Experimental)"
|
|
509
|
+
on_press:
|
|
510
|
+
- ble_client.ble_write:
|
|
511
|
+
id: qubo_lock_ble
|
|
512
|
+
service_uuid: "0000fee0-0000-1000-8000-00805f9b34fb"
|
|
513
|
+
characteristic_uuid: "0000fee1-0000-1000-8000-00805f9b34fb"
|
|
514
|
+
# Payload requires AES handshake using exported dbtauthkey
|
|
515
|
+
value: [0x00]
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
---
|
|
519
|
+
|
|
520
|
+
## Contributing & Testing
|
|
521
|
+
|
|
522
|
+
Run unit tests locally with `pytest`:
|
|
523
|
+
|
|
524
|
+
```bash
|
|
525
|
+
pytest tests/ -v
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
Lint with `ruff`:
|
|
529
|
+
|
|
530
|
+
```bash
|
|
531
|
+
ruff check .
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
---
|
|
535
|
+
|
|
536
|
+
## Credits & License
|
|
537
|
+
|
|
538
|
+
### Disclaimer
|
|
539
|
+
`qubopy` is an independent, open-source project and is not affiliated with, endorsed by, or sponsored by Hero Electronix Pvt. Ltd. or Qubo. All trademarks, service marks, and brand names are property of their respective owners. Use of cloud APIs is subject to Qubo's Terms of Service.
|
|
540
|
+
|
|
541
|
+
### Author & Contributors
|
|
542
|
+
* **Architecture & Lead Engineering**: [@selvakk2k](https://github.com/selvakk2k)
|
|
543
|
+
* **Code Implementation & Engineering**: **Antigravity** (Google DeepMind)
|
|
544
|
+
* **Code Review & Pre-Release Auditing**: **Claude** (Anthropic)
|
|
545
|
+
|
|
546
|
+
Licensed under the **MIT License**. See the [LICENSE](LICENSE) file for details.
|