@@ -4,17 +4,59 @@ import android.app.*
44import android.content.Context
55import android.content.Intent
66import android.graphics.Color
7+ import android.hardware.Sensor
8+ import android.hardware.SensorEvent
9+ import android.hardware.SensorEventListener
10+ import android.hardware.SensorManager
711import android.os.Build
812import android.os.IBinder
13+ import android.util.Log
14+ import android.widget.Toast
915import androidx.annotation.RequiresApi
16+ import weka.classifiers.Classifier
17+ import weka.core.*
18+ import java.io.IOException
19+ import java.util.*
1020
11- class SensorService : Service () {
21+ class SensorService : Service (), SensorEventListener {
22+ private val samplingRate = SensorManager .SENSOR_DELAY_GAME
1223
24+ private val sitting: String = " sitting"
25+ private val walking: String = " walking"
26+ private val running: String = " running"
27+
28+ private lateinit var gyroscope: Sensor
29+ private lateinit var accelerometer: Sensor
30+ private lateinit var sensorManager: SensorManager
1331 private var thread: Thread ? = null
1432
33+ private val windowSize = 100
34+ private val strideSize = 20
35+ private val processor = Processor (windowSize, strideSize)
36+ private var stop_count = 0
37+ private var not_stop_count = 0
38+
39+ private val xAttr = Attribute (" x" )
40+ private val yAttr = Attribute (" y" )
41+ private val zAttr = Attribute (" z" )
42+ private val attributes = ArrayList (listOf (xAttr, yAttr, zAttr))
43+
44+ private val labelList: ArrayList <String > = ArrayList (
45+ listOf (
46+ sitting,
47+ walking,
48+ running
49+ )
50+ )
51+
52+ var labelAttr: Attribute ? = null
53+ val initialInstancesSize = 2000
54+ private val inferenceSegment = Instances (" inference" , attributes, initialInstancesSize)
55+
56+ private lateinit var assetClassifier: Classifier
57+
1558 companion object {
1659 private const val ONGOING_NOTIFICATION_ID = 1
17- private const val CHANNEL_DEFAULT_IMPORTANCE = " healthbuzz.channel"
1860 }
1961
2062 override fun onBind (intent : Intent ): IBinder ? {
@@ -54,17 +96,28 @@ class SensorService : Service() {
5496
5597 // Notification ID cannot be 0.
5698 startForeground(ONGOING_NOTIFICATION_ID , notification)
99+ // thread = Thread {
100+ // SensorThread.run(this)
101+ // }
102+ // thread?.start()
57103
58- thread = Thread {
59- SensorThread .run (this )
60- }
61- thread?.start()
104+ sensorManager = getSystemService(SENSOR_SERVICE ) as SensorManager
105+ accelerometer = sensorManager.getDefaultSensor(Sensor .TYPE_ACCELEROMETER )
106+ gyroscope = sensorManager.getDefaultSensor(Sensor .TYPE_GYROSCOPE )
107+
108+ loadModel(" rf.model" )
109+ Log .d(TAG , " Load model finished" )
110+
111+ sensorManager.registerListener(this , accelerometer, samplingRate)
112+ sensorManager.registerListener(this , gyroscope, samplingRate)
62113 return START_STICKY
63114 }
64115
65116 override fun onDestroy () {
66117 super .onDestroy()
67- thread?.interrupt()
118+ // thread?.interrupt()
119+ sensorManager.unregisterListener(this , accelerometer)
120+ sensorManager.unregisterListener(this , gyroscope)
68121 }
69122
70123 @RequiresApi(Build .VERSION_CODES .O )
@@ -79,4 +132,79 @@ class SensorService : Service() {
79132 service.createNotificationChannel(chan)
80133 return channelId
81134 }
135+
136+ override fun onSensorChanged (event : SensorEvent ? ) {
137+ if (event?.sensor == accelerometer) {
138+ val sample: Instance = DenseInstance (attributes.size)
139+ for (i in event.values.indices) {
140+ sample.setValue(i, event.values[i].toDouble())
141+ }
142+ handleInference(sample)
143+ } else if (event?.sensor == gyroscope) {
144+ val sample: Instance = DenseInstance (attributes.size)
145+ for (i in event.values.indices) {
146+ sample.setValue(i, event.values[i].toDouble())
147+ }
148+ handleInference(sample)
149+ }
150+ }
151+
152+ override fun onAccuracyChanged (sensor : Sensor ? , accuracy : Int ) {
153+ // TODO("Not yet implemented")
154+ }
155+
156+ private fun handleInference (sample : Instance ) {
157+ inferenceSegment.add(sample)
158+ if (inferenceSegment.size >= windowSize) {
159+ val features: Instances = processor.extractFeaturesAndAddLabels(inferenceSegment, - 1 )
160+ inferenceSegment.clear()
161+ val feature = features[0 ]
162+
163+ try {
164+
165+ // int prediction = (int)classifier.classifyInstance(feature);
166+ val prediction = assetClassifier.classifyInstance(feature).toInt()
167+ // inferenceResultView.setText(labelList.get(prediction));
168+ Log .d(" stop_count" , stop_count.toString())
169+ Log .d(" prediction" , prediction.toString())
170+ if (prediction == 0 ) {
171+ stop_count + = 1
172+ not_stop_count = 0
173+ if (stop_count > 50 ) {
174+ // TODO("Show notification channel")
175+ // https://developer.android.com/training/notify-user/build-notification
176+ Log .d(TAG , " You need to move $stop_count " )
177+ // inferenceResultView.setText("you need to move")
178+ } else {
179+ Log .d(TAG , " val:${labelList[prediction]} " )
180+ // inferenceResultView.setText(labelList[prediction])
181+ }
182+ } else {
183+ not_stop_count + = 1
184+ if (not_stop_count >= 5 ) {
185+ stop_count = 0
186+ }
187+ Log .d(TAG , " val:${labelList[prediction]} " )
188+ // inferenceResultView.setText(labelList[prediction])
189+ }
190+ } catch (e: Exception ) {
191+ Log .d(TAG , e.toString())
192+ Toast .makeText(applicationContext, " Inference failed!" , Toast .LENGTH_SHORT ).show()
193+ }
194+ }
195+ }
196+
197+ private fun loadModel (model_name : String ) {
198+ Log .d(" load_asset_model" , " loading the model from asset folder" )
199+ val assetManager = assets
200+ try {
201+ assetClassifier = SerializationHelper .read(assetManager.open(model_name)) as Classifier
202+ } catch (e: IOException ) {
203+ Log .e(TAG , " Failed to load" , e)
204+ } catch (e: Exception ) {
205+ Log .e(TAG , " Failed to load " , e)
206+ }
207+ Toast .makeText(this , " Model loaded" , Toast .LENGTH_SHORT ).show()
208+ }
209+
82210}
0 commit comments