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

[WIP] - Websocket data streaming #145

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
52 changes: 52 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,58 @@
<img src="logo.png" alt="Interactive Brain Playground Logo" width=500 />
</p>

# REMIX2 - server and client architecture

To start, you will need to install [Homebrew](https://brew.sh) and [npm](https://nodejs.org/en/). These are easy to install with the following Terminal / `bash` commands:

```sh
## Install homebrew
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

## Install npm
# NOTE: this will also install Node.js if it is not already installed.
brew install node

# NOTE: Node.js must be version 10.x for Muse interaction

# Thus, if you are getting version issues, install n, with the following command:
sudo npm install -g n

# Then, you can switch to version 10.x with the following command:
sudo n 10.16.0
```

Then, in Terminal/`bash`, clone this Git repository and change directory into the newly cloned folder:

```sh
git clone https://github.com/kylemath/EEGEdu
cd EEGEdu
```

Then, you can install the required `npm` packages for EEGEdu:

```sh
npm install
```

## Local Development Environment
Then, you can run the *Local Development Environment* of EEGEdu:

```sh
npm start
```

Then go to https://localhost:3000 in the browser to start a client instance. In another browser window go to https://localhost:3000/together to see the server side, where all the clients data is streamed into.








# OLD STUFF

`EEGEdu` is an Interactive Brain Playground.

`EEGEdu` is served live at [https://eegedu.com/](https://eegedu.com). This website is served from the software in this repository. So, all you need to do to try the system out is head to [EEGEdu](https://eegedu.com/).
Expand Down
8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
"npm": "5.x",
"node": "10.x"
},
"proxy": "http://localhost:8080",
"name": "eegedu",
"version": "0.1.0",
"private": true,
"dependencies": {
"@neurosity/pipes": "^3.0.2",
"@shopify/polaris": "^4.9.0",
"chart.js": "^2.7.2",
"express": "^4.17.1",
"file-saver": "^2.0.2",
"firebase": "^7.5.0",
"firebase-tools": "^7.9.0",
Expand All @@ -25,10 +27,12 @@
"react-p5-wrapper": "^2.0.0",
"react-scripts": "^3.2.0",
"react-youtube": "^7.9.0",
"rxjs": "^6.5.3"
"rxjs": "^6.5.3",
"socket.io": "^2.3.0"
},
"scripts": {
"start": "react-scripts --max_old_space_size=4096 start",
"dev": "react-scripts --max_old_space_size=4096 start",
"start": "node server.js",
"build": "react-scripts --max_old_space_size=4096 build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
Expand Down
6 changes: 6 additions & 0 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,11 @@
}
});
</script>

<!-- Can connect from the HTML front end, to handle new inputs... -->
<!-- <script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
</script> -->
</body>
</html>
67 changes: 67 additions & 0 deletions public/together.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<title>EEGEdu</title>
<script src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/smoothie/1.34.0/smoothie.min.js" integrity="sha256-s4pCizM36ibu/qMLSJHZLwhA5sV0/Jn1J/1TrzryEKQ=" crossorigin="anonymous"></script>
<script src="/socket.io/socket.io.js"></script>
<link rel="stylesheet" href="https://unpkg.com/@shopify/polaris@4.9.0/styles.min.css" />
</head
>
<body>
<div id="together">
<h1>
Start streaming data from subscribers
</h1>
<p>Plots will appear for each user connected:</p>

<canvas id="mycanvas1" width="100" height="100"></canvas>
<canvas id="mycanvas2" width="100" height="100"></canvas>
<canvas id="mycanvas3" width="100" height="100"></canvas>
<canvas id="mycanvas4" width="100" height="100"></canvas>
<canvas id="mycanvas5" width="100" height="100"></canvas>
<canvas id="mycanvas6" width="100" height="100"></canvas>
<canvas id="mycanvas7" width="100" height="100"></canvas>
<canvas id="mycanvas8" width="100" height="100"></canvas>

<ul id="messages"></ul>
</div>

<script>
var allData = {};
var allCharts = {};
var userCount = 0;
</script>
<script>
$(function () {
var socket = io();
console.log('socket details', socket);
socket.on('outgoing data', function (data) {

var user = data['num']['userName'];
var reading = data['num']['psd'][0][10];

if (!allData[user]) {
userCount++
allData[user] = new TimeSeries();

allCharts[user] = new SmoothieChart({ millisPerPixel: 88, minValue: 0, maxValue: 20, grid: { strokeStyle: 'rgb(125, 0, 0)', fillStyle: 'rgb(60, 0, 0)', lineWidth: 1, millisPerLine: 250, verticalSections: 6 } });
allCharts[user].streamTo(document.getElementById("mycanvas" + userCount), 1000);
thisColour = 'hsl(' + Math.floor(Math.random() * 255) + ', 99%, 50%)';
allCharts[user].addTimeSeries(allData[user], {strokeStyle: thisColour, fillStyle: thisColour});
console.log('Welcome new user ' + user)
}

allData[user].append(new Date().getTime(), reading);
$('#messages').prepend($('<li>').text(`[${user}]: ${reading} `));
console.log(data['num']['userName']);
});
});
</script>
</body>
</html>
43 changes: 43 additions & 0 deletions server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
const express = require("express");
const bodyParser = require("body-parser");
const path = require("path");

const app = express();
var http = require('http').createServer(app);
var io = require('socket.io')(http);

app.use(express.static(path.join(__dirname, "build")));

app.get("/", function(req, res) {
res.sendFile(path.join(__dirname, "build", "index.html"));
});

app.get("/together", function(req, res) {
res.sendFile(path.join(__dirname, "build", "together.html"));
});

// app.listen(process.env.PORT || 3000);

io.on('connection', function(socket){
console.log("New client connected");

//Here we listen on a new namespace called "incoming data"
socket.on("incoming data", (data)=>{
// Here we broadcast it out to all other sockets EXCLUDING the
// socket which sent us the data
// The broadcast flag is special because it allows us to emit data to every
// client EXCEPT the one that sent us the data. There's no point in sending
// data back to the producer so we broadcast on yet another namespace,
// outgoing data.
socket.broadcast.emit("outgoing data", {num: data});
console.log('broadcast outgoing data', data.userName, data.info.startTime);

});

//A special namespace "disconnect" for when a client disconnects
socket.on("disconnect", () => console.log("Client disconnected"));
});

http.listen(3000, function(){
console.log('listening on *:3000');
});
9 changes: 6 additions & 3 deletions src/components/App/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@ import React from "react";
import { PageSwitcher } from "../PageSwitcher/PageSwitcher";
import { AppProvider, Card, Page, Link } from "@shopify/polaris";
import enTranslations from "@shopify/polaris/locales/en.json";
import * as translations from "./translations/en.json";

export function App() {
return (
<AppProvider i18n={enTranslations}>
<Page title={translations.title} subtitle={translations.subtitle}>
<Page title={"EEGEdu"}
subtitle={[
"Welcome to the EEGEdu live EEG tutorial. "
]}
>
<PageSwitcher />
<Card sectioned>
<p>{translations.footer}
<p>{"EEGEdu - An Interactive Electrophysiology Tutorial with the Muse brought to you by Mathewson Sons."}
A
<Link url="http://kylemathewson.com"> Ky</Link>
<Link url="http://korymathewson.com">Kor</Link>
Expand Down
21 changes: 0 additions & 21 deletions src/components/App/translations/en.json

This file was deleted.

Loading