From d22952d83ba48cf918c453bdc80318e5473c551c Mon Sep 17 00:00:00 2001 From: Miguel Siebenhaar Date: Thu, 11 May 2023 15:38:14 +0200 Subject: [PATCH 01/65] Initial commit Project Version 0 --- .../main/java/com/example/ueberwachungssystem/MainActivity.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java b/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java index f4fdae7..483716e 100644 --- a/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java +++ b/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java @@ -10,5 +10,6 @@ public class MainActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); + // } } \ No newline at end of file From 90a2aad491038513c6e871739df5988a1e460d72 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 11 May 2023 16:21:59 +0200 Subject: [PATCH 02/65] new class Mikrofon --- .../main/java/com/example/ueberwachungssystem/Mikrofon.java | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 app/src/main/java/com/example/ueberwachungssystem/Mikrofon.java diff --git a/app/src/main/java/com/example/ueberwachungssystem/Mikrofon.java b/app/src/main/java/com/example/ueberwachungssystem/Mikrofon.java new file mode 100644 index 0000000..510d104 --- /dev/null +++ b/app/src/main/java/com/example/ueberwachungssystem/Mikrofon.java @@ -0,0 +1,4 @@ +package com.example.ueberwachungssystem; + +public class Mikrofon { +} From 620528302e929f634db62079325acf23a3c29994 Mon Sep 17 00:00:00 2001 From: Leon Market Date: Wed, 24 May 2023 20:39:31 +0200 Subject: [PATCH 03/65] added Beschleunigungssensor --- .../Beschleunigungssensor.java | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 app/src/main/java/com/example/ueberwachungssystem/Beschleunigungssensor.java diff --git a/app/src/main/java/com/example/ueberwachungssystem/Beschleunigungssensor.java b/app/src/main/java/com/example/ueberwachungssystem/Beschleunigungssensor.java new file mode 100644 index 0000000..e15dc5b --- /dev/null +++ b/app/src/main/java/com/example/ueberwachungssystem/Beschleunigungssensor.java @@ -0,0 +1,86 @@ +package com.example.ueberwachungssystem; + +import android.content.Context; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.os.Bundle; +import androidx.appcompat.app.AppCompatActivity; +import android.widget.TextView; +import com.example.ueberwachungssystem.Logger; + +public class Beschleunigungssensor extends AppCompatActivity implements SensorEventListener +{ + + private Logger logger; + private SensorManager sensorManager; + private int sensorType = Sensor.TYPE_ACCELEROMETER; + private Sensor sensor; + + @Override + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + setTitle(this.getClass().getSimpleName()); + TextView textView = new TextView(this); + setContentView(textView); + + logger = new Logger(this.getClass().getSimpleName(),textView,""); + + sensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE); + if(sensorManager.getSensorList(sensorType).size()==0) + { + logger.log("Es gibt den gewünschten Sensor nicht"); + sensor = null; + } + else + { + sensor = sensorManager.getSensorList(sensorType).get(0); + } + } + + @Override + protected void onResume() + { + super.onResume(); + if(sensor != null) + { + if(sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME)) + { + logger.log("Wir haben uns beim Sensor angemeldet."); + } + else + { + logger.log("Das Anmelden beim Sensor hat nicht so gut geklappt"); + } + } + } + + @Override + protected void onPause() + { + super.onPause(); + if(sensor != null) { + sensorManager.unregisterListener(this, sensor); + logger.log("Wir haben uns beim Sensor abgemeldet"); + } + } + + @Override + public void onSensorChanged(SensorEvent event) + { + StringBuilder sb = new StringBuilder(); + sb.append("t=").append(event.timestamp) + .append("\nx=").append(event.values[0]) + .append("\ny=").append(event.values[1]) + .append("\nz=").append(event.values[2]); + logger.clearLog(); + logger.log(sb.toString()); + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) + { + } +} From 4999f1b99827960a425da38f087b1ae13985f022 Mon Sep 17 00:00:00 2001 From: Leon Market Date: Wed, 24 May 2023 20:39:31 +0200 Subject: [PATCH 04/65] added Detector, DetectorReport, Logger --- .../Beschleunigungssensor.java | 83 +++++++++++++++++++ .../ueberwachungssystem/DetectionReport.java | 36 ++++++++ .../example/ueberwachungssystem/Detector.java | 39 +++++++++ .../example/ueberwachungssystem/Logger.java | 44 ++++++++++ .../ueberwachungssystem/MainActivity.java | 7 +- app/src/main/res/layout/activity_main.xml | 2 +- 6 files changed, 209 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/com/example/ueberwachungssystem/Beschleunigungssensor.java create mode 100644 app/src/main/java/com/example/ueberwachungssystem/DetectionReport.java create mode 100644 app/src/main/java/com/example/ueberwachungssystem/Detector.java create mode 100644 app/src/main/java/com/example/ueberwachungssystem/Logger.java diff --git a/app/src/main/java/com/example/ueberwachungssystem/Beschleunigungssensor.java b/app/src/main/java/com/example/ueberwachungssystem/Beschleunigungssensor.java new file mode 100644 index 0000000..f15ae8e --- /dev/null +++ b/app/src/main/java/com/example/ueberwachungssystem/Beschleunigungssensor.java @@ -0,0 +1,83 @@ +package com.example.ueberwachungssystem; + +import android.content.Context; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.os.Bundle; +import androidx.appcompat.app.AppCompatActivity; +import android.widget.TextView; + +public class Beschleunigungssensor extends AppCompatActivity implements SensorEventListener +{ + private Logger logger; + private SensorManager sensorManager; + private int sensorType = Sensor.TYPE_ACCELEROMETER; + private Sensor sensor; + + @Override + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + setTitle(this.getClass().getSimpleName()); + TextView textView = new TextView(this); + setContentView(textView); + + logger = new Logger(this.getClass().getSimpleName(),textView,""); + + sensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE); + if(sensorManager.getSensorList(sensorType).size()==0) + { + logger.log("Es gibt den gewünschten Sensor nicht"); + sensor = null; + } + else + { + sensor = sensorManager.getSensorList(sensorType).get(0); + } + } + + @Override + protected void onResume() + { + super.onResume(); + if(sensor != null) + { + if(sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME)) + { + logger.log("Wir haben uns beim Sensor angemeldet."); + } + else + { + logger.log("Das Anmelden beim Sensor hat nicht so gut geklappt"); + } + } + } + + @Override + protected void onPause() + { + super.onPause(); + if(sensor != null) { + sensorManager.unregisterListener(this, sensor); + logger.log("Wir haben uns beim Sensor abgemeldet"); + } + } + + @Override + public void onSensorChanged(SensorEvent event) + { + String sb = "t=" + event.timestamp + + "\nx=" + event.values[0] + // Wert legend: x = 0.04 + "\ny=" + event.values[1] + // Wert liegend: y = 0.44 + "\nz=" + event.values[2]; // Wert liegend: z = 9.90 = Erdbeschleunigung --> Wenn Ausrichtung unbekannt ist, müsste kalibrierung bei Start der Bewegungsüberwachung vorgenommen werden + logger.clearLog(); + logger.log(sb); + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) + { + } +} diff --git a/app/src/main/java/com/example/ueberwachungssystem/DetectionReport.java b/app/src/main/java/com/example/ueberwachungssystem/DetectionReport.java new file mode 100644 index 0000000..bfcb52c --- /dev/null +++ b/app/src/main/java/com/example/ueberwachungssystem/DetectionReport.java @@ -0,0 +1,36 @@ +package com.example.ueberwachungssystem; + +import android.util.Log; + +import java.util.Calendar; + +/** Detection Report Class */ +public class DetectionReport { + public String timeStamp; + public String detectionType; + public float detectedValue; + public String detectorID; + + public DetectionReport(String detectorID, String detectionType, float detectedAmplitude) { + this.timeStamp = String.valueOf(Calendar.getInstance().getTime()); + this.detectionType = detectionType; + this.detectedValue = detectedAmplitude; + this.detectorID = detectorID; + } + + + /** Get Detection Report in String format */ + public String toString() { + String time = "Time: " + "[" + this.timeStamp + "]"; + String type = "Type: " + "[" + this.detectionType + "]"; + String value = "Value: " + "[" + this.detectedValue + "]"; + String id = "ID: " + "[" + this.detectorID + "]"; + + return String.join("\t", time, type, value, id); + } + + /** Debug Report */ + public void log(String tag) { + Log.d(tag, this.toString()); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/ueberwachungssystem/Detector.java b/app/src/main/java/com/example/ueberwachungssystem/Detector.java new file mode 100644 index 0000000..d09fe1f --- /dev/null +++ b/app/src/main/java/com/example/ueberwachungssystem/Detector.java @@ -0,0 +1,39 @@ +package com.example.ueberwachungssystem; + +import android.content.Context; +import androidx.annotation.NonNull; + + +abstract public class Detector { + private OnDetectionListener listener; + + /** Constructor - takes context of current activity */ + public Detector(Context context) {}; + + + /** On Detection Listener - runs when violation is reported */ + public interface OnDetectionListener { + void onDetection(@NonNull DetectionReport detectionReport); + } + public void setOnDetectionListener(@NonNull OnDetectionListener listener) { + this.listener = listener; + } + + + /** Triggers onDetectionListener - call this to trigger violation/alarm */ + private void reportViolation(String detectorID, String detectionType, float amplitude) { + if (listener != null) { + DetectionReport detectionReport = new DetectionReport(detectorID, detectionType, amplitude); + listener.onDetection(detectionReport); + } else { + throw new IllegalStateException("No listener set for violation reporting"); + } + } + + + /** Starts Detection (abstract method: needs to be overridden in child class) */ + public abstract void startDetection(); + + /** Stops Detection (abstract method: needs to be overridden in child class) */ + public abstract void stopDetection(); +} \ No newline at end of file diff --git a/app/src/main/java/com/example/ueberwachungssystem/Logger.java b/app/src/main/java/com/example/ueberwachungssystem/Logger.java new file mode 100644 index 0000000..86299fb --- /dev/null +++ b/app/src/main/java/com/example/ueberwachungssystem/Logger.java @@ -0,0 +1,44 @@ +package com.example.ueberwachungssystem; + +import android.widget.TextView; +import android.util.Log; +import java.io.PrintWriter; +import java.io.StringWriter; + +public class Logger { + private TextView textView; + private StringBuffer sb = new StringBuffer(); + private String tag; + + public Logger(String tag, TextView textView, String logInitText) { + this.tag = tag; + this.textView = textView; + sb.append(logInitText); + } + + public void log(String s) { + Log.d(tag, s); + sb.append(s).append("\n"); + if (textView != null) { + textView.setText(sb.toString()); + } + } + public void log(Exception e) { + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + log(sw.toString()); + } + + public void clearLog() { + sb.setLength(0); + if (textView != null) { + textView.setText(""); + } + } + + public String getLoggedText() { + return sb.toString(); + } +} + + diff --git a/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java b/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java index f4fdae7..5a5c92a 100644 --- a/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java +++ b/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java @@ -4,11 +4,16 @@ import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; -public class MainActivity extends AppCompatActivity { +public class MainActivity extends AppCompatActivity{ + + private Logger logger; + private Beschleunigungssensor beschleunigungssensor; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + setTitle(this.getClass().getSimpleName()); setContentView(R.layout.activity_main); + } } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 17eab17..7762181 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -4,7 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".MainActivity"> + tools:context=".MainActivityBackup"> Date: Thu, 25 May 2023 16:58:08 +0200 Subject: [PATCH 05/65] Move from Mikrofon to MicrophoneDetector class and add of abstract Detector class --- app/src/main/AndroidManifest.xml | 7 + .../ueberwachungssystem/DetectionReport.java | 36 ++ .../example/ueberwachungssystem/Detector.java | 40 +++ .../ueberwachungssystem/MainActivity.java | 55 +++ .../MicrophoneDetector.java | 333 ++++++++++++++++++ .../example/ueberwachungssystem/Mikrofon.java | 325 +++++++++++++++++ .../ueberwachungssystem/logger/Logger.java | 61 ++++ app/src/main/res/layout/activity_main.xml | 14 +- 8 files changed, 869 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/com/example/ueberwachungssystem/DetectionReport.java create mode 100644 app/src/main/java/com/example/ueberwachungssystem/Detector.java create mode 100644 app/src/main/java/com/example/ueberwachungssystem/MicrophoneDetector.java create mode 100644 app/src/main/java/com/example/ueberwachungssystem/logger/Logger.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index cef8f3d..397d997 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,6 +2,13 @@ + + + + + + + { + 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; + private RingPuffer ringPuffer = new RingPuffer(10); + + AufnahmeTask() { + minPufferGroesseInBytes = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat); + pufferGroesseInBytes = minPufferGroesseInBytes * 2; + recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRateInHz, channelConfig, audioFormat, pufferGroesseInBytes); + +// textViewMinPufferGroesseInBytes.setText("" + minPufferGroesseInBytes); +// textViewPufferGroesseInBytes.setText("" + pufferGroesseInBytes); +// textViewAbtastrate.setText("" + recorder.getSampleRate()); +// textViewAnzahlKanaele.setText("" + recorder.getChannelCount()); + + logger.log("Puffergroeße: "+ minPufferGroesseInBytes + " " + pufferGroesseInBytes); + logger.log("Recorder (SR, CH): "+ recorder.getSampleRate() + " " + recorder.getChannelCount()); + + int anzahlBytesProAbtastwert; + String s; + switch (recorder.getAudioFormat()) { + case AudioFormat.ENCODING_PCM_8BIT: + s = "8 Bit PCM "; + anzahlBytesProAbtastwert = 1; + break; + case AudioFormat.ENCODING_PCM_16BIT: + s = "16 Bit PCM"; + anzahlBytesProAbtastwert = 2; + break; + case AudioFormat.ENCODING_PCM_FLOAT: + s = "Float PCM"; + anzahlBytesProAbtastwert = 4; + break; + default: + throw new IllegalArgumentException(); + } +// textViewAudioFormat.setText(s); + + switch (recorder.getChannelConfiguration()) { + case AudioFormat.CHANNEL_IN_MONO: + s = "Mono"; + break; + case AudioFormat.CHANNEL_IN_STEREO: + s = "Stereo"; + anzahlBytesProAbtastwert *= 2; + break; + case AudioFormat.CHANNEL_INVALID: + s = "ungültig"; + break; + default: + throw new IllegalArgumentException(); + } +// textViewKanalKonfiguration.setText(s); + logger.log("Konfiguration: "+ s); + + int pufferGroesseInAnzahlAbtastwerten = pufferGroesseInBytes / anzahlBytesProAbtastwert; + int pufferGroesseInMillisekunden = 1000 * pufferGroesseInAnzahlAbtastwerten / recorder.getSampleRate(); + +// textViewPufferGroesseInAnzahlAbtastwerte.setText("" + pufferGroesseInAnzahlAbtastwerten); +// textViewPufferGroesseInMillisekunden.setText("" + pufferGroesseInMillisekunden); + } + + @Override + protected Void doInBackground(Long... params) { + recorder.startRecording(); + short[] puffer = new short[pufferGroesseInBytes / 2]; + long lastTime = System.currentTimeMillis(); + float verarbeitungsrate = 0; + final int maxZaehlerZeitMessung = 10; + int zaehlerZeitMessung = 0; + int anzahlVerarbeitet = 0; + GleitenderMittelwert gleitenderMittelwert = new GleitenderMittelwert(0.3f); + + for (; ; ) { + if (aufnahmeTask.isCancelled()) { + break; + } else { + int n = recorder.read(puffer, 0, puffer.length); + Verarbeitungsergebnis ergebnis = verarbeiten(puffer, n); + anzahlVerarbeitet += n; + + zaehlerZeitMessung++; + if (zaehlerZeitMessung == maxZaehlerZeitMessung) { + long time = System.currentTimeMillis(); + long deltaTime = time - lastTime; + verarbeitungsrate = 1000.0f * anzahlVerarbeitet / deltaTime; + verarbeitungsrate = gleitenderMittelwert.mittel(verarbeitungsrate); + zaehlerZeitMessung = 0; + anzahlVerarbeitet = 0; + lastTime = time; + } + + float noiseLevel = gleitenderMittelwert.MittelwertPuffer(puffer); + + // logger.log("Noise Level:" + noiseLevel); + ergebnis.noiseLevel = noiseLevel; + ergebnis.verarbeitungsrate = (int) verarbeitungsrate; + publishProgress(ergebnis); + + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + recorder.release(); + return null; + } + + private Verarbeitungsergebnis verarbeiten(short[] daten, int n) { + String status; + short maxAmp = -1; + 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(); + } + + return new Verarbeitungsergebnis(status, maxAmp, 0, 0); + } + + @Override + protected void onProgressUpdate(Verarbeitungsergebnis... progress) { + super.onProgressUpdate(progress); +// textViewMaxAmp.setText("" + progress[0].maxAmp); +// textViewVerarbeitungsrate.setText("" + progress[0].verarbeitungsrate); + logger.overwriteLastlog("VR, Max, NL:" + progress[0].verarbeitungsrate + ", " + progress[0].maxAmp + + ", " + progress[0].noiseLevel); + + if (progress[0].maxAmp >= Schwellwert_Alarm) { + Alarm = true; + } + } + } + + class Verarbeitungsergebnis { + String status; + short maxAmp; + int verarbeitungsrate; + float noiseLevel; + + Verarbeitungsergebnis(String status, short maxAmp, int verarbeitungsrate, float noiseLevel) { + this.status = status; + this.maxAmp = maxAmp; + this.verarbeitungsrate = verarbeitungsrate; + this.noiseLevel = noiseLevel; + } + } + + 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 void hinzufuegen(short[] daten) { + for (short d : daten) { + puffer[position] = d; + position++; + if (position >= laenge) { + position = 0; + } + } + if (anzahlEnthaltenerDaten < laenge) { + anzahlEnthaltenerDaten += daten.length; + if (anzahlEnthaltenerDaten >= laenge) { + anzahlEnthaltenerDaten = laenge; + } + } + } + + public short maximum() { + short max = 0; + for (int i = 0; i < anzahlEnthaltenerDaten; i++) { + if (puffer[i] > max) { + max = puffer[i]; + } + } + return max; + } + + public float mittelwert() { + float summe = 0; + for (int i = 0; i < anzahlEnthaltenerDaten; i++) { + summe += puffer[i]; + } + return summe / anzahlEnthaltenerDaten; + } + } + + class GleitenderMittelwert { + private final float wichtungNeuerWert; + private final float wichtungAlterWert; + private float mittelwert = 0; + private boolean istMittelwertGesetzt = false; + + GleitenderMittelwert(float wichtungNeuerWert) { + this.wichtungNeuerWert = wichtungNeuerWert; + this.wichtungAlterWert = 1 - this.wichtungNeuerWert; + } + + float MittelwertPuffer(short[] puffer) { + + for (int i = 0; i < puffer.length; i++) { + mittelwert = Math.abs(puffer[i]); + } + mittelwert = mittelwert/puffer.length; + + return mittelwert; + } + + 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/ueberwachungssystem/Mikrofon.java b/app/src/main/java/com/example/ueberwachungssystem/Mikrofon.java index 510d104..2d3c815 100644 --- a/app/src/main/java/com/example/ueberwachungssystem/Mikrofon.java +++ b/app/src/main/java/com/example/ueberwachungssystem/Mikrofon.java @@ -1,4 +1,329 @@ package com.example.ueberwachungssystem; +import android.Manifest; +import android.app.Activity; +import android.content.Context; +import android.content.pm.PackageManager; +import android.media.AudioFormat; +import android.media.AudioRecord; +import android.media.MediaRecorder; +import android.os.AsyncTask; +import android.os.Bundle; +import android.os.Environment; +import android.widget.TextView; + +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; + +import com.example.ueberwachungssystem.logger.Logger; + +import java.io.File; + public class Mikrofon { + + Logger logger; + private static final int RECHTEANFORDERUNG_MIKROFON = 1; + + private Activity MainActivityForClass; + private AufnahmeTask aufnahmeTask; + public boolean Alarm = false; + public int Schwellwert_Alarm = 500; + + public void onCreate(Activity MainActivity, Logger MainLogger) { + MainActivityForClass = MainActivity; + logger = MainLogger; //Class uses the same logger as the MainActivity + logger.log(this.getClass().getSimpleName() + ".onCreate"); + + if (!istZugriffAufMikrofonErlaubt()) { + zugriffAufMikrofonAnfordern(); + } + } + + public void onResume() { + logger.log(this.getClass().getSimpleName() + ".onResume"); + if (!istZugriffAufMikrofonErlaubt()) { + zugriffAufMikrofonAnfordern(); + } + if (istZugriffAufMikrofonErlaubt()) { + aufnahmeTask = new AufnahmeTask(); + aufnahmeTask.execute(); + } + } + + public void onPause() { + logger.log(this.getClass().getSimpleName() + ".onPause"); + if(aufnahmeTask!=null) { + aufnahmeTask.cancel(true); + // aufnahmeTask = null; // if aufnahmeTask = null, break in for loop would not work (Nullpointer Exception) + } + } + + private boolean istZugriffAufMikrofonErlaubt() { + if (ContextCompat.checkSelfPermission(MainActivityForClass, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { + logger.log("Zugriff auf Mikrofon ist verboten."); + return false; + } else { + logger.log("Zugriff auf Mikrofon ist erlaubt."); + return true; + } + } + private void zugriffAufMikrofonAnfordern() { + ActivityCompat.requestPermissions(MainActivityForClass, new String[]{Manifest.permission.RECORD_AUDIO}, RECHTEANFORDERUNG_MIKROFON); + } + + 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; + private RingPuffer ringPuffer = new RingPuffer(10); + + AufnahmeTask() { + minPufferGroesseInBytes = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat); + pufferGroesseInBytes = minPufferGroesseInBytes * 2; + recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRateInHz, channelConfig, audioFormat, pufferGroesseInBytes); + +// textViewMinPufferGroesseInBytes.setText("" + minPufferGroesseInBytes); +// textViewPufferGroesseInBytes.setText("" + pufferGroesseInBytes); +// textViewAbtastrate.setText("" + recorder.getSampleRate()); +// textViewAnzahlKanaele.setText("" + recorder.getChannelCount()); + + logger.log("Puffergroeße: "+ minPufferGroesseInBytes + " " + pufferGroesseInBytes); + logger.log("Recorder (SR, CH): "+ recorder.getSampleRate() + " " + recorder.getChannelCount()); + + int anzahlBytesProAbtastwert; + String s; + switch (recorder.getAudioFormat()) { + case AudioFormat.ENCODING_PCM_8BIT: + s = "8 Bit PCM "; + anzahlBytesProAbtastwert = 1; + break; + case AudioFormat.ENCODING_PCM_16BIT: + s = "16 Bit PCM"; + anzahlBytesProAbtastwert = 2; + break; + case AudioFormat.ENCODING_PCM_FLOAT: + s = "Float PCM"; + anzahlBytesProAbtastwert = 4; + break; + default: + throw new IllegalArgumentException(); + } +// textViewAudioFormat.setText(s); + + switch (recorder.getChannelConfiguration()) { + case AudioFormat.CHANNEL_IN_MONO: + s = "Mono"; + break; + case AudioFormat.CHANNEL_IN_STEREO: + s = "Stereo"; + anzahlBytesProAbtastwert *= 2; + break; + case AudioFormat.CHANNEL_INVALID: + s = "ungültig"; + break; + default: + throw new IllegalArgumentException(); + } +// textViewKanalKonfiguration.setText(s); + logger.log("Konfiguration: "+ s); + + int pufferGroesseInAnzahlAbtastwerten = pufferGroesseInBytes / anzahlBytesProAbtastwert; + int pufferGroesseInMillisekunden = 1000 * pufferGroesseInAnzahlAbtastwerten / recorder.getSampleRate(); + +// textViewPufferGroesseInAnzahlAbtastwerte.setText("" + pufferGroesseInAnzahlAbtastwerten); +// textViewPufferGroesseInMillisekunden.setText("" + pufferGroesseInMillisekunden); + } + + @Override + protected Void doInBackground(Long... params) { + recorder.startRecording(); + short[] puffer = new short[pufferGroesseInBytes / 2]; + long lastTime = System.currentTimeMillis(); + float verarbeitungsrate = 0; + final int maxZaehlerZeitMessung = 10; + int zaehlerZeitMessung = 0; + int anzahlVerarbeitet = 0; + GleitenderMittelwert gleitenderMittelwert = new GleitenderMittelwert(0.3f); + + for (; ; ) { + if (aufnahmeTask.isCancelled()) { + break; + } else { + int n = recorder.read(puffer, 0, puffer.length); + Verarbeitungsergebnis ergebnis = verarbeiten(puffer, n); + anzahlVerarbeitet += n; + + zaehlerZeitMessung++; + if (zaehlerZeitMessung == maxZaehlerZeitMessung) { + long time = System.currentTimeMillis(); + long deltaTime = time - lastTime; + verarbeitungsrate = 1000.0f * anzahlVerarbeitet / deltaTime; + verarbeitungsrate = gleitenderMittelwert.mittel(verarbeitungsrate); + zaehlerZeitMessung = 0; + anzahlVerarbeitet = 0; + lastTime = time; + } + + float noiseLevel = gleitenderMittelwert.MittelwertPuffer(puffer); + + // logger.log("Noise Level:" + noiseLevel); + ergebnis.noiseLevel = noiseLevel; + ergebnis.verarbeitungsrate = (int) verarbeitungsrate; + publishProgress(ergebnis); + + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + recorder.release(); + return null; + } + + private Verarbeitungsergebnis verarbeiten(short[] daten, int n) { + String status; + short maxAmp = -1; + 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(); + } + + return new Verarbeitungsergebnis(status, maxAmp, 0, 0); + } + + @Override + protected void onProgressUpdate(Verarbeitungsergebnis... progress) { + super.onProgressUpdate(progress); +// textViewMaxAmp.setText("" + progress[0].maxAmp); +// textViewVerarbeitungsrate.setText("" + progress[0].verarbeitungsrate); + logger.overwriteLastlog("VR, Max, NL:" + progress[0].verarbeitungsrate + ", " + progress[0].maxAmp + + ", " + progress[0].noiseLevel); + + if (progress[0].maxAmp >= Schwellwert_Alarm) { + Alarm = true; + } + } + } + + class Verarbeitungsergebnis { + String status; + short maxAmp; + int verarbeitungsrate; + float noiseLevel; + + Verarbeitungsergebnis(String status, short maxAmp, int verarbeitungsrate, float noiseLevel) { + this.status = status; + this.maxAmp = maxAmp; + this.verarbeitungsrate = verarbeitungsrate; + this.noiseLevel = noiseLevel; + } + } + + 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 void hinzufuegen(short[] daten) { + for (short d : daten) { + puffer[position] = d; + position++; + if (position >= laenge) { + position = 0; + } + } + if (anzahlEnthaltenerDaten < laenge) { + anzahlEnthaltenerDaten += daten.length; + if (anzahlEnthaltenerDaten >= laenge) { + anzahlEnthaltenerDaten = laenge; + } + } + } + + public short maximum() { + short max = 0; + for (int i = 0; i < anzahlEnthaltenerDaten; i++) { + if (puffer[i] > max) { + max = puffer[i]; + } + } + return max; + } + + public float mittelwert() { + float summe = 0; + for (int i = 0; i < anzahlEnthaltenerDaten; i++) { + summe += puffer[i]; + } + return summe / anzahlEnthaltenerDaten; + } + } + + class GleitenderMittelwert { + private final float wichtungNeuerWert; + private final float wichtungAlterWert; + private float mittelwert = 0; + private boolean istMittelwertGesetzt = false; + + GleitenderMittelwert(float wichtungNeuerWert) { + this.wichtungNeuerWert = wichtungNeuerWert; + this.wichtungAlterWert = 1 - this.wichtungNeuerWert; + } + + float MittelwertPuffer(short[] puffer) { + + for (int i = 0; i < puffer.length; i++) { + mittelwert = Math.abs(puffer[i]); + } + mittelwert = mittelwert/puffer.length; + + return mittelwert; + } + + 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/ueberwachungssystem/logger/Logger.java b/app/src/main/java/com/example/ueberwachungssystem/logger/Logger.java new file mode 100644 index 0000000..07af51a --- /dev/null +++ b/app/src/main/java/com/example/ueberwachungssystem/logger/Logger.java @@ -0,0 +1,61 @@ +package com.example.ueberwachungssystem.logger; + +import android.util.Log; +import android.widget.TextView; + +import java.io.PrintWriter; +import java.io.StringWriter; + +public class Logger { + private TextView textView; + private StringBuffer sb = new StringBuffer(); + private String tag; + private int lengthOfLastLog = 0; + private boolean overwrite = false; + + public Logger(String tag, TextView textView, String logInitText) { + this.tag = tag; + this.textView = textView; + sb.append(logInitText); + } + + public void log(String s) { + overwrite = false; + Log.d(tag, s); + sb.append(s).append("\n"); + if (textView != null) { + textView.setText(sb.toString()); + } + } + + public void overwriteLastlog(String s) { + Log.d(tag, s); + lengthOfLastLog = s.length(); + if (overwrite) + { + sb.setLength(sb.length() - (lengthOfLastLog + 1)); + } + sb.append(s).append("\n"); + overwrite = true; + if (textView != null) { + textView.setText(sb.toString()); + } + } + + public void log(Exception e) { + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + log(sw.toString()); + } + + public void clearLog() { + sb.setLength(0); + if (textView != null) { + textView.setText(""); + } + } + + public String getLoggedText() { + return sb.toString(); + } +} diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 17eab17..bea580a 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -7,12 +7,22 @@ tools:context=".MainActivity"> + + \ No newline at end of file From 3c1366bd1075103819fdd31d102e75ac966301f2 Mon Sep 17 00:00:00 2001 From: Miguel Siebenhaar Date: Thu, 8 Jun 2023 17:40:21 +0200 Subject: [PATCH 06/65] Kommunikation Version 1 UDP Socket --- app/build.gradle | 4 + app/src/main/AndroidManifest.xml | 8 +- .../ueberwachungssystem/MainActivity.java | 69 +++++++++- .../WifiCommunication.java | 119 ++++++++++++++++++ app/src/main/res/layout/activity_main.xml | 41 +++--- settings.gradle | 1 + 6 files changed, 221 insertions(+), 21 deletions(-) create mode 100644 app/src/main/java/com/example/ueberwachungssystem/WifiCommunication.java diff --git a/app/build.gradle b/app/build.gradle index 631248a..1e4e000 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -26,6 +26,9 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + buildFeatures { + viewBinding true + } } dependencies { @@ -33,6 +36,7 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'com.google.android.material:material:1.8.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + implementation 'com.google.android.gms:play-services-nearby:18.0.0' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index cef8f3d..857fcad 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,18 +2,24 @@ + + + + + android:exported="true" + android:label="Server"> diff --git a/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java b/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java index 483716e..db6dac7 100644 --- a/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java +++ b/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java @@ -1,15 +1,74 @@ package com.example.ueberwachungssystem; - -import androidx.appcompat.app.AppCompatActivity; - +import android.annotation.SuppressLint; +import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; +import androidx.appcompat.app.AppCompatActivity; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.UnknownHostException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +@SuppressLint("SetTextI18n") public class MainActivity extends AppCompatActivity { + TextView tvMessages; + TextView tvConnectionInfos; + + WifiCommunication communication; + public static String SERVER_IP = ""; + public static final int SERVER_PORT = 2222; + int i=0; + + boolean sending = false; + + String message; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); - // + tvMessages = findViewById(R.id.tvMessages); + tvConnectionInfos = findViewById(R.id.tvConnectionInfos); + try { + SERVER_IP = getLocalIpAddress(); + tvConnectionInfos.setText("Connection Infos: \n Own IP-Adress: " + SERVER_IP+ " Port: " + SERVER_PORT); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + Button btnSend = findViewById(R.id.btnSend); + btnSend.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + i++; + communication.sendTrue("Test" +i); + } + }); } -} \ No newline at end of file + protected void onResume() { + super.onResume(); + communication = new WifiCommunication(MainActivity.this, SERVER_PORT); + + } + @Override + protected void onPause() { + super.onPause(); + communication.stopCommunication(); + } + private String getLocalIpAddress() throws UnknownHostException { + WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE); + assert wifiManager != null; + WifiInfo wifiInfo = wifiManager.getConnectionInfo(); + int ipInt = wifiInfo.getIpAddress(); + return InetAddress.getByAddress(ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(ipInt).array()).getHostAddress(); + } +} diff --git a/app/src/main/java/com/example/ueberwachungssystem/WifiCommunication.java b/app/src/main/java/com/example/ueberwachungssystem/WifiCommunication.java new file mode 100644 index 0000000..d0aad05 --- /dev/null +++ b/app/src/main/java/com/example/ueberwachungssystem/WifiCommunication.java @@ -0,0 +1,119 @@ +package com.example.ueberwachungssystem; +import android.annotation.SuppressLint; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.Inet4Address; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.util.Enumeration; + +public class WifiCommunication { + private final MainActivity mainActivity; + private final InetAddress address; + private final int port; + + private String messageToSend; + volatile private boolean send; + private final DatagramSocket socket; + volatile private boolean running; + @SuppressLint("SetTextI18n") + public WifiCommunication(MainActivity mainActivity, int port) { + this.mainActivity = mainActivity; + this.port = port; + try { + socket = new DatagramSocket(this.port); + socket.setBroadcast(true); + address = InetAddress.getByName("255.255.255.255"); + running = true; + send = false; + new ReceiveThread().start(); + new SendThread().start(); + } catch (SocketException | UnknownHostException e) { + throw new RuntimeException(e); + } + mainActivity.runOnUiThread(() -> mainActivity.tvMessages.setText("Communication running")); + } + private class ReceiveThread extends Thread { + private StringBuffer rxStringBuffer = new StringBuffer(); + private String rxString; + private String previousRxString = ""; + @Override + public void run() { + try { + do { + byte[] rxBuffer = new byte[512]; + InetAddress fromAdress; + int fromPort; + DatagramPacket rxPacket = new DatagramPacket(rxBuffer, rxBuffer.length); + socket.receive(rxPacket); + fromAdress = rxPacket.getAddress(); + fromPort = rxPacket.getPort(); + rxString = new String(rxBuffer, 0, rxPacket.getLength()); + if(!previousRxString.equals(rxString)) { + mainActivity.runOnUiThread(() -> mainActivity.tvMessages.setText(rxStringBuffer)); + rxStringBuffer.append("Adress: " + fromAdress).append(" Port: " + fromPort).append(" Message " +rxString).append("\n"); + } + previousRxString = rxString; + + } while (running); + } + catch (IOException e) { + e.printStackTrace(); + } + } + } + private class SendThread extends Thread { + private int tmpCnt = 0; + @Override + public void run() { + try { + do { + if(send) + { + send = false; + + String txString = getLocalIpAddress() + " sends:" +messageToSend+ " Count: " + tmpCnt++; + byte[] txBuffer = txString.getBytes(); + + DatagramPacket txPacket = new DatagramPacket(txBuffer, txBuffer.length, address, port); + + for(int i = 0; i < 20; i++) { + socket.send(txPacket); + } + } + } while (running); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + public static String getLocalIpAddress() { + try { + for (Enumeration en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) { + NetworkInterface networkInterface = (NetworkInterface) ((Enumeration) en).nextElement(); + for (Enumeration addresses = networkInterface.getInetAddresses(); addresses.hasMoreElements();) { + InetAddress inetAddress = addresses.nextElement(); + if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) { + return inetAddress.getHostAddress(); + } + } + } + } catch (SocketException ex) { + ex.printStackTrace(); + } + return null; + } + + public void sendTrue(String message){ + send = true; + messageToSend = message; + } + public void stopCommunication() { + running = false; + socket.close(); + } +} diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 17eab17..fd91a97 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,18 +1,29 @@ - - - + + + + +