From 1bc27fcaaa4a44ca593a1b6ca5f6314f133b3bfe Mon Sep 17 00:00:00 2001 From: Elijah AB Date: Wed, 19 Nov 2025 14:18:55 -0800 Subject: [PATCH 01/12] Initial commit for ATC fw Daemon --- daemons/hsfei/atcfwheel | 149 +++++++++++++++++++++++++++++++++++++ daemons/hsfei/hsfei.config | 8 ++ hispec/util/sunpower | 2 +- 3 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 daemons/hsfei/atcfwheel create mode 100644 daemons/hsfei/hsfei.config diff --git a/daemons/hsfei/atcfwheel b/daemons/hsfei/atcfwheel new file mode 100644 index 0000000..b18683e --- /dev/null +++ b/daemons/hsfei/atcfwheel @@ -0,0 +1,149 @@ +#!/usr/bin/python3 + +import argparse +import logging +import sys +import configparser +from typing import Dict, Any +from libby.daemon import LibbyDaemon +from hispec.util.thorlabs.fw102c import FilterWheelController + +class atcfwheel(LibbyDaemon): + peer_id = "atcfwheel" + transport = "rabbitmq" + #address_book = { + # "pi_1_daemon": "tcp://131.215.200.218:5560" + #} + discovery_enabled = False + discovery_interval_s = 5.0 + rabbitmq_url = "amqp://localhost" # RabbitMQ on hispec + daemon_desc = "ATC FWheel" + + # pub/sub topics + topics = {} + + def __init__(self): + """Initialize the pickoff daemon. + + Args: come from the hsfei configuration file + """ + #on start set up the daemon from config and initialize device + config = configparser.ConfigParser() + config.read('hsfei.config') + self.host = config["Device Control"]["atcfwheel_host"] + self.port = int(config["Device Control"]["atcfwheel_port"]) + + self.dev = FilterWheelController() + self.dev.set_connection(ip = self.host, port = self.port) + + # Daemon state + self.state = { + 'connected': False, + 'error': '', + } + + # Setup logging + self.logger = logging.getLogger(self.peer_id) + + # Call parent __init__ first + super().__init__() + + def on_start(self, libby): + # Add services + self.logger.info(f"Starting {self.daemon_desc} Daemon") + self.add_services({ + "connect": lambda p: self.connect(), + "disconnect": lambda p: self.disconnect(), + "initialize": lambda p: self.initialize(), + "status": lambda p: self.status(), + "get.position": lambda p: self.get_pos(), + "set.position": lambda p: self.set_pos(pos = p.get("position")) + }) + + try: + self.connect() + self.logger.info(f"Connected to {self.daemon_desc}") + self.initialize() + self.logger.info(f"Initialized {self.daemon_desc}") + #publish to libby + libby.publish("atcfwheel", {"Daemon Startup": "Success"}) + except Exception as e: + self.logger.error(f"Error Connecting and Initializing {self.daemon_desc}") + #publish failure + libby.publish("atcfwheel", {"Daemon Startup": "Failed", "Connection Error": f"{e}"}) + + + def on_stop(self, libby): + #Disconnect and let user know + try: + self.disconnect() + self.logger.info(f"Disconnected {self.daemon_desc}") + libby.publish("atcfwheel", {"Daemon Shutdown": "Success"}) + except Exception as e: + libby.publish("atcfwheel", {"Daemon Startup": "Failed", "Error":f"{e}"}) + self.logger.error(f"Disconnect {self.daemon_desc}:: Failed ") + + + def connect(self): + #handles connection + try: + self.dev.connect() + self.logger.info(f"Connected {self.daemon_desc}") + except Exception as e: + self.logger.error(F"Error: {e}") + return {"Connect": "Failed", "Error": f"{e}"} + return {"Connect": "Success"} + + def disconnect(self): + #handles disconnection + try: + self.dev.disconnect() + self.logger.info(f"Disconnected from {self.daemon_desc}") + except Exception as e: + self.logger.error(F"Error: {e}") + return {"Disconnect": "Failed", "Error": f"{e}"} + return {"Disconnect": "Success"} + + def initialize(self): + #handles initialization + # for PPC102_Coms, this involves setting the enabled status + try: + self.dev.initialize() + except Exception as e: + self.logger.error(F"Error: {e}") + return {"Initialize": "Failed", "Error": f"{e}"} + return {"Initialize": "Success"} + + def status(self): + #handles status + try: + status = self.dev.get_status() + self.logger.debug(f"status: {status}") + except Exception as e: + self.logger.error(F"Error: {e}") + return {"status": "Failed", "Error": f"{e}"} + return {"Status": status} + + def get_pos(self): + #gets current position + try: + position = self.dev.get_pos() + self.logger.debug(f"get_pos: {position}") + except Exception as e: + self.logger.error(F"Error: {e}") + return {"get_pos": "Failed", "Error": f"{e}"} + return {"Position": str(position)} + + def set_pos(self, pos): + #sets current position + try: + position = int(pos) + self.dev.set_pos(pos = position) + self.logger.debug(f"set_pos: {position}") + except Exception as e: + self.logger.error(F"Error: {e}") + return {"Move": "Failed", "Error": f"{e}"} + return {"Move": "Success"} + +if __name__ == "__main__": + atcfwheel().serve() \ No newline at end of file diff --git a/daemons/hsfei/hsfei.config b/daemons/hsfei/hsfei.config new file mode 100644 index 0000000..18896ac --- /dev/null +++ b/daemons/hsfei/hsfei.config @@ -0,0 +1,8 @@ +# Config file for daemon references across FEI daemons + +[Device Control] +atcpress_host = feiinficon +atcpress_port = 8000 + +atcfwheel_host = feilantronix +atcfwheel_port = 10010 \ No newline at end of file diff --git a/hispec/util/sunpower b/hispec/util/sunpower index fba751c..7363bb3 160000 --- a/hispec/util/sunpower +++ b/hispec/util/sunpower @@ -1 +1 @@ -Subproject commit fba751c640203f5e0131c56e64ccb015c13455c3 +Subproject commit 7363bb3f10204056a5056b63aa6f58a633d6d4e0 From c4ad5c6b23dffc8837e6f6270b024cdce0e9f172 Mon Sep 17 00:00:00 2001 From: Elijah AB Date: Wed, 19 Nov 2025 15:14:19 -0800 Subject: [PATCH 02/12] Slight updates --- daemons/hsfei/atcfwheel | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) mode change 100644 => 100755 daemons/hsfei/atcfwheel diff --git a/daemons/hsfei/atcfwheel b/daemons/hsfei/atcfwheel old mode 100644 new mode 100755 index b18683e..9765c53 --- a/daemons/hsfei/atcfwheel +++ b/daemons/hsfei/atcfwheel @@ -56,8 +56,8 @@ class atcfwheel(LibbyDaemon): "disconnect": lambda p: self.disconnect(), "initialize": lambda p: self.initialize(), "status": lambda p: self.status(), - "get.position": lambda p: self.get_pos(), - "set.position": lambda p: self.set_pos(pos = p.get("position")) + "position.get": lambda p: self.get_pos(), + "position.set": lambda p: self.set_pos(pos = p.get("position")) }) try: @@ -132,7 +132,7 @@ class atcfwheel(LibbyDaemon): except Exception as e: self.logger.error(F"Error: {e}") return {"get_pos": "Failed", "Error": f"{e}"} - return {"Position": str(position)} + return {"position": str(position)} def set_pos(self, pos): #sets current position From a5855332db168285004801d75e95db8e4bc1645c Mon Sep 17 00:00:00 2001 From: Elijah AB Date: Mon, 24 Nov 2025 16:43:46 -0800 Subject: [PATCH 03/12] First implementation of named positions --- daemons/hsfei/atcfwheel | 75 ++++++++++++++++++++++++-------------- daemons/hsfei/hsfei.config | 13 ++++++- 2 files changed, 59 insertions(+), 29 deletions(-) diff --git a/daemons/hsfei/atcfwheel b/daemons/hsfei/atcfwheel index 9765c53..ed03ceb 100755 --- a/daemons/hsfei/atcfwheel +++ b/daemons/hsfei/atcfwheel @@ -1,23 +1,19 @@ -#!/usr/bin/python3 - -import argparse +# !/usr/bin/python3.12 +'''Module for the ATC Filter Wheel Daemon''' import logging -import sys import configparser -from typing import Dict, Any -from libby.daemon import LibbyDaemon +from libby.daemon import LibbyDaemon # pyright: ignore[reportMissingImports] from hispec.util.thorlabs.fw102c import FilterWheelController -class atcfwheel(LibbyDaemon): +class Atcfwheel(LibbyDaemon): + '''Daemon for controlling the ATC Filter Wheel via Thorlabs FW102C controller''' peer_id = "atcfwheel" transport = "rabbitmq" - #address_book = { - # "pi_1_daemon": "tcp://131.215.200.218:5560" - #} discovery_enabled = False discovery_interval_s = 5.0 rabbitmq_url = "amqp://localhost" # RabbitMQ on hispec daemon_desc = "ATC FWheel" + named_positions = {} # pub/sub topics topics = {} @@ -30,26 +26,24 @@ class atcfwheel(LibbyDaemon): #on start set up the daemon from config and initialize device config = configparser.ConfigParser() config.read('hsfei.config') - self.host = config["Device Control"]["atcfwheel_host"] - self.port = int(config["Device Control"]["atcfwheel_port"]) + self.host = config["atcfwheel"]["host"] + self.port = int(config["atcfwheel"]["port"]) self.dev = FilterWheelController() self.dev.set_connection(ip = self.host, port = self.port) + # Daemon state self.state = { 'connected': False, 'error': '', } - # Setup logging - self.logger = logging.getLogger(self.peer_id) - # Call parent __init__ first super().__init__() def on_start(self, libby): - # Add services + '''Starts up daemon and initializies the hardware device''' self.logger.info(f"Starting {self.daemon_desc} Daemon") self.add_services({ "connect": lambda p: self.connect(), @@ -57,24 +51,25 @@ class atcfwheel(LibbyDaemon): "initialize": lambda p: self.initialize(), "status": lambda p: self.status(), "position.get": lambda p: self.get_pos(), - "position.set": lambda p: self.set_pos(pos = p.get("position")) + "position.set": lambda p: self.set_pos(pos = p.get("position")), + "position.goto_named": lambda p: self.goto_named_pos(name = p.get("name")) }) - try: self.connect() self.logger.info(f"Connected to {self.daemon_desc}") self.initialize() self.logger.info(f"Initialized {self.daemon_desc}") + self.load_named_pos() #publish to libby libby.publish("atcfwheel", {"Daemon Startup": "Success"}) except Exception as e: self.logger.error(f"Error Connecting and Initializing {self.daemon_desc}") #publish failure libby.publish("atcfwheel", {"Daemon Startup": "Failed", "Connection Error": f"{e}"}) - - + + def on_stop(self, libby): - #Disconnect and let user know + '''Stops the daemon and disconnects from hardware device''' try: self.disconnect() self.logger.info(f"Disconnected {self.daemon_desc}") @@ -85,7 +80,7 @@ class atcfwheel(LibbyDaemon): def connect(self): - #handles connection + """handles connection""" try: self.dev.connect() self.logger.info(f"Connected {self.daemon_desc}") @@ -95,7 +90,7 @@ class atcfwheel(LibbyDaemon): return {"Connect": "Success"} def disconnect(self): - #handles disconnection + """handles disconnection""" try: self.dev.disconnect() self.logger.info(f"Disconnected from {self.daemon_desc}") @@ -105,7 +100,7 @@ class atcfwheel(LibbyDaemon): return {"Disconnect": "Success"} def initialize(self): - #handles initialization + """handles initialization""" # for PPC102_Coms, this involves setting the enabled status try: self.dev.initialize() @@ -114,15 +109,29 @@ class atcfwheel(LibbyDaemon): return {"Initialize": "Failed", "Error": f"{e}"} return {"Initialize": "Success"} + def load_named_pos(self): + """loads named positions into the device from config file""" + config = configparser.ConfigParser() + config.read('hsfei.config') + try: + for name, pos in config["atcfwheel-named_pos"].items(): + self.add_named_pos(name, int(pos)) + self.named_positions[name] = int(pos) + self.logger.info(f"Loaded named positions for {self.daemon_desc}") + except Exception as e: + self.logger.error(F"Error: {e}") + return {"Load Named Positions": "Failed", "Error": f"{e}"} + return {"Load Named Positions": "Success"} + def status(self): - #handles status + """handles status""" try: status = self.dev.get_status() self.logger.debug(f"status: {status}") except Exception as e: self.logger.error(F"Error: {e}") return {"status": "Failed", "Error": f"{e}"} - return {"Status": status} + return {"status": status} def get_pos(self): #gets current position @@ -145,5 +154,17 @@ class atcfwheel(LibbyDaemon): return {"Move": "Failed", "Error": f"{e}"} return {"Move": "Success"} + def goto_named_pos(self, name): + #moves to named position + try: + goal = self.named_positions.get(name.lower()) + if goal is not None: + self.dev.set_pos(pos = int(goal)) + self.logger.debug(f"goto_named_pos: {name} -> {goal}") + except Exception as e: + self.logger.error(F"Error: {e}") + return {"Move to Named Position": "Failed", "Error": f"{e}"} + return {"Move to Named Position": "Success"} + if __name__ == "__main__": - atcfwheel().serve() \ No newline at end of file + Atcfwheel().serve() \ No newline at end of file diff --git a/daemons/hsfei/hsfei.config b/daemons/hsfei/hsfei.config index 18896ac..85d07b1 100644 --- a/daemons/hsfei/hsfei.config +++ b/daemons/hsfei/hsfei.config @@ -4,5 +4,14 @@ atcpress_host = feiinficon atcpress_port = 8000 -atcfwheel_host = feilantronix -atcfwheel_port = 10010 \ No newline at end of file +[atcfwheel] +host = feilantronix +port = 10010\ + +[atcfwheel-named_pos] +clear = 1 +nd2 = 2 +nd3 = 3 +nd4 = 4 +nd5 = 5 +nd6 = 6 \ No newline at end of file From 5f4d791ff708c976f4d106321d6732a0bf0b5bd4 Mon Sep 17 00:00:00 2001 From: Elijah AB Date: Mon, 24 Nov 2025 18:00:12 -0800 Subject: [PATCH 04/12] First implementation of named positions-REVISED --- daemons/hsfei/atcfwheel | 89 ++++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 41 deletions(-) diff --git a/daemons/hsfei/atcfwheel b/daemons/hsfei/atcfwheel index ed03ceb..89a2bd7 100755 --- a/daemons/hsfei/atcfwheel +++ b/daemons/hsfei/atcfwheel @@ -3,7 +3,7 @@ import logging import configparser from libby.daemon import LibbyDaemon # pyright: ignore[reportMissingImports] -from hispec.util.thorlabs.fw102c import FilterWheelController +from hispec.util.thorlabs.fw102c import FilterWheelController #pylint: disable = E0401 class Atcfwheel(LibbyDaemon): '''Daemon for controlling the ATC Filter Wheel via Thorlabs FW102C controller''' @@ -30,13 +30,21 @@ class Atcfwheel(LibbyDaemon): self.port = int(config["atcfwheel"]["port"]) self.dev = FilterWheelController() - self.dev.set_connection(ip = self.host, port = self.port) + + # Set up logging (temporary UNTIL LIBBY LOGGING IS IMPLEMENTED) + self.logger = logging.getLogger(__name__) + self.logger.setLevel(logging.DEBUG) + ch = logging.StreamHandler() + ch.setLevel(logging.DEBUG) + formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + ch.setFormatter(formatter) + self.logger.addHandler(ch) # Daemon state self.state = { 'connected': False, - 'error': '', + 'error': '' } # Call parent __init__ first @@ -44,7 +52,7 @@ class Atcfwheel(LibbyDaemon): def on_start(self, libby): '''Starts up daemon and initializies the hardware device''' - self.logger.info(f"Starting {self.daemon_desc} Daemon") + self.logger.info("Starting %s Daemon", self.daemon_desc) self.add_services({ "connect": lambda p: self.connect(), "disconnect": lambda p: self.disconnect(), @@ -56,36 +64,36 @@ class Atcfwheel(LibbyDaemon): }) try: self.connect() - self.logger.info(f"Connected to {self.daemon_desc}") + self.logger.info("Connected to %s", self.daemon_desc) self.initialize() - self.logger.info(f"Initialized {self.daemon_desc}") + self.logger.info("Initialized %s", self.daemon_desc) self.load_named_pos() #publish to libby libby.publish("atcfwheel", {"Daemon Startup": "Success"}) - except Exception as e: - self.logger.error(f"Error Connecting and Initializing {self.daemon_desc}") + except Exception as e: # pylint: disable=W0718 + self.logger.error("Error Connecting and Initializing %s: %s", self.daemon_desc, e) #publish failure libby.publish("atcfwheel", {"Daemon Startup": "Failed", "Connection Error": f"{e}"}) - def on_stop(self, libby): + def on_stop(self, libby) -> None: '''Stops the daemon and disconnects from hardware device''' try: self.disconnect() - self.logger.info(f"Disconnected {self.daemon_desc}") + self.logger.info("Disconnected %s", self.daemon_desc) libby.publish("atcfwheel", {"Daemon Shutdown": "Success"}) - except Exception as e: + except Exception as e: # pylint: disable=W0718 libby.publish("atcfwheel", {"Daemon Startup": "Failed", "Error":f"{e}"}) - self.logger.error(f"Disconnect {self.daemon_desc}:: Failed ") + self.logger.error("Disconnect %s:: Failed ", self.daemon_desc) def connect(self): """handles connection""" try: - self.dev.connect() - self.logger.info(f"Connected {self.daemon_desc}") - except Exception as e: - self.logger.error(F"Error: {e}") + self.dev.connect(ip = self.host, port = self.port) + self.logger.info("Connected %s", self.daemon_desc) + except Exception as e: # pylint: disable=W0718 + self.logger.error("Error: %s",e) return {"Connect": "Failed", "Error": f"{e}"} return {"Connect": "Success"} @@ -93,9 +101,9 @@ class Atcfwheel(LibbyDaemon): """handles disconnection""" try: self.dev.disconnect() - self.logger.info(f"Disconnected from {self.daemon_desc}") - except Exception as e: - self.logger.error(F"Error: {e}") + self.logger.info("Disconnected from %s", self.daemon_desc) + except Exception as e: # pylint: disable=W0718 + self.logger.error("Error: %s",e) return {"Disconnect": "Failed", "Error": f"{e}"} return {"Disconnect": "Success"} @@ -104,8 +112,8 @@ class Atcfwheel(LibbyDaemon): # for PPC102_Coms, this involves setting the enabled status try: self.dev.initialize() - except Exception as e: - self.logger.error(F"Error: {e}") + except Exception as e: # pylint: disable=W0718 + self.logger.error("Error: %s",e) return {"Initialize": "Failed", "Error": f"{e}"} return {"Initialize": "Success"} @@ -115,11 +123,10 @@ class Atcfwheel(LibbyDaemon): config.read('hsfei.config') try: for name, pos in config["atcfwheel-named_pos"].items(): - self.add_named_pos(name, int(pos)) self.named_positions[name] = int(pos) - self.logger.info(f"Loaded named positions for {self.daemon_desc}") - except Exception as e: - self.logger.error(F"Error: {e}") + self.logger.info("Loaded named positions for %s", self.daemon_desc) + except Exception as e: # pylint: disable=W0718 + self.logger.error("Error: %s",e) return {"Load Named Positions": "Failed", "Error": f"{e}"} return {"Load Named Positions": "Success"} @@ -127,44 +134,44 @@ class Atcfwheel(LibbyDaemon): """handles status""" try: status = self.dev.get_status() - self.logger.debug(f"status: {status}") - except Exception as e: - self.logger.error(F"Error: {e}") + self.logger.debug("status: %s",status) + except Exception as e: # pylint: disable=W0718 + self.logger.error("Error: %s",e) return {"status": "Failed", "Error": f"{e}"} return {"status": status} def get_pos(self): - #gets current position + '''gets current position''' try: position = self.dev.get_pos() - self.logger.debug(f"get_pos: {position}") - except Exception as e: - self.logger.error(F"Error: {e}") + self.logger.debug("get_pos: %s",position) + except Exception as e: # pylint: disable=W0718 + self.logger.error("Error: %s",e) return {"get_pos": "Failed", "Error": f"{e}"} return {"position": str(position)} def set_pos(self, pos): - #sets current position + '''sets current position''' try: position = int(pos) self.dev.set_pos(pos = position) - self.logger.debug(f"set_pos: {position}") - except Exception as e: - self.logger.error(F"Error: {e}") + self.logger.debug("set_pos: %s",position) + except Exception as e: # pylint: disable=W0718 + self.logger.error("Error: %s",e) return {"Move": "Failed", "Error": f"{e}"} return {"Move": "Success"} def goto_named_pos(self, name): - #moves to named position + '''moves to named position''' try: goal = self.named_positions.get(name.lower()) if goal is not None: self.dev.set_pos(pos = int(goal)) - self.logger.debug(f"goto_named_pos: {name} -> {goal}") - except Exception as e: - self.logger.error(F"Error: {e}") + self.logger.debug("goto_named_pos: %s -> %s",name,goal) + except Exception as e: # pylint: disable=W0718 + self.logger.error("Error: %s",e) return {"Move to Named Position": "Failed", "Error": f"{e}"} return {"Move to Named Position": "Success"} if __name__ == "__main__": - Atcfwheel().serve() \ No newline at end of file + Atcfwheel().serve() From 95b1bff2ed2146ac95305393cb7442e5fda5110e Mon Sep 17 00:00:00 2001 From: Elijah AB Date: Wed, 26 Nov 2025 14:52:22 -0800 Subject: [PATCH 05/12] Implementation of ATC FW daemon with named postions and base class changes --- daemons/hsfei/atcfwheel | 29 +++++++++++++++++++---------- daemons/hsfei/hsfei.config | 4 ++-- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/daemons/hsfei/atcfwheel b/daemons/hsfei/atcfwheel index 89a2bd7..0bbf581 100755 --- a/daemons/hsfei/atcfwheel +++ b/daemons/hsfei/atcfwheel @@ -1,9 +1,10 @@ -# !/usr/bin/python3.12 +#!/usr/bin/python3.12 '''Module for the ATC Filter Wheel Daemon''' import logging import configparser from libby.daemon import LibbyDaemon # pyright: ignore[reportMissingImports] -from hispec.util.thorlabs.fw102c import FilterWheelController #pylint: disable = E0401 +#from hispec.util.thorlabs.fw102c import FilterWheelController #pylint: disable = E0401,E0611 +from fw102c import FilterWheelController # Assuming fw102c.py is in the same directory class Atcfwheel(LibbyDaemon): '''Daemon for controlling the ATC Filter Wheel via Thorlabs FW102C controller''' @@ -60,7 +61,8 @@ class Atcfwheel(LibbyDaemon): "status": lambda p: self.status(), "position.get": lambda p: self.get_pos(), "position.set": lambda p: self.set_pos(pos = p.get("position")), - "position.goto_named": lambda p: self.goto_named_pos(name = p.get("name")) + "position.get_named": lambda p: self.get_named_position(), + "position.set_named": lambda p: self.goto_named_pos(name = p.get("named_pos")) }) try: self.connect() @@ -75,7 +77,6 @@ class Atcfwheel(LibbyDaemon): #publish failure libby.publish("atcfwheel", {"Daemon Startup": "Failed", "Connection Error": f"{e}"}) - def on_stop(self, libby) -> None: '''Stops the daemon and disconnects from hardware device''' try: @@ -90,7 +91,7 @@ class Atcfwheel(LibbyDaemon): def connect(self): """handles connection""" try: - self.dev.connect(ip = self.host, port = self.port) + self.dev.connect(host = self.host, port = self.port) self.logger.info("Connected %s", self.daemon_desc) except Exception as e: # pylint: disable=W0718 self.logger.error("Error: %s",e) @@ -153,9 +154,9 @@ class Atcfwheel(LibbyDaemon): def set_pos(self, pos): '''sets current position''' try: - position = int(pos) - self.dev.set_pos(pos = position) - self.logger.debug("set_pos: %s",position) + pos = int(pos) + self.dev.set_pos(pos) + self.logger.debug("set_pos: %d",pos) except Exception as e: # pylint: disable=W0718 self.logger.error("Error: %s",e) return {"Move": "Failed", "Error": f"{e}"} @@ -166,12 +167,20 @@ class Atcfwheel(LibbyDaemon): try: goal = self.named_positions.get(name.lower()) if goal is not None: - self.dev.set_pos(pos = int(goal)) + self.dev.set_pos(int(goal)) self.logger.debug("goto_named_pos: %s -> %s",name,goal) except Exception as e: # pylint: disable=W0718 self.logger.error("Error: %s",e) return {"Move to Named Position": "Failed", "Error": f"{e}"} - return {"Move to Named Position": "Success"} + return {"move": "Success"} + + def get_named_position(self): + '''returns current named position''' + current = self.dev.get_pos() + for name, pos in self.named_positions.items(): + if pos == current: + return {"named_pos":f"{name}"} + return {"named_pos": "Unknown"} if __name__ == "__main__": Atcfwheel().serve() diff --git a/daemons/hsfei/hsfei.config b/daemons/hsfei/hsfei.config index 85d07b1..c3a23be 100644 --- a/daemons/hsfei/hsfei.config +++ b/daemons/hsfei/hsfei.config @@ -5,8 +5,8 @@ atcpress_host = feiinficon atcpress_port = 8000 [atcfwheel] -host = feilantronix -port = 10010\ +host = 192.168.29.100 +port = 10010 [atcfwheel-named_pos] clear = 1 From 5733f9e9555be7fa911ff9a5cec1b871d9f6f74b Mon Sep 17 00:00:00 2001 From: Elijah AB Date: Wed, 26 Nov 2025 14:58:24 -0800 Subject: [PATCH 06/12] Implementation of ATC FW daemon with named postions and base class changes --- daemons/hsfei/atcfwheel | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/daemons/hsfei/atcfwheel b/daemons/hsfei/atcfwheel index 0bbf581..e18be24 100755 --- a/daemons/hsfei/atcfwheel +++ b/daemons/hsfei/atcfwheel @@ -3,10 +3,10 @@ import logging import configparser from libby.daemon import LibbyDaemon # pyright: ignore[reportMissingImports] -#from hispec.util.thorlabs.fw102c import FilterWheelController #pylint: disable = E0401,E0611 -from fw102c import FilterWheelController # Assuming fw102c.py is in the same directory +from hispec.util.thorlabs.fw102c import FilterWheelController #pylint: disable = E0401,E0611 +#from fw102c import FilterWheelController # Assuming fw102c.py is in the same directory -class Atcfwheel(LibbyDaemon): +class Atcfwheel(LibbyDaemon): #pylint: disable = W0223 '''Daemon for controlling the ATC Filter Wheel via Thorlabs FW102C controller''' peer_id = "atcfwheel" transport = "rabbitmq" @@ -77,7 +77,7 @@ class Atcfwheel(LibbyDaemon): #publish failure libby.publish("atcfwheel", {"Daemon Startup": "Failed", "Connection Error": f"{e}"}) - def on_stop(self, libby) -> None: + def on_stop(self, libby) -> None: #pylint: disable=W0222 '''Stops the daemon and disconnects from hardware device''' try: self.disconnect() From a1552750c7c0e7296d33e81ceb9b29b261da0968 Mon Sep 17 00:00:00 2001 From: Elijah AB Date: Fri, 5 Dec 2025 12:52:08 -0800 Subject: [PATCH 07/12] Added group id to the rabbit MQ daemon --- daemons/hsfei/atcfwheel | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/daemons/hsfei/atcfwheel b/daemons/hsfei/atcfwheel index e18be24..5b71d6c 100755 --- a/daemons/hsfei/atcfwheel +++ b/daemons/hsfei/atcfwheel @@ -9,10 +9,13 @@ from hispec.util.thorlabs.fw102c import FilterWheelController #pylint: disable = class Atcfwheel(LibbyDaemon): #pylint: disable = W0223 '''Daemon for controlling the ATC Filter Wheel via Thorlabs FW102C controller''' peer_id = "atcfwheel" + group_id = "hsfei" + + # RabbitMQ on hispec transport = "rabbitmq" discovery_enabled = False discovery_interval_s = 5.0 - rabbitmq_url = "amqp://localhost" # RabbitMQ on hispec + rabbitmq_url = "amqp://localhost" daemon_desc = "ATC FWheel" named_positions = {} From 3db8d81258d9646d6ba680369494157c2079db8d Mon Sep 17 00:00:00 2001 From: Elijah AB Date: Fri, 5 Dec 2025 12:52:50 -0800 Subject: [PATCH 08/12] Added group id to the rabbit MQ daemon --- daemons/hsfei/atcfwheel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemons/hsfei/atcfwheel b/daemons/hsfei/atcfwheel index 5b71d6c..dfec519 100755 --- a/daemons/hsfei/atcfwheel +++ b/daemons/hsfei/atcfwheel @@ -15,7 +15,7 @@ class Atcfwheel(LibbyDaemon): #pylint: disable = W0223 transport = "rabbitmq" discovery_enabled = False discovery_interval_s = 5.0 - rabbitmq_url = "amqp://localhost" + rabbitmq_url = "amqp://localhost" daemon_desc = "ATC FWheel" named_positions = {} From 11ed8429c575b9d47f6d7c3d42fd344368cdc14f Mon Sep 17 00:00:00 2001 From: Elijah AB Date: Mon, 15 Dec 2025 11:44:04 -0800 Subject: [PATCH 09/12] Config changes for .toml --- daemons/hsfei/hsfei.config | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/daemons/hsfei/hsfei.config b/daemons/hsfei/hsfei.config index c3a23be..a6f76d8 100644 --- a/daemons/hsfei/hsfei.config +++ b/daemons/hsfei/hsfei.config @@ -1,17 +1,22 @@ # Config file for daemon references across FEI daemons -[Device Control] -atcpress_host = feiinficon -atcpress_port = 8000 +atcfwheel-communication: + host: "192.168.29.100" + port: 10010 + peer_id: atcfwheel + group_id: hsfei + bind: null + address_book: null + transport = "rabbitmq" + discovery_enabled = False + discovery_interval_s = 5.0 + rabbitmq_url = "amqp://localhost" + daemon_desc = "ATC FWheel" -[atcfwheel] -host = 192.168.29.100 -port = 10010 - -[atcfwheel-named_pos] -clear = 1 -nd2 = 2 -nd3 = 3 -nd4 = 4 -nd5 = 5 -nd6 = 6 \ No newline at end of file +atcfwheel-named_pos: + clear: 1 + nd2: 2 + nd3: 3 + nd4: 4 + nd5: 5 + nd6: 6 From 65fea25bae342ad2b370aaa8384e19da50f06c5f Mon Sep 17 00:00:00 2001 From: Elijah AB Date: Mon, 15 Dec 2025 11:44:18 -0800 Subject: [PATCH 10/12] Config changes for .toml --- daemons/hsfei/{hsfei.config => hsfei.toml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename daemons/hsfei/{hsfei.config => hsfei.toml} (100%) diff --git a/daemons/hsfei/hsfei.config b/daemons/hsfei/hsfei.toml similarity index 100% rename from daemons/hsfei/hsfei.config rename to daemons/hsfei/hsfei.toml From bb3343a33015b866a56c8c29732df72f3b77279a Mon Sep 17 00:00:00 2001 From: Elijah AB Date: Mon, 15 Dec 2025 12:30:25 -0800 Subject: [PATCH 11/12] Config changes for HispecDaemon --- daemons/hsfei/atcfwheel | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/daemons/hsfei/atcfwheel b/daemons/hsfei/atcfwheel index dfec519..20f72c7 100755 --- a/daemons/hsfei/atcfwheel +++ b/daemons/hsfei/atcfwheel @@ -2,11 +2,11 @@ '''Module for the ATC Filter Wheel Daemon''' import logging import configparser -from libby.daemon import LibbyDaemon # pyright: ignore[reportMissingImports] +from daemon import HispecDaemon # pyright: ignore[reportMissingImports] from hispec.util.thorlabs.fw102c import FilterWheelController #pylint: disable = E0401,E0611 #from fw102c import FilterWheelController # Assuming fw102c.py is in the same directory -class Atcfwheel(LibbyDaemon): #pylint: disable = W0223 +class Atcfwheel(HispecDaemon): #pylint: disable = W0223 '''Daemon for controlling the ATC Filter Wheel via Thorlabs FW102C controller''' peer_id = "atcfwheel" group_id = "hsfei" @@ -29,7 +29,7 @@ class Atcfwheel(LibbyDaemon): #pylint: disable = W0223 """ #on start set up the daemon from config and initialize device config = configparser.ConfigParser() - config.read('hsfei.config') + config.read('hsfei.toml') self.host = config["atcfwheel"]["host"] self.port = int(config["atcfwheel"]["port"]) From b751e51eae40531abf990cb05db950e06d9c6f9c Mon Sep 17 00:00:00 2001 From: Elijah AB Date: Mon, 15 Dec 2025 12:45:44 -0800 Subject: [PATCH 12/12] Config changes for HispecDaemon --- daemons/hsfei/atcfwheel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemons/hsfei/atcfwheel b/daemons/hsfei/atcfwheel index 20f72c7..e3f816b 100755 --- a/daemons/hsfei/atcfwheel +++ b/daemons/hsfei/atcfwheel @@ -2,7 +2,7 @@ '''Module for the ATC Filter Wheel Daemon''' import logging import configparser -from daemon import HispecDaemon # pyright: ignore[reportMissingImports] +from hispec import HispecDaemon # pyright: ignore[reportMissingImports] from hispec.util.thorlabs.fw102c import FilterWheelController #pylint: disable = E0401,E0611 #from fw102c import FilterWheelController # Assuming fw102c.py is in the same directory