Schedules GATT Characteristic
UUID: b77abf7f-66b5-4899-821d-efb177843783
Service: Shelly (de8a5aac-a99b-c315-0c80-60d4cbb51225)
All multi-byte values are little-endian. Temperature target is an IEEE 754 float (4 bytes LE).
Max 10 rules (IDs 0-9). Timespec is a 6-field cron string: SEC MIN HOUR DOM MON DOW.
Read
Returns all active rules packed sequentially, terminated by 0xFF:
repeat per rule:
┌──────────┬──────────┬────────────────┬──────────┬──────────────────┐
│ rule_id │ enable │ target │ ts_len │ timespec │
│ uint8 │ uint8 │ float (4B LE) │ uint8 │ char[ts_len] │
└──────────┴──────────┴────────────────┴──────────┴──────────────────┘
terminator:
┌──────┐
│ 0xFF │
└──────┘
*target <= 1.0 stands for valve position in percent / 100. Otherwise target is target_temperature_C
Example
Device has two rules — rule 0 (enabled, 21.5 °C, weekdays 07:00) and rule 3 (disabled, 18.0 °C, daily 22:30):
00 01 00 00 ac 41 11 30 20 30 20 37 20 2a 20 2a 20 4d 4f 4e 2d 46 52 49
03 00 00 00 90 41 0d 30 20 33 30 20 32 32 20 2a 20 2a 20 2a
ff
Breakdown:
| Bytes | Field | Value |
|---|---|---|
00 | rule_id | 0 |
01 | enable | 1 (yes) |
00 00 ac 41 | target | 21.5 °C |
11 | ts_len | 17 |
30 20 … 49 | timespec | 0 0 7 * * MON-FRI |
03 | rule_id | 3 |
00 | enable | 0 (no) |
00 00 90 41 | target | 18.0 °C |
0d | ts_len | 13 |
30 20 … 2a | timespec | 0 30 22 * * * |
ff | terminator | — |
Empty device returns a single byte: ff.
Write
Add rule (0x01)
Assigns the first free rule ID automatically.
┌──────┬──────────┬────────────────┬──────────┬──────────────────┐
│ 0x01 │ enable │ target │ ts_len │ timespec │
│ │ uint8 │ float (4B LE) │ uint8 │ char[ts_len] │
└──────┴──────────┴────────────────┴──────────┴──────────────────┘
Example — add enabled rule, 21.5 °C, weekdays at 07:00 (0 0 7 * * MON-FRI):
01 01 00 00 ac 41 11 30 20 30 20 37 20 2a 20 2a 20 4d 4f 4e 2d 46 52 49
Update rule (0x02)
Modifies an existing rule by ID.
┌──────┬──────────┬──────────┬────────────────┬──────────┬──────────────────┐
│ 0x02 │ rule_id │ enable │ target │ ts_len │ timespec │
│ │ uint8 │ uint8 │ float (4B LE) │ uint8 │ char[ts_len] │
└──────┴──────────┴──────────┴────────────────┴──────────┴──────────────────┘
Example — update rule 0, enabled, 18.0 °C, daily at 22:30 (0 30 22 * * *):
02 00 01 00 00 90 41 0d 30 20 33 30 20 32 32 20 2a 20 2a 20 2a
Remove rule (0x03)
┌──────┬──────────┐
│ 0x03 │ rule_id │
│ │ uint8 │
└──────┴──────────┘
Example — remove rule 2:
03 02
Remove all (0xFF)
┌──────┐
│ 0xFF │
└──────┘
Example:
ff
Error responses
Write errors are returned as ATT status codes:
| ATT status | Meaning |
|---|---|
0x00 | Success |
0x0D | Invalid length (missing fields, ts_len mismatch) |
0x11 | Out of range (rule_id >= 10) |
0x13 | Value not allowed (rule_id does not exist) |
0x11 | Insufficient resources (no free slot on add) |
0x06 | Request not supported (unknown command byte) |
Reference float values
| °C | Hex (LE) |
|---|---|
| 5.0 | 00 00 a0 40 |
| 18.0 | 00 00 90 41 |
| 20.0 | 00 00 a0 41 |
| 21.0 | 00 00 a8 41 |
| 21.5 | 00 00 ac 41 |
| 22.0 | 00 00 b0 41 |
| 25.0 | 00 00 c8 41 |
| 30.0 | 00 00 f0 41 |
GUI tool
A Python/Tkinter GUI tool is included for interactively managing schedule rules over BLE.
Prerequisites
- Python 3.8+
- bleak BLE library
pip install bleak
Usage
Run the tool from the repository root:
python3 docs-ble/Devices/BLU_ZB/tools/schedules.py
The GUI allows you to:
- Read all schedule rules currently on the device
- Add a new rule (auto-assigned ID)
- Update an existing rule by ID
- Remove a single rule or all rules
Enter the device MAC address (e.g. AA:BB:CC:DD:EE:FF) and click Read Schedules to connect.
Source
The script is located at tools/schedules.py.
Click to expand full source code
#!/usr/bin/env python3
"""
Shelly TRV Schedule Manager — BLE GATT GUI Tool
Connects to a Shelly TRV device over BLE to read/write schedule rules
via the 'schedules' GATT characteristic (UUID b77abf7f-66b5-4899-821d-efb177843783).
"""
import asyncio, math, struct, sys
import tkinter as tk, tkinter.font as tkfont
from tkinter import ttk, messagebox
from typing import List, Optional
try:
from bleak import BleakClient, BleakError
except ImportError:
print("ERROR: 'bleak' package is required. Install with: pip install bleak")
sys.exit(1)
SCHEDULES_CHAR_UUID = "b77abf7f-66b5-4899-821d-efb177843783"
BLE_CONNECT_TIMEOUT = 30
MAX_RULES = 10
CMD_ADD, CMD_UPDATE, CMD_REMOVE, CMD_REMOVE_ALL = 0x01, 0x02, 0x03, 0xFF
# ... (full source in tools/schedules.py)