wiki:ProtocolEmotiv

Protocol: Emotiv

  • Taken from Puzzlebox Jigsaw

Code highlighting:

# -*- coding: utf-8 -*-

# Copyright Puzzlebox Productions, LLC (2012)

__changelog__ = """\
Last Update: 2012.04.03
"""

import time

#####################################################################
# Headers
#####################################################################

cdef extern from "edk.h":
        ctypedef void* EmoEngineEventHandle
        ctypedef void* EmoStateHandle
        
        ctypedef enum EE_Event_t:
                EE_UnknownEvent         = 0x0000,
                EE_EmulatorError        = 0x0001,
                EE_ReservedEvent        = 0x0002,
                EE_UserAdded            = 0x0010,
                EE_UserRemoved          = 0x0020,
                EE_EmoStateUpdated      = 0x0040,
                EE_ProfileEvent         = 0x0080,
                EE_CognitivEvent        = 0x0100,
                EE_ExpressivEvent       = 0x0200,
                EE_InternalStateChanged = 0x0400,
                EE_AllEvent             = EE_UserAdded | EE_UserRemoved | EE_EmoStateUpdated | EE_ProfileEvent | EE_CognitivEvent | EE_ExpressivEvent | EE_InternalStateChanged
        
        ctypedef enum EE_ExpressivAlgo_t:
                EXP_NEUTRAL     = 0x0001,
                EXP_BLINK       = 0x0002,
                EXP_WINK_LEFT   = 0x0004,
                EXP_WINK_RIGHT  = 0x0008,
                EXP_HORIEYE     = 0x0010,
                EXP_EYEBROW     = 0x0020,
                EXP_FURROW      = 0x0040,
                EXP_SMILE       = 0x0080,
                EXP_CLENCH      = 0x0100,
                EXP_LAUGH       = 0x0200,
                EXP_SMIRK_LEFT  = 0x0400,
                EXP_SMIRK_RIGHT = 0x0800
        
        ctypedef enum EE_CognitivAction_t:
                COG_NEUTRAL                  = 0x0001,
                COG_PUSH                     = 0x0002,
                COG_PULL                     = 0x0004,
                COG_LIFT                     = 0x0008,
                COG_DROP                     = 0x0010,
                COG_LEFT                     = 0x0020,
                COG_RIGHT                    = 0x0040,
                COG_ROTATE_LEFT              = 0x0080,
                COG_ROTATE_RIGHT             = 0x0100,
                COG_ROTATE_CLOCKWISE         = 0x0200,
                COG_ROTATE_COUNTER_CLOCKWISE = 0x0400,
                COG_ROTATE_FORWARDS          = 0x0800,
                COG_ROTATE_REVERSE           = 0x1000,
                COG_DISAPPEAR                = 0x2000
        
        cdef int EE_EngineRemoteConnect(char* szHost, unsigned short port)
        cdef int EE_EngineGetNextEvent(EmoEngineEventHandle hEvent)
        cdef EmoEngineEventHandle EE_EmoEngineEventCreate()
        cdef EmoStateHandle EE_EmoStateCreate()
        
        cdef int EE_EngineDisconnect()
        cdef void EE_EmoStateFree(EmoStateHandle state)
        cdef void EE_EmoEngineEventFree(EmoEngineEventHandle hEvent)
        
        cdef EE_Event_t EE_EmoEngineEventGetType(EmoEngineEventHandle hEvent)
        cdef int EE_EmoEngineEventGetUserId(EmoEngineEventHandle hEvent, unsigned int *pUserIdOut)
        cdef int EE_EmoEngineEventGetEmoState(EmoEngineEventHandle hEvent, EmoStateHandle hEmoState)
        
        cdef float ES_GetTimeFromStart(EmoStateHandle state)
        cdef int ES_GetHeadsetOn(EmoStateHandle state)
        cdef int ES_GetNumContactQualityChannels(EmoStateHandle state)
        cdef int ES_GetContactQualityFromAllChannels(EmoStateHandle state)
        cdef int ES_GetWirelessSignalStatus(EmoStateHandle state)
        cdef void* ES_GetBatteryChargeLevel(EmoStateHandle state)
        
        cdef EE_ExpressivAlgo_t EE_ExpressivEventGetType(EmoStateHandle state)
        
        cdef float ES_AffectivGetExcitementShortTermScore(EmoStateHandle state)
        cdef float ES_AffectivGetExcitementLongTermScore(EmoStateHandle state)
        cdef float ES_AffectivGetMeditationScore(EmoStateHandle state)
        cdef float ES_AffectivGetFrustrationScore(EmoStateHandle state)
        cdef float ES_AffectivGetEngagementBoredomScore(EmoStateHandle state)
        
        cdef EE_CognitivAction_t ES_CognitivGetCurrentAction(EmoStateHandle state)
        cdef float ES_CognitivGetCurrentActionPower(EmoStateHandle state)


