Ejemplo n.º 1
0
def check_actions(action, error):
    """Check if the Actions form inputs are valid"""
    if action.action_type == 'command':
        if not action.do_action_string or action.do_action_string == '':
            error.append("Command must be set")
    elif action.action_type == 'output':
        if not action.do_unique_id or action.do_unique_id == '':
            error.append("Output must be set")
        if not action.do_output_state or action.do_output_state == '':
            error.append("State must be set")
    elif action.action_type in ['activate_pid', 'deactivate_pid']:
        if not action.do_unique_id or action.do_unique_id == '':
            error.append("PID must be set")
    elif action.action_type == 'email':
        if not action.do_action_string or action.do_action_string == '':
            error.append("Email must be set")
    elif action.action_type in ['photo_email', 'video_email']:
        if not action.do_action_string or action.do_action_string == '':
            error.append("Email must be set")
        if not action.do_unique_id or action.do_unique_id == '':
            error.append("Camera must be set")
        if (action.action_type == 'video_email' and Camera.query.filter(
                and_(Camera.unique_id == action.do_unique_id,
                     Camera.library != 'picamera')).count()):
            error.append('Only Pi Cameras can record video')
    elif action.action_type == 'flash_lcd_on' and not action.do_unique_id:
        error.append("LCD must be set")
    elif action.action_type == 'lcd_backlight_color':
        if not action.do_unique_id:
            error.append("LCD must be set")
        try:
            tuple_colors = action.do_action_string.split(",")
            if len(tuple_colors) != 3:
                error.append(
                    'LCD backlight color must be in the R,G,B format "255,255,255"'
                )

            if not is_int(tuple_colors[0]):
                error.append('Red color does not represent an integer.')
            elif int(tuple_colors[0]) < 0 or int(tuple_colors[0]) > 255:
                error.append('Red color must be >= 0 and <= 255')

            if not is_int(tuple_colors[1]):
                error.append('Blue color does not represent an integer.')
            elif int(tuple_colors[1]) < 0 or int(tuple_colors[1]) > 255:
                error.append('Blue color must be >= 0 and <= 255')

            if not is_int(tuple_colors[2]):
                error.append('Green color does not represent an integer.')
            elif int(tuple_colors[2]) < 0 or int(tuple_colors[2]) > 255:
                error.append('Green color must be >= 0 and <= 255')
        except:
            error.append(
                'Error parsing LCD backlight color. Must be in the R,G,B format '
                '"255,255,255" without quotes.')
    elif (action.action_type in ['photo', 'video']
          and (not action.do_unique_id or action.do_unique_id == '')):
        error.append("Camera must be set")
    return error
Ejemplo n.º 2
0
    def calibration_export(self, args_dict):
        try:
            atlas_status, atlas_return = self.atlas_device.query("Export,?")
            self.logger.info("Command returned: {}".format(atlas_return))
            if atlas_return and ',' in atlas_return:
                list_return = atlas_return.split(',')
                length = None
                bytes = None
                for each_item in list_return:
                    if is_int(each_item):
                        if length is None:
                            length = int(each_item)
                        elif bytes is None:
                            bytes = int(each_item)
                            break
                list_export = []
                for _ in range(length):
                    atlas_status, atlas_return = self.atlas_device.query(
                        "Export")
                    if atlas_return:
                        list_export.append(atlas_return)
                atlas_status, atlas_return = self.atlas_device.query("Export")
                if atlas_return != "*DONE":
                    self.logger.error(
                        "Did not receive *DONE response indicating export ended"
                    )
                self.logger.info("pH Calibration export string: {}".format(
                    ",".join(list_export)))

            atlas_status, atlas_return = self.atlas_device.query("Slope,?")
            if atlas_status == "success":
                self.logger.info("Slope: {}".format(atlas_return))
        except:
            self.logger.exception("Exception exporting calibrating")
Ejemplo n.º 3
0
def output_mod(output_id, channel, state, output_type, amount):
    """ Manipulate output (using non-unique ID) """
    if not utils_general.user_has_permission('edit_controllers'):
        return 'Insufficient user permissions to manipulate outputs'

    if is_int(channel):
        # if an integer was returned
        output_channel = int(channel)
    else:
        # if a channel ID was returned
        channel_dev = db_retrieve_table(OutputChannel).filter(
            OutputChannel.unique_id == channel).first()
        if channel_dev:
            output_channel = channel_dev.channel
        else:
            return "Could not determine channel number from channel ID '{}'".format(
                channel)

    daemon = DaemonControl()
    if (state in ['on', 'off'] and str_is_float(amount) and
        ((output_type in ['sec', 'pwm', 'vol'] and float(amount) >= 0) or
         (output_type == 'value'))):
        out_status = daemon.output_on_off(output_id,
                                          state,
                                          output_type=output_type,
                                          amount=float(amount),
                                          output_channel=output_channel)
        if out_status[0]:
            return 'ERROR: {}'.format(out_status[1])
        else:
            return 'SUCCESS: {}'.format(out_status[1])
    else:
        return 'ERROR: unknown parameters: ' \
               'output_id: {}, channel: {}, state: {}, output_type: {}, amount: {}'.format(
                output_id, channel, state, output_type, amount)
