diff --git a/app/build.gradle b/app/build.gradle
index a44d92a5..a745b749 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -34,6 +34,11 @@ def getGitHash = { ->
}
android {
+ packagingOptions {
+ resources {
+ excludes += ['META-INF/INDEX.LIST', 'META-INF/io.netty.versions.properties']
+ }
+ }
signingConfigs {
debug {
keyAlias keystoreProperties['keyAlias']
@@ -122,10 +127,18 @@ spdxSbom {
}
dependencies {
- implementation 'androidx.preference:preference:1.2.1'
- implementation 'androidx.work:work-runtime:2.10.0'
+ def work_version = "2.10.0"
def room_version = "2.6.1"
+ implementation "androidx.work:work-runtime:$work_version"
+ implementation "androidx.work:work-runtime-ktx:$work_version"
+ implementation "androidx.work:work-rxjava2:$work_version"
+ implementation "androidx.work:work-gcm:$work_version"
+ androidTestImplementation "androidx.work:work-testing:$work_version"
+ implementation "androidx.work:work-multiprocess:$work_version"
+ implementation 'com.google.android.flexbox:flexbox:3.0.0'
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.6.0"
+ implementation 'androidx.preference:preference:1.2.1'
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
implementation 'androidx.appcompat:appcompat:1.7.0'
@@ -149,7 +162,11 @@ dependencies {
implementation 'com.google.android.gms:play-services-location:21.3.0'
implementation 'com.github.anastr:speedviewlib:1.6.1'
implementation "androidx.viewpager2:viewpager2:1.1.0"
+ implementation "androidx.compose.material3:material3:1.3.0"
+ implementation("com.hivemq:hivemq-mqtt-client:1.3.4")
implementation "androidx.compose.material3:material3:1.3.1"
+ implementation("com.squareup.moshi:moshi:1.15.2")
+ implementation("com.squareup.moshi:moshi-adapters:1.8.0")
}
configurations.implementation {
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
index 9c325e21..09374eb0 100644
--- a/app/proguard-rules.pro
+++ b/app/proguard-rules.pro
@@ -29,4 +29,9 @@
-assumenosideeffects class android.util.Log {
public static *** d(...);
public static *** v(...);
-}
\ No newline at end of file
+}
+
+-keepclassmembernames class io.netty.** { *; }
+-keepclassmembers class org.jctools.** { *; }
+
+
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 4dddc0e6..b9fb0ab9 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -38,8 +38,8 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -128,6 +196,5 @@
-
\ No newline at end of file
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Application.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Application.java
new file mode 100644
index 00000000..c392e698
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Application.java
@@ -0,0 +1,15 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit;
+
+import androidx.annotation.NonNull;
+import androidx.work.Configuration;
+
+public class Application extends android.app.Application implements Configuration.Provider {
+ @NonNull
+ @Override
+ public Configuration getWorkManagerConfiguration() {
+ return new Configuration.Builder()
+ .setDefaultProcessName(getPackageName())
+ .setMinimumLoggingLevel(android.util.Log.DEBUG)
+ .build();
+ }
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/CustomEventListener.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/CustomEventListener.java
new file mode 100644
index 00000000..afff4596
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/CustomEventListener.java
@@ -0,0 +1,11 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit;
+
+import androidx.work.WorkInfo;
+
+import java.util.EventListener;
+import java.util.HashMap;
+import java.util.UUID;
+
+public interface CustomEventListener extends EventListener {
+ void onChange(HashMap workInfos);
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/DataProvider/CellInformations/NRInformation.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/DataProvider/CellInformations/NRInformation.java
index 110706f7..97825ba1 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/DataProvider/CellInformations/NRInformation.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/DataProvider/CellInformations/NRInformation.java
@@ -297,7 +297,7 @@ public StringBuilder getStringBuilder(){
if(!this.getSsrsrpString().equals(max)) stringBuilder.append(" SSRSRP: ").append(this.getSsrsrpString()).append(" dBm").append("\n");
- if(!this.getSssinrString().equals(max)) stringBuilder.append(" SSRSRP: ").append(this.getSssinrString()).append(" dBm").append("\n");
+ if(!this.getSssinrString().equals(max)) stringBuilder.append(" SSSINR: ").append(this.getSssinrString()).append(" dBm").append("\n");
if(!this.getFirstCqiString().equals(max)) stringBuilder.append(" CQI: ").append(this.getFirstCqiString()).append("\n");
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/DataProvider/DataProvider.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/DataProvider/DataProvider.java
index 2181a7c7..0b5e60d9 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/DataProvider/DataProvider.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/DataProvider/DataProvider.java
@@ -70,6 +70,7 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.UUID;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.DataProvider.CellInformations.CDMAInformation;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.DataProvider.CellInformations.CellInformation;
@@ -731,6 +732,9 @@ public Map getTagsMap() {
tags_map_modifiable.put("sdk_version", String.valueOf(di.getAndroidSDK()));
tags_map_modifiable.put("android_version", di.getAndroidRelease());
tags_map_modifiable.put("security_patch", di.getSecurityPatchLevel());
+ String device = spg.getSharedPreference(SPType.default_sp).getString("device_name", "null").strip();
+ //if(device.equals("null")); TODO handle this
+ tags_map_modifiable.put("device", device);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
tags_map_modifiable.put("soc_model", di.getSOCModel());
}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/InfluxDB2x/Worker/InfluxDB2xUploadWorker.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/InfluxDB2x/Worker/InfluxDB2xUploadWorker.java
new file mode 100644
index 00000000..55115321
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/InfluxDB2x/Worker/InfluxDB2xUploadWorker.java
@@ -0,0 +1,88 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Peter Hasse
+ * SPDX-FileCopyrightText: 2023 Johann Hackler
+ * SPDX-FileCopyrightText: 2023 Fraunhofer FOKUS
+ *
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.InfluxDB2x.Worker;
+
+import android.content.Context;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.work.Data;
+import androidx.work.Worker;
+import androidx.work.WorkerParameters;
+
+import com.google.gson.Gson;
+
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.InfluxDB2x.InfluxdbConnection;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.InfluxDB2x.InfluxdbConnections;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Inputs.Inputs;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Inputs.Iperf3Input;
+
+public class InfluxDB2xUploadWorker extends Worker {
+ public static final String TAG = "InfDB2xUploadWorker";
+ InfluxdbConnection influx;
+ private Inputs input;
+ public static final String UPLOAD = "influxdb2x_upload";
+
+ public InfluxDB2xUploadWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
+ super(context, workerParams);
+ Gson gson = new Gson();
+ String inputString = getInputData().getString(Inputs.INPUT);
+ input = gson.fromJson(inputString, Inputs.class);
+ }
+ private void setup(){
+ influx = InfluxdbConnections.getRicInstance(getApplicationContext());
+ }
+
+ @NonNull
+ @Override
+ public Result doWork() {
+ setup();
+ Data output = new Data.Builder().putBoolean(UPLOAD, false).build();
+ if(influx == null){
+ return Result.failure(output);
+ }
+ if(influx.getWriteApi() == null){
+ influx.open_write_api();
+ if(influx.getWriteApi() == null)
+ return Result.failure(output);
+ }
+
+ if(!influx.ping()){
+ return Result.failure(output);
+ }
+ BufferedReader br;
+ try {
+ br = new BufferedReader(new FileReader(input.getParameter().getLineProtocolFile()));
+ } catch (FileNotFoundException | NullPointerException e) {
+ Log.d(TAG,e.toString());
+ return Result.failure(output);
+ }
+ List points = br.lines().collect(Collectors.toList());
+ try {
+ Log.d(TAG, String.format("doWork: uploading %s", input.getParameter().getLineProtocolFile()));
+ influx.writeRecords(points);
+ } catch (IOException e) {
+ Log.d(TAG, String.format("doWork: upload of %s failed!", input.getParameter().getLineProtocolFile()));
+ return Result.failure(output);
+ }
+
+
+ influx.flush();
+
+ output = new Data.Builder().putBoolean(UPLOAD, true).build();
+ return Result.success(output);
+ }
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Inputs/Inputs.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Inputs/Inputs.java
new file mode 100644
index 00000000..8855ffb1
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Inputs/Inputs.java
@@ -0,0 +1,133 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Inputs;
+
+import android.os.Environment;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import androidx.annotation.NonNull;
+import androidx.work.Data;
+import androidx.work.OneTimeWorkRequest;
+
+import java.sql.Timestamp;
+
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Parameter.Parameter;
+
+public class Inputs implements Parcelable {
+
+
+ public static final String INPUT = "input";
+ public static final String TESTUUID = "testUUID";
+ public static final String SEQUENCEUUID = "sequenceUUID";
+ public static final String MEASUREMENTUUID = "measurementUUID";
+ public static final String CAMPAIGNUUID = "campaignUUID";
+ public static final String DEVICE = "device";
+ public static final String TYPE = "type";
+ public static final String PARAMS = "params";
+ public static final String NOTIFICATIONUMBER = "notificationNumber";
+ private String testUUID;
+
+ private Timestamp timestamp;
+ private String campaignUUID;
+ private String sequenceUUID;
+ private String measurementUUID;
+ private Parameter parameter;
+
+
+ public static final Creator CREATOR = new Creator() {
+ @Override
+ public Inputs createFromParcel(Parcel in) {
+ return new Inputs(in);
+ }
+
+ @Override
+ public Inputs[] newArray(int size) {
+ return new Inputs[size];
+ }
+ };
+
+ public String getTestUUID() {
+ return testUUID;
+ }
+
+ public void setTestUUID(String testUUID) {
+ this.testUUID = testUUID;
+ }
+
+
+ public Timestamp getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(Timestamp timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ public String getCampaignUUID() {
+ return campaignUUID;
+ }
+
+ public String getSequenceUUID() {
+ return sequenceUUID;
+ }
+
+ public String getMeasurementUUID() {
+ return measurementUUID;
+ }
+ protected Inputs(Parcel in) {
+ timestamp = (Timestamp) in.readSerializable();
+ campaignUUID = in.readString();
+ sequenceUUID = in.readString();
+ measurementUUID = in.readString();
+ testUUID = in.readString();
+ parameter = in.readParcelable(Parameter.class.getClassLoader());
+ }
+
+ public Inputs(String campaignUUID, String sequenceUUID, String measurementUUID, String testUUID, Parameter parameter) {
+ this.timestamp = new Timestamp(System.currentTimeMillis());
+ this.campaignUUID = campaignUUID;
+ this.sequenceUUID = sequenceUUID;
+ this.measurementUUID = measurementUUID;
+ this.testUUID = testUUID;
+ this.parameter = parameter;
+ }
+
+ public Parameter getParameter() {
+ return parameter;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeSerializable(timestamp);
+ dest.writeString(campaignUUID);
+ dest.writeString(sequenceUUID);
+ dest.writeString(measurementUUID);
+ dest.writeString(testUUID);
+ dest.writeParcelable(parameter, flags);
+ }
+
+ public Data.Builder getInputAsDataBuilder(int i, String packageName) {
+ return null;
+ }
+
+ public OneTimeWorkRequest getWorkRequestExecutor(int i, String packageName) {
+ return null;
+ }
+
+ public OneTimeWorkRequest getWorkRequestMonitor(int i, String packageName) {
+ return null;
+ }
+
+ public OneTimeWorkRequest getWorkRequestLineProtocol(int i, String packageName) {
+ return null;
+ }
+
+ public OneTimeWorkRequest getWorkRequestUpload(int i, String packageName) {
+ return null;
+ }
+
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Inputs/Iperf3Input.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Inputs/Iperf3Input.java
new file mode 100644
index 00000000..875a2a85
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Inputs/Iperf3Input.java
@@ -0,0 +1,191 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Inputs;
+
+import static androidx.work.multiprocess.RemoteListenableWorker.ARGUMENT_CLASS_NAME;
+import static androidx.work.multiprocess.RemoteListenableWorker.ARGUMENT_PACKAGE_NAME;
+
+import android.content.ComponentName;
+import android.os.Parcel;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.work.Data;
+import androidx.work.OneTimeWorkRequest;
+
+
+import com.google.gson.GsonBuilder;
+
+
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Service.Monitor.Iperf3MonitorServiceWorkerFour;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Service.Monitor.Iperf3MonitorServiceWorkerOne;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Service.Monitor.Iperf3MonitorServiceWorkerThree;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Service.Monitor.Iperf3MonitorServiceWorkerTwo;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Worker.Iperf3MonitorWorker;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Parameter.Iperf3Parameter;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Service.Executor.Iperf3ServiceWorkerFour;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Service.Executor.Iperf3ServiceWorkerThree;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Service.Executor.Iperf3ServiceWorkerTwo;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Worker.Iperf3ExecutorWorker;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Service.Executor.Iperf3ServiceWorkerOne;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Worker.Iperf3ToLineProtocolWorker;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Worker.Iperf3UploadWorker;
+
+
+public class Iperf3Input extends Inputs {
+
+ private static final String TAG = "Iperf3Input";
+ public static final String IPERF3UUID = "iPerf3UUID";
+
+ private Iperf3Parameter iperf3Parameter;
+ protected Iperf3Input(Parcel in) {
+ super(in);
+ iperf3Parameter = in.readParcelable(Iperf3Parameter.class.getClassLoader());
+ }
+
+
+ public static final Creator CREATOR = new Creator<>() {
+ @Override
+ public Iperf3Input createFromParcel(Parcel in) {
+ return new Iperf3Input(in);
+ }
+
+ @Override
+ public Iperf3Input[] newArray(int size) {
+ return new Iperf3Input[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel parcel, int i) {
+ super.writeToParcel(parcel, i);
+// parcel.writeParcelable(iperf3Parameter, i);
+ }
+ public Iperf3Input(Iperf3Parameter iperf3Parameter, String testUUID) {
+ this(iperf3Parameter, testUUID, "", "", "");
+ }
+ public Iperf3Input(Iperf3Parameter iperf3Parameter,
+ String testUUID,
+ String sequenceUUID,
+ String measurementUUID,
+ String campaignUUID) {
+ super(testUUID, sequenceUUID, measurementUUID, campaignUUID, iperf3Parameter);
+ this.iperf3Parameter = iperf3Parameter;
+ }
+
+ @Override
+ public Iperf3Parameter getParameter() {
+ return this.iperf3Parameter;
+ }
+
+
+ public Data.Builder getInputAsDataBuilder(int workerProcess, String packageName, String serviceName) {
+ Data.Builder data = new Data.Builder();
+ ComponentName componentName = new ComponentName(packageName, serviceName);
+ data.putString(ARGUMENT_PACKAGE_NAME, componentName.getPackageName());
+ data.putString(ARGUMENT_CLASS_NAME, componentName.getClassName());
+ data.putInt(NOTIFICATIONUMBER, workerProcess);
+ data.putString(Inputs.INPUT, new GsonBuilder().create().toJson(this, Iperf3Input.class));
+ Log.d(TAG, "getInputAsDataBuilder: ARGUMENT_PACKAGE_NAME: " + componentName.getPackageName());
+ Log.d(TAG, "getInputAsDataBuilder: ARGUMENT_CLASS_NAME: " + componentName.getClassName());
+ Log.d(TAG, "getInputAsDataBuilder: workerProcess: " + workerProcess);
+ Log.d(TAG, "getInputAsDataBuilder: testUUID: " + getTestUUID());
+ return data;
+ }
+
+
+
+ public Data.Builder getInputAsDataBuilder(int i) {
+ Data.Builder data = new Data.Builder();
+ data.putInt(NOTIFICATIONUMBER, i);
+ data.putString(Inputs.INPUT, new GsonBuilder().create().toJson(this, Iperf3Input.class));
+ return data;
+ }
+
+ @Override
+ public OneTimeWorkRequest getWorkRequestExecutor(int i, String packageName) {
+
+ String serviceName = "";
+ switch (i){
+ case 0:
+ serviceName = Iperf3ServiceWorkerOne.class.getName();
+ break;
+ case 1:
+ serviceName = Iperf3ServiceWorkerTwo.class.getName();
+ break;
+ case 2:
+ serviceName = Iperf3ServiceWorkerThree.class.getName();
+ break;
+ case 3:
+ serviceName = Iperf3ServiceWorkerFour.class.getName();
+ break;
+ }
+
+ return new OneTimeWorkRequest.Builder(Iperf3ExecutorWorker.class)
+ .addTag(super.getTestUUID())
+ .addTag(super.getMeasurementUUID())
+ .addTag(super.getSequenceUUID())
+ .addTag(super.getCampaignUUID())
+ .addTag(Iperf3ExecutorWorker.TAG)
+ .addTag(getParameter().getiPerf3UUID())
+ .setInputData(getInputAsDataBuilder(i, packageName, serviceName).build())
+ .build();
+ }
+
+ @Override
+ public OneTimeWorkRequest getWorkRequestMonitor(int i, String packageName) {
+ String serviceName = "";
+ switch (i){
+ case 0:
+ serviceName = Iperf3MonitorServiceWorkerOne.class.getName();
+ break;
+ case 1:
+ serviceName = Iperf3MonitorServiceWorkerTwo.class.getName();
+ break;
+ case 2:
+ serviceName = Iperf3MonitorServiceWorkerThree.class.getName();
+ break;
+ case 3:
+ serviceName = Iperf3MonitorServiceWorkerFour.class.getName();
+ break;
+ }
+ return new OneTimeWorkRequest.Builder(Iperf3MonitorWorker.class)
+ .addTag(super.getTestUUID())
+ .addTag(super.getMeasurementUUID())
+ .addTag(super.getSequenceUUID())
+ .addTag(super.getCampaignUUID())
+ .addTag(Iperf3MonitorWorker.TAG)
+ .addTag(getParameter().getiPerf3UUID())
+ .setInputData(getInputAsDataBuilder(i, packageName, serviceName).build())
+ .build();
+ }
+
+ @Override
+ public OneTimeWorkRequest getWorkRequestLineProtocol(int i, String packageName) {
+ return new OneTimeWorkRequest.Builder(Iperf3ToLineProtocolWorker.class)
+ .addTag(super.getTestUUID())
+ .addTag(super.getMeasurementUUID())
+ .addTag(super.getSequenceUUID())
+ .addTag(super.getCampaignUUID())
+ .addTag(Iperf3ToLineProtocolWorker.TAG)
+ .addTag(getParameter().getiPerf3UUID())
+ .setInputData(getInputAsDataBuilder(i).build())
+ .build();
+ }
+
+ @Override
+ public OneTimeWorkRequest getWorkRequestUpload(int i, String packageName) {
+ return new OneTimeWorkRequest.Builder(Iperf3UploadWorker.class)
+ .addTag(super.getTestUUID())
+ .addTag(super.getMeasurementUUID())
+ .addTag(super.getSequenceUUID())
+ .addTag(super.getCampaignUUID())
+ .addTag(Iperf3UploadWorker.TAG)
+ .addTag(getParameter().getiPerf3UUID())
+ .setInputData(getInputAsDataBuilder(i).build())
+ .build();
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Inputs/PingInput.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Inputs/PingInput.java
new file mode 100644
index 00000000..cb37252e
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Inputs/PingInput.java
@@ -0,0 +1,105 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Inputs;
+
+import android.os.Parcel;
+
+import androidx.work.Data;
+import androidx.work.OneTimeWorkRequest;
+
+import com.google.gson.Gson;
+
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.InfluxDB2x.Worker.InfluxDB2xUploadWorker;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Worker.Iperf3ToLineProtocolWorker;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Parameter.PingParameter;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping.Worker.PingToLineProtocolWorker;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping.Worker.PingWorker;
+
+
+public class PingInput extends Inputs {
+ private PingParameter pingParameter;
+
+ protected PingInput(Parcel in) {
+ super(in);
+
+ }
+ public PingInput(PingParameter pingParameter,
+ String testUUID,
+ String sequenceUUID,
+ String measurementUUID,
+ String campaignUUID) {
+ super(testUUID, sequenceUUID, measurementUUID, campaignUUID, pingParameter);
+ this.pingParameter = pingParameter;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ }
+
+ @Override
+ public Data.Builder getInputAsDataBuilder(int i, String packageName) {
+ Data.Builder data = new Data.Builder();
+ Gson gson = new Gson();
+ data.putInt(NOTIFICATIONUMBER, i);
+ data.putString(INPUT, gson.toJson(this));
+ return data;
+ }
+
+ public PingParameter getPingParameter() {
+ return pingParameter;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Creator CREATOR = new Creator() {
+ @Override
+ public PingInput createFromParcel(Parcel in) {
+ return new PingInput(in);
+ }
+
+ @Override
+ public PingInput[] newArray(int size) {
+ return new PingInput[size];
+ }
+ };
+
+
+ @Override
+ public OneTimeWorkRequest getWorkRequestLineProtocol(int i, String packageName) {
+ // TODO FIX
+ return new OneTimeWorkRequest.Builder(PingToLineProtocolWorker.class)
+ .addTag(super.getTestUUID())
+ .addTag(super.getMeasurementUUID())
+ .addTag(super.getSequenceUUID())
+ .addTag(super.getCampaignUUID())
+ .addTag(PingToLineProtocolWorker.TAG) // TODO FIX
+ .setInputData(getInputAsDataBuilder(i, packageName).build())
+ .build();
+ }
+
+ @Override
+ public OneTimeWorkRequest getWorkRequestUpload(int i, String packageName) {
+ return new OneTimeWorkRequest.Builder(InfluxDB2xUploadWorker.class)
+ .addTag(super.getTestUUID())
+ .addTag(super.getMeasurementUUID())
+ .addTag(super.getSequenceUUID())
+ .addTag(super.getCampaignUUID())
+ .addTag(InfluxDB2xUploadWorker.TAG)
+ .setInputData(getInputAsDataBuilder(i, packageName).build())
+ .build();
+ }
+
+ @Override
+ public OneTimeWorkRequest getWorkRequestExecutor(int i, String packageName) {
+ return new OneTimeWorkRequest.Builder(PingWorker.class)
+ .addTag(super.getTestUUID())
+ .addTag(super.getMeasurementUUID())
+ .addTag(super.getSequenceUUID())
+ .addTag(super.getCampaignUUID())
+ .addTag(PingWorker.TAG)
+ .setInputData(getInputAsDataBuilder(i, packageName).build())
+ .build();
+ }
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/Converter/Iperf3ErrorConverter.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/Converter/Iperf3ErrorConverter.java
new file mode 100644
index 00000000..0b9e5f89
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/Converter/Iperf3ErrorConverter.java
@@ -0,0 +1,30 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Peter Hasse
+ * SPDX-FileCopyrightText: 2023 Johann Hackler
+ * SPDX-FileCopyrightText: 2023 Fraunhofer FOKUS
+ *
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Converter;
+
+import androidx.room.ProvidedTypeConverter;
+import androidx.room.TypeConverter;
+
+import com.google.gson.Gson;
+
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Error;
+
+
+@ProvidedTypeConverter
+public class Iperf3ErrorConverter {
+ @TypeConverter
+ public Error fromJSONString(String string) {
+ return new Gson().fromJson(string, Error.class);
+ }
+
+ @TypeConverter
+ public String toJSONString(Error example) {
+ return new Gson().toJson(example);
+ }
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3InputConverter.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/Converter/Iperf3InputConverter.java
similarity index 61%
rename from app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3InputConverter.java
rename to app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/Converter/Iperf3InputConverter.java
index 61c014c5..2820800d 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3InputConverter.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/Converter/Iperf3InputConverter.java
@@ -6,22 +6,25 @@
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
-package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3;
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Converter;
import androidx.room.ProvidedTypeConverter;
import androidx.room.TypeConverter;
import com.google.gson.Gson;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Inputs.Iperf3Input;
+
+
@ProvidedTypeConverter
public class Iperf3InputConverter {
@TypeConverter
- public Iperf3Fragment.Iperf3Input StringToIperf3Input(String string) {
- return new Gson().fromJson(string, Iperf3Fragment.Iperf3Input.class);
+ public Iperf3Input StringToIperf3Input(String string) {
+ return new Gson().fromJson(string, Iperf3Input.class);
}
@TypeConverter
- public String Iperf3InputToString(Iperf3Fragment.Iperf3Input example) {
+ public String Iperf3InputToString(Iperf3Input example) {
return new Gson().toJson(example);
}
}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/Converter/Iperf3IntervalsConverter.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/Converter/Iperf3IntervalsConverter.java
new file mode 100644
index 00000000..ab8e4893
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/Converter/Iperf3IntervalsConverter.java
@@ -0,0 +1,85 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Converter;
+
+import androidx.room.ProvidedTypeConverter;
+import androidx.room.TypeConverter;
+
+import com.google.common.reflect.TypeToken;
+import com.squareup.moshi.JsonAdapter;
+import com.squareup.moshi.Moshi;
+import com.squareup.moshi.adapters.PolymorphicJsonAdapterFactory;
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.util.List;
+
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.MoshiAdapter.ArrayListIntervalsAdapter;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.MoshiAdapter.ArrayListStreamsAdapter;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Intervals;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.STREAM_TYPE;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.Stream;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.Streams;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.TCP.TCP_DL_STREAM;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.TCP.TCP_UL_STREAM;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.UDP.UDP_DL_STREAM;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.UDP.UDP_UL_STREAM;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.SUM_TYPE;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.Sum;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.TCP.TCP_DL_SUM;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.TCP.TCP_UL_SUM;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.UDP.UDP_DL_SUM;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.UDP.UDP_UL_SUM;
+
+@ProvidedTypeConverter
+public class Iperf3IntervalsConverter {
+
+
+ @TypeConverter
+ public Intervals stringToIperf3Intervals(String string) {
+ Moshi moshi = new Moshi.Builder()
+ .add(new ArrayListIntervalsAdapter())
+ .add(new ArrayListStreamsAdapter())
+
+ .add(PolymorphicJsonAdapterFactory.of(Stream.class, "streamType")
+ .withSubtype(TCP_DL_STREAM.class, STREAM_TYPE.TCP_DL.toString())
+ .withSubtype(TCP_UL_STREAM.class, STREAM_TYPE.TCP_UL.toString())
+ .withSubtype(UDP_DL_STREAM.class, STREAM_TYPE.UDP_DL.toString())
+ .withSubtype(UDP_UL_STREAM.class, STREAM_TYPE.UDP_UL.toString()))
+ .add(PolymorphicJsonAdapterFactory.of(Sum.class, "sumType")
+ .withSubtype(TCP_DL_SUM.class, SUM_TYPE.TCP_DL.toString())
+ .withSubtype(TCP_UL_SUM.class, SUM_TYPE.TCP_UL.toString())
+ .withSubtype(UDP_DL_SUM.class, SUM_TYPE.UDP_DL.toString())
+ .withSubtype(UDP_UL_SUM.class, SUM_TYPE.UDP_UL.toString()))
+ .build();
+ JsonAdapter jsonAdapter = moshi.adapter(Intervals.class);
+ Intervals intervals = new Intervals();
+ try {
+ intervals = jsonAdapter.fromJson(string);
+ } catch (IOException e) {
+ }
+
+
+ return intervals;
+ }
+
+ @TypeConverter
+ public String iperf3IntervalsToString(Intervals intervals) {
+
+ Moshi moshi = new Moshi.Builder()
+ .add(PolymorphicJsonAdapterFactory.of(Stream.class, "streamType")
+ .withSubtype(TCP_DL_STREAM.class, STREAM_TYPE.TCP_DL.toString())
+ .withSubtype(TCP_UL_STREAM.class, STREAM_TYPE.TCP_UL.toString())
+ .withSubtype(UDP_DL_STREAM.class, STREAM_TYPE.UDP_DL.toString())
+ .withSubtype(UDP_UL_STREAM.class, STREAM_TYPE.UDP_UL.toString()))
+ .add(PolymorphicJsonAdapterFactory.of(Sum.class, "sumType")
+ .withSubtype(TCP_DL_SUM.class, SUM_TYPE.TCP_DL.toString())
+ .withSubtype(TCP_UL_SUM.class, SUM_TYPE.TCP_UL.toString())
+ .withSubtype(UDP_DL_SUM.class, SUM_TYPE.UDP_DL.toString())
+ .withSubtype(UDP_UL_SUM.class, SUM_TYPE.UDP_UL.toString()))
+ .add(new ArrayListIntervalsAdapter())
+ .add(new ArrayListStreamsAdapter())
+ .build();
+ JsonAdapter jsonAdapter = moshi.adapter(Intervals.class);
+
+ return jsonAdapter.toJson(intervals);
+ }
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/Converter/Iperf3StartConverter.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/Converter/Iperf3StartConverter.java
new file mode 100644
index 00000000..888381bd
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/Converter/Iperf3StartConverter.java
@@ -0,0 +1,41 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Peter Hasse
+ * SPDX-FileCopyrightText: 2023 Johann Hackler
+ * SPDX-FileCopyrightText: 2023 Fraunhofer FOKUS
+ *
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Converter;
+
+import android.util.Log;
+
+import androidx.room.ProvidedTypeConverter;
+import androidx.room.TypeConverter;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonSyntaxException;
+
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Inputs.Iperf3Input;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.start.Start;
+
+
+@ProvidedTypeConverter
+public class Iperf3StartConverter {
+ private final String TAG = "Iperf3StartConverter";
+ @TypeConverter
+ public Start StringToIperf3Start(String string) {
+ Start start = new Start();
+ try {
+ start = new Gson().fromJson(string, Start.class);
+ } catch (JsonSyntaxException e){
+ Log.d(TAG, "StringToIperf3Start: "+e);
+ }
+ return start;
+ }
+
+ @TypeConverter
+ public String Iperf3StartToString(Start example) {
+ return new Gson().toJson(example);
+ }
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/Converter/MetricConverter.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/Converter/MetricConverter.java
new file mode 100644
index 00000000..d122c752
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/Converter/MetricConverter.java
@@ -0,0 +1,36 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Peter Hasse
+ * SPDX-FileCopyrightText: 2023 Johann Hackler
+ * SPDX-FileCopyrightText: 2023 Fraunhofer FOKUS
+ *
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Converter;
+
+import androidx.room.ProvidedTypeConverter;
+import androidx.room.TypeConverter;
+
+import com.google.gson.Gson;
+
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Inputs.Iperf3Input;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Metric.MetricCalculator;
+
+
+@ProvidedTypeConverter
+public class MetricConverter {
+ private double median;
+ private double mean;
+ private double max;
+ private double min;
+ private double last;
+ @TypeConverter
+ public MetricCalculator fromJSONString(String string) {
+ return new Gson().fromJson(string, MetricCalculator.class);
+ }
+
+ @TypeConverter
+ public String toJSONString(MetricCalculator example) {
+ return new Gson().toJson(example);
+ }
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/MoshiAdapter/ArrayListIntervalsAdapter.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/MoshiAdapter/ArrayListIntervalsAdapter.java
new file mode 100644
index 00000000..38925a5a
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/MoshiAdapter/ArrayListIntervalsAdapter.java
@@ -0,0 +1,24 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.MoshiAdapter;
+
+import com.squareup.moshi.FromJson;
+import com.squareup.moshi.ToJson;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Intervals;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Interval;
+
+public class ArrayListIntervalsAdapter {
+ @ToJson
+ List ToJson(Intervals interval) {
+ return interval.getIntervalArrayList();
+ }
+
+ @FromJson
+ Intervals FromJson(List listInterval) {
+ Intervals intervals = new Intervals();
+ intervals.setIntervals(new ArrayList<>(listInterval));
+ return intervals;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/MoshiAdapter/ArrayListStreamsAdapter.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/MoshiAdapter/ArrayListStreamsAdapter.java
new file mode 100644
index 00000000..a238e9c2
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/MoshiAdapter/ArrayListStreamsAdapter.java
@@ -0,0 +1,29 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.MoshiAdapter;
+
+import com.squareup.moshi.FromJson;
+import com.squareup.moshi.ToJson;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Intervals;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Interval;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.Stream;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.Streams;
+
+public class ArrayListStreamsAdapter {
+ @ToJson
+ List ToJson(Streams streams) {
+ return streams.getStreamArrayList();
+ }
+
+ @FromJson
+ Streams FromJson(List listStreams) {
+
+
+
+ Streams streams = new Streams();
+ streams.setStreams(new ArrayList<>(listStreams));
+ return streams;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3ResultsDataBase.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/RunResult/Iperf3ResultsDataBase.java
similarity index 54%
rename from app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3ResultsDataBase.java
rename to app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/RunResult/Iperf3ResultsDataBase.java
index d9b01a29..981c2131 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3ResultsDataBase.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/RunResult/Iperf3ResultsDataBase.java
@@ -6,7 +6,7 @@
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
-package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3;
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.RunResult;
import android.content.Context;
@@ -14,14 +14,22 @@
import androidx.room.Room;
import androidx.room.RoomDatabase;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Converter.Iperf3ErrorConverter;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Converter.Iperf3InputConverter;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Converter.Iperf3IntervalsConverter;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Converter.Iperf3StartConverter;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Converter.MetricConverter;
+
@Database(
entities = {Iperf3RunResult.class},
version = 3
)
+
public abstract class Iperf3ResultsDataBase extends RoomDatabase {
+
private static volatile Iperf3ResultsDataBase INSTANCE;
- static Iperf3ResultsDataBase getDatabase(final Context context) {
+ public static Iperf3ResultsDataBase getDatabase(final Context context) {
if (INSTANCE == null) {
synchronized (Iperf3ResultsDataBase.class) {
if (INSTANCE == null) {
@@ -29,7 +37,12 @@ static Iperf3ResultsDataBase getDatabase(final Context context) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
Iperf3ResultsDataBase.class, "iperf3_result_database")
.addTypeConverter(new Iperf3InputConverter())
+ .addTypeConverter(new Iperf3IntervalsConverter())
+ .addTypeConverter(new Iperf3StartConverter())
+ .addTypeConverter(new MetricConverter())
+ .addTypeConverter(new Iperf3ErrorConverter())
.allowMainThreadQueries()
+ .enableMultiInstanceInvalidation()
.build();
}
}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/RunResult/Iperf3RunResult.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/RunResult/Iperf3RunResult.java
new file mode 100644
index 00000000..9a5dfe2c
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/RunResult/Iperf3RunResult.java
@@ -0,0 +1,70 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.RunResult;
+
+import androidx.annotation.NonNull;
+import androidx.room.ColumnInfo;
+import androidx.room.Embedded;
+import androidx.room.Entity;
+import androidx.room.PrimaryKey;
+import androidx.room.TypeConverters;
+
+import java.sql.Timestamp;
+
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Inputs.Iperf3Input;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Converter.Iperf3ErrorConverter;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Converter.Iperf3InputConverter;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Converter.Iperf3IntervalsConverter;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Converter.Iperf3StartConverter;
+
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Converter.MetricConverter;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Intervals;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Error;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.start.Start;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Metric.MetricCalculator;
+
+@Entity(tableName = "iperf3_result_database")
+@TypeConverters({Iperf3InputConverter.class, Iperf3IntervalsConverter.class, Iperf3StartConverter.class, MetricConverter.class})
+public class Iperf3RunResult {
+ @NonNull
+ @PrimaryKey
+ public String uid;
+
+ @ColumnInfo(name = "result")
+ public int result;
+
+ @ColumnInfo(name = "uploaded")
+ public boolean uploaded;
+
+ @ColumnInfo(name = "timestamp")
+ public long timestamp;
+
+ @ColumnInfo(name = "input")
+ public Iperf3Input input;
+
+ @ColumnInfo(name = "_start")
+ public Start start;
+
+ @ColumnInfo(name = "_end")
+ public String end;
+ @ColumnInfo(name = "_intervals")
+ public Intervals intervals;
+ @ColumnInfo(name = "metricUL")
+ public MetricCalculator metricUL;
+ @ColumnInfo(name = "metricDL")
+ public MetricCalculator metricDL;
+
+ @ColumnInfo(name = "error")
+ @TypeConverters({Iperf3ErrorConverter.class})
+ public Error error;
+
+ public Iperf3RunResult(String uid, int result, boolean upload, Iperf3Input input,
+ Timestamp timestamp) {
+ this.uid = uid;
+ this.result = result;
+ this.uploaded = upload;
+ this.input = input;
+ this.timestamp = timestamp.getTime();
+ }
+
+ public Iperf3RunResult() {
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/RunResult/Iperf3RunResultDao.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/RunResult/Iperf3RunResultDao.java
new file mode 100644
index 00000000..ed26a97c
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Database/RunResult/Iperf3RunResultDao.java
@@ -0,0 +1,88 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Peter Hasse
+ * SPDX-FileCopyrightText: 2023 Johann Hackler
+ * SPDX-FileCopyrightText: 2023 Fraunhofer FOKUS
+ *
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.RunResult;
+
+import androidx.lifecycle.LiveData;
+import androidx.room.Dao;
+import androidx.room.Insert;
+import androidx.room.OnConflictStrategy;
+import androidx.room.Query;
+import androidx.room.TypeConverters;
+
+import java.util.List;
+
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Converter.Iperf3ErrorConverter;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Converter.Iperf3IntervalsConverter;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.Converter.MetricConverter;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Intervals;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Error;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Metric.MetricCalculator;
+
+@Dao
+public interface Iperf3RunResultDao {
+ @Query("SELECT * FROM iperf3_result_database")
+ LiveData> getAll();
+
+ @Query("SELECT uid FROM iperf3_result_database ORDER BY timestamp DESC")
+ List getIDs();
+
+ @Query("SELECT * FROM iperf3_result_database WHERE uid = :comp_uid")
+ Iperf3RunResult getRunResult(String comp_uid);
+
+ @Query("SELECT timestamp FROM iperf3_result_database WHERE uid = :comp_uid")
+ long getTimestampFromUid(String comp_uid);
+
+ @Query("SELECT _intervals FROM iperf3_result_database WHERE uid = :comp_uid")
+ @TypeConverters({Iperf3IntervalsConverter.class})
+ Intervals getIntervals(String comp_uid);
+
+ @Query("UPDATE iperf3_result_database SET _intervals = :intervals WHERE uid = :uid")
+ @TypeConverters({Iperf3IntervalsConverter.class})
+ void updateIntervals(String uid, Intervals intervals);
+ @Query("UPDATE iperf3_result_database SET metricUL = :metricUL WHERE uid = :uid")
+ @TypeConverters({MetricConverter.class})
+ void updateMetricUL(String uid, MetricCalculator metricUL);
+
+ @Query("UPDATE iperf3_result_database SET metricDL = :metricDL WHERE uid = :uid")
+ @TypeConverters({MetricConverter.class})
+ void updateMetricDL(String uid, MetricCalculator metricDL);
+
+ @Query("UPDATE iperf3_result_database SET _start = :start WHERE uid = :uid")
+ void updateStart(String uid, String start);
+
+ @Query("UPDATE iperf3_result_database SET _end = :end WHERE uid = :uid")
+ void updateEnd(String uid, String end);
+
+ @Query("UPDATE iperf3_result_database SET uploaded = :uploaded WHERE uid = :uid")
+ void updateUploaded(String uid, boolean uploaded);
+
+ @Query("UPDATE iperf3_result_database SET result = :result WHERE uid = :uid")
+ void updateResult(String uid, int result);
+
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ void insert(Iperf3RunResult iperf3RunResult);
+
+ @Query("SELECT metricDL FROM iperf3_result_database WHERE uid = :uid")
+ @TypeConverters({MetricConverter.class})
+ MetricCalculator getMetricDL(String uid);
+
+ @Query("SELECT metricUL FROM iperf3_result_database WHERE uid = :uid")
+ @TypeConverters({MetricConverter.class})
+ MetricCalculator getMetricUL(String uid);
+
+ @Query("SELECT error FROM iperf3_result_database WHERE uid = :uid")
+ @TypeConverters({Iperf3ErrorConverter.class})
+ Error getError(String uid);
+
+ @Query("UPDATE iperf3_result_database SET error = :error WHERE uid = :uid")
+ @TypeConverters({Iperf3ErrorConverter.class})
+ void updateError(String uid, Error error);
+
+
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Fragments/Iperf3Fragment.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Fragments/Iperf3Fragment.java
new file mode 100644
index 00000000..0ef11e4d
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Fragments/Iperf3Fragment.java
@@ -0,0 +1,513 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Fragments;
+
+import static android.view.View.GONE;
+import static android.view.View.VISIBLE;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.lifecycle.Observer;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.work.ListenableWorker;
+import androidx.work.WorkInfo;
+import androidx.work.WorkQuery;
+import androidx.work.multiprocess.RemoteWorkManager;
+
+import com.google.android.material.bottomsheet.BottomSheetBehavior;
+import com.google.android.material.button.MaterialButton;
+import com.google.android.material.button.MaterialButtonToggleGroup;
+import com.google.android.material.floatingactionbutton.FloatingActionButton;
+import com.google.android.material.progressindicator.LinearProgressIndicator;
+import com.google.android.material.textfield.TextInputEditText;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+
+import org.json.JSONException;
+
+import java.io.File;
+import java.io.IOException;
+import java.sql.Timestamp;
+import java.util.Arrays;
+import java.util.List;
+import java.util.UUID;
+import java.util.function.Consumer;
+
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Inputs.Iperf3Input;
+
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.RunResult.Iperf3ResultsDataBase;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.RunResult.Iperf3RunResult;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.RunResult.Iperf3RunResultDao;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Iperf3Executor;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Iperf3RecyclerViewAdapter;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Interval;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.Sum;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Worker.Iperf3ExecutorWorker;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Worker.Iperf3MonitorWorker;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Metric.METRIC_TYPE;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Metric.MetricCalculator;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Metric.MetricView;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Parameter.Iperf3Parameter;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SPType;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SharedPreferencesGrouper;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R;
+
+public class Iperf3Fragment extends Fragment {
+
+ private static final String ARG_POSITION = "position";
+ private Iperf3Input iperf3Input;
+ private Context ct;
+ private MaterialButton sendBtn;
+ private View view;
+ private TextInputEditText ip;
+ private TextInputEditText port;
+ private TextInputEditText bitrate;
+ private TextInputEditText duration;
+ private TextInputEditText interval;
+ private TextInputEditText bytes;
+ private TextInputEditText streams;
+ private TextInputEditText cport;
+
+
+ private MaterialButtonToggleGroup mode;
+ private MaterialButtonToggleGroup protocol;
+ private MaterialButtonToggleGroup direction;
+
+ private MaterialButton modeClient;
+ private MaterialButton modeServer;
+ private MaterialButton protocolTCP;
+ private MaterialButton protocolUDP;
+ private MaterialButton directionUp;
+ private MaterialButton directionDown;
+ private MaterialButton directonBidir;
+ private Handler handler;
+ private RecyclerView recyclerView;
+ private SharedPreferencesGrouper spg;
+
+ private String TAG = "Iperf3CardFragment";
+ private String uuid;
+ private Iperf3RecyclerViewAdapter adapter;
+ private Iperf3RunResultDao iperf3RunResultDao;
+ private Iperf3ResultsDataBase iperf3ResultsDataBase;
+ private BottomSheetBehavior bottomSheetBehavior;
+ private FloatingActionButton fab;
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ this.ct = requireContext();
+ }
+
+ /**
+ * Create a text watcher
+ * @param consumer
+ * @param name
+ * @return
+ */
+ private TextWatcher createTextWatcher(Consumer consumer, String name) {
+ return new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
+
+ }
+
+ @Override
+ public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
+ consumer.accept(charSequence.toString());
+ spg.getSharedPreference(SPType.iperf3_sp).edit().putString(name, charSequence.toString()).apply();
+ }
+
+ @Override
+ public void afterTextChanged(Editable editable) {
+ }
+ };
+ }
+
+ /**
+ * Set up the text watchers
+ */
+ private void setupTextWatchers() {
+ ip.addTextChangedListener(createTextWatcher(s -> iperf3Input.getParameter().setHost(s), Iperf3Parameter.HOST));
+ port.addTextChangedListener(createTextWatcher(s -> iperf3Input.getParameter().setPort(Integer.parseInt("0"+s)), Iperf3Parameter.PORT));
+ bitrate.addTextChangedListener(createTextWatcher(s -> iperf3Input.getParameter().setBandwidth(s), Iperf3Parameter.BITRATE));
+ duration.addTextChangedListener(createTextWatcher(s -> iperf3Input.getParameter().setTime(Integer.parseInt("0"+s)), Iperf3Parameter.TIME));
+ interval.addTextChangedListener(createTextWatcher(s -> iperf3Input.getParameter().setInterval(Double.parseDouble("0"+s)), Iperf3Parameter.INTERVAL));
+ bytes.addTextChangedListener(createTextWatcher(s -> iperf3Input.getParameter().setBytes(s), Iperf3Parameter.BYTES));
+ streams.addTextChangedListener(createTextWatcher(s -> iperf3Input.getParameter().setParallel(Integer.parseInt("0"+s)), Iperf3Parameter.PARALLEL));
+ cport.addTextChangedListener(createTextWatcher(s -> iperf3Input.getParameter().setCport(Integer.parseInt("0"+s) ), Iperf3Parameter.CPORT));
+ }
+
+ /**
+ * Set the text from the shared preferences
+ * @param editText
+ * @param key
+ */
+ private void setTextFromSharedPreferences(TextInputEditText editText, String key) {
+ if (spg.getSharedPreference(SPType.iperf3_sp).contains(key)) {
+ editText.setText(spg.getSharedPreference(SPType.iperf3_sp).getString(key, ""));
+ }
+ }
+
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ RemoteWorkManager remoteWorkManager = RemoteWorkManager.getInstance(ct);
+
+ WorkQuery workQuery = WorkQuery.Builder
+ .fromTags(Arrays.asList(iperf3Input.getTestUUID()))
+ .build();
+ ListenableFuture> foobar = remoteWorkManager.getWorkInfos(workQuery);
+ Futures.addCallback(
+ foobar,
+ new FutureCallback<>() {
+ public void onSuccess(List result) {
+
+ for (WorkInfo workInfo : result) {
+ Log.d(TAG, "onSuccess: workInfoTags: "+ workInfo.getTags());
+ Log.d(TAG, "onSuccess workInfo State: " + workInfo.getState());
+ Log.d(TAG, "onSuccess workInfo isFinished: " + workInfo.getState().isFinished());
+
+ if (workInfo.getTags().contains(Iperf3MonitorWorker.class.getCanonicalName())) {
+ Log.d(TAG, "onSuccess: "+Iperf3MonitorWorker.class.getName()+" in state"+workInfo.getState());
+ switch (workInfo.getState()) {
+ case SUCCEEDED:
+ adapter.notifyDataSetChanged();
+ break;
+ case CANCELLED:
+ case FAILED:
+ try {
+ Log.d(TAG, "onSuccess: going sleeping");
+ Thread.sleep(1000); //todo handle better, is needed because write to db is to slow
+ Log.d(TAG, "onSuccess: "+iperf3RunResultDao.getRunResult(uuid).error);
+ Log.d(TAG, "onSuccess: woke up");
+ } catch (InterruptedException e) {
+
+ }
+ adapter.notifyDataSetChanged();
+ break;
+ case BLOCKED:
+ case ENQUEUED:
+ case RUNNING:
+ adapter.notifyDataSetChanged();
+ handler.postDelayed(runnable, 500);
+ break;
+ }
+ } else if(workInfo.getTags().contains(Iperf3ExecutorWorker.class.getCanonicalName())){
+ Log.d(TAG, "onSuccess: "+Iperf3ExecutorWorker.class.getName()+" in state"+workInfo.getState());
+ switch (workInfo.getState()) {
+ case SUCCEEDED:
+ adapter.notifyDataSetChanged();
+ break;
+ case CANCELLED:
+ case FAILED:
+ iperf3RunResultDao.updateResult(uuid, -1);
+ remoteWorkManager.cancelAllWorkByTag(iperf3Input.getTestUUID());
+ adapter.notifyDataSetChanged();
+ break;
+ case BLOCKED:
+ case ENQUEUED:
+ case RUNNING:
+ String line = workInfo.getProgress().getString("interval");
+ Log.d(TAG, "onSuccess: "+line);
+ adapter.notifyDataSetChanged();
+
+ break;
+ }
+ }
+ }
+ adapter.notifyDataSetChanged();
+ }
+
+ public void onFailure(@NonNull Throwable thrown) {
+ // handle failure
+ }
+ },
+ getContext().getMainExecutor()
+ );
+
+ }
+ };
+
+ /**
+ * Set the texts from the shared preferences
+ */
+ private void setTextsFromSharedPreferences(){
+ setTextFromSharedPreferences(ip, Iperf3Parameter.HOST);
+ setTextFromSharedPreferences(port, Iperf3Parameter.PORT);
+ setTextFromSharedPreferences(bitrate, Iperf3Parameter.BITRATE);
+ setTextFromSharedPreferences(duration, Iperf3Parameter.TIME);
+ setTextFromSharedPreferences(interval, Iperf3Parameter.INTERVAL);
+ setTextFromSharedPreferences(bytes, Iperf3Parameter.BYTES);
+ setTextFromSharedPreferences(streams, Iperf3Parameter.STREAMS);
+ setTextFromSharedPreferences(cport, Iperf3Parameter.CPORT);
+ }
+
+ private void setupBottomSheet(){
+ bottomSheetBehavior = BottomSheetBehavior.from(view.findViewById(R.id.standard_bottom_sheet));
+ bottomSheetBehavior.setPeekHeight(100);
+ bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
+ bottomSheetBehavior.setHideable(false);
+
+ }
+ private void setupDatabase(){
+ iperf3ResultsDataBase = Iperf3ResultsDataBase.getDatabase(ct);
+ iperf3RunResultDao = iperf3ResultsDataBase.iperf3RunResultDao();
+ }
+ private void setupRecyclerView(){
+ LinearLayoutManager linearLayoutManager =
+ new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
+
+ recyclerView = view.findViewById(R.id.runners_list);
+ adapter = new Iperf3RecyclerViewAdapter(fab);
+ adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
+ @Override
+ public void onChanged() {
+ super.onChanged();
+ Log.d(TAG, "onChanged: "+adapter.getSelectedUUID());
+ }
+ });
+
+ recyclerView.setAdapter(adapter);
+ recyclerView.setLayoutManager(linearLayoutManager);
+ }
+
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ view = inflater.inflate(R.layout.fragment_iperf3_input, container, false);
+ // Initialize the TextView
+ String iperf3UUID = UUID.randomUUID().toString();
+ Iperf3Parameter iperf3Parameter = new Iperf3Parameter(iperf3UUID);
+ iperf3Input = new Iperf3Input(iperf3Parameter, "");
+ sendBtn = view.findViewById(R.id.iperf3_send);
+ spg = SharedPreferencesGrouper.getInstance(ct);
+ handler = new Handler(Looper.getMainLooper());
+
+ setupBottomSheet();
+ sendBtn.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ uuid = UUID.randomUUID().toString();
+ iperf3Input.setTestUUID(uuid);
+ iperf3Input.getParameter().setTestUUID(uuid);
+ iperf3Input.getParameter().updatePaths();
+ iperf3Input.setTimestamp(new Timestamp(System.currentTimeMillis()));
+
+ File logFile = new File(iperf3Input.getParameter().getLogfile());
+ File rawPath = new File(Iperf3Parameter.rawDirPath);
+
+ if(!rawPath.exists()) {
+ rawPath.mkdirs();
+ }
+ try {
+ logFile.createNewFile();
+ Log.d(TAG, "onClick: created File: "+logFile.toString());
+ } catch (Exception e) {
+ Log.d(TAG, "startRemoteWork: "+e);
+ }
+
+
+
+ Iperf3Executor iperf3Executor = new Iperf3Executor(iperf3Input, getContext());
+ iperf3Executor.execute();
+ Log.d(TAG, "onClick: "+iperf3Input.getParameter().getTime());
+
+
+ Iperf3RunResult iperf3RunResult = new Iperf3RunResult(iperf3Input.getTestUUID(), -100, false, iperf3Input, new java.sql.Timestamp(System.currentTimeMillis()));
+ iperf3RunResultDao.insert(iperf3RunResult);
+
+ handler.post(runnable); // start the first execution
+ bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
+ adapter.notifyDataSetChanged();
+
+ }
+ });
+ //fab = view.findViewById(R.id.iperf3_influx_upload_button);
+ ip = view.findViewById(R.id.iperf3_ip);
+ port = view.findViewById(R.id.iperf3_port);
+ bitrate = view.findViewById(R.id.iperf3_bandwidth);
+ duration = view.findViewById(R.id.iperf3_duration);
+ interval = view.findViewById(R.id.iperf3_interval);
+ bytes = view.findViewById(R.id.iperf3_bytes);
+ streams = view.findViewById(R.id.iperf3_streams);
+ cport = view.findViewById(R.id.iperf3_cport);
+
+
+ mode = view.findViewById(R.id.iperf3_mode_toggle_group);
+ protocol = view.findViewById(R.id.iperf3_protocol_toggle_group);
+ direction = view.findViewById(R.id.iperf3_direction_toggle_group);
+
+ modeClient = view.findViewById(R.id.iperf3_client_button);
+ modeServer = view.findViewById(R.id.iperf3_server_button);
+
+ protocolTCP = view.findViewById(R.id.iperf3_tcp_button);
+ protocolUDP = view.findViewById(R.id.iperf3_udp_button);
+
+ directionDown = view.findViewById(R.id.iperf3_download_button);
+ directionUp = view.findViewById(R.id.iperf3_upload_button);
+ directonBidir = view.findViewById(R.id.iperf3_bidir_button);
+
+ setupTextWatchers();
+ setTextsFromSharedPreferences();
+ try {
+ switch (Iperf3Parameter.Iperf3Mode.valueOf(spg.getSharedPreference(SPType.iperf3_sp).getString(Iperf3Parameter.MODE, String.valueOf(Iperf3Parameter.Iperf3Mode.UNDEFINED)))){
+ case CLIENT:
+ updateModeState(modeClient, modeServer, Iperf3Parameter.Iperf3Mode.CLIENT);
+ break;
+ case SERVER:
+ updateModeState(modeServer, modeClient, Iperf3Parameter.Iperf3Mode.SERVER);
+ break;
+ case UNDEFINED:
+ default:
+ modeClient.setBackgroundColor(Color.TRANSPARENT);
+ modeServer.setBackgroundColor(Color.TRANSPARENT);
+ spg.getSharedPreference(SPType.iperf3_sp).edit().putString(Iperf3Parameter.MODE, Iperf3Parameter.Iperf3Mode.UNDEFINED.toString()).apply();
+ break;
+ }
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "onCreateView: ", e);
+ }
+ try {
+ switch (Iperf3Parameter.Iperf3Protocol.valueOf(spg.getSharedPreference(SPType.iperf3_sp).getString(Iperf3Parameter.PROTOCOL, Iperf3Parameter.Iperf3Protocol.UNDEFINED.toString()))){
+ case TCP:
+ updateProtocolState(protocolTCP, protocolUDP, Iperf3Parameter.Iperf3Protocol.TCP);
+ break;
+ case UDP:
+ updateProtocolState(protocolUDP, protocolTCP, Iperf3Parameter.Iperf3Protocol.UDP);
+ break;
+ case UNDEFINED:
+ default:
+ protocolTCP.setBackgroundColor(Color.TRANSPARENT);
+ protocolUDP.setBackgroundColor(Color.TRANSPARENT);
+ spg.getSharedPreference(SPType.iperf3_sp).edit().putString(Iperf3Parameter.PROTOCOL, Iperf3Parameter.Iperf3Protocol.UNDEFINED.toString()).apply();
+ break;
+ }
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "onCreateView: ", e);
+ }
+ try {
+ switch (Iperf3Parameter.Iperf3Direction.valueOf(spg.getSharedPreference(SPType.iperf3_sp).getString(Iperf3Parameter.DIRECTION, Iperf3Parameter.Iperf3Direction.UNDEFINED.toString()))) {
+ case UP:
+ updateDirectionState(directionUp, directionDown, directonBidir, Iperf3Parameter.Iperf3Direction.UP);
+ break;
+ case DOWN:
+ updateDirectionState(directionDown, directionUp, directonBidir, Iperf3Parameter.Iperf3Direction.DOWN);
+ break;
+ case BIDIR:
+ updateDirectionState(directonBidir, directionUp, directionDown, Iperf3Parameter.Iperf3Direction.BIDIR);
+ break;
+ case UNDEFINED:
+ default:
+ directionUp.setBackgroundColor(Color.TRANSPARENT);
+ directionDown.setBackgroundColor(Color.TRANSPARENT);
+ directonBidir.setBackgroundColor(Color.TRANSPARENT);
+ break;
+ }
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "onCreateView: ", e);
+ }
+
+ mode.addOnButtonCheckedListener(new MaterialButtonToggleGroup.OnButtonCheckedListener() {
+ @Override
+ public void onButtonChecked(MaterialButtonToggleGroup group, int checkedId, boolean isChecked) {
+ if (isChecked) {
+ switch (checkedId) {
+ case R.id.iperf3_client_button:
+ updateModeState(modeClient, modeServer, Iperf3Parameter.Iperf3Mode.CLIENT);
+ break;
+ case R.id.iperf3_server_button:
+ updateModeState(modeServer, modeClient, Iperf3Parameter.Iperf3Mode.SERVER);
+ break;
+ }
+ }
+ }
+ });
+ protocol.addOnButtonCheckedListener(new MaterialButtonToggleGroup.OnButtonCheckedListener() {
+ @Override
+ public void onButtonChecked(MaterialButtonToggleGroup group, int checkedId, boolean isChecked) {
+ if (isChecked) {
+ switch (checkedId) {
+ case R.id.iperf3_tcp_button:
+ updateProtocolState(protocolTCP, protocolUDP, Iperf3Parameter.Iperf3Protocol.TCP);
+ break;
+ case R.id.iperf3_udp_button:
+ updateProtocolState(protocolUDP, protocolTCP, Iperf3Parameter.Iperf3Protocol.UDP);
+ break;
+ }
+ }
+ }
+ });
+ direction.addOnButtonCheckedListener(new MaterialButtonToggleGroup.OnButtonCheckedListener() {
+ @Override
+ public void onButtonChecked(MaterialButtonToggleGroup group, int checkedId, boolean isChecked) {
+ if (isChecked) {
+ switch (checkedId) {
+ case R.id.iperf3_upload_button:
+ updateDirectionState(directionUp, directionDown, directonBidir, Iperf3Parameter.Iperf3Direction.UP);
+ break;
+ case R.id.iperf3_download_button:
+ updateDirectionState(directionDown, directionUp, directonBidir, Iperf3Parameter.Iperf3Direction.DOWN);
+ break;
+ case R.id.iperf3_bidir_button:
+ updateDirectionState(directonBidir, directionUp, directionDown, Iperf3Parameter.Iperf3Direction.BIDIR);
+ break;
+ }
+ }
+ }
+ });
+ setupDatabase();
+ setupBottomSheet();
+ setupRecyclerView();
+ return view;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ view.requestLayout();
+ }
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ handler.removeCallbacks(runnable);
+ }
+
+
+ private void updateModeState(MaterialButton activeButton, MaterialButton inactiveButton, Iperf3Parameter.Iperf3Mode protocol) {
+ activeButton.setBackgroundColor(getResources().getColor(R.color.purple_500, null));
+ inactiveButton.setBackgroundColor(Color.TRANSPARENT);
+ iperf3Input.getParameter().setMode(protocol);
+ spg.getSharedPreference(SPType.iperf3_sp).edit().putString(Iperf3Parameter.MODE, protocol.toString()).apply();
+ }
+
+ private void updateProtocolState(MaterialButton activeButton, MaterialButton inactiveButton, Iperf3Parameter.Iperf3Protocol protocol) {
+ activeButton.setBackgroundColor(getResources().getColor(R.color.purple_500, null));
+ inactiveButton.setBackgroundColor(Color.TRANSPARENT);
+ iperf3Input.getParameter().setProtocol(protocol);
+ spg.getSharedPreference(SPType.iperf3_sp).edit().putString(Iperf3Parameter.PROTOCOL, protocol.toString()).apply();
+ }
+
+ private void updateDirectionState(MaterialButton activeButton, MaterialButton inactiveButton1, MaterialButton inactiveButton2, Iperf3Parameter.Iperf3Direction direction) {
+ activeButton.setBackgroundColor(getResources().getColor(R.color.purple_500, null));
+ inactiveButton1.setBackgroundColor(Color.TRANSPARENT);
+ inactiveButton2.setBackgroundColor(Color.TRANSPARENT);
+ iperf3Input.getParameter().setDirection(direction);
+ spg.getSharedPreference(SPType.iperf3_sp).edit().putString(Iperf3Parameter.DIRECTION, direction.toString()).apply();
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Intervals.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Intervals.java
index 08635896..37c05662 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Intervals.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Intervals.java
@@ -16,4 +16,8 @@ public ArrayList getIntervalArrayList(){
return intervals;
}
+ public void setIntervals(ArrayList intervals) {
+ this.intervals.clear();
+ this.intervals.addAll(intervals);
+ }
}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Executor.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Executor.java
new file mode 100644
index 00000000..c94da161
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Executor.java
@@ -0,0 +1,78 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+
+import androidx.work.Constraints;
+import androidx.work.OneTimeWorkRequest;
+import androidx.work.WorkContinuation;
+import androidx.work.WorkManager;
+import androidx.work.multiprocess.RemoteWorkContinuation;
+import androidx.work.multiprocess.RemoteWorkManager;
+
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.concurrent.TimeUnit;
+
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.InfluxDB2x.Worker.InfluxDB2xUploadWorker;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Inputs.Iperf3Input;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Service.Executor.Iperf3ServiceWorkerOne;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Service.Monitor.Iperf3MonitorServiceWorkerOne;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Worker.Iperf3ExecutorWorker;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Worker.Iperf3MonitorWorker;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Worker.Iperf3ToLineProtocolWorker;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SPType;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SharedPreferencesGrouper;
+
+public class Iperf3Executor {
+ private static final String TAG = "Iperf3Executor";
+ private RemoteWorkManager remoteWorkManager;
+ private WorkManager workManager;
+ private Context context;
+ private SharedPreferencesGrouper spg;
+ private RemoteWorkContinuation remoteWorkContinuation;
+ private WorkContinuation localWorkContinuation;
+ @SuppressLint("EnqueueWork")
+ public Iperf3Executor(Iperf3Input iperf3Input, Context context){
+
+ if(iperf3Input == null){
+ throw new IllegalArgumentException("Iperf3Input cannot be null");
+ }
+ if(context == null){
+ throw new IllegalArgumentException("Context cannot be null");
+ }
+ this.context = context;
+ this.spg = SharedPreferencesGrouper.getInstance(this.context);
+ this.remoteWorkManager = RemoteWorkManager.getInstance(this.context);
+ this.workManager = WorkManager.getInstance(this.context);
+ OneTimeWorkRequest iperf3ExecutorWorker = new OneTimeWorkRequest.Builder(Iperf3ExecutorWorker.class)
+ .setInputData(iperf3Input.getInputAsDataBuilder(0, context.getPackageName(), Iperf3ServiceWorkerOne.class.getName()).build())
+ .addTag(iperf3Input.getTestUUID())
+ .build();
+ OneTimeWorkRequest iperf3MonitorWorker = new OneTimeWorkRequest.Builder(Iperf3MonitorWorker.class)
+ .setInputData(iperf3Input.getInputAsDataBuilder(0, context.getPackageName(), Iperf3MonitorServiceWorkerOne.class.getName()).build())
+ .addTag(iperf3Input.getTestUUID())
+ .build();
+ OneTimeWorkRequest iPerf3ToLineProtocolWorker = new OneTimeWorkRequest.Builder(Iperf3ToLineProtocolWorker.class)
+ .setInputData(iperf3Input.getInputAsDataBuilder(0).build())
+ .addTag(iperf3Input.getTestUUID())
+ .build();
+ OneTimeWorkRequest influxDB2xUploadWorker = new OneTimeWorkRequest.Builder(InfluxDB2xUploadWorker.class)
+ .setInputData(iperf3Input.getInputAsDataBuilder(0).build())
+ .addTag(iperf3Input.getTestUUID())
+ .build();
+
+
+ this.remoteWorkContinuation = this.remoteWorkManager.beginWith(Arrays.asList(iperf3ExecutorWorker, iperf3MonitorWorker)).then(iPerf3ToLineProtocolWorker);
+ if(spg.getSharedPreference(SPType.logging_sp).getBoolean("enable_influx", false)){
+ this.remoteWorkContinuation = remoteWorkContinuation.then(influxDB2xUploadWorker);
+ }
+ }
+
+ public void execute(){
+ this.remoteWorkContinuation.enqueue();
+
+ }
+
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Fragment.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Fragment.java
deleted file mode 100644
index ff16e37c..00000000
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Fragment.java
+++ /dev/null
@@ -1,857 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2023 Peter Hasse
- * SPDX-FileCopyrightText: 2023 Johann Hackler
- * SPDX-FileCopyrightText: 2023 Fraunhofer FOKUS
- *
- * SPDX-License-Identifier: BSD-3-Clause-Clear
- */
-
-package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.os.Bundle;
-import android.os.Environment;
-import android.os.Handler;
-import android.os.Looper;
-import android.system.ErrnoException;
-import android.system.Os;
-import android.text.Editable;
-import android.text.TextWatcher;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.Button;
-import android.widget.CheckBox;
-import android.widget.EditText;
-import android.widget.LinearLayout;
-import android.widget.Spinner;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentResultListener;
-import androidx.lifecycle.MutableLiveData;
-import androidx.lifecycle.Observer;
-import androidx.navigation.NavController;
-import androidx.navigation.fragment.NavHostFragment;
-import androidx.work.Data;
-import androidx.work.OneTimeWorkRequest;
-import androidx.work.WorkInfo;
-import androidx.work.WorkManager;
-
-import com.google.android.material.progressindicator.LinearProgressIndicator;
-import com.google.common.util.concurrent.ListenableFuture;
-
-import java.io.File;
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.UUID;
-
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R;
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SPType;
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SharedPreferencesGrouper;
-
-public class Iperf3Fragment extends Fragment {
- private static final String TAG = "iperf3InputFragment";
- private final int SHOW_PROGRESSBAR = 3000;
- private final String IPERF3IP = "iperf3IP";
- private final String IPERF3PORT = "iperf3Port";
- private final String IPERF3BANDWIDTH = "iperf3Bandwidth";
- private final String IPERF3DURATION = "iperf3Duration";
- private final String IPERF3INTERVAL = "iperf3Interval";
- private final String IPERF3BYTES = "iperf3Bytes";
- private final String IPERF3STREAMS = "iperf3Streams";
- private final String IPERF3BIDIR = "iperf3BiDir";
- private final String IPERF3REVERSE = "iperf3Reverse";
- private final String IPERF3JSON = "iperf3Json";
- private final String IPERF3ONEOFF = "iperf3OneOff";
- private final String IPERF3IDXPROTOCOL = "iperf3IdxProtocol";
- private final String IPERF3IDXMODE = "iperf3IdxMode";
- private final String IPERF3CPORT = "iperf3cport";
- private CheckBox iperf3BiDir;
- private CheckBox iperf3Reverse;
-
- private CheckBox iperf3OneOff;
- private EditText iperf3EtIp;
- private EditText iperf3EtPort;
- private EditText iperf3EtBandwidth;
- private EditText iperf3EtDuration;
- private EditText iperf3EtInterval;
- private EditText iperf3EtBytes;
- private EditText iperf3EtStreams;
- private EditText iperf3Cport;
- private Button sendBtn;
- private Button instancesBtn;
- private Spinner protocolSpinner;
- private Spinner iperf3ModeSpinner;
- private Iperf3RunResultDao iperf3RunResultDao;
- private LinearProgressIndicator progressIndicator;
- private int[] failedColors;
- private int[] runningColors;
- private int[] succesColors;
- private LinkedList editTexts;
- private String rawIperf3file;
- private String logFileDir;
- private String logFileName;
- private View v;
- private SharedPreferencesGrouper spg;
- private Iperf3Input input;
- private WorkManager iperf3WM;
- private Iperf3ResultsDataBase db;
- private ArrayList uids;
- private Context ct;
- private final Runnable progressbarUpdate = new Runnable() {
- @Override
- public void run() {
- progressIndicator.setVisibility(LinearProgressIndicator.INVISIBLE);
- progressIndicator.setIndicatorColor(runningColors);
- }
- };
-
- @Override
- public void onPause() {
- super.onPause();
- }
-
- @Override
- public void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- this.input = new Iperf3Input();
- this.db = Iperf3ResultsDataBase.getDatabase(getActivity().getApplicationContext());
- this.uids = new ArrayList<>(this.db.iperf3RunResultDao().getIDs());
- this.iperf3WM = WorkManager.getInstance(getActivity().getApplicationContext());
- this.logFileDir =
- Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS)
- .getAbsolutePath() + "/omnt/iperf3RawLogs/";
- this.iperf3RunResultDao = db.iperf3RunResultDao();
- File iperf3Path = new File(this.logFileDir);
- if (!iperf3Path.exists()) {
- iperf3Path.mkdir();
- }
- this.ct = requireContext();
- this.spg = SharedPreferencesGrouper.getInstance(this.ct);
- }
-
- @Override
- public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
-
-
- NavController navController = NavHostFragment.findNavController(this);
- MutableLiveData liveData = navController.getCurrentBackStackEntry()
- .getSavedStateHandle()
- .getLiveData("uid");
-
-
-
- liveData.observe(getViewLifecycleOwner(), new Observer() {
- @Override
- public void onChanged(String s) {
- Iperf3RunResult iperf3RunResult = db.iperf3RunResultDao().getRunResult(s);
-
- iperf3EtIp.setText(iperf3RunResult.input.iperf3IP);
- iperf3EtPort.setText(iperf3RunResult.input.iperf3Port);
- iperf3EtBandwidth.setText(iperf3RunResult.input.iperf3Bandwidth);
- iperf3EtDuration.setText(iperf3RunResult.input.iperf3Duration);
- iperf3EtInterval.setText(iperf3RunResult.input.iperf3Interval);
- iperf3EtBytes.setText(iperf3RunResult.input.iperf3Bytes);
- iperf3Cport.setText(iperf3RunResult.input.iperf3Cport);
-
- iperf3Reverse.setChecked(iperf3RunResult.input.iperf3Reverse);
- iperf3BiDir.setChecked(iperf3RunResult.input.iperf3BiDir);
- iperf3OneOff.setChecked(iperf3RunResult.input.iperf3OneOff);
- protocolSpinner.setSelection(iperf3RunResult.input.iperf3IdxProtocol);
- iperf3ModeSpinner.setSelection(iperf3RunResult.input.iperf3IdxMode);
-
-
- }
- });
- }
-
-
- private void saveTextInputToSharedPreferences(EditText field, String name) {
- field.addTextChangedListener(new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
-
- }
-
- @Override
- public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
- spg.getSharedPreference(SPType.iperf3_sp).edit().putString(name, field.getText().toString()).apply();
- }
-
- @Override
- public void afterTextChanged(Editable editable) {
-
- }
- });
-
- }
-
-
-
- private void saveCheckboxInputToSharedPreferences(CheckBox box, String name) {
- box.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- spg.getSharedPreference(SPType.iperf3_sp).edit().putBoolean(name, box.isChecked()).apply();
- }
- });
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
- v = inflater.inflate(R.layout.fragment_iperf3_input, parent, false);
- iperf3EtIp = v.findViewById(R.id.iperf3_ip);
- iperf3EtPort = v.findViewById(R.id.iperf3_port);
- iperf3EtBandwidth = v.findViewById(R.id.iperf3_bandwidth);
- iperf3EtDuration = v.findViewById(R.id.iperf3_duration);
-
-
-
-
- iperf3EtInterval = v.findViewById(R.id.iperf3_interval);
- iperf3EtBytes = v.findViewById(R.id.iperf3_bytes);
- iperf3EtStreams = v.findViewById(R.id.iperf3_streams);
- iperf3Cport = v.findViewById(R.id.iperf3_cport);
- progressIndicator = v.findViewById(R.id.iperf3_progress);
-
- iperf3EtDuration.addTextChangedListener(new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
-
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- iperf3EtBytes.setEnabled(s.length() <= 0);
- }
-
- @Override
- public void afterTextChanged(Editable s) {
-
- }
- });
-
-
- iperf3EtBytes.addTextChangedListener(new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
-
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- iperf3EtDuration.setEnabled(s.length() <= 0);
- }
-
- @Override
- public void afterTextChanged(Editable s) {
-
- }
- });
-
- saveTextInputToSharedPreferences(iperf3EtIp, IPERF3IP);
- saveTextInputToSharedPreferences(iperf3EtPort, IPERF3PORT);
- saveTextInputToSharedPreferences(iperf3EtBandwidth, IPERF3BANDWIDTH);
- saveTextInputToSharedPreferences(iperf3EtDuration, IPERF3DURATION);
- saveTextInputToSharedPreferences(iperf3EtInterval, IPERF3INTERVAL);
- saveTextInputToSharedPreferences(iperf3EtBytes, IPERF3BYTES);
- saveTextInputToSharedPreferences(iperf3EtStreams, IPERF3STREAMS);
- saveTextInputToSharedPreferences(iperf3Cport, IPERF3CPORT);
-
- failedColors = new int[] {getContext().getColor(R.color.crimson),
- getContext().getColor(R.color.crimson), getContext().getColor(R.color.crimson)};
- runningColors = new int[] {getContext().getColor(R.color.purple_500),
- getContext().getColor(R.color.crimson), getContext().getColor(R.color.forestgreen)};
- succesColors = new int[] {getContext().getColor(R.color.forestgreen),
- getContext().getColor(R.color.forestgreen), getContext().getColor(R.color.forestgreen)};
-
- progressIndicator.setIndicatorColor(runningColors);
- progressIndicator.setIndeterminateAnimationType(
- LinearProgressIndicator.INDETERMINATE_ANIMATION_TYPE_CONTIGUOUS);
- progressIndicator.setVisibility(LinearProgressIndicator.INVISIBLE);
-
- editTexts = new LinkedList<>();
- editTexts.add(iperf3EtIp);
- editTexts.add(iperf3EtPort);
- editTexts.add(iperf3EtBandwidth);
- editTexts.add(iperf3EtDuration);
- editTexts.add(iperf3EtInterval);
- editTexts.add(iperf3EtBytes);
- editTexts.add(iperf3EtStreams);
- editTexts.add(iperf3Cport);
- sendBtn = v.findViewById(R.id.iperf3_send);
- instancesBtn = v.findViewById(R.id.iperf3_instances_button);
-
- sendBtn.setOnClickListener(this::executeIperfCommand);
- instancesBtn.setOnClickListener(this::showInstances);
-
- iperf3BiDir = v.findViewById(R.id.iperf_bidir);
- iperf3Reverse = v.findViewById(R.id.iperf3_reverse);
- iperf3OneOff = v.findViewById(R.id.iperf3_one_off);
-
- saveCheckboxInputToSharedPreferences(iperf3BiDir, IPERF3BIDIR);
- saveCheckboxInputToSharedPreferences(iperf3Reverse, IPERF3REVERSE);
- saveCheckboxInputToSharedPreferences(iperf3OneOff, IPERF3ONEOFF);
-
- protocolSpinner = v.findViewById(R.id.iperf3_protocol_spinner);
- ArrayAdapter adapter =
- ArrayAdapter.createFromResource(getContext(), R.array.iperf_protocol,
- R.layout.support_simple_spinner_dropdown_item);
- adapter.setDropDownViewResource(R.layout.support_simple_spinner_dropdown_item);
- protocolSpinner.setAdapter(adapter);
-
- iperf3ModeSpinner = v.findViewById(R.id.iperf3_mode_spinner);
- ArrayAdapter mode_adapter =
- ArrayAdapter.createFromResource(getContext(), R.array.iperf_mode,
- R.layout.support_simple_spinner_dropdown_item);
- adapter.setDropDownViewResource(R.layout.support_simple_spinner_dropdown_item);
- iperf3ModeSpinner.setAdapter(mode_adapter);
-
-
- getActivity().getSupportFragmentManager()
- .setFragmentResultListener("input", getViewLifecycleOwner(),
- new FragmentResultListener() {
- @Override
- public void onFragmentResult(@NonNull String requestKey,
- @NonNull Bundle result) {
-
- Iperf3RunResult iperf3RunResult =
- db.iperf3RunResultDao().getRunResult(result.getString("uid"));
- String logFileName = iperf3RunResult.input.iperf3LogFileName.split("_")[0];
- if (logFileName.equals("iperf3")) {
- logFileName = "";
- }
-
- iperf3EtIp.setText(iperf3RunResult.input.iperf3IP);
- iperf3EtPort.setText(iperf3RunResult.input.iperf3Port);
- iperf3EtBandwidth.setText(iperf3RunResult.input.iperf3Bandwidth);
- iperf3EtDuration.setText(iperf3RunResult.input.iperf3Duration);
- iperf3EtInterval.setText(iperf3RunResult.input.iperf3Interval);
- iperf3EtBytes.setText(iperf3RunResult.input.iperf3Bytes);
- iperf3EtStreams.setText(iperf3RunResult.input.streams);
- iperf3Cport.setText(iperf3RunResult.input.iperf3Cport);
-
- iperf3Reverse.setChecked(iperf3RunResult.input.iperf3Reverse);
- iperf3BiDir.setChecked(iperf3RunResult.input.iperf3BiDir);
- iperf3OneOff.setChecked(iperf3RunResult.input.iperf3OneOff);
- protocolSpinner.setSelection(iperf3RunResult.input.iperf3IdxProtocol);
- iperf3ModeSpinner.setSelection(iperf3RunResult.input.iperf3IdxMode);
-
- writeToSP();
- }
- });
- iperf3EtIp.setText(spg.getSharedPreference(SPType.iperf3_sp).getString(IPERF3IP, null));
- iperf3EtPort.setText(spg.getSharedPreference(SPType.iperf3_sp).getString(IPERF3PORT, null));
- iperf3EtBandwidth.setText(spg.getSharedPreference(SPType.iperf3_sp).getString(IPERF3BANDWIDTH, null));
- iperf3EtDuration.setText(spg.getSharedPreference(SPType.iperf3_sp).getString(IPERF3DURATION, null));
- iperf3EtInterval.setText(spg.getSharedPreference(SPType.iperf3_sp).getString(IPERF3INTERVAL, null));
- iperf3EtBytes.setText(spg.getSharedPreference(SPType.iperf3_sp).getString(IPERF3BYTES, null));
- iperf3EtStreams.setText(spg.getSharedPreference(SPType.iperf3_sp).getString(IPERF3STREAMS, null));
- iperf3Cport.setText(spg.getSharedPreference(SPType.iperf3_sp).getString(IPERF3CPORT, null));
-
- iperf3BiDir.setChecked(spg.getSharedPreference(SPType.iperf3_sp).getBoolean(IPERF3BIDIR, false));
- iperf3Reverse.setChecked(spg.getSharedPreference(SPType.iperf3_sp).getBoolean(IPERF3REVERSE, false));
- iperf3OneOff.setChecked(spg.getSharedPreference(SPType.iperf3_sp).getBoolean(IPERF3ONEOFF, false));
- protocolSpinner.setSelection(spg.getSharedPreference(SPType.iperf3_sp).getInt(IPERF3IDXPROTOCOL, 0));
- iperf3ModeSpinner.setSelection(spg.getSharedPreference(SPType.iperf3_sp).getInt(IPERF3IDXMODE, 0));
-
-
- try {
- Os.setenv("TMPDIR", String.valueOf(getActivity().getCacheDir()), true);
- } catch (ErrnoException e) {
- Log.d(TAG,e.toString());
- }
- return v;
- }
-
- public void showInstances(View view) {
- Bundle bundle = new Bundle();
- bundle.putStringArrayList("iperf3List", uids);
-
- NavController navController;
-
- NavHostFragment navHostFragment =
- (NavHostFragment) getActivity().getSupportFragmentManager()
- .findFragmentById(R.id.fragmentContainerView);
- navController = navHostFragment.getNavController();
-
- navController.navigate(R.id.runners_list, bundle);
- }
-
- private boolean isModeSpinnerClient() {
- String status = iperf3ModeSpinner.getSelectedItem().toString();
- return status.equals("Client");
- }
-
- public void executeIperfCommand(View view) {
- String[] command = parseInput().split(" ");
-
- String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath() + "/omnt/iperf3LP/";
-
- if(input.iperf3Json){
- try {
- Files.createDirectories(Paths.get(path));
- } catch (IOException e) {
- Toast.makeText(requireContext(),"Could not create Dir files!", Toast.LENGTH_SHORT).show();
- }
- }
-
- // create the log file;
-
- String iperf3WorkerID = input.uuid;
-
- input.iperf3LineProtocolFile = path + iperf3WorkerID + ".txt";
- Data.Builder iperf3Data = new Data.Builder();
- iperf3Data.putStringArray("commands", command);
- iperf3Data.putString("iperf3WorkerID", iperf3WorkerID);
- iperf3Data.putString("rawIperf3file", rawIperf3file);
- iperf3Data.putString("iperf3LineProtocolFile", input.iperf3LineProtocolFile);
- iperf3Data.putString("measurementName", input.measurementName);
- iperf3Data.putString("ip", input.iperf3IP);
- iperf3Data.putString("port", input.iperf3Port);
- iperf3Data.putString("bandwidth", input.iperf3Bandwidth);
- iperf3Data.putString("duration", input.iperf3Duration);
- iperf3Data.putString("interval", input.iperf3Interval);
- iperf3Data.putString("bytes", input.iperf3Bytes);
- iperf3Data.putString("protocol", protocolSpinner.getSelectedItem().toString());
- iperf3Data.putBoolean("rev", input.iperf3Reverse);
- iperf3Data.putBoolean("biDir", input.iperf3BiDir);
- iperf3Data.putBoolean("oneOff", input.iperf3OneOff);
- iperf3Data.putString("client", iperf3ModeSpinner.getSelectedItem().toString());
- iperf3Data.putString("timestamp", input.timestamp.toString());
- iperf3Data.putString("protocol", protocolSpinner.getSelectedItem().toString());
- iperf3Data.putString("cport", input.iperf3Cport);
-
- ListenableFuture> status = iperf3WM.getWorkInfosByTag("iperf3Run");
-
-/* try {
- for (WorkInfo workInfo : status.get()) {
- if (workInfo.getState().equals(WorkInfo.State.RUNNING)) {
- Toast.makeText(getContext(), "iperf3 Test is running!", Toast.LENGTH_SHORT)
- .show();
- return;
- }
- }
- } catch (ExecutionException | InterruptedException e) {
- Log.d(TAG,e.toString());
-;
- }*/
-
- uids.add(0, iperf3WorkerID);
- iperf3Data.putInt("notificationID", uids.size());
-
-
- OneTimeWorkRequest iperf3WR =
- new OneTimeWorkRequest
- .Builder(Iperf3Worker.class)
- .setInputData(iperf3Data.build())
- .addTag("iperf3Run")
- .addTag(iperf3WorkerID)
- .build();
- OneTimeWorkRequest iperf3LP =
- new OneTimeWorkRequest
- .Builder(Iperf3ToLineProtocolWorker.class)
- .setInputData(iperf3Data.build())
- .build();
- OneTimeWorkRequest iperf3UP =
- new OneTimeWorkRequest
- .Builder(Iperf3UploadWorker.class)
- .setInputData(iperf3Data.build())
- .addTag("iperf3")
- .build();
-
- iperf3RunResultDao.insert(
- new Iperf3RunResult(iperf3WorkerID, -100, false, input, input.timestamp));
-
-
-
- if (spg.getSharedPreference(SPType.logging_sp).getBoolean("enable_influx", false) && input.iperf3Json) {
- iperf3WM.beginWith(iperf3WR).then(iperf3LP).then(iperf3UP).enqueue();
- } else if(input.iperf3Json) {
- iperf3WM.beginWith(iperf3WR).then(iperf3LP).enqueue();
- } else {
- iperf3WM.beginWith(iperf3WR).enqueue();
- }
-
-
-
- Handler progressbarHandler = new Handler(Looper.myLooper());
-
- iperf3WM.getWorkInfoByIdLiveData(iperf3WR.getId()).observeForever(workInfo -> {
- int iperf3_result;
- iperf3_result = workInfo.getOutputData().getInt("iperf3_result", -100);
- if (workInfo.getState().equals(WorkInfo.State.CANCELLED)) {
- iperf3_result = -1;
- }
- iperf3RunResultDao.updateResult(iperf3WorkerID, iperf3_result);
- Log.d(TAG, "onChanged: iperf3_result: " + iperf3_result);
- if (iperf3_result == -100) {
- progressIndicator.setVisibility(LinearProgressIndicator.VISIBLE);
- if (!isModeSpinnerClient()) {
- progressbarHandler.postDelayed(progressbarUpdate, SHOW_PROGRESSBAR);
- }
- } else if (iperf3_result != 0) {
- progressIndicator.setIndicatorColor(failedColors);
- progressbarHandler.postDelayed(progressbarUpdate, SHOW_PROGRESSBAR);
-
- } else {
- progressIndicator.setIndicatorColor(succesColors);
- progressbarHandler.postDelayed(progressbarUpdate, SHOW_PROGRESSBAR);
- }
-
- });
- iperf3WM.getWorkInfoByIdLiveData(iperf3UP.getId()).observeForever(workInfo -> {
- boolean iperf3_upload;
- iperf3_upload = workInfo.getOutputData().getBoolean("iperf3_upload", false);
- Log.d(TAG, "onChanged: iperf3_upload: " + iperf3_upload);
- iperf3RunResultDao.updateUpload(iperf3WorkerID, iperf3_upload);
- });
-
-
- }
-
- private String getKeyFromId(String s, String value) {
- String key = "";
- switch (s) {
- case "iperf3_logfile":
- key = "--logfile";
- input.measurementName = value;
- break;
- case "iperf3_streams":
- key = "-P";
- input.streams = value;
- break;
- case "iperf3_ip":
- key = "-c";
- input.iperf3IP = value;
- break;
- case "iperf3_port":
- key = "-p";
- input.iperf3Port = value;
- break;
- case "iperf3_bandwidth":
- key = "-b";
- input.iperf3Bandwidth = value;
- break;
- case "iperf3_duration":
- key = "-t";
- input.iperf3Duration = value;
- break;
- case "iperf3_interval":
- key = "-i";
- input.iperf3Interval = value;
- break;
- case "iperf3_bytes":
- key = "-n";
- input.iperf3Bytes = value;
- break;
- case "iperf3_cport":
- key = "--cport";
- input.iperf3Cport = value;
- break;
- }
- return key;
- }
-
- private String parseInput() {
- List stb = new LinkedList<>();
- for (EditText et : editTexts) {
- String value = et.getText().toString();
- if (!value.equals("")) {
- String s = getResources().getResourceEntryName(et.getId());
- String key = getKeyFromId(s, value);
- if (s.equals("iperf3_bandwidth")) {
- value += "M";
- }
- stb.add(key);
- stb.add(value);
- }
- }
-
- String protocol = protocolSpinner.getSelectedItem().toString();
- if (!protocol.equals("TCP")) {
- stb.add("--" + protocol.toLowerCase());
- }
- input.iperf3IdxProtocol = protocolSpinner.getSelectedItemPosition();
-
- input.timestamp = new Timestamp(System.currentTimeMillis());
- String iperf3TS = input.timestamp.toString().replace(" ", "_").replace(":", "_");
-
- input.uuid = UUID.randomUUID().toString();
-
- input.measurementName = "Iperf3";
- this.logFileName = String.format("iperf3_%s_%s.json", iperf3TS, input.uuid);
-
- input.iperf3LogFileName = this.logFileName;
- this.rawIperf3file = this.logFileDir + this.logFileName;
- input.iperf3rawIperf3file = this.rawIperf3file;
-
- stb.add("--logfile");
- stb.add(this.rawIperf3file);
-
- input.iperf3BiDir = false;
- input.iperf3Reverse = false;
- input.iperf3OneOff = false;
- input.iperf3Json = true;
-
- if (!isModeSpinnerClient()) {
- stb.add("-s");
- input.iperf3IdxMode = iperf3ModeSpinner.getSelectedItemPosition();
- }
- if (iperf3BiDir.isChecked()) {
- stb.add("--bidir");
- input.iperf3BiDir = true;
- }
- if (iperf3Reverse.isChecked()) {
- stb.add("--reverse");
- input.iperf3Reverse = true;
- }
- if (iperf3OneOff.isChecked()) {
- stb.add("--one-off");
- input.iperf3OneOff = true;
- }
- stb.add("--json-stream");
-
- stb.add("--connect-timeout");
- stb.add("500");
-
-
- String joined = String.join(" ", stb);
-
- Log.d(TAG, "parseInput: joined command " + joined);
- input.iperf3Command = joined;
-
-
- return joined;
- }
-
- @Override
- public void onSaveInstanceState(@NonNull Bundle outState) {
- super.onSaveInstanceState(outState);
- }
-
- private void writeToSP() {
- SharedPreferences.Editor editor = spg.getSharedPreference(SPType.iperf3_sp).edit();
- editor.putInt(IPERF3IDXPROTOCOL, protocolSpinner.getSelectedItemPosition());
- editor.putInt(IPERF3IDXMODE, iperf3ModeSpinner.getSelectedItemPosition());
- editor.putString(IPERF3IP, iperf3EtIp.getText().toString());
- editor.putString(IPERF3PORT, iperf3EtPort.getText().toString());
- editor.putString(IPERF3BANDWIDTH, iperf3EtBandwidth.getText().toString());
- editor.putString(IPERF3DURATION, iperf3EtDuration.getText().toString());
- editor.putString(IPERF3INTERVAL, iperf3EtInterval.getText().toString());
- editor.putString(IPERF3BYTES, iperf3EtBytes.getText().toString());
- editor.putString(IPERF3STREAMS, iperf3EtStreams.getText().toString());
- editor.putString(IPERF3CPORT, iperf3Cport.getText().toString());
-
- editor.putBoolean(IPERF3BIDIR, iperf3BiDir.isChecked());
- editor.putBoolean(IPERF3REVERSE, iperf3Reverse.isChecked());
- editor.putBoolean(IPERF3ONEOFF, iperf3OneOff.isChecked());
- editor.apply();
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- if(this.isResumed())
- writeToSP();
- }
-
-
-
- public static class Iperf3Input {
- public boolean iperf3BiDir;
- public boolean iperf3Reverse;
- public boolean iperf3Json;
- public boolean iperf3OneOff;
- public int iperf3IdxMode;
- public int iperf3IdxProtocol;
- public String uuid;
- public String iperf3Command;
- public String iperf3rawIperf3file;
- public String iperf3LogFileName;
- public String measurementName;
- public String iperf3IP;
- public String iperf3Port;
- public String iperf3Bandwidth;
- public String iperf3LineProtocolFile;
- public String iperf3Duration;
- public String iperf3Interval;
- public String iperf3Bytes;
- public Timestamp timestamp;
- public String streams;
- public String iperf3Cport;
- private List getFields(){
- List fields = Arrays.asList(Iperf3Input.class.getDeclaredFields());
- fields.sort((o1, o2) -> {
- return o1.toGenericString().compareTo(o2.toGenericString());
- });
- return fields;
- }
- private LinearLayout getTextView(String name, String value, Context ct){
- LinearLayout mainLL = new LinearLayout(ct);
- mainLL.setOrientation(LinearLayout.HORIZONTAL);
-
-
- LinearLayout.LayoutParams parameterLayoutName = new LinearLayout.LayoutParams(
- 0,
- ViewGroup.LayoutParams.WRAP_CONTENT);
- parameterLayoutName.weight = 1F;
- TextView parameterName = new TextView(ct);
- parameterName.setTextIsSelectable(true);
- parameterName.setText(String.format("%s", name));
- parameterName.setLayoutParams(parameterLayoutName);
- TextView parameterValue = new TextView(ct);
- parameterValue.setTextIsSelectable(true);
- parameterValue.setText(String.format("%s", value));
- LinearLayout.LayoutParams parameterLayoutValue = new LinearLayout.LayoutParams(
- 0,
- ViewGroup.LayoutParams.WRAP_CONTENT);
- parameterLayoutValue.weight = 3F;
- parameterValue.setLayoutParams(parameterLayoutValue);
-
- mainLL.addView(parameterName);
- mainLL.addView(parameterValue);
- return mainLL;
- }
- private LinearLayout getTextViewValue(String key, String value, Context ct){
- LinearLayout mainLL = new LinearLayout(ct);
- mainLL.setOrientation(LinearLayout.HORIZONTAL);
- mainLL.setFocusable(false);
- mainLL.setFocusedByDefault(false);
-
- TextView parameterValue = new TextView(ct);
-
- parameterValue.setTextIsSelectable(true);
- parameterValue.setText(String.format("%s", value));
- LinearLayout.LayoutParams parameterLayoutValue = new LinearLayout.LayoutParams(
- 0,
- ViewGroup.LayoutParams.WRAP_CONTENT);
- parameterValue.setPadding(5, 5, 5, 5);
- parameterLayoutValue.setMargins(0, 0, 10, 10);
- parameterLayoutValue.weight = 1F;
- parameterValue.setLayoutParams(parameterLayoutValue);
-
- mainLL.addView(parameterValue);
- return mainLL;
- }
- public LinearLayout getInputAsLinearLayoutKeyValue(LinearLayout mainLL, Context ct){
- mainLL.setOrientation(LinearLayout.VERTICAL);
- LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
- 0,
- ViewGroup.LayoutParams.WRAP_CONTENT);
- layoutParams.weight = 8F;
- mainLL.setLayoutParams(layoutParams);
- String[] protocol =
- ct.getResources().getStringArray(R.array.iperf_protocol);
- String[] mode = ct.getResources().getStringArray(R.array.iperf_mode);
- for(Field parameter: getFields()){
- try {
- Object parameterValueObj = parameter.get(this);
- if(parameterValueObj == null){
- continue;
- }
-
- String parameterName = parameter.getName().replace("iperf3", "");
- if(parameterName.equals("measurementName")
- || parameterName.equals("rawIperf3file")
- || parameterName.equals("LogFileName")
- || parameterName.equals("Command")
- || parameterName.equals("LineProtocolFile")) continue;
-
- String parameterValue = parameter.get(this).toString();
- if(parameterValue.equals("false")){
- continue;
- }
- if(parameterName.equals("IdxProtocol")){
- parameterName = "Protocol";
- parameterValue = protocol[Integer.parseInt(parameterValue)];
- }
-
- if(parameterName.equals("IdxMode")){
- parameterName = "Mode";
- parameterValue = mode[Integer.parseInt(parameterValue)];
- }
- mainLL.addView(getTextView(
- parameterName,
- parameterValue,
- ct));
-
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- }
- return mainLL;
- }
-
- public LinearLayout getInputAsLinearLayoutValue(LinearLayout mainLL, Context ct){
- mainLL.setOrientation(LinearLayout.HORIZONTAL);
- LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
- 0,
- ViewGroup.LayoutParams.WRAP_CONTENT);
- layoutParams.weight = 10F;
- mainLL.setLayoutParams(layoutParams);
- String[] protocol =
- ct.getResources().getStringArray(R.array.iperf_protocol);
- String[] mode = ct.getResources().getStringArray(R.array.iperf_mode);
- for(Field parameter: getFields()){
- try {
- Object parameterValueObj = parameter.get(this);
- if(parameterValueObj == null){
- continue;
- }
-
- String parameterName = parameter.getName().replace("iperf3", "");
- if(parameterName.equals("measurementName")
- || parameterName.equals("rawIperf3file")
- || parameterName.equals("LogFileName")
- || parameterName.equals("Command")
- || parameterName.equals("LineProtocolFile")
- || parameterName.equals("timestamp")
- || parameterName.equals("uuid")) continue;
-
- String parameterValue = parameter.get(this).toString();
- if(parameterValue.equals("false")){
- continue;
- }
- if(parameterName.equals("IdxProtocol")){
- parameterName = "Protocol";
- parameterValue = protocol[Integer.parseInt(parameterValue)];
- }
-
- if(parameterName.equals("IdxMode")){
- parameterName = "Mode";
- parameterValue = mode[Integer.parseInt(parameterValue)];
- }
-
- if(parameterValue.equals("true")){
- parameterValue = parameterName;
- }
-
- mainLL.addView(getTextViewValue(
- parameterName,
- parameterValue,
- ct));
-
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- }
- return mainLL;
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3LibLoader.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3LibLoader.java
index c8d20e25..90e51528 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3LibLoader.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3LibLoader.java
@@ -13,7 +13,8 @@
import java.util.ArrayList;
import java.util.List;
-public class Iperf3LibLoader {
+public class
+Iperf3LibLoader {
private static boolean done = false;
private static final String TAG = "Iperf3LibLoader";
@@ -24,10 +25,11 @@ public class Iperf3LibLoader {
"iperf3.12",
"iperf3.15",
"iperf3.16",
- "iperf3.17.1"
+ "iperf3.17.1",
+ "iperf3.18"
);
- protected static synchronized void load() {
+ public static synchronized void load() {
if (done) {
return;
}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3ListFragment.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3ListFragment.java
deleted file mode 100644
index 6ae30a5d..00000000
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3ListFragment.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2023 Peter Hasse
- * SPDX-FileCopyrightText: 2023 Johann Hackler
- * SPDX-FileCopyrightText: 2023 Fraunhofer FOKUS
- *
- * SPDX-License-Identifier: BSD-3-Clause-Clear
- */
-
-//from https://codeburst.io/android-swipe-menu-with-recyclerview-8f28a235ff28
-
-package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3;
-
-import android.annotation.SuppressLint;
-import android.graphics.Canvas;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
-import androidx.recyclerview.widget.ItemTouchHelper;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.work.Data;
-import androidx.work.OneTimeWorkRequest;
-import androidx.work.WorkManager;
-
-import com.google.android.material.floatingactionbutton.FloatingActionButton;
-
-import java.util.ArrayList;
-
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R;
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.SwipeController;
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.SwipeControllerActions;
-
-
-public class Iperf3ListFragment extends Fragment {
- private final String TAG = "Iperf3ListFragment";
- private SwipeController swipeController = null;
- private RecyclerView recyclerView;
- private Iperf3RecyclerViewAdapter adapter;
- private LinearLayoutManager linearLayoutManager;
- private FloatingActionButton uploadBtn;
- private Iperf3ResultsDataBase db;
- @Override
- public void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- }
-
- @SuppressLint("NotifyDataSetChanged")
- public void updateIperf3ListAdapter() {
- if (this.adapter != null) {
- this.adapter.notifyDataSetChanged();
- }
- }
-
- @SuppressLint("ClickableViewAccessibility")
- public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
- View v = inflater.inflate(R.layout.fragment_iperf3_list, parent, false);
- ArrayList uids = this.getArguments().getStringArrayList("iperf3List");
- recyclerView = v.findViewById(R.id.runners_list);
- uploadBtn = v.findViewById(R.id.iperf3_upload_button);
- linearLayoutManager =
- new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
- recyclerView.setLayoutManager(linearLayoutManager);
- adapter = new Iperf3RecyclerViewAdapter(getActivity(), uids, uploadBtn);
- recyclerView.setAdapter(adapter);
- db = Iperf3ResultsDataBase.getDatabase(requireContext());
-
-
- swipeController = new SwipeController(new SwipeControllerActions() {
- @SuppressLint("NotifyDataSetChanged")
- @Override
- public void onRightClicked(int position) {
- WorkManager iperf3WM = WorkManager.getInstance(getContext());
- String uid = uids.get(position);
- iperf3WM.cancelAllWorkByTag(uid);
- Iperf3RunResultDao iperf3RunResultDao = Iperf3ResultsDataBase.getDatabase(requireContext()).iperf3RunResultDao();
- Iperf3RunResult runResult = iperf3RunResultDao.getRunResult(uid);
-
-
- Data.Builder iperf3Data = new Data.Builder();
-
- iperf3Data.putString("rawIperf3file", runResult.input.iperf3rawIperf3file);
- iperf3Data.putString("iperf3LineProtocolFile", runResult.input.iperf3LineProtocolFile);
- iperf3Data.putString("measurementName", runResult.input.measurementName);
- iperf3Data.putString("ip", runResult.input.iperf3IP);
- iperf3Data.putString("port", runResult.input.iperf3Port);
- iperf3Data.putString("bandwidth", runResult.input.iperf3Bandwidth);
- iperf3Data.putString("duration", runResult.input.iperf3Duration);
- iperf3Data.putString("interval", runResult.input.iperf3Interval);
- iperf3Data.putString("bytes", runResult.input.iperf3Bytes);
- iperf3Data.putString("protocol", Iperf3Utils.getProtocolString(runResult.input.iperf3IdxProtocol));
- iperf3Data.putBoolean("rev", runResult.input.iperf3Reverse);
- iperf3Data.putBoolean("biDir", runResult.input.iperf3BiDir);
- iperf3Data.putBoolean("oneOff", runResult.input.iperf3OneOff);
- iperf3Data.putString("client", Iperf3Utils.getModeString(runResult.input.iperf3IdxMode));
- iperf3Data.putString("timestamp", runResult.input.timestamp.toString());
-
- OneTimeWorkRequest iperf3LP =
- new OneTimeWorkRequest
- .Builder(Iperf3ToLineProtocolWorker.class)
- .setInputData(iperf3Data.build())
- .build();
- iperf3WM.enqueue(iperf3LP);
-
-
- if(runResult.result != 0)
- iperf3RunResultDao.updateResult(uid, 1);
- new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
- @Override
- public void run() {
- adapter.notifyDataSetChanged();
- }
- }, 100);
- }
-
- @Override
- public void onLeftClicked(int position) {
- Bundle input = new Bundle();
- input.putString("uid", uids.get(position));
- getActivity().getSupportFragmentManager().setFragmentResult("input", input);
- getActivity().getSupportFragmentManager().popBackStack();
- }
- });
-
-
- ItemTouchHelper itemTouchhelper = new ItemTouchHelper(swipeController);
- itemTouchhelper.attachToRecyclerView(recyclerView);
-
- recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() {
- @Override
- public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
- swipeController.onDraw(c);
- }
- });
- return v;
- }
-
- @Override
- public void onViewCreated(View v, Bundle savedInstanceState) {
- super.onViewCreated(v, savedInstanceState);
- }
-
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- }
-}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3LogFragment.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3LogFragment.java
deleted file mode 100644
index d6364041..00000000
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3LogFragment.java
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2023 Peter Hasse
- * SPDX-FileCopyrightText: 2023 Johann Hackler
- * SPDX-FileCopyrightText: 2023 Fraunhofer FOKUS
- *
- * SPDX-License-Identifier: BSD-3-Clause-Clear
- */
-
-package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.util.Log;
-import android.util.TypedValue;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.ScrollView;
-import android.widget.TextView;
-
-import androidx.cardview.widget.CardView;
-import androidx.core.widget.TextViewCompat;
-import androidx.fragment.app.Fragment;
-
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Error;
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Interval;
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.SUM_TYPE;
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.Sum;
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.UDP.UDP_DL_SUM;
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Metric.METRIC_TYPE;
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Metric.Metric;
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R;
-
-public class Iperf3LogFragment extends Fragment {
-
- private static final String TAG = "Iperf3LogFragment";
- private View v;
- private Iperf3ResultsDataBase db;
- private Handler logHandler;
- private File file;
- private String uid;
- private Drawable runIcon;
- private Drawable uploadIcon;
- private ImageView runIconView;
- private ImageView uploadIconView;
-
- private TextView iperf3OutputViewer;
- private LinearLayout parameterLL;
- private Context ct;
- private LinearLayout metricLL;
- private Metric defaultReverseThroughput;
- private Metric defaultThroughput;
- private Metric defaultRTT;
- private Metric defaultJITTER;
- private Metric PACKET_LOSS;
-
- public Iperf3LogFragment() {
- }
-
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- this.db = Iperf3ResultsDataBase.getDatabase(getActivity().getApplicationContext());
- }
-
- private void setFields(Iperf3RunResult iperf3RunResult) {
-
- }
- private final Runnable logUpdate = new Runnable() {
- @Override
- public void run() {
- Iperf3RunResult iperf3RunResult = db.iperf3RunResultDao().getRunResult(uid);
- Log.d(TAG, "run: " + iperf3RunResult.result);
- runIcon = Iperf3Utils.getDrawableResult(requireContext(), iperf3RunResult.result);
- runIconView.setImageDrawable(runIcon);
- uploadIcon = Iperf3Utils.getDrawableUpload(ct, iperf3RunResult.result, iperf3RunResult.uploaded);
- uploadIconView.setImageDrawable(uploadIcon);
-
- BufferedReader br = null;
- StringBuilder text = new StringBuilder();
-
- try {
- br = new BufferedReader(new FileReader(file));
- } catch (FileNotFoundException e) {
- iperf3OutputViewer.setText(String.format("no iPerf3 file found, with following path: \n %s", iperf3RunResult.input.iperf3rawIperf3file));
- logHandler.removeCallbacks(logUpdate);
- return;
- }
- String line;
-
- Iperf3Parser iperf3Parser = new Iperf3Parser(iperf3RunResult.input.iperf3rawIperf3file);
- iperf3Parser.addPropertyChangeListener(new PropertyChangeListener() {
-
- private void parseSum(Sum sum, Metric throughput){
- SUM_TYPE sumType = sum.getSumType();
- throughput.update(sum.getBits_per_second());
- switch (sumType){
- case UDP_DL:
- defaultJITTER.update(((UDP_DL_SUM)sum).getJitter_ms());
- PACKET_LOSS.update(((UDP_DL_SUM) sum).getLost_percent());
- case TCP_DL:
- if(throughput.getDirectionName().getText().equals("Throughput")){
- throughput.getDirectionName().setText("Downlink Mbit/s");
- }
- break;
- case UDP_UL:
- case TCP_UL:
- if(throughput.getDirectionName().getText().equals("Throughput")){
- throughput.getDirectionName().setText("Uplink Mbit/s");
- }
- break;
- }
-
- }
- public void propertyChange(PropertyChangeEvent evt) {
-
- switch (evt.getPropertyName()){
- case "interval":
- Interval interval = (Interval) evt.getNewValue();
- parseSum(interval.getSum(), defaultThroughput);
- if(interval.getSumBidirReverse() != null) parseSum(interval.getSumBidirReverse(),
- defaultReverseThroughput);
- break;
- case "start":
- break;
- case "end":
- break;
- case "error":
- Error error = (Error) evt.getNewValue();
- TextView errorView = new TextView(ct);
- errorView.setText(error.getError());
- errorView.setTextColor(ct.getColor(R.color.crimson));
- errorView.setPadding(10, 10, 10, 10);
- errorView.setTextSize(20);
- metricLL.addView(errorView);
- break;
- }
- }
- });
-
- iperf3Parser.parse();
- if (iperf3RunResult.result != -100) {
- logHandler.removeCallbacks(logUpdate);
- return;
- }
- setFields(iperf3RunResult);
- logHandler.removeCallbacks(logUpdate);
- logHandler.postDelayed(this, 1000);
- }
- };
-
-
-
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- v = inflater.inflate(R.layout.fragment_iperf3_log, container, false);
- Iperf3RunResult iperf3RunResult =
- db.iperf3RunResultDao().getRunResult(this.getArguments().getString("uid"));
- ct = requireContext();
- LinearLayout mainLL = v.findViewById(R.id.iperf3_list_fragment);
- mainLL.setOrientation(LinearLayout.VERTICAL);
-
- LinearLayout firstRow = new LinearLayout(ct);
- firstRow.setOrientation(LinearLayout.HORIZONTAL);
-
- LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT);
- mainLL.setLayoutParams(layoutParams);
-
- LinearLayout.LayoutParams foo = new LinearLayout.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT);
- foo.setMargins(30, 10, 0, 0);
- firstRow.setLayoutParams(foo);
-
-
- runIconView = new ImageView(ct);
- LinearLayout.LayoutParams runIconViewLayout = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT);
- runIconViewLayout.weight = 0.2F;
- runIconViewLayout.height = 100;
- runIconViewLayout.gravity = Gravity.RIGHT;
- runIconView.setLayoutParams(runIconViewLayout);
- runIcon = Iperf3Utils.getDrawableResult(ct, iperf3RunResult.result);
- runIconView.setImageDrawable(runIcon);
- runIconView.setTooltipText(String.format("Indicates the result of the iPerf3 run: %s", iperf3RunResult.result));
- runIconView.setLayoutParams(runIconViewLayout);
-
-
- uploadIconView = new ImageView(ct);
- uploadIconView.setTooltipText(String.format("Indicates if the iPerf3 run was uploaded to the server: %s", iperf3RunResult.uploaded));
- LinearLayout.LayoutParams uploadIconViewLayout = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT);
- uploadIconViewLayout.weight = 0.2F;
- uploadIconViewLayout.height = 100;
- uploadIconViewLayout.gravity = Gravity.RIGHT;
- uploadIcon = Iperf3Utils.getDrawableUpload(ct, iperf3RunResult.result, iperf3RunResult.uploaded);
- uploadIconView.setImageDrawable(uploadIcon);
- uploadIconView.setLayoutParams(uploadIconViewLayout);
-
-
- parameterLL = iperf3RunResult.input.getInputAsLinearLayoutKeyValue(new LinearLayout(ct), ct);
-
-
-
- firstRow.addView(parameterLL);
-
-
-
-
- LinearLayout headerWrapper = new LinearLayout(ct);
- LinearLayout.LayoutParams headerWrapperLayout = new LinearLayout.LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT,
- ViewGroup.LayoutParams.WRAP_CONTENT);
- headerWrapper.setLayoutParams(headerWrapperLayout);
- headerWrapper.setOrientation(LinearLayout.VERTICAL);
- CardView cardView = new CardView(ct);
- LinearLayout.LayoutParams cardViewLayout = Iperf3Utils.getLayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT,
- 0);
- headerWrapper.setPadding(30, 30, 30, 30);
- cardView.setLayoutParams(cardViewLayout);
- cardView.setRadius(10);
- cardView.setCardElevation(10);
- cardView.setUseCompatPadding(true);
- cardView.addView(headerWrapper);
- cardView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- //TODO: implement click on card, goto input fragmet
- }
- });
-
- LinearLayout header = new LinearLayout(ct);
- LinearLayout.LayoutParams headerLayout = new LinearLayout.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT, 100);
- header.setLayoutParams(headerLayout);
- header.setOrientation(LinearLayout.HORIZONTAL);
-
- TextView headerName = new TextView(ct);
- headerName.setText("iPerf3 run");
- LinearLayout.LayoutParams headerNameLayout = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT);
- headerNameLayout.weight = 0.6F;
- headerName.setLayoutParams(headerNameLayout);
- header.addView(headerName);
- header.addView(runIconView);
- header.addView(uploadIconView);
- ImageButton expandButton = new ImageButton(ct);
- expandButton.setImageResource(R.drawable.baseline_expand_more_24);
- firstRow.setVisibility(View.GONE);
- expandButton.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- if (firstRow.getVisibility() == View.VISIBLE) {
- firstRow.setVisibility(View.GONE);
- expandButton.setImageResource(R.drawable.baseline_expand_more_24);
- } else {
- firstRow.setVisibility(View.VISIBLE);
- expandButton.setImageResource(R.drawable.baseline_expand_less_24);
- }
-
- }
- });
- LinearLayout.LayoutParams imageButtonLayout = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT);
- imageButtonLayout.weight = 0.2F;
- expandButton.setLayoutParams(imageButtonLayout);
-
- header.addView(expandButton);
- headerWrapper.addView(header);
- headerWrapper.addView(firstRow);
-
- uid = iperf3RunResult.uid;
-
- mainLL.addView(cardView);
-
- LinearLayout secondRow = new LinearLayout(ct);
- LinearLayout.LayoutParams secondRowLayoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT);
- secondRow.setOrientation(LinearLayout.HORIZONTAL);
- secondRowLayoutParams.setMargins(0, 20, 0, 20);
- secondRow.setLayoutParams(secondRowLayoutParams);
- ScrollView scrollView = new ScrollView(ct);
- iperf3OutputViewer = new TextView(ct);
- iperf3OutputViewer.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
- TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration(iperf3OutputViewer,
- 1, 10, 1,
- TypedValue.COMPLEX_UNIT_SP);
- iperf3OutputViewer.setTextIsSelectable(true);
-
- metricLL = new LinearLayout(ct);
- metricLL.setOrientation(LinearLayout.VERTICAL);
- metricLL.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
-
-
-
- defaultThroughput = new Metric(METRIC_TYPE.THROUGHPUT, ct);
- defaultReverseThroughput = new Metric(METRIC_TYPE.THROUGHPUT, ct);
-
- metricLL.addView(defaultThroughput.createMainLL("Throughput"));
-
- if(iperf3RunResult.input.iperf3BiDir) {
- metricLL.addView(defaultReverseThroughput.createMainLL("Throughput"));
- if(iperf3RunResult.input.iperf3IdxProtocol == 0) {
- //defaultRTT = new Metric(METRIC_TYPE.RTT);
- //metricLL.addView(defaultRTT.createOneDirection("RTT"));
- }
- if(iperf3RunResult.input.iperf3IdxProtocol == 1) {
- defaultJITTER = new Metric(METRIC_TYPE.JITTER, ct);
- metricLL.addView(defaultJITTER.createMainLL("Jitter ms"));
- PACKET_LOSS = new Metric(METRIC_TYPE.PACKET_LOSS, ct);
- metricLL.addView(PACKET_LOSS.createMainLL("Packet Loss %"));
- }
- }
- if(iperf3RunResult.input.iperf3Reverse) {
- if(iperf3RunResult.input.iperf3IdxProtocol == 1) {
- defaultJITTER = new Metric(METRIC_TYPE.JITTER, ct);
- metricLL.addView(defaultJITTER.createMainLL("Jitter ms"));
- PACKET_LOSS = new Metric(METRIC_TYPE.JITTER, ct);
- metricLL.addView(PACKET_LOSS.createMainLL("Packet Loss %"));
- }
- } else if(!iperf3RunResult.input.iperf3BiDir) {
- if(iperf3RunResult.input.iperf3IdxProtocol == 0) {
- //defaultRTT = new Metric(METRIC_TYPE.RTT);
- //metricLL.addView(defaultRTT.createOneDirection("RTT ms"));
- }
- }
-
- mainLL.addView(metricLL);
-
-
-
-
- mainLL.addView(secondRow);
- if(iperf3RunResult.input.iperf3rawIperf3file == null){
- iperf3OutputViewer.setText("iPerf3 file path empty!");
- return v;
- }
- file = new File(iperf3RunResult.input.iperf3rawIperf3file);
-
-
- logHandler = new Handler(Looper.myLooper());
- logHandler.post(logUpdate);
- return v;
- }
-
- public void onPause() {
- super.onPause();
- if(logHandler != null) logHandler.removeCallbacks(logUpdate);
- }
-
-
-}
\ No newline at end of file
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Parser.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Parser.java
deleted file mode 100644
index 781ade6b..00000000
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Parser.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3;
-
-import org.json.JSONObject;
-
-import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeSupport;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Error;
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Interval;
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.start.Start;
-
-
-public class Iperf3Parser {
-
- private final String pathToFile;
- private final File file;
- private BufferedReader br = null;
- private PropertyChangeSupport support;
- private Start start;
- private final Intervals intervals = new Intervals();
- Iperf3Parser(String pathToFile) {
- this.pathToFile = pathToFile;
- this.file = new File(this.pathToFile);
- try {
- br = new BufferedReader(new FileReader(file));
- } catch (FileNotFoundException ex) {
- System.out.println("File not found");
- return;
- }
- this.support = new PropertyChangeSupport(this);
- }
-
- public void parse(){
- String line;
- try {
- while ((line = br.readLine()) != null) {
- JSONObject obj = new JSONObject(line);
- String event = obj.getString("event");
- switch (event) {
- case "start":
- start = new Start();
- JSONObject startData = obj.getJSONObject("data");
- start.parseStart(startData);
- break;
- case "interval":
- Interval interval = new Interval();
- JSONObject intervalData = obj.getJSONObject("data");
- interval.parse(intervalData);
- support.firePropertyChange("interval", null, interval);
- intervals.addInterval(interval);
- break;
- case "end":
- System.out.println("End");
- break;
- case "error":
- Error error = new Error();
- String errorString = obj.getString("data");
- error.parse(errorString);
- support.firePropertyChange("error", null, error);
- break;
- default:
- System.out.println("Unknown event");
- break;
- }
- }
- } catch (Exception e) {
- System.out.println("Error reading file");
- }
- }
-
- public Intervals getIntervals() {
- return intervals;
- }
- public Start getStart() {
- return start;
- }
- public void addPropertyChangeListener(PropertyChangeListener pcl) {
- support.addPropertyChangeListener(pcl);
- }
-
- public void removePropertyChangeListener(PropertyChangeListener pcl) {
- support.removePropertyChangeListener(pcl);
- }
-}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3RecyclerViewAdapter.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3RecyclerViewAdapter.java
index 0ab33dce..089cbab3 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3RecyclerViewAdapter.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3RecyclerViewAdapter.java
@@ -8,60 +8,67 @@
package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3;
-import android.annotation.SuppressLint;
+import static android.view.View.GONE;
+import static android.view.View.VISIBLE;
+
import android.content.Context;
-import android.content.SharedPreferences;
import android.content.res.Configuration;
-import android.os.Bundle;
-import android.util.Log;
+import android.graphics.Color;
+import android.graphics.drawable.GradientDrawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
-import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.cardview.widget.CardView;
import androidx.core.content.ContextCompat;
-import androidx.fragment.app.FragmentActivity;
-import androidx.preference.PreferenceManager;
+import androidx.lifecycle.Observer;
import androidx.recyclerview.widget.RecyclerView;
-import androidx.work.Data;
-import androidx.work.OneTimeWorkRequest;
-import androidx.work.WorkManager;
+import com.google.android.flexbox.FlexboxLayout;
+import com.google.android.material.button.MaterialButton;
+import com.google.android.material.card.MaterialCardView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
+import com.google.android.material.progressindicator.LinearProgressIndicator;
+
+import org.w3c.dom.Text;
import java.util.ArrayList;
import java.util.HashMap;
-import java.util.Map;
-
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SPType;
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SharedPreferencesGrouper;
+import java.util.Objects;
+
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.RunResult.Iperf3ResultsDataBase;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.RunResult.Iperf3RunResult;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.RunResult.Iperf3RunResultDao;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Interval;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Metric.METRIC_TYPE;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Metric.MetricCalculator;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Metric.MetricView;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R;
public class Iperf3RecyclerViewAdapter
extends RecyclerView.Adapter {
private final String TAG = "Iperf3RecyclerViewAdapter";
private final Iperf3ResultsDataBase db;
- private final ArrayList uids;
private Context context;
- private final FragmentActivity c;
private final HashMap selectedRuns;
private final HashMap selectedCardViews;
private final FloatingActionButton uploadBtn;
+ private Iperf3RunResultDao iperf3RunResultDao;
+ private Observer observer;
+ private String selectedUUID;
+ public Iperf3RecyclerViewAdapter(FloatingActionButton uploadBtn) {
- public Iperf3RecyclerViewAdapter(FragmentActivity c, ArrayList uids,
- FloatingActionButton uploadBtn) {
- this.c = c;
- this.uids = uids;
this.db = Iperf3ResultsDataBase.getDatabase(context);
+ this.iperf3RunResultDao = db.iperf3RunResultDao();
+
this.selectedRuns = new HashMap<>();
this.selectedCardViews = new HashMap<>();
this.uploadBtn = uploadBtn;
- this.uploadBtn.setOnClickListener(new View.OnClickListener() {
+
+ /* this.uploadBtn.setOnClickListener(new View.OnClickListener() {
@SuppressLint("NotifyDataSetChanged")
@Override
public void onClick(View view) {
@@ -83,7 +90,7 @@ public void onClick(View view) {
Iperf3RunResult runResult = iperf3RunResultDao.getRunResult(uid);
Data.Builder data = new Data.Builder();
- data.putString("iperf3LineProtocolFile", runResult.input.iperf3LineProtocolFile);
+ data.putString("iperf3LineProtocolFile", runResult.input.getParameter().getLineProtocolFile());
OneTimeWorkRequest iperf3UP =
new OneTimeWorkRequest.Builder(Iperf3UploadWorker.class)
.setInputData(data.build())
@@ -95,7 +102,7 @@ public void onClick(View view) {
boolean iperf3_upload;
iperf3_upload = workInfo.getOutputData().getBoolean("iperf3_upload", false);
if (iperf3_upload) {
- iperf3RunResultDao.updateUpload(uid, iperf3_upload);
+ //iperf3RunResultDao.updateUpload(uid, iperf3_upload);
selectedRuns.remove(stringIntegerEntry.getKey());
notifyItemChanged(stringIntegerEntry.getValue());
}
@@ -108,7 +115,7 @@ public void onClick(View view) {
}
});
-
+*/
}
@@ -118,7 +125,7 @@ public Iperf3RecyclerViewAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGrou
int viewType) {
context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
- CardView v = (CardView) inflater.inflate(R.layout.fragment_iperf3_row_item, parent, false);
+ MaterialCardView v = (MaterialCardView) inflater.inflate(R.layout.fragment_iperf3_row_item, parent, false);
v.setFocusable(false);
v.setClickable(false);
ViewHolder viewHolder = new ViewHolder(v);
@@ -126,6 +133,10 @@ public Iperf3RecyclerViewAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGrou
return viewHolder;
}
+ public String getSelectedUUID(){
+ return selectedUUID;
+ }
+
public boolean isNightMode(Context context) {
int nightModeFlags = context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
return nightModeFlags == Configuration.UI_MODE_NIGHT_YES;
@@ -133,145 +144,268 @@ public boolean isNightMode(Context context) {
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
- holder.iPerf3Parameters.removeAllViews();
Iperf3RunResult test = getItemByPosition(position);
- holder.itemView.setTag(uids.get(position));
- if (selectedRuns.containsKey(test.uid)) {
- holder.itemView.setBackgroundColor(
- ContextCompat.getColor(context, R.color.forestgreen));
+ holder.metricViewDL.setVisibility(GONE);
+ holder.metricViewUL.setVisibility(GONE);
+
+ holder.metricViewUL.setMetricCalculator(test.metricUL == null ? new MetricCalculator(METRIC_TYPE.THROUGHPUT) : test.metricUL);
+ holder.metricViewDL.setMetricCalculator(test.metricDL == null ? new MetricCalculator(METRIC_TYPE.THROUGHPUT) : test.metricDL);
+
+ holder.itemView.setTag(iperf3RunResultDao.getIDs().get(position));
+
+
+ holder.itemView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // selectedUUID = test.uid;
+ // notifyDataSetChanged();
+ }
+ });
+ if(Objects.equals(selectedUUID, test.uid)){
+ holder.itemView.setBackgroundColor(Color.parseColor("#567845"));
+ }
+ String host = String.valueOf(test.input.getParameter().getHost());
+ String dstPort = String.valueOf(test.input.getParameter().getPort());
+ String bandwidth = String.valueOf(test.input.getParameter().getBitrate());
+ String duration = String.valueOf(test.input.getParameter().getTime());
+ String interval = String.valueOf(test.input.getParameter().getInterval());
+ String bytes = String.valueOf(test.input.getParameter().getBytes());
+ String streams = String.valueOf(test.input.getParameter().getParallel());
+ String srcPort = String.valueOf(test.input.getParameter().getCport());
+
+ String mode = String.valueOf(test.input.getParameter().getMode());
+ String protocol = String.valueOf(test.input.getParameter().getProtocol());
+ String direction = String.valueOf(test.input.getParameter().getDirection());
+
+ ((TextView) holder.host.findViewById(R.id.text_parameter)).setText(host);
+ ((TextView) holder.dstPort.findViewById(R.id.text_parameter)).setText(dstPort);
+ ((TextView) holder.bandwidth.findViewById(R.id.text_parameter)).setText(bandwidth);
+ ((TextView) holder.duration.findViewById(R.id.text_parameter)).setText(duration);
+ ((TextView) holder.interval.findViewById(R.id.text_parameter)).setText(interval);
+ ((TextView) holder.bytes.findViewById(R.id.text_parameter)).setText(bytes);
+ ((TextView) holder.streams.findViewById(R.id.text_parameter)).setText(streams);
+ ((TextView) holder.srcPort.findViewById(R.id.text_parameter)).setText(srcPort);
+
+ ((TextView) holder.mode.findViewById(R.id.text_parameter)).setText(mode);
+ ((TextView) holder.protocol.findViewById(R.id.text_parameter)).setText(protocol);
+ ((TextView) holder.direction.findViewById(R.id.text_parameter)).setText(direction);
+ holder.linearProgressIndicator.setIndicatorColor(Color.CYAN);
+ switch (test.result){
+ case 0:
+ holder.linearProgressIndicator.setIndicatorColor(Color.GREEN);
+ holder.linearProgressIndicator.setProgress(1);
+ holder.linearProgressIndicator.setMax(1);
+ break;
+ case -1:
+ holder.linearProgressIndicator.setMax(1);
+ holder.linearProgressIndicator.setProgress(1);
+ holder.linearProgressIndicator.setIndicatorColor(Color.RED);
+ break;
+ case -100:
+ holder.linearProgressIndicator.setMax(test.input.getParameter().getTime()-1);
+ ArrayList intervals = new ArrayList();
+ if(test.intervals != null)
+ intervals = test.intervals.getIntervalArrayList();
+ int progress = intervals.size();
+ holder.linearProgressIndicator.setProgress(progress);
+ break;
+
+ }
+
+ if(!dstPort.isEmpty() || dstPort.equals("")){
+ holder.dstPort.setVisibility(GONE);
+ } else {
+ holder.dstPort.setVisibility(VISIBLE);
+ }
+ if(!bandwidth.isEmpty() || bandwidth.equals("")) {
+ holder.bandwidth.setVisibility(GONE);
+ } else {
+ holder.bandwidth.setVisibility(VISIBLE);
+ }
+ if(!duration.isEmpty() || duration.equals("")) {
+ holder.duration.setVisibility(GONE);
+ } else {
+ holder.duration.setVisibility(VISIBLE);
+ }
+ if(!interval.isEmpty() || interval.equals("")){
+ holder.interval.setVisibility(GONE);
} else {
- if(isNightMode(context))
- holder.itemView.setBackgroundColor(
- ContextCompat.getColor(context, R.color.cardview_dark_background));
- else
- holder.itemView.setBackgroundColor(
- ContextCompat.getColor(context, R.color.ic_launcher_background));
+ holder.interval.setVisibility(VISIBLE);
+ }
+ if(!bytes.isEmpty() || bytes.equals("")) {
+ holder.bytes.setVisibility(GONE);
+ } else {
+ holder.bytes.setVisibility(VISIBLE);
+ }
+ if(!streams.isEmpty() || streams.equals("")){
+ holder.streams.setVisibility(GONE);
+ } else {
+ holder.streams.setVisibility(VISIBLE);
+ }
+ if(!srcPort.isEmpty() || srcPort.equals("")) {
+ holder.srcPort.setVisibility(GONE);
+ } else {
+ holder.srcPort.setVisibility(VISIBLE);
+ }
+
+ switch (test.input.getParameter().getDirection()){
+ case BIDIR:
+ holder.metricViewUL.setVisibility(VISIBLE);
+ holder.metricViewDL.setVisibility(VISIBLE);
+ if(holder.metricViewUL.getMetricCalculator() != null || holder.metricViewDL.getMetricCalculator() != null){
+ holder.metricViewUL.getMetricCalculator().calcAll();
+ holder.metricViewDL.getMetricCalculator().calcAll();
+ holder.metricViewUL.update();
+ holder.metricViewDL.update();
+ }
+ break;
+ case UP:
+ holder.metricViewUL.setVisibility(VISIBLE);
+ holder.metricViewDL.setVisibility(GONE);
+ if(holder.metricViewUL.getMetricCalculator() != null){
+ holder.metricViewUL.getMetricCalculator().calcAll();
+ holder.metricViewUL.update();
+ }
+ break;
+ case DOWN:
+ holder.metricViewUL.setVisibility(GONE);
+ holder.metricViewDL.setVisibility(VISIBLE);
+ if(holder.metricViewDL.getMetricCalculator() != null){
+ holder.metricViewDL.getMetricCalculator().calcAll();
+ holder.metricViewDL.update();
+ }
+ break;
+ }
+ holder.errorView.setVisibility(GONE);
+ if(test.result == -1) {
+ holder.metricViewUL.setVisibility(GONE);
+ holder.metricViewDL.setVisibility(GONE);
+ String errorText = "Error!";
+ test = iperf3RunResultDao.getRunResult(test.uid);
+ if(test.error != null){
+ errorText = test.error.getError();
+ }
+ holder.errorView.setText(errorText);
+ holder.errorView.setVisibility(VISIBLE);
}
- holder.measurement.setText("iPerf3");
- holder.timestamp.setText(test.input.timestamp.toString());
- holder.runIcon.setImageDrawable(Iperf3Utils.getDrawableResult(context, test.result));
- holder.uploadIcon.setImageDrawable(Iperf3Utils.getDrawableUpload(context, test.result, test.uploaded));
- holder.iPerf3Parameters = test.input.getInputAsLinearLayoutValue(holder.iPerf3Parameters, context);
}
private Iperf3RunResult getItemByPosition(int position) {
- return this.db.iperf3RunResultDao().getRunResult(this.uids.get(position));
+ return iperf3RunResultDao.getRunResult(iperf3RunResultDao.getIDs().get(position));
}
@Override
public int getItemCount() {
- return uids.size();
+ return iperf3RunResultDao.getIDs().size();
}
- public class ViewHolder extends RecyclerView.ViewHolder {
- public TextView measurement;
- public TextView timestamp;
- public TextView iperf3State;
- public ImageView runIcon;
- public ImageView uploadIcon;
- private final LinearLayout linearLayout;
- private LinearLayout iPerf3Parameters;
-
- private LinearLayout firstRow(LinearLayout ll){
- measurement.setLayoutParams(
- Iperf3Utils.getLayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 8F));
+ private void setSelectedUUID(String selectedUUID) {
+ this.selectedUUID = selectedUUID;
+ }
- runIcon.setLayoutParams(
- Iperf3Utils.getLayoutParams(0, 80, 1F));
-
- uploadIcon.setLayoutParams(
- Iperf3Utils.getLayoutParams(0, 80, 1F));
-
+ public class ViewHolder extends RecyclerView.ViewHolder {
+ private FlexboxLayout parameterFlexBoxLayout;
+ private LinearLayout host;
+ private LinearLayout dstPort;
+ private LinearLayout bandwidth;
+ private LinearLayout duration;
+ private LinearLayout interval;
+ private LinearLayout bytes;
+ private LinearLayout streams;
+ private LinearLayout srcPort;
+ private LinearLayout mode;
+ private LinearLayout protocol;
+ private LinearLayout direction;
+ private LayoutInflater li;
+ private LinearProgressIndicator linearProgressIndicator;
+ private MetricView metricViewDL;
+ private MetricView metricViewUL;
+ private TextView errorView;
+ private LinearLayout metricLL;
+ private CardView cardViewError;
+ private MaterialButton cancel;
+ private MaterialButton rerun;
+ private void setupParameterFlexBox(){
+ parameterFlexBoxLayout = itemView.findViewById(R.id.parameter_iperf3_fl);
+
+ host = (LinearLayout) li.inflate(R.layout.parameter_view, null);
+ dstPort = (LinearLayout) li.inflate(R.layout.parameter_view, null);
+ dstPort = (LinearLayout) li.inflate(R.layout.parameter_view, null);
+ bandwidth = (LinearLayout) li.inflate(R.layout.parameter_view, null);
+ duration = (LinearLayout) li.inflate(R.layout.parameter_view, null);
+ interval = (LinearLayout) li.inflate(R.layout.parameter_view, null);
+ bytes = (LinearLayout) li.inflate(R.layout.parameter_view, null);
+ streams = (LinearLayout) li.inflate(R.layout.parameter_view, null);
+ srcPort = (LinearLayout) li.inflate(R.layout.parameter_view, null);
+
+ mode = (LinearLayout) li.inflate(R.layout.parameter_view, null);
+ protocol = (LinearLayout) li.inflate(R.layout.parameter_view, null);
+ direction = (LinearLayout) li.inflate(R.layout.parameter_view, null);
+
+ parameterFlexBoxLayout.addView(host);
+ parameterFlexBoxLayout.addView(dstPort);
+ parameterFlexBoxLayout.addView(bandwidth);
+ parameterFlexBoxLayout.addView(duration);
+ parameterFlexBoxLayout.addView(interval);
+ parameterFlexBoxLayout.addView(bytes);
+ parameterFlexBoxLayout.addView(streams);
+ parameterFlexBoxLayout.addView(srcPort);
+ parameterFlexBoxLayout.addView(mode);
+ parameterFlexBoxLayout.addView(protocol);
+ parameterFlexBoxLayout.addView(direction);
- ll.setOrientation(LinearLayout.HORIZONTAL);
- ll.addView(measurement);
- ll.addView(runIcon);
- ll.addView(uploadIcon);
- return ll;
}
- private LinearLayout secondRow(LinearLayout ll){
- ll.setOrientation(LinearLayout.HORIZONTAL);
- timestamp.setLayoutParams(
- Iperf3Utils.getLayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1F));
- ll.addView(timestamp);
- return ll;
+ public void setupLinearProgressIndicator(){
+ linearProgressIndicator = itemView.findViewById(R.id.progress_indicator);
}
- private LinearLayout thirdRow(LinearLayout ll){
- ll.setOrientation(LinearLayout.HORIZONTAL);
- ll.addView(iPerf3Parameters);
- iPerf3Parameters.setLayoutParams(
- Iperf3Utils.getLayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 0.1F));
- return ll;
+ public void setupMetricLinearLayout(){
+ metricLL = itemView.findViewById(R.id.metrics_iperf3_ll);
+ metricViewDL = new MetricView(context);
+ metricViewUL = new MetricView(context);
+ metricViewDL.setup("Download [Mbit/s]");
+ metricViewUL.setup("Upload [Mbit/s]");
+
+ errorView = new TextView(context);
+ errorView.setTextColor(context.getColor(R.color.material_dynamic_neutral0));
+
+ LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ );
+ errorView.setLayoutParams(params);
+
+ cardViewError = new CardView(context);
+ LinearLayout.LayoutParams cardViewParams = new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ );
+ cardViewParams.setMargins(10, 10, 10, 10);
+ errorView.setPadding(10, 10, 10, 10);
+ cardViewError.setLayoutParams(cardViewParams);
+ GradientDrawable gd = new GradientDrawable();
+ gd.setColor(context.getColor( R.color.material_dynamic_primary100));
+ gd.setCornerRadius(10);
+// gd.setStroke(2, 0xFF000000);
+ cardViewError.setBackground(gd);
+
+
+
+ cardViewError.addView(errorView);
+ metricLL.addView(cardViewError);
+ metricLL.addView(metricViewDL);
+ metricLL.addView(metricViewUL);
+ errorView.setVisibility(GONE);
}
public ViewHolder(View itemView) {
super(itemView);
- Log.d(TAG, "ViewHolder: " + itemView);
- measurement = new TextView(context);
- timestamp = new TextView(context);
- iperf3State = new TextView(context);
- runIcon = new ImageView(context);
- runIcon.setPadding(0, 10, 0, 0);
- uploadIcon = new ImageView(context);
- uploadIcon.setPadding(0, 10, 0, 0);
- timestamp = new TextView(context);
- iPerf3Parameters = new LinearLayout(context);
- linearLayout = itemView.findViewById(R.id.iperf3_main_layout);
- linearLayout.setOrientation(LinearLayout.VERTICAL);
- linearLayout.addView(firstRow(new LinearLayout(context)));
- linearLayout.addView(secondRow(new LinearLayout(context)));
- linearLayout.addView(thirdRow(new LinearLayout(context)));
- itemView.setOnLongClickListener(new View.OnLongClickListener() {
- @Override
- public boolean onLongClick(View v) {
- int viewPosition = getLayoutPosition();
- Log.d(TAG, "onLongClick: " + v.toString());
- Log.d(TAG, "onLongClick: " + viewPosition);
- if (!selectedRuns.isEmpty()) {
- return true;
- }
- if (viewPosition == RecyclerView.NO_POSITION) {
- return false;
- }
- String uid = uids.get(viewPosition);
- selectedRuns.put(uid, viewPosition);
- notifyItemChanged(viewPosition);
- uploadBtn.setVisibility(View.VISIBLE);
- return true;
- }
- });
- itemView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- int viewPosition = getLayoutPosition();
- String uid = uids.get(viewPosition);
- if (!selectedRuns.isEmpty() && selectedRuns.containsKey(uid)) {
- if (selectedRuns.size() == 1 && selectedRuns.containsKey(uid)) {
- uploadBtn.setVisibility(View.INVISIBLE);
- }
- selectedRuns.remove(uid);
- notifyItemChanged(viewPosition);
- return;
- } else if (!selectedRuns.isEmpty()) {
- selectedRuns.put(uid, viewPosition);
- notifyItemChanged(viewPosition);
- uploadBtn.setVisibility(View.VISIBLE);
- return;
- }
- Log.d(TAG, "onCreateView: CLICKED!");
- Bundle bundle = new Bundle();
- bundle.putString("uid", uid);
- Iperf3LogFragment test = new Iperf3LogFragment();
- test.setArguments(bundle);
- c.getSupportFragmentManager().beginTransaction()
- .replace(R.id.fragmentContainerView, test, "iperf3LogFragment")
- .addToBackStack("findThisFragment").commit();
-
- }
- });
-
+ li = LayoutInflater.from(context);
+ itemView.setBackgroundColor(context.getColor(R.color.material_dynamic_tertiary30));
+ setupLinearProgressIndicator();
+ setupParameterFlexBox();
+ setupMetricLinearLayout();
}
}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3RunResult.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3RunResult.java
deleted file mode 100644
index 1a7f9854..00000000
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3RunResult.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2023 Peter Hasse
- * SPDX-FileCopyrightText: 2023 Johann Hackler
- * SPDX-FileCopyrightText: 2023 Fraunhofer FOKUS
- *
- * SPDX-License-Identifier: BSD-3-Clause-Clear
- */
-
-package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3;
-
-import androidx.annotation.NonNull;
-import androidx.room.ColumnInfo;
-import androidx.room.Entity;
-import androidx.room.PrimaryKey;
-import androidx.room.TypeConverters;
-
-import java.sql.Timestamp;
-
-@Entity(tableName = "iperf3_result_database")
-public class Iperf3RunResult {
- @NonNull
- @PrimaryKey
- public String uid;
-
- @ColumnInfo(name = "result")
- public int result;
-
- @ColumnInfo(name = "uploaded")
- public boolean uploaded;
-
- @ColumnInfo(name = "timestamp")
- public long timestamp;
-
- @ColumnInfo(name = "input")
- @TypeConverters({Iperf3InputConverter.class})
- public Iperf3Fragment.Iperf3Input input;
-
- public Iperf3RunResult(String uid, int result, boolean upload, Iperf3Fragment.Iperf3Input input,
- Timestamp timestamp) {
- this.uid = uid;
- this.result = result;
- this.uploaded = upload;
- this.input = input;
- this.timestamp = timestamp.getTime();
- }
-
-
- public Iperf3RunResult() {
-
- }
-}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3RunResultDao.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3RunResultDao.java
deleted file mode 100644
index 158823aa..00000000
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3RunResultDao.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2023 Peter Hasse
- * SPDX-FileCopyrightText: 2023 Johann Hackler
- * SPDX-FileCopyrightText: 2023 Fraunhofer FOKUS
- *
- * SPDX-License-Identifier: BSD-3-Clause-Clear
- */
-
-package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3;
-
-import androidx.lifecycle.LiveData;
-import androidx.room.Dao;
-import androidx.room.Delete;
-import androidx.room.Insert;
-import androidx.room.OnConflictStrategy;
-import androidx.room.Query;
-import androidx.room.Update;
-
-import java.util.List;
-
-@Dao
-public interface Iperf3RunResultDao {
- @Query("SELECT * FROM iperf3_result_database")
- LiveData> getAll();
-
- @Query("SELECT COUNT(*) FROM iperf3_result_database")
- LiveData getLength();
-
- @Query("SELECT uid FROM iperf3_result_database ORDER BY timestamp DESC")
- List getIDs();
-
- @Query("SELECT * FROM iperf3_result_database WHERE uid = :comp_uid")
- Iperf3RunResult getRunResult(String comp_uid);
-
- @Insert
- void insertAll(Iperf3RunResult... iperf3RunResults);
-
- @Insert(onConflict = OnConflictStrategy.REPLACE)
- void insert(Iperf3RunResult iperf3RunResult);
-
- @Query("UPDATE iperf3_result_database SET result=:result WHERE uid=:uid")
- void updateResult(String uid, int result);
-
- @Query("UPDATE iperf3_result_database SET uploaded=:uploaded WHERE uid=:uid")
- void updateUpload(String uid, boolean uploaded);
-
- @Update
- void update(Iperf3RunResult iperf3RunResult);
-
- @Delete
- void delete(Iperf3RunResult iperf3RunResult);
-}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Worker.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Worker.java
deleted file mode 100644
index 1a228178..00000000
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3Worker.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2023 Peter Hasse
- * SPDX-FileCopyrightText: 2023 Johann Hackler
- * SPDX-FileCopyrightText: 2023 Fraunhofer FOKUS
- *
- * SPDX-License-Identifier: BSD-3-Clause-Clear
- */
-
-package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3;
-
-import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC;
-import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION;
-import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE;
-
-import android.app.Notification;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.graphics.Color;
-import android.os.Build;
-import android.util.Log;
-
-import android.widget.TextView;
-import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
-import androidx.core.app.NotificationCompat;
-import androidx.room.util.StringUtil;
-import androidx.work.Data;
-import androidx.work.ForegroundInfo;
-import androidx.work.WorkManager;
-import androidx.work.Worker;
-import androidx.work.WorkerParameters;
-
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R;
-import java.util.Locale;
-
-public class Iperf3Worker extends Worker {
- private static final String TAG = "iperf3Worker";
-
- static {
- Iperf3LibLoader.load();
- }
-
- private final String[] cmd;
- private final String iperf3WorkerID;
- private final String measurementName;
- private final String timestamp;
- private final int notificationID;
- private final String client;
- private final String protocol;
- private String serverPort;
- private final String ip;
- private final int FOREGROUND_SERVICE_TYPE = FOREGROUND_SERVICE_TYPE_SPECIAL_USE;
-
- public Iperf3Worker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
- super(context, workerParams);
- cmd = getInputData().getStringArray("commands");
- measurementName = getInputData().getString("measurementName");
- iperf3WorkerID = getInputData().getString("iperf3WorkerID");
- timestamp = getInputData().getString("timestamp");
- notificationID = 100;
- client = getInputData().getString("client");
- ip = getInputData().getString("ip");
- serverPort = getInputData().getString("port");
- protocol = getInputData().getString("protocol");
-
- }
-
- private native int iperf3Wrapper(String[] argv, String cache);
-
- private native int iperf3Stop();
-
- private ForegroundInfo createForegroundInfo(@NonNull String progress) {
-
- Context context = getApplicationContext();
- String id = "OMNT_notification_channel";
- PendingIntent intent = WorkManager.getInstance(context)
- .createCancelPendingIntent(getId());
- Notification notification = new NotificationCompat.Builder(context, id)
- .setContentTitle("iPerf3 "+ client.substring(0, 1).toUpperCase() + client.substring(1).toLowerCase())
- .setContentText(progress)
- .setOngoing(true)
- .setColor(Color.WHITE)
- .setSmallIcon(R.mipmap.ic_launcher_foreground)
- .setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_DEFAULT)
- .addAction(R.drawable.ic_close, "Cancel", intent)
- .build();
- return new ForegroundInfo(notificationID, notification, FOREGROUND_SERVICE_TYPE);
- }
-
- @Override
- public void onStopped() {
- Log.d(TAG, "onStopped: called!");
- iperf3Stop();
- }
-
- @NonNull
- @Override
- public Result doWork() {
- if (serverPort == null) serverPort = "5201";
- String progress = String.format("Connected to %s:%s with %s", ip, serverPort, protocol);
- if (client.equals("server")) {
- progress = String.format("Running on %s:%s", ip, serverPort);
- }
-
- setForegroundAsync(createForegroundInfo(progress));
-
- int result =
- iperf3Wrapper(cmd, getApplicationContext().getApplicationInfo().nativeLibraryDir);
- Log.d(TAG, "doWork: " + result);
-
-
- Data.Builder output = new Data.Builder()
- .putInt("iperf3_result", result)
- .putString("iperf3WorkerID", iperf3WorkerID);
- if (result == 0) {
- return Result.success(output.build());
- }
- return Result.failure(output
- .build());
- }
-}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Interval.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Interval.java
index 47d51b1a..fc351996 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Interval.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Interval.java
@@ -2,6 +2,9 @@
import static de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.SUM_TYPE.*;
+import com.google.gson.Gson;
+import com.influxdb.client.JSON;
+
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.STREAM_TYPE;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.SUM_TYPE;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Sum.Sum;
@@ -35,7 +38,27 @@ private SUM_TYPE getSumType(JSONObject data) throws JSONException {
if(data.has("jitter_ms")) return SUM_TYPE.UDP_DL;
return SUM_TYPE.TCP_DL;
}
-
+ public String getNotificationString(){
+ StringBuilder notificationString = new StringBuilder();
+ notificationString.append("Throughput: ");
+ notificationString.append(Math.round(this.getSum().getBits_per_second() / 1e6));
+ notificationString.append(" Mbit/s");
+ notificationString.append("\n");
+ notificationString.append("Direction: ");
+ notificationString.append(this.getSum().getSumType());
+ notificationString.append("\n");
+ if(sumBidirReverse != null){
+ notificationString.append("--------------------\n");
+ notificationString.append("Throughput: ");
+ notificationString.append(Math.round(this.getSumBidirReverse().getBits_per_second() / 1e6));
+ notificationString.append(" Mbit/s");
+ notificationString.append("\n");
+ notificationString.append("Direction: ");
+ notificationString.append(this.getSumBidirReverse().getSumType());
+ notificationString.append("\n");
+ }
+ return notificationString.toString();
+ }
public Sum identifySum(JSONObject data) throws JSONException {
Sum identifiedSum = null;
switch (getSumType(data)){
@@ -76,4 +99,16 @@ public Sum getSum() {
public Sum getSumBidirReverse() {
return sumBidirReverse;
}
+
+ public String toString(){
+ return new Gson().toJson(this);
+ }
+ public Interval(String line){
+ this.streams = new Streams();
+ Interval interval = new Gson().fromJson(line, Interval.class);
+ this.sum = interval.sum;
+ this.sumBidirReverse = interval.sumBidirReverse;
+ }
+
+
}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/Streams.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/Streams.java
index 4a07cf84..d1ceb420 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/Streams.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/Streams.java
@@ -71,4 +71,9 @@ public void addStream(Stream stream){
public Stream getStream(int i) {
return streams.get(i);
}
+
+ public void setStreams(ArrayList streams) {
+ this.streams.clear();
+ this.streams.addAll(streams);
+ }
}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/UDP/UDP_STREAM.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/UDP/UDP_STREAM.java
index acf8e17f..869a71f7 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/UDP/UDP_STREAM.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/Interval/Streams/UDP/UDP_STREAM.java
@@ -5,7 +5,6 @@
import org.json.JSONObject;
public class UDP_STREAM extends Stream {
- public int packets;
public UDP_STREAM(){
super();
}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/start/Start.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/start/Start.java
index af9ebbba..c0ed5e02 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/start/Start.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/JSON/start/Start.java
@@ -1,5 +1,7 @@
package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.start;
+import com.google.gson.Gson;
+
import java.util.ArrayList;
import org.json.JSONArray;
import org.json.JSONException;
@@ -85,4 +87,8 @@ public TestStart getTest_start() {
return test_start;
}
+ public String toString(){
+ return new Gson().toJson(this);
+ }
+
}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Service/Executor/Iperf3ServiceWorkerFour.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Service/Executor/Iperf3ServiceWorkerFour.java
new file mode 100644
index 00000000..d96aab1d
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Service/Executor/Iperf3ServiceWorkerFour.java
@@ -0,0 +1,7 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Service.Executor;
+
+import androidx.work.multiprocess.RemoteWorkerService;
+
+public class Iperf3ServiceWorkerFour extends RemoteWorkerService {
+
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Service/Executor/Iperf3ServiceWorkerOne.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Service/Executor/Iperf3ServiceWorkerOne.java
new file mode 100644
index 00000000..634ad263
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Service/Executor/Iperf3ServiceWorkerOne.java
@@ -0,0 +1,7 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Service.Executor;
+
+import androidx.work.multiprocess.RemoteWorkerService;
+
+public class Iperf3ServiceWorkerOne extends RemoteWorkerService {
+
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Service/Executor/Iperf3ServiceWorkerThree.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Service/Executor/Iperf3ServiceWorkerThree.java
new file mode 100644
index 00000000..50a9636b
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Service/Executor/Iperf3ServiceWorkerThree.java
@@ -0,0 +1,7 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Service.Executor;
+
+import androidx.work.multiprocess.RemoteWorkerService;
+
+public class Iperf3ServiceWorkerThree extends RemoteWorkerService {
+
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Service/Executor/Iperf3ServiceWorkerTwo.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Service/Executor/Iperf3ServiceWorkerTwo.java
new file mode 100644
index 00000000..94e31262
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Service/Executor/Iperf3ServiceWorkerTwo.java
@@ -0,0 +1,7 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Service.Executor;
+
+import androidx.work.multiprocess.RemoteWorkerService;
+
+public class Iperf3ServiceWorkerTwo extends RemoteWorkerService {
+
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Service/Monitor/Iperf3MonitorServiceWorkerFour.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Service/Monitor/Iperf3MonitorServiceWorkerFour.java
new file mode 100644
index 00000000..906d3fcf
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Service/Monitor/Iperf3MonitorServiceWorkerFour.java
@@ -0,0 +1,7 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Service.Monitor;
+
+import androidx.work.multiprocess.RemoteWorkerService;
+
+public class Iperf3MonitorServiceWorkerFour extends RemoteWorkerService {
+
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Service/Monitor/Iperf3MonitorServiceWorkerOne.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Service/Monitor/Iperf3MonitorServiceWorkerOne.java
new file mode 100644
index 00000000..49d48c8e
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Service/Monitor/Iperf3MonitorServiceWorkerOne.java
@@ -0,0 +1,7 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Service.Monitor;
+
+import androidx.work.multiprocess.RemoteWorkerService;
+
+public class Iperf3MonitorServiceWorkerOne extends RemoteWorkerService {
+
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Service/Monitor/Iperf3MonitorServiceWorkerThree.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Service/Monitor/Iperf3MonitorServiceWorkerThree.java
new file mode 100644
index 00000000..6780d123
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Service/Monitor/Iperf3MonitorServiceWorkerThree.java
@@ -0,0 +1,7 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Service.Monitor;
+
+import androidx.work.multiprocess.RemoteWorkerService;
+
+public class Iperf3MonitorServiceWorkerThree extends RemoteWorkerService {
+
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Service/Monitor/Iperf3MonitorServiceWorkerTwo.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Service/Monitor/Iperf3MonitorServiceWorkerTwo.java
new file mode 100644
index 00000000..668a0b31
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Service/Monitor/Iperf3MonitorServiceWorkerTwo.java
@@ -0,0 +1,7 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Service.Monitor;
+
+import androidx.work.multiprocess.RemoteWorkerService;
+
+public class Iperf3MonitorServiceWorkerTwo extends RemoteWorkerService {
+
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Worker/Iperf3ExecutorWorker.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Worker/Iperf3ExecutorWorker.java
new file mode 100644
index 00000000..f1af4024
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Worker/Iperf3ExecutorWorker.java
@@ -0,0 +1,152 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Peter Hasse
+ * SPDX-FileCopyrightText: 2023 Johann Hackler
+ * SPDX-FileCopyrightText: 2023 Fraunhofer FOKUS
+ *
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Worker;
+
+import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE;
+import static android.view.View.GONE;
+
+import static com.google.common.reflect.Reflection.getPackageName;
+
+import android.app.Notification;
+import android.content.Context;
+import android.graphics.Color;
+import android.util.Log;
+import android.widget.RemoteViews;
+
+import androidx.annotation.NonNull;
+import androidx.concurrent.futures.CallbackToFutureAdapter;
+import androidx.core.app.NotificationCompat;
+import androidx.work.Data;
+import androidx.work.ForegroundInfo;
+import androidx.work.WorkerParameters;
+import androidx.work.multiprocess.RemoteListenableWorker;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.gson.Gson;
+
+import java.io.File;
+
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Inputs.Iperf3Input;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Inputs.PingInput;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.RunResult.Iperf3ResultsDataBase;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.RunResult.Iperf3RunResult;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.RunResult.Iperf3RunResultDao;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Iperf3LibLoader;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Parameter.Iperf3Parameter;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R;
+
+public class Iperf3ExecutorWorker extends RemoteListenableWorker {
+ public static final String TAG = "Iperf3ExecutorWorker";
+
+ static {
+ Iperf3LibLoader.load();
+ }
+ private final String channelId = "OMNT_notification_channel";
+ private final int FOREGROUND_SERVICE_TYPE = FOREGROUND_SERVICE_TYPE_SPECIAL_USE;
+ private Iperf3Input iperf3Input;
+ private int notificationID = 2000;
+ private NotificationCompat.Builder notificationBuilder;
+ private Notification notification;
+ private Iperf3ResultsDataBase db;
+ private Iperf3RunResultDao iperf3RunResultDao;
+ private Iperf3RunResult iperf3RunResult;
+ public Iperf3ExecutorWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
+ super(context, workerParams);
+ Log.d(TAG, "Iperf3ExecutorWorker: called!");
+ Gson gson = new Gson();
+ String iperf3InputString = getInputData().getString(Iperf3Input.INPUT);
+ iperf3Input = gson.fromJson(iperf3InputString, Iperf3Input.class);
+ int notificationNumber = getInputData().getInt(PingInput.NOTIFICATIONUMBER, 0);
+ notificationID += notificationNumber;
+ db = Iperf3ResultsDataBase.getDatabase(context);
+ iperf3RunResultDao = db.iperf3RunResultDao();
+
+ notificationBuilder = new NotificationCompat.Builder(context, channelId);
+
+ }
+
+
+ @NonNull
+ @Override
+ public ListenableFuture startRemoteWork() {
+ return CallbackToFutureAdapter.getFuture(completer -> {
+ Log.d(TAG, "startRemoteWork: tags: "+this.getTags());
+ File logFile = new File(iperf3Input.getParameter().getLogfile());
+ File rawPath = new File(Iperf3Parameter.rawDirPath);
+
+ if(!rawPath.exists()) {
+ rawPath.mkdirs();
+ }
+ try {
+ logFile.createNewFile();
+ } catch (Exception e) {
+ Log.d(TAG, "startRemoteWork: "+e);
+ return completer.set(Result.failure());
+ }
+ Log.i(TAG, "startRemoteWork: "+TAG);
+
+ RemoteViews notificationLayout = new RemoteViews(getApplicationContext().getPackageName(), R.layout.iperf3_notification);
+ notificationLayout.setTextViewText(R.id.notification_title, "Running iPerf3 test...");
+ notificationLayout.setViewVisibility(R.id.notification_throughput, GONE);
+ notificationLayout.setViewVisibility(R.id.notification_direction, GONE);
+
+
+ setForegroundAsync(createForegroundInfo(notificationLayout));
+
+ int result = -1;
+
+ Log.d(TAG, "startRemoteWork: about to call iPerf3 JNI!");
+ result = iperf3Wrapper(iperf3Input.getParameter().getInputAsCommand(), getApplicationContext().getApplicationInfo().nativeLibraryDir);
+ Log.d(TAG, "startRemoteWork: JNI Thread: " + result);
+
+
+
+ iperf3RunResultDao.updateResult(iperf3Input.getTestUUID(), result);
+ Data.Builder output = new Data.Builder()
+ .putInt("result", result)
+ .putString("testUUID", iperf3Input.getTestUUID());
+
+
+ if (result == 0) {
+ Log.d(TAG, "startRemoteWork: iperf3Wrapper: success");
+ return completer.set(Result.success(output.build()));
+ }
+ Log.d(TAG, "startRemoteWork: iperf3Wrapper: failure");
+ return completer.set(Result.failure(output.build()));
+ });
+
+
+ }
+
+
+ @NonNull
+ @Override
+ public ListenableFuture setProgressAsync(@NonNull Data data) {
+ return super.setProgressAsync(data);
+ }
+
+ private native int iperf3Wrapper(String[] argv, String cache);
+
+
+ private ForegroundInfo createForegroundInfo(RemoteViews notificationLayout) {
+
+
+ notification = notificationBuilder
+ .setSmallIcon(R.mipmap.ic_launcher_foreground)
+ .setStyle(new NotificationCompat.DecoratedCustomViewStyle())
+ .setCustomContentView(notificationLayout)
+ .setOngoing(true)
+ .setOnlyAlertOnce(true)
+ .setColor(Color.WHITE)
+ .setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_IMMEDIATE)
+ .build();
+
+ return new ForegroundInfo(notificationID, notification, FOREGROUND_SERVICE_TYPE);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Worker/Iperf3MonitorWorker.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Worker/Iperf3MonitorWorker.java
new file mode 100644
index 00000000..46a56243
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Worker/Iperf3MonitorWorker.java
@@ -0,0 +1,308 @@
+
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Worker;
+
+import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE;
+import static android.view.View.GONE;
+import static android.view.View.VISIBLE;
+
+import android.app.Notification;
+import android.content.Context;
+import android.graphics.Color;
+import android.os.FileObserver;
+import android.util.Log;
+import android.widget.RemoteViews;
+
+import androidx.annotation.NonNull;
+import androidx.concurrent.futures.CallbackToFutureAdapter;
+import androidx.core.app.NotificationCompat;
+import androidx.work.Data;
+import androidx.work.ForegroundInfo;
+import androidx.work.WorkQuery;
+import androidx.work.WorkerParameters;
+import androidx.work.multiprocess.RemoteListenableWorker;
+import androidx.work.multiprocess.RemoteWorkManager;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.gson.Gson;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.sql.Timestamp;
+import java.util.Arrays;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Inputs.Iperf3Input;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.RunResult.Iperf3ResultsDataBase;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.RunResult.Iperf3RunResult;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.RunResult.Iperf3RunResultDao;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Intervals;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Error;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Interval;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.start.Start;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Metric.METRIC_TYPE;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Metric.MetricCalculator;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R;
+
+public class Iperf3MonitorWorker extends RemoteListenableWorker {
+ public static final String TAG = "Iperf3MonitorWorker";
+
+ private final String channelId = "OMNT_notification_channel";
+ private final int FOREGROUND_SERVICE_TYPE = FOREGROUND_SERVICE_TYPE_SPECIAL_USE;
+ private Iperf3Input iperf3Input;
+ private int notificationID = 4000;
+ private NotificationCompat.Builder notificationBuilder;
+ private Notification notification;
+ private Iperf3ResultsDataBase db;
+ private Iperf3RunResultDao iperf3RunResultDao;
+ private Iperf3RunResult iperf3RunResult;
+ private Context context;
+ private RemoteWorkManager remoteWorkManager;
+ private WorkQuery workQuery;
+ private ScheduledExecutorService executorService;
+ private BufferedReader br = null;
+ private String pathToFile;
+ private File file;
+ private boolean isStopped;
+
+ private RemoteViews notificationLayout;
+ private FileObserver fileObserver;
+
+ MetricCalculator metricCalculatorUL;
+ MetricCalculator metricCalculatorDL;
+
+ public Iperf3MonitorWorker(@NonNull Context context, @NonNull WorkerParameters workerParams){
+ super(context, workerParams);
+ Gson gson = new Gson();
+ this.context = context;
+ metricCalculatorUL = new MetricCalculator(METRIC_TYPE.THROUGHPUT);
+ metricCalculatorDL = new MetricCalculator(METRIC_TYPE.THROUGHPUT);
+ String iperf3InputString = getInputData().getString(Iperf3Input.INPUT);
+ iperf3Input = gson.fromJson(iperf3InputString, Iperf3Input.class);
+ int notificationNumber = getInputData().getInt(Iperf3Input.NOTIFICATIONUMBER, 0);
+ notificationID += notificationNumber;
+ db = Iperf3ResultsDataBase.getDatabase(this.context);
+ iperf3RunResultDao = db.iperf3RunResultDao();
+ notificationBuilder = new NotificationCompat.Builder(this.context, channelId);
+ iperf3RunResultDao.getRunResult(iperf3Input.getTestUUID());
+ remoteWorkManager = RemoteWorkManager.getInstance(this.context);
+ workQuery = WorkQuery.Builder
+ .fromTags(Arrays.asList(iperf3Input.getTestUUID()))
+ .build();
+
+ executorService = Executors.newScheduledThreadPool(1);
+
+ notificationLayout = new RemoteViews(getApplicationContext().getPackageName(), R.layout.iperf3_notification);
+ notificationLayout.setTextViewText(R.id.notification_title, "Running iPerf3 test...");
+ notificationLayout.setViewVisibility(R.id.notification_throughput, GONE);
+ notificationLayout.setViewVisibility(R.id.notification_direction, GONE);
+ setForegroundAsync(createForegroundInfo(notificationLayout));
+
+ this.pathToFile = iperf3Input.getParameter().getLogfile();
+ Log.d(TAG, "Iperf3MonitorWorker: pathToFile: "+this.pathToFile);
+ this.file = new File(this.pathToFile);
+ }
+
+
+ @NonNull
+ @Override
+ public ListenableFuture startRemoteWork() {
+ return CallbackToFutureAdapter.getFuture(completer -> {
+
+
+ setForegroundAsync(createForegroundInfo(notificationLayout));
+ try {
+ br = new BufferedReader(new FileReader(file));
+ br.ready();
+ } catch (IOException ex) {
+ Log.d(TAG, "Iperf3MonitorWorker: file not found!" + ex);
+ }
+ Log.d(TAG, "doWork: starting "+this.getClass().getCanonicalName());
+ Timestamp starTtime = new Timestamp(iperf3RunResultDao.getTimestampFromUid(iperf3Input.getTestUUID()));
+ while(true){
+ Timestamp newTimestamp = new java.sql.Timestamp(System.currentTimeMillis());
+ long deltaInMillis = Math.abs(newTimestamp.getTime() - starTtime.getTime());
+ if(deltaInMillis > iperf3Input.getParameter().getTime()*1000){
+ break;
+ }
+ String line = null;
+ try {
+ while ((line = br.readLine()) != null) {
+ JSONObject obj = null;
+ try {
+ obj = new JSONObject(line);
+ } catch (JSONException e) {
+ Log.d(TAG, "run: parsing line as JSONObject failed");
+ break;
+ }
+ String event = null;
+ try {
+ event = obj.getString("event");
+ Log.d(TAG, "run: got event: " + event);
+ } catch (JSONException e) {
+ Log.d(TAG, "run: parsing event failed");
+ break;
+ }
+ switch (event) {
+ case "start":
+ Log.d(TAG, "parse: Start");
+ Start start = new Start();
+ JSONObject startData = null;
+ try {
+ startData = obj.getJSONObject("data");
+ } catch (JSONException e) {
+ Log.e(TAG, "parse: getting start failed");
+ Log.d(TAG, "parse: " + e);
+
+ }
+ try {
+ start.parseStart(startData);
+ } catch (JSONException e) {
+ Log.e(TAG, "parse: parsing start failed");
+ Log.d(TAG, "parse: " + e);
+
+ }
+ setProgressAsync(new Data.Builder().putString("start", start.toString()).build());
+ iperf3RunResultDao.updateStart(iperf3Input.getTestUUID(), start.toString());
+
+
+ break;
+ case "interval":
+ Log.d(TAG, "parse: Interval");
+ Interval interval = new Interval();
+ JSONObject intervalData = null;
+ try {
+ intervalData = obj.getJSONObject("data");
+ } catch (JSONException e) {
+ Log.e(TAG, "run: getting interval failed");
+ Log.d(TAG, "parse: " + e);
+
+ }
+ try {
+ interval.parse(intervalData);
+ } catch (JSONException e) {
+ Log.e(TAG, "run: parsing interval failed");
+ Log.d(TAG, "parse: " + e);
+
+ }
+
+
+ Log.d(TAG, "Read Thread: interval: " + interval.toString());
+ if (interval.getSum().getSender()) {
+ metricCalculatorUL.update(interval.getSum().getBits_per_second());
+ } else {
+ metricCalculatorDL.update(interval.getSum().getBits_per_second());
+ }
+
+ String megabitPerSecond = String.valueOf( Math.round(interval.getSum().getBits_per_second() / 1e6));
+ metricCalculatorUL.update(interval.getSum().getBits_per_second());
+ notificationLayout.setTextViewText(R.id.notification_title, String.format("iPerf3 %s:%s", iperf3Input.getParameter().getHost(), iperf3Input.getParameter().getPort()));
+ notificationLayout.setTextViewText(R.id.notification_throughput, String.format("Throughput: %s Mbit/s", megabitPerSecond));
+ notificationLayout.setTextViewText(R.id.notification_direction, String.format("Direction: %s", interval.getSum().getSumType()));
+ notificationLayout.setViewVisibility(R.id.notification_throughput, VISIBLE);
+ notificationLayout.setViewVisibility(R.id.notification_direction, VISIBLE);
+
+
+ if (interval.getSumBidirReverse() != null) {
+ notificationLayout.setViewVisibility(R.id.notification_bidir_throughput, VISIBLE);
+ notificationLayout.setViewVisibility(R.id.notification_bidir_direction, VISIBLE);
+ notificationLayout.setTextViewText(R.id.notification_bidir_throughput, String.format("Throughput: %d Mbit/s", Math.round(interval.getSumBidirReverse().getBits_per_second() / 1e6)));
+ notificationLayout.setTextViewText(R.id.notification_bidir_direction, String.format("Direction: %s", interval.getSumBidirReverse().getSumType()));
+ metricCalculatorDL.update(interval.getSumBidirReverse().getBits_per_second());
+ }
+ metricCalculatorDL.calcAll();
+ metricCalculatorUL.calcAll();
+ iperf3RunResultDao.updateMetricDL(iperf3Input.getTestUUID(), metricCalculatorDL);
+ iperf3RunResultDao.updateMetricUL(iperf3Input.getTestUUID(), metricCalculatorUL);
+
+ setProgressAsync(new Data.Builder().putString("interval", interval.toString()).build());
+ setForegroundAsync(createForegroundInfo(notificationLayout));
+
+ Intervals _intervals = iperf3RunResultDao.getIntervals(iperf3Input.getTestUUID());
+ if (_intervals == null) {
+ _intervals = new Intervals();
+ }
+ _intervals.addInterval(interval);
+ iperf3RunResultDao.updateIntervals(iperf3Input.getTestUUID(), _intervals);
+ break;
+ case "end":
+ Log.d(TAG, "parse: End");
+ //todo
+ //End end = new End();
+ //JSONObject endData = obj.getJSONObject("data");
+ //end.parseEnd(endData);
+ //support.firePropertyChange("interval", null, end);
+
+ break;
+ case "error":
+ Log.d(TAG, "parse: Error");
+ de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Error error = new Error();
+ String errorString = null;
+ iperf3RunResultDao.updateResult(iperf3Input.getTestUUID(), -1);
+ try {
+ errorString = obj.getString("data");
+ } catch (JSONException e) {
+ Log.e(TAG, "run: getting error failed!");
+ Log.d(TAG, "parse: " + e);
+ break;
+ }
+ try {
+ error.parse(errorString);
+ Log.d(TAG, "startRemoteWork: got error!"+error);
+ setProgressAsync(new Data.Builder().putString("error", error.toString()).build());
+ iperf3RunResultDao.updateError(iperf3Input.getTestUUID(), error);
+ } catch (JSONException e) {
+ Log.e(TAG, "run: parsing error failed!");
+ Log.d(TAG, "parse: " + e);
+ break;
+ }
+
+ return completer.set(Result.success());
+ default:
+ Log.d(TAG, "parse: Unknown event");
+ break;
+ }
+ Thread.sleep((long) (iperf3Input.getParameter().getInterval() * 1001));
+
+ }
+ } catch (Exception e){
+ Log.d(TAG, "run: error reading file: "+e);
+
+ }
+ }
+
+
+
+
+
+
+
+ return completer.set(Result.success());
+ });
+ }
+
+ private ForegroundInfo createForegroundInfo(RemoteViews notificationLayout) {
+
+
+ notification = notificationBuilder
+ .setSmallIcon(R.mipmap.ic_launcher_foreground)
+ .setStyle(new NotificationCompat.DecoratedCustomViewStyle())
+ .setCustomContentView(notificationLayout)
+ .setOngoing(true)
+ .setOnlyAlertOnce(true)
+ .setColor(Color.WHITE)
+ .setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_IMMEDIATE)
+ .build();
+
+ return new ForegroundInfo(notificationID, notification, FOREGROUND_SERVICE_TYPE);
+ }
+
+
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3ToLineProtocolWorker.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Worker/Iperf3ToLineProtocolWorker.java
similarity index 53%
rename from app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3ToLineProtocolWorker.java
rename to app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Worker/Iperf3ToLineProtocolWorker.java
index 86cf58fc..adbeeef7 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3ToLineProtocolWorker.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Worker/Iperf3ToLineProtocolWorker.java
@@ -6,184 +6,136 @@
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
-package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3;
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Worker;
+import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE;
+
+import android.app.Notification;
import android.content.Context;
+import android.graphics.Color;
import android.os.Build;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
+import androidx.core.app.NotificationCompat;
import androidx.work.Data;
+import androidx.work.ForegroundInfo;
import androidx.work.Worker;
import androidx.work.WorkerParameters;
-import com.google.common.base.Splitter;
+import com.google.gson.Gson;
import com.influxdb.client.domain.WritePrecision;
import com.influxdb.client.write.Point;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.util.Collections;
-import java.util.HashMap;
+import java.util.ArrayList;
import java.util.LinkedList;
-import java.util.Map;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.DataProvider.DeviceInformation;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.GlobalVars;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.InfluxDB2x.InfluxdbConnection;
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.InfluxDB2x.InfluxdbConnections;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Inputs.Iperf3Input;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.RunResult.Iperf3ResultsDataBase;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.RunResult.Iperf3RunResult;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.RunResult.Iperf3RunResultDao;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Interval;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.Stream;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.TCP.TCP_UL_STREAM;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.JSON.Interval.Streams.UDP.UDP_DL_STREAM;
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SPType;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SharedPreferencesGrouper;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R;
public class Iperf3ToLineProtocolWorker extends Worker {
- private static final String TAG = "Iperf3UploadWorker";
+ public static final String TAG = "Iperf3ToLineProtocolWorker";
InfluxdbConnection influx;
- private String rawIperf3file;
- private String measurementName;
- private String ip;
+ private final int FOREGROUND_SERVICE_TYPE = FOREGROUND_SERVICE_TYPE_SPECIAL_USE;
private SharedPreferencesGrouper spg;
-
- private String port;
- private String bandwidth;
- private String duration;
- private String intervalIperf;
- private String bytes;
- private final String protocol;
- private final String iperf3LineProtocolFile;
-
+ private Notification notification;
+ private NotificationCompat.Builder notificationBuilder;
+ private Iperf3RunResultDao iperf3RunResultDao;
private final DeviceInformation di = GlobalVars.getInstance().get_dp().getDeviceInformation();
-
- private final boolean rev;
- private final boolean biDir;
- private final boolean oneOff;
- private final boolean client;
-
- private final String runID;
+ private int notificationID;
+ private Iperf3Input iperf3Input;
public Iperf3ToLineProtocolWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
- rawIperf3file = getInputData().getString("rawIperf3file");
-
- ip = getInputData().getString("ip");
- measurementName = getInputData().getString("measurementName");
- iperf3LineProtocolFile = getInputData().getString("iperf3LineProtocolFile");
- port = getInputData().getString("port");
- if(port == null)
- port = "5201";
- protocol = getInputData().getString("protocol");
- bandwidth = getInputData().getString("bandwidth");
-
- if(bandwidth == null){
- if(protocol.equals("TCP")) {
- bandwidth = "unlimited";
- } else {
- bandwidth = "1000";
- }
- }
-
- duration = getInputData().getString("duration");
- if(duration == null)
- duration = "10";
- intervalIperf = getInputData().getString("interval");
- if(intervalIperf == null)
- intervalIperf = "1";
- bytes = getInputData().getString("bytes");
- if(bytes == null){
- if(protocol.equals("TCP")) {
- bytes = "8";
- } else {
- bytes = "1470";
- }
- }
-
- rev = getInputData().getBoolean("rev", false);
- biDir = getInputData().getBoolean("biDir",false);
- oneOff = getInputData().getBoolean("oneOff",false);
- client = getInputData().getBoolean("client",false);
- runID = getInputData().getString("iperf3WorkerID");
+ Gson gson = new Gson();
+ String iperf3InputString = getInputData().getString(Iperf3Input.INPUT);
+ iperf3Input = gson.fromJson(iperf3InputString, Iperf3Input.class);
+ notificationBuilder = new NotificationCompat.Builder(getApplicationContext(), "OMNT_notification_channel");
+ notificationID = 200+getInputData().getInt(Iperf3Input.NOTIFICATIONUMBER, 0);
spg = SharedPreferencesGrouper.getInstance(getApplicationContext());
+ setForegroundAsync(createForegroundInfo("Processing iPerf3 data"));
+ iperf3RunResultDao = Iperf3ResultsDataBase.getDatabase(getApplicationContext()).iperf3RunResultDao();
}
-
- private void setup(){
- influx = InfluxdbConnections.getRicInstance(getApplicationContext());
- }
-
-
- public Map getTagsMap() {
- String tags = spg.getSharedPreference(SPType.logging_sp).getString("tags", "").strip().replace(" ", "");
- Map tags_map = Collections.emptyMap();
- if (!tags.isEmpty()) {
- try {
- tags_map = Splitter.on(',').withKeyValueSeparator('=').split(tags);
- } catch (IllegalArgumentException e) {
- Log.d(TAG, "can't parse tags, ignoring");
- }
- }
- Map tags_map_modifiable = new HashMap<>(tags_map);
- tags_map_modifiable.put("measurement_name", spg.getSharedPreference(SPType.logging_sp).getString("measurement_name", "OMNT"));
- tags_map_modifiable.put("manufacturer", di.getManufacturer());
- tags_map_modifiable.put("model", di.getModel());
- tags_map_modifiable.put("sdk_version", String.valueOf(di.getAndroidSDK()));
- tags_map_modifiable.put("android_version", di.getAndroidRelease());
- tags_map_modifiable.put("secruity_patch", di.getSecurityPatchLevel());
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
- tags_map_modifiable.put("soc_model", di.getSOCModel());
- }
- tags_map_modifiable.put("radio_version", Build.getRadioVersion());
- return tags_map_modifiable;
+ private ForegroundInfo createForegroundInfo(String progress) {
+ notification = notificationBuilder
+ .setContentTitle("iPerf32LineProtocol")
+ .setContentText(progress)
+ .setOngoing(true)
+ .setOnlyAlertOnce(true)
+ .setColor(Color.WHITE)
+ .setSmallIcon(R.mipmap.ic_launcher_foreground)
+ .setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_DEFAULT)
+ .build();
+ return new ForegroundInfo(notificationID, notification, FOREGROUND_SERVICE_TYPE);
}
@NonNull
@Override
public Result doWork() {
- setup();
Data output = new Data.Builder().putBoolean("iperf3_upload", false).build();
- Iperf3Parser iperf3Parser = new Iperf3Parser(rawIperf3file);
- iperf3Parser.parse();
+ Iperf3RunResult iperf3RunResult = iperf3RunResultDao.getRunResult(iperf3Input.getTestUUID());
-
- long timestamp = Integer.toUnsignedLong( iperf3Parser.getStart().getTimestamp().getTimesecs())*1000;
+ long timestamp = Integer.toUnsignedLong( iperf3RunResult.start.getTimestamp().getTimesecs())*1000;
Log.d(TAG, "doWork: "+timestamp);
String role = "server";
- if(iperf3Parser.getStart().getConnecting_to() != null){
+ if(iperf3RunResult.start.getConnecting_to() != null){
role = "client";
}
LinkedList points = new LinkedList();
- for (Interval interval: iperf3Parser.getIntervals().getIntervalArrayList()) {
+ ArrayList intervals = iperf3RunResult.intervals.getIntervalArrayList();
+ for (Interval interval: intervals) {
long tmpTimestamp = timestamp + (long) (interval.getSum().getEnd() * 1000);
- int intervalIdx = iperf3Parser.getIntervals().getIntervalArrayList().indexOf(interval);
+ int intervalIdx = intervals.indexOf(interval);
for (Stream stream: interval.getStreams().getStreamArrayList()){
Point point = new Point("Iperf3");
- point.addTag("run_uid", runID);
- point.addTag("bidir", String.valueOf(biDir));
+
+ point.addTag(Iperf3Input.TESTUUID, iperf3Input.getTestUUID());
+ point.addTag(Iperf3Input.SEQUENCEUUID, iperf3Input.getSequenceUUID());
+ point.addTag(Iperf3Input.MEASUREMENTUUID, iperf3Input.getMeasurementUUID());
+ point.addTag(Iperf3Input.CAMPAIGNUUID, iperf3Input.getCampaignUUID());
+ point.addTag(Iperf3Input.IPERF3UUID, iperf3Input.getParameter().getiPerf3UUID());
+
+
+
+
+ point.addTag("bidir", String.valueOf(iperf3Input.getParameter().getBidir()));
point.addTag("sender", String.valueOf(stream.getSender()));
point.addTag("role", role);
point.addTag("socket", String.valueOf(stream.getSocket()));
- point.addTag("protocol", protocol);
- point.addTag("interval", intervalIperf);
- point.addTag("version", iperf3Parser.getStart().getVersion());
- point.addTag("reversed", String.valueOf(rev));
- point.addTag("oneOff", String.valueOf(oneOff));
- point.addTag("connectingToHost", iperf3Parser
- .getStart()
+ point.addTag("protocol", iperf3RunResult.start.getTest_start().protocol);
+ point.addTag("interval", String.valueOf(iperf3Input.getParameter().getInterval()));
+ point.addTag("version", iperf3RunResult.start.getVersion());
+ point.addTag("reversed", String.valueOf(iperf3Input.getParameter().getReverse()));
+ point.addTag("oneOff", String.valueOf(iperf3Input.getParameter().getOneOff()));
+ point.addTag("connectingToHost", iperf3RunResult
+ .start
.getConnecting_to()
.getHost());
- point.addTag("connectingToPort", String.valueOf(iperf3Parser
- .getStart()
+ point.addTag("connectingToPort", String.valueOf(iperf3RunResult
+ .start
.getConnecting_to()
.getPort()));
- point.addTag("bandwidth", bandwidth);
- point.addTag("duration", duration);
- point.addTag("bytesToTransmit", bytes);
+ point.addTag("bandwidth", iperf3Input.getParameter().getBitrate());
+ point.addTag("duration", String.valueOf(iperf3Input.getParameter().getTime()));
+ point.addTag("bytesToTransmit", String.valueOf(iperf3Input.getParameter().getBytes()));
point.addTag("streams", String.valueOf(interval.getStreams().size()));
point.addTag("streamIdx", String.valueOf(interval.getStreams().getStreamArrayList().indexOf(stream)));
point.addTag("intervalIdx", String.valueOf(intervalIdx));
@@ -221,13 +173,14 @@ public Result doWork() {
point.time(tmpTimestamp, WritePrecision.MS);
points.add(point);
+ setForegroundAsync(createForegroundInfo("Processing iPerf3 data: "+intervalIdx+"/"+intervals.size()));
}
}
// is needed when only --udp is, otherwise no lostpackets/lostpercent parsed
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
for (Point point:points) {
- point.addTags(getTagsMap());
+ point.addTags(GlobalVars.getInstance().get_dp().getTagsMap());
}
}
@@ -235,7 +188,7 @@ public Result doWork() {
FileOutputStream iperf3Stream = null;
try {
- iperf3Stream = new FileOutputStream(iperf3LineProtocolFile, true);
+ iperf3Stream = new FileOutputStream(iperf3Input.getParameter().getLineProtocolFile(), true);
} catch (FileNotFoundException e) {
Toast.makeText(getApplicationContext(), "logfile not created", Toast.LENGTH_SHORT).show();
Log.d(TAG,e.toString());
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3UploadWorker.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Worker/Iperf3UploadWorker.java
similarity index 78%
rename from app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3UploadWorker.java
rename to app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Worker/Iperf3UploadWorker.java
index b3ff8d43..54e9cbcf 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Iperf3UploadWorker.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Iperf3/Worker/Iperf3UploadWorker.java
@@ -6,7 +6,7 @@
* SPDX-License-Identifier: BSD-3-Clause-Clear
*/
-package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3;
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Worker;
import android.content.Context;
import android.util.Log;
@@ -16,6 +16,8 @@
import androidx.work.Worker;
import androidx.work.WorkerParameters;
+import com.google.gson.Gson;
+
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
@@ -25,16 +27,18 @@
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.InfluxDB2x.InfluxdbConnection;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.InfluxDB2x.InfluxdbConnections;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Inputs.Iperf3Input;
public class Iperf3UploadWorker extends Worker {
- private static final String TAG = "Iperf3UploadWorker";
+ public static final String TAG = "Iperf3UploadWorker";
InfluxdbConnection influx;
- private final String iperf3LineProtocolFile;
-
+ private Iperf3Input iperf3Input;
public Iperf3UploadWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
- iperf3LineProtocolFile = getInputData().getString("iperf3LineProtocolFile");
+ Gson gson = new Gson();
+ String iperf3InputString = getInputData().getString(Iperf3Input.INPUT);
+ iperf3Input = gson.fromJson(iperf3InputString, Iperf3Input.class);
}
private void setup(){
influx = InfluxdbConnections.getRicInstance(getApplicationContext());
@@ -61,17 +65,17 @@ public Result doWork() {
}
BufferedReader br;
try {
- br = new BufferedReader(new FileReader(iperf3LineProtocolFile));
+ br = new BufferedReader(new FileReader(iperf3Input.getParameter().getLineProtocolFile()));
} catch (FileNotFoundException | NullPointerException e) {
Log.d(TAG,e.toString());
return Result.failure(output);
}
List points = br.lines().collect(Collectors.toList());
try {
- Log.d(TAG, String.format("doWork: uploading %s", iperf3LineProtocolFile));
+ Log.d(TAG, String.format("doWork: uploading %s", iperf3Input.getParameter().getLineProtocolFile()));
influx.writeRecords(points);
} catch (IOException e) {
- Log.d(TAG, String.format("doWork: upload of %s failed!", iperf3LineProtocolFile));
+ Log.d(TAG, String.format("doWork: upload of %s failed!", iperf3Input.getParameter().getLineProtocolFile()));
return Result.failure(output);
}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/LoggingService.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/LoggingService.java
index 447bd96f..c3e0b2f7 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/LoggingService.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/LoggingService.java
@@ -370,7 +370,7 @@ public int onStartCommand(Intent intent, int flags, int startId) {
}
if (spg.getSharedPreference(SPType.logging_sp).getBoolean("enable_local_influx_log", false)) {
- setupLocalFile();
+ //TODO
}
setupNotification();
@@ -609,7 +609,9 @@ private void stopLocalInfluxDB() {
public void run() {
if (ic == null) return;
boolean newInfluxConnectionStatus = ic.ping();
- Log.d(TAG, "run: monitorInfluxDBConnectionStatus: "+newInfluxConnectionStatus);
+ if(!newInfluxConnectionStatus) {
+ Log.d(TAG, "InfluxDB not reachable");
+ }
if(newInfluxConnectionStatus != influxConnectionStatus) {
influxConnectionStatus = newInfluxConnectionStatus;
updateNotification();
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/MQTT/Handler/Handler.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/MQTT/Handler/Handler.java
new file mode 100644
index 00000000..74db5d15
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/MQTT/Handler/Handler.java
@@ -0,0 +1,41 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.MQTT.Handler;
+
+import android.content.Context;
+import android.util.Log;
+
+import androidx.work.OneTimeWorkRequest;
+import androidx.work.WorkInfo;
+import androidx.work.WorkManager;
+import androidx.work.multiprocess.RemoteWorkContinuation;
+import androidx.work.multiprocess.RemoteWorkManager;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Inputs.Iperf3Input;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Inputs.PingInput;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Parameter.Iperf3Parameter;
+
+abstract public class Handler {
+ private final String TAG = "Handler";
+ abstract public void parsePayload(String payload) throws JSONException;
+
+ public Handler() {
+ }
+ abstract public ArrayList getExecutorWorkRequests(Context context);
+
+ abstract public ArrayList getMonitorWorkRequests(Context context);
+
+ abstract public ArrayList getToLineProtocolWorkRequests(Context context);
+
+ abstract public ArrayList getUploadWorkRequests(Context context);
+
+ abstract public void preperareSequence(Context context);
+
+ abstract public void enableSequence();
+
+ abstract public void disableSequence(Context context);
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/MQTT/Handler/Iperf3Handler.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/MQTT/Handler/Iperf3Handler.java
new file mode 100644
index 00000000..befa824e
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/MQTT/Handler/Iperf3Handler.java
@@ -0,0 +1,174 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.MQTT.Handler;
+
+import android.content.Context;
+import android.util.Log;
+
+import androidx.work.OneTimeWorkRequest;
+import androidx.work.WorkInfo;
+import androidx.work.WorkManager;
+import androidx.work.WorkRequest;
+import androidx.work.multiprocess.RemoteWorkContinuation;
+import androidx.work.multiprocess.RemoteWorkManager;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+
+import java.io.File;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Inputs.Iperf3Input;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Inputs.PingInput;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.RunResult.Iperf3ResultsDataBase;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.RunResult.Iperf3RunResult;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Iperf3.Database.RunResult.Iperf3RunResultDao;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Parameter.Iperf3Parameter;
+
+public class Iperf3Handler extends Handler {
+ private final String TAG = "Iperf3Handler";
+ private ArrayList iperf3Inputs;
+ private boolean isEnable = false;
+ private ArrayList continuations;
+ private Iperf3RunResultDao iperf3RunResultDao;
+ @Override
+ public void parsePayload(String payload) throws JSONException {
+ iperf3Inputs = new ArrayList<>();
+ JSONArray tests = new JSONArray(payload);
+ for (int i = 0; i < tests.length(); i++) {
+ JSONObject test = tests.getJSONObject(i);
+ String testUUID = test.getString("testUUID");
+ String measurementUUUID = test.getString("measurementUUID");
+ String sequenceUUID = test.getString("sequenceUUID");
+ String campaignUUID = test.getString("campaignUUID");
+ String device = test.getString("device");
+ String testType = test.getString("type");
+ if(!testType.equals("iperf3")) continue;
+ JSONObject params = test.getJSONObject("params");
+
+ Iperf3Parameter iperf3Parameter = new Iperf3Parameter(params, testUUID);
+ if(iperf3Parameter == null) continue;
+ Iperf3Input iperf3Input = new Iperf3Input(iperf3Parameter, testUUID, sequenceUUID, measurementUUUID,campaignUUID);
+ iperf3Input.setTimestamp(new Timestamp(System.currentTimeMillis()));
+ iperf3Inputs.add(iperf3Input);
+
+ Iperf3RunResult iperf3RunResult = new Iperf3RunResult(iperf3Input.getTestUUID(), -100, false, iperf3Input, new java.sql.Timestamp(System.currentTimeMillis()));
+ iperf3RunResultDao.insert(iperf3RunResult);
+ File logFile = new File(iperf3Input.getParameter().getLogfile());
+ if(logFile.exists()) {
+ logFile.delete();
+ }
+
+ }
+ }
+
+ public ArrayList getTestUUIDs() {
+ ArrayList testUUIDs = new ArrayList<>();
+ for(Iperf3Input iperf3Input : iperf3Inputs) {
+ testUUIDs.add(iperf3Input.getTestUUID());
+ }
+ return testUUIDs;
+ }
+ public Iperf3Handler(Context context) {
+ super();
+ iperf3RunResultDao = Iperf3ResultsDataBase.getDatabase(context).iperf3RunResultDao();
+ }
+ @Override
+ public ArrayList getExecutorWorkRequests(Context context) {
+ ArrayList executorWorkRequests = new ArrayList<>();
+ for(Iperf3Input iperf3Input : iperf3Inputs) {
+ executorWorkRequests.add(iperf3Input.getWorkRequestExecutor(iperf3Inputs.indexOf(iperf3Input), context.getPackageName()));
+ }
+ return executorWorkRequests;
+ }
+ @Override
+ public ArrayList getMonitorWorkRequests(Context context) {
+ ArrayList monitorWorkRequests = new ArrayList<>();
+ for(Iperf3Input iperf3Input : iperf3Inputs) {
+ monitorWorkRequests.add(iperf3Input.getWorkRequestMonitor(iperf3Inputs.indexOf(iperf3Input), context.getPackageName()));
+ }
+ return monitorWorkRequests;
+ }
+
+
+
+
+ @Override
+ public ArrayList getToLineProtocolWorkRequests(Context context) {
+ ArrayList lineProtocolWorkRequests = new ArrayList<>();
+ for(Iperf3Input iperf3Input : iperf3Inputs) {
+ lineProtocolWorkRequests.add(iperf3Input.getWorkRequestLineProtocol(iperf3Inputs.indexOf(iperf3Input), context.getPackageName()));
+ }
+ return lineProtocolWorkRequests;
+ }
+ @Override
+ public ArrayList getUploadWorkRequests(Context context) {
+ ArrayList uploadWorkRequests = new ArrayList<>();
+ for(Iperf3Input iperf3Input : iperf3Inputs) {
+ uploadWorkRequests.add(iperf3Input.getWorkRequestUpload(iperf3Inputs.indexOf(iperf3Input), context.getPackageName()));
+ }
+ return uploadWorkRequests;
+ }
+
+ @Override
+ public void preperareSequence(Context context){
+ continuations = new ArrayList<>();
+ Log.d(TAG, "enableSequence: called!");
+ if(iperf3Inputs.isEmpty()) {
+ Log.e(TAG, "No iperf3 tests to run");
+ return;
+ };
+
+ ArrayList> workRequestss = new ArrayList<>();
+ RemoteWorkManager remoteWorkManager = RemoteWorkManager.getInstance(context);
+ for(Iperf3Input iperf3Input: iperf3Inputs){
+ remoteWorkManager.cancelAllWorkByTag(iperf3Input.getTestUUID());
+ ArrayList workRequests = new ArrayList<>();
+ int i = iperf3Inputs.indexOf(iperf3Input);
+ workRequests.add(iperf3Input.getWorkRequestExecutor(i, context.getPackageName()));
+ workRequests.add(iperf3Input.getWorkRequestMonitor(i, context.getPackageName()));
+ workRequests.add(iperf3Input.getWorkRequestLineProtocol(i, context.getPackageName()));
+ workRequests.add(iperf3Input.getWorkRequestUpload(i, context.getPackageName()));
+ workRequestss.add(workRequests);
+ Log.d(TAG, "enableSequence: workRequests size: "+workRequests.size());
+ }
+
+
+ Log.d(TAG, "enableSequence: workRequestss size: "+workRequestss.size());
+ for(ArrayList workRequests: workRequestss){
+ RemoteWorkContinuation remoteWorkContinuation = remoteWorkManager.beginWith(workRequests.subList(0, 2)).then(workRequests.get(2)).then(workRequests.get(3));
+ continuations.add(remoteWorkContinuation);
+ }
+ Log.d(TAG, "enableSequence: continuations size: "+continuations.size());
+ }
+
+ @Override
+ public void enableSequence(){
+
+ for(RemoteWorkContinuation continuation: continuations){
+ continuation.enqueue();
+ }
+ }
+
+ @Override
+ public void disableSequence(Context context){
+ RemoteWorkManager workManager = RemoteWorkManager.getInstance(context);
+ for(Iperf3Input iperf3Input: iperf3Inputs){
+ workManager.cancelAllWorkByTag(iperf3Input.getTestUUID());
+ }
+ }
+
+ public boolean isEnable() {
+ return isEnable;
+ }
+
+ public void setEnable(boolean enable) {
+ isEnable = enable;
+ }
+}
+
+
+
+
+
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/MQTT/Handler/PingHandler.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/MQTT/Handler/PingHandler.java
new file mode 100644
index 00000000..8ecb8438
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/MQTT/Handler/PingHandler.java
@@ -0,0 +1,116 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.MQTT.Handler;
+
+import android.content.Context;
+
+import androidx.work.OneTimeWorkRequest;
+import androidx.work.multiprocess.RemoteWorkContinuation;
+import androidx.work.multiprocess.RemoteWorkManager;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.File;
+import java.util.ArrayList;
+
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Inputs.PingInput;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Parameter.PingParameter;
+
+public class PingHandler extends Handler {
+
+ public static final String TAG = "PingHandler";
+ private ArrayList pingInputs = new ArrayList<>();
+ private boolean isEnable = false;
+ private RemoteWorkContinuation workContinuation;
+ @Override
+ public void parsePayload(String payload) throws JSONException {
+ pingInputs.clear();
+ JSONArray tests = new JSONArray(payload);
+ for (int i = 0; i < tests.length(); i++) {
+ JSONObject test = tests.getJSONObject(i);
+ String testUUID = test.getString("testUUID");
+ String measurementUUUID = test.getString("measurementUUID");
+ String sequenceUUID = test.getString("sequenceUUID");
+ String campaignUUID = test.getString("campaignUUID");
+ String device = test.getString("device");
+ String testType = test.getString("type");
+ if(!testType.equals("ping")) continue;
+ JSONObject params = test.getJSONObject("params");
+
+ PingParameter pingParameter = new PingParameter(params, testUUID);
+ if(pingParameter == null) continue;
+ PingInput pingInput = new PingInput(pingParameter, testUUID, sequenceUUID, measurementUUUID,campaignUUID);
+ File logFile = new File(pingInput.getParameter().getLogfile());
+ if(logFile.exists()) {
+ logFile.delete();
+ }
+ pingInputs.add(pingInput);
+
+ }
+
+ }
+
+ public ArrayList getTestUUIDs() {
+ ArrayList testUUIDs = new ArrayList<>();
+ for(PingInput pingInput : pingInputs) {
+ testUUIDs.add(pingInput.getTestUUID());
+ }
+ return testUUIDs;
+ }
+
+ @Override
+ public ArrayList getExecutorWorkRequests(Context context) {
+ ArrayList executorWorkRequests = new ArrayList<>();
+ for(PingInput pingInput : pingInputs) {
+ executorWorkRequests.add(pingInput.getWorkRequestExecutor(pingInputs.indexOf(pingInput), context.getPackageName()));
+ }
+ return executorWorkRequests;
+ }
+
+ @Override
+ public ArrayList getMonitorWorkRequests(Context context) {
+ return null;
+ }
+
+ @Override
+ public ArrayList getToLineProtocolWorkRequests(Context context) {
+ ArrayList toLineProtocolWorkRequests = new ArrayList<>();
+ for(PingInput pingInput : pingInputs) {
+ toLineProtocolWorkRequests.add(pingInput.getWorkRequestLineProtocol(pingInputs.indexOf(pingInput), context.getPackageName()));
+ }
+ return toLineProtocolWorkRequests;
+ }
+ @Override
+ public ArrayList getUploadWorkRequests(Context context) {
+ ArrayList uploadWorkRequests = new ArrayList<>();
+ for(PingInput pingInput : pingInputs) {
+ uploadWorkRequests.add(pingInput.getWorkRequestUpload(pingInputs.indexOf(pingInput), context.getPackageName()));
+ }
+ return uploadWorkRequests;
+ }
+ @Override
+ public void preperareSequence(Context context) {
+ workContinuation = RemoteWorkManager.getInstance(context).beginWith(getExecutorWorkRequests(context)).then(getToLineProtocolWorkRequests(context)).then(getUploadWorkRequests(context));
+ }
+ @Override
+ public void enableSequence() {
+ if(workContinuation == null){
+ return;
+ }
+ workContinuation.enqueue();
+ }
+
+ @Override
+ public void disableSequence(Context context) {
+
+
+ }
+
+ public boolean isEnable() {
+ return isEnable;
+ }
+
+ public void setEnable(boolean enable) {
+ isEnable = enable;
+ }
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/MQTT/MQTTService.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/MQTT/MQTTService.java
new file mode 100644
index 00000000..708e4f73
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/MQTT/MQTTService.java
@@ -0,0 +1,506 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.MQTT;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.graphics.Color;
+import android.os.Build;
+import android.os.Handler;
+import android.os.IBinder;
+import android.util.Log;
+
+import androidx.annotation.Nullable;
+import androidx.core.app.NotificationCompat;
+import androidx.work.Data;
+import androidx.work.ExistingWorkPolicy;
+import androidx.work.OneTimeWorkRequest;
+import androidx.work.WorkInfo;
+import androidx.work.multiprocess.RemoteWorkManager;
+
+
+import com.hivemq.client.mqtt.datatypes.MqttQos;
+import com.hivemq.client.mqtt.mqtt5.Mqtt5AsyncClient;
+import com.hivemq.client.mqtt.mqtt5.Mqtt5Client;
+import com.hivemq.client.mqtt.mqtt5.message.connect.connack.Mqtt5ConnAck;
+import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5PayloadFormatIndicator;
+import com.influxdb.client.domain.Run;
+
+import org.json.JSONObject;
+
+import java.net.InetSocketAddress;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.CustomEventListener;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.MQTT.Handler.Iperf3Handler;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.MQTT.Handler.PingHandler;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.MainActivity;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SPType;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SharedPreferencesGrouper;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.RemoteWorkInfoChecker;
+
+public class MQTTService extends Service {
+ private static final String TAG = "MQTTService";
+ private Context context;
+ private SharedPreferences mqttSP;
+ private NotificationCompat.Builder builder;
+ public NotificationManager nm;
+ private Handler notificationHandler;
+ private Mqtt5AsyncClient client;
+ private SharedPreferencesGrouper spg;
+ private String deviceName;
+ private Iperf3Handler iperf3Handler;
+ private PingHandler pingHandler;
+ private boolean isEnabled = false;
+
+ @Nullable
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ private void setupSharedPreferences(){
+ spg = SharedPreferencesGrouper.getInstance(context);
+ mqttSP = spg.getSharedPreference(SPType.mqtt_sp);
+ mqttSP.registerOnSharedPreferenceChangeListener((sharedPreferences, key) -> {
+ if(key == null) return;
+ if (key.equals("mqtt_host")) {
+ Log.d(TAG, "MQTT Host update: " + sharedPreferences.getString("mqtt_host", ""));
+ client.disconnect();
+ createClient();
+ createNotification();
+ }
+ });
+ }
+
+ public void createClient(){
+ String addressString = mqttSP.getString("mqtt_host", "localhost:1883");
+ String host = null;
+ int port = -1;
+ try {
+ host = addressString.split(":")[0];
+ port = Integer.parseInt(addressString.split(":")[1]);
+ } catch (Exception e) {
+ Log.e(TAG, "createClient: Invalid address string: " + addressString);
+ return;
+ }
+ if(host == null || port == -1){
+ Log.e(TAG, "createClient: Invalid address string: " + addressString);
+ return;
+ }
+ InetSocketAddress address = new InetSocketAddress(host, port);
+ client = Mqtt5Client.builder()
+ .identifier(deviceName)
+ .serverAddress(address)
+ .automaticReconnect()
+ .initialDelay(200, TimeUnit.MILLISECONDS)
+ .maxDelay(30, TimeUnit.SECONDS)
+ .applyAutomaticReconnect()
+ .addConnectedListener(context -> {
+ Log.i(TAG, "createClient: Connected to MQTT server");
+ createNotification();
+ publishToTopic(String.format("device/%s/status", deviceName), "1", false);
+ })
+ .addDisconnectedListener(context -> {
+ Log.i(TAG, "createClient: Disconnected from MQTT server");
+ createNotification();
+ })
+ .willPublish()
+ .topic(String.format("device/%s/status", deviceName))
+ .qos(MqttQos.EXACTLY_ONCE)
+ .payload("0".getBytes())
+ .retain(true)
+ .payloadFormatIndicator(Mqtt5PayloadFormatIndicator.UTF_8)
+ .contentType("text/plain")
+ .noMessageExpiry()
+ .applyWillPublish()
+ .buildAsync();
+
+ Log.i(TAG, "createClient: Client created with address: " + addressString);
+ }
+
+ private void createNotification(){
+ StringBuilder s = new StringBuilder();
+ String address = spg.getSharedPreference(SPType.mqtt_sp).getString("mqtt_host", "None");
+ if(address.equals("None")){
+ s.append("MQTT Host: None\n");
+ } else {
+ s.append("Host: ").append(address).append("\n");
+ s.append("State: ").append(client.getState().toString()).append("\n");
+ }
+ builder.setStyle(new NotificationCompat.BigTextStyle()
+ .bigText(s));
+ nm.notify(3, builder.build());
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ nm = getSystemService(NotificationManager.class);
+ Intent notificationIntent = new Intent(this, MainActivity.class);
+ PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ // create notification
+ builder = new NotificationCompat.Builder(this, "OMNT_notification_channel")
+ .setContentTitle(getText(R.string.mqtt_service_running))
+ .setSmallIcon(R.mipmap.ic_launcher_foreground)
+ .setColor(Color.WHITE)
+ .setContentIntent(pendingIntent)
+ // prevent to swipe the notification away
+ .setOngoing(true)
+ // don't wait 10 seconds to show the notification
+ .setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_IMMEDIATE);
+ } else {
+ // create notification
+ builder = new NotificationCompat.Builder(this, "OMNT_notification_channel")
+ .setContentTitle(getText(R.string.mqtt_service_running))
+ .setSmallIcon(R.mipmap.ic_launcher_foreground)
+ .setColor(Color.WHITE)
+ .setContentIntent(pendingIntent)
+ // prevent to swipe the notification away
+ .setOngoing(true);
+ }
+
+ }
+
+ public void publishToTopic(String topic, String message, boolean retain){
+ client.publishWith()
+ .topic(topic)
+ .qos(MqttQos.EXACTLY_ONCE)
+ .payload(message.getBytes())
+ .retain(retain)
+ .send();
+ }
+
+ public void disconnectClient(){
+ CompletableFuture disconnect = client.disconnect();
+ disconnect.whenComplete((aVoid, throwable) -> {
+ if(throwable != null){
+ Log.e(TAG, "disconnectClient: Error disconnecting from MQTT server: " + throwable.getMessage());
+ } else {
+ Log.i(TAG, "disconnectClient: Disconnected from MQTT server");
+ }
+ });
+ }
+
+ public void connectClient(){
+
+ CompletableFuture connAck = client.connectWith()
+ .keepAlive(1)
+ .willPublish()
+ .topic(String.format("device/%s/status", deviceName))
+ .qos(MqttQos.EXACTLY_ONCE)
+ .payload("0".getBytes())
+ .retain(true)
+ .payloadFormatIndicator(Mqtt5PayloadFormatIndicator.UTF_8)
+ .contentType("text/plain")
+ .noMessageExpiry()
+ .applyWillPublish()
+ .send();
+
+ connAck.whenComplete((mqtt5ConnAck, throwable) -> {
+ if(throwable != null){
+ Log.e(TAG, "connectClient: Error connecting to MQTT server: " + throwable.getMessage());
+ } else {
+ Log.i(TAG, "connectClient: Connected to MQTT server");
+ publishToTopic(String.format("device/%s/status", deviceName), "1", true);
+ }
+ });
+ }
+
+ private boolean parseBoolean(String value){
+ switch (value.toLowerCase()){
+ case "true":
+ case "1":
+ return true;
+ case "false":
+ case "0":
+ return false;
+ }
+ return false;
+ }
+
+ private void handleConfigMessage(String topic, String payload){
+
+
+ // config logging service
+ if(topic.contains("/logging/enable")){
+ Log.d(TAG, "handleConfigMessage: Enable Logging: " + payload);
+ spg.getSharedPreference(SPType.logging_sp).edit().putBoolean("enable_logging", parseBoolean(payload)).apply();
+ return;
+ }
+
+ if(topic.contains("/logging/start_on_boot")){
+ Log.d(TAG, "handleConfigMessage: Start on Boot: " + payload);
+ spg.getSharedPreference(SPType.logging_sp).edit().putBoolean("start_logging_on_boot", parseBoolean(payload)).apply();
+ return;
+ }
+ if(topic.contains("/logging/notification_update_enabled")){
+ Log.d(TAG, "handleConfigMessage: Notification Update: " + payload);
+ spg.getSharedPreference(SPType.logging_sp).edit().putBoolean("enable_notification_update", parseBoolean(payload)).apply();
+ return;
+ }
+ if(topic.contains("/logging/interval_ms")){
+ Log.d(TAG, "handleConfigMessage: Logging Interval: " + payload);
+ spg.getSharedPreference(SPType.logging_sp).edit().putString("logging_interval", payload).apply();
+ return;
+ }
+
+ // config influxdv_v2 parameter
+ if(topic.contains("/influxv2/enabled")){
+ Log.d(TAG, "handleConfigMessage: Enable Influx: " + payload);
+ spg.getSharedPreference(SPType.logging_sp).edit().putBoolean("enable_influx", parseBoolean(payload)).apply();
+ return;
+ }
+ if(topic.contains("/influxv2/address")){
+ Log.d(TAG, "handleConfigMessage: Influx Address: " + payload);
+ spg.getSharedPreference(SPType.logging_sp).edit().putString("influx_URL", payload).apply();
+ return;
+ }
+ if(topic.contains("/influxv2/token")){
+ Log.d(TAG, "handleConfigMessage: Influx Token received!");
+ spg.getSharedPreference(SPType.logging_sp).edit().putString("influx_token", payload).apply();
+ return;
+ }
+ if(topic.contains("/influxv2/bucket")){
+ Log.d(TAG, "handleConfigMessage: Influx Bucket: " + payload);
+ spg.getSharedPreference(SPType.logging_sp).edit().putString("influx_bucket", payload).apply();
+ return;
+ }
+ if(topic.contains("/influxv2/org")){
+ Log.d(TAG, "handleConfigMessage: Influx Org: " + payload);
+ spg.getSharedPreference(SPType.logging_sp).edit().putString("influx_org", payload).apply();
+ return;
+ }
+ if(topic.contains("/influxv2/tags")){
+ Log.d(TAG, "handleConfigMessage: Influx Tags: " + payload);
+ //spg.getSharedPreference(SPType.logging_sp).edit().putString("influx_org", payload).apply();
+ //TODO
+ return;
+ }
+
+
+ // config log file
+ if(topic.contains("/file/enabled")){
+ Log.d(TAG, "handleConfigMessage: Enable Local File Log: " + payload);
+ spg.getSharedPreference(SPType.logging_sp).edit().putBoolean("enable_local_file_log", parseBoolean(payload)).apply();
+ return;
+ }
+
+ // config logging content
+ if(topic.contains("/content/measurement_name")){
+ Log.d(TAG, "handleConfigMessage: Measurement Name: " + payload);
+ spg.getSharedPreference(SPType.logging_sp).edit().putString("measurement_name", payload).apply();
+ return;
+ }
+ if(topic.contains("/content/network_information")){
+ Log.d(TAG, "handleConfigMessage: Network Information: " + payload);
+ spg.getSharedPreference(SPType.logging_sp).edit().putBoolean("influx_network_data", parseBoolean(payload)).apply();
+ return;
+ }
+ if(topic.contains("/content/signal_information")){
+ Log.d(TAG, "handleConfigMessage: Signal Information: " + payload);
+ spg.getSharedPreference(SPType.logging_sp).edit().putBoolean("log_signal_data", parseBoolean(payload)).apply();
+ return;
+ }
+ if(topic.contains("/content/cell_information")){
+ Log.d(TAG, "handleConfigMessage: Cell Information: " + payload);
+ spg.getSharedPreference(SPType.logging_sp).edit().putBoolean("influx_cell_data", parseBoolean(payload)).apply();
+ return;
+ }
+ if(topic.contains("/content/neighbour_cells")){
+ Log.d(TAG, "handleConfigMessage: Neighbour Cells: " + payload);
+ spg.getSharedPreference(SPType.logging_sp).edit().putBoolean("log_neighbour_cells", parseBoolean(payload)).apply();
+ return;
+ }
+ if(topic.contains("/content/throughput_information")){
+ Log.d(TAG, "handleConfigMessage: Throughput Information: " + payload);
+ spg.getSharedPreference(SPType.logging_sp).edit().putBoolean("influx_throughput_data", parseBoolean(payload)).apply();
+ return;
+ }
+ if(topic.contains("/content/wifi_information")){
+ Log.d(TAG, "handleConfigMessage: Wifi Information: " + payload);
+ spg.getSharedPreference(SPType.logging_sp).edit().putBoolean("log_wifi_data", parseBoolean(payload)).apply();
+ return;
+ }
+ if(topic.contains("/content/battery_information")){
+ Log.d(TAG, "handleConfigMessage: Battery Information: " + payload);
+ spg.getSharedPreference(SPType.logging_sp).edit().putBoolean("influx_battery_data", parseBoolean(payload)).apply();
+ return;
+ }
+ if(topic.contains("/content/ip_information")){
+ Log.d(TAG, "handleConfigMessage: IP Information: " + payload);
+ spg.getSharedPreference(SPType.logging_sp).edit().putBoolean("influx_ip_address_data", parseBoolean(payload)).apply();
+ return;
+ }
+
+ if(topic.contains("/iperf3/command")){
+ Log.d(TAG, "handleConfigMessage: Iperf3 Command: " + payload);
+ iperf3Handler = new Iperf3Handler(context);
+ try {
+ iperf3Handler.parsePayload(payload);
+ } catch (Exception e) {
+ Log.e(TAG, "handleConfigMessage: Error parsing iperf3 payload: " + e.getMessage());
+ //TODO PUBLISH ERROR
+ }
+ return;
+ }
+ if(topic.contains("/iperf3/enable")){
+ Log.d(TAG, "handleConfigMessage: Enable Iperf3: " + payload);
+
+ if(iperf3Handler != null && parseBoolean(payload)){
+ iperf3Handler.preperareSequence(getApplicationContext());
+ //TODO PUBLISH iperf3 sequence enabled
+ } else if(iperf3Handler != null && !parseBoolean(payload)){
+ iperf3Handler.disableSequence(getApplicationContext());
+ //TODO PUBLISH iperf3 sequence disabled
+ }
+ return;
+ }
+
+ if(topic.contains("/ping/command")){
+ Log.d(TAG, "handleConfigMessage: Ping Command: " + payload);
+ pingHandler = new PingHandler();
+ try {
+ pingHandler.parsePayload(payload);
+ } catch (Exception e) {
+ Log.e(TAG, "handleConfigMessage: Error parsing ping payload: " + e.getMessage());
+ //TODO PUBLISH ERROR
+ }
+ return;
+ }
+
+ if(topic.contains("/ping/enable")){
+ Log.d(TAG, "handleConfigMessage: Enable Ping: " + payload);
+
+ if(pingHandler != null && parseBoolean(payload)){
+ pingHandler.preperareSequence(getApplicationContext());
+ //TODO PUBLISH ping sequence enabled
+ } else if(pingHandler != null && !parseBoolean(payload)){
+ pingHandler.disableSequence(getApplicationContext());
+ //TODO PUBLISH ping sequence disabled
+ }
+ return;
+ }
+
+ if(topic.contains("/sequence/enable")){
+ Log.d(TAG, "handleConfigMessage: Enable Sequence: " + payload);
+ setEnabled(parseBoolean(payload));
+ return;
+ }
+
+ Log.d(TAG, "handleConfigMessage: No matching topic found: " + topic);
+
+ return;
+ }
+
+ private void subsribetoTopic(String topic){
+ client.subscribeWith()
+ .topicFilter(topic)
+ .qos(MqttQos.AT_LEAST_ONCE)
+ .callback(publish -> {
+ if (!publish.getPayload().isPresent()){
+ Log.e(TAG, "Received empty payload from topic: " + publish.getTopic());
+ return;
+ };
+ Log.d(TAG, "Received message: " + publish.getTopic());
+ String payload = StandardCharsets.UTF_8.decode(publish.getPayload().get()).toString();
+ handleConfigMessage(publish.getTopic().toString(), payload);
+ })
+ .send()
+ .whenComplete((subAck, throwable) -> {
+ if(throwable != null){
+ Log.e(TAG, "Error subscribing to topic: " + topic + " Error: " + throwable.getMessage());
+ } else {
+ Log.i(TAG, "Subscribed to topic: " + topic);
+ }
+ });
+ }
+
+
+ private void subscribeToAllTopics(){
+ subsribetoTopic(String.format("device/%s/#", deviceName));
+ }
+
+
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ Log.d(TAG, "onStartCommand: Start MQTT service");
+ context = getApplicationContext();
+ mqttSP = SharedPreferencesGrouper.getInstance(context).getSharedPreference(SPType.mqtt_sp);
+ deviceName = SharedPreferencesGrouper.getInstance(context).getSharedPreference(SPType.default_sp).getString("device_name", "null").strip();
+ startForeground(3, builder.build());
+ setupSharedPreferences();
+ createClient();
+ connectClient();
+
+ subscribeToAllTopics();
+
+ return START_STICKY;
+ }
+
+ private void executeWork() {
+ new Runnable(){
+ @Override
+ public void run() {
+ if (iperf3Handler != null && isEnabled) {
+ iperf3Handler.enableSequence();
+ } else {
+ Log.d(TAG, "executeWork: Iperf3 Handler is either null or not enabled");
+ }
+ }
+ }.run();
+ new Runnable(){
+ @Override
+ public void run() {
+ if (pingHandler != null && isEnabled) {
+ pingHandler.enableSequence();
+ } else {
+ Log.d(TAG, "executeWork: Ping Handler is either null or not enabled");
+ }
+ }
+ }.run();
+
+ CustomEventListener listener = new CustomEventListener() {
+ @Override
+ public void onChange(HashMap workInfos) {
+ for (WorkInfo info : workInfos.values()) {
+ WorkInfo.State state = info.getState();
+ Log.d(TAG, "onChange: WorkInfo: " + info.getTags() + " State: " + state);
+ Data data = info.getOutputData();
+ Log.i(TAG, "onChange: "+data.toString());
+
+ publishToTopic("device/"+deviceName+"/campaign/status", String.valueOf(state.ordinal()), false);
+ }
+
+ }
+ };
+ //startWorkInfoChecker(RemoteWorkManager.getInstance(context), iperf3Handler.getExecutorWorkRequests(context), listener);
+ //TODO
+ }
+
+ private void startWorkInfoChecker(RemoteWorkManager remoteWorkManager, ArrayList workRequests, CustomEventListener listener) {
+ ArrayList workIdGroups = new ArrayList<>();
+ for (OneTimeWorkRequest workRequest : workRequests) {
+ workIdGroups.add(workRequest.getId());
+ }
+ RemoteWorkInfoChecker remoteWorkInfoChecker = new RemoteWorkInfoChecker(remoteWorkManager, workIdGroups);
+ remoteWorkInfoChecker.setListener(listener);
+ remoteWorkInfoChecker.start();
+ }
+
+ private void setEnabled(boolean isEnabled) {
+ this.isEnabled = isEnabled;
+ executeWork();
+ }
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/MainActivity.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/MainActivity.java
index e3d0fcec..6fc6a1bb 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/MainActivity.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/MainActivity.java
@@ -57,6 +57,7 @@
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.DataProvider.DataProvider;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.DataProvider.NetworkCallback;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.MQTT.MQTTService;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SPType;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SharedPreferencesGrouper;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.WorkProfile.WorkProfileActivity;
@@ -70,6 +71,7 @@ public class MainActivity extends AppCompatActivity implements PreferenceFragmen
public boolean cp = false;
public boolean feature_telephony = false;
Intent loggingServiceIntent;
+ Intent mqttServiceIntent;
Intent notificationServiceIntent;
NavController navController;
private Handler requestCellInfoUpdateHandler;
@@ -231,6 +233,24 @@ protected void onCreate(Bundle savedInstanceState) {
}
}, SPType.default_sp);
+ mqttServiceIntent = new Intent(this, MQTTService.class);
+ if (spg.getSharedPreference(SPType.mqtt_sp).getBoolean("enable_mqtt", false)) {
+ Log.d(TAG, "Start MQTT service");
+ context.startService(mqttServiceIntent);
+ }
+
+ spg.setListener((prefs, key) -> {
+ if (Objects.equals(key, "enable_mqtt")) {
+ if (prefs.getBoolean(key, false)) {
+ Log.d(TAG, "MQTT enabled");
+ context.startForegroundService(mqttServiceIntent);
+ } else {
+ Log.d(TAG, "MQTT disabled");
+ context.stopService(mqttServiceIntent);
+ }
+ }
+ }, SPType.mqtt_sp);
+
getAppSignature();
gv.setGit_hash(getString(R.string.git_hash));
}
@@ -493,6 +513,9 @@ public boolean onPreferenceStartFragment(@NonNull PreferenceFragmentCompat calle
case "shared_preferences_io":
navController.navigate(R.id.fragment_shared_preferences_io);
break;
+ case "mqtt_settings":
+ navController.navigate(R.id.mqttSettingsFragment);
+ break;
}
return true;
}
@@ -503,4 +526,4 @@ private void initHandlerAndHandlerThread() {
requestCellInfoUpdateHandler = new Handler(Objects.requireNonNull(requestCellInfoUpdateHandlerThread.getLooper()));
requestCellInfoUpdateHandler.post(requestCellInfoUpdate);
}
-}
+}
\ No newline at end of file
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Metric/Metric.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Metric/Metric.java
deleted file mode 100644
index 4c82f94f..00000000
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Metric/Metric.java
+++ /dev/null
@@ -1,240 +0,0 @@
-package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Metric;
-
-import android.content.Context;
-import android.graphics.Typeface;
-import android.graphics.drawable.GradientDrawable;
-import android.view.Gravity;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import java.util.ArrayList;
-import java.util.Locale;
-
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R;
-
-public class Metric {
- private LinearLayout mean;
- private LinearLayout median;
- private LinearLayout max;
- private LinearLayout min;
- private LinearLayout last;
- private TextView directionName;
- private ArrayList meanList = new ArrayList<>();
- private double maxValueSum = Double.MIN_VALUE;
- private double minValueSum = Double.MAX_VALUE;
- private final METRIC_TYPE metricType;
- private final Context ct;
- private LinearLayout mainLL;
-
- public Metric(METRIC_TYPE metricType, Context ct){
- this.metricType = metricType;
- this.ct = ct;
- }
-
- private LinearLayout createTile(String key) {
- LinearLayout ll = new LinearLayout(ct);
-
- GradientDrawable gd = new GradientDrawable();
- gd.setColor(ct.getColor(R.color.cardview_dark_background));
- gd.setCornerRadius(10);
- gd.setStroke(2, 0xFF000000);
- ll.setBackground(gd);
- ll.setMinimumHeight(ll.getWidth());
- ll.setGravity(Gravity.CENTER);
-
- ll.setOrientation(LinearLayout.VERTICAL);
- LinearLayout.LayoutParams foo = new LinearLayout.LayoutParams(200, 150);
- foo.weight = 1;
- foo.setMargins(10, 10, 10, 10);
- ll.setLayoutParams(foo);
- TextView keyView = new TextView(ct);
- keyView.setGravity(Gravity.CENTER);
- LinearLayout.LayoutParams keyViewLayoutParams = new LinearLayout.LayoutParams(200, 50);
- keyViewLayoutParams.setMargins(0, 0, 0, 10);
- keyView.setLayoutParams(keyViewLayoutParams);
- keyView.setTypeface(null, Typeface.BOLD);
-
- keyView.setText(key);
- ll.addView(keyView);
- TextView valueView = new TextView(ct);
- valueView.setGravity(Gravity.CENTER);
- LinearLayout.LayoutParams valueViewLayoutParams = new LinearLayout.LayoutParams(200, 50);
- valueViewLayoutParams.setMargins(0, 0, 0, 0);
- valueView.setLayoutParams(valueViewLayoutParams);
- ll.addView(valueView);
- return ll;
- }
-
- private LinearLayout createLL(String key) {
- LinearLayout ll = null;
- switch (key) {
- case "mean":
- mean = createTile(key);
- ll = mean;
- break;
- case "median":
- median = createTile(key);
- ll = median;
- break;
- case "max":
- max = createTile(key);
- ll = max;
- break;
- case "min":
- min = createTile(key);
- ll = min;
- break;
- case "last":
- last = createTile(key);
- ll = last;
- break;
- }
- return ll;
- }
- private String getFormatedString(double value){
- switch (this.metricType){
- case THROUGHPUT:
- return String.format(Locale.getDefault(), "%.2f", value/1e+6);
- case RTT:
- case PACKET_LOSS:
- case JITTER:
- case PING_RTT:
- case PING_PACKET_LOSS:
- return String.format(Locale.getDefault(), "%.2f", value);
- }
- return Double.toString(value);
- }
- public LinearLayout createMainLL(String direction) {
- mainLL = new LinearLayout(ct);
- LinearLayout.LayoutParams foo1 = new LinearLayout.LayoutParams(
- LinearLayout.LayoutParams.MATCH_PARENT,
- LinearLayout.LayoutParams.WRAP_CONTENT
- );
- mainLL.setOrientation(LinearLayout.VERTICAL);
- mainLL.setLayoutParams(foo1);
-
- directionName = new TextView(ct);
- directionName.setText(direction);
- mainLL.addView(directionName);
-
- LinearLayout cardViewResult = new LinearLayout(ct);
- LinearLayout.LayoutParams cardParams = new LinearLayout.LayoutParams(
- LinearLayout.LayoutParams.MATCH_PARENT,
- LinearLayout.LayoutParams.WRAP_CONTENT
- );
- cardViewResult.setOrientation(LinearLayout.HORIZONTAL);
- cardViewResult.setLayoutParams(cardParams);
-
- cardViewResult.addView(createLL("mean"));
- cardViewResult.addView(createLL("median"));
- cardViewResult.addView(createLL("max"));
- cardViewResult.addView(createLL("min"));
- cardViewResult.addView(createLL("last"));
- mainLL.addView(cardViewResult);
- return mainLL;
- }
-
- public double calcMean(){
- return meanList.stream().mapToDouble(a -> a).sum()/meanList.size();
- }
-
- public double calcMedian(){
- this.getMeanList().sort(Double::compareTo);
- return meanList.get(Math.round(meanList.size()/2));
- }
-
- public double calcMax(){
- return meanList.stream().mapToDouble(a -> a).max().getAsDouble();
- }
-
- public double calcMin(){
- return meanList.stream().mapToDouble(a -> a).min().getAsDouble();
- }
- public void update(Double value){
- this.meanList.add(value);
-
- ((TextView)mean.getChildAt(1)).setText(String.format(" %s", getFormatedString(calcMean())));
- ((TextView)median.getChildAt(1)).setText(String.format(" %s", getFormatedString(calcMedian())));
- ((TextView)max.getChildAt(1)).setText(String.format(" %s", getFormatedString(calcMax())));
- ((TextView)min.getChildAt(1)).setText(String.format(" %s", getFormatedString(calcMin())));
- ((TextView)last.getChildAt(1)).setText(String.format(" %s", getFormatedString(value)));
- }
-
- public ArrayList getMeanList() {
- return meanList;
- }
- public void setMaxValueSum(double maxValueSum) {
- this.maxValueSum = maxValueSum;
- }
- public void setMinValueSum(double minValueSum) {
- this.minValueSum = minValueSum;
- }
- public double getMaxValueSum() {
- return maxValueSum;
- }
- public double getMinValueSum() {
- return minValueSum;
- }
-
- public void setMeanList(ArrayList meanList) {
- this.meanList = meanList;
- }
-
- public LinearLayout getMean() {
- return mean;
- }
-
- public void setMean(LinearLayout mean) {
- this.mean = mean;
- }
-
- public LinearLayout getMedian() {
- return median;
- }
-
- public void setMedian(LinearLayout median) {
- this.median = median;
- }
-
- public LinearLayout getMax() {
- return max;
- }
-
- public void setMax(LinearLayout max) {
- this.max = max;
- }
-
- public LinearLayout getMin() {
- return min;
- }
-
- public void setMin(LinearLayout min) {
- this.min = min;
- }
-
- public LinearLayout getLast() {
- return last;
- }
-
- public void setLast(LinearLayout last) {
- this.last = last;
- }
-
-
- public TextView getDirectionName() {
- return directionName;
- }
-
- public void setDirectionName(TextView directionName) {
- this.directionName = directionName;
- }
-
- public void resetMetric(){
- meanList.clear();
- this.maxValueSum = Double.MIN_VALUE;
- this.minValueSum = Double.MAX_VALUE;
- }
- public void setVisibility(int visibility){
- mainLL.setVisibility(visibility);
- }
- }
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Metric/MetricCalculator.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Metric/MetricCalculator.java
new file mode 100644
index 00000000..e6f7ccbd
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Metric/MetricCalculator.java
@@ -0,0 +1,119 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Metric;
+
+import java.util.ArrayList;
+import java.util.Locale;
+
+public class MetricCalculator {
+ private ArrayList meanList = new ArrayList<>();
+ private double maxValueSum = Double.MIN_VALUE;
+ private double minValueSum = Double.MAX_VALUE;
+ private final METRIC_TYPE metricType;
+
+ private double median;
+ private double mean;
+ private double max;
+ private double min;
+ private double last;
+
+ public MetricCalculator(METRIC_TYPE metricType) {
+ this.metricType = metricType;
+ }
+
+ public METRIC_TYPE getMetricType() {
+ return metricType;
+ }
+
+ public double getMedian() {
+ return median;
+ }
+
+ public double getMean() {
+ return mean;
+ }
+
+ public double getMax() {
+ return max;
+ }
+
+ public double getMin() {
+ return min;
+ }
+
+ public double getLast() {
+ return last;
+ }
+
+ public void calcAll(){
+ if(meanList.isEmpty()){
+ return;
+ }
+ calcMin();
+ calcMax();
+ calcMedian();
+ calcMean();
+ }
+
+ private void calcMean() {
+ mean = meanList.stream().mapToDouble(a -> a).sum() / meanList.size();
+ }
+
+ private void calcMedian() {
+ this.meanList.sort(Double::compareTo);
+ median = meanList.get(Math.round(meanList.size() / 2));
+ }
+
+ private void calcMax() {
+ max = meanList.stream().mapToDouble(a -> a).max().getAsDouble();
+ }
+
+ private void calcMin() {
+ min = meanList.stream().mapToDouble(a -> a).min().getAsDouble();
+
+ }
+
+ public void update(Double value) {
+ this.meanList.add(value);
+ this.last = value;
+ }
+
+ public String getFormattedString(double value) {
+ switch (this.metricType) {
+ case THROUGHPUT:
+ return String.format(Locale.getDefault(), "%.2f", value / 1e+6);
+ case RTT:
+ case PACKET_LOSS:
+ case JITTER:
+ case PING_RTT:
+ case PING_PACKET_LOSS:
+ return String.format(Locale.getDefault(), "%.2f", value);
+ }
+ return Double.toString(value);
+ }
+
+ public ArrayList getMeanList() {
+ return meanList;
+ }
+
+ public void resetMetric() {
+ meanList.clear();
+ this.maxValueSum = Double.MIN_VALUE;
+ this.minValueSum = Double.MAX_VALUE;
+ }
+
+ public void setMaxValueSum(double maxValueSum) {
+ this.maxValueSum = maxValueSum;
+ }
+
+ public void setMinValueSum(double minValueSum) {
+ this.minValueSum = minValueSum;
+ }
+
+ public double getMaxValueSum() {
+ return maxValueSum;
+ }
+
+ public double getMinValueSum() {
+ return minValueSum;
+ }
+
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Metric/MetricView.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Metric/MetricView.java
new file mode 100644
index 00000000..5215de77
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Metric/MetricView.java
@@ -0,0 +1,169 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Metric;
+
+import static android.widget.LinearLayout.HORIZONTAL;
+import static android.widget.LinearLayout.VERTICAL;
+
+import android.content.Context;
+import android.graphics.Typeface;
+import android.graphics.drawable.GradientDrawable;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+import androidx.cardview.widget.CardView;
+
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R;
+
+public class MetricView extends CardView {
+
+ private LinearLayout mean;
+ private LinearLayout median;
+ private LinearLayout max;
+ private LinearLayout min;
+ private LinearLayout last;
+ private TextView directionName;
+ private MetricCalculator metricCalculator;
+
+ public MetricView(Context context) {
+ super(context);
+ init(context, null);
+ }
+ public MetricView(MetricCalculator metricCalculator, Context context) {
+ super(context);
+ init(context, null);
+ this.metricCalculator = metricCalculator;
+ }
+ public MetricView(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ init(context, attrs);
+ }
+
+ public MetricView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init(context, attrs);
+ }
+
+ private void init(Context context, @Nullable AttributeSet attrs) {
+ // You may want to customize view via XML attributes if needed.
+ }
+
+ public void setup(String title) {
+
+ removeAllViews();
+ LinearLayout cardView = new LinearLayout(getContext());
+ cardView.setOrientation(VERTICAL);
+
+ directionName = new TextView(getContext());
+ directionName.setText(title);
+ directionName.setTextAppearance(R.style.Base_TextAppearance_AppCompat_Light_Widget_PopupMenu_Large);
+ directionName.setTextColor(getContext().getColor(R.color.material_dynamic_secondary100));
+ cardView.addView(directionName);
+
+ LinearLayout cardViewResult = new LinearLayout(getContext());
+ cardViewResult.setOrientation(HORIZONTAL);
+ cardViewResult.setLayoutParams(new LayoutParams(
+ LayoutParams.MATCH_PARENT,
+ LayoutParams.WRAP_CONTENT
+ ));
+
+ mean = createTile("mean", 0, 10);
+ median = createTile("median", 10, 10);
+ max = createTile("max", 10, 10);
+ min = createTile("min", 10, 10);
+ last = createTile("last", 10, 0);
+
+ cardViewResult.addView(mean);
+ cardViewResult.addView(median);
+ cardViewResult.addView(max);
+ cardViewResult.addView(min);
+ cardViewResult.addView(last);
+
+ cardView.addView(cardViewResult);
+ addView(cardView);
+ LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
+ LayoutParams.MATCH_PARENT,
+ LayoutParams.WRAP_CONTENT
+ );
+ cardView.setPadding(20, 20, 20 ,20);
+
+
+ GradientDrawable gd = new GradientDrawable();
+ gd.setColor(getContext().getColor( R.color.material_dynamic_secondary30));
+ gd.setCornerRadius(10);
+// gd.setStroke(2, 0xFF000000);
+ this.setBackground(gd);
+
+ params.setMargins(20 , 10, 20, 10);
+ this.setLayoutParams(params);
+ }
+
+ private LinearLayout createTile(String key, int marginLeft, int marginRight) {
+ Context ct = getContext();
+ LinearLayout ll = new LinearLayout(ct);
+ ll.setOrientation(VERTICAL);
+ ll.setGravity(Gravity.CENTER);
+
+ GradientDrawable gd = new GradientDrawable();
+ gd.setColor(ct.getColor(R.color.material_dynamic_primary100));
+ gd.setCornerRadius(10);
+ gd.setStroke(2, 0xFF000000);
+ ll.setBackground(gd);
+
+ LinearLayout.LayoutParams tileParams = new LinearLayout.LayoutParams(200, 150);
+ tileParams.weight = 1;
+ tileParams.setMargins(marginLeft, 10, marginRight, 10);
+ ll.setLayoutParams(tileParams);
+
+ TextView keyView = new TextView(ct);
+ keyView.setGravity(Gravity.CENTER);
+ keyView.setText(key);
+ LinearLayout.LayoutParams keyViewParams = new LinearLayout.LayoutParams(200, 0);
+ keyViewParams.weight = 1;
+ keyViewParams.setMargins(0, 0, 0, 10);
+ keyView.setLayoutParams(keyViewParams);
+ keyView.setTypeface(null, Typeface.BOLD);
+ keyView.setTextAppearance(R.style.Base_TextAppearance_AppCompat_Medium);
+ keyView.setTextColor(ct.getColor(R.color.material_dynamic_primary10));
+ keyView.setGravity(Gravity.CENTER);
+
+
+ TextView valueView = new TextView(ct);
+ valueView.setGravity(Gravity.CENTER);
+ LinearLayout.LayoutParams valueViewParams = new LinearLayout.LayoutParams(200, 0);
+ valueViewParams.weight = 1;
+ valueView.setLayoutParams(valueViewParams);
+ valueView.setTextAppearance(R.style.TextAppearance_AppCompat_Small);
+ valueView.setTextColor(ct.getColor(R.color.material_dynamic_primary10));
+
+
+ ll.addView(keyView);
+ ll.addView(valueView);
+ return ll;
+ }
+
+ public void update(Double value) {
+ if (metricCalculator == null) return;
+
+ metricCalculator.update(value);
+ update();
+ }
+
+ public void update(){
+ metricCalculator.calcAll();
+ ((TextView) mean.getChildAt(1)).setText(metricCalculator.getFormattedString(metricCalculator.getMean()));
+ ((TextView) median.getChildAt(1)).setText(metricCalculator.getFormattedString(metricCalculator.getMedian()));
+ ((TextView) max.getChildAt(1)).setText(metricCalculator.getFormattedString(metricCalculator.getMax()));
+ ((TextView) min.getChildAt(1)).setText(metricCalculator.getFormattedString(metricCalculator.getMin()));
+ ((TextView) last.getChildAt(1)).setText(metricCalculator.getFormattedString(metricCalculator.getLast()));
+ }
+
+ public void setMetricCalculator(MetricCalculator metricCalculator) {
+ this.metricCalculator = metricCalculator;
+ }
+
+ public MetricCalculator getMetricCalculator() {
+ return metricCalculator;
+ }
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Parameter/Iperf3Parameter.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Parameter/Iperf3Parameter.java
new file mode 100644
index 00000000..aaef802e
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Parameter/Iperf3Parameter.java
@@ -0,0 +1,1810 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Parameter;
+
+import android.os.Environment;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+
+public class Iperf3Parameter extends Parameter {
+ public static final String rootPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath();
+ public static final String rawDirPath = rootPath+"/omnt/iperf3/raw/";
+ public static final String lineProtocolDirPath = rootPath+"/omnt/iperf3/lineprotocol/";
+ public static final String HOST = "host";
+ public static final String PORT = "port";
+ public static final String BITRATE = "bitrate";
+ public static final String INTERVAL = "interval";
+ public static final String BYTES = "bytes";
+ public static final String STREAMS = "streams";
+ public static final String DIRECTION = "direction";
+ public static final String ONEOFF = "oneOff";
+ public static final String CPORT = "cport";
+ public static final String TESTUUID = "testUUID";
+ public static final String USERNAME = "username";
+ public static final String RSAPUBLICKEYPATH = "rsaPublicKeyPath";
+ public static final String EXTRADATA = "extraData";
+ public static final String TITLE = "title";
+ public static final String OMIT = "omit";
+ public static final String ZEROCOPY = "zerocopy";
+ public static final String FLOWLABEL = "flowlabel";
+ public static final String DSCP = "dscp";
+ public static final String TOS = "tos";
+ public static final String VERSION6 = "version6";
+ public static final String VERSION4 = "version4";
+ public static final String NODELAY = "noDelay";
+ public static final String SETMSS = "setMss";
+ public static final String CONGESTION = "congestion";
+ public static final String WINDOW = "window";
+ public static final String PARALLEL = "parallel";
+ public static final String BLOCKCOUNT = "blockcount";
+ public static final String TIME = "time";
+ public static final String FQRATE = "fqRate";
+ public static final String PACINGTIMER = "pacingTimer";
+ public static final String CONNECTTIMEOUT = "connectTimeout";
+ public static final String UDP = "udp";
+ public static final String XBIND = "xbind";
+ public static final String SCTP = "sctp";
+ public static final String USEPKCS1PADDING = "usePkcs1Padding";
+ public static final String TIMESKEWTHRESHOLD = "timeSkewThreshold";
+ public static final String AUTHORIZEDUSERSPATH = "authorizedUsersPath";
+ public static final String RSAPRIVATEKEYPATH = "rsaPrivateKeyPath";
+ public static final String IDLETIMEOUT = "idleTimeout";
+ public static final String SERVERBITRATELIMIT = "serverBitrateLimit";
+
+ public static final String SERVER = "server";
+ public static final String CLIENT = "client";
+ public static final String DAEMON = "daemon";
+ public static final String HELP = "help";
+ public static final String VERSION = "version";
+ public static final String DEBUG = "debug";
+ public static final String SNDTIMEOUT = "sndTimeout";
+ public static final String RCVTIMEOUT = "rcvTimeout";
+ public static final String TIMESTAMPS = "timestamps";
+ public static final String FORCEFLUSH = "forceflush";
+ public static final String LOGFILE = "logfile";
+
+ public static final String JSON = "json";
+ public static final String VERBOSE = "verbose";
+ public static final String BINDDEV = "bindDev";
+ public static final String BIND = "bind";
+ public static final String AFFINITY = "affinity";
+ public static final String FILE = "file";
+ public static final String MODE = "mode";
+ public static final String PROTOCOL = "protocol";
+ public static final String IPERF3UUID = "iperf3UUID";
+
+ private static final String TAG = "Iperf3Parameter";
+
+
+ protected Iperf3Parameter(Parcel in) {
+ super(in);
+ host = in.readString();
+ iPerf3UUID = in.readString();
+ port = in.readInt();
+ interval = in.readDouble();
+ bitrate = in.readString();
+ length = in.readInt();
+ pidfile = in.readString();
+ file = in.readString();
+ affinity = in.readString();
+ bind = in.readString();
+ bindDev = in.readString();
+ byte tmpVerbose = in.readByte();
+ verbose = tmpVerbose == 0 ? null : tmpVerbose == 1;
+ byte tmpJson = in.readByte();
+ json = tmpJson == 0 ? null : tmpJson == 1;
+ byte tmpJsonStream = in.readByte();
+ jsonStream = tmpJsonStream == 0 ? null : tmpJsonStream == 1;
+ byte tmpForceflush = in.readByte();
+ forceflush = tmpForceflush == 0 ? null : tmpForceflush == 1;
+ timestamps = in.readString();
+ if (in.readByte() == 0) {
+ rcvTimeout = null;
+ } else {
+ rcvTimeout = in.readInt();
+ }
+ if (in.readByte() == 0) {
+ sndTimeout = null;
+ } else {
+ sndTimeout = in.readInt();
+ }
+ if (in.readByte() == 0) {
+ debug = null;
+ } else {
+ debug = in.readInt();
+ }
+ byte tmpVersion = in.readByte();
+ version = tmpVersion == 0 ? null : tmpVersion == 1;
+ byte tmpHelp = in.readByte();
+ help = tmpHelp == 0 ? null : tmpHelp == 1;
+ byte tmpDaemon = in.readByte();
+ daemon = tmpDaemon == 0 ? null : tmpDaemon == 1;
+ byte tmpOneOff = in.readByte();
+ oneOff = tmpOneOff == 0 ? null : tmpOneOff == 1;
+ serverBitrateLimit = in.readString();
+ if (in.readByte() == 0) {
+ idleTimeout = null;
+ } else {
+ idleTimeout = in.readInt();
+ }
+ rsaPrivateKeyPath = in.readString();
+ authorizedUsersPath = in.readString();
+ if (in.readByte() == 0) {
+ timeSkewThreshold = null;
+ } else {
+ timeSkewThreshold = in.readInt();
+ }
+ byte tmpUsePkcs1Padding = in.readByte();
+ usePkcs1Padding = tmpUsePkcs1Padding == 0 ? null : tmpUsePkcs1Padding == 1;
+ byte tmpSctp = in.readByte();
+ sctp = tmpSctp == 0 ? null : tmpSctp == 1;
+ xbind = in.readString();
+ if (in.readByte() == 0) {
+ nstreams = null;
+ } else {
+ nstreams = in.readInt();
+ }
+ if (in.readByte() == 0) {
+ connectTimeout = null;
+ } else {
+ connectTimeout = in.readInt();
+ }
+ pacingTimer = in.readString();
+ fqRate = in.readString();
+ if (in.readByte() == 0) {
+ time = null;
+ } else {
+ time = in.readInt();
+ }
+ bytes = in.readString();
+ blockcount = in.readString();
+ if (in.readByte() == 0) {
+ cport = null;
+ } else {
+ cport = in.readInt();
+ }
+ if (in.readByte() == 0) {
+ parallel = null;
+ } else {
+ parallel = in.readInt();
+ }
+ byte tmpReverse = in.readByte();
+ reverse = tmpReverse == 0 ? null : tmpReverse == 1;
+ byte tmpBidir = in.readByte();
+ bidir = tmpBidir == 0 ? null : tmpBidir == 1;
+ window = in.readString();
+ congestion = in.readString();
+ if (in.readByte() == 0) {
+ setMss = null;
+ } else {
+ setMss = in.readInt();
+ }
+ byte tmpNoDelay = in.readByte();
+ noDelay = tmpNoDelay == 0 ? null : tmpNoDelay == 1;
+ byte tmpVersion4 = in.readByte();
+ version4 = tmpVersion4 == 0 ? null : tmpVersion4 == 1;
+ byte tmpVersion6 = in.readByte();
+ version6 = tmpVersion6 == 0 ? null : tmpVersion6 == 1;
+ if (in.readByte() == 0) {
+ tos = null;
+ } else {
+ tos = in.readInt();
+ }
+ dscp = in.readString();
+ if (in.readByte() == 0) {
+ flowlabel = null;
+ } else {
+ flowlabel = in.readInt();
+ }
+ byte tmpZerocopy = in.readByte();
+ zerocopy = tmpZerocopy == 0 ? null : tmpZerocopy == 1;
+ if (in.readByte() == 0) {
+ omit = null;
+ } else {
+ omit = in.readInt();
+ }
+ title = in.readString();
+ extraData = in.readString();
+ byte tmpGetServerOutput = in.readByte();
+ getServerOutput = tmpGetServerOutput == 0 ? null : tmpGetServerOutput == 1;
+ byte tmpUdpCounters64bit = in.readByte();
+ udpCounters64bit = tmpUdpCounters64bit == 0 ? null : tmpUdpCounters64bit == 1;
+ byte tmpRepeatingPayload = in.readByte();
+ repeatingPayload = tmpRepeatingPayload == 0 ? null : tmpRepeatingPayload == 1;
+ byte tmpDontFragment = in.readByte();
+ dontFragment = tmpDontFragment == 0 ? null : tmpDontFragment == 1;
+ username = in.readString();
+ rsaPublicKeyPath = in.readString();
+ }
+
+ public static final Creator CREATOR = new Creator() {
+ @Override
+ public Iperf3Parameter createFromParcel(Parcel in) {
+ return new Iperf3Parameter(in);
+ }
+
+ @Override
+ public Iperf3Parameter[] newArray(int size) {
+ return new Iperf3Parameter[size];
+ }
+ };
+
+ public Iperf3Parameter(String ip,
+ int port,
+ String bitrate,
+ int duration,
+ double interval,
+ String bytes,
+ int streams,
+ int cport,
+ String testUUID,
+ Iperf3Mode mode,
+ Iperf3Protocol protocol,
+ Iperf3Direction direction
+ ) {
+
+ super(rawDirPath+testUUID+".txt", lineProtocolDirPath+testUUID+".txt");
+ this.testUUID = testUUID;
+ this.host = ip;
+ this.port = port;
+ this.bitrate = bitrate;
+ this.time = duration;
+ this.interval = interval;
+ this.bytes = bytes;
+ this.nstreams = streams;
+ this.cport = cport;
+ this.mode = mode;
+ this.direction = direction;
+ this.protocol = protocol;
+
+ }
+
+ public Iperf3Parameter(String iPerf3UUID){
+ super(rawDirPath+iPerf3UUID+".txt", lineProtocolDirPath+iPerf3UUID+".txt");
+ }
+ public Iperf3Parameter(String ip,
+ String iPerf3UUID,
+ Iperf3Protocol protocol,
+ int port,
+ double interval,
+ String bitrate,
+ int length,
+ Iperf3Mode mode,
+ Iperf3Direction direction,
+ String pidfile,
+ String file,
+ String affinity,
+ String bind,
+ String bindDev,
+ Boolean verbose,
+ Boolean json,
+ Boolean jsonStream,
+ String logfile,
+ Boolean forceflush,
+ String timestamps,
+ Integer rcvTimeout,
+ Integer sndTimeout,
+ Integer debug,
+ Boolean version,
+ Boolean help,
+ Boolean daemon,
+ Boolean oneOff,
+ String serverBitrateLimit,
+ Integer idleTimeout,
+ String rsaPrivateKeyPath,
+ String authorizedUsersPath,
+ Integer timeSkewThreshold,
+ Boolean usePkcs1Padding,
+ Boolean sctp,
+ String xbind,
+ Integer nstreams,
+ Integer connectTimeout,
+ String pacingTimer,
+ String fqRate,
+ Integer time,
+ String bytes,
+ String blockcount,
+ Integer cport,
+ Integer parallel,
+ Boolean reverse,
+ Boolean bidir,
+ String window,
+ String congestion,
+ Integer setMss,
+ Boolean noDelay,
+ Boolean version4,
+ Boolean version6,
+ Integer tos,
+ String dscp,
+ Integer flowlabel,
+ Boolean zerocopy,
+ Integer omit,
+ String title,
+ String extraData,
+ Boolean getServerOutput,
+ Boolean udpCounters64bit,
+ Boolean repeatingPayload,
+ Boolean dontFragment,
+ String username,
+ String rsaPublicKeyPath) {
+ super(rawDirPath+iPerf3UUID+".txt", lineProtocolDirPath+iPerf3UUID+".txt");
+ this.host = ip;
+ this.iPerf3UUID = iPerf3UUID;
+ this.protocol = protocol;
+ this.port = port;
+ this.interval = interval;
+ this.bitrate = bitrate;
+ this.length = length;
+ this.mode = mode;
+ this.direction = direction;
+ this.pidfile = pidfile;
+ this.file = file;
+ this.affinity = affinity;
+ this.bind = bind;
+ this.bindDev = bindDev;
+ this.verbose = verbose;
+ this.json = json;
+ this.jsonStream = jsonStream;
+ this.forceflush = forceflush;
+ this.timestamps = timestamps;
+ this.rcvTimeout = rcvTimeout;
+ this.sndTimeout = sndTimeout;
+ this.debug = debug;
+ this.version = version;
+ this.help = help;
+ this.daemon = daemon;
+ this.oneOff = oneOff;
+ this.serverBitrateLimit = serverBitrateLimit;
+ this.idleTimeout = idleTimeout;
+ this.rsaPrivateKeyPath = rsaPrivateKeyPath;
+ this.authorizedUsersPath = authorizedUsersPath;
+ this.timeSkewThreshold = timeSkewThreshold;
+ this.usePkcs1Padding = usePkcs1Padding;
+ this.sctp = sctp;
+ this.xbind = xbind;
+ this.nstreams = nstreams;
+ this.connectTimeout = connectTimeout;
+ this.pacingTimer = pacingTimer;
+ this.fqRate = fqRate;
+ this.time = time;
+ this.bytes = bytes;
+ this.blockcount = blockcount;
+ this.cport = cport;
+ this.parallel = parallel;
+ this.reverse = reverse;
+ this.bidir = bidir;
+ this.window = window;
+ this.congestion = congestion;
+ this.setMss = setMss;
+ this.noDelay = noDelay;
+ this.version4 = version4;
+ this.version6 = version6;
+ this.tos = tos;
+ this.dscp = dscp;
+ this.flowlabel = flowlabel;
+ this.zerocopy = zerocopy;
+ this.omit = omit;
+ this.title = title;
+ this.extraData = extraData;
+ this.getServerOutput = getServerOutput;
+ this.udpCounters64bit = udpCounters64bit;
+ this.repeatingPayload = repeatingPayload;
+ this.dontFragment = dontFragment;
+ this.username = username;
+ this.rsaPublicKeyPath = rsaPublicKeyPath;
+ }
+
+ public void updatePaths(){
+ super.setLogfile(rawDirPath+testUUID+".txt");
+ super.setLineProtocolFile(lineProtocolDirPath+testUUID+".txt");
+ }
+ public Iperf3Parameter(JSONObject jsonObject, String testUUID) {
+ super(rawDirPath+testUUID+".txt", lineProtocolDirPath+testUUID+".txt");
+
+ this.testUUID = testUUID;
+ this.jsonStream = true;
+
+ try {
+ this.host = jsonObject.getString(HOST);
+ } catch (JSONException e) {
+ return;
+ }
+ try {
+ this.iPerf3UUID = jsonObject.getString(IPERF3UUID);
+ } catch (JSONException e) {
+ throw new IllegalArgumentException("Iperf3Parameter: iPerf3UUID is required.");
+ }
+ try {
+ this.port = jsonObject.getInt(PORT);
+ } catch (JSONException e) {
+ Log.d(TAG, "port is not set. Defaulting to iPerf3 default Port.");
+ }
+ try {
+ this.bitrate = jsonObject.getString(BITRATE);
+ } catch (JSONException e) {
+ Log.d(TAG, "bitrate is not set. Defaulting to iPerf3 default bitrate.");
+ }
+ try {
+ this.time = jsonObject.getInt(TIME);
+ Log.d(TAG, "Iperf3Parameter: time: "+time);
+ } catch (JSONException e) {
+ Log.d(TAG, "time is not set. Defaulting to iPerf3 default time.");
+ }
+
+ try {
+ this.interval = jsonObject.getDouble(INTERVAL);
+ } catch (JSONException e) {
+ Log.d(TAG, "interval is not set. Defaulting to iPerf3 default interval.");
+ }
+ try {
+ this.length = jsonObject.getInt(BYTES);
+ } catch (JSONException e) {
+ Log.d(TAG, "Length not set.");
+ }
+ try {
+ this.nstreams = jsonObject.getInt(STREAMS);
+ } catch (JSONException e) {
+ Log.d(TAG, "nstreams not set.");
+ }
+ try {
+ String direction = jsonObject.getString(DIRECTION);
+ Log.d(TAG, "Iperf3Parameter: direction: "+direction);
+ this.direction = Iperf3Direction.valueOf(direction.toUpperCase().trim());
+ } catch (JSONException e) {
+ this.direction = Iperf3Direction.UP;
+ Log.d(TAG, "direction not set.");
+ }
+ try {
+ this.oneOff = jsonObject.getBoolean(ONEOFF);
+ } catch (JSONException e) {
+ Log.d(TAG, "oneOff not set.");
+ }
+ try {
+ this.protocol = Iperf3Protocol.valueOf(jsonObject.getString(PROTOCOL).toUpperCase().trim());
+ } catch (JSONException | IllegalArgumentException e) {
+ Log.d(TAG, "protocol not set."+e.getMessage());
+ Log.e(TAG, "Iperf3Parameter: No matching Protocol found! Using TCP as default.");
+ this.protocol = Iperf3Protocol.TCP;
+ }
+ try {
+ boolean isServer = false, isClient = false;
+ try {
+ // check if server
+ isServer = jsonObject.getBoolean(SERVER);
+ } catch (JSONException e) {
+ Log.d(TAG, "mode not set.");
+ }
+ try {
+ //check if client
+ jsonObject.getString(HOST);
+ isClient = true;
+ } catch (JSONException e) {
+ isClient = false;
+ Log.d(TAG, "mode not set.");
+ }
+ // check if both are set
+ if(isServer && isClient){
+ throw new IllegalArgumentException("Iperf3Parameter: Server and Client mode cannot be set at the same time.");
+ }
+ // check if none is set
+ if(isServer){
+ this.mode = Iperf3Mode.SERVER;
+ } else if(isClient){
+ this.mode = Iperf3Mode.CLIENT;
+ } else {
+ throw new IllegalArgumentException("Iperf3Parameter: Server or Client mode must be set.");
+ }
+ } catch (IllegalArgumentException e) {
+ Log.d(TAG, "mode not set.");
+ Log.e(TAG, e.getMessage());
+ }
+ try {
+ this.cport = jsonObject.getInt(CPORT);
+ } catch (JSONException e) {
+ Log.d(TAG, "cport not set.");
+ }
+
+ try{
+ this.username = jsonObject.getString(USERNAME);
+ } catch (JSONException e) {
+ Log.d(TAG, "username not set.");
+ }
+ try{
+ this.rsaPublicKeyPath = jsonObject.getString(RSAPUBLICKEYPATH);
+ } catch (JSONException e) {
+ Log.d(TAG, "rsaPublicKeyPath not set.");
+ }
+ try{
+ this.extraData = jsonObject.getString(EXTRADATA);
+ } catch (JSONException e) {
+ Log.d(TAG, "extraData not set.");
+ }
+ try{
+ this.title = jsonObject.getString(TITLE);
+ } catch (JSONException e) {
+ Log.d(TAG, "title not set.");
+ }
+ try{
+ this.omit = jsonObject.getInt(OMIT);
+ } catch (JSONException e) {
+ Log.d(TAG, "omit not set.");
+ }
+ try{
+ this.zerocopy = jsonObject.getBoolean(ZEROCOPY);
+ } catch (JSONException e) {
+ Log.d(TAG, "zerocopy not set.");
+ }
+ try{
+ this.flowlabel = jsonObject.getInt(FLOWLABEL);
+ } catch (JSONException e) {
+ Log.d(TAG, "flowlabel not set.");
+ }
+ try{
+ this.dscp = jsonObject.getString(DSCP);
+ } catch (JSONException e) {
+ Log.d(TAG, "dscp not set.");
+ }
+ try{
+ this.tos = jsonObject.getInt(TOS);
+ } catch (JSONException e) {
+ Log.d(TAG, "tos not set.");
+ }
+ try{
+ this.version6 = jsonObject.getBoolean(VERSION6);
+ } catch (JSONException e) {
+ Log.d(TAG, "version6 not set.");
+ }
+ try{
+ this.version4 = jsonObject.getBoolean(VERSION4);
+ } catch (JSONException e) {
+ Log.d(TAG, "version4 not set.");
+ }
+ try{
+ this.noDelay = jsonObject.getBoolean(NODELAY);
+ } catch (JSONException e) {
+ Log.d(TAG, "noDelay not set.");
+ }
+ try{
+ this.setMss = jsonObject.getInt(SETMSS);
+ } catch (JSONException e) {
+ Log.d(TAG, "setMss not set.");
+ }
+ try{
+ this.congestion = jsonObject.getString(CONGESTION);
+ } catch (JSONException e) {
+ Log.d(TAG, "congestion not set.");
+ }
+ try{
+ this.window = jsonObject.getString(WINDOW);
+ } catch (JSONException e) {
+ Log.d(TAG, "window not set.");
+ }
+
+ try{
+ this.parallel = jsonObject.getInt(PARALLEL);
+ } catch (JSONException e) {
+ Log.d(TAG, "parallel not set.");
+ }
+ try{
+ this.blockcount = jsonObject.getString(BLOCKCOUNT);
+ } catch (JSONException e) {
+ Log.d(TAG, "blockcount not set.");
+ }
+ try{
+ this.bytes = jsonObject.getString(BYTES);
+ } catch (JSONException e) {
+ Log.d(TAG, "bytes not set.");
+ }
+ try{
+ this.fqRate = jsonObject.getString(FQRATE);
+ } catch (JSONException e) {
+ Log.d(TAG, "fqRate not set.");
+ }
+ try{
+ this.pacingTimer = jsonObject.getString(PACINGTIMER);
+ } catch (JSONException e) {
+ Log.d(TAG, "pacingTimer not set.");
+ }
+ try{
+ this.connectTimeout = jsonObject.getInt(CONNECTTIMEOUT);
+ } catch (JSONException e) {
+ Log.d(TAG, "connectTimeout not set.");
+ }
+ try{
+ this.xbind = jsonObject.getString(XBIND);
+ } catch (JSONException e) {
+ Log.d(TAG, "xbind not set.");
+ }
+ try{
+ this.sctp = jsonObject.getBoolean(SCTP);
+ } catch (JSONException e) {
+ Log.d(TAG, "sctp not set.");
+ }
+ try{
+ this.usePkcs1Padding = jsonObject.getBoolean(USEPKCS1PADDING);
+ } catch (JSONException e) {
+ Log.d(TAG, "usePkcs1Padding not set.");
+ }
+ try{
+ this.timeSkewThreshold = jsonObject.getInt(TIMESKEWTHRESHOLD);
+ } catch (JSONException e) {
+ Log.d(TAG, "timeSkewThreshold not set.");
+ }
+ try{
+ this.authorizedUsersPath = jsonObject.getString(AUTHORIZEDUSERSPATH);
+ } catch (JSONException e) {
+ Log.d(TAG, "authorizedUsersPath not set.");
+ }
+ try{
+ this.rsaPrivateKeyPath = jsonObject.getString(RSAPRIVATEKEYPATH);
+ } catch (JSONException e) {
+ Log.d(TAG, "rsaPrivateKeyPath not set.");
+ }
+ try{
+ this.idleTimeout = jsonObject.getInt(IDLETIMEOUT);
+ } catch (JSONException e) {
+ Log.d(TAG, "idleTimeout not set.");
+ }
+ try{
+ this.serverBitrateLimit = jsonObject.getString(SERVERBITRATELIMIT);
+ } catch (JSONException e) {
+ Log.d(TAG, "serverBitrateLimit not set.");
+ }
+ try{
+ this.oneOff = jsonObject.getBoolean(ONEOFF);
+ } catch (JSONException e) {
+ Log.d(TAG, "oneOff not set.");
+ }
+ try{
+ this.daemon = jsonObject.getBoolean(DAEMON);
+ } catch (JSONException e) {
+ Log.d(TAG, "daemon not set.");
+ }
+ try{
+ this.help = jsonObject.getBoolean(HELP);
+ } catch (JSONException e) {
+ Log.d(TAG, "help not set.");
+ }
+ try{
+ this.version = jsonObject.getBoolean(VERSION);
+ } catch (JSONException e) {
+ Log.d(TAG, "version not set.");
+ }
+ try{
+ this.debug = jsonObject.getInt(DEBUG);
+ } catch (JSONException e) {
+ Log.d(TAG, "debug not set.");
+ }
+ try{
+ this.sndTimeout = jsonObject.getInt(SNDTIMEOUT);
+ } catch (JSONException e) {
+ Log.d(TAG, "sndTimeout not set.");
+ }
+ try{
+ this.rcvTimeout = jsonObject.getInt(RCVTIMEOUT);
+ } catch (JSONException e) {
+ Log.d(TAG, "rcvTimeout not set.");
+ }
+ try{
+ this.timestamps = jsonObject.getString(TIMESTAMPS);
+ } catch (JSONException e) {
+ Log.d(TAG, "timestamps not set.");
+ }
+ try{
+ this.forceflush = jsonObject.getBoolean(FORCEFLUSH);
+ } catch (JSONException e) {
+ Log.d(TAG, "forceflush not set.");
+ }
+
+ try{
+ this.verbose = jsonObject.getBoolean(VERBOSE);
+ } catch (JSONException e) {
+ Log.d(TAG, "verbose not set.");
+ }
+ try{
+ this.bindDev = jsonObject.getString(BINDDEV);
+ } catch (JSONException e) {
+ Log.d(TAG, "bindDev not set.");
+ }
+ try{
+ this.affinity = jsonObject.getString(AFFINITY);
+ } catch (JSONException e) {
+ Log.d(TAG, "affinity not set.");
+ }
+ try{
+ this.file = jsonObject.getString(FILE);
+ } catch (JSONException e) {
+ Log.d(TAG, "file not set.");
+ }
+ try {
+ String mode = jsonObject.getString(MODE);
+ Log.d(TAG, "Iperf3Parameter: mode: "+mode);
+ this.mode = Iperf3Mode.valueOf(mode.toUpperCase().trim());
+ } catch (JSONException e) {
+ Log.d(TAG, "mode not set.");
+ Log.i(TAG, "Iperf3Parameter: No mode set. Defaulting to Client.");
+ this.mode = Iperf3Mode.CLIENT;
+ }
+ try{
+ this.bind = jsonObject.getString(BIND);
+ } catch (JSONException e) {
+ Log.d(TAG, "bind not set.");
+ }
+ try{
+ this.title = jsonObject.getString(TITLE);
+ } catch (JSONException e) {
+ Log.d(TAG, "title not set.");
+ }
+ try {
+ Files.createDirectories(Paths.get(rawDirPath));
+ Files.createDirectories(Paths.get(lineProtocolDirPath));
+ } catch (IOException e) {
+ Log.d(TAG, "Could not create directories.");
+ }
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeString(host);
+ dest.writeString(iPerf3UUID);
+ dest.writeInt(port);
+ dest.writeDouble(interval);
+ dest.writeString(bitrate);
+ dest.writeInt(length);
+ dest.writeString(mode.name());
+ dest.writeString(direction.name());
+ dest.writeString(pidfile);
+ dest.writeString(file);
+ dest.writeString(affinity);
+ dest.writeString(bind);
+ dest.writeString(bindDev);
+ dest.writeBoolean(verbose);
+ dest.writeBoolean(json);
+ dest.writeBoolean(jsonStream);
+ dest.writeBoolean(forceflush);
+ dest.writeString(timestamps);
+ dest.writeInt(rcvTimeout);
+ dest.writeInt(sndTimeout);
+ dest.writeInt(debug);
+ dest.writeBoolean(version);
+ dest.writeBoolean(help);
+ dest.writeBoolean(daemon);
+ dest.writeBoolean(oneOff);
+ dest.writeString(serverBitrateLimit);
+ dest.writeInt(idleTimeout);
+ dest.writeString(rsaPrivateKeyPath);
+ dest.writeString(authorizedUsersPath);
+ dest.writeInt(timeSkewThreshold);
+ dest.writeBoolean(usePkcs1Padding);
+ dest.writeBoolean(sctp);
+ dest.writeString(xbind);
+ dest.writeInt(nstreams);
+ dest.writeInt(connectTimeout);
+ dest.writeString(pacingTimer);
+ dest.writeString(fqRate);
+ dest.writeInt(time);
+ dest.writeString(bytes);
+ dest.writeString(blockcount);
+ dest.writeInt(cport);
+ dest.writeInt(parallel);
+ dest.writeBoolean(reverse);
+ dest.writeBoolean(bidir);
+ dest.writeString(window);
+ dest.writeString(congestion);
+ dest.writeInt(setMss);
+ dest.writeBoolean(noDelay);
+ dest.writeBoolean(version4);
+ dest.writeBoolean(version6);
+ dest.writeInt(tos);
+ dest.writeString(dscp);
+ dest.writeInt(flowlabel);
+ dest.writeBoolean(zerocopy);
+ dest.writeInt(omit);
+ dest.writeString(title);
+ dest.writeString(extraData);
+ dest.writeBoolean(getServerOutput);
+ dest.writeBoolean(udpCounters64bit);
+ dest.writeBoolean(repeatingPayload);
+ dest.writeBoolean(dontFragment);
+ dest.writeString(username);
+ dest.writeString(rsaPublicKeyPath);
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setHost(String s) {
+ this.host = s;
+ }
+
+ public void setBandwidth(String s) {
+ this.bitrate = s ;
+ }
+
+
+ // --- Enums ---
+ public enum Iperf3Mode {
+ CLIENT,
+ SERVER,
+ UNDEFINED;
+ public String toPrettyPrint() {
+ return this.name().substring(0, 1).toUpperCase() + this.name().toLowerCase().substring(1);
+ }
+ }
+
+ public enum Iperf3Protocol {
+ TCP,
+ UDP,
+ UNDEFINED;
+ }
+
+ public enum Iperf3Direction {
+ UP,
+ DOWN,
+ BIDIR,
+ UNDEFINED;
+ public String toPrettyPrint() {
+ return this.name().toLowerCase();
+ }
+ }
+
+ // --- Fields ---
+ // Required field.
+ private String host;
+ private String iPerf3UUID;
+ private String testUUID;
+ // Optional fields with defaults based on iperf3.
+ private Iperf3Protocol protocol = Iperf3Protocol.TCP; // Default protocol: TCP.
+ private int port = 5201; // Default port: 5201.
+ private double interval = 1.0; // Default interval: 1.0 second.
+ // For UDP mode: if not set, default bitrate is "1M".
+ private String bitrate;
+ // For TCP mode: if not set, default buffer length is 131072 (128 KB).
+ private int length;
+
+ // Mode selection fields.
+ // The mode field indicates whether the test is run in CLIENT or SERVER mode.
+ // When mode is CLIENT, the client field (host) must be provided.
+ private Iperf3Mode mode = Iperf3Mode.UNDEFINED;
+
+
+ private Iperf3Direction direction = Iperf3Direction.UNDEFINED;
+
+ // Additional optional parameters.
+ private String pidfile;
+ private String file;
+ private String affinity;
+ private String bind;
+ private String bindDev;
+ private Boolean verbose;
+ private Boolean json;
+ private Boolean jsonStream = true;
+ private Boolean forceflush;
+ private String timestamps;
+ private Integer rcvTimeout;
+ private Integer sndTimeout;
+ private Integer debug;
+ private Boolean version;
+ private Boolean help;
+ private Boolean daemon;
+ private Boolean oneOff;
+ private String serverBitrateLimit;
+ private Integer idleTimeout;
+ private String rsaPrivateKeyPath;
+ private String authorizedUsersPath;
+ private Integer timeSkewThreshold;
+ private Boolean usePkcs1Padding;
+ private Boolean sctp;
+ private String xbind;
+ private Integer nstreams;
+
+ private Integer connectTimeout;
+ private String pacingTimer;
+ private String fqRate;
+ private Integer time = 10;
+ private String bytes;
+ private String blockcount;
+ private Integer cport;
+ private Integer parallel;
+ private Boolean reverse;
+ private Boolean bidir;
+ private String window;
+ private String congestion;
+ private Integer setMss;
+ private Boolean noDelay;
+ private Boolean version4;
+ private Boolean version6;
+ private Integer tos;
+ private String dscp;
+ private Integer flowlabel;
+ private Boolean zerocopy;
+ private Integer omit;
+ private String title;
+ private String extraData;
+ private Boolean getServerOutput;
+ private Boolean udpCounters64bit;
+ private Boolean repeatingPayload;
+ private Boolean dontFragment;
+ private String username;
+ private String rsaPublicKeyPath;
+
+
+ // --- Getters and Setters ---
+
+ public String getiPerf3UUID() {
+ return iPerf3UUID;
+ }
+
+ public void setiPerf3UUID(String iPerf3UUID) {
+ this.iPerf3UUID = iPerf3UUID;
+ }
+
+ public Iperf3Protocol getProtocol() {
+ return protocol;
+ }
+
+ /**
+ * Set the protocol. If the input is not null, the protocol is set accordingly.
+ * Otherwise, it defaults to TCP.
+ */
+ public void setProtocol(Iperf3Protocol protocol) {
+ this.protocol = (protocol != null) ? protocol : Iperf3Protocol.TCP;
+ }
+ public void setTestUUID(String testUUID) {
+ this.testUUID = testUUID;
+ }
+ public int getPort() {
+ if(port == 0){
+ return 5201;
+ }
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public double getInterval() {
+ if(interval == 0.0){
+ return 1.0;
+ }
+
+ return interval;
+ }
+
+ public void setInterval(double interval) {
+ this.interval = interval;
+ }
+
+ public String getBitrate() {
+ return bitrate;
+ }
+
+ public void setBitrate(String bitrate) {
+ this.bitrate = bitrate;
+ }
+
+ public int getLength() {
+ return length;
+ }
+
+ public void setLength(int length) {
+ this.length = length;
+ }
+
+ public Iperf3Mode getMode() {
+ return mode;
+ }
+
+ /**
+ * Set the mode. If the mode is set to SERVER, the client field is cleared.
+ */
+ public void setMode(Iperf3Mode mode) {
+ this.mode = (mode != null) ? mode : Iperf3Mode.UNDEFINED;
+ }
+
+
+
+ public Iperf3Direction getDirection() {
+ return direction;
+ }
+
+ public void setDirection(Iperf3Direction direction) {
+ this.direction = (direction != null) ? direction : Iperf3Direction.UNDEFINED;
+ }
+
+ // Additional getters and setters for remaining fields...
+
+ public String getPidfile() {
+ return pidfile;
+ }
+
+ public void setPidfile(String pidfile) {
+ this.pidfile = pidfile;
+ }
+
+ public String getFile() {
+ return file;
+ }
+
+ public void setFile(String file) {
+ this.file = file;
+ }
+
+ public String getAffinity() {
+ return affinity;
+ }
+
+ public void setAffinity(String affinity) {
+ this.affinity = affinity;
+ }
+
+ public String getBind() {
+ return bind;
+ }
+
+ public void setBind(String bind) {
+ this.bind = bind;
+ }
+
+ public String getBindDev() {
+ return bindDev;
+ }
+
+ public void setBindDev(String bindDev) {
+ this.bindDev = bindDev;
+ }
+
+ public Boolean getVerbose() {
+ return verbose;
+ }
+
+ public void setVerbose(Boolean verbose) {
+ this.verbose = verbose;
+ }
+
+ public Boolean getJson() {
+ return json;
+ }
+
+ public void setJson(Boolean json) {
+ this.json = json;
+ }
+
+ public Boolean getJsonStream() {
+ return jsonStream;
+ }
+
+ public void setJsonStream(Boolean jsonStream) {
+ this.jsonStream = jsonStream;
+ }
+
+
+ public Boolean getForceflush() {
+ return forceflush;
+ }
+
+ public void setForceflush(Boolean forceflush) {
+ this.forceflush = forceflush;
+ }
+
+ public String getTimestamps() {
+ return timestamps;
+ }
+
+ public void setTimestamps(String timestamps) {
+ this.timestamps = timestamps;
+ }
+
+ public Integer getRcvTimeout() {
+ return rcvTimeout;
+ }
+
+ public void setRcvTimeout(Integer rcvTimeout) {
+ this.rcvTimeout = rcvTimeout;
+ }
+
+ public Integer getSndTimeout() {
+ return sndTimeout;
+ }
+
+ public void setSndTimeout(Integer sndTimeout) {
+ this.sndTimeout = sndTimeout;
+ }
+
+ public Integer getDebug() {
+ return debug;
+ }
+
+ public void setDebug(Integer debug) {
+ this.debug = debug;
+ }
+
+ public Boolean getVersion() {
+ return version;
+ }
+
+ public void setVersion(Boolean version) {
+ this.version = version;
+ }
+
+ public Boolean getHelp() {
+ return help;
+ }
+
+ public void setHelp(Boolean help) {
+ this.help = help;
+ }
+
+ public Boolean getDaemon() {
+ return daemon;
+ }
+
+ public void setDaemon(Boolean daemon) {
+ this.daemon = daemon;
+ }
+
+ public Boolean getOneOff() {
+ return oneOff;
+ }
+
+ public void setOneOff(Boolean oneOff) {
+ this.oneOff = oneOff;
+ }
+
+ public String getServerBitrateLimit() {
+ return serverBitrateLimit;
+ }
+
+ public void setServerBitrateLimit(String serverBitrateLimit) {
+ this.serverBitrateLimit = serverBitrateLimit;
+ }
+
+ public Integer getIdleTimeout() {
+ return idleTimeout;
+ }
+
+ public void setIdleTimeout(Integer idleTimeout) {
+ this.idleTimeout = idleTimeout;
+ }
+
+ public String getRsaPrivateKeyPath() {
+ return rsaPrivateKeyPath;
+ }
+
+ public void setRsaPrivateKeyPath(String rsaPrivateKeyPath) {
+ this.rsaPrivateKeyPath = rsaPrivateKeyPath;
+ }
+
+ public String getAuthorizedUsersPath() {
+ return authorizedUsersPath;
+ }
+
+ public void setAuthorizedUsersPath(String authorizedUsersPath) {
+ this.authorizedUsersPath = authorizedUsersPath;
+ }
+
+ public Integer getTimeSkewThreshold() {
+ return timeSkewThreshold;
+ }
+
+ public void setTimeSkewThreshold(Integer timeSkewThreshold) {
+ this.timeSkewThreshold = timeSkewThreshold;
+ }
+
+ public Boolean getUsePkcs1Padding() {
+ return usePkcs1Padding;
+ }
+
+ public void setUsePkcs1Padding(Boolean usePkcs1Padding) {
+ this.usePkcs1Padding = usePkcs1Padding;
+ }
+
+ public Boolean getSctp() {
+ return sctp;
+ }
+
+ public void setSctp(Boolean sctp) {
+ this.sctp = sctp;
+ }
+
+ public String getXbind() {
+ return xbind;
+ }
+
+ public void setXbind(String xbind) {
+ this.xbind = xbind;
+ }
+
+ public Integer getNstreams() {
+ return nstreams;
+ }
+
+ public void setNstreams(Integer nstreams) {
+ this.nstreams = nstreams;
+ }
+
+
+ public Integer getConnectTimeout() {
+ return connectTimeout;
+ }
+
+ public void setConnectTimeout(Integer connectTimeout) {
+ this.connectTimeout = connectTimeout;
+ }
+
+ public String getPacingTimer() {
+ return pacingTimer;
+ }
+
+ public void setPacingTimer(String pacingTimer) {
+ this.pacingTimer = pacingTimer;
+ }
+
+ public String getFqRate() {
+ return fqRate;
+ }
+
+ public void setFqRate(String fqRate) {
+ this.fqRate = fqRate;
+ }
+
+ public Integer getTime() {
+ if(time == 0){
+ time = 10;
+ }
+ return time;
+ }
+
+ public void setTime(Integer time) {
+ this.time = time;
+ }
+
+ public String getBytes() {
+ return bytes;
+ }
+
+ public void setBytes(String bytes) {
+ this.bytes = bytes;
+ }
+
+ public String getBlockcount() {
+ return blockcount;
+ }
+
+ public void setBlockcount(String blockcount) {
+ this.blockcount = blockcount;
+ }
+
+ public Integer getCport() {
+ return cport;
+ }
+
+ public void setCport(Integer cport) {
+ this.cport = cport;
+ }
+
+ public Integer getParallel() {
+ return parallel;
+ }
+
+ public void setParallel(Integer parallel) {
+ this.parallel = parallel;
+ }
+
+ public Boolean getReverse() {
+ return reverse;
+ }
+
+ public void setReverse(Boolean reverse) {
+ this.reverse = reverse;
+ }
+
+ public Boolean getBidir() {
+ return bidir;
+ }
+
+ public void setBidir(Boolean bidir) {
+ this.bidir = bidir;
+ }
+
+ public String getWindow() {
+ return window;
+ }
+
+ public void setWindow(String window) {
+ this.window = window;
+ }
+
+ public String getCongestion() {
+ return congestion;
+ }
+
+ public void setCongestion(String congestion) {
+ this.congestion = congestion;
+ }
+
+ public Integer getSetMss() {
+ return setMss;
+ }
+
+ public void setSetMss(Integer setMss) {
+ this.setMss = setMss;
+ }
+
+ public Boolean getNoDelay() {
+ return noDelay;
+ }
+
+ public void setNoDelay(Boolean noDelay) {
+ this.noDelay = noDelay;
+ }
+
+ public Boolean getVersion4() {
+ return version4;
+ }
+
+ public void setVersion4(Boolean version4) {
+ this.version4 = version4;
+ }
+
+ public Boolean getVersion6() {
+ return version6;
+ }
+
+ public void setVersion6(Boolean version6) {
+ this.version6 = version6;
+ }
+
+ public Integer getTos() {
+ return tos;
+ }
+
+ public void setTos(Integer tos) {
+ this.tos = tos;
+ }
+
+ public String getDscp() {
+ return dscp;
+ }
+
+ public void setDscp(String dscp) {
+ this.dscp = dscp;
+ }
+
+ public Integer getFlowlabel() {
+ return flowlabel;
+ }
+
+ public void setFlowlabel(Integer flowlabel) {
+ this.flowlabel = flowlabel;
+ }
+
+ public Boolean getZerocopy() {
+ return zerocopy;
+ }
+
+ public void setZerocopy(Boolean zerocopy) {
+ this.zerocopy = zerocopy;
+ }
+
+ public Integer getOmit() {
+ return omit;
+ }
+
+ public void setOmit(Integer omit) {
+ this.omit = omit;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getExtraData() {
+ return extraData;
+ }
+
+ public void setExtraData(String extraData) {
+ this.extraData = extraData;
+ }
+
+ public Boolean getGetServerOutput() {
+ return getServerOutput;
+ }
+
+ public void setGetServerOutput(Boolean getServerOutput) {
+ this.getServerOutput = getServerOutput;
+ }
+
+ public Boolean getUdpCounters64bit() {
+ return udpCounters64bit;
+ }
+
+ public void setUdpCounters64bit(Boolean udpCounters64bit) {
+ this.udpCounters64bit = udpCounters64bit;
+ }
+
+ public Boolean getRepeatingPayload() {
+ return repeatingPayload;
+ }
+
+ public void setRepeatingPayload(Boolean repeatingPayload) {
+ this.repeatingPayload = repeatingPayload;
+ }
+
+ public Boolean getDontFragment() {
+ return dontFragment;
+ }
+
+ public void setDontFragment(Boolean dontFragment) {
+ this.dontFragment = dontFragment;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getRsaPublicKeyPath() {
+ return rsaPublicKeyPath;
+ }
+
+ public void setRsaPublicKeyPath(String rsaPublicKeyPath) {
+ this.rsaPublicKeyPath = rsaPublicKeyPath;
+ }
+
+ @Override
+ public String toString() {
+ return "Params{" +
+ "iPerf3UUID='" + iPerf3UUID + '\'' +
+ ", protocol=" + protocol +
+ ", port=" + port +
+ ", interval=" + interval +
+ ", bitrate='" + bitrate + '\'' +
+ ", length=" + length +
+ ", mode=" + mode +
+ ", direction=" + direction +
+ ", pidfile='" + pidfile + '\'' +
+ ", file='" + file + '\'' +
+ ", affinity='" + affinity + '\'' +
+ ", bind='" + bind + '\'' +
+ ", bindDev='" + bindDev + '\'' +
+ ", verbose=" + verbose +
+ ", json=" + json +
+ ", jsonStream=" + jsonStream +
+ ", forceflush=" + forceflush +
+ ", timestamps='" + timestamps + '\'' +
+ ", rcvTimeout=" + rcvTimeout +
+ ", sndTimeout=" + sndTimeout +
+ ", debug=" + debug +
+ ", version=" + version +
+ ", help=" + help +
+ ", daemon=" + daemon +
+ ", oneOff=" + oneOff +
+ ", serverBitrateLimit='" + serverBitrateLimit + '\'' +
+ ", idleTimeout=" + idleTimeout +
+ ", rsaPrivateKeyPath='" + rsaPrivateKeyPath + '\'' +
+ ", authorizedUsersPath='" + authorizedUsersPath + '\'' +
+ ", timeSkewThreshold=" + timeSkewThreshold +
+ ", usePkcs1Padding=" + usePkcs1Padding +
+ ", sctp=" + sctp +
+ ", xbind='" + xbind + '\'' +
+ ", nstreams=" + nstreams +
+ ", connectTimeout=" + connectTimeout +
+ ", pacingTimer='" + pacingTimer + '\'' +
+ ", fqRate='" + fqRate + '\'' +
+ ", time=" + time +
+ ", bytes='" + bytes + '\'' +
+ ", blockcount='" + blockcount + '\'' +
+ ", cport=" + cport +
+ ", parallel=" + parallel +
+ ", reverse=" + reverse +
+ ", bidir=" + bidir +
+ ", window='" + window + '\'' +
+ ", congestion='" + congestion + '\'' +
+ ", setMss=" + setMss +
+ ", noDelay=" + noDelay +
+ ", version4=" + version4 +
+ ", version6=" + version6 +
+ ", tos=" + tos +
+ ", dscp='" + dscp + '\'' +
+ ", flowlabel=" + flowlabel +
+ ", zerocopy=" + zerocopy +
+ ", omit=" + omit +
+ ", title='" + title + '\'' +
+ ", extraData='" + extraData + '\'' +
+ ", getServerOutput=" + getServerOutput +
+ ", udpCounters64bit=" + udpCounters64bit +
+ ", repeatingPayload=" + repeatingPayload +
+ ", dontFragment=" + dontFragment +
+ ", username='" + username + '\'' +
+ ", rsaPublicKeyPath='" + rsaPublicKeyPath + '\'' +
+ '}';
+ }
+
+ public String[] getInputAsCommand() {
+ ArrayList command = new ArrayList<>();
+
+ // Mode: either CLIENT (-c host) or SERVER (-s)
+ switch (mode) {
+ case CLIENT:
+ command.add("-c");
+ command.add(host);
+ break;
+ case SERVER:
+ command.add("-s");
+ break;
+ default:
+ // Optionally, throw an exception or handle UNDEFINED mode
+ break;
+ }
+
+ // Common options
+ if (port > 0) {
+ command.add("-p");
+ command.add(String.valueOf(port));
+ }
+ if (interval > 0) {
+ command.add("-i");
+ command.add(String.valueOf(interval));
+ }
+ if (pidfile != null && !pidfile.trim().isEmpty()) {
+ command.add("-I");
+ command.add(pidfile);
+ }
+ if (file != null && !file.trim().isEmpty()) {
+ command.add("-F");
+ command.add(file);
+ }
+ if (affinity != null && !affinity.trim().isEmpty()) {
+ command.add("-A");
+ command.add(affinity);
+ }
+ if (bind != null && !bind.trim().isEmpty()) {
+ command.add("-B");
+ command.add(bind);
+ }
+ if (bindDev != null && !bindDev.trim().isEmpty()) {
+ command.add("--bind-dev");
+ command.add(bindDev);
+ }
+ if (verbose != null && verbose) {
+ command.add("-V");
+ }
+ if (json != null && json) {
+ command.add("-J");
+ }
+
+ if (timestamps != null && !timestamps.trim().isEmpty()) {
+ command.add("--timestamps");
+ command.add(timestamps);
+ }
+ if (rcvTimeout != null && rcvTimeout > 0) {
+ command.add("--rcv-timeout");
+ command.add(String.valueOf(rcvTimeout));
+ }
+ if (sndTimeout != null && sndTimeout > 0) {
+ command.add("--snd-timeout");
+ command.add(String.valueOf(sndTimeout));
+ }
+ if (debug != null && debug > 0) {
+ command.add("-d");
+ command.add(String.valueOf(debug));
+ }
+ if (version != null && version) {
+ command.add("-v");
+ }
+ if (help != null && help) {
+ command.add("-h");
+ }
+
+ // Server-specific options
+ if (daemon != null && daemon) {
+ command.add("-D");
+ }
+ if (oneOff != null && oneOff) {
+ command.add("-1");
+ }
+ if (serverBitrateLimit != null && !serverBitrateLimit.trim().isEmpty()) {
+ command.add("--server-bitrate-limit");
+ command.add(serverBitrateLimit);
+ }
+ if (idleTimeout != null && idleTimeout > 0) {
+ command.add("--idle-timeout");
+ command.add(String.valueOf(idleTimeout));
+ }
+ if (rsaPrivateKeyPath != null && !rsaPrivateKeyPath.trim().isEmpty()) {
+ command.add("--rsa-private-key-path");
+ command.add(rsaPrivateKeyPath);
+ }
+ if (authorizedUsersPath != null && !authorizedUsersPath.trim().isEmpty()) {
+ command.add("--authorized-users-path");
+ command.add(authorizedUsersPath);
+ }
+ if (timeSkewThreshold != null && timeSkewThreshold > 0) {
+ command.add("--time-skew-threshold");
+ command.add(String.valueOf(timeSkewThreshold));
+ }
+ if (usePkcs1Padding != null && usePkcs1Padding) {
+ command.add("--use-pkcs1-padding");
+ }
+
+ // Client-specific options
+ if (sctp != null && sctp) {
+ command.add("--sctp");
+ }
+ if (xbind != null && !xbind.trim().isEmpty()) {
+ command.add("-X");
+ command.add(xbind);
+ }
+ if (nstreams != null && nstreams > 0) {
+ command.add("--nstreams");
+ command.add(String.valueOf(nstreams));
+ }
+ switch (protocol){
+ case UDP:
+ command.add("-u");
+ break;
+ case TCP:
+ default:
+ break;
+ }
+ if (connectTimeout != null && connectTimeout > 0) {
+ command.add("--connect-timeout");
+ command.add(String.valueOf(connectTimeout));
+ }
+ if (bitrate != null && !bitrate.trim().isEmpty()) {
+ command.add("-b");
+ command.add(bitrate+"M");
+ }
+ if (pacingTimer != null && !pacingTimer.trim().isEmpty()) {
+ command.add("--pacing-timer");
+ command.add(pacingTimer);
+ }
+ if (fqRate != null && !fqRate.trim().isEmpty()) {
+ command.add("--fq-rate");
+ command.add(fqRate);
+ }
+ if (time > 0) {
+ command.add("-t");
+ command.add(String.valueOf(time));
+ }
+ if (bytes != null && !bytes.trim().isEmpty()) {
+ command.add("-n");
+ command.add(bytes);
+ }
+ if (blockcount != null && !blockcount.trim().isEmpty()) {
+ command.add("-k");
+ command.add(blockcount);
+ }
+ if (length > 0) {
+ command.add("-l");
+ command.add(String.valueOf(length));
+ }
+ if (cport != null && cport > 0) {
+ command.add("--cport");
+ command.add(String.valueOf(cport));
+ }
+ if (parallel != null && parallel > 0) {
+ command.add("-P");
+ command.add(String.valueOf(parallel));
+ }
+
+ // Data direction options (client-specific)
+ if (direction != null) {
+ switch (direction) {
+ case DOWN:
+ command.add("--reverse");
+ break;
+ case BIDIR:
+ command.add("--bidir");
+ break;
+ default:
+ // UP direction requires no flag.
+ break;
+ }
+ }
+
+ if (window != null && !window.trim().isEmpty()) {
+ command.add("-w");
+ command.add(window);
+ }
+ if (congestion != null && !congestion.trim().isEmpty()) {
+ command.add("-C");
+ command.add(congestion);
+ }
+ if (setMss != null && setMss > 0) {
+ command.add("-M");
+ command.add(String.valueOf(setMss));
+ }
+ if (noDelay != null && noDelay) {
+ command.add("-N");
+ }
+ if (version4 != null && version4) {
+ command.add("-4");
+ }
+ if (version6 != null && version6) {
+ command.add("-6");
+ }
+ if (tos != null && tos > 0) {
+ command.add("-S");
+ command.add(String.valueOf(tos));
+ }
+ if (dscp != null && !dscp.trim().isEmpty()) {
+ command.add("--dscp");
+ command.add(dscp);
+ }
+ if (flowlabel != null && flowlabel > 0) {
+ command.add("-L");
+ command.add(String.valueOf(flowlabel));
+ }
+ if (zerocopy != null && zerocopy) {
+ command.add("-Z");
+ }
+ if (omit != null && omit > 0) {
+ command.add("-O");
+ command.add(String.valueOf(omit));
+ }
+ if (title != null && !title.trim().isEmpty()) {
+ command.add("-T");
+ command.add(title);
+ }
+ if (extraData != null && !extraData.trim().isEmpty()) {
+ command.add("--extra-data");
+ command.add(extraData);
+ }
+ if (getServerOutput != null && getServerOutput) {
+ command.add("--get-server-output");
+ }
+ if (udpCounters64bit != null && udpCounters64bit) {
+ command.add("--udp-counters-64bit");
+ }
+ if (repeatingPayload != null && repeatingPayload) {
+ command.add("--repeating-payload");
+ }
+ if (dontFragment != null && dontFragment) {
+ command.add("--dont-fragment");
+ }
+ if (username != null && !username.trim().isEmpty()) {
+ command.add("--username");
+ command.add(username);
+ }
+ if (rsaPublicKeyPath != null && !rsaPublicKeyPath.trim().isEmpty()) {
+ command.add("--rsa-public-key-path");
+ command.add(rsaPublicKeyPath);
+ }
+
+ // Always add these extra fixed options.
+ command.add("--json-stream");
+ command.add("--forceflush");
+ command.add("--logfile");
+ command.add(super.getLogfile());
+
+
+
+ return command.toArray(new String[0]);
+ }
+
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Parameter/Parameter.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Parameter/Parameter.java
new file mode 100644
index 00000000..d4d8f6d0
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Parameter/Parameter.java
@@ -0,0 +1,56 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Parameter;
+
+import android.os.Environment;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class Parameter implements Parcelable {
+ public static final String rootPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath();
+ private String lineProtocolFile;
+ private String logfile;
+ protected Parameter(Parcel in) {
+ lineProtocolFile = in.readString();
+ logfile = in.readString();
+ }
+
+ public Parameter(String logfile, String lineProtocolFile) {
+ this.logfile = logfile;
+ this.lineProtocolFile = lineProtocolFile;
+ }
+
+ public static final Creator CREATOR = new Creator() {
+ @Override
+ public Parameter createFromParcel(Parcel in) {
+ return new Parameter(in);
+ }
+
+ @Override
+ public Parameter[] newArray(int size) {
+ return new Parameter[size];
+ }
+ };
+
+ public String getLineProtocolFile() {
+ return lineProtocolFile;
+ }
+
+ public String getLogfile() {
+ return logfile;
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(android.os.Parcel dest, int flags) {
+ dest.writeString(lineProtocolFile);
+ dest.writeString(logfile);
+ }
+ public void setLineProtocolFile(String lineProtocolFile) {
+ this.lineProtocolFile = lineProtocolFile;
+ }
+
+ public void setLogfile(String logfile) {
+ this.logfile = logfile;
+ }
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Parameter/PingParameter.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Parameter/PingParameter.java
new file mode 100644
index 00000000..74b2137c
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Parameter/PingParameter.java
@@ -0,0 +1,182 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Parameter;
+
+import android.net.Network;
+import android.os.Parcel;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+
+public class PingParameter extends Parameter {
+ public static final String rawDirPath = rootPath+"/omnt/ping/raw/";
+
+ public static final String lineProtocolDirPath = rootPath+"/omnt/ping/lineprotocol/";
+ private static final String TAG = "PingParameter";
+
+ public static final String PING = "ping";
+ public static final String DESTINATION = "destination";
+ public static final String COUNT = "count";
+ public static final String TIMEOUT = "timeout"; // in seconds
+ public static final String PACKET_SIZE = "packetSize";
+ public static final String INTERVAL = "interval"; // in seconds
+
+ public String getDestination() {
+ return destination;
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+ public int getTimeoutMillis() {
+ return timeoutMillis;
+ }
+
+ public int getPacketSize() {
+ return packetSize;
+ }
+
+ public long getIntervalMillis() {
+ return intervalMillis;
+ }
+
+
+ public Network getNetwork() {
+ return network;
+ }
+
+ private String destination;
+ private int count;
+ private int timeoutMillis;
+ private int packetSize;
+ private long intervalMillis;
+ private Network network;
+ private int deadline;
+ private String testUUID;
+
+
+ public String[] getInputAsCommand() {
+ ArrayList command = new ArrayList<>();
+ command.add("/system/bin/ping");
+ if (count > 0) {
+ command.add("-c");
+ command.add(String.valueOf(count));
+ }
+ if (timeoutMillis > 0) {
+ command.add("-W");
+ command.add(String.valueOf(timeoutMillis));
+ }
+ if (packetSize > 0) {
+ command.add("-s");
+ command.add(String.valueOf(packetSize));
+ }
+ if (intervalMillis > 0) {
+ command.add("-i");
+ command.add(String.valueOf(intervalMillis));
+ }
+ if (deadline > 0) {
+ command.add("-w");
+ command.add(String.valueOf(deadline));
+ }
+ command.add("-D");
+ command.add(destination);
+
+ return command.toArray(new String[0]);
+ }
+ public PingParameter(JSONObject parameter, String testUUID) {
+ super(rawDirPath + testUUID + ".txt", lineProtocolDirPath + testUUID + ".txt");
+ this.testUUID = testUUID;
+ try {
+ destination = parameter.getString(DESTINATION);
+ } catch (JSONException e) {
+ Log.d(TAG, e.toString());
+ Log.w(TAG, "could not create PingParameter!");
+ throw new IllegalArgumentException("Destination is missing");
+ }
+ try {
+ count = parameter.getInt(COUNT);
+ } catch (JSONException e) {
+ Log.d(TAG, e.toString());
+ Log.i(TAG, "No count set.");
+ }
+ try {
+ timeoutMillis = parameter.getInt(TIMEOUT);
+ } catch (JSONException e) {
+ Log.d(TAG, e.toString());
+ Log.i(TAG, "no timeout set.");
+ }
+ try {
+ packetSize = parameter.getInt(PACKET_SIZE);
+ } catch (JSONException e) {
+ Log.d(TAG, e.toString());
+ Log.i(TAG, "no packet size set.");
+ }
+ try {
+ intervalMillis = parameter.getLong(INTERVAL);
+ } catch (JSONException e) {
+ Log.d(TAG, e.toString());
+ Log.i(TAG, "no interval set.");
+ }
+ try {
+ deadline = parameter.getInt("deadline");
+ } catch (JSONException e) {
+ Log.d(TAG, e.toString());
+ Log.i(TAG, "no deadline set.");
+ }
+
+ try {
+ Files.createDirectories(Paths.get(rawDirPath));
+ Files.createDirectories(Paths.get(lineProtocolDirPath));
+ } catch (IOException e) {
+ Log.d(TAG, "Could not create directories.");
+ }
+
+
+ }
+
+ protected PingParameter(Parcel in) {
+ super(in);
+ destination = in.readString();
+ count = in.readInt();
+ timeoutMillis = in.readInt();
+ packetSize = in.readInt();
+ intervalMillis = in.readLong();
+ network = in.readParcelable(Network.class.getClassLoader());
+ }
+
+ public static final Creator CREATOR = new Creator() {
+ @Override
+ public PingParameter createFromParcel(Parcel in) {
+ return new PingParameter(in);
+ }
+
+ @Override
+ public PingParameter[] newArray(int size) {
+ return new PingParameter[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return super.describeContents();
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeString(destination);
+ dest.writeInt(count);
+ dest.writeInt(timeoutMillis);
+ dest.writeInt(packetSize);
+ dest.writeLong(intervalMillis);
+ dest.writeParcelable(network, flags);
+ }
+
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingFragment.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingFragment.java
index 0947055d..7175aeb7 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingFragment.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingFragment.java
@@ -32,10 +32,8 @@
import java.io.FileOutputStream;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Metric.METRIC_TYPE;
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Metric.Metric;
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping.PingInformations.PacketLossLine;
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping.PingInformations.PingInformation;
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping.PingInformations.RTTLine;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Metric.MetricCalculator;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Metric.MetricView;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SPType;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SharedPreferencesGrouper;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R;
@@ -51,8 +49,8 @@ public class PingFragment extends Fragment {
private TextInputEditText input;
private Context ct;
private SharedPreferencesGrouper spg;
- private Metric rttMetric;
- private Metric packetLossMetric;
+ private MetricView rttMetric;
+ private MetricView packetLossMetric;
public PingFragment() {
}
@@ -67,8 +65,8 @@ private void startPingService() {
input.setEnabled(false);
Intent pingStart = new Intent(ct, PingService.class);
ct.startService(pingStart);
- rttMetric.resetMetric();
- packetLossMetric.resetMetric();
+ rttMetric.getMetricCalculator().resetMetric();
+ packetLossMetric.getMetricCalculator().resetMetric();
}
private void stopPingService() {
@@ -160,8 +158,10 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,
});
- rttMetric = new Metric(METRIC_TYPE.PING_RTT, ct);
- packetLossMetric = new Metric(METRIC_TYPE.PING_PACKET_LOSS, ct);
+ rttMetric = new MetricView(new MetricCalculator(METRIC_TYPE.PING_RTT), ct);
+ rttMetric.setup("RTT [ms]");
+ packetLossMetric = new MetricView(new MetricCalculator(METRIC_TYPE.PACKET_LOSS), ct);
+ packetLossMetric.setup("Packet Loss [%]");
LinearLayout metricsLL = new LinearLayout(ct);
metricsLL.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams foo1 = new LinearLayout.LayoutParams(
@@ -169,13 +169,14 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,
LinearLayout.LayoutParams.WRAP_CONTENT
);
metricsLL.setLayoutParams(foo1);
- metricsLL.addView(rttMetric.createMainLL("RTT [ms]"));
- metricsLL.addView(packetLossMetric.createMainLL("Packet Loss [%]"));
+ metricsLL.addView(rttMetric);
+ metricsLL.addView(packetLossMetric);
horizontalLL1.addView(metricsLL);
-
- PingParser pingParser = PingParser.getInstance(null);
+ //ToDO
+ /*
+ PingParser pingParser = PingParser;
pingParser.addPropertyChangeListener(evt -> {
PingInformation pi = (PingInformation) evt.getNewValue();
switch (pi.getLineType()) {
@@ -188,7 +189,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,
break;
}
});
-
+ */
//packetLossMetric.setVisibility(View.INVISIBLE);
return v;
}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingInformations/PacketLossLine.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingInformations/PacketLossLine.java
index 33bbc2d7..9f31057d 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingInformations/PacketLossLine.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingInformations/PacketLossLine.java
@@ -1,5 +1,6 @@
package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping.PingInformations;
+import com.influxdb.client.domain.WritePrecision;
import com.influxdb.client.write.Point;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -15,12 +16,14 @@ public PacketLossLine(String line) {
this.setLineType(LINEType.PACKET_LOSS);
}
public void parse(){
+ super.parse();
matcher = pattern.matcher(this.getLine());
if(matcher.find()){
packetsTransmitted = Long.parseLong(matcher.group(1));
packetsReceived = Long.parseLong(matcher.group(2));
packetLoss = Double.parseDouble(matcher.group(3).replace("%", ""));
}
+
}
public long getPacketsReceived() {
return packetsReceived;
@@ -36,6 +39,8 @@ public Point getPoint(){
return super.getPoint()
.addField("packets_transmitted", this.getPacketsTransmitted())
.addField("packets_received", this.getPacketsReceived())
- .addField("packet_loss", this.getPacketLoss());
+ .addField("packet_loss", this.getPacketLoss())
+ .time(System.currentTimeMillis(), WritePrecision.MS);
+ //ping does not provide timestamp for packet loss line
}
}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingParser.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingParser.java
index 78fc4fa4..c0f40c99 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingParser.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingParser.java
@@ -18,17 +18,13 @@ public class PingParser {
private final PropertyChangeSupport support;
private PropertyChangeListener listener;
- private PingParser(BufferedReader br) {
+ public PingParser(BufferedReader br) {
this.br = br;
this.lines = new ArrayList<>();
support = new PropertyChangeSupport(this);
}
- public static PingParser getInstance(BufferedReader br){
- if (instance == null) instance = new PingParser(br);
- if(br != null); instance.setBr(br);
- return instance;
- }
+
private LINEType getLineType(String line){
if (line.contains("bytes from")) {
return LINEType.RTT;
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingService.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingService.java
index 8f9f1f6e..f0fcaf70 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingService.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingService.java
@@ -133,11 +133,6 @@ private void setupPing(){
pingLoggingHandleThread = new HandlerThread("PingLoggingHandlerThread");
pingLoggingHandleThread.start();
pingLogging = new Handler(Objects.requireNonNull(pingLoggingHandleThread.getLooper()));
- PingParser pingParser = PingParser.getInstance(null);
- propertyChangeListener = pingParser.getListener();
- if(propertyChangeListener != null){
- pingParser.removePropertyChangeListener(propertyChangeListener);
- }
propertyChangeListener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
@@ -163,8 +158,6 @@ public void propertyChange(PropertyChangeEvent evt) {
}
};
- pingParser.addPropertyChangeListener(propertyChangeListener);
- pingParser.setListener(propertyChangeListener);
pingLogging.post(pingUpdate);
}
public void parsePingCommand() {
@@ -196,38 +189,9 @@ public void run() {
Data data = new Data.Builder()
.putString("input", spg.getSharedPreference(SPType.ping_sp).getString("ping_input", "8.8.8.8"))
.build();
- OneTimeWorkRequest pingWR =
- new OneTimeWorkRequest.Builder(PingWorker.class)
- .setInputData(data)
- .addTag("Ping").build();
- pingWRs.add(pingWR);
- wm.beginWith(pingWR).enqueue();
- Observer observer = new Observer() {
- @Override
- public void onChanged(Object o) {
- WorkInfo workInfo = (WorkInfo) o;
- WorkInfo.State state = workInfo.getState();
- switch (state){
- case RUNNING:
- case ENQUEUED:
- return;
- case CANCELLED:
- try {
- ping_stream.close();
- } catch (IOException e) {
- Log.d(TAG,e.toString());
- }
- pingLogging.removeCallbacks(pingUpdate);
- return;
- }
- wm.getWorkInfoByIdLiveData(pingWR.getId()).removeObserver(this);
- pingWRs.remove(pingWR);
- pingLogging.postDelayed(pingUpdate, 200);
- }
- };
- wm.getWorkInfoByIdLiveData(pingWR.getId()).observeForever(observer);
+
}
};
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingWorker.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingWorker.java
deleted file mode 100644
index dd1d04d7..00000000
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/PingWorker.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2023 Peter Hasse
- * SPDX-FileCopyrightText: 2023 Johann Hackler
- * SPDX-FileCopyrightText: 2023 Fraunhofer FOKUS
- *
- * SPDX-License-Identifier: BSD-3-Clause-Clear
- */
-
-package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping;
-
-import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE;
-
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Color;
-import android.os.Bundle;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.core.app.NotificationCompat;
-import androidx.work.Data;
-import androidx.work.ForegroundInfo;
-import androidx.work.WorkManager;
-import androidx.work.Worker;
-import androidx.work.WorkerParameters;
-
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.HashMap;
-
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.MainActivity;
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping.PingInformations.PingInformation;
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping.PingInformations.RTTLine;
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SPType;
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SharedPreferencesGrouper;
-import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R;
-
-
-public class PingWorker extends Worker {
-
- private static final String TAG = "PingWorker";
- Runtime runtime;
- private ArrayList lines;
- private Process pingProcess;
- private final int notificationID = 102;
- HashMap parsedCommand = new HashMap<>();
- private String pingCommand;
- private final int FOREGROUND_SERVICE_TYPE = FOREGROUND_SERVICE_TYPE_SPECIAL_USE;
- private final Context ct;
- private final String channelId = "OMNT_notification_channel";
- private NotificationCompat.Builder notificationBuilder;
- private Notification notification;
- private final String timeRegex = "\\btime=([0-9]+\\.[0-9]+)\\s+ms\\b";
- private double rtt;
- private NotificationManager notificationManager;
- private SharedPreferencesGrouper spg;
-
-
- public void parsePingCommand() {
-
- String[] commandParts = pingCommand.split("\\s+");
-
- String previousPart = null;
- for (String part : commandParts) {
- switch (part) {
- case "ping":
- parsedCommand.put("command", part);
- break;
- case "-w":
- if (previousPart != null) {
- parsedCommand.put("timeout", previousPart);
- }
- break;
- default:
- parsedCommand.put("target", part);
- break;
- }
- previousPart = part;
- }
- }
-
- public PingWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
- super(context, workerParams);
- runtime = Runtime.getRuntime();
- ct = context;
- spg = SharedPreferencesGrouper.getInstance(ct);
- }
-
-
- @Override
- public void onStopped() {
- super.onStopped();
- Log.d(TAG, "onStopped: worker stopped!");
- if(pingProcess.isAlive()) pingProcess.destroy();
- spg.getSharedPreference(SPType.ping_sp).edit().putBoolean("ping_running", false).apply();
-
- }
-
- private ForegroundInfo createForegroundInfo(@NonNull String progress) {
- // Create an Intent to launch the main activity
- Intent launchIntent = new Intent(ct, MainActivity.class);
- launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
-
- // Add a Bundle to the Intent to indicate that the PingFragment should be opened
- Bundle bundle = new Bundle();
- bundle.putString("openFragment", "PingFragment");
- launchIntent.putExtras(bundle);
-
- // Create a PendingIntent with the Intent
- PendingIntent pendingIntent = PendingIntent.getActivity(ct, 0, launchIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
-
- PendingIntent cancelIntent = WorkManager.getInstance(ct)
- .createCancelPendingIntent(getId());
-
- notification = notificationBuilder
- .setContentTitle("Ping " + parsedCommand.get("target"))
- .setContentText(progress)
- .setOngoing(true)
- .setOnlyAlertOnce(true)
- .setColor(Color.WHITE)
- .setSmallIcon(R.mipmap.ic_launcher_foreground)
- .setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_DEFAULT)
- .addAction(R.drawable.ic_close, "Cancel", cancelIntent)
- .setContentIntent(pendingIntent) // Set the content intent
- .build();
- return new ForegroundInfo(notificationID, notification, FOREGROUND_SERVICE_TYPE);
- }
-
- Runnable updateNotification = new Runnable() {
- @Override
- public void run() {
- if(notification != null){
- notificationBuilder.setContentText(rtt+" ms");
- notificationManager.notify(notificationID, notificationBuilder.build());
- } else {
- setForegroundAsync(createForegroundInfo(rtt+" ms"));
- }
- }
- };
-
- @NonNull
- @Override
- public Result doWork() {
- lines = new ArrayList<>();
- Data data = null;
- notificationBuilder = new NotificationCompat.Builder(ct, channelId);
- notificationManager = ct.getSystemService(NotificationManager.class);
- try {
-
- StringBuilder stringBuilder = new StringBuilder();
- stringBuilder.append("/system/bin/ping ")
- .append("-D ")
- .append(getInputData().getString("input"));
-
- pingCommand = stringBuilder.toString();
- parsePingCommand();
- pingProcess = runtime.exec(stringBuilder.toString());
-
- BufferedReader outputReader =
- new BufferedReader(new InputStreamReader(pingProcess.getInputStream()));
-
-
-
- PingParser pingParser = PingParser.getInstance(outputReader);
-
- pingParser.addPropertyChangeListener(new PropertyChangeListener() {
- @Override
- public void propertyChange(PropertyChangeEvent evt) {
- PingInformation pi = (PingInformation) evt.getNewValue();
- switch(pi.getLineType()){
- case PACKET_LOSS:
- break;
- case RTT:
- rtt = ((RTTLine)pi).getRtt();
- break;
- }
- updateNotification.run();
- }
- });
- pingParser.parse();
- int result = pingProcess.waitFor();
-
- if(isStopped()){
- Log.d(TAG, "doWork: got cancelled because Worker got stopped!");
-
- return Result.success();
- }
-
-
- Log.d(TAG, "doWork: result " + result);
- if (result != 0) {
- return Result.failure();
- }
- } catch (IOException e) {
- Log.d(TAG,e.toString());
- System.out.printf(e.toString());
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
-
- return Result.success();
- }
-}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/Worker/PingToLineProtocolWorker.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/Worker/PingToLineProtocolWorker.java
new file mode 100644
index 00000000..faad5762
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/Worker/PingToLineProtocolWorker.java
@@ -0,0 +1,141 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Peter Hasse
+ * SPDX-FileCopyrightText: 2023 Johann Hackler
+ * SPDX-FileCopyrightText: 2023 Fraunhofer FOKUS
+ *
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping.Worker;
+
+import android.content.Context;
+import android.os.Build;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.work.Data;
+import androidx.work.Worker;
+import androidx.work.WorkerParameters;
+
+import com.google.gson.Gson;
+import com.influxdb.client.write.Point;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Scanner;
+
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.DataProvider.DeviceInformation;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.GlobalVars;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.InfluxDB2x.InfluxdbConnection;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Inputs.PingInput;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping.PingInformations.LINEType;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping.PingInformations.PacketLossLine;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping.PingInformations.PingInformation;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping.PingInformations.RTTLine;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SharedPreferencesGrouper;
+
+public class PingToLineProtocolWorker extends Worker {
+ public static final String TAG = "PingToLineProtocolWorker";
+ InfluxdbConnection influx;
+ private SharedPreferencesGrouper spg;
+
+ private final DeviceInformation di = GlobalVars.getInstance().get_dp().getDeviceInformation();
+ private PingInput pingInput;
+ public PingToLineProtocolWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
+ super(context, workerParams);
+ Gson gson = new Gson();
+ String iperf3InputString = getInputData().getString(PingInput.INPUT);
+ pingInput = gson.fromJson(iperf3InputString, PingInput.class);
+ spg = SharedPreferencesGrouper.getInstance(getApplicationContext());
+ }
+
+
+ private LINEType getLineType(String line){
+ if (line.contains("bytes from")) {
+ return LINEType.RTT;
+ } else if (line.contains("Unreachable")) {
+ return LINEType.UNREACHABLE;
+ } else if (line.contains("Request timeout")) {
+ return LINEType.TIMEOUT;
+ } else if (line.contains("packets transmitted")){
+ return LINEType.PACKET_LOSS;
+ } else {
+ return LINEType.UNKNOWN;
+ }
+ }
+
+ @NonNull
+ @Override
+ public Result doWork() {
+ Data.Builder output = new Data.Builder().putBoolean("pingUpload", false);
+ File myObj = new File(pingInput.getPingParameter().getLogfile());
+ Scanner scanner = null;
+ try {
+ scanner = new Scanner(myObj);
+ } catch (FileNotFoundException e) {
+ return Result.failure(output.putString("error", "File not found").build());
+ }
+ ArrayList pingInformations = new ArrayList<>();
+ while (scanner.hasNextLine()) {
+ String line = scanner.nextLine();
+ PingInformation pi = null;
+ switch (getLineType(line)) {
+ case RTT:
+ pi = new RTTLine(line);
+ case UNREACHABLE:
+ //TDODO
+ break;
+ case TIMEOUT:
+ //TODO
+ break;
+ case PACKET_LOSS:
+ pi = new PacketLossLine(line);
+ break;
+ case UNKNOWN:
+ break;
+ }
+ if (pi == null) continue;
+ pi.parse();
+ pingInformations.add(pi);
+ }
+ scanner.close();
+ File lineprotocolfile = new File(pingInput.getPingParameter().getLineProtocolFile());
+ if(lineprotocolfile.exists()){
+ lineprotocolfile.delete();
+ try {
+ lineprotocolfile.createNewFile();
+ } catch (IOException e) {
+ Log.e(TAG, "doWork: could not create LP File!", e);
+ return Result.failure(output.putString("error", "LP-File not created").build());
+ }
+ }
+ FileOutputStream pingStream = null;
+ try {
+ pingStream = new FileOutputStream(pingInput.getPingParameter().getLineProtocolFile(), true);
+ } catch (FileNotFoundException e) {
+ Log.d(TAG, "doWork: " + e.toString());
+ Log.e(TAG, "doWork: Could not create FileOutputStream");
+ }
+
+ for (PingInformation pi : pingInformations) {
+ try {
+ Point point = pi.getPoint();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ point.addTags(GlobalVars.getInstance().get_dp().getTagsMap());
+ }
+ pingStream.write((point.toLineProtocol() + "\n").getBytes());
+
+ } catch (IOException e) {
+ Log.d(TAG, "doWork: "+e.toString());
+ return Result.failure(output.putString("error", "File not written").build());
+ }
+ }
+ return Result.success(output.build());
+ }
+
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/Worker/PingWorker.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/Worker/PingWorker.java
new file mode 100644
index 00000000..1f9e30de
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Ping/Worker/PingWorker.java
@@ -0,0 +1,165 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Peter Hasse
+ * SPDX-FileCopyrightText: 2023 Johann Hackler
+ * SPDX-FileCopyrightText: 2023 Fraunhofer FOKUS
+ *
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.Ping.Worker;
+
+import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.graphics.Color;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.core.app.NotificationCompat;
+import androidx.work.Data;
+import androidx.work.ForegroundInfo;
+import androidx.work.Worker;
+import androidx.work.WorkerParameters;
+
+import com.google.gson.Gson;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Inputs.PingInput;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Parameter.PingParameter;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R;
+
+public class PingWorker extends Worker {
+
+ public static final String PING = "ping";
+ public static final String REASON = "reason";
+ public static final String LINE = "line";
+ public static final String TAG = "PingWorker";
+
+ private int notificationID = 102;
+ private final int FOREGROUND_SERVICE_TYPE = FOREGROUND_SERVICE_TYPE_SPECIAL_USE;
+ private final Context ct;
+ private NotificationManager notificationManager;
+ private final String channelId = "OMNT_notification_channel";
+ private NotificationCompat.Builder notificationBuilder;
+ private float rtt; // round-trip time
+ private PingInput pingInput;
+ private Notification notification;
+ public PingWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
+ super(context, workerParams);
+ ct = context;
+
+ // Retrieve the PingInput from the Worker's input data.
+ String pingInputString = getInputData().getString(PingInput.INPUT);
+ pingInput = new Gson().fromJson(pingInputString, PingInput.class);
+
+ int notificationNumber = getInputData().getInt(PingInput.NOTIFICATIONUMBER, 0);
+ notificationID += notificationNumber;
+
+ notificationManager = (NotificationManager) ct.getSystemService(Context.NOTIFICATION_SERVICE);
+ notificationBuilder = new NotificationCompat.Builder(ct, channelId);
+ setForegroundAsync(createForegroundInfo(""));
+ }
+
+ private ForegroundInfo createForegroundInfo(String progress) {
+ notification = notificationBuilder
+ .setContentTitle("Ping")
+ .setContentText(pingInput.getPingParameter().getDestination()+": "+progress)
+ .setOngoing(true)
+ .setOnlyAlertOnce(true)
+ .setColor(Color.WHITE)
+ .setSmallIcon(R.mipmap.ic_launcher_foreground)
+ .setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_DEFAULT)
+ .build();
+ return new ForegroundInfo(notificationID, notification, FOREGROUND_SERVICE_TYPE);
+ }
+
+
+ @NonNull
+ @Override
+ public Result doWork() {
+ Data.Builder output = new Data.Builder().putBoolean(PING, false);
+
+ if (pingInput == null) {
+ Log.e(TAG, "PingInput is null");
+ return Result.failure(output.putString(REASON, "PingInput is null").build());
+ }
+ PingParameter pingParameter = pingInput.getPingParameter();
+ if (pingParameter == null) {
+ Log.e(TAG, "PingParameter is null");
+ return Result.failure(output.putString(REASON, "PingParameter is null").build());
+ }
+ String[] command = pingParameter.getInputAsCommand();
+ if (command == null) {
+ Log.e(TAG, "Command is null");
+ return Result.failure(output.putString(REASON, "Command is null").build());
+ }
+
+ Log.d(TAG, "doWork: executing " + String.join(" ", command));
+ int result = -1;
+ try {
+ String timeRegex = "time=(\\d+(?:\\.\\d+)?)\\s*ms";
+ Pattern pattern = Pattern.compile(timeRegex);
+
+
+ ProcessBuilder processBuilder = new ProcessBuilder(command);
+ Process process = processBuilder.start();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
+ FileOutputStream pingStream = new FileOutputStream(pingInput.getPingParameter().getLogfile(), true);
+
+ String line;
+ while ((line = reader.readLine()) != null) {
+ Log.d(TAG, "doWork: "+line);
+ pingStream.write((line + "\n").getBytes());
+ Matcher matcher = pattern.matcher(line);
+ if (matcher.find()) {
+ try {
+ rtt = Float.parseFloat(Objects.requireNonNull(matcher.group(1)));
+ Log.d(TAG, "Updated RTT: " + rtt);
+ new Runnable() {
+ @Override
+ public void run() {
+ setForegroundAsync(createForegroundInfo( rtt + " ms"));
+ }
+ }.run();
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "Error parsing RTT value: " + e.toString());
+ }
+ }
+ // Optionally, report progress with the output line.
+ setProgressAsync(output.putString(LINE, line).build());
+ }
+
+ pingStream.close();
+ reader.close();
+
+ result = process.waitFor();
+ } catch (IOException e) {
+ Log.e(TAG, "Error while executing ping command: " + e.toString());
+ return Result.failure(output.putString(REASON, "Error while executing ping command.").build());
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Error while waiting for ping command: " + e.toString());
+ return Result.failure(output.putString(REASON, "Error while waiting for ping command.").build());
+ }
+
+ if (result != 0) {
+ Log.e(TAG, "Ping command failed with result: " + result);
+ return Result.failure(output.putString(REASON, "Ping command failed with result: " + result).build());
+ }
+
+ return Result.success(output.putBoolean(PING, true).build());
+ }
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Preferences/SPType.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Preferences/SPType.java
index 6607b0ab..893fc16c 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Preferences/SPType.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Preferences/SPType.java
@@ -6,7 +6,8 @@ public enum SPType {
ping_sp,
carrier_sp,
mobile_network_sp,
- default_sp;
+ default_sp,
+ mqtt_sp;
public String toString() {
@@ -16,6 +17,7 @@ public String toString() {
case logging_sp:
case ping_sp:
case carrier_sp:
+ case mqtt_sp:
case mobile_network_sp:
return super.toString();
default:
@@ -37,12 +39,15 @@ public String toReadable(){
case logging_sp:
case ping_sp:
case carrier_sp:
+
case default_sp:
return name.substring(0,1).toUpperCase() + name.substring(1);
case mobile_network_sp:
return "Mobile Network";
case iperf3_sp:
return "iPerf3";
+ case mqtt_sp:
+ return "MQTT";
default:
return null;
}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Preferences/SharedPreferencesGrouper.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Preferences/SharedPreferencesGrouper.java
index 26c35a4f..2782ace0 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Preferences/SharedPreferencesGrouper.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/Preferences/SharedPreferencesGrouper.java
@@ -21,6 +21,7 @@ public class SharedPreferencesGrouper {
private final SharedPreferences carrierSP;
private final SharedPreferences iperf3SP;
private final SharedPreferences mobileNetworkSP;
+ private final SharedPreferences mqttSP;
private final SharedPreferences defaultSP;
private final SharedPreferences pingSP;
private final Context ct;
@@ -36,12 +37,13 @@ public void clearConfig(){
}
- private SharedPreferencesGrouper(Context ct) {
+ private SharedPreferencesGrouper( Context ct) {
this.ct = ct;
loggingSP = ct.getSharedPreferences(getSharedPreferenceIdentifier(SPType.logging_sp), Context.MODE_PRIVATE);
carrierSP = ct.getSharedPreferences(getSharedPreferenceIdentifier(SPType.carrier_sp), Context.MODE_PRIVATE);
iperf3SP = ct.getSharedPreferences(getSharedPreferenceIdentifier(SPType.iperf3_sp), Context.MODE_PRIVATE);
pingSP = ct.getSharedPreferences(getSharedPreferenceIdentifier(SPType.ping_sp), Context.MODE_PRIVATE);
+ mqttSP = ct.getSharedPreferences(getSharedPreferenceIdentifier(SPType.mqtt_sp), Context.MODE_PRIVATE);
mobileNetworkSP = ct.getSharedPreferences(getSharedPreferenceIdentifier(SPType.mobile_network_sp), Context.MODE_PRIVATE);
defaultSP = PreferenceManager.getDefaultSharedPreferences(ct);
}
@@ -71,6 +73,9 @@ public SharedPreferences getSharedPreference(SPType key){
case mobile_network_sp:
sp = mobileNetworkSP;
break;
+ case mqtt_sp:
+ sp = mqttSP;
+ break;
default:
sp = defaultSP;
break;
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/RemoteWorkInfoChecker.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/RemoteWorkInfoChecker.java
new file mode 100644
index 00000000..91333b22
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/RemoteWorkInfoChecker.java
@@ -0,0 +1,97 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.work.WorkInfo;
+import androidx.work.WorkQuery;
+import androidx.work.multiprocess.RemoteWorkManager;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.Executor;
+
+
+public class RemoteWorkInfoChecker implements Runnable {
+ private static final String TAG = "WorkInfoChecker";
+ private final Handler handler = new Handler(Looper.getMainLooper());
+ private final HashMap workInfors = new HashMap<>();
+ private final RemoteWorkManager remoteWorkManager;
+ private final ArrayList workIdGroups;
+ private boolean isDone = false;
+ private final Executor executor;
+ private CustomEventListener listener;
+
+ private int workCount = 0;
+ public RemoteWorkInfoChecker(RemoteWorkManager remoteWorkManager, ArrayList workIdGroups) {
+ this.remoteWorkManager = remoteWorkManager;
+ this.workIdGroups = workIdGroups;
+ this.executor = Runnable::run;
+ }
+
+
+ private void update(WorkInfo workInfo) {
+ workInfors.put(workInfo.getId(), workInfo);
+ if(listener != null) {
+ listener.onChange(new HashMap<>(workInfors));
+ }
+ }
+
+ private void checkWorkInfos(UUID workIds) {
+ ListenableFuture> future = remoteWorkManager.getWorkInfos(WorkQuery.fromIds(workIds));
+ Futures.addCallback(future, new com.google.common.util.concurrent.FutureCallback>() {
+ @Override
+ public void onSuccess(List workInfos) {
+ Log.d(TAG, "onSuccess: WorkInfos: " + workInfos.size());
+ for (WorkInfo workInfo : workInfos) {
+ Log.d(TAG, "onSuccess: WorkInfo: " + workInfo.getId() + " State: " + workInfo.getState());
+ update(workInfo);
+ }
+ }
+
+ @Override
+ public void onFailure(@NonNull Throwable throwable) {
+ Log.e(TAG, " executeWork: Error getting work info: " + throwable.getMessage());
+ }
+ }, executor);
+ }
+
+ private void isAllWorkDone() {
+ for (WorkInfo info : workInfors.values()) {
+ WorkInfo.State state = info.getState();
+ isDone = (state != WorkInfo.State.RUNNING) && (state != WorkInfo.State.ENQUEUED);
+ }
+ }
+
+ @Override
+ public void run() {
+ for (int i = 0; i < workIdGroups.size(); i++) {
+ checkWorkInfos(workIdGroups.get(i));
+ }
+
+ executor.execute(this::isAllWorkDone);
+
+ if (isDone || workIdGroups.isEmpty()) {
+ Log.d(TAG, "run: All work done");
+ handler.removeCallbacks(this);
+ } else {
+ handler.postDelayed(this, 1000);
+ }
+ }
+
+ public void setListener(CustomEventListener listener) {
+ this.listener = listener;
+ }
+
+ public void start() {
+ handler.postDelayed(this, 200);
+ }
+
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/SettingPreferences/LoggingSettingsFragment.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/SettingPreferences/LoggingSettingsFragment.java
index 0be64e35..3ddfab74 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/SettingPreferences/LoggingSettingsFragment.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/SettingPreferences/LoggingSettingsFragment.java
@@ -13,10 +13,14 @@
import android.text.InputType;
import android.util.Log;
+import androidx.fragment.app.FragmentTransaction;
+import androidx.preference.EditTextPreference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreferenceCompat;
+import java.util.Objects;
+
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SPType;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SharedPreferencesGrouper;
@@ -31,25 +35,77 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
SharedPreferencesGrouper spg = SharedPreferencesGrouper.getInstance(requireContext());
getPreferenceManager().setSharedPreferencesName(spg.getSharedPreferenceIdentifier(SPType.logging_sp));
setPreferencesFromResource(R.xml.preference_logging, rootKey);
- getPreferenceScreen().getSharedPreferences()
+ Objects.requireNonNull(getPreferenceScreen().getSharedPreferences())
.registerOnSharedPreferenceChangeListener(this);
- enable_influx_switch = findPreference("enable_influx");
-
-
androidx.preference.EditTextPreference editTextPreference =
getPreferenceManager().findPreference("logging_interval");
editTextPreference.setOnBindEditTextListener(
editText -> editText.setInputType(InputType.TYPE_CLASS_NUMBER));
}
+ @Override
+ public void onResume() {
+ super.onResume();
+ // Register the listener
+ Objects.requireNonNull(getPreferenceManager().getSharedPreferences())
+ .registerOnSharedPreferenceChangeListener(this);
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ // Unregister the listener to prevent memory leaks
+ Objects.requireNonNull(getPreferenceManager().getSharedPreferences())
+ .unregisterOnSharedPreferenceChangeListener(this);
+ }
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) {
if(s == null) return;
+ Log.d(TAG, "onSharedPreferenceChanged: " + s);
if (s.equals("enable_logging")) {
boolean logger = sharedPreferences.getBoolean("enable_logging", false);
- Log.d(TAG, "Logger update: " + logger);
+ Log.d(TAG, "onSharedPreferenceChanged: " + logger);
+ }
+
+ switch (s){
+ case "enable_logging":
+ case "start_logging_on_boot":
+ case "enable_local_influx_log":
+ case "enable_local_file_log":
+ case "enable_influx":
+ case "fake_location":
+ case "influx_network_data":
+ case "log_signal_data":
+ case "influx_cell_data":
+ case "log_neighbour_cells":
+ case "influx_throughput_data":
+ case "log_wifi_data":
+ case "influx_battery_data":
+ case "influx_ip_address_data":
+ boolean booleanValue = sharedPreferences.getBoolean(s, false);
+ SwitchPreferenceCompat switchPreferenceCompat = findPreference(s);
+ if (switchPreferenceCompat != null) {
+ switchPreferenceCompat.setChecked(booleanValue);
+ }
+ break;
+ case "logging_interval":
+ case "influx_URL":
+ case "influx_token":
+ case "influx_org":
+ case "influx_bucket":
+ case "measurement_name":
+ case "tags":
+ String stringValue = sharedPreferences.getString(s, "");
+ EditTextPreference editTextPreference = findPreference(s);
+ if (editTextPreference != null) {
+ editTextPreference.setText(stringValue);
+ }
+
+ break;
+
}
+
}
@Override
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/SettingPreferences/MQTTSettingsFragment.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/SettingPreferences/MQTTSettingsFragment.java
new file mode 100644
index 00000000..b65c902c
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/SettingPreferences/MQTTSettingsFragment.java
@@ -0,0 +1,44 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.SettingPreferences;
+
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.text.InputType;
+import android.util.Log;
+
+import androidx.annotation.Nullable;
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.SwitchPreferenceCompat;
+
+import java.util.Objects;
+
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SPType;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SharedPreferencesGrouper;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.R;
+
+public class MQTTSettingsFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener {
+ private static final String TAG = "MQTTSettingsFragment";
+ SwitchPreferenceCompat enable_mqtt_switch;
+ @Override
+ public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
+ SharedPreferencesGrouper spg = SharedPreferencesGrouper.getInstance(requireContext());
+ getPreferenceManager().setSharedPreferencesName(spg.getSharedPreferenceIdentifier(SPType.mqtt_sp));
+ setPreferencesFromResource(R.xml.preference_mqtt, rootKey);
+ Objects.requireNonNull(getPreferenceScreen().getSharedPreferences())
+ .registerOnSharedPreferenceChangeListener(this);
+ enable_mqtt_switch = findPreference("enable_mqtt");
+
+
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, @Nullable String key) {
+ if(key == null) return;
+ if (key.equals("enable_mqtt")) {
+ boolean logger = sharedPreferences.getBoolean("enable_mqtt", false);
+ Log.d(TAG, "Logger update: " + logger);
+ }
+
+
+
+ }
+}
diff --git a/app/src/main/res/drawable/mqtt.xml b/app/src/main/res/drawable/mqtt.xml
new file mode 100644
index 00000000..64b84c3f
--- /dev/null
+++ b/app/src/main/res/drawable/mqtt.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_iperf3_input.xml b/app/src/main/res/layout/fragment_iperf3_input.xml
index 84d8b895..3a16e451 100644
--- a/app/src/main/res/layout/fragment_iperf3_input.xml
+++ b/app/src/main/res/layout/fragment_iperf3_input.xml
@@ -1,293 +1,287 @@
-
-
+ xmlns:app="http://schemas.android.com/apk/res-auto">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
\ No newline at end of file
+ app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_iperf3_list.xml b/app/src/main/res/layout/fragment_iperf3_list.xml
deleted file mode 100644
index 14c2ea82..00000000
--- a/app/src/main/res/layout/fragment_iperf3_list.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_iperf3_row_item.xml b/app/src/main/res/layout/fragment_iperf3_row_item.xml
index aef54079..39b444eb 100644
--- a/app/src/main/res/layout/fragment_iperf3_row_item.xml
+++ b/app/src/main/res/layout/fragment_iperf3_row_item.xml
@@ -5,22 +5,80 @@
~
~ SPDX-License-Identifier: BSD-3-Clause-Clear
-->
-
-
+ android:id="@+id/card"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_margin="8dp"
+ style="?attr/materialCardViewElevatedStyle">
+ android:orientation="vertical">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
diff --git a/app/src/main/res/layout/iperf3_notification.xml b/app/src/main/res/layout/iperf3_notification.xml
new file mode 100644
index 00000000..5e761904
--- /dev/null
+++ b/app/src/main/res/layout/iperf3_notification.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/parameter_view.xml b/app/src/main/res/layout/parameter_view.xml
new file mode 100644
index 00000000..40a4ce75
--- /dev/null
+++ b/app/src/main/res/layout/parameter_view.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml
index 38072b60..d660bfef 100644
--- a/app/src/main/res/navigation/nav_graph.xml
+++ b/app/src/main/res/navigation/nav_graph.xml
@@ -53,6 +53,7 @@
app:destination="@id/HomeFragment" />
+
@@ -97,16 +98,6 @@
android:id="@+id/action_fragment_iperf3_input_to_runners_list"
app:destination="@id/runners_list" />
-
-
-
-
+
+
+
+
Android IMS
>
Log WiFi information>
+
+
+ MQTT Username
+ Enable MQTT
+ Enable MQTT on boot
+ Username provided by your MQTT-Broker
+ MQTT Client Username
+ Password provided by your MQTT-Broker
+ MQTT Client Password
+ MQTT-Broker Address, including Port
+ MQTT-Broker Address
+ tcp://192.168.213.89:1883
+ MQTT Service
+
+
@@ -254,12 +269,21 @@
Standard
Channel Bandwidth
Security Type
- Serving Cell Parameter: PCI, RSRP...
- Enable Cell Notification
+ Serving Cell Parameter: PCI, RSRP...
+ Enable Cell Notification
Serving Cell
ICMP / Ping
Special Codes
Subscriptions\n
About
+ Notification settings
+ Unique Device Name
+ iPerf3
+ Rerun
+ Cancel
+ X
+ State
+ Parameter
+
\ No newline at end of file
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index ce3edeea..879f3462 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -1,20 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
index 34eede4b..b91d05e1 100644
--- a/app/src/main/res/values/themes.xml
+++ b/app/src/main/res/values/themes.xml
@@ -16,4 +16,6 @@
- true
- true
+
+
\ No newline at end of file
diff --git a/app/src/main/res/xml/preference.xml b/app/src/main/res/xml/preference.xml
index 6af95295..f0b603ba 100644
--- a/app/src/main/res/xml/preference.xml
+++ b/app/src/main/res/xml/preference.xml
@@ -22,22 +22,33 @@
app:allowDividerAbove="false"
app:allowDividerBelow="false"
app:iconSpaceReserved="false" />
+
+
+
-
+ app:summary="@string/enable_radio_notification_summary"
+ app:title="@string/enable_radio_notification" />
+
-
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/xml/preference_logging.xml b/app/src/main/res/xml/preference_logging.xml
index f3c8a505..391dbe64 100644
--- a/app/src/main/res/xml/preference_logging.xml
+++ b/app/src/main/res/xml/preference_logging.xml
@@ -74,7 +74,6 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index a0e9d158..5b2cf27c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -5,6 +5,7 @@ buildscript {
repositories {
google()
mavenCentral()
+
}
dependencies {
classpath 'com.android.tools.build:gradle:8.9.1'
diff --git a/gradle.properties b/gradle.properties
index f49b2417..2c57a4ed 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -26,4 +26,4 @@ android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=false
android.nonTransitiveRClass=false
-android.nonFinalResIds=false
\ No newline at end of file
+android.nonFinalResIds=false
diff --git a/settings.gradle b/settings.gradle
index c77964c0..8b5d1b87 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -16,3 +16,4 @@ dependencyResolutionManagement {
rootProject.name = "OpenMobileNetworkToolkit"
include ':app'
+include ':model'