Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
333b596
Added Sphero Functionality
VinceIngram07 Jan 28, 2025
084a74c
More Controls
VinceIngram07 Feb 25, 2025
6da0b3e
changed block names to fit project
VinceIngram07 Mar 31, 2025
f96cd4a
Start of Vex Branch
VinceIngram07 May 25, 2025
94021c8
added block functionality
VinceIngram07 Jun 1, 2025
b031569
Add support for Gaglion
chris35469 Jun 15, 2025
cb6eefa
Merge branch 'feature/ganglion' into VEXAIM
VinceIngram07 Jun 15, 2025
46af284
Added muscle energy block
VinceIngram07 Jun 17, 2025
2fe7c87
Merge branch 'VEXAIM' into feature/ganglion
VinceIngram07 Jun 17, 2025
1950b33
Python server starts automatically
VinceIngram07 Jun 23, 2025
ceb24df
[UNSTABLE] Exe python
VinceIngram07 Jun 25, 2025
e44b1e1
Revert "[UNSTABLE] Exe python"
VinceIngram07 Jul 8, 2025
c54884c
Added Vex Files
VinceIngram07 Jul 8, 2025
370adce
fixed startup error
VinceIngram07 Jul 8, 2025
762a32b
added turn left/ right block and Vex Category
VinceIngram07 Jul 9, 2025
42d6f44
added venv setup
VinceIngram07 Jul 9, 2025
dae3186
Update requirements.txt
VinceIngram07 Jul 9, 2025
076764b
Update requirements.txt
VinceIngram07 Jul 9, 2025
b1f1bd2
Update requirements.txt
VinceIngram07 Jul 9, 2025
eea135d
updated vex category
VinceIngram07 Jul 10, 2025
f70d531
added start bash script
VinceIngram07 Jul 10, 2025
4f79cf2
Added NeuroScope Icon
VinceIngram07 Jul 10, 2025
2510906
Update signal.js
chris35469 Jul 10, 2025
11fb9b1
Merge branch 'feature/ganglion' of https://github.com/htil/neuroscope…
chris35469 Jul 10, 2025
4013a5b
Camp Neuroscope EMG V1.0
VinceIngram07 Jul 11, 2025
5f2c31c
Removed command delay
VinceIngram07 Jul 11, 2025
f02b2cd
feat: Implement single executable build with Ganglion device support
VinceIngram07 Oct 7, 2025
31b1b0d
feat: Add console output, VEX reconnect, and enhanced testing with wo…
VinceIngram07 Oct 13, 2025
1bedf73
Add EMG robot control blocks and block-to-text converter
VinceIngram07 Oct 16, 2025
cc86b3e
feat: robust VEX reconnect, production Python startup, status UI, and…
VinceIngram07 Nov 14, 2025
22e8bde
Revert "Add support for Gaglion"
VinceIngram07 Jan 9, 2026
7f6762a
Migrate from EMG to EEG: Restore Muse headset support and refactor VE…
VinceIngram07 Jan 11, 2026
03bf794
Bump app version to 1.4.0
VinceIngram07 Jan 11, 2026
c89dad6
fix(eeg/blockly): prevent freeze with beta/theta/gamma by sanitizing …
VinceIngram07 Jan 22, 2026
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
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ yarn-error.log
.pnp.js
# Yarn Integrity file
.yarn-integrity
*.pyc

build

build
# Ignore virtual environments
venv/
/resources/python/vex/__pycache__
Binary file added Neuroscope-EMG.lnk
Binary file not shown.
14 changes: 14 additions & 0 deletions Neuroscope.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
@echo off
setlocal

REM This script should be placed inside the neuroscope-emg folder

echo Starting Neuroscope EMG...

REM Activate virtual environment
call venv\Scripts\activate.bat

REM Start the application
yarn serve

pause
302 changes: 299 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,301 @@
# Readme
# Neuroscope

TODO
Neuroscope is an Electron-based application for real-time EEG/BCI signal visualization, feature extraction, and device connectivity using Bluetooth-enabled headsets like **OpenBCI Ganglion**. It features a Blockly-based visual programming interface for custom workflows and supports VEX and Ganglion devices.

