From 3914d26da9b4c8c461af12cddcc56a58f8e0eda8 Mon Sep 17 00:00:00 2001 From: tung_tung Date: Thu, 20 Aug 2026 18:17:15 +0700 Subject: [PATCH 1/3] COR-6291: support export and query record --- unity/Assets/Plugins/Emotiv-Unity-Plugin | 2 +- unity/Assets/SimpleExample.cs | 97 +- unity/Assets/SimpleExample.unity | 2107 +++++++++++++++++++--- 3 files changed, 1907 insertions(+), 299 deletions(-) diff --git a/unity/Assets/Plugins/Emotiv-Unity-Plugin b/unity/Assets/Plugins/Emotiv-Unity-Plugin index 245f4e0..e720b9b 160000 --- a/unity/Assets/Plugins/Emotiv-Unity-Plugin +++ b/unity/Assets/Plugins/Emotiv-Unity-Plugin @@ -1 +1 @@ -Subproject commit 245f4e0b1a75c19fb70cc3d93846152fb1d5fb33 +Subproject commit e720b9be98b079fa58d4509c25410f3687bfd7eb diff --git a/unity/Assets/SimpleExample.cs b/unity/Assets/SimpleExample.cs index 53ed419..d80050c 100644 --- a/unity/Assets/SimpleExample.cs +++ b/unity/Assets/SimpleExample.cs @@ -5,6 +5,7 @@ using UnityEngine.UI; using System; using System.Threading.Tasks; +using Newtonsoft.Json.Linq; #if UNITY_ANDROID using UnityEngine.Android; @@ -16,6 +17,7 @@ public class SimpleExample : MonoBehaviour EmotivUnityItf _eItf = EmotivUnityItf.Instance; float _timerDataUpdate = 0; const float TIME_UPDATE_DATA = 1f; + private string _lastMessageLog = ""; // tracks last displayed _eItf.MessageLog to avoid overwriting manual MessageLog updates [SerializeField] public InputField HeadsetId; // headsetId [SerializeField] public InputField RecordTitle; // record Title @@ -36,16 +38,9 @@ public class SimpleExample : MonoBehaviour [SerializeField] public Toggle FEToggle; [SerializeField] public Toggle SYSToggle; - [SerializeField] public Text MessageLog; - - // Enable horizontal wrapping for MessageLog - private void Awake() - { - if (MessageLog != null) - { - MessageLog.horizontalOverflow = HorizontalWrapMode.Wrap; - } - } + [SerializeField] public InputField MessageLog; + // recordid for export record + [SerializeField] public InputField RecordId; // record id for export record // for android #if UNITY_ANDROID @@ -188,8 +183,12 @@ void Update() // Check buttons interactable CheckButtonsInteractable(); - // Display message log - MessageLog.text = _eItf.MessageLog; + // Display message log only when it has changed + if (_eItf.MessageLog != _lastMessageLog) + { + _lastMessageLog = _eItf.MessageLog; + MessageLog.text = _eItf.MessageLog; + } // Demo how to get detected headset lists // List detectedHeadsets = _eItf.GetDetectedHeadsets(); @@ -210,7 +209,7 @@ void Update() // eegDataStr += "null, "; // for null value // } // string msgLog = eegHeaderStr + "\n" + eegDataStr; - // MessageLog.text = msgLog; + // msgLogTextField.text = msgLog; // } // Demo how to get cq data @@ -280,13 +279,13 @@ public void onStopRecordBtnClick() { } // export record to desktop - public void onExportRecordBtnClick() + public async void onExportRecordBtnClick() { Debug.Log("onExportRecordBtnClick"); - string _recordId = _eItf.RecentRecord?.Uuid; + string _recordId = RecordId.text; if (string.IsNullOrEmpty(_recordId)) { - UnityEngine.Debug.Log("The recordId is empty. Please export with a valid recordId."); + UnityEngine.Debug.LogError("The recordId must not be empty. Please export with a valid recordId."); return; } @@ -308,9 +307,71 @@ public void onExportRecordBtnClick() List streamTypes = new List { "EEG", "MOTION" }; // Specify the stream types you want to export string format = "CSV"; // or "CSV", "EDFPLUS", "BDFPLUS" string version = "V2"; // Optional, specify if needed - _eItf.ExportRecord(recordsToExport, folderPath, streamTypes, format, version); + + try + { + string licenseId = "licenseid-link-record"; // Replace with your actual license ID + ExportRecordResult result = await _eItf.ExportRecordAsync(recordsToExport, folderPath, streamTypes, format, version, new List { licenseId }); + + string msgLog = "Export records - success: " + result.SuccessRecordIds.Count + ", failed: " + result.FailedRecords.Count + "\n"; + foreach (string recordId in result.SuccessRecordIds) + { + msgLog += "Success: " + recordId + "\n"; + } + foreach (ExportRecordFailure failure in result.FailedRecords) + { + msgLog += "Failed: " + failure.RecordId + " (code " + failure.Code + "): " + failure.Message + "\n"; + } + MessageLog.text = msgLog; + } + catch (Exception ex) + { + UnityEngine.Debug.LogError("onExportRecordBtnClick failed: " + ex.Message); + MessageLog.text = "Export records failed: " + ex.Message; + } } + // query records with a startDatetime range + public async void onQueryRecordBtnClick() + { + Debug.Log("onQueryRecordBtnClick"); + JObject query = new JObject( + new JProperty("startDatetime", new JObject( + new JProperty("from", "2026-01-06T16:32:50.572490+07:00"), + new JProperty("to", "2026-08-06T16:32:50.572490+07:00") + )) + ); + + // demo to query with keywords + // JObject query = new JObject( + // new JProperty("keyword", "123abc") + // ); + + // demo to query by license and application + // JObject query = new JObject( + // new JProperty("applicationId", "applicationId-of-app-create-record"), // If you set the licenseId, then you can set this parameter to further filter the records by application. + // new JProperty("licenseId", "licenseid-link-record") // Set this parameter to filter the records by their license. + // ); + + try + { + List records = await _eItf.QueryRecords(query, null, 100, 0, true, true); + + string msgLog = "Query records: found " + records.Count + " record(s).\n"; + foreach (Record record in records) + { + msgLog += "RecordId: " + record.Uuid + ", Title: " + record.Title + ", StartTime: " + record.StartDateTime + + ", EndTime: " + record.EndDateTime + ", SyncStatus: " + record.SyncStatus + "\n"; + } + MessageLog.text = msgLog; + } + catch (Exception ex) + { + UnityEngine.Debug.LogError("onQueryRecordBtnClick failed: " + ex.Message); + MessageLog.text = "Query records failed: " + ex.Message; + } + } + public void onInjectMarkerBtnClick() { Debug.Log("onInjectMarkerBtnClick " + MarkerValue.text + ":" + MarkerLabel.text); @@ -446,12 +507,14 @@ private void CheckButtonsInteractable() Button stopRecordBtn = GameObject.Find("RecordPart").transform.Find("stopRecordBtn").GetComponent