-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add saga * More changes * Add UI * Add comments
- Loading branch information
Showing
17 changed files
with
295 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
/*** | ||
* This file defines the UI to view robot statuses | ||
*/ | ||
|
||
import { Tag } from '@blueprintjs/core'; | ||
import { Box } from '@rebass/grid'; | ||
import * as React from 'react'; | ||
|
||
import { Flex } from 'SRC/components/Layout'; | ||
import { IRobotStatuses } from 'SRC/types'; | ||
import { theme } from 'SRC/constants'; | ||
|
||
interface IRobotStatusPanelProps { | ||
robotStatuses: IRobotStatuses; | ||
} | ||
|
||
/** | ||
* Displays robot statuses sorted by time | ||
*/ | ||
export const RobotStatusPanel = (props: IRobotStatusPanelProps) => { | ||
// Sort by time, then by robot number, then by message alphabetically | ||
const sortedRobotStatuses = Object.values(props.robotStatuses).sort((a, b) => { | ||
const timeDelta = a.timestamp - b.timestamp; | ||
const robotDelta = a.robot - b.robot; | ||
if (timeDelta != 0) { | ||
return timeDelta; | ||
} else if (robotDelta != 0) { | ||
return robotDelta; | ||
} else { | ||
return a.message.localeCompare(b.message); | ||
} | ||
}); | ||
|
||
return ( | ||
<Box padding="2px 0"> | ||
{sortedRobotStatuses.map((status) => ( | ||
<Flex | ||
key={`${status.robot}:${status.message}`} | ||
width="100%" | ||
alignItems="center" | ||
padding="2px 5px" | ||
> | ||
<Tag | ||
style={{ | ||
background: | ||
theme.qualitativeColorScale[ | ||
status.robot % theme.qualitativeColorScale.length | ||
], | ||
}} | ||
> | ||
Robot {status.robot} | ||
</Tag> | ||
<div style={{ marginLeft: '5px' }}>{status.message}</div> | ||
<Tag style={{ marginLeft: 'auto' }}>{status.timestamp} s. ago</Tag> | ||
</Flex> | ||
))} | ||
</Box> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
/* | ||
* This file specifies robot_status specific action | ||
* | ||
* We are using the format specified here | ||
* @see https://github.com/piotrwitek/typesafe-actions#createaction | ||
*/ | ||
|
||
import { createAction } from 'typesafe-actions'; | ||
|
||
import { IRobotStatuses } from 'SRC/types'; | ||
|
||
/** | ||
* Update the displayed list of robot statuses | ||
*/ | ||
export const updateRobotStatuses = createAction('status_UPDATE', (resolve) => { | ||
return (statuses: IRobotStatuses) => resolve({ statuses }); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/* | ||
* This file specifies the robots status reducer | ||
*/ | ||
|
||
import { ActionType, getType } from 'typesafe-actions'; | ||
|
||
import { IRobotStatusState } from 'SRC/types'; | ||
|
||
import * as status from '../actions/robotStatus'; | ||
|
||
export type StatusAction = ActionType<typeof status>; | ||
|
||
const defaultState: IRobotStatusState = { | ||
statuses: {}, | ||
}; | ||
|
||
/** | ||
* Reducer function for robot status | ||
*/ | ||
export default (state: IRobotStatusState = defaultState, action: StatusAction) => { | ||
switch (action.type) { | ||
case getType(status.updateRobotStatuses): | ||
return { | ||
...state, | ||
statuses: { ...state.statuses, ...action.payload.statuses }, | ||
}; | ||
default: | ||
return state; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/*** | ||
* This file defines the saga for robot statuses | ||
*/ | ||
|
||
import { channel } from 'redux-saga'; | ||
import { put, spawn, take, takeLatest } from 'redux-saga/effects'; | ||
import { getType } from 'typesafe-actions'; | ||
|
||
import { TOPIC_ROBOT_STATUS, TOPIC_ROBOT_STATUS_TYPE } from 'SRC/constants'; | ||
import { IRobotStatus, IRobotStatusMessage } from 'SRC/types'; | ||
import * as ROS from 'SRC/utils/ros'; | ||
|
||
import { actions } from '../actions/index'; | ||
|
||
const statusChannel = channel(); | ||
|
||
export default function* init() { | ||
// Listen to start actions and start robot status | ||
yield takeLatest(getType(actions.ros.connected), startRobotStatusSaga); | ||
|
||
// Start listening to robot status messages | ||
yield spawn(listenToConsoleChannel); | ||
} | ||
|
||
/** | ||
* Take any messages received from robot status and push them as Redux actions | ||
*/ | ||
function* listenToConsoleChannel() { | ||
while (true) { | ||
const action = yield take(statusChannel); | ||
yield put(action); | ||
} | ||
} | ||
|
||
let processedMessages: { [key: string]: IRobotStatus } = {}; | ||
|
||
/** | ||
* We subscribe to topic robot_status to start receiving messages | ||
*/ | ||
function startRobotStatusSaga() { | ||
ROS.subscribeToROSTopic( | ||
TOPIC_ROBOT_STATUS, | ||
TOPIC_ROBOT_STATUS_TYPE, | ||
(message: IRobotStatusMessage) => { | ||
processedMessages = { ...processedMessages, ...processMessage(message) }; | ||
}, | ||
100, | ||
); | ||
|
||
// We update the state once a second | ||
setTimeout(updateTimestampAndPush, 1000); | ||
} | ||
|
||
function updateTimestampAndPush() { | ||
// Push current robot status to the state | ||
statusChannel.put(actions.status.updateRobotStatuses(processedMessages)); | ||
|
||
// And increase timestamp by 1 (one second elapsed) | ||
Object.values(processedMessages).forEach((processedMessage) => { | ||
processedMessage.timestamp = processedMessage.timestamp + 1; | ||
}); | ||
setTimeout(updateTimestampAndPush, 1000); | ||
} | ||
|
||
function processMessage(message: IRobotStatusMessage) { | ||
const processedMessage: { [key: string]: IRobotStatus } = {}; | ||
message.robot_messages.forEach((robotMessage: string) => { | ||
const robotStatus: IRobotStatus = { | ||
message: robotMessage, | ||
robot: message.robot, | ||
timestamp: 0, | ||
}; | ||
|
||
processedMessage[`${message.robot}: ${robotMessage}`] = robotStatus; | ||
}); | ||
|
||
return processedMessage; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.