feat(frontend): fecth and display sensor data

This commit is contained in:
Halit Aksoy 2025-02-22 19:50:05 +03:00
parent d42b840b18
commit ee1a7102cb
6 changed files with 176 additions and 29 deletions

View File

@ -1,7 +1,15 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'sensor_provider.dart';
import 'package:timeago/timeago.dart' as timeago;
void main() { void main() {
runApp(const MyApp()); runApp(
ChangeNotifierProvider(
create: (context) => SensorProvider(),
child: const MyApp(),
),
);
} }
class MyApp extends StatelessWidget { class MyApp extends StatelessWidget {
@ -10,30 +18,28 @@ class MyApp extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MaterialApp( return MaterialApp(
title: 'Flutter Demo', title: 'Sensor App',
theme: ThemeData( theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), primarySwatch: Colors.blue,
), ),
home: const MyHomePage(title: 'Flutter Demo Home Page'), home: const SensorScreen(),
); );
} }
} }
class MyHomePage extends StatefulWidget { class SensorScreen extends StatefulWidget {
const MyHomePage({super.key, required this.title}); const SensorScreen({super.key});
final String title;
@override @override
State<MyHomePage> createState() => _MyHomePageState(); _SensorScreenState createState() => _SensorScreenState();
} }
class _MyHomePageState extends State<MyHomePage> { class _SensorScreenState extends State<SensorScreen> {
int _counter = 0; @override
void initState() {
void _incrementCounter() { super.initState();
setState(() { WidgetsBinding.instance.addPostFrameCallback((_) {
_counter++; Provider.of<SensorProvider>(context, listen: false).fetchData();
}); });
} }
@ -41,25 +47,37 @@ class _MyHomePageState extends State<MyHomePage> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: const Text('Mercury'),
title: Text(widget.title),
), ),
body: Center( body: Center(
child: Column( child: Consumer<SensorProvider>(
builder: (context, sensorProvider, child) {
if (sensorProvider.sensorData == null) {
if (sensorProvider.error != null) {
return Text('Error: ${sensorProvider.error}');
}
return const CircularProgressIndicator();
} else {
final data = sensorProvider.sensorData!;
final timeAgo = timeago.format(DateTime.fromMillisecondsSinceEpoch(data.timestamp));
return Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[ children: [
const Text('You have pushed the button this many times:'), Text('🌡️ Temperature: ${data.temperature}°C'),
Text( Text('💧 Humidity: ${data.humidity}%'),
'$_counter', Text('❄️ Dew Point: ${data.dewPoint}°C'),
style: Theme.of(context).textTheme.headlineMedium, Text('🕒 $timeAgo'),
),
], ],
);
}
},
), ),
), ),
floatingActionButton: FloatingActionButton( floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter, onPressed: () {
tooltip: 'Increment', Provider.of<SensorProvider>(context, listen: false).fetchData();
child: const Icon(Icons.add), },
child: const Icon(Icons.refresh),
), ),
); );
} }

View File

@ -0,0 +1,22 @@
class SensorData {
final double temperature;
final double humidity;
final double dewPoint;
final int timestamp;
SensorData({
required this.temperature,
required this.humidity,
required this.dewPoint,
required this.timestamp,
});
factory SensorData.fromJson(Map<String, dynamic> json) {
return SensorData(
temperature: json['temperature'],
humidity: json['humidity'],
dewPoint: json['dewPoint'],
timestamp: json['timestamp'],
);
}
}

View File

@ -0,0 +1,23 @@
import 'package:flutter/material.dart';
import 'sensor_data.dart';
import 'sensor_service.dart';
class SensorProvider with ChangeNotifier {
final SensorService _service = SensorService();
SensorData? _sensorData;
Error? _error;
SensorData? get sensorData => _sensorData;
Error? get error => _error;
Future<void> fetchData() async {
try {
_sensorData = await _service.fetchSensorData();
} catch (e) {
_error = e as Error;
}
notifyListeners();
}
}

View File

@ -0,0 +1,17 @@
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'sensor_data.dart';
class SensorService {
final String url = 'https://mercury.segin.one/sensor';
Future<SensorData> fetchSensorData() async {
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
return SensorData.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to load sensor data');
}
}
}

View File

@ -75,6 +75,30 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
http:
dependency: "direct main"
description:
name: http
sha256: fe7ab022b76f3034adc518fb6ea04a82387620e19977665ea18d30a1cf43442f
url: "https://pub.dev"
source: hosted
version: "1.3.0"
http_parser:
dependency: transitive
description:
name: http_parser
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
url: "https://pub.dev"
source: hosted
version: "4.1.2"
intl:
dependency: transitive
description:
name: intl
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
url: "https://pub.dev"
source: hosted
version: "0.19.0"
leak_tracker: leak_tracker:
dependency: transitive dependency: transitive
description: description:
@ -131,6 +155,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.16.0" version: "1.16.0"
nested:
dependency: transitive
description:
name: nested
sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
path: path:
dependency: transitive dependency: transitive
description: description:
@ -139,6 +171,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.9.1" version: "1.9.1"
provider:
dependency: "direct main"
description:
name: provider
sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c
url: "https://pub.dev"
source: hosted
version: "6.1.2"
sky_engine: sky_engine:
dependency: transitive dependency: transitive
description: flutter description: flutter
@ -192,6 +232,22 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.4" version: "0.7.4"
timeago:
dependency: "direct main"
description:
name: timeago
sha256: "054cedf68706bb142839ba0ae6b135f6b68039f0b8301cbe8784ae653d5ff8de"
url: "https://pub.dev"
source: hosted
version: "3.7.0"
typed_data:
dependency: transitive
description:
name: typed_data
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
url: "https://pub.dev"
source: hosted
version: "1.4.0"
vector_math: vector_math:
dependency: transitive dependency: transitive
description: description:
@ -208,6 +264,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "14.3.1" version: "14.3.1"
web:
dependency: transitive
description:
name: web
sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb
url: "https://pub.dev"
source: hosted
version: "1.1.0"
sdks: sdks:
dart: ">=3.7.0 <4.0.0" dart: ">=3.7.0 <4.0.0"
flutter: ">=3.18.0-18.0.pre.54" flutter: ">=3.18.0-18.0.pre.54"

View File

@ -34,6 +34,9 @@ dependencies:
# The following adds the Cupertino Icons font to your application. # The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons. # Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.8 cupertino_icons: ^1.0.8
provider: ^6.1.2
http: ^1.3.0
timeago: ^3.7.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: