예제 #1
0
class InputAdd(FlaskForm):
    choices_inputs = [('', lazy_gettext('Select Input to Add'))]
    dict_inputs = parse_input_information()
    list_inputs_sorted = generate_form_input_list(dict_inputs)

    for each_input in list_inputs_sorted:
        if 'interfaces' not in dict_inputs[each_input]:
            choices_inputs.append(
                ('{inp},'.format(inp=each_input),
                 '{manuf}: {name}: {meas}'.format(
                     manuf=dict_inputs[each_input]['input_manufacturer'],
                     name=dict_inputs[each_input]['input_name'],
                     meas=dict_inputs[each_input]['measurements_name'])))
        else:
            for each_interface in dict_inputs[each_input]['interfaces']:
                choices_inputs.append(
                    ('{inp},{int}'.format(inp=each_input, int=each_interface),
                     '{manuf}: {name}: {meas} ({int})'.format(
                         manuf=dict_inputs[each_input]['input_manufacturer'],
                         name=dict_inputs[each_input]['input_name'],
                         meas=dict_inputs[each_input]['measurements_name'],
                         int=each_interface)))

    input_type = SelectField(choices=choices_inputs,
                             validators=[DataRequired()])
    input_add = SubmitField(lazy_gettext('Add Input'))
예제 #2
0
def get_installed_apt_dependencies():
    met_deps = []

    list_dependencies = [
        parse_function_information(),
        parse_action_information(),
        parse_input_information(),
        parse_output_information(),
        parse_widget_information(),
        CAMERA_INFO,
        FUNCTION_INFO,
        METHOD_INFO,
        DEPENDENCIES_GENERAL
    ]

    for each_section in list_dependencies:
        for device_type in each_section:
            if 'dependencies_module' in each_section[device_type]:
                dep_mod = each_section[device_type]['dependencies_module']
                for (install_type, package, install_id) in dep_mod:
                    if install_type == 'apt':
                        start = "dpkg-query -W -f='${Status}'"
                        end = '2>/dev/null | grep -c "ok installed"'
                        cmd = "{} {} {}".format(start, package, end)
                        _, _, status = cmd_output(cmd, user='******')
                        if not status and install_id not in met_deps:
                            met_deps.append(install_id)

    return met_deps
예제 #3
0
class InputAdd(FlaskForm):
    choices_inputs = []
    dict_inputs = parse_input_information()
    list_inputs_sorted = generate_form_input_list(dict_inputs)

    for each_input in list_inputs_sorted:
        value = '{inp},'.format(inp=each_input)
        name = '{manuf}: {name}'.format(
            manuf=dict_inputs[each_input]['input_manufacturer'],
            name=dict_inputs[each_input]['input_name'])

        if 'input_library' in dict_inputs[each_input]:
            name += ' ({lib})'.format(lib=dict_inputs[each_input]['input_library'])

        name += ': {meas}'.format(meas=dict_inputs[each_input]['measurements_name'])

        if 'interfaces' in dict_inputs[each_input]:
            for each_interface in dict_inputs[each_input]['interfaces']:
                tmp_value = '{val}{int}'.format(val=value, int=each_interface)
                tmp_name = '{name} ({int})'.format(name=name, int=each_interface)
                choices_inputs.append((tmp_value, tmp_name))
        else:
            choices_inputs.append((value, name))

    input_type = SelectField(
        choices=choices_inputs,
        validators=[DataRequired()]
    )
    input_add = SubmitField(TRANSLATIONS['add']['title'])
def get_installed_dependencies():
    met_deps = []

    dict_inputs = parse_input_information()

    list_dependencies = [
        dict_inputs,
        MATH_INFO,
        METHOD_INFO,
        OUTPUT_INFO
    ]
    for each_section in list_dependencies:
        for device_type in each_section:
            for each_device, each_dict in each_section[device_type].items():
                if each_device == 'dependencies_module':
                    for (install_type, package, install_id) in each_dict:
                        entry = '{0} {1}'.format(install_type, install_id)
                        if install_type in ['pip-pypi', 'pip-git']:
                            try:
                                module = importlib.util.find_spec(package)
                                if module is not None and entry not in met_deps:
                                    met_deps.append(entry)
                            except Exception:
                                logger.error(
                                    'Exception while checking python dependency: '
                                    '{dep}'.format(dep=package))
                        elif install_type == 'apt':
                            cmd = 'dpkg -l {}'.format(package)
                            _, _, stat = cmd_output(cmd)
                            if not stat and entry not in met_deps:
                                met_deps.append(entry)

    return met_deps
예제 #5
0
def get_installed_dependencies():
    met_deps = []

    list_dependencies = [
        parse_function_information(),
        parse_input_information(),
        parse_output_information(), CAMERA_INFO, FUNCTION_ACTION_INFO,
        FUNCTION_INFO, LCD_INFO, METHOD_INFO, DEPENDENCIES_GENERAL
    ]

    for each_section in list_dependencies:
        for device_type in each_section:
            if 'dependencies_module' in each_section[device_type]:
                dep_mod = each_section[device_type]['dependencies_module']
                for (install_type, package, install_id) in dep_mod:
                    entry = '{0} {1}'.format(install_type, install_id)
                    if install_type in ['pip-pypi', 'pip-git']:
                        try:
                            module = importlib.util.find_spec(package)
                            if module is not None and entry not in met_deps:
                                met_deps.append(entry)
                        except Exception:
                            logger.error(
                                'Exception checking python dependency: '
                                '{dep}'.format(dep=package))
                    elif install_type == 'apt':
                        start = "dpkg-query -W -f='${Status}'"
                        end = '2>/dev/null | grep -c "ok installed"'
                        cmd = "{} {} {}".format(start, package, end)
                        _, _, status = cmd_output(cmd, user='******')
                        if not status and entry not in met_deps:
                            met_deps.append(entry)

    return met_deps
예제 #6
0
def test_add_all_input_devices_logged_in_as_admin(_, testapp):
    """ Verifies adding all inputs as a logged in admin user """
    print("\nTest: test_add_all_input_devices_logged_in_as_admin")
    login_user(testapp, 'admin', '53CR3t_p4zZW0rD')

    # Add All Inputs
    input_count = 0

    dict_inputs = parse_input_information()
    list_inputs_sorted = generate_form_input_list(dict_inputs)

    choices_input = []
    for each_input in list_inputs_sorted:
        if 'interfaces' not in dict_inputs[each_input]:
            choices_input.append('{inp},'.format(inp=each_input))
        else:
            for each_interface in dict_inputs[each_input]['interfaces']:
                choices_input.append('{inp},{int}'.format(inp=each_input, int=each_interface))

    for index, each_input in enumerate(choices_input):
        choice_name = each_input.split(',')[0]
        print("test_add_all_input_devices_logged_in_as_admin: Adding, saving, and deleting Input ({}/{}): {}".format(
            index + 1, len(choices_input), each_input))
        response = add_data(testapp, input_type=each_input)
        assert 'data' in response.json
        assert 'messages' in response.json['data']
        assert 'error' in response.json['data']['messages']
        assert response.json['data']['messages']['error'] == []
        assert 'success' in response.json['data']['messages']
        assert len(response.json['data']['messages']['success']) == 1

        # Verify data was entered into the database
        input_count += 1
        assert Input.query.count() == input_count, "Number of Inputs doesn't match: In DB {}, Should be: {}".format(
            Input.query.count(), input_count)

        input_dev = Input.query.filter(Input.id == input_count).first()
        assert choice_name == input_dev.device, "Input name doesn't match: {}".format(choice_name)

        # Save input
        response = save_data(testapp, 'input', device_dev=input_dev)
        assert 'data' in response.json
        assert 'messages' in response.json['data']
        assert 'error' in response.json['data']['messages']
        assert response.json['data']['messages']['error'] == []
        assert 'success' in response.json['data']['messages']
        assert len(response.json['data']['messages']['success']) == 1

        # Delete input (speeds up further input addition checking)
        response = delete_data(testapp, 'input', device_dev=input_dev)
        assert 'data' in response.json
        assert 'messages' in response.json['data']
        assert 'error' in response.json['data']['messages']
        assert response.json['data']['messages']['error'] == []
        assert 'success' in response.json['data']['messages']
        assert len(response.json['data']['messages']['success']) == 1
        input_count -= 1
        assert Input.query.count() == input_count, "Number of Inputs doesn't match: In DB {}, Should be: {}".format(
            Input.query.count(), input_count)
