From c36010aebed66c0dcb78eaf3ccc05c43e7bbe129 Mon Sep 17 00:00:00 2001 From: Sara <sarasdj@stud.ntnu.no> Date: Fri, 9 Feb 2024 15:00:53 +0100 Subject: [PATCH] update: json data parsing --- app/lib/api_handler/fetch_markers.dart | 0 app/lib/pages_and_widgets/default_page.dart | 39 +++-- app/lib/pages_and_widgets/marker_data.dart | 147 ++++++++++++++---- .../__pycache__/data_structs.cpython-311.pyc | Bin 3945 -> 3945 bytes .../__pycache__/get_markers.cpython-311.pyc | Bin 2626 -> 2626 bytes server/map/get_markers.py | 6 +- 6 files changed, 143 insertions(+), 49 deletions(-) create mode 100644 app/lib/api_handler/fetch_markers.dart diff --git a/app/lib/api_handler/fetch_markers.dart b/app/lib/api_handler/fetch_markers.dart new file mode 100644 index 00000000..e69de29b diff --git a/app/lib/pages_and_widgets/default_page.dart b/app/lib/pages_and_widgets/default_page.dart index 1b0574c3..1713e1d0 100644 --- a/app/lib/pages_and_widgets/default_page.dart +++ b/app/lib/pages_and_widgets/default_page.dart @@ -17,24 +17,29 @@ class DefaultPage extends StatefulWidget { class _DefaultPageState extends State<DefaultPage> { late Timer _timer; - List<MarkerData> markerList = []; + List<MarkerTemplate> markerList = []; - // fetchMarkerData requests data from the update_map endpoint - Future<void> fetchMarkerData() async { + // fetchMarkerTemplate requests data from the update_map endpoint + Future<void> fetchMarkerTemplate() async { try { // Custom HTTP client HttpClient client = HttpClient() ..badCertificateCallback = // NB: temporary disable SSL certificate validation (X509Certificate cert, String host, int port) => true; + // Request makers from API and wait for response var request = await client.getUrl(Uri.parse(serverURI+mapEndpoint)); var response = await request.close(); - // Parse json response to list of MarkerData objects if request is ok + // Attempt to parse json if request is ok if (response.statusCode == 200) { var responseBody = await response.transform(utf8.decoder).join(); setState(() { - markerList = parseMarkerData(responseBody); + // Parse JSON string from response body + List<dynamic> jsonData = json.decode(responseBody); + + // Convert response from type List<dynamic> to List<MarkerTemplate> + markerList = jsonData.map((data) => MarkerTemplate.fromJson(data)).toList(); }); } else { print('Request failed with status: ${response.statusCode}'); @@ -44,17 +49,17 @@ class _DefaultPageState extends State<DefaultPage> { } } - // Timer initializer + // State initializer @override void initState() { super.initState(); - // Call fetchMarkerData when the widget is first created - fetchMarkerData(); + // Call fetchMarkerTemplate when the widget is first created + fetchMarkerTemplate(); - // Schedule fetchMarkerData to run periodically based on fetchInterval const + // Schedule fetchMarkerTemplate to run periodically based on fetchInterval const const Duration fiveMinutes = Duration(minutes: fetchInterval); _timer = Timer.periodic(fiveMinutes, (timer) { - fetchMarkerData(); + fetchMarkerTemplate(); }); } @@ -99,11 +104,11 @@ class _DefaultPageState extends State<DefaultPage> { ), MarkerLayer( // Dynamically allocate markers based on a list - markers: markerList.map((MarkerData markerData) { + markers: markerList.map((MarkerTemplate MarkerTemplate) { return Marker( - width: markerData.size, - height: markerData.size, - point: markerData.location, + width: MarkerTemplate.size, + height: MarkerTemplate.size, + point: MarkerTemplate.location, builder: (ctx) => GestureDetector( onTap: () { // NB: temporary print @@ -112,9 +117,9 @@ class _DefaultPageState extends State<DefaultPage> { }, child: Image.asset( 'assets/icons/circle-red.png', // Path to your custom icon asset - color: markerData.color, - width: markerData.radius, - height: markerData.radius, + color: MarkerTemplate.color, + width: MarkerTemplate.size, + height: MarkerTemplate.size, ), ), ); diff --git a/app/lib/pages_and_widgets/marker_data.dart b/app/lib/pages_and_widgets/marker_data.dart index 66b0f252..1c3d6150 100644 --- a/app/lib/pages_and_widgets/marker_data.dart +++ b/app/lib/pages_and_widgets/marker_data.dart @@ -1,38 +1,127 @@ import 'package:flutter/material.dart'; import 'package:latlong2/latlong.dart'; -import 'dart:convert'; -// MarkerData holds data for the dynamically allocated markers -class MarkerData { - final LatLng location; - final double size; - final Color color; - final double radius; +// Sensor holds data about a single sensor +class Sensor { + int id; + String type; + bool active; - MarkerData({required this.location, required this.size, required this.color, required this.radius}); + Sensor({required this.id, required this.type, required this.active}); + + factory Sensor.fromJson(Map<String, dynamic> json) { + return Sensor( + id: json['ID'], + type: json['type'], + active: json['active'], + ); + } } -// parseMarkerData parses jsonData into an object of type MakerData -List<MarkerData> parseMarkerData(String jsonString) { - final parsed = json.decode(jsonString); - return List<MarkerData>.from(parsed.map((data) => MarkerData( - location: LatLng(data['latitude'], data['longitude']), - size: data['size'].toDouble(), - color: parseColor(data['color']), - radius: data['radius'].toDouble(), - ))); +// DateAndTime holds the date and time for a single measurement +class DateAndTime { + int year; + int month; + int day; + int hour; + int minute; + + DateAndTime({ + required this.year, + required this.month, + required this.day, + required this.hour, + required this.minute, + }); + + factory DateAndTime.fromJson(Map<String, dynamic> json) { + return DateAndTime( + year: json['year'], + month: json['month'], + day: json['day'], + hour: json['hour'], + minute: json['minute'], + ); + } } -// parseColor parses the color strings into Colors types -Color parseColor(String colorString) { - switch (colorString) { - case 'blue': - return Colors.blue; - case 'red': - return Colors.red; - case 'green': - return Colors.green; - default: - return Colors.black; // Default color if unrecognized +// Measurement holds data related to a singular measurement taken +// at a given time +class Measurement { + double longitude; + double latitude; + DateAndTime datetime; + Sensor sensor; + double precipitation; + double thickness; + double maxWeight; + double safetyLevel; + double accuracy; + + Measurement({ + required this.longitude, + required this.latitude, + required this.datetime, + required this.sensor, + required this.precipitation, + required this.thickness, + required this.maxWeight, + required this.safetyLevel, + required this.accuracy, + }); + + factory Measurement.fromJson(Map<String, dynamic> json) { + return Measurement( + longitude: json['longitude'], + latitude: json['latitude'], + datetime: DateAndTime.fromJson(json['datetime']), + sensor: Sensor.fromJson(json['sensor']), + precipitation: json['precipitation'], + thickness: json['thickness'], + maxWeight: json['max_weight'], + safetyLevel: json['safety_level'], + accuracy: json['accuracy'], + ); } -} \ No newline at end of file +} + +// MarkerTemplate holds all data required for rendering a marker +class MarkerTemplate { + Measurement geoData; + LatLng location; + double size; + Color color; + + MarkerTemplate({ + required this.geoData, + required this.location, + required this.size, + required this.color + }); + + factory MarkerTemplate.fromJson(Map<String, dynamic> json) { + // Parse from JSON string to type Color + Color parsedColor = parseColor(json['color']); + + return MarkerTemplate( + geoData: Measurement.fromJson(json['geo_data']), + location: LatLng(json['latitude'], json['longitude']), + size: json['size'], + color: parsedColor, + ); + } + + // parseColor parses the color strings into Colors types + static Color parseColor(String colorString) { + switch (colorString) { + case 'yellow': + return Colors.yellow; + case 'red': + return Colors.red; + case 'green': + return Colors.green; + default: + return Colors.black; // Default color if unrecognized + } + } +} diff --git a/server/__pycache__/data_structs.cpython-311.pyc b/server/__pycache__/data_structs.cpython-311.pyc index 4163607b4b1b56fb78c7310f4a0863892bb42ce3..234ac85964595741b6de2f77e9d025cb0ae7b722 100644 GIT binary patch delta 18 YcmaDU_fn2?IWI340}#yE$eF+o05kFgqyPW_ delta 18 YcmaDU_fn2?IWI340}zOB<V@fP05NR@BLDyZ diff --git a/server/map/__pycache__/get_markers.cpython-311.pyc b/server/map/__pycache__/get_markers.cpython-311.pyc index fe067d8d451136985eb529449e19ff358e97b22b..59bda76604761ffdecd11385bb472c5054fdf005 100644 GIT binary patch delta 56 zcmX>ka!7=0IWI340}!my+sMVsDxY4Inwpmm5@29Zak#}?l$rwNnK;~HtK4kH%EJl( DZ;A|W delta 56 zcmX>ka!7=0IWI340}%WZ-^j(wD(_yDnwpmm5@29Zak#}Cl$rwNnK;~Hi`;C+%EJl( Damoxz diff --git a/server/map/get_markers.py b/server/map/get_markers.py index fe91e6ce..1bcb9100 100644 --- a/server/map/get_markers.py +++ b/server/map/get_markers.py @@ -26,9 +26,9 @@ def get_markers(): precipitation=0.0, thickness=0.0, max_weight=0.0, safety_level=0.0, accuracy=4.0) testData = [ - MarkerTemplate(measurement1, 30.0-measurement1.accuracy, "Green"), - MarkerTemplate(measurement2, 10.0-measurement2.accuracy, "Red"), - MarkerTemplate(measurement3, 20.0-measurement3.accuracy, "Yellow"), + MarkerTemplate(measurement1, 30.0-measurement1.accuracy, "green"), + MarkerTemplate(measurement2, 10.0-measurement2.accuracy, "red"), + MarkerTemplate(measurement3, 20.0-measurement3.accuracy, "yellow"), ] # NB: return test data as JSON -- GitLab