def initialize_variables(self):
        from mycodo.devices.lcd_pioled_circuitpython import PiOLEDCircuitpython

        try:
            function_channels = db_retrieve_table_daemon(
                FunctionChannel).filter(FunctionChannel.function_id == self.unique_id).all()
            self.options_channels = self.setup_custom_channel_options_json(
                FUNCTION_INFORMATION['custom_channel_options'], function_channels)

            for each_set in range(self.number_line_sets):
                self.line_sets.append([])
                for each_line in range(lcd_lines):
                    self.line_sets[each_set].append(each_line)

            self.logger.debug("Line sets: {}".format(self.line_sets))

            lcd_settings_dict = {
                "unique_id": self.unique_id,
                "interface": "I2C",
                "i2c_address": self.i2c_address,
                "i2c_bus": self.i2c_bus,
                "x_characters": lcd_x_characters,
                "lcd_type": "128x64_pioled_circuit_python"
            }

            self.device = PiOLEDCircuitpython(lcd_settings_dict=lcd_settings_dict)
            self.device.lcd_init()

            self.logger.debug("LCD Function started")
        except:
            self.logger.exception("Starting LCD Function")
    def initialize_variables(self):
        from mycodo.devices.lcd_pioled_circuitpython import PiOLEDCircuitpython

        try:
            function_channels = db_retrieve_table_daemon(
                FunctionChannel).filter(
                    FunctionChannel.function_id == self.unique_id).all()
            self.options_channels = self.setup_custom_channel_options_json(
                FUNCTION_INFORMATION['custom_channel_options'],
                function_channels)

            for each_set in range(self.number_line_sets):
                self.line_sets.append([])
                for each_line in range(lcd_lines):
                    self.line_sets[each_set].append(each_line)

            self.logger.debug("Line sets: {}".format(self.line_sets))

            lcd_settings_dict = {
                "unique_id": self.unique_id,
                "interface": "SPI",
                "spi_bus": self.spi_bus,
                "spi_device": self.spi_device,
                "pin_dc": self.pin_dc,
                "pin_reset": self.pin_reset,
                "pin_cs": self.pin_cs,
                "x_characters": self.characters_x,
                "line_y_dimensions": self.line_y_dimensions,
                "lcd_type": "128x32_pioled_circuit_python",
                "font_size": self.font_size
            }

            font = None
            if self.use_non_default_font:
                font = self.non_default_font

            self.device = PiOLEDCircuitpython(
                lcd_settings_dict=lcd_settings_dict, font=font)
            self.device.lcd_init()

            self.logger.debug("LCD Function started")
        except:
            self.logger.exception("Starting LCD Function")
