Source code for jaeger.chiller

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# @Author: José Sánchez-Gallego (gallegoj@uw.edu)
# @Date: 2022-02-02
# @Filename: chiller.py
# @License: BSD 3-clause (http://www.opensource.org/licenses/BSD-3-Clause)

from __future__ import annotations

import asyncio
import logging

from typing import TYPE_CHECKING

from jaeger import config
from jaeger.ieb import IEB, Chiller
from jaeger.utils.helpers import BaseBot


if TYPE_CHECKING:
    from jaeger.fps import FPS


__all__ = ["ChillerBot"]


[docs] class ChillerBot(BaseBot): """Manages the FPS chiller.""" def __init__(self, fps: FPS): self.chiller_config = config.get("chiller", {}) self.temperature: bool | float = self.chiller_config.get("temperature", False) self.flow: bool | float = self.chiller_config.get("flow", False) super().__init__(fps) async def _loop(self): """Sets the chiller set point temperature.""" chiller = Chiller.create() assert chiller is not None while True: await self._set_temperature(chiller) await self._set_flow(chiller) await asyncio.sleep(60) async def _set_temperature(self, chiller: Chiller): """Sets the temperature set point.""" dev_name = "TEMPERATURE_USER_SETPOINT" dev = chiller.get_device(dev_name) if self.temperature is False or self.temperature is None: return if self.temperature == "auto": if not isinstance(self.ieb, IEB) or self.ieb.disabled is True: return failed: bool = False # Try up to 10 times since sometimes setting the temperature fails. for _ in range(10): failed = False try: current_setpoint = (await dev.read())[0] # If we are maintaining a fixed temperature, check if we # need to reset the set point and exit. if self.temperature is not True and self.temperature != "auto": if abs(current_setpoint - self.temperature) > 0.1: await dev.write(int(self.temperature * 10)) self.notify( f"Setting chiller to {self.temperature} C", logging.DEBUG, ) break assert isinstance(self.ieb, IEB) and self.ieb.disabled is False ambient_temp = (await self.ieb.read_device("T3"))[0] rh = (await self.ieb.read_device("RH3"))[0] # Dewpoint temperature. t_d = ambient_temp - (100 - rh) / 5.0 # What follows is if we are setting the set point # based on the ambient temperature. # Calculate the new set point temperature and write it # to the device if it's different than the current one. # New set point is two degC below ambient clipped to 1 degC # and above the dew point depression region. new_temp = ambient_temp - 2 if new_temp <= 1: new_temp = 1 if new_temp < (t_d + 3): new_temp = t_d + 3 # Round to closest 0.5 new_temp = round(new_temp * 2) / 2.0 delta_temp = abs(current_setpoint - new_temp) if delta_temp > 0.1: await dev.write(int(new_temp * 10)) self.notify(f"Setting chiller to {new_temp} C", logging.DEBUG) break except Exception: failed = True await asyncio.sleep(2) continue if failed is True: self.notify("Failed setting chiller temperature.", level=logging.ERROR) async def _set_flow(self, chiller: Chiller): """Sets the flow set point.""" dev_name = "FLOW_USER_SETPOINT" dev = chiller.get_device(dev_name) if self.flow is True or self.flow == "auto": self.flow = self.chiller_config.get("flow", False) if self.flow is False or self.flow is None: return failed: bool = False # Try up to 10 times since sometimes setting the flow fails. for _ in range(10): failed = False try: current_setpoint = (await dev.read())[0] if isinstance(self.flow, (float, int)): if abs(current_setpoint - self.flow) > 0.1: await dev.write(int(self.flow * 10)) self.notify( f"Setting chiller flow to {self.flow:.1f} gpm.", level=logging.DEBUG, ) else: self.notify( f"Invalid chiller set point {self.flow!r}.", level=logging.WARNING, ) break except Exception: failed = True await asyncio.sleep(2) continue if failed is True: self.notify("Failed setting chiller flow.", level=logging.ERROR)