Ejemplo n.º 1
0
def math_del(form_mod_math):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['delete']['title'],
        controller=TRANSLATIONS['math']['title'])
    error = []

    math_id = form_mod_math.math_id.data

    try:
        math = Math.query.filter(
            Math.unique_id == math_id).first()
        if math.is_activated:
            controller_activate_deactivate(
                'deactivate',
                'Math',
                form_mod_math.math_id.data)

        device_measurements = DeviceMeasurements.query.filter(
            DeviceMeasurements.device_id == math_id).all()

        for each_measurement in device_measurements:
            delete_entry_with_id(DeviceMeasurements, each_measurement.unique_id)

        delete_entry_with_id(Math, math_id)
        try:
            display_order = csv_to_list_of_str(DisplayOrder.query.first().math)
            display_order.remove(math_id)
            DisplayOrder.query.first().math = list_to_csv(display_order)
        except Exception:  # id not in list
            pass
        db.session.commit()
    except Exception as except_msg:
        error.append(except_msg)

    flash_success_errors(error, action, url_for('routes_page.page_data'))
Ejemplo n.º 2
0
def conditional_condition_add(form):
    """Add a Conditional Condition"""
    error = []
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['add']['title'],
        controller='{} {}'.format(TRANSLATIONS['conditional']['title'],
                                  gettext("Condition")))

    cond = Conditional.query.filter(
        Conditional.unique_id == form.function_id.data).first()
    if cond.is_activated:
        error.append("Deactivate the Conditional before adding a Condition")

    if form.condition_type.data == '':
        error.append("Must select a condition")

    try:
        new_condition = ConditionalConditions()
        new_condition.conditional_id = form.function_id.data
        new_condition.condition_type = form.condition_type.data

        if new_condition.condition_type == 'measurement':
            new_condition.max_age = 360

        if not error:
            new_condition.save()
    except sqlalchemy.exc.OperationalError as except_msg:
        error.append(except_msg)
    except sqlalchemy.exc.IntegrityError as except_msg:
        error.append(except_msg)
    except Exception as except_msg:
        error.append(except_msg)

    flash_success_errors(error, action, url_for('routes_page.page_function'))
Ejemplo n.º 3
0
def action_del(form):
    """Delete a Conditional Action"""
    error = []
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['delete']['title'],
        controller='{} {}'.format(TRANSLATIONS['conditional']['title'], TRANSLATIONS['actions']['title']))

    conditional = Conditional.query.filter(
        Conditional.unique_id == form.function_id.data).first()

    trigger = Trigger.query.filter(
        Trigger.unique_id == form.function_id.data).first()

    if ((conditional and conditional.is_activated) or
            (trigger and trigger.is_activated)):
        error.append("Deactivate the Conditional before deleting an Action")

    try:
        if not error:
            function_action_id = Actions.query.filter(
                Actions.unique_id == form.function_action_id.data).first().unique_id
            delete_entry_with_id(Actions, function_action_id)

    except sqlalchemy.exc.OperationalError as except_msg:
        error.append(except_msg)
    except sqlalchemy.exc.IntegrityError as except_msg:
        error.append(except_msg)
    except Exception as except_msg:
        error.append(except_msg)

    flash_success_errors(error, action, url_for('routes_page.page_function'))
Ejemplo n.º 4
0
def export_measurements(form):
    """
    Take user input to query the InfluxDB and return a CSV file of timestamps
    and measurement values
    """
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['export']['title'],
        controller=TRANSLATIONS['measurement']['title'])
    error = []

    if form.validate():
        try:
            if not error:
                start_time = form.date_range.data.split(' - ')[0]
                start_seconds = int(time.mktime(
                    time.strptime(start_time, '%m/%d/%Y %H:%M')))
                end_time = form.date_range.data.split(' - ')[1]
                end_seconds = int(time.mktime(
                    time.strptime(end_time, '%m/%d/%Y %H:%M')))

                unique_id = form.measurement.data.split(',')[0]
                measurement_id = form.measurement.data.split(',')[1]

                url = '/export_data/{id}/{meas}/{start}/{end}'.format(
                    id=unique_id,
                    meas=measurement_id,
                    start=start_seconds, end=end_seconds)
                return url
        except Exception as err:
            error.append("Error: {}".format(err))
    else:
        flash_form_errors(form)
        return

    flash_success_errors(error, action, url_for('routes_page.page_export'))
Ejemplo n.º 5
0
def function_del(function_id):
    """Delete a Function"""
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['delete']['title'],
        controller=TRANSLATIONS['function']['title'])
    error = []

    try:
        # Delete Actions
        actions = Actions.query.filter(
            Actions.function_id == function_id).all()
        for each_action in actions:
            delete_entry_with_id(Actions,
                                 each_action.unique_id)

        delete_entry_with_id(Function, function_id)

        display_order = csv_to_list_of_str(DisplayOrder.query.first().function)
        display_order.remove(function_id)
        DisplayOrder.query.first().function = list_to_csv(display_order)
        db.session.commit()
    except Exception as except_msg:
        error.append(except_msg)

    flash_success_errors(error, action, url_for('routes_page.page_function'))
Ejemplo n.º 6
0
def conditional_activate(cond_id):
    """Activate a Conditional"""
    error = []
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['activate']['title'],
        controller=TRANSLATIONS['conditional']['title'])

    conditions = ConditionalConditions.query.filter(
        ConditionalConditions.conditional_id == cond_id).all()

    for each_condition in conditions:
        # Check for errors in the Conditional settings
        error = check_cond_measurements(each_condition, error)

    conditions = ConditionalConditions.query.filter(
        ConditionalConditions.conditional_id == cond_id)
    if not conditions.count():
        error.append("No Conditions found: Add at least one Condition before activating.")

    actions = Actions.query.filter(
        Actions.function_id == cond_id)
    if not actions.count():
        error.append("No Actions found: Add at least one Action before activating.")

    for each_action in actions.all():
        error = check_actions(each_action, error)

    if not error:
        controller_activate_deactivate('activate', 'Conditional', cond_id)

    flash_success_errors(error, action, url_for('routes_page.page_function'))
Ejemplo n.º 7
0
def conditional_condition_del(form):
    """Delete a Conditional Condition"""
    error = []
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['delete']['title'],
        controller='{} {}'.format(TRANSLATIONS['conditional']['title'],
                                  gettext("Condition")))

    cond = Conditional.query.filter(
        Conditional.unique_id == form.conditional_id.data).first()
    if cond.is_activated:
        error.append("Deactivate the Conditional before deleting a Condition")

    try:
        if not error:
            cond_condition_id = ConditionalConditions.query.filter(
                ConditionalConditions.unique_id == form.conditional_condition_id.data).first().unique_id
            delete_entry_with_id(ConditionalConditions, cond_condition_id)

    except sqlalchemy.exc.OperationalError as except_msg:
        error.append(except_msg)
    except sqlalchemy.exc.IntegrityError as except_msg:
        error.append(except_msg)
    except Exception as except_msg:
        error.append(except_msg)

    flash_success_errors(error, action, url_for('routes_page.page_function'))
Ejemplo n.º 8
0
def export_influxdb(form):
    """
    Save the InfluxDB metastore and mycodo_db database to a zip file and serve
    it to the user
    """
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['export']['title'],
        controller=TRANSLATIONS['measurement']['title'])
    error = []

    try:
        influx_backup_dir = os.path.join(INSTALL_DIRECTORY, 'influx_backup')

        # Delete influxdb directory if it exists
        if os.path.isdir(influx_backup_dir):
            shutil.rmtree(influx_backup_dir)

        # Create new directory (make sure it's empty)
        assure_path_exists(influx_backup_dir)

        cmd = "/usr/bin/influxd backup -database mycodo_db {path}".format(
            path=influx_backup_dir)
        _, _, status = cmd_output(cmd)

        influxd_version_out, _, _ = cmd_output(
            '/usr/bin/influxd version')
        if influxd_version_out:
            influxd_version = influxd_version_out.decode('utf-8').split(' ')[1]
        else:
            influxd_version = None
            error.append("Could not determine Influxdb version")

        if not status and influxd_version:
            # Zip all files in the influx_backup directory
            data = io.BytesIO()
            with zipfile.ZipFile(data, mode='w') as z:
                for _, _, files in os.walk(influx_backup_dir):
                    for filename in files:
                        z.write(os.path.join(influx_backup_dir, filename),
                                filename)
            data.seek(0)

            # Delete influxdb directory if it exists
            if os.path.isdir(influx_backup_dir):
                shutil.rmtree(influx_backup_dir)

            # Send zip file to user
            return send_file(
                data,
                mimetype='application/zip',
                as_attachment=True,
                attachment_filename='Mycodo_{mv}_Influxdb_{iv}_{host}_{dt}.zip'.format(
                     mv=MYCODO_VERSION, iv=influxd_version,
                     host=socket.gethostname().replace(' ', ''),
                     dt=datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S"))
            )
    except Exception as err:
        error.append("Error: {}".format(err))

    flash_success_errors(error, action, url_for('routes_page.page_export'))
Ejemplo n.º 9
0
def pid_del(pid_id):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['delete']['title'],
        controller=TRANSLATIONS['pid']['title'])
    error = []

    try:
        pid = PID.query.filter(
            PID.unique_id == pid_id).first()
        if pid.is_activated:
            pid_deactivate(pid_id)

        device_measurements = DeviceMeasurements.query.filter(
            DeviceMeasurements.device_id == pid_id).all()

        for each_measurement in device_measurements:
            delete_entry_with_id(DeviceMeasurements, each_measurement.unique_id)

        delete_entry_with_id(PID, pid_id)
        try:
            display_order = csv_to_list_of_str(DisplayOrder.query.first().math)
            display_order.remove(pid_id)
            DisplayOrder.query.first().function = list_to_csv(display_order)
        except Exception:  # id not in list
            pass
        db.session.commit()
    except Exception as except_msg:
        error.append(except_msg)

    flash_success_errors(error, action, url_for('routes_page.page_function'))
Ejemplo n.º 10
0
def lcd_del(lcd_id):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['delete']['title'],
        controller=TRANSLATIONS['lcd']['title'])
    error = []

    lcd = LCD.query.filter(
        LCD.unique_id == lcd_id).first()
    if lcd.is_activated:
        error.append(gettext("Deactivate LCD controller before modifying "
                             "its settings."))

    if not error:
        try:
            # Delete all LCD Displays
            lcd_displays = LCDData.query.filter(
                LCDData.lcd_id == lcd_id).all()
            for each_lcd_display in lcd_displays:
                lcd_display_del(each_lcd_display.unique_id, delete_last=True)

            # Delete LCD
            delete_entry_with_id(LCD, lcd_id)
            display_order = csv_to_list_of_str(DisplayOrder.query.first().lcd)
            display_order.remove(lcd_id)
            DisplayOrder.query.first().lcd = list_to_csv(display_order)
            db.session.commit()
        except Exception as except_msg:
            error.append(except_msg)
    flash_success_errors(error, action, url_for('routes_page.page_lcd'))
Ejemplo n.º 11
0
def lcd_activate(lcd_id):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['activate']['title'],
        controller=TRANSLATIONS['lcd']['title'])
    error = []

    try:
        # All display lines must be filled to activate display
        lcd = LCD.query.filter(
            LCD.unique_id == lcd_id).first()
        lcd_data = LCDData.query.filter(
            LCDData.lcd_id == lcd_id).all()
        blank_line_detected = False

        for each_lcd_data in lcd_data:
            if (
                    (lcd.y_lines in [2, 4] and
                        (not each_lcd_data.line_1_id or
                         not each_lcd_data.line_2_id)
                     ) or
                    (lcd.y_lines == 4 and
                        (not each_lcd_data.line_3_id or
                         not each_lcd_data.line_4_id))
                    ):
                blank_line_detected = True

        if blank_line_detected:
            error.append(gettext(
                "Cannot activate LCD if there are blank lines"))

        if not error:
            controller_activate_deactivate('activate', 'LCD', lcd_id)
    except Exception as except_msg:
        error.append(except_msg)
    flash_success_errors(error, action, url_for('routes_page.page_lcd'))
Ejemplo n.º 12
0
def export_settings(form):
    """
    Save the Mycodo settings database (mycodo.db) to a zip file and serve it
    to the user
    """
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['export']['title'],
        controller=TRANSLATIONS['settings']['title'])
    error = []

    try:
        data = io.BytesIO()
        with zipfile.ZipFile(data, mode='w') as z:
            z.write(SQL_DATABASE_MYCODO,
                    os.path.basename(SQL_DATABASE_MYCODO))
        data.seek(0)
        return send_file(
            data,
            mimetype='application/zip',
            as_attachment=True,
            attachment_filename=
                'Mycodo_{mver}_Settings_{aver}_{host}_{dt}.zip'.format(
                    mver=MYCODO_VERSION, aver=ALEMBIC_VERSION,
                    host=socket.gethostname().replace(' ', ''),
                    dt=datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S"))
        )
    except Exception as err:
        error.append("Error: {}".format(err))

    flash_success_errors(error, action, url_for('routes_page.page_export'))
Ejemplo n.º 13
0
def lcd_display_del(lcd_data_id, delete_last=False):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['delete']['title'],
        controller=TRANSLATIONS['display']['title'])
    error = []

    lcd_data_this = LCDData.query.filter(
        LCDData.unique_id == lcd_data_id).first()
    lcd_data_all = LCDData.query.filter(
        LCDData.lcd_id == lcd_data_this.lcd_id).all()
    lcd = LCD.query.filter(
        LCD.unique_id == lcd_data_this.lcd_id).first()

    if lcd.is_activated:
        error.append(gettext("Deactivate LCD controller before modifying"
                             " its settings"))
    if not delete_last and len(lcd_data_all) < 2:
        error.append(gettext("The last display cannot be deleted"))

    if not error:
        try:
            delete_entry_with_id(LCDData,
                                 lcd_data_id)
            db.session.commit()
        except Exception as except_msg:
            error.append(except_msg)
    flash_success_errors(error, action, url_for('routes_page.page_lcd'))
Ejemplo n.º 14
0
def lcd_add(form):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['add']['title'],
        controller=TRANSLATIONS['lcd']['title'])
    error = []

    if current_app.config['TESTING']:
        dep_unmet = False
    else:
        dep_unmet, _ = return_dependencies(form.lcd_type.data)
        if dep_unmet:
            list_unmet_deps = []
            for each_dep in dep_unmet:
                list_unmet_deps.append(each_dep[0])
            error.append("The {dev} device you're trying to add has unmet dependencies: {dep}".format(
                dev=form.lcd_type.data, dep=', '.join(list_unmet_deps)))

    try:
        new_lcd = LCD()
        new_lcd_data = LCDData()
        if GPIO.RPI_REVISION == 2 or GPIO.RPI_REVISION == 3:
            new_lcd.i2c_bus = 1
        else:
            new_lcd.i2c_bus = 0
        new_lcd.lcd_type = form.lcd_type.data
        new_lcd.name = str(LCD_INFO[form.lcd_type.data]['name'])

        if form.lcd_type.data == '128x32_pioled':
            new_lcd.location = '0x3c'
            new_lcd.x_characters = 21
            new_lcd.y_lines = 4
        elif form.lcd_type.data == '128x64_pioled':
            new_lcd.location = '0x3c'
            new_lcd.x_characters = 21
            new_lcd.y_lines = 8
        elif form.lcd_type.data == '16x2_generic':
            new_lcd.location = '0x27'
            new_lcd.x_characters = 16
            new_lcd.y_lines = 2
        elif form.lcd_type.data == '16x4_generic':
            new_lcd.location = '0x27'
            new_lcd.x_characters = 16
            new_lcd.y_lines = 4

        if not error:
            new_lcd.save()
            new_lcd_data.lcd_id = new_lcd.unique_id
            new_lcd_data.save()
            display_order = csv_to_list_of_str(DisplayOrder.query.first().lcd)
            DisplayOrder.query.first().lcd = add_display_order(
                display_order, new_lcd.unique_id)
            db.session.commit()
    except sqlalchemy.exc.OperationalError as except_msg:
        error.append(except_msg)
    except sqlalchemy.exc.IntegrityError as except_msg:
        error.append(except_msg)
    flash_success_errors(error, action, url_for('routes_page.page_lcd'))

    if dep_unmet:
        return 1
Ejemplo n.º 15
0
def lcd_mod(form_mod_lcd):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['modify']['title'],
        controller=TRANSLATIONS['lcd']['title'])
    error = []

    mod_lcd = LCD.query.filter(
        LCD.unique_id == form_mod_lcd.lcd_id.data).first()
    if mod_lcd.is_activated:
        error.append(gettext("Deactivate LCD controller before modifying"
                             " its settings."))

    if not error:
        if form_mod_lcd.validate():
            try:
                mod_lcd.name = form_mod_lcd.name.data
                if mod_lcd.lcd_type in ['16x2_generic',
                                        '16x4_generic']:
                    mod_lcd.location = form_mod_lcd.location.data
                mod_lcd.i2c_bus = form_mod_lcd.i2c_bus.data
                mod_lcd.period = form_mod_lcd.period.data
                db.session.commit()
            except Exception as except_msg:
                error.append(except_msg)
        else:
            flash_form_errors(form_mod_lcd)
    flash_success_errors(error, action, url_for('routes_page.page_lcd'))
Ejemplo n.º 16
0
def file_del(form):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['delete']['title'],
        controller=gettext("File"))
    error = []

    if not form.note_unique_id.data:
        error.append("Unique id is empty")

    mod_note = Notes.query.filter(
        Notes.unique_id == form.note_unique_id.data).first()
    files_list = mod_note.files.split(",")

    if form.file_selected.data in files_list:
        try:
            files_list.remove(form.file_selected.data)
        except:
            error.append("Could not remove file from note")

    if mod_note.files:
        try:
            full_file_path = os.path.join(PATH_NOTE_ATTACHMENTS, form.file_selected.data)
            os.remove(full_file_path)
        except:
            error.append("Could not remove file from filesystem")

    if not error:
        mod_note.files = ",".join(files_list)
        db.session.commit()

    flash_success_errors(error, action, url_for('routes_page.page_notes'))
Ejemplo n.º 17
0
def input_del(input_id):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['delete']['title'],
        controller=TRANSLATIONS['input']['title'])
    error = []

    try:
        input_dev = Input.query.filter(
            Input.unique_id == input_id).first()

        if input_dev.is_activated:
            input_deactivate_associated_controllers(input_id)
            controller_activate_deactivate('deactivate', 'Input', input_id)

        device_measurements = DeviceMeasurements.query.filter(
            DeviceMeasurements.device_id == input_id).all()

        for each_measurement in device_measurements:
            delete_entry_with_id(DeviceMeasurements, each_measurement.unique_id)

        delete_entry_with_id(Input, input_id)
        try:
            display_order = csv_to_list_of_str(
                DisplayOrder.query.first().inputs)
            display_order.remove(input_id)
            DisplayOrder.query.first().inputs = list_to_csv(display_order)
        except Exception:  # id not in list
            pass
        db.session.commit()
    except Exception as except_msg:
        error.append(except_msg)

    flash_success_errors(error, action, url_for('routes_page.page_data'))
Ejemplo n.º 18
0
def math_add(form_add_math):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['add']['title'],
        controller=TRANSLATIONS['math']['title'])
    error = []

    dep_unmet, _ = return_dependencies(form_add_math.math_type.data)
    if dep_unmet:
        list_unmet_deps = []
        for each_dep in dep_unmet:
            list_unmet_deps.append(each_dep[0])
        error.append("The {dev} device you're trying to add has unmet dependencies: {dep}".format(
            dev=form_add_math.math_type.data, dep=', '.join(list_unmet_deps)))

    if form_add_math.validate():
        new_math = Math()
        new_math.name = str(MATH_INFO[form_add_math.math_type.data]['name'])
        new_math.math_type = form_add_math.math_type.data

        try:
            new_math.save()

            display_order = csv_to_list_of_str(
                DisplayOrder.query.first().math)
            DisplayOrder.query.first().math = add_display_order(
                display_order, new_math.unique_id)
            db.session.commit()

            if not MATH_INFO[form_add_math.math_type.data]['measure']:
                new_measurement = DeviceMeasurements()
                new_measurement.device_id = new_math.unique_id
                new_measurement.channel = 0
                new_measurement.save()
            else:
                for each_channel, measure_info in MATH_INFO[form_add_math.math_type.data]['measure'].items():
                    new_measurement = DeviceMeasurements()
                    if 'name' in measure_info and measure_info['name']:
                        new_measurement.name = measure_info['name']
                    new_measurement.device_id = new_math.unique_id
                    new_measurement.measurement = measure_info['measurement']
                    new_measurement.unit = measure_info['unit']
                    new_measurement.channel = each_channel
                    new_measurement.save()

            flash(gettext(
                "%(type)s Math with ID %(id)s (%(uuid)s) successfully added",
                type=form_add_math.math_type.data,
                id=new_math.id,
                uuid=new_math.unique_id),
                  "success")
        except sqlalchemy.exc.OperationalError as except_msg:
            error.append(except_msg)
        except sqlalchemy.exc.IntegrityError as except_msg:
            error.append(except_msg)
        flash_success_errors(error, action, url_for('routes_page.page_data'))
    else:
        flash_form_errors(form_add_math)

    if dep_unmet:
        return 1
Ejemplo n.º 19
0
def output_on_off(form_output):
    action = '{action} {controller}'.format(
        action=gettext("Actuate"),
        controller=TRANSLATIONS['output']['title'])
    error = []

    try:
        control = DaemonControl()
        output = Output.query.filter_by(unique_id=form_output.output_id.data).first()
        if output.output_type == 'wired' and int(form_output.output_pin.data) == 0:
            error.append(gettext("Cannot modulate output with a GPIO of 0"))
        elif form_output.on_submit.data:
            if output.output_type in ['wired',
                                      'wireless_rpi_rf',
                                      'command']:
                if float(form_output.sec_on.data) <= 0:
                    error.append(gettext("Value must be greater than 0"))
                else:
                    return_value = control.output_on(form_output.output_id.data,
                                                     duration=float(form_output.sec_on.data))
                    flash(gettext("Output turned on for %(sec)s seconds: %(rvalue)s",
                                  sec=form_output.sec_on.data,
                                  rvalue=return_value),
                          "success")
            if output.output_type == 'pwm':
                if int(form_output.output_pin.data) == 0:
                    error.append(gettext("Invalid pin"))
                if output.pwm_hertz <= 0:
                    error.append(gettext("PWM Hertz must be a positive value"))
                if float(form_output.pwm_duty_cycle_on.data) <= 0:
                    error.append(gettext("PWM duty cycle must be a positive value"))
                if not error:
                    return_value = control.output_on(
                        form_output.output_id.data,
                        duty_cycle=float(form_output.pwm_duty_cycle_on.data))
                    flash(gettext("PWM set to %(dc)s %% at %(hertz)s Hz: %(rvalue)s",
                                  dc=float(form_output.pwm_duty_cycle_on.data),
                                  hertz=output.pwm_hertz,
                                  rvalue=return_value),
                          "success")
        elif form_output.turn_on.data:
            return_value = control.output_on(form_output.output_id.data, 0)
            flash(gettext("Output turned on: %(rvalue)s",
                          rvalue=return_value), "success")
        elif form_output.turn_off.data:
            return_value = control.output_off(form_output.output_id.data)
            flash(gettext("Output turned off: %(rvalue)s",
                          rvalue=return_value), "success")
    except ValueError as except_msg:
        error.append('{err}: {msg}'.format(
            err=gettext("Invalid value"),
            msg=except_msg))
    except Exception as except_msg:
        error.append(except_msg)

    flash_success_errors(error, action, url_for('routes_page.page_output'))