Ejemplo n.º 4
0
def output_add(form_add):
    action = '{action} {controller}'.format(action=gettext("Add"),
                                            controller=gettext("Output"))
    error = []

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

    if is_int(form_add.output_quantity.data, check_range=[1, 20]):
        for _ in range(0, form_add.output_quantity.data):
            try:
                new_output = Output()
                new_output.name = OUTPUT_INFO[
                    form_add.output_type.data]['name']
                new_output.output_type = form_add.output_type.data
                if form_add.output_type.data == 'wired':
                    new_output.on_at_start = False
                elif form_add.output_type.data == 'wireless_433MHz_pi_switch':
                    new_output.pin = None
                    new_output.protocol = 1
                    new_output.pulse_length = 189
                    new_output.on_command = '22559'
                    new_output.off_command = '22558'
                elif form_add.output_type.data == 'command':
                    new_output.on_command = '/home/pi/script_on.sh'
                    new_output.off_command = '/home/pi/script_off.sh'
                elif form_add.output_type.data == 'command_pwm':
                    new_output.pwm_command = '/home/pi/script_pwm.sh ((duty_cycle))'
                elif form_add.output_type.data == 'pwm':
                    new_output.pwm_hertz = 22000
                    new_output.pwm_library = 'pigpio_any'

                if not error:
                    new_output.save()
                    display_order = csv_to_list_of_str(
                        DisplayOrder.query.first().output)
                    DisplayOrder.query.first().output = add_display_order(
                        display_order, new_output.unique_id)
                    db.session.commit()
                    manipulate_output('Add', new_output.unique_id)
            except sqlalchemy.exc.OperationalError as except_msg:
                error.append(except_msg)
            except sqlalchemy.exc.IntegrityError as except_msg:
                error.append(except_msg)
    else:
        error_msg = "{error}. {accepted_values}: 1-20".format(
            error=gettext("Invalid quantity"),
            accepted_values=gettext("Acceptable values"))
        error.append(error_msg)
    flash_success_errors(error, action, url_for('routes_page.page_output'))

    if dep_unmet:
        return 1
Ejemplo n.º 5
0
def output_mod(form_relay):
    action = '{action} {controller}'.format(action=gettext("Modify"),
                                            controller=gettext("Output"))
    error = []

    try:
        mod_relay = Output.query.filter(
            Output.id == form_relay.relay_id.data).first()
        mod_relay.name = form_relay.name.data
        if mod_relay.relay_type == 'wired':
            if not is_int(form_relay.gpio.data):
                error.append("BCM Pin must be an integer")
            mod_relay.pin = form_relay.gpio.data
            mod_relay.trigger = bool(int(form_relay.trigger.data))
        elif mod_relay.relay_type == 'wireless_433MHz_pi_switch':
            if not is_int(form_relay.wiringpi_pin.data):
                error.append("Pin must be an integer")
            if not is_int(form_relay.protocol.data):
                error.append("Protocol must be an integer")
            if not is_int(form_relay.pulse_length.data):
                error.append("Pulse Length must be an integer")
            if not is_int(form_relay.bit_length.data):
                error.append("Bit Length must be an integer")
            if not is_int(form_relay.on_command.data):
                error.append("On Command must be an integer")
            if not is_int(form_relay.off_command.data):
                error.append("Off Command must be an integer")
            mod_relay.pin = form_relay.wiringpi_pin.data
            mod_relay.protocol = form_relay.protocol.data
            mod_relay.pulse_length = form_relay.pulse_length.data
            mod_relay.bit_length = form_relay.bit_length.data
            mod_relay.on_command = form_relay.on_command.data
            mod_relay.off_command = form_relay.off_command.data
        elif mod_relay.relay_type == 'command':
            mod_relay.on_command = form_relay.on_command.data
            mod_relay.off_command = form_relay.off_command.data
        elif mod_relay.relay_type == 'pwm':
            mod_relay.pin = form_relay.gpio.data
            mod_relay.pwm_hertz = form_relay.pwm_hertz.data
            mod_relay.pwm_library = form_relay.pwm_library.data
        mod_relay.amps = form_relay.amps.data

        if form_relay.on_at_start.data == '-1' or mod_relay.relay_type == 'pwm':
            mod_relay.on_at_start = None
        else:
            mod_relay.on_at_start = bool(int(form_relay.on_at_start.data))

        if not error:
            db.session.commit()
            manipulate_output('Modify', form_relay.relay_id.data)
    except Exception as except_msg:
        error.append(except_msg)
    flash_success_errors(error, action, url_for('routes_page.page_output'))
