diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e348435..e66c2b5 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -4,6 +4,7 @@ + diff --git a/app/src/main/java/com/example/greenwatch/AudiodetectionActivity.java b/app/src/main/java/com/example/greenwatch/AudiodetectionActivity.java index 06913c8..a4b0f80 100644 --- a/app/src/main/java/com/example/greenwatch/AudiodetectionActivity.java +++ b/app/src/main/java/com/example/greenwatch/AudiodetectionActivity.java @@ -1,27 +1,111 @@ package com.example.greenwatch; import androidx.appcompat.app.AppCompatActivity; +import androidx.lifecycle.Observer; +import androidx.lifecycle.ViewModelProvider; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import android.hardware.SensorManager; import android.os.Bundle; import android.view.View; import android.widget.Button; +import android.widget.TextView; +import android.widget.Toast; + +import com.example.greenwatch.adapters.AlarmHistoryListAdapter; +import com.example.greenwatch.adapters.DeviceListAdapter; +import com.example.greenwatch.models.Device; +import com.example.greenwatch.viewmodels.AccelerometerViewModel; +import com.example.greenwatch.viewmodels.MicrofonViewModel; + +import java.util.List; public class AudiodetectionActivity extends AppCompatActivity { - + private TextView microfonStatusMessage; private Button backToMainActivityButton; + private MicrofonViewModel mMicrofonViewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_audiodetection); + microfonStatusMessage = (TextView) findViewById(R.id.tvAudiodetectionStatusmessage); backToMainActivityButton = (Button) findViewById(R.id.audiodetectorBackToMainActivity); + RecyclerView recyclerView = findViewById(R.id.deviceListRecyclerView); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + recyclerView.setHasFixedSize(true); + + final DeviceListAdapter deviceListAdapter = new DeviceListAdapter(); + recyclerView.setAdapter(deviceListAdapter); + + RecyclerView alarmHistoryListRecyclerView = findViewById(R.id.alarmHistoryListRecyclerView); + alarmHistoryListRecyclerView.setLayoutManager(new LinearLayoutManager(this)); + alarmHistoryListRecyclerView.setHasFixedSize(true); + + final AlarmHistoryListAdapter alarmHistoryListAdapter = new AlarmHistoryListAdapter(); + alarmHistoryListRecyclerView.setAdapter(alarmHistoryListAdapter); + backToMainActivityButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finish(); } }); + + mMicrofonViewModel = new ViewModelProvider(this).get(MicrofonViewModel.class); + mMicrofonViewModel.init(); + mMicrofonViewModel.getConnectedDeviceList().observe(this, new Observer>() { + @Override + public void onChanged(List devices) { + deviceListAdapter.setDevices(devices); + } + }); + + mMicrofonViewModel.getAlarmHistoryList().observe(this, new Observer>() { + @Override + public void onChanged(List devices) { + alarmHistoryListAdapter.setAlarmHistoryList(devices); + } + }); + + mMicrofonViewModel.getStartAlarmRecording().observe(this, new Observer() { + @Override + public void onChanged(Boolean aBoolean) { + if (aBoolean) { + Toast.makeText(AudiodetectionActivity.this, "Start Alarm Recording", Toast.LENGTH_LONG).show(); + } + else { + Toast.makeText(AudiodetectionActivity.this, "Stop Alarm Recording", Toast.LENGTH_LONG).show(); + } + } + }); + + mMicrofonViewModel.getMicrofonAlarmDetected().observe(this, new Observer() { + @Override + public void onChanged(Boolean aBoolean) { + if (aBoolean) { + mMicrofonViewModel.updateDevice(mMicrofonViewModel.getLocalDeviceUUID(), mMicrofonViewModel.getSystemTimeStamp(), true, "Microfon", (int) mMicrofonViewModel.getAmplitudeInDB()); + } + else { + mMicrofonViewModel.updateDevice(mMicrofonViewModel.getLocalDeviceUUID(), mMicrofonViewModel.getSystemTimeStamp(), false, "Microfon", (int) mMicrofonViewModel.getAmplitudeInDB()); + } + + } + }); + } + + @Override + protected void onResume() { + super.onResume(); + mMicrofonViewModel.startMicrofonSensor(); + } + + @Override + protected void onPause() { + super.onPause(); + mMicrofonViewModel.stopMicrofonSensor(); } } \ No newline at end of file diff --git a/app/src/main/java/com/example/greenwatch/MainActivity.java b/app/src/main/java/com/example/greenwatch/MainActivity.java index 683f40c..d878ff7 100644 --- a/app/src/main/java/com/example/greenwatch/MainActivity.java +++ b/app/src/main/java/com/example/greenwatch/MainActivity.java @@ -58,6 +58,7 @@ public class MainActivity extends AppCompatActivity { mMainActivityViewModel = new ViewModelProvider(this).get(MainActivityViewModel.class); mMainActivityViewModel.init(); mMainActivityViewModel.accessRequestCamera(this); + mMainActivityViewModel.accessRequestMicrofon(this); mMainActivityViewModel.getConnectedDeviceList().observe(this, new Observer>() { @Override public void onChanged(List devices) { @@ -87,8 +88,12 @@ public class MainActivity extends AppCompatActivity { audiodetectionButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - //openAudiodetectionActivity(); - mMainActivityViewModel.updateDevice(mMainActivityViewModel.getLocalDeviceUUID(), "10:51", false, "Audio", 10); + if (mMainActivityViewModel.isMicrofonAccessAllowed(MainActivity.this)) { + openAudiodetectionActivity(); + } + else { + mMainActivityViewModel.accessRequestMicrofon(MainActivity.this); + } } }); videodetectionButton.setOnClickListener(new View.OnClickListener() { diff --git a/app/src/main/java/com/example/greenwatch/sensors/MicrofonHelperClasses/GleitenderMittelwert.java b/app/src/main/java/com/example/greenwatch/sensors/MicrofonHelperClasses/GleitenderMittelwert.java new file mode 100644 index 0000000..3dfd410 --- /dev/null +++ b/app/src/main/java/com/example/greenwatch/sensors/MicrofonHelperClasses/GleitenderMittelwert.java @@ -0,0 +1,23 @@ +package com.example.greenwatch.sensors.MicrofonHelperClasses; + +public class GleitenderMittelwert { + private final float wichtungNeuerWert; + private final float wichtungAlterWert; + private float mittelwert = 0; + + private boolean istMittelwertGesetzt = false; + + public GleitenderMittelwert(float wichtungNeuerWert) { + this.wichtungNeuerWert = wichtungNeuerWert; + this.wichtungAlterWert = 1 - this.wichtungNeuerWert; + } + + public float mittel(float wert) { + if (istMittelwertGesetzt) { + mittelwert = wert * wichtungNeuerWert + mittelwert * wichtungAlterWert; + } else { + mittelwert = wert; + istMittelwertGesetzt = true; + } + return mittelwert; + }} diff --git a/app/src/main/java/com/example/greenwatch/sensors/MicrofonHelperClasses/RingPuffer.java b/app/src/main/java/com/example/greenwatch/sensors/MicrofonHelperClasses/RingPuffer.java new file mode 100644 index 0000000..bd5d7cc --- /dev/null +++ b/app/src/main/java/com/example/greenwatch/sensors/MicrofonHelperClasses/RingPuffer.java @@ -0,0 +1,38 @@ +package com.example.greenwatch.sensors.MicrofonHelperClasses; + +public class RingPuffer { + + private short[] puffer; + private final int laenge; + private int anzahlEnthaltenerDaten; + private int position; + + + public RingPuffer(int n) { + laenge = n; + anzahlEnthaltenerDaten = 0; + position = 0; + puffer = new short[laenge]; + } + + public void hinzufuegen(short wert) { + puffer[position] = wert; + position++; + if (position >= laenge) { + position = 0; + } + if (anzahlEnthaltenerDaten < laenge) { + anzahlEnthaltenerDaten++; + } + } + + public short maximum() { + short max = 0; + for (int i = 0; i < anzahlEnthaltenerDaten; i++) { + if (puffer[i] > max) { + max = puffer[i]; + } + } + return max; + } +} diff --git a/app/src/main/java/com/example/greenwatch/sensors/MicrofonHelperClasses/Verarbeitungsergebnis.java b/app/src/main/java/com/example/greenwatch/sensors/MicrofonHelperClasses/Verarbeitungsergebnis.java new file mode 100644 index 0000000..672773d --- /dev/null +++ b/app/src/main/java/com/example/greenwatch/sensors/MicrofonHelperClasses/Verarbeitungsergebnis.java @@ -0,0 +1,37 @@ +package com.example.greenwatch.sensors.MicrofonHelperClasses; + +public class Verarbeitungsergebnis { + private String status; + private short maxAmp; + private float db; + // + public Verarbeitungsergebnis(String status, short maxAmp, int db) { + this.status = status; + this.maxAmp = maxAmp; + this.db = db; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public short getMaxAmp() { + return maxAmp; + } + + public void setMaxAmp(short maxAmp) { + this.maxAmp = maxAmp; + } + + public float getDB() { + return db; + } + + public void setDB(float db) { + this.db = db; + } +} diff --git a/app/src/main/java/com/example/greenwatch/sensors/MicrofonSensor.java b/app/src/main/java/com/example/greenwatch/sensors/MicrofonSensor.java new file mode 100644 index 0000000..8f1270d --- /dev/null +++ b/app/src/main/java/com/example/greenwatch/sensors/MicrofonSensor.java @@ -0,0 +1,202 @@ +package com.example.greenwatch.sensors; + +import android.media.AudioFormat; +import android.media.AudioRecord; +import android.media.MediaRecorder; +import android.os.AsyncTask; + +import androidx.lifecycle.MutableLiveData; + +import com.example.greenwatch.sensors.MicrofonHelperClasses.GleitenderMittelwert; +import com.example.greenwatch.sensors.MicrofonHelperClasses.RingPuffer; +import com.example.greenwatch.sensors.MicrofonHelperClasses.Verarbeitungsergebnis; + + public class MicrofonSensor { + + private MutableLiveData mMicrofonAlarmDetected = new MutableLiveData<>(); + private AufnahmeTask aufnahmeTask; + private static MicrofonSensor microfonSensorInstance; + private boolean microfonAlarmDetected = false; + private boolean kalibrierung_do = true; + private float threshold = 40; + private float sensitivity = 5; + + private float amplitudeInDB = 0; + + private RingPuffer ringPuffer = new RingPuffer(10); + + private MicrofonSensor() { + } + + public static synchronized MicrofonSensor getInstance() { + if (microfonSensorInstance == null){ + microfonSensorInstance = new MicrofonSensor(); + } + return microfonSensorInstance; + } + + public void start() { + aufnahmeTask = new AufnahmeTask(); + aufnahmeTask.execute(); + } + + public void stop() { + if(aufnahmeTask !=null) { + aufnahmeTask.cancel(true); + aufnahmeTask = null; + } + } + + public void doRecalibration() { + stop(); + microfonAlarmDetected = false; + kalibrierung_do = true; + threshold = 40; + sensitivity = 5; + amplitudeInDB = 0; + start(); + } + + public float getAmplitudeInDB() { + return amplitudeInDB; + } + + private void setAmplitudeInDB(float amplitudeInDB) { + this.amplitudeInDB = amplitudeInDB; + } + + public MutableLiveData getAccelerometerAlarmDetected() { + setMutableLiveDataMicrofonAlarmDetected(); + return mMicrofonAlarmDetected; + } + + private void setMutableLiveDataMicrofonAlarmDetected() { + mMicrofonAlarmDetected.setValue(microfonAlarmDetected); + } + + class AufnahmeTask extends AsyncTask { + private AudioRecord recorder; + private final int sampleRateInHz = 44100; + private final int channelConfig = AudioFormat.CHANNEL_IN_MONO; + private final int audioFormat = AudioFormat.ENCODING_PCM_16BIT; + private int minPufferGroesseInBytes; + private int pufferGroesseInBytes; + public AufnahmeTask() { + minPufferGroesseInBytes = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat); + pufferGroesseInBytes = minPufferGroesseInBytes * 2; + recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRateInHz, channelConfig, audioFormat, pufferGroesseInBytes); + } + public float kalibrieren(short[] puffer){ + try { + Thread.sleep(3000); + + } catch (InterruptedException e) { + e.printStackTrace(); + } + int anzahlIterationen = 100; + float sum = 0.0f; + for(int i = 0; i < anzahlIterationen; i++){ + int z = recorder.read(puffer, 0, puffer.length); + Verarbeitungsergebnis kalibrierung = verarbeiten(puffer, z); + sum += kalibrierung.getDB(); + } + return sum/anzahlIterationen; + } + + public void Detektion(Verarbeitungsergebnis ergebnis){ + if(ergebnis.getDB() >= (threshold+sensitivity)){ + microfonAlarmDetected = true; + } + else if (ergebnis.getDB() <= (threshold)) { + microfonAlarmDetected = false; + } + } + + @Override + protected Void doInBackground(Long... params) { + + recorder.startRecording(); + short[] puffer = new short[pufferGroesseInBytes / 2]; + GleitenderMittelwert gleitenderMittelwertdB = new GleitenderMittelwert(0.2f); + float db = 0.0f; + + //kalibrierung + if(kalibrierung_do){ + threshold = kalibrieren(puffer); + kalibrierung_do = false; + } + + + for (; ; ) { + if (isCancelled()) { + break; + } + else { + //ergebnis ermitteln + int n = recorder.read(puffer, 0, puffer.length); + Verarbeitungsergebnis ergebnis = verarbeiten(puffer, n); + + //Mittelwertberechnnung + db = ergebnis.getDB(); + db = gleitenderMittelwertdB.mittel(db); + ergebnis.setDB(db); + + //Db Wert mit Schwellwert vergleichen und Warnung setzen + Detektion(ergebnis); + publishProgress(ergebnis); + + try { + Thread.sleep(10); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + recorder.release(); + return null; + } + + private Verarbeitungsergebnis verarbeiten(short[] daten, int n) { + String status; + short maxAmp = -1; + int db = 0, db_wert = 0; + + if (n == AudioRecord.ERROR_INVALID_OPERATION) { + status = "ERROR_INVALID_OPERATION"; + } else if (n == AudioRecord.ERROR_BAD_VALUE) { + status = "ERROR_BAD_VALUE"; + } else { + status = "OK"; + short max = 0; + for (int i = 0; i < n; i++) { + if (daten[i] > max) { + max = daten[i]; + } + } + ringPuffer.hinzufuegen(max); + maxAmp = ringPuffer.maximum(); + } + //Umwandlung Amplitudenwert in dB + db_wert = (int) (20*Math.log10(maxAmp)); + if (db_wert > 0){ + db = db_wert; + } + + + return new Verarbeitungsergebnis(status, maxAmp, db); + } + @Override + protected void onProgressUpdate(Verarbeitungsergebnis... progress) { + super.onProgressUpdate(progress); + + setAmplitudeInDB(progress[0].getDB()); + + if (microfonAlarmDetected != mMicrofonAlarmDetected.getValue()){ + setMutableLiveDataMicrofonAlarmDetected(); + } + //textViewMaxAmpdb.setText("" + progress[0].db); + } + + } +} + diff --git a/app/src/main/java/com/example/greenwatch/viewmodels/AccelerometerViewModel.java b/app/src/main/java/com/example/greenwatch/viewmodels/AccelerometerViewModel.java index 344480f..bc8fcff 100644 --- a/app/src/main/java/com/example/greenwatch/viewmodels/AccelerometerViewModel.java +++ b/app/src/main/java/com/example/greenwatch/viewmodels/AccelerometerViewModel.java @@ -11,7 +11,6 @@ import com.example.greenwatch.sensors.AccelerometerSensor; import java.util.List; public class AccelerometerViewModel extends ViewModel implements ViewModelInterface { - private MutableLiveData> mDeviceList; private MutableLiveData mAccelerometerAlarmDetected; private MutableLiveData> mAlarmHistoryList; diff --git a/app/src/main/java/com/example/greenwatch/viewmodels/MainActivityViewModel.java b/app/src/main/java/com/example/greenwatch/viewmodels/MainActivityViewModel.java index 8f74ef1..a4446db 100644 --- a/app/src/main/java/com/example/greenwatch/viewmodels/MainActivityViewModel.java +++ b/app/src/main/java/com/example/greenwatch/viewmodels/MainActivityViewModel.java @@ -1,5 +1,6 @@ package com.example.greenwatch.viewmodels; +import android.Manifest; import android.app.Activity; import android.content.Context; import android.content.pm.PackageManager; @@ -23,6 +24,7 @@ public class MainActivityViewModel extends ViewModel implements ViewModelInterfa private MutableLiveData mStartAlarmRecording; private DeviceRepository mDeviceRepository; private static final int RIGHTS_REQUEST_CAMERA = 10; + private static final int RIGHTS_REQUEST_CAMERA_MICROFON = 1; @Override public void init() { @@ -41,6 +43,14 @@ public class MainActivityViewModel extends ViewModel implements ViewModelInterfa mStartAlarmRecording = mDeviceRepository.getStartAlarmRecording(); } + public boolean isMicrofonAccessAllowed(Context context) { + return ContextCompat.checkSelfPermission(context, android.Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED; + } + + public void accessRequestMicrofon(Activity activity) { + ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.RECORD_AUDIO}, RIGHTS_REQUEST_CAMERA_MICROFON); + } + public boolean isCameraAccessAllowed(Context context) { return ContextCompat.checkSelfPermission(context, android.Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED; } diff --git a/app/src/main/java/com/example/greenwatch/viewmodels/MicrofonViewModel.java b/app/src/main/java/com/example/greenwatch/viewmodels/MicrofonViewModel.java new file mode 100644 index 0000000..1a48e53 --- /dev/null +++ b/app/src/main/java/com/example/greenwatch/viewmodels/MicrofonViewModel.java @@ -0,0 +1,142 @@ +package com.example.greenwatch.viewmodels; + +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.ViewModel; + +import com.example.greenwatch.models.Device; +import com.example.greenwatch.repositories.DeviceRepository; +import com.example.greenwatch.sensors.MicrofonSensor; + +import java.util.List; + +public class MicrofonViewModel extends ViewModel implements ViewModelInterface { + private MutableLiveData> mDeviceList; + private MutableLiveData mMicrofonAlarmDetected; + private MutableLiveData> mAlarmHistoryList; + private MutableLiveData mStartAlarmRecording; + private MicrofonSensor mMicrofonSensor; + private DeviceRepository mDeviceRepository; + + @Override + public void init() { + if (mDeviceRepository == null) { + mDeviceRepository = DeviceRepository.getInstance(); + } + if (mMicrofonSensor == null) { + mMicrofonSensor = MicrofonSensor.getInstance(); + } + if (mDeviceList == null) { + mDeviceList = mDeviceRepository.getConnectedDeviceList(); + } + if (mAlarmHistoryList == null) { + mAlarmHistoryList = mDeviceRepository.getAlarmHistoryDeviceList(); + } + if (mStartAlarmRecording == null) { + mStartAlarmRecording = mDeviceRepository.getStartAlarmRecording(); + } + if (mMicrofonAlarmDetected == null) { + mMicrofonAlarmDetected = mMicrofonSensor.getAccelerometerAlarmDetected(); + } + } + + public void startMicrofonSensor() { + mMicrofonSensor.start(); + } + + public void stopMicrofonSensor() { + mMicrofonSensor.stop(); + } + + public void recalibrationMicrofonSensor() { + mMicrofonSensor.doRecalibration(); + } + + public float getAmplitudeInDB() { + return mMicrofonSensor.getAmplitudeInDB(); + } + + public LiveData getMicrofonAlarmDetected() { + return mMicrofonAlarmDetected; + } + + @Override + public LiveData> getConnectedDeviceList() { + return mDeviceList; + } + + @Override + public LiveData> getAlarmHistoryList() { + return mAlarmHistoryList; + } + + @Override + public LiveData getStartAlarmRecording() { + return mStartAlarmRecording; + } + + @Override + public void updateDevice(String deviceID, String timeStamp, boolean sensorStatus, String sensorType, int sensorMassage) { + mDeviceRepository.updateDevice(deviceID, timeStamp, sensorStatus, sensorType, sensorMassage); + } + + @Override + public void setTimeStamp(String deviceID, String timeStamp) { + mDeviceRepository.setTimeStamp(deviceID, timeStamp); + } + + @Override + public String getTimeStamp(String deviceID) { + return mDeviceRepository.getTimeStamp(deviceID); + } + + @Override + public void setDeviceID(String deviceID, String newDeviceID) { + mDeviceRepository.setDeviceID(deviceID, newDeviceID); + } + + @Override + public String getDeviceID(String deviceID) { + return mDeviceRepository.getDeviceID(deviceID); + } + + @Override + public void setSensorStatus(String deviceID, boolean sensorStatus) { + mDeviceRepository.setSensorStatus(deviceID, sensorStatus); + } + + @Override + public boolean getSensorStatus(String deviceID) { + return mDeviceRepository.getSensorStatus(deviceID); + } + + @Override + public void setSensorType(String deviceID, String sensorType) { + mDeviceRepository.setSensorType(deviceID, sensorType); + } + + @Override + public String getSensorType(String deviceID) { + return mDeviceRepository.getSensorType(deviceID); + } + + @Override + public void setSensorMassage(String deviceID, int sensorMessage) { + mDeviceRepository.setSensorMassage(deviceID, sensorMessage); + } + + @Override + public int getSensorMassage(String deviceID) { + return mDeviceRepository.getSensorMassage(deviceID); + } + + @Override + public String getLocalDeviceUUID() { + return mDeviceRepository.getLocalDeviceUUID(); + } + + @Override + public String getSystemTimeStamp() { + return mDeviceRepository.getSystemTimeStamp(); + } +} diff --git a/app/src/main/res/layout/activity_audiodetection.xml b/app/src/main/res/layout/activity_audiodetection.xml index 12ffd4a..95ca5e4 100644 --- a/app/src/main/res/layout/activity_audiodetection.xml +++ b/app/src/main/res/layout/activity_audiodetection.xml @@ -12,7 +12,7 @@ android:id="@+id/tvAudiodetectionStatusmessage" android:layout_width="match_parent" android:layout_height="wrap_content" - android:text="Audiodetection Activity"> + android:text=""> + + + + + + + + + + \ No newline at end of file