2424from openscan_firmware .models .camera import Camera , CameraType
2525from openscan_firmware .models .motor import Motor , Endstop
2626from openscan_firmware .models .light import Light
27+ from openscan_firmware .models .trigger import Trigger
2728from openscan_firmware .models .scanner import (
2829 ScannerDevice ,
2930 ScannerDeviceConfig ,
3940from openscan_firmware .config .motor import MotorConfig
4041from openscan_firmware .config .light import LightConfig
4142from openscan_firmware .config .endstop import EndstopConfig
43+ from openscan_firmware .config .trigger import TriggerConfig
4244from openscan_firmware .config .cloud import (
4345 load_cloud_settings_from_env ,
4446 set_cloud_settings ,
6062 remove_motor_controller
6163from openscan_firmware .controllers .hardware .lights import create_light_controller , get_all_light_controllers , remove_light_controller , \
6264 get_light_controller
65+ from openscan_firmware .controllers .hardware .triggers import (
66+ create_trigger_controller ,
67+ get_all_trigger_controllers ,
68+ remove_trigger_controller ,
69+ )
6370from openscan_firmware .controllers .hardware .endstops import EndstopController
6471from openscan_firmware .controllers .hardware .gpio import cleanup_all_pins
6572
@@ -88,6 +95,7 @@ def _create_default_scanner_device() -> ScannerDevice:
8895 cameras = {},
8996 motors = {},
9097 lights = {},
98+ triggers = {},
9199 endstops = {},
92100 )
93101 # beware, PrivateAttr are NOT initialized in constructor
@@ -105,6 +113,7 @@ def _create_default_scanner_device() -> ScannerDevice:
105113 cameras = {},
106114 motors = {},
107115 lights = {},
116+ triggers = {},
108117 endstops = {},
109118).model_dump (mode = "json" )
110119
@@ -129,6 +138,7 @@ def _runtime_to_persisted_config() -> ScannerDeviceConfig:
129138 },
130139 motors = {name : motor .settings for name , motor in _scanner_device .motors .items ()},
131140 lights = {name : light .settings for name , light in _scanner_device .lights .items ()},
141+ triggers = {name : trigger .settings for name , trigger in _scanner_device .triggers .items ()},
132142 endstops = {
133143 name : PersistedEndstopConfig (settings = endstop .settings )
134144 for name , endstop in _scanner_device .endstops .items ()
@@ -256,6 +266,7 @@ def get_device_info():
256266 "cameras" : {name : controller .get_status () for name , controller in get_all_camera_controllers ().items ()},
257267 "motors" : {name : controller .get_status () for name , controller in get_all_motor_controllers ().items ()},
258268 "lights" : {name : controller .get_status () for name , controller in get_all_light_controllers ().items ()},
269+ "triggers" : {name : controller .get_status () for name , controller in get_all_trigger_controllers ().items ()},
259270
260271 "motors_timeout" : _scanner_device .motors_timeout ,
261272 "startup_mode" : _scanner_device .startup_mode ,
@@ -295,6 +306,15 @@ def _load_light_config(settings: dict) -> LightConfig:
295306 return LightConfig ()
296307
297308
309+ def _load_trigger_config (settings : dict ) -> TriggerConfig :
310+ """Load trigger configuration for the current model."""
311+ try :
312+ return TriggerConfig (** settings )
313+ except Exception as e :
314+ logger .error ("Error loading trigger settings: " , e )
315+ raise
316+
317+
298318def _load_endstop_config (settings : dict ) -> EndstopConfig :
299319 """Helper function to load and validate endstop settings from a dictionary."""
300320 try :
@@ -523,6 +543,8 @@ async def _initialize_with_config(config: dict | ScannerDeviceConfig, detect_cam
523543 remove_motor_controller (controller )
524544 for controller in get_all_light_controllers ():
525545 remove_light_controller (controller )
546+ for controller in get_all_trigger_controllers ():
547+ remove_trigger_controller (controller )
526548 for controller in get_all_camera_controllers ():
527549 remove_camera_controller (controller )
528550 cleanup_all_pins ()
@@ -561,6 +583,16 @@ async def _initialize_with_config(config: dict | ScannerDeviceConfig, detect_cam
561583 light_objects [light_name ] = light
562584 logger .debug (f"Loaded light { light_name } with settings: { light .settings } " )
563585
586+ # Create trigger objects
587+ trigger_objects = {}
588+ for trigger_name in config_dict ["triggers" ]:
589+ trigger = Trigger (
590+ name = trigger_name ,
591+ settings = _load_trigger_config (config_dict ["triggers" ][trigger_name ])
592+ )
593+ trigger_objects [trigger_name ] = trigger
594+ logger .debug (f"Loaded trigger { trigger_name } with settings: { trigger .settings } " )
595+
564596 # Cloud settings
565597 persistent_settings = load_persistent_cloud_settings ()
566598 if persistent_settings :
@@ -635,6 +667,12 @@ async def _initialize_with_config(config: dict | ScannerDeviceConfig, detect_cam
635667 except Exception as e :
636668 logger .error (f"Error initializing light controller for { name } : { e } " )
637669
670+ for name , trigger in trigger_objects .items ():
671+ try :
672+ create_trigger_controller (trigger )
673+ except Exception as e :
674+ logger .error (f"Error initializing trigger controller for { name } : { e } " )
675+
638676 # initialize project manager
639677 try :
640678 project_manager = get_project_manager ()
@@ -652,6 +690,7 @@ async def _initialize_with_config(config: dict | ScannerDeviceConfig, detect_cam
652690 cameras = camera_objects ,
653691 motors = motor_objects ,
654692 lights = light_objects ,
693+ triggers = trigger_objects ,
655694 endstops = endstop_objects ,
656695
657696 # motors timeout in seconds - 0 to disable
0 commit comments