Ricoh Theta x Nurosky Shutter
Révision | fdfef9efd73b0b8a34f65e1c0407a3dbb4a964c4 (tree) |
---|---|
l'heure | 2021-02-23 09:45:49 |
Auteur | MRSa <mrsa@myad...> |
Commiter | MRSa |
いったんコミット。
@@ -13,16 +13,19 @@ import jp.osdn.gokigen.thetathoughtshutter.R.layout | ||
13 | 13 | import jp.osdn.gokigen.thetathoughtshutter.bluetooth.connection.IBluetoothScanResult |
14 | 14 | import jp.osdn.gokigen.thetathoughtshutter.bluetooth.connection.eeg.MindWaveConnection |
15 | 15 | import jp.osdn.gokigen.thetathoughtshutter.brainwave.BrainwaveDataHolder |
16 | +import jp.osdn.gokigen.thetathoughtshutter.brainwave.IDetectSensingReceiver | |
17 | +import jp.osdn.gokigen.thetathoughtshutter.theta.ThetaCaptureControl | |
16 | 18 | import jp.osdn.gokigen.thetathoughtshutter.theta.ThetaHardwareControl |
17 | 19 | import jp.osdn.gokigen.thetathoughtshutter.theta.ThetaSetupBluetoothSPP |
18 | 20 | import jp.osdn.gokigen.thetathoughtshutter.theta.operation.IOperationCallback |
19 | 21 | import java.lang.Exception |
20 | 22 | |
21 | -class MainActivity : PluginActivity(), IBluetoothScanResult | |
23 | +class MainActivity : PluginActivity(), IBluetoothScanResult, IDetectSensingReceiver | |
22 | 24 | { |
23 | 25 | private val thetaHardwareControl = ThetaHardwareControl(this) |
26 | + private val thetaCaptureControl = ThetaCaptureControl("http://localhost:8080") | |
24 | 27 | private val applicationStatus : MyApplicationStatus = MyApplicationStatus() |
25 | - private val bluetoothConnection = MindWaveConnection(this, BrainwaveDataHolder(), this) | |
28 | + private val bluetoothConnection = MindWaveConnection(this, BrainwaveDataHolder(this), this) | |
26 | 29 | |
27 | 30 | companion object |
28 | 31 | { |
@@ -44,24 +47,6 @@ class MainActivity : PluginActivity(), IBluetoothScanResult | ||
44 | 47 | |
45 | 48 | override fun onKeyUp(keyCode: Int, event: KeyEvent?) |
46 | 49 | { |
47 | - if (keyCode == KeyReceiver.KEYCODE_CAMERA) // Shutterボタン | |
48 | - { | |
49 | - when (applicationStatus.status) | |
50 | - { | |
51 | - MyApplicationStatus.Status.Connected -> { | |
52 | - // EEGからの情報を取得して撮影する | |
53 | - applicationStatus.status = MyApplicationStatus.Status.Scanning | |
54 | - } | |
55 | - MyApplicationStatus.Status.Scanning -> { | |
56 | - // スタンバイ状態に戻す | |
57 | - applicationStatus.status = MyApplicationStatus.Status.Connected | |
58 | - } | |
59 | - else -> { | |
60 | - // ダミー処理 (仮にEEG接続失敗のステータスにする) | |
61 | - applicationStatus.status = MyApplicationStatus.Status.FailedInitialize | |
62 | - } | |
63 | - } | |
64 | - } | |
65 | 50 | if (keyCode == KeyReceiver.KEYCODE_WLAN_ON_OFF) // Wirelessボタン |
66 | 51 | { |
67 | 52 | if (applicationStatus.status == MyApplicationStatus.Status.Initialized) |
@@ -70,6 +55,7 @@ class MainActivity : PluginActivity(), IBluetoothScanResult | ||
70 | 55 | connectToEEG() |
71 | 56 | } |
72 | 57 | } |
58 | +/* | |
73 | 59 | if (keyCode == KeyReceiver.KEYCODE_MEDIA_RECORD) // Modeボタン |
74 | 60 | { |
75 | 61 | when (applicationStatus.status) { |
@@ -91,11 +77,14 @@ class MainActivity : PluginActivity(), IBluetoothScanResult | ||
91 | 77 | } |
92 | 78 | } |
93 | 79 | } |
94 | -/* | |
95 | 80 | if (keyCode == KeyReceiver.KEYCODE_FUNCTION) // Fnボタン (Z1のみ) |
96 | 81 | { |
97 | 82 | |
98 | 83 | } |
84 | + if (keyCode == KeyReceiver.KEYCODE_CAMERA) // Shutterボタン | |
85 | + { | |
86 | + | |
87 | + } | |
99 | 88 | */ |
100 | 89 | updateStatus(applicationStatus.status) |
101 | 90 | } |
@@ -155,7 +144,6 @@ class MainActivity : PluginActivity(), IBluetoothScanResult | ||
155 | 144 | applicationStatus.status = MyApplicationStatus.Status.Initialized |
156 | 145 | } |
157 | 146 | |
158 | - | |
159 | 147 | private fun updateStatus(currentStatus : MyApplicationStatus.Status) |
160 | 148 | { |
161 | 149 | try |
@@ -220,6 +208,14 @@ class MainActivity : PluginActivity(), IBluetoothScanResult | ||
220 | 208 | { |
221 | 209 | Log.v(TAG , " isApConnected : $isApConnected") |
222 | 210 | } |
211 | + try | |
212 | + { | |
213 | + thetaCaptureControl.setupCaptureMode() | |
214 | + } | |
215 | + catch (e : Exception) | |
216 | + { | |
217 | + e.printStackTrace() | |
218 | + } | |
223 | 219 | initializeBluetooth() |
224 | 220 | } |
225 | 221 |
@@ -236,7 +232,6 @@ class MainActivity : PluginActivity(), IBluetoothScanResult | ||
236 | 232 | } |
237 | 233 | } |
238 | 234 | |
239 | - | |
240 | 235 | private fun initializeBluetooth() |
241 | 236 | { |
242 | 237 | try |
@@ -297,6 +292,58 @@ class MainActivity : PluginActivity(), IBluetoothScanResult | ||
297 | 292 | e.printStackTrace() |
298 | 293 | } |
299 | 294 | } |
295 | + | |
296 | + override fun startSensing() | |
297 | + { | |
298 | + // データの検出を開始する | |
299 | + Log.v(TAG, " ===== START SENSING =====") | |
300 | + applicationStatus.status = MyApplicationStatus.Status.Scanning | |
301 | + updateStatus(applicationStatus.status) | |
302 | + } | |
303 | + | |
304 | + override fun detectAttention() | |
305 | + { | |
306 | + Log.v(TAG, " ===== DETECT ATTENTION =====") | |
307 | + applicationStatus.status = MyApplicationStatus.Status.Syncing | |
308 | + updateStatus(applicationStatus.status) | |
309 | + } | |
310 | + | |
311 | + override fun detectMediation() | |
312 | + { | |
313 | + //Log.v(TAG, " ===== DETECT MEDIATION =====") | |
314 | + } | |
315 | + | |
316 | + override fun lostAttention() | |
317 | + { | |
318 | + Log.v(TAG, " ===== LOST ATTENTION =====") | |
319 | + applicationStatus.status = MyApplicationStatus.Status.Scanning | |
320 | + updateStatus(applicationStatus.status) | |
321 | + } | |
322 | + | |
323 | + override fun lostMediation() | |
324 | + { | |
325 | + //Log.v(TAG, " ===== LOST MEDIATION =====") | |
326 | + } | |
327 | + | |
328 | + override fun detectAttentionThreshold() | |
329 | + { | |
330 | + Log.v(TAG, " ===== DETECT ATTENTION THRESHOLD =====") | |
331 | + try | |
332 | + { | |
333 | + // 静止画の撮影! | |
334 | + thetaCaptureControl.doCapture() | |
335 | + } | |
336 | + catch (e : Exception) | |
337 | + { | |
338 | + e.printStackTrace() | |
339 | + } | |
340 | + } | |
341 | + | |
342 | + override fun detectMediationThreshold() | |
343 | + { | |
344 | + Log.v(TAG, " ===== DETECT MEDIATION THRESHOLD =====") | |
345 | + } | |
346 | + | |
300 | 347 | } |
301 | 348 | |
302 | 349 | // |
@@ -1,14 +1,17 @@ | ||
1 | 1 | package jp.osdn.gokigen.thetathoughtshutter.brainwave |
2 | 2 | |
3 | 3 | import android.util.Log |
4 | -import jp.osdn.gokigen.thetathoughtshutter.bluetooth.connection.eeg.MindWaveConnection | |
5 | 4 | import java.util.* |
6 | 5 | |
7 | -class BrainwaveDataHolder(maxBufferSize: Int = 16000) : IBrainwaveDataReceiver | |
6 | +class BrainwaveDataHolder(private val receiver: IDetectSensingReceiver? = null, maxBufferSize: Int = 16000) : IBrainwaveDataReceiver | |
8 | 7 | { |
9 | 8 | companion object |
10 | 9 | { |
11 | 10 | private val TAG = BrainwaveDataHolder::class.java.simpleName |
11 | + private const val THRESHOLD_ATTENTION = 80 | |
12 | + private const val THRESHOLD_MEDIATION = 90 | |
13 | + private const val COUNT_CONTINUOUS_ATTENTION = 5 | |
14 | + private const val COUNT_CONTINUOUS_MEDIATION = 5 | |
12 | 15 | } |
13 | 16 | |
14 | 17 | private var valueBuffer: IntArray |
@@ -16,6 +19,9 @@ class BrainwaveDataHolder(maxBufferSize: Int = 16000) : IBrainwaveDataReceiver | ||
16 | 19 | private var maxBufferSize = 0 |
17 | 20 | private var currentPosition = 0 |
18 | 21 | private var bufferIsFull = false |
22 | + private var attentionCount = 0 | |
23 | + private var mediationCount = 0 | |
24 | + private var dataReceived = false | |
19 | 25 | |
20 | 26 | init |
21 | 27 | { |
@@ -58,6 +64,58 @@ class BrainwaveDataHolder(maxBufferSize: Int = 16000) : IBrainwaveDataReceiver | ||
58 | 64 | val attention = currentSummaryData.getAttention() |
59 | 65 | val mediation = currentSummaryData.getMediation() |
60 | 66 | Log.v(TAG, " ATTENTION : $attention MEDIATION : $mediation") |
67 | + if ((!dataReceived)&&(attention > 0)&&(mediation > 0)) | |
68 | + { | |
69 | + // データの受信を開始した | |
70 | + dataReceived = true | |
71 | + receiver?.startSensing() | |
72 | + } | |
73 | + | |
74 | + if (attention > THRESHOLD_ATTENTION) | |
75 | + { | |
76 | + if (attentionCount == 0) | |
77 | + { | |
78 | + receiver?.detectAttention() | |
79 | + } | |
80 | + attentionCount++ | |
81 | + if (attentionCount == COUNT_CONTINUOUS_ATTENTION) | |
82 | + { | |
83 | + // 検出を通知する | |
84 | + receiver?.detectAttentionThreshold() | |
85 | + } | |
86 | + } | |
87 | + else | |
88 | + { | |
89 | + // リミッターを下回ったので連続カウンタをクリアする | |
90 | + if( attentionCount > 0) | |
91 | + { | |
92 | + receiver?.lostAttention() | |
93 | + } | |
94 | + attentionCount = 0 | |
95 | + } | |
96 | + | |
97 | + if (mediation > THRESHOLD_MEDIATION) | |
98 | + { | |
99 | + if (mediationCount == 0) | |
100 | + { | |
101 | + receiver?.detectMediation() | |
102 | + } | |
103 | + mediationCount++ | |
104 | + if (mediationCount == COUNT_CONTINUOUS_MEDIATION) | |
105 | + { | |
106 | + // 検出を通知する | |
107 | + receiver?.detectMediationThreshold() | |
108 | + } | |
109 | + } | |
110 | + else | |
111 | + { | |
112 | + // リミッターを下回ったので連続カウンタをクリアする | |
113 | + if( mediationCount > 0) | |
114 | + { | |
115 | + receiver?.lostMediation() | |
116 | + } | |
117 | + mediationCount = 0 | |
118 | + } | |
61 | 119 | } |
62 | 120 | catch (e : Exception) |
63 | 121 | { |
@@ -0,0 +1,12 @@ | ||
1 | +package jp.osdn.gokigen.thetathoughtshutter.brainwave | |
2 | + | |
3 | +interface IDetectSensingReceiver | |
4 | +{ | |
5 | + fun startSensing() | |
6 | + fun detectAttention() | |
7 | + fun lostAttention() | |
8 | + fun detectAttentionThreshold() | |
9 | + fun detectMediation() | |
10 | + fun lostMediation() | |
11 | + fun detectMediationThreshold() | |
12 | +} |
@@ -0,0 +1,49 @@ | ||
1 | +package jp.osdn.gokigen.thetathoughtshutter.theta | |
2 | + | |
3 | +import android.util.Log | |
4 | +import jp.osdn.gokigen.thetathoughtshutter.theta.operation.IOperationCallback | |
5 | +import jp.osdn.gokigen.thetathoughtshutter.theta.operation.ThetaOptionSetControl | |
6 | +import jp.osdn.gokigen.thetathoughtshutter.theta.operation.ThetaSingleShotControl | |
7 | +import java.lang.Exception | |
8 | + | |
9 | +class ThetaCaptureControl(executeUrl : String = "http://192.168.1.1") | |
10 | +{ | |
11 | + private val setOption = ThetaOptionSetControl(executeUrl) | |
12 | + private val singleShot = ThetaSingleShotControl(executeUrl) | |
13 | + private var isCapturing = false | |
14 | + | |
15 | + companion object | |
16 | + { | |
17 | + private val TAG = ThetaCaptureControl::class.java.simpleName | |
18 | + } | |
19 | + | |
20 | + fun setupCaptureMode() | |
21 | + { | |
22 | + setOption.setOptions("\"captureMode\" : \"image\"", object : IOperationCallback { | |
23 | + override fun operationExecuted(result: Int, resultStr: String?) | |
24 | + { | |
25 | + if (resultStr != null) | |
26 | + { | |
27 | + Log.v(TAG, "set to Image : $resultStr ") | |
28 | + } | |
29 | + } | |
30 | + }) | |
31 | + } | |
32 | + | |
33 | + fun doCapture() | |
34 | + { | |
35 | + try | |
36 | + { | |
37 | + if (isCapturing) | |
38 | + { | |
39 | + Log.v(TAG, "ALREADY START CAPTURE SEQUENCE") | |
40 | + return | |
41 | + } | |
42 | + singleShot.singleShot() // まじか、応答しない... | |
43 | + } | |
44 | + catch (e : Exception) | |
45 | + { | |
46 | + e.printStackTrace() | |
47 | + } | |
48 | + } | |
49 | +} | |
\ No newline at end of file |