mindwave 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.codeclimate.yml +33 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.rubocop.yml +1156 -0
- data/.travis.yml +5 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +340 -0
- data/README.md +115 -0
- data/Rakefile +7 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/examples/mindwaver.rb +29 -0
- data/lib/mindwave.rb +538 -0
- data/lib/mindwave/version.rb +4 -0
- data/mindwave.gemspec +25 -0
- metadata +101 -0
data/Rakefile
ADDED
data/bin/console
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require "bundler/setup"
|
|
4
|
+
require "mindwave"
|
|
5
|
+
|
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
|
8
|
+
|
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
|
10
|
+
# require "pry"
|
|
11
|
+
# Pry.start
|
|
12
|
+
|
|
13
|
+
require "irb"
|
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require "bundler/setup"
|
|
4
|
+
require 'mindwave'
|
|
5
|
+
|
|
6
|
+
class EEG < Mindwave::Headset
|
|
7
|
+
# override Attention-Callback-Method
|
|
8
|
+
def attentionCall(attention)
|
|
9
|
+
str = eSenseStr(attention)
|
|
10
|
+
puts "this is an attention #{attention} #{str}\n"
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# create a new instance
|
|
15
|
+
mw = EEG.new
|
|
16
|
+
# mw.log.level = Logger::DEBUG
|
|
17
|
+
|
|
18
|
+
# if we hit ctrl+c then just stop the run()-method
|
|
19
|
+
Signal.trap("INT") do
|
|
20
|
+
mw.stop
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Create a new Thread
|
|
24
|
+
thread = Thread.new { mw.run }
|
|
25
|
+
# ..and run it
|
|
26
|
+
thread.join
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
mw.close
|
data/lib/mindwave.rb
ADDED
|
@@ -0,0 +1,538 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright (C) 2016 Wolfgang Hotwagner <code@feedyourhead.at>
|
|
3
|
+
#
|
|
4
|
+
# This file is part of the mindwave gem
|
|
5
|
+
#
|
|
6
|
+
# This mindwave gem is free software; you can redistribute it and/or
|
|
7
|
+
# modify it under the terms of the GNU General Public License
|
|
8
|
+
# as published by the Free Software Foundation; either version 2
|
|
9
|
+
# of the License, or (at your option) any later version.
|
|
10
|
+
#
|
|
11
|
+
# This mindwave gem is distributed in the hope that it will be useful,
|
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
# GNU General Public License for more details.
|
|
15
|
+
#
|
|
16
|
+
# You should have received a copy of the GNU General Public License
|
|
17
|
+
# along with this mindwave gem; if not, write to the
|
|
18
|
+
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
|
19
|
+
# Boston, MA 02110-1301 USA
|
|
20
|
+
#++
|
|
21
|
+
|
|
22
|
+
require "mindwave/version"
|
|
23
|
+
|
|
24
|
+
require 'serialport'
|
|
25
|
+
require 'bindata'
|
|
26
|
+
require 'logger'
|
|
27
|
+
|
|
28
|
+
# This module provides access to the Mindwave-Headset
|
|
29
|
+
module Mindwave
|
|
30
|
+
|
|
31
|
+
# The Mindwave::Headset-class gives access to the Mindwave-Headset.
|
|
32
|
+
# It's written for the Mindwave-Headset only, but most of the code
|
|
33
|
+
# should work for Mindwave-Mobile too.
|
|
34
|
+
#
|
|
35
|
+
# To use the callback-methods, just inherit from this class and
|
|
36
|
+
# override the Callback-Methods with your own code.
|
|
37
|
+
class Headset
|
|
38
|
+
# -----------------------
|
|
39
|
+
# :section: Request Codes
|
|
40
|
+
# -----------------------
|
|
41
|
+
|
|
42
|
+
# Connection Requests
|
|
43
|
+
CONNECT = 0xc0
|
|
44
|
+
# Disconnect Request
|
|
45
|
+
DISCONNECT = 0xc1
|
|
46
|
+
# Autoconnect Request
|
|
47
|
+
AUTOCONNECT = 0xc2
|
|
48
|
+
|
|
49
|
+
# -----------------------
|
|
50
|
+
# :section: Headset Status Codes
|
|
51
|
+
# -----------------------
|
|
52
|
+
|
|
53
|
+
# Headset connected
|
|
54
|
+
HEADSET_CONNECTED = 0xd0
|
|
55
|
+
# Headset not found
|
|
56
|
+
HEADSET_NOTFOUND = 0xd1
|
|
57
|
+
# Headset disconnected
|
|
58
|
+
HEADSET_DISCONNECTED = 0xd2
|
|
59
|
+
# Request denied
|
|
60
|
+
REQUEST_DENIED = 0xd3
|
|
61
|
+
# Dongle is in standby mode
|
|
62
|
+
DONGLE_STANDBY = 0xd4
|
|
63
|
+
|
|
64
|
+
# -----------------------
|
|
65
|
+
# :section: Control Codes
|
|
66
|
+
# -----------------------
|
|
67
|
+
|
|
68
|
+
# Start of a new data-set(packet)
|
|
69
|
+
SYNC = 0xaa
|
|
70
|
+
# Extended codes
|
|
71
|
+
EXCODE = 0x55
|
|
72
|
+
|
|
73
|
+
# -----------------------
|
|
74
|
+
# :section: Single-Byte-Codes
|
|
75
|
+
# -----------------------
|
|
76
|
+
|
|
77
|
+
# 0-255(zero is good). 200 means no-skin-contact
|
|
78
|
+
POOR_SIGNAL = 0x02
|
|
79
|
+
# Heartrate
|
|
80
|
+
HEART_RATE = 0x03
|
|
81
|
+
# Attention
|
|
82
|
+
# @see #eSenseStr
|
|
83
|
+
ATTENTION = 0x04
|
|
84
|
+
# Meditation
|
|
85
|
+
# @see #eSenseStr
|
|
86
|
+
MEDITATION = 0x05
|
|
87
|
+
# Not available in Mindwave and Mindwave Mobile
|
|
88
|
+
BIT8_RAW = 0x06
|
|
89
|
+
# Not available in Mindwave and Mindwave Mobile
|
|
90
|
+
RAW_MARKER = 0x07
|
|
91
|
+
|
|
92
|
+
# -----------------------
|
|
93
|
+
# :section: Multi-Byte-Codes
|
|
94
|
+
# -----------------------
|
|
95
|
+
|
|
96
|
+
# Raw Wave output
|
|
97
|
+
RAW_WAVE = 0x80
|
|
98
|
+
# EEG-Power
|
|
99
|
+
EEG_POWER = 0x81
|
|
100
|
+
# ASIC-EEG-POWER-INT
|
|
101
|
+
ASIC_EEG_POWER = 0x83
|
|
102
|
+
# RRinterval
|
|
103
|
+
RRINTERVAL = 0x86
|
|
104
|
+
|
|
105
|
+
# @!attribute headsetid
|
|
106
|
+
# @return [Integer] headset id
|
|
107
|
+
# @!attribute device
|
|
108
|
+
# @return [String] dongle device(like /dev/ttyUSB0)
|
|
109
|
+
# @!attribute rate
|
|
110
|
+
# @return [Integer] baud-rate of the device
|
|
111
|
+
# @!attribute log
|
|
112
|
+
# @return [Logger] logger instance
|
|
113
|
+
attr_accessor :headsetid, :device, :rate, :log
|
|
114
|
+
|
|
115
|
+
# @!attribute [r] attention
|
|
116
|
+
# stores the current attention-value
|
|
117
|
+
# @!attribute [r] meditation
|
|
118
|
+
# stores the current meditation-value
|
|
119
|
+
# @!attribute [r] asic
|
|
120
|
+
# stores the current asic-value
|
|
121
|
+
# @!attribute [r] poor
|
|
122
|
+
# stores the current poor-value
|
|
123
|
+
# @!attribute [r] headsetstatus
|
|
124
|
+
# stores the current headsetstatus-value
|
|
125
|
+
# @!attribute [r] heart
|
|
126
|
+
# stores the current heart-value
|
|
127
|
+
# @!attribute [r] runner
|
|
128
|
+
# @see #stop
|
|
129
|
+
attr_reader :attention, :meditation, :asic,:poor, :headsetstatus, :heart, :runner
|
|
130
|
+
|
|
131
|
+
# If connectserial is true, then this constructor opens a serial connection
|
|
132
|
+
# and automatically connects to the headset
|
|
133
|
+
#
|
|
134
|
+
# @param [Integer] headsetid it's on the sticker in the battery-case
|
|
135
|
+
# @param [String] device tty-device
|
|
136
|
+
# @param [Integer] rate baud-rate
|
|
137
|
+
# @param [Logger] log (logger-instance)
|
|
138
|
+
def initialize(headsetid=nil,device='/dev/ttyUSB0', connectserial=true,rate=115200, log=Logger.new(STDOUT))
|
|
139
|
+
@headsetid=headsetid
|
|
140
|
+
@device=device
|
|
141
|
+
@rate=rate
|
|
142
|
+
@log=log
|
|
143
|
+
@log.level = Logger::FATAL
|
|
144
|
+
@headsetstatus = 0
|
|
145
|
+
@runner = true
|
|
146
|
+
|
|
147
|
+
if connectserial
|
|
148
|
+
serial_open
|
|
149
|
+
connect(@headsetid)
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# connects the Mindwave-headset(not needed with Mindwave-Mobile)
|
|
154
|
+
# (Mindwave only)
|
|
155
|
+
#
|
|
156
|
+
# @param [Integer] headsetid it's on the sticker in the battery-case
|
|
157
|
+
# TODO: implement connection with headsetid
|
|
158
|
+
def connect(headsetid=nil)
|
|
159
|
+
if not headsetid.nil?
|
|
160
|
+
@headsetid = headsetid
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
if @headsetid.nil?
|
|
164
|
+
autoconnect()
|
|
165
|
+
return
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
cmd = BinData::Uint8be.new(Mindwave::Headset::CONNECT)
|
|
169
|
+
cmd.write(@conn)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# This method creates an infinite loop
|
|
173
|
+
# and reads out all data from the headset using
|
|
174
|
+
# the open serial-line.
|
|
175
|
+
def run
|
|
176
|
+
|
|
177
|
+
tmpbyte = 0;
|
|
178
|
+
@runner = true
|
|
179
|
+
|
|
180
|
+
while @runner
|
|
181
|
+
log.debug("<<< START RECORD >>>")
|
|
182
|
+
tmpbyte = logreadbyte
|
|
183
|
+
|
|
184
|
+
# 0xaa indicates the first start of a packet
|
|
185
|
+
if tmpbyte != Mindwave::Headset::SYNC
|
|
186
|
+
log.info(sprintf("LOST: %x\n",tmpbyte))
|
|
187
|
+
next
|
|
188
|
+
else
|
|
189
|
+
tmpbyte = logreadbyte()
|
|
190
|
+
# a second 0xaa verifies the start of a packet
|
|
191
|
+
if tmpbyte != Mindwave::Headset::SYNC
|
|
192
|
+
log.info(sprintf("LOST: %x\n",tmpbyte))
|
|
193
|
+
next
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
while true
|
|
199
|
+
# read out the length of the packet
|
|
200
|
+
plength = logreadbyte()
|
|
201
|
+
if(plength != 170)
|
|
202
|
+
break
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
if(plength > 170)
|
|
207
|
+
next
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
log.info(sprintf("Header-Length: %d",plength))
|
|
211
|
+
payload = Array.new(plength)
|
|
212
|
+
checksum = 0
|
|
213
|
+
# read out payload
|
|
214
|
+
(0..plength-1).each do |n|
|
|
215
|
+
payload[n] = logreadbyte()
|
|
216
|
+
# ..and add it to the checksum
|
|
217
|
+
checksum += payload[n]
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# weird checksum calculations
|
|
221
|
+
checksum &= 0xff
|
|
222
|
+
checksum = ~checksum & 0xff
|
|
223
|
+
|
|
224
|
+
# read checksum-packet
|
|
225
|
+
c = logreadbyte()
|
|
226
|
+
|
|
227
|
+
# compare checksum-packet with the calculated checksum
|
|
228
|
+
if( c != checksum)
|
|
229
|
+
log.info(sprintf("Checksum Error: %x - %x\n",c,checksum))
|
|
230
|
+
else
|
|
231
|
+
# so finally parse the payload of our packet
|
|
232
|
+
parse_payload(payload)
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
# this method parses the payload of a data-row, parses the values and invokes the callback methods
|
|
240
|
+
# @param [Array] payload Array with the payload
|
|
241
|
+
def parse_payload(payload)
|
|
242
|
+
if not payload.instance_of?Array or payload.nil? or payload.length < 2
|
|
243
|
+
raise "Invalid Argument"
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
log.info("####### PARSE PAYLOAD #########")
|
|
247
|
+
|
|
248
|
+
extcodelevel = 0
|
|
249
|
+
|
|
250
|
+
# parse the first code and it's payload
|
|
251
|
+
code = payload[0]
|
|
252
|
+
pl = payload[1,payload.length-1]
|
|
253
|
+
|
|
254
|
+
if code == Mindwave::Headset::EXCODE
|
|
255
|
+
extcodelevel += 1
|
|
256
|
+
|
|
257
|
+
# iterate through the payload-array
|
|
258
|
+
(1..payload.length).each do |n|
|
|
259
|
+
# if there is an excode, increment the level
|
|
260
|
+
if payload[n] == Mindwave::Headset::EXCODE
|
|
261
|
+
extcodelevel += 1
|
|
262
|
+
else
|
|
263
|
+
# ..otherwise parse the next code and it's payload
|
|
264
|
+
code = payload[n]
|
|
265
|
+
pl = payload[n+1,payload.length-(n+1)]
|
|
266
|
+
break
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
# some debugging output
|
|
272
|
+
log.info(sprintf("extcodelevel: %x",extcodelevel))
|
|
273
|
+
log.info(sprintf("Code: %x",code))
|
|
274
|
+
log.debug(sprintf("Length: %d",pl.length))
|
|
275
|
+
pl.each do |n|
|
|
276
|
+
log.debug(sprintf("payload: Hex: %x Dec: %d",n,n))
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
# SINGLE-BYTE-CODES
|
|
281
|
+
if code < Mindwave::Headset::RAW_WAVE or code >= Mindwave::Headset::HEADSET_CONNECTED
|
|
282
|
+
|
|
283
|
+
sbpayload = pl[0]
|
|
284
|
+
codestr = ""
|
|
285
|
+
|
|
286
|
+
case code
|
|
287
|
+
when Mindwave::Headset::HEADSET_CONNECTED
|
|
288
|
+
codestr = "Headset connected"
|
|
289
|
+
@headsetstatus = code
|
|
290
|
+
when Mindwave::Headset::HEADSET_NOTFOUND
|
|
291
|
+
codestr = "Headset not found"
|
|
292
|
+
@headsetstatus = code
|
|
293
|
+
when Mindwave::Headset::HEADSET_DISCONNECTED
|
|
294
|
+
codestr = "Headset disconnected"
|
|
295
|
+
@headsetstatus = code
|
|
296
|
+
when Mindwave::Headset::REQUEST_DENIED
|
|
297
|
+
codestr = "Request denied"
|
|
298
|
+
@headsetstatus = code
|
|
299
|
+
when Mindwave::Headset::DONGLE_STANDBY
|
|
300
|
+
codestr = "Dongle standby"
|
|
301
|
+
@headsetstatus = code
|
|
302
|
+
when Mindwave::Headset::POOR_SIGNAL
|
|
303
|
+
codestr = "Poor Signal"
|
|
304
|
+
@poor = sbpayload
|
|
305
|
+
poorCall(@poor)
|
|
306
|
+
when Mindwave::Headset::HEART_RATE
|
|
307
|
+
codestr = "Heart Rate"
|
|
308
|
+
@heart = sbpayload
|
|
309
|
+
heartCall(@heart)
|
|
310
|
+
when Mindwave::Headset::ATTENTION
|
|
311
|
+
codestr = "Attention"
|
|
312
|
+
@attention = sbpayload
|
|
313
|
+
attentionCall(@attention)
|
|
314
|
+
when Mindwave::Headset::MEDITATION
|
|
315
|
+
codestr = "Meditation"
|
|
316
|
+
@meditation = sbpayload
|
|
317
|
+
meditationCall(@meditation)
|
|
318
|
+
## THIS METHODS ARE NOT AVAILABLE FOR MINDWAVE(MOBILE)
|
|
319
|
+
when Mindwave::Headset::BIT8_RAW
|
|
320
|
+
codestr = "8Bit Raw"
|
|
321
|
+
when Mindwave::Headset::RAW_MARKER
|
|
322
|
+
codestr = "Raw Marker"
|
|
323
|
+
# EOF NOT AVAILABLE
|
|
324
|
+
else
|
|
325
|
+
codestr = "Unknown"
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
log.debug(sprintf("SINGLEBYTE-PAYLOAD: Code: %s Hex: %x - Dec: %d",codestr,sbpayload,sbpayload))
|
|
329
|
+
|
|
330
|
+
# Re-Parse the rest of the payload
|
|
331
|
+
if pl.length > 2
|
|
332
|
+
payload = pl[1,pl.length-1]
|
|
333
|
+
# recursive call of parse_payload for the next data-rows
|
|
334
|
+
parse_payload(payload)
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
# MULTI-BYTE-CODES
|
|
338
|
+
else
|
|
339
|
+
codestr = ""
|
|
340
|
+
plength = pl[0]
|
|
341
|
+
mpl = pl[1,plength]
|
|
342
|
+
|
|
343
|
+
case code
|
|
344
|
+
|
|
345
|
+
when Mindwave::Headset::RAW_WAVE
|
|
346
|
+
codestr = "RAW_WAVE Code detected"
|
|
347
|
+
rawCall(convertRaw(mpl[0],mpl[1]))
|
|
348
|
+
when Mindwave::Headset::EEG_POWER
|
|
349
|
+
codestr = "EEG Power"
|
|
350
|
+
when Mindwave::Headset::ASIC_EEG_POWER
|
|
351
|
+
codestr = "ASIC EEG POWER"
|
|
352
|
+
@asic = mpl
|
|
353
|
+
asicCall(@asic)
|
|
354
|
+
when Mindwave::Headset::RRINTERVAL
|
|
355
|
+
codestr = "RRINTERVAL"
|
|
356
|
+
else
|
|
357
|
+
codestr = "Unknown"
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
# Fetch the Multi-Payload
|
|
361
|
+
log.info(sprintf("Multibyte-Code: %s",codestr))
|
|
362
|
+
log.info(sprintf("Multibyte-Payload-Length: %d",pl[0]))
|
|
363
|
+
|
|
364
|
+
mpl.each() do |n|
|
|
365
|
+
log.debug(sprintf("MULTIBYTE-PAYLOAD: Hex: %x - Dec: %d",n,n))
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
# Re-Parse the rest of the payload
|
|
369
|
+
if pl.length-1 > plength
|
|
370
|
+
payload = pl[mpl.length+1,pl.length-mpl.length]
|
|
371
|
+
# recursive call of parse_payload for the next data-rows
|
|
372
|
+
parse_payload(payload)
|
|
373
|
+
end
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
# this method sends a byte to the serial connection
|
|
380
|
+
# (Mindwave only)
|
|
381
|
+
#
|
|
382
|
+
# @param [Integer] hexbyte byte to send
|
|
383
|
+
def sendbyte(hexbyte)
|
|
384
|
+
cmd = BinData::Uint8be.new(hexbyte)
|
|
385
|
+
cmd.write(@conn)
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
# This method connects to the headset automatically without knowing the device-id
|
|
389
|
+
# (Mindwave only)
|
|
390
|
+
def autoconnect
|
|
391
|
+
cmd = BinData::Uint8be.new(Mindwave::Headset::AUTOCONNECT)
|
|
392
|
+
cmd.write(@conn)
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
# this method disconnects a connection between headset and dongle
|
|
396
|
+
# (Mindwave only)
|
|
397
|
+
def disconnect
|
|
398
|
+
cmd = BinData::Uint8be.new(Mindwave::Headset::DISCONNECT)
|
|
399
|
+
cmd.write(@conn)
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
# this method opens a serial connection to the device
|
|
403
|
+
def serial_open
|
|
404
|
+
@conn = SerialPort.new(@device,@rate)
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
# this method closes a serial connection to the device
|
|
408
|
+
def serial_close
|
|
409
|
+
@conn.close
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
# this method disconnects the headset and closes the serial line
|
|
413
|
+
def close
|
|
414
|
+
disconnect
|
|
415
|
+
serial_close
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
# this method stops the run-method
|
|
419
|
+
def stop
|
|
420
|
+
@runner = false
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
# --------------------------
|
|
424
|
+
# :section: Callback Methods
|
|
425
|
+
# --------------------------
|
|
426
|
+
|
|
427
|
+
# this method is called when the poor-value is parsed
|
|
428
|
+
# override this method to implement your own clode
|
|
429
|
+
#
|
|
430
|
+
# @param [Integer] poor poor-value
|
|
431
|
+
def poorCall(poor)
|
|
432
|
+
if poor == 200
|
|
433
|
+
log.info("No skin-contact detected")
|
|
434
|
+
end
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
# this method is called when the attention-value is parsed
|
|
438
|
+
# override this method to implement your own code
|
|
439
|
+
#
|
|
440
|
+
# @param [Integer] attention attention-value
|
|
441
|
+
def attentionCall(attention)
|
|
442
|
+
str = eSenseStr(attention)
|
|
443
|
+
log.info("ATTENTION #{attention} #{str}")
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
# this method is called when the meditation-value is parsed
|
|
447
|
+
# override this method to implement your own code
|
|
448
|
+
#
|
|
449
|
+
# @param [Integer] meditation meditation-value
|
|
450
|
+
def meditationCall(meditation)
|
|
451
|
+
str = eSenseStr(meditation)
|
|
452
|
+
log.info("MEDITATION #{meditation} #{str}")
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
# this method is called when the heart-rate-value is parsed
|
|
456
|
+
# override this method to implement your own code
|
|
457
|
+
#
|
|
458
|
+
# @param [Integer] heart heart-value
|
|
459
|
+
def heartCall(heart)
|
|
460
|
+
log.info("HEART RATE #{heart}")
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
# this method is called when the raw-wave-value is parsed
|
|
464
|
+
# override this method to implement your own code
|
|
465
|
+
#
|
|
466
|
+
# @param [Integer] rawvalue raw-wave-value
|
|
467
|
+
def rawCall(rawvalue)
|
|
468
|
+
log.debug("Converted Raw-Value: #{rawvalue}")
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
##
|
|
472
|
+
# this method is called when the asic-value is parsed
|
|
473
|
+
# override this method to implement your own code
|
|
474
|
+
#
|
|
475
|
+
# @param [Integer] asic asic-value
|
|
476
|
+
#
|
|
477
|
+
def asicCall(asic)
|
|
478
|
+
log.debug("ASIC Value: #{asic}")
|
|
479
|
+
end
|
|
480
|
+
|
|
481
|
+
private
|
|
482
|
+
|
|
483
|
+
# reads out a byte from the serial-line and
|
|
484
|
+
# logs the byte using "debug"
|
|
485
|
+
def logreadbyte
|
|
486
|
+
begin
|
|
487
|
+
ret = @conn.readbyte
|
|
488
|
+
rescue EOFError
|
|
489
|
+
log.fatal("EOFError")
|
|
490
|
+
# But Ignore it with FF
|
|
491
|
+
ret = 0x00
|
|
492
|
+
end
|
|
493
|
+
log.debug(sprintf("HEX: %x DEC: %d",ret,ret))
|
|
494
|
+
return ret
|
|
495
|
+
end
|
|
496
|
+
|
|
497
|
+
# this method converts the numeric eSense-value of attention or meditation
|
|
498
|
+
# to a string
|
|
499
|
+
#
|
|
500
|
+
# @param [Integer] value eSense-value
|
|
501
|
+
# @returns [String] string-value
|
|
502
|
+
# = eSense Values(Attention and Meditation)
|
|
503
|
+
# * 1-20 = strongly lowered
|
|
504
|
+
# * 20-40 = reduced
|
|
505
|
+
# * 40-60 = neutral
|
|
506
|
+
# * 60-80 = slightly elevated
|
|
507
|
+
# * 80-100 = elevated
|
|
508
|
+
def eSenseStr(value)
|
|
509
|
+
result = case value
|
|
510
|
+
when 0..20 then "Strongly lowered"
|
|
511
|
+
when 21..40 then "Reduced"
|
|
512
|
+
when 41..60 then "Neutral"
|
|
513
|
+
when 61..80 then "Slightly elevated"
|
|
514
|
+
when 81..100 then "Elevated"
|
|
515
|
+
else
|
|
516
|
+
"Unknown"
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
return result
|
|
520
|
+
end
|
|
521
|
+
|
|
522
|
+
# converts a raw-wave-data-packet of 2 bytes to a single value
|
|
523
|
+
#
|
|
524
|
+
# @param [Integer] rawval1 first byte-packet of the raw-wave-code
|
|
525
|
+
# @param [Integer] rawval2 second byte-packet of the raw-wave-code
|
|
526
|
+
#
|
|
527
|
+
# @return [Integer] single value generated from the 2 bytes
|
|
528
|
+
def convertRaw(rawval1,rawval2)
|
|
529
|
+
raw = rawval1*256 + rawval2
|
|
530
|
+
if raw >= 32768
|
|
531
|
+
raw = raw - 65536
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
return raw
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
end
|
|
538
|
+
end
|