Ejemplo n.º 3
0
class CustomModule(AbstractFunction):
    """
    Class to operate custom controller
    """
    def __init__(self, function, testing=False):
        super(CustomModule, self).__init__(function, testing=testing, name=__name__)

        self.options_channels = {}
        self.device = None
        self.timer_loop = time.time()
        self.line_sets = []
        self.current_line_set = 0
        self.line_y_dimensions = [0, 16, 32, 48]
        self.pad = -2

        # Initialize custom options
        self.period = None
        self.i2c_address = None
        self.i2c_bus = None
        self.number_line_sets = None
        self.pin_reset = None
        self.characters_x = None
        self.use_non_default_font = None
        self.non_default_font = None
        self.font_size = None

        # Set custom options
        custom_function = db_retrieve_table_daemon(
            CustomController, unique_id=self.unique_id)
        self.setup_custom_options(
            FUNCTION_INFORMATION['custom_options'], custom_function)

        if not testing:
            self.initialize_variables()

    def initialize_variables(self):
        from mycodo.devices.lcd_pioled_circuitpython import PiOLEDCircuitpython

        try:
            function_channels = db_retrieve_table_daemon(
                FunctionChannel).filter(FunctionChannel.function_id == self.unique_id).all()
            self.options_channels = self.setup_custom_channel_options_json(
                FUNCTION_INFORMATION['custom_channel_options'], function_channels)

            for each_set in range(self.number_line_sets):
                self.line_sets.append([])
                for each_line in range(lcd_lines):
                    self.line_sets[each_set].append(each_line)

            self.logger.debug("Line sets: {}".format(self.line_sets))

            lcd_settings_dict = {
                "unique_id": self.unique_id,
                "interface": "I2C",
                "i2c_address": self.i2c_address,
                "i2c_bus": self.i2c_bus,
                "x_characters": self.characters_x,
                "line_y_dimensions": self.line_y_dimensions,
                "lcd_type": "128x64_pioled_circuit_python",
                "font_size": self.font_size
            }

            font = None
            if self.use_non_default_font:
                font = self.non_default_font

            self.device = PiOLEDCircuitpython(lcd_settings_dict=lcd_settings_dict, font=font)
            self.device.lcd_init()

            self.logger.debug("LCD Function started")
        except:
            self.logger.exception("Starting LCD Function")

    def loop(self):
        if self.timer_loop > time.time():
            return

        while self.timer_loop < time.time():
            self.timer_loop += self.period

        if not self.device:
            self.logger.error("LCD not set up")
            return

        # Generate lines to display
        lines_display = {}
        for line in range(lcd_lines):
            lines_display[line] = ""

        for current_line in self.line_sets[self.current_line_set]:
            current_channel = (self.current_line_set * lcd_lines) + current_line
            self.logger.debug("Channel: {}, Set: {} Line: {}, ".format(
                current_channel, self.current_line_set, current_line))

            try:
                # Get measurement value and timestamp
                if self.options_channels['line_display_type'][current_channel] in [
                    'measurement_value', 'measurement_ts']:
                    lines_display[current_line] = "NONE"
                    measure_ts = None
                    measure_value = None

                    last_measurement = self.get_last_measurement(
                        self.options_channels['select_measurement'][current_channel]['device_id'],
                        self.options_channels['select_measurement'][current_channel]['measurement_id'],
                        max_age=self.options_channels['measure_max_age'][current_channel])

                    if last_measurement:
                        measure_ts = last_measurement[0]
                        measure_value = last_measurement[1]

                    if self.options_channels['line_display_type'][current_channel] == 'measurement_value':
                        if measure_value:
                            if self.options_channels['measure_decimal'][current_channel] == 0:
                                val_rounded = int(self.options_channels['measure_decimal'][current_channel])
                            else:
                                val_rounded = round(
                                    measure_value,
                                    self.options_channels['measure_decimal'][current_channel])

                            lines_display[current_line] = format_measurement_line(
                                self.options_channels['select_measurement'][current_channel]['device_id'],
                                self.options_channels['select_measurement'][current_channel]['measurement_id'],
                                val_rounded,
                                self.characters_x,
                                display_unit=self.options_channels['display_unit'][current_channel])

                    elif self.options_channels['line_display_type'][current_channel] == 'measurement_ts':
                        if measure_ts:
                            # Convert UTC timestamp to local timezone
                            utc_dt = datetime.datetime.strptime(
                                measure_ts.split(".")[0], '%Y-%m-%dT%H:%M:%S')
                            utc_timestamp = calendar.timegm(utc_dt.timetuple())
                            lines_display[current_line] = str(
                                datetime.datetime.fromtimestamp(utc_timestamp))

                elif self.options_channels['line_display_type'][current_channel] == 'current_time':
                    lines_display[current_line] = time.strftime('%Y-%m-%d %H:%M:%S')

                elif self.options_channels['line_display_type'][current_channel] == 'text':
                    lines_display[current_line] = self.options_channels['text'][current_channel]

                elif self.options_channels['line_display_type'][current_channel] == 'blank_line':
                    lines_display[current_line] = ""

                elif self.options_channels['line_display_type'][current_channel] == 'ip_address':
                    str_ip_cmd = "ip addr | " \
                                 "grep 'state UP' -A2 | " \
                                 "tail -n1 | " \
                                 "awk '{print $2}' | " \
                                 "cut -f1  -d'/'"
                    ip_out, _, _ = cmd_output(str_ip_cmd)
                    lines_display[current_line] = ip_out.rstrip().decode("utf-8")
            except Exception as err:
                # self.logger.exception("Generating line")
                self.logger.error("Error generating channel {} line: {}".format(current_channel, err))
                lines_display[current_line] = "ERROR"

        if self.current_line_set == len(self.line_sets) - 1:
            self.current_line_set = 0
        else:
            self.current_line_set += 1

        self.logger.debug("Displaying: {}".format(lines_display))

        # Display lines
        self.device.lcd_init()
        self.device.lcd_write_lines(
            lines_display[0],
            lines_display[1],
            lines_display[2],
            lines_display[3])

    def stop_function(self):
        self.device.lcd_write_lines(
            "Mycodo {}".format(MYCODO_VERSION), "Display Deactivated", "", "")
Ejemplo n.º 4
0
class LCDController(AbstractController, threading.Thread):
    """
    Class to operate LCD controller
    """
    def __init__(self, ready, unique_id):
        threading.Thread.__init__(self)
        super(LCDController, self).__init__(ready, unique_id=unique_id, name=__name__)

        self.unique_id = unique_id
        self.sample_rate = 1

        self.flash_lcd_on = False
        self.lcd_initialized = False
        self.lcd_is_on = False

        self.display_sets = []
        self.display_set_count = 0

        self.lcd_out = None
        self.lcd_type = None
        self.lcd_name = None
        self.lcd_period = None
        self.lcd_x_characters = None
        self.lcd_y_lines = None
        self.timer = None
        self.backlight_timer = None
        self.log_level_debug = None

        self.list_inputs = None
        self.dict_units = None

        self.lcd_string_line = {}
        self.lcd_line = {}
        self.lcd_text = {}
        self.lcd_max_age = {}
        self.lcd_decimal_places = {}

    def loop(self):
        if not self.lcd_initialized:
            self.stop_controller()
        elif (self.lcd_is_on and
                self.lcd_initialized and
                time.time() > self.timer):
            try:
                # Acquire all measurements to be displayed on the LCD
                display_id = self.display_sets[self.display_set_count]
                for line in range(1, self.lcd_y_lines + 1):
                    if not self.running:
                        break
                    if self.lcd_line[display_id][line]['id'] and self.lcd_line[display_id][line]['setup']:
                        self.create_lcd_line(
                            self.get_measurement(display_id, line),
                            display_id,
                            line)
                    else:
                        self.lcd_string_line[display_id][line] = 'LCD LINE ERROR'
                # Output lines to the LCD
                if self.running:
                    self.output_lcds()
            except KeyError:
                self.logger.exception(
                    "KeyError: Unable to output to LCD.")
            except IOError:
                self.logger.exception(
                    "IOError: Unable to output to LCD.")
            except Exception:
                self.logger.exception(
                    "Exception: Unable to output to LCD.")

            # Increment display counter to show the next display
            if len(self.display_sets) > 1:
                if self.display_set_count < len(self.display_sets) - 1:
                    self.display_set_count += 1
                else:
                    self.display_set_count = 0

            self.timer = time.time() + self.lcd_period

        elif not self.lcd_is_on:
            # Turn backlight off
            self.lcd_out.lcd_backlight(0)

        if self.flash_lcd_on:
            if time.time() > self.backlight_timer:
                if self.lcd_is_on:
                    self.lcd_backlight(0)
                    seconds = 0.2
                else:
                    self.output_lcds()
                    seconds = 1.1
                self.backlight_timer = time.time() + seconds

    def run_finally(self):
        self.lcd_out.lcd_init()  # Blank LCD
        line_1 = 'Mycodo {}'.format(MYCODO_VERSION)
        line_2 = 'Stop {}'.format(self.lcd_name)
        self.lcd_out.lcd_write_lines(line_1, line_2, '', '')

    def initialize_variables(self):
        lcd_dev = db_retrieve_table_daemon(LCD, unique_id=self.unique_id)
        self.lcd_type = lcd_dev.lcd_type
        self.lcd_name = lcd_dev.name
        self.lcd_period = lcd_dev.period
        self.lcd_x_characters = lcd_dev.x_characters
        self.lcd_y_lines = lcd_dev.y_lines
        self.timer = time.time() + self.lcd_period
        self.backlight_timer = time.time()
        self.log_level_debug = lcd_dev.log_level_debug

        self.set_log_level_debug(self.log_level_debug)

        # Add custom measurement and units to list
        self.list_inputs = add_custom_measurements(
            db_retrieve_table_daemon(Measurement, entry='all'))

        self.list_inputs.update(
            {'input_time': {'unit': None, 'name': 'Time'}})
        self.list_inputs.update(
            {'pid_time': {'unit': None, 'name': 'Time'}})

        self.dict_units = add_custom_units(
            db_retrieve_table_daemon(Unit, entry='all'))

        lcd_data = db_retrieve_table_daemon(
            LCDData).filter(LCDData.lcd_id == lcd_dev.unique_id).all()

        for each_lcd_display in lcd_data:
            self.display_sets.append(each_lcd_display.unique_id)
            self.lcd_string_line[each_lcd_display.unique_id] = {}
            self.lcd_line[each_lcd_display.unique_id] = {}
            self.lcd_text[each_lcd_display.unique_id] = {}
            self.lcd_max_age[each_lcd_display.unique_id] = {}
            self.lcd_decimal_places[each_lcd_display.unique_id] = {}

            for i in range(1, self.lcd_y_lines + 1):
                self.lcd_string_line[each_lcd_display.unique_id][i] = ''
                self.lcd_line[each_lcd_display.unique_id][i] = {}
                if i == 1:
                    self.lcd_text[each_lcd_display.unique_id][i] = each_lcd_display.line_1_text
                    self.lcd_max_age[each_lcd_display.unique_id][i] = each_lcd_display.line_1_max_age
                    self.lcd_decimal_places[each_lcd_display.unique_id][i] = each_lcd_display.line_1_decimal_places
                elif i == 2:
                    self.lcd_text[each_lcd_display.unique_id][i] = each_lcd_display.line_2_text
                    self.lcd_max_age[each_lcd_display.unique_id][i] = each_lcd_display.line_2_max_age
                    self.lcd_decimal_places[each_lcd_display.unique_id][i] = each_lcd_display.line_2_decimal_places
                elif i == 3:
                    self.lcd_text[each_lcd_display.unique_id][i] = each_lcd_display.line_3_text
                    self.lcd_max_age[each_lcd_display.unique_id][i] = each_lcd_display.line_3_max_age
                    self.lcd_decimal_places[each_lcd_display.unique_id][i] = each_lcd_display.line_3_decimal_places
                elif i == 4:
                    self.lcd_text[each_lcd_display.unique_id][i] = each_lcd_display.line_4_text
                    self.lcd_max_age[each_lcd_display.unique_id][i] = each_lcd_display.line_4_max_age
                    self.lcd_decimal_places[each_lcd_display.unique_id][i] = each_lcd_display.line_4_decimal_places
                elif i == 5:
                    self.lcd_text[each_lcd_display.unique_id][i] = each_lcd_display.line_5_text
                    self.lcd_max_age[each_lcd_display.unique_id][i] = each_lcd_display.line_5_max_age
                    self.lcd_decimal_places[each_lcd_display.unique_id][i] = each_lcd_display.line_5_decimal_places
                elif i == 6:
                    self.lcd_text[each_lcd_display.unique_id][i] = each_lcd_display.line_6_text
                    self.lcd_max_age[each_lcd_display.unique_id][i] = each_lcd_display.line_6_max_age
                    self.lcd_decimal_places[each_lcd_display.unique_id][i] = each_lcd_display.line_6_decimal_places
                elif i == 7:
                    self.lcd_text[each_lcd_display.unique_id][i] = each_lcd_display.line_7_text
                    self.lcd_max_age[each_lcd_display.unique_id][i] = each_lcd_display.line_7_max_age
                    self.lcd_decimal_places[each_lcd_display.unique_id][i] = each_lcd_display.line_7_decimal_places
                elif i == 8:
                    self.lcd_text[each_lcd_display.unique_id][i] = each_lcd_display.line_8_text
                    self.lcd_max_age[each_lcd_display.unique_id][i] = each_lcd_display.line_8_max_age
                    self.lcd_decimal_places[each_lcd_display.unique_id][i] = each_lcd_display.line_8_decimal_places

            if self.lcd_y_lines in [2, 4, 8]:
                self.setup_lcd_line(
                    each_lcd_display.unique_id, 1,
                    each_lcd_display.line_1_id,
                    each_lcd_display.line_1_measurement)
                self.setup_lcd_line(
                    each_lcd_display.unique_id, 2,
                    each_lcd_display.line_2_id,
                    each_lcd_display.line_2_measurement)

            if self.lcd_y_lines in [4, 8]:
                self.setup_lcd_line(
                    each_lcd_display.unique_id, 3,
                    each_lcd_display.line_3_id,
                    each_lcd_display.line_3_measurement)
                self.setup_lcd_line(
                    each_lcd_display.unique_id, 4,
                    each_lcd_display.line_4_id,
                    each_lcd_display.line_4_measurement)

            if self.lcd_y_lines == 8:
                self.setup_lcd_line(
                    each_lcd_display.unique_id, 5,
                    each_lcd_display.line_5_id,
                    each_lcd_display.line_5_measurement)
                self.setup_lcd_line(
                    each_lcd_display.unique_id, 6,
                    each_lcd_display.line_6_id,
                    each_lcd_display.line_6_measurement)
                self.setup_lcd_line(
                    each_lcd_display.unique_id, 7,
                    each_lcd_display.line_7_id,
                    each_lcd_display.line_7_measurement)
                self.setup_lcd_line(
                    each_lcd_display.unique_id, 8,
                    each_lcd_display.line_8_id,
                    each_lcd_display.line_8_measurement)

        if self.lcd_type in ['16x2_generic',
                             '20x4_generic']:
            from mycodo.devices.lcd_generic import LCD_Generic
            self.lcd_out = LCD_Generic(lcd_dev)
            self.lcd_init()
        elif self.lcd_type in ['16x2_grove_lcd_rgb']:
            from mycodo.devices.lcd_grove_lcd_rgb import LCD_Grove_LCD_RGB
            self.lcd_out = LCD_Grove_LCD_RGB(lcd_dev)
            self.lcd_init()
        elif self.lcd_type in ['128x32_pioled',
                               '128x64_pioled']:
            from mycodo.devices.lcd_pioled import LCD_Pioled
            self.lcd_out = LCD_Pioled(lcd_dev)
            self.lcd_init()
        elif self.lcd_type in ['128x32_pioled_circuit_python',
                               '128x64_pioled_circuit_python']:
            from mycodo.devices.lcd_pioled_circuitpython import PiOLEDCircuitpython
            self.lcd_out = PiOLEDCircuitpython(lcd_dev)
            self.lcd_init()
        else:
            self.logger.error("Unknown LCD type: {}".format(self.lcd_type))

        if self.lcd_initialized:
            line_1 = 'Mycodo {}'.format(MYCODO_VERSION)
            line_2 = 'Start {}'.format(self.lcd_name)
            self.lcd_out.lcd_write_lines(line_1, line_2, '', '')

    def lcd_init(self):
        self.lcd_out.lcd_init()
        self.lcd_initialized = True
        self.lcd_is_on = True

    def get_measurement(self, display_id, i):
        try:
            if self.lcd_line[display_id][i]['measure'] == 'TEXT':
                # Display custom, user-entered text
                self.lcd_line[display_id][i]['name'] = ''
                self.lcd_line[display_id][i]['unit'] = ''
                if len(self.lcd_text[display_id][i]) > self.lcd_x_characters:
                    self.lcd_line[display_id][i]['measure_val'] = self.lcd_text[display_id][i][:self.lcd_x_characters]
                else:
                    self.lcd_line[display_id][i]['measure_val'] = self.lcd_text[display_id][i]
                return True
            elif self.lcd_line[display_id][i]['measure'] == 'BLANK':
                # Display an empty line
                self.lcd_line[display_id][i]['name'] = ''
                self.lcd_line[display_id][i]['unit'] = ''
                self.lcd_line[display_id][i]['measure_val'] = ''
                return True
            elif self.lcd_line[display_id][i]['measure'] == 'IP':
                # Display the device's IP address
                str_ip_cmd = "ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1  -d'/'"
                ip_out, _, _ = cmd_output(str_ip_cmd)
                self.lcd_line[display_id][i]['name'] = ''
                self.lcd_line[display_id][i]['unit'] = ''
                self.lcd_line[display_id][i]['measure_val'] = ip_out.rstrip().decode("utf-8")
                return True
            elif self.lcd_line[display_id][i]['measure'] == 'output_state':
                # Display the GPIO state
                # TODO: Currently not a selectable option in the LCD Line dropdown
                self.lcd_line[display_id][i]['measure_val'] = self.output_state(
                    self.lcd_line[display_id][i]['id'])
                return True
            else:
                if self.lcd_line[display_id][i]['measure'] == 'time':
                    # Display the time of the last measurement
                    last_measurement = read_last_influxdb(
                        self.lcd_line[display_id][i]['id'],
                        '/.*/',
                        None,
                        duration_sec=self.lcd_max_age[display_id][i])
                else:
                    last_measurement = read_last_influxdb(
                        self.lcd_line[display_id][i]['id'],
                        self.lcd_line[display_id][i]['unit'],
                        self.lcd_line[display_id][i]['channel'],
                        measure=self.lcd_line[display_id][i]['measure'],
                        duration_sec=self.lcd_max_age[display_id][i])

                if last_measurement:
                    self.lcd_line[display_id][i]['time'] = last_measurement[0]
                    if self.lcd_decimal_places[display_id][i] == 0:
                        self.lcd_line[display_id][i]['measure_val'] = int(last_measurement[1])
                    else:
                        self.lcd_line[display_id][i]['measure_val'] = round(
                            last_measurement[1], self.lcd_decimal_places[display_id][i])
                    utc_dt = datetime.datetime.strptime(
                        self.lcd_line[display_id][i]['time'].split(".")[0],
                        '%Y-%m-%dT%H:%M:%S')
                    utc_timestamp = calendar.timegm(utc_dt.timetuple())
                    local_timestamp = str(datetime.datetime.fromtimestamp(utc_timestamp))
                    self.logger.debug("Latest {}: {} @ {}".format(
                        self.lcd_line[display_id][i]['measure'],
                        self.lcd_line[display_id][i]['measure_val'], local_timestamp))
                    return True

                else:
                    self.lcd_line[display_id][i]['time'] = None
                    self.lcd_line[display_id][i]['measure_val'] = None
                    self.logger.debug("No data returned from influxdb")
            return False
        except Exception as except_msg:
            self.logger.debug(
                "Failed to read measurement from the influxdb database: "
                "{err}".format(err=except_msg))
            return False

    def create_lcd_line(self, last_measurement_success, display_id, i):
        try:
            if last_measurement_success:
                if self.lcd_line[display_id][i]['unit'] in self.dict_units:
                    unit_display = self.dict_units[self.lcd_line[display_id][i]['unit']]['unit']
                else:
                    unit_display = ''

                if unit_display:
                    unit_length = len(unit_display.replace('°', u''))
                else:
                    unit_length = 0

                # Produce the line that will be displayed on the LCD
                if self.lcd_line[display_id][i]['measure'] == 'time':
                    # Convert UTC timestamp to local timezone
                    utc_dt = datetime.datetime.strptime(
                        self.lcd_line[display_id][i]['time'].split(".")[0],
                        '%Y-%m-%dT%H:%M:%S')
                    utc_timestamp = calendar.timegm(utc_dt.timetuple())
                    self.lcd_string_line[display_id][i] = str(
                        datetime.datetime.fromtimestamp(utc_timestamp))
                elif unit_length > 0:
                    value_length = len(str(
                        self.lcd_line[display_id][i]['measure_val']))
                    name_length = self.lcd_x_characters - value_length - unit_length - 2
                    name_cropped = self.lcd_line[display_id][i]['name'].ljust(name_length)[:name_length]
                    self.lcd_string_line[display_id][i] = '{name} {value} {unit}'.format(
                        name=name_cropped,
                        value=self.lcd_line[display_id][i]['measure_val'],
                        unit=unit_display.replace('°', u''))
                else:
                    value_length = len(str(
                        self.lcd_line[display_id][i]['measure_val']))
                    name_length = self.lcd_x_characters - value_length - 1
                    name_cropped = self.lcd_line[display_id][i]['name'][:name_length]
                    if name_cropped != '':
                        line_str = '{name} {value}'.format(
                            name=name_cropped,
                            value=self.lcd_line[display_id][i]['measure_val'])
                    else:
                        line_str = self.lcd_line[display_id][i]['measure_val']
                    self.lcd_string_line[display_id][i] = line_str

            else:
                error = 'NO DATA'
                name_length = self.lcd_x_characters - len(error) - 1
                name_cropped = self.lcd_line[display_id][i]['name'].ljust(name_length)[:name_length]
                self.lcd_string_line[display_id][i] = '{name} {error}'.format(
                    name=name_cropped, error=error)

        except Exception as except_msg:
            self.logger.exception("Error: {err}".format(err=except_msg))

    def output_lcds(self):
        """ Output to all LCDs all at once """
        line_1 = ''
        line_2 = ''
        line_3 = ''
        line_4 = ''
        line_5 = ''
        line_6 = ''
        line_7 = ''
        line_8 = ''

        self.lcd_out.lcd_init()
        display_id = self.display_sets[self.display_set_count]

        if 1 in self.lcd_string_line[display_id] and self.lcd_string_line[display_id][1]:
            line_1 = self.lcd_string_line[display_id][1]
        if 2 in self.lcd_string_line[display_id] and self.lcd_string_line[display_id][2]:
            line_2 = self.lcd_string_line[display_id][2]
        if 3 in self.lcd_string_line[display_id] and self.lcd_string_line[display_id][3]:
            line_3 = self.lcd_string_line[display_id][3]
        if 4 in self.lcd_string_line[display_id] and self.lcd_string_line[display_id][4]:
            line_4 = self.lcd_string_line[display_id][4]
        if 5 in self.lcd_string_line[display_id] and self.lcd_string_line[display_id][5]:
            line_5 = self.lcd_string_line[display_id][5]
        if 6 in self.lcd_string_line[display_id] and self.lcd_string_line[display_id][6]:
            line_6 = self.lcd_string_line[display_id][6]
        if 7 in self.lcd_string_line[display_id] and self.lcd_string_line[display_id][7]:
            line_7 = self.lcd_string_line[display_id][7]
        if 8 in self.lcd_string_line[display_id] and self.lcd_string_line[display_id][8]:
            line_8 = self.lcd_string_line[display_id][8]

        if self.lcd_type in ['128x32_pioled',
                             '128x32_pioled_circuit_python',
                             '16x2_generic',
                             '20x4_generic',
                             '16x2_grove_lcd_rgb']:
            self.lcd_out.lcd_write_lines(line_1, line_2, line_3, line_4)

        elif self.lcd_type in ['128x64_pioled', '128x64_pioled_circuit_python']:
            self.lcd_out.lcd_write_lines(line_1, line_2, line_3, line_4,
                                         message_line_5=line_5,
                                         message_line_6=line_6,
                                         message_line_7=line_7,
                                         message_line_8=line_8)

    def output_state(self, output_id):
        output = db_retrieve_table_daemon(Output, unique_id=output_id)
        try:
            import RPi.GPIO as GPIO
            GPIO.setmode(GPIO.BCM)
            if GPIO.input(output.pin) == output.on_state:
                gpio_state = 'On'
            else:
                gpio_state = 'Off'
            return gpio_state
        except:
            self.logger.error(
                "RPi.GPIO and Raspberry Pi required for this action")

    def setup_lcd_line(self, display_id, line, device_id, measurement_id):
        if measurement_id == 'output':
            device_measurement = db_retrieve_table_daemon(
                Output, unique_id=device_id)
        elif measurement_id in ['BLANK', 'IP', 'TEXT']:
            device_measurement = None
        else:
            device_measurement = db_retrieve_table_daemon(
                DeviceMeasurements, unique_id=measurement_id)

        if device_measurement:
            conversion = db_retrieve_table_daemon(
                Conversion, unique_id=device_measurement.conversion_id)
            channel, unit, measurement = return_measurement_info(
                device_measurement, conversion)
        else:
            channel = None
            unit = None
            measurement = None

        self.lcd_line[display_id][line]['setup'] = False
        self.lcd_line[display_id][line]['id'] = device_id
        self.lcd_line[display_id][line]['name'] = None
        self.lcd_line[display_id][line]['unit'] = unit
        self.lcd_line[display_id][line]['measure'] = measurement
        self.lcd_line[display_id][line]['channel'] = channel

        if 'time' in measurement_id:
            self.lcd_line[display_id][line]['measure'] = 'time'
        elif measurement_id in ['BLANK', 'IP', 'TEXT']:
            self.lcd_line[display_id][line]['measure'] = measurement_id
            self.lcd_line[display_id][line]['name'] = ''

        if not device_id:
            return

        if unit in self.dict_units:
            self.lcd_line[display_id][line]['unit'] = unit
        else:
            self.lcd_line[display_id][line]['unit'] = ''

        # Determine the name
        controllers = [
            Output,
            PID,
            Input,
            Math
        ]
        for each_controller in controllers:
            controller_found = db_retrieve_table_daemon(each_controller, unique_id=device_id)
            if controller_found:
                self.lcd_line[display_id][line]['name'] = controller_found.name

        if (self.lcd_line[display_id][line]['measure'] in ['BLANK', 'IP', 'TEXT', 'time'] or
                None not in [self.lcd_line[display_id][line]['name'],
                             self.lcd_line[display_id][line]['unit']]):
            self.lcd_line[display_id][line]['setup'] = True

    def lcd_backlight(self, state):
        """ Turn the backlight on or off """
        if state:
            self.lcd_out.lcd_backlight(state)
            self.lcd_is_on = True
            self.timer = time.time() - 1  # Induce LCD to update after turning backlight on
        else:
            self.lcd_is_on = False  # Instruct LCD backlight to turn off

    def lcd_backlight_color(self, color):
        """ Set backlight color """
        self.lcd_out.lcd_backlight_color(color)
        self.timer = time.time() - 1  # Induce LCD to update after turning backlight on

    def lcd_flash(self, state):
        """ Enable the LCD to begin or end flashing """
        if state:
            self.flash_lcd_on = True
            return 1, "LCD {} Flashing Turned On".format(self.unique_id)
        else:
            self.flash_lcd_on = False
            self.lcd_backlight(True)
            return 1, "LCD {} Reset".format(self.unique_id)
