Skip to content

feat: add opt-in contextual execution event bus - #1198

Open
j0nch wants to merge 12 commits into
PyLabRobot:mainfrom
j0nch:feat/contextual-event-bus
Open

feat: add opt-in contextual execution event bus#1198
j0nch wants to merge 12 commits into
PyLabRobot:mainfrom
j0nch:feat/contextual-event-bus

Conversation

@j0nch

@j0nch j0nch commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Introduces an opt-in, in-process structured EventBus for contextual PLR execution events.

  • Adds pylabrobot.events with a synchronous fan-out EventBus, scoped/default bus helpers, inherited operation context, JSON-friendly resource/coordinate references, and correlated started / completed / failed operation events.
  • Adds optional diagnostic transport events for serial, USB, and FTDI I/O, plus Hamilton USB firmware commands; these are intentionally distinct from semantic frontend operations.
  • Preserves direct operated-resource identity in event payloads while including structural ancestry for consumers that need a higher-level view.
  • Keeps normal execution unchanged when no EventBus subscriber is registered; observer exceptions are isolated from hardware control flow.
  • Adds focused coverage for the EventBus and each instrumented frontend.

Current implementation coverage

This is deliberately an initial, opt-in implementation. It does not automatically instrument every PLR device or public method.

Currently instrumented frontends:

  • legacy.machines.Machine: setup, stop
  • legacy.storage.Incubator: fetch_plate, take_in_plate
  • legacy.liquid_handling.LiquidHandler: resource pickup/move/drop, tip pickup/drop, 96-head tip pickup/drop, aspirate, and dispense
  • legacy.shaking.Shaker: shake, stop_shaking
  • legacy.temperature_controlling.TemperatureController: set temperature, wait for temperature, deactivate
  • brooks.precise_flex.PreciseFlex: lifecycle, fault/home/freedrive, joint/cartesian/rail/gripper motion, pick/drop, and park

Diagnostic transport coverage, not semantic frontend-operation coverage:

  • io.Serial, io.USB, and io.FTDI: io.read and io.write
  • hamilton.transport.usb.HamiltonUSBDriver: firmware.command.started, .completed, and .failed

These records are complementary diagnostic coverage: semantic events describe PLR-level operations, while diagnostic events describe the transport and controller activity performed to execute them.

Proposed driver-adoption contract

New and existing drivers can adopt EventBus support incrementally at their public semantic API boundaries. The included EventBus operation semantics guide defines:

  • lifecycle naming and operation-ID correlation;
  • required device and direct-resource references;
  • resource-transfer, liquid-handling, tip-handling, thermal/shaking, and arm/controller templates;
  • failure-event behavior and unit-bearing quantitative fields; and
  • a contributor test checklist.

The guide intentionally does not require irrelevant fields for every device. Drivers should describe what their PLR frontend actually did, while downstream consumers derive their own display or protocol views from the structured references.

Dependency

This branch is intentionally stacked on #1194 (f0f05d513, real-time legacy arm resource-state updates ported to main). Until #1194 merges, this PR's comparison against main includes that commit. Once it lands, this branch will be rebased onto upstream main so this PR contains only the EventBus changes.

Event model

Semantic operations emit correlated lifecycle records such as:

liquid_handler.resource_pickup.started
liquid_handler.resource_pickup.completed
liquid_handler.resource_pickup.failed

The event context carries a stable operation ID and can be augmented by callers with execution context. Event data identifies the issuing device and direct PLR resources, without requiring consumers to infer resource identity from controller-level commands.

@j0nch
j0nch marked this pull request as ready for review August 11, 2026 01:55
@rickwierenga

Copy link
Copy Markdown
Member

this is sick! very nice

  • I dont think it should apply to legacy since we want to keep that code as similar as possible
  • can you write a simple user guide / move some contributor things out of that tutorial and move it into one for users? basically most is user information right now.
  • individual device pages in the user guide would benefit from a page on which events are emitted with which lifecycle options. ideally we include that for the devices that are also getting the life cycle events in this PR (many devices will be added later)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants