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

Add Shepherd overlay and double video feed #86

Open
wants to merge 52 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
a2d36a7
Push starter files
HaileyJang Mar 11, 2021
07f8b4f
updated keyboard connect/disconnect
uthmanmomen13 Mar 11, 2021
78eebf2
Videofeed Window In process
HaileyJang Mar 13, 2021
cfced80
removed unnecessary bitmap change in editor.tsx
uthmanmomen13 Mar 13, 2021
af275cd
Change buttons back to 0
ewc340 Mar 13, 2021
7a84455
Now the button is funky
HaileyJang Mar 13, 2021
85239a6
Merge branch 'keyboard-video-feed' of https://github.com/pioneers/daw…
HaileyJang Mar 13, 2021
bea3af7
Fix merge conflicts
ewc340 Mar 20, 2021
6cc06a8
Remove duplicate sendKeyboardInputs function
ewc340 Mar 20, 2021
345ce20
Change VideoFeed component to functional
ewc340 Mar 20, 2021
c545e02
Changed to functional component
HaileyJang Mar 20, 2021
e2bce0e
Fix merge conflict
HaileyJang Mar 20, 2021
a1b5d8c
Added Ovenplayer as module and added type declaration
HaileyJang Mar 23, 2021
5a1e627
Small naming change for main video player
ewc340 Mar 23, 2021
cae7025
Change video feed html title
ewc340 Mar 23, 2021
5e7328a
More changes
HaileyJang Mar 23, 2021
8add5a3
Fix network error
ewc340 Mar 23, 2021
b93beac
Add try/catch to RendererBridge reduxDispatch
ewc340 Mar 23, 2021
2b1b33a
Add maximize to video feed window
ewc340 Mar 23, 2021
e552479
Add overhead video feed and styling
ewc340 Mar 23, 2021
8bdc0bf
Fix variable spacing
ewc340 Mar 23, 2021
7269bdd
Fix merge conflict
HaileyJang Mar 24, 2021
2e4aeb5
Fixed button issue
HaileyJang Mar 27, 2021
d6b79b6
Add Shepherd overlay
ewc340 Mar 27, 2021
d804515
Add ctrl + q special case and make button text more explicit
ewc340 Mar 27, 2021
917a5ff
Fix merge conflicts
ewc340 Mar 27, 2021
2f7d39d
Add overlay url box
ewc340 Mar 28, 2021
b15de5b
Style tweaks
ewc340 Mar 28, 2021
a034d64
Fix sandstorm showing
ewc340 Mar 28, 2021
fe7dd19
Fix video feed button click, turn off scoreboard overlay toggling, an…
ewc340 Mar 30, 2021
cd2cbb0
Fix video feed multiple key send bug and Editor.tsx ctrl+q disconnect…
ewc340 Mar 31, 2021
de2f4a7
Merge branch 'dev' into shepherd-overlay
ewc340 Apr 10, 2021
0e5a296
Merge branch 'dev' into shepherd-overlay
ewc340 Apr 15, 2021
5717ede
Add new RendererBridge changes
ewc340 Apr 22, 2021
08f0c74
Integrate new RendererBridge changes in main-process and FieldControl
ewc340 Apr 22, 2021
adf28e8
Merge branch 'dev' into shepherd-overlay
ewc340 Apr 22, 2021
825bc67
Make scoreboard responsive
ewc340 Apr 22, 2021
86b87d8
Slight css tweak
ewc340 Apr 22, 2021
6689895
Add clearInterval for setInterval calls in Runtime
ewc340 Apr 29, 2021
aa21258
Fix merge conflicts from dev
ewc340 Apr 29, 2021
0629dd3
Switch Runtime connection establishment to TCP
ewc340 Apr 30, 2021
bbb1fe2
Make runtimeHeartbeat deprecated
ewc340 Apr 30, 2021
793bda9
Lint ConfigBox
ewc340 Apr 30, 2021
9eb2198
Change video feed naming
ewc340 Apr 30, 2021
bdcdb9e
Merge branch 'dev' into shepherd-overlay
ewc340 Apr 30, 2021
9499715
Remove runtimeHeartbeat from sagas
ewc340 Apr 30, 2021
f4b08db
Add connectionStatus: true in RUNTIME_CONNECT action
ewc340 Apr 30, 2021
ce002db
Remove formatter for js in webpack config
ewc340 Apr 30, 2021
5cf3d5b
Remove scoreboard toggle on/off for now - so always on for now
ewc340 Apr 30, 2021
7250195
Fix scoreboard outer container width and add newlines
ewc340 Apr 30, 2021
cf78092
Add another newline in scoreboard.html
ewc340 Apr 30, 2021
52d01d2
Add another newline in scoreboard.css
ewc340 Apr 30, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions main/MenuTemplate/DebugMenu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,13 @@ const DebugMenu: MenuItemConstructorOptions = {
});
},
},

{
label: 'Toggle Videofeed DevTools',
click() {
RendererBridge.toggleWindowDevtools('video_feed');
},
},
],
};

Expand Down
27 changes: 27 additions & 0 deletions main/main-process.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ export default function showAPI() {
}

app.on('ready', () => {
let videoWindow: BrowserWindow | null = null;

Runtime.setup();
ipcMain.on('FC_CONFIG_CHANGE', FCObject.changeFCInfo);
ipcMain.on('FC_INITIALIZE', initializeFC);
Expand All @@ -73,6 +75,31 @@ app.on('ready', () => {
}
});

ipcMain.on('SHOW_VIDEO_FEED', () => {
if (!videoWindow) {
videoWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: true,
enableRemoteModule: true,
},
width: 1000,
height: 700,
});
RendererBridge.registerWindow('video_feed', videoWindow);
videoWindow.on('closed', () => {
videoWindow = null;
});
videoWindow.maximize();
videoWindow.loadURL(`file://${__dirname}/../static/video-feed/video.html`);
videoWindow.webContents.on('dom-ready', () => RendererBridge.dispatch('video_feed', 'shepherdScoreboardServerIpAddress', FCObject.bridgeAddress))
videoWindow.on('ready-to-show', () => {
if (videoWindow) {
videoWindow.show();
}
});
}
})

// Binding for the main process to inject into Redux workflow
RendererBridge.registerWindow('main', mainWindow);

Expand Down
3 changes: 2 additions & 1 deletion main/networking/FieldControl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class FCInternals {
}