EDK_ERROR_CODES = {
        'EDK_OK': 0x0000, # Default success value
        'EDK_UNKNOWN_ERROR': 0x0001, #An internal error occurred
        'EDK_INVALID_DEV_ID_ERROR': 0x0002, #Invalid Developer ID
        'EDK_INVALID_PROFILE_ARCHIVE': 0x0101, #The contents of the buffer supplied to EE_SetUserProfile aren't a valid, serialized EmoEngine profile.
        'EDK_NO_USER_FOR_BASEPROFILE': 0x0102, #Returned from EE_EmoEngineEventGetUserId if the event supplied contains a base profile (which isn't associated with specific user).
        'EDK_CANNOT_ACQUIRE_DATA': 0x0200, #The EmoEngine is unable to acquire EEG data for processing.
        'EDK_BUFFER_TOO_SMALL': 0x0300, #The buffer supplied to the function isn't large enough
        'EDK_OUT_OF_RANGE': 0x0301, #A parameter supplied to the function is out of range
        'EDK_INVALID_PARAMETER': 0x0302, #One of the parameters supplied to the function is invalid
        'EDK_PARAMETER_LOCKED': 0x0303, #The parameter value is currently locked by a running detection and cannot be modified at this time.
        'EDK_COG_INVALID_TRAINING_ACTION': 0x0304, #The current training action is not in the list of expected training actions
        'EDK_COG_INVALID_TRAINING_CONTROL': 0x0305, #The current training control is not in the list of expected training controls
        'EDK_COG_INVALID_ACTIVE_ACTION': 0x0306, #One of the field in the action bits vector is invalid
        'EDK_COG_EXCESS_MAX_ACTIONS': 0x0307, #The current action bits vector contains more action types than it is allowed
        'EDK_EXP_NO_SIG_AVAILABLE': 0x0308, #A trained signature is not currently available for use - addition actions (including neutral) may be required
        'EDK_FILESYSTEM_ERROR': 0x0309, #A filesystem error occurred that prevented the function from succeeding
        'EDK_INVALID_USER_ID': 0x0400, #The user ID supplied to the function is invalid
        'EDK_EMOENGINE_UNINITIALIZED': 0x0500, #The EDK needs to be initialized via EE_EngineConnect or EE_EngineRemoteConnect
        'EDK_EMOENGINE_DISCONNECTED': 0x0501, #The connection with a remote instance of the EmoEngine (made via EE_EngineRemoteConnect) has been lost
        'EDK_EMOENGINE_PROXY_ERROR': 0x0502, #The API was unable to establish a connection with a remote instance of the EmoEngine.
        'EDK_NO_EVENT': 0x0600, #There are no new EmoEngine events at this time
        'EDK_GYRO_NOT_CALIBRATED': 0x0700, #The gyro is not calibrated. Ask the user to stay still for at least 0.5s
        'EDK_OPTIMIZATION_IS_ON': 0x0800, #Operation failure due to optimization
        'EDK_RESERVED1': 0x0900, #Reserved return value
}

EE_AffectivAlgo = {
        'AFF_EXCITEMENT': 0x0001, \
        'AFF_MEDITATION': 0x0002, \
        'AFF_FRUSTRATION': 0x0004, \
        'AFF_ENGAGEMENT_BOREDOM': 0x0008
}

EE_CognitivAction = {
        'COG_NEUTRAL': 0x0001, \
        'COG_PUSH': 0x0002, \
        'COG_PULL': 0x0004, \
        'COG_LIFT': 0x0008, \
        'COG_DROP': 0x0010, \
        'COG_LEFT': 0x0020, \
        'COG_RIGHT': 0x0040, \
        'COG_ROTATE_LEFT': 0x0080, \
        'COG_ROTATE_RIGHT': 0x0100, \
        'COG_ROTATE_CLOCKWISE': 0x0200, \
        'COG_ROTATE_COUNTER_CLOCKWISE': 0x0400, \
        'COG_ROTATE_FORWARDS': 0x0800, \
        'COG_ROTATE_REVERSE': 0x1000, \
        'COG_DISAPPEAR': 0x2000
}

EE_EEG_ContactQuality = [
        'EEG_CQ_NO_SIGNAL', \
        'EEG_CQ_VERY_BAD', \
        'EEG_CQ_POOR', \
        'EEG_CQ_FAIR',
        'EEG_CQ_GOOD'
]

EE_Event = {
        'EE_UnknownEvent'         : 0x0000,
        'EE_EmulatorError'        : 0x0001,
        'EE_ReservedEvent'        : 0x0002,
        'EE_UserAdded'            : 0x0010,
        'EE_UserRemoved'          : 0x0020,
        'EE_EmoStateUpdated'      : 0x0040,
        'EE_ProfileEvent'         : 0x0080,
        'EE_CognitivEvent'        : 0x0100,
        'EE_ExpressivEvent'       : 0x0200,
        'EE_InternalStateChanged' : 0x0400,
        'EE_AllEvent'             : EE_UserAdded | EE_UserRemoved | EE_EmoStateUpdated | EE_ProfileEvent | EE_CognitivEvent | EE_ExpressivEvent | EE_InternalStateChanged,
}

EE_CognitivAction = {
        'COG_NEUTRAL':                  0x0001,
        'COG_PUSH':                     0x0002,
        'COG_PULL':                     0x0004,
        'COG_LIFT':                     0x0008,
        'COG_DROP':                     0x0010,
        'COG_LEFT':                     0x0020,
        'COG_RIGHT':                    0x0040,
        'COG_ROTATE_LEFT':              0x0080,
        'COG_ROTATE_RIGHT':             0x0100,
        'COG_ROTATE_CLOCKWISE':         0x0200,
        'COG_ROTATE_COUNTER_CLOCKWISE': 0x0400,
        'COG_ROTATE_FORWARDS':          0x0800,
        'COG_ROTATE_REVERSE':           0x1000,
        'COG_DISAPPEAR':                0x2000,
}

#####################################################################
# Globals
#####################################################################

DEBUG = 1

#UserID = 0

EMOTIV_SERVER_HOST = '127.0.0.1'
EMOTIV_SERVER_PORT_CONTROL_PANEL = 3008
EMOTIV_SERVER_PORT_EMOCOMPOSER = 1726

MINIMUM_SLEEP_BETWEEN_PACKETS = 0.10

CONNECTED = False
KEEP_RUNNING = True

#####################################################################
# Classes
#####################################################################

#####################################################################
# Functions
#####################################################################

def printPacket(packet):
        
        print
        print
        print "INFO [Emotiv]: Packet Received:"
        for group in packet.keys():
                for key in packet[group].keys():
                        print '[%s][%s]:' % (group, key),
                        if type(packet[group][key]) == type(0.0):
                                print '%.2f' % packet[group][key]
                        else:
                                print packet[group][key]


#####################################################################

