ezmsg-blackrock 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.
- ezmsg_blackrock-0.1.0/.github/workflows/python-publish-ezmsg-blackrock.yml +26 -0
- ezmsg_blackrock-0.1.0/.github/workflows/python-tests.yml +41 -0
- ezmsg_blackrock-0.1.0/.gitignore +162 -0
- ezmsg_blackrock-0.1.0/LICENSE.txt +9 -0
- ezmsg_blackrock-0.1.0/PKG-INFO +97 -0
- ezmsg_blackrock-0.1.0/README.md +84 -0
- ezmsg_blackrock-0.1.0/examples/demo.py +80 -0
- ezmsg_blackrock-0.1.0/examples/enable_cont.py +74 -0
- ezmsg_blackrock-0.1.0/pyproject.toml +39 -0
- ezmsg_blackrock-0.1.0/src/ezmsg/blackrock/__init__.py +1 -0
- ezmsg_blackrock-0.1.0/src/ezmsg/blackrock/__version__.py +16 -0
- ezmsg_blackrock-0.1.0/src/ezmsg/blackrock/nsp.py +153 -0
- ezmsg_blackrock-0.1.0/tests/test_dummy.py +2 -0
- ezmsg_blackrock-0.1.0/uv.lock +500 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: Upload Python Package - ezmsg-blackrock
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build:
|
|
10
|
+
name: build and upload release to PyPI
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
environment: "release"
|
|
13
|
+
permissions:
|
|
14
|
+
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Install uv
|
|
20
|
+
uses: astral-sh/setup-uv@v2
|
|
21
|
+
|
|
22
|
+
- name: Build Package
|
|
23
|
+
run: uv build
|
|
24
|
+
|
|
25
|
+
- name: Publish package distributions to PyPI
|
|
26
|
+
run: uv publish
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
name: Test package
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build:
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: [3.9, "3.10", "3.11", "3.12"]
|
|
15
|
+
os:
|
|
16
|
+
- "ubuntu-latest"
|
|
17
|
+
- "windows-latest"
|
|
18
|
+
- "macos-latest"
|
|
19
|
+
runs-on: ${{matrix.os}}
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v4
|
|
23
|
+
|
|
24
|
+
- name: Install uv
|
|
25
|
+
uses: astral-sh/setup-uv@v2
|
|
26
|
+
with:
|
|
27
|
+
enable-cache: true
|
|
28
|
+
cache-dependency-glob: "uv.lock"
|
|
29
|
+
|
|
30
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
31
|
+
run: uv python install ${{ matrix.python-version }}
|
|
32
|
+
|
|
33
|
+
- name: Install the project
|
|
34
|
+
run: uv sync --all-extras --dev
|
|
35
|
+
|
|
36
|
+
- name: Lint
|
|
37
|
+
run:
|
|
38
|
+
uv tool run ruff check --output-format=github src
|
|
39
|
+
|
|
40
|
+
- name: Run tests
|
|
41
|
+
run: uv run pytest tests
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py,cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
#Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# poetry
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
102
|
+
#poetry.lock
|
|
103
|
+
|
|
104
|
+
# pdm
|
|
105
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
106
|
+
#pdm.lock
|
|
107
|
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
108
|
+
# in version control.
|
|
109
|
+
# https://pdm.fming.dev/#use-with-ide
|
|
110
|
+
.pdm.toml
|
|
111
|
+
|
|
112
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
113
|
+
__pypackages__/
|
|
114
|
+
|
|
115
|
+
# Celery stuff
|
|
116
|
+
celerybeat-schedule
|
|
117
|
+
celerybeat.pid
|
|
118
|
+
|
|
119
|
+
# SageMath parsed files
|
|
120
|
+
*.sage.py
|
|
121
|
+
|
|
122
|
+
# Environments
|
|
123
|
+
.env
|
|
124
|
+
.venv
|
|
125
|
+
env/
|
|
126
|
+
venv/
|
|
127
|
+
ENV/
|
|
128
|
+
env.bak/
|
|
129
|
+
venv.bak/
|
|
130
|
+
|
|
131
|
+
# Spyder project settings
|
|
132
|
+
.spyderproject
|
|
133
|
+
.spyproject
|
|
134
|
+
|
|
135
|
+
# Rope project settings
|
|
136
|
+
.ropeproject
|
|
137
|
+
|
|
138
|
+
# mkdocs documentation
|
|
139
|
+
/site
|
|
140
|
+
|
|
141
|
+
# mypy
|
|
142
|
+
.mypy_cache/
|
|
143
|
+
.dmypy.json
|
|
144
|
+
dmypy.json
|
|
145
|
+
|
|
146
|
+
# Pyre type checker
|
|
147
|
+
.pyre/
|
|
148
|
+
|
|
149
|
+
# pytype static type analyzer
|
|
150
|
+
.pytype/
|
|
151
|
+
|
|
152
|
+
# Cython debug symbols
|
|
153
|
+
cython_debug/
|
|
154
|
+
|
|
155
|
+
# PyCharm
|
|
156
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
157
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
158
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
159
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
160
|
+
.idea/
|
|
161
|
+
|
|
162
|
+
src/ezmsg/blackrock/__version__.py
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Johns Hopkins University Applied Physics Lab
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: ezmsg-blackrock
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Blackrock Cerebus ecosystem interface for ezmsg
|
|
5
|
+
Author-email: Griffin Milsap <chadwick.boulay@gmail.com>, Chadwick Boulay <chadwick.boulay@gmail.com>
|
|
6
|
+
Requires-Python: >=3.9
|
|
7
|
+
Requires-Dist: ezmsg-event
|
|
8
|
+
Requires-Dist: ezmsg>=3.6.0
|
|
9
|
+
Requires-Dist: pycbsdk>=0.2.0
|
|
10
|
+
Provides-Extra: test
|
|
11
|
+
Requires-Dist: pytest>=8.3.3; extra == 'test'
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# ezmsg.blackrock
|
|
15
|
+
|
|
16
|
+
Interface for Blackrock Cerebus ecosystem (incl. Neuroport) using `pycbsdk`
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
`pip install git+https://github.com/CerebusOSS/ezmsg-blackrock`
|
|
20
|
+
|
|
21
|
+
## Dependencies
|
|
22
|
+
|
|
23
|
+
* `python` >=3.9
|
|
24
|
+
* `pycbsdk`
|
|
25
|
+
* `ezmsg-sigproc`
|
|
26
|
+
|
|
27
|
+
## Setup (Development)
|
|
28
|
+
|
|
29
|
+
1. Install `ezmsg` either using `pip install ezmsg` or set up the repo for development as described in the `ezmsg` readme.
|
|
30
|
+
2. `cd` to this directory and run `pip install -e .`
|
|
31
|
+
3. Blackrock components are available under `import ezmsg.blackrock`
|
|
32
|
+
|
|
33
|
+
## Setup Notes
|
|
34
|
+
|
|
35
|
+
__IMPORTANT NOTE:__ _`pycbsdk` is only compatible with Central Neuroport/Cerebus Suite/NSP Firmware `7.0.5+`, built using `cbhwlib`/hardware library/network protocol `3.11+`. Anything older is not supported by `pycbsdk`_. Check this requirement in Central by navigating to `Help > About Central`
|
|
36
|
+
|
|
37
|
+
Blackrock Neuroport/Cerebus uses UDP multicast traffic to deliver upwards of 30000 packets/sec of data with low latency. There are better ways to do this now, but back when this hardware was made, the engineers were dealing with the limitations of the hardware they had. UDP comes with no packet delivery guarantee, but dropped packets can be catastrophic when interfacing with the Blackrock hardware. As such, do your best to locate the highest quality networking equipment you can find, and have a high tolerance for blaming ethernet adapters and/or your router/switch for errors during troubleshooting.
|
|
38
|
+
|
|
39
|
+
The NSP startup procedure involves blasting several thousand UDP packets from the NSP to the interfacing computer in a few milliseconds. Many low-quality adapters and network switches will simply drop some of these UDP packets, but this will result in errors during startup.
|
|
40
|
+
|
|
41
|
+
### Hardware Setup
|
|
42
|
+
|
|
43
|
+
This setup describes a setup with a Legacy NSP, a Windows PC (called "Central PC") running Central Suite that can configure the NSP, and a third machine (Windows, MacOS, or Linux) that will be running `ezmsg-blackrock`, henceforth forward referred to as the "Client PC". The documentation highlights the differences when using Blockrock's newer ("Gemini") NSP and Hubs.
|
|
44
|
+
|
|
45
|
+
Central cannot run on the same PC simultaneously as `ezmsg-blackrock` because `pycbsdk` exclusively binds the port that central would use to communicate with the NSP. The NSP has too many settings to implement in `ezmsg-blackrock`, so in practice, we use Central to configure the NSP then acquire live data thereafter. If you want to, you _can_ use `ezmsg-blackrock` on the Central PC once you've configured the NSP and closed Central. When you do this, the Central PC and the Client PC are the same PC/IP address. Its assumed that this PC is running windows because Central Suite is only available on Windows.
|
|
46
|
+
|
|
47
|
+
Find the highest quality ethernet (yes, wired) network switch or router that you can. Look for 1+ Gigabit speed ratings (2.5 Gigabit better, 10 Gigabit is best), and features like QoS (Quality of Service) that can guarantee packet delivery. Ensure both the Central PC and the Client PC have high quality ethernet network adapters. Not every ethernet adapter will work, due to packet buffering requirements. High quality ethernet cables are also important; aim for Cat6E or better.
|
|
48
|
+
|
|
49
|
+
1. Attach the NSP, Central PC, and Client PC to the router or switch using ethernet cables.
|
|
50
|
+
1. Blackrock NSP and Gemini Hubs use hard-coded static IP addresses.
|
|
51
|
+
* If using a router (recommended), configure the router to sit at `192.168.137.254` and configure static DHCP assignments (mapping adapter MAC addresses to preset IP addresses) for:
|
|
52
|
+
* NSP (Legacy or Gemini) -- `192.168.137.128`
|
|
53
|
+
* Gemini Hub1 -- `192.168.137.200`
|
|
54
|
+
* Gemini Hub2 -- `192.168.137.201`
|
|
55
|
+
* Central PC -- `192.168.137.1` (Central likes to run on IP addresses below `192.168.137.16`)
|
|
56
|
+
* Client PC -- `192.168.137.32` (Arbitrary address within subnet)
|
|
57
|
+
* If using a network switch, configure the network adapters on the Central PC and Client PC to the aforementioned IP addresses
|
|
58
|
+
1. At this point, it's handy to make sure you can ping the NSP and Client PC from the Central PC and that you can ping the NSP and the Central PC from the Client PC. Adjust firewall settings accordingly, enabling multicast UDP traffic on the ethernet adapters, and all TCP/UDP traffic on ports `51001` and `51002`.
|
|
59
|
+
1. Download and install the Central Suite on the Central PC from the [Blackrock Support](https://blackrockneurotech.com/support/) site:
|
|
60
|
+
* The public "Cerebus Central Suite" will not function with the FDA approved Neuroport system, which will instead require the "Neuroport Central Suite". Acquiring this installer will require you to submit a ticket to Blackrock Support because the download is NOT public.
|
|
61
|
+
|
|
62
|
+
#### Emulate an NSP (Useful for development without an NSP)
|
|
63
|
+
|
|
64
|
+
It is possible to emulate Blackrock hardware while playing back previously recorded data using a software tool called "nPlayServer".
|
|
65
|
+
The publicly-available and supported nPlayServer is only available on Windows but unsupported Mac and Linux binaries (x86 or ARM) are available. Open an issue to ask.
|
|
66
|
+
|
|
67
|
+
1. Power down the NSP if you already have it on the switch/router.
|
|
68
|
+
1. Download and extract the "Real Sample Data" from the [Blackrock Support](https://blackrockneurotech.com/support/) site. Extract the `*.ns6` file somewhere memorable in the filesystem (like `Documents`)
|
|
69
|
+
1. Run nPlayServer. On Windows, use the nPlayServer shortcut on the desktop to start Central and use the nPlay control window to navigate to the `*.ns6` file directory, select the file to replay, and start replaying it. Then close Central/nPlayServer. This is important for using the `-L` flag with `nPlayServer.exe` later.
|
|
70
|
+
1. Navigate to the installation directory (e.g., "C:\Program Files\Blackrock Microsystems\Cerebus Central Suite") and locate the `nPlayServer.exe` executable. Right click it and create a shortcut on the desktop.
|
|
71
|
+
1. Rename the shortcut to "Simulate NSP" or another friendly name.
|
|
72
|
+
|
|
73
|
+
If your intention is to only test on 'localhost' (i.e., ezmsg-blackrock and nPlayServer on the same machine), then there is nothing more to be done.
|
|
74
|
+
However, if your intention is for the emulation PC to be a different machine than the client PC, nPlayServer must be configured to work over the network.
|
|
75
|
+
|
|
76
|
+
1. Reconfigure the emulation host PC to have an IP address matching the emulated device (see addresses listed above).
|
|
77
|
+
1. Right click the shortcut and go to "Properties". Set the "Target" line to: `"C:\Program Files (x86)\Blackrock Microsystems\Neuroport Central Suite\nPlayServer.exe" --network bcast=192.168.137.255:51002 --network inst=192.168.137.128:51001 -L`, adjusting for the actual install path of your Central suite.
|
|
78
|
+
* `bcast` address is `.255` because that's the UDP multicast address.
|
|
79
|
+
* `inst` address is `.128` to emulate Legacy NSP. See the list above for Gemini hardware. Also, Gemini hardware requires the instrument port to be set to `51002`.
|
|
80
|
+
* `-L` uses the last `.nsX` file for replay. You can also manually specify an `.nsX` file for replay, but be aware nothing will replay when using `-L` if you've never replayed a file using nPlayServer, or if that file has moved or no longer exists.
|
|
81
|
+
|
|
82
|
+
### Software Setup
|
|
83
|
+
|
|
84
|
+
* Use Central to set up the NSP hardware.
|
|
85
|
+
* If running Central and `ezmsg-blackrock` on the same PC, shut down Central
|
|
86
|
+
* Assuming `pycbsdk` is installed in your python environment (which it should be, considering it's a dependency of `ezmsg-blackrock` that automatically gets installed with a `pip install -e .`), you should have the `pycbsdk-rates` command on your path. Test the connection and hardware/software setup using `pycbsdk-rates --inst_addr 192.168.137.128 --inst_port 51001 --protocol 3.11`
|
|
87
|
+
* Note that this command line is for Legacy NSP with hard-coded address `192.168.137.128` running on port 51001
|
|
88
|
+
* Also note that network protocol is not automatically detected. Our old hardware can only be updated to firmware `7.0.6` which uses hardware library/protocol `3.11`. This can be checked by opening Central and navigating to "About Central" which will tell you which hardware library the firmware is running (assuming your NSP's firmware and Central version match). As of this writing, most Gemini hardware should be using protocol 4.1 (default).
|
|
89
|
+
|
|
90
|
+
### Troubleshooting
|
|
91
|
+
|
|
92
|
+
* When in doubt, restart equipment.
|
|
93
|
+
* Try software multiple times. If you get different results every time you run, you might have ethernet adapters/network equipment of insufficient quality (it might be dropping packets, especially during configuration).
|
|
94
|
+
* Make sure the Central PC and the Client PC can ping each other and the NSP.
|
|
95
|
+
* Ensure NSP Firmware matches Central version.
|
|
96
|
+
* Ensure the protocol version you specify matches the firmware's protocol version.
|
|
97
|
+
* `pycbsdk-rates` and Wireshark + [a dissector](https://github.com/CerebusOSS/CerebusWireshark) are your friends. Godspeed.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# ezmsg.blackrock
|
|
2
|
+
|
|
3
|
+
Interface for Blackrock Cerebus ecosystem (incl. Neuroport) using `pycbsdk`
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
`pip install git+https://github.com/CerebusOSS/ezmsg-blackrock`
|
|
7
|
+
|
|
8
|
+
## Dependencies
|
|
9
|
+
|
|
10
|
+
* `python` >=3.9
|
|
11
|
+
* `pycbsdk`
|
|
12
|
+
* `ezmsg-sigproc`
|
|
13
|
+
|
|
14
|
+
## Setup (Development)
|
|
15
|
+
|
|
16
|
+
1. Install `ezmsg` either using `pip install ezmsg` or set up the repo for development as described in the `ezmsg` readme.
|
|
17
|
+
2. `cd` to this directory and run `pip install -e .`
|
|
18
|
+
3. Blackrock components are available under `import ezmsg.blackrock`
|
|
19
|
+
|
|
20
|
+
## Setup Notes
|
|
21
|
+
|
|
22
|
+
__IMPORTANT NOTE:__ _`pycbsdk` is only compatible with Central Neuroport/Cerebus Suite/NSP Firmware `7.0.5+`, built using `cbhwlib`/hardware library/network protocol `3.11+`. Anything older is not supported by `pycbsdk`_. Check this requirement in Central by navigating to `Help > About Central`
|
|
23
|
+
|
|
24
|
+
Blackrock Neuroport/Cerebus uses UDP multicast traffic to deliver upwards of 30000 packets/sec of data with low latency. There are better ways to do this now, but back when this hardware was made, the engineers were dealing with the limitations of the hardware they had. UDP comes with no packet delivery guarantee, but dropped packets can be catastrophic when interfacing with the Blackrock hardware. As such, do your best to locate the highest quality networking equipment you can find, and have a high tolerance for blaming ethernet adapters and/or your router/switch for errors during troubleshooting.
|
|
25
|
+
|
|
26
|
+
The NSP startup procedure involves blasting several thousand UDP packets from the NSP to the interfacing computer in a few milliseconds. Many low-quality adapters and network switches will simply drop some of these UDP packets, but this will result in errors during startup.
|
|
27
|
+
|
|
28
|
+
### Hardware Setup
|
|
29
|
+
|
|
30
|
+
This setup describes a setup with a Legacy NSP, a Windows PC (called "Central PC") running Central Suite that can configure the NSP, and a third machine (Windows, MacOS, or Linux) that will be running `ezmsg-blackrock`, henceforth forward referred to as the "Client PC". The documentation highlights the differences when using Blockrock's newer ("Gemini") NSP and Hubs.
|
|
31
|
+
|
|
32
|
+
Central cannot run on the same PC simultaneously as `ezmsg-blackrock` because `pycbsdk` exclusively binds the port that central would use to communicate with the NSP. The NSP has too many settings to implement in `ezmsg-blackrock`, so in practice, we use Central to configure the NSP then acquire live data thereafter. If you want to, you _can_ use `ezmsg-blackrock` on the Central PC once you've configured the NSP and closed Central. When you do this, the Central PC and the Client PC are the same PC/IP address. Its assumed that this PC is running windows because Central Suite is only available on Windows.
|
|
33
|
+
|
|
34
|
+
Find the highest quality ethernet (yes, wired) network switch or router that you can. Look for 1+ Gigabit speed ratings (2.5 Gigabit better, 10 Gigabit is best), and features like QoS (Quality of Service) that can guarantee packet delivery. Ensure both the Central PC and the Client PC have high quality ethernet network adapters. Not every ethernet adapter will work, due to packet buffering requirements. High quality ethernet cables are also important; aim for Cat6E or better.
|
|
35
|
+
|
|
36
|
+
1. Attach the NSP, Central PC, and Client PC to the router or switch using ethernet cables.
|
|
37
|
+
1. Blackrock NSP and Gemini Hubs use hard-coded static IP addresses.
|
|
38
|
+
* If using a router (recommended), configure the router to sit at `192.168.137.254` and configure static DHCP assignments (mapping adapter MAC addresses to preset IP addresses) for:
|
|
39
|
+
* NSP (Legacy or Gemini) -- `192.168.137.128`
|
|
40
|
+
* Gemini Hub1 -- `192.168.137.200`
|
|
41
|
+
* Gemini Hub2 -- `192.168.137.201`
|
|
42
|
+
* Central PC -- `192.168.137.1` (Central likes to run on IP addresses below `192.168.137.16`)
|
|
43
|
+
* Client PC -- `192.168.137.32` (Arbitrary address within subnet)
|
|
44
|
+
* If using a network switch, configure the network adapters on the Central PC and Client PC to the aforementioned IP addresses
|
|
45
|
+
1. At this point, it's handy to make sure you can ping the NSP and Client PC from the Central PC and that you can ping the NSP and the Central PC from the Client PC. Adjust firewall settings accordingly, enabling multicast UDP traffic on the ethernet adapters, and all TCP/UDP traffic on ports `51001` and `51002`.
|
|
46
|
+
1. Download and install the Central Suite on the Central PC from the [Blackrock Support](https://blackrockneurotech.com/support/) site:
|
|
47
|
+
* The public "Cerebus Central Suite" will not function with the FDA approved Neuroport system, which will instead require the "Neuroport Central Suite". Acquiring this installer will require you to submit a ticket to Blackrock Support because the download is NOT public.
|
|
48
|
+
|
|
49
|
+
#### Emulate an NSP (Useful for development without an NSP)
|
|
50
|
+
|
|
51
|
+
It is possible to emulate Blackrock hardware while playing back previously recorded data using a software tool called "nPlayServer".
|
|
52
|
+
The publicly-available and supported nPlayServer is only available on Windows but unsupported Mac and Linux binaries (x86 or ARM) are available. Open an issue to ask.
|
|
53
|
+
|
|
54
|
+
1. Power down the NSP if you already have it on the switch/router.
|
|
55
|
+
1. Download and extract the "Real Sample Data" from the [Blackrock Support](https://blackrockneurotech.com/support/) site. Extract the `*.ns6` file somewhere memorable in the filesystem (like `Documents`)
|
|
56
|
+
1. Run nPlayServer. On Windows, use the nPlayServer shortcut on the desktop to start Central and use the nPlay control window to navigate to the `*.ns6` file directory, select the file to replay, and start replaying it. Then close Central/nPlayServer. This is important for using the `-L` flag with `nPlayServer.exe` later.
|
|
57
|
+
1. Navigate to the installation directory (e.g., "C:\Program Files\Blackrock Microsystems\Cerebus Central Suite") and locate the `nPlayServer.exe` executable. Right click it and create a shortcut on the desktop.
|
|
58
|
+
1. Rename the shortcut to "Simulate NSP" or another friendly name.
|
|
59
|
+
|
|
60
|
+
If your intention is to only test on 'localhost' (i.e., ezmsg-blackrock and nPlayServer on the same machine), then there is nothing more to be done.
|
|
61
|
+
However, if your intention is for the emulation PC to be a different machine than the client PC, nPlayServer must be configured to work over the network.
|
|
62
|
+
|
|
63
|
+
1. Reconfigure the emulation host PC to have an IP address matching the emulated device (see addresses listed above).
|
|
64
|
+
1. Right click the shortcut and go to "Properties". Set the "Target" line to: `"C:\Program Files (x86)\Blackrock Microsystems\Neuroport Central Suite\nPlayServer.exe" --network bcast=192.168.137.255:51002 --network inst=192.168.137.128:51001 -L`, adjusting for the actual install path of your Central suite.
|
|
65
|
+
* `bcast` address is `.255` because that's the UDP multicast address.
|
|
66
|
+
* `inst` address is `.128` to emulate Legacy NSP. See the list above for Gemini hardware. Also, Gemini hardware requires the instrument port to be set to `51002`.
|
|
67
|
+
* `-L` uses the last `.nsX` file for replay. You can also manually specify an `.nsX` file for replay, but be aware nothing will replay when using `-L` if you've never replayed a file using nPlayServer, or if that file has moved or no longer exists.
|
|
68
|
+
|
|
69
|
+
### Software Setup
|
|
70
|
+
|
|
71
|
+
* Use Central to set up the NSP hardware.
|
|
72
|
+
* If running Central and `ezmsg-blackrock` on the same PC, shut down Central
|
|
73
|
+
* Assuming `pycbsdk` is installed in your python environment (which it should be, considering it's a dependency of `ezmsg-blackrock` that automatically gets installed with a `pip install -e .`), you should have the `pycbsdk-rates` command on your path. Test the connection and hardware/software setup using `pycbsdk-rates --inst_addr 192.168.137.128 --inst_port 51001 --protocol 3.11`
|
|
74
|
+
* Note that this command line is for Legacy NSP with hard-coded address `192.168.137.128` running on port 51001
|
|
75
|
+
* Also note that network protocol is not automatically detected. Our old hardware can only be updated to firmware `7.0.6` which uses hardware library/protocol `3.11`. This can be checked by opening Central and navigating to "About Central" which will tell you which hardware library the firmware is running (assuming your NSP's firmware and Central version match). As of this writing, most Gemini hardware should be using protocol 4.1 (default).
|
|
76
|
+
|
|
77
|
+
### Troubleshooting
|
|
78
|
+
|
|
79
|
+
* When in doubt, restart equipment.
|
|
80
|
+
* Try software multiple times. If you get different results every time you run, you might have ethernet adapters/network equipment of insufficient quality (it might be dropping packets, especially during configuration).
|
|
81
|
+
* Make sure the Central PC and the Client PC can ping each other and the NSP.
|
|
82
|
+
* Ensure NSP Firmware matches Central version.
|
|
83
|
+
* Ensure the protocol version you specify matches the firmware's protocol version.
|
|
84
|
+
* `pycbsdk-rates` and Wireshark + [a dissector](https://github.com/CerebusOSS/CerebusWireshark) are your friends. Godspeed.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
|
|
3
|
+
import ezmsg.core as ez
|
|
4
|
+
from ezmsg.util.debuglog import DebugLog
|
|
5
|
+
import typer
|
|
6
|
+
from typing_extensions import Annotated
|
|
7
|
+
|
|
8
|
+
from ezmsg.blackrock.nsp import NSPSource, NSPSourceSettings
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def main(
|
|
12
|
+
inst_addr: Annotated[
|
|
13
|
+
str,
|
|
14
|
+
typer.Option(
|
|
15
|
+
help="ipv4 address of device. pycbsdk will send control packets to this address. Subnet OK. Use 127.0.0.1 "
|
|
16
|
+
"for use with nPlayServer (non-bcast). The default is 0.0.0.0 (IPADDR_ANY) on Mac and Linux. On "
|
|
17
|
+
"Windows, known IPs will be searched."
|
|
18
|
+
),
|
|
19
|
+
] = "192.168.137.128",
|
|
20
|
+
inst_port: Annotated[
|
|
21
|
+
int,
|
|
22
|
+
typer.Option(
|
|
23
|
+
help="Network port to send control packets. Use 51002 for Gemini and 51001 for Legacy NSP."
|
|
24
|
+
),
|
|
25
|
+
] = 51001,
|
|
26
|
+
client_addr: Annotated[
|
|
27
|
+
str,
|
|
28
|
+
typer.Option(
|
|
29
|
+
help="ipv4 address of this machine's network adapter we will receive packets on. Defaults to INADDR_ANY. "
|
|
30
|
+
"If address is provided, assumes Cerebus Subnet."
|
|
31
|
+
),
|
|
32
|
+
] = "",
|
|
33
|
+
client_port: Annotated[
|
|
34
|
+
int,
|
|
35
|
+
typer.Option(
|
|
36
|
+
help="Network port to receive packets. This should always be 51002."
|
|
37
|
+
),
|
|
38
|
+
] = 51002,
|
|
39
|
+
recv_bufsize: Annotated[
|
|
40
|
+
int, typer.Option(help="UDP socket recv buffer size.")
|
|
41
|
+
] = (8 if sys.platform == "win32" else 6) * 1024 * 1024,
|
|
42
|
+
protocol: Annotated[
|
|
43
|
+
str, typer.Option(help="Protocol Version. 3.11, 4.0, or 4.1 supported.")
|
|
44
|
+
] = "3.11",
|
|
45
|
+
cont_buffer_dur: Annotated[
|
|
46
|
+
float,
|
|
47
|
+
typer.Option(
|
|
48
|
+
help="Duration of buffer for continuous data. Note: buffer may occupy ~15 MB / second."
|
|
49
|
+
),
|
|
50
|
+
] = 0.5,
|
|
51
|
+
):
|
|
52
|
+
source_settings = NSPSourceSettings(
|
|
53
|
+
inst_addr,
|
|
54
|
+
inst_port,
|
|
55
|
+
client_addr,
|
|
56
|
+
client_port,
|
|
57
|
+
recv_bufsize,
|
|
58
|
+
protocol,
|
|
59
|
+
cont_buffer_dur,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
comps = {
|
|
63
|
+
"SRC": NSPSource(source_settings),
|
|
64
|
+
# TODO: SparseResample(fs=1000.0, max_age=0.005),
|
|
65
|
+
# TODO: EventRates(),
|
|
66
|
+
"SPKLOG": DebugLog(name="SPK"),
|
|
67
|
+
"GRPLOG": DebugLog(name="GRP"),
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
conns = (
|
|
71
|
+
(comps["SRC"].OUTPUT_SPIKE, comps["SPKLOG"].INPUT),
|
|
72
|
+
(comps["SRC"].OUTPUT_SIGNAL, comps["GRPLOG"].INPUT),
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
ez.run(components=comps, connections=conns)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
if __name__ == "__main__":
|
|
80
|
+
typer.run(main)
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import time
|
|
3
|
+
from typing_extensions import Annotated
|
|
4
|
+
|
|
5
|
+
from pycbsdk import cbsdk
|
|
6
|
+
from pycbsdk.cbhw.packet.common import CBChannelType
|
|
7
|
+
import typer
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def main(
|
|
11
|
+
smp_group: int,
|
|
12
|
+
inst_addr: Annotated[
|
|
13
|
+
str,
|
|
14
|
+
typer.Option(
|
|
15
|
+
help="ipv4 address of device. pycbsdk will send control packets to this address. Subnet OK. Use 127.0.0.1 "
|
|
16
|
+
"for use with nPlayServer (non-bcast). The default is 0.0.0.0 (IPADDR_ANY) on Mac and Linux. On "
|
|
17
|
+
"Windows, known IPs will be searched."
|
|
18
|
+
),
|
|
19
|
+
] = "192.168.137.128",
|
|
20
|
+
inst_port: Annotated[
|
|
21
|
+
int,
|
|
22
|
+
typer.Option(
|
|
23
|
+
help="Network port to send control packets. Use 51002 for Gemini and 51001 for Legacy NSP."
|
|
24
|
+
),
|
|
25
|
+
] = 51001,
|
|
26
|
+
client_addr: Annotated[
|
|
27
|
+
str,
|
|
28
|
+
typer.Option(
|
|
29
|
+
help="ipv4 address of this machine's network adapter we will receive packets on. Defaults to INADDR_ANY. "
|
|
30
|
+
"If address is provided, assumes Cerebus Subnet."
|
|
31
|
+
),
|
|
32
|
+
] = "",
|
|
33
|
+
client_port: Annotated[
|
|
34
|
+
int,
|
|
35
|
+
typer.Option(
|
|
36
|
+
help="Network port to receive packets. This should always be 51002."
|
|
37
|
+
),
|
|
38
|
+
] = 51002,
|
|
39
|
+
recv_bufsize: Annotated[
|
|
40
|
+
int, typer.Option(help="UDP socket recv buffer size.")
|
|
41
|
+
] = (8 if sys.platform == "win32" else 6) * 1024 * 1024,
|
|
42
|
+
protocol: Annotated[
|
|
43
|
+
str, typer.Option(help="Protocol Version. 3.11, 4.0, or 4.1 supported.")
|
|
44
|
+
] = "3.11",
|
|
45
|
+
):
|
|
46
|
+
|
|
47
|
+
params = cbsdk.create_params(
|
|
48
|
+
inst_addr=inst_addr,
|
|
49
|
+
inst_port=inst_port,
|
|
50
|
+
client_addr=client_addr,
|
|
51
|
+
client_port=client_port,
|
|
52
|
+
recv_bufsize=recv_bufsize,
|
|
53
|
+
protocol=protocol,
|
|
54
|
+
)
|
|
55
|
+
device = cbsdk.NSPDevice(params)
|
|
56
|
+
run_level = device.connect(startup_sequence=False)
|
|
57
|
+
if not run_level:
|
|
58
|
+
raise ValueError(f"Failed to connect to NSP; {params=}")
|
|
59
|
+
config = cbsdk.get_config(device, force_refresh=True)
|
|
60
|
+
for chid in [
|
|
61
|
+
k
|
|
62
|
+
for k, v in config["channel_infos"].items()
|
|
63
|
+
if config["channel_types"][k]
|
|
64
|
+
in (CBChannelType.FrontEnd, CBChannelType.AnalogIn)
|
|
65
|
+
]:
|
|
66
|
+
_ = cbsdk.set_channel_config(
|
|
67
|
+
device, chid, "smpgroup", smp_group
|
|
68
|
+
)
|
|
69
|
+
# Refresh config
|
|
70
|
+
time.sleep(0.5) # Make sure all the config packets have returned.
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
if __name__ == "__main__":
|
|
74
|
+
typer.run(main)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "ezmsg-blackrock"
|
|
3
|
+
description = "Blackrock Cerebus ecosystem interface for ezmsg"
|
|
4
|
+
authors = [
|
|
5
|
+
{ name = "Griffin Milsap", email = "chadwick.boulay@gmail.com" },
|
|
6
|
+
{ name = "Chadwick Boulay", email = "chadwick.boulay@gmail.com" },
|
|
7
|
+
]
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
requires-python = ">=3.9"
|
|
10
|
+
dynamic = ["version"]
|
|
11
|
+
dependencies = [
|
|
12
|
+
"ezmsg-event",
|
|
13
|
+
"ezmsg>=3.6.0",
|
|
14
|
+
"pycbsdk>=0.2.0",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[project.optional-dependencies]
|
|
18
|
+
test = [
|
|
19
|
+
"pytest>=8.3.3",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
[build-system]
|
|
23
|
+
requires = ["hatchling", "hatch-vcs"]
|
|
24
|
+
build-backend = "hatchling.build"
|
|
25
|
+
|
|
26
|
+
[tool.hatch.version]
|
|
27
|
+
source = "vcs"
|
|
28
|
+
|
|
29
|
+
[tool.hatch.build.hooks.vcs]
|
|
30
|
+
version-file = "src/ezmsg/blackrock/__version__.py"
|
|
31
|
+
|
|
32
|
+
[tool.hatch.build.targets.wheel]
|
|
33
|
+
packages = ["src/ezmsg"]
|
|
34
|
+
|
|
35
|
+
[tool.uv]
|
|
36
|
+
dev-dependencies = [
|
|
37
|
+
"ruff>=0.6.8",
|
|
38
|
+
"typer>=0.12.5",
|
|
39
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .__version__ import __version__ as __version__
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# file generated by setuptools_scm
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
TYPE_CHECKING = False
|
|
4
|
+
if TYPE_CHECKING:
|
|
5
|
+
from typing import Tuple, Union
|
|
6
|
+
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
7
|
+
else:
|
|
8
|
+
VERSION_TUPLE = object
|
|
9
|
+
|
|
10
|
+
version: str
|
|
11
|
+
__version__: str
|
|
12
|
+
__version_tuple__: VERSION_TUPLE
|
|
13
|
+
version_tuple: VERSION_TUPLE
|
|
14
|
+
|
|
15
|
+
__version__ = version = '0.1.0'
|
|
16
|
+
__version_tuple__ = version_tuple = (0, 1, 0)
|