init() {
this.socket = io(`http://${this.bridgeAddress}:7000`);
this.socket = io.connect(this.bridgeAddress);
this.socket.on('connect', () => {
this.logger.log('Connected to Field Control Socket');
this.socket!.on('robot_state', (data: any) => {
Expand Down Expand Up @@ -76,6 +76,7 @@ export const FCObject = {

if (arg.bridgeAddress !== null) {
FCObject.bridgeAddress = arg.bridgeAddress;
RendererBridge.dispatch('video_feed', 'shepherdScoreboardServerIpAddress', arg.bridgeAddress);
}
},
};
14 changes: 9 additions & 5 deletions main/networking/Runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as protos from '../../protos/protos';

import RendererBridge from '../RendererBridge';
import { updateConsole } from '../../renderer/actions/ConsoleActions';
import { runtimeDisconnect, infoPerMessage } from '../../renderer/actions/InfoActions';
import { runtimeConnect, runtimeDisconnect } from '../../renderer/actions/InfoActions';
import { updatePeripherals } from '../../renderer/actions/PeripheralActions';
import { Logger, defaults } from '../../renderer/utils/utils';
import { Peripheral } from '../../renderer/types';
Expand Down Expand Up @@ -153,6 +153,7 @@ class UDPTunneledConn {
udpForwarder: UDPSocket;
ip: string;
port: number;
connectionInterval: ReturnType<typeof setInterval>;

constructor(logger: Logger) {
this.logger = logger;
Expand All @@ -161,7 +162,7 @@ class UDPTunneledConn {
this.tcpSocket = new TCPSocket();

// Connect to most recent IP
setInterval(() => {
this.connectionInterval = setInterval(() => {
if (!this.tcpSocket.connecting && this.tcpSocket.pending) {
if (this.ip !== defaults.IPADDRESS) {
if (this.ip.includes(':')) {
Expand Down Expand Up @@ -235,6 +236,7 @@ class UDPTunneledConn {
this.tcpSocket.end();
}
this.udpForwarder.close();
clearInterval(this.connectionInterval);
ipcMain.removeListener('udpTunnelIpAddress', this.ipAddressListener);
};
}
Expand All @@ -243,13 +245,14 @@ class TCPConn {
logger: Logger;
socket: TCPSocket;
leftoverBytes: Buffer | undefined;
connectionInterval: ReturnType<typeof setInterval>;

constructor(logger: Logger) {
this.logger = logger;
this.socket = new TCPSocket();

// Connect to most recent IP
setInterval(() => {
this.connectionInterval = setInterval(() => {
if (!this.socket.connecting && this.socket.pending) {
if (runtimeIP !== defaults.IPADDRESS) {
let port = DEFAULT_TCP_PORT;
Expand All @@ -267,6 +270,7 @@ class TCPConn {

this.socket.on('connect', () => {
this.logger.log('Runtime connected');
RendererBridge.reduxDispatch(runtimeConnect());
this.socket.write(new Uint8Array([1])); // Runtime needs first byte to be 1 to recognize client as Dawn (instead of Shepherd)
});

Expand Down Expand Up @@ -402,7 +406,9 @@ class TCPConn {
};

close = () => {
RendererBridge.reduxDispatch(runtimeDisconnect());
this.socket.end();
clearInterval(this.connectionInterval);
ipcMain.removeListener('runModeUpdate', this.sendRunMode);
ipcMain.removeListener('ipAddress', this.ipAddressListener);
ipcMain.removeListener('initiateLatencyCheck', this.initiateLatencyCheck);
Expand All @@ -427,7 +433,6 @@ class UDPConn {
});

this.socket.on('close', () => {
RendererBridge.reduxDispatch(runtimeDisconnect());
this.logger.log('UDP connection closed');
});

Expand All @@ -438,7 +443,6 @@ class UDPConn {
*/
this.socket.on('message', (msg: Uint8Array) => {
try {
RendererBridge.reduxDispatch(infoPerMessage());
const sensorData: protos.Device[] = protos.DevData.decode(msg).devices;
// Need to convert protos.Device to Peripheral here because when dispatching to the renderer over IPC,
// some of the inner properties (i.e. device.uid which is a Long) loses its prototype, which means any
Expand Down
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,17 @@
"bufferutil": "4.0.1",
"create-react-class": "15.6.2",
"electron-json-storage": "4.0.2",
"html-loader": "^0.5.5",
"html-react-parser": "^1.2.4",
"immutable": "3.8.2",
"jquery": "^3.6.0",
"json-loader": "0.5.7",
"keymirror": "0.1.1",
"lodash": ">=4.17.19",
"mousetrap": "1.6.1",
"numeral": "2.0.6",
"object-assign": "4.1.1",
"ovenplayer": "^0.10.0-alpha.1",
"patch-package": "^6.2.2",
"postinstall-postinstall": "^2.1.0",
"prop-types": "15.6.0",
Expand All @@ -135,7 +139,7 @@
"redux-saga": "^1.1.3",
"seedrandom": "2.4.3",
"smalltalk": "^4.0.6",
"socket.io-client": "^2.3.0",
"socket.io-client": "^4.0.0",
"ssh2": "^0.8.9",
"superagent": "3.8.2",
"ts-node": "^9.0.0",
Expand Down
32 changes: 22 additions & 10 deletions renderer/components/ConfigBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@ export const ConfigBoxComponent = (props: Props) => {
if (err) {
logging.log(err);
}
})
});

const newConfig = {
stationNumber: stationNumber,
bridgeAddress: fcAddress,
bridgeAddress: fcAddress
};
props.onFCUpdate(newConfig);
setOriginalStationNumber(stationNumber);
Expand All @@ -97,7 +97,7 @@ export const ConfigBoxComponent = (props: Props) => {

const handleSSHIpChange = (e: React.FormEvent<FormControl & HTMLInputElement>) => {
setSSHAddress(e.currentTarget.value);
}
};

const handleFcChange = (e: React.FormEvent<FormControl & HTMLInputElement>) => {
setFCAddress(e.currentTarget.value);
Expand All @@ -120,7 +120,9 @@ export const ConfigBoxComponent = (props: Props) => {
if (defaults.NGROK) {
return false;
}
return getValidationState(ipAddress) === 'error' || getValidationState(fcAddress) === 'error' || (stationNumber < 0 && stationNumber > 4);
return (
getValidationState(ipAddress) === 'error' || getValidationState(fcAddress) === 'error' || (stationNumber < 0 && stationNumber > 4)
);
};

useEffect(() => {
Expand Down Expand Up @@ -204,12 +206,22 @@ export const ConfigBoxComponent = (props: Props) => {
<FormControl.Feedback />
</FormGroup>

{defaults.NGROK ? (
<FormGroup controlId="fcAddress" validationState={getValidationState(fcAddress)}>
<ControlLabel>Overlay URL</ControlLabel>
<FormControl type="text" value={fcAddress} placeholder="https://92309a8s09.ngrok.io" onChange={handleFcChange} />
<FormControl.Feedback />
</FormGroup>
) : null}

<p>Field Control Settings</p>
<FormGroup controlId="fcAddress" validationState={getValidationState(fcAddress)}>
<ControlLabel>Field Control IP Address</ControlLabel>
<FormControl type="text" value={fcAddress} placeholder="i.e. 192.168.100.13" onChange={handleFcChange} />
<FormControl.Feedback />
</FormGroup>
{!defaults.NGROK ? (
<FormGroup controlId="fcAddress" validationState={getValidationState(fcAddress)}>
<ControlLabel>Field Control IP Address</ControlLabel>
<FormControl type="text" value={fcAddress} placeholder="i.e. 192.168.100.13" onChange={handleFcChange} />
<FormControl.Feedback />
</FormGroup>
) : null}

<FormGroup controlId="stationNumber" validationState={stationNumber >= 0 && stationNumber <= 4 ? 'success' : 'error'}>
<ControlLabel>Field Control Station Number</ControlLabel>
Expand Down Expand Up @@ -244,7 +256,7 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({

const mapStateToProps = (state: ApplicationState) => ({
stationNumber: state.fieldStore.stationNumber,
fcAddress: state.fieldStore.bridgeAddress,
fcAddress: state.fieldStore.bridgeAddress
});

export const ConfigBox = connect(mapStateToProps, mapDispatchToProps)(ConfigBoxComponent);
10 changes: 10 additions & 0 deletions renderer/components/DNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { StatusLabel } from './StatusLabel';
import { TooltipButton } from './TooltipButton';
import { VERSION } from '../consts';
import { robotState } from '../utils/utils';
import { ipcRenderer } from 'electron';

interface StateProps {
runtimeVersion: string;
Expand Down Expand Up @@ -154,6 +155,15 @@ const DNavComponent = (props: Props) => {
id="update-software-button"
glyph="cloud-upload"
/>
<TooltipButton
placement="bottom"
text="Open Video Feed"
bsStyle="info"
onClick={() => ipcRenderer.send('SHOW_VIDEO_FEED')}
id="show-video-feed-button"
glyph="play"
disabled={false}
/>
</ButtonGroup>
</ButtonToolbar>
</Navbar.Form>
Expand Down
8 changes: 7 additions & 1 deletion renderer/components/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -328,8 +328,14 @@ export class Editor extends React.Component<Props, State> {
// NOT THE ACTION updateKeyboardBitmap. THIS IS A LOCAL FUNCTION
this.updateKeyboardBitmap(e.key, false);
}

turnCharacterOn = (e: KeyboardEvent) => {
this.updateKeyboardBitmap(e.key, true)
// Handle special ctrl + q edge case
if (e.ctrlKey && e.key === 'q') {
this.props.onUpdateKeyboardModeToggle(false);
} else {
this.updateKeyboardBitmap(e.key, true);
}
}

upload = () => {
Expand Down
11 changes: 11 additions & 0 deletions renderer/components/video-feed/ShepherdOverlay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import parse from 'html-react-parser';
import './scoreboard';
import '../../../static/video-feed/scoreboard.css';

const shepherdScoreHtml = require('../../../static/video-feed/scoreboard.html');

export const ShepherdOverlay = () => {
return (
parse(shepherdScoreHtml)
);
};
Loading