Ejemplo n.º 6
0
def output_add(form_add_relay):
    action = '{action} {controller}'.format(action=gettext("Add"),
                                            controller=gettext("Output"))
    error = []

    if is_int(form_add_relay.relay_quantity.data, check_range=[1, 20]):
        for _ in range(0, form_add_relay.relay_quantity.data):
            try:
                new_relay = Output()
                new_relay.relay_type = form_add_relay.relay_type.data
                if form_add_relay.relay_type.data == 'wired':
                    new_relay.on_at_start = False
                elif form_add_relay.relay_type.data == 'wireless_433MHz_pi_switch':
                    new_relay.protocol = 1
                    new_relay.bit_length = 25
                    new_relay.pulse_length = 189
                    new_relay.on_command = '22559'
                    new_relay.off_command = '22558'
                elif form_add_relay.relay_type.data == 'command':
                    new_relay.on_command = '/home/pi/script_on.sh'
                    new_relay.off_command = '/home/pi/script_off.sh'
                elif form_add_relay.relay_type.data == 'pwm':
                    new_relay.pwm_hertz = 22000
                    new_relay.pwm_library = 'pigpio_any'
                new_relay.save()
                display_order = csv_to_list_of_int(
                    DisplayOrder.query.first().relay)
                DisplayOrder.query.first().relay = add_display_order(
                    display_order, new_relay.id)
                db.session.commit()
                manipulate_output('Add', new_relay.id)
            except sqlalchemy.exc.OperationalError as except_msg:
                error.append(except_msg)
            except sqlalchemy.exc.IntegrityError as except_msg:
                error.append(except_msg)
    else:
        error_msg = "{error}. {accepted_values}: 1-20".format(
            error=gettext("Invalid quantity"),
            accepted_values=gettext("Acceptable values"))
        error.append(error_msg)
    flash_success_errors(error, action, url_for('routes_page.page_output'))
Ejemplo n.º 7
0
def output_add(form_add):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['add']['title'],
        controller=TRANSLATIONS['output']['title'])
    error = []

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

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

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

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

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

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

                new_output.channel = 0

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

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

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

    if dep_unmet:
        return 1
Ejemplo n.º 8
0
def output_add(form_add):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['add']['title'],
        controller=TRANSLATIONS['output']['title'])
    error = []

    dict_outputs = parse_output_information()
    output_types_dict = output_types()

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

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

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

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

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

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

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

                #
                # Set default values for new input being added
                #

                # input add options
                if output_type in dict_outputs:

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

                    #
                    # Interfacing options
                    #

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

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

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

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

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

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

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

                #
                # Custom Options
                #

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

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

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

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

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

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

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

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

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

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

                    #
                    # If measurements defined in the Output Module
                    #

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

                    db.session.commit()

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

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

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

    dict_outputs = parse_output_information()

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

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

        mod_output.name = form_output.name.data

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

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

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

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

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

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

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

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

        mod_output.linux_command_user = form_output.linux_command_user.data

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

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

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

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

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

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

        if not error:
            mod_output.custom_options = custom_options

            db.session.commit()
            manipulate_output('Modify', form_output.output_id.data)
    except Exception as except_msg:
        logger.exception(1)
        error.append(except_msg)
    flash_success_errors(error, action, url_for('routes_page.page_output'))
