Beispiel #1
0
    def __init__(self, input_dev):
        self.cmd_send = None
        self.ph_sensor_uart = None
        self.ph_sensor_i2c = None
        self.interface = input_dev.interface

        if self.interface == 'FTDI':
            from mycodo.devices.atlas_scientific_ftdi import AtlasScientificFTDI
            self.ph_sensor_ftdi = AtlasScientificFTDI(
                input_dev.ftdi_location)
        elif self.interface == 'UART':
            from mycodo.devices.atlas_scientific_uart import AtlasScientificUART
            self.ph_sensor_uart = AtlasScientificUART(
                input_dev.uart_location,
                baudrate=input_dev.baud_rate)
        elif self.interface == 'I2C':
            from mycodo.devices.atlas_scientific_i2c import AtlasScientificI2C
            self.ph_sensor_i2c = AtlasScientificI2C(
                i2c_address=int(str(input_dev.i2c_location), 16),
                i2c_bus=input_dev.i2c_bus)

        self.board_version, self.board_info = self.get_board_version()

        if self.board_version == 0:
            logger.error("Unable to retrieve device info (this indicates the "
                         "device was not properly initialized or connected)")
        else:
            # TODO: Change back to debug
            logger.error("Device Info: {info}".format(info=self.board_info))
            logger.error("Detected Version: {ver}".format(ver=self.board_version))
Beispiel #2
0
    def __init__(self, input_dev):
        self.cmd_send = None
        self.ph_sensor_uart = None
        self.ph_sensor_i2c = None
        self.interface = input_dev.interface

        if self.interface == 'FTDI':
            from mycodo.devices.atlas_scientific_ftdi import AtlasScientificFTDI
            self.ph_sensor_ftdi = AtlasScientificFTDI(input_dev.ftdi_location)
        elif self.interface == 'UART':
            from mycodo.devices.atlas_scientific_uart import AtlasScientificUART
            self.ph_sensor_uart = AtlasScientificUART(
                input_dev.uart_location, baudrate=input_dev.baud_rate)
        elif self.interface == 'I2C':
            from mycodo.devices.atlas_scientific_i2c import AtlasScientificI2C
            self.ph_sensor_i2c = AtlasScientificI2C(i2c_address=int(
                str(input_dev.i2c_location), 16),
                                                    i2c_bus=input_dev.i2c_bus)

        self.measurement, self.board_version, self.firmware_version = self.get_board_version(
        )

        if self.board_version == 0:
            logger.error("Atlas Scientific board initialization unsuccessful. "
                         "Unable to retrieve device info (this indicates the "
                         "device was not properly initialized or connected)")
        else:
            # TODO: Change back to debug
            logger.info(
                "Atlas Scientific board initialization success. "
                "Measurement: {meas}, Board: {brd}, Firmware: {fw}".format(
                    meas=self.measurement,
                    brd=self.board_version,
                    fw=self.firmware_version))
Beispiel #3
0
 def initialize_sensor(self):
     from mycodo.devices.atlas_scientific_i2c import AtlasScientificI2C
     from mycodo.devices.atlas_scientific_uart import AtlasScientificUART
     if self.interface == 'UART':
         self.atlas_sensor_uart = AtlasScientificUART(
             self.device_loc, baudrate=self.baud_rate)
     elif self.interface == 'I2C':
         self.atlas_sensor_i2c = AtlasScientificI2C(
             i2c_address=self.i2c_address, i2c_bus=self.i2c_bus)
Beispiel #4
0
 def initialize_sensor(self):
     from mycodo.devices.atlas_scientific_ftdi import AtlasScientificFTDI
     from mycodo.devices.atlas_scientific_i2c import AtlasScientificI2C
     from mycodo.devices.atlas_scientific_uart import AtlasScientificUART
     if self.interface == 'FTDI':
         self.atlas_sensor_ftdi = AtlasScientificFTDI(self.ftdi_location)
     elif self.interface == 'UART':
         self.atlas_sensor_uart = AtlasScientificUART(self.uart_location)
     elif self.interface == 'I2C':
         self.atlas_sensor_i2c = AtlasScientificI2C(
             i2c_address=self.i2c_address, i2c_bus=self.i2c_bus)
Beispiel #5
0
 def __init__(self, interface, device_loc=None, baud_rate=None,
              i2c_address=None, i2c_bus=None, sensor_sel=None):
     super(AtlaspHSensor, self).__init__()
     self._ph = 0
     self.interface = interface
     self.sensor_sel = sensor_sel
     if self.interface == 'UART':
         self.atlas_sensor_uart = AtlasScientificUART(device_loc,
                                                      baudrate=baud_rate)
     elif self.interface == 'I2C':
         self.atlas_sensor_i2c = AtlasScientificI2C(
             i2c_address=i2c_address, i2c_bus=i2c_bus)
Beispiel #6
0
 def initialize_sensor(self):
     from mycodo.devices.atlas_scientific_i2c import AtlasScientificI2C
     from mycodo.devices.atlas_scientific_uart import AtlasScientificUART
     if self.interface == 'UART':
         self.logger = logging.getLogger(
             "mycodo.inputs.atlas_ph_{uart}".format(uart=self.device_loc))
         self.atlas_sensor_uart = AtlasScientificUART(self.device_loc)
     elif self.interface == 'I2C':
         self.logger = logging.getLogger(
             "mycodo.inputs.atlas_ph_{bus}_{add}".format(
                 bus=self.i2c_bus, add=self.i2c_address))
         self.atlas_sensor_i2c = AtlasScientificI2C(
             i2c_address=self.i2c_address, i2c_bus=self.i2c_bus)
Beispiel #7
0
 def initialize_sensor(self):
     if self.interface == 'FTDI':
         from mycodo.devices.atlas_scientific_ftdi import AtlasScientificFTDI
         self.ftdi_location = self.input_dev.ftdi_location
         self.atlas_sensor = AtlasScientificFTDI(self.ftdi_location)
     elif self.interface == 'UART':
         from mycodo.devices.atlas_scientific_uart import AtlasScientificUART
         self.uart_location = self.input_dev.uart_location
         self.atlas_sensor = AtlasScientificUART(self.uart_location)
     elif self.interface == 'I2C':
         from mycodo.devices.atlas_scientific_i2c import AtlasScientificI2C
         self.i2c_address = int(str(self.input_dev.i2c_location), 16)
         self.i2c_bus = self.input_dev.i2c_bus
         self.atlas_sensor = AtlasScientificI2C(
             i2c_address=self.i2c_address, i2c_bus=self.i2c_bus)
Beispiel #8
0
 def setup_output(self):
     if self.interface == 'FTDI':
         from mycodo.devices.atlas_scientific_ftdi import AtlasScientificFTDI
         self.atlas_command = AtlasScientificFTDI(self.output.ftdi_location)
     elif self.interface == 'I2C':
         from mycodo.devices.atlas_scientific_i2c import AtlasScientificI2C
         self.atlas_command = AtlasScientificI2C(
             i2c_address=int(str(self.output.i2c_location), 16),
             i2c_bus=self.output.i2c_bus)
     elif self.interface == 'UART':
         from mycodo.devices.atlas_scientific_uart import AtlasScientificUART
         self.atlas_command = AtlasScientificUART(
             self.output.uart_location, baudrate=self.output.baud_rate)
     else:
         self.logger.error("Unknown interface: {}".format(self.interface))
Beispiel #9
0
def setup_atlas_ph_measure(input_id):
    """
    Acquire a measurement from the Atlas Scientific pH input and return it
    Used during calibration to display the current pH to the user
    """
    if not utils_general.user_has_permission('edit_controllers'):
        return redirect(url_for('routes_page.page_atlas_ph_calibrate'))

    selected_input = Input.query.filter_by(unique_id=input_id).first()

    ph = None
    error = None

    if selected_input.interface == 'UART':
        ph_input_uart = AtlasScientificUART(
            selected_input.device_loc, baudrate=selected_input.baud_rate)
        lines = ph_input_uart.query('R')
        logger.debug("All Lines: {lines}".format(lines=lines))

        if 'check probe' in lines:
            error = '"check probe" returned from input'
        elif not lines:
            error = 'Nothing returned from input'
        elif str_is_float(lines[0]):
            ph = lines[0]
            logger.debug('Value[0] is float: {val}'.format(val=ph))
        else:
            error = 'Value[0] is not float or "check probe": {val}'.format(
                val=lines[0])
    elif selected_input.interface == 'I2C':
        ph_input_i2c = AtlasScientificI2C(
            i2c_address=int(str(selected_input.location), 16),
            i2c_bus=selected_input.i2c_bus)
        ph_status, ph_str = ph_input_i2c.query('R')
        if ph_status == 'error':
            error = "Input read unsuccessful: {err}".format(err=ph_str)
        elif ph_status == 'success':
            ph = ph_str

    if error:
        logger.error(error)
        return error, 204
    else:
        return ph
Beispiel #10
0
 def initialize_sensor(self):
     from mycodo.devices.atlas_scientific_ftdi import AtlasScientificFTDI
     from mycodo.devices.atlas_scientific_i2c import AtlasScientificI2C
     from mycodo.devices.atlas_scientific_uart import AtlasScientificUART
     if self.interface == 'FTDI':
         self.logger = logging.getLogger(
             "mycodo.inputs.atlas_electrical_conductivity_ftdi_{ftdi}".format(
                 ftdi=self.ftdi_location))
         self.atlas_sensor_ftdi = AtlasScientificFTDI(self.ftdi_location)
     elif self.interface == 'UART':
         self.logger = logging.getLogger(
             "mycodo.inputs.atlas_electrical_conductivity_uart_{uart}".format(
                 uart=self.uart_location))
         self.atlas_sensor_uart = AtlasScientificUART(self.uart_location)
     elif self.interface == 'I2C':
         self.logger = logging.getLogger(
             "mycodo.inputs.atlas_electrical_conductivity_i2c_{bus}_{add}".format(
                 bus=self.i2c_bus, add=self.i2c_address))
         self.atlas_sensor_i2c = AtlasScientificI2C(
             i2c_address=self.i2c_address, i2c_bus=self.i2c_bus)
 def connect_atlas_ezo_pump(selected_output):
     atlas_command = None
     if selected_output.interface == 'FTDI':
         atlas_command = AtlasScientificFTDI(selected_output.ftdi_location)
     elif selected_output.interface == 'I2C':
         atlas_command = AtlasScientificI2C(i2c_address=int(
             str(selected_output.location), 16),
                                            i2c_bus=selected_output.i2c_bus)
     elif selected_output.interface == 'UART':
         atlas_command = AtlasScientificUART(
             selected_output.location, baudrate=selected_output.baud_rate)
     return atlas_command
Beispiel #12
0
    def __init__(self, sensor_sel):
        self.cmd_send = None
        self.ph_sensor_uart = None
        self.ph_sensor_i2c = None
        self.interface = sensor_sel.interface

        if self.interface == 'UART':
            self.ph_sensor_uart = AtlasScientificUART(
                sensor_sel.device_loc, baudrate=sensor_sel.baud_rate)
        elif self.interface == 'I2C':
            self.ph_sensor_i2c = AtlasScientificI2C(
                i2c_address=sensor_sel.i2c_address, i2c_bus=sensor_sel.i2c_bus)

        self.board_version, self.board_info = self.board_version()

        if self.board_version == 0:
            logger.error("Unable to retrieve device info (this indicates the "
                         "device was not properly initialized or connected)")
        else:
            logger.debug("Device Info: {info}".format(info=self.board_info))
            logger.debug(
                "Detected Version: {ver}".format(ver=self.board_version))
Beispiel #13
0
 def setup_output(self):
     if self.output_interface == 'FTDI':
         from mycodo.devices.atlas_scientific_ftdi import AtlasScientificFTDI
         self.ftdi_location = self.output.ftdi_location
         self.atlas_command = AtlasScientificFTDI(self.ftdi_location)
     elif self.output_interface == 'I2C':
         from mycodo.devices.atlas_scientific_i2c import AtlasScientificI2C
         self.i2c_address = int(str(self.output.i2c_location), 16)
         self.i2c_bus = self.output.i2c_bus
         self.atlas_command = AtlasScientificI2C(
             i2c_address=self.i2c_address, i2c_bus=self.i2c_bus)
     elif self.output_interface == 'UART':
         from mycodo.devices.atlas_scientific_uart import AtlasScientificUART
         self.uart_location = self.output.uart_location
         self.output_baud_rate = self.output.baud_rate
         self.atlas_command = AtlasScientificUART(
             self.uart_location, baudrate=self.output_baud_rate)
Beispiel #14
0
def setup_atlas_device(atlas_device):
    if atlas_device.interface == 'FTDI':
        from mycodo.devices.atlas_scientific_ftdi import AtlasScientificFTDI
        atlas_device = AtlasScientificFTDI(atlas_device.ftdi_location)
    elif atlas_device.interface == 'UART':
        from mycodo.devices.atlas_scientific_uart import AtlasScientificUART
        atlas_device = AtlasScientificUART(atlas_device.uart_location,
                                           baudrate=atlas_device.baud_rate)
    elif atlas_device.interface == 'I2C':
        from mycodo.devices.atlas_scientific_i2c import AtlasScientificI2C
        atlas_device = AtlasScientificI2C(i2c_address=int(
            str(atlas_device.i2c_location), 16),
                                          i2c_bus=atlas_device.i2c_bus)
    else:
        logger.error("Unrecognized interface: {}".format(
            atlas_device.interface))
        return
    return atlas_device
Beispiel #15
0
 def initialize_sensor(self):
     from mycodo.devices.atlas_scientific_ftdi import AtlasScientificFTDI
     from mycodo.devices.atlas_scientific_i2c import AtlasScientificI2C
     from mycodo.devices.atlas_scientific_uart import AtlasScientificUART
     if self.interface == 'FTDI':
         self.logger = logging.getLogger(
             "mycodo.inputs.atlas_pt1000_ftdi_{ftdi}".format(
                 ftdi=self.ftdi_location))
         self.atlas_sensor_ftdi = AtlasScientificFTDI(self.ftdi_location)
     elif self.interface == 'UART':
         self.logger = logging.getLogger(
             "mycodo.inputs.atlas_pt1000_uart_{uart}".format(
                 uart=self.uart_location))
         self.atlas_sensor_uart = AtlasScientificUART(self.uart_location)
     elif self.interface == 'I2C':
         self.logger = logging.getLogger(
             "mycodo.inputs.atlas_pt1000_i2c_{bus}_{add}".format(
                 bus=self.i2c_bus, add=self.i2c_address))
         self.atlas_sensor_i2c = AtlasScientificI2C(
             i2c_address=self.i2c_address, i2c_bus=self.i2c_bus)
     else:
         self.logger = logging.getLogger("mycodo.inputs.atlas_pt1000")
Beispiel #16
0
class InputModule(AbstractInput):
    """A sensor support class that monitors the Atlas Scientific sensor DO"""
    def __init__(self, input_dev, testing=False):
        super(InputModule, self).__init__(input_dev,
                                          testing=testing,
                                          name=__name__)
        self.atlas_sensor_ftdi = None
        self.atlas_sensor_uart = None
        self.atlas_sensor_i2c = None
        self.ftdi_location = None
        self.uart_location = None
        self.i2c_address = None
        self.i2c_bus = None

        if not testing:
            self.interface = input_dev.interface
            self.calibrate_sensor_measure = input_dev.calibrate_sensor_measure
            self.max_age = None

            if input_dev.custom_options:
                for each_option in input_dev.custom_options.split(';'):
                    option = each_option.split(',')[0]
                    value = each_option.split(',')[1]
                    if option == 'max_age':
                        self.max_age = int(value)

            try:
                self.initialize_sensor()
            except Exception:
                self.logger.exception("Exception while initializing sensor")

    def initialize_sensor(self):
        from mycodo.devices.atlas_scientific_ftdi import AtlasScientificFTDI
        from mycodo.devices.atlas_scientific_i2c import AtlasScientificI2C
        from mycodo.devices.atlas_scientific_uart import AtlasScientificUART
        if self.interface == 'FTDI':
            self.ftdi_location = self.input_dev.ftdi_location
            self.atlas_sensor_ftdi = AtlasScientificFTDI(self.ftdi_location)
        elif self.interface == 'UART':
            self.uart_location = self.input_dev.uart_location
            self.atlas_sensor_uart = AtlasScientificUART(self.uart_location)
        elif self.interface == 'I2C':
            self.i2c_address = int(str(self.input_dev.i2c_location), 16)
            self.i2c_bus = self.input_dev.i2c_bus
            self.atlas_sensor_i2c = AtlasScientificI2C(
                i2c_address=self.i2c_address, i2c_bus=self.i2c_bus)

    def get_measurement(self):
        """ Gets the sensor's DO measurement via UART/I2C """
        do = None
        self.return_dict = measurements_dict.copy()

        # Read sensor via UART
        if self.interface == 'FTDI':
            if self.atlas_sensor_ftdi.setup:
                lines = self.atlas_sensor_ftdi.query('R')
                if lines:
                    self.logger.debug("All Lines: {lines}".format(lines=lines))

                    # 'check probe' indicates an error reading the sensor
                    if 'check probe' in lines:
                        self.logger.error('"check probe" returned from sensor')
                    # if a string resembling a float value is returned, this
                    # is out measurement value
                    elif str_is_float(lines[0]):
                        do = float(lines[0])
                        self.logger.debug(
                            'Value[0] is float: {val}'.format(val=do))
                    else:
                        # During calibration, the sensor is put into
                        # continuous mode, which causes a return of several
                        # values in one string. If the return value does
                        # not represent a float value, it is likely to be a
                        # string of several values. This parses and returns
                        # the first value.
                        if str_is_float(lines[0].split(b'\r')[0]):
                            do = lines[0].split(b'\r')[0]
                        # Lastly, this is called if the return value cannot
                        # be determined. Watchthe output in the GUI to see
                        # what it is.
                        else:
                            do = lines[0]
                            self.logger.error(
                                'Value[0] is not float or "check probe": '
                                '{val}'.format(val=do))
            else:
                self.logger.error('FTDI device is not set up.'
                                  'Check the log for errors.')

        # Read sensor via UART
        elif self.interface == 'UART':
            if self.atlas_sensor_uart.setup:
                lines = self.atlas_sensor_uart.query('R')
                if lines:
                    self.logger.debug("All Lines: {lines}".format(lines=lines))

                    # 'check probe' indicates an error reading the sensor
                    if 'check probe' in lines:
                        self.logger.error('"check probe" returned from sensor')
                    # if a string resembling a float value is returned, this
                    # is out measurement value
                    elif str_is_float(lines[0]):
                        do = float(lines[0])
                        self.logger.debug(
                            'Value[0] is float: {val}'.format(val=do))
                    else:
                        # During calibration, the sensor is put into
                        # continuous mode, which causes a return of several
                        # values in one string. If the return value does
                        # not represent a float value, it is likely to be a
                        # string of several values. This parses and returns
                        # the first value.
                        if str_is_float(lines[0].split(b'\r')[0]):
                            do = lines[0].split(b'\r')[0]
                        # Lastly, this is called if the return value cannot
                        # be determined. Watchthe output in the GUI to see
                        # what it is.
                        else:
                            do = lines[0]
                            self.logger.error(
                                'Value[0] is not float or "check probe": '
                                '{val}'.format(val=do))
            else:
                self.logger.error('UART device is not set up.'
                                  'Check the log for errors.')

        # Read sensor via I2C
        elif self.interface == 'I2C':
            if self.atlas_sensor_i2c.setup:
                ec_status, ec_str = self.atlas_sensor_i2c.query('R')
                if ec_status == 'error':
                    self.logger.error(
                        "Sensor read unsuccessful: {err}".format(err=ec_str))
                elif ec_status == 'success':
                    do = float(ec_str)
            else:
                self.logger.error(
                    'I2C device is not set up. Check the log for errors.')

        self.value_set(0, do)

        return self.return_dict
Beispiel #17
0
class InputModule(AbstractInput):
    """ A sensor support class that monitors the PT1000's temperature """

    def __init__(self, input_dev, testing=False):
        super(InputModule, self).__init__()
        self.logger = logging.getLogger("mycodo.inputs.atlas_pt1000")
        self.atlas_sensor_ftdi = None
        self.atlas_sensor_uart = None
        self.atlas_sensor_i2c = None

        if not testing:
            self.logger = logging.getLogger(
                "mycodo.inputs.atlas_pt1000_{id}".format(id=input_dev.unique_id.split('-')[0]))

            self.interface = input_dev.interface
            if self.interface == 'FTDI':
                self.ftdi_location = input_dev.ftdi_location
            elif self.interface == 'UART':
                self.uart_location = input_dev.uart_location
            elif self.interface == 'I2C':
                self.i2c_address = int(str(input_dev.i2c_location), 16)
                self.i2c_bus = input_dev.i2c_bus
            self.initialize_sensor()

    def initialize_sensor(self):
        from mycodo.devices.atlas_scientific_ftdi import AtlasScientificFTDI
        from mycodo.devices.atlas_scientific_i2c import AtlasScientificI2C
        from mycodo.devices.atlas_scientific_uart import AtlasScientificUART
        if self.interface == 'FTDI':
            self.logger = logging.getLogger(
                "mycodo.inputs.atlas_pt1000_ftdi_{ftdi}".format(
                    ftdi=self.ftdi_location))
            self.atlas_sensor_ftdi = AtlasScientificFTDI(self.ftdi_location)
        elif self.interface == 'UART':
            self.logger = logging.getLogger(
                "mycodo.inputs.atlas_pt1000_uart_{uart}".format(
                    uart=self.uart_location))
            self.atlas_sensor_uart = AtlasScientificUART(self.uart_location)
        elif self.interface == 'I2C':
            self.logger = logging.getLogger(
                "mycodo.inputs.atlas_pt1000_i2c_{bus}_{add}".format(
                    bus=self.i2c_bus, add=self.i2c_address))
            self.atlas_sensor_i2c = AtlasScientificI2C(
                i2c_address=self.i2c_address, i2c_bus=self.i2c_bus)
        else:
            self.logger = logging.getLogger("mycodo.inputs.atlas_pt1000")

    def get_measurement(self):
        """ Gets the Atlas PT1000's temperature in Celsius """
        temp = None

        return_dict = measurements_dict.copy()

        if self.interface == 'FTDI':
            if self.atlas_sensor_ftdi.setup:
                lines = self.atlas_sensor_ftdi.query('R')
                self.logger.debug("All Lines: {lines}".format(lines=lines))

                if 'check probe' in lines:
                    self.logger.error('"check probe" returned from sensor')
                elif isinstance(lines, list):
                    if str_is_float(lines[0]):
                        temp = float(lines[0])
                        self.logger.debug(
                            'Value[0] is float: {val}'.format(val=temp))
                elif str_is_float(lines):
                    temp = float(lines)
                    self.logger.debug(
                        'Value is float: {val}'.format(val=temp))
                else:
                    self.logger.error(
                        'Unknown value: {val}'.format(val=lines))
            else:
                self.logger.error('FTDI device is not set up. '
                                  'Check the log for errors.')

        elif self.interface == 'UART':
            if self.atlas_sensor_uart.setup:
                lines = self.atlas_sensor_uart.query('R')
                self.logger.debug("All Lines: {lines}".format(lines=lines))

                if 'check probe' in lines:
                    self.logger.error('"check probe" returned from sensor')
                elif str_is_float(lines[0]):
                    temp = float(lines[0])
                    self.logger.debug(
                        'Value[0] is float: {val}'.format(val=temp))
                else:
                    self.logger.error(
                        'Value[0] is not float or "check probe": '
                        '{val}'.format(val=lines[0]))
            else:
                self.logger.error('UART device is not set up. '
                                  'Check the log for errors.')

        elif self.interface == 'I2C':
            if self.atlas_sensor_i2c.setup:
                temp_status, temp_str = self.atlas_sensor_i2c.query('R')
                if temp_status == 'error':
                    self.logger.error(
                        "Sensor read unsuccessful: {err}".format(
                            err=temp_str))
                elif temp_status == 'success':
                    temp = float(temp_str)
            else:
                self.logger.error('I2C device is not set up.'
                                  'Check the log for errors.')

        return_dict[0]['value'] = temp

        return return_dict
Beispiel #18
0
class OutputModule(AbstractOutput):
    """
    An output support class that operates an output
    """
    def __init__(self, output, testing=False):
        super(OutputModule, self).__init__(output,
                                           testing=testing,
                                           name=__name__)

        self.atlas_command = None
        self.currently_dispensing = False
        self.interface = None
        self.mode = None
        self.flow_rate = None

        if not testing:
            self.initialize_output()

    def initialize_output(self):
        self.interface = self.output.interface
        self.mode = self.output.output_mode
        self.flow_rate = self.output.flow_rate

    def setup_output(self):
        if self.interface == 'FTDI':
            from mycodo.devices.atlas_scientific_ftdi import AtlasScientificFTDI
            self.atlas_command = AtlasScientificFTDI(self.output.ftdi_location)
        elif self.interface == 'I2C':
            from mycodo.devices.atlas_scientific_i2c import AtlasScientificI2C
            self.atlas_command = AtlasScientificI2C(
                i2c_address=int(str(self.output.i2c_location), 16),
                i2c_bus=self.output.i2c_bus)
        elif self.interface == 'UART':
            from mycodo.devices.atlas_scientific_uart import AtlasScientificUART
            self.atlas_command = AtlasScientificUART(
                self.output.uart_location, baudrate=self.output.baud_rate)
        else:
            self.logger.error("Unknown interface: {}".format(self.interface))

    def record_dispersal(self, amount_ml=None, seconds_to_run=None):
        measure_dict = copy.deepcopy(measurements_dict)
        if amount_ml:
            measure_dict[0]['value'] = amount_ml
        if seconds_to_run:
            measure_dict[1]['value'] = seconds_to_run
        add_measurements_influxdb(self.unique_id, measure_dict)

    def dispense_duration(self, seconds):
        self.currently_dispensing = True
        timer_dispense = time.time() + seconds

        write_cmd = "D,*"
        self.atlas_command.write(write_cmd)
        self.logger.debug("EZO-PMP command: {}".format(write_cmd))

        while time.time() < timer_dispense and self.currently_dispensing:
            time.sleep(0.1)

        write_cmd = 'X'
        self.atlas_command.write(write_cmd)
        self.logger.debug("EZO-PMP command: {}".format(write_cmd))
        self.currently_dispensing = False

        self.record_dispersal(seconds_to_run=seconds)

    def output_switch(self,
                      state,
                      output_type=None,
                      amount=None,
                      duty_cycle=None):
        if state == 'on' and output_type == 'sec' and amount:
            # Only dispense for a duration if output_type is 'sec'
            # Otherwise, refer to output_mode
            write_db = threading.Thread(target=self.dispense_duration,
                                        args=(amount, ))
            write_db.start()
            return

        elif state == 'on' and output_type in ['vol', None] and amount:
            if self.mode == 'fastest_flow_rate':
                minutes_to_run = amount / 105
                seconds_to_run = minutes_to_run * 60
                write_cmd = 'D,{ml:.2f}'.format(ml=amount)
            elif self.mode == 'specify_flow_rate':
                minutes_to_run = amount / self.flow_rate
                seconds_to_run = minutes_to_run * 60
                write_cmd = 'D,{ml:.2f},{min:.2f}'.format(ml=amount,
                                                          min=minutes_to_run)
            else:
                self.logger.error("Invalid output_mode: '{}'".format(
                    self.mode))
                return

        elif state == 'off' or (amount is not None and amount <= 0):
            self.currently_dispensing = False
            write_cmd = 'X'
            amount = 0
            seconds_to_run = 0

        else:
            self.logger.error(
                "Invalid parameters: State: {state}, Output Type: {ot}, Volume: {vol}, Flow Rate: {fr}"
                .format(state=state,
                        ot=output_type,
                        vol=amount,
                        fr=self.flow_rate))
            return

        self.atlas_command.write(write_cmd)
        self.logger.debug("EZO-PMP command: {}".format(write_cmd))

        if amount and seconds_to_run:
            self.record_dispersal(amount_ml=amount,
                                  seconds_to_run=seconds_to_run)

    def is_on(self):
        if self.is_setup():
            if self.currently_dispensing:
                return True

            device_measurements = db_retrieve_table_daemon(
                DeviceMeasurements).filter(
                    DeviceMeasurements.device_id == self.unique_id)
            for each_dev_meas in device_measurements:
                if each_dev_meas.unit == 'minute':
                    last_measurement = read_last_influxdb(
                        self.unique_id,
                        each_dev_meas.unit,
                        each_dev_meas.channel,
                        measure=each_dev_meas.measurement)
                    if last_measurement:
                        try:
                            datetime_ts = datetime.datetime.strptime(
                                last_measurement[0][:-7],
                                '%Y-%m-%dT%H:%M:%S.%f')
                        except:
                            # Sometimes the original timestamp is in milliseconds
                            # instead of nanoseconds. Therefore, remove 3 less digits
                            # past the decimal and try again to parse.
                            datetime_ts = datetime.datetime.strptime(
                                last_measurement[0][:-4],
                                '%Y-%m-%dT%H:%M:%S.%f')
                        minutes_on = last_measurement[1]
                        ts_pmp_off = datetime_ts + datetime.timedelta(
                            minutes=minutes_on)
                        now = datetime.datetime.utcnow()
                        is_on = bool(now < ts_pmp_off)
                        if is_on:
                            return True
            return False

    def is_setup(self):
        if self.atlas_command:
            return True
        return False
Beispiel #19
0
class AtlaspHSensor(AbstractInput):
    """A sensor support class that monitors the Atlas Scientific sensor pH"""
    def __init__(self,
                 interface,
                 device_loc=None,
                 baud_rate=None,
                 i2c_address=None,
                 i2c_bus=None,
                 sensor_sel=None,
                 testing=False):
        super(AtlaspHSensor, self).__init__()
        self._ph = None
        self.interface = interface
        self.device_loc = device_loc
        self.baud_rate = baud_rate
        self.i2c_address = i2c_address
        self.i2c_bus = i2c_bus
        self.sensor_sel = sensor_sel
        self.atlas_sensor_uart = None
        self.atlas_sensor_i2c = None

        if not testing:
            self.initialize_sensor()

    def __repr__(self):
        """ Representation of object """
        return "<{cls}(ph={ph})>".format(cls=type(self).__name__,
                                         ph="{0:.2f}".format(self._ph))

    def __str__(self):
        """ Return pH information """
        return "pH: {ph}".format(ph="{0:.2f}".format(self._ph))

    def __iter__(self):  # must return an iterator
        """ Atlas pH sensor iterates through live pH readings """
        return self

    def next(self):
        """ Get next pH reading """
        if self.read():  # raised an error
            raise StopIteration  # required
        return dict(ph=float(self._ph))

    @property
    def ph(self):
        """ pH (potential hydrogen) in moles/liter """
        if self._ph is None:  # update if needed
            self.read()
        return self._ph

    def initialize_sensor(self):
        from mycodo.devices.atlas_scientific_i2c import AtlasScientificI2C
        from mycodo.devices.atlas_scientific_uart import AtlasScientificUART
        if self.interface == 'UART':
            self.atlas_sensor_uart = AtlasScientificUART(
                self.device_loc, baudrate=self.baud_rate)
        elif self.interface == 'I2C':
            self.atlas_sensor_i2c = AtlasScientificI2C(
                i2c_address=self.i2c_address, i2c_bus=self.i2c_bus)

    def get_measurement(self):
        """ Gets the sensor's pH measurement via UART/I2C """
        self._ph = None

        try:
            if ',' in self.sensor_sel.calibrate_sensor_measure:
                logger.debug("pH sensor set to calibrate temperature")

                device_id = self.sensor_sel.calibrate_sensor_measure.split(
                    ',')[0]
                measurement = self.sensor_sel.calibrate_sensor_measure.split(
                    ',')[1]
                last_measurement = read_last_influxdb(device_id,
                                                      measurement,
                                                      duration_sec=300)
                if last_measurement:
                    logger.debug(
                        "Latest temperature used to calibrate: {temp}".format(
                            temp=last_measurement[1]))

                    atlas_command = AtlasScientificCommand(self.sensor_sel)
                    ret_value, ret_msg = atlas_command.calibrate(
                        'temperature', temperature=last_measurement[1])
                    time.sleep(0.5)

                    logger.debug("Calibration returned: {val}, {msg}".format(
                        val=ret_value, msg=ret_msg))

            ph = None
            if self.interface == 'UART':
                if self.atlas_sensor_uart.setup:
                    lines = self.atlas_sensor_uart.query('R')
                    if lines:
                        logger.debug("All Lines: {lines}".format(lines=lines))

                        if 'check probe' in lines:
                            logger.error('"check probe" returned from sensor')
                        elif str_is_float(lines[0]):
                            ph = float(lines[0])
                            logger.debug(
                                'Value[0] is float: {val}'.format(val=ph))
                        else:
                            ph = lines[0]
                            logger.error(
                                'Value[0] is not float or "check probe": '
                                '{val}'.format(val=ph))
                else:
                    logger.error('UART device is not set up.'
                                 'Check the log for errors.')
            elif self.interface == 'I2C':
                if self.atlas_sensor_i2c.setup:
                    ph_status, ph_str = self.atlas_sensor_i2c.query('R')
                    if ph_status == 'error':
                        logger.error("Sensor read unsuccessful: {err}".format(
                            err=ph_str))
                    elif ph_status == 'success':
                        ph = float(ph_str)
                else:
                    logger.error('I2C device is not set up.'
                                 'Check the log for errors.')

            return ph
        except:
            logger.exception(1)

    def read(self):
        """
        Takes a reading from the sensor and updates the self._ph value

        :returns: None on success or 1 on error
        """
        try:
            self._ph = self.get_measurement()
            if self._ph is not None:
                return  # success - no errors
        except Exception as e:
            logger.exception(
                "{cls} raised an exception when taking a reading: "
                "{err}".format(cls=type(self).__name__, err=e))
        return 1
Beispiel #20
0
    def initialize_sensor(self):
        from mycodo.devices.atlas_scientific_ftdi import AtlasScientificFTDI
        from mycodo.devices.atlas_scientific_i2c import AtlasScientificI2C
        from mycodo.devices.atlas_scientific_uart import AtlasScientificUART
        if self.interface == 'FTDI':
            self.ftdi_location = self.input_dev.ftdi_location
            self.atlas_sensor = AtlasScientificFTDI(self.ftdi_location)
        elif self.interface == 'UART':
            self.uart_location = self.input_dev.uart_location
            self.atlas_sensor = AtlasScientificUART(self.uart_location)
        elif self.interface == 'I2C':
            self.i2c_address = int(str(self.input_dev.i2c_location), 16)
            self.i2c_bus = self.input_dev.i2c_bus
            self.atlas_sensor = AtlasScientificI2C(
                i2c_address=self.i2c_address, i2c_bus=self.i2c_bus)

        if self.is_enabled(0):
            self.atlas_sensor.query('O,TV,1')
            self.logger.debug("Enabling Total Volume measurement")
        else:
            self.atlas_sensor.query('O,TV,0')
            self.logger.debug("Disabling Total Volume measurement")

        if self.is_enabled(1):
            self.atlas_sensor.query('O,FR,1')
            self.logger.debug("Enabling Flow Rate measurement")
        else:
            self.atlas_sensor.query('O,FR,0')
            self.logger.debug("Disabling Flow Rate measurement")

        if self.flow_meter_type:
            if self.flow_meter_type == 'non-atlas':
                if ';' in self.custom_k_values:
                    list_k_values = self.custom_k_values.split(';')
                    self.atlas_sensor.query('K,clear')
                    self.logger.debug("Cleared K Values")
                    for each_k in list_k_values:
                        if ',' in each_k:
                            self.atlas_sensor.query('K,{}'.format(each_k))
                            self.logger.debug("Set K Value: {}".format(each_k))
                        else:
                            self.logger.error(
                                "Improperly-formatted K-value: {}".format(
                                    each_k))
                elif ',' in self.custom_k_values:
                    self.atlas_sensor.query('K,clear')
                    self.logger.debug("Cleared K Values")
                    self.atlas_sensor.query('K,{}'.format(
                        self.custom_k_values))
                    self.logger.debug("Set K Value: {}".format(
                        self.custom_k_values))
                else:
                    self.logger.error(
                        "Improperly-formatted K-value: {}".format(
                            self.custom_k_values))
                self.atlas_sensor.query('Vp,{}'.format(
                    self.custom_k_value_time_base))
                self.logger.debug("Set Custom Time Base: {}".format(
                    self.custom_k_value_time_base))
            else:
                self.atlas_sensor.query('Set,{}'.format(self.flow_meter_type))
                self.logger.debug("Set Flow Meter: {}".format(
                    self.flow_meter_type))

        if self.flow_rate_unit:
            self.atlas_sensor.query('Frp,{}'.format(self.flow_rate_unit))
            self.logger.debug("Set Flow Rate: l/{}".format(
                self.flow_rate_unit))

        if self.internal_resistor and self.internal_resistor != 'atlas':
            self.atlas_sensor.query('P,{}'.format(int(self.internal_resistor)))
            if self.internal_resistor == '0':
                self.logger.debug("Internal Resistor disabled")
            else:
                self.logger.debug("Internal Resistor set: {} K".format(
                    self.internal_resistor))
