Skip to content

Commit

Permalink
Add more robust error handling (#162)
Browse files Browse the repository at this point in the history
Co-authored-by: Hailey Jang <55821834+HaileyJang@users.noreply.github.com>
  • Loading branch information
ewc340 and HaileyJang authored May 30, 2022
1 parent b010227 commit 07295de
Showing 1 changed file with 68 additions and 37 deletions.
105 changes: 68 additions & 37 deletions main/networking/Runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,36 +104,41 @@ function readPackets(data: Buffer, previousLeftoverBytes?: Buffer): { leftoverBy
* Create TCP packet header and prepend to
* payload to send to Runtime.
*/
function createPacket(payload: unknown, messageType: MsgType): Buffer {
function createPacket(payload: unknown, messageType: MsgType): Buffer | null {
let encodedPayload: Uint8Array;

switch (messageType) {
case MsgType.DEVICE_DATA:
encodedPayload = protos.DevData.encode(payload as protos.IDevData).finish();
break;
case MsgType.RUN_MODE:
encodedPayload = protos.RunMode.encode(payload as protos.IRunMode).finish();
break;
case MsgType.START_POS:
encodedPayload = protos.StartPos.encode(payload as protos.IStartPos).finish();
break;
case MsgType.TIME_STAMPS:
encodedPayload = protos.TimeStamps.encode(payload as protos.ITimeStamps).finish();
break;
case MsgType.INPUTS:
encodedPayload = protos.UserInputs.encode({ inputs: payload as protos.Input[] }).finish();
break;
default:
console.log('ERROR: trying to create TCP Packet with unknown message type');
encodedPayload = new Uint8Array();
break;
}
try {
switch (messageType) {
case MsgType.DEVICE_DATA:
encodedPayload = protos.DevData.encode(payload as protos.IDevData).finish();
break;
case MsgType.RUN_MODE:
encodedPayload = protos.RunMode.encode(payload as protos.IRunMode).finish();
break;
case MsgType.START_POS:
encodedPayload = protos.StartPos.encode(payload as protos.IStartPos).finish();
break;
case MsgType.TIME_STAMPS:
encodedPayload = protos.TimeStamps.encode(payload as protos.ITimeStamps).finish();
break;
case MsgType.INPUTS:
encodedPayload = protos.UserInputs.encode({ inputs: payload as protos.Input[] }).finish();
break;
default:
console.log('ERROR: trying to create TCP Packet with unknown message type');
encodedPayload = new Uint8Array();
break;
}

const msgLength = Buffer.byteLength(encodedPayload);
const msgLengthArr = new Uint8Array([msgLength & 0x00ff, msgLength & 0xff00]); // Assuming little-endian byte order, since runs on x64
const msgTypeArr = new Uint8Array([messageType]);
const msgLength = Buffer.byteLength(encodedPayload);
const msgLengthArr = new Uint8Array([msgLength & 0x00ff, msgLength & 0xff00]); // Assuming little-endian byte order, since runs on x64
const msgTypeArr = new Uint8Array([messageType]);

return Buffer.concat([msgTypeArr, msgLengthArr, encodedPayload], msgLength + 3);
return Buffer.concat([msgTypeArr, msgLengthArr, encodedPayload], msgLength + 3);
} catch (err) {
console.log(err);
return null;
}
}

class RuntimeConnection {
Expand Down Expand Up @@ -189,16 +194,24 @@ class RuntimeConnection {

switch (packet.type) {
case MsgType.LOG:
decoded = protos.Text.decode(packet.payload);
RendererBridge.reduxDispatch(updateConsole(decoded.payload));
try {
decoded = protos.Text.decode(packet.payload);
RendererBridge.reduxDispatch(updateConsole(decoded.payload));
} catch (err) {
this.logger.log(err);
}
break;

case MsgType.TIME_STAMPS:
decoded = protos.TimeStamps.decode(packet.payload);
const oneWayLatency = (Date.now() - Number(decoded.dawnTimestamp)) / 2;
try {
decoded = protos.TimeStamps.decode(packet.payload);
const oneWayLatency = (Date.now() - Number(decoded.dawnTimestamp)) / 2;

// TODO: we can probably do an average of n timestamps so the display doesn't change too frequently
RendererBridge.reduxDispatch(setLatencyValue(oneWayLatency));
// TODO: we can probably do an average of n timestamps so the display doesn't change too frequently
RendererBridge.reduxDispatch(setLatencyValue(oneWayLatency));
} catch (err) {
this.logger.log(err);
}
break;

case MsgType.DEVICE_DATA:
Expand Down Expand Up @@ -227,7 +240,7 @@ class RuntimeConnection {
break;

default:
this.logger.log(`Unsupported received message type: ${packet.type}`)
this.logger.log(`Unsupported received message type: ${packet.type}`);
}
}

Expand All @@ -252,6 +265,24 @@ class RuntimeConnection {
return cb(event, ...args);
};

sendMessage = (message: Buffer | null, cb?: ((err?: Error | undefined) => void) | undefined) => {
if (message == null) {
return;
}

this.socket.write(message, cb);
};

/**
* Initiates latency check by sending first packet to Runtime
*/
initiateLatencyCheck = (_event: IpcMainEvent, data: protos.ITimeStamps) => {
const message = createPacket(data, MsgType.TIME_STAMPS);
this.sendMessage(message, () => {
this.logger.log(`Sent timestamp data to runtime: ${JSON.stringify(data)}`);
});
};

/**
* IPC Connection with ConfigBox.ts' saveChanges()
* Receives new IP Address to send messages to.
Expand All @@ -274,23 +305,23 @@ class RuntimeConnection {
*/
sendRunMode = (_event: IpcMainEvent, runModeData: protos.IRunMode) => {
const message = createPacket(runModeData, MsgType.RUN_MODE);
this.socket.write(message, () => {
this.sendMessage(message, () => {
this.logger.log(`Run Mode message sent: ${JSON.stringify(runModeData)}`);
});
};

sendDevicePreferences = (_event: IpcMainEvent, deviceData: protos.IDevData) => {
// TODO: Serialize uid from string -> Long type
const message = createPacket(deviceData, MsgType.DEVICE_DATA);
this.socket.write(message, () => {
this.sendMessage(message, () => {
this.logger.log(`Device preferences sent: ${deviceData.toString()}`);
});
};

sendRobotStartPos = (_event: IpcMainEvent, startPosData: protos.IStartPos) => {
// TODO: Get start pos from sagas
const message = createPacket(startPosData, MsgType.START_POS);
this.socket.write(message, () => {
this.sendMessage(message, () => {
this.logger.log(`Start position sent: ${startPosData.toString()}`);
});
};
Expand All @@ -305,7 +336,7 @@ class RuntimeConnection {
);
}
const message = createPacket(data, MsgType.INPUTS);
this.socket.write(message, (err?: Error) => {
this.sendMessage(message, (err?: Error) => {
if (err !== undefined) {
this.logger.log(`Error when sending inputs: ${JSON.stringify(err)}`);
}
Expand Down

0 comments on commit 07295de

Please sign in to comment.