예제 #7
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 = parse_custom_option_values(input_dev)

    #
    # 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 == 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']:
            value = custom_options_values[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_data'))
예제 #8
0
def choices_inputs(inputs):
    """ populate form multi-select choices from Input entries """
    choices = OrderedDict()
    dict_inputs = parse_input_information()

    for each_input in inputs:
        choices = form_input_choices(choices, each_input, dict_inputs)
    return choices
예제 #9
0
def test_add_all_data_devices_logged_in_as_admin(_, testapp):
    """ Verifies adding all inputs as a logged in admin user """
    login_user(testapp, 'admin', '53CR3t_p4zZW0rD')

    # Add All Inputs
    input_count = 0

    dict_inputs = parse_input_information()
    list_inputs_sorted = generate_form_input_list(dict_inputs)

    choices_input = []
    for each_input in list_inputs_sorted:
        if 'interfaces' not in dict_inputs[each_input]:
            choices_input.append('{inp},'.format(inp=each_input))
        else:
            for each_interface in dict_inputs[each_input]['interfaces']:
                choices_input.append('{inp},{int}'.format(inp=each_input,
                                                          int=each_interface))

    for each_input in choices_input:
        choice_name = each_input.split(',')[0]
        print("Testing {}".format(each_input))
        response = add_data(testapp, data_type='input', input_type=each_input)

        # Verify success message flashed
        assert "{} Input with ID".format(choice_name) in response
        assert "successfully added" in response

        # Verify data was entered into the database
        input_count += 1
        assert Input.query.count(
        ) == input_count, "Number of Inputs doesn't match: In DB {}, Should be: {}".format(
            Input.query.count(), input_count)

        input_dev = Input.query.filter(Input.id == input_count).first()
        assert dict_inputs[choice_name][
            'input_name'] in input_dev.name, "Input name doesn't match: {}".format(
                choice_name)

    # Add All Maths
    math_count = 0
    for each_math in MATH_INFO.keys():
        response = add_data(testapp, data_type='math', input_type=each_math)

        # Verify success message flashed
        assert "{} Math with ID".format(each_math) in response
        assert "successfully added" in response

        # Verify data was entered into the database
        math_count += 1
        actual_count = Math.query.count()
        assert actual_count == math_count, "Number of Maths don't match: In DB {}, Should be: {}".format(
            actual_count, math_count)

        math_dev = Math.query.filter(Math.id == math_count).first()
        assert each_math in math_dev.math_type, "Math type doesn't match: {}".format(
            each_math)
예제 #10
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

        if form.input_type.data == 'measurement_select':
            mod_meas.measurement = form.select_measurement_unit.data.split(',')[0]
            mod_meas.unit = form.select_measurement_unit.data.split(',')[1]

        elif form.input_type.data == 'measurement_convert':
            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'))
예제 #11
0
def test_add_all_data_devices_logged_in_as_admin(_, testapp):
    """ Verifies adding all inputs as a logged in admin user """
    login_user(testapp, 'admin', '53CR3t_p4zZW0rD')

    # Add All Inputs
    input_count = 0

    dict_inputs = parse_input_information()
    list_inputs_sorted = generate_form_input_list(dict_inputs)

    choices_input = []
    for each_input in list_inputs_sorted:
        if 'interfaces' not in dict_inputs[each_input]:
            choices_input.append('{inp},'.format(inp=each_input))
        else:
            for each_interface in dict_inputs[each_input]['interfaces']:
                choices_input.append('{inp},{int}'.format(inp=each_input, int=each_interface))

    for each_input in choices_input:
        choice_name = each_input.split(',')[0]
        print("Testing {}".format(each_input))
        response = add_data(testapp, data_type='input', input_type=each_input)

        # Verify success message flashed
        assert "{} Input with ID".format(choice_name) in response
        assert "successfully added" in response

        # Verify data was entered into the database
        input_count += 1
        assert Input.query.count() == input_count, "Number of Inputs doesn't match: In DB {}, Should be: {}".format(Input.query.count(), input_count)

        input_dev = Input.query.filter(Input.id == input_count).first()
        assert dict_inputs[choice_name]['input_name'] in input_dev.name, "Input name doesn't match: {}".format(choice_name)

    # Add All Maths
    math_count = 0
    for each_math in MATH_INFO.keys():
        response = add_data(testapp, data_type='math', input_type=each_math)

        # Verify success message flashed
        assert "{} Math with ID".format(each_math) in response
        assert "successfully added" in response

        # Verify data was entered into the database
        math_count += 1
        actual_count = Math.query.count()
        assert actual_count == math_count, "Number of Maths don't match: In DB {}, Should be: {}".format(actual_count, math_count)

        math_dev = Math.query.filter(Math.id == math_count).first()
        assert each_math in math_dev.math_type, "Math type doesn't match: {}".format(each_math)
예제 #12
0
def choices_lcd(inputs, maths, pids, outputs):
    choices = OrderedDict()
    dict_inputs = parse_input_information()

    # Display IP address
    value = '0000,IP'
    display = 'IP Address of Raspberry Pi'
    choices.update({value: display})

    # Inputs
    for each_input in inputs:
        value = '{id},input_time'.format(
            id=each_input.unique_id)
        display = '[Input {id:02d}] {name} (Timestamp)'.format(
            id=each_input.id,
            name=each_input.name)
        choices.update({value: display})
        choices = form_input_choices(choices, each_input, dict_inputs)

    # Maths
    for each_math in maths:
        value = '{id},math_time'.format(
            id=each_math.unique_id)
        display = '[Math {id:02d}] {name} (Timestamp)'.format(
            id=each_math.id,
            name=each_math.name)
        choices.update({value: display})
        choices = form_math_choices(choices, each_math)

    # PIDs
    for each_pid in pids:
        value = '{id},pid_time'.format(
            id=each_pid.unique_id)
        display = '[PID {id:02d}] {name} (Timestamp)'.format(
            id=each_pid.id,
            name=each_pid.name)
        choices.update({value: display})
        choices = form_pid_choices(choices, each_pid)

    # Outputs
    for each_output in outputs:
        value = '{id},pid_time'.format(
            id=each_output.unique_id)
        display = '[Output {id:02d}] {name} (Timestamp)'.format(
            id=each_output.id,
            name=each_output.name)
        choices.update({value: display})
        choices = form_output_choices(choices, each_output)

    return choices
예제 #13
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'))
예제 #14
0
def setup_atlas_flow():
    """
    Step-by-step tool for calibrating the Atlas Scientific RGB sensor
    """
    if not utils_general.user_has_permission('edit_controllers'):
        return redirect(url_for('routes_general.home'))

    form_flow_calibrate = forms_calibration.CalibrationAtlasFlow()

    input_dev = Input.query.filter(Input.device == 'ATLAS_FLOW').all()

    ui_stage = 'start'
    selected_input = None
    input_device_name = None
    complete_with_error = None

    # Begin calibration from Selected input
    if form_flow_calibrate.clear_calibration.data:
        selected_input = Input.query.filter_by(
            unique_id=form_flow_calibrate.selected_input_id.data).first()
        dict_inputs = parse_input_information()
        list_inputs_sorted = generate_form_input_list(dict_inputs)
        if not selected_input:
            flash(
                'Input not found: {}'.format(
                    form_flow_calibrate.selected_input_id.data), 'error')
        else:
            for each_input in list_inputs_sorted:
                if selected_input.device == each_input[0]:
                    input_device_name = each_input[1]
        if selected_input.is_activated:
            control = DaemonControl()
            return_status, return_string = control.input_atlas_flow_clear_total_volume(
                selected_input.unique_id)
        else:
            atlas_command = AtlasScientificCommand(selected_input)
            return_status, return_string = atlas_command.send_command('Clear')
        if return_status:
            complete_with_error = return_string
        ui_stage = 'complete'

    return render_template('tools/calibration_options/atlas_flow.html',
                           complete_with_error=complete_with_error,
                           form_flow_calibrate=form_flow_calibrate,
                           input=input_dev,
                           input_device_name=input_device_name,
                           selected_input=selected_input,
                           ui_stage=ui_stage)
예제 #15
0
def test_add_all_data_devices_logged_in_as_admin(_, testapp):
    """ Verifies adding all inputs as a logged in admin user """
    login_user(testapp, 'admin', '53CR3t_p4zZW0rD')

    # Add All Inputs
    input_count = 0
    for each_input, each_data in parse_input_information().items():
        for each_interface in each_data['interfaces']:
            response = add_data(testapp,
                                data_type='input',
                                input_type='{},{}'.format(
                                    each_input, each_interface))

            # Verify success message flashed
            assert "{} Input with ID".format(each_input) in response
            assert "successfully added" in response

            # Verify data was entered into the database
            input_count += 1
            assert Input.query.count(
            ) == input_count, "Number of Inputs doesn't match: In DB {}, Should be: {}".format(
                Input.query.count(), input_count)

            input_dev = Input.query.filter(Input.id == input_count).first()
            assert each_data[
                'input_name'] in input_dev.name, "Input name doesn't match: {}".format(
                    each_input)

    # Add All Maths
    math_count = 0
    for each_math, each_data in MATH_INFO.items():
        response = add_data(testapp, data_type='math', input_type=each_math)

        # Verify success message flashed
        assert "{} Math with ID".format(each_math) in response
        assert "successfully added" in response

        # Verify data was entered into the database
        math_count += 1
        actual_count = Math.query.count()
        assert actual_count == math_count, "Number of Maths doesn't match: In DB {}, Should be: {}".format(
            actual_count, math_count)

        math_dev = Math.query.filter(Math.id == math_count).first()
        assert each_data[
            'name'] in math_dev.name, "Math name doesn't match: {}".format(
                each_math)
예제 #16
0
def get_installed_dependencies():
    met_deps = []

    list_dependencies = [
        parse_controller_information(),
        parse_input_information(),
        parse_output_information(),
        CALIBRATION_INFO,
        CAMERA_INFO,
        FUNCTION_ACTION_INFO,
        FUNCTION_INFO,
        LCD_INFO,
        MATH_INFO,
        METHOD_INFO,
    ]

    for each_section in list_dependencies:
        for device_type in each_section:
            if 'dependencies_module' in each_section[device_type]:
                dep_mod = each_section[device_type]['dependencies_module']
                for (install_type, package, install_id) in dep_mod:
                    entry = '{0} {1}'.format(install_type, install_id)
                    if install_type in ['pip-pypi', 'pip-git']:
                        try:
                            module = importlib.util.find_spec(package)
                            if module is not None and entry not in met_deps:
                                met_deps.append(entry)
                        except Exception:
                            logger.error(
                                'Exception checking python dependency: '
                                '{dep}'.format(dep=package))
                    elif install_type == 'apt':
                        cmd = 'dpkg -l {}'.format(package)
                        _, _, status = cmd_output(cmd, user='******')
                        if not status and entry not in met_deps:
                            met_deps.append(entry)

    return met_deps
예제 #17
0
def setup_atlas_ec():
    """
    Step-by-step tool for calibrating the Atlas Scientific EC sensor
    """
    if not utils_general.user_has_permission('edit_controllers'):
        return redirect(url_for('routes_general.home'))

    form_ec_calibrate = forms_calibration.CalibrationAtlasEC()

    input_dev = Input.query.filter(Input.device == 'ATLAS_EC').all()

    ui_stage = 'start'
    backend_stage = None
    next_stage = None
    selected_input = None
    selected_point_calibration = None
    input_device_name = None
    complete_with_error = None

    if form_ec_calibrate.hidden_current_stage.data:
        backend_stage = form_ec_calibrate.hidden_current_stage.data

    if form_ec_calibrate.hidden_selected_point_calibration.data:
        selected_point_calibration = form_ec_calibrate.hidden_selected_point_calibration.data
    elif form_ec_calibrate.point_calibration.data:
        selected_point_calibration = form_ec_calibrate.point_calibration.data

    if selected_point_calibration:
        list_point_calibrations = selected_point_calibration.split(',')
    else:
        list_point_calibrations = []

    if form_ec_calibrate.point_low_uS.data:
        point_low_uS = form_ec_calibrate.point_low_uS.data
    else:
        point_low_uS = form_ec_calibrate.hidden_point_low_uS.data

    if form_ec_calibrate.point_high_uS.data:
        point_high_uS = form_ec_calibrate.point_high_uS.data
    else:
        point_high_uS = form_ec_calibrate.hidden_point_high_uS.data

    # Begin calibration from Selected input
    if form_ec_calibrate.start_calibration.data:
        ui_stage = 'point_enter_uS'
        selected_input = Input.query.filter_by(
            unique_id=form_ec_calibrate.selected_input_id.data).first()
        dict_inputs = parse_input_information()
        list_inputs_sorted = generate_form_input_list(dict_inputs)
        if not selected_input:
            flash(
                'Input not found: {}'.format(
                    form_ec_calibrate.selected_input_id.data), 'error')
        else:
            for each_input in list_inputs_sorted:
                if selected_input.device == each_input[0]:
                    input_device_name = each_input[1]

    # Continue calibration from selected input
    elif (form_ec_calibrate.go_to_next_stage.data
          or form_ec_calibrate.go_to_last_stage.data
          or (backend_stage is not None
              and backend_stage not in ['start', 'point_enter_uS'])):
        selected_input = Input.query.filter_by(
            unique_id=form_ec_calibrate.hidden_input_id.data).first()
        dict_inputs = parse_input_information()
        list_inputs_sorted = generate_form_input_list(dict_inputs)
        for each_input in list_inputs_sorted:
            if selected_input.device == each_input[0]:
                input_device_name = each_input[1]

    if backend_stage in ['point_enter_uS', 'dry', 'low', 'high']:
        time.sleep(2)  # Sleep makes querying sensor more stable

        # Determine next ui_stage
        if backend_stage == 'point_enter_uS':
            next_stage = 'dry'
            logger.error("next_stage: {}".format(next_stage))
        elif backend_stage == 'dry':
            next_stage = list_point_calibrations[0]
            logger.error("next_stage: {}".format(next_stage))
        else:
            current_stage_index = list_point_calibrations.index(backend_stage)
            if current_stage_index == len(list_point_calibrations) - 1:
                next_stage = 'complete'
            else:
                next_stage = list_point_calibrations[current_stage_index + 1]

    if backend_stage == 'point_enter_uS':
        ui_stage = next_stage
        complete_with_error = None
    elif backend_stage == 'dry':
        ui_stage, complete_with_error = dual_commands_to_sensor(
            selected_input,
            'ec_dry',
            None,
            'continuous',
            current_stage='dry',
            next_stage=next_stage)
    elif backend_stage == 'low':
        ui_stage, complete_with_error = dual_commands_to_sensor(
            selected_input,
            'ec_low',
            point_low_uS,
            'continuous',
            current_stage='low',
            next_stage=next_stage)
    elif backend_stage == 'high':
        ui_stage, complete_with_error = dual_commands_to_sensor(
            selected_input,
            'ec_high',
            point_high_uS,
            'end',
            current_stage='high',
            next_stage=next_stage)

    return render_template(
        'tools/calibration_options/atlas_ec.html',
        complete_with_error=complete_with_error,
        form_ec_calibrate=form_ec_calibrate,
        input=input_dev,
        input_device_name=input_device_name,
        point_high_uS=point_high_uS,
        point_low_uS=point_low_uS,
        selected_input=selected_input,
        selected_point_calibration=selected_point_calibration,
        ui_stage=ui_stage)
예제 #18
0
def measurement_mod(form):
    messages = {"success": [], "info": [], "warning": [], "error": []}
    mod_device = None
    device_info = None

    try:
        mod_meas = DeviceMeasurements.query.filter(
            DeviceMeasurements.unique_id == form.measurement_id.data).first()
        if not mod_meas:
            messages["error"].append("Count not found measurement")

        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_Custom":
            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:
            messages["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:
                messages["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.rescale_method = form.rescale_method.data
            mod_meas.rescale_equation = form.rescale_equation.data
            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 messages["error"]:
            db.session.commit()
            messages["success"].append("Measurement settings saved")

    except Exception as except_msg:
        logger.exception(1)
        messages["error"].append(str(except_msg))

    return messages
예제 #19
0
def return_dependencies(device_type):
    unmet_deps = []
    met_deps = False

    dict_inputs = parse_input_information()

    list_dependencies = [
        dict_inputs,
        FUNCTION_ACTION_INFO,
        FUNCTION_INFO,
        LCD_INFO,
        MATH_INFO,
        METHOD_INFO,
        OUTPUT_INFO,
        CALIBRATION_INFO
    ]
    for each_section in list_dependencies:
        if device_type in each_section:
            for each_device, each_dict in each_section[device_type].items():
                if not each_dict:
                    met_deps = True
                elif each_device == 'dependencies_module':
                    for (install_type, package, install_id) in each_dict:
                        entry = (
                            package, '{0} {1}'.format(install_type, install_id),
                            install_type,
                            install_id
                        )
                        if install_type in ['pip-pypi', 'pip-git']:
                            try:
                                module = importlib.util.find_spec(package)
                                if module is None:
                                    if entry not in unmet_deps:
                                        unmet_deps.append(entry)
                                else:
                                    met_deps = True
                            except ImportError:
                                if entry not in unmet_deps:
                                    unmet_deps.append(entry)
                        elif install_type == 'apt':
                            if (not dpkg_package_exists(package) and
                                    entry not in unmet_deps):
                                unmet_deps.append(entry)
                            else:
                                met_deps = True
                        elif install_type == 'internal':
                            if package.startswith('file-exists'):
                                filepath = package.split(' ', 1)[1]
                                if not os.path.isfile(filepath):
                                    if entry not in unmet_deps:
                                        unmet_deps.append(entry)
                                    else:
                                        met_deps = True
                            elif package.startswith('pip-exists'):
                                py_module = package.split(' ', 1)[1]
                                try:
                                    module = importlib.util.find_spec(py_module)
                                    if module is None:
                                        if entry not in unmet_deps:
                                            unmet_deps.append(entry)
                                    else:
                                        met_deps = True
                                except ImportError:
                                    if entry not in unmet_deps:
                                        unmet_deps.append(entry)
                            elif package.startswith('apt'):
                                if (not dpkg_package_exists(package) and
                                        entry not in unmet_deps):
                                    unmet_deps.append(entry)
                                else:
                                    met_deps = True

    return unmet_deps, met_deps
예제 #20
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 (mod_input.device != 'EDGE' 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"))

        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:
            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.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
        mod_input.period = form_mod.period.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

        # Custom options
        list_options = []
        if 'custom_options' in dict_inputs[mod_input.device]:
            for each_option in dict_inputs[mod_input.device]['custom_options']:
                null_value = True
                for key in request_form.keys():
                    if each_option['id'] == key:
                        constraints_pass = True
                        constraints_errors = []
                        value = None
                        if each_option['type'] == 'float':
                            if str_is_float(request_form.get(key)):
                                if 'constraints_pass' in each_option:
                                    (constraints_pass,
                                     constraints_errors,
                                     mod_input) = each_option['constraints_pass'](
                                        mod_input, float(request_form.get(key)))
                                if constraints_pass:
                                    value = float(request_form.get(key))
                            else:
                                error.append(
                                    "{name} must represent a float/decimal value "
                                    "(submitted '{value}')".format(
                                        name=each_option['name'],
                                        value=request_form.get(key)))

                        elif each_option['type'] == 'integer':
                            if is_int(request_form.get(key)):
                                if 'constraints_pass' in each_option:
                                    (constraints_pass,
                                     constraints_errors,
                                     mod_input) = each_option['constraints_pass'](
                                        mod_input, int(request_form.get(key)))
                                if constraints_pass:
                                    value = int(request_form.get(key))
                            else:
                                error.append(
                                    "{name} must represent an integer value "
                                    "(submitted '{value}')".format(
                                        name=each_option['name'],
                                        value=request_form.get(key)))

                        elif each_option['type'] in ['text', 'select']:
                            if 'constraints_pass' in each_option:
                                (constraints_pass,
                                 constraints_errors,
                                 mod_input) = each_option['constraints_pass'](
                                    mod_input, request_form.get(key))
                            if constraints_pass:
                                value = request_form.get(key)

                        elif each_option['type'] == 'bool':
                            value = bool(request_form.get(key))

                        for each_error in constraints_errors:
                            error.append(
                                "Error: {name}: {error}".format(
                                    name=each_option['name'],
                                    error=each_error))

                        if value:
                            null_value = False
                            option = '{id},{value}'.format(
                                id=key,
                                value=value)
                            list_options.append(option)

                if null_value:
                    option = '{id},'.format(id=each_option['id'])
                    list_options.append(option)

        mod_input.custom_options = ';'.join(list_options)

        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_data'))
예제 #21
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

        if GPIO.RPI_INFO['P1_REVISION'] in [2, 3]:
            new_input.i2c_bus = 1
        else:
            new_input.i2c_bus = 0

        if 'input_name' in dict_inputs[input_name]:
            new_input.name = dict_inputs[input_name]['input_name']
        else:
            new_input.name = 'Input 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
            #

            # I2C 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

            # UART options
            if dict_has_value('uart_location'):
                new_input.uart_location = dict_inputs[input_name]['uart_location']
            if dict_has_value('ftdi_location'):
                new_input.uart_location = dict_inputs[input_name]['ftdi_location']
            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'):
                    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
        #

        list_options = []
        if 'custom_options' in dict_inputs[input_name]:
            for each_option in dict_inputs[input_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_input.custom_options = ';'.join(list_options)

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

                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_data'))
    else:
        flash_form_errors(form_add)

    if dep_unmet:
        return 1
예제 #22
0
    def initialize_variables(self):
        self.dict_inputs = parse_input_information()

        self.sample_rate = db_retrieve_table_daemon(
            Misc, entry='first').sample_rate_controller_input

        input_dev = db_retrieve_table_daemon(Input, unique_id=self.unique_id)

        self.device_measurements = db_retrieve_table_daemon(
            DeviceMeasurements).filter(
                DeviceMeasurements.device_id == self.unique_id)

        self.conversions = db_retrieve_table_daemon(Conversion)

        self.input_dev = input_dev
        self.input_name = input_dev.name
        self.unique_id = input_dev.unique_id
        self.log_level_debug = input_dev.log_level_debug
        self.gpio_location = input_dev.gpio_location
        self.device = input_dev.device
        self.interface = input_dev.interface
        self.period = input_dev.period
        self.start_offset = input_dev.start_offset

        # Edge detection
        self.switch_edge = input_dev.switch_edge
        self.switch_bouncetime = input_dev.switch_bouncetime
        self.switch_reset_period = input_dev.switch_reset_period

        # Pre-Output: Activates prior to input measurement
        self.pre_output_id = input_dev.pre_output_id
        self.pre_output_duration = input_dev.pre_output_duration
        self.pre_output_during_measure = input_dev.pre_output_during_measure
        self.pre_output_setup = False
        self.last_measurement = 0
        self.next_measurement = time.time() + self.start_offset
        self.get_new_measurement = False
        self.trigger_cond = False
        self.measurement_acquired = False
        self.pre_output_activated = False
        self.pre_output_locked = False
        self.pre_output_timer = time.time()

        self.set_log_level_debug(self.log_level_debug)

        # Check if Pre-Output ID actually exists
        output = db_retrieve_table_daemon(Output, entry='all')
        for each_output in output:
            if (each_output.unique_id == self.pre_output_id
                    and self.pre_output_duration):
                self.pre_output_setup = True

        smtp = db_retrieve_table_daemon(SMTP, entry='first')
        self.smtp_max_count = smtp.hourly_max
        self.email_count = 0
        self.allowed_to_send_notice = True

        # Set up input lock
        self.input_lock = None
        self.lock_file = '/var/lock/input_pre_output_{id}'.format(
            id=self.pre_output_id)

        # Convert string I2C address to base-16 int
        if self.interface == 'I2C':
            self.i2c_address = int(str(self.input_dev.i2c_location), 16)

        # Set up edge detection of a GPIO pin
        if self.device == 'EDGE':
            if self.switch_edge == 'rising':
                self.switch_edge_gpio = GPIO.RISING
            elif self.switch_edge == 'falling':
                self.switch_edge_gpio = GPIO.FALLING
            else:
                self.switch_edge_gpio = GPIO.BOTH

        self.device_recognized = True

        if self.device in self.dict_inputs:
            input_loaded = load_module_from_file(
                self.dict_inputs[self.device]['file_path'], 'inputs')

            if self.device == 'EDGE':
                # Edge detection handled internally, no module to load
                self.measure_input = None
            else:
                self.measure_input = input_loaded.InputModule(self.input_dev)

        else:
            self.device_recognized = False
            self.logger.debug(
                "Device '{device}' not recognized".format(device=self.device))
            raise Exception("'{device}' is not a valid device type.".format(
                device=self.device))

        self.edge_reset_timer = time.time()
        self.input_timer = time.time()
        self.lastUpdate = None

        # Set up edge detection
        if self.device == 'EDGE':
            GPIO.setmode(GPIO.BCM)
            GPIO.setup(int(self.gpio_location), GPIO.IN)
            GPIO.add_event_detect(int(self.gpio_location),
                                  self.switch_edge_gpio,
                                  callback=self.edge_detected,
                                  bouncetime=self.switch_bouncetime)

        # Set up MQTT listener
        elif ('listener' in self.dict_inputs[self.device]
              and self.dict_inputs[self.device]['listener']):
            input_listener = threading.Thread(
                target=self.measure_input.listener())
            input_listener.daemon = True
            input_listener.start()
예제 #23
0
    def __init__(self, ready, input_id):
        threading.Thread.__init__(self)

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

        self.stop_iteration_counter = 0
        self.thread_startup_timer = timeit.default_timer()
        self.thread_shutdown_timer = 0
        self.ready = ready
        self.lock = {}
        self.measurement = None
        self.measurement_success = False
        self.control = DaemonControl()
        self.pause_loop = False
        self.verify_pause_loop = True
        self.force_measurements_trigger = False

        self.dict_inputs = parse_input_information()

        self.sample_rate = db_retrieve_table_daemon(
            Misc, entry='first').sample_rate_controller_input

        self.input_id = input_id
        input_dev = db_retrieve_table_daemon(
            Input, unique_id=self.input_id)

        self.device_measurements = db_retrieve_table_daemon(
            DeviceMeasurements).filter(
                DeviceMeasurements.device_id == self.input_id)

        self.conversions = db_retrieve_table_daemon(Conversion)

        self.input_dev = input_dev
        self.input_name = input_dev.name
        self.unique_id = input_dev.unique_id
        self.gpio_location = input_dev.gpio_location
        self.device = input_dev.device
        self.interface = input_dev.interface
        self.period = input_dev.period

        # Edge detection
        self.switch_edge = input_dev.switch_edge
        self.switch_bouncetime = input_dev.switch_bouncetime
        self.switch_reset_period = input_dev.switch_reset_period

        # Pre-Output: Activates prior to input measurement
        self.pre_output_id = input_dev.pre_output_id
        self.pre_output_duration = input_dev.pre_output_duration
        self.pre_output_during_measure = input_dev.pre_output_during_measure
        self.pre_output_setup = False
        self.next_measurement = time.time()
        self.get_new_measurement = False
        self.trigger_cond = False
        self.measurement_acquired = False
        self.pre_output_activated = False
        self.pre_output_locked = False
        self.pre_output_timer = time.time()

        # Check if Pre-Output ID actually exists
        output = db_retrieve_table_daemon(Output, entry='all')
        for each_output in output:
            if each_output.unique_id == self.pre_output_id and self.pre_output_duration:
                self.pre_output_setup = True

        smtp = db_retrieve_table_daemon(SMTP, entry='first')
        self.smtp_max_count = smtp.hourly_max
        self.email_count = 0
        self.allowed_to_send_notice = True

        # Set up input lock
        self.input_lock = None
        self.lock_file = '/var/lock/input_pre_output_{id}'.format(id=self.pre_output_id)

        # Convert string I2C address to base-16 int
        if self.interface == 'I2C':
            self.i2c_address = int(str(self.input_dev.i2c_location), 16)

        # Set up edge detection of a GPIO pin
        if self.device == 'EDGE':
            if self.switch_edge == 'rising':
                self.switch_edge_gpio = GPIO.RISING
            elif self.switch_edge == 'falling':
                self.switch_edge_gpio = GPIO.FALLING
            else:
                self.switch_edge_gpio = GPIO.BOTH

        self.device_recognized = True

        if self.device in self.dict_inputs:
            input_loaded = load_module_from_file(self.dict_inputs[self.device]['file_path'])

            if self.device == 'EDGE':
                # Edge detection handled internally, no module to load
                self.measure_input = None
            else:
                self.measure_input = input_loaded.InputModule(self.input_dev)

        else:
            self.device_recognized = False
            self.logger.debug("Device '{device}' not recognized".format(
                device=self.device))
            raise Exception("'{device}' is not a valid device type.".format(
                device=self.device))

        self.edge_reset_timer = time.time()
        self.input_timer = time.time()
        self.running = False
        self.lastUpdate = None
예제 #24
0
def input_mod(form_mod, request_form):
    messages = {
        "success": [],
        "info": [],
        "warning": [],
        "error": [],
        "name": None,
        "return_text": []
    }
    page_refresh = False

    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:
            messages["error"].append(
                gettext("Deactivate controller before modifying its settings"))

        if (mod_input.device == 'AM2315' and form_mod.period.data < 7):
            messages["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 form_mod.pre_output_duration.data
                and form_mod.pre_output_id.data
                and form_mod.period.data < form_mod.pre_output_duration.data):
            messages["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)):
            messages["warning"].append(
                gettext(
                    "Invalid device or improper permissions to read device"))

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

        mod_input.name = form_mod.name.data
        messages["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)

        # Save Measurement settings
        messages, page_refresh = utils_measurement.measurement_mod_form(
            messages, page_refresh, request_form)

        # 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:
                page_refresh = True

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

                    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 > form_mod.num_channels.data:
                                    delete_entry_with_id(
                                        InputChannel,
                                        each_channel.unique_id,
                                        flash_message=False)

                # 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

                            messages[
                                "error"], custom_options = custom_channel_options_return_json(
                                    messages["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
        messages[
            "error"], custom_options_json_postsave = custom_options_return_json(
                messages["error"],
                dict_inputs,
                request_form,
                mod_dev=mod_input,
                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():
            messages[
                "error"], custom_options_channels_json_postsave_tmp = custom_channel_options_return_json(
                    messages["error"],
                    dict_inputs,
                    request_form,
                    form_mod.input_id.data,
                    each_channel.channel,
                    device=mod_input.device,
                    use_defaults=False)
            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
            (messages, mod_input, custom_options_dict,
             custom_options_channels_dict
             ) = dict_inputs[mod_input.device]['execute_at_modification'](
                 messages, 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
        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 messages["error"]:
            db.session.commit()
            messages["success"].append(
                f"{TRANSLATIONS['modify']['title']} {TRANSLATIONS['input']['title']}"
            )

    except Exception as except_msg:
        logger.exception("input_mod")
        messages["error"].append(str(except_msg))

    return messages, page_refresh
예제 #25
0
def input_add(form_add):
    messages = {"success": [], "info": [], "warning": [], "error": []}
    new_input_id = None
    list_unmet_deps = []
    dep_name = None
    dep_message = ''

    dict_inputs = parse_input_information()

    # only one comma should be in the input_type string
    if form_add.input_type.data.count(',') > 1:
        messages["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 = ''
        messages["error"].append(
            "Invalid input string (must be a comma-separated string)")

    if not current_app.config['TESTING']:
        dep_unmet, _, dep_message = return_dependencies(input_name)
        if dep_unmet:
            for each_dep in dep_unmet:
                list_unmet_deps.append(each_dep[3])
            messages["error"].append(
                f"{input_name} has unmet dependencies. They must be installed before the Input can be added."
            )
            if input_name in dict_inputs:
                dep_name = dict_inputs[input_name]['input_name']
            else:
                messages["error"].append(f"Input not found: {input_name}")

            return messages, dep_name, list_unmet_deps, dep_message, None

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

        if input_interface:
            new_input.interface = input_interface

        new_input.i2c_bus = 1

        if 'input_name_short' in dict_inputs[input_name]:
            new_input.name = dict_inputs[input_name]['input_name_short']
        elif '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']):
                        messages["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
        messages["error"], custom_options = custom_options_return_json(
            messages["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']):
            messages["error"], new_input = dict_inputs[
                new_input.device]['execute_at_creation'](
                    messages["error"], new_input,
                    dict_inputs[new_input.device])

        try:
            if not messages["error"]:
                new_input.save()
                new_input_id = new_input.unique_id

                #
                # 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
                        messages[
                            "error"], custom_options = custom_channel_options_return_json(
                                messages["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()

                messages["success"].append(
                    f"{TRANSLATIONS['add']['title']} {TRANSLATIONS['input']['title']}"
                )
        except sqlalchemy.exc.OperationalError as except_msg:
            messages["error"].append(except_msg)
        except sqlalchemy.exc.IntegrityError as except_msg:
            messages["error"].append(except_msg)

    else:
        for field, errors in form_add.errors.items():
            for error in errors:
                messages["error"].append(
                    gettext("Error in the %(field)s field - %(err)s",
                            field=getattr(form_add, field).label.text,
                            err=error))

    return messages, dep_name, list_unmet_deps, dep_message, new_input_id
예제 #26
0
    def __init__(self, ready, input_id):
        threading.Thread.__init__(self)

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

        self.stop_iteration_counter = 0
        self.thread_startup_timer = timeit.default_timer()
        self.thread_shutdown_timer = 0
        self.ready = ready
        self.lock = {}
        self.measurement = None
        self.measurement_success = False
        self.control = DaemonControl()
        self.pause_loop = False
        self.verify_pause_loop = True
        self.force_measurements_trigger = False

        self.dict_inputs = parse_input_information()

        self.sample_rate = db_retrieve_table_daemon(
            Misc, entry='first').sample_rate_controller_input

        self.input_id = input_id
        input_dev = db_retrieve_table_daemon(
            Input, unique_id=self.input_id)

        self.device_measurements = db_retrieve_table_daemon(
            DeviceMeasurements).filter(
                DeviceMeasurements.device_id == self.input_id)

        self.conversions = db_retrieve_table_daemon(Conversion)

        self.input_dev = input_dev
        self.input_name = input_dev.name
        self.unique_id = input_dev.unique_id
        self.gpio_location = input_dev.gpio_location
        self.device = input_dev.device
        self.interface = input_dev.interface
        self.period = input_dev.period

        # Edge detection
        self.switch_edge = input_dev.switch_edge
        self.switch_bouncetime = input_dev.switch_bouncetime
        self.switch_reset_period = input_dev.switch_reset_period

        # Pre-Output: Activates prior to input measurement
        self.pre_output_id = input_dev.pre_output_id
        self.pre_output_duration = input_dev.pre_output_duration
        self.pre_output_during_measure = input_dev.pre_output_during_measure
        self.pre_output_setup = False
        self.next_measurement = time.time()
        self.get_new_measurement = False
        self.trigger_cond = False
        self.measurement_acquired = False
        self.pre_output_activated = False
        self.pre_output_locked = False
        self.pre_output_timer = time.time()

        # Check if Pre-Output ID actually exists
        output = db_retrieve_table_daemon(Output, entry='all')
        for each_output in output:
            if each_output.unique_id == self.pre_output_id and self.pre_output_duration:
                self.pre_output_setup = True

        smtp = db_retrieve_table_daemon(SMTP, entry='first')
        self.smtp_max_count = smtp.hourly_max
        self.email_count = 0
        self.allowed_to_send_notice = True

        # Set up input lock
        self.input_lock = None
        self.lock_file = '/var/lock/input_pre_output_{id}'.format(id=self.pre_output_id)

        # Convert string I2C address to base-16 int
        if self.interface == 'I2C':
            self.i2c_address = int(str(self.input_dev.i2c_location), 16)

        # Set up edge detection of a GPIO pin
        if self.device == 'EDGE':
            if self.switch_edge == 'rising':
                self.switch_edge_gpio = GPIO.RISING
            elif self.switch_edge == 'falling':
                self.switch_edge_gpio = GPIO.FALLING
            else:
                self.switch_edge_gpio = GPIO.BOTH

        self.device_recognized = True

        if self.device in self.dict_inputs:
            input_loaded = load_module_from_file(self.dict_inputs[self.device]['file_path'])

            if self.device == 'EDGE':
                # Edge detection handled internally, no module to load
                self.measure_input = None
            else:
                self.measure_input = input_loaded.InputModule(self.input_dev)

        else:
            self.device_recognized = False
            self.logger.debug("Device '{device}' not recognized".format(
                device=self.device))
            raise Exception("'{device}' is not a valid device type.".format(
                device=self.device))

        self.edge_reset_timer = time.time()
        self.input_timer = time.time()
        self.running = False
        self.lastUpdate = None
예제 #27
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'):
                    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']):
            new_input = dict_inputs[new_input.device]['execute_at_creation'](
                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()

                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_data'))
    else:
        flash_form_errors(form_add)

    if dep_unmet:
        return 1
예제 #28
0
 def input_information_update(self):
     try:
         self.dict_input_information = parse_input_information()
     except Exception:
         self.logger.exception("Exception while parsing inputs")
예제 #29
0
def setup_atlas_ph():
    """
    Step-by-step tool for calibrating the Atlas Scientific pH sensor
    """
    if not utils_general.user_has_permission('edit_controllers'):
        return redirect(url_for('routes_general.home'))

    form_ph_calibrate = forms_calibration.CalibrationAtlasph()

    input_dev = Input.query.filter(Input.device == 'ATLAS_PH').all()

    ui_stage = 'start'
    backend_stage = None
    next_stage = None
    selected_input = None
    selected_point_calibration = None
    input_device_name = None
    complete_with_error = None

    if form_ph_calibrate.hidden_current_stage.data:
        backend_stage = form_ph_calibrate.hidden_current_stage.data

    if form_ph_calibrate.hidden_selected_point_calibration.data:
        selected_point_calibration = form_ph_calibrate.hidden_selected_point_calibration.data
    elif form_ph_calibrate.point_calibration.data:
        selected_point_calibration = form_ph_calibrate.point_calibration.data

    if selected_point_calibration:
        list_point_calibrations = selected_point_calibration.split(',')
    else:
        list_point_calibrations = []

    # Clear Calibration memory
    if form_ph_calibrate.clear_calibration.data:
        selected_input = Input.query.filter_by(
            unique_id=form_ph_calibrate.selected_input_id.data).first()
        atlas_command = AtlasScientificCommand(selected_input)
        status, message = atlas_command.calibrate('clear_calibration')

        sensor_measurement = atlas_command.get_sensor_measurement()

        if isinstance(message, tuple):
            message_status = message[0]
            message_info = message[1]
            message = "Calibration command returned from sensor: {}".format(
                message_status)
            if message_info:
                message += ": {}".format(message_info)
        else:
            message = "Calibration command returned from sensor: {}".format(
                message)

        if sensor_measurement != 'NA':
            message = "{} {}".format(sensor_measurement, message)

        if status:
            flash(message, "error")
        else:
            flash(message, "success")

    # Begin calibration from Selected input
    elif form_ph_calibrate.start_calibration.data:
        ui_stage = 'temperature'
        selected_input = Input.query.filter_by(
            unique_id=form_ph_calibrate.selected_input_id.data).first()
        dict_inputs = parse_input_information()
        list_inputs_sorted = generate_form_input_list(dict_inputs)
        if not selected_input:
            flash(
                'Input not found: {}'.format(
                    form_ph_calibrate.selected_input_id.data), 'error')
        else:
            for each_input in list_inputs_sorted:
                if selected_input.device == each_input[0]:
                    input_device_name = each_input[1]

    # Continue calibration from selected input
    elif (form_ph_calibrate.go_to_next_stage.data
          or form_ph_calibrate.go_to_last_stage.data
          or (backend_stage is not None
              and backend_stage not in ['start', 'temperature'])):
        selected_input = Input.query.filter_by(
            unique_id=form_ph_calibrate.hidden_input_id.data).first()
        dict_inputs = parse_input_information()
        list_inputs_sorted = generate_form_input_list(dict_inputs)
        for each_input in list_inputs_sorted:
            if selected_input.device == each_input[0]:
                input_device_name = each_input[1]

    if backend_stage in ['temperature', 'low', 'mid', 'high']:
        time.sleep(2)  # Sleep makes querying sensor more stable

        # Determine next ui_stage
        if backend_stage == 'temperature':
            next_stage = list_point_calibrations[0]
            logger.error("next_stage: {}".format(next_stage))
        else:
            current_stage_index = list_point_calibrations.index(backend_stage)
            if current_stage_index == len(list_point_calibrations) - 1:
                next_stage = 'complete'
            else:
                next_stage = list_point_calibrations[current_stage_index + 1]

    if form_ph_calibrate.clear_calibration.data:
        pass
    elif backend_stage == 'temperature':
        if form_ph_calibrate.temperature.data is None:
            flash(
                gettext(
                    "A valid temperature is required: %(temp)s is invalid.",
                    temp=form_ph_calibrate.temperature.data), "error")
            ui_stage = 'start'
        else:
            temp = '{temp:.2f}'.format(
                temp=float(form_ph_calibrate.temperature.data))
            ui_stage, complete_with_error = dual_commands_to_sensor(
                selected_input,
                'temperature',
                temp,
                'continuous',
                current_stage='temperature',
                next_stage=next_stage)
    elif backend_stage == 'low':
        ui_stage, complete_with_error = dual_commands_to_sensor(
            selected_input,
            'low',
            '4.0',
            'continuous',
            current_stage='low',
            next_stage=next_stage)
    elif backend_stage == 'mid':
        ui_stage, complete_with_error = dual_commands_to_sensor(
            selected_input,
            'mid',
            '7.0',
            'continuous',
            current_stage='mid',
            next_stage=next_stage)
    elif backend_stage == 'high':
        ui_stage, complete_with_error = dual_commands_to_sensor(
            selected_input,
            'high',
            '10.0',
            'end',
            current_stage='high',
            next_stage=next_stage)

    return render_template(
        'tools/calibration_options/atlas_ph.html',
        complete_with_error=complete_with_error,
        form_ph_calibrate=form_ph_calibrate,
        input=input_dev,
        input_device_name=input_device_name,
        selected_input=selected_input,
        selected_point_calibration=selected_point_calibration,
        ui_stage=ui_stage)
예제 #30
0
def input_activate(form_mod):
    messages = {"success": [], "info": [], "warning": [], "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:
        messages["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):
        messages["error"].append(
            "Pre Output Duration must be > 0 if Pre Output is enabled")

    if not device_measurements.filter(
            DeviceMeasurements.is_enabled.is_(True)).count():
        messages["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 'id' not in each_option:
                continue

            if each_option['id'] not in custom_options_values_inputs[
                    input_dev.unique_id]:
                if 'required' in each_option and each_option['required']:
                    messages["error"].append(
                        f"{each_option['name']} not found and is required to be set. "
                        "Set option and save Input.")
            else:
                value = custom_options_values_inputs[input_dev.unique_id][
                    each_option['id']]
                if ('required' in each_option and each_option['required']
                        and value != 0 and not value):
                    messages["error"].append(
                        f"{each_option['name']} is required to be set. "
                        f"Current value: {value}")

    #
    # Input-specific checks
    #
    if input_dev.device == 'LinuxCommand' and not input_dev.cmd_command:
        messages["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:
            messages["error"].append(
                "All measurements must have a name and unit/measurement set")

    messages = controller_activate_deactivate(messages,
                                              'activate',
                                              'Input',
                                              input_id,
                                              flash_message=False)

    if not messages["error"]:
        messages["success"].append(
            f"{TRANSLATIONS['activate']['title']} {TRANSLATIONS['input']['title']}"
        )

    return messages
예제 #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 (mod_input.device != 'EDGE' 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

        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

        if 'test_before_saving' in dict_inputs[mod_input.device]:
            (constraints_pass, constraints_errors,
             mod_input) = dict_inputs[mod_input.device]['test_before_saving'](
                 mod_input, request_form)
            if constraints_pass:
                pass
            elif constraints_errors:
                for each_error in constraints_errors:
                    flash(each_error, 'error')

        # Custom options
        list_options = []
        if 'custom_options' in dict_inputs[mod_input.device]:
            for each_option in dict_inputs[mod_input.device]['custom_options']:
                null_value = True
                for key in request_form.keys():
                    if each_option['id'] == key:
                        constraints_pass = True
                        constraints_errors = []
                        value = None
                        if each_option['type'] == 'float':
                            if str_is_float(request_form.get(key)):
                                if 'constraints_pass' in each_option:
                                    (constraints_pass, constraints_errors,
                                     mod_input
                                     ) = each_option['constraints_pass'](
                                         mod_input,
                                         float(request_form.get(key)))
                                if constraints_pass:
                                    value = float(request_form.get(key))
                            else:
                                error.append(
                                    "{name} must represent a float/decimal value "
                                    "(submitted '{value}')".format(
                                        name=each_option['name'],
                                        value=request_form.get(key)))

                        elif each_option['type'] == 'integer':
                            if is_int(request_form.get(key)):
                                if 'constraints_pass' in each_option:
                                    (constraints_pass, constraints_errors,
                                     mod_input
                                     ) = each_option['constraints_pass'](
                                         mod_input, int(request_form.get(key)))
                                if constraints_pass:
                                    value = int(request_form.get(key))
                            else:
                                error.append(
                                    "{name} must represent an integer value "
                                    "(submitted '{value}')".format(
                                        name=each_option['name'],
                                        value=request_form.get(key)))

                        elif each_option['type'] in ['text', 'select']:
                            if 'constraints_pass' in each_option:
                                (constraints_pass, constraints_errors,
                                 mod_input) = each_option['constraints_pass'](
                                     mod_input, request_form.get(key))
                            if constraints_pass:
                                value = request_form.get(key)

                        elif each_option['type'] == 'bool':
                            value = bool(request_form.get(key))

                        for each_error in constraints_errors:
                            error.append("Error: {name}: {error}".format(
                                name=each_option['name'], error=each_error))

                        if value is not None:
                            null_value = False
                            option = '{id},{value}'.format(id=key, value=value)
                            list_options.append(option)

                if null_value:
                    option = '{id},'.format(id=each_option['id'])
                    list_options.append(option)

        mod_input.custom_options = ';'.join(list_options)

        if not error:
            # 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']):
                channels = DeviceMeasurements.query.filter(
                    DeviceMeasurements.device_id == form_mod.input_id.data)

                if channels.count() != form_mod.num_channels.data:
                    # Delete channels
                    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(DeviceMeasurements,
                                                     each_channel.unique_id)

                    # Add channels
                    elif form_mod.num_channels.data > channels.count():
                        start_number = channels.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()

            db.session.commit()

    except Exception as except_msg:
        error.append(except_msg)

    flash_success_errors(error, action, url_for('routes_page.page_data'))
예제 #32
0
def admin_dependencies(device):
    """ Display Dependency page """
    form_dependencies = forms_dependencies.Dependencies()

    if device != '0':
        device_unmet_dependencies, _ = utils_general.return_dependencies(device)
    elif form_dependencies.device.data:
        device_unmet_dependencies, _ = utils_general.return_dependencies(form_dependencies.device.data)
    else:
        device_unmet_dependencies = []

    unmet_dependencies = OrderedDict()
    unmet_exist = False
    met_dependencies = []
    met_exist = False
    unmet_list = {}
    install_in_progress = False
    device_name = None

    # Read from the dependency status file created by the upgrade script
    # to indicate if the upgrade is running.
    try:
        with open(DEPENDENCY_INIT_FILE) as f:
            dep = int(f.read(1))
    except (IOError, ValueError):
        try:
            with open(DEPENDENCY_INIT_FILE, 'w') as f:
                f.write('0')
        finally:
            dep = 0

    if dep:
        install_in_progress = True

    dict_inputs = parse_input_information()

    list_dependencies = [
        dict_inputs,
        LCD_INFO,
        MATH_INFO,
        METHOD_INFO,
        OUTPUT_INFO,
        CALIBRATION_INFO
    ]
    for each_section in list_dependencies:
        for each_device in each_section:

            if device in each_section:
                for each_device, each_val in each_section[device].items():
                    if each_device in ['name', 'input_name']:
                        device_name = each_val

            # Determine if there are any unmet dependencies
            dep_unmet, dep_met = utils_general.return_dependencies(each_device)

            unmet_dependencies.update({
                each_device: dep_unmet
            })
            if dep_unmet:
                unmet_exist = True

            # Determine if there are any met dependencies
            if dep_met:
                if each_device not in met_dependencies:
                    met_dependencies.append(each_device)
                    met_exist = True

            # Find all the devices that use each unmet dependency
            if unmet_dependencies[each_device]:
                for each_dep in unmet_dependencies[each_device]:
                    if each_dep not in unmet_list:
                        unmet_list[each_dep] = []
                    if each_device not in unmet_list[each_dep]:
                        unmet_list[each_dep].append(each_device)

    if request.method == 'POST':
        if not utils_general.user_has_permission('edit_controllers'):
            return redirect(url_for('routes_admin.admin_dependencies', device=device))

        if form_dependencies.install.data:
            install_in_progress = True
            with open(DEPENDENCY_INIT_FILE, 'w') as f:
                f.write('1')
            install_deps = threading.Thread(
                target=install_dependencies,
                args=(device_unmet_dependencies,))
            install_deps.start()

        return redirect(url_for('routes_admin.admin_dependencies', device=device))

    return render_template('admin/dependencies.html',
                           measurements=parse_input_information(),
                           unmet_list=unmet_list,
                           device=device,
                           device_name=device_name,
                           install_in_progress=install_in_progress,
                           unmet_dependencies=unmet_dependencies,
                           unmet_exist=unmet_exist,
                           met_dependencies=met_dependencies,
                           met_exist=met_exist,
                           form_dependencies=form_dependencies,
                           device_unmet_dependencies=device_unmet_dependencies)
예제 #33
0
MYCODO_DB_PATH = 'sqlite:///' + SQL_DATABASE_MYCODO

save_path = os.path.join(INSTALL_DIRECTORY,
                         "docs/Supported-Inputs-By-Measurement.md")

inputs_info = OrderedDict()
mycodo_info = OrderedDict()


def repeat_to_length(s, wanted):
    return (s * (wanted // len(s) + 1))[:wanted]


if __name__ == "__main__":
    for input_id, input_data in parse_input_information(
            exclude_custom=True).items():
        name_str = ""
        if 'input_manufacturer' in input_data and input_data[
                'input_manufacturer']:
            name_str += "{}".format(input_data['input_manufacturer'])
        if 'input_name' in input_data and input_data['input_name']:
            name_str += ": {}".format(input_data['input_name'])
        if 'measurements_name' in input_data and input_data[
                'measurements_name']:
            name_str += ": {}".format(input_data['measurements_name'])
        if 'input_library' in input_data and input_data['input_library']:
            name_str += ": {}".format(input_data['input_library'])

        if name_str in inputs_info and 'dependencies_module' in inputs_info[
                name_str]:
            # Multiple sets of dependencies, append library
예제 #34
0
    def initialize_variables(self):
        input_dev = db_retrieve_table_daemon(Input, unique_id=self.unique_id)

        self.log_level_debug = input_dev.log_level_debug
        self.set_log_level_debug(self.log_level_debug)

        self.dict_inputs = parse_input_information()

        self.sample_rate = db_retrieve_table_daemon(
            Misc, entry='first').sample_rate_controller_input

        self.device_measurements = db_retrieve_table_daemon(
            DeviceMeasurements).filter(
                DeviceMeasurements.device_id == self.unique_id)

        self.conversions = db_retrieve_table_daemon(Conversion)

        self.input_dev = input_dev
        self.input_name = input_dev.name
        self.unique_id = input_dev.unique_id
        self.gpio_location = input_dev.gpio_location
        self.device = input_dev.device
        self.interface = input_dev.interface
        self.period = input_dev.period
        self.start_offset = input_dev.start_offset

        # Pre-Output (activates output prior to and/or during input measurement)
        self.pre_output_setup = False

        if self.input_dev.pre_output_id and "," in self.input_dev.pre_output_id:
            try:
                self.pre_output_id = input_dev.pre_output_id.split(",")[0]
                self.pre_output_channel_id = input_dev.pre_output_id.split(
                    ",")[1]

                self.pre_output_duration = input_dev.pre_output_duration
                self.pre_output_during_measure = input_dev.pre_output_during_measure
                self.pre_output_activated = False
                self.pre_output_timer = time.time()
                self.pre_output_lock_file = '/var/lock/input_pre_output_{id}_{ch}'.format(
                    id=self.pre_output_id, ch=self.pre_output_channel_id)

                # Check if Pre Output and channel IDs exists
                output = db_retrieve_table_daemon(Output,
                                                  unique_id=self.pre_output_id)
                output_channel = db_retrieve_table_daemon(
                    OutputChannel, unique_id=self.pre_output_channel_id)
                if output and output_channel and self.pre_output_duration:
                    self.pre_output_channel = output_channel.channel
                    self.logger.debug("Pre output successfully set up")
                    self.pre_output_setup = True
            except:
                self.logger.exception("Could not set up pre-output")

        self.last_measurement = 0
        self.next_measurement = time.time() + self.start_offset
        self.get_new_measurement = False
        self.trigger_cond = False
        self.measurement_acquired = False

        smtp = db_retrieve_table_daemon(SMTP, entry='first')
        self.smtp_max_count = smtp.hourly_max
        self.email_count = 0
        self.allowed_to_send_notice = True

        # Convert string I2C address to base-16 int
        if self.interface == 'I2C' and self.input_dev.i2c_location:
            self.i2c_address = int(str(self.input_dev.i2c_location), 16)

        self.device_recognized = True

        if self.device in self.dict_inputs:
            input_loaded = load_module_from_file(
                self.dict_inputs[self.device]['file_path'], 'inputs')

            self.measure_input = input_loaded.InputModule(self.input_dev)

        else:
            self.device_recognized = False
            self.logger.debug(
                "Device '{device}' not recognized".format(device=self.device))
            raise Exception("'{device}' is not a valid device type.".format(
                device=self.device))

        self.input_timer = time.time()
        self.lastUpdate = None

        # Set up listener (e.g. MQTT, EDGE)
        if ('listener' in self.dict_inputs[self.device]
                and self.dict_inputs[self.device]['listener']):
            self.logger.debug(
                "Detected as listener. Starting listener thread.")
            input_listener = threading.Thread(
                target=self.measure_input.listener())
            input_listener.daemon = True
            input_listener.start()
예제 #35
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 (mod_input.device != 'EDGE' 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

        # Custom options
        try:
            custom_options_json_presave = json.loads(mod_input.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_inputs, request_form, device=mod_input.device)

        if 'execute_at_modification' in dict_inputs[mod_input.device]:
            (allow_saving, mod_input, custom_options
             ) = dict_inputs[mod_input.device]['execute_at_modification'](
                 mod_input, 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_input.custom_options = custom_options

        if not error:
            # 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']):
                channels = DeviceMeasurements.query.filter(
                    DeviceMeasurements.device_id == form_mod.input_id.data)

                if channels.count() != form_mod.num_channels.data:
                    # Delete channels
                    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(DeviceMeasurements,
                                                     each_channel.unique_id)

                    # Add channels
                    elif form_mod.num_channels.data > channels.count():
                        start_number = channels.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()

            db.session.commit()

    except Exception as except_msg:
        error.append(except_msg)

    flash_success_errors(error, action, url_for('routes_page.page_data'))
예제 #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.rescale_method = form.rescale_method.data
            mod_meas.rescale_equation = form.rescale_equation.data
            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)
예제 #37
0
def admin_dependencies(device):
    """ Display Dependency page """
    form_dependencies = forms_dependencies.Dependencies()

    if device != '0':
        device_unmet_dependencies, _ = utils_general.return_dependencies(
            device)
    elif form_dependencies.device.data:
        device_unmet_dependencies, _ = utils_general.return_dependencies(
            form_dependencies.device.data)
    else:
        device_unmet_dependencies = []

    unmet_dependencies = OrderedDict()
    unmet_exist = False
    met_dependencies = []
    met_exist = False
    unmet_list = {}
    install_in_progress = False
    device_name = None

    # Read from the dependency status file created by the upgrade script
    # to indicate if the upgrade is running.
    try:
        with open(DEPENDENCY_INIT_FILE) as f:
            dep = int(f.read(1))
    except (IOError, ValueError):
        try:
            with open(DEPENDENCY_INIT_FILE, 'w') as f:
                f.write('0')
        finally:
            dep = 0

    if dep:
        install_in_progress = True

    dict_inputs = parse_input_information()

    list_dependencies = [
        dict_inputs, FUNCTION_ACTION_INFO, FUNCTION_INFO, LCD_INFO, MATH_INFO,
        METHOD_INFO, OUTPUT_INFO, CALIBRATION_INFO
    ]
    for each_section in list_dependencies:
        for each_device in each_section:

            if device in each_section:
                for each_device_, each_val in each_section[device].items():
                    if each_device_ in ['name', 'input_name']:
                        device_name = each_val

            # Determine if there are any unmet dependencies
            dep_unmet, dep_met = utils_general.return_dependencies(each_device)

            unmet_dependencies.update({each_device: dep_unmet})
            if dep_unmet:
                unmet_exist = True

            # Determine if there are any met dependencies
            if dep_met:
                if each_device not in met_dependencies:
                    met_dependencies.append(each_device)
                    met_exist = True

            # Find all the devices that use each unmet dependency
            if unmet_dependencies[each_device]:
                for each_dep in unmet_dependencies[each_device]:
                    if each_dep not in unmet_list:
                        unmet_list[each_dep] = []
                    if each_device not in unmet_list[each_dep]:
                        unmet_list[each_dep].append(each_device)

    if request.method == 'POST':
        if not utils_general.user_has_permission('edit_controllers'):
            return redirect(
                url_for('routes_admin.admin_dependencies', device=device))

        if form_dependencies.install.data:
            install_in_progress = True
            with open(DEPENDENCY_INIT_FILE, 'w') as f:
                f.write('1')
            install_deps = threading.Thread(target=install_dependencies,
                                            args=(device_unmet_dependencies, ))
            install_deps.start()

        return redirect(
            url_for('routes_admin.admin_dependencies', device=device))

    return render_template('admin/dependencies.html',
                           measurements=parse_input_information(),
                           unmet_list=unmet_list,
                           device=device,
                           device_name=device_name,
                           install_in_progress=install_in_progress,
                           unmet_dependencies=unmet_dependencies,
                           unmet_exist=unmet_exist,
                           met_dependencies=met_dependencies,
                           met_exist=met_exist,
                           form_dependencies=form_dependencies,
                           device_unmet_dependencies=device_unmet_dependencies)
예제 #38
0
def return_dependencies(device_type):
    unmet_deps = []
    met_deps = False

    dict_inputs = parse_input_information()

    list_dependencies = [
        dict_inputs,
        LCD_INFO,
        MATH_INFO,
        METHOD_INFO,
        OUTPUT_INFO,
        CALIBRATION_INFO
    ]
    for each_section in list_dependencies:
        if device_type in each_section:
            for each_device, each_dict in each_section[device_type].items():
                if not each_dict:
                    met_deps = True
                elif each_device == 'dependencies_module':
                    for (install_type, package, install_id) in each_dict:
                        entry = (
                            package, '{0} {1}'.format(install_type, install_id),
                            install_type,
                            install_id
                        )
                        if install_type in ['pip-pypi', 'pip-git']:
                            try:
                                module = importlib.util.find_spec(package)
                                if module is None:
                                    if entry not in unmet_deps:
                                        unmet_deps.append(entry)
                                else:
                                    met_deps = True
                            except ImportError:
                                if entry not in unmet_deps:
                                    unmet_deps.append(entry)
                        elif install_type == 'apt':
                            if (not dpkg_package_exists(package) and
                                    entry not in unmet_deps):
                                unmet_deps.append(entry)
                            else:
                                met_deps = True
                        elif install_type == 'internal':
                            if package.startswith('file-exists'):
                                filepath = package.split(' ', 1)[1]
                                if not os.path.isfile(filepath):
                                    if entry not in unmet_deps:
                                        unmet_deps.append(entry)
                                    else:
                                        met_deps = True
                            elif package.startswith('pip-exists'):
                                py_module = package.split(' ', 1)[1]
                                try:
                                    module = importlib.util.find_spec(py_module)
                                    if module is None:
                                        if entry not in unmet_deps:
                                            unmet_deps.append(entry)
                                    else:
                                        met_deps = True
                                except ImportError:
                                    if entry not in unmet_deps:
                                        unmet_deps.append(entry)
                            elif package.startswith('apt'):
                                if (not dpkg_package_exists(package) and
                                        entry not in unmet_deps):
                                    unmet_deps.append(entry)
                                else:
                                    met_deps = True

    return unmet_deps, met_deps