OSDN Git Service

edaf6da80091143315f5c40db3664b6403ad81f2
[gokigen/ThetaThoughtShutter.git] / app / src / main / java / jp / osdn / gokigen / thetathoughtshutter / bluetooth / connection / eeg / MindWaveConnection.kt
1 package jp.osdn.gokigen.thetathoughtshutter.bluetooth.connection.eeg
2
3 import android.app.Activity
4 import android.bluetooth.BluetoothDevice
5 import android.bluetooth.BluetoothSocket
6 import android.content.BroadcastReceiver
7 import android.content.Context
8 import android.content.Intent
9 import android.content.IntentFilter
10 import android.util.Log
11 import jp.osdn.gokigen.thetathoughtshutter.bluetooth.connection.IBluetoothScanResult
12 import jp.osdn.gokigen.thetathoughtshutter.bluetooth.connection.BluetoothDeviceFinder
13 import jp.osdn.gokigen.thetathoughtshutter.brainwave.BrainwaveFileLogger
14 import jp.osdn.gokigen.thetathoughtshutter.brainwave.IBrainwaveDataReceiver
15 import java.io.ByteArrayOutputStream
16 import java.io.InputStream
17 import java.util.*
18 import kotlin.experimental.and
19
20 class MindWaveConnection(private val activity : Activity, private val dataReceiver: IBrainwaveDataReceiver, private val scanResult: IBluetoothScanResult? = null) : IBluetoothScanResult
21 {
22     companion object
23     {
24         private val TAG = MindWaveConnection::class.java.simpleName
25     }
26
27     private val deviceFinder = BluetoothDeviceFinder(activity, this)
28     private var fileLogger: BrainwaveFileLogger? = null
29     private var foundDevice = false
30     private var isPairing = false
31     private var loggingFlag = false
32     private var targetDevice: BluetoothDevice? = null
33
34     private var connectionReceiver = object : BroadcastReceiver()
35     {
36         override fun onReceive(context: Context, intent: Intent)
37         {
38             onReceiveBroadcastOfConnection(this, context, intent)
39         }
40     }
41
42     fun connect(deviceName: String, loggingFlag: Boolean = false)
43     {
44         Log.v(TAG, " BrainWaveMobileCommunicator::connect() : $deviceName Logging : $loggingFlag")
45         try
46         {
47             registerReceiver()
48
49             this.loggingFlag = loggingFlag
50
51             // Bluetooth のサービスを取得、BLEデバイスをスキャンする
52             foundDevice = false
53             deviceFinder.reset()
54             deviceFinder.startScan(deviceName)
55         }
56         catch (e: Exception)
57         {
58             e.printStackTrace()
59         }
60     }
61
62     private fun registerReceiver()
63     {
64         try
65         {
66             val filter = IntentFilter()
67             filter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST)
68             filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED)
69             activity.registerReceiver(connectionReceiver, filter)
70         }
71         catch (e : Exception)
72         {
73             e.printStackTrace()
74         }
75     }
76
77     private fun unregisterReceiver()
78     {
79         try
80         {
81             activity.unregisterReceiver(connectionReceiver)
82         }
83         catch (e : Exception)
84         {
85             e.printStackTrace()
86         }
87     }
88
89     private fun parseReceivedData(data: ByteArray)
90     {
91         // 受信データブロック1つ分
92         try
93         {
94             if (data.size <= 3)
95             {
96                 // ヘッダ部しか入っていない...無視する
97                 return
98             }
99             val length = data[2]
100             if (data.size < length + 2)
101             {
102                 // データが最小サイズに満たない...無視する
103                 return
104             }
105             if (data.size == 8 || data.size == 9)
106             {
107                 var value: Int = (data[5] and 0xff.toByte()) * 256 + (data[6] and 0xff.toByte())
108                 if (value > 32768)
109                 {
110                     value -= 65536
111                 }
112                 dataReceiver.receivedRawData(value)
113                 return
114             }
115             dataReceiver.receivedSummaryData(data)
116
117             // ファイルにサマリーデータを出力する
118             fileLogger?.outputSummaryData(data)
119         }
120         catch (e: Exception)
121         {
122             e.printStackTrace()
123         }
124     }
125
126     private fun serialCommunicationMain(btSocket: BluetoothSocket)
127     {
128         Log.v(TAG, "serialCommunicationMain ")
129         var inputStream: InputStream? = null
130         try
131         {
132             btSocket.connect()
133             inputStream = btSocket.inputStream
134         }
135         catch (e: Exception)
136         {
137             Log.e(TAG, "Fail to accept.", e)
138         }
139         if (inputStream == null)
140         {
141             return
142         }
143         if (loggingFlag)
144         {
145             try
146             {
147                 // ログ出力を指示されていた場合...ファイル出力クラスを作成しておく
148                 fileLogger = BrainwaveFileLogger()
149             }
150             catch (e: Exception)
151             {
152                 e.printStackTrace()
153             }
154         }
155
156         // シリアルデータの受信メイン部分
157         var previousData = 0xff.toByte()
158         val outputStream = ByteArrayOutputStream()
159         while (foundDevice)
160         {
161             try
162             {
163                 val data: Int = inputStream.read()
164                 Log.v(TAG, " RECEIVED ")
165                 val byteData = (data and 0xff).toByte()
166                 if (previousData == byteData && byteData == 0xaa.toByte())
167                 {
168                     // 先頭データを見つけた。 (0xaa 0xaa がヘッダ)
169                     parseReceivedData(outputStream.toByteArray())
170                     outputStream.reset()
171                     outputStream.write(0xaa)
172                     outputStream.write(0xaa)
173                 }
174                 else
175                 {
176                     outputStream.write(byteData.toInt())
177                 }
178                 previousData = byteData
179             }
180             catch (e: Exception)
181             {
182                 e.printStackTrace()
183             }
184         }
185         try
186         {
187             btSocket.close()
188         }
189         catch (e: Exception)
190         {
191             e.printStackTrace()
192         }
193     }
194
195
196     override fun foundBluetoothDevice(device: BluetoothDevice)
197     {
198         try
199         {
200             Log.v(TAG, " foundBluetoothDevice : ${device.name} : ${device.bondState}")
201
202             deviceFinder.stopScan()
203
204             if (device.bondState == BluetoothDevice.BOND_BONDED)
205             {
206                 // すでにペアリング済み
207                 Log.v(TAG, " ALREADY PAIRED ")
208                 isPairing = true
209                 targetDevice = device
210                 connectBluetoothDevice(device)
211                 return
212             }
213
214             if ((!foundDevice)&&(!isPairing))
215             {
216                 Log.v(TAG, "START PAIRING ${device.name}")
217                 device.setPin(byteArrayOf(0x30, 0x30, 0x30, 0x30))
218                 targetDevice = device
219                 device.createBond()
220                 isPairing = true
221             }
222             deviceFinder.stopScan()
223         }
224         catch (e : Exception)
225         {
226             e.printStackTrace()
227         }
228         //return (device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")))
229     }
230
231
232 /*
233     private fun prepareBluetoothDevice(device: BluetoothDevice) : BluetoothSocket?
234     {
235         try
236         {
237             device.setPin(byteArrayOf(0x30,0x30, 0x30, 0x30))
238
239             val result = device.createBond()
240             if (!result)
241             {
242                 // ペアリング失敗
243                 return (null)
244             }
245
246
247         }
248         catch (e : Exception)
249         {
250             e.printStackTrace()
251         }
252         return (device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")))
253     }
254
255     override fun foundBluetoothDevice(device: BluetoothDevice)
256     {
257         try
258         {
259             Log.v(TAG, " foundBluetoothDevice : ${device.name}")
260             if (foundDevice)
261             {
262                 // デバイスがすでに見つかっている
263                 Log.v(TAG, " ALREADY FIND BLUETOOTH DEVICE. : $device.name")
264                 deviceFinder.stopScan()
265                 return
266             }
267             foundDevice = true
268             deviceFinder.stopScan()
269
270             val btSocket = prepareBluetoothDevice(device) // device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"))
271             val thread = Thread {
272                 try
273                 {
274                     if (btSocket != null)
275                     {
276                         serialCommunicationMain(btSocket)
277                     }
278                 }
279                 catch (e: Exception)
280                 {
281                     e.printStackTrace()
282                 }
283             }
284             if (btSocket != null)
285             {
286                 thread.start()
287             }
288             else
289             {
290                 Log.v(TAG, " btSocket is NULL.")
291             }
292             scanResult?.foundBluetoothDevice(device)
293         }
294         catch (e: Exception)
295         {
296             e.printStackTrace()
297         }
298     }
299 */
300
301     private fun connectBluetoothDevice(device : BluetoothDevice?)
302     {
303         try
304         {
305             Log.v(TAG, "connectBluetoothDevice() : ${device?.name}")
306             if (device == null)
307             {
308                 Log.v(TAG, " DEVICE IS NULL...")
309                 return
310             }
311
312             val btSocket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"))
313             val thread = Thread {
314                 try
315                 {
316                     if (btSocket != null)
317                     {
318                         serialCommunicationMain(btSocket)
319                     }
320                 }
321                 catch (e: Exception)
322                 {
323                     e.printStackTrace()
324                 }
325             }
326             if (btSocket != null)
327             {
328                 thread.start()
329             }
330             else
331             {
332                 Log.v(TAG, " btSocket is NULL.")
333             }
334             scanResult?.foundBluetoothDevice(device)
335         }
336         catch (e: Exception)
337         {
338             e.printStackTrace()
339         }
340     }
341
342     override fun notFindBluetoothDevice()
343     {
344         Log.v(TAG, " notFindBluetoothDevice()")
345         scanResult?.notFindBluetoothDevice()
346         deviceFinder.stopScan()
347     }
348
349     /**
350      *
351      *
352      */
353     private fun onReceiveBroadcastOfConnection(receiver: BroadcastReceiver, context: Context, intent: Intent)
354     {
355         val action = intent.action
356         if (action == null)
357         {
358             Log.v(TAG, "intent.getAction() : null")
359             return
360         }
361         try
362         {
363             if (action == BluetoothDevice.ACTION_PAIRING_REQUEST)
364             {
365                 val device = intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE)!!
366                 Log.v(TAG, " onReceiveBroadcastOfConnection : BluetoothDevice.ACTION_PAIRING_REQUEST  device: ${device.name}")
367                  try
368                 {
369                     targetDevice?.setPin(byteArrayOf(0x30,0x30, 0x30, 0x30))
370                     device.setPin(byteArrayOf(0x30,0x30, 0x30, 0x30))
371                     receiver.abortBroadcast()
372                 }
373                 catch (e : Exception)
374                 {
375                     e.printStackTrace()
376                 }
377             }
378             else if (action == BluetoothDevice.ACTION_BOND_STATE_CHANGED)
379             {
380                 val device = intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE)!!
381                 val bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1)
382                 Log.v(TAG, " onReceiveBroadcastOfConnection : BluetoothDevice.ACTION_BOND_STATE_CHANGED ($bondState) device: ${device.name}")
383                 if (bondState == BluetoothDevice.BOND_BONDED)
384                 {
385                     // ペアリング完了!
386                     Log.v(TAG, " ----- Device is Paired! ${device.name}")
387                     foundDevice = true
388                     connectBluetoothDevice(device)
389                 }
390             }
391         }
392         catch (e: Exception)
393         {
394             Log.w(TAG, "onReceiveBroadcastOfConnection() EXCEPTION" + e.message)
395             e.printStackTrace()
396         }
397     }
398 }