Ejemplo n.º 10
0
def output_mod(form_output, request_form):
    messages = {
        "success": [],
        "info": [],
        "warning": [],
        "error": [],
        "name": None,
        "return_text": []
    }
    page_refresh = False

    dict_outputs = parse_output_information()

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

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

        mod_output.name = form_output.name.data
        messages["name"] = form_output.name.data

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

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

        mod_output.log_level_debug = form_output.log_level_debug.data

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

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

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

        custom_options_channels_dict_postsave = {}
        for each_channel in channels:
            messages["error"], custom_options_channels_json_postsave_tmp = custom_channel_options_return_json(
                messages["error"], dict_outputs, request_form,
                form_output.output_id.data, each_channel.channel,
                device=mod_output.output_type, 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_outputs[mod_output.output_type]:
            # pass custom options to module prior to saving to database
            (messages,
             mod_output,
             custom_options_dict,
             custom_options_channels_dict) = dict_outputs[mod_output.output_type]['execute_at_modification'](
                messages,
                mod_output,
                request_form,
                custom_options_dict_presave,
                custom_options_channels_dict_presave,
                custom_options_dict_postsave,
                custom_options_channels_dict_postsave)
            custom_options = json.dumps(custom_options_dict)  # Convert from dict to JSON string
            custom_channel_options = custom_options_channels_dict
        else:
            # Don't pass custom options to module
            custom_options = json.dumps(custom_options_dict_postsave)
            custom_channel_options = custom_options_channels_dict_postsave

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

        if not messages["error"]:
            db.session.commit()
            messages["success"].append('{action} {controller}'.format(
                action=TRANSLATIONS['modify']['title'],
                controller=TRANSLATIONS['output']['title']))

            if not current_app.config['TESTING']:
                new_messages = manipulate_output(
                    'Modify', form_output.output_id.data)
                messages["error"].extend(new_messages["error"])
                messages["success"].extend(new_messages["success"])
    except Exception as except_msg:
        messages["error"].append(str(except_msg))

    return messages, page_refresh
Ejemplo n.º 11
0
def custom_options_return_string(error, dict_options, mod_dev, request_form):
    # Custom options
    list_options = []
    if 'custom_options' in dict_options[mod_dev.device]:
        for each_option in dict_options[mod_dev.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_dev) = each_option['constraints_pass'](
                                    mod_dev, 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_dev) = each_option['constraints_pass'](
                                    mod_dev, 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',
                            'select_measurement',
                            'select_device']:
                        if 'constraints_pass' in each_option:
                            (constraints_pass,
                             constraints_errors,
                             mod_dev) = each_option['constraints_pass'](
                                mod_dev, 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)

    return error, ';'.join(list_options)
Ejemplo n.º 12
0
def output_add(form_add, request_form):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['add']['title'],
        controller=TRANSLATIONS['output']['title'])
    error = []

    dict_outputs = parse_output_information()

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

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

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

    if not error:
        for _ in range(0, form_add.output_quantity.data):
            try:
                new_output = Output()
                try:
                    from RPi import GPIO
                    if GPIO.RPI_INFO['P1_REVISION'] == 1:
                        new_output.i2c_bus = 0
                    else:
                        new_output.i2c_bus = 1
                except:
                    logger.error(
                        "RPi.GPIO and Raspberry Pi required for this action")

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

                #
                # Set default values for new input being added
                #

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

                    #
                    # Interfacing options
                    #

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

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

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

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

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

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

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

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

                #
                # Execute at Creation
                #

                new_output.unique_id = set_uuid()

                if 'execute_at_creation' in dict_outputs[output_type] and not current_app.config['TESTING']:
                    dict_outputs[output_type]['execute_at_creation'](
                        new_output, dict_outputs[output_type])

                if not error:
                    new_output.save()

                    display_order = csv_to_list_of_str(
                        DisplayOrder.query.first().output)
                    DisplayOrder.query.first().output = add_display_order(
                        display_order, new_output.unique_id)

                    db.session.commit()

                    #
                    # If measurements defined in the Output Module
                    #

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

                    for each_channel, channel_info in dict_outputs[output_type]['channels_dict'].items():
                        new_channel = OutputChannel()
                        new_channel.channel = each_channel
                        new_channel.output_id = new_output.unique_id

                        # Generate string to save from custom options
                        error, custom_options = custom_channel_options_return_json(
                            error, dict_outputs, request_form,
                            new_output.unique_id, each_channel,
                            device=output_type, use_defaults=True)
                        new_channel.custom_options = custom_options

                        new_channel.save()

                    # Refresh output settings
                    if not current_app.config['TESTING']:
                        manipulate_output('Add', new_output.unique_id)

                    flash(gettext("{dev} with ID %(id)s successfully added".format(
                        dev=dict_outputs[output_type]['output_name']), id=new_output.id),
                        "success")
            except sqlalchemy.exc.OperationalError as except_msg:
                error.append(except_msg)
            except sqlalchemy.exc.IntegrityError as except_msg:
                error.append(except_msg)
            except Exception:
                logger.exception(1)

    return dep_unmet
