-
Notifications
You must be signed in to change notification settings - Fork 84
Description
NeuralLinkerApp/
├─ app/
│ ├─ src/
│ │ ├─ main/
│ │ │ ├─ java/com/neurallinker/app/
│ │ │ │ ├─ MainActivity.kt
│ │ │ │ ├─ AndroidBridge.kt
│ │ │ │ ├─ EEGManager.kt
│ │ │ │ ├─ BrainIA.kt
│ │ │ ├─ res/
│ │ │ │ ├─ layout/activity_main.xml
│ │ │ │ ├─ values/strings.xml
│ │ │ ├─ assets/
│ │ │ │ └─ www/
│ │ │ │ ├─ index.html
│ │ │ │ ├─ tailwind.css
│ │ │ │ └─ js/
│ │ │ │ ├─ bridge.js
│ │ │ │ └─ brain.js
│ │ │ └─ AndroidManifest.xml
│ └─ build.gradle
├─ build.gradle
└─ settings.gradlepackage com.neurallinker.app
import android.os.Bundle
import android.os.VibrationEffect
import android.os.Vibrator
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
lateinit var webView: WebView
lateinit var eegManager: EEGManager
lateinit var brainIA: BrainIA
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
webView = findViewById(R.id.webview)
webView.settings.javaScriptEnabled = true
webView.settings.domStorageEnabled = true
webView.webViewClient = WebViewClient()
webView.loadUrl("file:///android_asset/www/index.html")
val bridge = AndroidBridge(this, webView)
webView.addJavascriptInterface(bridge, "Android")
// Initialisation EEG
eegManager = EEGManager(this) { eegData ->
val state = brainIA.predict(eegData)
bridge.sendStateToJS(state)
bridge.provideFeedback(state)
}
// IA locale
brainIA = BrainIA(this)
// Démarrer EEG Bluetooth
eegManager.start()
}
}package com.neurallinker.app
import android.content.Context
import android.os.VibrationEffect
import android.os.Vibrator
import android.webkit.WebView
import android.webkit.JavascriptInterface
class AndroidBridge(val context: Context, val webView: WebView) {
@JavascriptInterface
fun showMessage(msg: String) {
android.util.Log.d("JS_BRIDGE", msg)
}
fun sendStateToJS(state: String){
webView.post {
webView.evaluateJavascript("window.onBrainState('$state')", null)
}
}
fun provideFeedback(state: String){
val vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
when(state){
"ACTIVATE" -> vibrator.vibrate(VibrationEffect.createOneShot(50, 200))
"REST" -> vibrator.vibrate(VibrationEffect.createOneShot(20, 100))
"FOCUS" -> vibrator.vibrate(VibrationEffect.createOneShot(30, 150))
}
}
}package com.neurallinker.app
import android.content.Context
class EEGManager(val context: Context, val callback: (EEGData) -> Unit) {
fun start(){
// TODO: implémenter Bluetooth EEG pour Muse/NeuroSky
// Exemple : lecture d'échantillons simulés
Thread {
while(true){
val eeg = EEGData(
alpha = Math.random().toFloat(),
beta = Math.random().toFloat(),
theta = Math.random().toFloat(),
attention = Math.random().toFloat()
)
callback(eeg)
Thread.sleep(200)
}
}.start()
}
}
data class EEGData(
val alpha: Float,
val beta: Float,
val theta: Float,
val attention: Float
){
fun toFloatArray() = floatArrayOf(alpha,beta,theta,attention)
}package com.neurallinker.app
import android.content.Context
import org.tensorflow.lite.Interpreter
import java.io.FileInputStream
import java.nio.MappedByteBuffer
import java.nio.channels.FileChannel
class BrainIA(val context: Context) {
private val interpreter: Interpreter = Interpreter(loadModelFile("eeg_model.tflite"))
private fun loadModelFile(filename: String): MappedByteBuffer {
val file = context.assets.openFd(filename)
val input = FileInputStream(file.fileDescriptor)
val channel = input.channel
return channel.map(FileChannel.MapMode.READ_ONLY, file.startOffset, file.declaredLength)
}
fun predict(eeg: EEGData): String {
val input = arrayOf(eeg.toFloatArray())
val output = Array(1){ FloatArray(3) }
interpreter.run(input, output)
val predicted = output[0].indices.maxBy { output[0][it] }
return when(predicted){
0 -> "REST"
1 -> "FOCUS"
2 -> "ACTIVATE"
else -> "UNKNOWN"
}
}
}
<title>NeuralLinker Demo</title>if(state === "ACTIVATE"){
btn.textContent = "ON"
btn.classList.remove("bg-blue-500")
btn.classList.add("bg-green-500")
status.textContent = "Activation détectée !"
} else if(state === "REST"){
btn.textContent = "OFF"
btn.classList.remove("bg-green-500")
btn.classList.add("bg-blue-500")
status.textContent = "Repos détecté"
} else if(state === "FOCUS"){
status.textContent = "Concentration détectée"
}
}
<title>NeuralLinker Advanced BCI</title>