Skip to content

Commit 068b598

Browse files
authored
COR-5318: update export feature for csharp and some readme (#233)
* COR-5318: update export feature and readme for csharp * COR-5687: update readme for unity example * COR-5687: update rework for unity readme
1 parent 452e9e5 commit 068b598

File tree

14 files changed

+416
-190
lines changed

14 files changed

+416
-190
lines changed

csharp/CortexAccess/Config.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ static class Config
77
* account on emotiv.com and create a Cortex app.
88
* https://www.emotiv.com/my-account/cortex-apps/
99
*/
10-
public static string AppClientId = "The client id of your Cortex app goes here";
11-
public static string AppClientSecret = "The client secret of your Cortex app goes here";
10+
public static string AppClientId = "put_your_application_client_id_here";
11+
public static string AppClientSecret = "put_your_application_client_secret_here";
1212

1313
// If you use an Epoc Flex headset, then you must put your configuration here
1414
public static string FlexMapping = @"{
@@ -38,6 +38,7 @@ public static class WarningCode
3838
public const int UserLoginOnAnotherOsUser = 16;
3939
public const int EULAAccepted = 17;
4040
public const int StreamWritingClosed = 18;
41+
public const int DataPostProcessingFinished = 30;
4142
public const int HeadsetWrongInformation = 100;
4243
public const int HeadsetCannotConnected = 101;
4344
public const int HeadsetConnectingTimeout = 102;

csharp/CortexAccess/CtxClient.cs

Lines changed: 94 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ public sealed class CortexClient
117117
public event EventHandler<Record> OnUpdateRecord;
118118
public event EventHandler<List<Record>> OnQueryRecords;
119119
public event EventHandler<MultipleResultEventArgs> OnDeleteRecords;
120+
public event EventHandler<MultipleResultEventArgs> ExportRecordsFinished;
120121
public event EventHandler<JObject> OnInjectMarker;
121122
public event EventHandler<JObject> OnUpdateMarker;
122123
public event EventHandler<JObject> OnGetDetectionInfo;
@@ -133,6 +134,7 @@ public sealed class CortexClient
133134
public event EventHandler<string> SessionClosedNotify;
134135
public event EventHandler<HeadsetConnectEventArgs> HeadsetConnectNotify;
135136
public event EventHandler<string> HeadsetScanFinished;
137+
public event EventHandler<string> DataPostProcessingFinished;
136138

137139
// Constructor
138140
static CortexClient()
@@ -425,72 +427,72 @@ private void HandleResponse(string method, JToken data)
425427
{
426428
OnGetTrainingTime(this, (double)data["time"]);
427429
}
430+
// export record
431+
else if (method == "exportRecord")
432+
{
433+
JArray successList = (JArray)data["success"];
434+
JArray failList = (JArray)data["failure"];
435+
ExportRecordsFinished(this, new MultipleResultEventArgs(successList, failList));
436+
}
428437

429438
}
430439

