Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Protocol Advice #42

Open
xloem opened this issue Dec 11, 2020 · 8 comments
Open

Protocol Advice #42

xloem opened this issue Dec 11, 2020 · 8 comments

Comments

@xloem
Copy link

xloem commented Dec 11, 2020

Is anyone discussing how to code for these devices anywhere? Would this wiki be a place?

I'm trying to manually access my Muse S and I keep getting access error reading from the gatt data, or trying to bond. What am I missing?

@xloem
Copy link
Author

xloem commented Dec 11, 2020

I think I figured it out enough to use it eventually.

It looks like the Muse 2 and Muse S are BTLE devices. They dont' need pairing. They expose GATT characteristics under the primary service 0000fe8d-0000-1000-8000-00805f9b34fb . The control GATT characteristic has UUID 273e0001-4c4d-454d-96be-f03bac821358 and acts like a serial port. Data is available as property change notifications in dbus on linux, but not as raw reads to the value. Bytes are written to the serial port as an array, first the length of a command as a byte, then each ascii character.

Some commands are, from muse-js:
'p20\n': set to aux-enabled preset
'p21\n': set to aux-disabled preset
's\n': save preset?
'h\n': pause
'd\n': resume
'v1\n': get device info (encoded data available as control value changes)

Data is streamed out via 'Value' property changes once the resume command is sent, i.e. the 3 bytes '\x03d\n'.

characteristics seem to be:
CONTROL_CHARACTERISTIC = '273e0001-4c4d-454d-96be-f03bac821358'
BATTERY_CHARACTERISTIC = '273e000b-4c4d-454d-96be-f03bac821358';
GYROSCOPE_CHARACTERISTIC = '273e0009-4c4d-454d-96be-f03bac821358';
ACCELEROMETER_CHARACTERISTIC = '273e000a-4c4d-454d-96be-f03bac821358';
EEG_CHARACTERISTICS = {
'TP9': '273e0003-4c4d-454d-96be-f03bac821358',
'AF7': '273e0004-4c4d-454d-96be-f03bac821358',
'AF8': '273e0005-4c4d-454d-96be-f03bac821358',
'TP10': '273e0006-4c4d-454d-96be-f03bac821358',
'AUX': '273e0007-4c4d-454d-96be-f03bac821358',
}

These are more fully enumerated in the muse-lsl source code and at Enigma644/ix-muse-player#1 (comment) .

@xloem
Copy link
Author

xloem commented Dec 11, 2020

I can't figure out where the gyroscope multiplier comes from. Where would I find what IMU the Muse 2 uses?

@xloem
Copy link
Author

xloem commented Dec 12, 2020

presets:

   'p10', # muse 1, 2014, 2016
   'p12',
   'p14',
   'p20', # muse 2, muse S
   'p21',
   'p22',
   'p23',
   'p31', # unknown, maybe muse 1?
   'p32',
   'p50', # these all worked on my muse S
   'p51',
   'p52',
   'p53',   # this one places it into a different runstate, maybe bootloaderish.  the led blnks on and off
   'p60',
   'p61',
   'p63',
   'pAB', # muse 1, reseach
   'pAD',

data channels (one for each gatt uuid):

    # i'm not sure these names have the right numbers
    # the presets are associated with the numbers, not the names, on my Muse S
    'SERIAL': 1,
    # packets start with a 16-bit sequence number
    # eeg signals are all 12-bit numbers concatenated together
    'SIGNAL_AUX_LEFT': 2,  #                                              p63
    'SIGNAL_TP9': 3,       # p20, p21, p22, p23, p50, p51, p52, p60, p61, p63
    'SIGNAL_FP1': 4,       # p20, p21, p22, p23, p50, p51, p52, p60, p61, p63
    'SIGNAL_FP2': 5,       # p20, p21, p22, p23, p50, p51, p52, p60, p61, p63
    'SIGNAL_TP10': 6,      # p20, p21, p22, p23, p50, p51, p52, p60, p61, p63
    'SIGNAL_AUX_RIGHT': 7, # p20            p23  p50            p60       p63
    'DRL_REF': 8,          # p20  p21  p22  p23  p50  p51  p52  p60  p61  p63
    # imu data is sent as 16-bit numbers, 3 3-axis vectors at a time
    'GYRO': 9,             # p20  p21            p50  p51       p60  p61  p63
    'ACCELEROMETER': 0xa,  # p20  p21            p50  p51       p60  p61  p63
    # battery packet format is uncertain
    'BATTERY': 0xb,        # p20  p21  p22  p23  p50  p51  p52  p60  p61  p63
    'MAGNETOMETER': 0xc,   #                        not on muse S
    'PRESSURE': 0xd,       #                        not on muse S
    'ULTRA_VIOLET': 0xe,   #                        not on muse S
    # PPG appears to be 24bit intensity data.
    'PPG_AMBIENT': 0xf,    #                     p50  p51  p52  p60  p61  p63
    'PPG_IR': 0x10,        #                     p50  p51  p52  p60  p61  p63
    'PPG_RED': 0x11,       #                     p50  p51  p52  p60  p61  p63
    # thermistor has 12-bit format, like the eeg signals
    # it looks like lower numbers indicate warmer temperature
    'THERMISTOR': 0x12,    # p20       p22       p50            p60       p63

There is also some old information on presets at https://sites.google.com/a/interaxon.ca/muse-developer-site/museio/presets . That site also enumerates the serial commands.

@xloem
Copy link
Author

xloem commented Dec 17, 2020

Depending on your language there are different bluetooth libraries available. In python, there's a list at https://github.com/ukBaz/python-bluezero/wiki and the Bleak project looks promising: https://github.com/hbldh/bleak

@albheim
Copy link

albheim commented Oct 10, 2021

Playing around with accessing the data also, and having some problems. Not related to muse-js specifically, but you seem to have some idea of how to access the things in general so I thought I could maybe ask here.

It looks like the Muse 2 and Muse S are BTLE devices. They dont' need pairing. They expose GATT characteristics under the primary service 0000fe8d-0000-1000-8000-00805f9b34fb . The control GATT characteristic has UUID 273e0001-4c4d-454d-96be-f03bac821358 and acts like a serial port. Data is available as property change notifications in dbus on linux, but not as raw reads to the value. Bytes are written to the serial port as an array, first the length of a command as a byte, then each ascii character.

I have tried to read up on dbus, but it is not completely clear to me how I should use this. Using bluetoothctl on linux I can connect and see all the attributes, though as you say I can't seem to read right there in the gatt menu. Running dbus-monitor I can see some of the stuff sent, but it seems to be much the same as in the gatt menu of bluetoothctl.

Some commands are, from muse-js: 'p20\n': set to aux-enabled preset 'p21\n': set to aux-disabled preset 's\n': save preset? 'h\n': pause 'd\n': resume 'v1\n': get device info (encoded data available as control value changes)

Data is streamed out via 'Value' property changes once the resume command is sent, i.e. the 3 bytes '\x03d\n'.

Do you have an example of how I would send this resume command? I tried the write in bluetoothctls gatt menu as well as trying to write to the file created on acquire-write, but neither seems to work for me.

Maybe a simple example, such as how to show the battery status over dbus, would allow me to figure out the rest by myself.

Thanks for any help, and sorry for maybe going off topic in the issue. Hard to find good resources on this.

@xloem
Copy link
Author

xloem commented Oct 10, 2021

There's actually an official Muse page on this archived somewhere, but I don't know where.
I don't think it's normal (yet?) to send/recv data to a bluetooth serial interface using the commandline: using it is done inside an application.
In python, here is muse-lsl: https://github.com/alexandrebarachant/muse-lsl
There's also a small script I banged together while trying to figure things out: https://github.com/xloem/pymuse/blob/master/muse_async.py#L345 . the different files in that repo are half-implemented muse backends for different bluetooth backends.

it could be fun to make a muse serial terminal, but there are so few commands, and they haven't been expanded (I decompiled the Muse app for the Muse S and didn't see any new commands, although they do take new arguments), so it makes more sense to just work on improving an interface like muse-lsl or muse-js

@albheim
Copy link

albheim commented Oct 12, 2021

Okay, yeah I have used muse-lsl and wanted to port it or make something similar in Julia.

Then I realised I could not run muse-lsl anymore on my linux since it was using pygatt which complained that I didn't have gatttool or something along those lines. From what I could read gatttool was not used with BlueZ anymore so I assume it might get updated, but in the meantime I set out to understand how to create the communication from scratch (interesting learning more about bt).

That is how I got into trying to use the commandline tools to just see if I can send simple commands and get responses. I feel like this might be a bigger task then I realistically have time for right now so might put it on ice, but will for sure try to come back to it at some point.

@xloem
Copy link
Author

xloem commented Oct 12, 2021

it's not hard to make a commandline tool to do that
see also alexandrebarachant/muse-lsl#148 and xloem/muse-lsl#12 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants