rvt-monitor 0.2.2__tar.gz → 0.2.4__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.
- rvt_monitor-0.2.4/PKG-INFO +182 -0
- rvt_monitor-0.2.4/README.md +168 -0
- {rvt_monitor-0.2.2 → rvt_monitor-0.2.4}/pyproject.toml +1 -1
- rvt_monitor-0.2.4/rvt_monitor/__main__.py +6 -0
- {rvt_monitor-0.2.2 → rvt_monitor-0.2.4}/rvt_monitor/ble/manager.py +485 -90
- rvt_monitor-0.2.4/rvt_monitor/ble/profiles.py +59 -0
- {rvt_monitor-0.2.2 → rvt_monitor-0.2.4}/rvt_monitor/ble/protocol.py +32 -27
- {rvt_monitor-0.2.2 → rvt_monitor-0.2.4}/rvt_monitor/server/app.py +17 -1
- rvt_monitor-0.2.4/rvt_monitor/server/routes/device.py +127 -0
- {rvt_monitor-0.2.2 → rvt_monitor-0.2.4}/rvt_monitor/server/state.py +3 -0
- {rvt_monitor-0.2.2 → rvt_monitor-0.2.4}/rvt_monitor/server/websocket.py +42 -7
- {rvt_monitor-0.2.2 → rvt_monitor-0.2.4}/rvt_monitor/static/css/style.css +20 -0
- {rvt_monitor-0.2.2 → rvt_monitor-0.2.4}/rvt_monitor/static/index.html +188 -27
- {rvt_monitor-0.2.2 → rvt_monitor-0.2.4}/rvt_monitor/static/js/app.js +275 -50
- rvt_monitor-0.2.2/PKG-INFO +0 -31
- rvt_monitor-0.2.2/README.md +0 -17
- rvt_monitor-0.2.2/rvt_monitor/server/routes/device.py +0 -74
- {rvt_monitor-0.2.2 → rvt_monitor-0.2.4}/.gitignore +0 -0
- {rvt_monitor-0.2.2 → rvt_monitor-0.2.4}/rvt_monitor/__init__.py +0 -0
- {rvt_monitor-0.2.2 → rvt_monitor-0.2.4}/rvt_monitor/ble/__init__.py +0 -0
- {rvt_monitor-0.2.2 → rvt_monitor-0.2.4}/rvt_monitor/ble/scanner.py +0 -0
- {rvt_monitor-0.2.2 → rvt_monitor-0.2.4}/rvt_monitor/core/__init__.py +0 -0
- {rvt_monitor-0.2.2 → rvt_monitor-0.2.4}/rvt_monitor/core/logger.py +0 -0
- {rvt_monitor-0.2.2 → rvt_monitor-0.2.4}/rvt_monitor/isv2_config/__init__.py +0 -0
- {rvt_monitor-0.2.2 → rvt_monitor-0.2.4}/rvt_monitor/isv2_config/cli.py +0 -0
- {rvt_monitor-0.2.2 → rvt_monitor-0.2.4}/rvt_monitor/isv2_config/protocol.py +0 -0
- {rvt_monitor-0.2.2 → rvt_monitor-0.2.4}/rvt_monitor/isv2_config/serial_port.py +0 -0
- {rvt_monitor-0.2.2 → rvt_monitor-0.2.4}/rvt_monitor/isv2_config/server.py +0 -0
- {rvt_monitor-0.2.2 → rvt_monitor-0.2.4}/rvt_monitor/isv2_config/static/index.html +0 -0
- {rvt_monitor-0.2.2 → rvt_monitor-0.2.4}/rvt_monitor/main.py +0 -0
- {rvt_monitor-0.2.2 → rvt_monitor-0.2.4}/rvt_monitor/server/__init__.py +0 -0
- {rvt_monitor-0.2.2 → rvt_monitor-0.2.4}/rvt_monitor/server/routes/__init__.py +0 -0
- {rvt_monitor-0.2.2 → rvt_monitor-0.2.4}/rvt_monitor/server/routes/config.py +0 -0
- {rvt_monitor-0.2.2 → rvt_monitor-0.2.4}/rvt_monitor/server/routes/control.py +0 -0
- {rvt_monitor-0.2.2 → rvt_monitor-0.2.4}/rvt_monitor/server/routes/logs.py +0 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rvt-monitor
|
|
3
|
+
Version: 0.2.4
|
|
4
|
+
Summary: BLE Device Monitor for Ceily/Wally
|
|
5
|
+
Author-email: Rovothome <chandler.kim@rovothome.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Requires-Dist: bleak>=0.21.0
|
|
9
|
+
Requires-Dist: fastapi>=0.109.0
|
|
10
|
+
Requires-Dist: platformdirs>=4.0.0
|
|
11
|
+
Requires-Dist: pyserial>=3.5
|
|
12
|
+
Requires-Dist: uvicorn[standard]>=0.27.0
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
|
|
15
|
+
# RVT-Monitor
|
|
16
|
+
|
|
17
|
+
BLE Device Monitor and Control Tool for Ceily/Wally devices.
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install rvt-monitor
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Or install from source:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
cd rvt-monitor
|
|
29
|
+
pip install -e .
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
rvt-monitor
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Opens web UI at http://127.0.0.1:8000
|
|
39
|
+
|
|
40
|
+
## BLE Protocol Reference
|
|
41
|
+
|
|
42
|
+
### Device Information Service (0x180A)
|
|
43
|
+
|
|
44
|
+
Standard BLE SIG service for device identification.
|
|
45
|
+
|
|
46
|
+
| Characteristic | UUID | Format | Example |
|
|
47
|
+
|----------------|------|--------|---------|
|
|
48
|
+
| Model Number | 0x2A24 | `{device}-p{protocol}` | `ceily-p2`, `wally-p2` |
|
|
49
|
+
| Hardware Revision | 0x2A27 | `v{version}` | `v0`, `v1` |
|
|
50
|
+
| Firmware Revision | 0x2A26 | semver | `2.0.0` |
|
|
51
|
+
|
|
52
|
+
### Custom Services
|
|
53
|
+
|
|
54
|
+
| Service | UUID | Description |
|
|
55
|
+
|---------|------|-------------|
|
|
56
|
+
| Control | `0000ff20-...` | Motion control |
|
|
57
|
+
| System Status | `501a8cf5-98a7-4370-bb97-632c84910000` | Device state |
|
|
58
|
+
| Dimension | `cc9762a6-bbb7-4b21-b2e2-153059030000` | Device config |
|
|
59
|
+
| LED | `07ecc81b-b952-47e6-a1f1-0999577f0000` | LED control |
|
|
60
|
+
| Log | `cc9762a6-bbb7-4b21-b2e2-153059032200` | Event logs |
|
|
61
|
+
|
|
62
|
+
### Motion Commands
|
|
63
|
+
|
|
64
|
+
Write to `MOTION_CONTROL` characteristic (`0x0000ff21-...`):
|
|
65
|
+
|
|
66
|
+
| Command | Value | Ceily | Wally |
|
|
67
|
+
|---------|-------|-------|-------|
|
|
68
|
+
| STOP | 0x00 | Stop | Stop |
|
|
69
|
+
| UP/OPEN | 0x01 | Up | Open |
|
|
70
|
+
| DOWN/CLOSE | 0x02 | Down | Close |
|
|
71
|
+
|
|
72
|
+
### Motion States
|
|
73
|
+
|
|
74
|
+
Read from `SYSTEM_STATUS` characteristic (byte 0):
|
|
75
|
+
|
|
76
|
+
| State | Value | Description |
|
|
77
|
+
|-------|-------|-------------|
|
|
78
|
+
| DOWN/CLOSED | 0 | At bottom/closed position |
|
|
79
|
+
| UP/OPENED | 1 | At top/opened position |
|
|
80
|
+
| MOVING_DOWN | 2 | Moving down/closing |
|
|
81
|
+
| MOVING_UP | 3 | Moving up/opening |
|
|
82
|
+
| STOP | 4 | Stopped mid-motion |
|
|
83
|
+
| EMERGENCY | 5 | Emergency stop |
|
|
84
|
+
| INIT | 255 | Initializing |
|
|
85
|
+
|
|
86
|
+
## Protocol Version Detection
|
|
87
|
+
|
|
88
|
+
### By Device Info Service
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
from bleak import BleakClient
|
|
92
|
+
|
|
93
|
+
MODEL_NUMBER_UUID = "00002a24-0000-1000-8000-00805f9b34fb"
|
|
94
|
+
|
|
95
|
+
async def detect_protocol(client: BleakClient) -> int:
|
|
96
|
+
"""Detect protocol version from Model Number."""
|
|
97
|
+
try:
|
|
98
|
+
data = await client.read_gatt_char(MODEL_NUMBER_UUID)
|
|
99
|
+
model = data.decode("utf-8").rstrip("\x00")
|
|
100
|
+
# Format: "ceily-p2" or "wally-p2"
|
|
101
|
+
if "-p" in model:
|
|
102
|
+
return int(model.split("-p")[1])
|
|
103
|
+
except Exception:
|
|
104
|
+
pass
|
|
105
|
+
return 1 # Legacy fallback
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### By Service Discovery
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
DEVICE_INFO_SERVICE = "0000180a-0000-1000-8000-00805f9b34fb"
|
|
112
|
+
|
|
113
|
+
async def detect_by_services(client: BleakClient) -> int:
|
|
114
|
+
"""Detect by checking for Device Info Service."""
|
|
115
|
+
for service in client.services:
|
|
116
|
+
if service.uuid.lower() == DEVICE_INFO_SERVICE:
|
|
117
|
+
return 2
|
|
118
|
+
return 1 # Legacy (no Device Info Service)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Example: Connect and Control
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
from bleak import BleakClient
|
|
125
|
+
|
|
126
|
+
MOTION_CONTROL_UUID = "0000ff21-0000-1000-8000-00805f9b34fb"
|
|
127
|
+
SYSTEM_STATUS_UUID = "501a8cf5-98a7-4370-bb97-632c84910001"
|
|
128
|
+
|
|
129
|
+
async def control_device(address: str):
|
|
130
|
+
async with BleakClient(address) as client:
|
|
131
|
+
# Read status
|
|
132
|
+
data = await client.read_gatt_char(SYSTEM_STATUS_UUID)
|
|
133
|
+
state = data[0]
|
|
134
|
+
print(f"Current state: {state}")
|
|
135
|
+
|
|
136
|
+
# Send UP command
|
|
137
|
+
await client.write_gatt_char(MOTION_CONTROL_UUID, bytes([0x01]))
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Project Structure
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
rvt-monitor/
|
|
144
|
+
├── rvt_monitor/
|
|
145
|
+
│ ├── ble/
|
|
146
|
+
│ │ ├── manager.py # BLE connection management
|
|
147
|
+
│ │ ├── profiles.py # Protocol version profiles
|
|
148
|
+
│ │ ├── protocol.py # UUID definitions & parsers
|
|
149
|
+
│ │ └── scanner.py # Device discovery
|
|
150
|
+
│ ├── server/
|
|
151
|
+
│ │ ├── app.py # FastAPI server
|
|
152
|
+
│ │ └── routes/ # API endpoints
|
|
153
|
+
│ └── static/ # Web UI
|
|
154
|
+
└── pyproject.toml
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Publishing to PyPI
|
|
158
|
+
|
|
159
|
+
### Via Git Tag (Recommended)
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
# Update version in pyproject.toml first
|
|
163
|
+
git add pyproject.toml
|
|
164
|
+
git commit -m "chore(rvt-monitor): Bump version to x.y.z"
|
|
165
|
+
|
|
166
|
+
# Create and push tag
|
|
167
|
+
git tag rvt-monitor-vX.Y.Z
|
|
168
|
+
git push origin main --tags
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
CI/CD will automatically build and publish to PyPI.
|
|
172
|
+
|
|
173
|
+
### Manual Trigger
|
|
174
|
+
|
|
175
|
+
1. Go to GitHub → Actions
|
|
176
|
+
2. Select "Publish rvt-monitor to PyPI"
|
|
177
|
+
3. Click "Run workflow"
|
|
178
|
+
|
|
179
|
+
## Related
|
|
180
|
+
|
|
181
|
+
- Firmware: `v1/common_components/` - Device-side BLE implementation
|
|
182
|
+
- OTA Tool: `ota/ota.py` - Firmware deployment
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# RVT-Monitor
|
|
2
|
+
|
|
3
|
+
BLE Device Monitor and Control Tool for Ceily/Wally devices.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install rvt-monitor
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or install from source:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
cd rvt-monitor
|
|
15
|
+
pip install -e .
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
rvt-monitor
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Opens web UI at http://127.0.0.1:8000
|
|
25
|
+
|
|
26
|
+
## BLE Protocol Reference
|
|
27
|
+
|
|
28
|
+
### Device Information Service (0x180A)
|
|
29
|
+
|
|
30
|
+
Standard BLE SIG service for device identification.
|
|
31
|
+
|
|
32
|
+
| Characteristic | UUID | Format | Example |
|
|
33
|
+
|----------------|------|--------|---------|
|
|
34
|
+
| Model Number | 0x2A24 | `{device}-p{protocol}` | `ceily-p2`, `wally-p2` |
|
|
35
|
+
| Hardware Revision | 0x2A27 | `v{version}` | `v0`, `v1` |
|
|
36
|
+
| Firmware Revision | 0x2A26 | semver | `2.0.0` |
|
|
37
|
+
|
|
38
|
+
### Custom Services
|
|
39
|
+
|
|
40
|
+
| Service | UUID | Description |
|
|
41
|
+
|---------|------|-------------|
|
|
42
|
+
| Control | `0000ff20-...` | Motion control |
|
|
43
|
+
| System Status | `501a8cf5-98a7-4370-bb97-632c84910000` | Device state |
|
|
44
|
+
| Dimension | `cc9762a6-bbb7-4b21-b2e2-153059030000` | Device config |
|
|
45
|
+
| LED | `07ecc81b-b952-47e6-a1f1-0999577f0000` | LED control |
|
|
46
|
+
| Log | `cc9762a6-bbb7-4b21-b2e2-153059032200` | Event logs |
|
|
47
|
+
|
|
48
|
+
### Motion Commands
|
|
49
|
+
|
|
50
|
+
Write to `MOTION_CONTROL` characteristic (`0x0000ff21-...`):
|
|
51
|
+
|
|
52
|
+
| Command | Value | Ceily | Wally |
|
|
53
|
+
|---------|-------|-------|-------|
|
|
54
|
+
| STOP | 0x00 | Stop | Stop |
|
|
55
|
+
| UP/OPEN | 0x01 | Up | Open |
|
|
56
|
+
| DOWN/CLOSE | 0x02 | Down | Close |
|
|
57
|
+
|
|
58
|
+
### Motion States
|
|
59
|
+
|
|
60
|
+
Read from `SYSTEM_STATUS` characteristic (byte 0):
|
|
61
|
+
|
|
62
|
+
| State | Value | Description |
|
|
63
|
+
|-------|-------|-------------|
|
|
64
|
+
| DOWN/CLOSED | 0 | At bottom/closed position |
|
|
65
|
+
| UP/OPENED | 1 | At top/opened position |
|
|
66
|
+
| MOVING_DOWN | 2 | Moving down/closing |
|
|
67
|
+
| MOVING_UP | 3 | Moving up/opening |
|
|
68
|
+
| STOP | 4 | Stopped mid-motion |
|
|
69
|
+
| EMERGENCY | 5 | Emergency stop |
|
|
70
|
+
| INIT | 255 | Initializing |
|
|
71
|
+
|
|
72
|
+
## Protocol Version Detection
|
|
73
|
+
|
|
74
|
+
### By Device Info Service
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from bleak import BleakClient
|
|
78
|
+
|
|
79
|
+
MODEL_NUMBER_UUID = "00002a24-0000-1000-8000-00805f9b34fb"
|
|
80
|
+
|
|
81
|
+
async def detect_protocol(client: BleakClient) -> int:
|
|
82
|
+
"""Detect protocol version from Model Number."""
|
|
83
|
+
try:
|
|
84
|
+
data = await client.read_gatt_char(MODEL_NUMBER_UUID)
|
|
85
|
+
model = data.decode("utf-8").rstrip("\x00")
|
|
86
|
+
# Format: "ceily-p2" or "wally-p2"
|
|
87
|
+
if "-p" in model:
|
|
88
|
+
return int(model.split("-p")[1])
|
|
89
|
+
except Exception:
|
|
90
|
+
pass
|
|
91
|
+
return 1 # Legacy fallback
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### By Service Discovery
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
DEVICE_INFO_SERVICE = "0000180a-0000-1000-8000-00805f9b34fb"
|
|
98
|
+
|
|
99
|
+
async def detect_by_services(client: BleakClient) -> int:
|
|
100
|
+
"""Detect by checking for Device Info Service."""
|
|
101
|
+
for service in client.services:
|
|
102
|
+
if service.uuid.lower() == DEVICE_INFO_SERVICE:
|
|
103
|
+
return 2
|
|
104
|
+
return 1 # Legacy (no Device Info Service)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Example: Connect and Control
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
from bleak import BleakClient
|
|
111
|
+
|
|
112
|
+
MOTION_CONTROL_UUID = "0000ff21-0000-1000-8000-00805f9b34fb"
|
|
113
|
+
SYSTEM_STATUS_UUID = "501a8cf5-98a7-4370-bb97-632c84910001"
|
|
114
|
+
|
|
115
|
+
async def control_device(address: str):
|
|
116
|
+
async with BleakClient(address) as client:
|
|
117
|
+
# Read status
|
|
118
|
+
data = await client.read_gatt_char(SYSTEM_STATUS_UUID)
|
|
119
|
+
state = data[0]
|
|
120
|
+
print(f"Current state: {state}")
|
|
121
|
+
|
|
122
|
+
# Send UP command
|
|
123
|
+
await client.write_gatt_char(MOTION_CONTROL_UUID, bytes([0x01]))
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Project Structure
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
rvt-monitor/
|
|
130
|
+
├── rvt_monitor/
|
|
131
|
+
│ ├── ble/
|
|
132
|
+
│ │ ├── manager.py # BLE connection management
|
|
133
|
+
│ │ ├── profiles.py # Protocol version profiles
|
|
134
|
+
│ │ ├── protocol.py # UUID definitions & parsers
|
|
135
|
+
│ │ └── scanner.py # Device discovery
|
|
136
|
+
│ ├── server/
|
|
137
|
+
│ │ ├── app.py # FastAPI server
|
|
138
|
+
│ │ └── routes/ # API endpoints
|
|
139
|
+
│ └── static/ # Web UI
|
|
140
|
+
└── pyproject.toml
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Publishing to PyPI
|
|
144
|
+
|
|
145
|
+
### Via Git Tag (Recommended)
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
# Update version in pyproject.toml first
|
|
149
|
+
git add pyproject.toml
|
|
150
|
+
git commit -m "chore(rvt-monitor): Bump version to x.y.z"
|
|
151
|
+
|
|
152
|
+
# Create and push tag
|
|
153
|
+
git tag rvt-monitor-vX.Y.Z
|
|
154
|
+
git push origin main --tags
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
CI/CD will automatically build and publish to PyPI.
|
|
158
|
+
|
|
159
|
+
### Manual Trigger
|
|
160
|
+
|
|
161
|
+
1. Go to GitHub → Actions
|
|
162
|
+
2. Select "Publish rvt-monitor to PyPI"
|
|
163
|
+
3. Click "Run workflow"
|
|
164
|
+
|
|
165
|
+
## Related
|
|
166
|
+
|
|
167
|
+
- Firmware: `v1/common_components/` - Device-side BLE implementation
|
|
168
|
+
- OTA Tool: `ota/ota.py` - Firmware deployment
|