Ejemplo n.º 13
0
def input_mod(form_mod, request_form):
    action = '{action} {controller}'.format(action=gettext("Modify"),
                                            controller=gettext("Input"))
    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 sensor 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.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

        if mod_input.device == 'LinuxCommand':
            mod_input.measurements = form_mod.selected_measurement_unit.data.split(
                ',')[0]

        if (mod_input.device == 'LinuxCommand' or
            ('analog_to_digital_converter' in dict_inputs[mod_input.device] and
             dict_inputs[mod_input.device]['analog_to_digital_converter'])):
            mod_input.convert_to_unit = form_mod.selected_measurement_unit.data

        short_list = []
        mod_units = False
        for key in request_form.keys():
            if 'convert_unit' in key:
                mod_units = True
                for value in request_form.getlist(key):
                    if value == 'default':
                        pass
                    elif (len(value.split(',')) < 2
                          or value.split(',')[0] == ''
                          or value.split(',')[1] == ''):
                        error.append("Invalid custom unit")
                    else:
                        short_list.append(value)
        if mod_units:
            mod_input.convert_to_unit = ';'.join(short_list)

        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
        # ADC options
        mod_input.adc_channel = form_mod.adc_channel.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
        mod_input.adc_volts_min = form_mod.adc_volts_min.data
        mod_input.adc_volts_max = form_mod.adc_volts_max.data
        mod_input.adc_units_min = form_mod.adc_units_min.data
        mod_input.adc_units_max = form_mod.adc_units_max.data
        mod_input.adc_inverse_unit_scale = form_mod.adc_inverse_unit_scale.data
        # Switch options
        mod_input.switch_edge = form_mod.switch_edge.data
        mod_input.switch_bouncetime = form_mod.switch_bounce_time.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 = each_option[
                                        'constraints_pass'](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 = each_option[
                                        'constraints_pass'](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 = each_option[
                                    'constraints_pass'](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'))
Ejemplo n.º 14
0
def output_mod(form_output):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['modify']['title'],
        controller=TRANSLATIONS['output']['title'])
    error = []

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

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

        if mod_output.output_type == 'wired':
            if not is_int(form_output.gpio_location.data):
                error.append("BCM GPIO Pin must be an integer")
            mod_output.pin = form_output.gpio_location.data
            mod_output.on_state = bool(int(form_output.on_state.data))

        elif mod_output.output_type == 'wireless_rpi_rf':
            if not is_int(form_output.gpio_location.data):
                error.append("Pin must be an integer")
            if not is_int(form_output.protocol.data):
                error.append("Protocol must be an integer")
            if not is_int(form_output.pulse_length.data):
                error.append("Pulse Length must be an integer")
            if not is_int(form_output.on_command.data):
                error.append("On Command must be an integer")
            if not is_int(form_output.off_command.data):
                error.append("Off Command must be an integer")
            mod_output.pin = form_output.gpio_location.data
            mod_output.protocol = form_output.protocol.data
            mod_output.pulse_length = form_output.pulse_length.data
            mod_output.on_command = form_output.on_command.data
            mod_output.off_command = form_output.off_command.data

        elif mod_output.output_type in ['command', 'python']:
            mod_output.on_command = form_output.on_command.data
            mod_output.off_command = form_output.off_command.data

        elif mod_output.output_type in ['command_pwm', 'python_pwm']:
            mod_output.pwm_command = form_output.pwm_command.data
            mod_output.pwm_invert_signal = form_output.pwm_invert_signal.data

        elif mod_output.output_type == 'pwm':
            mod_output.pin = form_output.gpio_location.data
            mod_output.pwm_hertz = form_output.pwm_hertz.data
            mod_output.pwm_library = form_output.pwm_library.data
            mod_output.pwm_invert_signal = form_output.pwm_invert_signal.data

        elif mod_output.output_type.startswith('atlas_ezo_pmp'):
            mod_output.location = form_output.location.data
            mod_output.output_mode = form_output.output_mode.data
            if form_output.flow_rate.data > 105 or form_output.flow_rate.data < 0.5:
                error.append("Flow Rate must be between 0.5 and 105 ml/min")
            else:
                mod_output.flow_rate = form_output.flow_rate.data
            if form_output.i2c_bus.data:
                mod_output.i2c_bus = form_output.i2c_bus.data
            if form_output.baud_rate.data:
                mod_output.baud_rate = form_output.baud_rate.data

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

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

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

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

        if not error:
            db.session.commit()
            manipulate_output('Modify', form_output.output_id.data)
    except Exception as except_msg:
        error.append(except_msg)
    flash_success_errors(error, action, url_for('routes_page.page_output'))
Ejemplo n.º 15
0
def check_form_actions(form, error):
    """Check if the Actions form inputs are valid"""
    action = Actions.query.filter(
        Actions.unique_id == form.function_action_id.data).first()
    if action.action_type == 'command':
        if not form.do_action_string.data or form.do_action_string.data == '':
            error.append("Command must be set")
    elif action.action_type == 'output':
        if not form.do_unique_id.data or form.do_unique_id.data == '':
            error.append("Output must be set")
        if not form.do_output_state.data or form.do_output_state.data == '':
            error.append("State must be set")
    elif action.action_type == 'output_pwm':
        if not form.do_unique_id.data or form.do_unique_id.data == '':
            error.append("Output must be set")
        if form.do_output_pwm.data < 0 or form.do_output_pwm.data > 100 or form.do_output_pwm.data == '':
            error.append("Duty Cycle must be set (0 <= duty cycle <= 100)")
    elif action.action_type == 'output_value':
        if not form.do_unique_id.data or form.do_unique_id.data == '':
            error.append("Output must be set")
        if not form.do_output_amount.data:
            error.append("Value must be set")
    elif action.action_type == 'output_volume':
        if not form.do_unique_id.data or form.do_unique_id.data == '':
            error.append("Output must be set")
        if not form.do_output_amount.data:
            error.append("Volume must be set")
    elif action.action_type in ['activate_pid',
                                'deactivate_pid',
                                'resume_pid',
                                'pause_pid']:
        if not form.do_unique_id.data or form.do_unique_id.data == '':
            error.append("ID must be set")
    elif action.action_type == 'email':
        if not form.do_action_string.data or form.do_action_string.data == '':
            error.append("Email must be set")
    elif action.action_type in ['photo_email', 'video_email']:
        if not form.do_action_string.data or form.do_action_string.data == '':
            error.append("Email must be set")
        if not form.do_unique_id.data or form.do_unique_id.data == '':
            error.append("Camera must be set")
        if (action.action_type == 'video_email' and
                Camera.query.filter(
                    and_(Camera.unique_id == form.do_unique_id.data,
                         Camera.library != 'picamera')).count()):
            error.append('Only Pi Cameras can record video')
    elif action.action_type == 'flash_lcd_on' and not form.do_unique_id.data:
        error.append("LCD must be set")
    elif action.action_type == 'lcd_backlight_color':
        if not form.do_unique_id.data:
            error.append("LCD must be set")
        try:
            tuple_colors = form.do_action_string.data.split(",")
            if len(tuple_colors) != 3:
                error.append('LCD backlight color must be in the R,G,B format "255,255,255"')

            if not is_int(tuple_colors[0]):
                error.append('Red color does not represent an integer.')
            elif int(tuple_colors[0]) < 0 or int(tuple_colors[0]) > 255:
                error.append('Red color must be >= 0 and <= 255')

            if not is_int(tuple_colors[1]):
                error.append('Blue color does not represent an integer.')
            elif int(tuple_colors[1]) < 0 or int(tuple_colors[1]) > 255:
                error.append('Blue color must be >= 0 and <= 255')

            if not is_int(tuple_colors[2]):
                error.append('Green color does not represent an integer.')
            elif int(tuple_colors[2]) < 0 or int(tuple_colors[2]) > 255:
                error.append('Green color must be >= 0 and <= 255')
        except:
            error.append('Error parsing LCD backlight color. Must be in the R,G,B format '
                         '"255,255,255" without quotes.')
    elif (action.action_type in ['photo', 'video'] and
            (not form.do_unique_id.data or form.do_unique_id.data == '')):
        error.append("Camera must be set")
    return error
Ejemplo n.º 16
0
def output_mod(form_output):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['modify']['title'],
        controller=TRANSLATIONS['output']['title'])
    error = []

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

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

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

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

        if not error:
            db.session.commit()
            manipulate_output('Modify', form_output.output_id.data)
    except Exception as except_msg:
        error.append(except_msg)
    flash_success_errors(error, action, url_for('routes_page.page_output'))
Ejemplo n.º 17
0
    def check_conditionals(self):
        """
        Check if any Conditionals are activated and
        execute their actions if the Conditional is true.

        For example, if "temperature > 30", notify [email protected]

        "if measured temperature is above 30C" is the Conditional to check.
        "notify [email protected]" is the Condition Action to execute if the
        Conditional is True.
        """

        cond = db_retrieve_table_daemon(
            Conditional, unique_id=self.function_id, entry='first')

        now = time.time()
        timestamp = datetime.datetime.fromtimestamp(now).strftime('%Y-%m-%d %H:%M:%S')
        message = "{ts}\n[Conditional {id}]\n[Name: {name}]".format(
            ts=timestamp,
            name=cond.name,
            id=self.function_id)

        # self.logger.info("Conditional Statement (pre-replacement):\n{}".format(self.conditional_statement))
        cond_statement_replaced = self.conditional_statement

        # Replace short condition IDs in conditional statement with full condition IDs
        for each_condition in db_retrieve_table_daemon(ConditionalConditions, entry='all'):
            cond_statement_replaced = cond_statement_replaced.replace(
                '{{{id}}}'.format(id=each_condition.unique_id.split('-')[0]), each_condition.unique_id)

        # Replace short action IDs in conditional statement with full action IDs
        for each_action in db_retrieve_table_daemon(Actions, entry='all'):
            cond_statement_replaced = cond_statement_replaced.replace(
                '{{{id}}}'.format(id=each_action.unique_id.split('-')[0]), each_action.unique_id)

        message += '\n[Conditional Statement]:\n--------------------\n{statement}\n--------------------\n'.format(
            statement=cond.conditional_statement)

        # Add functions to the top of the statement string
        pre_statement = """
import os, sys
sys.path.append(os.path.abspath('/var/mycodo-root'))
from mycodo.mycodo_client import DaemonControl
control = DaemonControl()

message='''{message}'''

def measure(condition_id):
    return control.get_condition_measurement(condition_id)

def run_all_actions(message=message):
    control.trigger_all_actions('{function_id}', message=message)

def run_action(action_id, message=message):
    control.trigger_action(action_id, message=message, single_action=True)

""".format(message=message, function_id=self.function_id)

        cond_statement_replaced = pre_statement + cond_statement_replaced
        # self.logger.info("Conditional Statement (replaced):\n{}".format(cond_statement_replaced))

        # Set the refractory period
        if self.refractory_period:
            self.timer_refractory_period = time.time() + self.refractory_period

        try:
            codeOut = StringIO()
            codeErr = StringIO()
            # capture output and errors
            sys.stdout = codeOut
            sys.stderr = codeErr

            exec(cond_statement_replaced, globals())

            # restore stdout and stderr
            sys.stdout = sys.__stdout__
            sys.stderr = sys.__stderr__
            py_error = codeErr.getvalue()
            py_output = codeOut.getvalue()

            # Evaluate conditional returned value (should be string of "1" (True) or "0" (False))
            if is_int(py_output):
                evaluated_statement = bool(int(py_output))
            else:
                evaluated_statement = False

            if py_error:
                self.logger.error("Error: {err}".format(err=py_error))

            codeOut.close()
            codeErr.close()

            # self.logger.info("Conditional Statement (evaluated): {}".format(eval(cond_statement_replaced)))
        except:
            self.logger.error(
                "Error evaluating conditional statement. "
                "Replaced Conditional Statement:\n\n{cond_rep}\n\n{traceback}".format(
                    cond_rep=cond_statement_replaced,
                    traceback=traceback.format_exc()))
            evaluated_statement = None
Ejemplo n.º 18
0
def output_add(form_add, request_form):
    messages = {
        "success": [],
        "info": [],
        "warning": [],
        "error": []
    }
    output_id = None
    dep_name = None
    size_y = None

    dict_outputs = parse_output_information()

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

    if current_app.config['TESTING']:
        dep_unmet = False
    else:
        dep_unmet, _ = return_dependencies(form_add.output_type.data.split(',')[0])
        if dep_unmet:
            list_unmet_deps = []
            for each_dep in dep_unmet:
                list_unmet_deps.append(each_dep[0])
            messages["error"].append(
                "{dev} has unmet dependencies. They must be installed before the Output can be added.".format(
                    dev=output_type))
            if output_type in dict_outputs:
                dep_name = dict_outputs[output_type]["output_name"]
            else:
                messages["error"].append("Output not found: {}".format(output_type))

            return messages, dep_name, list_unmet_deps, None, None

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

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

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

                new_output.name = "Name"
                new_output.interface = output_interface
                size_y = len(dict_outputs[output_type]['channels_dict']) + 1
                new_output.size_y = len(dict_outputs[output_type]['channels_dict']) + 1
                new_output.output_type = output_type
                new_output.position_y = 999

                #
                # Set default values for new input being added
                #

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

                    #
                    # Interfacing options
                    #

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

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

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

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

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

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

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

                # Generate string to save from custom options
                messages["error"], custom_options = custom_options_return_json(
                    messages["error"], dict_outputs, request_form, device=output_type, use_defaults=True)
                new_output.custom_options = custom_options

                #
                # Execute at Creation
                #

                new_output.unique_id = set_uuid()

                if 'execute_at_creation' in dict_outputs[output_type] and not current_app.config['TESTING']:
                    messages["error"], new_output = dict_outputs[output_type]['execute_at_creation'](
                        messages["error"], new_output, dict_outputs[output_type])

                if not messages["error"]:
                    new_output.save()
                    output_id = new_output.unique_id
                    db.session.commit()

                    messages["success"].append('{action} {controller}'.format(
                        action=TRANSLATIONS['add']['title'],
                        controller=TRANSLATIONS['output']['title']))

                    #
                    # If measurements defined in the Output Module
                    #

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

                    for each_channel, channel_info in dict_outputs[output_type]['channels_dict'].items():
                        new_channel = OutputChannel()
                        new_channel.channel = each_channel
                        new_channel.output_id = new_output.unique_id

                        # Generate string to save from custom options
                        messages["error"], custom_options = custom_channel_options_return_json(
                            messages["error"], dict_outputs, request_form,
                            new_output.unique_id, each_channel,
                            device=output_type, use_defaults=True)
                        new_channel.custom_options = custom_options

                        new_channel.save()

                    # Refresh output settings
                    if not current_app.config['TESTING']:
                        new_messages = manipulate_output(
                            'Add', new_output.unique_id)
                        messages["error"].extend(new_messages["error"])
                        messages["success"].extend(new_messages["success"])

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

    return messages, dep_unmet, None, output_id, size_y
Ejemplo n.º 19
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'))
Ejemplo n.º 20
0
def output_mod(form_output, request_form):
    action = '{action} {controller}'.format(
        action=TRANSLATIONS['modify']['title'],
        controller=TRANSLATIONS['output']['title'])
    error = []

    dict_outputs = parse_output_information()

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

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

        mod_output.name = form_output.name.data

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

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

        mod_output.log_level_debug = form_output.log_level_debug.data

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

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

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

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

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

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

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

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

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

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

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

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

                if output_type in [
                        'wired', 'wireless_rpi_rf', 'command', 'python'
                ]:
                    new_output.measurement = 'duration_time'
                    new_output.unit = 's'

                elif output_type in OUTPUTS_PWM:
                    new_output.measurement = 'duty_cycle'
                    new_output.unit = 'percent'

                new_output.channel = 0

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

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

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

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

                elif output_type == 'pwm':
                    new_output.pwm_hertz = 22000
                    new_output.pwm_library = 'pigpio_any'

                elif output_type == 'python':
                    new_output.on_command = """
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
write_string = "{ts}: ID: {id}: ON\\n".format(id=output_id, ts=timestamp)
with open("/home/pi/Mycodo/OutputTest.txt", "a") as myfile:
    myfile.write(write_string)"""
                    new_output.off_command = """
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
write_string = "{ts}: ID: {id}: OFF\\n".format(id=output_id, ts=timestamp)
with open("/home/pi/Mycodo/OutputTest.txt", "a") as myfile:
    myfile.write(write_string)"""

                elif output_type == 'python_pwm':
                    new_output.pwm_command = """
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
write_string = "{ts}: ID: {id}: Duty Cycle: ((duty_cycle)) %\\n".format(
    id=output_id, ts=timestamp)
with open("/home/pi/Mycodo/OutputTest.txt", "a") as myfile:
    myfile.write(write_string)"""

                elif output_type == 'atlas_ezo_pmp':
                    new_output.output_mode = 'fastest_flow_rate'
                    new_output.flow_rate = 10
                    if interface == 'FTDI':
                        new_output.location = '/dev/ttyUSB0'
                    elif interface == 'I2C':
                        new_output.location = '0x67'
                        new_output.i2c_bus = 1
                    elif interface == 'UART':
                        new_output.location = '/dev/ttyAMA0'
                        new_output.baud_rate = 9600

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

                    # Add device measurements
                    for measurement, measure_data in OUTPUT_INFO[
                            new_output.output_type]['measure'].items():
                        for unit, unit_data in measure_data.items():
                            for channel, _ in unit_data.items():
                                new_measurement = DeviceMeasurements()
                                new_measurement.device_id = new_output.unique_id
                                new_measurement.name = ''
                                new_measurement.is_enabled = True
                                new_measurement.measurement = measurement
                                new_measurement.unit = unit
                                new_measurement.channel = channel
                                new_measurement.save()

                    manipulate_output('Add', new_output.unique_id)
            except sqlalchemy.exc.OperationalError as except_msg:
                error.append(except_msg)
            except sqlalchemy.exc.IntegrityError as except_msg:
                error.append(except_msg)

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

    if dep_unmet:
        return 1
Ejemplo n.º 22
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'))