Version 1 (modified by sc, 7 years ago) (diff) |
---|
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()