Beispiel #21
0
class AtlasScientificCommand:
    """
    Class to handle issuing commands to the Atlas Scientific sensor boards
    """

    def __init__(self, input_dev):
        self.cmd_send = None
        self.ph_sensor_uart = None
        self.ph_sensor_i2c = None
        self.interface = input_dev.interface

        if self.interface == 'FTDI':
            from mycodo.devices.atlas_scientific_ftdi import AtlasScientificFTDI
            self.ph_sensor_ftdi = AtlasScientificFTDI(
                input_dev.ftdi_location)
        elif self.interface == 'UART':
            from mycodo.devices.atlas_scientific_uart import AtlasScientificUART
            self.ph_sensor_uart = AtlasScientificUART(
                input_dev.uart_location,
                baudrate=input_dev.baud_rate)
        elif self.interface == 'I2C':
            from mycodo.devices.atlas_scientific_i2c import AtlasScientificI2C
            self.ph_sensor_i2c = AtlasScientificI2C(
                i2c_address=int(str(input_dev.i2c_location), 16),
                i2c_bus=input_dev.i2c_bus)

        self.board_version, self.board_info = self.get_board_version()

        if self.board_version == 0:
            logger.error("Unable to retrieve device info (this indicates the "
                         "device was not properly initialized or connected)")
        else:
            # TODO: Change back to debug
            logger.error("Device Info: {info}".format(info=self.board_info))
            logger.error("Detected Version: {ver}".format(ver=self.board_version))

    def get_board_version(self):
        """Return the board version of the Atlas Scientific pH sensor"""
        info = None

        try:
            if self.interface == 'FTDI':
                info = self.ph_sensor_ftdi.query('i')
            elif self.interface == 'UART':
                info = self.ph_sensor_uart.query('i')
            elif self.interface == 'I2C':
                info = self.ph_sensor_i2c.query('i')
        except TypeError:
            logger.exception("Unable to determine board version of Atlas sensor")
            return 0, None

        # Check first letter of info response
        # "P" indicates a legacy board version
        if info is None:
            return 0, None
        elif info is list:
            for each_line in info:
                if each_line == 'P':
                    return 1, each_line  # Older board version
                elif ',' in each_line and len(each_line.split(',')) == 3:
                    return 2, each_line  # Newer board version
        return 0, None

    def calibrate(self, command, temperature=None, custom_cmd=None):
        """
        Determine and send the correct command to an Atlas Scientific sensor,
        based on the board version
        """
        # Formulate command based on calibration step and board version.
        # Legacy boards requires a different command than recent boards.
        # Some commands are not necessary for recent boards and will not
        # generate a response.
        err = 1
        msg = "Default message"
        if command == 'temperature' and temperature is not None:
            if self.board_version == 1:
                err, msg = self.send_command(temperature)
            elif self.board_version == 2:
                err, msg = self.send_command('T,{temp}'.format(temp=temperature))
        elif command == 'clear_calibration':
            if self.board_version == 1:
                err, msg = self.send_command('X')
                self.send_command('L0')
            elif self.board_version == 2:
                err, msg = self.send_command('Cal,clear')
        elif command == 'continuous':
            if self.board_version == 1:
                err, msg = self.send_command('C')
            elif self.board_version == 2:
                err, msg = self.send_command('C,1')
        elif command == 'low':
            if self.board_version == 1:
                err, msg = self.send_command('F')
            elif self.board_version == 2:
                err, msg = self.send_command('Cal,low,4.00')
        elif command == 'mid':
            if self.board_version == 1:
                err, msg = self.send_command('S')
            elif self.board_version == 2:
                err, msg = self.send_command('Cal,mid,7.00')
        elif command == 'high':
            if self.board_version == 1:
                err, msg = self.send_command('T')
            elif self.board_version == 2:
                err, msg = self.send_command('Cal,high,10.00')
        elif command == 'end':
            if self.board_version == 1:
                err, msg = self.send_command('E')
            elif self.board_version == 2:
                err, msg = self.send_command('C,0')
        elif custom_cmd:
            err, msg = self.send_command(custom_cmd)
        return err, msg

    def send_command(self, cmd_send):
        """ Send the command (if not None) and return the response """
        try:
            return_value = "No message"
            if cmd_send is not None:
                if self.interface == 'FTDI':
                    return_value = self.ph_sensor_ftdi.query(cmd_send)
                elif self.interface == 'UART':
                    return_value = self.ph_sensor_uart.query(cmd_send)
                elif self.interface == 'I2C':
                    return_value = self.ph_sensor_i2c.query(cmd_send)
                time.sleep(0.1)
                return 0, return_value
            else:
                return 1, "No command given"
        except Exception as err:
            logger.error("{cls} raised an exception while communicating with "
                         "the board: {err}".format(cls=type(self).__name__,
                                                   err=err))
            return 1, err
Beispiel #22
0
class InputModule(AbstractInput):
    """ A sensor support class that monitors the PT1000's temperature """

    def __init__(self, input_dev, testing=False):
        super(InputModule, self).__init__(input_dev, testing=testing, name=__name__)
        self.atlas_sensor = None

        if not testing:
            self.input_dev = input_dev
            self.interface = input_dev.interface

            try:
                self.initialize_sensor()
            except Exception:
                self.logger.exception("Exception while initializing sensor")

            # Throw out first measurement of Atlas Scientific sensor, as it may be prone to error
            self.get_measurement()

    def initialize_sensor(self):
        if self.interface == 'FTDI':
            from mycodo.devices.atlas_scientific_ftdi import AtlasScientificFTDI
            self.ftdi_location = self.input_dev.ftdi_location
            self.atlas_sensor = AtlasScientificFTDI(self.ftdi_location)
        elif self.interface == 'UART':
            from mycodo.devices.atlas_scientific_uart import AtlasScientificUART
            self.uart_location = self.input_dev.uart_location
            self.atlas_sensor = AtlasScientificUART(self.uart_location)
        elif self.interface == 'I2C':
            from mycodo.devices.atlas_scientific_i2c import AtlasScientificI2C
            self.i2c_address = int(str(self.input_dev.i2c_location), 16)
            self.i2c_bus = self.input_dev.i2c_bus
            self.atlas_sensor = AtlasScientificI2C(
                i2c_address=self.i2c_address, i2c_bus=self.i2c_bus)

    def get_measurement(self):
        """ Gets the Atlas PT1000's temperature in Celsius """
        temp = None
        self.return_dict = measurements_dict.copy()

        if self.interface == 'FTDI':
            if self.atlas_sensor.setup:
                lines = self.atlas_sensor.query('R')
                self.logger.debug("All Lines: {lines}".format(lines=lines))

                if 'check probe' in lines:
                    self.logger.error('"check probe" returned from sensor')
                elif isinstance(lines, list):
                    if str_is_float(lines[0]):
                        temp = float(lines[0])
                        self.logger.debug(
                            'Value[0] is float: {val}'.format(val=temp))
                elif str_is_float(lines):
                    temp = float(lines)
                    self.logger.debug(
                        'Value is float: {val}'.format(val=temp))
                else:
                    self.logger.error(
                        'Unknown value: {val}'.format(val=lines))
            else:
                self.logger.error('FTDI device is not set up. '
                                  'Check the log for errors.')

        elif self.interface == 'UART':
            if self.atlas_sensor.setup:
                lines = self.atlas_sensor.query('R')
                self.logger.debug("All Lines: {lines}".format(lines=lines))

                if 'check probe' in lines:
                    self.logger.error('"check probe" returned from sensor')
                elif str_is_float(lines[0]):
                    temp = float(lines[0])
                    self.logger.debug(
                        'Value[0] is float: {val}'.format(val=temp))
                else:
                    self.logger.error(
                        'Value[0] is not float or "check probe": '
                        '{val}'.format(val=lines[0]))
            else:
                self.logger.error('UART device is not set up. '
                                  'Check the log for errors.')

        elif self.interface == 'I2C':
            if self.atlas_sensor.setup:
                temp_status, temp_str = self.atlas_sensor.query('R')
                if temp_status == 'error':
                    self.logger.error(
                        "Sensor read unsuccessful: {err}".format(
                            err=temp_str))
                elif temp_status == 'success':
                    temp = float(temp_str)
            else:
                self.logger.error('I2C device is not set up.'
                                  'Check the log for errors.')

        if temp == -1023:  # Erroneous measurement
            return

        self.value_set(0, temp)

        return self.return_dict
Beispiel #23
0
class InputModule(AbstractInput):
    """A sensor support class that monitors the Atlas Scientific sensor ORP"""
    def __init__(self, input_dev, testing=False):
        super(InputModule, self).__init__(input_dev,
                                          testing=testing,
                                          name=__name__)
        self.atlas_sensor_ftdi = None
        self.atlas_sensor_uart = None
        self.atlas_sensor_i2c = None
        self.ftdi_location = None
        self.uart_location = None
        self.i2c_address = None
        self.i2c_bus = None

        # Initialize custom options
        self.temperature_comp_meas_device_id = None
        self.temperature_comp_meas_measurement_id = None
        self.max_age = None
        # Set custom options
        self.setup_custom_options(INPUT_INFORMATION['custom_options'],
                                  input_dev)

        if not testing:
            self.input_dev = input_dev
            self.interface = input_dev.interface

            if self.temperature_comp_meas_measurement_id:
                self.atlas_command = AtlasScientificCommand(self.input_dev)

            try:
                self.initialize_sensor()
            except Exception:
                self.logger.exception("Exception while initializing sensor")

            # Throw out first measurement of Atlas Scientific sensor, as it may be prone to error
            self.get_measurement()

    def initialize_sensor(self):
        from mycodo.devices.atlas_scientific_ftdi import AtlasScientificFTDI
        from mycodo.devices.atlas_scientific_i2c import AtlasScientificI2C
        from mycodo.devices.atlas_scientific_uart import AtlasScientificUART
        if self.interface == 'FTDI':
            self.ftdi_location = self.input_dev.ftdi_location
            self.atlas_sensor_ftdi = AtlasScientificFTDI(self.ftdi_location)
        elif self.interface == 'UART':
            self.uart_location = self.input_dev.uart_location
            self.atlas_sensor_uart = AtlasScientificUART(self.uart_location)
        elif self.interface == 'I2C':
            self.i2c_address = int(str(self.input_dev.i2c_location), 16)
            self.i2c_bus = self.input_dev.i2c_bus
            self.atlas_sensor_i2c = AtlasScientificI2C(
                i2c_address=self.i2c_address, i2c_bus=self.i2c_bus)

    def get_measurement(self):
        """ Gets the sensor's ORP measurement via UART/I2C """
        orp = None
        self.return_dict = measurements_dict.copy()

        # Compensate measurement based on a temperature measurement
        if self.temperature_comp_meas_measurement_id and self.atlas_command:
            self.logger.debug("pH sensor set to calibrate temperature")

            last_measurement = self.get_last_measurement(
                self.temperature_comp_meas_device_id,
                self.temperature_comp_meas_measurement_id,
                max_age=self.max_age)

            if last_measurement:
                self.logger.debug(
                    "Latest temperature used to calibrate: {temp}".format(
                        temp=last_measurement[1]))

                ret_value, ret_msg = self.atlas_command.calibrate(
                    'temperature', set_amount=last_measurement[1])
                time.sleep(0.5)

                self.logger.debug("Calibration returned: {val}, {msg}".format(
                    val=ret_value, msg=ret_msg))
            else:
                self.logger.error(
                    "Calibration measurement not found within the past "
                    "{} seconds".format(self.max_age))

        # Read sensor via UART
        if self.interface == 'FTDI':
            if self.atlas_sensor_ftdi.setup:
                lines = self.atlas_sensor_ftdi.query('R')
                if lines:
                    self.logger.debug("All Lines: {lines}".format(lines=lines))

                    # 'check probe' indicates an error reading the sensor
                    if 'check probe' in lines:
                        self.logger.error('"check probe" returned from sensor')
                    # if a string resembling a float value is returned, this
                    # is out measurement value
                    elif str_is_float(lines[0]):
                        orp = float(lines[0])
                        self.logger.debug(
                            'Value[0] is float: {val}'.format(val=orp))
                    else:
                        # During calibration, the sensor is put into
                        # continuous mode, which causes a return of several
                        # values in one string. If the return value does
                        # not represent a float value, it is likely to be a
                        # string of several values. This parses and returns
                        # the first value.
                        if str_is_float(lines[0].split(b'\r')[0]):
                            orp = lines[0].split(b'\r')[0]
                        # Lastly, this is called if the return value cannot
                        # be determined. Watchthe output in the GUI to see
                        # what it is.
                        else:
                            orp = lines[0]
                            self.logger.error(
                                'Value[0] is not float or "check probe": '
                                '{val}'.format(val=orp))
            else:
                self.logger.error('FTDI device is not set up.'
                                  'Check the log for errors.')

        # Read sensor via UART
        elif self.interface == 'UART':
            if self.atlas_sensor_uart.setup:
                lines = self.atlas_sensor_uart.query('R')
                if lines:
                    self.logger.debug("All Lines: {lines}".format(lines=lines))

                    # 'check probe' indicates an error reading the sensor
                    if 'check probe' in lines:
                        self.logger.error('"check probe" returned from sensor')
                    # if a string resembling a float value is returned, this
                    # is out measurement value
                    elif str_is_float(lines[0]):
                        orp = float(lines[0])
                        self.logger.debug(
                            'Value[0] is float: {val}'.format(val=orp))
                    else:
                        # During calibration, the sensor is put into
                        # continuous mode, which causes a return of several
                        # values in one string. If the return value does
                        # not represent a float value, it is likely to be a
                        # string of several values. This parses and returns
                        # the first value.
                        if str_is_float(lines[0].split(b'\r')[0]):
                            orp = lines[0].split(b'\r')[0]
                        # Lastly, this is called if the return value cannot
                        # be determined. Watchthe output in the GUI to see
                        # what it is.
                        else:
                            orp = lines[0]
                            self.logger.error(
                                'Value[0] is not float or "check probe": '
                                '{val}'.format(val=orp))
            else:
                self.logger.error('UART device is not set up.'
                                  'Check the log for errors.')

        # Read sensor via I2C
        elif self.interface == 'I2C':
            if self.atlas_sensor_i2c.setup:
                ec_status, ec_str = self.atlas_sensor_i2c.query('R')
                if ec_status == 'error':
                    self.logger.error(
                        "Sensor read unsuccessful: {err}".format(err=ec_str))
                elif ec_status == 'success':
                    orp = float(ec_str)
            else:
                self.logger.error(
                    'I2C device is not set up. Check the log for errors.')

        self.value_set(0, orp)

        return self.return_dict