def start(host=EMOTIV_SERVER_HOST, \
          port=EMOTIV_SERVER_PORT_CONTROL_PANEL, \
          initialized=True, \
          parent=None):
        
        if not initialized:
                
                result = EE_EngineRemoteConnect(host, port)
                
                CONNECTED = True
        
        
        eEvent = EE_EmoEngineEventCreate()
        eState = EE_EmoStateCreate()
        
        
        while KEEP_RUNNING:
                
                state = EE_EngineGetNextEvent(eEvent)
                
                # New event needs to be handled
                if (state == EDK_ERROR_CODES['EDK_OK']):
                        
                        eventType = EE_EmoEngineEventGetType(eEvent)
                        #EE_EmoEngineEventGetUserId(eEvent, &userID)
                        
                        # Log the EmoState if it has been updated
                        if (eventType == EE_Event['EE_EmoStateUpdated']):
                        
                                result = EE_EmoEngineEventGetEmoState(eEvent, eState)
                                
                                packet = {}
                                
                                packet['timestamp'] = time.time()
                                
                                # Headset Status
                                time_from_start = ES_GetTimeFromStart(eState)
                                headset_on = (ES_GetHeadsetOn(eState))
                                contact_number_of_quality_channels = ES_GetNumContactQualityChannels(eState)
                                #contact_quality_from_all_channels = ES_GetContactQualityFromAllChannels(eState)
                                wireless_signal_status = ES_GetWirelessSignalStatus(eState)
                                #battery = ES_GetBatteryChargeLevel(eState)
                                
                                packet['emotivStatus'] = {}
                                packet['emotivStatus']['timeFromStart'] = time_from_start
                                packet['emotivStatus']['headsetOn'] = headset_on
                                packet['emotivStatus']['contactNumberOfQualityChannels'] = contact_number_of_quality_channels
                                #packet['emotiv_status']['contact_quality_from_all_channels'] = contact_quality_from_all_channels
                                packet['emotivStatus']['wireless'] = wireless_signal_status
                                #packet['emotiv_status']['battery'] = battery
                                
                                
                                # Expressiv Suite
                                packet['expressiv'] = {}
                                packet['expressiv']['currentAction'] = EE_ExpressivEventGetType(eState)
                                
                                
                                # Affectiv Suite
                                excitement = ES_AffectivGetExcitementShortTermScore(eState)
                                excitement_long_term = ES_AffectivGetExcitementLongTermScore(eState)
                                meditation = ES_AffectivGetMeditationScore(eState)
                                frustration = ES_AffectivGetFrustrationScore(eState)
                                engagement_boredom = ES_AffectivGetEngagementBoredomScore(eState)
                                
                                packet['affectiv'] = {}
                                packet['affectiv']['excitement'] = excitement
                                packet['affectiv']['longTermExcitement'] = excitement_long_term
                                packet['affectiv']['meditation'] = meditation
                                packet['affectiv']['frustration'] = frustration
                                packet['affectiv']['engagementBoredom'] = engagement_boredom
                                
                                
                                # Cognitiv Suite
                                current_action = ES_CognitivGetCurrentAction(eState)
                                current_action_power = ES_CognitivGetCurrentActionPower(eState)
                                
                                packet['cognitiv'] = {}
                                packet['cognitiv']['currentAction'] = current_action
                                packet['cognitiv']['currentActionPower'] = current_action_power
                                
                                
                                if DEBUG > 2:
                                        printPacket(packet)
                                
                                
                                # Pass the packet up to the parent object
                                if parent != None:
                                        parent.processPacketEmotiv(packet)
                
                
                time.sleep(MINIMUM_SLEEP_BETWEEN_PACKETS)
        
        
        # no longer "KEEP_RUNNING"
        
        if DEBUG:
                print "INFO [Synapse:Emotiv:Protocol] Disconnecting from Emotiv Engine"
        
        result = EE_EngineDisconnect()
        EE_EmoStateFree(eState)
        EE_EmoEngineEventFree(eEvent)
        
        CONNECTED = False


#####################################################################
# Main
#####################################################################

if __name__ == '__main__':
        start()
Last modified 6 years ago Last modified on 09/19/13 15:41:04