Ejemplo n.º 5
0
    def initialize_variables(self):
        lcd_dev = db_retrieve_table_daemon(LCD, unique_id=self.unique_id)
        self.lcd_type = lcd_dev.lcd_type
        self.lcd_name = lcd_dev.name
        self.lcd_period = lcd_dev.period
        self.lcd_x_characters = lcd_dev.x_characters
        self.lcd_y_lines = lcd_dev.y_lines
        self.timer = time.time() + self.lcd_period
        self.backlight_timer = time.time()
        self.log_level_debug = lcd_dev.log_level_debug

        self.set_log_level_debug(self.log_level_debug)

        # Add custom measurement and units to list
        self.list_inputs = add_custom_measurements(
            db_retrieve_table_daemon(Measurement, entry='all'))

        self.list_inputs.update(
            {'input_time': {'unit': None, 'name': 'Time'}})
        self.list_inputs.update(
            {'pid_time': {'unit': None, 'name': 'Time'}})

        self.dict_units = add_custom_units(
            db_retrieve_table_daemon(Unit, entry='all'))

        lcd_data = db_retrieve_table_daemon(
            LCDData).filter(LCDData.lcd_id == lcd_dev.unique_id).all()

        for each_lcd_display in lcd_data:
            self.display_sets.append(each_lcd_display.unique_id)
            self.lcd_string_line[each_lcd_display.unique_id] = {}
            self.lcd_line[each_lcd_display.unique_id] = {}
            self.lcd_text[each_lcd_display.unique_id] = {}
            self.lcd_max_age[each_lcd_display.unique_id] = {}
            self.lcd_decimal_places[each_lcd_display.unique_id] = {}

            for i in range(1, self.lcd_y_lines + 1):
                self.lcd_string_line[each_lcd_display.unique_id][i] = ''
                self.lcd_line[each_lcd_display.unique_id][i] = {}
                if i == 1:
                    self.lcd_text[each_lcd_display.unique_id][i] = each_lcd_display.line_1_text
                    self.lcd_max_age[each_lcd_display.unique_id][i] = each_lcd_display.line_1_max_age
                    self.lcd_decimal_places[each_lcd_display.unique_id][i] = each_lcd_display.line_1_decimal_places
                elif i == 2:
                    self.lcd_text[each_lcd_display.unique_id][i] = each_lcd_display.line_2_text
                    self.lcd_max_age[each_lcd_display.unique_id][i] = each_lcd_display.line_2_max_age
                    self.lcd_decimal_places[each_lcd_display.unique_id][i] = each_lcd_display.line_2_decimal_places
                elif i == 3:
                    self.lcd_text[each_lcd_display.unique_id][i] = each_lcd_display.line_3_text
                    self.lcd_max_age[each_lcd_display.unique_id][i] = each_lcd_display.line_3_max_age
                    self.lcd_decimal_places[each_lcd_display.unique_id][i] = each_lcd_display.line_3_decimal_places
                elif i == 4:
                    self.lcd_text[each_lcd_display.unique_id][i] = each_lcd_display.line_4_text
                    self.lcd_max_age[each_lcd_display.unique_id][i] = each_lcd_display.line_4_max_age
                    self.lcd_decimal_places[each_lcd_display.unique_id][i] = each_lcd_display.line_4_decimal_places
                elif i == 5:
                    self.lcd_text[each_lcd_display.unique_id][i] = each_lcd_display.line_5_text
                    self.lcd_max_age[each_lcd_display.unique_id][i] = each_lcd_display.line_5_max_age
                    self.lcd_decimal_places[each_lcd_display.unique_id][i] = each_lcd_display.line_5_decimal_places
                elif i == 6:
                    self.lcd_text[each_lcd_display.unique_id][i] = each_lcd_display.line_6_text
                    self.lcd_max_age[each_lcd_display.unique_id][i] = each_lcd_display.line_6_max_age
                    self.lcd_decimal_places[each_lcd_display.unique_id][i] = each_lcd_display.line_6_decimal_places
                elif i == 7:
                    self.lcd_text[each_lcd_display.unique_id][i] = each_lcd_display.line_7_text
                    self.lcd_max_age[each_lcd_display.unique_id][i] = each_lcd_display.line_7_max_age
                    self.lcd_decimal_places[each_lcd_display.unique_id][i] = each_lcd_display.line_7_decimal_places
                elif i == 8:
                    self.lcd_text[each_lcd_display.unique_id][i] = each_lcd_display.line_8_text
                    self.lcd_max_age[each_lcd_display.unique_id][i] = each_lcd_display.line_8_max_age
                    self.lcd_decimal_places[each_lcd_display.unique_id][i] = each_lcd_display.line_8_decimal_places

            if self.lcd_y_lines in [2, 4, 8]:
                self.setup_lcd_line(
                    each_lcd_display.unique_id, 1,
                    each_lcd_display.line_1_id,
                    each_lcd_display.line_1_measurement)
                self.setup_lcd_line(
                    each_lcd_display.unique_id, 2,
                    each_lcd_display.line_2_id,
                    each_lcd_display.line_2_measurement)

            if self.lcd_y_lines in [4, 8]:
                self.setup_lcd_line(
                    each_lcd_display.unique_id, 3,
                    each_lcd_display.line_3_id,
                    each_lcd_display.line_3_measurement)
                self.setup_lcd_line(
                    each_lcd_display.unique_id, 4,
                    each_lcd_display.line_4_id,
                    each_lcd_display.line_4_measurement)

            if self.lcd_y_lines == 8:
                self.setup_lcd_line(
                    each_lcd_display.unique_id, 5,
                    each_lcd_display.line_5_id,
                    each_lcd_display.line_5_measurement)
                self.setup_lcd_line(
                    each_lcd_display.unique_id, 6,
                    each_lcd_display.line_6_id,
                    each_lcd_display.line_6_measurement)
                self.setup_lcd_line(
                    each_lcd_display.unique_id, 7,
                    each_lcd_display.line_7_id,
                    each_lcd_display.line_7_measurement)
                self.setup_lcd_line(
                    each_lcd_display.unique_id, 8,
                    each_lcd_display.line_8_id,
                    each_lcd_display.line_8_measurement)

        if self.lcd_type in ['16x2_generic',
                             '20x4_generic']:
            from mycodo.devices.lcd_generic import LCD_Generic
            self.lcd_out = LCD_Generic(lcd_dev)
            self.lcd_init()
        elif self.lcd_type in ['16x2_grove_lcd_rgb']:
            from mycodo.devices.lcd_grove_lcd_rgb import LCD_Grove_LCD_RGB
            self.lcd_out = LCD_Grove_LCD_RGB(lcd_dev)
            self.lcd_init()
        elif self.lcd_type in ['128x32_pioled',
                               '128x64_pioled']:
            from mycodo.devices.lcd_pioled import LCD_Pioled
            self.lcd_out = LCD_Pioled(lcd_dev)
            self.lcd_init()
        elif self.lcd_type in ['128x32_pioled_circuit_python',
                               '128x64_pioled_circuit_python']:
            from mycodo.devices.lcd_pioled_circuitpython import PiOLEDCircuitpython
            self.lcd_out = PiOLEDCircuitpython(lcd_dev)
            self.lcd_init()
        else:
            self.logger.error("Unknown LCD type: {}".format(self.lcd_type))

        if self.lcd_initialized:
            line_1 = 'Mycodo {}'.format(MYCODO_VERSION)
            line_2 = 'Start {}'.format(self.lcd_name)
            self.lcd_out.lcd_write_lines(line_1, line_2, '', '')