Beispiel #24
0
class AtlasElectricalConductivitySensor(AbstractInput):
    """A sensor support class that monitors the Atlas Scientific sensor ElectricalConductivity"""
    def __init__(self,
                 interface,
                 device_loc=None,
                 baud_rate=None,
                 i2c_address=None,
                 i2c_bus=None,
                 sensor_sel=None,
                 testing=False):
        super(AtlasElectricalConductivitySensor, self).__init__()
        self.logger = logging.getLogger("mycodo.inputs.atlas_ec")

        self._electrical_conductivity = None
        self.interface = interface
        self.device_loc = device_loc
        self.baud_rate = baud_rate
        self.i2c_address = i2c_address
        self.i2c_bus = i2c_bus
        self.sensor_sel = sensor_sel
        self.atlas_sensor_uart = None
        self.atlas_sensor_i2c = None

        if not testing:
            try:
                self.initialize_sensor()
            except Exception:
                self.logger.exception("Exception while initializing sensor")

    def __repr__(self):
        """ Representation of object """
        return "<{cls}(electrical_conductivity={ec})>".format(
            cls=type(self).__name__,
            ec="{0:.2f}".format(self._electrical_conductivity))

    def __str__(self):
        """ Return Electrical Conductivity information """
        return "Electrical Conductivity: {ec}".format(
            ec="{0:.2f}".format(self._electrical_conductivity))

    def __iter__(self):  # must return an iterator
        """ Atlas Electrical Conductivity sensor iterates through live Electrical Conductivity readings """
        return self

    def next(self):
        """ Get next Electrical Conductivity reading """
        if self.read():  # raised an error
            raise StopIteration  # required
        return dict(
            electrical_conductivity=float(self._electrical_conductivity))

    @property
    def electrical_conductivity(self):
        """ Electrical Conductivity """
        if self._electrical_conductivity is None:  # update if needed
            self.read()
        return self._electrical_conductivity

    def initialize_sensor(self):
        from mycodo.devices.atlas_scientific_i2c import AtlasScientificI2C
        from mycodo.devices.atlas_scientific_uart import AtlasScientificUART
        if self.interface == 'UART':
            self.logger = logging.getLogger(
                "mycodo.inputs.atlas_electrical_conductivity_{uart}".format(
                    uart=self.device_loc))
            self.atlas_sensor_uart = AtlasScientificUART(
                self.device_loc, baudrate=self.baud_rate)
        elif self.interface == 'I2C':
            self.logger = logging.getLogger(
                "mycodo.inputs.atlas_electrical_conductivity_{bus}_{add}".
                format(bus=self.i2c_bus, add=self.i2c_address))
            self.atlas_sensor_i2c = AtlasScientificI2C(
                i2c_address=self.i2c_address, i2c_bus=self.i2c_bus)

    def get_measurement(self):
        """ Gets the sensor's Electrical Conductivity measurement via UART/I2C """
        self._electrical_conductivity = None
        electrical_conductivity = None

        # Read sensor via UART
        if self.interface == 'UART':
            if self.atlas_sensor_uart.setup:
                lines = self.atlas_sensor_uart.query('R')
                if lines:
                    self.logger.debug("All Lines: {lines}".format(lines=lines))

                    # 'check probe' indicates an error reading the sensor
                    if 'check probe' in lines:
                        self.logger.error('"check probe" returned from sensor')
                    # if a string resembling a float value is returned, this
                    # is out measurement value
                    elif str_is_float(lines[0]):
                        electrical_conductivity = float(lines[0])
                        self.logger.debug('Value[0] is float: {val}'.format(
                            val=electrical_conductivity))
                    else:
                        # During calibration, the sensor is put into
                        # continuous mode, which causes a return of several
                        # values in one string. If the return value does
                        # not represent a float value, it is likely to be a
                        # string of several values. This parses and returns
                        # the first value.
                        if str_is_float(lines[0].split(b'\r')[0]):
                            electrical_conductivity = lines[0].split(b'\r')[0]
                        # Lastly, this is called if the return value cannot
                        # be determined. Watchthe output in the GUI to see
                        # what it is.
                        else:
                            electrical_conductivity = lines[0]
                            self.logger.error(
                                'Value[0] is not float or "check probe": '
                                '{val}'.format(val=electrical_conductivity))
            else:
                self.logger.error('UART device is not set up.'
                                  'Check the log for errors.')

        # Read sensor via I2C
        elif self.interface == 'I2C':
            if self.atlas_sensor_i2c.setup:
                ec_status, ec_str = self.atlas_sensor_i2c.query('R')
                if ec_status == 'error':
                    self.logger.error(
                        "Sensor read unsuccessful: {err}".format(err=ec_str))
                elif ec_status == 'success':
                    electrical_conductivity = float(ec_str)
            else:
                self.logger.error(
                    'I2C device is not set up. Check the log for errors.')

        return electrical_conductivity

    def read(self):
        """
        Takes a reading from the sensor and updates the self._electrical_conductivity value

        :returns: None on success or 1 on error
        """
        try:
            self._electrical_conductivity = self.get_measurement()
            if self._electrical_conductivity is not None:
                return  # success - no errors
        except Exception as e:
            self.logger.exception(
                "{cls} raised an exception when taking a reading: "
                "{err}".format(cls=type(self).__name__, err=e))
        return 1
Beispiel #25
0
class AtlaspHSensor(AbstractInput):
    """A sensor support class that monitors the Atlas Scientific sensor pH"""
    def __init__(self, input_dev, testing=False):
        super(AtlaspHSensor, self).__init__()
        self.logger = logging.getLogger("mycodo.inputs.atlas_ph")
        self._ph = None
        self.atlas_sensor_uart = None
        self.atlas_sensor_i2c = None

        if not testing:
            self.logger = logging.getLogger(
                "mycodo.inputs.atlas_ph_{id}".format(id=input_dev.id))
            self.input_dev = input_dev
            self.interface = input_dev.interface
            self.device_loc = input_dev.device_loc
            self.i2c_address = int(str(input_dev.location), 16)
            self.i2c_bus = input_dev.i2c_bus
            self.calibrate_sensor_measure = input_dev.calibrate_sensor_measure
            try:
                self.initialize_sensor()
            except Exception:
                self.logger.exception("Exception while initializing sensor")

    def __repr__(self):
        """ Representation of object """
        return "<{cls}(ph={ph})>".format(cls=type(self).__name__,
                                         ph="{0:.2f}".format(self._ph))

    def __str__(self):
        """ Return pH information """
        return "pH: {ph}".format(ph="{0:.2f}".format(self._ph))

    def __iter__(self):  # must return an iterator
        """ Atlas pH sensor iterates through live pH readings """
        return self

    def next(self):
        """ Get next pH reading """
        if self.read():  # raised an error
            raise StopIteration  # required
        return dict(ph=float(self._ph))

    @property
    def ph(self):
        """ pH (potential hydrogen) in moles/liter """
        if self._ph is None:  # update if needed
            self.read()
        return self._ph

    def initialize_sensor(self):
        from mycodo.devices.atlas_scientific_i2c import AtlasScientificI2C
        from mycodo.devices.atlas_scientific_uart import AtlasScientificUART
        if self.interface == 'UART':
            self.logger = logging.getLogger(
                "mycodo.inputs.atlas_ph_{uart}".format(uart=self.device_loc))
            self.atlas_sensor_uart = AtlasScientificUART(self.device_loc)
        elif self.interface == 'I2C':
            self.logger = logging.getLogger(
                "mycodo.inputs.atlas_ph_{bus}_{add}".format(
                    bus=self.i2c_bus, add=self.i2c_address))
            self.atlas_sensor_i2c = AtlasScientificI2C(
                i2c_address=self.i2c_address, i2c_bus=self.i2c_bus)

    def get_measurement(self):
        """ Gets the sensor's pH measurement via UART/I2C """
        self._ph = None
        ph = None

        # Calibrate the pH measurement based on a temperature measurement
        if (self.calibrate_sensor_measure
                and ',' in self.calibrate_sensor_measure):
            self.logger.debug("pH sensor set to calibrate temperature")

            device_id = self.calibrate_sensor_measure.split(',')[0]
            measurement = self.calibrate_sensor_measure.split(',')[1]
            last_measurement = read_last_influxdb(device_id,
                                                  measurement,
                                                  duration_sec=300)
            if last_measurement:
                self.logger.debug(
                    "Latest temperature used to calibrate: {temp}".format(
                        temp=last_measurement[1]))

                atlas_command = AtlasScientificCommand(self.input_dev)
                ret_value, ret_msg = atlas_command.calibrate(
                    'temperature', temperature=last_measurement[1])
                time.sleep(0.5)

                self.logger.debug("Calibration returned: {val}, {msg}".format(
                    val=ret_value, msg=ret_msg))

        # Read sensor via UART
        if self.interface == 'UART':
            if self.atlas_sensor_uart.setup:
                lines = self.atlas_sensor_uart.query('R')
                if lines:
                    self.logger.debug("All Lines: {lines}".format(lines=lines))

                    # 'check probe' indicates an error reading the sensor
                    if 'check probe' in lines:
                        self.logger.error('"check probe" returned from sensor')
                    # if a string resembling a float value is returned, this
                    # is out measurement value
                    elif str_is_float(lines[0]):
                        ph = float(lines[0])
                        self.logger.debug(
                            'Value[0] is float: {val}'.format(val=ph))
                    else:
                        # During calibration, the sensor is put into
                        # continuous mode, which causes a return of several
                        # values in one string. If the return value does
                        # not represent a float value, it is likely to be a
                        # string of several values. This parses and returns
                        # the first value.
                        if str_is_float(lines[0].split(b'\r')[0]):
                            ph = lines[0].split(b'\r')[0]
                        # Lastly, this is called if the return value cannot
                        # be determined. Watchthe output in the GUI to see
                        # what it is.
                        else:
                            ph = lines[0]
                            self.logger.error(
                                'Value[0] is not float or "check probe": '
                                '{val}'.format(val=ph))
            else:
                self.logger.error('UART device is not set up.'
                                  'Check the log for errors.')

        # Read sensor via I2C
        elif self.interface == 'I2C':
            if self.atlas_sensor_i2c.setup:
                ph_status, ph_str = self.atlas_sensor_i2c.query('R')
                if ph_status == 'error':
                    self.logger.error(
                        "Sensor read unsuccessful: {err}".format(err=ph_str))
                elif ph_status == 'success':
                    ph = float(ph_str)
            else:
                self.logger.error(
                    'I2C device is not set up. Check the log for errors.')

        return ph

    def read(self):
        """
        Takes a reading from the sensor and updates the self._ph value

        :returns: None on success or 1 on error
        """
        try:
            self._ph = self.get_measurement()
            if self._ph is not None:
                return  # success - no errors
        except Exception as e:
            self.logger.exception(
                "{cls} raised an exception when taking a reading: "
                "{err}".format(cls=type(self).__name__, err=e))
        return 1
