@anthriq/instinct-js
v1.5.1
Published
Control and interact with your Instinct headset.
Readme
@nexstem/instinct-js
Node.js SDK for controlling and interacting with Nexstem Instinct headsets.
Overview
The Instinct JavaScript SDK provides a comprehensive set of tools for discovering, connecting to, and controlling Nexstem Instinct headsets from Node.js applications. This SDK enables developers to:
- Discover Instinct headsets on the local network
- Monitor headset state (battery, CPU, RAM, storage)
- Configure electrodes and sensors
- Create and manage data streams
- Build custom signal processing pipelines
- Store and retrieve device configuration values
Installation
# Using npm
npm install @nexstem/instinct-js
# Using yarn
yarn add @nexstem/instinct-jsRequirements
- Node.js 14 or later
- An Instinct headset on the same network
Quick Start
Discovering Headsets
import { Headset } from '@nexstem/instinct-js';
// Discover all Instinct headsets on the network
const headsets = await Headset.discover();
console.log(`Found ${headsets.length} headsets`);
// Connect to the first headset found
const headset = headsets[0];Getting Headset State
// Get basic headset information
const state = await headset.getState();
console.log(`Headset status: ${state.status}`);
console.log(`Battery: ${state.battery.percent}%`);
console.log(`CPU load: ${state.cpu.load}%`);
// Get the headset name
const name = await headset.getName();
console.log(`Headset name: ${name}`);Working with Streams
import { v4 as uuidv4 } from 'uuid';
const sourceId = v4();
const ssvepId = v4();
// Create a stream
const stream = headset.StreamsManager.createStream({
id: uuidv4(),
nodes: [
{
executable: 'eeg_source',
config: {
sampleRate: 1000,
gain: 1,
},
id: sourceId,
},
{
executable: 'ssvep_algo',
config: {},
id: ssvepId,
},
],
pipes: [
{
source: 'source_id',
destination: 'destination_id',
},
],
});
// Create the stream on the headset
await stream.create();
// Start the stream
await stream.start();
// Stop the stream when done
await stream.stop();API Documentation
Headset Class
The main entry point for interacting with Instinct headsets.
Static Methods
| Method | Description |
| ---------------------------------------------------- | ------------------------------------------ |
| Headset.discover(timeout?, discoveryPort?, debug?) | Discovers Instinct headsets on the network |
Instance Properties
| Property | Type | Description |
| --------------------- | -------------------------- | ------------------------------------------------- |
| StreamsManager | HeadsetStreamsManager | Manager for creating and controlling data streams |
| ElectrodeManager | HeadsetElectrodesManager | Manager for electrode configurations |
| SensorManager | HeadsetSensorsManager | Manager for sensor data |
| DeviceConfigManager | DeviceConfigManager | Manager for device configuration storage |
| hostAddress | string | IP address of the headset |
Instance Methods
| Method | Description |
| --------------------------- | ------------------------------------------------------ |
| getState() | Gets the current state of the headset |
| getName() | Gets the current name of the headset |
| setName(name) | Sets a new name for the headset |
| sendDebugCommand(command) | Sends a debug command to the headset (debug mode only) |
Device Configuration Management
The SDK provides DeviceConfigManager for storing and retrieving persistent configuration values on the headset.
DeviceConfigManager Class
Manages device configuration storage.
| Method | Description |
| ------------------------------- | --------------------------------- |
| createConfig(configData) | Creates a new configuration entry |
| getConfig(key) | Retrieves a configuration by key |
| updateConfig(key, configData) | Updates an existing configuration |
| deleteConfig(key) | Deletes a configuration entry |
Configuration Data Types
| Field | Type | Description |
| ----------- | -------- | --------------------------------------------------- |
| key | string | Unique identifier for the configuration |
| value | any | Value to store (serialized to string) |
| expiresIn | string | Optional time-to-live (e.g., "1h", "2d", "30m") |
| id | string | Optional unique ID (auto-generated if not provided) |
Storing Device Configuration
// Store user preferences
await headset.DeviceConfigManager.createConfig({
key: 'userPreference.theme',
value: 'dark',
});
// Store temporary data with expiration
await headset.DeviceConfigManager.createConfig({
key: 'session.authToken',
value: 'abc123xyz',
expiresOn: '2023-12-31T23:59:59Z', // Expires at specific date/time
});
// Retrieve configuration
const config = await headset.DeviceConfigManager.getConfig(
'userPreference.theme'
);
console.log(`Theme preference: ${config.value}`);
// Update configuration
await headset.DeviceConfigManager.updateConfig('userPreference.theme', {
key: 'userPreference.theme',
value: 'light',
});
// Delete configuration
await headset.DeviceConfigManager.deleteConfig('session.authToken');Stream Management
The SDK provides classes for creating and managing data processing streams:
Stream Class
Represents a data processing stream with nodes and pipes.
| Method | Description |
| --------------------------------- | --------------------------------- |
| create() | Creates the stream on the headset |
| start() | Starts data processing |
| stop() | Stops data processing |
| sendSignal(signal, parameters?) | Sends a signal to the stream |
| addNodes(nodes) | Adds new nodes to the stream |
| deleteNode(nodeId) | Deletes a node from the stream |
| addPipes(pipes) | Adds new pipes to the stream |
| deletePipe(pipeId) | Deletes a pipe from the stream |
Node Class
Represents a processing node in a stream.
| Method | Description |
| -------------------------------- | -------------------------------- |
| create() | Creates the node on the headset |
| sendSignal(signal, parameters) | Sends a signal to the node |
| delete() | Deletes the node from the stream |
Pipe Class
Represents a connection between nodes.
| Method | Description |
| ---------- | -------------------------------- |
| create() | Creates the pipe on the headset |
| delete() | Deletes the pipe from the stream |
Advanced Usage
Custom Stream Configuration
import { Headset, v4 as uuidv4 } from '@nexstem/instinct-js';
// Connect to a headset at a specific IP address
const headset = new Headset('192.168.1.100');
// Create a stream with custom metadata
const sourceId = uuidv4();
const bandpassId = uuidv4();
const fftId = uuidv4();
const websocketId = uuidv4();
const stream = headset.StreamsManager.createStream({
id: uuidv4(),
meta: {
name: 'Alpha Rhythm Analysis',
description:
'Extracts and analyzes alpha rhythms from occipital electrodes',
version: '1.0.0',
},
nodes: [
// EEG data source
{
executable: 'eeg_source',
config: {
sampleRate: 250,
channels: ['O1', 'O2', 'PZ'],
},
id: sourceId,
},
// Bandpass filter for alpha band (8-12 Hz)
{
executable: 'bandpass_filter',
config: {
cutoff: 10,
bandwidth: 4,
order: 4,
},
id: bandpassId,
},
// Spectral analysis node
{
executable: 'fft_analyzer',
config: {
windowSize: 512,
overlap: 0.5,
},
id: fftId,
},
// Data output node
{
executable: 'websocket_output',
config: {
port: 36006,
},
id: websocketId,
},
],
pipes: [
// Connect the nodes in sequence
{
id: uuidv4(),
source: sourceId,
destination: bandpassId,
},
{
id: uuidv4(),
source: bandpassId,
destination: fftId,
},
{
id: uuidv4(),
source: fftId,
destination: websocketId,
},
],
});
// Create and start the stream
await stream.create();
await stream.start();
// Connect to the websocket output in your application
// const socket = new WebSocket('ws://localhost:36006');Custom Node Integration
The Instinct platform supports custom processing nodes developed following the Nexstem Node API:
// Add a custom processing node to a stream
// First, stop the running stream
await stream.stop();
// Add the new custom node
const customNodeId = uuidv4();
await stream.addNodes([
{
executable: 'another_custom_node',
config: {
threshold: 0.75,
windowSize: 256,
},
meta: {
author: 'Nexstem',
version: '1.1.0',
},
id: customNodeId,
},
]);
// Add new pipes to connect the custom node
await stream.addPipes([
{
id: uuidv4(),
source: fftId, // Connect from existing FFT node
destination: customNodeId,
},
{
id: uuidv4(),
source: customNodeId,
destination: websocketId, // Connect to existing websocket node
},
]);
// Delete the pipe which is no longer relevant
await stream.deletePipes(['<PIPE_FFT_TO_WEBSOCKET>']);
// Reconcile the stream configuration to adapt to the new configuration
await stream.reconcile();
// Start the stream again
await stream.start();Error Handling
The SDK uses standard Promise-based error handling:
try {
const headsets = await Headset.discover();
if (headsets.length === 0) {
console.log('No headsets found.');
return;
}
const headset = headsets[0];
await headset.setName('My Headset');
} catch (error) {
console.error('Error:', error.message);
}Troubleshooting
Common Issues
Cannot discover headsets
- Ensure the headset is powered on and connected to the same network
- Check firewall settings that might block UDP broadcasts (port 48010)
- Try specifying the IP address directly:
new Headset('192.168.1.100')
Stream creation fails
- Verify all UUIDs are valid
- Check that node executables exist on the headset
- Ensure pipe connections reference valid node IDs
Configuration storage fails
- Check that the key is a valid string
- Ensure the value can be properly serialized
- Verify that the expiration format is correct (e.g., "1h", "2d", "30m")
Connection timeouts
- The headset may be overloaded; try simplifying your stream
- Check network stability and latency
- Increase timeout values in API calls
Debug Mode
Enable debug mode for additional logging:
const headset = new Headset('192.168.1.100', { debug: true });