An easy-to-use platform for EEG experimentation in the classroom
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Improved error handling for emotiv devices

jdpigeon 4e8f27ff 2b860634

+25 -26
+1 -3
app/epics/deviceEpics.js
··· 165 165 promise.then( 166 166 deviceInfo => deviceInfo, 167 167 error => { 168 - console.error('connectEpic: ', error); 169 168 toast.error(`"Device Error: " ${error.toString()}`); 170 - return null; 171 169 } 172 170 ) 173 171 ), 174 172 mergeMap(deviceInfo => { 175 - if (deviceInfo) { 173 + if (!isNil(deviceInfo.name)) { 176 174 return of( 177 175 setDeviceType( 178 176 deviceInfo.name.includes('Muse') ? DEVICES.MUSE : DEVICES.EMOTIV
+24 -23
app/utils/eeg/emotiv.js
··· 3 3 * an RxJS Observable of raw EEG data 4 4 * 5 5 */ 6 - import { fromEvent } from "rxjs"; 7 - import { map, withLatestFrom, share } from "rxjs/operators"; 8 - import { addInfo, epoch, bandpassFilter } from "@neurosity/pipes"; 9 - import { toast } from "react-toastify"; 10 - import { parseEmotivSignalQuality } from "./pipes"; 6 + import { fromEvent } from 'rxjs'; 7 + import { map, withLatestFrom, share } from 'rxjs/operators'; 8 + import { addInfo, epoch, bandpassFilter } from '@neurosity/pipes'; 9 + import { toast } from 'react-toastify'; 10 + import { parseEmotivSignalQuality } from './pipes'; 11 11 import { 12 12 USERNAME, 13 13 PASSWORD, 14 14 CLIENT_ID, 15 15 CLIENT_SECRET, 16 16 LICENSE_ID 17 - } from "../../../keys"; 18 - import { EMOTIV_CHANNELS, PLOTTING_INTERVAL } from "../../constants/constants"; 19 - import Cortex from "./cortex"; 17 + } from '../../../keys'; 18 + import { EMOTIV_CHANNELS, PLOTTING_INTERVAL } from '../../constants/constants'; 19 + import Cortex from './cortex'; 20 20 21 21 // Just returns the Cortex object from SDK 22 22 const verbose = process.env.LOG_LEVEL || 1; ··· 44 44 ) 45 45 .then(() => 46 46 client.createSession({ 47 - status: "active", 47 + status: 'active', 48 48 headset: device.id 49 49 }) 50 50 ) 51 - .then( 52 - session => ({ 53 - name: session.headset.id, 54 - samplingRate: session.headset.settings.eegRate, 55 - channels: EMOTIV_CHANNELS 56 - }), 57 - err => toast("Device Error: ", err) 58 - ); 51 + .then(session => ({ 52 + name: session.headset.id, 53 + samplingRate: session.headset.settings.eegRate, 54 + channels: EMOTIV_CHANNELS 55 + })) 56 + .catch(err => { 57 + toast.error(`Couldn't connect to device ${device.id}`); 58 + return err; 59 + }); 59 60 60 61 export const disconnectFromEmotiv = async () => { 61 - const sessionStatus = await client.updateSession({ status: "close" }); 62 + const sessionStatus = await client.updateSession({ status: 'close' }); 62 63 return sessionStatus; 63 64 }; 64 65 65 66 // Returns an observable that will handle both connecting to Client and providing a source of EEG data 66 67 export const createRawEmotivObservable = async () => { 67 - const subs = await client.subscribe({ streams: ["eeg", "dev"] }); 68 - if (!subs[0].eeg) throw new Error("failed to subscribe"); 69 - return fromEvent(client, "eeg").pipe(map(createEEGSample)); 68 + const subs = await client.subscribe({ streams: ['eeg', 'dev'] }); 69 + if (!subs[0].eeg) throw new Error('failed to subscribe'); 70 + return fromEvent(client, 'eeg').pipe(map(createEEGSample)); 70 71 }; 71 72 72 73 // Creates an observable that will epoch, filter, and add signal quality to EEG stream 73 74 export const createEmotivSignalQualityObservable = rawObservable => { 74 - const signalQualityObservable = fromEvent(client, "dev"); 75 + const signalQualityObservable = fromEvent(client, 'dev'); 75 76 const samplingRate = 128; 76 77 const channels = EMOTIV_CHANNELS; 77 78 const intervalSamples = (PLOTTING_INTERVAL * samplingRate) / 1000; ··· 96 97 }; 97 98 98 99 export const injectEmotivMarker = (value, time) => { 99 - client.injectMarker({ label: "event", value, time }); 100 + client.injectMarker({ label: 'event', value, time }); 100 101 }; 101 102 102 103 // ---------------------------------------------------------------------