Some developers may wish to not include MetroEEG directly but include lower-level code. In this sample we'll endeavor to show a standalone example of getting information from a Mindwave Mobile headset into WP8.
Using the new Bluetooth support in WP8, it's possible to iterate over all paired Bluetooth devices and open a BT-SPP socket to them.
First, we get the list of all connected Bluetooth paired devices.
Next we iterate over that collection attempting to find one with the word "Mindwave" in it. If we don't find one, that could be for multiple reasons: Phone Bluetooth is off, mindwave is off, both devices aren't paired, etc.
And finally we open up a socket that'll be used later to retrieve information from.
Mindwave tends to be very chatty and has over 500+ messages every seconds. Those messages are received over as Bytes by C#. We can see the message format at
.
We'll use socket.InputStream.ReadAsync to read the data sent over by Mindwave.
We'll have to continuously read that data in a while (true) loop.
Mindwave sends back A LOT of data. It's quite easy to see a pattern of using 2 bytes of
and has an overall length of 36 bytes. for example:
170,170,32,2,25,131,24,0,0,132,0,0,53,0,0,22,0,0,12,0,0,10,0,0,5,0,0,1,0,0,1,4,0,5,0,84
header in it.
If our code has those values then we found the one packet out of 500 packets every second that interested us. Otherwise if that header doesn't exist we can just ignore all 512 bytes.
One unfortunate thing that might happen is that we get 512 bytes that have the header for our 36 bytes packet, but only a part of it. And we might need to read another 512 bytes to get the full 36 byte packet. Once we have that we'll take the length of the data packet (and 2 more bytes to see the next header).
When we run this code snippet we can see the following print out with useful data packets.
170,170,32,2,25,131,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,5,0,64,170,170,4,128
170,170,32,2,25,131,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,5,0,64,170,170,4,128
170,170,32,2,25,131,24,5,76,181,1,109,49,0,165,255,0,67,142,0,72,239,0,29,197,0,20,50,0,14,11,4,0,5,0,174,170,170,4,128
170,170,32,2,0,131,24,0,54,21,0,59,230,0,13,123,0,2,35,0,7,190,0,4,121,0,1,134,0,1,18,4,0,5,0,100,170,170,4,128
170,170,32,2,0,131,24,9,131,218,3,187,65,0,25,6,0,188,221,0,190,75,0,61,189,0,9,6,0,39,19,4,0,5,0,240,170,170,4,128
170,170,32,2,0,131,24,16,167,140,0,232,31,0,184,100,0,70,183,0,92,99,0,88,228,0,27,190,0,16,81,4,0,5,0,193,170,170,4,128
170,170,32,2,0,131,24,21,60,117,3,90,220,0,69,112,0,70,240,0,124,10,0,41,106,0,100,249,0,53,199,4,30,5,30,193,170,170,4,128
170,170,32,2,51,131,24,9,47,134,0,37,83,0,6,210,0,12,53,0,6,211,0,15,83,0,4,124,0,2,232,4,30,5,30,246,170,170,4,128
170,170,32,2,25,131,24,5,224,15,3,239,254,2,229,125,0,53,105,0,63,75,0,116,127,0,157,83,0,131,10,4,30,5,30,36,170,170,4,128
170,170,32,2,0,131,24,10,187,109,1,120,31,0,196,103,0,143,57,0,84,87,0,104,26,0,45,53,0,121,65,4,43,5,44,252,170,170,4,128
170,170,32,2,0,131,24,4,47,171,4,68,202,0,55,217,0,128,94,0,37,85,0,94,14,0,36,34,0,59,103,4,43,5,38,92,170,170,4,128
170,170,32,2,0,131,24,5,222,176,0,39,237,0,19,9,0,8,159,0,19,186,0,8,23,0,6,29,0,4,195,4,51,5,44,186,170,170,4,128
170,170,32,2,0,131,24,18,191,112,1,97,97,1,29,246,0,29,133,0,9,8,0,58,54,0,16,23,0,25,175,4,63,5,67,173,170,170,4,128
The mindwave packet is actually pretty easy to parse. Here's a sample packet and it's meaning directly from the docs:
We'll create a new data class that has properties corresponding to each of these items.
And finally we can unpack the data packet, get the useful data out of it, put it on our data class and print it.
The method GetIntValue takes 3 bytes and prints out a corresponding unsigned Int24. Thanks to Bill Reiss that helped me figure out how to convert those bytes to something useful.
Quality: 25, Delta: 6, Theta: 2, AlphaLow: 0, AlphaHigh: 0, BetaLow: 0, BetaHigh: 0, GammaLow: 0, GammaMid: 0, eSenseAttention: 0, eSenseMeditation: 0
Quality: 25, Delta: 0, Theta: 0, AlphaLow: 0, AlphaHigh: 0, BetaLow: 0, BetaHigh: 0, GammaLow: 0, GammaMid: 0, eSenseAttention: 0, eSenseMeditation: 0
Quality: 25, Delta: 1615213, Theta: 42582, AlphaLow: 31380, AlphaHigh: 46256, BetaLow: 19899, BetaHigh: 7208, GammaLow: 3845, GammaMid: 4395, eSenseAttention: 0, eSenseMeditation: 0
Quality: 0, Delta: 426257, Theta: 33904, AlphaLow: 6628, AlphaHigh: 13725, BetaLow: 7579, BetaHigh: 10067, GammaLow: 8842, GammaMid: 9374, eSenseAttention: 0, eSenseMeditation: 0
Quality: 0, Delta: 583371, Theta: 510441, AlphaLow: 19150, AlphaHigh: 112287, BetaLow: 47943, BetaHigh: 39250, GammaLow: 24035, GammaMid: 17424, eSenseAttention: 0, eSenseMeditation: 0
Quality: 0, Delta: 222602, Theta: 33844, AlphaLow: 23690, AlphaHigh: 22298, BetaLow: 4977, BetaHigh: 15146, GammaLow: 13963, GammaMid: 7088, eSenseAttention: 0, eSenseMeditation: 0
Quality: 0, Delta: 1812838, Theta: 24675, AlphaLow: 39716, AlphaHigh: 23848, BetaLow: 11263, BetaHigh: 6688, GammaLow: 13527, GammaMid: 6301, eSenseAttention: 37, eSenseMeditation: 51
Quality: 0, Delta: 447038, Theta: 305377, AlphaLow: 33535, AlphaHigh: 98314, BetaLow: 99116, BetaHigh: 89947, GammaLow: 19895, GammaMid: 35526, eSenseAttention: 51, eSenseMeditation: 47
Quality: 0, Delta: 46900, Theta: 2625, AlphaLow: 12408, AlphaHigh: 4522, BetaLow: 3427, BetaHigh: 1863, GammaLow: 2832, GammaMid: 1734, eSenseAttention: 51, eSenseMeditation: 63
Quality: 0, Delta: 690112, Theta: 39077, AlphaLow: 3379, AlphaHigh: 4319, BetaLow: 1836, BetaHigh: 3086, GammaLow: 9628, GammaMid: 3239, eSenseAttention: 44, eSenseMeditation: 53
Quality: 0, Delta: 1016230, Theta: 248297, AlphaLow: 117104, AlphaHigh: 24892, BetaLow: 16677, BetaHigh: 30317, GammaLow: 36050, GammaMid: 18515, eSenseAttention: 44, eSenseMeditation: 40
Quality: 0, Delta: 201986, Theta: 18987, AlphaLow: 4782, AlphaHigh: 7936, BetaLow: 3120, BetaHigh: 2211, GammaLow: 2566, GammaMid: 3939, eSenseAttention: 24, eSenseMeditation: 47
Quality: 0, Delta: 26635, Theta: 2578, AlphaLow: 673, AlphaHigh: 1935, BetaLow: 3925, BetaHigh: 4181, GammaLow: 2492, GammaMid: 803, eSenseAttention: 47, eSenseMeditation: 23