Getting started
About the IDUN Guardian SDK
What can I do with the IDUN Guardian SDK?
The IDUN Guardian earbud can record data for a specified duration. The recording can be started and stopped programmatically, and the data can be accessed after the recording is completed. The recording duration is specified in seconds (see Start a recording).
During the recording, you can subscribe to real-time insights and predictions to get live data from the earbud. Real-time insights include raw EEG, band-passed EEG, and IMU data. Real-time predictions include jaw clench, horizontal eye movements (HEOG), Quality Score, and FFT z-scores (see Subscribe to real time insights and predictions).
In addition, you can stream data to LSL (Lab Streaming Layer) to integrate data from the earbud with other devices or software (see Stream data to LSL).
After the recording is completed, you can access the recorded data and generate reports (see Post Recording).
How do I record data with the IDUN Guardian SDK?
The main class is GuardianClient
, which provides methods to connect to the earbud, record data, and access real-time insights and predictions.
It can be initialized with the following main parameters:
Device address:
The address of the earbud you want to connect to. It has the form of 6 groups of 2 characters separated by :
, for example A1:B2:C3:D4:E5:F6
.
If not provided, the SDK will search for the earbud automatically (see Search the earbud manually).
API Token:
Your IDUN API token. This is required for any Cloud API operation, like downloading recordings or generating reports. It is a long string composed of letters and numbers, and starting with idun_
, for example idun_1abc23def456gh78ij9k0lm1nop2q3rs
.
You can set this as an environment variable or pass it as an argument to the GuardianClient constructor (see Setup your API Token).
The rest of the parameters and functionalities can be found in the class documentation.
What is the general process for recording data?
Please visit our user manual for a detailed guide on how to use the IDUN Guardian earbud.
The general process for recording data with the IDUN Guardian SDK is as follows:
Pre-recording:
Assemble the earbud.
Clean ears.
Turn the device on, put it on and let it stabilize for 10 minutes.
Measure impedance. It should be below 300 kOhms (see Check impedance values).
Check the battery level (see Check battery level).
Recording:
Prepare your recording setup.
Connect to the earbud.
If necessary, subscribe to real-time insights and predictions (see Subscribe to real time insights and predictions).
Start the recording for a specified duration (see Start a recording).
Post-recording:
Download the recording (see Download recording).
Generate reports if needed (see Generate Sleep Report for a Recording).
Pre Recording
Search the earbud manually
To search for the earbud, you need to run the following command in your Python shell or script:
import asyncio
from idun_guardian_sdk import GuardianClient
client = GuardianClient()
device_address = asyncio.run(client.search_device())
Follow the steps in the terminal to search for the earbud with the name IGEB.
If there are more than one IGEB device in the area, you will be asked to select the device you want to connect to. A list such as below will pop up in the terminal:
For Windows:
----- Available devices ----- Index | Name | Address ---------------------------- 0 | IGEB | XX:XX:XX:XX:XX:XX 1 | IGEB | XX:XX:XX:XX:XX:XX 2 | IGEB | XX:XX:XX:XX:XX:XX ----------------------------
For Mac OS:
----- Available devices ----- Index | Name | UUID ---------------------------- 0 | IGEB | XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX 1 | IGEB | XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX 2 | IGEB | XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX ----------------------------
Enter the index number of the device you want to connect to.
For the next executions, you can save the address and initialize the GuardianClient with address
parameter:
import asyncio
from idun_guardian_sdk import GuardianClient
device_address = "" # add address string here
client = GuardianClient(address=device_address)
If the address is not provided and you start connection to the device, the search_device() prompt will be automatically started.
Setup your API Token
To do any Cloud API operation you should have your IDUN API TOKEN.
You can configure the token whether by setting IDUN_API_TOKEN
Environment Variable:
export IDUN_API_TOKEN=my-api-token
or by initializing GuardianClient
object in Python with api_token
argument:
my_api_token = "xxxxxx"
client = GuardianClient(api_token=my_api_token)
Note
You can get your API Token from the IDUN team.
Check battery level
To read out the battery level, run the following command in your Python shell or script:
import asyncio
from idun_guardian_sdk import GuardianClient
client = GuardianClient()
battery_level = asyncio.run(client.check_battery())
print("Battery Level: %s%%" % battery_level)
Check impedance values
To read out the impedance values, run the following commands in your Python shell or script.
Note that stream_impedance
will run until you manually stop it by pressing Ctrl + C:
import asyncio
from idun_guardian_sdk import GuardianClient
MAINS_FREQUENCY_60Hz = False
client = GuardianClient()
asyncio.run(client.stream_impedance(mains_freq_60hz=MAINS_FREQUENCY_60Hz))
mains_freq_60hz
is a boolean parameter that sets the mains frequency to 60Hz (for the US).
If you need to start/stop streaming impedance programmatically, you can create a coroutine task:
import asyncio
from idun_guardian_sdk import GuardianClient
def print_impedance(data):
print(f"{data}\tOhm")
async def sample_task(seconds):
for i in range(seconds):
print(f"Run a sample task for: {i}/{seconds} seconds")
await asyncio.sleep(1)
async def main():
client = GuardianClient(debug=True)
await client.connect_device()
print("Starting impedance task")
task = asyncio.create_task(client.stream_impedance(handler=print_impedance))
try:
await sample_task(seconds=15)
client.stop_impedance()
await task
await client.disconnect_device()
except (KeyboardInterrupt, asyncio.CancelledError):
pass
if __name__ == "__main__":
asyncio.run(main())
Recording
Start a recording
To start a recording with a pre-defined timer, you need to provide the recording duration in seconds. For example, for a 2 hours recording, you can use the following code:
import asyncio
from idun_guardian_sdk import GuardianClient
RECORDING_TIMER = 60 * 60 * 2 # 2 hours
LED_SLEEP = False
my_api_token = "idun_xxx"
my_device_address = "XX:XX:XX:XX:XX:XX"
def print_data(event):
print("CB Func:", event.message)
client = GuardianClient(api_token=my_api_token, address=my_device_address)
asyncio.run(client.start_recording(recording_timer=RECORDING_TIMER, led_sleep=LED_SLEEP))
The default value for the recording timer is 10 hours (36000 seconds).
To stop the recording, wait for the timer or interrupt it with Ctrl+C
.
Subscribe to real time insights and predictions
With the IDUN Guardian SDK, you can subscribe to real-time insights and predictions during the recording to get real-time feedback from the earbud.
Note
The realtime predictions feature is not enabled by default. If you want to test this, get in touch with us.
Functions
To access real-time signals such as raw EEG, band-passed EEG, and IMU data, use the following function:
client.subscribe_live_insights(raw_eeg=True, filtered_eeg=True, imu=True, handler=print_data)
To receive real-time predictions, including jaw clench, horizontal eye movements (HEOG), Quality Score and FFT z-scores, use this function:
client.subscribe_realtime_predictions(fft=True, jaw_clench=True, bin_heog=True, quality_score=True, handler=print_data)
You can select the specific features to subscribe to by setting the respective boolean arguments (True
or False
).
Handler
To process real-time data, you must define a handler function and pass it as an argument to the above functions. The handler is called whenever new data is available. For example, a simple handler that prints the data might look like this:
def print_data(data):
print(data.message)
The data.message
attribute contains the subscribed data. Depending on the type of subscription:
For live insights, the handler is triggered every 20 EEG samples.
For real-time predictions, the handler is triggered:
Whenever a jaw clench or eye movement is detected.
Every second for FFT z-scores and quality score.
Message Format
Live Insights
If you subscribe to raw_eeg
, filtered_eeg
, and imu
, the message format will be:
{
"idunId": "idunId",
"deviceId": "XX:XX:XX:XX:XX:XX",
"action": "liveStreamInsights",
"sequence": int,
"imu": [
{"timestamp": time_value1, "acc_x": acc_x_value1, "acc_y": acc_y_value1, ...},
{"timestamp": time_value2, "acc_x": acc_x_value2, "acc_y": acc_y_value2, ...},
...
],
"raw_eeg": [
{"timestamp": time_value1, "ch1": eeg_value1},
{"timestamp": time_value2, "ch1": eeg_value2},
...
],
"filtered_eeg": [
{"timestamp": time_value1, "ch1": eeg_value1},
{"timestamp": time_value2, "ch1": eeg_value2},
...
]
}
The raw_eeg
and filtered_eeg
lists contain 20 dictionaries with paired timestamps and EEG values.
The imu
list contains 2 dictionaries with timestamps and IMU values (Accelerometer, Magnetometer and Gyroscope) for each axis.
Realtime Predictions
The message for real-time predictions will be:
{
"idunId": "idunId",
"deviceId": "XX:XX:XX:XX:XX:XX",
"action": "realtimePredictionsResponse",
"predictionType": "JAW_CLENCH", "BIN_HEOG", "QUALITY_SCORE", or "FFT",
"result": { ... }, # Prediction results (varies by prediction type)
"partitioningKey": "partitioningKeyString"
}
You will receive this message every time a prediction is made,
for each of the features you set to True
.
predictionType
indicates the type of prediction made,
and result
contains the prediction results.
Prediction Results format
Jaw Clench ( `JAW_CLENCH` ) Provides the timestamp of the detected jaw clench:
{ "result": 1, "timestamp": time_value }
Horizontal Eye Movements ( `BIN_HEOG` ) Provides the timestamp and the direction of the detected eye movement:
-1
for left1
for right
{ "heog": 1 or -1, "timestamp": time_value }
FFT Z-Scores ( `FFT` ) Provides the timestamp and a dictionary of z-scores for frequency bands:
{ "z-scores": [ { "Delta": delta_value, "Theta": theta_value, "Alpha": alpha_value, "Sigma": sigma_value, "Beta": beta_value, "Gamma": gamma_value } ], "timestamp": time_value }
Note
For FFT predictions, the real-time results are only available after a few minutes of recording, once the FFT z-scores stabilize.
Quality Score ( `QUALITY_SCORE` ) Provides the timestamp and the quality score:
{ "quality_score": quality_score_value, "timestamp": time_value }
Examples
You can find example scripts and use cases under Example Scripts and Demo Scripts sections.
Stream data to LSL
LSL (Lab Streaming Layer) is a system for synchronizing streaming data from different sources. It can be used to integrate data from the IDUN Guardian earbud with other devices or software.
To stream data to LSL, you need to install the pylsl library.
The process is similar to subscribing to real-time insights and predictions, but the handler function should be modified to stream the data to LSL.
Here is an example of how to stream raw EEG data to LSL:
import asyncio
from idun_guardian_sdk import GuardianClient
from pylsl import StreamInfo, StreamOutlet
device_address = "XX:XX:XX:XX:XX:XX"
my_api_token = "idun_xxx"
def stream_to_lsl(data):
message = event.message
eeg = message["raw_eeg"]
most_recent_ts = eeg[-1]["timestamp"]
data = [sample["ch1"] for sample in eeg]
lsl_outlet.push_chunk(data, most_recent_ts)
client = GuardianClient(api_token=my_api_token, address=device_address)
client.subscribe_live_insights(raw_eeg=True, handler=stream_to_lsl)
# Create LSL stream
info = StreamInfo("IDUN", "EEG", 1, 250, "float32", device_address)
outlet = StreamOutlet(info, 20, 360)
asyncio.run(client.start_recording(recording_timer=60))
Post Recording
Get all recorded info
To retrieve the list of completed recordings:
from idun_guardian_sdk import GuardianClient
client = GuardianClient()
recordings = client.get_recordings(status="COMPLETED", limit=10)
print(recordings)
Download recording
To download a specific recording:
from idun_guardian_sdk import GuardianClient, FileTypes
my_api_token = ""
my_recording_id = ""
client = GuardianClient(api_token=my_api_token)
client.download_file(recording_id=my_recording_id, file_type=FileTypes.EEG)
Generate Sleep Report for a Recording
To generate a sleep report:
from idun_guardian_sdk import GuardianClient
my_api_token = ""
my_recording_id = ""
client = GuardianClient(api_token=my_api_token)
client.generate_and_download_sleep_report(recording_id=my_recording_id)
Generate Daytime Report for a Recording
To generate a daytime report:
from idun_guardian_sdk import GuardianClient
my_api_token = ""
my_recording_id = ""
client = GuardianClient(api_token=my_api_token)
client.generate_and_download_daytime_report(recording_id=my_recording_id)