Esempio n. 1
0
async def post_serial_update(
        serial: str = Path(...,
                           description="Serial number of the module"),
        hardware: ThreadManager = Depends(get_hardware))\
        -> V1BasicResponse:
    """Update module firmware"""
    attached_modules = hardware.attached_modules     # type: ignore
    matching_module = find_matching_module(serial, attached_modules)

    if not matching_module:
        raise V1HandlerError(message=f'Module {serial} not found',
                             status_code=status.HTTP_404_NOT_FOUND)

    try:
        if matching_module.bundled_fw:
            await asyncio.wait_for(
                modules.update_firmware(
                    matching_module,
                    matching_module.bundled_fw.path,
                    asyncio.get_event_loop()),
                100)
            return V1BasicResponse(
                message=f'Successfully updated module {serial}'
            )
        else:
            res = (f'Bundled fw file not found for module of '
                   f'type: {matching_module.name()}')
            status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
    except modules.UpdateError as e:
        res = f'Update error: {e}'
        status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
    except asyncio.TimeoutError:
        res = 'Module not responding'
        status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
    raise V1HandlerError(message=res, status_code=status_code)
Esempio n. 2
0
async def post_home_robot(
        robot_home_target: control.RobotHomeTarget,
        hardware: ThreadManager = Depends(get_hardware),
        motion_lock: ThreadedAsyncLock = Depends(get_motion_lock)) \
        -> V1BasicResponse:
    """Home the robot or one of the pipettes"""
    try:
        async with motion_lock.forbid():
            mount = robot_home_target.mount
            target = robot_home_target.target

            home = hardware.home  # type: ignore
            home_plunger = hardware.home_plunger  # type: ignore

            if target == control.HomeTarget.pipette and mount:
                await home([Axis.by_mount(Mount[mount.upper()])])
                await home_plunger(Mount[mount.upper()])
                message = f"Pipette on {mount} homed successfully"
            elif target == control.HomeTarget.robot:
                await home()
                message = "Homing robot."
            else:
                raise V1HandlerError(message=f"{target} is invalid",
                                     status_code=status.HTTP_400_BAD_REQUEST)

            return V1BasicResponse(message=message)
    except ThreadedAsyncForbidden as e:
        raise V1HandlerError(status_code=status.HTTP_403_FORBIDDEN,
                             message=str(e))
Esempio n. 3
0
async def post_serial_command(
        command: SerialCommand,
        serial: str = Path(...,
                           description="Serial number of the module"),
        hardware: HardwareAPILike = Depends(get_hardware)) \
        -> SerialCommandResponse:
    """Send a command on device identified by serial"""
    attached_modules = hardware.attached_modules  # type: ignore
    if not attached_modules:
        raise V1HandlerError(message="No connected modules",
                             status_code=status.HTTP_404_NOT_FOUND)

    # Search for the module
    matching_mod = find_matching_module(serial, attached_modules)

    if not matching_mod:
        raise V1HandlerError(message="Specified module not found",
                             status_code=status.HTTP_404_NOT_FOUND)

    if hasattr(matching_mod, command.command_type):
        clean_args = command.args or []
        method = getattr(matching_mod, command.command_type)
        if asyncio.iscoroutinefunction(method):
            val = await method(*clean_args)
        else:
            val = method(*clean_args)

        return SerialCommandResponse(message='Success', returnValue=val)
    else:
        raise V1HandlerError(
            message=f'Module does not have command: {command.command_type}',
            status_code=status.HTTP_400_BAD_REQUEST)
Esempio n. 4
0
async def post_settings(update: AdvancedSettingRequest)\
        -> AdvancedSettingsResponse:
    """Update advanced setting (feature flag)"""
    try:
        await advanced_settings.set_adv_setting(update.id, update.value)
    except ValueError as e:
        raise V1HandlerError(message=str(e),
                             status_code=status.HTTP_400_BAD_REQUEST)
    except advanced_settings.SettingException as e:
        # Severe internal error
        raise V1HandlerError(message=str(e),
                             status_code=status.HTTP_500_INTERNAL_SERVER_ERROR)
    return _create_settings_response()
Esempio n. 5
0
async def post_calibration_deck_start(
        command: DeckStart = DeckStart(),
        hardware: ThreadManager = Depends(get_hardware)) \
        -> DeckStartResponse:
    try:
        res = await dc.create_session(command.force, hardware)
        return DeckStartResponse(token=UUID(res.token),
                                 pipette=PipetteDeckCalibration(**res.pipette))
    except dc.SessionForbidden as e:
        raise V1HandlerError(status_code=status.HTTP_403_FORBIDDEN,
                             message=str(e))
    except dc.SessionInProgress as e:
        raise V1HandlerError(status_code=status.HTTP_409_CONFLICT,
                             message=str(e))
Esempio n. 6
0
async def post_calibration_deck(operation: DeckCalibrationDispatch) \
        -> V1BasicResponse:
    try:
        res = await dc.dispatch(token=str(operation.token),
                                command=operation.command,
                                command_data=operation.dict(
                                    exclude={'token', 'command'},
                                    exclude_none=True))

        if not res.success:
            raise AssertionError(res.message)

        return V1BasicResponse(message=res.message)
    except dc.NoSessionInProgress as e:
        message = str(e)
        status_code = 418
    except dc.SessionForbidden as e:
        message = str(e)
        status_code = status.HTTP_403_FORBIDDEN
    except AssertionError as e:
        message = str(e)
        status_code = status.HTTP_400_BAD_REQUEST
    except Exception as e:
        message = f'Exception {type(e)} raised by dispatch of {operation}: {e}'
        status_code = status.HTTP_500_INTERNAL_SERVER_ERROR

    raise V1HandlerError(status_code=status_code, message=message)
Esempio n. 7
0
async def post_log_level_upstream(log_level: LogLevel) -> V1BasicResponse:
    log_level_value = log_level.log_level
    log_level_name = None if log_level_value is None else log_level_value.name
    ok_syslogs = {
        LogLevels.error.name: "err",
        LogLevels.warning.name: "warning",
        LogLevels.info.name: "info",
        LogLevels.debug.name: "debug"
    }

    syslog_level = "emerg"
    if log_level_name is not None:
        syslog_level = ok_syslogs[log_level_name]

    code, stdout, stderr = await log_control.set_syslog_level(syslog_level)

    if code != 0:
        msg = f"Could not reload config: {stdout} {stderr}"
        log.error(msg)
        raise V1HandlerError(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                             message=msg)

    if log_level_name:
        result = f"Upstreaming log level changed to {log_level_name}"
        getattr(log, log_level_name)(result)
    else:
        result = "Upstreaming logs disabled"
        log.info(result)

    return V1BasicResponse(message=result)
Esempio n. 8
0
async def delete_wifi_key(key_uuid: str = Path(
    ...,
    description="The ID of key to delete, as determined by a previous"
    " call to GET /wifi/keys")) -> V1BasicResponse:
    """Delete wifi key handler"""
    deleted_file = wifi.remove_key(key_uuid)
    if not deleted_file:
        raise V1HandlerError(status.HTTP_404_NOT_FOUND,
                             message=f"No such key file {key_uuid}")
    return V1BasicResponse(message=f'Key file {deleted_file} deleted')
Esempio n. 9
0
async def get_engaged_motors(hardware: ThreadManager = Depends(get_hardware)
                             ) -> model.EngagedMotors:  # type: ignore
    try:
        engaged_axes = hardware.engaged_axes    # type: ignore
        axes_dict = {str(k).lower(): model.EngagedMotor(enabled=v)
                     for k, v in engaged_axes.items()}
        return model.EngagedMotors(**axes_dict)
    except ValidationError as e:
        raise V1HandlerError(
            status.HTTP_500_INTERNAL_SERVER_ERROR, str(e)
        )
