diff --git a/app/src/main/java/com/example/ueberwachungssystem/Detection/DetectionReport.java b/app/src/main/java/com/example/ueberwachungssystem/Detection/DetectionReport.java new file mode 100644 index 0000000..6e80a74 --- /dev/null +++ b/app/src/main/java/com/example/ueberwachungssystem/Detection/DetectionReport.java @@ -0,0 +1,57 @@ +package com.example.ueberwachungssystem.Detection; + +import android.annotation.SuppressLint; +import android.util.Log; + +import com.example.ueberwachungssystem.WifiCommunication; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + +/** Detection Report Class */ +public class DetectionReport { + public String timeStamp; + public String detectionType; + public float detectedValue; + public boolean detectionState; + + public DetectionReport(boolean detectionState, String detectionType, float detectedAmplitude) { + // New Date Format + @SuppressLint("SimpleDateFormat") SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss"); + Date curDate = new Date(System.currentTimeMillis()); + this.timeStamp = formatter.format(curDate); + //Old Date Format: this.timeStamp = String.valueOf(Calendar.getInstance().getTime()); + this.detectionType = detectionType; + this.detectedValue = detectedAmplitude; + this.detectionState = detectionState; + + //this.detectorID = detectorID; + } + + + /** Get Detection Report in String format */ + public String toString() { + String state = "State: " + "[" + this.detectionState + "]"; + String time = "Time: " + "[" + this.timeStamp + "]"; + String type = "Type: " + "[" + this.detectionType + "]"; + String value = "Value: " + "[" + this.detectedValue + "]"; + + return String.join("\t", state, time, type, value); + } + + public String toMessage() { + String state; + if(detectionState) + state = "An"; + else + state = "Aus"; + + return String.join(",", "1", timeStamp, "Gruppe2", WifiCommunication.getLocalIpAddress(), state, detectionType, String.valueOf(detectedValue)); + } + + /** 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/Detection/DetectorService.java b/app/src/main/java/com/example/ueberwachungssystem/Detection/DetectorService.java new file mode 100644 index 0000000..7613614 --- /dev/null +++ b/app/src/main/java/com/example/ueberwachungssystem/Detection/DetectorService.java @@ -0,0 +1,167 @@ +package com.example.ueberwachungssystem.Detection; + +import android.content.Intent; +import android.os.Binder; +import android.os.IBinder; +import android.util.Log; +import android.widget.ImageView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.camera.core.ExperimentalGetImage; +import androidx.lifecycle.LifecycleService; + +import com.example.ueberwachungssystem.WifiCommunication; + +import java.io.File; + +@ExperimentalGetImage +public class DetectorService extends LifecycleService { + public ServiceBinder serviceBinder = new ServiceBinder(); + private DetectorService.OnDetectionListener listener; + private boolean isServiceRunning = false; + + // Used Objects: + public VideoDetector videoDetector = null; + public AudioRecorder audioRecorder = null; + public Accelerometer motionDetector = null; + public MicrophoneDetector audioDetector = null; + + public WifiCommunication wifiCommunication; + + String wifiData; + StringBuffer stringBufferWifi = new StringBuffer(); + + String typOfAlarm; + + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + if (isServiceRunning) + return START_NOT_STICKY; + + /** Wifi Instanz **/ + wifiCommunication = new WifiCommunication(1234); + wifiCommunication.sendTrue("TEst"); + + wifiCommunication.setOnConnectionListener(new WifiCommunication.OnConnectionListener() { + @Override + public void onConnection(String data) { + Log.d("Listener", data); + wifiData = data; + stringToStringbuffer(data); + Log.d("buffer",stringBufferWifi.toString()); + passToServiceListener(stringBufferWifi); + checkState(data); + checkTyp(data); + + } + }); + + + + + + /** Video Detection/Recorder **/ + videoDetector = new VideoDetector(this); + videoDetector.setOnDetectionListener(new Detector.OnDetectionListener() { + @Override + public void onDetection(@NonNull DetectionReport detectionReport) { + //passToServiceListener(detectionReport); + wifiCommunication.sendTrue(detectionReport.toMessage()); + } + }); + /** Motion Detection**/ + motionDetector = new Accelerometer(this); + motionDetector.getSensor(); + motionDetector.setOnDetectionListener(new Detector.OnDetectionListener() { + @Override + public void onDetection(@NonNull DetectionReport detectionReport) { + //passToServiceListener(detectionReport); + wifiCommunication.sendTrue(detectionReport.toMessage()); + } + }); + /** Audio Detection **/ + audioDetector = new MicrophoneDetector(this); + audioDetector.setOnDetectionListener(new Detector.OnDetectionListener() { + @Override + public void onDetection(@NonNull DetectionReport detectionReport) { + //passToServiceListener(detectionReport); + wifiCommunication.sendTrue(detectionReport.toMessage()); + } + }); + /** Audio Recorder**/ + audioRecorder = new AudioRecorder(this); + + + + + + + isServiceRunning = true; + return super.onStartCommand(intent, flags, startId); + } + + @Override + public void onDestroy() { + super.onDestroy(); + isServiceRunning = false; + } + + /** Service methods */ + public class ServiceBinder extends Binder { + public DetectorService getBoundService() { + // Return an instance of the TestService + return DetectorService.this; + } + } + @Nullable + @Override + public IBinder onBind(Intent intent) { + super.onBind(intent); + return serviceBinder; + } + + + /** Pass Detection Report to Service Detection Listener and trigger it */ + public void passToServiceListener(StringBuffer stringBuffer) { + if (listener != null) { + listener.onDetection(stringBuffer); + } + } + + + /** On Detection Listener - runs when violation is reported */ + public interface OnDetectionListener { + void onDetection(@NonNull StringBuffer stringBuffer); + } + public void setOnDetectionListener(@NonNull DetectorService.OnDetectionListener listener) { + this.listener = listener; + } + + public void stringToStringbuffer(String string){ + if(string != null) { + stringBufferWifi.insert(0,string + "\n"); + } + } + + public String[] splitString(String string){ + String[] splitrxString = string.split(","); + return splitrxString; //splitrxString[0] = "1",splitrxString[1] = "HH:MM:SS", splitrxString[0].equals("1") + + } + + + public boolean checkState(String string){ + Log.d("state", String.valueOf(splitString(string)[4].equals("An"))); + return splitString(string)[4].equals("An"); + } + + public String checkTyp(String string){ + if (splitString(string)[5] != null) { + typOfAlarm = splitString(string)[5]; + Log.d("Type", typOfAlarm); + } + return typOfAlarm; + } +} diff --git a/app/src/main/java/com/example/ueberwachungssystem/Detection/MicrophoneDetector.java b/app/src/main/java/com/example/ueberwachungssystem/Detection/MicrophoneDetector.java new file mode 100644 index 0000000..697a732 --- /dev/null +++ b/app/src/main/java/com/example/ueberwachungssystem/Detection/MicrophoneDetector.java @@ -0,0 +1,365 @@ +package com.example.ueberwachungssystem.Detection; + +import static java.lang.Math.*; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.media.AudioFormat; +import android.media.AudioRecord; +import android.media.MediaRecorder; +import android.os.AsyncTask; +import android.util.Log; + +import com.example.ueberwachungssystem.Detection.Signalverarbeitung.Complex; +import com.example.ueberwachungssystem.Detection.Signalverarbeitung.FFT; + +public class MicrophoneDetector extends Detector { + /** + * Constructor - takes context of current activity + * + * @param context + */ + + private AufnahmeTask aufnahmeTask; + public boolean armed = false; + public int schwellwertAlarm = 100; + private Context context; + + public MicrophoneDetector(Context context) { + super(); + this.context = context; + } + + @Override + public void startDetection() { + aufnahmeTask = new AufnahmeTask(); + aufnahmeTask.execute(); + } + + @Override + public void stopDetection() { + if (aufnahmeTask != null) { + aufnahmeTask.cancel(true); + } + } + + 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 final int startDelay = 20000; + private final int threadSleeptime = 10; + private int minPufferGroesseInBytes; + private int pufferGroesseInBytes; + private RingPuffer ringPuffer = new RingPuffer(10); + private float kalibierWert; + private com.example.ueberwachungssystem.Detection.DetectionReport detectionReport; + + + + @SuppressLint("MissingPermission") + AufnahmeTask() { + minPufferGroesseInBytes = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat); + pufferGroesseInBytes = minPufferGroesseInBytes * 2; + try { + recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRateInHz, channelConfig, audioFormat, pufferGroesseInBytes); + } catch (Exception e) { + e.printStackTrace(); + } + Log.d("0","Puffergroeße: "+ minPufferGroesseInBytes + " " + pufferGroesseInBytes); + Log.d("0","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(); + } + + 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(); + } + + Log.d("0","Konfiguration: "+ s); + + } + + @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); + + //Kalibrierung + try { + Thread.sleep(startDelay); // Time to lay down the phone + } catch (InterruptedException e) { + e.printStackTrace(); + } + int i = 0; + for (i = 0; i < 20; i++) { + int n = recorder.read(puffer, 0, puffer.length); + Verarbeitungsergebnis kalibrierErgebnis = verarbeiten(puffer, n); + kalibierWert += kalibrierErgebnis.maxAmp; + try { + Thread.sleep(threadSleeptime); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + kalibierWert = kalibierWert/i; + +// __Part of FFT__ +// Complex[] zeitSignal = new Complex[puffer.length]; +// for (int j = 0; j < puffer.length; j++) { +// zeitSignal[j] = new Complex(puffer[j], 0); +// } +// Complex[] spektrum = FFT.fft(zeitSignal); +// double[] spektrum = calculateFFT(puffer); +// DataPoint AddPoint; +// LineGraphSeries series = new LineGraphSeries(new DataPoint[]{}); +// for (i = 0; i < spektrum.length; i++) { +// AddPoint = new DataPoint(i, spektrum[i]); +// series.appendData(AddPoint, true, spektrum.length); +// } +// graph.addSeries(series); + + for (; ; ) { + if (aufnahmeTask.isCancelled()) { + break; + } else { + int n = recorder.read(puffer, 0, puffer.length); + Verarbeitungsergebnis ergebnis = verarbeiten(puffer, n); + anzahlVerarbeitet += n; + +// __Part of FFT__ +// spektrum = calculateFFT(puffer); +// LineGraphSeries newseries = new LineGraphSeries(new DataPoint[]{}); +// for (i = 0; i < spektrum.length; i++) { +// AddPoint = new DataPoint(i, spektrum[i]); +// newseries.appendData(AddPoint, true, spektrum.length); +// } + + 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; + } + + + ergebnis.verarbeitungsrate = (int) verarbeitungsrate; + publishProgress(ergebnis); + + try { + Thread.sleep(threadSleeptime); + } 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(); + if (maxAmp <= schwellwertAlarm + kalibierWert) { + armed = true; + } + } + + return new Verarbeitungsergebnis(status, maxAmp, 0); + } + + @Override + protected void onProgressUpdate(Verarbeitungsergebnis... progress) { + super.onProgressUpdate(progress); + float maxAmpPrint = round(20*log10(abs(progress[0].maxAmp/1.0))); + float kalibierWertPrint = round(20*log10(abs(kalibierWert))); + Log.d("alarmAudio","VR: " + progress[0].verarbeitungsrate + ", Amp: " + maxAmpPrint + + " dB, Kal: " + kalibierWertPrint + " dB"); + + if (progress[0].maxAmp >= schwellwertAlarm + kalibierWert && armed == true) { + armed = false; + detectionReport = new DetectionReport(true, "Audio", maxAmpPrint); + reportViolation("Audio", maxAmpPrint); + Log.d("1",detectionReport.toString()); + } + } + } + + private double[] calculateFFT(short[] zeitsignal) + { + byte signal[] = new byte[zeitsignal.length]; + // loops through all the values of a Short + for (int i = 0; i < zeitsignal.length-1; i++) { + signal[i] = (byte) (zeitsignal[i]); + signal[i+1] = (byte) (zeitsignal[i] >> 8); + } + + final int mNumberOfFFTPoints =1024; + + double temp; + Complex[] y; + Complex[] complexSignal = new Complex[mNumberOfFFTPoints]; + double[] absSignal = new double[mNumberOfFFTPoints/2]; + + for(int i = 0; i < mNumberOfFFTPoints; i++){ + temp = (double)((signal[2*i] & 0xFF) | (signal[2*i+1] << 8)) / 32768.0F; + complexSignal[i] = new Complex(temp,0.0); + } + + y = FFT.fft(complexSignal); + + for(int i = 0; i < (mNumberOfFFTPoints/2); i++) + { + absSignal[i] = y[i].abs(); + } + + return absSignal; + + } + + class Verarbeitungsergebnis { + String status; + short maxAmp; + int verarbeitungsrate; + Verarbeitungsergebnis(String status, short maxAmp, int verarbeitungsrate) { + this.status = status; + this.maxAmp = maxAmp; + this.verarbeitungsrate = verarbeitungsrate; + } + } + + 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 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/Detection/VideoDetector.java b/app/src/main/java/com/example/ueberwachungssystem/Detection/VideoDetector.java new file mode 100644 index 0000000..75ca0fb --- /dev/null +++ b/app/src/main/java/com/example/ueberwachungssystem/Detection/VideoDetector.java @@ -0,0 +1,332 @@ +package com.example.ueberwachungssystem.Detection; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.pm.PackageManager; +import android.graphics.ImageFormat; +import android.media.Image; +import android.os.CountDownTimer; +import android.util.Log; +import android.view.Display; +import android.view.Surface; +import android.view.WindowManager; +import android.widget.ImageView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.camera.core.CameraSelector; +import androidx.camera.core.ExperimentalGetImage; +import androidx.camera.core.ImageAnalysis; +import androidx.camera.core.ImageProxy; +import androidx.camera.core.Preview; +import androidx.camera.core.VideoCapture; +import androidx.camera.lifecycle.ProcessCameraProvider; +import androidx.camera.view.PreviewView; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; +import androidx.lifecycle.LifecycleOwner; + +import com.google.common.util.concurrent.ListenableFuture; + +import org.opencv.android.OpenCVLoader; +import org.opencv.core.Mat; +import org.opencv.core.Size; + +import java.io.File; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.concurrent.ExecutionException; + + +/** + * Video Detector inherits some methods from abstract Detector class (more info there) + * */ + + +@ExperimentalGetImage +public class VideoDetector extends Detector { + // Calling Activity + private final Context context; + + // Camera Provider + private ProcessCameraProvider cameraProvider; + private ImageAnalysis imageAnalysis; + private VideoCapture videoCapture; + //private Preview preview; + + // Logic + private boolean isDetecting = false; + private boolean isRecording = false; + private boolean allowReportViolation = false; + + // Image Processing + private Mat previousImage = null; + + // Debugging + private ImageView inputImageView = null; + private ImageView outputImageView = null; + + // Recorder + private File outputDir; // Default: in app files directory + + + // Parameters + private static final float ALARM_THRESHOLD = 0f; // Percent of pixels changed + private static final float AREA_THRESHOLD = 10f; + private static final int DILATE_ITERATIONS = 2; + private static final float START_DELAY = 20000; // milliseconds + private static final android.util.Size IMAGE_RES = new android.util.Size(640, 480); + + + + /** Constructor */ + public VideoDetector(Context context) { + super(); + this.context = context; + this.imageAnalysis = setupImageAnalysis(); + this.videoCapture = setupVideoCapture(); + this.outputDir = context.getFilesDir(); + //this.preview = new Preview.Builder().build(); + } + + /** Get States */ + public boolean isDetecting() { + return isDetecting; + } + public boolean isRecording(){ + return isRecording; + } + + + /** Starts the Video Detection */ + @Override + public void startDetection() { + // Check States + if (isDetecting) + return; + // Configure Image Analysis + imageAnalysis = setupImageAnalysis(); + // Open CV startup check + if (!OpenCVLoader.initDebug()) { + Log.e("OpenCV", "Unable to load OpenCV!"); + return; + } else + Log.d("OpenCV", "OpenCV loaded Successfully!"); + // Get Process Camera Provider and start + final ListenableFuture cameraProviderFuture = ProcessCameraProvider.getInstance(context); + cameraProviderFuture.addListener(() -> { + try { + cameraProvider = cameraProviderFuture.get(); + isDetecting = true; + bindCameraProvider(); + } catch (ExecutionException | InterruptedException e) {} + }, ContextCompat.getMainExecutor(context)); + // Disable Violation Calling for Setup Time + startViolationTimer(START_DELAY); + } + + /** Starts the Recorder */ + @SuppressLint("RestrictedApi") + public void startRecording() { + // Check States + if (isRecording){ + return; + } + + videoCapture = setupVideoCapture(); + + final ListenableFuture cameraProviderFuture = ProcessCameraProvider.getInstance(context); + cameraProviderFuture.addListener(() -> { + try { + cameraProvider = cameraProviderFuture.get(); + isRecording = true; + bindCameraProvider(); + + File vidFile = new File(context.getFilesDir() + "/" + generateFileName() + ".mp4"); + if (ActivityCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { + return; + } + videoCapture.startRecording( + new VideoCapture.OutputFileOptions.Builder(vidFile).build(), + context.getMainExecutor(), + new VideoCapture.OnVideoSavedCallback() { + @Override + public void onVideoSaved(@NonNull VideoCapture.OutputFileResults outputFileResults) { + isRecording = false; + Toast.makeText(context, "video recording saved", Toast.LENGTH_SHORT).show(); + } + @Override + public void onError(int videoCaptureError, @NonNull String message, @Nullable Throwable cause) { + isRecording = false; + Toast.makeText(context, "video recording failed", Toast.LENGTH_SHORT).show(); + } + } + ); + } catch (ExecutionException | InterruptedException ignored) {} + }, ContextCompat.getMainExecutor(context)); + } + + /** Stops the Video Detection */ + @Override + public void stopDetection() { + if (!isDetecting || imageAnalysis == null) + return; + if (!isRecording) + cameraProvider.unbindAll(); + else + cameraProvider.unbind(imageAnalysis); + isDetecting = false; + allowReportViolation = false; + } + + /** Stops the Recording */ + @SuppressLint("RestrictedApi") + public void stopRecording(){ + if(!isRecording) + return; + + videoCapture.stopRecording(); + + if (!isDetecting()) + cameraProvider.unbindAll(); + else + cameraProvider.unbind(videoCapture); + isRecording = false; + } + + /** Bind Camera Provider */ + private void bindCameraProvider() { + // Specify which Camera to use + CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build(); + cameraProvider.unbindAll(); + cameraProvider.bindToLifecycle((LifecycleOwner) context, cameraSelector, imageAnalysis, videoCapture); + } + + /** Setup Use Cases */ + private ImageAnalysis setupImageAnalysis() { + // Configure and create Image Analysis + ImageAnalysis.Builder builder = new ImageAnalysis.Builder(); + builder.setTargetResolution(IMAGE_RES); + builder.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST); + builder.setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_YUV_420_888); + builder.setTargetRotation(Surface.ROTATION_90); + ImageAnalysis imageAnalysis = builder.build(); + // Set Analyzer + imageAnalysis.setAnalyzer(ContextCompat.getMainExecutor(context), imageProxy -> { + if (imageProxy.getFormat() == ImageFormat.YUV_420_888) { + Image image = imageProxy.getImage(); + assert image != null; + + // Violation Handling + Mat processed = processImage(imageProxy); + + int n = OpenCVHelper.countNonZeroPixels(processed); + int pixelCount = image.getWidth() * image.getHeight(); + float percentChanged = ((float) n / pixelCount) * 100; + + // Violation Condition + if (percentChanged> ALARM_THRESHOLD) { + if (allowReportViolation) + reportViolation("Video", percentChanged); + } + } + imageProxy.close(); + }); + return imageAnalysis; + } + + @SuppressLint("RestrictedApi") + private VideoCapture setupVideoCapture() { + int rotation = getDisplayRotation(); + return new VideoCapture.Builder() + .setTargetRotation(rotation) + .build(); + } + + /** Process Image to be used for Motion Detection */ + private Mat processImage(ImageProxy imageProxy){ + if (imageProxy == null) + return null; + // Image Transformation + Mat imageMat = OpenCVHelper.extractYChannel(imageProxy); + // Show Input Image + if (inputImageView != null) + OpenCVHelper.debugMat(imageMat, inputImageView); + // Preprocess Image + Mat preprocessed = imageMat; + preprocessed = OpenCVHelper.addGaussianBlur(preprocessed, new Size(21, 21)); + preprocessed = OpenCVHelper.addBlur(preprocessed, new Size(3, 3)); + // Set Previous Image + if (previousImage == null) { + previousImage = preprocessed; + return null; + } + // Process Image + Mat processed = preprocessed.clone(); + processed = OpenCVHelper.thresholdPixels(processed, previousImage, 25); + + for(int i = 0; i < DILATE_ITERATIONS; i++) + processed = OpenCVHelper.dilateBinaryMat(processed, new Size(3,3)); + + processed = OpenCVHelper.thresholdContourArea(processed, AREA_THRESHOLD); + // Output + previousImage = preprocessed.clone(); + // Show Output Image + if (outputImageView != null) + OpenCVHelper.debugMat(processed, outputImageView); + return processed; + } + + + /** Debug input and result of processing */ + public void debugProcessing(@NonNull ImageView inputImageView, @NonNull ImageView outputImageView){ + this.inputImageView = inputImageView; + this.outputImageView = outputImageView; + } + + /** + private void setPreviewView(@NonNull PreviewView previewView) { + // Create Preview + if (this.preview != null) + this.preview.setSurfaceProvider(previewView.getSurfaceProvider()); + } + */ + + + /** Generate File Name */ + private String generateFileName(){ + // Get the current timestamp + LocalDateTime currentTime = LocalDateTime.now(); + // Define the format for the timestamp + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"); + // Return the timestamp as a string + return currentTime.format(formatter); + } + + + /** Get current Display Rotation */ + private int getDisplayRotation() { + WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + Display display = windowManager.getDefaultDisplay(); + return display.getRotation(); + } + + /** Start delay until Violation Report is allowed */ + private void startViolationTimer(float setupTime) { + new CountDownTimer((long) (setupTime), 100) { + @Override + public void onTick(long millisUntilFinished) { + } + @Override + public void onFinish() { + allowReportViolation = true; + } + }.start(); + } + + public void setOutputDir(File outputDir) { + this.outputDir = outputDir; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java b/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java index be28406..392a306 100644 --- a/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java +++ b/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java @@ -3,17 +3,36 @@ package com.example.ueberwachungssystem; import androidx.camera.core.ExperimentalGetImage; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentTransaction; +import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; +import androidx.camera.core.ExperimentalGetImage; +import androidx.camera.view.PreviewView; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; import android.os.Bundle; +import android.os.IBinder; import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.TextView; +import android.widget.ImageView; +import android.widget.Toast; import android.widget.ToggleButton; import com.example.ueberwachungssystem.Fragments.Fragment1; import com.example.ueberwachungssystem.Fragments.Fragment2; +import com.example.ueberwachungssystem.Detection.Accelerometer; +import com.example.ueberwachungssystem.Detection.AudioRecorder; +import com.example.ueberwachungssystem.Detection.DetectionReport; +import com.example.ueberwachungssystem.Detection.Detector; +import com.example.ueberwachungssystem.Detection.DetectorService; +import com.example.ueberwachungssystem.Detection.MicrophoneDetector; +import com.example.ueberwachungssystem.Detection.VideoDetector; @ExperimentalGetImage public class MainActivity extends AppCompatActivity implements View.OnClickListener { @@ -22,6 +41,8 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe private Fragment1 fragment1; private Fragment2 fragment2; + private DetectorService detectorService = new DetectorService(); + int num=0; //Textviews private TextView Auswahl; private TextView AoderA; @@ -50,6 +71,148 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe } @Override + public void onClick(View v) { + if (v == toggleKamera) { + if (toggleKamera.isChecked()) { + vd.startDetection(); + } else { + vd.stopDetection(); + } + } + } + + @Override + protected void onResume() { + super.onResume(); + + PermissionHandler permissionHandler = new PermissionHandler(this); + //permissionHandler.getPermissions(); + if (permissionHandler.hasPermissions()) { + + Intent serviceIntent = new Intent(this, DetectorService.class); + bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE); + startService(serviceIntent); + + toggleButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (toggleButton.isChecked()) + { + if (detectorService != null){ + + detectorService.videoDetector.startDetection(); + + detectorService.audioDetector.startDetection(); + + detectorService.motionDetector.startDetection(); + + detectorService.audioRecorder.stopRecording(); + + detectorService.videoDetector.startRecording(); + } + } + else { + detectorService.videoDetector.stopDetection(); + + detectorService.audioDetector.stopDetection(); + + detectorService.motionDetector.stopDetection(); + + detectorService.audioRecorder.stopRecording(); + + detectorService.videoDetector.stopRecording(); + } + } + }); + }else{ + Toast.makeText(this,"Bitte Rechte geben", Toast.LENGTH_SHORT).show(); + } + + } + + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.options_menu, menu); + return true; + } + + public boolean onOptionsItemSelected(MenuItem item) { + Toast.makeText(this, "Selected Item: " + item.getTitle(), Toast.LENGTH_SHORT).show(); + PopUpClass popUpClass; + switch (item.getItemId()) { + case R.id.Rechteverwaltung: + popUpClass = new PopUpClass(MainActivity.this); + popUpClass.showPopupWindow(inputImageView); + popUpClass.RechtePrüfen(); + return true; + case R.id.Sensoren: + popUpClass = new PopUpClass(MainActivity.this); + popUpClass.showPopupWindow(inputImageView); + popUpClass.Sensoren(); + return true; + case R.id.Impressum: + popUpClass = new PopUpClass(MainActivity.this); + popUpClass.showPopupWindow(inputImageView); + popUpClass.Impressum(); + return true; + case R.id.Detection: + popUpClass = new PopUpClass(MainActivity.this); + popUpClass.showPopupWindow(inputImageView); + popUpClass.DetectionTotal(num); + return true; + default: + return super.onOptionsItemSelected(item); + } + } + + private ServiceConnection serviceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + DetectorService.ServiceBinder binder = (DetectorService.ServiceBinder) service; + detectorService = binder.getBoundService(); + detectorService.videoDetector.debugProcessing(null, outputImageView); //inputImageView + + detectorService.setOnDetectionListener(new DetectorService.OnDetectionListener() { + @Override + public void onDetection(@NonNull StringBuffer stringBuffer) { + Log.d("onDetection", stringBuffer.toString()); //Für oli hier Textview einbauen + num++; + } + }); + } + @Override + public void onServiceDisconnected(ComponentName name) { + } + }; + + public void onClickZeigeFragment1(View view) { + Button button = (Button) view; + zeigeFragment(fragment1.erstellen("Hier stehen dann die Alarme")); + } + + public void onClickZeigeFragment2(View view) { + Button button = (Button) view; + zeigeFragment(fragment2.erstellen("Hier stehen dann die Videos")); + } + + public void onClickEntferneFragment(View view) { + entferneFragment(); + } + + private void zeigeFragment(Fragment fragment) { + FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); + ft.replace(R.id.frame, fragment); + ft.commit(); + aktuellesFragment = fragment; + } + private void entferneFragment() { + if (aktuellesFragment != null) { + FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); + ft.remove(aktuellesFragment); + ft.commit(); + aktuellesFragment = null ; + } + } + @Override public void onClick(View v) { if (v == toggleKamera) { if (toggleKamera.isChecked()) { @@ -73,31 +236,4 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe } } } - public void onClickZeigeFragment1(View view) { - Button button = (Button) view; - zeigeFragment(fragment1.erstellen("Hier stehen dann die Alarme")); - } - - public void onClickZeigeFragment2(View view) { - Button button = (Button) view; - zeigeFragment(fragment2.erstellen("Hier stehen dann die Videos")); - } - - public void onClickEntferneFragment(View view) { - entferneFragment(); - } - private void zeigeFragment(Fragment fragment) { - FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); - ft.replace(R.id.frame, fragment); - ft.commit(); - aktuellesFragment = fragment; - } - private void entferneFragment() { - if (aktuellesFragment != null) { - FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); - ft.remove(aktuellesFragment); - ft.commit(); - aktuellesFragment = null ; - } - } } \ No newline at end of file diff --git a/app/src/main/java/com/example/ueberwachungssystem/PermissionRequest.java b/app/src/main/java/com/example/ueberwachungssystem/PermissionRequest.java index 6c66539..e7a56c0 100644 --- a/app/src/main/java/com/example/ueberwachungssystem/PermissionRequest.java +++ b/app/src/main/java/com/example/ueberwachungssystem/PermissionRequest.java @@ -35,7 +35,7 @@ public class PermissionRequest extends AppCompatActivity{ handler.post(new Runnable() { @Override public void run() { - Toast.makeText(mainActivity.getApplicationContext(),"Es werden Rechte benötigt", Toast.LENGTH_LONG).show(); + Toast.makeText(mainActivity.getApplicationContext(),"Es werden Rechte benötigt", Toast.LENGTH_SHORT).show(); } }); } diff --git a/app/src/main/java/com/example/ueberwachungssystem/PopUpClass.java b/app/src/main/java/com/example/ueberwachungssystem/PopUpClass.java index 9b1990a..9062729 100644 --- a/app/src/main/java/com/example/ueberwachungssystem/PopUpClass.java +++ b/app/src/main/java/com/example/ueberwachungssystem/PopUpClass.java @@ -15,6 +15,8 @@ public class PopUpClass { PermissionRequest permission; TextView PopUpText; + Button buttonEdit; + public PopUpClass(MainActivity mainActivity) { this.mainActivity = mainActivity; @@ -47,7 +49,7 @@ public class PopUpClass { PopUpText = popupView.findViewById(R.id.titleText); - Button buttonEdit = popupView.findViewById(R.id.RechteAnfordern); + buttonEdit = popupView.findViewById(R.id.RechteAnfordern); buttonEdit.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -70,17 +72,25 @@ public class PopUpClass { public void RechtePrüfen(){ StringBuilder Text = permission.rechtePruefen(); PopUpText.setText(Text); + buttonEdit.setVisibility(View.VISIBLE); + } public void RechteAnfordern(){ permission.rechteAnfordern(); StringBuilder Text = permission.rechtePruefen(); PopUpText.setText(Text); + } public void Sensoren(){ PopUpText.setText("Es können 3 verschiedene Sensoren verwendet werden \n -1. Beschleunigungssensor\n -2. Mikrofon\n -3. Kamera"); + buttonEdit.setVisibility(View.GONE); } public void Impressum(){ PopUpText.setText("Die Ueberwachungsapp wurde im Rahmen eines Praktikums der TH-Nürnberg programmiert"); + buttonEdit.setVisibility(View.GONE); + } + public void DetectionTotal(int num) { + PopUpText.setText("Total Detektions:" +num); + buttonEdit.setVisibility(View.GONE); } - } \ No newline at end of file diff --git a/app/src/main/java/com/example/ueberwachungssystem/WifiCommunication.java b/app/src/main/java/com/example/ueberwachungssystem/WifiCommunication.java index 731d46e..14f1329 100644 --- a/app/src/main/java/com/example/ueberwachungssystem/WifiCommunication.java +++ b/app/src/main/java/com/example/ueberwachungssystem/WifiCommunication.java @@ -1,8 +1,14 @@ package com.example.ueberwachungssystem; import android.annotation.SuppressLint; +import android.util.Log; +import android.widget.Toast; import androidx.annotation.NonNull; +import com.example.ueberwachungssystem.Detection.DetectionReport; +import com.example.ueberwachungssystem.Detection.Detector; +import com.example.ueberwachungssystem.Detection.DetectorService; + import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; @@ -25,6 +31,11 @@ public class WifiCommunication { private final DatagramSocket socket; volatile private boolean running; + private boolean Gruppe =true; + private boolean showMessage = true; + + StringBuffer rxStringBuffer = new StringBuffer(); + private OnConnectionListener listener; @SuppressLint("SetTextI18n") public WifiCommunication(int port) { @@ -46,20 +57,20 @@ public class WifiCommunication { } public interface OnConnectionListener { - void onConnection(StringBuffer data); + void onConnection(String data); } public void setOnConnectionListener(@NonNull OnConnectionListener listener) { this.listener = listener; } - public void sendWifiData(StringBuffer wifiMessage) { + public void sendWifiData(String wifiMessage) { if (listener != null) { listener.onConnection(wifiMessage); + } } private class ReceiveThread extends Thread { - private StringBuffer rxStringBuffer = new StringBuffer(); private String rxString=""; private String previousRxString = ""; @@ -72,11 +83,30 @@ public class WifiCommunication { socket.receive(rxPacket); rxString = new String(receiveData, 0, rxPacket.getLength()); String[] splitrxString = rxString.split(","); - if(!previousRxString.equals(rxString) && splitrxString[0].equals("1") && splitrxString.length==7) { - rxStringBuffer.append(rxString).append("\n"); - sendWifiData(rxStringBuffer); - //mainActivity.runOnUiThread(() -> mainActivity.tvMessages.setText(rxStringBuffer)); - previousRxString = rxString; + String[] splitrxStringBuffer = splitBufferIntoStrings(rxStringBuffer); + for(String elem: splitrxStringBuffer){ + if(elem.equals(rxString)){ + showMessage = false; + }else{ + showMessage = true; + } + } + if(Gruppe){ + if(!previousRxString.equals(rxString) && splitrxString[0].equals("1") && splitrxString.length==7 && showMessage) { + rxStringBuffer.append(rxString).append("\n"); + Log.d("empfangen", rxString); + sendWifiData(rxString); + //mainActivity.runOnUiThread(() -> mainActivity.tvMessages.setText(rxStringBuffer)); + previousRxString = rxString; + } + }else{ + if(!previousRxString.equals(rxString) && splitrxString[0].equals("1") && splitrxString.length==7 && showMessage) { + rxStringBuffer.append(rxString).append("\n"); + Log.d("empfangen", rxString); + sendWifiData(rxString); + //mainActivity.runOnUiThread(() -> mainActivity.tvMessages.setText(rxStringBuffer)); + previousRxString = rxString; + } } } while (running); } @@ -94,16 +124,17 @@ public class WifiCommunication { if(send) { send = false; - SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss"); + /*SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss"); Date curDate = new Date(System.currentTimeMillis()); - String str = formatter.format(curDate); + String str = formatter.format(curDate);*/ byte[] send_Data = new byte[512]; - String txString = ("1," +str+ ",Gruppe2," + getLocalIpAddress() + ",An,Video," +messageToSend); + String txString = (messageToSend); //"1," +str+ ",Gruppe2," + getLocalIpAddress() + ",An,Video," + Log.d("send", txString); send_Data = txString.getBytes(); DatagramPacket txPacket = new DatagramPacket(send_Data, txString.length(), address, port); - for(int i = 0; i < 300; i++) { + for(int i = 0; i < 500; i++) { socket.send(txPacket); } } @@ -138,4 +169,8 @@ public class WifiCommunication { running = false; socket.close(); } + public String[] splitBufferIntoStrings(StringBuffer string){ + String[] splitrxString2 = string.toString().split("\n"); + return splitrxString2; + } } diff --git a/app/src/main/res/menu/options_menu.xml b/app/src/main/res/menu/options_menu.xml index f2c05bf..ddb0237 100644 --- a/app/src/main/res/menu/options_menu.xml +++ b/app/src/main/res/menu/options_menu.xml @@ -4,6 +4,8 @@ android:title="Rechteverwaltung" /> + \ No newline at end of file