async def read( command: Command, controllers: dict[str, ArchonController], controller_name: str, save: bool, ): """Reads the configuration from the controller.""" if controller_name not in controllers: return command.fail(f"Controller {controller_name!r} does not exist.") controller = controllers[controller_name] if not check_controller(command, controller): return command.fail() if save: path: str | bool = os.path.expanduser( f"~/archon_{controller.name}.acf") else: path: str | bool = False try: config = await controller.read_config(save=path) except ArchonError as err: return command.fail(text={ "controller": controller.name, "text": str(err), }) if save is False: return command.finish(config={ "controller": controller.name, "config": config, }) return command.finish(text=f"Config written to {path!r}")
async def status(command: Command, nodes: Dict[str, Node]): """Outputs the status of the nodes and containers.""" enabled_nodes = [node for node in nodes.values() if node.enabled] command.info(enabledNodes=[node.name for node in enabled_nodes]) for node in enabled_nodes: await node.report_status(command) command.finish()
async def status( command: Command, controllers: dict[str, ArchonController], controller_name: str, ): """Reads the frame status.""" if controller_name not in controllers: return command.fail(f"Controller {controller_name!r} does not exist.") controller = controllers[controller_name] if not check_controller(command, controller): return command.fail() try: frame = await controller.get_frame() except ArchonError as err: return command.fail(text={ "controller": controller.name, "text": err, }) return command.finish(frame={ "controller": controller.name, **frame, })
async def status(command: Command, controllers: dict[str, IebController]): #return the status of shutter. print(controllers) command.info(text="Checking all shutters") tasks = [] for shutter in controllers: if controllers[shutter].name == 'shutter': try: tasks.append(controllers[shutter].send_command("status")) except LvmIebError as err: return command.fail(error=str(err)) result_shutter = await asyncio.gather(*tasks) for n in result_shutter: try: if n == "opened": return command.info(status={ "opened/closed:": n, }) elif n == "closed": return command.info(status={ "opened/closed:": n, }) else: return command.fail(test='shutter is in a bad state') except LvmIebError as err: return command.fail(error=str(err)) return command.finish()
async def status(command: Command, controllers: dict[str, IebController]): """Returns the status of wago sensor.""" #loop = asyncio.get_running_loop() for wago in controllers: if controllers[wago].name == 'wago': try: wago_status1 = await controllers[wago].getWAGOEnv() if wago_status1: command.info(text="Temperature & Humidity is:",status={ "rhtT1(40001)":controllers[wago].sensors['rhtT1(40001)'], "rhtRH1(40002)":controllers[wago].sensors['rhtRH1(40002)'], "rhtT2(40003)":controllers[wago].sensors['rhtT2(40003)'], "rhtRH2(40004)":controllers[wago].sensors['rhtRH2(40004)'], "rtd1(40009)":controllers[wago].sensors['rtd1(40009)'], "rtd2(40010)":controllers[wago].sensors['rtd2(40010)'], "rtd3(40011)":controllers[wago].sensors['rtd3(40011)'], "rtd4(40012)":controllers[wago].sensors['rtd4(40012)'] }) else: return command.fail(text=f"ERROR: Did not read sensors/powers") except LvmIebError as err: return command.fail(error=str(err)) return command.finish()
async def fetch( command: Command, controllers: dict[str, ArchonController], controller_name: str, buffer: str, file, ): """Low-level command to fetch a buffer and write it to disk.""" if controller_name not in controllers: return command.fail(f"Controller {controller_name!r} does not exist.") controller = controllers[controller_name] if not check_controller(command, controller): return command.fail() buffer_no = int(buffer) if file is None: # Save to ~/archon_<controller_name>_NNNN.fits. Find the highest file with that # format and increase the counter. pattern = os.path.expanduser( f"~/archon_{controller.name}_[0-9][0-9][0-9][0-9].fits") existing = glob(pattern) if len(existing) == 0: nfile = 1 else: last = sorted(existing)[-1] nfile = int(re.search(r"([0-9]{4})\.fits$", last)[1]) + 1 path = os.path.expanduser( f"~/archon_{controller.name}_{nfile:04d}.fits") else: path: str = os.path.relpath(str(file)) dirname = os.path.dirname(path) if not os.path.exists(dirname): return command.fail( error= "Parent of file does not exists or file is badly formatted.") def notifier(msg): command.info(text={ "controller": controller.name, "text": msg, }) try: array = await controller.fetch(buffer_no, notifier=notifier) except BaseException as err: return command.fail( text={ "controller": controller.name, "text": f"Failed fetching data: {str(err)}", }) # Create a simple HDU list with the data. hdu = astropy.io.fits.PrimaryHDU(data=array) hdulist = astropy.io.fits.HDUList([hdu]) hdulist.writeto(path, overwrite=True) return command.finish(f"File saved to {path}")
async def talk( command: Command, nodes: Dict[str, Node], camera_command: str, names: str, category: str, ): """Sends a command to selected or all cameras.""" assert command.actor camera_command = " ".join(camera_command) c_nodes = select_nodes(nodes, category, names) node_names = [node.name for node in c_nodes if node.enabled] flicameras = command.actor.flicameras connected_nodes = [] for name in node_names: if flicameras[name].is_connected(): connected_nodes.append(name) continue command.warning(text=f"Failed connecting to {name}.") dev_commands = [] for name in connected_nodes: dev_commands.append(flicameras[name].send_message( command, camera_command)) await asyncio.gather(*dev_commands, return_exceptions=True) # Check if the device commands returned "filename" keywords. If so, # bundle them in a single keyword list that indicates all the filenames # for exposures taken together. filenames = [] for reply in command.replies: if "filename" in reply.message: filenames.append(reply.message["filename"][1]["filename"]) if len(filenames) > 0: command.info(filename_bundle=filenames) command.finish()
async def enable( command: Command, nodes: Dict[str, Node], nodes_to_enable: List[str], all: bool, ): """Enables one or multiple cameras.""" if all is True: nodes_to_enable = list(nodes) for name in nodes_to_enable: if name not in nodes: command.warning(text=f"Cannot find node {name}.") continue nodes[name].enabled = True command.finish()
async def status(command: Command, switches: [], name: str, portnum: int): """print the status of the NPS.""" status = {} for switch in switches: try: # status |= await switch.statusAsJson(name, portnum) works only with python 3.9 status = dict( list(status.items()) + list((await switch.statusAsJson(name, portnum)).items())) except PowerException as ex: return command.fail(error=str(ex)) command.info(STATUS=status) return command.finish("done")
async def init(command: Command, controllers: dict[str, IebController]): #return the status of hartmann. command.info(text="Checking all hartmanns") tasks = [] for h in controllers: if controllers[h].name == 'hartmann_right': try: tasks.append(controllers[h].initialize()) except LvmIebError as err: return command.fail(error=str(err)) if controllers[h].name == 'hartmann_left': try: tasks.append(controllers[h].initialize()) except LvmIebError as err: return command.fail(error=str(err)) await asyncio.gather(*tasks) return command.finish()
async def close(command: Command, controllers: dict[str, IebController]): """close the shutter""" tasks = [] for shutter in controllers: if controllers[shutter].name == 'shutter': try: tasks.append(controllers[shutter].send_command("close")) except LvmIebError as err: return command.fail(error=str(err)) command.info(text="Closing all shutters") print("----close----") current_time = datetime.datetime.now() print('before command gathered : %s', current_time) await asyncio.gather(*tasks) current_time = datetime.datetime.now() print('after command gathered : %s', current_time) return command.finish(shutter="closed")
async def setpower(command: Command, controllers: dict[str, IebController]): """Returns the status of wago sensor.""" #loop = asyncio.get_running_loop() for wago in controllers: if controllers[wago].name == 'wago': try: wago_status1 = await controllers[wago].setWAGOPower("hartmann_right_power", 'ON') if wago_status1: command.info(text="Power state of the components are:",status={ "shutter_power":controllers[wago].power_status["shutter_power"], "hartmann_right_power":controllers[wago].power_status["hartmann_right_power"], "hartmann_left_power":controllers[wago].power_status["hartmann_left_power"] }) else: return command.fail(text=f"ERROR: Did not read sensors/powers") except LvmIebError as err: return command.fail(error=str(err)) return command.finish()
async def write( command: Command, controllers: dict[str, ArchonController], controller_name: str, config_path: click.Path, applyall: bool, poweron: bool, ): """Writes a configuration file to the controller.""" if controller_name not in controllers: return command.fail(f"Controller {controller_name!r} does not exist.") controller = controllers[controller_name] if not check_controller(command, controller): return command.fail() path = str(config_path) def notifier(msg): command.info(text={ "controller": controller.name, "text": msg, }) try: await controller.write_config( path, applyall=applyall, poweron=poweron, notifier=notifier, ) except ArchonError as err: return command.fail(text={ "controller": controller.name, "text": str(err), }) return command.finish(text=f"Config file {path!r} successfully loaded.")
async def status(command: Command, controllers: dict[str, IebController]): #return the status of hartmann. command.info(text="Checking all hartmanns") tasks = [] print(controllers) for h in controllers: print(controllers[h].name) if controllers[h].name == 'hartmann_right': print(controllers[h].name, controllers[h].host, controllers[h].port) try: tasks.append(controllers[h].get_status()) except LvmIebError as err: return command.fail(error=str(err)) if controllers[h].name == 'hartmann_left': print(controllers[h].name, controllers[h].host, controllers[h].port) try: tasks.append(controllers[h].get_status()) except LvmIebError as err: return command.fail(error=str(err)) result_hartmann = await asyncio.gather(*tasks) print(result_hartmann) try: command.info( status={ "hartmann_left opened/closed:": result_hartmann[0], "hartmann_right opened/closed:": result_hartmann[1], }) except LvmIebError as err: return command.fail(error=str(err)) return command.finish()
async def close(command: Command, controllers: dict[str, IebController], side: str): """close the hartmann""" #side = "all" tasks = [] for hartmann in controllers: if side == "all" or side == "right": if controllers[hartmann].name == 'hartmann_right': try: tasks.append(controllers[hartmann].send_command("close")) except LvmIebError as err: return command.fail(error=str(err)) if side == "all" or side == "left": if controllers[hartmann].name == 'hartmann_left': try: tasks.append(controllers[hartmann].send_command("close")) except LvmIebError as err: return command.fail(error=str(err)) command.info(text="Closing all hartmanns") await asyncio.gather(*tasks) return command.finish(hartmann="closed")
async def reconnect( command: Command, nodes: Dict[str, Node], names: str, category: str, force: bool, ): """Recreates volumes and restarts the Docker containers.""" assert command.actor config = command.actor.config async def reconnect_node(node): """Reconnect sync. Will be run in an executor.""" actor = command.actor assert actor try: await node.connect() if not (await node.connected()): raise ConnectionError() except ConnectionError: command.warning(text=f"Node {node.name} is not pinging back or " "the Docker daemon is not running. Try " "rebooting the computer.") return # Stop container first, because we cannot remove volumes that are # attached to running containers. await node.stop_container( config["container_name"] + f"-{node.name}", config["image"], force=True, command=command, ) for vname in config["volumes"]: vconfig = config["volumes"][vname] await node.create_volume( vname, driver=vconfig["driver"], opts=vconfig["opts"], force=force, command=command, ) return await node.run_container( actor.get_container_name(node), config["image"], volumes=list(config["volumes"]), privileged=True, registry=config["registry"], ports=[config["nodes"][actor.observatory][node.name]["port"]], envs={ "ACTOR_NAME": node.name, "OBSERVATORY": actor.observatory }, force=True, command=command, ) c_nodes = select_nodes(nodes, category, names) # Drop the device before doing anything with the containers, or we'll # get weird hangups. for node in c_nodes: node_name = node.name device = command.actor.flicameras[node_name] if device.is_connected(): await device.stop() await asyncio.gather(*[reconnect_node(node) for node in c_nodes]) command.info(text="Waiting 5 seconds before reconnecting the devices ...") await asyncio.sleep(5) for node in c_nodes: container_name = config["container_name"] + f"-{node.name}" if not (await node.is_container_running(container_name)): continue device = command.actor.flicameras[node.name] await device.restart() if device.is_connected(): port = device.port await node.report_status(command) command.debug( text=f"{node.name}: reconnected to device on port {port}.") else: command.warning(text=f"{node.name}: failed to connect to device.") command.finish()
async def offall(command: Command, switches: [], name: str): """Turn off all Outlet""" command.info(STATUS=await switch_control(switches, False, 0, name)) return command.finish(text="done")
async def off(command: Command, switches: [], name: str, portnum: int): """Turn off the Outlet""" command.info(STATUS=await switch_control(switches, False, name, portnum)) return command.finish(text="done")