From da1cf5cc529433d41db8ccaf2ec1ad424daa6437 Mon Sep 17 00:00:00 2001 From: Denis Nutiu Date: Sat, 21 Nov 2020 23:49:47 +0200 Subject: [PATCH] NUC-11: Add Android application. Grpc is working! --- NucuHub.Android/.gitignore | 14 ++ NucuHub.Android/app/.gitignore | 1 + NucuHub.Android/app/build.gradle | 63 +++++++ NucuHub.Android/app/proguard-rules.pro | 21 +++ .../nucuhub/ExampleInstrumentedTest.java | 25 +++ .../app/src/main/AndroidManifest.xml | 26 +++ .../nuculabs/grpc/EnvironmentSensorData.java | 54 ++++++ .../grpc/EnvironmentSensorService.java | 64 +++++++ .../dev/nuculabs/nucuhub/MainActivity.java | 53 ++++++ .../nucuhub/ui/gallery/GalleryFragment.java | 33 ++++ .../nucuhub/ui/gallery/GalleryViewModel.java | 19 ++ .../sensors/EnvironmentSensorViewModel.java | 43 +++++ .../nucuhub/ui/sensors/SensorsFragment.java | 59 ++++++ .../ui/slideshow/SlideshowFragment.java | 33 ++++ .../ui/slideshow/SlideshowViewModel.java | 19 ++ .../app/src/main/proto/NucuCarSensors.proto | 29 +++ .../drawable-v24/ic_launcher_foreground.xml | 31 ++++ .../res/drawable/ic_launcher_background.xml | 74 ++++++++ .../src/main/res/drawable/ic_menu_camera.xml | 12 ++ .../src/main/res/drawable/ic_menu_gallery.xml | 9 + .../main/res/drawable/ic_menu_slideshow.xml | 9 + .../app/src/main/res/drawable/no_signal.png | Bin 0 -> 9563 bytes .../src/main/res/drawable/side_nav_bar.xml | 9 + .../app/src/main/res/drawable/status_bad.png | Bin 0 -> 12685 bytes .../app/src/main/res/drawable/status_good.png | Bin 0 -> 21390 bytes .../src/main/res/drawable/status_netural.png | Bin 0 -> 7422 bytes .../app/src/main/res/layout/activity_main.xml | 25 +++ .../app/src/main/res/layout/app_bar_main.xml | 25 +++ .../app/src/main/res/layout/content_main.xml | 22 +++ .../layout/fragment_environment_sensor.xml | 30 +++ .../src/main/res/layout/fragment_gallery.xml | 23 +++ .../main/res/layout/fragment_slideshow.xml | 23 +++ .../src/main/res/layout/nav_header_main.xml | 36 ++++ .../main/res/menu/activity_main_drawer.xml | 20 ++ .../app/src/main/res/menu/main.xml | 8 + .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3593 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 5339 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2636 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 3388 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4926 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 7472 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 7909 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 11873 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 10652 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 16570 bytes .../main/res/navigation/mobile_navigation.xml | 25 +++ .../app/src/main/res/values/colors.xml | 6 + .../app/src/main/res/values/dimens.xml | 8 + .../app/src/main/res/values/strings.xml | 14 ++ .../app/src/main/res/values/styles.xml | 16 ++ .../dev/nuculabs/nucuhub/ExampleUnitTest.java | 17 ++ NucuHub.Android/build.gradle | 28 +++ NucuHub.Android/gradle.properties | 19 ++ .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54329 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 + NucuHub.Android/gradlew | 172 ++++++++++++++++++ NucuHub.Android/gradlew.bat | 84 +++++++++ NucuHub.Android/settings.gradle | 2 + 60 files changed, 1319 insertions(+) create mode 100644 NucuHub.Android/.gitignore create mode 100644 NucuHub.Android/app/.gitignore create mode 100644 NucuHub.Android/app/build.gradle create mode 100644 NucuHub.Android/app/proguard-rules.pro create mode 100644 NucuHub.Android/app/src/androidTest/java/dev/nuculabs/nucuhub/ExampleInstrumentedTest.java create mode 100644 NucuHub.Android/app/src/main/AndroidManifest.xml create mode 100644 NucuHub.Android/app/src/main/java/dev/nuculabs/grpc/EnvironmentSensorData.java create mode 100644 NucuHub.Android/app/src/main/java/dev/nuculabs/grpc/EnvironmentSensorService.java create mode 100644 NucuHub.Android/app/src/main/java/dev/nuculabs/nucuhub/MainActivity.java create mode 100644 NucuHub.Android/app/src/main/java/dev/nuculabs/nucuhub/ui/gallery/GalleryFragment.java create mode 100644 NucuHub.Android/app/src/main/java/dev/nuculabs/nucuhub/ui/gallery/GalleryViewModel.java create mode 100644 NucuHub.Android/app/src/main/java/dev/nuculabs/nucuhub/ui/sensors/EnvironmentSensorViewModel.java create mode 100644 NucuHub.Android/app/src/main/java/dev/nuculabs/nucuhub/ui/sensors/SensorsFragment.java create mode 100644 NucuHub.Android/app/src/main/java/dev/nuculabs/nucuhub/ui/slideshow/SlideshowFragment.java create mode 100644 NucuHub.Android/app/src/main/java/dev/nuculabs/nucuhub/ui/slideshow/SlideshowViewModel.java create mode 100644 NucuHub.Android/app/src/main/proto/NucuCarSensors.proto create mode 100644 NucuHub.Android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml create mode 100644 NucuHub.Android/app/src/main/res/drawable/ic_launcher_background.xml create mode 100644 NucuHub.Android/app/src/main/res/drawable/ic_menu_camera.xml create mode 100644 NucuHub.Android/app/src/main/res/drawable/ic_menu_gallery.xml create mode 100644 NucuHub.Android/app/src/main/res/drawable/ic_menu_slideshow.xml create mode 100644 NucuHub.Android/app/src/main/res/drawable/no_signal.png create mode 100644 NucuHub.Android/app/src/main/res/drawable/side_nav_bar.xml create mode 100644 NucuHub.Android/app/src/main/res/drawable/status_bad.png create mode 100644 NucuHub.Android/app/src/main/res/drawable/status_good.png create mode 100644 NucuHub.Android/app/src/main/res/drawable/status_netural.png create mode 100644 NucuHub.Android/app/src/main/res/layout/activity_main.xml create mode 100644 NucuHub.Android/app/src/main/res/layout/app_bar_main.xml create mode 100644 NucuHub.Android/app/src/main/res/layout/content_main.xml create mode 100644 NucuHub.Android/app/src/main/res/layout/fragment_environment_sensor.xml create mode 100644 NucuHub.Android/app/src/main/res/layout/fragment_gallery.xml create mode 100644 NucuHub.Android/app/src/main/res/layout/fragment_slideshow.xml create mode 100644 NucuHub.Android/app/src/main/res/layout/nav_header_main.xml create mode 100644 NucuHub.Android/app/src/main/res/menu/activity_main_drawer.xml create mode 100644 NucuHub.Android/app/src/main/res/menu/main.xml create mode 100644 NucuHub.Android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 NucuHub.Android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 NucuHub.Android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 NucuHub.Android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 NucuHub.Android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 NucuHub.Android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 NucuHub.Android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 NucuHub.Android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 NucuHub.Android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 NucuHub.Android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 NucuHub.Android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 NucuHub.Android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 NucuHub.Android/app/src/main/res/navigation/mobile_navigation.xml create mode 100644 NucuHub.Android/app/src/main/res/values/colors.xml create mode 100644 NucuHub.Android/app/src/main/res/values/dimens.xml create mode 100644 NucuHub.Android/app/src/main/res/values/strings.xml create mode 100644 NucuHub.Android/app/src/main/res/values/styles.xml create mode 100644 NucuHub.Android/app/src/test/java/dev/nuculabs/nucuhub/ExampleUnitTest.java create mode 100644 NucuHub.Android/build.gradle create mode 100644 NucuHub.Android/gradle.properties create mode 100644 NucuHub.Android/gradle/wrapper/gradle-wrapper.jar create mode 100644 NucuHub.Android/gradle/wrapper/gradle-wrapper.properties create mode 100644 NucuHub.Android/gradlew create mode 100644 NucuHub.Android/gradlew.bat create mode 100644 NucuHub.Android/settings.gradle diff --git a/NucuHub.Android/.gitignore b/NucuHub.Android/.gitignore new file mode 100644 index 0000000..603b140 --- /dev/null +++ b/NucuHub.Android/.gitignore @@ -0,0 +1,14 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx diff --git a/NucuHub.Android/app/.gitignore b/NucuHub.Android/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/NucuHub.Android/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/NucuHub.Android/app/build.gradle b/NucuHub.Android/app/build.gradle new file mode 100644 index 0000000..6d6215a --- /dev/null +++ b/NucuHub.Android/app/build.gradle @@ -0,0 +1,63 @@ +apply plugin: 'com.android.application' +apply plugin: 'com.google.protobuf' + +android { + compileSdkVersion 30 + buildToolsVersion "30.0.2" + + defaultConfig { + applicationId "dev.nuculabs.nucuhub" + minSdkVersion 29 + targetSdkVersion 30 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } +} + +protobuf { + protoc { artifact = 'com.google.protobuf:protoc:3.12.0' } + plugins { + grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.33.1' // CURRENT_GRPC_VERSION + } + } + generateProtoTasks { + all().each { task -> + task.builtins { + java { option 'lite' } + } + task.plugins { + grpc { // Options added to --grpc_out + option 'lite' } + } + } + } +} + +dependencies { + implementation fileTree(dir: "libs", include: ["*.jar"]) + implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'androidx.legacy:legacy-support-v4:1.0.0' + implementation 'com.google.android.material:material:1.0.0' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + implementation 'androidx.navigation:navigation-fragment:2.1.0' + implementation 'androidx.navigation:navigation-ui:2.1.0' + implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test.ext:junit:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + // You need to build grpc-java to obtain these libraries below. + implementation 'io.grpc:grpc-okhttp:1.33.1' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-protobuf-lite:1.33.1' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-stub:1.33.1' // CURRENT_GRPC_VERSION + compileOnly 'org.apache.tomcat:annotations-api:6.0.53' // necessary for Java 9+ + +} \ No newline at end of file diff --git a/NucuHub.Android/app/proguard-rules.pro b/NucuHub.Android/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/NucuHub.Android/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/NucuHub.Android/app/src/androidTest/java/dev/nuculabs/nucuhub/ExampleInstrumentedTest.java b/NucuHub.Android/app/src/androidTest/java/dev/nuculabs/nucuhub/ExampleInstrumentedTest.java new file mode 100644 index 0000000..5b2dc96 --- /dev/null +++ b/NucuHub.Android/app/src/androidTest/java/dev/nuculabs/nucuhub/ExampleInstrumentedTest.java @@ -0,0 +1,25 @@ +package dev.nuculabs.nucuhub; + +import android.content.Context; +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + assertEquals("dev.nuculabs.nucuhub", appContext.getPackageName()); + } +} \ No newline at end of file diff --git a/NucuHub.Android/app/src/main/AndroidManifest.xml b/NucuHub.Android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..0979990 --- /dev/null +++ b/NucuHub.Android/app/src/main/AndroidManifest.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/NucuHub.Android/app/src/main/java/dev/nuculabs/grpc/EnvironmentSensorData.java b/NucuHub.Android/app/src/main/java/dev/nuculabs/grpc/EnvironmentSensorData.java new file mode 100644 index 0000000..e63704f --- /dev/null +++ b/NucuHub.Android/app/src/main/java/dev/nuculabs/grpc/EnvironmentSensorData.java @@ -0,0 +1,54 @@ +package dev.nuculabs.grpc; + +import NucuCarSensorsProto.NucuCarSensors; +import android.util.Log; +import org.json.JSONException; +import org.json.JSONObject; + +public class EnvironmentSensorData { + @SuppressWarnings("FieldCanBeLocal") + private final String TAG = EnvironmentSensorData.class.getName(); + private double temperature; + private double humidity; + private double pressure; + private double volatileOrganicCompounds; + private NucuCarSensors.SensorStateEnum sensorState; + + public EnvironmentSensorData(String data, NucuCarSensors.SensorStateEnum state) { + try { + JSONObject json = new JSONObject(data); + temperature = json.getDouble("Temperature"); + humidity = json.getDouble("Humidity"); + pressure = json.getDouble("Pressure"); + volatileOrganicCompounds = json.getDouble("VolatileOrganicCompounds"); + sensorState = state; + } catch (JSONException e) { + Log.e(TAG, e.getLocalizedMessage()); + temperature = -1; + humidity = -1; + pressure = -1; + volatileOrganicCompounds = -1; + sensorState = NucuCarSensors.SensorStateEnum.Error; + } + } + + public NucuCarSensors.SensorStateEnum getSensorState() { + return sensorState; + } + + public double getTemperature() { + return temperature; + } + + public double getHumidity() { + return humidity; + } + + public double getPressure() { + return pressure; + } + + public double getVolatileOrganicCompounds() { + return volatileOrganicCompounds; + } +} diff --git a/NucuHub.Android/app/src/main/java/dev/nuculabs/grpc/EnvironmentSensorService.java b/NucuHub.Android/app/src/main/java/dev/nuculabs/grpc/EnvironmentSensorService.java new file mode 100644 index 0000000..91208d4 --- /dev/null +++ b/NucuHub.Android/app/src/main/java/dev/nuculabs/grpc/EnvironmentSensorService.java @@ -0,0 +1,64 @@ +package dev.nuculabs.grpc; + +import NucuCarSensorsProto.EnvironmentSensorGrpcServiceGrpc; +import NucuCarSensorsProto.NucuCarSensors; +import android.util.Log; +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import io.grpc.StatusRuntimeException; + +import java.util.Locale; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; + +import static java.util.concurrent.TimeUnit.SECONDS; + + +public class EnvironmentSensorService { + private final String TAG = EnvironmentSensorService.class.getName(); + private final ManagedChannel channel; + private final EnvironmentSensorGrpcServiceGrpc.EnvironmentSensorGrpcServiceBlockingStub blockingStub; + private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); + private ScheduledFuture periodicGrpcRequestHandle = null; + private EnvironmentSensorData lastMeasurementData = new EnvironmentSensorData("{}", NucuCarSensors.SensorStateEnum.Uninitialized); + + public EnvironmentSensorService(String host, int port) { + this(ManagedChannelBuilder.forAddress(host, port).usePlaintext()); + Log.i(TAG, String.format(Locale.ENGLISH, "Initializing channel host=%s port=%d", host, port)); + } + + public EnvironmentSensorService(ManagedChannelBuilder channelBuilder) { + channel = channelBuilder.build(); + blockingStub = EnvironmentSensorGrpcServiceGrpc.newBlockingStub(channel); + } + + public void start() { + final Runnable grpcPoolingTask = new Runnable() { + public void run() { + lastMeasurementData = getMeasurement(); + } + }; + periodicGrpcRequestHandle = scheduler.scheduleAtFixedRate(grpcPoolingTask, 5, 10, SECONDS); + } + + public void stop() { + periodicGrpcRequestHandle.cancel(true); + } + + public EnvironmentSensorData getLastMeasurementData() { + return lastMeasurementData; + } + + private EnvironmentSensorData getMeasurement() { + try { + NucuCarSensors.NucuCarSensorResponse response = null; + response = blockingStub.getMeasurement(null); + Log.d(TAG, "getMeasurement " + response.getJsonData()); + return new EnvironmentSensorData(response.getJsonData(), response.getState()); + } catch (StatusRuntimeException e) { + Log.e(TAG, e.getLocalizedMessage()); + return new EnvironmentSensorData("{}", NucuCarSensors.SensorStateEnum.Error); + } + } +} diff --git a/NucuHub.Android/app/src/main/java/dev/nuculabs/nucuhub/MainActivity.java b/NucuHub.Android/app/src/main/java/dev/nuculabs/nucuhub/MainActivity.java new file mode 100644 index 0000000..9fc78c3 --- /dev/null +++ b/NucuHub.Android/app/src/main/java/dev/nuculabs/nucuhub/MainActivity.java @@ -0,0 +1,53 @@ +package dev.nuculabs.nucuhub; + +import android.os.Bundle; +import android.view.Menu; +import com.google.android.material.navigation.NavigationView; +import androidx.navigation.NavController; +import androidx.navigation.Navigation; +import androidx.navigation.ui.AppBarConfiguration; +import androidx.navigation.ui.NavigationUI; +import androidx.drawerlayout.widget.DrawerLayout; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; + +public class MainActivity extends AppCompatActivity { + + private AppBarConfiguration mAppBarConfiguration; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + + DrawerLayout drawer = findViewById(R.id.drawer_layout); + NavigationView navigationView = findViewById(R.id.nav_view); + // Passing each menu ID as a set of Ids because each + // menu should be considered as top level destinations. + mAppBarConfiguration = new AppBarConfiguration.Builder( + R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow) + .setDrawerLayout(drawer) + .build(); + + NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment); + NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration); + NavigationUI.setupWithNavController(navigationView, navController); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.main, menu); + return true; + } + + @Override + public boolean onSupportNavigateUp() { + NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment); + return NavigationUI.navigateUp(navController, mAppBarConfiguration) + || super.onSupportNavigateUp(); + } +} \ No newline at end of file diff --git a/NucuHub.Android/app/src/main/java/dev/nuculabs/nucuhub/ui/gallery/GalleryFragment.java b/NucuHub.Android/app/src/main/java/dev/nuculabs/nucuhub/ui/gallery/GalleryFragment.java new file mode 100644 index 0000000..091532c --- /dev/null +++ b/NucuHub.Android/app/src/main/java/dev/nuculabs/nucuhub/ui/gallery/GalleryFragment.java @@ -0,0 +1,33 @@ +package dev.nuculabs.nucuhub.ui.gallery; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.Observer; +import androidx.lifecycle.ViewModelProviders; +import dev.nuculabs.nucuhub.R; + +public class GalleryFragment extends Fragment { + + private GalleryViewModel galleryViewModel; + + public View onCreateView(@NonNull LayoutInflater inflater, + ViewGroup container, Bundle savedInstanceState) { + galleryViewModel = + ViewModelProviders.of(this).get(GalleryViewModel.class); + View root = inflater.inflate(R.layout.fragment_gallery, container, false); + final TextView textView = root.findViewById(R.id.text_gallery); + galleryViewModel.getText().observe(getViewLifecycleOwner(), new Observer() { + @Override + public void onChanged(@Nullable String s) { + textView.setText(s); + } + }); + return root; + } +} \ No newline at end of file diff --git a/NucuHub.Android/app/src/main/java/dev/nuculabs/nucuhub/ui/gallery/GalleryViewModel.java b/NucuHub.Android/app/src/main/java/dev/nuculabs/nucuhub/ui/gallery/GalleryViewModel.java new file mode 100644 index 0000000..3cd51c5 --- /dev/null +++ b/NucuHub.Android/app/src/main/java/dev/nuculabs/nucuhub/ui/gallery/GalleryViewModel.java @@ -0,0 +1,19 @@ +package dev.nuculabs.nucuhub.ui.gallery; + +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.ViewModel; + +public class GalleryViewModel extends ViewModel { + + private MutableLiveData mText; + + public GalleryViewModel() { + mText = new MutableLiveData<>(); + mText.setValue("This is gallery fragment"); + } + + public LiveData getText() { + return mText; + } +} \ No newline at end of file diff --git a/NucuHub.Android/app/src/main/java/dev/nuculabs/nucuhub/ui/sensors/EnvironmentSensorViewModel.java b/NucuHub.Android/app/src/main/java/dev/nuculabs/nucuhub/ui/sensors/EnvironmentSensorViewModel.java new file mode 100644 index 0000000..fc9b8b4 --- /dev/null +++ b/NucuHub.Android/app/src/main/java/dev/nuculabs/nucuhub/ui/sensors/EnvironmentSensorViewModel.java @@ -0,0 +1,43 @@ +package dev.nuculabs.nucuhub.ui.sensors; + +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.ViewModel; +import dev.nuculabs.nucuhub.R; + +public class EnvironmentSensorViewModel extends ViewModel { + + private MutableLiveData sensorStatusImageTooltip; + private MutableLiveData sensorStatusImageResourceId; + + public EnvironmentSensorViewModel() { + sensorStatusImageResourceId = new MutableLiveData<>(); + sensorStatusImageResourceId.setValue(R.drawable.no_signal); + sensorStatusImageTooltip = new MutableLiveData<>(); + } + + public LiveData getSensorStatusImageResourceId() { + return sensorStatusImageResourceId; + } + + public LiveData getSensorStatusImageTooltip() { + Integer sensorStatusImageResourceId = this.sensorStatusImageResourceId.getValue(); + if (sensorStatusImageResourceId == null) { + sensorStatusImageResourceId = -1; + } + + switch (sensorStatusImageResourceId) { + case R.drawable.status_good: + sensorStatusImageTooltip.setValue("The air quality is good."); + case R.drawable.status_netural: + sensorStatusImageTooltip.setValue("The air quality is not great, not terrible."); + case R.drawable.status_bad: + sensorStatusImageTooltip.setValue("The air quality is bad."); + case R.drawable.no_signal: + default: + sensorStatusImageTooltip.setValue("No signal. Please ensure device is connected!"); + break; + } + return sensorStatusImageTooltip; + } +} \ No newline at end of file diff --git a/NucuHub.Android/app/src/main/java/dev/nuculabs/nucuhub/ui/sensors/SensorsFragment.java b/NucuHub.Android/app/src/main/java/dev/nuculabs/nucuhub/ui/sensors/SensorsFragment.java new file mode 100644 index 0000000..a8cd871 --- /dev/null +++ b/NucuHub.Android/app/src/main/java/dev/nuculabs/nucuhub/ui/sensors/SensorsFragment.java @@ -0,0 +1,59 @@ +package dev.nuculabs.nucuhub.ui.sensors; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ImageView; +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.Observer; +import androidx.lifecycle.ViewModelProviders; +import dev.nuculabs.grpc.EnvironmentSensorService; +import dev.nuculabs.nucuhub.R; + +import java.util.logging.Logger; + +public class SensorsFragment extends Fragment { + private static final Logger logger = Logger.getLogger(SensorsFragment.class.getName()); + private View root; + private EnvironmentSensorViewModel environmentSensorViewModel; + + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + environmentSensorViewModel = ViewModelProviders.of(this).get(EnvironmentSensorViewModel.class); + root = inflater.inflate(R.layout.fragment_environment_sensor, container, false); + + // test button TODO: Investigate lifecycle methods and stop/start the scheduler accordingly. + Button testButton = root.findViewById(R.id.grpc_test_button); + final EnvironmentSensorService client = new EnvironmentSensorService("192.168.0.101", 8000); + client.start(); + testButton.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + logger.info("test button clicked!"); + client.stop(); + } + }); + + setupSensorStatusImage(); + return root; + } + + + private void setupSensorStatusImage() { + // Dynamically observe the image of the sensor status image view. + final ImageView sensorStatusImageView = root.findViewById(R.id.sensorStatusImageView); + environmentSensorViewModel.getSensorStatusImageResourceId().observe(getViewLifecycleOwner(), new Observer() { + @Override + public void onChanged(Integer resourceId) { + sensorStatusImageView.setImageResource(resourceId); + } + }); + environmentSensorViewModel.getSensorStatusImageTooltip().observe(getViewLifecycleOwner(), new Observer() { + @Override + public void onChanged(String tooltip) { + sensorStatusImageView.setTooltipText(tooltip); + } + }); + } +} \ No newline at end of file diff --git a/NucuHub.Android/app/src/main/java/dev/nuculabs/nucuhub/ui/slideshow/SlideshowFragment.java b/NucuHub.Android/app/src/main/java/dev/nuculabs/nucuhub/ui/slideshow/SlideshowFragment.java new file mode 100644 index 0000000..f59d10c --- /dev/null +++ b/NucuHub.Android/app/src/main/java/dev/nuculabs/nucuhub/ui/slideshow/SlideshowFragment.java @@ -0,0 +1,33 @@ +package dev.nuculabs.nucuhub.ui.slideshow; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.Observer; +import androidx.lifecycle.ViewModelProviders; +import dev.nuculabs.nucuhub.R; + +public class SlideshowFragment extends Fragment { + + private SlideshowViewModel slideshowViewModel; + + public View onCreateView(@NonNull LayoutInflater inflater, + ViewGroup container, Bundle savedInstanceState) { + slideshowViewModel = + ViewModelProviders.of(this).get(SlideshowViewModel.class); + View root = inflater.inflate(R.layout.fragment_slideshow, container, false); + final TextView textView = root.findViewById(R.id.text_slideshow); + slideshowViewModel.getText().observe(getViewLifecycleOwner(), new Observer() { + @Override + public void onChanged(@Nullable String s) { + textView.setText(s); + } + }); + return root; + } +} \ No newline at end of file diff --git a/NucuHub.Android/app/src/main/java/dev/nuculabs/nucuhub/ui/slideshow/SlideshowViewModel.java b/NucuHub.Android/app/src/main/java/dev/nuculabs/nucuhub/ui/slideshow/SlideshowViewModel.java new file mode 100644 index 0000000..633af2c --- /dev/null +++ b/NucuHub.Android/app/src/main/java/dev/nuculabs/nucuhub/ui/slideshow/SlideshowViewModel.java @@ -0,0 +1,19 @@ +package dev.nuculabs.nucuhub.ui.slideshow; + +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.ViewModel; + +public class SlideshowViewModel extends ViewModel { + + private MutableLiveData mText; + + public SlideshowViewModel() { + mText = new MutableLiveData<>(); + mText.setValue("This is slideshow fragment"); + } + + public LiveData getText() { + return mText; + } +} \ No newline at end of file diff --git a/NucuHub.Android/app/src/main/proto/NucuCarSensors.proto b/NucuHub.Android/app/src/main/proto/NucuCarSensors.proto new file mode 100644 index 0000000..55ec222 --- /dev/null +++ b/NucuHub.Android/app/src/main/proto/NucuCarSensors.proto @@ -0,0 +1,29 @@ +syntax = "proto3"; +import "google/protobuf/empty.proto"; + +package NucuCarSensorsProto; + +// General +enum SensorStateEnum { + Error = 0; + Uninitialized = 1; + Initialized = 2; + Disabled = 3; + GrpcDisabled = 4; +} + +// Environment Sensor +service EnvironmentSensorGrpcService { + rpc GetMeasurement(google.protobuf.Empty) returns (NucuCarSensorResponse) {} +} + +// Health Sensor +service HealthSensorGrpcService { + rpc GetCpuTemperature(google.protobuf.Empty) returns (NucuCarSensorResponse) {} +} + +// Responses +message NucuCarSensorResponse { + SensorStateEnum State = 1; + string JsonData = 2; +} \ No newline at end of file diff --git a/NucuHub.Android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/NucuHub.Android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..1ee1493 --- /dev/null +++ b/NucuHub.Android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/NucuHub.Android/app/src/main/res/drawable/ic_launcher_background.xml b/NucuHub.Android/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..956b344 --- /dev/null +++ b/NucuHub.Android/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/NucuHub.Android/app/src/main/res/drawable/ic_menu_camera.xml b/NucuHub.Android/app/src/main/res/drawable/ic_menu_camera.xml new file mode 100644 index 0000000..41688d5 --- /dev/null +++ b/NucuHub.Android/app/src/main/res/drawable/ic_menu_camera.xml @@ -0,0 +1,12 @@ + + + + diff --git a/NucuHub.Android/app/src/main/res/drawable/ic_menu_gallery.xml b/NucuHub.Android/app/src/main/res/drawable/ic_menu_gallery.xml new file mode 100644 index 0000000..ff8ce52 --- /dev/null +++ b/NucuHub.Android/app/src/main/res/drawable/ic_menu_gallery.xml @@ -0,0 +1,9 @@ + + + diff --git a/NucuHub.Android/app/src/main/res/drawable/ic_menu_slideshow.xml b/NucuHub.Android/app/src/main/res/drawable/ic_menu_slideshow.xml new file mode 100644 index 0000000..ae51e49 --- /dev/null +++ b/NucuHub.Android/app/src/main/res/drawable/ic_menu_slideshow.xml @@ -0,0 +1,9 @@ + + + diff --git a/NucuHub.Android/app/src/main/res/drawable/no_signal.png b/NucuHub.Android/app/src/main/res/drawable/no_signal.png new file mode 100644 index 0000000000000000000000000000000000000000..c4b74233c763234747c30e94294b9b2a03c70590 GIT binary patch literal 9563 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 literal 0 HcmV?d00001 diff --git a/NucuHub.Android/app/src/main/res/drawable/side_nav_bar.xml b/NucuHub.Android/app/src/main/res/drawable/side_nav_bar.xml new file mode 100644 index 0000000..a33798b --- /dev/null +++ b/NucuHub.Android/app/src/main/res/drawable/side_nav_bar.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/NucuHub.Android/app/src/main/res/drawable/status_bad.png b/NucuHub.Android/app/src/main/res/drawable/status_bad.png new file mode 100644 index 0000000000000000000000000000000000000000..e6f489c540fd7a8d9ec6bbe4d3084307557658cd GIT binary patch literal 12685 zcmaibWmp?su<$0h6)hBZD-Ojy#a)U^aWC!~ihFT~7AZxFYtf>`-HN-r`%T~P$M^5v zJkMq~*>h%R=Zw#s2o)u13{)ai001y#WhB%900g@P0mz83lfLs03)l(X1tR+a8TRo- zHVcRSMsbwUaRC6t!+!^e%#Dv5_9vmMq_(TNgN3Vyv9meg;o-q*ZEx#hYV2sv>fmgd zc`QT(02F|%g!l)~tfOp?v=7sFeWI3sXXcmZ47BmJQxF&@u*E^d+Esl-2W%*eMBG&p zF~Z|NRP*Uz7qm80;gO^ukT|HAsx>u)#jb*D=cbQY&*-F;t7dY?H^(w}Dck3`_2h8m zZdrYqsvwC0FLJjV&kha`Rq|8?{8dGQLk_@;WROCELa=)nKq?G*Z)gEjNxXb`v2Wof zNdN<$YBUZILKUg{{|EQtz~)D)yho0QCqXMfTu4!pF`}>3l$&2KjY55mUZCPi5uAn~ z1nx#yz{jYEOO<0Jcvv_2_Z*&JEKAS{(!wiV2Bg?{wd0e$kSQW4Wc+tU&?jhS0bJ_s zI^^HDSD^?C04Bp(kK{iLNasF(f+A`AIbr`l)apUh!Sz2&<2!!TS1hjTPMOkFqTOoC z-Gw&Oqfq*T6_C8)I=g)6yyrv?Rl!)>$dr+RJJ5}@M>z6V`mDixl5$?js_!Yg+o8Gl zUE%U0%-bopQuiAZ8AFZsJP)sC?ykt>fKEKhV3bDeM)GisYX0Z#B1pJLK@zzQHx?u- zFjqiSOjDPHT8{I{?asbR$IWt=0EJTNV!e90!=uAMZGZ(fAB$3glO2hVb*>)%i#7B+ zP)mA4obzi?2Ia)JKK*Xxm~!5J{ClP$qpSz_&98CVqZl0$Y>0K zQga|eK)d)3UtIf@IfddxK~vA~OWPI87j=S1gtT2-RuYUj$^X zV5~_{*PUa5)4A2tCx`qEVM))*U+1X=ny!0~fKt(BY+t+a-7h$i`Z8$+6)=_*GNqa$ z%dO;VQ9&Qh$v%wnPh5VBSpM$UX6^H<{dlWE74>cpza|;)E)PgWs{hazlrV~UI&ps~ zn(Z*d!P~NoPfWq1NPG+u8*9)Kuv8@J9g?M96xf+xc@9?ZO=9;Mx2Zp2l3tgp_+$?+ z%>|(Gl6I^edf5$KFHL9kxgS*=on84w;6P7J%9ei@Q%8C2)idp7zm`)i3pC#@z_v$2 z1dtlU>X^RMna^Z?;Jy@^sHb3ycrw3QA{!ii#i9jA3#|3L`3Wa^r{jA%#ugrjLGLj0 zXLE=#gxSE&^=nQ)4WFA@pz^V55(YiGkgqYjE&6TBC+HS&T}3`Tg#s3&0Pd+a_T_vL zS7Qeg+rG_$hMa9~B=7aZ-;cQ9;|%VU@jkP=O|p&q-|DIL1`DVhM7hzTZ3XZYYGW}U zh&d=kRoofS!>iJDPXFGuJgsNQ?Zo%>S6Ymrgo$R{B-{dMBZzcy);n3@;Q&IF%SL&B$Jo z(90TC&WmIGaorFdZjD7wM{WR5qIRZo!r)s0RsFPqga+32@1lOgd9QtBqZ>FbHlH8w zQX;g6zH#qrg0a?-Deu7^AT2;7T}&WLDaUt*X~+UMZdhQ2AoT;u?^AI?-?Iq?UDA;+ z2bb9>27`FWlu{rjM_S}P#g@95U~l;b5)RQXZh!Q`^miIT5%OG`e{PAPf=}bYQQ8y1uEK3p><`#=qDBlM zXXCd7m#FfEQ z1YjaUz?@`38zGZS$Yh|qPBI2or>cX9JK*HhmdkD}1X*%prU&Gac zStR_EKT3vwgYQ85E9Y{9fC%pS^f4@81WxD&O_2&bCM{r35iA2w2T~7Y?BIA~wx_|+ z38Dp-D1yU5bgTQP>Q2d zW?0*d3)@9$gRmgc@W&n8eK$I6GI3R$wDj2#>BZ=BN?-XH<39(_=X7tg3!vxx_IbiGbq?Lw?4seOP?i$nB*guDSPR!_u8x65X^8FK8(ox0yd-_^anKeF^*p}A;RlPHzQo1$= ze*-?w&JCe~_8%e0{w~i`&_#J{|KMcUylSYlqelN(8rONvZP(ay^x)V~(;5NMz}sJs z{x5Cs`QRK^KKKYJKW$TeCn?P((!_2Jj)6@pM|zG{>diW4NBQmLSKVZ~3xpQ^eKO5@ zHL+GuTx}Zf;ABAkapv7_j%i%n);?h$M@b`QI-}vR{U3#TuCf3!O?j*2e9d5d%75Ht zwu&I6zgdI)TN%}*=_&0Qw*04YPWEGer>1)5ck)ZTm#(|+ch1_8{H2U5&;v5Rs|44> zaFBv?06z)wpRBjFdalj|UdmrS*|Zh$Wn?rzKAYy(=PUb`#Wb8WDY^Meb|CA(IPDS9 z^G#)wkCKxbSUHZkvzFu&!Mxap-SJz1*iGnZB-57}&d2g$fhHs``wNVXBv4P;R!KZY zBe*h~OsxX!3Dv@f@pQ%gvZaAA5+yl3l8jGrEU2E*2~-0pjQ(t*D919c*>Rg`GPKaq zz>6U};g&!7HDsNQ93>8;;f5xds9WFTMdo0A0AZCIU4;c^E?JYC@|>lr2Hl!F1qNWK zGvoz-MG?zndqHd5o968x8_i6NGdI&s`0rNuS7ay_6`3b-+M3cs)cy5(?nWGCKM@WW zeh8HbvS%C)qyR*|KG0kt50mSU(wN&Xh*G`RX>ucl$lTz!FhtRfLhUwH)YYoLF>8>_e6YSxFsvlfBXsJ4oz(u1h7%WBpyf zjHc-fA0G7rG7D5{H#|UAr3DYDj@7CQRfPS_LZ5^XP`>R=?_ki`YJt+?%TA6wrgII~ zB3?!cr#oy_zMUcjrh$b5ndsYDi#9Dzk5Q;)!@u6TS;{ljHD9}V9j#AEJnMTSOW)Lq zT3Nd}cBwnK+(eOcTHgXVCe3URX86kyxvk5y_x#2Z@fC_%5-9$!VY(o@gDvK-f%aIG zRvdZkG#>xKX6$#1lKSJ0@kQ?Yiq18P9=q=?8iEYSUrWjZF$pR-T1KfId`HUC=}#Mo zS&!peVR49qItY|=CyM1PFv%ED~VWD=k^1^2TX0t6v z66!=+zf%dEM!|SpsW-V+J@t%`@zLYFN@TE^{O#1?Vo;4b{mR5tXE%n=osUl4_E>w7 z?`p4=_%}YBTr?HnJc%6I#?w!@X)jGA+2&PKF*Q}IZv9%wObV>CakAMf)bKrKf zEoQhk1}~EOv>2%UdE5TVY_IMh8*9*#K8BKot~&3IL~*$M@#WK$K(>C%5zw5W_vG)8 ze5bXB(MASZj1jjkuYJRmt3>?X-?uEzfz+3X>1{LKi)TS?WF5wH0B0_HUO1By>B-Fl z0~KcO5g3{B``X)qV%e6SA!&7K^#l?^B@u%!3B8fAmn*M-DjBkRRNP8OPea6&1ag=| zkl~vM`?Cbx*?A4wG1TE%^4@~Olwo2LA47ccywgkGbqf$|A>$2m*YW8IhTgw0mwsO^ zZeRD9_#rNI8L-3N63{lVQgIqysJEt7QTJp5u8~T5tj4&X-Kzp>haWz|IbZ%Yfayzl zR2Lub<}Za!-^&M2*tDkh>)Wp;)V)rB)nH@S!{s5PXUZ9T6z(Cg1sXt;mqh4_RTtf9 zIOL0OU7cLzUJRD^$CeJrc^khxR0zw%^v&4bIIFHNG~xCLk4@qXkvcP zQa>F|^xp~@`fF^O8kNy^BtihpF4+EvQvwbV414Z(4m6J$`+kZ^HX@Ozh z4L~+)%SA&Q-yXv~^n@Mn%8FQmECjP`$|=tsF66A6`3^Hb#`cekLH5_~@Qwsu(|;%f zqcP+}XBYmGR#i2%p9yxDw?pFaYaWcuD~Hc`W5kk;OY`~Rec=|V3m1>8V2q3i$GczG z88aW$Vam(23~Q&~xzj0HS8O=x(a5?f7DzptF~{+}&i(a#tpH z$K-C(iCk3Gc~N}NvR;8oqpZ3-Q(W5}0_Nj`X*<&U*5}`dhA$l*rF7_LGBDSNz=*T<_ayWL%rhAck^l&$h6L*IQmtRA7XsN~{QuqaN^gz;mf^)V7gwKkNw^m%<}V7Qszdg`l~HomHFr6)JR%Ejk~EB0jkKE?s+%q(W}-VQSv$Zl7s7Xfn=6J4&=l1R>!*b;RwDQzW@-|$!!>K zc7R|x`&FCTz@FLw?>ksn&i7JuU_63s#jIOHi)9fatS0CGa&vRrW9qQ#=v|xp5itvVnW(nRRJgd+%dhNhZnnzUm+V>8 z*C+@c^Sgh^You7Oe(;POUS2!Svf_05Y#_K6G0DikF;nDq#iao+5%)bsleOtYlFWaD z%RxyQsa_tlrMe)g#>u?O{&YJOWFqL8lH}aZ#!46cECLBH?nu?`+ZeK_&-MY&6Wtx; zBfzxsmZ)pe^?ly=K>2#oG5)TeFP(e*4kK)(pA z&x6W@eNVGFk|z`z7XEAblKKy)rJ+aF%ogW%7Ht)?25(xV24i@GEUcUm!iMaV(o4AdbPUeK6^0;!8Mye%ySL>yCyLb8YfYxsIZB5|#&iMf=N53r1 zrkT6fC!^?O{wE(NJ*CLA{Nge0~bcb}tK%V+3H zlXK(Va+I)meZ!(^*){>?>A{?^&3xR;$rZ9ur}S^N?{U1lEiDt$Qs3{Gy;y*FEof`< zXyT;LC($0SCagS4G zBYW9DJ-nG6>y*)B*lX#OQ@?QuG%|ml^m#~VjDE*l#qr@}ZnDrqETv~CdC$H4@SW?Y zlmxMDY-c&GhYf_8;mYW-6tx0(Ti)~r%WR{V-zDf~y5T3}5V3Nz z=gpl?W$YkWxE&RIiAGjgG4hi*Ud{SQLA>cxmW36`+sIftvlJ9VMOdvZ1s`R2hp77ll8) zAQ_$Fn-r|Z$x6PO0wXD!y2M0|^|kAEpL+Hj zvBvm;gzqIpSuCXLiIWNI{G!}}FPbxMKA~NEn?XIcjW+l2xjJWKw)e^}de!PO+#cCC zeU|3#3)chwUXS*7akVyr4T?x)7b6pY3IsuE-=^m*IGv2e*+esNh11IL?KHcNnA#K4 zGT(1}v$1hMwhs8DX_4?90LoUXMlEmHD#|xtwun2fC__;{;qRI@?T|$R>iL+QKs>&w zxvvE(8m1K;d^U5i%ojDA_TLQogLp7!1j!0NLsVFlYd`;)3Y9WkQSq2Fiww_{TGLX? z#37wG!m8Qwc_8MOtWZUNrN=yF#Hd1-+4Re!;^=|D>sTm85U2ZiZ@ev_enmuVSI5wq zG*|n|L$}89sKHiMSM{joVdTM3a6%c-B3)a>P0Xdsu38F;nR^(tes|1t=mVZWr})(No57b=0YcIQNU zl)8;yhYx5bYKx=1)|IaS8@w^49c(DkGZQ#;`IOuUV$#RHoRS9ZU-t(esC%0mO~f^* zfXAeE+DpCz$VPJRW@utw>S$<~A5@km2Iivis4J=~P1O}iO7b~csdeiBZzSw&2lihbGm7Uc4cFFkgpE( zlone>y(j1xevj(qX=b*0{PGlu@wgTCiEklv(V9ckP{jU?<)$UV@b~JsM?Y`RPz(sp zhBQZ+=CV^Vi|GM(N(pkt!g^Fm6gsQ8=gGy5sLi#P*k6dOI*lc*7eRxRC-H6zo^GYr zR2q$^`!lUVE%vrPJ4ipQY}OJ&O6ODwT0VGrv-aFcyLu{zzJw8G8mBS-xlvU#{HzREJRWj)TRo32?C&q7%V{CV$~LA_G@;Z` znT1z^39h6!6EbsmV?HpbOSx}i00Cu?g5e=RVj&ZGd~HmEb!Gii5fbhxR)eQdfYu?A zy-q+c)v;c*>@((b^4!gE#dU%t%4TVo92k|!rgb<(;v?QaGi7VSB#FkojGrq zH2T~^DYQ5Bj>$xzi;ej~rXvT5UFfE%^Oe0usDK<$X;cZPl7-hK2!wgro+IZxIw75$ zye<4yn0%Jb_~@jKO~|n(its1As%n2|qsimS0-y8;4UE+em**e7Rm3Y5F9iK?)+_Z` zG8S6i*ab+#;fvjH5bUV~KqA(n%0w!$+&$s~Ui%kp)2P4T@*Y_fW~SLoWb_w)Lrjiu z>R|q56FMd^eka~|lsF>OjY%~18{Dr=A2OzbUTcR?;mORrpfiEQq=7@>xgZS&NT8V? zuL&)%ivpc?Ay5dRN|KqVAUX6;iAR=H1mR)F{Ko4bJ6eV!QUkO=)d ztWty>L!3YN!w^Zu7KqIMd~|8j{uxhfmm4t(`W0U6CrCn2dImv;+g3RWldR;dfnTHt zMjq8REGzK4QikqJ3at0oA|&Zf^m>+?4Mm4v+K0~=t9oa9 zV>wlCg9xtUMF}ST7FiB7p7p6qAk)eBz5Cit@oajXH~q}hXW4j$g;pVnL2gO`*uZ14 zXyXcg@9f&J+uV-^|4S9#_il@&O`Ezx0v9sjJ7ZOP;H~JaTsGp0!m;dR4G6l5=&k8L zvy_%>oi(&yHpq&6lTrk^s!{_8Kz;Wu>p~z`!WEae=wq*CXwwq}6cnailf)?$%IOdJ z2uvYUcw>D|Q<~4Eqv=j4+CWk>nEjKC*%m!X_%}zq?%ozq6@EktVic>xf&S=BS>(W| zL~i7kUXitj1>%p#Cnxs{Wn{+e2*^*A(YYKTb6q5P;!JCI0XVBzsOyI#YDGW-0>Sb;~QfQozYTRNkt8S$bdy9x|LkgVjY?C!KG#~l3P z{2-s(?Nf#C(2(e3knYn6J|2(e0Y2sYYX(8cYurkmir@IzRI!nNx>AzD>(m(=6AzuT zQcbenTt9`BzHyx=_i`FBAwkUV%|P^1?o4AHmtEE>v~d@hFFvVj>_3Q-Mh=Aqk0@eO z@nfa7g}3e3N|t6V7Jp;}eFk1R4d=cLSC$^{jPte|9V{PProKG87GJk2etuK}2`%Fx z3J;}Zc<0}T5x2H^1{;Cg!7O48iNf6AaFMbzr*89taTQHaW6mEo0yF1o5cnKSg~sJJAGnGQpXE^x!F>^U&am@u4TTk3ksLQadB~c$34EN2@zVb*`99G(XTxM%*k%U9xMIGMeSyfPo+7T%S(x? zX<0S%3pp~Q$qiN6fUq7-7ox9HfNCVP;Ir>gb_q2`OwE~&>Z`u)yCThCoiX!P@iYZ( z+|~*Ob9S&*C-;4f%_}tMwo*s^UvG#@ko1~E@VtWa%5u083grAJzQ}%VS2|+O=Vf*# zuBJiVAQndK@t}!IL~x~s9O0GEB1{QNg(bQfryxkJ2@X|p6kMJ}_0LpE;924bef-kD zaksa5%kXLOt2R^n;PIv>4FzShWsf}XE}GaBEbkcx_*TsB9>67o*d?(`wAW2!S>ASM zjGavpbQD@gFtdzo)Mw!x3RrhXzrnWLDE!Q9mtFs2qOQ)~M|2`&RaN+X`40-i{?5x7 zC9nd{5XVN7V*;DTP?>S)Fc)01QSh)74jwqs{f^P;_tnc9d}^{*P>Ak1-2Smd2j8$$ zz-}qVcHiS#cCBY(Dmx_j%dDAxi1&GDU*s|m0S%f|t%_Vlk~U^Q%?(xoDB!P`o8}U5 ziWfWpY4tuX>Lruydvw8B%ei7#zPs9AIVbxWbF=G40i{8HEU(_`k>brUqsPS=YiGr% zC$2LH4^5%uzF)U$0y@Y>>2b0o{asdF=^S@qzF|R~7N+NJ&QCs}ax~qSg z+|D?v$8cFCD!P89_g=JDg-A|hRV-;XJWftFR0Kut2ES8xAFgy@G&^2s9`p`s7@8!2 zDyj{%3b)C^kLg$t>~TN-`Va%g%f|W)^U){dB4z&ccdqyP8q{1g7%-WOeav-zKB~hw zESromPM_V#lt6~1b$@{?SH%#tu17Cw_#++Przya~2bhx`nBSDXT|$&mVrx}g+Gq7L zXI6)mXh+Y=1y_S9@NB&J=6UpHez-Hs9rQ&l1y+)WM|7K2VS#@e&AwpQZT=lMH9gi< zE{lbQPfyROzPA2_dB{QmA1!6>4fENvY=6b}%dtyA{uSgMypfBdu&CxV2g5ucr@}WZ zxgLSVLdHCIu1Sw zBS5|$iGG;U;C^^h!Hp`3>E+kFw*K4#q+#>8Vgrm@l&fezdu=hND@D*bf4|McMQQnl zYZHC2cI{+ThJyL)qTW;QB)DOkK@2<3*Fg98vG)?XSgs7?w2eFcFI?!&csAk>H$c*A zz4!FxN^A~WiG&vTgvzgV5bPFab0@9{hes(DrA`#1WE(gS;-t458)&%XaV(jUb+B6) z^rJ?+@5@8ZD=AFoPUcSH=2l;xnz&xNsyQf4$1kE0?v?Y7{yBIPU4H_1cy=ipzK?Tl zf7ZVo^x>WLD}B&%s#?h*k2J-v!5!9M8KmocN-Ui!9`_u^&)&2S`$c4#l!YJApweSM z0a$WM1VL$B;H+mO)LG-jH(>rXJ`BZ+-g>_wwx34hzvc38U2@~CIJiW(LN;n98XFzh zA`|l#_-(ZesGnYV-f!JYm49WmZd{wjNz3 zS(g`dh;Wh<>C6kA4OAUi8FnS@@L~u2o9%?-Dpty8HwhWH%7AoS&0Um^wG2>*E`5O4 zxi+l&^w3{BmRDO9ky?MacBj}3sn>)=4i9WSIX9L6;C-)t_?w5G;sZ~^*iLpu^jn>{ zR5cp{>Tr{H2mmZ62zS~zbM~*uV>G}JF!!3XtfXwMZ8|f(wfTcXIH7a&pv>C$-y!-c zV>Lqp-$vkU>rcayf9*Zt%QMm=4&*p?$pD8P_7uen8y%r8bn0etE&RK`do7Oj>*9BK zj;{M5hLveq*}aLTh+IP4=Th)7ujmm@{CfhWhV9&e9T~iCC2SS9lIrm!~uNr^=dtZgOx~;O^Bc>G@UhFhgn`P{^L`*|VS1l&js_&NPVaLs(-@3k{|(n(}gK!0i7 zkGmn+Y#5xqFikd=Wi%Lqurp7ObPs)q9hEazkm8)L;-G2N*(smjD`+VWnNH?r7SQg` zgG**+5tJ~%4593?*ox~yVlQn3rU#MqWSyxh6i9k^FU>Z3DF>MJZXCDrro9!f!69mLOLyY68|45=nD{^? z?Ib-rE45^WtjxrwBj*=WOlx8fQNC$8HZ!W%vpp^F|&|cOT{7Tn+k`8!9p}GFV~UH z!*}JRUq16ukihAb#?= z`Zt1~LojAGmV9LS;`{l+?-1>!vZ97xoR9Z?Gk?9w^xB7i%-57$G>0vKDGK%BTFPd( zXI>L`+EkF}J7GxS(bJxePmK?y3uI6-E^C!u@xnqqGE(kvZc8N-?;IzC)-tlBWmJ4# zmWOexBz43`MzQT+;hg)JWfUtq{RMsX(Me+W%b`5LMe;>x7@^s$w6OL4uw(xF5LB42 z{|_u?QS8jsc$&r{Jyi25i|so3qTQfSYWR69WnOL#(Y^vyn@iCR*KwrVhs$E2naj^u zR*#UHs>NY?T zCVemZ_G}PpOP%~TD@zS?j13V(yLUGM@^W6PU+p6CT3!Q8m8cBkHn^5NHTy#m*o5?7 zkx5|B$QRYMOA0Lqy`d>wB&4XJLagX*QX9Zul@puft^2*US`;-C>_!nob-P%5DDB~_ z@~q?Le{$-b$5ij|bnV&)XZv`}#x$Npq4!i=DLf7>4@hc*R zrO_Gnz>XYa05ViZHRK~?xge>oLkD_n7U1DWtuCTBFd{$;9+wL0`mJ-3auM$npteEgZ4hMx>#0_uaYqq+S9!a zxw-Ae6uUu$=wm*1{V<3Z4!kRh&DYZR>?vjv%7^&_lWn)LwC47-M|TZL=coY-c*C~_ z04)E+3ku+{(K1su8mS#euk3qRqLW-@bg)@VVrw%G@nM|X0Tq?BJU`P?{KwqF_B6H% zaaHHb5&3CJ$wWXYUf@52nJDrSTNk!C(Ah%7rz)qjXIYb%14RK~MH6@QM|i-F4wp^g z&4BrnGn`R!=L*a;8gI939UtE^cU^5(oYv@|f|&tW4WOAFnM`2FpbOD)^pr|eui%va zpRRP1pHVw8H0YA-K(Cu6=L56;8|vf4k51?;Ys|`~^hQo0n07DPl|;>X@SNPs_sQKu zIUOyFw(tXM9*BnFAKso=jlRb`?Zeye1||IiE1US zs{rmh5P$_)1cV}qpOIxX(Ujvz^JWkrSzB8gS%NP<%300JaIBi8ProUD`~%BJdW*TL zIs7x~;d*`E>Ag&q&Xa9gCpC%M`R)DDVv{p<%rOCj-|I#>x%qwRNjw4g|0v!C#RM8` zG_I7ww~`~eV0wADJ(O|LWa*o3`LhN0N($lqC3!Dsk*?6UJI;b}k%H!*6^RdGigYX! zJW_->UaUfniB*G#3-FPH#7mPNt&cR1^;+i>T^(LGhCb##jK2%X437Ti39Lg?p=e9O zMSpTSHcaLCgrg%pq`)g$A6%|@ZMFAuv{sBYL0k*#5_ptiGXGW!0(flvrE`547ZGMl z?2}Ga$trk@eV2HziG*1;-`RCgKe0b=xr4E)%UCD}#)brE0VGn$9N3-+j?KY8r)h4d zzqT!M+X4MVwC%5#$JdjD8mtL!e$Ed)BgUz<2trrn8Og5_ts}{>s{c_>2L2gUf1}?E z=3|lx)u)x-?-=8(eaPp#{L&Fnf3h)>Ogz8tg;?~nQS(ltXBmsO0AZCK5?%w{fif$P z5T_+|C8746wq*|M!$XowQ&}FK>HyJM?x& z#?>9T2Zk3A9L?!goAa?=O*%rMVb4YxQn}`9Sb?Gv8`=eHz3J6J=Ukd}fmxbz^0_c# z`TGQN@&liZ&a{DTe8a!hVeJl!{Zc2KJPqsj?Tbu>AKX?ugDY_XSVPO(^6bw#(7sYX z&BWD55m--=Xk4O?xl!!8+h>?6@O1A|dam&!$9UC1b^Xhfw!G;1M&z9$HqfaCyrK?% z6U>xi6xuNRCpKmc)^gKW_K`JzGSSacA6b2RVn9&v`eLXzo0)gyPpLGcBl#)j)(CM< zaNWNpa3VT=qcQ>OgQBN()PeOuu?!WmcT!<`z?6p1EXd-7)!g4YMDVre<&RG8#Q;di zNhmKiB}|Ht(N10T)#2i1kz&oXOR^c~_Z0eNO`Y9|ijC_%83N6>G=`Qn1`d~yv<>z& z-?CB@L5rZGrP0Fi;@!v{#=%%99d#WJPF#(DkQ1?@W$L(K&1JBHhr)myEn_!HjE%0Y zj;iYL`T5(FWG#;N+Rv>y{D-^as4Y<2K!=J7))Hh9YMn6aD^o&HF2 zPCQ|&K<2?_0VT4Y1^|8Kr8M#gRGK~nJy;*-ln6SZi4hIESGF-sz~ayPdu-; z(w%cJb^Xruv8CZ#LJ^BEx5CtDj~F;XKN9H_)44EO#S1R*tk#@@G1Sler=$ zVANrmba$kkBn@LIMXeltGv@U-$q%SvmIX=Njh(R{u_0#bI6=i7C}Oc}$7emy=XV_o zVmL;k>&;%r&*wNDo;j<+!;KU6qlhA3)Q+z=TJek}J}7|}3x_99C5%v6#s6HNtEI{_ zew=O^CGB`JG;9{sg>pBR9K!1FFg1WGNst71!rENmQz=NI1`jIXO^fo`oRWV{xYiOt z@Ydy0&2Ku(H1$ib2L=3os)G1YJz!;s_rX|%uHnDG)}K5D!gWY@m>#=IQFixtM2S6P zhv_=qEuO$#yWh7F%&Pk*zy0y;6rUEL4923u=R^Dhf4#B4iBy**wzU^R#Hi#9AfnOe*io5MtcAN literal 0 HcmV?d00001 diff --git a/NucuHub.Android/app/src/main/res/drawable/status_good.png b/NucuHub.Android/app/src/main/res/drawable/status_good.png new file mode 100644 index 0000000000000000000000000000000000000000..7e047eb5431f8178d8cb58b2ff9ae382edd57b04 GIT binary patch literal 21390 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 literal 0 HcmV?d00001 diff --git a/NucuHub.Android/app/src/main/res/drawable/status_netural.png b/NucuHub.Android/app/src/main/res/drawable/status_netural.png new file mode 100644 index 0000000000000000000000000000000000000000..2098f0c16f6d221db913bc26e10bb35e29cdd849 GIT binary patch literal 7422 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 + + + + + + \ No newline at end of file diff --git a/NucuHub.Android/app/src/main/res/layout/app_bar_main.xml b/NucuHub.Android/app/src/main/res/layout/app_bar_main.xml new file mode 100644 index 0000000..e87580d --- /dev/null +++ b/NucuHub.Android/app/src/main/res/layout/app_bar_main.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/NucuHub.Android/app/src/main/res/layout/content_main.xml b/NucuHub.Android/app/src/main/res/layout/content_main.xml new file mode 100644 index 0000000..e1e04b1 --- /dev/null +++ b/NucuHub.Android/app/src/main/res/layout/content_main.xml @@ -0,0 +1,22 @@ + + + + + \ No newline at end of file diff --git a/NucuHub.Android/app/src/main/res/layout/fragment_environment_sensor.xml b/NucuHub.Android/app/src/main/res/layout/fragment_environment_sensor.xml new file mode 100644 index 0000000..2cc9746 --- /dev/null +++ b/NucuHub.Android/app/src/main/res/layout/fragment_environment_sensor.xml @@ -0,0 +1,30 @@ + + + +