Skip to content

Commit

Permalink
Merge pull request #30 from Northeastern-Electric-Racing/#27-Adjust-P…
Browse files Browse the repository at this point in the history
…roxy-Controller-for-Server

#27 Add Proxy Client
  • Loading branch information
Peyton-McKee authored Sep 18, 2023
2 parents 4ecd50f + 6d7d3b0 commit 2a1236f
Show file tree
Hide file tree
Showing 13 changed files with 136 additions and 51 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "scylla-server/src/odyssey-base"]
path = scylla-server/src/odyssey-base
url = https://github.com/Northeastern-Electric-Racing/Odyssey-Base.git
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

I've setup the barebones skeleton for what we're gonna be running on the telemetry hub router. It's a react app running in its own docker container and an express server (scylla) setup with prisma and sqlite in its own docker container (prisma and sqlite to probably be swapped out with other things later, this was just what I knew, so I set it up with them for now).

### Initializing Submodule

To initialize the odyssey submodule run `git submodule init` and `git submodule update`

### Running the Project in Dev Mode

To run the project locally for development, you'll want to run the client and the server separately.
Expand Down
3 changes: 2 additions & 1 deletion scylla-server/.dockerignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
src/prisma/mydatabase.db
src/prisma/mydatabase.db-journal
src/prisma/mydatabase.db-journal
src/odyssey-base
7 changes: 7 additions & 0 deletions scylla-server/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,17 @@ RUN npm install

COPY . .

# Initialize for git submodules
RUN git init
RUN git submodule add -f https://github.com/Northeastern-Electric-Racing/Odyssey-Base.git ./src/odyssey-base && \
git submodule update --init --recursive

RUN npx [email protected] generate

RUN npx [email protected] migrate deploy

RUN npm i --save-dev @types/ws

RUN npm run build

CMD ["sh", "-c", "npm run start:production"]
4 changes: 2 additions & 2 deletions scylla-server/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions scylla-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@
"ts-node": "^10.9.1",
"typescript": "^5.1.6",
"vitest": "^0.34.4",
"ws": "^8.14.1"
"ws": "8.14.1"
},
"prisma": {
"schema": "./src/prisma/schema.prisma"
},
"devDependencies": {
"@types/jest": "^29.5.4",
"@types/ws": "^8.5.5",
"@types/ws": "8.5.5",
"prisma": "^5.2.0"
}
}
33 changes: 12 additions & 21 deletions scylla-server/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import express, { Request, Response } from 'express';
import { Server, Socket } from 'socket.io';
import ProxyController from './proxy/proxy-controller';
import { createServerMessageMap } from './utils/message-maps.utils';
// Ignoring this because it wont build on github for some reason
// @ts-ignore
import { WebSocket } from 'ws';
import ProxyServer from './proxy/proxy-server';
import ProxyClient from './proxy/proxy-client';
import { createClientMessageMap } from './utils/message-maps.utils';

const app = express();
const port = 8000;