Beispiel #26
0
class InputModule(AbstractInput):
    """A sensor support class that monitors the Atlas Scientific sensor ElectricalConductivity"""

    def __init__(self, input_dev, testing=False):
        super(InputModule, self).__init__()
        self.logger = logging.getLogger("mycodo.inputs.atlas_ec")
        self.atlas_sensor_ftdi = None
        self.atlas_sensor_uart = None
        self.atlas_sensor_i2c = None

        if not testing:
            self.logger = logging.getLogger(
                "mycodo.inputs.atlas_ec_{id}".format(
                    id=input_dev.unique_id.split('-')[0]))

            self.interface = input_dev.interface
            if self.interface == 'FTDI':
                self.ftdi_location = input_dev.ftdi_location
            elif self.interface == 'UART':
                self.uart_location = input_dev.uart_location
            elif self.interface == 'I2C':
                self.i2c_address = int(str(input_dev.i2c_location), 16)
                self.i2c_bus = input_dev.i2c_bus
            try:
                self.initialize_sensor()
            except Exception:
                self.logger.exception("Exception while initializing sensor")

    def initialize_sensor(self):
        from mycodo.devices.atlas_scientific_ftdi import AtlasScientificFTDI
        from mycodo.devices.atlas_scientific_i2c import AtlasScientificI2C
        from mycodo.devices.atlas_scientific_uart import AtlasScientificUART
        if self.interface == 'FTDI':
            self.logger = logging.getLogger(
                "mycodo.inputs.atlas_electrical_conductivity_ftdi_{ftdi}".format(
                    ftdi=self.ftdi_location))
            self.atlas_sensor_ftdi = AtlasScientificFTDI(self.ftdi_location)
        elif self.interface == 'UART':
            self.logger = logging.getLogger(
                "mycodo.inputs.atlas_electrical_conductivity_uart_{uart}".format(
                    uart=self.uart_location))
            self.atlas_sensor_uart = AtlasScientificUART(self.uart_location)
        elif self.interface == 'I2C':
            self.logger = logging.getLogger(
                "mycodo.inputs.atlas_electrical_conductivity_i2c_{bus}_{add}".format(
                    bus=self.i2c_bus, add=self.i2c_address))
            self.atlas_sensor_i2c = AtlasScientificI2C(
                i2c_address=self.i2c_address, i2c_bus=self.i2c_bus)

    def get_measurement(self):
        """ Gets the sensor's Electrical Conductivity measurement via UART/I2C """
        electrical_conductivity = None

        return_dict = measurements_dict.copy()

        # Read sensor via UART
        if self.interface == 'FTDI':
            if self.atlas_sensor_ftdi.setup:
                lines = self.atlas_sensor_ftdi.query('R')
                if lines:
                    self.logger.debug(
                        "All Lines: {lines}".format(lines=lines))

                    # 'check probe' indicates an error reading the sensor
                    if 'check probe' in lines:
                        self.logger.error(
                            '"check probe" returned from sensor')
                    # if a string resembling a float value is returned, this
                    # is out measurement value
                    elif str_is_float(lines[0]):
                        electrical_conductivity = float(lines[0])
                        self.logger.debug(
                            'Value[0] is float: {val}'.format(val=electrical_conductivity))
                    else:
                        # During calibration, the sensor is put into
                        # continuous mode, which causes a return of several
                        # values in one string. If the return value does
                        # not represent a float value, it is likely to be a
                        # string of several values. This parses and returns
                        # the first value.
                        if str_is_float(lines[0].split(b'\r')[0]):
                            electrical_conductivity = lines[0].split(b'\r')[0]
                        # Lastly, this is called if the return value cannot
                        # be determined. Watchthe output in the GUI to see
                        # what it is.
                        else:
                            electrical_conductivity = lines[0]
                            self.logger.error(
                                'Value[0] is not float or "check probe": '
                                '{val}'.format(val=electrical_conductivity))
            else:
                self.logger.error('FTDI device is not set up.'
                                  'Check the log for errors.')

        # Read sensor via UART
        elif self.interface == 'UART':
            if self.atlas_sensor_uart.setup:
                lines = self.atlas_sensor_uart.query('R')
                if lines:
                    self.logger.debug(
                        "All Lines: {lines}".format(lines=lines))

                    # 'check probe' indicates an error reading the sensor
                    if 'check probe' in lines:
                        self.logger.error(
                            '"check probe" returned from sensor')
                    # if a string resembling a float value is returned, this
                    # is out measurement value
                    elif str_is_float(lines[0]):
                        electrical_conductivity = float(lines[0])
                        self.logger.debug(
                            'Value[0] is float: {val}'.format(val=electrical_conductivity))
                    else:
                        # During calibration, the sensor is put into
                        # continuous mode, which causes a return of several
                        # values in one string. If the return value does
                        # not represent a float value, it is likely to be a
                        # string of several values. This parses and returns
                        # the first value.
                        if str_is_float(lines[0].split(b'\r')[0]):
                            electrical_conductivity = lines[0].split(b'\r')[0]
                        # Lastly, this is called if the return value cannot
                        # be determined. Watchthe output in the GUI to see
                        # what it is.
                        else:
                            electrical_conductivity = lines[0]
                            self.logger.error(
                                'Value[0] is not float or "check probe": '
                                '{val}'.format(val=electrical_conductivity))
            else:
                self.logger.error('UART device is not set up.'
                                  'Check the log for errors.')

        # Read sensor via I2C
        elif self.interface == 'I2C':
            if self.atlas_sensor_i2c.setup:
                ec_status, ec_str = self.atlas_sensor_i2c.query('R')
                if ec_status == 'error':
                    self.logger.error(
                        "Sensor read unsuccessful: {err}".format(
                            err=ec_str))
                elif ec_status == 'success':
                    electrical_conductivity = float(ec_str)
            else:
                self.logger.error(
                    'I2C device is not set up. Check the log for errors.')

        return_dict[0]['value'] = electrical_conductivity

        return return_dict
Beispiel #27
0
class InputModule(AbstractInput):
    """A sensor support class that monitors the Atlas Scientific sensor"""
    def __init__(self, input_dev, testing=False):
        super(InputModule, self).__init__(input_dev,
                                          testing=testing,
                                          name=__name__)
        self.atlas_sensor = None
        self.enabled_rgb = False

        # Initialize custom option variables to None
        self.led_only_while_reading = None
        self.led_percentage = None
        self.gamma_correction = None

        # Set custom option variables to defaults or user-set values
        self.setup_custom_options(INPUT_INFORMATION['custom_options'],
                                  input_dev)

        if not testing:
            self.input_dev = input_dev
            self.interface = input_dev.interface

            try:
                self.initialize_sensor()
            except Exception:
                self.logger.exception("Exception while initializing sensor")

            if self.led_only_while_reading and self.led_percentage:
                self.atlas_sensor.query('L,{},T'.format(self.led_percentage))

            if self.gamma_correction:
                self.atlas_sensor.query('G,{}'.format(self.gamma_correction))

            if self.is_enabled(0) or self.is_enabled(1) or self.is_enabled(2):
                self.enabled_rgb = True
                self.atlas_sensor.query('O,RGB,1')
            else:
                self.atlas_sensor.query('O,RGB,0')

            if self.is_enabled(3) or self.is_enabled(4) or self.is_enabled(5):
                self.atlas_sensor.query('O,CIE,1')
            else:
                self.atlas_sensor.query('O,CIE,0')

            if self.is_enabled(6):
                self.atlas_sensor.query('O,LUX,1')
            else:
                self.atlas_sensor.query('O,LUX,0')

            if self.is_enabled(7):
                self.atlas_sensor.query('O,PROX,1')
            else:
                self.atlas_sensor.query('O,PROX,0')

            # Throw out first measurement of Atlas Scientific sensor, as it may be prone to error
            self.get_measurement()

    def initialize_sensor(self):
        from mycodo.devices.atlas_scientific_ftdi import AtlasScientificFTDI
        from mycodo.devices.atlas_scientific_i2c import AtlasScientificI2C
        from mycodo.devices.atlas_scientific_uart import AtlasScientificUART
        if self.interface == 'FTDI':
            self.ftdi_location = self.input_dev.ftdi_location
            self.atlas_sensor = AtlasScientificFTDI(self.ftdi_location)
        elif self.interface == 'UART':
            self.uart_location = self.input_dev.uart_location
            self.atlas_sensor = AtlasScientificUART(self.uart_location)
        elif self.interface == 'I2C':
            self.i2c_address = int(str(self.input_dev.i2c_location), 16)
            self.i2c_bus = self.input_dev.i2c_bus
            self.atlas_sensor = AtlasScientificI2C(
                i2c_address=self.i2c_address, i2c_bus=self.i2c_bus)

    def get_measurement(self):
        """ Gets the sensor's Electrical Conductivity measurement via UART/I2C """
        return_string = None
        self.return_dict = measurements_dict.copy()

        # Read sensor via FTDI
        if self.interface == 'FTDI':
            if self.atlas_sensor.setup:
                lines = self.atlas_sensor.query('R')
                if lines:
                    self.logger.debug("All Lines: {lines}".format(lines=lines))

                    # 'check probe' indicates an error reading the sensor
                    if 'check probe' in lines:
                        self.logger.error('"check probe" returned from sensor')
                    # if a string resembling a float value is returned, this
                    # is out measurement value
                    elif str_is_float(lines[0]):
                        return_string = lines[0]
                        self.logger.debug('Value[0] is float: {val}'.format(
                            val=return_string))
                    else:
                        # During calibration, the sensor is put into
                        # continuous mode, which causes a return of several
                        # values in one string. If the return value does
                        # not represent a float value, it is likely to be a
                        # string of several values. This parses and returns
                        # the first value.
                        if str_is_float(lines[0].split(b'\r')[0]):
                            return_string = lines[0].split(b'\r')[0]
                        # Lastly, this is called if the return value cannot
                        # be determined. Watchthe output in the GUI to see
                        # what it is.
                        else:
                            return_string = lines[0]
                            self.logger.error(
                                'Value[0] is not float or "check probe": '
                                '{val}'.format(val=return_string))
            else:
                self.logger.error('FTDI device is not set up.'
                                  'Check the log for errors.')

        # Read sensor via UART
        elif self.interface == 'UART':
            if self.atlas_sensor.setup:
                lines = self.atlas_sensor.query('R')
                if lines:
                    self.logger.debug("All Lines: {lines}".format(lines=lines))

                    # 'check probe' indicates an error reading the sensor
                    if 'check probe' in lines:
                        self.logger.error('"check probe" returned from sensor')
                    # if a string resembling a float value is returned, this
                    # is out measurement value
                    elif str_is_float(lines[0]):
                        return_string = lines[0]
                        self.logger.debug('Value[0] is float: {val}'.format(
                            val=return_string))
                    else:
                        # During calibration, the sensor is put into
                        # continuous mode, which causes a return of several
                        # values in one string. If the return value does
                        # not represent a float value, it is likely to be a
                        # string of several values. This parses and returns
                        # the first value.
                        if str_is_float(lines[0].split(b'\r')[0]):
                            return_string = lines[0].split(b'\r')[0]
                        # Lastly, this is called if the return value cannot
                        # be determined. Watchthe output in the GUI to see
                        # what it is.
                        else:
                            return_string = lines[0]
                            self.logger.error(
                                'Value[0] is not float or "check probe": '
                                '{val}'.format(val=return_string))
            else:
                self.logger.error('UART device is not set up.'
                                  'Check the log for errors.')

        # Read sensor via I2C
        elif self.interface == 'I2C':
            if self.atlas_sensor.setup:
                ec_status, return_string = self.atlas_sensor.query('R')
                if ec_status == 'error':
                    self.logger.error("Sensor read unsuccessful: {err}".format(
                        err=return_string))
                elif ec_status == 'success':
                    self.logger.debug('Value: {val}'.format(val=return_string))
            else:
                self.logger.error(
                    'I2C device is not set up. Check the log for errors.')

        # Parse return string
        if ',' in return_string:
            index_place = 0
            return_list = return_string.split(',')
            if self.enabled_rgb:
                if self.is_enabled(0):
                    self.value_set(0, int(return_list[index_place + 0]))
                if self.is_enabled(1):
                    self.value_set(1, int(return_list[index_place + 1]))
                if self.is_enabled(2):
                    self.value_set(2, int(return_list[index_place + 2]))
                index_place += 3
            if return_list[index_place] == 'P':
                if self.is_enabled(7):
                    self.value_set(7, int(return_list[index_place + 1]))
                index_place += 2
            if return_list[index_place] == 'Lux':
                if self.is_enabled(6):
                    self.value_set(6, int(return_list[index_place + 1]))
                index_place += 2
            if return_list[index_place] == 'xyY':
                if self.is_enabled(3):
                    self.value_set(3, float(return_list[index_place + 1]))
                if self.is_enabled(4):
                    self.value_set(4, float(return_list[index_place + 2]))
                if self.is_enabled(5):
                    self.value_set(5, int(return_list[index_place + 3]))

        return self.return_dict

    def calibrate(self):
        self.atlas_sensor.query('Cal')
Beispiel #28
0
class AtlasScientificCommand:
    """
    Class to handle issuing commands to the Atlas Scientific sensor boards
    """
    def __init__(self, sensor_sel):
        self.cmd_send = None
        self.ph_sensor_uart = None
        self.ph_sensor_i2c = None
        self.interface = sensor_sel.interface

        if self.interface == 'UART':
            self.ph_sensor_uart = AtlasScientificUART(
                sensor_sel.device_loc, baudrate=sensor_sel.baud_rate)
        elif self.interface == 'I2C':
            self.ph_sensor_i2c = AtlasScientificI2C(
                i2c_address=sensor_sel.i2c_address, i2c_bus=sensor_sel.i2c_bus)

        self.board_version, self.board_info = self.board_version()

        if self.board_version == 0:
            logger.error("Unable to retrieve device info (this indicates the "
                         "device was not properly initialized or connected)")
        else:
            logger.debug("Device Info: {info}".format(info=self.board_info))
            logger.debug(
                "Detected Version: {ver}".format(ver=self.board_version))

    def board_version(self):
        """Return the board version of the Atlas Scientific pH sensor"""
        info = None

        if self.interface == 'UART':
            info = self.ph_sensor_uart.query('i')[0]
        elif self.interface == 'I2C':
            info = self.ph_sensor_i2c.query('i')

        # Check first letter of info response
        # "P" indicates a legacy board version
        if info is None:
            return 0, None
        elif info[0] == 'P':
            return 1, info  # Older board version
        else:
            return 2, info  # Newer board version

    def calibrate(self, command, temperature=None, custom_cmd=None):
        """
        Determine and send the correct command to an Atlas Scientific sensor,
        based on the board version
        """
        # Formulate command based on calibration step and board version.
        # Legacy boards requires a different command than recent boards.
        # Some commands are not necessary for recent boards and will not
        # generate a response.
        err = 1
        msg = "Default message"
        if command == 'temperature' and temperature is not None:
            if self.board_version == 1:
                err, msg = self.send_command(temperature)
            elif self.board_version == 2:
                err, msg = self.send_command(
                    'T,{temp}'.format(temp=temperature))
        elif command == 'clear_calibration':
            if self.board_version == 1:
                err, msg = self.send_command('X')
                self.send_command('L0')
            elif self.board_version == 2:
                err, msg = self.send_command('Cal,clear')
        elif command == 'continuous':
            if self.board_version == 1:
                err, msg = self.send_command('C')
        elif command == 'low':
            if self.board_version == 1:
                err, msg = self.send_command('F')
            elif self.board_version == 2:
                err, msg = self.send_command('Cal,low,4.00')
        elif command == 'mid':
            if self.board_version == 1:
                err, msg = self.send_command('S')
            elif self.board_version == 2:
                err, msg = self.send_command('Cal,mid,7.00')
        elif command == 'high':
            if self.board_version == 1:
                err, msg = self.send_command('T')
            elif self.board_version == 2:
                err, msg = self.send_command('Cal,high,10.00')
        elif command == 'end':
            if self.board_version == 1:
                err, msg = self.send_command('E')
        elif custom_cmd:
            err, msg = self.send_command(custom_cmd)
        return err, msg

    def send_command(self, cmd_send):
        """ Send the command (if not None) and return the response """
        try:
            return_value = "No message"
            if cmd_send is not None:
                if self.interface == 'UART':
                    return_value = self.ph_sensor_uart.query(cmd_send)
                elif self.interface == 'I2C':
                    return_value = self.ph_sensor_i2c.query(cmd_send)
                time.sleep(0.1)
                return 0, return_value
            else:
                return 1, "No command given"
        except Exception as err:
            logger.error("{cls} raised an exception while communicating with "
                         "the board: {err}".format(cls=type(self).__name__,
                                                   err=err))
            return 1, err