431440
// handle warning response
432441
private void HandleWarning(int code, JToken messageData)
433442
{
434443
Console.WriteLine("handleWarning: " + code);
435-
if (code == WarningCode.AccessRightGranted)
444+
switch (code)
436445
{
437-
// granted access right
446+
case WarningCode.AccessRightGranted:
438447
OnAccessRightGranted(this, true);
439-
}
440-
else if (code == WarningCode.AccessRightRejected)
441-
{
448+
break;
449+
case WarningCode.AccessRightRejected:
442450
OnAccessRightGranted(this, false);
443-
}
444-
else if (code == WarningCode.EULAAccepted)
445-
{
451+
break;
452+
case WarningCode.EULAAccepted:
446453
OnEULAAccepted(this, true);
447-
}
448-
else if (code == WarningCode.UserLogin)
449-
{
450-
string message = messageData.ToString();
451-
OnUserLogin(this, message);
452-
}
453-
else if (code == WarningCode.UserLogout)
454-
{
455-
string message = messageData.ToString();
456-
OnUserLogout(this, message);
457-
}
458-
else if (code == WarningCode.HeadsetScanFinished)
459-
{
460-
string message = messageData["behavior"].ToString();
461-
HeadsetScanFinished(this, message);
462-
}
463-
else if (code == WarningCode.StreamStop)
464-
{
465-
string sessionId = messageData["sessionId"].ToString();
466-
SessionClosedNotify(this, sessionId);
467-
}
468-
else if (code == WarningCode.SessionAutoClosed)
469-
{
470-
string sessionId = messageData["sessionId"].ToString();
471-
SessionClosedNotify(this, sessionId);
472-
}
473-
else if (code == WarningCode.HeadsetConnected)
474-
{
454+
break;
455+
case WarningCode.UserLogin:
456+
OnUserLogin(this, messageData.ToString());
457+
break;
458+
case WarningCode.UserLogout:
459+
OnUserLogout(this, messageData.ToString());
460+
break;
461+
case WarningCode.HeadsetScanFinished:
462+
HeadsetScanFinished(this, messageData["behavior"].ToString());
463+
break;
464+
case WarningCode.StreamStop:
465+
case WarningCode.SessionAutoClosed:
466+
SessionClosedNotify(this, messageData["sessionId"].ToString());
467+
break;
468+
case WarningCode.HeadsetConnected:
469+
{
475470
string headsetId = messageData["headsetId"].ToString();
476471
string message = messageData["behavior"].ToString();
477472
Console.WriteLine("handleWarning:" + message);
478473
HeadsetConnectNotify(this, new HeadsetConnectEventArgs(true, message, headsetId));
479-
}
480-
else if (code == WarningCode.HeadsetWrongInformation ||
481-
code == WarningCode.HeadsetCannotConnected ||
482-
code == WarningCode.HeadsetConnectingTimeout)
483-
{
474+
break;
475+
}
476+
case WarningCode.HeadsetWrongInformation:
477+
case WarningCode.HeadsetCannotConnected:
478+
case WarningCode.HeadsetConnectingTimeout:
479+
{
484480
string headsetId = messageData["headsetId"].ToString();
485481
string message = messageData["behavior"].ToString();
486482
HeadsetConnectNotify(this, new HeadsetConnectEventArgs(false, message, headsetId));
487-
}
488-
else if (code == WarningCode.CortexAutoUnloadProfile)
489-
{
490-
// the current profile is unloaded automatically
483+
break;
484+
}
485+
case WarningCode.CortexAutoUnloadProfile:
491486
OnUnloadProfile(this, true);
487+
break;
488+
case WarningCode.DataPostProcessingFinished:
489+
Console.WriteLine("Data post processing finished");
490+
DataPostProcessingFinished(this, messageData["recordId"].ToString());
491+
break;
492+
default:
493+
Console.WriteLine("Warning code: " + code + ", message: " + messageData.ToString());
494+
break;
492495
}
493-
494496
}
495497
private void WebSocketClient_Closed(object sender, EventArgs e)
496498
{
@@ -726,6 +728,52 @@ public void DeleteRecord(string cortexToken, List<string> records)
726728
SendTextMessage(param, "deleteRecord", true);
727729
}
728730

731+
// Export Records
732+
// Required params: cortexToken, records, folderPath, streamTypes, format
733+
public void ExportRecord(string cortexToken, List<string> records, string folderPath,
734+
List<string> streamTypes, string format, string version = null,
735+
List<string> licenseIds = null, bool includeDemographics = false,
736+
bool includeMarkerExtraInfos = false, bool includeSurvey = false,
737+
bool includeDeprecatedPM = false)
738+
{
739+
JObject param = new JObject();
740+
param.Add("recordIds", JArray.FromObject(records));
741+
param.Add("cortexToken", cortexToken);
742+
param.Add("folder", folderPath);
743+
param.Add("streamTypes", JArray.FromObject(streamTypes));
744+
param.Add("format", format); // EDF, CSV, EDFPLUS, BDFPLUS
745+
746+
// If the format is "EDF", then you must omit version parameter.
747+
// If the format is "CSV", then version parameter must be "V1" or "V2".
748+
if (version != null)
749+
{
750+
param.Add("version", version);
751+
}
752+
if (licenseIds != null)
753+
{
754+
param.Add("licenseIds", JArray.FromObject(licenseIds));
755+
}
756+
757+
if (includeDemographics)
758+
{
759+
param.Add("includeDemographics", includeDemographics);
760+
}
761+
if (includeMarkerExtraInfos)
762+
{
763+
param.Add("includeMarkerExtraInfos", includeMarkerExtraInfos);
764+
}
765+
if (includeSurvey)
766+
{
767+
param.Add("includeSurvey", includeSurvey);
768+
}
769+
if (includeDeprecatedPM)
770+
{
771+
param.Add("includeDeprecatedPM", includeDeprecatedPM);
772+
}
773+
774+
SendTextMessage(param, "exportRecord", true);
775+
}
776+
729777
// InjectMarker
730778
// Required params: session, cortexToken, label, value, time
731779
public void InjectMarker(string cortexToken, string sessionId, string label, JToken value, double time, string port = null)

csharp/CortexAccess/DataStreamExample.cs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,23 +194,37 @@ private void MessageErrorRecieved(object sender, ErrorMsgEventArgs e)
194194
Console.WriteLine("MessageErrorRecieved :code " + e.Code + " message " + e.MessageError);
195195
}
196196

197-
// set Streams
197+
/// <summary>
198+
/// Add a data stream to the subscription list.
199+
/// Call this before Start().
200+
/// Example: AddStreams("eeg"), AddStreams("mot"), etc.
201+
/// </summary>
202+
/// <param name="stream">Stream name (e.g., "eeg", "mot", "pow", "met")</param>
198203
public void AddStreams(string stream)
199204
{
200205
if (!_streams.Contains(stream))
201206
{
202207
_streams.Add(stream);
203208
}
204209
}
205-
// start
210+
/// <summary>
211+
/// Start the workflow: authorization, headset finding, session creation, and data stream subscription.
212+
/// You must call AddStreams() for each stream you want to subscribe before calling Start().
213+
/// </summary>
214+
/// <param name="licenseID">(Obsolete) This parameter is kept for backward compatibility. Always set to empty string "".</param>
215+
/// <param name="activeSession">True to use a license-required session (needed for EEG, high performance metrics, etc.)</param>
216+
/// <param name="wantedHeadsetId">Specify headset ID to connect (default: first headset found)</param>
206217
public void Start(string licenseID="", bool activeSession = false, string wantedHeadsetId = "")
207218
{
208219
_wantedHeadsetId = wantedHeadsetId;
209220
_isActiveSession = activeSession;
210221
_authorizer.Start(licenseID);
211222
}
212223

213-
// Unsubscribe
224+
/// <summary>
225+
/// Unsubscribe from data streams. If no streams are specified, unsubscribes from all currently subscribed streams.
226+
/// </summary>
227+
/// <param name="streams">List of stream names to unsubscribe (optional)</param>
214228
public void UnSubscribe(List<string> streams = null)
215229
{
216230
if (streams == null)

csharp/CortexAccess/HeadsetFinder.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66

77
namespace CortexAccess
88
{
9+
/// <summary>
10+
/// HeadsetFinder is a utility class for scanning, querying, and connecting to Emotiv headsets.
11+
/// Use FindHeadset(headsetId) to start a timer to query headset and set desired headset. The class starts a timer to repeatedly query headsets until a connection is established.
12+
/// </summary>
913
public class HeadsetFinder
1014
{
1115
private CortexClient _ctxClient;

0 commit comments

Comments
 (0)