pieeg-server 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 PiEEG Community
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,288 @@
1
+ Metadata-Version: 2.4
2
+ Name: pieeg-server
3
+ Version: 0.1.0
4
+ Summary: One-command local streaming server for PiEEG-16 (16-channel EEG shield for Raspberry Pi)
5
+ Author: PiEEG Community
6
+ License: MIT License
7
+
8
+ Copyright (c) 2025 PiEEG Community
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://github.com/yelabb/PiEEG-16-server
29
+ Project-URL: Documentation, https://pieeg.com/docs/docs/pieeg-16/
30
+ Project-URL: Repository, https://github.com/yelabb/PiEEG-16-server
31
+ Project-URL: Issues, https://github.com/yelabb/PiEEG-16-server/issues
32
+ Keywords: eeg,bci,raspberry-pi,pieeg,neuroscience,websocket,brain-computer-interface,ads1299,spi
33
+ Classifier: Development Status :: 3 - Alpha
34
+ Classifier: Intended Audience :: Science/Research
35
+ Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
36
+ Classifier: Programming Language :: Python :: 3.11
37
+ Classifier: Programming Language :: Python :: 3.12
38
+ Classifier: Programming Language :: Python :: 3.13
39
+ Classifier: Operating System :: POSIX :: Linux
40
+ Classifier: License :: OSI Approved :: MIT License
41
+ Classifier: Environment :: Console
42
+ Classifier: Framework :: AsyncIO
43
+ Requires-Python: >=3.11
44
+ Description-Content-Type: text/markdown
45
+ License-File: LICENSE
46
+ Requires-Dist: websockets>=12.0
47
+ Requires-Dist: scipy>=1.10
48
+ Requires-Dist: rich>=13.0
49
+ Provides-Extra: rpi
50
+ Requires-Dist: spidev>=3.6; extra == "rpi"
51
+ Provides-Extra: dev
52
+ Requires-Dist: pytest>=7.0; extra == "dev"
53
+ Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
54
+ Dynamic: license-file
55
+
56
+ # PiEEG-16-server
57
+
58
+ A lightweight server for the [PiEEG-16](https://github.com/pieeg-club/PiEEG-16) shield that initializes the hardware, reads 16 channels at 250 Hz, streams live data over WebSocket, and serves a real-time dashboard — all on your local network.
59
+
60
+ ## Install
61
+
62
+ > Pick **one** method. They all get you to the same place: `pieeg-server` ready to run.
63
+
64
+ ### Option A — One-line install (recommended)
65
+
66
+ SSH into your Pi and paste:
67
+
68
+ ```bash
69
+ curl -sSL https://raw.githubusercontent.com/yelabb/PiEEG-16-server/main/install.sh | bash
70
+ sudo reboot # only needed first time, to enable SPI
71
+ ```
72
+
73
+ ### Option B — Clone & setup
74
+
75
+ ```bash
76
+ git clone https://github.com/yelabb/PiEEG-16-server.git
77
+ cd PiEEG-16-server
78
+ chmod +x setup.sh
79
+ ./setup.sh
80
+ sudo reboot # only needed first time, to enable SPI
81
+ ```
82
+
83
+ ---
84
+
85
+ ## Run
86
+
87
+ ```bash
88
+ pieeg-server # start streaming
89
+ pieeg-server --filter # with 1–40 Hz bandpass filter
90
+ pieeg-server --monitor # with live terminal display
91
+ pieeg-server --mock # synthetic data, no hardware needed
92
+ pieeg-server doctor # diagnose SPI, GPIO, deps, permissions
93
+ ```
94
+
95
+ That's it. LEDs turn on, data streams to `ws://raspberrypi.local:1616`.
96
+
97
+ Open **http://raspberrypi.local:1617** in any browser on your network for the real-time dashboard.
98
+
99
+ <img height="400" alt="image" src="https://github.com/user-attachments/assets/3f33bfd4-c721-4b94-a672-2a0b744d127b" />
100
+
101
+ ### Terminal
102
+ <img width="422" height="475" alt="image" src="https://github.com/user-attachments/assets/7d58af68-85c4-41d3-b1ab-89b23e99faff" />
103
+
104
+
105
+ **Ports:**
106
+ - **`:1616`** — WebSocket data stream (PiEEG-**16** → **1616**)
107
+ - **`:1617`** — Web dashboard (next door)
108
+
109
+ ## Record data
110
+
111
+ ```bash
112
+ pieeg-server record session.csv # record until Ctrl-C
113
+ pieeg-server record session.csv --duration 300 # record 5 minutes
114
+ pieeg-server --record session.csv # record while streaming
115
+ pieeg-server --record session.csv --record-duration 60 # record 60s while streaming
116
+ ```
117
+
118
+ CSV format: `timestamp, ch1, ch2, ..., ch16` (compatible with the official PiEEG-16 dataset format).
119
+
120
+ ## Terminal monitor
121
+
122
+ ```bash
123
+ pieeg-server monitor # standalone live view (no server)
124
+ pieeg-server --monitor # live view alongside the server
125
+ ```
126
+
127
+ Displays all 16 channels with real-time µV values and sparkline waveforms directly in the terminal. Works over SSH — no browser or display needed.
128
+
129
+ > **`pieeg-server: command not found`?** Run `pieeg-server doctor` (or `./setup.sh` again).
130
+ > As a fallback: `cd PiEEG-16-server && .venv/bin/pieeg-server`
131
+
132
+ ## Troubleshooting
133
+
134
+ ```bash
135
+ pieeg-server doctor
136
+ ```
137
+
138
+ Checks everything in one shot: Pi model, Python version, SPI devices, GPIO chips, file permissions, port availability, installed dependencies, systemd service. Returns exit code `0` (all good), `1` (warnings), or `2` (errors) — scriptable with `--quiet`.
139
+
140
+ ### Windows: `Could not install packages due to an OSError`
141
+
142
+ If `pip install -e .` fails with a `WinError 2` or `Failed to write executable` error, pip can't replace an old `pieeg-server.exe` in your Python Scripts folder. Fix it:
143
+
144
+ ```powershell
145
+ pip uninstall pieeg-server -y
146
+ pip install -e .
147
+ ```
148
+
149
+ If that still fails, run your terminal **as Administrator** (right-click → Run as administrator).
150
+
151
+ > On Windows you can only use mock mode (`pieeg-server --mock`) since SPI/GPIO hardware is not available.
152
+
153
+ ## Connect from any device
154
+
155
+ ### Python
156
+
157
+ ```python
158
+ import asyncio, json, websockets
159
+
160
+ async def main():
161
+ async with websockets.connect("ws://raspberrypi.local:1616") as ws:
162
+ async for message in ws:
163
+ frame = json.loads(message)
164
+ print(f"Sample #{frame['n']}: {frame['channels']}")
165
+
166
+ asyncio.run(main())
167
+ ```
168
+
169
+ ### JavaScript (browser)
170
+
171
+ ```javascript
172
+ const ws = new WebSocket("ws://raspberrypi.local:1616");
173
+ ws.onmessage = (event) => {
174
+ const frame = JSON.parse(event.data);
175
+ console.log(`Sample #${frame.n}:`, frame.channels);
176
+ };
177
+ ```
178
+
179
+ ## Data Format
180
+
181
+ Each WebSocket message is a JSON frame:
182
+
183
+ ```json
184
+ {
185
+ "t": 1711234567.123456,
186
+ "n": 42,
187
+ "channels": [12.34, -5.67, 8.90, ...]
188
+ }
189
+ ```
190
+
191
+ | Field | Type | Description |
192
+ |-------|------|-------------|
193
+ | `t` | float | Unix timestamp (seconds) |
194
+ | `n` | int | Sample number (monotonic) |
195
+ | `channels` | float[16] | Voltage in microvolts (µV) per channel |
196
+
197
+ ## CLI Options
198
+
199
+ ```
200
+ pieeg-server [OPTIONS] [COMMAND]
201
+
202
+ Commands:
203
+ doctor Diagnose hardware, software, and configuration
204
+ record FILE Record EEG data to CSV (standalone, no server)
205
+ monitor Live terminal display (standalone, no server)
206
+
207
+ Server options:
208
+ --host HOST Bind address (default: 0.0.0.0)
209
+ --port PORT WebSocket port (default: 1616)
210
+ --dashboard-port PORT Dashboard HTTP port (default: 1617)
211
+ --no-dashboard Disable the web dashboard
212
+ --gpio-chip PATH GPIO chip device path (default: /dev/gpiochip4)
213
+ --filter Enable 1–40 Hz bandpass filter server-side
214
+ --lowcut HZ Filter low cutoff (default: 1.0)
215
+ --highcut HZ Filter high cutoff (default: 40.0)
216
+ --record FILE Record to CSV while streaming
217
+ --record-duration SEC Stop recording after N seconds
218
+ --monitor Show live terminal monitor alongside server
219
+ --mock Synthetic EEG data (no hardware needed)
220
+ -v, --verbose Debug logging
221
+ ```
222
+
223
+ ## Runtime Commands
224
+
225
+ Clients can send JSON commands over the WebSocket:
226
+
227
+ ```json
228
+ {"cmd": "set_filter", "enabled": true, "lowcut": 1.0, "highcut": 40.0}
229
+ {"cmd": "set_filter", "enabled": false}
230
+ ```
231
+
232
+ ## Architecture
233
+
234
+ ```
235
+ ┌─────────────────────────────────────────────────────────┐
236
+ │ Raspberry Pi 5 + PiEEG-16 Shield │
237
+ │ │
238
+ │ hardware.py → SPI/GPIO init, ADC register config │
239
+ │ ↓ │
240
+ │ acquisition.py → 250 Hz read loop (background thread) │
241
+ │ ↓ pub/sub (multiple consumers) │
242
+ │ ├── server.py → WebSocket broadcast │
243
+ │ ├── recorder.py → CSV file writer │
244
+ │ └── monitor.py → Terminal sparkline display │
245
+ │ ↓ │
246
+ │ dashboard.py → HTTP server for real-time web UI │
247
+ │ ↓ │
248
+ │ ws://0.0.0.0:1616 │ http://0.0.0.0:1617 │
249
+ └──────────┬───────────────────────────────────────────────┘
250
+ │ Local network
251
+ ├── Browser (JS client)
252
+ ├── Python notebook
253
+ ├── Mobile app
254
+ └── Any WebSocket client
255
+ ```
256
+
257
+ ## Runs as a Service
258
+
259
+ Setup creates a systemd service that auto-starts on boot:
260
+
261
+ ```bash
262
+ sudo systemctl status pieeg-server # check status
263
+ sudo systemctl stop pieeg-server # stop
264
+ sudo systemctl restart pieeg-server # restart
265
+ journalctl -u pieeg-server -f # view logs
266
+ ```
267
+
268
+ ## GPIO: No `gpiod` Dependency
269
+
270
+ This server talks to GPIO directly via the Linux kernel's character device interface (`/dev/gpiochipN`) using standard `ioctl` calls — no `gpiod` pip package needed.
271
+
272
+ We only use two GPIO pins (chip-select output + data-ready input), so the ~20 lines of `struct` packing replace an entire external dependency that:
273
+
274
+ - Has **breaking API changes** between v1 and v2 (completely incompatible)
275
+ - Requires **system C headers** (`libgpiod-dev`) to install via pip
276
+ - Only works on **Linux** (blocks development/testing on macOS/Windows)
277
+
278
+ The chardev v1 ioctl ABI has been stable since Linux 4.8 (2016) and is guaranteed not to break by the kernel's userspace compatibility policy.
279
+
280
+ ## Safety
281
+
282
+ > **PiEEG-16 must operate from battery power (5V) only.**
283
+ > Do NOT connect to mains-powered equipment via USB.
284
+ > PiEEG-16 is NOT a medical device.
285
+
286
+ ## License
287
+
288
+ MIT
@@ -0,0 +1,233 @@
1
+ # PiEEG-16-server
2
+
3
+ A lightweight server for the [PiEEG-16](https://github.com/pieeg-club/PiEEG-16) shield that initializes the hardware, reads 16 channels at 250 Hz, streams live data over WebSocket, and serves a real-time dashboard — all on your local network.
4
+
5
+ ## Install
6
+
7
+ > Pick **one** method. They all get you to the same place: `pieeg-server` ready to run.
8
+
9
+ ### Option A — One-line install (recommended)
10
+
11
+ SSH into your Pi and paste:
12
+
13
+ ```bash
14
+ curl -sSL https://raw.githubusercontent.com/yelabb/PiEEG-16-server/main/install.sh | bash
15
+ sudo reboot # only needed first time, to enable SPI
16
+ ```
17
+
18
+ ### Option B — Clone & setup
19
+
20
+ ```bash
21
+ git clone https://github.com/yelabb/PiEEG-16-server.git
22
+ cd PiEEG-16-server
23
+ chmod +x setup.sh
24
+ ./setup.sh
25
+ sudo reboot # only needed first time, to enable SPI
26
+ ```
27
+
28
+ ---
29
+
30
+ ## Run
31
+
32
+ ```bash
33
+ pieeg-server # start streaming
34
+ pieeg-server --filter # with 1–40 Hz bandpass filter
35
+ pieeg-server --monitor # with live terminal display
36
+ pieeg-server --mock # synthetic data, no hardware needed
37
+ pieeg-server doctor # diagnose SPI, GPIO, deps, permissions
38
+ ```
39
+
40
+ That's it. LEDs turn on, data streams to `ws://raspberrypi.local:1616`.
41
+
42
+ Open **http://raspberrypi.local:1617** in any browser on your network for the real-time dashboard.
43
+
44
+ <img height="400" alt="image" src="https://github.com/user-attachments/assets/3f33bfd4-c721-4b94-a672-2a0b744d127b" />
45
+
46
+ ### Terminal
47
+ <img width="422" height="475" alt="image" src="https://github.com/user-attachments/assets/7d58af68-85c4-41d3-b1ab-89b23e99faff" />
48
+
49
+
50
+ **Ports:**
51
+ - **`:1616`** — WebSocket data stream (PiEEG-**16** → **1616**)
52
+ - **`:1617`** — Web dashboard (next door)
53
+
54
+ ## Record data
55
+
56
+ ```bash
57
+ pieeg-server record session.csv # record until Ctrl-C
58
+ pieeg-server record session.csv --duration 300 # record 5 minutes
59
+ pieeg-server --record session.csv # record while streaming
60
+ pieeg-server --record session.csv --record-duration 60 # record 60s while streaming
61
+ ```
62
+
63
+ CSV format: `timestamp, ch1, ch2, ..., ch16` (compatible with the official PiEEG-16 dataset format).
64
+
65
+ ## Terminal monitor
66
+
67
+ ```bash
68
+ pieeg-server monitor # standalone live view (no server)
69
+ pieeg-server --monitor # live view alongside the server
70
+ ```
71
+
72
+ Displays all 16 channels with real-time µV values and sparkline waveforms directly in the terminal. Works over SSH — no browser or display needed.
73
+
74
+ > **`pieeg-server: command not found`?** Run `pieeg-server doctor` (or `./setup.sh` again).
75
+ > As a fallback: `cd PiEEG-16-server && .venv/bin/pieeg-server`
76
+
77
+ ## Troubleshooting
78
+
79
+ ```bash
80
+ pieeg-server doctor
81
+ ```
82
+
83
+ Checks everything in one shot: Pi model, Python version, SPI devices, GPIO chips, file permissions, port availability, installed dependencies, systemd service. Returns exit code `0` (all good), `1` (warnings), or `2` (errors) — scriptable with `--quiet`.
84
+
85
+ ### Windows: `Could not install packages due to an OSError`
86
+
87
+ If `pip install -e .` fails with a `WinError 2` or `Failed to write executable` error, pip can't replace an old `pieeg-server.exe` in your Python Scripts folder. Fix it:
88
+
89
+ ```powershell
90
+ pip uninstall pieeg-server -y
91
+ pip install -e .
92
+ ```
93
+
94
+ If that still fails, run your terminal **as Administrator** (right-click → Run as administrator).
95
+
96
+ > On Windows you can only use mock mode (`pieeg-server --mock`) since SPI/GPIO hardware is not available.
97
+
98
+ ## Connect from any device
99
+
100
+ ### Python
101
+
102
+ ```python
103
+ import asyncio, json, websockets
104
+
105
+ async def main():
106
+ async with websockets.connect("ws://raspberrypi.local:1616") as ws:
107
+ async for message in ws:
108
+ frame = json.loads(message)
109
+ print(f"Sample #{frame['n']}: {frame['channels']}")
110
+
111
+ asyncio.run(main())
112
+ ```
113
+
114
+ ### JavaScript (browser)
115
+
116
+ ```javascript
117
+ const ws = new WebSocket("ws://raspberrypi.local:1616");
118
+ ws.onmessage = (event) => {
119
+ const frame = JSON.parse(event.data);
120
+ console.log(`Sample #${frame.n}:`, frame.channels);
121
+ };
122
+ ```
123
+
124
+ ## Data Format
125
+
126
+ Each WebSocket message is a JSON frame:
127
+
128
+ ```json
129
+ {
130
+ "t": 1711234567.123456,
131
+ "n": 42,
132
+ "channels": [12.34, -5.67, 8.90, ...]
133
+ }
134
+ ```
135
+
136
+ | Field | Type | Description |
137
+ |-------|------|-------------|
138
+ | `t` | float | Unix timestamp (seconds) |
139
+ | `n` | int | Sample number (monotonic) |
140
+ | `channels` | float[16] | Voltage in microvolts (µV) per channel |
141
+
142
+ ## CLI Options
143
+
144
+ ```
145
+ pieeg-server [OPTIONS] [COMMAND]
146
+
147
+ Commands:
148
+ doctor Diagnose hardware, software, and configuration
149
+ record FILE Record EEG data to CSV (standalone, no server)
150
+ monitor Live terminal display (standalone, no server)
151
+
152
+ Server options:
153
+ --host HOST Bind address (default: 0.0.0.0)
154
+ --port PORT WebSocket port (default: 1616)
155
+ --dashboard-port PORT Dashboard HTTP port (default: 1617)
156
+ --no-dashboard Disable the web dashboard
157
+ --gpio-chip PATH GPIO chip device path (default: /dev/gpiochip4)
158
+ --filter Enable 1–40 Hz bandpass filter server-side
159
+ --lowcut HZ Filter low cutoff (default: 1.0)
160
+ --highcut HZ Filter high cutoff (default: 40.0)
161
+ --record FILE Record to CSV while streaming
162
+ --record-duration SEC Stop recording after N seconds
163
+ --monitor Show live terminal monitor alongside server
164
+ --mock Synthetic EEG data (no hardware needed)
165
+ -v, --verbose Debug logging
166
+ ```
167
+
168
+ ## Runtime Commands
169
+
170
+ Clients can send JSON commands over the WebSocket:
171
+
172
+ ```json
173
+ {"cmd": "set_filter", "enabled": true, "lowcut": 1.0, "highcut": 40.0}
174
+ {"cmd": "set_filter", "enabled": false}
175
+ ```
176
+
177
+ ## Architecture
178
+
179
+ ```
180
+ ┌─────────────────────────────────────────────────────────┐
181
+ │ Raspberry Pi 5 + PiEEG-16 Shield │
182
+ │ │
183
+ │ hardware.py → SPI/GPIO init, ADC register config │
184
+ │ ↓ │
185
+ │ acquisition.py → 250 Hz read loop (background thread) │
186
+ │ ↓ pub/sub (multiple consumers) │
187
+ │ ├── server.py → WebSocket broadcast │
188
+ │ ├── recorder.py → CSV file writer │
189
+ │ └── monitor.py → Terminal sparkline display │
190
+ │ ↓ │
191
+ │ dashboard.py → HTTP server for real-time web UI │
192
+ │ ↓ │
193
+ │ ws://0.0.0.0:1616 │ http://0.0.0.0:1617 │
194
+ └──────────┬───────────────────────────────────────────────┘
195
+ │ Local network
196
+ ├── Browser (JS client)
197
+ ├── Python notebook
198
+ ├── Mobile app
199
+ └── Any WebSocket client
200
+ ```
201
+
202
+ ## Runs as a Service
203
+
204
+ Setup creates a systemd service that auto-starts on boot:
205
+
206
+ ```bash
207
+ sudo systemctl status pieeg-server # check status
208
+ sudo systemctl stop pieeg-server # stop
209
+ sudo systemctl restart pieeg-server # restart
210
+ journalctl -u pieeg-server -f # view logs
211
+ ```
212
+
213
+ ## GPIO: No `gpiod` Dependency
214
+
215
+ This server talks to GPIO directly via the Linux kernel's character device interface (`/dev/gpiochipN`) using standard `ioctl` calls — no `gpiod` pip package needed.
216
+
217
+ We only use two GPIO pins (chip-select output + data-ready input), so the ~20 lines of `struct` packing replace an entire external dependency that:
218
+
219
+ - Has **breaking API changes** between v1 and v2 (completely incompatible)
220
+ - Requires **system C headers** (`libgpiod-dev`) to install via pip
221
+ - Only works on **Linux** (blocks development/testing on macOS/Windows)
222
+
223
+ The chardev v1 ioctl ABI has been stable since Linux 4.8 (2016) and is guaranteed not to break by the kernel's userspace compatibility policy.
224
+
225
+ ## Safety
226
+
227
+ > **PiEEG-16 must operate from battery power (5V) only.**
228
+ > Do NOT connect to mains-powered equipment via USB.
229
+ > PiEEG-16 is NOT a medical device.
230
+
231
+ ## License
232
+
233
+ MIT
@@ -0,0 +1,3 @@
1
+ """PiEEG-16-server: One-command EEG data streaming server."""
2
+
3
+ __version__ = "0.1.0"