NUC-11: Finishing implementing Environment Sensor activity.
|
@ -5,6 +5,8 @@ import android.util.Log;
|
|||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
public class EnvironmentSensorData {
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
private final String TAG = EnvironmentSensorData.class.getName();
|
||||
|
@ -17,9 +19,10 @@ public class EnvironmentSensorData {
|
|||
public EnvironmentSensorData(String data, NucuCarSensors.SensorStateEnum state) {
|
||||
try {
|
||||
JSONObject json = new JSONObject(data);
|
||||
DecimalFormat df = new DecimalFormat("#.#");
|
||||
temperature = json.getDouble("Temperature");
|
||||
humidity = json.getDouble("Humidity");
|
||||
pressure = json.getDouble("Pressure");
|
||||
pressure = Double.parseDouble(df.format(json.getDouble("Pressure")));
|
||||
volatileOrganicCompounds = json.getDouble("VolatileOrganicCompounds");
|
||||
sensorState = state;
|
||||
} catch (JSONException e) {
|
||||
|
@ -36,6 +39,32 @@ public class EnvironmentSensorData {
|
|||
return sensorState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the air quality score. The score goes from 0 to 3.
|
||||
* For example if the temperature value is abnormal but the rest of the values are normal, the score will be 1.
|
||||
* @return The air quality score.
|
||||
*/
|
||||
public int computeAirQualityScore() {
|
||||
if (getSensorState() != NucuCarSensors.SensorStateEnum.Initialized) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int airQualityScore = 0;
|
||||
// Ideal room temperature range is 18-26 celsius.
|
||||
if (temperature > 26 || temperature < 20) {
|
||||
airQualityScore += 1;
|
||||
}
|
||||
// Ideal humidity for humans is 30–70%
|
||||
if (humidity < 30 || humidity > 70) {
|
||||
airQualityScore += 1;
|
||||
}
|
||||
// Let's guess that ideal VoC resistance is > 150
|
||||
if (volatileOrganicCompounds < 150) {
|
||||
airQualityScore += 1;
|
||||
}
|
||||
return airQualityScore;
|
||||
}
|
||||
|
||||
public double getTemperature() {
|
||||
return temperature;
|
||||
}
|
||||
|
@ -51,4 +80,16 @@ public class EnvironmentSensorData {
|
|||
public double getVolatileOrganicCompounds() {
|
||||
return volatileOrganicCompounds;
|
||||
}
|
||||
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EnvironmentSensorData{" +
|
||||
", temperature=" + temperature +
|
||||
", humidity=" + humidity +
|
||||
", pressure=" + pressure +
|
||||
", volatileOrganicCompounds=" + volatileOrganicCompounds +
|
||||
", sensorState=" + sensorState +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ package dev.nuculabs.grpc;
|
|||
import NucuCarSensorsProto.EnvironmentSensorGrpcServiceGrpc;
|
||||
import NucuCarSensorsProto.NucuCarSensors;
|
||||
import android.util.Log;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import io.grpc.ManagedChannel;
|
||||
import io.grpc.ManagedChannelBuilder;
|
||||
import io.grpc.StatusRuntimeException;
|
||||
|
@ -17,11 +19,10 @@ 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);
|
||||
private final MutableLiveData<EnvironmentSensorData> lastMeasurementData;
|
||||
|
||||
public EnvironmentSensorService(String host, int port) {
|
||||
this(ManagedChannelBuilder.forAddress(host, port).usePlaintext());
|
||||
|
@ -29,31 +30,40 @@ public class EnvironmentSensorService {
|
|||
}
|
||||
|
||||
public EnvironmentSensorService(ManagedChannelBuilder<?> channelBuilder) {
|
||||
channel = channelBuilder.build();
|
||||
ManagedChannel channel = channelBuilder.build();
|
||||
blockingStub = EnvironmentSensorGrpcServiceGrpc.newBlockingStub(channel);
|
||||
lastMeasurementData = new MutableLiveData<>();
|
||||
lastMeasurementData.setValue(new EnvironmentSensorData("{}", NucuCarSensors.SensorStateEnum.Uninitialized));
|
||||
}
|
||||
|
||||
public void start() {
|
||||
final Runnable grpcPoolingTask = new Runnable() {
|
||||
public void run() {
|
||||
lastMeasurementData = getMeasurement();
|
||||
try {
|
||||
EnvironmentSensorData data = getMeasurement();
|
||||
Log.i(TAG, "Got new data " + data.toString());
|
||||
lastMeasurementData.postValue(data);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
};
|
||||
periodicGrpcRequestHandle = scheduler.scheduleAtFixedRate(grpcPoolingTask, 5, 10, SECONDS);
|
||||
Log.i(TAG, "Scheduling automatic update.");
|
||||
periodicGrpcRequestHandle = scheduler.scheduleAtFixedRate(grpcPoolingTask, 0, 10, SECONDS);
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
Log.i(TAG, "Stopping automatic update.");
|
||||
periodicGrpcRequestHandle.cancel(true);
|
||||
}
|
||||
|
||||
public EnvironmentSensorData getLastMeasurementData() {
|
||||
public LiveData<EnvironmentSensorData> getLastMeasurementData() {
|
||||
return lastMeasurementData;
|
||||
}
|
||||
|
||||
private EnvironmentSensorData getMeasurement() {
|
||||
try {
|
||||
NucuCarSensors.NucuCarSensorResponse response = null;
|
||||
response = blockingStub.getMeasurement(null);
|
||||
NucuCarSensors.NucuCarSensorResponse response = blockingStub.getMeasurement(null);
|
||||
Log.d(TAG, "getMeasurement " + response.getJsonData());
|
||||
return new EnvironmentSensorData(response.getJsonData(), response.getState());
|
||||
} catch (StatusRuntimeException e) {
|
||||
|
|
|
@ -28,7 +28,7 @@ public class MainActivity extends AppCompatActivity {
|
|||
// 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)
|
||||
R.id.nav_environment_sensor, R.id.nav_gallery, R.id.nav_slideshow)
|
||||
.setDrawerLayout(drawer)
|
||||
.build();
|
||||
|
||||
|
|
|
@ -3,25 +3,78 @@ package dev.nuculabs.nucuhub.ui.sensors;
|
|||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
import dev.nuculabs.grpc.EnvironmentSensorData;
|
||||
import dev.nuculabs.nucuhub.R;
|
||||
|
||||
public class EnvironmentSensorViewModel extends ViewModel {
|
||||
|
||||
private MutableLiveData<String> sensorStatusImageTooltip;
|
||||
private MutableLiveData<Integer> sensorStatusImageResourceId;
|
||||
private final MutableLiveData<String> sensorStatusImageTooltip;
|
||||
private final MutableLiveData<Integer> sensorStatusImage;
|
||||
private final MutableLiveData<Double> sensorMeasurementTemperature;
|
||||
private final MutableLiveData<Double> sensorMeasurementHumidity;
|
||||
private final MutableLiveData<Double> sensorMeasurementPressure;
|
||||
private final MutableLiveData<Double> sensorMeasurementVoc;
|
||||
|
||||
public EnvironmentSensorViewModel() {
|
||||
sensorStatusImageResourceId = new MutableLiveData<>();
|
||||
sensorStatusImageResourceId.setValue(R.drawable.no_signal);
|
||||
sensorStatusImageTooltip = new MutableLiveData<>();
|
||||
public LiveData<Double> getSensorMeasurementTemperature() {
|
||||
return sensorMeasurementTemperature;
|
||||
}
|
||||
|
||||
public LiveData<Integer> getSensorStatusImageResourceId() {
|
||||
return sensorStatusImageResourceId;
|
||||
public LiveData<Double> getSensorMeasurementHumidity() {
|
||||
return sensorMeasurementHumidity;
|
||||
}
|
||||
|
||||
public LiveData<Double> getSensorMeasurementPressure() {
|
||||
return sensorMeasurementPressure;
|
||||
}
|
||||
|
||||
public LiveData<Double> getSensorMeasurementVoc() {
|
||||
return sensorMeasurementVoc;
|
||||
}
|
||||
|
||||
public EnvironmentSensorViewModel() {
|
||||
// image.
|
||||
sensorStatusImage = new MutableLiveData<>();
|
||||
sensorStatusImage.setValue(R.drawable.no_signal);
|
||||
sensorStatusImageTooltip = new MutableLiveData<>();
|
||||
// measurements
|
||||
sensorMeasurementTemperature = new MutableLiveData<>();
|
||||
sensorMeasurementHumidity = new MutableLiveData<>();
|
||||
sensorMeasurementPressure = new MutableLiveData<>();
|
||||
sensorMeasurementVoc = new MutableLiveData<>();
|
||||
}
|
||||
|
||||
public void notifyNewData(EnvironmentSensorData data) {
|
||||
updateStatusImage(data);
|
||||
sensorMeasurementTemperature.setValue(data.getTemperature());
|
||||
sensorMeasurementHumidity.setValue(data.getHumidity());
|
||||
sensorMeasurementPressure.setValue(data.getPressure());
|
||||
sensorMeasurementVoc.setValue(data.getVolatileOrganicCompounds());
|
||||
updateStatusImageTooltipValue();
|
||||
}
|
||||
|
||||
public LiveData<Integer> getSensorStatusImage() {
|
||||
return sensorStatusImage;
|
||||
}
|
||||
|
||||
public LiveData<String> getSensorStatusImageTooltip() {
|
||||
Integer sensorStatusImageResourceId = this.sensorStatusImageResourceId.getValue();
|
||||
return sensorStatusImageTooltip;
|
||||
}
|
||||
|
||||
private void updateStatusImage(EnvironmentSensorData data) {
|
||||
int airQualityScore = data.computeAirQualityScore();
|
||||
if (airQualityScore >= 0 && airQualityScore <= 1) {
|
||||
sensorStatusImage.setValue(R.drawable.status_good);
|
||||
} else if (airQualityScore == 2) {
|
||||
sensorStatusImage.setValue(R.drawable.status_neutral);
|
||||
} else if (airQualityScore >= 3) {
|
||||
sensorStatusImage.setValue(R.drawable.status_bad);
|
||||
} else {
|
||||
sensorStatusImage.setValue(R.drawable.no_signal);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateStatusImageTooltipValue() {
|
||||
Integer sensorStatusImageResourceId = this.sensorStatusImage.getValue();
|
||||
if (sensorStatusImageResourceId == null) {
|
||||
sensorStatusImageResourceId = -1;
|
||||
}
|
||||
|
@ -29,15 +82,17 @@ public class EnvironmentSensorViewModel extends ViewModel {
|
|||
switch (sensorStatusImageResourceId) {
|
||||
case R.drawable.status_good:
|
||||
sensorStatusImageTooltip.setValue("The air quality is good.");
|
||||
case R.drawable.status_netural:
|
||||
break;
|
||||
case R.drawable.status_neutral:
|
||||
sensorStatusImageTooltip.setValue("The air quality is not great, not terrible.");
|
||||
break;
|
||||
case R.drawable.status_bad:
|
||||
sensorStatusImageTooltip.setValue("The air quality is bad.");
|
||||
break;
|
||||
case R.drawable.no_signal:
|
||||
default:
|
||||
sensorStatusImageTooltip.setValue("No signal. Please ensure device is connected!");
|
||||
break;
|
||||
}
|
||||
return sensorStatusImageTooltip;
|
||||
}
|
||||
}
|
|
@ -4,46 +4,97 @@ 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 android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.lifecycle.ViewModelProviders;
|
||||
import dev.nuculabs.grpc.EnvironmentSensorData;
|
||||
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;
|
||||
private EnvironmentSensorService environmentSensorService;
|
||||
// ui elements
|
||||
private ImageView sensorStatusImageView;
|
||||
private TextView sensorStatusText;
|
||||
private TextView temperatureText;
|
||||
private TextView humidityText;
|
||||
private TextView pressureText;
|
||||
private TextView vocText;
|
||||
|
||||
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);
|
||||
View 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();
|
||||
}
|
||||
});
|
||||
temperatureText = root.findViewById(R.id.envSensorTempText);
|
||||
humidityText = root.findViewById(R.id.envSensorHumidityText);
|
||||
pressureText = root.findViewById(R.id.envSensorPressureText);
|
||||
vocText = root.findViewById(R.id.envSensorVocText);
|
||||
sensorStatusImageView = root.findViewById(R.id.sensorStatusImageView);
|
||||
sensorStatusText = root.findViewById(R.id.sensorStatusText);
|
||||
|
||||
environmentSensorService = new EnvironmentSensorService("192.168.0.100", 8000);
|
||||
|
||||
setupSensorStatusImage();
|
||||
setupSensorMeasurementsDisplays();
|
||||
setupEnvironmentSensorService();
|
||||
return root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
environmentSensorService.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
environmentSensorService.stop();
|
||||
}
|
||||
|
||||
private void setupSensorMeasurementsDisplays() {
|
||||
environmentSensorViewModel.getSensorMeasurementTemperature().observe(getViewLifecycleOwner(), new Observer<Double>() {
|
||||
@Override
|
||||
public void onChanged(Double value) {
|
||||
temperatureText.setText(value.toString());
|
||||
}
|
||||
});
|
||||
environmentSensorViewModel.getSensorMeasurementHumidity().observe(getViewLifecycleOwner(), new Observer<Double>() {
|
||||
@Override
|
||||
public void onChanged(Double value) {
|
||||
humidityText.setText(value.toString());
|
||||
}
|
||||
});
|
||||
environmentSensorViewModel.getSensorMeasurementPressure().observe(getViewLifecycleOwner(), new Observer<Double>() {
|
||||
@Override
|
||||
public void onChanged(Double value) {
|
||||
pressureText.setText(value.toString());
|
||||
}
|
||||
});
|
||||
environmentSensorViewModel.getSensorMeasurementVoc().observe(getViewLifecycleOwner(), new Observer<Double>() {
|
||||
@Override
|
||||
public void onChanged(Double value) {
|
||||
vocText.setText(value.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupEnvironmentSensorService() {
|
||||
environmentSensorService.getLastMeasurementData().observe(getViewLifecycleOwner(), new Observer<EnvironmentSensorData>() {
|
||||
@Override
|
||||
public void onChanged(EnvironmentSensorData environmentSensorData) {
|
||||
environmentSensorViewModel.notifyNewData(environmentSensorData);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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<Integer>() {
|
||||
environmentSensorViewModel.getSensorStatusImage().observe(getViewLifecycleOwner(), new Observer<Integer>() {
|
||||
@Override
|
||||
public void onChanged(Integer resourceId) {
|
||||
sensorStatusImageView.setImageResource(resourceId);
|
||||
|
@ -53,6 +104,7 @@ public class SensorsFragment extends Fragment {
|
|||
@Override
|
||||
public void onChanged(String tooltip) {
|
||||
sensorStatusImageView.setTooltipText(tooltip);
|
||||
sensorStatusText.setText(tooltip);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
BIN
NucuHub.Android/app/src/main/res/drawable/barometer.png
Normal file
After Width: | Height: | Size: 28 KiB |
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12c0,5.52 4.48,10 10,10s10,-4.48 10,-10C22,6.48 17.52,2 12,2zM8.46,14.45L7.1,13.83c0.28,-0.61 0.41,-1.24 0.4,-1.86c-0.01,-0.63 -0.14,-1.24 -0.4,-1.8l1.36,-0.63c0.35,0.75 0.53,1.56 0.54,2.4C9.01,12.8 8.83,13.64 8.46,14.45zM11.53,16.01l-1.3,-0.74c0.52,-0.92 0.78,-1.98 0.78,-3.15c0,-1.19 -0.27,-2.33 -0.8,-3.4l1.34,-0.67c0.64,1.28 0.96,2.65 0.96,4.07C12.51,13.55 12.18,14.86 11.53,16.01zM14.67,17.33l-1.35,-0.66c0.78,-1.6 1.18,-3.18 1.18,-4.69c0,-1.51 -0.4,-3.07 -1.18,-4.64l1.34,-0.67C15.56,8.45 16,10.23 16,11.98C16,13.72 15.56,15.52 14.67,17.33z"/>
|
||||
</vector>
|
BIN
NucuHub.Android/app/src/main/res/drawable/humidity.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
NucuHub.Android/app/src/main/res/drawable/poisoning.png
Normal file
After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.2 KiB |
BIN
NucuHub.Android/app/src/main/res/drawable/thermometer.png
Normal file
After Width: | Height: | Size: 10 KiB |
|
@ -13,18 +13,115 @@
|
|||
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent"
|
||||
android:layout_marginStart="70dp"
|
||||
android:contentDescription="@string/environment_status_description"
|
||||
app:layout_constraintBottom_toBottomOf="parent" android:layout_marginBottom="376dp"
|
||||
android:background="#00FFFFFF"
|
||||
app:layout_constraintHorizontal_bias="1.0" app:layout_constraintTop_toTopOf="parent"
|
||||
android:tooltipText="what is this amaaaizng"
|
||||
android:layout_marginTop="90dp" app:srcCompat="@drawable/status_netural"
|
||||
tools:srcCompat="@drawable/status_netural"/>
|
||||
<Button
|
||||
android:text="Button"
|
||||
android:layout_marginTop="90dp" app:srcCompat="@drawable/status_neutral"
|
||||
tools:srcCompat="@drawable/status_neutral" android:adjustViewBounds="true" android:scaleType="center"
|
||||
android:layout_marginBottom="32dp" app:layout_constraintBottom_toTopOf="@+id/constraintLayout"/>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="415dp"
|
||||
android:layout_height="172dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_marginBottom="164dp" android:layout_marginTop="32dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/sensorStatusImageView" android:id="@+id/constraintLayout">
|
||||
|
||||
<TextView
|
||||
android:layout_width="55dp"
|
||||
android:layout_height="52dp" android:id="@+id/envSensorPressureText"
|
||||
android:gravity="center" android:foregroundGravity="center" android:backgroundTint="#00FFFEFE"
|
||||
android:clickable="false" android:drawableTint="#00FFFFFF"
|
||||
android:textStyle="bold" android:textColor="#000000"
|
||||
android:textSize="16sp"
|
||||
tools:text="1000.5"
|
||||
android:layout_marginStart="48dp"
|
||||
app:layout_constraintStart_toEndOf="@+id/envSensorHumidityText" android:layout_marginTop="22dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/envSensorPresureImg"
|
||||
app:layout_constraintEnd_toStartOf="@+id/envSensorVocText"
|
||||
app:layout_constraintBottom_toBottomOf="parent" android:layout_marginBottom="25dp"/>
|
||||
<TextView
|
||||
android:layout_width="55dp"
|
||||
android:layout_height="52dp" android:id="@+id/envSensorVocText"
|
||||
android:gravity="center" android:foregroundGravity="center" android:backgroundTint="#00FFFEFE"
|
||||
android:clickable="false" android:drawableTint="#00FFFFFF"
|
||||
android:textStyle="bold" android:textColor="#000000"
|
||||
android:textSize="16sp"
|
||||
tools:text="100.11"
|
||||
android:layout_marginTop="22dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/envSensorVocImg" android:layout_marginStart="48dp"
|
||||
app:layout_constraintStart_toEndOf="@+id/envSensorPressureText" android:layout_marginEnd="29dp"
|
||||
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_marginBottom="25dp"/>
|
||||
<TextView
|
||||
android:layout_width="55dp"
|
||||
android:layout_height="52dp" android:id="@+id/envSensorHumidityText"
|
||||
android:gravity="center" android:foregroundGravity="center" android:backgroundTint="#00FFFEFE"
|
||||
android:clickable="false" android:drawableTint="#00FFFFFF"
|
||||
android:textStyle="bold" android:textColor="#000000"
|
||||
android:textSize="16sp"
|
||||
tools:text="0.00"
|
||||
android:layout_marginStart="48dp"
|
||||
app:layout_constraintStart_toEndOf="@+id/envSensorTempText" android:layout_marginTop="22dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/envSensorHumidityImg"
|
||||
app:layout_constraintEnd_toStartOf="@+id/envSensorPressureText"
|
||||
app:layout_constraintBottom_toBottomOf="parent" android:layout_marginBottom="25dp"/>
|
||||
<ImageView
|
||||
android:src="@drawable/thermometer"
|
||||
android:layout_width="55dp"
|
||||
android:layout_height="52dp" android:id="@+id/envSensorTempImg"
|
||||
android:adjustViewBounds="false"
|
||||
android:contentDescription="@string/temperature_icon_desc" android:cropToPadding="false"
|
||||
android:scaleType="fitCenter"
|
||||
app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="29dp"
|
||||
app:layout_constraintEnd_toStartOf="@+id/envSensorHumidityImg" app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_marginTop="21dp"/>
|
||||
<ImageView
|
||||
android:src="@drawable/poisoning"
|
||||
android:layout_width="55dp"
|
||||
android:layout_height="52dp" android:id="@+id/envSensorVocImg"
|
||||
android:contentDescription="@string/voc_icon_desc"
|
||||
app:layout_constraintStart_toEndOf="@+id/envSensorPresureImg"
|
||||
android:layout_marginEnd="29dp" app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_marginStart="48dp" app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_marginTop="21dp"/>
|
||||
<ImageView
|
||||
android:src="@drawable/barometer"
|
||||
android:layout_width="55dp"
|
||||
android:layout_height="52dp" android:id="@+id/envSensorPresureImg"
|
||||
android:contentDescription="@string/barometer_icon_desc"
|
||||
android:layout_marginStart="48dp" app:layout_constraintStart_toEndOf="@+id/envSensorHumidityImg"
|
||||
app:layout_constraintEnd_toStartOf="@+id/envSensorVocImg" app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_marginTop="21dp"/>
|
||||
<ImageView
|
||||
android:src="@drawable/humidity"
|
||||
android:layout_width="55dp"
|
||||
android:layout_height="52dp" android:id="@+id/envSensorHumidityImg"
|
||||
android:adjustViewBounds="true"
|
||||
android:contentDescription="@string/humidity_icon_desc"
|
||||
android:layout_marginStart="48dp"
|
||||
app:layout_constraintStart_toEndOf="@+id/envSensorTempImg"
|
||||
app:layout_constraintEnd_toStartOf="@+id/envSensorPresureImg" app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_marginTop="21dp"/>
|
||||
<TextView
|
||||
android:layout_width="55dp"
|
||||
android:layout_height="52dp" android:id="@+id/envSensorTempText"
|
||||
android:gravity="center" android:foregroundGravity="center" android:backgroundTint="#00FFFEFE"
|
||||
android:clickable="false" android:drawableTint="#00FFFFFF"
|
||||
android:textStyle="bold" android:textColor="#000000"
|
||||
android:textSize="16sp" android:layout_marginTop="22dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/envSensorTempImg"
|
||||
app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="29dp" tools:text="10000"
|
||||
app:layout_constraintEnd_toStartOf="@+id/envSensorHumidityText"
|
||||
app:layout_constraintBottom_toBottomOf="parent" android:layout_marginBottom="25dp"/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" android:id="@+id/grpc_test_button"
|
||||
app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="161dp"
|
||||
android:layout_marginEnd="162dp" app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" android:layout_marginBottom="106dp"
|
||||
android:layout_marginTop="221dp" app:layout_constraintTop_toBottomOf="@+id/sensorStatusImageView"/>
|
||||
android:layout_height="19dp" android:id="@+id/sensorStatusText"
|
||||
android:layout_marginTop="40dp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/sensorStatusImageView"
|
||||
app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="40dp"
|
||||
android:layout_marginEnd="40dp" app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_marginBottom="26dp" app:layout_constraintBottom_toTopOf="@+id/constraintLayout"
|
||||
tools:text="Sensor Status Explain" android:textStyle="bold"/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -5,16 +5,20 @@
|
|||
|
||||
<group android:checkableBehavior="single">
|
||||
<item
|
||||
android:id="@+id/nav_home"
|
||||
android:icon="@drawable/ic_menu_camera"
|
||||
android:title="@string/menu_home"/>
|
||||
android:id="@+id/nav_environment_sensor"
|
||||
android:icon="@drawable/baseline_contactless_24"
|
||||
android:title="@string/menu_environment_sensor"/>
|
||||
<item
|
||||
android:id="@+id/nav_gallery"
|
||||
android:icon="@drawable/ic_menu_gallery"
|
||||
android:title="@string/menu_gallery"/>
|
||||
android:title="@string/menu_gallery"
|
||||
android:enabled="false"
|
||||
/>
|
||||
<item
|
||||
android:id="@+id/nav_slideshow"
|
||||
android:icon="@drawable/ic_menu_slideshow"
|
||||
android:title="@string/menu_slideshow"/>
|
||||
android:title="@string/menu_slideshow"
|
||||
android:enabled="false"
|
||||
/>
|
||||
</group>
|
||||
</menu>
|
After Width: | Height: | Size: 406 B |
After Width: | Height: | Size: 492 B |
After Width: | Height: | Size: 712 B |
After Width: | Height: | Size: 921 B |
After Width: | Height: | Size: 260 B |
After Width: | Height: | Size: 355 B |
After Width: | Height: | Size: 492 B |
After Width: | Height: | Size: 622 B |
After Width: | Height: | Size: 492 B |
After Width: | Height: | Size: 622 B |
After Width: | Height: | Size: 921 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 712 B |
After Width: | Height: | Size: 921 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 921 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 2.1 KiB |
|
@ -3,12 +3,12 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/mobile_navigation"
|
||||
app:startDestination="@+id/nav_home">
|
||||
app:startDestination="@+id/nav_environment_sensor">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_home"
|
||||
android:id="@+id/nav_environment_sensor"
|
||||
android:name="dev.nuculabs.nucuhub.ui.sensors.SensorsFragment"
|
||||
android:label="@string/menu_home"
|
||||
android:label="@string/menu_environment_sensor"
|
||||
tools:layout="@layout/fragment_environment_sensor"/>
|
||||
|
||||
<fragment
|
||||
|
|
|
@ -3,12 +3,16 @@
|
|||
<string name="environment_status_description">Temperature sensor status</string>
|
||||
<string name="navigation_drawer_open">Open navigation drawer</string>
|
||||
<string name="navigation_drawer_close">Close navigation drawer</string>
|
||||
<string name="nav_header_title">Android Studio</string>
|
||||
<string name="nav_header_subtitle">android.studio@android.com</string>
|
||||
<string name="nav_header_title">NucuHub</string>
|
||||
<string name="nav_header_subtitle">denis@nuculabs.dev</string>
|
||||
<string name="nav_header_desc">Navigation header</string>
|
||||
<string name="action_settings">Settings</string>
|
||||
|
||||
<string name="menu_home">Home</string>
|
||||
<string name="menu_environment_sensor">Environment Sensor</string>
|
||||
<string name="menu_gallery">Gallery</string>
|
||||
<string name="menu_slideshow">Slideshow</string>
|
||||
<string name="humidity_icon_desc">humidity image</string>
|
||||
<string name="temperature_icon_desc">temperature icon</string>
|
||||
<string name="barometer_icon_desc">barometer icon</string>
|
||||
<string name="voc_icon_desc">voc icon</string>
|
||||
</resources>
|