app.get('/', (req: Request, res: Response) => {
app.get('/', (_req: Request, res: Response) => {
res.send('Hello, Express server with TypeScript!');
});

Expand All @@ -21,25 +25,12 @@ const serverSocket = new Server(server, {
});

serverSocket.on('connection', (socket: Socket) => {
const serverProxy = new ProxyController(createServerMessageMap(), socket);
const serverProxy = new ProxyServer(createClientMessageMap(), socket);
serverProxy.configure();
});

//TODO: Get host/port from DNC
// const socketClient = new WebSocket('http://localhost:8080');
// TODO: Get host/port from DNC
const socketClient = new WebSocket('ws://localhost:8000');

// socketClient.on('open', () => {
// console.log('connected to Siren');
// socketClient.on('message', (data: any) => {
// try {
// const message = JSON.parse(data) as Message;
// console.log(message);
// } catch (error) {
// console.log('error parsing message', error);
// }
// });
// });

// socketClient.on('close', () => {
// console.log('disconnected from Siren');
// });
const proxyClient = new ProxyClient(socketClient);
proxyClient.configure();
1 change: 1 addition & 0 deletions scylla-server/src/odyssey-base
Submodule odyssey-base added at 31f3e5
97 changes: 97 additions & 0 deletions scylla-server/src/proxy/proxy-client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// Ignoring this because it wont build on github for some reason
// @ts-ignore
import { ErrorEvent, Event, MessageEvent, WebSocket } from 'ws';
import { ServerMessage, SubscriptionMessage } from '../odyssey-base/src/types/message.types';
import { Topic } from '../odyssey-base/src/types/topic';

/**
* Handler for receiving messages from Siren
*/
export default class ProxyClient {
socket: WebSocket;

/**
* Constructor
* @param socket The socket to send and receive messages from
*/
constructor(socket: WebSocket) {
this.socket = socket;
}

/**
* Sends a subscription message to Siren
* @param topics The topics to subscribe to
*/
private subscribeToTopics = (topics: Topic[]) => {
const subscriptionMessage: SubscriptionMessage = {
argument: 'subscribe',
topics
};
this.socket.send(JSON.stringify(subscriptionMessage));
};

/**
* Handles disconnecting from Siren
* @param event The event that triggered the close
*/
private handleClose = (event: Event) => {
console.log('Disconnected from Siren', event);
};

/**
* Handles connecting to Siren
* @param event The event that triggered the open
*/
private handleOpen = (event: Event) => {
console.log('Connected to Siren', event);
this.subscribeToTopics(Object.values(Topic));
};

/**
* Handles messages received from Siren
* @param message The message received from Siren
*/
private handleMessage = (message: MessageEvent) => {
console.log('Received Message: ', message);
try {
const data = JSON.parse(message.data.toString()) as ServerMessage;
this.handleData(data);
} catch (error) {
if (error instanceof Error) {
console.log('Error Decoding Message: ', error.message);
this.socket.emit('Error', error.message);
}
}
};

/**
* Handles receiving data from the car and:
* 1. Logs the data
* 2. Sends the data to the client
* @param data The data received from Siren
*/
private handleData = (data: ServerMessage) => {
//TODO: Send data to client
//TODO: Log data
console.log('Received Data: ', data);
};

/**
* Handles errors that occur
* @param error The error that occurred
*/
private handleError = (error: ErrorEvent) => {
console.log('Error Encountered: ', error.message);
};

/**
* Configures the proxy client for connecting and disconnecting to/from Siren,
* sending and receiving messages, and handling errors
*/
public configure = () => {
this.socket.onopen = this.handleOpen;
this.socket.onmessage = this.handleMessage;
this.socket.onerror = this.handleError;
this.socket.onclose = this.handleClose;
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { ClientMessage } from '../utils/message.utils';
import { ResponseFunction } from '../utils/message-maps.utils';

/**
* Proxy Controller To Handle Inputting and Outputting Messages to a Client
* Proxy for handling Inputting and Outputting Messages to a Client
*/
export default class ProxyController {
export default class ProxyServer {
messageMap: Map<string, ResponseFunction>;
socket: Socket;

Expand Down
1 change: 0 additions & 1 deletion scylla-server/src/services/systems.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { ResponseFunction } from '../utils/message-maps.utils';
* CRUD operation to get all systems with ResponseFunction type
* @returns string contianing all the systems in the db
*/

export const getAllSystems: ResponseFunction = async () => {
const data = await prisma.system.findMany();
return JSON.stringify(data);
Expand Down
11 changes: 1 addition & 10 deletions scylla-server/src/utils/message-maps.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,7 @@ import { getAllSystems } from '../services/systems.services';
export type ResponseFunction = (data: JSON) => Promise<string>;

/**
* Creates a map of server messages to functions that handle the messages
* @returns A map of server messages to functions that handle the messages
*/
export const createServerMessageMap = (): Map<string, ResponseFunction> => {
const serverMessageMap = new Map<string, ResponseFunction>();
return serverMessageMap;
};

/**
* Creates a map of client messages to functions that handle the messages
* Creates a map of messages received from the client to functions that handle the messages
* @returns A map of client messages to functions that handle the messages
*/
export const createClientMessageMap = (): Map<string, ResponseFunction> => {
Expand Down
15 changes: 3 additions & 12 deletions scylla-server/src/utils/message.utils.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,6 @@
export type ServerMessage = {
unix_time: number;
node: string;
data: ServerData[];
};

type ServerData = {
name: string;
value: number;
units: string;
};

/**
* The format of a message sent from the client
*/
export type ClientMessage = {
argument: string;
data: JSON;
Expand Down

0 comments on commit 2a1236f

Please sign in to comment.