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:

  1. 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).

  2. Recording:

  3. Post-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 left

    • 1 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)