Esempio n. 10
0
async def post_wifi_configure(configuration: WifiConfiguration)\
        -> WifiConfigurationResponse:
    try:
        psk = configuration.psk.get_secret_value() if \
            configuration.psk else None
        ok, message = await nmcli.configure(
            ssid=configuration.ssid,
            securityType=nmcli.SECURITY_TYPES(configuration.securityType),
            eapConfig=configuration.eapConfig,
            hidden=configuration.hidden is True,
            psk=psk)
        log.debug(f"Wifi configure result: {message}")
    except (ValueError, TypeError) as e:
        # Indicates an unexpected kwarg; check is done here to avoid keeping
        # the _check_configure_args signature up to date with nmcli.configure
        raise V1HandlerError(status.HTTP_400_BAD_REQUEST, str(e))

    if not ok:
        raise V1HandlerError(status.HTTP_401_UNAUTHORIZED, message=message)

    return WifiConfigurationResponse(message=message, ssid=configuration.ssid)
Esempio n. 11
0
async def post_move_robot(
        robot_move_target: control.RobotMoveTarget,
        hardware: ThreadManager = Depends(get_hardware),
        motion_lock: ThreadedAsyncLock = Depends(get_motion_lock))\
        -> V1BasicResponse:
    """Move the robot"""
    try:
        async with motion_lock.forbid():
            pos = await _do_move(hardware=hardware,
                                 robot_move_target=robot_move_target)
            return V1BasicResponse(
                message=f"Move complete. New position: {pos}")
    except ThreadedAsyncForbidden as e:
        raise V1HandlerError(status_code=status.HTTP_403_FORBIDDEN,
                             message=str(e))
Esempio n. 12
0
async def get_module_serial(
        serial: str = Path(...,
                           description="Serial number of the module"),
        hardware: ThreadManager = Depends(get_hardware)) \
        -> ModuleSerial:
    res = None

    attached_modules = hardware.attached_modules   # type: ignore
    matching_module = find_matching_module(serial, attached_modules)
    if matching_module and hasattr(matching_module, 'live_data'):
        res = matching_module.live_data

    if not res:
        raise V1HandlerError(status_code=status.HTTP_404_NOT_FOUND,
                             message="Module not found")
    return ModuleSerial(status=res.get('status'), data=res.get('data'))
Esempio n. 13
0
async def post_log_level_local(
    log_level: LogLevel, hardware: HardwareAPILike = Depends(get_hardware)
) -> V1BasicResponse:
    """Update local log level"""
    level = log_level.log_level
    if not level:
        raise V1HandlerError(message="log_level must be set",
                             status_code=status.HTTP_422_UNPROCESSABLE_ENTITY)
    # Level name is upper case
    level_name = level.value.upper()
    # Set the log levels
    for logger_name in ('opentrons', 'robot_server', 'uvicorn'):
        logging.getLogger(logger_name).setLevel(level.level_id)
    # Update and save settings
    await hardware.update_config(log_level=level_name)  # type: ignore
    robot_configs.save_robot_settings(hardware.config)  # type: ignore

    return V1BasicResponse(message=f'log_level set to {level}')
Esempio n. 14
0
async def patch_pipette_setting(
        pipette_id: str,
        settings_update: PipetteSettingsUpdate) \
        -> PipetteSettings:

    # Convert fields to dict of field name to value
    fields = settings_update.setting_fields or {}
    field_values = {
        k: None if v is None else v.value
        for k, v in fields.items()
    }
    if field_values:
        try:
            pipette_config.override(fields=field_values, pipette_id=pipette_id)
        except ValueError as e:
            raise V1HandlerError(
                status_code=status.HTTP_412_PRECONDITION_FAILED,
                message=str(e))
    r = _pipette_settings_from_config(pipette_config, pipette_id)
    return r
Esempio n. 15
0
async def get_pipette_setting(pipette_id: str) -> PipetteSettings:
    if pipette_id not in pipette_config.known_pipettes():
        raise V1HandlerError(status_code=status.HTTP_404_NOT_FOUND,
                             message=f'{pipette_id} is not a valid pipette id')
    r = _pipette_settings_from_config(pipette_config, pipette_id)
    return r