Skip to content

Commit 53f4102

Browse files
Yugesh-Kumar-Ssourcery-ai[bot]marcnause
authored
feat: ported thermometer screen. (#2761)
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Co-authored-by: Marc Nause <marc.nause@audioattack.de>
1 parent ff8c73d commit 53f4102

12 files changed

+971
-4
lines changed

android/app/src/main/AndroidManifest.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
22
xmlns:tools="http://schemas.android.com/tools">
33
<uses-permission android:name="android.permission.RECORD_AUDIO" />
4+
<uses-permission android:name="android.permission.BODY_SENSORS" />
45
<uses-feature android:name="android.hardware.usb.host" />
6+
<uses-feature
7+
android:name="android.hardware.sensor.ambient_temperature"
8+
android:required="false" />
59
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
610
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
711
android:maxSdkVersion="28" />
Lines changed: 162 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,166 @@
11
package io.pslab;
22

3+
import android.content.Context;
4+
import android.hardware.Sensor;
5+
import android.hardware.SensorEvent;
6+
import android.hardware.SensorEventListener;
7+
import android.hardware.SensorManager;
8+
import android.os.Bundle;
9+
import android.util.Log;
10+
11+
import androidx.annotation.NonNull;
12+
313
import io.flutter.embedding.android.FlutterActivity;
14+
import io.flutter.embedding.engine.FlutterEngine;
15+
import io.flutter.plugin.common.EventChannel;
16+
import io.flutter.plugin.common.MethodCall;
17+
import io.flutter.plugin.common.MethodChannel;
18+
19+
public class MainActivity extends FlutterActivity implements SensorEventListener {
20+
private static final String TEMPERATURE_CHANNEL = "io.pslab/temperature";
21+
private static final String TEMPERATURE_STREAM = "io.pslab/temperature_stream";
22+
private static final String TAG = "MainActivity";
23+
private SensorManager sensorManager;
24+
private Sensor temperatureSensor;
25+
private EventChannel.EventSink temperatureEventSink;
26+
private boolean isListening = false;
27+
private float currentTemperature = 0.0f;
28+
29+
@Override
30+
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
31+
super.configureFlutterEngine(flutterEngine);
32+
33+
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
34+
if (sensorManager != null) {
35+
temperatureSensor = sensorManager.getDefaultSensor(Sensor.TYPE_AMBIENT_TEMPERATURE);
36+
}
37+
38+
MethodChannel temperatureChannel = new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), TEMPERATURE_CHANNEL);
39+
temperatureChannel.setMethodCallHandler(this::handleMethodCall);
40+
41+
EventChannel temperatureEventChannel = new EventChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), TEMPERATURE_STREAM);
42+
temperatureEventChannel.setStreamHandler(new EventChannel.StreamHandler() {
43+
@Override
44+
public void onListen(Object arguments, EventChannel.EventSink events) {
45+
temperatureEventSink = events;
46+
startTemperatureUpdates();
47+
}
48+
49+
@Override
50+
public void onCancel(Object arguments) {
51+
temperatureEventSink = null;
52+
stopTemperatureUpdates();
53+
}
54+
});
55+
}
56+
57+
private void handleMethodCall(MethodCall call, MethodChannel.Result result) {
58+
switch (call.method) {
59+
case "isTemperatureSensorAvailable":
60+
result.success(temperatureSensor != null);
61+
break;
62+
case "getCurrentTemperature":
63+
result.success((double) currentTemperature);
64+
break;
65+
case "startTemperatureUpdates":
66+
if (startTemperatureUpdates()) {
67+
result.success(true);
68+
} else {
69+
result.error("SENSOR_ERROR", "Failed to start temperature updates", null);
70+
}
71+
break;
72+
case "stopTemperatureUpdates":
73+
stopTemperatureUpdates();
74+
result.success(true);
75+
break;
76+
default:
77+
result.notImplemented();
78+
break;
79+
}
80+
}
81+
82+
private boolean startTemperatureUpdates() {
83+
if (temperatureSensor == null || sensorManager == null) {
84+
Log.e(TAG, "Temperature sensor not available");
85+
return false;
86+
}
87+
88+
if (!isListening) {
89+
boolean registered = sensorManager.registerListener(this, temperatureSensor, SensorManager.SENSOR_DELAY_NORMAL);
90+
if (registered) {
91+
isListening = true;
92+
Log.d(TAG, "Temperature sensor listener registered");
93+
94+
if (currentTemperature != 0.0f && temperatureEventSink != null) {
95+
Log.d(TAG, "Sending initial temperature to Flutter: " + currentTemperature);
96+
temperatureEventSink.success((double) currentTemperature);
97+
}
98+
99+
return true;
100+
} else {
101+
Log.e(TAG, "Failed to register temperature sensor listener");
102+
return false;
103+
}
104+
}
105+
return true;
106+
}
107+
108+
private void stopTemperatureUpdates() {
109+
if (isListening && sensorManager != null) {
110+
sensorManager.unregisterListener(this, temperatureSensor);
111+
isListening = false;
112+
Log.d(TAG, "Temperature sensor listener unregistered");
113+
}
114+
}
115+
116+
@Override
117+
public void onSensorChanged(SensorEvent event) {
118+
if (event.sensor.getType() == Sensor.TYPE_AMBIENT_TEMPERATURE) {
119+
float temperature = event.values[0];
120+
121+
if (isValidTemperature(temperature)) {
122+
currentTemperature = temperature;
123+
Log.d(TAG, "Temperature updated: " + currentTemperature + "°C");
124+
125+
if (temperatureEventSink != null) {
126+
Log.d(TAG, "Sending temperature to Flutter: " + currentTemperature);
127+
temperatureEventSink.success((double) currentTemperature);
128+
}
129+
} else {
130+
Log.w(TAG, "Invalid temperature reading: " + temperature + " - ignoring");
131+
}
132+
}
133+
}
134+
135+
private boolean isValidTemperature(float temperature) {
136+
if (Float.isNaN(temperature) || Float.isInfinite(temperature)) return false;
137+
return temperature >= -273.15f && temperature <= 200f && Math.abs(temperature) <= 1e10f;
138+
}
139+
140+
@Override
141+
public void onAccuracyChanged(Sensor sensor, int accuracy) {
142+
Log.d(TAG, "Sensor accuracy changed: " + accuracy);
143+
}
144+
145+
@Override
146+
protected void onDestroy() {
147+
super.onDestroy();
148+
stopTemperatureUpdates();
149+
}
150+
151+
@Override
152+
protected void onPause() {
153+
super.onPause();
154+
if (isListening && sensorManager != null) {
155+
sensorManager.unregisterListener(this);
156+
}
157+
}
4158

