Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(app): Run timer stays at 00:00:00 if you reconnect in the middle of a delay #7841

Closed
wants to merge 11 commits into from
5 changes: 4 additions & 1 deletion api/src/opentrons/hardware_control/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,10 @@ async def delay(self, duration_s: float):
await self._wait_for_is_running()
self.pause(PauseType.DELAY)
try:
if not self.is_simulator:
if self.is_simulator:
celsasser marked this conversation as resolved.
Show resolved Hide resolved
print(f'sleeping {duration_s/60} minutes')
await asyncio.sleep(duration_s)
else:
async def sleep_for_seconds(seconds: float):
await asyncio.sleep(seconds)
delay_task = self._loop.create_task(sleep_for_seconds(duration_s))
Expand Down
4 changes: 3 additions & 1 deletion app/src/redux/robot/api-client/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,9 @@ export function client(dispatch) {
function setRunTimerInterval() {
if (runTimerInterval === NO_INTERVAL) {
runTimerInterval = setInterval(
() => dispatch(actions.tickRunTime()),
() => {
dispatch(actions.tickRunTime())
},
RUN_TIME_TICK_INTERVAL_MS
)
}
Expand Down
36 changes: 32 additions & 4 deletions app/src/redux/robot/reducer/session.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ export type SessionState = {
remoteTimeCompensation: number | null,
startTime: ?number,
runTime: number,
/**
* Set to `Date.now()` when session is paused. Set to `0` when session is resumed.
* todo? Managed locally. Lost if the app is re-loaded. How interested are we in this functionality?
*/
pausedTime: number,
/**
* Updated after cycle of pause -> resume.
* todo? Managed locally. Lost if the app is re-loaded. How interested are we in this functionality?
*/
pausedDuration: number,
apiLevel: [number, number] | null,
capabilities: Array<string>,
}
Expand Down Expand Up @@ -104,13 +114,16 @@ const INITIAL_STATE: SessionState = {
remoteTimeCompensation: null,
startTime: null,
runTime: 0,
pausedTime: 0,
pausedDuration: 0,
apiLevel: null,
}

export function sessionReducer(
state: SessionState = INITIAL_STATE,
action: Action
): SessionState {
console.log(`sessionReducer ${action.type}, action=`, action);
celsasser marked this conversation as resolved.
Show resolved Hide resolved
switch (action.type) {
case 'robot:CONNECT_RESPONSE': {
if (action.payload.error) return state
Expand Down Expand Up @@ -220,10 +233,15 @@ function handleSessionUpdate(
}

function handleSessionInProgress(state: SessionState): SessionState {
console.log('handleSessionInProgress', state);
return {
...state,
// todo: ce - think we want to pick up where we left off?
pausedDuration: 0,
// todo: ce - think we want to pick up where we left off?
runTime: 0,
startTime: null,
// todo: ce - think we want to pick up where we left off?
celsasser marked this conversation as resolved.
Show resolved Hide resolved
startTime: Date.now(),
remoteTimeCompensation: null,
sessionRequest: { inProgress: true, error: null },
}
Expand Down Expand Up @@ -262,7 +280,7 @@ function handleInvalidFile(
}

function handleRun(state: SessionState, action: any): SessionState {
return { ...state, runTime: 0, runRequest: { inProgress: true, error: null } }
return { ...state, runTime: Date.now(), runRequest: { inProgress: true, error: null } }
}

function handleRunResponse(state: SessionState, action: any): SessionState {
Expand All @@ -280,7 +298,11 @@ function handleTickRunTime(state: SessionState, action: any): SessionState {
}

function handlePause(state: SessionState, action: any): SessionState {
return { ...state, pauseRequest: { inProgress: true, error: null } }
return { ...state,
pausedTime: Date.now(),
pauseRequest: { inProgress: true, error: null },
runTime: Date.now()
}
}

function handlePauseResponse(state: SessionState, action: any): SessionState {
Expand All @@ -294,7 +316,13 @@ function handlePauseResponse(state: SessionState, action: any): SessionState {
}

function handleResume(state: SessionState, action: any): SessionState {
return { ...state, resumeRequest: { inProgress: true, error: null } }
const pausedDuration = state.pausedTime ? Date.now() - state.pausedTime : 0;
return { ...state,
pausedDuration: state.pausedDuration + pausedDuration,
pausedTime: 0,
resumeRequest: { inProgress: true, error: null },
runTime: Date.now()
}
}

function handleResumeResponse(state: SessionState, action: any): SessionState {
Expand Down
25 changes: 12 additions & 13 deletions app/src/redux/robot/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,12 +203,13 @@ export const getSessionError: State => string | null = createSelector(

const getStartTimeMs = (state: State): number | null => {
const { startTime, remoteTimeCompensation } = session(state)

if (startTime == null || remoteTimeCompensation === null) {
if (startTime == null) {
return null
}

return startTime + remoteTimeCompensation
// [7740] ce: 5/26/2021 - upon reload `remoteTimeCompensation` is null.
// will look to see why, but in the meantime this solves the start-time
// issue on reload but may create other issues?
return startTime + remoteTimeCompensation || 0
}

export const getStartTime: (state: State) => string | null = createSelector(
Expand All @@ -218,15 +219,13 @@ export const getStartTime: (state: State) => string | null = createSelector(
}
)

export const getRunSeconds: State => number = createSelector(
getStartTimeMs,
(state: State) => session(state).runTime,
(startTime: ?number, runTime: ?number): number => {
return runTime && startTime && runTime > startTime
? Math.floor((runTime - startTime) / 1000)
: 0
}
)
export function getRunSeconds(state: State): number {
const {startTime, runTime, pausedDuration} = session(state);
console.log('getRunSeconds: ', {startTime, runTime, pausedDuration});
celsasser marked this conversation as resolved.
Show resolved Hide resolved
return runTime && startTime && runTime > startTime
? Math.floor((runTime - startTime - pausedDuration) / 1000)
: 0
}

export function formatSeconds(runSeconds: number): string {
const hours = padStart(`${Math.floor(runSeconds / 3600)}`, 2, '0')
Expand Down
1 change: 1 addition & 0 deletions app/src/rpc/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ class RpcContext extends EventEmitter {
// then cache its type object
this._cacheCallResultMetadata(root)
this._cacheCallResultMetadata(rootType)
console.log('_handleMessage', this._resultTypes, this._typeObjectCache);

if (meta.monitor) this._startMonitoring()

Expand Down
1 change: 1 addition & 0 deletions app/src/rpc/websocket-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ function parseMessage(data) {

try {
message = JSON.parse(data)
console.log(`rpc.parseMessage: ${data}`);
celsasser marked this conversation as resolved.
Show resolved Hide resolved
} catch (e) {
console.warn('JSON parse error', e)
}
Expand Down