as
This commit is contained in:
+38
-5
@@ -1,15 +1,23 @@
|
||||
#!/usr/bin/env python3
|
||||
"""GATT service 0xA000 — Sensor Report + Slot & Config."""
|
||||
"""GATT service 0xA000 — Sensor Report + Interval + Slot & Config."""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import time
|
||||
from typing import Callable, Optional
|
||||
|
||||
from config import CHAR_REPORT_UUID, CHAR_SLOT_UUID, POLL_PERIOD_S, SERVICE_UUID
|
||||
from config import (
|
||||
CHAR_INTERVAL_UUID,
|
||||
CHAR_REPORT_UUID,
|
||||
CHAR_SLOT_UUID,
|
||||
DEFAULT_REPORT_INTERVAL_MIN,
|
||||
SERVICE_UUID,
|
||||
)
|
||||
from protocol import (
|
||||
CFG_JOIN_OPEN,
|
||||
CFG_POOL_FULL,
|
||||
SLOT_UNASSIGNED,
|
||||
pack_interval_min,
|
||||
pack_slot_config,
|
||||
unpack_report,
|
||||
)
|
||||
@@ -19,7 +27,8 @@ log = logging.getLogger("collector.gatt")
|
||||
|
||||
WriteHandler = Callable[[str, bytes], None]
|
||||
ReadSlotHandler = Callable[[str], bytes]
|
||||
ConnectHandler = Callable[[str], bool] # return False → should disconnect
|
||||
ReadIntervalHandler = Callable[[], bytes]
|
||||
ConnectHandler = Callable[[str], bool]
|
||||
DisconnectHandler = Callable[[str], None]
|
||||
|
||||
|
||||
@@ -29,8 +38,10 @@ class CollectorGatt:
|
||||
def __init__(self, registry: Registry):
|
||||
self.registry = registry
|
||||
self._current_addr: Optional[str] = None
|
||||
self.report_interval_min: int = DEFAULT_REPORT_INTERVAL_MIN
|
||||
self.on_write: Optional[WriteHandler] = None
|
||||
self.on_read_slot: Optional[ReadSlotHandler] = None
|
||||
self.on_read_interval: Optional[ReadIntervalHandler] = None
|
||||
self.on_connect: Optional[ConnectHandler] = None
|
||||
self.on_disconnect: Optional[DisconnectHandler] = None
|
||||
|
||||
@@ -40,7 +51,11 @@ class CollectorGatt:
|
||||
def current_addr(self) -> Optional[str]:
|
||||
return self._current_addr
|
||||
|
||||
def period_s(self) -> int:
|
||||
return max(1, int(self.report_interval_min) * 60)
|
||||
|
||||
def handle_write(self, characteristic, value: bytearray, **kwargs) -> None:
|
||||
t0 = time.monotonic()
|
||||
try:
|
||||
data = bytes(value) if value is not None else b""
|
||||
addr = self._current_addr or kwargs.get("address") or ""
|
||||
@@ -59,11 +74,21 @@ class CollectorGatt:
|
||||
self.on_write(addr, data)
|
||||
except Exception as e:
|
||||
log.error("write handler error: %s", e)
|
||||
finally:
|
||||
dt_ms = (time.monotonic() - t0) * 1000.0
|
||||
if dt_ms >= 5.0:
|
||||
log.info("write-handler %.1f ms", dt_ms)
|
||||
else:
|
||||
log.debug("write-handler %.2f ms", dt_ms)
|
||||
|
||||
def handle_read(self, characteristic, **kwargs) -> bytearray:
|
||||
try:
|
||||
uuid = str(getattr(characteristic, "uuid", "") or "").lower()
|
||||
addr = self._current_addr or kwargs.get("address") or ""
|
||||
if CHAR_INTERVAL_UUID.lower() in uuid or "a002" in uuid:
|
||||
if self.on_read_interval:
|
||||
return bytearray(self.on_read_interval())
|
||||
return bytearray(pack_interval_min(self.report_interval_min))
|
||||
if CHAR_SLOT_UUID.lower() in uuid or "a011" in uuid:
|
||||
if self.on_read_slot:
|
||||
return bytearray(self.on_read_slot(addr))
|
||||
@@ -81,7 +106,7 @@ class CollectorGatt:
|
||||
flags |= CFG_JOIN_OPEN
|
||||
else:
|
||||
flags |= CFG_POOL_FULL
|
||||
return pack_slot_config(slot, flags, POLL_PERIOD_S)
|
||||
return pack_slot_config(slot, flags, self.period_s())
|
||||
|
||||
|
||||
async def build_bless_server(gatt: CollectorGatt, loop, name: str):
|
||||
@@ -98,7 +123,6 @@ async def build_bless_server(gatt: CollectorGatt, loop, name: str):
|
||||
|
||||
await server.add_new_service(SERVICE_UUID)
|
||||
|
||||
# Signature: (service, char, properties, value, permissions)
|
||||
# Sensor Report — write-without-response
|
||||
await server.add_new_characteristic(
|
||||
SERVICE_UUID,
|
||||
@@ -109,6 +133,15 @@ async def build_bless_server(gatt: CollectorGatt, loop, name: str):
|
||||
GATTAttributePermissions.writeable,
|
||||
)
|
||||
|
||||
# Report Interval — read (2 bytes LE, minutes)
|
||||
await server.add_new_characteristic(
|
||||
SERVICE_UUID,
|
||||
CHAR_INTERVAL_UUID,
|
||||
GATTCharacteristicProperties.read,
|
||||
bytearray(pack_interval_min(gatt.report_interval_min)),
|
||||
GATTAttributePermissions.readable,
|
||||
)
|
||||
|
||||
# Slot & Config — read
|
||||
await server.add_new_characteristic(
|
||||
SERVICE_UUID,
|
||||
|
||||
Reference in New Issue
Block a user