Ejemplo n.º 20
0
def note_mod(form):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['modify']['title'],
        controller=TRANSLATIONS['note']['title'])
    error = []
    list_tags = []

    mod_note = Notes.query.filter(
        Notes.unique_id == form.note_unique_id.data).first()

    if not form.name.data:
        error.append("Name cannot be left blank")
    if not form.note_tags.data:
        error.append("At least one tag must be selected")
    if not form.note.data:
        error.append("Note cannot be left blank")

    try:
        for each_tag in form.note_tags.data:
            check_tag = NoteTags.query.filter(
                NoteTags.unique_id == each_tag).first()
            if not check_tag:
                error.append("Invalid tag: {}".format(each_tag))
            else:
                list_tags.append(check_tag.unique_id)
    except Exception as msg:
        error.append("Invalid tag format: {}".format(msg))

    try:
        mod_note.date_time = datetime_time_to_utc(form.date_time.data)
    except:
        error.append("Error while parsing date/time")

    if form.files.data:
        assure_path_exists(PATH_NOTE_ATTACHMENTS)
        if mod_note.files:
            filename_list = mod_note.files.split(",")
        else:
            filename_list = []
        for each_file in form.files.raw_data:
            file_name = "{pre}_{name}".format(
                pre=mod_note.unique_id, name=each_file.filename)
            file_save_path = os.path.join(PATH_NOTE_ATTACHMENTS, file_name)
            each_file.save(file_save_path)
            filename_list.append(file_name)
        mod_note.files = ",".join(filename_list)

    if not error:
        mod_note.name = form.name.data
        mod_note.tags = ",".join(list_tags)
        mod_note.note = form.note.data
        db.session.commit()

    flash_success_errors(error, action, url_for('routes_page.page_notes'))
Ejemplo n.º 21
0
def conditional_deactivate(cond_id):
    """Deactivate a Conditional"""
    error = []
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['deactivate']['title'],
        controller=TRANSLATIONS['conditional']['title'])

    if not error:
        controller_activate_deactivate('deactivate', 'Conditional', cond_id)

    flash_success_errors(error, action, url_for('routes_page.page_function'))
Ejemplo n.º 22
0
def method_del(method_id):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['delete']['title'],
        controller=TRANSLATIONS['method']['title'])
    error = []

    try:
        delete_entry_with_id(Method,
                             method_id)
    except Exception as except_msg:
        error.append(except_msg)
    flash_success_errors(error, action, url_for('routes_method.method_list'))
Ejemplo n.º 23
0
def energy_usage_delete(energy_usage_id):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['delete']['title'],
        controller=TRANSLATIONS['energy_usage']['title'])
    error = []

    try:
        delete_entry_with_id(EnergyUsage, energy_usage_id)
    except Exception as except_msg:
        error.append(except_msg)

    flash_success_errors(error, action, url_for('routes_page.page_data'))
Ejemplo n.º 24
0
def tag_del(form):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['delete']['title'],
        controller=TRANSLATIONS['tag']['title'])
    error = []

    if Notes.query.filter(Notes.tags.ilike("%{0}%".format(form.tag_unique_id.data))).first():
        error.append("Cannot delete tag because it's currently assicuated with at least one note")

    if not error:
        delete_entry_with_id(NoteTags, form.tag_unique_id.data)

    flash_success_errors(error, action, url_for('routes_page.page_notes'))
Ejemplo n.º 25
0
def trigger_deactivate(trigger_id):
    """Deactivate a Trigger"""
    error = []
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['deactivate']['title'],
        controller=TRANSLATIONS['trigger']['title'])

    if not error:
        controller_activate_deactivate(
            'deactivate',
            'Trigger',
            trigger_id)

    flash_success_errors(error, action, url_for('routes_page.page_function'))
Ejemplo n.º 26
0
def measurement_mod(form):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['modify']['title'],
        controller=TRANSLATIONS['measurement']['title'])
    error = []

    try:
        mod_meas = DeviceMeasurements.query.filter(
            DeviceMeasurements.unique_id == form.input_measurement_id.data).first()

        mod_input = Input.query.filter(Input.unique_id == mod_meas.device_id).first()
        if mod_input.is_activated:
            error.append(gettext(
                "Deactivate controller before modifying its settings"))

        mod_meas.name = form.name.data

        input_info = parse_input_information()
        if ('enable_channel_unit_select' in input_info[mod_input.device] and
                input_info[mod_input.device]['enable_channel_unit_select']):
            if ',' in form.select_measurement_unit.data:
                mod_meas.measurement = form.select_measurement_unit.data.split(',')[0]
                mod_meas.unit = form.select_measurement_unit.data.split(',')[1]
            else:
                mod_meas.measurement = ''
                mod_meas.unit = ''

        if form.rescaled_measurement_unit.data != '' and ',' in form.rescaled_measurement_unit.data:
            mod_meas.rescaled_measurement = form.rescaled_measurement_unit.data.split(',')[0]
            mod_meas.rescaled_unit = form.rescaled_measurement_unit.data.split(',')[1]
        elif form.rescaled_measurement_unit.data == '':
            mod_meas.rescaled_measurement = ''
            mod_meas.rescaled_unit = ''

        mod_meas.scale_from_min = form.scale_from_min.data
        mod_meas.scale_from_max = form.scale_from_max.data
        mod_meas.scale_to_min = form.scale_to_min.data
        mod_meas.scale_to_max = form.scale_to_max.data
        mod_meas.invert_scale = form.invert_scale.data
        mod_meas.conversion_id = form.convert_to_measurement_unit.data

        if not error:
            db.session.commit()

    except Exception as except_msg:
        logger.exception(1)
        error.append(except_msg)

    flash_success_errors(error, action, url_for('routes_page.page_data'))
Ejemplo n.º 27
0
def function_reorder(function_id, display_order, direction):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['reorder']['title'],
        controller=TRANSLATIONS['function']['title'])
    error = []
    try:
        status, reord_list = reorder(
            display_order, function_id, direction)
        if status == 'success':
            DisplayOrder.query.first().function = ','.join(map(str, reord_list))
            db.session.commit()
        else:
            error.append(reord_list)
    except Exception as except_msg:
        error.append(except_msg)
    flash_success_errors(error, action, url_for('routes_page.page_function'))
Ejemplo n.º 28
0
def pid_activate(pid_id):
    if has_required_pid_values(pid_id):
        return redirect(url_for('routes_page.page_function'))

    action = '{action} {controller}'.format(
        action=TRANSLATIONS['activate']['title'],
        controller=TRANSLATIONS['pid']['title'])
    error = []

    # Check if associated sensor is activated
    pid = PID.query.filter(
        PID.unique_id == pid_id).first()

    error = can_set_output(
        error, pid_id, pid.raise_output_id, pid.lower_output_id)

    device_unique_id = pid.measurement.split(',')[0]
    input_dev = Input.query.filter(
        Input.unique_id == device_unique_id).first()
    math = Math.query.filter(
        Math.unique_id == device_unique_id).first()

    if (input_dev and not input_dev.is_activated) or (math and not math.is_activated):
        error.append(gettext(
            "Cannot activate PID controller if the associated sensor "
            "controller is inactive"))

    if ((pid.direction == 'both' and not (pid.lower_output_id and pid.raise_output_id)) or
            (pid.direction == 'lower' and not pid.lower_output_id) or
            (pid.direction == 'raise' and not pid.raise_output_id)):
        error.append(gettext(
            "Cannot activate PID controller if raise and/or lower output IDs "
            "are not selected"))

    if not error:
        # Signal the duration method can run because it's been
        # properly initiated (non-power failure)
        method = Method.query.filter(
            Method.unique_id == pid.method_id).first()
        if method and method.method_type == 'Duration':
            mod_pid = PID.query.filter(PID.unique_id == pid_id).first()
            mod_pid.method_start_time = 'Ready'
            db.session.commit()
        time.sleep(1)
        controller_activate_deactivate('activate', 'PID', pid_id)

    flash_success_errors(error, action, url_for('routes_page.page_function'))
Ejemplo n.º 29
0
def dashboard_del(form_base):
    """Delete an item on the dashboard"""
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['delete']['title'],
        controller=TRANSLATIONS['dashboard']['title'])
    error = []

    try:
        delete_entry_with_id(Dashboard,
                             form_base.dashboard_id.data)
        display_order = csv_to_list_of_str(DisplayOrder.query.first().dashboard)
        display_order.remove(form_base.dashboard_id.data)
        DisplayOrder.query.first().dashboard = list_to_csv(display_order)
        db.session.commit()
    except Exception as except_msg:
        error.append(except_msg)
    flash_success_errors(error, action, url_for('routes_page.page_dashboard'))
Ejemplo n.º 30
0
def output_del(form_output):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['delete']['title'],
        controller=TRANSLATIONS['output']['title'])
    error = []

    try:
        delete_entry_with_id(Output,
                             form_output.output_id.data)
        display_order = csv_to_list_of_str(DisplayOrder.query.first().output)
        display_order.remove(form_output.output_id.data)
        DisplayOrder.query.first().output = list_to_csv(display_order)
        db.session.commit()
        manipulate_output('Delete', form_output.output_id.data)
    except Exception as except_msg:
        error.append(except_msg)
    flash_success_errors(error, action, url_for('routes_page.page_output'))
Ejemplo n.º 31
0
def input_mod(form_mod, request_form):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['modify']['title'],
        controller=TRANSLATIONS['input']['title'])
    error = []

    dict_inputs = parse_input_information()

    try:
        mod_input = Input.query.filter(
            Input.unique_id == form_mod.input_id.data).first()

        if mod_input.is_activated:
            error.append(gettext(
                "Deactivate controller before modifying its settings"))

        if (mod_input.device == 'AM2315' and
                form_mod.period.data < 7):
            error.append(gettext(
                "Choose a Read Period equal to or greater than 7. The "
                "AM2315 may become unresponsive if the period is "
                "below 7."))

        if (form_mod.period.data and
                mod_input.pre_output_duration and
                form_mod.period.data < mod_input.pre_output_duration):
            error.append(gettext(
                "The Read Period cannot be less than the Pre Output Duration"))

        if (form_mod.uart_location.data and
                not os.path.exists(form_mod.uart_location.data)):
            error.append(gettext(
                "Invalid device or improper permissions to read device"))

        if ('gpio_location' in dict_inputs[mod_input.device]['options_enabled'] and
                form_mod.gpio_location.data is None):
            error.append(gettext("Pin (GPIO) must be set"))

        mod_input.name = form_mod.name.data

        if form_mod.location.data:
            mod_input.location = form_mod.location.data
        if form_mod.i2c_location.data:
            mod_input.i2c_location = form_mod.i2c_location.data
        if form_mod.ftdi_location.data:
            mod_input.ftdi_location = form_mod.ftdi_location.data
        if form_mod.uart_location.data:
            mod_input.uart_location = form_mod.uart_location.data
        if form_mod.gpio_location.data and form_mod.gpio_location.data is not None:
            mod_input.gpio_location = form_mod.gpio_location.data

        if form_mod.power_output_id.data:
            mod_input.power_output_id = form_mod.power_output_id.data
        else:
            mod_input.power_output_id = None

        if form_mod.pre_output_id.data:
            mod_input.pre_output_id = form_mod.pre_output_id.data
        else:
            mod_input.pre_output_id = None

        # Enable/disable Channels
        measurements = DeviceMeasurements.query.filter(
            DeviceMeasurements.device_id == form_mod.input_id.data).all()
        if form_mod.measurements_enabled.data:
            for each_measurement in measurements:
                if each_measurement.unique_id in form_mod.measurements_enabled.data:
                    each_measurement.is_enabled = True
                else:
                    each_measurement.is_enabled = False

        mod_input.log_level_debug = form_mod.log_level_debug.data
        mod_input.i2c_bus = form_mod.i2c_bus.data
        mod_input.baud_rate = form_mod.baud_rate.data
        mod_input.pre_output_duration = form_mod.pre_output_duration.data
        mod_input.pre_output_during_measure = form_mod.pre_output_during_measure.data

        if form_mod.period.data:
            mod_input.period = form_mod.period.data
        if form_mod.start_offset.data:
            mod_input.start_offset = form_mod.start_offset.data

        mod_input.resolution = form_mod.resolution.data
        mod_input.resolution_2 = form_mod.resolution_2.data
        mod_input.sensitivity = form_mod.sensitivity.data
        mod_input.calibrate_sensor_measure = form_mod.calibrate_sensor_measure.data
        mod_input.cmd_command = form_mod.cmd_command.data
        mod_input.thermocouple_type = form_mod.thermocouple_type.data
        mod_input.ref_ohm = form_mod.ref_ohm.data
        # Serial options
        mod_input.pin_clock = form_mod.pin_clock.data
        mod_input.pin_cs = form_mod.pin_cs.data
        mod_input.pin_mosi = form_mod.pin_mosi.data
        mod_input.pin_miso = form_mod.pin_miso.data
        # Bluetooth options
        mod_input.bt_adapter = form_mod.bt_adapter.data

        mod_input.adc_gain = form_mod.adc_gain.data
        mod_input.adc_resolution = form_mod.adc_resolution.data
        mod_input.adc_sample_speed = form_mod.adc_sample_speed.data

        # Switch options
        mod_input.switch_edge = form_mod.switch_edge.data
        mod_input.switch_bouncetime = form_mod.switch_bouncetime.data
        mod_input.switch_reset_period = form_mod.switch_reset_period.data
        # PWM and RPM options
        mod_input.weighting = form_mod.weighting.data
        mod_input.rpm_pulses_per_rev = form_mod.rpm_pulses_per_rev.data
        mod_input.sample_time = form_mod.sample_time.data
        # Server options
        mod_input.port = form_mod.port.data
        mod_input.times_check = form_mod.times_check.data
        mod_input.deadline = form_mod.deadline.data
        # SHT sensor options
        if form_mod.sht_voltage.data:
            mod_input.sht_voltage = form_mod.sht_voltage.data

        channels = InputChannel.query.filter(
            InputChannel.input_id == form_mod.input_id.data)

        # Add or delete channels for variable measurement Inputs
        if ('measurements_variable_amount' in dict_inputs[mod_input.device] and
                dict_inputs[mod_input.device]['measurements_variable_amount']):
            measurements = DeviceMeasurements.query.filter(
                DeviceMeasurements.device_id == form_mod.input_id.data)

            if measurements.count() != form_mod.num_channels.data:
                # Delete measurements/channels
                if form_mod.num_channels.data < measurements.count():
                    for index, each_channel in enumerate(measurements.all()):
                        if index + 1 >= measurements.count():
                            delete_entry_with_id(DeviceMeasurements,
                                                 each_channel.unique_id)

                    if ('channel_quantity_same_as_measurements' in dict_inputs[mod_input.device] and
                            dict_inputs[mod_input.device]["channel_quantity_same_as_measurements"]):
                        if form_mod.num_channels.data < channels.count():
                            for index, each_channel in enumerate(channels.all()):
                                if index + 1 >= channels.count():
                                    delete_entry_with_id(InputChannel,
                                                         each_channel.unique_id)

                # Add measurements/channels
                elif form_mod.num_channels.data > measurements.count():
                    start_number = measurements.count()
                    for index in range(start_number, form_mod.num_channels.data):
                        new_measurement = DeviceMeasurements()
                        new_measurement.name = ""
                        new_measurement.device_id = mod_input.unique_id
                        new_measurement.measurement = ""
                        new_measurement.unit = ""
                        new_measurement.channel = index
                        new_measurement.save()

                        if ('channel_quantity_same_as_measurements' in dict_inputs[mod_input.device] and
                                dict_inputs[mod_input.device]["channel_quantity_same_as_measurements"]):
                            new_channel = InputChannel()
                            new_channel.name = ""
                            new_channel.input_id = mod_input.unique_id
                            new_channel.channel = index

                            error, custom_options = custom_channel_options_return_json(
                                error, dict_inputs, request_form,
                                mod_input.unique_id, index,
                                device=mod_input.device, use_defaults=True)
                            new_channel.custom_options = custom_options

                            new_channel.save()

        # Parse pre-save custom options for output device and its channels
        try:
            custom_options_dict_presave = json.loads(mod_input.custom_options)
        except:
            logger.error("Malformed JSON")
            custom_options_dict_presave = {}

        custom_options_channels_dict_presave = {}
        for each_channel in channels.all():
            if each_channel.custom_options and each_channel.custom_options != "{}":
                custom_options_channels_dict_presave[each_channel.channel] = json.loads(
                    each_channel.custom_options)
            else:
                custom_options_channels_dict_presave[each_channel.channel] = {}

        # Parse post-save custom options for output device and its channels
        error, custom_options_json_postsave = custom_options_return_json(
            error, dict_inputs, request_form, device=mod_input.device)
        custom_options_dict_postsave = json.loads(custom_options_json_postsave)

        custom_options_channels_dict_postsave = {}
        for each_channel in channels.all():
            error, custom_options_channels_json_postsave_tmp = custom_channel_options_return_json(
                error, dict_inputs, request_form,
                form_mod.input_id.data, each_channel.channel,
                device=mod_input.device, use_defaults=True)
            custom_options_channels_dict_postsave[each_channel.channel] = json.loads(
                custom_options_channels_json_postsave_tmp)

        if 'execute_at_modification' in dict_inputs[mod_input.device]:
            # pass custom options to module prior to saving to database
            (allow_saving,
             mod_output,
             custom_options_dict,
             custom_options_channels_dict) = dict_inputs[mod_input.device]['execute_at_modification'](
                mod_input,
                request_form,
                custom_options_dict_presave,
                custom_options_channels_dict_presave,
                custom_options_dict_postsave,
                custom_options_channels_dict_postsave)
            custom_options = json.dumps(custom_options_dict)  # Convert from dict to JSON string
            custom_channel_options = custom_options_channels_dict
            if not allow_saving:
                error.append("execute_at_modification() would not allow input options to be saved")
        else:
            # Don't pass custom options to module
            custom_options = json.dumps(custom_options_dict_postsave)
            custom_channel_options = custom_options_channels_dict_postsave

        # Finally, save custom options for both output and channels
        mod_input.custom_options = custom_options
        for each_channel in channels:
            if 'name' in custom_channel_options[each_channel.channel]:
                each_channel.name = custom_channel_options[each_channel.channel]['name']
            each_channel.custom_options = json.dumps(custom_channel_options[each_channel.channel])

        if not error:
            db.session.commit()

    except Exception as except_msg:
        error.append(except_msg)

    flash_success_errors(error, action, url_for('routes_page.page_input'))
Ejemplo n.º 32
0
def input_activate(form_mod):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['activate']['title'],
        controller=TRANSLATIONS['input']['title'])
    error = []

    dict_inputs = parse_input_information()
    input_id = form_mod.input_id.data
    input_dev = Input.query.filter(Input.unique_id == input_id).first()
    device_measurements = DeviceMeasurements.query.filter(
        DeviceMeasurements.device_id == input_dev.unique_id)

    custom_options_values_inputs = parse_custom_option_values(
        input_dev, dict_controller=dict_inputs)

    #
    # General Input checks
    #
    if not input_dev.period:
        error.append("Period must be set")

    if (input_dev.pre_output_id and
            len(input_dev.pre_output_id) > 1 and
            not input_dev.pre_output_duration):
        error.append("Pre Output Duration must be > 0 if Pre Output is enabled")

    if not device_measurements.filter(DeviceMeasurements.is_enabled.is_(True)).count():
        error.append("At least one measurement must be enabled")

    #
    # Check if required custom options are set
    #
    if 'custom_options' in dict_inputs[input_dev.device]:
        for each_option in dict_inputs[input_dev.device]['custom_options']:
            if each_option['id'] not in custom_options_values_inputs[input_dev.unique_id]:
                if 'required' in each_option and each_option['required']:
                    error.append("{} not found and is required to be set. "
                                 "Set option and save Input.".format(
                        each_option['name']))
            else:
                value = custom_options_values_inputs[input_dev.unique_id][each_option['id']]
                if ('required' in each_option and
                        each_option['required'] and
                        not value):
                    error.append("{} is required to be set".format(
                        each_option['name']))

    #
    # Input-specific checks
    #
    if input_dev.device == 'LinuxCommand' and not input_dev.cmd_command:
        error.append("Cannot activate Command Input without a Command set")

    elif ('measurements_variable_amount' in dict_inputs[input_dev.device] and
            dict_inputs[input_dev.device]['measurements_variable_amount']):
        measure_set = True
        for each_channel in device_measurements.all():
            if (not each_channel.name or
                    not each_channel.measurement or
                    not each_channel.unit):
                measure_set = False
        if not measure_set:
            error.append("All measurements must have a name and unit/measurement set")

    if not error:
        controller_activate_deactivate('activate', 'Input',  input_id)
    flash_success_errors(error, action, url_for('routes_page.page_input'))
Ejemplo n.º 33
0
def dashboard_mod(form_base, form_object, request_form):
    """Modify the settings of an item on the dashboard"""
    action = '{action} {controller}'.format(action=gettext("Modify"),
                                            controller=gettext("Dashboard"))
    error = []

    mod_graph = Dashboard.query.filter(
        Dashboard.unique_id == form_base.dashboard_id.data).first()
    mod_graph.name = form_base.name.data

    # Graph Mod
    if form_base.dashboard_type.data == 'graph':

        error = graph_error_check(form_object, error)

        # Generate color option string from form inputs
        sorted_colors_string, error = custom_colors_graph_str(
            request_form, error)
        mod_graph.custom_colors = sorted_colors_string
        mod_graph.use_custom_colors = form_object.use_custom_colors.data

        # Generate y-axis option string from form inputs
        yaxes_string = custom_yaxes_str_from_form(request_form)
        mod_graph.custom_yaxes = yaxes_string
        mod_graph.enable_manual_y_axis = form_object.enable_manual_y_axis.data
        mod_graph.enable_align_ticks = form_object.enable_align_ticks.data
        mod_graph.enable_start_on_tick = form_object.enable_start_on_tick.data
        mod_graph.enable_end_on_tick = form_object.enable_end_on_tick.data

        if form_object.math_ids.data:
            math_ids_joined = ";".join(form_object.math_ids.data)
            mod_graph.math_ids = math_ids_joined
        else:
            mod_graph.math_ids = ''

        if form_object.pid_ids.data:
            pid_ids_joined = ";".join(form_object.pid_ids.data)
            mod_graph.pid_ids = pid_ids_joined
        else:
            mod_graph.pid_ids = ''

        if form_object.output_ids.data:
            output_ids_joined = ";".join(form_object.output_ids.data)
            mod_graph.output_ids = output_ids_joined
        else:
            mod_graph.output_ids = ''

        if form_object.input_ids.data:
            input_ids_joined = ";".join(form_object.input_ids.data)
            mod_graph.input_ids_measurements = input_ids_joined
        else:
            mod_graph.input_ids_measurements = ''

        mod_graph.width = form_base.width.data
        mod_graph.height = form_base.height.data
        mod_graph.x_axis_duration = form_object.xaxis_duration.data
        mod_graph.refresh_duration = form_base.refresh_duration.data
        mod_graph.enable_auto_refresh = form_object.enable_auto_refresh.data
        mod_graph.enable_xaxis_reset = form_object.enable_xaxis_reset.data
        mod_graph.enable_title = form_object.enable_title.data
        mod_graph.enable_navbar = form_object.enable_navbar.data
        mod_graph.enable_export = form_object.enable_export.data
        mod_graph.enable_rangeselect = form_object.enable_range.data
        mod_graph.enable_graph_shift = form_object.enable_graph_shift.data

    # If a gauge type is changed, the color format must change
    elif (form_base.dashboard_type.data == 'gauge'
          and mod_graph.graph_type != form_object.gauge_type.data):

        mod_graph.graph_type = form_object.gauge_type.data
        if form_object.gauge_type.data == 'gauge_solid':
            mod_graph.range_colors = '0.2,#33CCFF;0.4,#55BF3B;0.6,#DDDF0D;0.8,#DF5353'
        elif form_object.gauge_type.data == 'gauge_angular':
            mod_graph.range_colors = '0,25,#33CCFF;25,50,#55BF3B;50,75,#DDDF0D;75,100,#DF5353'

    # Gauge Mod
    elif form_base.dashboard_type.data == 'gauge':

        error = gauge_error_check(form_object, error)

        # Generate color option string from form inputs
        sorted_colors_string, error = custom_colors_gauge_str(
            request_form, form_object.gauge_type.data, error)

        mod_graph.range_colors = sorted_colors_string
        mod_graph.width = form_base.width.data
        mod_graph.height = form_base.height.data
        mod_graph.refresh_duration = form_base.refresh_duration.data
        mod_graph.y_axis_min = form_object.y_axis_min.data
        mod_graph.y_axis_max = form_object.y_axis_max.data
        mod_graph.max_measure_age = form_object.max_measure_age.data
        mod_graph.enable_timestamp = form_object.enable_timestamp.data
        if form_object.input_ids.data:
            mod_graph.input_ids_measurements = form_object.input_ids.data
        else:
            error.append("A valid Measurement must be selected")

    # Measurement Mod
    elif form_base.dashboard_type.data == 'measurement':

        error = measurement_error_check(form_object, error)
        mod_graph.width = form_base.width.data
        mod_graph.height = form_base.height.data
        mod_graph.refresh_duration = form_base.refresh_duration.data
        mod_graph.max_measure_age = form_object.max_measure_age.data
        mod_graph.font_em_value = form_object.font_em_value.data
        mod_graph.font_em_timestamp = form_object.font_em_timestamp.data
        mod_graph.decimal_places = form_object.decimal_places.data
        if form_object.measurement_id.data:
            mod_graph.input_ids_measurements = form_object.measurement_id.data

    # Output Mod
    elif form_base.dashboard_type.data == 'output':

        error = output_error_check(form_object, error)
        mod_graph.width = form_base.width.data
        mod_graph.height = form_base.height.data
        mod_graph.refresh_duration = form_base.refresh_duration.data
        mod_graph.max_measure_age = form_object.max_measure_age.data
        mod_graph.font_em_value = form_object.font_em_value.data
        mod_graph.font_em_timestamp = form_object.font_em_timestamp.data
        mod_graph.decimal_places = form_object.decimal_places.data
        mod_graph.enable_output_controls = form_object.enable_output_controls.data
        if form_object.output_id.data:
            mod_graph.output_ids = form_object.output_id.data

    # PID Control Mod
    elif form_base.dashboard_type.data == 'pid_control':

        error = pid_error_check(form_object, error)
        mod_graph.width = form_base.width.data
        mod_graph.height = form_base.height.data
        mod_graph.refresh_duration = form_base.refresh_duration.data
        mod_graph.max_measure_age = form_object.max_measure_age.data
        mod_graph.font_em_value = form_object.font_em_value.data
        mod_graph.font_em_timestamp = form_object.font_em_timestamp.data
        mod_graph.decimal_places = form_object.decimal_places.data
        mod_graph.show_pid_info = form_object.show_pid_info.data
        mod_graph.show_set_setpoint = form_object.show_set_setpoint.data
        if form_object.pid_id.data:
            mod_graph.pid_ids = form_object.pid_id.data

    # Camera Mod
    elif form_base.dashboard_type.data == 'camera':
        mod_graph.width = form_base.width.data
        mod_graph.height = form_base.height.data
        mod_graph.refresh_duration = form_base.refresh_duration.data
        mod_graph.camera_max_age = form_object.camera_max_age.data
        mod_graph.camera_id = form_object.camera_id.data
        mod_graph.camera_image_type = form_object.camera_image_type.data

    else:
        flash_form_errors(form_base)

    if not error:
        try:
            db.session.commit()
        except sqlalchemy.exc.OperationalError as except_msg:
            error.append(except_msg)
        except sqlalchemy.exc.IntegrityError as except_msg:
            error.append(except_msg)

    flash_success_errors(error, action, url_for('routes_page.page_dashboard'))
Ejemplo n.º 34
0
def output_mod(form_output):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['modify']['title'],
        controller=TRANSLATIONS['output']['title'])
    error = []

    try:
        mod_output = Output.query.filter(
            Output.unique_id == form_output.output_id.data).first()
        mod_output.name = form_output.name.data
        mod_output.amps = form_output.amps.data

        if form_output.trigger_functions_at_start.data:
            mod_output.trigger_functions_at_start = form_output.trigger_functions_at_start.data

        if mod_output.output_type == 'wired':
            if not is_int(form_output.gpio_location.data):
                error.append("BCM GPIO Pin must be an integer")
            mod_output.pin = form_output.gpio_location.data
            mod_output.trigger = bool(int(form_output.trigger.data))
        elif mod_output.output_type == 'wireless_rpi_rf':
            if not is_int(form_output.gpio_location.data):
                error.append("Pin must be an integer")
            if not is_int(form_output.protocol.data):
                error.append("Protocol must be an integer")
            if not is_int(form_output.pulse_length.data):
                error.append("Pulse Length must be an integer")
            if not is_int(form_output.on_command.data):
                error.append("On Command must be an integer")
            if not is_int(form_output.off_command.data):
                error.append("Off Command must be an integer")
            mod_output.pin = form_output.gpio_location.data
            mod_output.protocol = form_output.protocol.data
            mod_output.pulse_length = form_output.pulse_length.data
            mod_output.on_command = form_output.on_command.data
            mod_output.off_command = form_output.off_command.data
        elif mod_output.output_type in ['command', 'python']:
            mod_output.on_command = form_output.on_command.data
            mod_output.off_command = form_output.off_command.data
        elif mod_output.output_type in ['command_pwm', 'python_pwm']:
            mod_output.pwm_command = form_output.pwm_command.data
            mod_output.pwm_invert_signal = form_output.pwm_invert_signal.data
        elif mod_output.output_type == 'pwm':
            mod_output.pin = form_output.gpio_location.data
            mod_output.pwm_hertz = form_output.pwm_hertz.data
            mod_output.pwm_library = form_output.pwm_library.data
            mod_output.pwm_invert_signal = form_output.pwm_invert_signal.data
        elif mod_output.output_type.startswith('atlas_ezo_pmp'):
            mod_output.location = form_output.location.data
            if form_output.flow_rate.data > 105 or form_output.flow_rate.data < 0.5:
                error.append("Flow Rate must be between 0.5 and 105 ml/min")
            else:
                mod_output.flow_rate = form_output.flow_rate.data
            if form_output.i2c_bus.data:
                mod_output.i2c_bus = form_output.i2c_bus.data
            if form_output.baud_rate.data:
                mod_output.baud_rate = form_output.baud_rate.data

        if (form_output.on_at_start.data == '-1'
                or mod_output.output_type in ['pwm', 'command_pwm']):
            mod_output.on_at_start = None
        elif form_output.on_at_start.data is not None:
            try:
                mod_output.on_at_start = bool(int(
                    form_output.on_at_start.data))
            except Exception:
                logger.error(
                    "Error: Could not handle form_output.on_at_start.data: "
                    "{}".format(form_output.on_at_start.data))

        if not error:
            db.session.commit()
            manipulate_output('Modify', form_output.output_id.data)
    except Exception as except_msg:
        error.append(except_msg)
    flash_success_errors(error, action, url_for('routes_page.page_output'))
Ejemplo n.º 35
0
def pid_mod(form_mod_pid_base, form_mod_pid_pwm_raise, form_mod_pid_pwm_lower,
            form_mod_pid_output_raise, form_mod_pid_output_lower,
            form_mod_pid_value_raise, form_mod_pid_value_lower,
            form_mod_pid_volume_raise, form_mod_pid_volume_lower):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['modify']['title'],
        controller=TRANSLATIONS['pid']['title'])
    error = []

    dict_outputs = parse_output_information()

    if not form_mod_pid_base.validate():
        error.append(TRANSLATIONS['error']['title'])
        flash_form_errors(form_mod_pid_base)

    mod_pid = PID.query.filter(
        PID.unique_id == form_mod_pid_base.function_id.data).first()

    mod_pid.name = form_mod_pid_base.name.data
    mod_pid.measurement = form_mod_pid_base.measurement.data
    mod_pid.direction = form_mod_pid_base.direction.data
    mod_pid.period = form_mod_pid_base.period.data
    mod_pid.log_level_debug = form_mod_pid_base.log_level_debug.data
    mod_pid.start_offset = form_mod_pid_base.start_offset.data
    mod_pid.max_measure_age = form_mod_pid_base.max_measure_age.data
    mod_pid.setpoint = form_mod_pid_base.setpoint.data
    mod_pid.band = abs(form_mod_pid_base.band.data)
    mod_pid.store_lower_as_negative = form_mod_pid_base.store_lower_as_negative.data
    mod_pid.p = form_mod_pid_base.k_p.data
    mod_pid.i = form_mod_pid_base.k_i.data
    mod_pid.d = form_mod_pid_base.k_d.data
    mod_pid.integrator_min = form_mod_pid_base.integrator_max.data
    mod_pid.integrator_max = form_mod_pid_base.integrator_min.data
    mod_pid.setpoint_tracking_type = form_mod_pid_base.setpoint_tracking_type.data

    if form_mod_pid_base.setpoint_tracking_type.data == 'method':
        mod_pid.setpoint_tracking_id = form_mod_pid_base.setpoint_tracking_method_id.data
    elif form_mod_pid_base.setpoint_tracking_type.data == 'input-math':
        mod_pid.setpoint_tracking_id = form_mod_pid_base.setpoint_tracking_input_math_id.data
        if form_mod_pid_base.setpoint_tracking_max_age.data:
            mod_pid.setpoint_tracking_max_age = form_mod_pid_base.setpoint_tracking_max_age.data
        else:
            mod_pid.setpoint_tracking_max_age = 120
    else:
        mod_pid.setpoint_tracking_id = ''

    # Change measurement information
    if ',' in form_mod_pid_base.measurement.data:
        measurement_id = form_mod_pid_base.measurement.data.split(',')[1]
        selected_measurement = get_measurement(measurement_id)

        measurements = DeviceMeasurements.query.filter(
            DeviceMeasurements.device_id ==
            form_mod_pid_base.function_id.data).all()
        for each_measurement in measurements:
            # Only set channels 0, 1, 2
            if each_measurement.channel in [0, 1, 2]:
                each_measurement.measurement = selected_measurement.measurement
                each_measurement.unit = selected_measurement.unit

        #
        # Handle Raise Output Settings
        #
        if form_mod_pid_base.raise_output_id.data:
            output_id = form_mod_pid_base.raise_output_id.data.split(",")[0]
            channel_id = form_mod_pid_base.raise_output_id.data.split(",")[1]
            raise_output_type = Output.query.filter(
                Output.unique_id == output_id).first().output_type

            def default_raise_output_settings(mod):
                if mod.raise_output_type == 'on_off':
                    mod.raise_min_duration = 0
                    mod.raise_max_duration = 0
                    mod.raise_min_off_duration = 0
                elif mod.raise_output_type == 'pwm':
                    mod.raise_min_duration = 2
                    mod.raise_max_duration = 98
                elif mod.raise_output_type == 'value':
                    mod.raise_min_duration = 0
                    mod.raise_max_duration = 0
                elif mod.raise_output_type == 'volume':
                    mod.raise_min_duration = 0
                    mod.raise_max_duration = 0
                return mod

            raise_output_id_changed = False
            if mod_pid.raise_output_id != form_mod_pid_base.raise_output_id.data:
                mod_pid.raise_output_id = form_mod_pid_base.raise_output_id.data
                raise_output_id_changed = True

            # Output ID changed
            if ('output_types' in dict_outputs[raise_output_type]
                    and mod_pid.raise_output_id and raise_output_id_changed):

                if len(dict_outputs[raise_output_type]['output_types']) == 1:
                    mod_pid.raise_output_type = dict_outputs[
                        raise_output_type]['output_types'][0]
                else:
                    mod_pid.raise_output_type = None

                mod_pid = default_raise_output_settings(mod_pid)

            # Output ID unchanged
            elif ('output_types' in dict_outputs[raise_output_type]
                  and mod_pid.raise_output_id and not raise_output_id_changed):

                if (not mod_pid.raise_output_type or mod_pid.raise_output_type
                        != form_mod_pid_base.raise_output_type.data):
                    if len(dict_outputs[raise_output_type]
                           ['output_types']) > 1:
                        mod_pid.raise_output_type = form_mod_pid_base.raise_output_type.data
                    mod_pid = default_raise_output_settings(mod_pid)
                elif mod_pid.raise_output_type == 'on_off':
                    if not form_mod_pid_output_raise.validate():
                        error.append(TRANSLATIONS['error']['title'])
                        flash_form_errors(form_mod_pid_output_raise)
                    else:
                        mod_pid.raise_min_duration = form_mod_pid_output_raise.raise_min_duration.data
                        mod_pid.raise_max_duration = form_mod_pid_output_raise.raise_max_duration.data
                        mod_pid.raise_min_off_duration = form_mod_pid_output_raise.raise_min_off_duration.data
                elif mod_pid.raise_output_type == 'pwm':
                    if not form_mod_pid_pwm_raise.validate():
                        error.append(TRANSLATIONS['error']['title'])
                        flash_form_errors(form_mod_pid_pwm_raise)
                    else:
                        mod_pid.raise_min_duration = form_mod_pid_pwm_raise.raise_min_duty_cycle.data
                        mod_pid.raise_max_duration = form_mod_pid_pwm_raise.raise_max_duty_cycle.data
                        mod_pid.raise_always_min_pwm = form_mod_pid_pwm_raise.raise_always_min_pwm.data
                elif mod_pid.raise_output_type == 'value':
                    if not form_mod_pid_value_raise.validate():
                        error.append(TRANSLATIONS['error']['title'])
                        flash_form_errors(form_mod_pid_value_raise)
                    else:
                        mod_pid.raise_min_duration = form_mod_pid_value_raise.raise_min_amount.data
                        mod_pid.raise_max_duration = form_mod_pid_value_raise.raise_max_amount.data
                elif mod_pid.raise_output_type == 'volume':
                    if not form_mod_pid_volume_raise.validate():
                        error.append(TRANSLATIONS['error']['title'])
                        flash_form_errors(form_mod_pid_volume_raise)
                    else:
                        mod_pid.raise_min_duration = form_mod_pid_volume_raise.raise_min_amount.data
                        mod_pid.raise_max_duration = form_mod_pid_volume_raise.raise_max_amount.data
        else:
            mod_pid.raise_output_id = None

        #
        # Handle Lower Output Settings
        #
        if form_mod_pid_base.lower_output_id.data:
            output_id = form_mod_pid_base.lower_output_id.data.split(",")[0]
            channel_id = form_mod_pid_base.lower_output_id.data.split(",")[1]
            lower_output_type = Output.query.filter(
                Output.unique_id == output_id).first().output_type

            def default_lower_output_settings(mod):
                if mod.lower_output_type == 'on_off':
                    mod.lower_min_duration = 0
                    mod.lower_max_duration = 0
                    mod.lower_min_off_duration = 0
                elif mod.lower_output_type == 'pwm':
                    mod.lower_min_duration = 2
                    mod.lower_max_duration = 98
                elif mod.lower_output_type == 'value':
                    mod.lower_min_duration = 0
                    mod.lower_max_duration = 0
                elif mod.lower_output_type == 'volume':
                    mod.lower_min_duration = 0
                    mod.lower_max_duration = 0
                return mod

            lower_output_id_changed = False
            if mod_pid.lower_output_id != form_mod_pid_base.lower_output_id.data:
                mod_pid.lower_output_id = form_mod_pid_base.lower_output_id.data
                lower_output_id_changed = True

            # Output ID changed
            if ('output_types' in dict_outputs[lower_output_type]
                    and mod_pid.lower_output_id and lower_output_id_changed):

                if len(dict_outputs[lower_output_type]['output_types']) == 1:
                    mod_pid.lower_output_type = dict_outputs[
                        lower_output_type]['output_types'][0]
                else:
                    mod_pid.lower_output_type = None

                mod_pid = default_lower_output_settings(mod_pid)

            # Output ID unchanged
            elif ('output_types' in dict_outputs[lower_output_type]
                  and mod_pid.lower_output_id and not lower_output_id_changed):

                if (not mod_pid.lower_output_type or mod_pid.lower_output_type
                        != form_mod_pid_base.lower_output_type.data):
                    if len(dict_outputs[lower_output_type]
                           ['output_types']) > 1:
                        mod_pid.lower_output_type = form_mod_pid_base.lower_output_type.data
                    mod_pid = default_lower_output_settings(mod_pid)
                elif mod_pid.lower_output_type == 'on_off':
                    if not form_mod_pid_output_lower.validate():
                        error.append(TRANSLATIONS['error']['title'])
                        flash_form_errors(form_mod_pid_output_lower)
                    else:
                        mod_pid.lower_min_duration = form_mod_pid_output_lower.lower_min_duration.data
                        mod_pid.lower_max_duration = form_mod_pid_output_lower.lower_max_duration.data
                        mod_pid.lower_min_off_duration = form_mod_pid_output_lower.lower_min_off_duration.data
                elif mod_pid.lower_output_type == 'pwm':
                    if not form_mod_pid_pwm_lower.validate():
                        error.append(TRANSLATIONS['error']['title'])
                        flash_form_errors(form_mod_pid_pwm_lower)
                    else:
                        mod_pid.lower_min_duration = form_mod_pid_pwm_lower.lower_min_duty_cycle.data
                        mod_pid.lower_max_duration = form_mod_pid_pwm_lower.lower_max_duty_cycle.data
                        mod_pid.lower_always_min_pwm = form_mod_pid_pwm_lower.lower_always_min_pwm.data
                elif mod_pid.lower_output_type == 'value':
                    if not form_mod_pid_value_lower.validate():
                        error.append(TRANSLATIONS['error']['title'])
                        flash_form_errors(form_mod_pid_value_lower)
                    else:
                        mod_pid.lower_min_duration = form_mod_pid_value_lower.lower_min_amount.data
                        mod_pid.lower_max_duration = form_mod_pid_value_lower.lower_max_amount.data
                elif mod_pid.lower_output_type == 'volume':
                    if not form_mod_pid_volume_lower.validate():
                        error.append(TRANSLATIONS['error']['title'])
                        flash_form_errors(form_mod_pid_volume_lower)
                    else:
                        mod_pid.lower_min_duration = form_mod_pid_volume_lower.lower_min_amount.data
                        mod_pid.lower_max_duration = form_mod_pid_volume_lower.lower_max_amount.data
        else:
            mod_pid.lower_output_id = None

    if (mod_pid.raise_output_id and mod_pid.lower_output_id
            and mod_pid.raise_output_id == mod_pid.lower_output_id):
        error.append(gettext("Raise and lower outputs cannot be the same"))

    try:
        if not error:
            db.session.commit()
            # If the controller is active or paused, refresh variables in thread
            if mod_pid.is_activated:
                control = DaemonControl()
                return_value = control.pid_mod(
                    form_mod_pid_base.function_id.data)
                flash(
                    "PID Controller settings refresh response: "
                    "{resp}".format(resp=return_value), "success")
    except Exception as except_msg:
        error.append(except_msg)
    flash_success_errors(error, action, url_for('routes_page.page_function'))
Ejemplo n.º 36
0
def measurement_mod(form, return_url):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['modify']['title'],
        controller=TRANSLATIONS['measurement']['title'])
    error = []

    mod_device = None
    device_info = None

    try:
        mod_meas = DeviceMeasurements.query.filter(
            DeviceMeasurements.unique_id == form.measurement_id.data).first()

        controller_type = determine_controller_type(mod_meas.device_id)

        if controller_type == "Input":
            mod_device = Input.query.filter(Input.unique_id == mod_meas.device_id).first()
            device_info = parse_input_information()
        elif controller_type == "Function":
            mod_device = CustomController.query.filter(CustomController.unique_id == mod_meas.device_id).first()
            device_info = parse_function_information()

        if not mod_device or not device_info:
            logger.error("Could not find mod_device or device_info")
            return

        if mod_device.is_activated:
            error.append(gettext(
                "Deactivate controller before modifying its settings"))

        mod_meas.name = form.name.data

        if form.device_type.data == 'measurement_select':
            if not form.select_measurement_unit.data:
                error.append("Must select a measurement unit")
            else:
                mod_meas.measurement = form.select_measurement_unit.data.split(',')[0]
                mod_meas.unit = form.select_measurement_unit.data.split(',')[1]

        elif form.device_type.data == 'measurement_convert':
            if ('enable_channel_unit_select' in device_info[mod_device.device] and
                    device_info[mod_device.device]['enable_channel_unit_select']):
                if ',' in form.select_measurement_unit.data:
                    mod_meas.measurement = form.select_measurement_unit.data.split(',')[0]
                    mod_meas.unit = form.select_measurement_unit.data.split(',')[1]
                else:
                    mod_meas.measurement = ''
                    mod_meas.unit = ''

            if form.rescaled_measurement_unit.data != '' and ',' in form.rescaled_measurement_unit.data:
                mod_meas.rescaled_measurement = form.rescaled_measurement_unit.data.split(',')[0]
                mod_meas.rescaled_unit = form.rescaled_measurement_unit.data.split(',')[1]
            elif form.rescaled_measurement_unit.data == '':
                mod_meas.rescaled_measurement = ''
                mod_meas.rescaled_unit = ''

            mod_meas.scale_from_min = form.scale_from_min.data
            mod_meas.scale_from_max = form.scale_from_max.data
            mod_meas.scale_to_min = form.scale_to_min.data
            mod_meas.scale_to_max = form.scale_to_max.data
            mod_meas.invert_scale = form.invert_scale.data
            mod_meas.conversion_id = form.convert_to_measurement_unit.data

        if not error:
            db.session.commit()

    except Exception as except_msg:
        logger.exception(1)
        error.append(except_msg)

    flash_success_errors(error, action, return_url)
Ejemplo n.º 37
0
def widget_mod(form_base, request_form):
    """Modify the settings of an item on the dashboard"""
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['modify']['title'],
        controller=TRANSLATIONS['widget']['title'])
    error = []

    dict_widgets = parse_widget_information()

    mod_widget = Widget.query.filter(
        Widget.unique_id == form_base.widget_id.data).first()
    mod_widget.name = form_base.name.data
    mod_widget.font_em_name = form_base.font_em_name.data
    mod_widget.enable_drag_handle = form_base.enable_drag_handle.data
    mod_widget.refresh_duration = form_base.refresh_duration.data

    try:
        custom_options_json_presave = json.loads(mod_widget.custom_options)
    except:
        logger.error("Malformed JSON")
        custom_options_json_presave = {}

    # Generate string to save from custom options
    error, custom_options_json_postsave = custom_options_return_json(
        error,
        dict_widgets,
        request_form,
        mod_dev=mod_widget,
        device=mod_widget.graph_type)

    if 'execute_at_modification' in dict_widgets[mod_widget.graph_type]:
        (allow_saving, page_refresh, mod_widget, custom_options
         ) = dict_widgets[mod_widget.graph_type]['execute_at_modification'](
             mod_widget, request_form, custom_options_json_presave,
             json.loads(custom_options_json_postsave))
        custom_options = json.dumps(
            custom_options)  # Convert from dict to JSON string
        if not allow_saving:
            error.append(
                "execute_at_modification() would not allow widget options to be saved"
            )
    else:
        custom_options = custom_options_json_postsave

    mod_widget.custom_options = custom_options

    if not error:
        try:
            db.session.commit()
        except sqlalchemy.exc.OperationalError as except_msg:
            error.append(except_msg)
        except sqlalchemy.exc.IntegrityError as except_msg:
            error.append(except_msg)

        control = DaemonControl()
        control.widget_add_refresh(mod_widget.unique_id)

    flash_success_errors(
        error, action,
        url_for('routes_dashboard.page_dashboard',
                dashboard_id=form_base.dashboard_id.data))
Ejemplo n.º 38
0
def conditional_action_mod(form):
    """Modify a Conditional Action"""
    error = []
    action = '{action} {controller}'.format(
        action=gettext("Mod"),
        controller=gettext("Conditional"))

    error = check_form_actions(form, error)

    try:
        mod_action = ConditionalActions.query.filter(
            ConditionalActions.id == form.conditional_action_id.data).first()

        if mod_action.do_action == 'output':
            mod_action.do_relay_id = form.do_relay_id.data
            mod_action.do_relay_state = form.do_relay_state.data
            mod_action.do_relay_duration = form.do_relay_duration.data

        elif mod_action.do_action in ['activate_pid',
                                      'deactivate_pid',
                                      'resume_pid',
                                      'pause_pid'                                      ]:
            mod_action.do_pid_id = form.do_pid_id.data

        elif mod_action.do_action == 'email':
            mod_action.do_action_string = form.do_action_string.data

        elif mod_action.do_action in ['photo_email',
                                      'video_email']:
            mod_action.do_action_string = form.do_action_string.data
            mod_action.do_camera_id = form.do_camera_id.data

        elif mod_action.do_action in ['flash_lcd',
                                      'flash_lcd_on',
                                      'flash_lcd_off',
                                      'lcd_backlight_off',
                                      'lcd_backlight_on']:
            mod_action.do_lcd_id = form.do_lcd_id.data

        elif mod_action.do_action == 'photo':
            mod_action.do_camera_id = form.do_camera_id.data

        elif mod_action.do_action == 'video':
            mod_action.do_camera_id = form.do_camera_id.data
            mod_action.do_camera_duration = form.do_camera_duration.data

        elif mod_action.do_action == 'command':
            mod_action.do_action_string = form.do_action_string.data

        if not error:
            db.session.commit()
            check_refresh_conditional(form.conditional_id.data)

    except sqlalchemy.exc.OperationalError as except_msg:
        error.append(except_msg)
    except sqlalchemy.exc.IntegrityError as except_msg:
        error.append(except_msg)
    except Exception as except_msg:
        error.append(except_msg)

    flash_success_errors(error, action, url_for('routes_page.page_function'))
Ejemplo n.º 39
0
def function_add(form_add_func):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['add']['title'],
        controller=TRANSLATIONS['function']['title'])
    error = []

    function_name = form_add_func.function_type.data

    dict_controllers = parse_controller_information()

    if current_app.config['TESTING']:
        dep_unmet = False
    else:
        dep_unmet, _ = return_dependencies(function_name)
        if dep_unmet:
            list_unmet_deps = []
            for each_dep in dep_unmet:
                list_unmet_deps.append(each_dep[0])
            error.append(
                "The {dev} device you're trying to add has unmet "
                "dependencies: {dep}".format(
                    dev=function_name, dep=', '.join(list_unmet_deps)))

    new_func = None

    try:
        if function_name.startswith('conditional_'):
            new_func = Conditional()
            new_func.conditional_statement = '''
# Example code for learning how to use a Conditional. See the manual for more information.

self.logger.info("This INFO log entry will appear in the Daemon Log")
self.logger.error("This ERROR log entry will appear in the Daemon Log")

# Replace "asdf1234" with a Condition ID
measurement = self.condition("{asdf1234}")
self.logger.info("Check this measurement in the Daemon Log. The value is {val}".format(val=measurement))

if measurement is not None:  # If a measurement exists
    self.message += "This message appears in email alerts and notes.\\n"

    if measurement < 23:  # If the measurement is less than 23
        self.message += "Measurement is too Low! Measurement is {meas}\\n".format(meas=measurement)
        self.run_all_actions(message=self.message)  # Run all actions sequentially

    elif measurement > 27:  # Else If the measurement is greater than 27
        self.message += "Measurement is too High! Measurement is {meas}\\n".format(meas=measurement)
        # Replace "qwer5678" with an Action ID
        self.run_action("{qwer5678}", message=self.message)  # Run a single specific Action'''

            if not error:
                new_func.save()
                save_conditional_code(
                    error,
                    new_func.conditional_statement,
                    new_func.unique_id,
                    test=False)

        elif function_name.startswith('pid_'):
            new_func = PID().save()

            for each_channel, measure_info in PID_INFO['measure'].items():
                new_measurement = DeviceMeasurements()

                if 'name' in measure_info:
                    new_measurement.name = measure_info['name']
                if 'measurement_type' in measure_info:
                    new_measurement.measurement_type = measure_info['measurement_type']

                new_measurement.device_id = new_func.unique_id
                new_measurement.measurement = measure_info['measurement']
                new_measurement.unit = measure_info['unit']
                new_measurement.channel = each_channel
                if not error:
                    new_measurement.save()

        elif function_name.startswith('trigger_'):
            new_func = Trigger()
            new_func.name = '{}'.format(FUNCTION_INFO[function_name]['name'])
            new_func.trigger_type = function_name
            if not error:
                new_func.save()

        elif function_name.startswith('function_'):
            new_func = Function()
            if function_name == 'function_spacer':
                new_func.name = 'Spacer'
            new_func.function_type = function_name
            if not error:
                new_func.save()

        elif function_name in dict_controllers:
            new_func = CustomController()
            new_func.device = function_name

            if 'controller_name' in dict_controllers[function_name]:
                new_func.name = dict_controllers[function_name]['controller_name']
            else:
                new_func.name = 'Controller Name'

            list_options = []
            if 'custom_options' in dict_controllers[function_name]:
                for each_option in dict_controllers[function_name]['custom_options']:
                    if each_option['default_value'] is False:
                        default_value = ''
                    else:
                        default_value = each_option['default_value']
                    option = '{id},{value}'.format(
                        id=each_option['id'],
                        value=default_value)
                    list_options.append(option)
            new_func.custom_options = ';'.join(list_options)
            if not error:
                new_func.save()

        elif function_name == '':
            error.append("Must select a function type")
        else:
            error.append("Unknown function type: '{}'".format(
                function_name))

        if not error:
            display_order = csv_to_list_of_str(
                DisplayOrder.query.first().function)
            DisplayOrder.query.first().function = add_display_order(
                display_order, new_func.unique_id)
            db.session.commit()

    except sqlalchemy.exc.OperationalError as except_msg:
        error.append(except_msg)
    except sqlalchemy.exc.IntegrityError as except_msg:
        error.append(except_msg)
    except Exception as except_msg:
        error.append(except_msg)

    flash_success_errors(error, action, url_for('routes_page.page_function'))

    if dep_unmet:
        return 1
Ejemplo n.º 40
0
def lcd_add(form):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['add']['title'],
        controller=TRANSLATIONS['lcd']['title'])
    error = []

    if current_app.config['TESTING']:
        dep_unmet = False
    else:
        dep_unmet, _ = return_dependencies(form.lcd_type.data.split(",")[0])
        if dep_unmet:
            list_unmet_deps = []
            for each_dep in dep_unmet:
                list_unmet_deps.append(each_dep[0])
            error.append(
                "The {dev} device you're trying to add has unmet "
                "dependencies: {dep}".format(
                    dev=form.lcd_type.data, dep=', '.join(list_unmet_deps)))

    try:
        new_lcd = LCD()
        new_lcd_data = LCDData()

        try:
            from RPi import GPIO
            if GPIO.RPI_REVISION == 2 or GPIO.RPI_REVISION == 3:
                new_lcd.i2c_bus = 1
            else:
                new_lcd.i2c_bus = 0
        except:
            logger.error("RPi.GPIO and Raspberry Pi required for this action")

        lcd_id = form.lcd_type.data.split(",")[0]
        lcd_interface = form.lcd_type.data.split(",")[1]

        new_lcd.lcd_type = lcd_id
        new_lcd.interface = lcd_interface
        new_lcd.name = str(LCD_INFO[lcd_id]['name'])

        if (lcd_interface == 'I2C' and lcd_id in [
                '128x32_pioled',
                '128x64_pioled',
                '128x32_pioled_circuit_python',
                '128x64_pioled_circuit_python']):
            new_lcd.location = '0x3c'
            new_lcd.pin_reset = 19
        elif lcd_interface == 'I2C' and lcd_id in ['16x2_generic', '20x4_generic']:
            new_lcd.location = '0x27'
        elif lcd_interface == 'I2C' and lcd_id == '16x2_grove_lcd_rgb':
            new_lcd.location = '0x3e'
            new_lcd.location_backlight = '0x62'
        elif lcd_interface == 'SPI':
            new_lcd.pin_reset = 19
            new_lcd.pin_dc = 16
            new_lcd.pin_cs = 17
            new_lcd.spi_device = 0
            new_lcd.spi_bus = 0

        if lcd_id in ['28x32_pioled', '128x32_pioled_circuit_python']:
            new_lcd.x_characters = 21
            new_lcd.y_lines = 4
        elif lcd_id in ['128x64_pioled', '128x64_pioled_circuit_python']:
            new_lcd.x_characters = 21
            new_lcd.y_lines = 8
        elif lcd_id == '16x2_generic':
            new_lcd.x_characters = 16
            new_lcd.y_lines = 2
        elif lcd_id == '20x4_generic':
            new_lcd.x_characters = 20
            new_lcd.y_lines = 4
        elif lcd_id == '16x2_grove_lcd_rgb':
            new_lcd.x_characters = 16
            new_lcd.y_lines = 2

        if not error:
            new_lcd.save()
            new_lcd_data.lcd_id = new_lcd.unique_id
            new_lcd_data.save()
            display_order = csv_to_list_of_str(DisplayOrder.query.first().lcd)
            DisplayOrder.query.first().lcd = add_display_order(
                display_order, new_lcd.unique_id)
            db.session.commit()
    except sqlalchemy.exc.OperationalError as except_msg:
        error.append(except_msg)
    except sqlalchemy.exc.IntegrityError as except_msg:
        error.append(except_msg)
    flash_success_errors(error, action, url_for('routes_page.page_lcd'))

    if dep_unmet:
        return 1
Ejemplo n.º 41
0
def widget_mod(form_base, form_object, request_form):
    """Modify the settings of an item on the dashboard"""
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['modify']['title'],
        controller=TRANSLATIONS['widget']['title'])
    error = []

    mod_widget = Widget.query.filter(
        Widget.unique_id == form_base.widget_id.data).first()
    mod_widget.name = form_base.name.data
    mod_widget.font_em_name = form_base.font_em_name.data
    mod_widget.enable_drag_handle = form_base.enable_drag_handle.data

    # Graph Mod
    if form_base.widget_type.data == 'graph':

        error = graph_error_check(form_object, error)

        # Generate color option string from form inputs
        sorted_colors_string, error = custom_colors_graph_str(
            request_form, error)
        mod_widget.custom_colors = sorted_colors_string
        disable_data_grouping_string, error = data_grouping_graph_str(
            request_form, error)
        mod_widget.disable_data_grouping = disable_data_grouping_string
        mod_widget.use_custom_colors = form_object.use_custom_colors.data

        # Generate y-axis option string from form inputs
        yaxes_string = custom_yaxes_str_from_form(request_form)
        mod_widget.custom_yaxes = yaxes_string
        mod_widget.enable_manual_y_axis = form_object.enable_manual_y_axis.data
        mod_widget.enable_align_ticks = form_object.enable_align_ticks.data
        mod_widget.enable_start_on_tick = form_object.enable_start_on_tick.data
        mod_widget.enable_end_on_tick = form_object.enable_end_on_tick.data

        if form_object.math_ids.data:
            mod_widget.math_ids = ";".join(form_object.math_ids.data)
        else:
            mod_widget.math_ids = ''

        if form_object.pid_ids.data:
            mod_widget.pid_ids = ";".join(form_object.pid_ids.data)
        else:
            mod_widget.pid_ids = ''

        if form_object.output_ids.data:
            mod_widget.output_ids = ";".join(form_object.output_ids.data)
        else:
            mod_widget.output_ids = ''

        if form_object.input_ids.data:
            mod_widget.input_ids_measurements = ";".join(
                form_object.input_ids.data)
        else:
            mod_widget.input_ids_measurements = ''

        if form_object.note_tag_ids.data:
            mod_widget.note_tag_ids = ";".join(form_object.note_tag_ids.data)
        else:
            mod_widget.note_tag_ids = ''

        mod_widget.refresh_duration = form_base.refresh_duration.data
        mod_widget.enable_header_buttons = form_object.enable_header_buttons.data
        mod_widget.x_axis_duration = form_object.xaxis_duration.data
        mod_widget.enable_auto_refresh = form_object.enable_auto_refresh.data
        mod_widget.enable_xaxis_reset = form_object.enable_xaxis_reset.data
        mod_widget.enable_title = form_object.enable_title.data
        mod_widget.enable_navbar = form_object.enable_navbar.data
        mod_widget.enable_export = form_object.enable_export.data
        mod_widget.enable_rangeselect = form_object.enable_rangeselect.data
        mod_widget.enable_graph_shift = form_object.enable_graph_shift.data

    # If a gauge type is changed, the color format must change
    elif (form_base.widget_type.data == 'gauge'
          and mod_widget.graph_type != form_object.gauge_type.data):

        mod_widget.graph_type = form_object.gauge_type.data
        mod_widget.range_colors = gauge_reformat_stops(
            form_object.gauge_type.data,
            4,
            form_object.stops.data,
            current_colors=None)
        mod_widget.stops = form_object.stops.data

    # Gauge Mod
    elif form_base.widget_type.data == 'gauge':

        error = gauge_error_check(form_object, error)

        # Generate color option string from form inputs
        sorted_colors_string, error = custom_colors_gauge_str(
            request_form, form_object.gauge_type.data, error)

        mod_widget.refresh_duration = form_base.refresh_duration.data
        mod_widget.range_colors = sorted_colors_string
        mod_widget.y_axis_min = form_object.y_axis_min.data
        mod_widget.y_axis_max = form_object.y_axis_max.data
        mod_widget.max_measure_age = form_object.max_measure_age.data
        mod_widget.enable_timestamp = form_object.enable_timestamp.data
        mod_widget.range_colors = gauge_reformat_stops(
            form_object.gauge_type.data,
            mod_widget.stops,
            form_object.stops.data,
            current_colors=mod_widget.range_colors)
        mod_widget.stops = form_object.stops.data

        if form_object.input_ids.data:
            mod_widget.input_ids_measurements = form_object.input_ids.data
        else:
            error.append("A valid Measurement must be selected")

    # Indicator Mod
    elif form_base.widget_type.data == 'indicator':

        error = indicator_error_check(form_object, error)

        mod_widget.refresh_duration = form_base.refresh_duration.data
        mod_widget.max_measure_age = form_object.max_measure_age.data
        mod_widget.font_em_timestamp = form_object.font_em_timestamp.data
        mod_widget.option_invert = form_object.option_invert.data
        mod_widget.enable_timestamp = form_object.enable_timestamp.data
        if form_object.measurement_id.data:
            mod_widget.input_ids_measurements = form_object.measurement_id.data

    # Measurement Mod
    elif form_base.widget_type.data == 'measurement':

        error = measurement_error_check(form_object, error)

        mod_widget.refresh_duration = form_base.refresh_duration.data
        mod_widget.max_measure_age = form_object.max_measure_age.data
        mod_widget.font_em_value = form_object.font_em_value.data
        mod_widget.font_em_timestamp = form_object.font_em_timestamp.data
        mod_widget.decimal_places = form_object.decimal_places.data
        mod_widget.enable_name = form_object.enable_name.data
        mod_widget.enable_unit = form_object.enable_unit.data
        mod_widget.enable_measurement = form_object.enable_measurement.data
        mod_widget.enable_channel = form_object.enable_channel.data
        mod_widget.enable_timestamp = form_object.enable_timestamp.data
        if form_object.measurement_id.data:
            mod_widget.input_ids_measurements = form_object.measurement_id.data

    # Output Mod
    elif form_base.widget_type.data in ['output', 'output_pwm_slider']:

        error = output_error_check(form_object, error)

        mod_widget.refresh_duration = form_base.refresh_duration.data
        mod_widget.max_measure_age = form_object.max_measure_age.data
        mod_widget.font_em_value = form_object.font_em_value.data
        mod_widget.font_em_timestamp = form_object.font_em_timestamp.data
        mod_widget.decimal_places = form_object.decimal_places.data
        mod_widget.enable_output_controls = form_object.enable_output_controls.data
        mod_widget.enable_status = form_object.enable_status.data
        mod_widget.enable_value = form_object.enable_value.data
        mod_widget.enable_unit = form_object.enable_unit.data
        mod_widget.enable_timestamp = form_object.enable_timestamp.data
        if form_object.output_id.data:
            mod_widget.output_ids = form_object.output_id.data

    # PID Control Mod
    elif form_base.widget_type.data == 'pid_control':

        error = pid_error_check(form_object, error)

        mod_widget.refresh_duration = form_base.refresh_duration.data
        mod_widget.max_measure_age = form_object.max_measure_age.data
        mod_widget.font_em_value = form_object.font_em_value.data
        mod_widget.font_em_timestamp = form_object.font_em_timestamp.data
        mod_widget.decimal_places = form_object.decimal_places.data
        mod_widget.enable_status = form_object.enable_status.data
        mod_widget.enable_timestamp = form_object.enable_timestamp.data
        mod_widget.show_pid_info = form_object.show_pid_info.data
        mod_widget.show_set_setpoint = form_object.show_set_setpoint.data
        if form_object.pid_id.data:
            mod_widget.pid_ids = form_object.pid_id.data

    # Camera Mod
    elif form_base.widget_type.data == 'camera':

        mod_widget.refresh_duration = form_base.refresh_duration.data
        mod_widget.camera_max_age = form_object.camera_max_age.data
        mod_widget.camera_id = form_object.camera_id.data
        mod_widget.camera_image_type = form_object.camera_image_type.data

    else:
        flash_form_errors(form_base)

    if not error:
        try:
            db.session.commit()
        except sqlalchemy.exc.OperationalError as except_msg:
            error.append(except_msg)
        except sqlalchemy.exc.IntegrityError as except_msg:
            error.append(except_msg)

    flash_success_errors(
        error, action,
        url_for('routes_page.page_dashboard',
                dashboard_id=form_base.dashboard_id.data))
Ejemplo n.º 42
0
def widget_add(form_base, form_object):
    """Add a widget to the dashboard"""
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['add']['title'],
        controller=TRANSLATIONS['widget']['title'])
    error = []

    new_widget = Widget()
    new_widget.dashboard_id = form_base.dashboard_id.data
    new_widget.name = form_base.name.data
    new_widget.font_em_name = form_base.font_em_name.data
    new_widget.enable_drag_handle = form_base.enable_drag_handle.data

    # Find where the next widget should be placed on the grid
    # Finds the lowest position to create as the new Widget's starting position
    position_y_start = 0
    for each_widget in Widget.query.filter(
            Widget.dashboard_id == form_base.dashboard_id.data).all():
        highest_position = each_widget.position_y + each_widget.height
        if highest_position > position_y_start:
            position_y_start = highest_position
    new_widget.position_y = position_y_start

    # Spacer
    if form_base.widget_type.data == 'spacer':

        widget_type = 'Spacer'

        new_widget.graph_type = form_base.widget_type.data

        new_widget.width = 20
        new_widget.height = 1

    # Graph
    elif (form_base.widget_type.data == 'graph'
          and (form_base.name.data and form_object.xaxis_duration.data
               and form_base.refresh_duration.data)):

        widget_type = 'Graph'

        error = graph_error_check(form_object, error)

        new_widget.graph_type = form_base.widget_type.data
        if form_object.math_ids.data:
            new_widget.math_ids = ";".join(form_object.math_ids.data)
        if form_object.pid_ids.data:
            new_widget.pid_ids = ";".join(form_object.pid_ids.data)
        if form_object.output_ids.data:
            new_widget.output_ids = ";".join(form_object.output_ids.data)
        if form_object.input_ids.data:
            new_widget.input_ids_measurements = ";".join(
                form_object.input_ids.data)
        if form_object.note_tag_ids.data:
            new_widget.note_tag_ids = ";".join(form_object.note_tag_ids.data)

        new_widget.refresh_duration = form_base.refresh_duration.data
        new_widget.enable_header_buttons = form_object.enable_header_buttons.data
        new_widget.x_axis_duration = form_object.xaxis_duration.data
        new_widget.enable_auto_refresh = form_object.enable_auto_refresh.data
        new_widget.enable_xaxis_reset = form_object.enable_xaxis_reset.data
        new_widget.enable_title = form_object.enable_title.data
        new_widget.enable_navbar = form_object.enable_navbar.data
        new_widget.enable_rangeselect = form_object.enable_rangeselect.data
        new_widget.enable_export = form_object.enable_export.data
        new_widget.enable_graph_shift = form_object.enable_graph_shift.data
        new_widget.enable_manual_y_axis = form_object.enable_manual_y_axis.data

        new_widget.width = 20
        new_widget.height = 9

    # Gauge
    elif form_base.widget_type.data == 'gauge':

        widget_type = 'Gauge'

        error = gauge_error_check(form_object, error)

        new_widget.graph_type = form_object.gauge_type.data
        new_widget.refresh_duration = form_base.refresh_duration.data
        new_widget.max_measure_age = form_object.max_measure_age.data
        new_widget.y_axis_min = form_object.y_axis_min.data
        new_widget.y_axis_max = form_object.y_axis_max.data
        new_widget.input_ids_measurements = form_object.input_ids.data
        new_widget.enable_timestamp = form_object.enable_timestamp.data
        new_widget.stops = form_object.stops.data
        new_widget.width = 4

        if form_object.gauge_type.data == 'gauge_solid':
            new_widget.height = 4
        elif form_object.gauge_type.data == 'gauge_angular':
            new_widget.height = 5

        if form_object.stops.data < 2:
            error.append("Must be at least 2 stops")
        else:
            new_widget.range_colors = gauge_reformat_stops(
                form_object.gauge_type.data,
                4,
                new_widget.stops,
                current_colors=None)

    # Indicator
    elif form_base.widget_type.data == 'indicator':

        widget_type = 'Indicator'

        error = measurement_error_check(form_object, error)

        new_widget.graph_type = 'indicator'
        new_widget.refresh_duration = form_base.refresh_duration.data
        new_widget.max_measure_age = form_object.max_measure_age.data
        new_widget.font_em_timestamp = form_object.font_em_timestamp.data
        new_widget.input_ids_measurements = form_object.measurement_id.data
        new_widget.enable_timestamp = form_object.enable_timestamp.data

        new_widget.width = 3
        new_widget.height = 4

    # Measurement
    elif form_base.widget_type.data == 'measurement':

        widget_type = 'Measurement'

        error = measurement_error_check(form_object, error)

        new_widget.graph_type = 'measurement'
        new_widget.max_measure_age = form_object.max_measure_age.data
        new_widget.refresh_duration = form_base.refresh_duration.data
        new_widget.font_em_value = form_object.font_em_value.data
        new_widget.font_em_timestamp = form_object.font_em_timestamp.data
        new_widget.decimal_places = form_object.decimal_places.data
        new_widget.input_ids_measurements = form_object.measurement_id.data
        new_widget.enable_name = form_object.enable_name.data
        new_widget.enable_unit = form_object.enable_unit.data
        new_widget.enable_measurement = form_object.enable_measurement.data
        new_widget.enable_channel = form_object.enable_channel.data
        new_widget.enable_timestamp = form_object.enable_timestamp.data

        new_widget.width = 4
        new_widget.height = 5

    # Output
    elif form_base.widget_type.data == 'output':

        widget_type = 'Output'

        error = output_error_check(form_object, error)

        new_widget.graph_type = 'output'
        new_widget.max_measure_age = form_object.max_measure_age.data
        new_widget.refresh_duration = form_base.refresh_duration.data
        new_widget.font_em_value = form_object.font_em_value.data
        new_widget.font_em_timestamp = form_object.font_em_timestamp.data
        new_widget.enable_output_controls = form_object.enable_output_controls.data
        new_widget.decimal_places = form_object.decimal_places.data
        new_widget.output_ids = form_object.output_id.data
        new_widget.enable_status = form_object.enable_status.data
        new_widget.enable_value = form_object.enable_value.data
        new_widget.enable_unit = form_object.enable_unit.data
        new_widget.enable_timestamp = form_object.enable_timestamp.data

        new_widget.width = 5
        new_widget.height = 4

    # Output Range Slider
    elif form_base.widget_type.data == 'output_pwm_slider':

        widget_type = 'Output Range Slider'

        error = output_error_check(form_object, error)

        new_widget.graph_type = 'output_pwm_slider'
        new_widget.max_measure_age = form_object.max_measure_age.data
        new_widget.refresh_duration = form_base.refresh_duration.data
        new_widget.font_em_value = form_object.font_em_value.data
        new_widget.font_em_timestamp = form_object.font_em_timestamp.data
        new_widget.enable_output_controls = form_object.enable_output_controls.data
        new_widget.decimal_places = form_object.decimal_places.data
        new_widget.output_ids = form_object.output_id.data
        new_widget.enable_status = form_object.enable_status.data
        new_widget.enable_value = form_object.enable_value.data
        new_widget.enable_unit = form_object.enable_unit.data
        new_widget.enable_timestamp = form_object.enable_timestamp.data

        new_widget.width = 5
        new_widget.height = 4

    # PID Control
    elif form_base.widget_type.data == 'pid_control':

        widget_type = 'PID Control'

        error = pid_error_check(form_object, error)

        new_widget.graph_type = 'pid_control'
        new_widget.max_measure_age = form_object.max_measure_age.data
        new_widget.refresh_duration = form_base.refresh_duration.data
        new_widget.font_em_value = form_object.font_em_value.data
        new_widget.font_em_timestamp = form_object.font_em_timestamp.data
        new_widget.decimal_places = form_object.decimal_places.data
        new_widget.show_pid_info = form_object.show_pid_info.data
        new_widget.enable_status = form_object.enable_status.data
        new_widget.enable_timestamp = form_object.enable_timestamp.data
        new_widget.show_set_setpoint = form_object.show_set_setpoint.data
        new_widget.pid_ids = form_object.pid_id.data

        new_widget.width = 6
        new_widget.height = 5

    # Camera
    elif form_base.widget_type.data == 'camera':

        widget_type = 'Camera'

        camera = Camera.query.filter(
            Camera.unique_id == form_object.camera_id.data).first()
        if not camera:
            error.append("Invalid Camera ID.")
        elif (form_object.camera_image_type.data == 'stream'
              and camera.library not in ['opencv', 'picamera']):
            error.append("Only cameras that use the 'picamera' or "
                         "'opencv' library may be used for streaming")

        new_widget.graph_type = form_base.widget_type.data
        new_widget.refresh_duration = form_base.refresh_duration.data
        new_widget.camera_max_age = form_object.camera_max_age.data
        new_widget.camera_id = form_object.camera_id.data
        new_widget.camera_image_type = form_object.camera_image_type.data

        new_widget.width = 7
        new_widget.height = 8

    else:
        flash_form_errors(form_base)
        return

    try:
        if not error:
            new_widget.save()
            flash(
                gettext("{dev} with ID %(id)s successfully added".format(
                    dev=widget_type),
                        id=new_widget.id), "success")
    except sqlalchemy.exc.OperationalError as except_msg:
        error.append(except_msg)
    except sqlalchemy.exc.IntegrityError as except_msg:
        error.append(except_msg)

    flash_success_errors(
        error, action,
        url_for('routes_page.page_dashboard',
                dashboard_id=form_base.dashboard_id.data))
Ejemplo n.º 43
0
def camera_mod(form_camera):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['modify']['title'],
        controller=TRANSLATIONS['camera']['title'])
    error = []

    try:
        if (Camera.query.filter(
                Camera.unique_id != form_camera.camera_id.data).filter(
                    Camera.name == form_camera.name.data).count()):
            flash("You must choose a unique name", "error")
            return redirect(url_for('routes_settings.settings_camera'))
        if 0 > form_camera.rotation.data > 360:
            flash("Rotation must be between 0 and 360 degrees", "error")
            return redirect(url_for('routes_settings.settings_camera'))

        mod_camera = Camera.query.filter(
            Camera.unique_id == form_camera.camera_id.data).first()
        mod_camera.name = form_camera.name.data

        mod_camera.width = form_camera.width.data
        mod_camera.height = form_camera.height.data
        mod_camera.hflip = form_camera.hflip.data
        mod_camera.vflip = form_camera.vflip.data
        mod_camera.rotation = form_camera.rotation.data
        mod_camera.brightness = form_camera.brightness.data
        mod_camera.hide_still = form_camera.hide_still.data
        mod_camera.hide_timelapse = form_camera.hide_timelapse.data
        mod_camera.path_still = form_camera.path_still.data
        mod_camera.path_timelapse = form_camera.path_timelapse.data
        mod_camera.path_video = form_camera.path_video.data

        if form_camera.stream_fps.data:
            if form_camera.stream_fps.data < 1:
                error.append("Stream FPS cannot be less than 1")
            mod_camera.stream_fps = form_camera.stream_fps.data

        if mod_camera.library == 'fswebcam':
            mod_camera.device = form_camera.device.data
            mod_camera.custom_options = form_camera.custom_options.data
        if mod_camera.library == 'raspistill':
            mod_camera.brightness = form_camera.brightness.data
            mod_camera.contrast = form_camera.contrast.data
            mod_camera.saturation = form_camera.saturation.data
            mod_camera.picamera_sharpness = form_camera.picamera_sharpness.data
            mod_camera.picamera_iso = int(form_camera.picamera_iso.data)
            mod_camera.picamera_awb = form_camera.picamera_awb.data
            mod_camera.custom_options = form_camera.custom_options.data
        elif mod_camera.library == 'picamera':
            mod_camera.resolution_stream_width = form_camera.resolution_stream_width.data
            mod_camera.resolution_stream_height = form_camera.resolution_stream_height.data
            mod_camera.contrast = form_camera.contrast.data
            mod_camera.exposure = form_camera.exposure.data
            mod_camera.saturation = form_camera.saturation.data
            mod_camera.picamera_shutter_speed = form_camera.picamera_shutter_speed.data
            mod_camera.picamera_sharpness = form_camera.picamera_sharpness.data
            mod_camera.picamera_iso = int(form_camera.picamera_iso.data)
            mod_camera.picamera_awb = form_camera.picamera_awb.data
            mod_camera.picamera_awb_gain_red = form_camera.picamera_awb_gain_red.data
            mod_camera.picamera_awb_gain_blue = form_camera.picamera_awb_gain_blue.data
            mod_camera.picamera_exposure_mode = form_camera.picamera_exposure_mode.data
            mod_camera.picamera_meter_mode = form_camera.picamera_meter_mode.data
            mod_camera.picamera_image_effect = form_camera.picamera_image_effect.data
        elif mod_camera.library == 'opencv':
            mod_camera.opencv_device = form_camera.opencv_device.data
            mod_camera.resolution_stream_width = form_camera.resolution_stream_width.data
            mod_camera.resolution_stream_height = form_camera.resolution_stream_height.data
            mod_camera.hflip = form_camera.hflip.data
            mod_camera.vflip = form_camera.vflip.data
            mod_camera.rotation = form_camera.rotation.data
            mod_camera.height = form_camera.height.data
            mod_camera.width = form_camera.width.data
            mod_camera.brightness = form_camera.brightness.data
            mod_camera.contrast = form_camera.contrast.data
            mod_camera.exposure = form_camera.exposure.data
            mod_camera.gain = form_camera.gain.data
            mod_camera.hue = form_camera.hue.data
            mod_camera.saturation = form_camera.saturation.data
            mod_camera.white_balance = form_camera.white_balance.data
        elif mod_camera.library == 'http_address':
            mod_camera.url_still = form_camera.url_still.data
            mod_camera.url_stream = form_camera.url_stream.data
        elif mod_camera.library == 'http_address_requests':
            mod_camera.url_still = form_camera.url_still.data
            mod_camera.url_stream = form_camera.url_stream.data
        else:
            error.append("Unknown camera library")

        if form_camera.output_id.data:
            mod_camera.output_id = form_camera.output_id.data
        else:
            mod_camera.output_id = None
        mod_camera.output_duration = form_camera.output_duration.data
        mod_camera.cmd_pre_camera = form_camera.cmd_pre_camera.data
        mod_camera.cmd_post_camera = form_camera.cmd_post_camera.data

        if not error:
            db.session.commit()
            control = DaemonControl()
            control.refresh_daemon_camera_settings()
    except Exception as except_msg:
        logger.exception(1)
        error.append(except_msg)

    flash_success_errors(error, action, url_for('routes_page.page_camera'))
Ejemplo n.º 44
0
def trigger_mod(form):
    """Modify a Trigger"""
    error = []
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['modify']['title'],
        controller=TRANSLATIONS['trigger']['title'])

    try:
        trigger = Trigger.query.filter(
            Trigger.unique_id == form.function_id.data).first()
        trigger.name = form.name.data

        if trigger.trigger_type == 'trigger_edge':
            error = check_form_edge(form, error)
            trigger.measurement = form.measurement.data
            trigger.edge_detected = form.edge_detected.data

        elif trigger.trigger_type == 'trigger_output':
            error = check_form_output(form, error)
            trigger.unique_id_1 = form.unique_id_1.data
            trigger.output_state = form.output_state.data
            trigger.output_duration = form.output_duration.data

        elif trigger.trigger_type == 'trigger_output_duration':
            error = check_form_output_duration(form, error)
            trigger.unique_id_1 = form.unique_id_1.data
            trigger.output_state = form.output_state.data
            trigger.output_duration = form.output_duration.data

        elif trigger.trigger_type == 'trigger_output_pwm':
            error = check_form_output_pwm(form, error)
            trigger.unique_id_1 = form.unique_id_1.data
            trigger.output_state = form.output_state.data
            trigger.output_duty_cycle = form.output_duty_cycle.data

        elif trigger.trigger_type == 'trigger_run_pwm_method':
            error = check_form_run_pwm_method(form, error)
            trigger.unique_id_1 = form.unique_id_1.data
            trigger.unique_id_2 = form.unique_id_2.data
            trigger.period = form.period.data
            trigger.trigger_actions_at_start = form.trigger_actions_at_start.data
            trigger.trigger_actions_at_period = form.trigger_actions_at_period.data

        elif trigger.trigger_type == 'trigger_sunrise_sunset':
            error = check_form_sunrise_sunset(form, error)
            trigger.rise_or_set = form.rise_or_set.data
            trigger.latitude = form.latitude.data
            trigger.longitude = form.longitude.data
            trigger.zenith = form.zenith.data
            trigger.date_offset_days = form.date_offset_days.data
            trigger.time_offset_minutes = form.time_offset_minutes.data

        elif trigger.trigger_type == 'trigger_timer_daily_time_point':
            error = check_form_timer_daily_time_point(form, error)
            trigger.timer_start_time = form.timer_start_time.data

        elif trigger.trigger_type == 'trigger_timer_daily_time_span':
            error = check_form_timer_daily_time_span(form, error)
            trigger.period = form.period.data
            trigger.timer_start_time = form.timer_start_time.data
            trigger.timer_end_time = form.timer_end_time.data

        elif trigger.trigger_type == 'trigger_timer_duration':
            error = check_form_timer_duration(form, error)
            trigger.period = form.period.data
            trigger.timer_start_offset = form.timer_start_offset.data

        if not error:
            db.session.commit()

            if trigger.is_activated:
                control = DaemonControl()
                return_value = control.refresh_daemon_trigger_settings(
                    form.function_id.data)
                flash(gettext("Daemon response: %(resp)s", resp=return_value),
                      "success")

    except sqlalchemy.exc.OperationalError as except_msg:
        error.append(except_msg)
    except sqlalchemy.exc.IntegrityError as except_msg:
        error.append(except_msg)
    except Exception as except_msg:
        error.append(except_msg)

    flash_success_errors(error, action, url_for('routes_page.page_function'))
Ejemplo n.º 45
0
def controller_mod(form_mod, request_form):
    """Modify a Custom Function"""
    error = []
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['modify']['title'],
        controller=TRANSLATIONS['controller']['title'])

    dict_controllers = parse_function_information()

    try:
        mod_controller = CustomController.query.filter(
            CustomController.unique_id == form_mod.function_id.data).first()

        if mod_controller.is_activated:
            error.append(
                gettext("Deactivate controller before modifying its settings"))

        mod_controller.name = form_mod.name.data
        mod_controller.log_level_debug = form_mod.log_level_debug.data

        # Enable/disable Channels
        measurements = DeviceMeasurements.query.filter(
            DeviceMeasurements.device_id == form_mod.function_id.data).all()
        if form_mod.measurements_enabled.data:
            for each_measurement in measurements:
                if each_measurement.unique_id in form_mod.measurements_enabled.data:
                    each_measurement.is_enabled = True
                else:
                    each_measurement.is_enabled = False

        channels = FunctionChannel.query.filter(
            FunctionChannel.function_id == form_mod.function_id.data)

        # Add or delete channels for variable measurement Inputs
        if ('measurements_variable_amount'
                in dict_controllers[mod_controller.device]
                and dict_controllers[
                    mod_controller.device]['measurements_variable_amount']):

            measurements = DeviceMeasurements.query.filter(
                DeviceMeasurements.device_id == form_mod.function_id.data)

            if measurements.count() != form_mod.num_channels.data:
                # Delete measurements/channels
                if form_mod.num_channels.data < measurements.count():
                    for index, each_channel in enumerate(measurements.all()):
                        if index + 1 >= measurements.count():
                            delete_entry_with_id(DeviceMeasurements,
                                                 each_channel.unique_id)

                    if ('channel_quantity_same_as_measurements'
                            in dict_controllers[mod_controller.device]
                            and dict_controllers[mod_controller.device]
                        ["channel_quantity_same_as_measurements"]):
                        if form_mod.num_channels.data < channels.count():
                            for index, each_channel in enumerate(
                                    channels.all()):
                                if index + 1 >= channels.count():
                                    delete_entry_with_id(
                                        FunctionChannel,
                                        each_channel.unique_id)

                # Add measurements/channels
                elif form_mod.num_channels.data > measurements.count():
                    start_number = measurements.count()
                    for index in range(start_number,
                                       form_mod.num_channels.data):
                        new_measurement = DeviceMeasurements()
                        new_measurement.name = ""
                        new_measurement.device_id = mod_controller.unique_id
                        new_measurement.measurement = ""
                        new_measurement.unit = ""
                        new_measurement.channel = index
                        new_measurement.save()

                        if ('channel_quantity_same_as_measurements'
                                in dict_controllers[mod_controller.device]
                                and dict_controllers[mod_controller.device]
                            ["channel_quantity_same_as_measurements"]):
                            new_channel = FunctionChannel()
                            new_channel.name = ""
                            new_channel.function_id = mod_controller.unique_id
                            new_measurement.channel = index

                            error, custom_options = custom_channel_options_return_json(
                                error,
                                dict_controllers,
                                request_form,
                                mod_controller.unique_id,
                                index,
                                device=mod_controller.device,
                                use_defaults=True)
                            new_channel.custom_options = custom_options

                            new_channel.save()

        # Generate string to save from custom options
        error, custom_options = custom_options_return_json(
            error,
            dict_controllers,
            request_form=request_form,
            device=mod_controller.device,
            use_defaults=True)
        mod_controller.custom_options = custom_options

        if not error:
            db.session.commit()

    except sqlalchemy.exc.OperationalError as except_msg:
        error.append(except_msg)
    except sqlalchemy.exc.IntegrityError as except_msg:
        error.append(except_msg)
    except Exception as except_msg:
        error.append(except_msg)

    flash_success_errors(error, action, url_for('routes_page.page_function'))
Ejemplo n.º 46
0
def method_add(form_add_method):
    """ Add line to method_data table """
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['add']['title'],
        controller=TRANSLATIONS['method']['title'])
    error = []

    start_time = None
    end_time = None

    method = Method.query.filter(
        Method.unique_id == form_add_method.method_id.data).first()
    display_order = csv_to_list_of_str(method.method_order)

    try:
        if validate_method_data(form_add_method, method):
            return 1

        if method.method_type == 'DailySine':
            add_method_data = MethodData.query.filter(
                MethodData.method_id == form_add_method.method_id.data).first()
            add_method_data.amplitude = form_add_method.amplitude.data
            add_method_data.frequency = form_add_method.frequency.data
            add_method_data.shift_angle = form_add_method.shift_angle.data
            add_method_data.shift_y = form_add_method.shiftY.data
            db.session.commit()
            return 0

        elif method.method_type == 'DailyBezier':
            if not 0 <= form_add_method.shift_angle.data <= 360:
                flash(gettext("Error: Angle Shift is out of range. It must be "
                              "<= 0 and <= 360."), "error")
                return 1
            if form_add_method.x0.data <= form_add_method.x3.data:
                flash(gettext("Error: X0 must be greater than X3."), "error")
                return 1
            add_method_data = MethodData.query.filter(
                MethodData.method_id == form_add_method.method_id.data).first()
            add_method_data.shift_angle = form_add_method.shift_angle.data
            add_method_data.x0 = form_add_method.x0.data
            add_method_data.y0 = form_add_method.y0.data
            add_method_data.x1 = form_add_method.x1.data
            add_method_data.y1 = form_add_method.y1.data
            add_method_data.x2 = form_add_method.x2.data
            add_method_data.y2 = form_add_method.y2.data
            add_method_data.x3 = form_add_method.x3.data
            add_method_data.y3 = form_add_method.y3.data
            db.session.commit()
            return 0

        if form_add_method.method_select.data == 'setpoint':
            if method.method_type == 'Date':
                start_time = datetime.strptime(
                    form_add_method.time_start.data,
                    '%Y-%m-%d %H:%M:%S')
                end_time = datetime.strptime(
                    form_add_method.time_end.data,
                    '%Y-%m-%d %H:%M:%S')
            elif method.method_type == 'Daily':
                start_time = datetime.strptime(
                    form_add_method.daily_time_start.data,
                    '%H:%M:%S')
                end_time = datetime.strptime(
                    form_add_method.daily_time_end.data,
                    '%H:%M:%S')

            if method.method_type in ['Date', 'Daily']:
                # Check if the start time comes after the last entry's end time
                display_order = csv_to_list_of_str(method.method_order)
                if display_order:
                    last_method = MethodData.query.filter(
                        MethodData.unique_id == display_order[-1]).first()
                else:
                    last_method = None

                if last_method is not None:
                    if method.method_type == 'Date':
                        last_method_end_time = datetime.strptime(
                            last_method.time_end,
                            '%Y-%m-%d %H:%M:%S')
                    elif method.method_type == 'Daily':
                        last_method_end_time = datetime.strptime(
                            last_method.time_end,
                            '%H:%M:%S')
                    else:
                        last_method_end_time = None

                    if (start_time and last_method_end_time and
                            start_time < last_method_end_time):
                        flash(gettext("The new entry start time (%(st)s) "
                                      "cannot overlap the last entry's end "
                                      "time (%(et)s). Note: They may be the "
                                      "same time.",
                                      st=last_method_end_time,
                                      et=start_time),
                              "error")
                        return 1

        elif form_add_method.method_select.data == 'output':
            if method.method_type == 'Date':
                start_time = datetime.strptime(
                    form_add_method.output_time.data,
                    '%Y-%m-%d %H:%M:%S')
            elif method.method_type == 'Daily':
                start_time = datetime.strptime(
                    form_add_method.output_daily_time.data,
                    '%H:%M:%S')

        add_method_data = MethodData()
        add_method_data.method_id = form_add_method.method_id.data

        if method.method_type == 'Date':
            if form_add_method.method_select.data == 'setpoint':
                add_method_data.time_start = start_time.strftime(
                    '%Y-%m-%d %H:%M:%S')
                add_method_data.time_end = end_time.strftime(
                    '%Y-%m-%d %H:%M:%S')
            if form_add_method.method_select.data == 'output':
                add_method_data.time_start = form_add_method.output_time.data
        elif method.method_type == 'Daily':
            if form_add_method.method_select.data == 'setpoint':
                add_method_data.time_start = start_time.strftime('%H:%M:%S')
                add_method_data.time_end = end_time.strftime('%H:%M:%S')
            if form_add_method.method_select.data == 'output':
                add_method_data.time_start = form_add_method.output_daily_time.data
        elif method.method_type == 'Duration':
            if form_add_method.restart.data:
                add_method_data.duration_sec = 0
                add_method_data.duration_end = form_add_method.duration_end.data
            else:
                add_method_data.duration_sec = form_add_method.duration.data

        if form_add_method.method_select.data == 'setpoint':
            add_method_data.setpoint_start = form_add_method.setpoint_start.data
            add_method_data.setpoint_end = form_add_method.setpoint_end.data
        elif form_add_method.method_select.data == 'output':
            add_method_data.output_id = form_add_method.output_id.data
            add_method_data.output_state = form_add_method.output_state.data
            add_method_data.output_duration = form_add_method.output_duration.data

        db.session.add(add_method_data)
        db.session.commit()

        # Add line to method data list if not a output duration
        if form_add_method.method_select.data != 'output':
            method.method_order = add_display_order(
                display_order, add_method_data.unique_id)
            db.session.commit()

        if form_add_method.method_select.data == 'setpoint':
            if method.method_type == 'Date':
                flash(gettext("Added duration to method from %(st)s to "
                              "%(end)s", st=start_time, end=end_time),
                      "success")
            elif method.method_type == 'Daily':
                flash(gettext("Added duration to method from %(st)s to "
                              "%(end)s",
                              st=start_time.strftime('%H:%M:%S'),
                              end=end_time.strftime('%H:%M:%S')),
                      "success")
            elif method.method_type == 'Duration':
                if form_add_method.restart.data:
                    flash(gettext("Added method restart"), "success")
                else:
                    flash(gettext("Added duration to method for %(sec)s seconds",
                                  sec=form_add_method.duration.data), "success")
        elif form_add_method.method_select.data == 'output':
            if method.method_type == 'Date':
                flash(gettext("Added output modulation to method at start "
                              "time: %(tm)s", tm=start_time), "success")
            elif method.method_type == 'Daily':
                flash(gettext("Added output modulation to method at start "
                              "time: %(tm)s",
                              tm=start_time.strftime('%H:%M:%S')), "success")
            elif method.method_type == 'Duration':
                flash(gettext("Added output modulation to method at start "
                              "time: %(tm)s",
                              tm=form_add_method.duration.data), "success")

    except Exception as except_msg:
        logger.exception(1)
        error.append(except_msg)
    flash_success_errors(error, action, url_for('routes_method.method_list'))
Ejemplo n.º 47
0
def output_add(form_add):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['add']['title'],
        controller=TRANSLATIONS['output']['title'])
    error = []

    dep_unmet, _ = return_dependencies(form_add.output_type.data)
    if dep_unmet:
        list_unmet_deps = []
        for each_dep in dep_unmet:
            list_unmet_deps.append(each_dep[0])
        error.append(
            "The {dev} device you're trying to add has unmet dependencies: "
            "{dep}".format(dev=form_add.output_type.data,
                           dep=', '.join(list_unmet_deps)))

    if len(form_add.output_type.data.split(',')) < 2:
        error.append("Must select an Output type")

    if not is_int(form_add.output_quantity.data, check_range=[1, 20]):
        error.append("{error}. {accepted_values}: 1-20".format(
            error=gettext("Invalid quantity"),
            accepted_values=gettext("Acceptable values")))

    if not error:
        for _ in range(0, form_add.output_quantity.data):
            try:
                output_type = form_add.output_type.data.split(',')[0]
                interface = form_add.output_type.data.split(',')[1]

                new_output = Output()
                new_output.name = str(OUTPUT_INFO[output_type]['name'])
                new_output.output_type = output_type
                new_output.interface = interface

                if output_type in [
                        'wired', 'wireless_rpi_rf', 'command', 'python'
                ]:
                    new_output.measurement = 'duration_time'
                    new_output.unit = 's'
                elif output_type in ['command_pwm', 'pwm', 'python_pwm']:
                    new_output.measurement = 'duty_cycle'
                    new_output.unit = 'percent'
                elif output_type == 'atlas_ezo_pmp':
                    new_output.measurement = 'volume'
                    new_output.unit = 'ml'

                new_output.channel = 0

                if output_type == 'wired':
                    new_output.on_at_start = False
                elif output_type == 'wireless_rpi_rf':
                    new_output.pin = None
                    new_output.protocol = 1
                    new_output.pulse_length = 189
                    new_output.on_command = '22559'
                    new_output.off_command = '22558'
                elif output_type == 'command':
                    new_output.on_command = '/home/pi/script_on.sh'
                    new_output.off_command = '/home/pi/script_off.sh'
                elif output_type == 'command_pwm':
                    new_output.pwm_command = '/home/pi/script_pwm.sh ((duty_cycle))'
                elif output_type == 'pwm':
                    new_output.pwm_hertz = 22000
                    new_output.pwm_library = 'pigpio_any'
                elif output_type == 'python':
                    new_output.on_command = """
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
write_string = "{ts}: ID: {id}: ON\\n".format(id=output_id, ts=timestamp)
with open("/home/pi/Mycodo/OutputTest.txt", "a") as myfile:
    myfile.write(write_string)"""
                    new_output.off_command = """
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
write_string = "{ts}: ID: {id}: OFF\\n".format(id=output_id, ts=timestamp)
with open("/home/pi/Mycodo/OutputTest.txt", "a") as myfile:
    myfile.write(write_string)"""
                elif output_type == 'python_pwm':
                    new_output.pwm_command = """
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
write_string = "{ts}: ID: {id}: Duty Cycle: ((duty_cycle)) %\\n".format(
    id=output_id, ts=timestamp)
with open("/home/pi/Mycodo/OutputTest.txt", "a") as myfile:
    myfile.write(write_string)"""
                elif output_type == 'atlas_ezo_pmp':
                    new_output.flow_rate = 10
                    if interface == 'I2C':
                        new_output.location = '0x67'
                        new_output.i2c_bus = 1
                    elif interface == 'UART':
                        new_output.location = '/dev/ttyAMA0'
                        new_output.baud_rate = 9600

                if not error:
                    new_output.save()
                    display_order = csv_to_list_of_str(
                        DisplayOrder.query.first().output)
                    DisplayOrder.query.first().output = add_display_order(
                        display_order, new_output.unique_id)
                    db.session.commit()
                    manipulate_output('Add', new_output.unique_id)
            except sqlalchemy.exc.OperationalError as except_msg:
                error.append(except_msg)
            except sqlalchemy.exc.IntegrityError as except_msg:
                error.append(except_msg)

    flash_success_errors(error, action, url_for('routes_page.page_output'))

    if dep_unmet:
        return 1
Ejemplo n.º 48
0
def method_mod(form_mod_method):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['modify']['title'],
        controller=TRANSLATIONS['method']['title'])
    error = []

    method = Method.query.filter(
        Method.unique_id == form_mod_method.method_id.data).first()
    method_data = MethodData.query.filter(
        MethodData.unique_id == form_mod_method.method_data_id.data).first()
    display_order = csv_to_list_of_str(method.method_order)

    try:
        if form_mod_method.delete.data:
            delete_entry_with_id(MethodData,
                                 form_mod_method.method_data_id.data)
            if form_mod_method.method_select.data != 'output':
                method_order = Method.query.filter(
                    Method.unique_id == method.unique_id).first()
                display_order = csv_to_list_of_str(method_order.method_order)
                display_order.remove(method_data.unique_id)
                method_order.method_order = list_to_csv(display_order)
                db.session.commit()
            return 0

        if form_mod_method.rename.data:
            method.name = form_mod_method.name.data
            db.session.commit()
            return 0

        # Ensure data is valid
        if validate_method_data(form_mod_method, method):
            return 1

        if form_mod_method.method_select.data == 'setpoint':
            if method.method_type == 'Date':
                start_time = datetime.strptime(form_mod_method.time_start.data, '%Y-%m-%d %H:%M:%S')
                end_time = datetime.strptime(form_mod_method.time_end.data, '%Y-%m-%d %H:%M:%S')

                # Ensure the start time comes after the previous entry's end time
                # and the end time comes before the next entry's start time
                # method_id_set is the id given to all method entries, 'method_id', not 'id'
                previous_method = None
                next_method = None
                for index, each_order in enumerate(display_order):
                    if each_order == method_data.unique_id:
                        if len(display_order) > 1 and index > 0:
                            previous_method = MethodData.query.filter(
                                MethodData.unique_id == display_order[index-1]).first()
                        if len(display_order) > index+1:
                            next_method = MethodData.query.filter(
                                MethodData.unique_id == display_order[index+1]).first()

                if previous_method is not None and previous_method.time_end is not None:
                    previous_end_time = datetime.strptime(
                        previous_method.time_end, '%Y-%m-%d %H:%M:%S')
                    if previous_end_time is not None and start_time < previous_end_time:
                        error.append(
                            gettext("The entry start time (%(st)s) cannot "
                                    "overlap the previous entry's end time "
                                    "(%(et)s)",
                                    st=start_time, et=previous_end_time))

                if next_method is not None and next_method.time_start is not None:
                    next_start_time = datetime.strptime(
                        next_method.time_start, '%Y-%m-%d %H:%M:%S')
                    if next_start_time is not None and end_time > next_start_time:
                        error.append(
                            gettext("The entry end time (%(et)s) cannot "
                                    "overlap the next entry's start time "
                                    "(%(st)s)",
                                    et=end_time, st=next_start_time))

                method_data.time_start = start_time.strftime('%Y-%m-%d %H:%M:%S')
                method_data.time_end = end_time.strftime('%Y-%m-%d %H:%M:%S')

            elif method.method_type == 'Duration':
                if method_data.duration_sec == 0:
                    method_data.duration_end = form_mod_method.duration_end.data
                else:
                    method_data.duration_sec = form_mod_method.duration.data

            elif method.method_type == 'Daily':
                method_data.time_start = form_mod_method.daily_time_start.data
                method_data.time_end = form_mod_method.daily_time_end.data

            method_data.setpoint_start = form_mod_method.setpoint_start.data
            method_data.setpoint_end = form_mod_method.setpoint_end.data

        elif form_mod_method.method_select.data == 'output':
            if method.method_type == 'Date':
                method_data.time_start = form_mod_method.output_time.data
            elif method.method_type == 'Duration':
                method_data.duration_sec = form_mod_method.duration.data
            if form_mod_method.output_id.data == '':
                method_data.output_id = None
            else:
                method_data.output_id = form_mod_method.output_id.data
            method_data.output_state = form_mod_method.output_state.data
            method_data.output_duration = form_mod_method.output_duration.data

        elif method.method_type == 'DailySine':
            if form_mod_method.method_select.data == 'output':
                method_data.time_start = form_mod_method.output_time.data
                if form_mod_method.output_id.data == '':
                    method_data.output_id = None
                else:
                    method_data.output_id = form_mod_method.output_id.data
                method_data.output_state = form_mod_method.output_state.data
                method_data.output_duration = form_mod_method.output_duration.data

        if not error:
            db.session.commit()

    except Exception as except_msg:
        logger.exception(1)
        error.append(except_msg)
    flash_success_errors(error, action, url_for('routes_method.method_list'))
Ejemplo n.º 49
0
def dashboard_add(form_base, form_object, display_order):
    """
    Add an item to the dashboard

    Either Graph, Gauge, or Camera
    """
    action = '{action} {controller}'.format(action=gettext("Add"),
                                            controller=gettext("Dashboard"))
    error = []
    dashboard_type = ''

    new_graph = Dashboard()
    new_graph.name = form_base.name.data

    # Graph
    if (form_base.dashboard_type.data == 'graph'
            and (form_base.name.data and form_base.width.data
                 and form_base.height.data and form_object.xaxis_duration.data
                 and form_base.refresh_duration.data)):

        dashboard_type = 'Graph'
        error = graph_error_check(form_object, error)
        new_graph.graph_type = form_base.dashboard_type.data
        if form_object.math_ids.data:
            math_ids_joined = ";".join(form_object.math_ids.data)
            new_graph.math_ids = math_ids_joined
        if form_object.pid_ids.data:
            pid_ids_joined = ";".join(form_object.pid_ids.data)
            new_graph.pid_ids = pid_ids_joined
        if form_object.output_ids.data:
            output_ids_joined = ";".join(form_object.output_ids.data)
            new_graph.output_ids = output_ids_joined
        if form_object.input_ids.data:
            input_ids_joined = ";".join(form_object.input_ids.data)
            new_graph.input_ids_measurements = input_ids_joined
        new_graph.width = form_base.width.data
        new_graph.height = form_base.height.data
        new_graph.x_axis_duration = form_object.xaxis_duration.data
        new_graph.refresh_duration = form_base.refresh_duration.data
        new_graph.enable_auto_refresh = form_object.enable_auto_refresh.data
        new_graph.enable_xaxis_reset = form_object.enable_xaxis_reset.data
        new_graph.enable_title = form_object.enable_title.data
        new_graph.enable_navbar = form_object.enable_navbar.data
        new_graph.enable_rangeselect = form_object.enable_range.data
        new_graph.enable_export = form_object.enable_export.data
        new_graph.enable_graph_shift = form_object.enable_graph_shift.data
        new_graph.enable_manual_y_axis = form_object.enable_manual_y_axis.data

    # Gauge
    elif form_base.dashboard_type.data == 'gauge':

        dashboard_type = 'Gauge'
        error = gauge_error_check(form_object, error)
        new_graph.graph_type = form_object.gauge_type.data
        if form_object.gauge_type.data == 'gauge_solid':
            new_graph.range_colors = '20,#33CCFF;40,#55BF3B;60,#DDDF0D;80,#DF5353'
        elif form_object.gauge_type.data == 'gauge_angular':
            new_graph.range_colors = '0,25,#33CCFF;25,50,#55BF3B;50,75,#DDDF0D;75,100,#DF5353'
        new_graph.width = form_base.width.data
        new_graph.height = form_base.height.data
        new_graph.max_measure_age = form_object.max_measure_age.data
        new_graph.refresh_duration = form_base.refresh_duration.data
        new_graph.y_axis_min = form_object.y_axis_min.data
        new_graph.y_axis_max = form_object.y_axis_max.data
        new_graph.input_ids_measurements = form_object.input_ids.data
        new_graph.enable_timestamp = form_object.enable_timestamp.data

    # Measurement
    elif form_base.dashboard_type.data == 'measurement':

        dashboard_type = 'Measurement'
        error = measurement_error_check(form_object, error)
        new_graph.graph_type = 'measurement'
        new_graph.width = form_base.width.data
        new_graph.height = form_base.height.data
        new_graph.max_measure_age = form_object.max_measure_age.data
        new_graph.refresh_duration = form_base.refresh_duration.data
        new_graph.font_em_value = form_object.font_em_value.data
        new_graph.font_em_timestamp = form_object.font_em_timestamp.data
        new_graph.decimal_places = form_object.decimal_places.data
        new_graph.input_ids_measurements = form_object.measurement_id.data

    # Output
    elif form_base.dashboard_type.data == 'output':

        dashboard_type = 'Output'
        error = output_error_check(form_object, error)
        new_graph.graph_type = 'output'
        new_graph.width = form_base.width.data
        new_graph.height = form_base.height.data
        new_graph.max_measure_age = form_object.max_measure_age.data
        new_graph.refresh_duration = form_base.refresh_duration.data
        new_graph.font_em_value = form_object.font_em_value.data
        new_graph.font_em_timestamp = form_object.font_em_timestamp.data
        new_graph.enable_output_controls = form_object.enable_output_controls.data
        new_graph.decimal_places = form_object.decimal_places.data
        new_graph.output_ids = form_object.output_id.data

    # PID Control
    elif form_base.dashboard_type.data == 'pid_control':

        dashboard_type = 'PID Control'
        error = pid_error_check(form_object, error)
        new_graph.graph_type = 'pid_control'
        new_graph.width = form_base.width.data
        new_graph.height = form_base.height.data
        new_graph.max_measure_age = form_object.max_measure_age.data
        new_graph.refresh_duration = form_base.refresh_duration.data
        new_graph.font_em_value = form_object.font_em_value.data
        new_graph.font_em_timestamp = form_object.font_em_timestamp.data
        new_graph.decimal_places = form_object.decimal_places.data
        new_graph.show_pid_info = form_object.show_pid_info.data
        new_graph.show_set_setpoint = form_object.show_set_setpoint.data
        new_graph.pid_ids = form_object.pid_id.data

    # Camera
    elif (form_base.dashboard_type.data == 'camera'
          and form_object.camera_id.data):

        dashboard_type = 'Camera'
        new_graph.graph_type = form_base.dashboard_type.data
        new_graph.width = form_base.width.data
        new_graph.height = form_base.height.data
        new_graph.refresh_duration = form_base.refresh_duration.data
        new_graph.camera_max_age = form_object.camera_max_age.data
        new_graph.camera_id = form_object.camera_id.data
        new_graph.camera_image_type = form_object.camera_image_type.data
    else:
        flash_form_errors(form_base)
        return

    try:
        if not error:
            new_graph.save()
            flash(
                gettext("{dev} with ID %(id)s successfully added".format(
                    dev=dashboard_type),
                        id=new_graph.id), "success")
            DisplayOrder.query.first().dashboard = add_display_order(
                display_order, new_graph.unique_id)
            db.session.commit()
    except sqlalchemy.exc.OperationalError as except_msg:
        error.append(except_msg)
    except sqlalchemy.exc.IntegrityError as except_msg:
        error.append(except_msg)

    flash_success_errors(error, action, url_for('routes_page.page_dashboard'))
Ejemplo n.º 50
0
def method_create(form_create_method):
    """ Create new method table entry (all data stored in method_data table) """
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['add']['title'],
        controller=TRANSLATIONS['method']['title'])
    error = []

    try:
        # Create method
        new_method = Method()
        new_method.name = form_create_method.name.data
        new_method.method_type = form_create_method.method_type.data
        db.session.add(new_method)
        db.session.commit()

        # Add new method line id to method display order
        method_order = DisplayOrder.query.first()
        display_order = csv_to_list_of_str(method_order.method)
        method_order.method = add_display_order(display_order,
                                                new_method.unique_id)
        db.session.commit()

        # Add new method data line id to method_data display order
        if new_method.method_type in ['DailyBezier', 'DailySine']:
            # For tables that require only one entry to configure,
            # create that single entry now with default values
            new_method_data = MethodData()
            new_method_data.method_id = new_method.unique_id

            if new_method.method_type == 'DailySine':
                new_method_data.amplitude = 1.0
                new_method_data.frequency = 1.0
                new_method_data.shift_angle = 0
                new_method_data.shift_y = 1.0
            elif new_method.method_type == 'DailyBezier':
                new_method_data = MethodData()
                new_method_data.method_id = new_method.unique_id
                new_method_data.shift_angle = 0.0
                new_method_data.x0 = 20.0
                new_method_data.y0 = 20.0
                new_method_data.x1 = 10.0
                new_method_data.y1 = 13.5
                new_method_data.x2 = 22.5
                new_method_data.y2 = 30.0
                new_method_data.x3 = 0.0
                new_method_data.y3 = 20.0

            db.session.add(new_method_data)
            db.session.commit()

            display_order = csv_to_list_of_str(new_method.method_order)
            method = Method.query.filter(
                Method.unique_id == new_method.unique_id).first()
            method.method_order = add_display_order(display_order,
                                                    new_method_data.unique_id)
            db.session.commit()

        return 0
    except Exception as except_msg:

        error.append(except_msg)
    flash_success_errors(error, action, url_for('routes_method.method_list'))
Ejemplo n.º 51
0
def pid_mod(form_mod_pid_base,
            form_mod_pid_pwm_raise, form_mod_pid_pwm_lower,
            form_mod_pid_output_raise, form_mod_pid_output_lower):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['modify']['title'],
        controller=TRANSLATIONS['pid']['title'])
    error = []

    if not form_mod_pid_base.validate():
        error.append(TRANSLATIONS['error']['title'])
        flash_form_errors(form_mod_pid_base)

    mod_pid = PID.query.filter(
        PID.unique_id == form_mod_pid_base.function_id.data).first()

    mod_pid.name = form_mod_pid_base.name.data
    mod_pid.measurement = form_mod_pid_base.measurement.data
    mod_pid.direction = form_mod_pid_base.direction.data
    mod_pid.period = form_mod_pid_base.period.data
    mod_pid.log_level_debug = form_mod_pid_base.log_level_debug.data
    mod_pid.start_offset = form_mod_pid_base.start_offset.data
    mod_pid.max_measure_age = form_mod_pid_base.max_measure_age.data
    mod_pid.setpoint = form_mod_pid_base.setpoint.data
    mod_pid.band = abs(form_mod_pid_base.band.data)
    mod_pid.store_lower_as_negative = form_mod_pid_base.store_lower_as_negative.data
    mod_pid.p = form_mod_pid_base.k_p.data
    mod_pid.i = form_mod_pid_base.k_i.data
    mod_pid.d = form_mod_pid_base.k_d.data
    mod_pid.integrator_min = form_mod_pid_base.integrator_max.data
    mod_pid.integrator_max = form_mod_pid_base.integrator_min.data
    mod_pid.setpoint_tracking_type = form_mod_pid_base.setpoint_tracking_type.data
    if form_mod_pid_base.setpoint_tracking_type.data == 'method':
        mod_pid.setpoint_tracking_id = form_mod_pid_base.setpoint_tracking_method_id.data
    elif form_mod_pid_base.setpoint_tracking_type.data == 'input-math':
        mod_pid.setpoint_tracking_id = form_mod_pid_base.setpoint_tracking_input_math_id.data
        mod_pid.setpoint_tracking_max_age = form_mod_pid_base.setpoint_tracking_max_age.data
    else:
        mod_pid.setpoint_tracking_id = ''

    # Change measurement information
    if ',' in form_mod_pid_base.measurement.data:
        measurement_id = form_mod_pid_base.measurement.data.split(',')[1]
        selected_measurement = get_measurement(measurement_id)

        measurements = DeviceMeasurements.query.filter(
            DeviceMeasurements.device_id == form_mod_pid_base.function_id.data).all()
        for each_measurement in measurements:
            # Only set channels 0, 1, 2
            if each_measurement.channel in [0, 1, 2]:
                each_measurement.measurement = selected_measurement.measurement
                each_measurement.unit = selected_measurement.unit

    if form_mod_pid_base.raise_output_id.data:
        raise_output_type = Output.query.filter(
            Output.unique_id == form_mod_pid_base.raise_output_id.data).first().output_type
        if mod_pid.raise_output_id == form_mod_pid_base.raise_output_id.data:
            if raise_output_type in OUTPUTS_PWM:
                if not form_mod_pid_pwm_raise.validate():
                    error.append(TRANSLATIONS['error']['title'])
                    flash_form_errors(form_mod_pid_pwm_raise)
                else:
                    mod_pid.raise_min_duration = form_mod_pid_pwm_raise.raise_min_duty_cycle.data
                    mod_pid.raise_max_duration = form_mod_pid_pwm_raise.raise_max_duty_cycle.data
            else:
                if not form_mod_pid_output_raise.validate():
                    error.append(TRANSLATIONS['error']['title'])
                    flash_form_errors(form_mod_pid_output_raise)
                else:
                    mod_pid.raise_min_duration = form_mod_pid_output_raise.raise_min_duration.data
                    mod_pid.raise_max_duration = form_mod_pid_output_raise.raise_max_duration.data
                    mod_pid.raise_min_off_duration = form_mod_pid_output_raise.raise_min_off_duration.data
        else:
            if raise_output_type in OUTPUTS_PWM:
                mod_pid.raise_min_duration = 2
                mod_pid.raise_max_duration = 98
            else:
                mod_pid.raise_min_duration = 0
                mod_pid.raise_max_duration = 0
                mod_pid.raise_min_off_duration = 0
        mod_pid.raise_output_id = form_mod_pid_base.raise_output_id.data
    else:
        mod_pid.raise_output_id = None

    if form_mod_pid_base.lower_output_id.data:
        lower_output_type = Output.query.filter(
            Output.unique_id == form_mod_pid_base.lower_output_id.data).first().output_type
        if mod_pid.lower_output_id == form_mod_pid_base.lower_output_id.data:
            if lower_output_type in OUTPUTS_PWM:
                if not form_mod_pid_pwm_lower.validate():
                    error.append(gettext("Error in form field(s)"))
                    flash_form_errors(form_mod_pid_pwm_lower)
                else:
                    mod_pid.lower_min_duration = form_mod_pid_pwm_lower.lower_min_duty_cycle.data
                    mod_pid.lower_max_duration = form_mod_pid_pwm_lower.lower_max_duty_cycle.data
            else:
                if not form_mod_pid_output_lower.validate():
                    error.append(gettext("Error in form field(s)"))
                    flash_form_errors(form_mod_pid_output_lower)
                else:
                    mod_pid.lower_min_duration = form_mod_pid_output_lower.lower_min_duration.data
                    mod_pid.lower_max_duration = form_mod_pid_output_lower.lower_max_duration.data
                    mod_pid.lower_min_off_duration = form_mod_pid_output_lower.lower_min_off_duration.data
        else:
            if lower_output_type in OUTPUTS_PWM:
                mod_pid.lower_min_duration = 2
                mod_pid.lower_max_duration = 98
            else:
                mod_pid.lower_min_duration = 0
                mod_pid.lower_max_duration = 0
                mod_pid.lower_min_off_duration = 0
        mod_pid.lower_output_id = form_mod_pid_base.lower_output_id.data
    else:
        mod_pid.lower_output_id = None

    if (mod_pid.raise_output_id and mod_pid.lower_output_id and
            mod_pid.raise_output_id == mod_pid.lower_output_id):
        error.append(gettext("Raise and lower outputs cannot be the same"))

    try:
        if not error:
            db.session.commit()
            # If the controller is active or paused, refresh variables in thread
            if mod_pid.is_activated:
                control = DaemonControl()
                return_value = control.pid_mod(form_mod_pid_base.function_id.data)
                flash("PID Controller settings refresh response: "
                      "{resp}".format(resp=return_value), "success")
    except Exception as except_msg:
        error.append(except_msg)
    flash_success_errors(error, action, url_for('routes_page.page_function'))
Ejemplo n.º 52
0
def lcd_activate(lcd_id):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['activate']['title'],
        controller=TRANSLATIONS['lcd']['title'])
    error = []

    try:
        # All display lines must be filled to activate display
        lcd = LCD.query.filter(LCD.unique_id == lcd_id).first()
        lcd_data = LCDData.query.filter(LCDData.lcd_id == lcd_id).all()
        blank_line_detected = False

        for each_lcd_data in lcd_data:
            if (
                    (lcd.y_lines in [2, 4, 8] and
                        (not each_lcd_data.line_1_id or
                         not each_lcd_data.line_2_id)
                     ) or
                    (lcd.y_lines in [4, 8] and
                        (not each_lcd_data.line_3_id or
                         not each_lcd_data.line_4_id)
                    ) or
                    (lcd.y_lines == 8 and
                        (not each_lcd_data.line_5_id or
                         not each_lcd_data.line_6_id or
                         not each_lcd_data.line_7_id or
                         not each_lcd_data.line_8_id))
                    ):
                blank_line_detected = True

        def check_display_set(error, display_num, measurement, max_age, decimal_places):
            if measurement not in ["BLANK", "IP", "TEXT"]:
                if max_age is None:
                    error.append(
                        "Display Set {n}: {set}: {opt}".format(
                            n=display_num, set=gettext("Must be set"), opt=TRANSLATIONS['max_age']['title']))
                if decimal_places is None:
                    error.append("Display Set {n}: {set}: {opt}".format(
                        n=display_num, set=gettext("Must be set"), opt=gettext("Decimal Places")))
            return error

        for each_lcd_data in lcd_data:
            if lcd.y_lines in [2, 4, 8]:
                error = check_display_set(
                    error, 1,
                    each_lcd_data.line_1_measurement,
                    each_lcd_data.line_1_max_age,
                    each_lcd_data.line_1_decimal_places)
                error = check_display_set(
                    error, 2,
                    each_lcd_data.line_2_measurement,
                    each_lcd_data.line_2_max_age,
                    each_lcd_data.line_2_decimal_places)
            if lcd.y_lines in [4, 8]:
                error = check_display_set(
                    error, 3,
                    each_lcd_data.line_3_measurement,
                    each_lcd_data.line_3_max_age,
                    each_lcd_data.line_3_decimal_places)
                error = check_display_set(
                    error, 4,
                    each_lcd_data.line_4_measurement,
                    each_lcd_data.line_4_max_age,
                    each_lcd_data.line_4_decimal_places)
            if lcd.y_lines == 8:
                error = check_display_set(
                    error, 5,
                    each_lcd_data.line_5_measurement,
                    each_lcd_data.line_5_max_age,
                    each_lcd_data.line_5_decimal_places)
                error = check_display_set(
                    error, 6,
                    each_lcd_data.line_6_measurement,
                    each_lcd_data.line_6_max_age,
                    each_lcd_data.line_6_decimal_places)
                error = check_display_set(
                    error, 7,
                    each_lcd_data.line_7_measurement,
                    each_lcd_data.line_7_max_age,
                    each_lcd_data.line_7_decimal_places)
                error = check_display_set(
                    error, 8,
                    each_lcd_data.line_8_measurement,
                    each_lcd_data.line_8_max_age,
                    each_lcd_data.line_8_decimal_places)

        if blank_line_detected:
            error.append(gettext(
                'Detected at least one "Line" unset. Cannot activate LCD if there are unconfigured lines.'))

        if not error:
            controller_activate_deactivate('activate', 'LCD', lcd_id)
    except Exception as except_msg:
        error.append(except_msg)
    flash_success_errors(error, action, url_for('routes_page.page_lcd'))
Ejemplo n.º 53
0
def input_add(form_add):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['add']['title'],
        controller=TRANSLATIONS['input']['title'])
    error = []

    dict_inputs = parse_input_information()

    # only one comma should be in the input_type string
    if form_add.input_type.data.count(',') > 1:
        error.append("Invalid input module formatting. It appears there is "
                     "a comma in either 'input_name_unique' or 'interfaces'.")

    if form_add.input_type.data.count(',') == 1:
        input_name = form_add.input_type.data.split(',')[0]
        input_interface = form_add.input_type.data.split(',')[1]
    else:
        input_name = ''
        input_interface = ''
        error.append("Invalid input string (must be a comma-separated string)")

    if current_app.config['TESTING']:
        dep_unmet = False
    else:
        dep_unmet, _ = return_dependencies(input_name)
        if dep_unmet:
            list_unmet_deps = []
            for each_dep in dep_unmet:
                list_unmet_deps.append(each_dep[0])
            error.append("The {dev} device you're trying to add has unmet dependencies: {dep}".format(
                dev=input_name, dep=', '.join(list_unmet_deps)))

    if form_add.validate():
        new_input = Input()
        new_input.device = input_name

        if input_interface:
            new_input.interface = input_interface

        try:
            from RPi import GPIO
            if GPIO.RPI_INFO['P1_REVISION'] == 1:
                new_input.i2c_bus = 0
            else:
                new_input.i2c_bus = 1
        except:
            logger.error(
                "RPi.GPIO and Raspberry Pi required for this action")

        if 'input_name' in dict_inputs[input_name]:
            new_input.name = dict_inputs[input_name]['input_name']
        else:
            new_input.name = 'Name'

        #
        # Set default values for new input being added
        #

        # input add options
        if input_name in dict_inputs:
            def dict_has_value(key):
                if (key in dict_inputs[input_name] and
                        (dict_inputs[input_name][key] or dict_inputs[input_name][key] == 0)):
                    return True

            #
            # Interfacing options
            #

            if input_interface == 'I2C':
                if dict_has_value('i2c_location'):
                    new_input.i2c_location = dict_inputs[input_name]['i2c_location'][0]  # First entry in list

            if input_interface == 'FTDI':
                if dict_has_value('ftdi_location'):
                    new_input.ftdi_location = dict_inputs[input_name]['ftdi_location']

            if input_interface == 'UART':
                if dict_has_value('uart_location'):
                    new_input.uart_location = dict_inputs[input_name]['uart_location']

            # UART options
            if dict_has_value('uart_baud_rate'):
                new_input.baud_rate = dict_inputs[input_name]['uart_baud_rate']
            if dict_has_value('pin_cs'):
                new_input.pin_cs = dict_inputs[input_name]['pin_cs']
            if dict_has_value('pin_miso'):
                new_input.pin_miso = dict_inputs[input_name]['pin_miso']
            if dict_has_value('pin_mosi'):
                new_input.pin_mosi = dict_inputs[input_name]['pin_mosi']
            if dict_has_value('pin_clock'):
                new_input.pin_clock = dict_inputs[input_name]['pin_clock']

            # Bluetooth (BT) options
            elif input_interface == 'BT':
                if dict_has_value('bt_location'):
                    if not re.match("[0-9a-fA-F]{2}([:]?)[0-9a-fA-F]{2}(\\1[0-9a-fA-F]{2}){4}$",
                                    dict_inputs[input_name]['bt_location']):
                        error.append("Please specify device MAC-Address in format AA:BB:CC:DD:EE:FF")
                    else:
                        new_input.location = dict_inputs[input_name]['bt_location']
                if dict_has_value('bt_adapter'):
                    new_input.bt_adapter = dict_inputs[input_name]['bt_adapter']

            # GPIO options
            elif input_interface == 'GPIO':
                if dict_has_value('gpio_location'):
                    new_input.gpio_location = dict_inputs[input_name]['gpio_location']

            # Custom location location
            elif dict_has_value('location'):
                new_input.location = dict_inputs[input_name]['location']['options'][0][0]  # First entry in list

            #
            # General options
            #

            if dict_has_value('period'):
                new_input.period = dict_inputs[input_name]['period']

            # Server Ping options
            if dict_has_value('times_check'):
                new_input.times_check = dict_inputs[input_name]['times_check']
            if dict_has_value('deadline'):
                new_input.deadline = dict_inputs[input_name]['deadline']
            if dict_has_value('port'):
                new_input.port = dict_inputs[input_name]['port']

            # Signal options
            if dict_has_value('weighting'):
                new_input.weighting = dict_inputs[input_name]['weighting']
            if dict_has_value('sample_time'):
                new_input.sample_time = dict_inputs[input_name]['sample_time']

            # Analog-to-digital converter options
            if dict_has_value('adc_gain'):
                if len(dict_inputs[input_name]['adc_gain']) == 1:
                    new_input.adc_gain = dict_inputs[input_name]['adc_gain'][0]
                elif len(dict_inputs[input_name]['adc_gain']) > 1:
                    new_input.adc_gain = dict_inputs[input_name]['adc_gain'][0][0]
            if dict_has_value('adc_resolution'):
                if len(dict_inputs[input_name]['adc_resolution']) == 1:
                    new_input.adc_resolution = dict_inputs[input_name]['adc_resolution'][0]
                elif len(dict_inputs[input_name]['adc_resolution']) > 1:
                    new_input.adc_resolution = dict_inputs[input_name]['adc_resolution'][0][0]
            if dict_has_value('adc_sample_speed'):
                if len(dict_inputs[input_name]['adc_sample_speed']) == 1:
                    new_input.adc_sample_speed = dict_inputs[input_name]['adc_sample_speed'][0]
                elif len(dict_inputs[input_name]['adc_sample_speed']) > 1:
                    new_input.adc_sample_speed = dict_inputs[input_name]['adc_sample_speed'][0][0]

            # Linux command
            if dict_has_value('cmd_command'):
                new_input.cmd_command = dict_inputs[input_name]['cmd_command']

            # Misc options
            if dict_has_value('resolution'):
                if len(dict_inputs[input_name]['resolution']) == 1:
                    new_input.resolution = dict_inputs[input_name]['resolution'][0]
                elif len(dict_inputs[input_name]['resolution']) > 1:
                    new_input.resolution = dict_inputs[input_name]['resolution'][0][0]
            if dict_has_value('resolution_2'):
                if len(dict_inputs[input_name]['resolution_2']) == 1:
                    new_input.resolution_2 = dict_inputs[input_name]['resolution_2'][0]
                elif len(dict_inputs[input_name]['resolution_2']) > 1:
                    new_input.resolution_2 = dict_inputs[input_name]['resolution_2'][0][0]
            if dict_has_value('sensitivity'):
                if len(dict_inputs[input_name]['sensitivity']) == 1:
                    new_input.sensitivity = dict_inputs[input_name]['sensitivity'][0]
                elif len(dict_inputs[input_name]['sensitivity']) > 1:
                    new_input.sensitivity = dict_inputs[input_name]['sensitivity'][0][0]
            if dict_has_value('thermocouple_type'):
                if len(dict_inputs[input_name]['thermocouple_type']) == 1:
                    new_input.thermocouple_type = dict_inputs[input_name]['thermocouple_type'][0]
                elif len(dict_inputs[input_name]['thermocouple_type']) > 1:
                    new_input.thermocouple_type = dict_inputs[input_name]['thermocouple_type'][0][0]
            if dict_has_value('sht_voltage'):
                if len(dict_inputs[input_name]['sht_voltage']) == 1:
                    new_input.sht_voltage = dict_inputs[input_name]['sht_voltage'][0]
                elif len(dict_inputs[input_name]['sht_voltage']) > 1:
                    new_input.sht_voltage = dict_inputs[input_name]['sht_voltage'][0][0]
            if dict_has_value('ref_ohm'):
                new_input.ref_ohm = dict_inputs[input_name]['ref_ohm']

        #
        # Custom Options
        #

        # Generate string to save from custom options
        error, custom_options = custom_options_return_json(
            error, dict_inputs, device=input_name, use_defaults=True)
        new_input.custom_options = custom_options

        #
        # Execute at Creation
        #

        new_input.unique_id = set_uuid()

        if ('execute_at_creation' in dict_inputs[new_input.device] and
                not current_app.config['TESTING']):
            error, new_input = dict_inputs[new_input.device]['execute_at_creation'](
                error, new_input, dict_inputs[new_input.device])

        try:
            if not error:
                new_input.save()

                display_order = csv_to_list_of_str(
                    DisplayOrder.query.first().inputs)

                DisplayOrder.query.first().inputs = add_display_order(
                    display_order, new_input.unique_id)
                db.session.commit()

                #
                # If there are a variable number of measurements
                #

                if ('measurements_variable_amount' in dict_inputs[input_name] and
                        dict_inputs[input_name]['measurements_variable_amount']):
                    # Add first default measurement with empty unit and measurement
                    new_measurement = DeviceMeasurements()
                    new_measurement.name = ""
                    new_measurement.device_id = new_input.unique_id
                    new_measurement.measurement = ""
                    new_measurement.unit = ""
                    new_measurement.channel = 0
                    new_measurement.save()

                #
                # If measurements defined in the Input Module
                #

                elif ('measurements_dict' in dict_inputs[input_name] and
                        dict_inputs[input_name]['measurements_dict']):
                    for each_channel in dict_inputs[input_name]['measurements_dict']:
                        measure_info = dict_inputs[input_name]['measurements_dict'][each_channel]
                        new_measurement = DeviceMeasurements()
                        if 'name' in measure_info:
                            new_measurement.name = measure_info['name']
                        new_measurement.device_id = new_input.unique_id
                        new_measurement.measurement = measure_info['measurement']
                        new_measurement.unit = measure_info['unit']
                        new_measurement.channel = each_channel
                        new_measurement.save()

                if 'channels_dict' in dict_inputs[new_input.device]:
                    for each_channel, channel_info in dict_inputs[new_input.device]['channels_dict'].items():
                        new_channel = InputChannel()
                        new_channel.channel = each_channel
                        new_channel.input_id = new_input.unique_id

                        # Generate string to save from custom options
                        error, custom_options = custom_channel_options_return_json(
                            error, dict_inputs, None,
                            new_input.unique_id, each_channel,
                            device=new_input.device, use_defaults=True)
                        new_channel.custom_options = custom_options

                        new_channel.save()

                flash(gettext(
                    "%(type)s Input with ID %(id)s (%(uuid)s) successfully added",
                    type=input_name,
                    id=new_input.id,
                    uuid=new_input.unique_id),
                      "success")
        except sqlalchemy.exc.OperationalError as except_msg:
            error.append(except_msg)
        except sqlalchemy.exc.IntegrityError as except_msg:
            error.append(except_msg)

        flash_success_errors(error, action, url_for('routes_page.page_input'))
    else:
        flash_form_errors(form_add)

    if dep_unmet:
        return 1
Ejemplo n.º 54
0
def output_mod(form_output, request_form):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['modify']['title'],
        controller=TRANSLATIONS['output']['title'])
    error = []

    dict_outputs = parse_output_information()

    try:
        channels = OutputChannel.query.filter(
            OutputChannel.output_id == form_output.output_id.data).all()
        mod_output = Output.query.filter(
            Output.unique_id == form_output.output_id.data).first()

        if (form_output.uart_location.data
                and not os.path.exists(form_output.uart_location.data)):
            error.append(
                gettext(
                    "Invalid device or improper permissions to read device"))

        mod_output.name = form_output.name.data

        if form_output.location.data:
            mod_output.location = form_output.location.data
        if form_output.i2c_location.data:
            mod_output.i2c_location = form_output.i2c_location.data
        if form_output.ftdi_location.data:
            mod_output.ftdi_location = form_output.ftdi_location.data
        if form_output.uart_location.data:
            mod_output.uart_location = form_output.uart_location.data
        if form_output.gpio_location.data:
            if not is_int(form_output.gpio_location.data):
                error.append("BCM GPIO Pin must be an integer")
            else:
                mod_output.pin = form_output.gpio_location.data

        if form_output.i2c_bus.data is not None:
            mod_output.i2c_bus = form_output.i2c_bus.data
        if form_output.baud_rate.data:
            mod_output.baud_rate = form_output.baud_rate.data

        mod_output.log_level_debug = form_output.log_level_debug.data

        # Parse pre-save custom options for output device and its channels
        try:
            custom_options_dict_presave = json.loads(mod_output.custom_options)
        except:
            logger.error("Malformed JSON")
            custom_options_dict_presave = {}

        custom_options_channels_dict_presave = {}
        for each_channel in channels:
            if each_channel.custom_options and each_channel.custom_options != "{}":
                custom_options_channels_dict_presave[
                    each_channel.channel] = json.loads(
                        each_channel.custom_options)
            else:
                custom_options_channels_dict_presave[each_channel.channel] = {}

        # Parse post-save custom options for output device and its channels
        error, custom_options_json_postsave = custom_options_return_json(
            error, dict_outputs, request_form, device=mod_output.output_type)
        custom_options_dict_postsave = json.loads(custom_options_json_postsave)

        custom_options_channels_dict_postsave = {}
        for each_channel in channels:
            error, custom_options_channels_json_postsave_tmp = custom_channel_options_return_json(
                error,
                dict_outputs,
                request_form,
                form_output.output_id.data,
                each_channel.channel,
                device=mod_output.output_type,
                use_defaults=True)
            custom_options_channels_dict_postsave[
                each_channel.channel] = json.loads(
                    custom_options_channels_json_postsave_tmp)

        if 'execute_at_modification' in dict_outputs[mod_output.output_type]:
            # pass custom options to module prior to saving to database
            (allow_saving, mod_output, custom_options_dict,
             custom_options_channels_dict) = dict_outputs[
                 mod_output.output_type]['execute_at_modification'](
                     mod_output, request_form, custom_options_dict_presave,
                     custom_options_channels_dict_presave,
                     custom_options_dict_postsave,
                     custom_options_channels_dict_postsave)
            custom_options = json.dumps(
                custom_options_dict)  # Convert from dict to JSON string
            custom_channel_options = custom_options_channels_dict
            if not allow_saving:
                error.append(
                    "execute_at_modification() would not allow output options to be saved"
                )
        else:
            # Don't pass custom options to module
            custom_options = json.dumps(custom_options_dict_postsave)
            custom_channel_options = custom_options_channels_dict_postsave

        # Finally, save custom options for both output and channels
        mod_output.custom_options = custom_options
        for each_channel in channels:
            if 'name' in custom_channel_options[each_channel.channel]:
                each_channel.name = custom_channel_options[
                    each_channel.channel]['name']
            each_channel.custom_options = json.dumps(
                custom_channel_options[each_channel.channel])

        if not error:
            db.session.commit()
            manipulate_output('Modify', form_output.output_id.data)
    except Exception as except_msg:
        logger.exception(1)
        error.append(except_msg)
    flash_success_errors(error, action, url_for('routes_page.page_output'))
Ejemplo n.º 55
0
def output_add(form_add):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['add']['title'],
        controller=TRANSLATIONS['output']['title'])
    error = []

    dict_outputs = parse_output_information()
    output_types_dict = output_types()

    # only one comma should be in the output_type string
    if form_add.output_type.data.count(',') > 1:
        error.append("Invalid output module formatting. It appears there is "
                     "a comma in either 'output_name_unique' or 'interfaces'.")

    if form_add.output_type.data.count(',') == 1:
        output_type = form_add.output_type.data.split(',')[0]
        output_interface = form_add.output_type.data.split(',')[1]
    else:
        output_type = ''
        output_interface = ''
        error.append("Invalid output string (must be a comma-separated string)")

    if current_app.config['TESTING']:
        dep_unmet = False
    else:
        dep_unmet, _ = return_dependencies(form_add.output_type.data.split(',')[0])
        if dep_unmet:
            list_unmet_deps = []
            for each_dep in dep_unmet:
                list_unmet_deps.append(each_dep[0])
            error.append(
                "The {dev} device you're trying to add has unmet dependencies: "
                "{dep}".format(dev=form_add.output_type.data,
                               dep=', '.join(list_unmet_deps)))

    if not is_int(form_add.output_quantity.data, check_range=[1, 20]):
        error.append("{error}. {accepted_values}: 1-20".format(
            error=gettext("Invalid quantity"),
            accepted_values=gettext("Acceptable values")
        ))

    if not error:
        for _ in range(0, form_add.output_quantity.data):
            try:
                new_output = Output()

                try:
                    from RPi import GPIO
                    if GPIO.RPI_INFO['P1_REVISION'] == 1:
                        new_output.i2c_bus = 0
                    else:
                        new_output.i2c_bus = 1
                except:
                    logger.error(
                        "RPi.GPIO and Raspberry Pi required for this action")

                new_output.name = "Name"
                new_output.output_type = output_type
                new_output.interface = output_interface

                #
                # Set default values for new input being added
                #

                # input add options
                if output_type in dict_outputs:
                    def dict_has_value(key):
                        if (key in dict_outputs[output_type] and
                                dict_outputs[output_type][key] is not None):
                            return True

                    #
                    # Interfacing options
                    #

                    if output_interface == 'I2C':
                        if dict_has_value('i2c_address_default'):
                            new_output.i2c_location = dict_outputs[output_type]['i2c_address_default']
                        elif dict_has_value('i2c_location'):
                            new_output.i2c_location = dict_outputs[output_type]['i2c_location'][0]  # First list entry

                    if output_interface == 'FTDI':
                        if dict_has_value('ftdi_location'):
                            new_output.ftdi_location = dict_outputs[output_type]['ftdi_location']

                    if output_interface == 'UART':
                        if dict_has_value('uart_location'):
                            new_output.uart_location = dict_outputs[output_type]['uart_location']

                    # UART options
                    if dict_has_value('uart_baud_rate'):
                        new_output.baud_rate = dict_outputs[output_type]['uart_baud_rate']
                    if dict_has_value('pin_cs'):
                        new_output.pin_cs = dict_outputs[output_type]['pin_cs']
                    if dict_has_value('pin_miso'):
                        new_output.pin_miso = dict_outputs[output_type]['pin_miso']
                    if dict_has_value('pin_mosi'):
                        new_output.pin_mosi = dict_outputs[output_type]['pin_mosi']
                    if dict_has_value('pin_clock'):
                        new_output.pin_clock = dict_outputs[output_type]['pin_clock']

                    # Bluetooth (BT) options
                    elif output_interface == 'BT':
                        if dict_has_value('bt_location'):
                            new_output.location = dict_outputs[output_type]['bt_location']
                        if dict_has_value('bt_adapter'):
                            new_output.bt_adapter = dict_outputs[output_type]['bt_adapter']

                    # GPIO options
                    elif output_interface == 'GPIO':
                        if dict_has_value('gpio_pin'):
                            new_output.pin = dict_outputs[output_type]['gpio_pin']

                    # Custom location location
                    elif dict_has_value('location'):
                        new_output.location = dict_outputs[output_type]['location']['options'][0][0]  # First entry in list

                #
                # Custom Options
                #

                list_options = []
                if 'custom_options' in dict_outputs[output_type]:
                    for each_option in dict_outputs[output_type]['custom_options']:
                        if each_option['default_value'] is False:
                            default_value = ''
                        else:
                            default_value = each_option['default_value']
                        option = '{id},{value}'.format(
                            id=each_option['id'],
                            value=default_value)
                        list_options.append(option)
                new_output.custom_options = ';'.join(list_options)

                if output_type in output_types_dict['pwm']:
                    new_output.pwm_hertz = 22000
                    new_output.pwm_library = 'pigpio_any'

                if output_type in output_types_dict['volume']:
                    new_output.output_mode = 'fastest_flow_rate'
                    new_output.flow_rate = 10
                    if output_type == 'atlas_ezo_pmp':
                        if output_interface == 'FTDI':
                            new_output.location = '/dev/ttyUSB0'
                        elif output_interface == 'I2C':
                            new_output.location = '0x67'
                            new_output.i2c_bus = 1
                        elif output_interface == 'UART':
                            new_output.location = '/dev/ttyAMA0'
                            new_output.baud_rate = 9600

                if output_type == 'wired':
                    new_output.state_startup = '0'
                    new_output.state_shutdown = '0'

                elif output_type == 'wireless_rpi_rf':
                    new_output.pin = None
                    new_output.protocol = 1
                    new_output.pulse_length = 189
                    new_output.on_command = '22559'
                    new_output.off_command = '22558'
                    new_output.force_command = True

                elif output_type == 'command':
                    new_output.linux_command_user = '******'
                    new_output.on_command = '/home/pi/script_on.sh'
                    new_output.off_command = '/home/pi/script_off.sh'
                    new_output.force_command = True

                elif output_type == 'command_pwm':
                    new_output.linux_command_user = '******'
                    new_output.pwm_command = '/home/pi/script_pwm.sh ((duty_cycle))'

                elif output_type == 'python':
                    new_output.on_command = """
import datetime
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
log_string = "{ts}: ID: {id}: ON".format(id=output_id, ts=timestamp)
self.logger.info(log_string)"""
                    new_output.off_command = """
import datetime
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
log_string = "{ts}: ID: {id}: OFF".format(id=output_id, ts=timestamp)
self.logger.info(log_string)"""
                    new_output.force_command = True

                elif output_type == 'python_pwm':
                    new_output.pwm_command = """
import datetime
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
log_string = "{ts}: ID: {id}: {dc} % Duty Cycle".format(
    dc=duty_cycle, id=output_id, ts=timestamp)
self.logger.info(log_string)"""

                if not error:
                    new_output.save()
                    display_order = csv_to_list_of_str(
                        DisplayOrder.query.first().output)
                    DisplayOrder.query.first().output = add_display_order(
                        display_order, new_output.unique_id)

                    #
                    # If measurements defined in the Output Module
                    #

                    if ('measurements_dict' in dict_outputs[output_type] and
                            dict_outputs[output_type]['measurements_dict'] != []):
                        for each_channel in dict_outputs[output_type]['measurements_dict']:
                            measure_info = dict_outputs[output_type]['measurements_dict'][each_channel]
                            new_measurement = DeviceMeasurements()
                            if 'name' in measure_info:
                                new_measurement.name = measure_info['name']
                            new_measurement.device_id = new_output.unique_id
                            new_measurement.measurement = measure_info['measurement']
                            new_measurement.unit = measure_info['unit']
                            new_measurement.channel = each_channel
                            new_measurement.save()

                    db.session.commit()

                    if not current_app.config['TESTING']:
                        manipulate_output('Add', new_output.unique_id)
            except sqlalchemy.exc.OperationalError as except_msg:
                error.append(except_msg)
            except sqlalchemy.exc.IntegrityError as except_msg:
                error.append(except_msg)

    flash_success_errors(error, action, url_for('routes_page.page_output'))

    if dep_unmet:
        return 1
Ejemplo n.º 56
0
def import_influxdb(form):
    """
    Receive a zip file contatining influx metastore and database that was
    exported with export_influxdb(), then import the metastore and database
    in InfluxDB.
    """
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['import']['title'],
        controller="Influxdb")
    error = []

    try:
        correct_format = 'Mycodo_MYCODOVERSION_Influxdb_INFLUXVERSION_HOST_DATETIME.zip'
        upload_folder = os.path.join(INSTALL_DIRECTORY, 'upload')
        tmp_folder = os.path.join(upload_folder, 'mycodo_influx_tmp')
        full_path = None

        if not form.influxdb_import_file.data:
            error.append('No file present')
        elif form.influxdb_import_file.data.filename == '':
            error.append('No file name')
        else:
            # Split the uploaded file into parts
            file_name = form.influxdb_import_file.data.filename
            name = file_name.rsplit('.', 1)[0]
            extension = file_name.rsplit('.', 1)[1].lower()
            name_split = name.split('_')

            # Split the correctly-formatted filename into parts
            correct_name = correct_format.rsplit('.', 1)[0]
            correct_name_1 = correct_name.split('_')[0]
            correct_name_2 = correct_name.split('_')[2]
            correct_extension = correct_format.rsplit('.', 1)[1].lower()

            # Compare the uploaded filename parts to the correct parts
            try:
                if name_split[0] != correct_name_1:
                    error.append(
                        "Invalid file name: {n}: {fn} != {cn}.".format(
                            n=file_name,
                            fn=name_split[0],
                            cn=correct_name_1))
                    error.append("Correct format is: {fmt}".format(
                        fmt=correct_format))
                elif name_split[2] != correct_name_2:
                    error.append(
                        "Invalid file name: {n}: {fn} != {cn}".format(
                            n=file_name,
                            fn=name_split[2],
                            cn=correct_name_2))
                    error.append("Correct format is: {fmt}".format(
                        fmt=correct_format))
                elif extension != correct_extension:
                    error.append("Extension not 'zip'")
            except Exception as err:
                error.append(
                    "Exception while verifying file name: "
                    "{err}".format(err=err))

        if not error:
            # Save file to upload directory
            filename = secure_filename(
                form.influxdb_import_file.data.filename)
            full_path = os.path.join(tmp_folder, filename)
            assure_path_exists(tmp_folder)
            form.influxdb_import_file.data.save(
                os.path.join(tmp_folder, filename))

            # Check if contents of zip file are correct
            try:
                file_list = zipfile.ZipFile(full_path, 'r').namelist()
                if not any(".meta" in s for s in file_list):
                    error.append("No '.meta' file found in archive")
                elif not any(".manifest" in s for s in file_list):
                    error.append("No '.manifest' file found in archive")
            except Exception as err:
                error.append("Exception while opening zip file: "
                             "{err}".format(err=err))

        if not error:
            # Unzip file
            try:
                zip_ref = zipfile.ZipFile(full_path, 'r')
                zip_ref.extractall(tmp_folder)
                zip_ref.close()
            except Exception as err:
                error.append("Exception while extracting zip file: "
                             "{err}".format(err=err))

        if not error:
            try:
                import_settings_db = threading.Thread(
                    target=thread_import_influxdb,
                    args=(tmp_folder,))
                import_settings_db.start()
                return "Initiated"
            except Exception as err:
                error.append(
                    "Exception while importing database: "
                    "{err}".format(err=err))
                return None

    except Exception as err:
        error.append("Exception: {}".format(err))

    flash_success_errors(error, action, url_for('routes_page.page_export'))
Ejemplo n.º 57
0
def output_mod(form_output, request_form):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['modify']['title'],
        controller=TRANSLATIONS['output']['title'])
    error = []

    dict_outputs = parse_output_information()

    try:
        mod_output = Output.query.filter(
            Output.unique_id == form_output.output_id.data).first()

        if (form_output.uart_location.data and
                not os.path.exists(form_output.uart_location.data)):
            error.append(gettext(
                "Invalid device or improper permissions to read device"))

        mod_output.name = form_output.name.data

        if form_output.location.data:
            mod_output.location = form_output.location.data
        if form_output.i2c_location.data:
            mod_output.i2c_location = form_output.i2c_location.data
        if form_output.ftdi_location.data:
            mod_output.ftdi_location = form_output.ftdi_location.data
        if form_output.uart_location.data:
            mod_output.uart_location = form_output.uart_location.data
        if form_output.gpio_location.data:
            if not is_int(form_output.gpio_location.data):
                error.append("BCM GPIO Pin must be an integer")
            else:
                mod_output.pin = form_output.gpio_location.data

        mod_output.i2c_bus = form_output.i2c_bus.data
        mod_output.baud_rate = form_output.baud_rate.data
        mod_output.log_level_debug = form_output.log_level_debug.data
        mod_output.amps = form_output.amps.data
        mod_output.trigger_functions_at_start = form_output.trigger_functions_at_start.data
        mod_output.location = form_output.location.data
        mod_output.output_mode = form_output.output_mode.data

        if form_output.on_state.data in ["0", "1"]:
            mod_output.on_state = bool(int(form_output.on_state.data))

        # Wireless options
        mod_output.protocol = form_output.protocol.data
        mod_output.pulse_length = form_output.pulse_length.data

        # Command options
        mod_output.on_command = form_output.on_command.data
        mod_output.off_command = form_output.off_command.data
        mod_output.force_command = form_output.force_command.data

        # PWM options
        mod_output.pwm_hertz = form_output.pwm_hertz.data
        mod_output.pwm_library = form_output.pwm_library.data
        mod_output.pwm_invert_signal = form_output.pwm_invert_signal.data

        # Pump options
        if form_output.flow_rate.data:
            if (mod_output.output_type == 'atlas_ezo_pmp' and
                    (form_output.flow_rate.data > 105 or form_output.flow_rate.data < 0.5)):
                error.append("The Atlas Scientific Flow Rate must be between 0.5 and 105 ml/min")
            elif form_output.flow_rate.data <= 0:
                error.append("Flow Rate must be a positive value")
            else:
                mod_output.flow_rate = form_output.flow_rate.data

        mod_output.pwm_command = form_output.pwm_command.data
        mod_output.pwm_invert_signal = form_output.pwm_invert_signal.data

        mod_output.linux_command_user = form_output.linux_command_user.data

        if form_output.state_startup.data == '-1':
            mod_output.state_startup = None
        elif form_output.state_startup.data is not None:
            mod_output.state_startup = form_output.state_startup.data

        if (hasattr(form_output, 'startup_value') and
                form_output.startup_value.data):
            mod_output.startup_value = form_output.startup_value.data

        if form_output.state_shutdown.data == '-1':
            mod_output.state_shutdown = None
        elif form_output.state_shutdown.data is not None:
            mod_output.state_shutdown = form_output.state_shutdown.data

        if (hasattr(form_output, 'shutdown_value') and
                form_output.shutdown_value.data):
            mod_output.shutdown_value = form_output.shutdown_value.data

        if 'execute_at_modification' in dict_outputs[mod_output.output_type]:
            (constraints_pass,
             constraints_errors,
             mod_input) = dict_outputs[mod_output.output_type]['execute_at_modification'](
                mod_output, request_form)
            if constraints_pass:
                pass
            elif constraints_errors:
                for each_error in constraints_errors:
                    flash(each_error, 'error')

        # Generate string to save from custom options
        error, custom_options = custom_options_return_string(
            error, dict_outputs, mod_output, request_form)

        if not error:
            mod_output.custom_options = custom_options

            db.session.commit()
            manipulate_output('Modify', form_output.output_id.data)
    except Exception as except_msg:
        logger.exception(1)
        error.append(except_msg)
    flash_success_errors(error, action, url_for('routes_page.page_output'))
Ejemplo n.º 58
0
def import_settings(form):
    """
    Receive a zip file containing a Mycodo settings database that was
    exported with export_settings(), then back up the current Mycodo settings
    database and implement the one form the zip in its's place.
    """
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['import']['title'],
        controller=TRANSLATIONS['settings']['title'])
    error = []

    try:
        correct_format = 'Mycodo_MYCODOVERSION_Settings_DBVERSION_HOST_DATETIME.zip'
        upload_folder = os.path.join(INSTALL_DIRECTORY, 'upload')
        tmp_folder = os.path.join(upload_folder, 'mycodo_db_tmp')
        mycodo_database_name = 'mycodo.db'
        full_path = None

        if not form.settings_import_file.data:
            error.append('No file present')
        elif form.settings_import_file.data.filename == '':
            error.append('No file name')
        else:
            # Split the uploaded file into parts
            file_name = form.settings_import_file.data.filename
            name = file_name.rsplit('.', 1)[0]
            extension = file_name.rsplit('.', 1)[1].lower()
            name_split = name.split('_')

            # Split the correctly-formatted filename into parts
            correct_name = correct_format.rsplit('.', 1)[0]
            correct_name_1 = correct_name.split('_')[0]
            correct_name_2 = correct_name.split('_')[2]
            correct_extension = correct_format.rsplit('.', 1)[1].lower()

            # Compare the uploaded filename parts to the correct parts
            try:
                if name_split[0] != correct_name_1:
                    error.append(
                        "Invalid file name: {n}: {fn} != {cn}.".format(
                            n=file_name,
                            fn=name_split[0],
                            cn=correct_name_1))
                    error.append("Correct format is: {fmt}".format(
                        fmt=correct_format))
                elif name_split[2] != correct_name_2:
                    error.append(
                        "Invalid file name: {n}: {fn} != {cn}".format(
                            n=file_name,
                            fn=name_split[2],
                            cn=correct_name_2))
                    error.append("Correct format is: {fmt}".format(
                        fmt=correct_format))
                elif extension != correct_extension:
                    error.append("Extension not 'zip'")
                elif name_split[1] > MYCODO_VERSION:
                    error.append(
                        "Invalid Mycodo version: {fv} > {mv}. "
                        "Only databases <= {mver} can only be imported".format(
                            fv=name_split[1],
                            mv=MYCODO_VERSION,
                            mver=name_split[1]))
            except Exception as err:
                error.append(
                    "Exception while verifying file name: {err}".format(err=err))

        if not error:
            # Save file to upload directory
            filename = secure_filename(
                form.settings_import_file.data.filename)
            full_path = os.path.join(tmp_folder, filename)
            assure_path_exists(upload_folder)
            assure_path_exists(tmp_folder)
            form.settings_import_file.data.save(
                os.path.join(tmp_folder, filename))

            # Check if contents of zip file are correct
            try:
                file_list = zipfile.ZipFile(full_path, 'r').namelist()
                if len(file_list) > 1:
                    error.append("Incorrect number of files in zip: "
                                 "{an} != 1".format(an=len(file_list)))
                elif file_list[0] != mycodo_database_name:
                    error.append("Incorrect file in zip: {af} != {cf}".format(
                        af=file_list[0], cf=mycodo_database_name))
            except Exception as err:
                error.append("Exception while opening zip file: "
                             "{err}".format(err=err))

        if not error:
            # Unzip file
            try:
                zip_ref = zipfile.ZipFile(full_path, 'r')
                zip_ref.extractall(tmp_folder)
                zip_ref.close()
            except Exception as err:
                error.append("Exception while extracting zip file: "
                             "{err}".format(err=err))

        if not error:
            try:
                # Stop Mycodo daemon (backend)
                cmd = "{pth}/mycodo/scripts/mycodo_wrapper " \
                      "daemon_stop".format(
                    pth=INSTALL_DIRECTORY)
                _, _, _ = cmd_output(cmd)

                # Backup current database and replace with extracted mycodo.db
                imported_database = os.path.join(
                    tmp_folder, mycodo_database_name)
                backup_name = (
                    SQL_DATABASE_MYCODO + '.backup_' +
                    datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S"))
                os.rename(SQL_DATABASE_MYCODO, backup_name)
                os.rename(imported_database, SQL_DATABASE_MYCODO)

                import_settings_db = threading.Thread(
                    target=thread_import_settings,
                    args=(tmp_folder,))
                import_settings_db.start()

                return backup_name
            except Exception as err:
                error.append("Exception while replacing database: "
                             "{err}".format(err=err))
                return None

    except Exception as err:
        error.append("Exception: {}".format(err))

    flash_success_errors(error, action, url_for('routes_page.page_export'))
Ejemplo n.º 59
0
def action_mod(form):
    """Modify a Conditional Action"""
    error = []
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['modify']['title'],
        controller='{} {}'.format(TRANSLATIONS['conditional']['title'], TRANSLATIONS['actions']['title']))

    error = check_form_actions(form, error)

    try:
        mod_action = Actions.query.filter(
            Actions.unique_id == form.function_action_id.data).first()

        if mod_action.action_type == 'pause_actions':
            mod_action.pause_duration = form.pause_duration.data

        elif mod_action.action_type == 'output':
            mod_action.do_unique_id = form.do_unique_id.data
            mod_action.do_output_state = form.do_output_state.data
            mod_action.do_output_duration = form.do_output_duration.data

        elif mod_action.action_type == 'output_pwm':
            mod_action.do_unique_id = form.do_unique_id.data
            mod_action.do_output_pwm = form.do_output_pwm.data

        elif mod_action.action_type == 'output_ramp_pwm':
            mod_action.do_unique_id = form.do_unique_id.data
            mod_action.do_output_pwm = form.do_output_pwm.data
            mod_action.do_output_pwm2 = form.do_output_pwm2.data
            mod_action.do_action_string = form.do_action_string.data
            mod_action.do_output_duration = form.do_output_duration.data

        elif mod_action.action_type in ['activate_controller',
                                        'deactivate_controller',
                                        'activate_pid',
                                        'deactivate_pid',
                                        'resume_pid',
                                        'pause_pid'
                                        'activate_timer',
                                        'deactivate_timer',
                                        'clear_total_volume',
                                        'input_force_measurements']:
            mod_action.do_unique_id = form.do_unique_id.data

        elif mod_action.action_type in ['setpoint_pid',
                                        'setpoint_pid_raise',
                                        'setpoint_pid_lower']:
            if not str_is_float(form.do_action_string.data):
                error.append("Setpoint value must be an integer or float value")
            mod_action.do_unique_id = form.do_unique_id.data
            mod_action.do_action_string = form.do_action_string.data

        elif mod_action.action_type == 'method_pid':
            mod_action.do_unique_id = form.do_unique_id.data
            mod_action.do_action_string = form.do_action_string.data

        elif mod_action.action_type == 'infrared_send':
            mod_action.remote = form.remote.data
            mod_action.code = form.code.data
            mod_action.send_times = form.send_times.data

        elif mod_action.action_type in ['email',
                                        'email_multiple']:
            mod_action.do_action_string = form.do_action_string.data

        elif mod_action.action_type in ['photo_email',
                                        'video_email']:
            mod_action.do_action_string = form.do_action_string.data
            mod_action.do_unique_id = form.do_unique_id.data
            mod_action.do_camera_duration = form.do_camera_duration.data

        elif mod_action.action_type in ['flash_lcd_on',
                                        'flash_lcd_off',
                                        'lcd_backlight_off',
                                        'lcd_backlight_on']:
            mod_action.do_unique_id = form.do_unique_id.data

        elif mod_action.action_type == 'photo':
            mod_action.do_unique_id = form.do_unique_id.data

        elif mod_action.action_type == 'video':
            mod_action.do_unique_id = form.do_unique_id.data
            mod_action.do_camera_duration = form.do_camera_duration.data

        elif mod_action.action_type in ['command',
                                        'create_note']:
            mod_action.do_action_string = form.do_action_string.data

        if not error:
            db.session.commit()

    except sqlalchemy.exc.OperationalError as except_msg:
        error.append(except_msg)
    except sqlalchemy.exc.IntegrityError as except_msg:
        error.append(except_msg)
    except Exception as except_msg:
        error.append(except_msg)

    flash_success_errors(error, action, url_for('routes_page.page_function'))
Ejemplo n.º 60
0
def lcd_display_mod(form):
    action = '{action} {controller}'.format(action=gettext("Mod"),
                                            controller=gettext("Display"))
    error = []

    lcd = LCD.query.filter(LCD.unique_id == form.lcd_id.data).first()
    if lcd.is_activated:
        error.append(
            gettext("Deactivate LCD controller before modifying"
                    " its settings."))

    if not error:
        try:
            mod_lcd = LCD.query.filter(
                LCD.unique_id == form.lcd_id.data).first()
            if mod_lcd.is_activated:
                flash(
                    gettext("Deactivate LCD controller before modifying"
                            " its settings."), "error")
                return redirect('/lcd')

            mod_lcd_data = LCDData.query.filter(
                LCDData.unique_id == form.lcd_data_id.data).first()

            if form.line_1_display.data:
                mod_lcd_data.line_1_id = form.line_1_display.data.split(",")[0]
                mod_lcd_data.line_1_measurement = form.line_1_display.data.split(
                    ",")[1]
                mod_lcd_data.line_1_max_age = form.line_1_max_age.data
                mod_lcd_data.line_1_decimal_places = form.line_1_decimal_places.data
            else:
                mod_lcd_data.line_1_id = ''
                mod_lcd_data.line_1_measurement = ''

            if form.line_2_display.data:
                mod_lcd_data.line_2_id = form.line_2_display.data.split(",")[0]
                mod_lcd_data.line_2_measurement = form.line_2_display.data.split(
                    ",")[1]
                mod_lcd_data.line_2_max_age = form.line_2_max_age.data
                mod_lcd_data.line_2_decimal_places = form.line_2_decimal_places.data
            else:
                mod_lcd_data.line_2_id = ''
                mod_lcd_data.line_2_measurement = ''

            if form.line_3_display.data:
                mod_lcd_data.line_3_id = form.line_3_display.data.split(",")[0]
                mod_lcd_data.line_3_measurement = form.line_3_display.data.split(
                    ",")[1]
                mod_lcd_data.line_3_max_age = form.line_3_max_age.data
                mod_lcd_data.line_3_decimal_places = form.line_3_decimal_places.data
            else:
                mod_lcd_data.line_3_id = ''
                mod_lcd_data.line_3_measurement = ''

            if form.line_4_display.data:
                mod_lcd_data.line_4_id = form.line_4_display.data.split(",")[0]
                mod_lcd_data.line_4_measurement = form.line_4_display.data.split(
                    ",")[1]
                mod_lcd_data.line_4_max_age = form.line_4_max_age.data
                mod_lcd_data.line_4_decimal_places = form.line_4_decimal_places.data
            else:
                mod_lcd_data.line_4_id = ''
                mod_lcd_data.line_4_measurement = ''

            db.session.commit()
        except Exception as except_msg:
            error.append(except_msg)
    flash_success_errors(error, action, url_for('routes_page.page_lcd'))