Skip to content
Snippets Groups Projects
Commit f36a162f authored by Sara Savanovic Djordjevic's avatar Sara Savanovic Djordjevic
Browse files

update: marker_data classes

parent c9f7ea29
No related branches found
No related tags found
No related merge requests found
......@@ -2,4 +2,7 @@
.vs/
# Auto-generated by Android Studio
.idea/
\ No newline at end of file
.idea/
# Python interpereter
venv/
\ No newline at end of file
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'widgets/map_widget.dart';
import 'marker_data.dart';
import 'marker_handler/marker_data.dart';
import 'consts.dart';
import 'marker_handler/get_markers.dart';
class DefaultPage extends StatefulWidget {
const DefaultPage({super.key});
......@@ -16,45 +15,27 @@ class DefaultPage extends StatefulWidget {
class _DefaultPageState extends State<DefaultPage> {
late Timer _timer;
List<MarkerTemplate> markerList = [];
List<Measurement> markerList = [];
// fetchMarkerTemplate requests data from the update_map endpoint
Future<void> fetchMarkerTemplate() async {
// Call fetchMarkerTemplate and await its result before setting the state
Future<void> loadMarkerList() async {
try {
// Custom HTTP client
HttpClient client = HttpClient()
..badCertificateCallback = // NB: temporary disable SSL certificate validation
(X509Certificate cert, String host, int port) => true;
List<Measurement> fetchedMarkers = await fetchMarkerData();
// Request makers from API and wait for response
var request = await client.getUrl(Uri.parse(serverURI + mapEndpoint));
var response = await request.close();
// Attempt to parse json if request is ok
if (response.statusCode == 200) {
var responseBody = await response.transform(utf8.decoder).join();
setState(() {
// 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}');
}
setState(() {
markerList = fetchedMarkers;
});
} catch (e) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Error"),
content: Text("Failed to connect to the server. Please check your network connection"),
content: Text(e.toString()),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop(); // Close the dialog
Navigator.of(context).pop();
},
child: Text("OK"),
),
......@@ -69,13 +50,13 @@ class _DefaultPageState extends State<DefaultPage> {
@override
void initState() {
super.initState();
// Call fetchMarkerTemplate when the widget is first created
fetchMarkerTemplate();
// Load marker data from server
loadMarkerList();
// Schedule fetchMarkerTemplate to run periodically based on fetchInterval const
const Duration fiveMinutes = Duration(minutes: fetchInterval);
_timer = Timer.periodic(fiveMinutes, (timer) {
fetchMarkerTemplate();
const Duration interval = Duration(minutes: fetchInterval);
_timer = Timer.periodic(interval, (timer) {
fetchMarkerData();
});
}
......
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import '../consts.dart';
import 'marker_data.dart';
// fetchMarkerTemplate requests all marker data from the server
Future<List<Measurement>> fetchMarkerData() async {
try {
HttpClient client = HttpClient()
..badCertificateCallback = (X509Certificate cert, String host, int port) => true;
var request = await client.getUrl(Uri.parse(serverURI + mapEndpoint));
var response = await request.close();
if (response.statusCode == 200) {
var responseBody = await response.transform(utf8.decoder).join();
List<dynamic> jsonData = json.decode(responseBody);
return jsonData.map((data) => Measurement.Measurement(data)).toList();
} else {
print('Request failed with status: ${response.statusCode}');
// Throw an exception or return null if the request fails
throw Exception('Failed to fetch marker template');
}
} catch (e) {
print('Error: $e');
// Throw an exception or return null if there's an error
throw Exception('Failed to connect to the server. Please check your network connection');
}
}
import 'package:flutter/material.dart';
import 'package:latlong2/latlong.dart';
// Sensor holds data about a single sensor
class Sensor {
int id;
String type;
bool active;
class Measurement {
int measurementID;
int timeMeasured;
Sensor sensor;
List<Data> dataList;
Sensor({required this.id, required this.type, required this.active});
Measurement({
required this.measurementID,
required this.timeMeasured,
required this.sensor,
required this.dataList,
});
factory Sensor.fromJson(Map<String, dynamic> json) {
return Sensor(
id: json['ID'],
type: json['type'],
active: json['active'],
factory Measurement.Measurement(Map<String, dynamic> json) {
return Measurement(
measurementID: json['MeasurementID'],
timeMeasured: json['TimeMeasured'],
sensor: Sensor.fromJson(json['Sensor']),
dataList: (json['Data'] as List<dynamic>)
.map((data) => Data.fromJson(data))
.toList(),
);
}
}
// DateAndTime holds the date and time for a single measurement
class DateAndTime {
int year;
int month;
int day;
int hour;
int minute;
class Sensor {
int sensorID;
String sensorType;
bool active;
DateAndTime({
required this.year,
required this.month,
required this.day,
required this.hour,
required this.minute,
Sensor({
required this.sensorID,
required this.sensorType,
required this.active,
});
factory DateAndTime.fromJson(Map<String, dynamic> json) {
return DateAndTime(
year: json['year'],
month: json['month'],
day: json['day'],
hour: json['hour'],
minute: json['minute'],
factory Sensor.fromJson(Map<String, dynamic> json) {
return Sensor(
sensorID: json['SensorID'],
sensorType: json['SensorType'],
active: json['Active'],
);
}
}
// Measurement holds data related to a singular measurement taken
// at a given time
class Measurement {
double longitude;
class Data {
double latitude;
DateAndTime datetime;
Sensor sensor;
double precipitation;
double thickness;
double maxWeight;
double safetyLevel;
double longitude;
double iceTop;
double iceBottom;
double calculatedThickness;
double accuracy;
Measurement({
required this.longitude,
Data({
required this.latitude,
required this.datetime,
required this.sensor,
required this.precipitation,
required this.thickness,
required this.maxWeight,
required this.safetyLevel,
required this.longitude,
required this.iceTop,
required this.iceBottom,
required this.calculatedThickness,
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'],
factory Data.fromJson(Map<String, dynamic> json) {
return Data(
latitude: json['Latitude'],
longitude: json['Longitude'],
iceTop: json['IceTop'],
iceBottom: json['IceBottom'],
calculatedThickness: json['CalculatedThickness'],
accuracy: json['Accuracy'],
);
}
}
// 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) {
colorString = colorString.toLowerCase();
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
}
}
}
}
\ No newline at end of file
import 'package:flutter/material.dart';
import '../marker_data.dart';
import '../marker_handler/marker_data.dart';
import '../consts.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart';
......@@ -8,7 +8,7 @@ import 'quick_view_chart.dart';
import 'stat_charts.dart';
class MapContainerWidget extends StatefulWidget {
final List<MarkerTemplate> markerList;
final List<Measurement> markerList;
const MapContainerWidget({Key? key, required this.markerList}) : super(key: key);
......@@ -18,7 +18,7 @@ class MapContainerWidget extends StatefulWidget {
class _MapContainerWidgetState extends State<MapContainerWidget> {
MarkerTemplate? selectedMarker;
Measurement? selectedMarker;
bool isMinimized = true; // Quick view box state tacker
@override
......@@ -31,83 +31,12 @@ class _MapContainerWidgetState extends State<MapContainerWidget> {
double screenWidth = constraints.maxWidth;
double boxWidth = 0.86;
double boxHeight = 1.4;
<<<<<<< HEAD
return Column(
children: [
Container(
width: screenWidth * boxWidth,
height: screenWidth * boxHeight,
color: Colors.blue,
child: FlutterMap(
options: MapOptions(
center: LatLng(60.7666, 10.8471),
zoom: 9.0,
),
children: [
TileLayer(
urlTemplate: "https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png",
subdomains: const ['a', 'b', 'c'],
),
MarkerLayer(
markers: widget.markerList.map((MarkerTemplate markerTemplate) {
return Marker(
width: markerTemplate.size,
height: markerTemplate.size,
point: markerTemplate.location,
builder: (ctx) => GestureDetector(
onTap: () {
setState(() {
selectedMarker = markerTemplate;
});
},
child: Image.asset(
'assets/icons/circle-red.png',
// Path to your custom icon asset
color: markerTemplate.color,
width: markerTemplate.size,
height: markerTemplate.size,
),
),
);
}).toList(),
),
/*PolygonLayer(
polygons: [
Polygon(
points: [
LatLng(60.7600, 10.8000),
LatLng(60.7600, 11.0000),
LatLng(60.7000, 11.0000),
LatLng(60.7000, 10.8000),
],
color: Colors.blue,
isFilled: true,
),
],
),*/
],
),
),
const SizedBox(height: contPadding), // Padding between containers
Container(
//width: screenWidth * boxWidth,
height: screenWidth * boxHeight*1.5, // NB: make dynamic
color: const Color(0xFF64B5F6),
child: Align(
alignment: Alignment.topLeft,
child: Padding(
padding: const EdgeInsets.only(top: 20, left: 20), // Edge padding, text
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
=======
return Column(
children: [
const SizedBox(height: contPadding),
ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Stack(
>>>>>>> faa9a56f985acdab1c81feefa6cee6b055f14b19
children: [
SizedBox(
width: screenWidth * boxWidth,
......@@ -123,22 +52,22 @@ class _MapContainerWidgetState extends State<MapContainerWidget> {
subdomains: const ['a', 'b', 'c'],
),
MarkerLayer(
markers: widget.markerList.map((MarkerTemplate markerTemplate) {
markers: widget.markerList.map((Measurement Measurement) {
return Marker(
width: markerTemplate.size,
height: markerTemplate.size,
point: markerTemplate.location,
width: 50,
height: 50,
point: LatLng(Measurement.dataList[0].latitude, Measurement.dataList[0].longitude),
builder: (ctx) => GestureDetector(
onTap: () {
setState(() {
selectedMarker = markerTemplate;
selectedMarker = Measurement;
});
},
child: Image.asset(
'assets/icons/circle-red.png',
color: markerTemplate.color,
width: markerTemplate.size,
height: markerTemplate.size,
color: Colors.red,
width: 50,
height: 50,
),
),
);
......@@ -209,11 +138,11 @@ class _MapContainerWidgetState extends State<MapContainerWidget> {
style: titleStyle,
),
Text(
'Safety level: ${selectedMarker?.geoData.safetyLevel}',
'Time of measurement: ${selectedMarker?.timeMeasured}',
style: regTextStyle,
),
Text(
'Location: (${selectedMarker?.geoData.latitude},${selectedMarker?.geoData.longitude})',
'Location: (placeholder, placeholder)',
style: regTextStyle,
),
const SizedBox(height: contPadding),
......
......@@ -5,6 +5,8 @@
import FlutterMacOS
import Foundation
import path_provider_foundation
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
}
No preview for this file type
import os
import sys
from bson import json_util
current_dir = os.path.dirname(__file__)
parent_dir = os.path.abspath(os.path.join(current_dir, '..'))
sys.path.append(parent_dir)
......@@ -10,40 +11,60 @@ import json
# get_markers requests all marker data from mongoDB
def get_all_markers(self, cursor):
try:
# Fetch all data
cursor.execute('''
SELECT m.MeasurementID, m.SensorID, m.TimeMeasured, m.Latitude, m.Longitude,
m.MeasuredThickness, m.Accuracy, s.SensorType, s.Active
SELECT m.MeasurementID, m.SensorID, m.TimeMeasured, d.Latitude, d.Longitude,
d.IceTop, d.IceBottom, d.CalculatedThickness, d.Accuracy, s.SensorType, s.Active
FROM Measurement m
INNER JOIN Sensor s ON m.SensorID = s.SensorID
INNER JOIN Data d ON m.MeasurementID = d.MeasurementID
''')
rows = cursor.fetchall()
data = []
measurement_data = {}
for row in rows:
measurement = {
'MeasurementID': row[0],
'TimeMeasured': row[1],
'Latitude': row[2],
'Longitude': row[3],
'MeasuredThickness': row[4],
'Accuracy': row[5],
'Sensor': {
'SensorID': row[6],
'SensorType': row[7],
'Active': bool(row[8])
}
measurement_id = row[0]
data_object = {
'Latitude': row[3],
'Longitude': row[4],
'IceTop': row[5],
'IceBottom': row[6],
'CalculatedThickness': row[7],
'Accuracy': row[8]
}
data.append(measurement)
resp_code = 200
# Convert the list of dictionaries to JSON
marker_json = json.dumps(data, indent=4)
# Append data with measurement ID x to measurement x object
if measurement_id in measurement_data:
measurement_data[measurement_id]['Data'].append(data_object)
else:
# Create a new measurement entry if measurement ID doesn't exist already
measurement_data[measurement_id] = {
'MeasurementID': measurement_id,
'TimeMeasured': row[1],
'Sensor': {
'SensorID': row[2],
'SensorType': row[9],
'Active': bool(row[10])
},
'Data': [data_object]
}
# Convert dictionary values to list of measurements
data = list(measurement_data.values())
if len(rows) == 0 or len(data) == 0: # Return 500 and empty list if no data is found
print(f"An error occurred while querying the database")
resp_code = 500
marker_json = '[]'
else:
resp_code = 200
# Convert list of dictionaries to JSON
marker_json = json.dumps(data, indent=4)
except Exception as e:
print(f"An error occurred while querying MongoDB: {e}")
print(f"An error occurred while querying the database: {e}")
resp_code = 500
marker_json = '[]'
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment