def initialize_variables(self):
        from mycodo.devices.lcd_generic import LCD_Generic

        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,
                "i2c_address": self.i2c_address,
                "i2c_bus": self.i2c_bus,
                "x_characters": lcd_x_characters,
                "y_lines": lcd_lines
            }

            self.lcd = LCD_Generic(lcd_settings_dict=lcd_settings_dict)
            self.lcd.lcd_init()

            self.logger.debug("LCD Function started")
        except:
            self.logger.exception("Starting LCD Function")
Exemple #2
0
    def __init__(self, ready, lcd_id):
        threading.Thread.__init__(self)

        self.logger = logging.getLogger(
            "mycodo.lcd_{id}".format(id=lcd_id.split('-')[0]))

        self.running = False
        self.thread_startup_timer = timeit.default_timer()
        self.thread_shutdown_timer = 0
        self.ready = ready
        self.flash_lcd_on = False
        self.lcd_initialized = False
        self.lcd_is_on = False
        self.lcd_id = lcd_id
        self.display_sets = []
        self.display_set_count = 0

        try:
            lcd_dev = db_retrieve_table_daemon(LCD, unique_id=self.lcd_id)
            self.lcd_type = lcd_dev.lcd_type
            self.lcd_name = lcd_dev.name
            self.lcd_i2c_address = int(lcd_dev.location, 16)
            self.lcd_i2c_bus = lcd_dev.i2c_bus
            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.list_pids = ['setpoint', 'pid_time']
            self.list_outputs = [
                'duration_time', 'output_time', 'output_state'
            ]

            # 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()

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

            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_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_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_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_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_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_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_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_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_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 ['128x32_pioled', '128x64_pioled']:
                from mycodo.devices.lcd_pioled import LCD_Pioled
                self.lcd_out = LCD_Pioled(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, '', '')
        except Exception as except_msg:
            self.logger.exception("Error: {err}".format(err=except_msg))
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.lcd = None
        self.timer_loop = time.time()
        self.line_sets = []
        self.current_line_set = 0
        self.line_y_dimensions = [0, 8]
        self.pad = -2

        # Initialize custom options
        self.period = None
        self.i2c_address = None
        self.i2c_bus = None
        self.number_line_sets = 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_generic import LCD_Generic

        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,
                "i2c_address": self.i2c_address,
                "i2c_bus": self.i2c_bus,
                "x_characters": lcd_x_characters,
                "y_lines": lcd_lines
            }

            self.lcd = LCD_Generic(lcd_settings_dict=lcd_settings_dict)
            self.lcd.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.lcd:
            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, lcd_x_characters)

                    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.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.lcd.lcd_init()
        self.lcd.lcd_write_lines(
            lines_display[0], lines_display[1], "", "")

    def stop_function(self):
        self.lcd.lcd_init()
        self.lcd.lcd_write_lines(
            "Mycodo {}".format(MYCODO_VERSION), "LCD Deactivated", "", "")
    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 LCD_Pioled_Circuitpython
            self.lcd_out = LCD_Pioled_Circuitpython(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, '', '')