Beispiel #29
0
class InputModule(AbstractInput):
    """ A sensor support class that monitors the PT1000's temperature """
    def __init__(self, input_dev, testing=False):
        super(InputModule, self).__init__()
        self.logger = logging.getLogger("mycodo.inputs.atlas_pt1000")
        self._temperature = None
        self.atlas_sensor_uart = None
        self.atlas_sensor_i2c = None

        if not testing:
            self.logger = logging.getLogger(
                "mycodo.inputs.atlas_pt1000_{id}".format(
                    id=input_dev.unique_id.split('-')[0]))
            self.interface = input_dev.interface
            if self.interface == 'UART':
                self.uart_location = input_dev.uart_location
            elif self.interface == 'I2C':
                self.i2c_address = int(str(input_dev.i2c_location), 16)
                self.i2c_bus = input_dev.i2c_bus
            self.convert_to_unit = input_dev.convert_to_unit
            self.initialize_sensor()

    def __repr__(self):
        """  Representation of object """
        return "<{cls}(temperature={temp})>".format(cls=type(self).__name__,
                                                    temp="{0:.2f}".format(
                                                        self._temperature))

    def __str__(self):
        """ Return temperature information """
        return "Temperature: {temp}".format(
            temp="{0:.2f}".format(self._temperature))

    def __iter__(self):  # must return an iterator
        """ Atlas_PT1000Sensor iterates through live temperature readings """
        return self

    def next(self):
        """ Get next temperature reading """
        if self.read():  # raised an error
            raise StopIteration  # required
        return dict(temperature=float('{0:.2f}'.format(self._temperature)))

    @property
    def temperature(self):
        """ CPU temperature in celsius """
        if self._temperature is None:  # update if needed
            self.read()
        return self._temperature

    def initialize_sensor(self):
        from mycodo.devices.atlas_scientific_i2c import AtlasScientificI2C
        from mycodo.devices.atlas_scientific_uart import AtlasScientificUART
        if self.interface == 'UART':
            self.logger = logging.getLogger(
                "mycodo.inputs.atlas_pt1000_{loc}".format(
                    loc=self.uart_location))
            self.atlas_sensor_uart = AtlasScientificUART(self.uart_location)
        elif self.interface == 'I2C':
            self.logger = logging.getLogger(
                "mycodo.inputs.atlas_pt1000_{bus}_{add}".format(
                    bus=self.i2c_bus, add=self.i2c_address))
            self.atlas_sensor_i2c = AtlasScientificI2C(
                i2c_address=self.i2c_address, i2c_bus=self.i2c_bus)
        else:
            self.logger = logging.getLogger("mycodo.inputs.atlas_pt1000")

    def get_measurement(self):
        """ Gets the Atlas PT1000's temperature in Celsius """
        self._temperature = None
        temp = None

        if self.interface == 'UART':
            if self.atlas_sensor_uart.setup:
                lines = self.atlas_sensor_uart.query('R')
                self.logger.debug("All Lines: {lines}".format(lines=lines))

                if 'check probe' in lines:
                    self.logger.error('"check probe" returned from sensor')
                elif str_is_float(lines[0]):
                    temp = float(lines[0])
                    self.logger.debug(
                        'Value[0] is float: {val}'.format(val=temp))
                else:
                    self.logger.error(
                        'Value[0] is not float or "check probe": '
                        '{val}'.format(val=lines[0]))
            else:
                self.logger.error('UART device is not set up. '
                                  'Check the log for errors.')

        elif self.interface == 'I2C':
            if self.atlas_sensor_i2c.setup:
                temp_status, temp_str = self.atlas_sensor_i2c.query('R')
                if temp_status == 'error':
                    self.logger.error(
                        "Sensor read unsuccessful: {err}".format(err=temp_str))
                elif temp_status == 'success':
                    temp = float(temp_str)
            else:
                self.logger.error('I2C device is not set up.'
                                  'Check the log for errors.')

        temp = convert_units('temperature', 'C', self.convert_to_unit, temp)

        return temp

    def read(self):
        """
        Takes a reading from the PT-1000 and updates self._temperature

        :returns: None on success or 1 on error
        """
        try:
            self._temperature = self.get_measurement()
            if self._temperature is not None:
                return  # success - no errors
        except Exception as e:
            self.logger.exception(
                "{cls} raised an exception when taking a reading: "
                "{err}".format(cls=type(self).__name__, err=e))
        return 1
Beispiel #30
0
class InputModule(AbstractInput):
    """A sensor support class that monitors the Atlas Scientific sensor pH"""

    def __init__(self, input_dev, testing=False):
        super(InputModule, self).__init__()
        self.logger = logging.getLogger("mycodo.inputs.atlas_ph")
        self.atlas_sensor_ftdi = None
        self.atlas_sensor_uart = None
        self.atlas_sensor_i2c = None
        self.ftdi_location = None
        self.uart_location = None
        self.i2c_address = None
        self.i2c_bus = None

        if not testing:
            self.logger = logging.getLogger(
                "mycodo.inputs.atlas_ph_{id}".format(id=input_dev.unique_id.split('-')[0]))

            self.input_dev = input_dev
            self.interface = input_dev.interface
            self.calibrate_sensor_measure = input_dev.calibrate_sensor_measure
            self.max_age = None

            if input_dev.custom_options:
                for each_option in input_dev.custom_options.split(';'):
                    option = each_option.split(',')[0]
                    value = each_option.split(',')[1]
                    if option == 'max_age':
                        self.max_age = int(value)

            try:
                self.initialize_sensor()
            except Exception:
                self.logger.exception("Exception while initializing sensor")

    def initialize_sensor(self):
        from mycodo.devices.atlas_scientific_ftdi import AtlasScientificFTDI
        from mycodo.devices.atlas_scientific_i2c import AtlasScientificI2C
        from mycodo.devices.atlas_scientific_uart import AtlasScientificUART
        if self.interface == 'FTDI':
            self.ftdi_location = self.input_dev.ftdi_location
            self.logger = logging.getLogger(
                "mycodo.inputs.atlas_ph_ftdi_{ftdi}".format(
                    ftdi=self.ftdi_location))
            self.atlas_sensor_ftdi = AtlasScientificFTDI(self.ftdi_location)
        elif self.interface == 'UART':
            self.uart_location = self.input_dev.uart_location
            self.logger = logging.getLogger(
                "mycodo.inputs.atlas_ph_uart_{uart}".format(
                    uart=self.uart_location))
            self.atlas_sensor_uart = AtlasScientificUART(self.uart_location)
        elif self.interface == 'I2C':
            self.i2c_address = int(str(self.input_dev.i2c_location), 16)
            self.logger = logging.getLogger(
                "mycodo.inputs.atlas_ph_i2c_{bus}_{add}".format(
                    bus=self.i2c_bus, add=self.i2c_address))
            self.i2c_bus = self.input_dev.i2c_bus
            self.atlas_sensor_i2c = AtlasScientificI2C(
                i2c_address=self.i2c_address, i2c_bus=self.i2c_bus)

    def get_measurement(self):
        """ Gets the sensor's pH measurement via UART/I2C """
        ph = None

        return_dict = measurements_dict.copy()

        # Calibrate the pH measurement based on a temperature measurement
        if (self.calibrate_sensor_measure and
                ',' in self.calibrate_sensor_measure):
            self.logger.debug("pH sensor set to calibrate temperature")

            device_id = self.calibrate_sensor_measure.split(',')[0]
            measurement_id = self.calibrate_sensor_measure.split(',')[1]

            device_measurement = self.device_measurements.filter(
                DeviceMeasurements.unique_id == measurement_id).first()
            if device_measurement:
                conversion = db_retrieve_table_daemon(
                    Conversion, unique_id=device_measurement.conversion_id)
            else:
                conversion = None
            channel, unit, measurement = return_measurement_info(
                device_measurement, conversion)

            last_measurement = read_last_influxdb(
                device_id,
                measurement.unit,
                measurement.measurement,
                measurement.channel,
                self.max_age)

            if last_measurement:
                self.logger.debug(
                    "Latest temperature used to calibrate: {temp}".format(
                        temp=last_measurement[1]))

                atlas_command = AtlasScientificCommand(self.input_dev)
                ret_value, ret_msg = atlas_command.calibrate(
                    'temperature', temperature=last_measurement[1])
                time.sleep(0.5)

                self.logger.debug(
                    "Calibration returned: {val}, {msg}".format(
                        val=ret_value, msg=ret_msg))
            else:
                self.logger.error(
                    "Calibration measurement not found within the past "
                    "{} seconds".format(self.max_age))

        # Read sensor via FTDI
        if self.interface == 'FTDI':
            if self.atlas_sensor_ftdi.setup:
                lines = self.atlas_sensor_ftdi.query('R')
                if lines:
                    self.logger.debug(
                        "All Lines: {lines}".format(lines=lines))

                    # 'check probe' indicates an error reading the sensor
                    if 'check probe' in lines:
                        self.logger.error(
                            '"check probe" returned from sensor')
                    # if a string resembling a float value is returned, this
                    # is out measurement value
                    elif str_is_float(lines[0]):
                        ph = float(lines[0])
                        self.logger.debug(
                            'Value[0] is float: {val}'.format(val=ph))
                    else:
                        # During calibration, the sensor is put into
                        # continuous mode, which causes a return of several
                        # values in one string. If the return value does
                        # not represent a float value, it is likely to be a
                        # string of several values. This parses and returns
                        # the first value.
                        if str_is_float(lines[0].split(b'\r')[0]):
                            ph = lines[0].split(b'\r')[0]
                        # Lastly, this is called if the return value cannot
                        # be determined. Watchthe output in the GUI to see
                        # what it is.
                        else:
                            ph = lines[0]
                            self.logger.error(
                                'Value[0] is not float or "check probe": '
                                '{val}'.format(val=ph))
            else:
                self.logger.error('FTDI device is not set up.'
                                  'Check the log for errors.')

        # Read sensor via UART
        elif self.interface == 'UART':
            if self.atlas_sensor_uart.setup:
                lines = self.atlas_sensor_uart.query('R')
                if lines:
                    self.logger.debug(
                        "All Lines: {lines}".format(lines=lines))

                    # 'check probe' indicates an error reading the sensor
                    if 'check probe' in lines:
                        self.logger.error(
                            '"check probe" returned from sensor')
                    # if a string resembling a float value is returned, this
                    # is out measurement value
                    elif str_is_float(lines[0]):
                        ph = float(lines[0])
                        self.logger.debug(
                            'Value[0] is float: {val}'.format(val=ph))
                    else:
                        # During calibration, the sensor is put into
                        # continuous mode, which causes a return of several
                        # values in one string. If the return value does
                        # not represent a float value, it is likely to be a
                        # string of several values. This parses and returns
                        # the first value.
                        if str_is_float(lines[0].split(b'\r')[0]):
                            ph = lines[0].split(b'\r')[0]
                        # Lastly, this is called if the return value cannot
                        # be determined. Watchthe output in the GUI to see
                        # what it is.
                        else:
                            ph = lines[0]
                            self.logger.error(
                                'Value[0] is not float or "check probe": '
                                '{val}'.format(val=ph))
            else:
                self.logger.error('UART device is not set up.'
                                  'Check the log for errors.')

        # Read sensor via I2C
        elif self.interface == 'I2C':
            if self.atlas_sensor_i2c.setup:
                ph_status, ph_str = self.atlas_sensor_i2c.query('R')
                if ph_status == 'error':
                    self.logger.error(
                        "Sensor read unsuccessful: {err}".format(
                            err=ph_str))
                elif ph_status == 'success':
                    ph = float(ph_str)
            else:
                self.logger.error(
                    'I2C device is not set up. Check the log for errors.')

        return_dict[0]['value'] = ph

        return return_dict
Beispiel #31
0
class AtlasPT1000Sensor(AbstractSensor):
    """ A sensor support class that monitors the PT1000's temperature """
    def __init__(self,
                 interface,
                 device_loc=None,
                 baud_rate=None,
                 i2c_address=None,
                 i2c_bus=None):
        super(AtlasPT1000Sensor, self).__init__()
        self._temperature = 0.0
        self.interface = interface
        if self.interface == 'UART':
            self.atlas_sensor_uart = AtlasScientificUART(device_loc,
                                                         baudrate=baud_rate)
        elif self.interface == 'I2C':
            self.atlas_sensor_i2c = AtlasScientificI2C(i2c_address=i2c_address,
                                                       i2c_bus=i2c_bus)

    def __repr__(self):
        """  Representation of object """
        return "<{cls}(temperature={temp})>".format(cls=type(self).__name__,
                                                    temp="{0:.2f}".format(
                                                        self._temperature))

    def __str__(self):
        """ Return temperature information """
        return "Temperature: {temp}".format(
            temp="{0:.2f}".format(self._temperature))

    def __iter__(self):  # must return an iterator
        """ Atlas_PT1000Sensor iterates through live temperature readings """
        return self

    def next(self):
        """ Get next temperature reading """
        if self.read():  # raised an error
            raise StopIteration  # required
        return dict(temperature=float('{0:.2f}'.format(self._temperature)))

    def info(self):
        conditions_measured = [("Temperature", "temperature", "float", "0.00",
                                self._temperature, self.temperature)]
        return conditions_measured

    @property
    def temperature(self):
        """ CPU temperature in celsius """
        if not self._temperature:  # update if needed
            self.read()
        return self._temperature

    def get_measurement(self):
        """ Gets the Atlas PT1000's temperature in Celsius """
        temp = None
        if self.interface == 'UART':
            if self.atlas_sensor_uart.setup:
                lines = self.atlas_sensor_uart.query('R')
                logger.debug("All Lines: {lines}".format(lines=lines))

                if 'check probe' in lines:
                    logger.error('"check probe" returned from sensor')
                elif str_is_float(lines[0]):
                    temp = float(lines[0])
                    logger.debug('Value[0] is float: {val}'.format(val=temp))
                else:
                    temp = lines[0]
                    logger.error('Value[0] is not float or "check probe": '
                                 '{val}'.format(val=temp))
            else:
                logger.error('UART device is not set up. '
                             'Check the log for errors.')
        elif self.interface == 'I2C':
            if self.atlas_sensor_i2c.setup:
                temp_status, temp_str = self.atlas_sensor_i2c.query('R')
                if temp_status == 'error':
                    logger.error(
                        "Sensor read unsuccessful: {err}".format(err=temp_str))
                elif temp_status == 'success':
                    temp = float(temp_str)
            else:
                logger.error('I2C device is not set up.'
                             'Check the log for errors.')

        return temp

    def read(self):
        """
        Takes a reading from the PT-1000 and updates self._temperature

        :returns: None on success or 1 on error
        """
        try:
            self._temperature = self.get_measurement()
            return  # success - no errors
        except Exception as e:
            logger.exception(
                "{cls} raised an exception when taking a reading: "
                "{err}".format(cls=type(self).__name__, err=e))
        return 1
Beispiel #32
0
class InputModule(AbstractInput):
    """A sensor support class that monitors the Atlas Scientific sensor ElectricalConductivity"""
    def __init__(self, input_dev, testing=False):
        super(InputModule, self).__init__(input_dev,
                                          testing=testing,
                                          name=__name__)
        self.atlas_sensor = None
        self.sensor_is_measuring = False
        self.sensor_is_clearing = False

        # Initialize custom options
        self.flow_meter_type = None
        self.flow_rate_unit = None
        self.internal_resistor = None
        self.custom_k_values = None
        self.custom_k_value_time_base = None
        # Set custom options
        self.setup_custom_options(INPUT_INFORMATION['custom_options'],
                                  input_dev)

        if not testing:
            self.input_dev = input_dev
            self.interface = input_dev.interface

            try:
                self.initialize_sensor()
            except Exception:
                self.logger.exception("Exception while initializing sensor")

    def initialize_sensor(self):
        from mycodo.devices.atlas_scientific_ftdi import AtlasScientificFTDI
        from mycodo.devices.atlas_scientific_i2c import AtlasScientificI2C
        from mycodo.devices.atlas_scientific_uart import AtlasScientificUART
        if self.interface == 'FTDI':
            self.ftdi_location = self.input_dev.ftdi_location
            self.atlas_sensor = AtlasScientificFTDI(self.ftdi_location)
        elif self.interface == 'UART':
            self.uart_location = self.input_dev.uart_location
            self.atlas_sensor = AtlasScientificUART(self.uart_location)
        elif self.interface == 'I2C':
            self.i2c_address = int(str(self.input_dev.i2c_location), 16)
            self.i2c_bus = self.input_dev.i2c_bus
            self.atlas_sensor = AtlasScientificI2C(
                i2c_address=self.i2c_address, i2c_bus=self.i2c_bus)

        if self.is_enabled(0):
            self.atlas_sensor.query('O,TV,1')
            self.logger.debug("Enabling Total Volume measurement")
        else:
            self.atlas_sensor.query('O,TV,0')
            self.logger.debug("Disabling Total Volume measurement")

        if self.is_enabled(1):
            self.atlas_sensor.query('O,FR,1')
            self.logger.debug("Enabling Flow Rate measurement")
        else:
            self.atlas_sensor.query('O,FR,0')
            self.logger.debug("Disabling Flow Rate measurement")

        if self.flow_meter_type:
            if self.flow_meter_type == 'non-atlas':
                if ';' in self.custom_k_values:
                    list_k_values = self.custom_k_values.split(';')
                    self.atlas_sensor.query('K,clear')
                    self.logger.debug("Cleared K Values")
                    for each_k in list_k_values:
                        if ',' in each_k:
                            self.atlas_sensor.query('K,{}'.format(each_k))
                            self.logger.debug("Set K Value: {}".format(each_k))
                        else:
                            self.logger.error(
                                "Improperly-formatted K-value: {}".format(
                                    each_k))
                elif ',' in self.custom_k_values:
                    self.atlas_sensor.query('K,clear')
                    self.logger.debug("Cleared K Values")
                    self.atlas_sensor.query('K,{}'.format(
                        self.custom_k_values))
                    self.logger.debug("Set K Value: {}".format(
                        self.custom_k_values))
                else:
                    self.logger.error(
                        "Improperly-formatted K-value: {}".format(
                            self.custom_k_values))
                self.atlas_sensor.query('Vp,{}'.format(
                    self.custom_k_value_time_base))
                self.logger.debug("Set Custom Time Base: {}".format(
                    self.custom_k_value_time_base))
            else:
                self.atlas_sensor.query('Set,{}'.format(self.flow_meter_type))
                self.logger.debug("Set Flow Meter: {}".format(
                    self.flow_meter_type))

        if self.flow_rate_unit:
            self.atlas_sensor.query('Frp,{}'.format(self.flow_rate_unit))
            self.logger.debug("Set Flow Rate: l/{}".format(
                self.flow_rate_unit))

        if self.internal_resistor and self.internal_resistor != 'atlas':
            self.atlas_sensor.query('P,{}'.format(int(self.internal_resistor)))
            if self.internal_resistor == '0':
                self.logger.debug("Internal Resistor disabled")
            else:
                self.logger.debug("Internal Resistor set: {} K".format(
                    self.internal_resistor))

    def get_measurement(self):
        """ Gets the sensor's Electrical Conductivity measurement via UART/I2C """
        return_string = None
        self.return_dict = measurements_dict.copy()

        while self.sensor_is_clearing:
            time.sleep(0.1)
        self.sensor_is_measuring = True

        # Read sensor via FTDI
        if self.interface == 'FTDI':
            if self.atlas_sensor.setup:
                lines = self.atlas_sensor.query('R')
                if lines:
                    self.logger.debug("All Lines: {lines}".format(lines=lines))

                    # 'check probe' indicates an error reading the sensor
                    if 'check probe' in lines:
                        self.logger.error('"check probe" returned from sensor')
                    # if a string resembling a float value is returned, this
                    # is out measurement value
                    elif str_is_float(lines[0]):
                        return_string = lines[0]
                        self.logger.debug('Value[0] is float: {val}'.format(
                            val=return_string))
                    else:
                        # During calibration, the sensor is put into
                        # continuous mode, which causes a return of several
                        # values in one string. If the return value does
                        # not represent a float value, it is likely to be a
                        # string of several values. This parses and returns
                        # the first value.
                        if str_is_float(lines[0].split(b'\r')[0]):
                            return_string = lines[0].split(b'\r')[0]
                        # Lastly, this is called if the return value cannot
                        # be determined. Watchthe output in the GUI to see
                        # what it is.
                        else:
                            return_string = lines[0]
                            self.logger.error(
                                'Value[0] is not float or "check probe": '
                                '{val}'.format(val=return_string))
            else:
                self.logger.error('FTDI device is not set up.'
                                  'Check the log for errors.')

        # Read sensor via UART
        elif self.interface == 'UART':
            if self.atlas_sensor.setup:
                lines = self.atlas_sensor.query('R')
                if lines:
                    self.logger.debug("All Lines: {lines}".format(lines=lines))

                    # 'check probe' indicates an error reading the sensor
                    if 'check probe' in lines:
                        self.logger.error('"check probe" returned from sensor')
                    # if a string resembling a float value is returned, this
                    # is out measurement value
                    elif str_is_float(lines[0]):
                        return_string = lines[0]
                        self.logger.debug('Value[0] is float: {val}'.format(
                            val=return_string))
                    else:
                        # During calibration, the sensor is put into
                        # continuous mode, which causes a return of several
                        # values in one string. If the return value does
                        # not represent a float value, it is likely to be a
                        # string of several values. This parses and returns
                        # the first value.
                        if str_is_float(lines[0].split(b'\r')[0]):
                            return_string = lines[0].split(b'\r')[0]
                        # Lastly, this is called if the return value cannot
                        # be determined. Watchthe output in the GUI to see
                        # what it is.
                        else:
                            return_string = lines[0]
                            self.logger.error(
                                'Value[0] is not float or "check probe": '
                                '{val}'.format(val=return_string))
            else:
                self.logger.error('UART device is not set up.'
                                  'Check the log for errors.')

        # Read sensor via I2C
        elif self.interface == 'I2C':
            if self.atlas_sensor.setup:
                return_status, return_string = self.atlas_sensor.query('R')
                if return_status == 'error':
                    self.logger.error("Sensor read unsuccessful: {err}".format(
                        err=return_string))
                elif return_status == 'success':
                    return_string = return_string
            else:
                self.logger.error(
                    'I2C device is not set up. Check the log for errors.')

        self.sensor_is_measuring = False

        self.logger.debug("Raw Return String: {}".format(return_string))
        total_volume = None
        flow_rate_raw = None
        flow_rate = None

        if self.is_enabled(0) and self.is_enabled(1):
            return_list = return_string.split(',')
            total_volume = float(return_list[0])
            flow_rate_raw = float(return_list[1])
            flow_rate = self.convert_to_l_m(flow_rate_raw)
            self.value_set(0, total_volume)
            self.value_set(1, flow_rate)
        elif self.is_enabled(0) and not self.is_enabled(1):
            total_volume = float(return_string)
            self.value_set(0, total_volume)
        elif not self.is_enabled(0) and self.is_enabled(1):
            flow_rate_raw = float(return_string)
            flow_rate = self.convert_to_l_m(flow_rate_raw)
            self.value_set(1, flow_rate)

        if total_volume is not None:
            self.logger.debug("Total Volume: {} l".format(total_volume))
        if flow_rate_raw is not None:
            self.logger.debug("Flow Rate (from sensor): {:.5f} l/{}".format(
                flow_rate_raw, self.flow_rate_unit))
        if flow_rate is not None:
            self.logger.debug(
                "Flow Rate (converted to l/m): {:.5f} l/m".format(flow_rate))

        return self.return_dict

    def clear_total_volume(self):
        while self.sensor_is_measuring:
            time.sleep(0.1)
        self.sensor_is_clearing = True
        self.logger.debug("Clearing total volume")
        return_status, return_string = self.atlas_sensor.query('Clear')
        self.sensor_is_clearing = False
        if return_status == 'error':
            return 1, "Error: {}".format(return_string)
        elif return_status == 'success':
            return 0, "Success"

    def convert_to_l_m(self, amount):
        if (self.custom_k_value_time_base
                and self.custom_k_value_time_base != 'disabled'):
            # Custom K values used for non-Atlas Scientific meter
            # use the custom time base
            time_base_unit = self.custom_k_value_time_base
        else:
            # Use time base set for Atlas Scientific meter
            time_base_unit = self.flow_rate_unit

        if time_base_unit == 'h':
            return amount / 60
        elif time_base_unit == 'm':
            return amount
        elif time_base_unit == 's':
            return amount * 60