Skip to content

Commit

Permalink
activate PromptButton
Browse files Browse the repository at this point in the history
  • Loading branch information
koji committed Apr 23, 2024
2 parents 685417b + 4794f55 commit f14b71c
Show file tree
Hide file tree
Showing 75 changed files with 1,602 additions and 350 deletions.
1 change: 1 addition & 0 deletions .eslintcache

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions api-client/src/robot/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export { acknowledgeEstopDisengage } from './acknowledgeEstopDisengage'
export { getLights } from './getLights'
export { setLights } from './setLights'
export { getRobotSettings } from './getRobotSettings'
export { updateRobotSetting } from './updateRobotSetting'

export type {
DoorStatus,
Expand All @@ -15,4 +16,5 @@ export type {
RobotSettingsField,
RobotSettingsResponse,
SetLightsData,
UpdateRobotSettingRequest,
} from './types'
5 changes: 5 additions & 0 deletions api-client/src/robot/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ export interface RobotSettingsField {

export type RobotSettings = RobotSettingsField[]

export interface UpdateRobotSettingRequest {
id: string
value: boolean | null
}

export interface RobotSettingsResponse {
settings: RobotSettings
links?: { restart?: string }
Expand Down
18 changes: 18 additions & 0 deletions api-client/src/robot/updateRobotSetting.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { POST, request } from '../request'

import type { ResponsePromise } from '../request'
import type { HostConfig } from '../types'
import type { RobotSettingsResponse, UpdateRobotSettingRequest } from './types'

export function updateRobotSetting(
config: HostConfig,
id: string,
value: boolean
): ResponsePromise<RobotSettingsResponse> {
return request<RobotSettingsResponse, UpdateRobotSettingRequest>(
POST,
'/settings',
{ id, value },
config
)
}
24 changes: 24 additions & 0 deletions api-client/src/system/createSplash.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { POST, request } from '../request'
import type { ResponsePromise } from '../request'
import type { HostConfig } from '../types'

export function createSplash(
config: HostConfig,
file: File
): ResponsePromise<void> {
// sanitize file name to ensure no spaces
const renamedFile = new File([file], file.name.replace(' ', '_'), {
type: 'image/png',
})

const formData = new FormData()
formData.append('file', renamedFile)

// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
return request<void, FormData>(
POST,
'/system/oem_mode/upload_splash',
formData,
config
)
}
1 change: 1 addition & 0 deletions api-client/src/system/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export { createAuthorization } from './createAuthorization'
export { createRegistration } from './createRegistration'
export { createSplash } from './createSplash'
export { getConnections } from './getConnections'
export * from './types'
64 changes: 59 additions & 5 deletions api/src/opentrons/config/defaults_ot3.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from typing import Any, Dict, cast, List, Iterable, Tuple
from typing import Any, Dict, cast, List, Iterable, Tuple, Optional
from typing_extensions import Final
from dataclasses import asdict

from opentrons.hardware_control.types import OT3AxisKind
from opentrons.hardware_control.types import OT3AxisKind, InstrumentProbeType
from .types import (
OT3Config,
ByGantryLoad,
Expand Down Expand Up @@ -34,7 +34,7 @@
aspirate_while_sensing=False,
auto_zero_sensor=True,
num_baseline_reads=10,
data_file="/var/pressure_sensor_data.csv",
data_files={InstrumentProbeType.PRIMARY: "/data/pressure_sensor_data.csv"},
)

DEFAULT_CALIBRATION_SETTINGS: Final[OT3CalibrationSettings] = OT3CalibrationSettings(
Expand Down Expand Up @@ -194,6 +194,49 @@
)


def _build_output_option_with_default(
from_conf: Any, default: OutputOptions
) -> OutputOptions:
if from_conf is None:
return default
else:
if isinstance(from_conf, OutputOptions):
return from_conf
else:
try:
enumval = OutputOptions[from_conf]
except KeyError: # not an enum entry
return default
else:
return enumval


def _build_log_files_with_default(
from_conf: Any,
default: Optional[Dict[InstrumentProbeType, str]],
) -> Optional[Dict[InstrumentProbeType, str]]:
print(f"from_conf {from_conf} default {default}")
if not isinstance(from_conf, dict):
if default is None:
return None
else:
return {k: v for k, v in default.items()}
else:
validated: Dict[InstrumentProbeType, str] = {}
for k, v in from_conf.items():
if isinstance(k, InstrumentProbeType):
validated[k] = v
else:
try:
enumval = InstrumentProbeType[k]
except KeyError: # not an enum entry
pass
else:
validated[enumval] = v
print(f"result {validated}")
return validated


def _build_dict_with_default(
from_conf: Any,
default: Dict[OT3AxisKind, float],
Expand Down Expand Up @@ -278,6 +321,17 @@ def _build_default_cap_pass(
def _build_default_liquid_probe(
from_conf: Any, default: LiquidProbeSettings
) -> LiquidProbeSettings:
output_option = _build_output_option_with_default(
from_conf.get("output_option", None), default.output_option
)
data_files: Optional[Dict[InstrumentProbeType, str]] = None
if (
output_option is OutputOptions.sync_buffer_to_csv
or output_option is OutputOptions.stream_to_csv
):
data_files = _build_log_files_with_default(
from_conf.get("data_files", {}), default.data_files
)
return LiquidProbeSettings(
starting_mount_height=from_conf.get(
"starting_mount_height", default.starting_mount_height
Expand All @@ -302,7 +356,7 @@ def _build_default_liquid_probe(
num_baseline_reads=from_conf.get(
"num_baseline_reads", default.num_baseline_reads
),
data_file=from_conf.get("data_file", default.data_file),
data_files=data_files,
)


Expand Down Expand Up @@ -412,7 +466,7 @@ def build_with_defaults(robot_settings: Dict[str, Any]) -> OT3Config:
def serialize(config: OT3Config) -> Dict[str, Any]:
def _build_dict(pairs: Iterable[Tuple[Any, Any]]) -> Dict[str, Any]:
def _normalize_key(key: Any) -> Any:
if isinstance(key, OT3AxisKind):
if isinstance(key, OT3AxisKind) or isinstance(key, InstrumentProbeType):
return key.name
return key

Expand Down
4 changes: 2 additions & 2 deletions api/src/opentrons/config/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from dataclasses import dataclass, asdict, fields
from typing import Dict, Tuple, TypeVar, Generic, List, cast, Optional
from typing_extensions import TypedDict, Literal
from opentrons.hardware_control.types import OT3AxisKind
from opentrons.hardware_control.types import OT3AxisKind, InstrumentProbeType


class AxisDict(TypedDict):
Expand Down Expand Up @@ -139,7 +139,7 @@ class LiquidProbeSettings:
aspirate_while_sensing: bool
auto_zero_sensor: bool
num_baseline_reads: int
data_file: Optional[str]
data_files: Optional[Dict[InstrumentProbeType, str]]


@dataclass(frozen=True)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ async def liquid_probe(
plunger_speed: float,
threshold_pascals: float,
output_format: OutputOptions = OutputOptions.can_bus_only,
data_file: Optional[str] = None,
data_files: Optional[Dict[InstrumentProbeType, str]] = None,
auto_zero_sensor: bool = True,
num_baseline_reads: int = 10,
probe: InstrumentProbeType = InstrumentProbeType.PRIMARY,
Expand Down
12 changes: 10 additions & 2 deletions api/src/opentrons/hardware_control/backends/ot3controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -1351,7 +1351,7 @@ async def liquid_probe(
plunger_speed: float,
threshold_pascals: float,
output_option: OutputOptions = OutputOptions.can_bus_only,
data_file: Optional[str] = None,
data_files: Optional[Dict[InstrumentProbeType, str]] = None,
auto_zero_sensor: bool = True,
num_baseline_reads: int = 10,
probe: InstrumentProbeType = InstrumentProbeType.PRIMARY,
Expand All @@ -1372,6 +1372,14 @@ async def liquid_probe(
can_bus_only_output = bool(
output_option.value & OutputOptions.can_bus_only.value
)
data_files_transposed = (
None
if data_files is None
else {
sensor_id_for_instrument(probe): data_files[probe]
for probe in data_files.keys()
}
)
positions = await liquid_probe(
messenger=self._messenger,
tool=tool,
Expand All @@ -1383,7 +1391,7 @@ async def liquid_probe(
csv_output=csv_output,
sync_buffer_output=sync_buffer_output,
can_bus_only_output=can_bus_only_output,
data_file=data_file,
data_files=data_files_transposed,
auto_zero_sensor=auto_zero_sensor,
num_baseline_reads=num_baseline_reads,
sensor_id=sensor_id_for_instrument(probe),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ async def liquid_probe(
plunger_speed: float,
threshold_pascals: float,
output_format: OutputOptions = OutputOptions.can_bus_only,
data_file: Optional[str] = None,
data_files: Optional[Dict[InstrumentProbeType, str]] = None,
auto_zero_sensor: bool = True,
num_baseline_reads: int = 10,
probe: InstrumentProbeType = InstrumentProbeType.PRIMARY,
Expand Down
1 change: 1 addition & 0 deletions api/src/opentrons/hardware_control/backends/ot3utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,7 @@ def sensor_node_for_pipette(mount: OT3Mount) -> PipetteProbeTarget:
_instr_sensor_id_lookup: Dict[InstrumentProbeType, SensorId] = {
InstrumentProbeType.PRIMARY: SensorId.S0,
InstrumentProbeType.SECONDARY: SensorId.S1,
InstrumentProbeType.BOTH: SensorId.BOTH,
}


Expand Down
10 changes: 2 additions & 8 deletions api/src/opentrons/hardware_control/ot3api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1521,14 +1521,8 @@ async def _home_axis(self, axis: Axis) -> None:
# G, Q should be handled in the backend through `self._home()`
assert axis not in [Axis.G, Axis.Q]

# TODO(CM): This is a temporary fix in response to the right mount causing
# errors while trying to home on startup or attachment. We should remove this
# when we fix this issue in the firmware.
enable_right_mount_on_startup = (
self._gantry_load == GantryLoad.HIGH_THROUGHPUT and axis == Axis.Z_R
)
encoder_ok = self._backend.check_encoder_status([axis])
if encoder_ok or enable_right_mount_on_startup:
if encoder_ok:
# enable motor (if needed) and update estimation
await self._enable_before_update_estimation(axis)

Expand Down Expand Up @@ -2601,7 +2595,7 @@ async def liquid_probe(
(probe_settings.plunger_speed * plunger_direction),
probe_settings.sensor_threshold_pascals,
probe_settings.output_option,
probe_settings.data_file,
probe_settings.data_files,
probe_settings.auto_zero_sensor,
probe_settings.num_baseline_reads,
probe=probe if probe else InstrumentProbeType.PRIMARY,
Expand Down
1 change: 1 addition & 0 deletions api/src/opentrons/hardware_control/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,7 @@ class GripperJawState(enum.Enum):
class InstrumentProbeType(enum.Enum):
PRIMARY = enum.auto()
SECONDARY = enum.auto()
BOTH = enum.auto()


class GripperProbe(enum.Enum):
Expand Down
1 change: 1 addition & 0 deletions api/src/opentrons/protocol_engine/actions/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ class QueueCommandAction:
created_at: datetime
request: CommandCreate
request_hash: Optional[str]
failed_command_id: Optional[str] = None


@dataclass(frozen=True)
Expand Down
4 changes: 2 additions & 2 deletions api/src/opentrons/protocol_engine/commands/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from . import thermocycler
from . import calibration

from .hash_command_params import hash_command_params
from .hash_command_params import hash_protocol_command_params
from .generate_command_schema import generate_command_schema

from .command import (
Expand Down Expand Up @@ -333,7 +333,7 @@
"CommandStatus",
"CommandIntent",
# command parameter hashing
"hash_command_params",
"hash_protocol_command_params",
# command schema generation
"generate_command_schema",
# aspirate command models
Expand Down
7 changes: 7 additions & 0 deletions api/src/opentrons/protocol_engine/commands/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class CommandIntent(str, Enum):

PROTOCOL = "protocol"
SETUP = "setup"
FIXIT = "fixit"


class BaseCommandCreate(GenericModel, Generic[CommandParamsT]):
Expand Down Expand Up @@ -159,6 +160,12 @@ class BaseCommand(GenericModel, Generic[CommandParamsT, CommandResultT]):
" the command's execution or the command's generation."
),
)
failedCommandId: Optional[str] = Field(
None,
description=(
"FIXIT command use only. Reference of the failed command id we are trying to fix."
),
)


class AbstractCommandImpl(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
# TODO(mm, 2023-04-28):
# This implementation will not notice that commands are different if they have different params
# but share the same commandType. We should also hash command params. (Jira RCORE-326.)
def hash_command_params(
def hash_protocol_command_params(
create: CommandCreate, last_hash: Optional[str]
) -> Optional[str]:
"""Given a command create object, return a hash.
Expand All @@ -28,12 +28,11 @@ def hash_command_params(
The command hash, if the command is a protocol command.
`None` if the command is a setup command.
"""
if create.intent == CommandIntent.SETUP:
if create.intent != CommandIntent.PROTOCOL:
return None
else:
# We avoid Python's built-in hash() function because it's not stable across
# runs of the Python interpreter. (Jira RSS-215.)
last_contribution = b"" if last_hash is None else last_hash.encode("ascii")
this_contribution = md5(create.commandType.encode("ascii")).digest()
to_hash = last_contribution + this_contribution
return md5(to_hash).hexdigest()
# We avoid Python's built-in hash() function because it's not stable across
# runs of the Python interpreter. (Jira RSS-215.)
last_contribution = b"" if last_hash is None else last_hash.encode("ascii")
this_contribution = md5(create.commandType.encode("ascii")).digest()
to_hash = last_contribution + this_contribution
return md5(to_hash).hexdigest()
Loading

0 comments on commit f14b71c

Please sign in to comment.