-
Notifications
You must be signed in to change notification settings - Fork 30
segmenter: Introduce live segmentation #854
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
1bb0c14
fa90d49
cc2ad8c
b2a4265
81dac17
291b924
1e3df1d
73e82d8
fa0ca2a
7efebd5
cab29be
4a881ea
da8bd58
c4ff0f2
742121b
efbf771
b8ac594
1362391
ad68a28
1b9f4de
7fc6eb4
f6f22e5
4e94cb2
8e80405
6ce95d2
055274c
951abb2
06ef9b5
392b194
c075703
451f99b
74627f0
89ec927
7be0035
a7a0a59
2bb4fe3
2d9c33c
699c459
a6bb031
ea9d6c4
c13eced
ef9bd25
e4c28db
698f8a2
dbf0ce1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -133,7 +133,10 @@ def run_step(self) -> typing.Optional[tuple[int, str]]: | |||||||||||||||
| + f"{capture_path}...", | ||||||||||||||||
| ) | ||||||||||||||||
| self._camera.capture_file(capture_path) | ||||||||||||||||
| os.sync() | ||||||||||||||||
| # FIX: Use fsync on specific file to ensure write completes before MQTT publish | ||||||||||||||||
| # os.sync() is system-wide and async - doesn't guarantee this file is written | ||||||||||||||||
| with open(capture_path, "rb") as f: | ||||||||||||||||
| os.fsync(f.fileno()) | ||||||||||||||||
|
Comment on lines
+136
to
+139
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
makes sense I'm going to benchmark this as part of https://github.com/fairscope/PlanktoScope3/issues/375 to measure impact but I agree we should do this anyway at least until we optimize sequence of events and start capturing n+1 before n finished writing
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||||||||
| # Note(ethanjli): updating the integrity file is the responsibility of the code which | ||||||||||||||||
| # calls this `run_step()` method. | ||||||||||||||||
|
|
||||||||||||||||
|
|
||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,6 +21,8 @@ | |
| pump_max_speed = 50 | ||
|
|
||
| pump_started = False | ||
| # FIX: Track acquisition state to prevent UI commands from interrupting acquisition | ||
| acquisition_in_progress = False | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is something I wanted to have as well 👍 However it doesn't belong in the controller. controllers should only concern themselves with providing a simple hardware API. Ideally we have a backend app handling "business logic". Until then we can do that logic in the node-red frontend. WDYT? |
||
|
|
||
| pump_stepper = Motor(pin=23, spi_bus=0, spi_device=0) | ||
| pump_stepper.acceleration = 2000 | ||
|
|
@@ -52,19 +54,40 @@ async def start() -> None: | |
| async with client, task_group: | ||
| _ = await asyncio.gather( | ||
| client.subscribe("actuator/pump"), | ||
| client.subscribe("status/imager"), # FIX: Track acquisition state | ||
| # publish_status(), | ||
| ) | ||
| async for message in client.messages: | ||
| task_group.create_task(handle_message(message)) | ||
|
|
||
|
|
||
| async def handle_message(message) -> None: | ||
| global acquisition_in_progress | ||
|
|
||
| # FIX: Handle imager status messages to track acquisition state | ||
| if message.topic.matches("status/imager"): | ||
| payload = json.loads(message.payload.decode("utf-8")) | ||
| status = payload.get("status", "") | ||
| if status == "Started": | ||
| print("Acquisition started - locking pump for acquisition commands only") | ||
| acquisition_in_progress = True | ||
| elif status in ("Done", "Interrupted"): | ||
| print("Acquisition ended - unlocking pump for manual control") | ||
| acquisition_in_progress = False | ||
| return | ||
|
|
||
| if not message.topic.matches("actuator/pump"): | ||
| return | ||
|
|
||
| payload = json.loads(message.payload.decode("utf-8")) | ||
| pprint(payload) | ||
|
|
||
| # FIX: During acquisition, only accept commands tagged with from_acquisition | ||
| is_from_acquisition = payload.get("from_acquisition", False) | ||
| if acquisition_in_progress and not is_from_acquisition: | ||
| print(f"Ignoring pump command during acquisition (use from_acquisition flag): {payload}") | ||
| return | ||
|
|
||
| action = payload.get("action") | ||
| if action is not None: | ||
| await handle_action(action, payload) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2183,8 +2183,8 @@ | |
| "initialize": "", | ||
| "finalize": "", | ||
| "libs": [], | ||
| "x": 650, | ||
| "y": 180, | ||
| "x": 710, | ||
| "y": 140, | ||
| "wires": [ | ||
| [] | ||
| ] | ||
|
|
@@ -2557,7 +2557,7 @@ | |
| "templateScope": "widget:ui", | ||
| "className": "", | ||
| "x": 800, | ||
| "y": 180, | ||
| "y": 200, | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please revert unrelated changes ( |
||
| "wires": [ | ||
| [ | ||
| "1db1c2e3e19e85ff" | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I introduced the retained messages. Can you elaborate on what the issue is? Maybe with a sequence of pseudo events.