Skip to content

Commit

Permalink
add everything for two device calibration
Browse files Browse the repository at this point in the history
  • Loading branch information
svhoy committed May 15, 2024
1 parent 694ac49 commit 6ec740c
Show file tree
Hide file tree
Showing 9 changed files with 497 additions and 153 deletions.
90 changes: 52 additions & 38 deletions apps/sit_gateway/adapter/ble.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@

# Third Party
from bleak import BleakClient
from bleak.backends.device import BLEDevice
from bleak.backends.characteristic import BleakGATTCharacteristic
from apps.sit_gateway.adapter.exceptions import BleDataException
from bleak.backends.device import BLEDevice

from apps.sit_gateway.domain.data import MsgData
# Library
from apps.sit_gateway.adapter.exceptions import BleDataException
from apps.sit_gateway.domain.data import MsgData, SimpleMsgData


LOG_CONFIG_PATH = "settings/logging.conf"
Expand All @@ -29,7 +30,7 @@ def __init__(self, gateway) -> None:
self._client: BleakClient | None
self._is_connected: bool = False
self._connected_device: BLEDevice | None
self._callback: Callable
self._notify_callback: Callable

def _set_client(self, device: BLEDevice):
self._client = BleakClient(device.address, self._on_disconnect)
Expand All @@ -53,7 +54,7 @@ async def connect_device(self, device: BLEDevice):
if not self._is_connected:
break
await asyncio.sleep(5.0)
except Exception as e: #pylint: disable=broad-exception-caught
except Exception as e:
logger.error(f"Exeption: {e}")
self._connected_device = None
self._client = None
Expand All @@ -66,38 +67,43 @@ async def cleanup(self):
if self._client is not None:
await self.disconnect_device()

async def _on_disconnect(self, client: BleakClient): #pylint: disable=unused-argument
async def _on_disconnect(self, client: BleakClient):
logger.info(f"Disconnected from {self._connected_device.name}!")
self._connected_device = None
self._is_connected = False
self._gateway.is_running = False

async def write_command(self, uuid: str, byte_data):
try:
await self._client.write_gatt_char(uuid, byte_data)
logger.info(f"Send {byte_data} to Periphal")
except Exception as e: #pylint: disable=broad-exception-caught
except Exception as e: # pylint: disable=broad-exception-caught
logger.error(f"Exeption: {e}")

async def get_notification(self, uuid: str, callback: Callable) -> None:
self._callback = callback
self._notify_callback = callback
await self._client.start_notify(uuid, self.on_distance_notification)