Project builds on [this boiler plate](https://github.com/a133xz/electron-vuejs-parcel-boilerplate).
---

## Features

- **EEG Device Support:** Connect to OpenBCI Ganglion headsets via Bluetooth.
- **Real-Time Visualization:** View EEG and telemetry data live.
- **Blockly Programming:** Drag-and-drop blocks for custom signal processing and logic.
- **Extensible:** Easily add new blocks or device integrations.

---

## Getting Started

### Prerequisites

- [Node.js](https://nodejs.org/) (v14+ recommended)
- npm or yarn
- Python 3.x (for some optional features)
- Python package: `websockets` (optional, only if using WebSocket features)
- A supported EEG device (OpenBCI Ganglion)

### Installation

1. **Clone the repository:**
```sh
git clone https://github.com/yourusername/neuroscope.git
cd neuroscope
```

2. **Install Node dependencies:**
```sh
yarn install
# or
npm install
```

3. *(Optional, only if using Python WebSocket features)*
**Install Python dependencies:**
```sh
pip install websockets
```

---

## Running the Application

1. **Start the Electron Application**
```sh
yarn serve
# or
npm run serve
```

This will launch the Electron app. In development mode, it will open with hot-reloading and developer tools enabled.

2. **Connect Your EEG Device**
- Click the **Bluetooth** button in the UI.
- Select your **Ganglion** device from the list.
- Wait for the connection confirmation.

---

## Usage

- **Signal Visualization:**
EEG channels are displayed in real time. You can view raw and filtered signals, as well as extracted features (alpha, beta, etc.).

- **Blockly Programming:**
Use the Blockly interface to create custom workflows. Drag and drop blocks for signal processing and feature extraction.

---

## Troubleshooting

- **Bluetooth Issues:**
Make sure your Ganglion device is powered on and not paired with another app. On Windows, you may need to grant Bluetooth permissions.
- **Missing Dependencies:**
If you see errors about missing modules, re-run `yarn install` or `npm install`.
- **Electron Fails to Start:**
Make sure you are using a compatible Node.js version and have all dependencies installed.

---

## Development

- **Hot Reload:**
The app reloads automatically in development mode.
- **Main Process:**
See `src/main/index.js` for Electron main process logic.
- **Renderer Process:**
See `src/renderer/js/` for UI and signal processing code.
- **Blockly Blocks:**
Custom blocks are defined in `src/renderer/js/customblock.js`.

---

## Adding a New Blockly Block (Example: VEX Kicker)

Below is the standard end-to-end pattern for introducing a new action block that can run both inside the js-interpreter (live run) and via generated JavaScript.

### 1. Define the Block (UI + Generator)
File: `src/renderer/js/customblock.js`

Add JSON spec and a generator. Example:

```javascript
// Block definition
var vexKicker = {
type: "vex_kicker",
message0: "kicker %1",
args0: [
{ type: "field_dropdown", name: "ACTION", options: [
["Kick Hard", "HARD"],
["Kick Soft", "SOFT"],
["Place", "PLACE"]
]}
],
previousStatement: null,
nextStatement: null,
colour: 70
};

Blockly.Blocks["vex_kicker"] = { init() { this.jsonInit(vexKicker); } };

javascriptGenerator.forBlock["vex_kicker"] = function(block){
const action = block.getFieldValue("ACTION").toLowerCase();
return `vex_kicker("${action}");\n`;
};
```

Why call `vex_kicker(...)`? Because wrapper functions are exposed to BOTH generated code and interpreter, keeping one unified runtime path.

### 2. Add Block to a Category
File: `src/renderer/js/categories.js`

Insert the block name in the appropriate category `modules` array (e.g. `cat_vex`).

```javascript
cat_vex: {
name: "VEX",
colour: 70,
modules: [ "vex_forward", "vex_back", "vex_left", "vex_right", "vex_kicker", "vex_turn_left", "vex_turn_right" ]
}
```

### 3. Provide a Wrapper Function
File: `src/renderer/js/wrapper-functions.js`

Create a method inside `WrapperFunctions`:

```javascript
vex_kicker(kind){
const k = String(kind||"").toLowerCase();
if(window.electronAPI?.vexKicker){
window.electronAPI.vexKicker(k);
} else {
window.electronAPI.sendCommand({ action:"kicker", type:k });
}
}
```

### 4. Expose Wrapper in Interpreter
File: `src/renderer/js/interpreter-api.js`

Add it to `nativeFunctions`:

```javascript
vex_kicker: this.wrapperFunctions.vex_kicker,
```

### 5. IPC Bridge (Renderer → Main)
File: `src/main/preload.js`

Expose a safe function:

```javascript
vexKicker: (type) => ipcRenderer.send("vex-kicker", type),
```

### 6. Main Process Handler
File: `src/main/index.js`

Listen and forward to Python server:

```javascript
ipcMain.on("vex-kicker", (event, type) => {
const t = String(type||"").toLowerCase();
console.log(`[VEX] Kicker action: ${t}`);
sendCommand({ action:"kicker", type:t });
});
```

### 7. Python Server Action (If New Action Not Yet Supported)
File: `resources/python/VEXServer.py`

Add an `elif action == "kicker":` block parsing `type` and invoking underlying AIM API (`robot.kicker.kick(...)` or `robot.kicker.place()`).

### 8. Test
1. Run `yarn serve`.
2. Drag the new block into the workspace.
3. Run the program.
4. Watch terminal for `[VEX] Kicker action: hard` and Python side confirmation.

### Summary Flow
Block → Generator → Wrapper → Interpreter (or generated JS) → `electronAPI.vexKicker` → IPC → Main → WebSocket → Python → Robot.

---

## Building a Distribution (Production Build)

The project ships JavaScript (Electron + Vue) and a Python WebSocket server (VEXServer). The bundled installer needs both.

### Prerequisites
1. Node/Yarn installed.
2. Python 3.x installed.
3. Virtual environment `.venv` created (recommended):
```powershell
python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txt
```

### Build Steps

You can run each step or use the shortcut:

| Step | Script | Purpose |
|------|--------|---------|
| 1 | `yarn build` | Builds renderer (Parcel) into `build/renderer` |
| 2 | `yarn python:build` | PyInstaller builds `dist/VEXServer.exe` from `VEXServer.spec` |
| 3 | `yarn electron:build` | Uses `electron-builder` to package the app (looks at `package.json` build config) |
| All-in-one | `yarn build:local` | Runs 1+2+3 sequentially |

Recommended single command:

```powershell
yarn build:local
```

### Output Locations
- Electron build artifacts: `dist/` (depends on electron-builder target; on Windows an unpacked dir plus resources)
- Python binary: `dist/VEXServer.exe` (copied into final app via `extraResources` in `package.json`)

### Changing Product/App Name
Edit in `package.json`:
```json
"name": "vex-emg-control",
"build": { "productName": "VEX EMG Control", "appId": "com.htlab.vex-emg-control" }
```
Optionally set BrowserWindow title in `src/main/index.js`:
```javascript
title: "VEX EMG Control"
```

### Signing / Distribution (Future)
- For Windows code-signing, add certificate config to `electron-builder`.
- For auto-update, integrate a release server (GitHub Releases or custom). Not yet configured here.

### Common Build Issues
| Symptom | Cause | Fix |
|---------|-------|-----|
| Python exe missing | PyInstaller failed | Activate venv & rerun `yarn python:build` |
| WebSocket not connecting | Robot not reachable | Confirm network / IP (AP mode `192.168.4.1`) |
| Port 3002 already used | Stale dev process | Kill previous Electron/Parcel instance |

### Quick Test After Build
1. Run the packaged app from `dist/`.
2. Observe Python server starts (console log: `Python WebSocket server is ready`).
3. Drag a block (e.g., `vex_forward`) and run; confirm log output and robot motion.

---

## Contributing

1. Fork & branch: `feat/new-block`.
2. Add block + wrapper + IPC.
3. Add docs section if introducing a new device pattern.
4. Run `yarn serve` and test.
5. Open PR.

---

---

## License

MIT License. See [LICENSE](LICENSE) for details.

---

## Acknowledgements

- [OpenBCI Ganglion](https://shop.openbci.com/products/ganglion-board)
- [Blockly](https://developers.google.com/blockly)
- [Electron](https://www.electronjs.org/)

---
Loading
Loading