diff --git a/dotbot/controller.py b/dotbot/controller.py
index 04e4bd7a..c7563733 100644
--- a/dotbot/controller.py
+++ b/dotbot/controller.py
@@ -362,9 +362,15 @@ def handle_received_payload(
header,
PayloadType.LH2_LOCATION,
LH2Location(
- int(dotbot.lh2_position.x * 1e6),
- int(dotbot.lh2_position.y * 1e6),
- int(dotbot.lh2_position.z * 1e6),
+ int(
+ dotbot.lh2_position.x
+ * self.lh2_manager.calibration_data.width
+ ),
+ int(
+ dotbot.lh2_position.y
+ * self.lh2_manager.calibration_data.height
+ ),
+ int(dotbot.lh2_position.z * 1e3),
),
)
)
diff --git a/dotbot/frontend/src/DotBots.test.js b/dotbot/frontend/src/DotBots.test.js
index 895198b4..08c52d88 100644
--- a/dotbot/frontend/src/DotBots.test.js
+++ b/dotbot/frontend/src/DotBots.test.js
@@ -84,6 +84,9 @@ const server = setupServer(
rest.get('/controller/lh2/calibration', (req, res, ctx) => {
return res(ctx.json({state: "done"}));
}),
+ rest.get('/controller/lh2/calibration/size', (req, res, ctx) => {
+ return res(ctx.json({width: "100", height: "100"}));
+ }),
rest.put('/controller/dotbots/:address/:application/move_raw', (req, res, ctx) => {
return res();
}),
diff --git a/dotbot/frontend/src/DotBotsMap.js b/dotbot/frontend/src/DotBotsMap.js
index 0ccc142e..1a32fbd3 100644
--- a/dotbot/frontend/src/DotBotsMap.js
+++ b/dotbot/frontend/src/DotBotsMap.js
@@ -4,7 +4,8 @@ import { ApplicationType } from "./constants";
import {
apiFetchLH2CalibrationState, apiApplyLH2Calibration,
- apiAddLH2CalibrationPoint, inactiveAddress
+ apiAddLH2CalibrationPoint, apiFetchLH2MapSize, apiUpdateLH2MapSize,
+ inactiveAddress
} from "./rest";
const referencePoints = [
@@ -169,6 +170,9 @@ export const DotBotsMap = (props) => {
const [ displayGrid, setDisplayGrid ] = useState(true);
const [ calibrationFetched, setCalibrationFetched ] = useState(false);
const [ calibrationState, setCalibrationState ] = useState("unknown");
+ const [ mapSizeFetched, setMapSizeFetched ] = useState(false);
+ const [ mapWidth, setMapWidth ] = useState(200);
+ const [ mapHeight, setMapHeight ] = useState(200);
const [ pointsChecked, setPointsChecked ] = useState([false, false, false, false]);
const fetchCalibrationState = useCallback(async () => {
@@ -178,6 +182,14 @@ export const DotBotsMap = (props) => {
}, [setCalibrationFetched, setCalibrationState]
);
+ const fetchMapSize = useCallback(async () => {
+ const size = await apiFetchLH2MapSize().catch((error) => console.error(error));
+ setMapWidth(size.width);
+ setMapHeight(size.height);
+ setMapSizeFetched(true);
+ }, [setMapSizeFetched, setMapWidth, setMapHeight]
+ );
+
const pointClicked = (index) => {
let pointsCheckedTmp = pointsChecked.slice();
pointsCheckedTmp[index] = true;
@@ -191,6 +203,7 @@ export const DotBotsMap = (props) => {
setCalibrationState("running");
} else if (calibrationState === "ready") {
setCalibrationState("done");
+ apiUpdateLH2MapSize(mapWidth, mapHeight);
apiApplyLH2Calibration();
}
};
@@ -215,10 +228,17 @@ export const DotBotsMap = (props) => {
if (!calibrationFetched) {
fetchCalibrationState();
}
+ if (!mapSizeFetched) {
+ fetchMapSize();
+ }
if (pointsChecked.every(v => v === true)) {
setCalibrationState("ready");
}
- }, [calibrationFetched, fetchCalibrationState, pointsChecked, setCalibrationState]);
+ }, [
+ calibrationFetched, fetchCalibrationState,
+ mapSizeFetched, fetchMapSize,
+ pointsChecked, setCalibrationState
+ ]);
let calibrationButtonLabel = "Start calibration";
let calibrationButtonClass = "btn-primary";
@@ -292,6 +312,15 @@ export const DotBotsMap = (props) => {
props.setHistorySize(event.target.value)}/>
+
+ {/*
+
+
*/}
diff --git a/dotbot/frontend/src/rest.js b/dotbot/frontend/src/rest.js
index 0e0a8709..3188fbfe 100644
--- a/dotbot/frontend/src/rest.js
+++ b/dotbot/frontend/src/rest.js
@@ -86,3 +86,17 @@ export const apiAddLH2CalibrationPoint = async (index) => {
`${process.env.REACT_APP_DOTBOTS_BASE_URL}/controller/lh2/calibration/${index}`,
);
}
+
+export const apiFetchLH2MapSize = async (width, height) => {
+ return await axios.get(
+ `${process.env.REACT_APP_DOTBOTS_BASE_URL}/controller/lh2/calibration/size`,
+ ).then(res => res.data);
+}
+
+export const apiUpdateLH2MapSize = async (width, height) => {
+ return await axios.put(
+ `${process.env.REACT_APP_DOTBOTS_BASE_URL}/controller/lh2/calibration/size`,
+ {width: width, height: height},
+ { headers: { 'Content-Type': 'application/json' } }
+ );
+}
diff --git a/dotbot/lighthouse2.py b/dotbot/lighthouse2.py
index 42f543da..a2857d59 100644
--- a/dotbot/lighthouse2.py
+++ b/dotbot/lighthouse2.py
@@ -17,7 +17,11 @@
import numpy as np
from dotbot.logger import LOGGER
-from dotbot.models import DotBotLH2Position, DotBotCalibrationStateModel
+from dotbot.models import (
+ DotBotLH2Position,
+ DotBotCalibrationStateModel,
+ DotBotCalibrationSizeModel,
+)
from dotbot.protocol import Lh2RawData
@@ -97,6 +101,8 @@ class CalibrationData:
random_rodriguez: np.array
normal: np.array
m: np.array
+ width: int = 200
+ height: int = 200
class LighthouseManagerState(Enum):
@@ -115,6 +121,7 @@ def __init__(self):
self.state = LighthouseManagerState.NotCalibrated
self.reference_points = REFERENCE_POINTS_DEFAULT
Path.mkdir(CALIBRATION_DIR, exist_ok=True)
+ self.calibration_size = DotBotCalibrationSizeModel()
self.calibration_output_path = CALIBRATION_DIR / "calibration.out"
self.calibration_data = self._load_calibration()
self.calibration_points = np.zeros(
@@ -245,13 +252,16 @@ def compute_calibration(self): # pylint: disable=too-many-locals
)
self.calibration_data = CalibrationData(zeta, random_rodriguez, n, M)
-
- with open(self.calibration_output_path, "wb") as output_file:
- pickle.dump(self.calibration_data, output_file)
+ self.save_calibration()
self.state = LighthouseManagerState.Calibrated
self.logger.info("Calibration done", data=self.calibration_data)
+ def save_calibration(self):
+ """Store the calibration data in a file."""
+ with open(self.calibration_output_path, "wb") as output_file:
+ pickle.dump(self.calibration_data, output_file)
+
def compute_position(self, raw_data: Lh2RawData) -> Optional[DotBotLH2Position]:
"""Compute the position coordinates from LH2 raw data and available calibration."""
if self.state != LighthouseManagerState.Calibrated:
diff --git a/dotbot/models.py b/dotbot/models.py
index b8d7acf7..bae8e2b5 100644
--- a/dotbot/models.py
+++ b/dotbot/models.py
@@ -23,6 +23,13 @@ class DotBotCalibrationStateModel(BaseModel):
state: str
+class DotBotCalibrationSizeModel(BaseModel):
+ """Model that holds the width and height of the LH2 calibration whole map."""
+
+ width: int = 200 # size in millimeters
+ height: int = 200
+
+
class DotBotMoveRawCommandModel(BaseModel):
"""Model class that defines a move raw command."""
@@ -46,6 +53,8 @@ class DotBotLH2Position(BaseModel):
x: float
y: float
z: float
+ width: int = 200
+ height: int = 200
class DotBotControlModeModel(BaseModel):
diff --git a/dotbot/protocol.py b/dotbot/protocol.py
index 9e83bf8e..81372c45 100644
--- a/dotbot/protocol.py
+++ b/dotbot/protocol.py
@@ -11,7 +11,7 @@
from dataclasses import dataclass
-PROTOCOL_VERSION = 8
+PROTOCOL_VERSION = 9
class PayloadType(Enum):
@@ -208,17 +208,17 @@ class LH2Location(ProtocolData):
@property
def fields(self) -> List[ProtocolField]:
return [
- ProtocolField(self.pos_x, name="x", length=4),
- ProtocolField(self.pos_y, name="y", length=4),
- ProtocolField(self.pos_z, name="z", length=4),
+ ProtocolField(self.pos_x, name="x", length=2),
+ ProtocolField(self.pos_y, name="y", length=2),
+ ProtocolField(self.pos_z, name="z", length=2),
]
@staticmethod
def from_bytes(bytes_) -> ProtocolData:
return LH2Location(
- int.from_bytes(bytes_[0:4], "little"),
- int.from_bytes(bytes_[4:8], "little"),
- int.from_bytes(bytes_[8:12], "little"),
+ pos_x=int.from_bytes(bytes_[0:2], "little"),
+ pos_y=int.from_bytes(bytes_[2:4], "little"),
+ pos_z=int.from_bytes(bytes_[4:6], "little"),
)
@@ -402,7 +402,7 @@ def from_bytes(bytes_: bytes):
elif payload_type == PayloadType.LH2_RAW_DATA:
values = Lh2RawData.from_bytes(bytes_[25:45])
elif payload_type == PayloadType.LH2_LOCATION:
- values = LH2Location.from_bytes(bytes_[25:37])
+ values = LH2Location.from_bytes(bytes_[25:31])
elif payload_type == PayloadType.ADVERTISEMENT:
values = Advertisement.from_bytes(None)
elif payload_type == PayloadType.GPS_POSITION:
diff --git a/dotbot/server.py b/dotbot/server.py
index bdd02f7f..7d5b54aa 100644
--- a/dotbot/server.py
+++ b/dotbot/server.py
@@ -13,6 +13,7 @@
from dotbot.logger import LOGGER
from dotbot.models import (
DotBotCalibrationStateModel,
+ DotBotCalibrationSizeModel,
DotBotModel,
DotBotQueryModel,
DotBotAddressModel,
@@ -312,6 +313,31 @@ async def controller_get_lh2_calibration():
return app.controller.lh2_manager.state_model
+@app.put(
+ path="/controller/lh2/calibration/size",
+ summary="Set the size of the LH2 map.",
+ tags=["dotbots"],
+)
+async def controller_set_lh2_size(size: DotBotCalibrationSizeModel):
+ """Set the size of the LH2 map."""
+ app.controller.lh2_manager.calibration_data.width = size.width
+ app.controller.lh2_manager.calibration_data.height = size.height
+
+
+@app.get(
+ path="/controller/lh2/calibration/size",
+ response_model=DotBotCalibrationSizeModel,
+ summary="Get the size of the LH2 map.",
+ tags=["dotbots"],
+)
+async def controller_lh2_size():
+ """Set the width of the LH2 map."""
+ return DotBotCalibrationSizeModel(
+ width=app.controller.lh2_manager.calibration_data.width,
+ height=app.controller.lh2_manager.calibration_data.height,
+ )
+
+
@app.websocket("/controller/ws/status")
async def websocket_endpoint(websocket: WebSocket):
"""Websocket server endpoint."""
diff --git a/dotbot/tests/test_protocol.py b/dotbot/tests/test_protocol.py
index 894d27f6..fa40314d 100644
--- a/dotbot/tests/test_protocol.py
+++ b/dotbot/tests/test_protocol.py
@@ -27,7 +27,7 @@
"payload,expected",
[
pytest.param(
- b"\x11\x11\x11\x11\x11\x22\x22\x11\x12\x12\x12\x12\x12\x12\x12\x12\x34\x12\x00\x08\x00\x00\x00\x00\x00\x00\x42\x00\x42",
+ b"\x11\x11\x11\x11\x11\x22\x22\x11\x12\x12\x12\x12\x12\x12\x12\x12\x34\x12\x00\x09\x00\x00\x00\x00\x00\x00\x42\x00\x42",
ProtocolPayload(
ProtocolHeader(
0x1122221111111111,
@@ -43,7 +43,7 @@
id="MoveRaw",
),
pytest.param(
- b"\x11\x11\x11\x11\x11\x22\x22\x11\x12\x12\x12\x12\x12\x12\x12\x12\x34\x12\x00\x08\x00\x00\x00\x00\x01\x42\x42\x42",
+ b"\x11\x11\x11\x11\x11\x22\x22\x11\x12\x12\x12\x12\x12\x12\x12\x12\x34\x12\x00\x09\x00\x00\x00\x00\x01\x42\x42\x42",
ProtocolPayload(
ProtocolHeader(
0x1122221111111111,
@@ -59,7 +59,7 @@
id="RGBLed",
),
pytest.param(
- b"\x88\x77\x66\x55\x44\x33\x22\x11\x21\x12\x22\x12\x22\x12\x22\x12\x42\x14\x00\x08\x00\x00\x00\x00\x02"
+ b"\x88\x77\x66\x55\x44\x33\x22\x11\x21\x12\x22\x12\x22\x12\x22\x12\x42\x14\x00\x09\x00\x00\x00\x00\x02"
b"\x12\x34\x56\x78\x9a\xbc\xde\xf1\x01\x02"
b"\x12\x34\x56\x78\x9a\xbc\xde\xf1\x01\x02",
ProtocolPayload(
@@ -82,8 +82,8 @@
id="LH2RawData",
),
pytest.param(
- b"\x11\x11\x11\x11\x11\x22\x22\x11\x12\x12\x12\x12\x12\x12\x12\x12\x34\x12\x00\x08\x00\x00\x00\x00\x03"
- b"\xe8\x03\x00\x00\xe8\x03\x00\x00\x02\x00\x00\x00",
+ b"\x11\x11\x11\x11\x11\x22\x22\x11\x12\x12\x12\x12\x12\x12\x12\x12\x34\x12\x00\x09\x00\x00\x00\x00\x03"
+ b"\xe8\x03\xe8\x03\x02\x00",
ProtocolPayload(
ProtocolHeader(
0x1122221111111111,
@@ -99,7 +99,7 @@
id="LH2Location",
),
pytest.param(
- b"\x11\x11\x11\x11\x11\x22\x22\x11\x12\x12\x12\x12\x12\x12\x12\x12\x34\x12\x00\x08\x00\x00\x00\x00\x04",
+ b"\x11\x11\x11\x11\x11\x22\x22\x11\x12\x12\x12\x12\x12\x12\x12\x12\x34\x12\x00\x09\x00\x00\x00\x00\x04",
ProtocolPayload(
ProtocolHeader(
0x1122221111111111,
@@ -115,7 +115,7 @@
id="Advertisement",
),
pytest.param(
- b"\x11\x11\x11\x11\x11\x22\x22\x11\x12\x12\x12\x12\x12\x12\x12\x12\x34\x12\x00\x08\x00\x00\x00\x00\x05"
+ b"\x11\x11\x11\x11\x11\x22\x22\x11\x12\x12\x12\x12\x12\x12\x12\x12\x34\x12\x00\x09\x00\x00\x00\x00\x05"
b"&~\xe9\x02]\xe4#\x00",
ProtocolPayload(
ProtocolHeader(
@@ -132,7 +132,7 @@
id="GPSPosition",
),
pytest.param(
- b"\x88\x77\x66\x55\x44\x33\x22\x11\x21\x12\x22\x12\x22\x12\x22\x12\x42\x14\x00\x08\x00\x00\x00\x00\x06"
+ b"\x88\x77\x66\x55\x44\x33\x22\x11\x21\x12\x22\x12\x22\x12\x22\x12\x42\x14\x00\x09\x00\x00\x00\x00\x06"
b"-\x00"
b"\x12\x34\x56\x78\x9a\xbc\xde\xf1\x01\x02"
b"\x12\x34\x56\x78\x9a\xbc\xde\xf1\x01\x02",
@@ -157,7 +157,7 @@
id="DotBotData",
),
pytest.param(
- b"\x11\x11\x11\x11\x11\x22\x22\x11\x12\x12\x12\x12\x12\x12\x12\x12\x34\x12\x00\x08\x00\x00\x00\x00\x07\x01",
+ b"\x11\x11\x11\x11\x11\x22\x22\x11\x12\x12\x12\x12\x12\x12\x12\x12\x34\x12\x00\x09\x00\x00\x00\x00\x07\x01",
ProtocolPayload(
ProtocolHeader(
0x1122221111111111,
@@ -173,9 +173,8 @@
id="ControlMode",
),
pytest.param(
- b"\x88\x77\x66\x55\x44\x33\x22\x11\x21\x12\x22\x12\x22\x12\x22\x12\x42\x14\x00\x08\x00\x00\x00\x00\x08\x02\x0a"
- b"\xe8\x03\x00\x00\xe8\x03\x00\x00\x02\x00\x00\x00"
- b"\xe8\x03\x00\x00\xe8\x03\x00\x00\x02\x00\x00\x00",
+ b"\x88\x77\x66\x55\x44\x33\x22\x11\x21\x12\x22\x12\x22\x12\x22\x12\x42\x14\x00\x09\x00\x00\x00\x00\x08\x02\x0a"
+ b"\xe8\x03\xe8\x03\x02\x00\xe8\x03\xe8\x03\x02\x00",
ProtocolPayload(
ProtocolHeader(
0x1122334455667788,
@@ -191,7 +190,7 @@
id="LH2Waypoints",
),
pytest.param(
- b"\x88\x77\x66\x55\x44\x33\x22\x11\x21\x12\x22\x12\x22\x12\x22\x12\x42\x14\x00\x08\x00\x00\x00\x00\x09\x02\x0a"
+ b"\x88\x77\x66\x55\x44\x33\x22\x11\x21\x12\x22\x12\x22\x12\x22\x12\x42\x14\x00\x09\x00\x00\x00\x00\x09\x02\x0a"
b"&~\xe9\x02]\xe4#\x00&~\xe9\x02]\xe4#\x00",
ProtocolPayload(
ProtocolHeader(
@@ -208,7 +207,7 @@
id="GPSWaypoints",
),
pytest.param(
- b"\x88\x77\x66\x55\x44\x33\x22\x11\x21\x12\x22\x12\x22\x12\x22\x12\x42\x14\x00\x08\x00\x00\x00\x00\x0a"
+ b"\x88\x77\x66\x55\x44\x33\x22\x11\x21\x12\x22\x12\x22\x12\x22\x12\x42\x14\x00\x09\x00\x00\x00\x00\x0a"
b"-\x00&~\xe9\x02]\xe4#\x00",
ProtocolPayload(
ProtocolHeader(
@@ -225,12 +224,12 @@
id="SailBotData",
),
pytest.param(
- b"\x11\x22\x22\x11\x11\x11\x11\x11\x12\x12\x12\x12\x12\x12\x12\x12\x00\x00\x00\x08\x00\x00\x00\x00\xff",
+ b"\x11\x22\x22\x11\x11\x11\x11\x11\x12\x12\x12\x12\x12\x12\x12\x12\x00\x00\x00\x09\x00\x00\x00\x00\xff",
ValueError("255 is not a valid PayloadType"),
id="invalid payload",
),
pytest.param(
- b"\x11\x22\x22\x11\x11\x11\x11\x11\x12\x12\x12\x12\x12\x12\x12\x12\x00\x00\x00\x08\x00\x00\x00\x00\x0b",
+ b"\x11\x22\x22\x11\x11\x11\x11\x11\x12\x12\x12\x12\x12\x12\x12\x12\x00\x00\x00\x09\x00\x00\x00\x00\x0b",
ProtocolPayloadParserException("Unsupported payload type '11'"),
id="unsupported payload type",
),
@@ -333,7 +332,7 @@ def test_protocol_parser(payload, expected):
LH2Location(1000, 1000, 2),
),
b"\x88\x77\x66\x55\x44\x33\x22\x11\x21\x12\x22\x12\x22\x12\x22\x12\x42\x14\x00\x01\x00\x00\x00\x00\x03"
- b"\xe8\x03\x00\x00\xe8\x03\x00\x00\x02\x00\x00\x00",
+ b"\xe8\x03\xe8\x03\x02\x00",
id="LH2Location",
),
pytest.param(
@@ -392,8 +391,7 @@ def test_protocol_parser(payload, expected):
),
),
b"\x88\x77\x66\x55\x44\x33\x22\x11\x21\x12\x22\x12\x22\x12\x22\x12\x42\x14\x00\x01\x00\x00\x00\x00\x08\x02\x0a"
- b"\xe8\x03\x00\x00\xe8\x03\x00\x00\x02\x00\x00\x00"
- b"\xe8\x03\x00\x00\xe8\x03\x00\x00\x02\x00\x00\x00",
+ b"\xe8\x03\xe8\x03\x02\x00\xe8\x03\xe8\x03\x02\x00",
id="LH2Waypoints",
),
pytest.param(
@@ -495,14 +493,10 @@ def test_payload(payload, expected):
LH2Location(1000, 1000, 2),
),
(
- " +----------------------------------+----------------------------------+----------+------+------+------------------+------+\n"
- " LH2_LOCATION | dst | src | swarm id | app. | ver. | msg id | type |\n"
- " (37 Bytes) | 0x1122334455667788 | 0x1222122212221221 | 0x2442 | 0x00 | 0x01 | 0x00000000 | 0x03 |\n"
- " +----------------------------------+----------------------------------+----------+------+------+------------------+------+\n"
- " +------------------+------------------+------------------+\n"
- " | x | y | z |\n"
- " | 0x000003e8 | 0x000003e8 | 0x00000002 |\n"
- " +------------------+------------------+------------------+\n"
+ " +----------------------------------+----------------------------------+----------+------+------+------------------+------+----------+----------+----------+\n"
+ " LH2_LOCATION | dst | src | swarm id | app. | ver. | msg id | type | x | y | z |\n"
+ " (31 Bytes) | 0x1122334455667788 | 0x1222122212221221 | 0x2442 | 0x00 | 0x01 | 0x00000000 | 0x03 | 0x03e8 | 0x03e8 | 0x0002 |\n"
+ " +----------------------------------+----------------------------------+----------+------+------+------------------+------+----------+----------+----------+\n"
"\n"
),
id="LH2Location",
@@ -593,12 +587,12 @@ def test_payload(payload, expected):
(
" +----------------------------------+----------------------------------+----------+------+------+------------------+------+\n"
" LH2_WAYPOINTS | dst | src | swarm id | app. | ver. | msg id | type |\n"
- " (51 Bytes) | 0x1122334455667788 | 0x1222122212221221 | 0x2442 | 0x00 | 0x01 | 0x00000000 | 0x08 |\n"
+ " (39 Bytes) | 0x1122334455667788 | 0x1222122212221221 | 0x2442 | 0x00 | 0x01 | 0x00000000 | 0x08 |\n"
" +----------------------------------+----------------------------------+----------+------+------+------------------+------+\n"
- " +------+------+------------------+------------------+------------------+------------------+------------------+------------------+\n"
- " | len. | thr. | x | y | z | x | y | z |\n"
- " | 0x02 | 0x0a | 0x000003e8 | 0x000003e8 | 0x00000002 | 0x000003e8 | 0x000003e8 | 0x00000002 |\n"
- " +------+------+------------------+------------------+------------------+------------------+------------------+------------------+\n"
+ " +------+------+----------+----------+----------+----------+----------+----------+\n"
+ " | len. | thr. | x | y | z | x | y | z |\n"
+ " | 0x02 | 0x0a | 0x03e8 | 0x03e8 | 0x0002 | 0x03e8 | 0x03e8 | 0x0002 |\n"
+ " +------+------+----------+----------+----------+----------+----------+----------+\n"
"\n"
),
id="LH2Waypoints",
diff --git a/dotbot/tests/test_server.py b/dotbot/tests/test_server.py
index f3d20b89..d42bd3be 100644
--- a/dotbot/tests/test_server.py
+++ b/dotbot/tests/test_server.py
@@ -14,6 +14,7 @@
DotBotMoveRawCommandModel,
DotBotRgbLedCommandModel,
DotBotCalibrationStateModel,
+ DotBotCalibrationSizeModel,
DotBotControlModeModel,
DotBotGPSPosition,
DotBotLH2Position,
@@ -49,6 +50,9 @@ def controller():
app.controller.lh2_manager = MagicMock()
app.controller.lh2_manager.state_model = DotBotCalibrationStateModel(state="test")
app.controller.notify_clients = AsyncMock()
+ app.controller.lh2_manager.calibration_data = MagicMock()
+ app.controller.lh2_manager.calibration_data.width = 100
+ app.controller.lh2_manager.calibration_data.height = 100
app.controller.send_payload = MagicMock()
app.controller.settings = MagicMock()
app.controller.settings.gw_address = "0000"
@@ -684,6 +688,24 @@ async def test_lh2_calibration():
calibration.assert_called_once()
+@pytest.mark.asyncio
+async def test_lh2_calibration_size():
+ response = await client.get("/controller/lh2/calibration/size")
+ assert (
+ response.json()
+ == DotBotCalibrationSizeModel(width=100, height=100).model_dump()
+ )
+ assert response.status_code == 200
+
+ response = await client.put(
+ "/controller/lh2/calibration/size",
+ json=DotBotCalibrationSizeModel(width=300, height=400).model_dump(),
+ )
+ assert response.status_code == 200
+ assert app.controller.lh2_manager.calibration_data.width == 300
+ assert app.controller.lh2_manager.calibration_data.height == 400
+
+
@pytest.mark.asyncio
async def test_ws_client():
with TestClient(app).websocket_connect("/controller/ws/status") as websocket:
diff --git a/tox.ini b/tox.ini
index 26e30de7..78241dde 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
[tox]
-envlist = tests,check
+envlist = check,tests
skip_missing_interpreters = true
isolated_build = true