async def on_distance_notification(
self,
sender: BleakGATTCharacteristic,
data: bytearray,
): #pylint: disable=unused-argument
self,
sender: BleakGATTCharacteristic,
data: bytearray,
): # pylint: disable=unused-argument
# Datatype 15 char[] (c string) and f->float and I->uint32_t and H->uint8_t
msg_structure = "15s 15s H I I f f f f f"
msg_structure_all = "15s 15s H I I f f f f f f f H H"
logger.debug(f"MSG Structure: {struct.calcsize(msg_structure)}")
logger.debug(f"All MSG Structure: {struct.calcsize(msg_structure_all)}")
dstwr_msg_structure = "15s 15s H I I f f f f f"
simple_msg_sturcture = "15s I I f f f f f f f f f f f f f f f I"
dstwr_msg_structure_all = "15s 15s H I I f f f f f f f H H"
logger.debug(f"MSG Structure: {struct.calcsize(dstwr_msg_structure)}")
logger.debug(
f"All MSG Structure: {struct.calcsize(dstwr_msg_structure_all)}"
)
logger.debug(
f"Simple MSG Structure: {struct.calcsize(simple_msg_sturcture)}"
)
logger.debug(f"Data Lenght: {len(data)}")
try:
if (struct.calcsize(msg_structure)) == len(data):
msg_data_buf = struct.unpack(
msg_structure, data
)
if (struct.calcsize(dstwr_msg_structure)) == len(data):
msg_data_buf = struct.unpack(dstwr_msg_structure, data)
msg_data = MsgData(
msg_type=msg_data_buf[0].decode("utf-8"),
state=msg_data_buf[1].decode("utf-8"),
Expand All @@ -110,10 +116,8 @@ async def on_distance_notification(
time_reply_1=msg_data_buf[8],
time_reply_2=msg_data_buf[9],
)
elif (struct.calcsize(msg_structure_all)) == len(data):
msg_data_buf = struct.unpack(
msg_structure_all, data
)
elif (struct.calcsize(dstwr_msg_structure_all)) == len(data):
msg_data_buf = struct.unpack(dstwr_msg_structure_all, data)
msg_data = MsgData(
msg_type=msg_data_buf[0].decode("utf-8"),
state=msg_data_buf[1].decode("utf-8"),
Expand All @@ -129,24 +133,34 @@ async def on_distance_notification(
rssi=msg_data_buf[10],
fpi=msg_data_buf[11],
)
elif (struct.calcsize(simple_msg_sturcture)) == len(data):
msg_data_buf = struct.unpack(simple_msg_sturcture, data)
msg_data = SimpleMsgData(
msg_type=msg_data_buf[0].decode("utf-8"),
sequence=msg_data_buf[1],
measurement=msg_data_buf[2],
time_m21=msg_data_buf[3],
time_m31=msg_data_buf[4],
time_a21=msg_data_buf[5],
time_a31=msg_data_buf[6],
time_b21=msg_data_buf[7],
time_b31=msg_data_buf[8],
time_tc_i=msg_data_buf[9],
time_tc_ii=msg_data_buf[10],
time_tb_i=msg_data_buf[11],
time_tb_ii=msg_data_buf[12],
time_round_1=msg_data_buf[13],
time_round_2=msg_data_buf[14],
time_reply_1=msg_data_buf[15],
time_reply_2=msg_data_buf[16],
distance=msg_data_buf[17],
)
else:
raise BleDataException(f"Data length not correct: {len(data)}")
except struct.error as e:
logger.error(f"Execption - {e}")
# msg_type = msg_type_b.decode("utf-8")
# state = state_b.decode("utf-8")
# logger.debug("From Handle {} Msg_Type: {}".format(sender, msg_type))
# logger.debug("From Handle {} Sequence: {}".format(sender, sequence))
# logger.debug(
# "From Handle {} Measurements: {}".format(sender, measurements)
# )
# logger.debug("From Handle {} Distance: {}".format(sender, distance))
# logger.debug("From Handle {} NLOS: {}".format(sender, nlos))
# logger.debug("From Handle {} RSSI: {}".format(sender, rssi))
# logger.debug("From Handle {} FPI: {}".format(sender, fpi))
await self._callback(
msg_data
)

await self._notify_callback(msg_data, self._connected_device.name)

def is_connected(self):
return self._is_connected
Expand Down
28 changes: 25 additions & 3 deletions apps/sit_gateway/domain/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


@dataclass
class Command: #pylint: disable=R0801
class Command: # pylint: disable=R0801
@property
def __dict__(self):
buf_dict = {}
Expand Down Expand Up @@ -64,8 +64,10 @@ class StartTestMeasurement(Command):
min_measurement: int
max_measurement: int
measurement_type: str = "ds_3_twr"
rx_ant_dly: int = 0
tx_ant_dly: int = 0
init_rx_ant_dly: float = 0
init_tx_ant_dly: float = 0
resp_rx_ant_dly: float = 0
resp_tx_ant_dly: float = 0


@dataclass
Expand All @@ -78,6 +80,26 @@ class StartCalibrationMeasurement(Command):
tx_ant_dly: int = 0


@dataclass
class StartSimpleCalibrationMeasurement(Command):
calibration_id: int
devices: list[str]
max_measurement: int
measurement_type: str = "two_device"
rx_ant_dly: int = 0
tx_ant_dly: int = 0


@dataclass
class StartSingleCalibrationMeasurement(Command):
pass


@dataclass
class StartDebugCalibration(Command):
calibration_id: int
devices: list[str]
measurement_type: str = "simple"
max_measurement: int = 0
rx_ant_dly: int = 0
tx_ant_dly: int = 0
27 changes: 26 additions & 1 deletion apps/sit_gateway/domain/data.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
# Standard Library
import dataclasses
import time


@dataclasses.dataclass
class MsgData:
msg_type: str
state: str
responder: int
sequence: int
measurement: float
measurement: int
distance: float
time_round_1: float
time_round_2: float
Expand All @@ -15,3 +18,25 @@ class MsgData:
nlos: int = 0
rssi: float = 0.0
fpi: float = 0.0


@dataclasses.dataclass
class SimpleMsgData:
msg_type: str
sequence: int
measurement: int
time_m21: float
time_m31: float
time_a21: float
time_a31: float
time_b21: float
time_b31: float
time_tc_i: float
time_tc_ii: float
time_tb_i: float
time_tb_ii: float
time_round_1: float
time_round_2: float
time_reply_1: float
time_reply_2: float
distance: float
42 changes: 38 additions & 4 deletions apps/sit_gateway/domain/events.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
#pylint: disable=R0801
# pylint: disable=R0801
# Standard Library
from dataclasses import asdict, dataclass
from json import dumps
from turtle import distance


@dataclass
class Event: #pylint: disable=R0801
class Event: # pylint: disable=R0801
@property
def __dict__(self):
buf_dict = {}
Expand Down Expand Up @@ -69,7 +70,7 @@ class TestMeasurement(Event):
responder: str
measurement_type: str
sequence: int
measurement: int #pylint: disable=R0801
measurement: int # pylint: disable=R0801
distance: float
time_round_1: float
time_round_2: float
Expand All @@ -87,7 +88,7 @@ class CalibrationMeasurement(Event):
responder: str
measurement_type: str
sequence: int
measurement: int #pylint: disable=R0801
measurement: int # pylint: disable=R0801
distance: float
time_round_1: float
time_round_2: float
Expand All @@ -98,11 +99,39 @@ class CalibrationMeasurement(Event):
fpi: float


@dataclass
class SimpleCalibrationMeasurement(Event):
calibration_id: int
sequence: int
measurement: int
devices: list[str]
time_m21: float
time_m31: float
time_a21: float
time_a31: float
time_b21: float
time_b31: float
time_tc_i: float
time_tc_ii: float
time_tb_i: float
time_tb_ii: float
time_round_1: float
time_round_2: float
time_reply_1: float
time_reply_2: float
distance: float


@dataclass
class CalibrationMeasurementFinished(Event):
calibration_id: int


@dataclass
class CalibrationSimpleMeasurementFinished(Event):
calibration_id: int


@dataclass
class CalibrationCalFinished(Event):
pass
Expand All @@ -111,3 +140,8 @@ class CalibrationCalFinished(Event):
@dataclass
class PositionMeasurement(Event):
pass


@dataclass
class TestMeasurementFinished(Event):
test_id: int
26 changes: 17 additions & 9 deletions apps/sit_gateway/entrypoint/websocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,24 @@ class Websocket:
_websocket: websockets.client.WebSocketClientProtocol
_uri: str
dataclasses: dict

def __init__(
self,
#
host: str = "ws://192.168.0.101:8000/",
# host: str = "ws://192.168.137.1:8000/",
# host: str = "ws://192.168.56.1:8000/",
path: str = "ws/sit/1",
) -> None:
# self._auth = Authenticator()
# self._auth.login()
self._uri = host + path
self.dataclasses = self.find_dataclasses_in_directory()


async def connect(self, bus):
logger.debug(f"Try Connected to: {self._uri}")
async for _websocket in websockets.client.connect(self._uri):

self._websocket = _websocket
await bus.handle(commands.RegisterWsClient("PI_Home"))
try:
Expand All @@ -61,10 +65,14 @@ async def recive(self, data_msg, bus):
data["type"], data["data"]
)
if not (
isinstance(message, (events.BleDeviceConnected,
events.BleDeviceConnectFailed,
events.BleDeviceConnectError,
))
isinstance(
message,
(
events.BleDeviceConnected,
events.BleDeviceConnectFailed,
events.BleDeviceConnectError,
),
)
):
await bus.handle(message)
except ValueError as e:
Expand Down Expand Up @@ -93,10 +101,10 @@ def find_dataclasses_in_directory(self):
logger.debug(f"Package Found: {package}")

for (
importer, #pylint: disable=unused-variable
modname,
ispkg, #pylint: disable=unused-variable
) in pkgutil.walk_packages(
importer, # pylint: disable=unused-variable
modname,
ispkg, # pylint: disable=unused-variable
) in pkgutil.walk_packages(
path=package.__path__, prefix=package.__name__ + "."
):
module = importlib.import_module(modname)
Expand Down
Loading

0 comments on commit 6ec740c

Please sign in to comment.