5-
public class MainActivity extends FlutterActivity {
6-
}
159+
@Override
160+
protected void onResume() {
161+
super.onResume();
162+
if (isListening && temperatureSensor != null && sensorManager != null) {
163+
sensorManager.registerListener(this, temperatureSensor, SensorManager.SENSOR_DELAY_NORMAL);
164+
}
165+
}
166+
}

lib/constants.dart

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,43 @@
11
import 'dart:core';
22

3+
List<String> instrumentHeadings = [
4+
'OSCILLOSCOPE',
5+
'MULTIMETER',
6+
'LOGIC ANALYZER',
7+
'SENSORS',
8+
'WAVE GENERATOR',
9+
'POWER SOURCE',
10+
'LUX METER',
11+
'ACCELEROMETER',
12+
'BAROMETER',
13+
'COMPASS',
14+
'GYROSCOPE',
15+
'THERMOMETER',
16+
'ROBOTIC ARM',
17+
'GAS SENSOR',
18+
'DUST SENSOR',
19+
'SOUND METER'
20+
];
21+
22+
List<String> instrumentDesc = [
23+
'Allows observation of varying signal voltages',
24+
'Measure voltage, current, resistance and capacitance',
25+
'Captures and displays signals from digital systems',
26+
'Allows logging of data returned by sensor connected',
27+
'Generates arbitrary analog and digital waveforms',
28+
'Generates programmable voltage and currents',
29+
'Measures the ambient light intensity',
30+
'Measures the Linear acceleration in XYZ directions',
31+
'Measures the atmospheric pressure',
32+
'Three axes magnetometer pointing to magnetic north',
33+
'Measures rate of rotation about XYZ axis',
34+
'To measure the ambient temperature',
35+
'Controls servos of a robotic arm',
36+
'Air quality sensor for detecting a wide range of gases, including NH3, NOx, alcohol, benzene, smoke and CO2',
37+
'Dust sensor is used to measure air quality in terms of particles per square meter',
38+
'To measure the loudness in the environment in decibel(dB)'
39+
];
40+
341
List<String> instrumentIcons = [
442
'assets/icons/tile_icon_oscilloscope.png',
543
'assets/icons/tile_icon_multimeter.png',

lib/l10n/app_en.arb

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -323,8 +323,14 @@
323323
"baroMeterBulletPoint2": "If you want to use the sensor BMP-180, connect the sensor to PSLab device as shown in the figure.",
324324
"baroMeterBulletPoint3": "The above pin configuration has to be same except for the pin GND. GND is meant for Ground and any of the PSLab device GND pins can be used since they are common.",
325325
"baroMeterBulletPoint4": "Select the sensor by going to the Configure tab from the bottom navigation bar and choose BMP-180 in the drop down menu under Select Sensor.",
326-
"sharingMessage": "Sharing PSLab Data",
327-
"delete": "Delete",
326+
"thermometerTitle" : "Thermometer",
327+
"thermometerIntro" : "Thermometer instrument is used to measure ambient temprature. It can be measured using inbuilt ambient temprature sensor or through SHT21.",
328+
"celsius": "°C",
329+
"temperatureSensorError" : "Temperature sensor error:",
330+
"temperatureSensorInitialError" : "Temperature sensor initialization error:",
331+
"temperatureSensorUnavailableMessage" : "Ambient temperature sensor is not available on this device",
332+
"sharingMessage" : "Sharing PSLab Data",
333+
"delete" : "Delete",
328334
"deleteHint": "Are you sure you want to delete this file?",
329335
"documentationLink" : "https://docs.pslab.io/",
330336
"documentationError" : "Could not open the documentation link",

lib/l10n/app_localizations.dart

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2032,6 +2032,42 @@ abstract class AppLocalizations {
20322032
/// **'Select the sensor by going to the Configure tab from the bottom navigation bar and choose BMP-180 in the drop down menu under Select Sensor.'**
20332033
String get baroMeterBulletPoint4;
20342034

2035+
/// No description provided for @thermometerTitle.
2036+
///
2037+
/// In en, this message translates to:
2038+
/// **'Thermometer'**
2039+
String get thermometerTitle;
2040+
2041+
/// No description provided for @thermometerIntro.
2042+
///
2043+
/// In en, this message translates to:
2044+
/// **'Thermometer instrument is used to measure ambient temprature. It can be measured using inbuilt ambient temprature sensor or through SHT21.'**
2045+
String get thermometerIntro;
2046+
2047+
/// No description provided for @celsius.
2048+
///
2049+
/// In en, this message translates to:
2050+
/// **'°C'**
2051+
String get celsius;
2052+
2053+
/// No description provided for @temperatureSensorError.
2054+
///
2055+
/// In en, this message translates to:
2056+
/// **'Temperature sensor error:'**
2057+
String get temperatureSensorError;
2058+
2059+
/// No description provided for @temperatureSensorInitialError.
2060+
///
2061+
/// In en, this message translates to:
2062+
/// **'Temperature sensor initialization error:'**
2063+
String get temperatureSensorInitialError;
2064+
2065+
/// No description provided for @temperatureSensorUnavailableMessage.
2066+
///
2067+
/// In en, this message translates to:
2068+
/// **'Ambient temperature sensor is not available on this device'**
2069+
String get temperatureSensorUnavailableMessage;
2070+
20352071
/// No description provided for @sharingMessage.
20362072
///
20372073
/// In en, this message translates to:

lib/l10n/app_localizations_en.dart

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,6 +1038,26 @@ class AppLocalizationsEn extends AppLocalizations {
10381038
'Select the sensor by going to the Configure tab from the bottom navigation bar and choose BMP-180 in the drop down menu under Select Sensor.';
10391039

10401040
@override
1041+
String get thermometerTitle => 'Thermometer';
1042+
1043+
@override
1044+
String get thermometerIntro =>
1045+
'Thermometer instrument is used to measure ambient temprature. It can be measured using inbuilt ambient temprature sensor or through SHT21.';
1046+
1047+
@override
1048+
String get celsius => '°C';
1049+
1050+
@override
1051+
String get temperatureSensorError => 'Temperature sensor error:';
1052+
1053+
@override
1054+
String get temperatureSensorInitialError =>
1055+
'Temperature sensor initialization error:';
1056+
1057+
@override
1058+
String get temperatureSensorUnavailableMessage =>
1059+
'Ambient temperature sensor is not available on this device';
1060+
10411061
String get sharingMessage => 'Sharing PSLab Data';
10421062

10431063
@override

lib/main.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import 'package:pslab/view/about_us_screen.dart';
2121
import 'package:pslab/view/software_licenses_screen.dart';
2222
import 'package:pslab/theme/app_theme.dart';
2323
import 'package:pslab/view/soundmeter_screen.dart';
24+
import 'package:pslab/view/thermometer_screen.dart';
2425
import 'package:pslab/view/wave_generator_screen.dart';
2526
import 'constants.dart';
2627

@@ -76,6 +77,7 @@ class MyApp extends StatelessWidget {
7677
'/luxmeter': (context) => const LuxMeterScreen(),
7778
'/barometer': (context) => const BarometerScreen(),
7879
'/soundmeter': (context) => const SoundMeterScreen(),
80+
'/thermometer': (context) => const ThermometerScreen(),
7981
'/sensors': (context) => const SensorsScreen()
8082
},
8183
);

0 commit comments

Comments
 (0)