diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies
index cf4364fb06a78d8bf21a3a465b597f9defd3bcc6..078d7af5290766659fc88126c85ac23b0ebcdf5f 100644
--- a/.flutter-plugins-dependencies
+++ b/.flutter-plugins-dependencies
@@ -1 +1 @@
-{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"connectivity","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\connectivity-0.4.9+2\\\\","dependencies":[]},{"name":"flutter_blue","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_blue-0.7.2\\\\","dependencies":[]},{"name":"geolocator","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\geolocator-5.2.1\\\\","dependencies":["google_api_availability","location_permissions"]},{"name":"google_api_availability","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_api_availability-2.0.2\\\\","dependencies":[]},{"name":"location_permissions","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location_permissions-2.0.4+1\\\\","dependencies":[]},{"name":"path_provider","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.0\\\\","dependencies":[]},{"name":"permission_handler","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\permission_handler-4.2.0+hotfix.3\\\\","dependencies":[]},{"name":"shared_preferences","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences-0.5.7+2\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-1.2.0\\\\","dependencies":[]}],"android":[{"name":"connectivity","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\connectivity-0.4.9+2\\\\","dependencies":[]},{"name":"flutter_blue","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_blue-0.7.2\\\\","dependencies":[]},{"name":"geolocator","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\geolocator-5.2.1\\\\","dependencies":["google_api_availability","location_permissions"]},{"name":"google_api_availability","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_api_availability-2.0.2\\\\","dependencies":[]},{"name":"location_permissions","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location_permissions-2.0.4+1\\\\","dependencies":[]},{"name":"path_provider","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.0\\\\","dependencies":[]},{"name":"permission_handler","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\permission_handler-4.2.0+hotfix.3\\\\","dependencies":[]},{"name":"shared_preferences","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences-0.5.7+2\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-1.2.0\\\\","dependencies":[]}],"macos":[{"name":"connectivity_macos","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\connectivity_macos-0.1.0+4\\\\","dependencies":[]},{"name":"shared_preferences_macos","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences_macos-0.0.1+8\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-1.2.0\\\\","dependencies":[]}],"linux":[],"windows":[],"web":[{"name":"connectivity_for_web","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\connectivity_for_web-0.3.1+2\\\\","dependencies":[]},{"name":"shared_preferences_web","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences_web-0.1.2+5\\\\","dependencies":[]}]},"dependencyGraph":[{"name":"connectivity","dependencies":["connectivity_macos","connectivity_for_web"]},{"name":"connectivity_for_web","dependencies":[]},{"name":"connectivity_macos","dependencies":[]},{"name":"flutter_blue","dependencies":[]},{"name":"geolocator","dependencies":["google_api_availability","location_permissions"]},{"name":"google_api_availability","dependencies":[]},{"name":"location_permissions","dependencies":[]},{"name":"path_provider","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_macos","shared_preferences_web"]},{"name":"shared_preferences_macos","dependencies":[]},{"name":"shared_preferences_web","dependencies":[]},{"name":"sqflite","dependencies":[]}],"date_created":"2020-09-07 01:52:18.814120","version":"1.21.0-10.0.pre.193"}
\ No newline at end of file
+{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"app_settings","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\app_settings-4.0.3\\\\","dependencies":[]},{"name":"connectivity","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\connectivity-0.4.9+2\\\\","dependencies":[]},{"name":"flutter_blue","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_blue-0.7.2\\\\","dependencies":[]},{"name":"geolocator","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\geolocator-5.2.1\\\\","dependencies":["google_api_availability","location_permissions"]},{"name":"google_api_availability","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_api_availability-2.0.2\\\\","dependencies":[]},{"name":"location_permissions","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location_permissions-2.0.4+1\\\\","dependencies":[]},{"name":"path_provider","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.0\\\\","dependencies":[]},{"name":"permission_handler","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\permission_handler-4.2.0+hotfix.3\\\\","dependencies":[]},{"name":"shared_preferences","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences-0.5.7+2\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-1.2.0\\\\","dependencies":[]}],"android":[{"name":"app_settings","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\app_settings-4.0.3\\\\","dependencies":[]},{"name":"connectivity","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\connectivity-0.4.9+2\\\\","dependencies":[]},{"name":"flutter_blue","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_blue-0.7.2\\\\","dependencies":[]},{"name":"geolocator","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\geolocator-5.2.1\\\\","dependencies":["google_api_availability","location_permissions"]},{"name":"google_api_availability","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_api_availability-2.0.2\\\\","dependencies":[]},{"name":"location_permissions","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location_permissions-2.0.4+1\\\\","dependencies":[]},{"name":"path_provider","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.0\\\\","dependencies":[]},{"name":"permission_handler","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\permission_handler-4.2.0+hotfix.3\\\\","dependencies":[]},{"name":"shared_preferences","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences-0.5.7+2\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-1.2.0\\\\","dependencies":[]}],"macos":[{"name":"connectivity_macos","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\connectivity_macos-0.1.0+4\\\\","dependencies":[]},{"name":"shared_preferences_macos","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences_macos-0.0.1+8\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-1.2.0\\\\","dependencies":[]}],"linux":[],"windows":[],"web":[{"name":"connectivity_for_web","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\connectivity_for_web-0.3.1+2\\\\","dependencies":[]},{"name":"shared_preferences_web","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences_web-0.1.2+5\\\\","dependencies":[]}]},"dependencyGraph":[{"name":"app_settings","dependencies":[]},{"name":"connectivity","dependencies":["connectivity_macos","connectivity_for_web"]},{"name":"connectivity_for_web","dependencies":[]},{"name":"connectivity_macos","dependencies":[]},{"name":"flutter_blue","dependencies":[]},{"name":"geolocator","dependencies":["google_api_availability","location_permissions"]},{"name":"google_api_availability","dependencies":[]},{"name":"location_permissions","dependencies":[]},{"name":"path_provider","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_macos","shared_preferences_web"]},{"name":"shared_preferences_macos","dependencies":[]},{"name":"shared_preferences_web","dependencies":[]},{"name":"sqflite","dependencies":[]}],"date_created":"2020-09-14 03:13:52.288184","version":"1.21.0-10.0.pre.193"}
\ No newline at end of file
diff --git a/README.md b/README.md
index bcdaf2b2d36cdf0b5067bb88d8d139bedce4f3d1..53abdc718fd4280e83518330eb647037be28e6c3 100644
--- a/README.md
+++ b/README.md
@@ -15,6 +15,25 @@ flutter pub pub run intl_translation:extract_to_arb --output-dir=lib/localizatio
flutter pub pub run intl_translation:generate_from_arb --output-dir=lib/localization/l10n --no-use-deferred-loading lib/localization/localization.dart lib/localization/l10n/intl_en.arb lib/localization/l10n/intl_fr.arb
```
+## Documentation
+
+You can generate the application documentation yourself using the following command :
+
+```bash
+dartdoc
+```
+
+
+ In case of "dartdoc failed: Invalid argument(s): join(null, "bin", "cache", "dart-sdk")"
+
+ Set the following environment variable:
+
+ ```bash
+ FLUTTER_ROOT=
+ ```
+
+
+
## File Structure
The project is divided in multiple components:
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index d13eaf3543c9da50099feecf13c32942ccc14830..baca04abeb6ff18531936d6ddff6c0c1588f24c2 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -6,6 +6,9 @@
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
+
+
+
{
'fr'
].contains(locale.languageCode);
- /// Delegates the loading of [Locale] to an [async] task, which enables it to be done in the background.
+ /// Delegates the loading of [Locale] to an async task, which enables it to be done in the background.
@override
Future load(Locale locale) => AppLocalization.load(locale);
diff --git a/lib/logic/controllers/home_controller.dart b/lib/logic/controllers/home_controller.dart
index 0b40c399fe6418770ecfc66065d3448e926bb135..0e7269efa38b4d7d3372913731446656e4231c59 100644
--- a/lib/logic/controllers/home_controller.dart
+++ b/lib/logic/controllers/home_controller.dart
@@ -16,6 +16,7 @@ class HomeController {
factory HomeController() => _singleton;
+ /// [HomeController] initializer that sets the default initial values.
HomeController._internal() {
this._currentPage = 0;
this._previousPage = 0;
diff --git a/lib/logic/controllers/map_display_controller.dart b/lib/logic/controllers/map_display_controller.dart
index 60cece797b01a9dff49f7bf58be27113e0c110ba..432c792ba6c1ecf4fae7cb7b1267fe338ec0b234 100644
--- a/lib/logic/controllers/map_display_controller.dart
+++ b/lib/logic/controllers/map_display_controller.dart
@@ -4,14 +4,14 @@ import 'package:flutter/material.dart';
import 'package:flutter_map/plugin_api.dart';
import 'package:latlong/latlong.dart';
import 'package:logair_application/logic/handlers/data_handler.dart';
-import 'package:logair_application/logic/handlers/database_handler.dart';
+import 'package:logair_application/logic/handlers/main_database_handler.dart';
import 'package:logair_application/logic/handlers/network_handler.dart';
import 'package:logair_application/logic/data_header.dart';
import 'package:logair_application/logic/data_packet.dart';
import 'package:logair_application/logic/handlers/position_handler.dart';
import 'package:logair_application/utils/enums/pm_symbol.dart';
-/// The [MapDisplayController] is a [Singleton] that handles the mapping of information.
+/// The [MapDisplayController] is a singleton that handles the mapping of information.
class MapDisplayController {
/// Whether or not the user has assumed manual control of the [FlutterMap],
bool _manualMotion = false;
@@ -35,20 +35,20 @@ class MapDisplayController {
Marker _marker;
Future _rebuildMarkers() async {
- List packets = await DatabaseHandler().getLastPackets(200);
+ List packets = await MainDatabaseHandler().getLastPackets(200);
packets.forEach((DataPacket packet) {
switch (_pmSymbol) {
case PMSymbol.PM1:
- this.addToList(this._currentPos, packet.pm1(), 200);
+ this.addToList(this._currentPos, packet.pm1, 200);
break;
case PMSymbol.PM1:
- this.addToList(this._currentPos, packet.pm2_5(), 200);
+ this.addToList(this._currentPos, packet.pm2_5, 200);
break;
case PMSymbol.PM4:
- this.addToList(this._currentPos, packet.pm4(), 200);
+ this.addToList(this._currentPos, packet.pm4, 200);
break;
case PMSymbol.PM10:
- this.addToList(this._currentPos, packet.pm10(), 200);
+ this.addToList(this._currentPos, packet.pm10, 200);
break;
default:
break;
@@ -90,7 +90,7 @@ class MapDisplayController {
}
/// This function is executed on first initialization of the [MapDisplayController]
- /// TODO: Throttle to 1 in 5 updates for efficiency ?
+ // TODO: Throttle to 1 in 5 updates for efficiency ?
MapDisplayController._internal() {
/// A new [MapController] is used as the global Controller.
/// This avoids Garbage Collection rules and enables the [FlutterMap] to survive [State] changes, and other such events.
@@ -103,10 +103,9 @@ class MapDisplayController {
return;
/// If a [BluetoothDevice] is connected, then the [DataHandler] will have a [DataPacket] available.
- DataPacket latest = DataHandler().getLatestData();
-
+ DataPacket latest = null;
/// If the [DataPacket] is older than 5 seconds we invalidate it.
- if (latest != null && latest.timestamp() <= (DateTime.now().millisecondsSinceEpoch - 5000))
+ if (latest != null && latest.timestamp <= (DateTime.now().millisecondsSinceEpoch - 5000))
latest = null;
/// Keep track of the last [Position] to draw [Polyline]s.
@@ -120,6 +119,7 @@ class MapDisplayController {
this._controller.move(this._currentPos, this._zoom);
/// Move the [Marker] to the current [Position].
+ // TODO: Use StreamBuilder in Map.
this._marker = this._buildLocationMarker(this._currentPos);
if ((this._lastPos != null && this._currentPos != null)) {// && this._distance.as(LengthUnit.Meter, this._lastPos, this._currentPos) >= 2)) {
@@ -136,20 +136,20 @@ class MapDisplayController {
if (latest != null) {
switch (_pmSymbol) {
case PMSymbol.PM1:
- if (latest.pm1() != null)
- this.addToList(this._currentPos, latest.pm1(), 200);
+ if (latest.pm1 != null)
+ this.addToList(this._currentPos, latest.pm1, 200);
break;
case PMSymbol.PM2_5:
- if (latest.pm2_5() != null)
- this.addToList(this._currentPos, latest.pm2_5(), 200);
+ if (latest.pm2_5 != null)
+ this.addToList(this._currentPos, latest.pm2_5, 200);
break;
case PMSymbol.PM4:
- if (latest.pm4() != null)
- this.addToList(this._currentPos, latest.pm4(), 200);
+ if (latest.pm4 != null)
+ this.addToList(this._currentPos, latest.pm4, 200);
break;
case PMSymbol.PM10:
- if (latest.pm10() != null)
- this.addToList(this._currentPos, latest.pm10(), 200);
+ if (latest.pm10 != null)
+ this.addToList(this._currentPos, latest.pm10, 200);
break;
default:
break;
@@ -161,7 +161,7 @@ class MapDisplayController {
new Timer.periodic(Duration(minutes: 1), (Timer t) {
if (this._controller != null && this._controller.bounds != null) {
//print('${this._controller.bounds.southWest}, ${this._controller.bounds.northEast}');
- NetworkHandler().getProximityPoints(DataHeader().deviceID, this._controller.bounds);
+ NetworkHandler().getProximityPoints(DataHeader().deviceId, this._controller.bounds);
}
});
}
diff --git a/lib/logic/data_header.dart b/lib/logic/data_header.dart
index 3d6cb9d3460198baef04a78cb5a5108b342ebf2d..31f71d6861d90cd50ea4ed6b3502f53f470d4135 100644
--- a/lib/logic/data_header.dart
+++ b/lib/logic/data_header.dart
@@ -19,19 +19,28 @@ class DataHeader {
bool _headerSet;
+ String _deviceId;
+
+ String _url;
+
void setHeader(List header) {
this._headerData = String.fromCharCodes(header.sublist(1, header.length - 1)).split(',');
+ this._deviceId = this._headerData[0];
+ this._url = this._headerData[1];
this._headerSet = true;
}
- void setHeaderFromExisting({String deviceId = '', String url = ''}) {
- this._headerData = [deviceID, url];
+ void setHeaderFromExisting({@required String deviceId, @required String url}) {
+ this._headerData = [deviceId, url];
+ this._deviceId = deviceId;
+ this._url = url;
this._headerSet = true;
}
/// Retrieve the deviceID from the header
- String get deviceID => (this._headerData != null && this._headerData.length > 0) ? this._headerData[0] : '';
- String get url => (this._headerData != null && this._headerData.length > 0) ? this._headerData[1] : '';
+ String get deviceId => (this._headerSet && this._deviceId != null) ? this._deviceId : '';
+ String get url => (this._headerSet && this._url != null) ? this._url : '';
+
/// @Getter for _headerSet;
bool get headerSet => this._headerSet;
@@ -46,7 +55,7 @@ class DataHeader {
bool isEqual(List that) => ListEquality().equals(_headerData, that);
// TODO
- Map jsonify() => { 'device_id' : this._headerData[0], 'url': '000000000000' };
+ Map jsonify() => { 'device_id' : this.deviceId, 'url': this.url };
void dispose() {
this._headerSet = false;
@@ -55,7 +64,7 @@ class DataHeader {
Stream deviceIdStream() async* {
while(true) {
- yield this.deviceID;
+ yield this._deviceId;
await Future.delayed(Duration(seconds: 1));
}
}
diff --git a/lib/logic/data_packet.dart b/lib/logic/data_packet.dart
index 0b371fcb390cad15791702a3e9f0865c0291a7ac..e6c3312ecdcca29efbe5a5496dc3afd609ec23ed 100644
--- a/lib/logic/data_packet.dart
+++ b/lib/logic/data_packet.dart
@@ -11,6 +11,7 @@ class DataPacket {
List _data;
int _timestamp;
String _deviceId;
+ String _url;
/* Location variables */
double _latitude;
@@ -31,26 +32,32 @@ class DataPacket {
double _pm10;
// TODO Firmware v2
+ // ignore: unused_field
String _extraData;
- int timestamp() => _timestamp;
- String deviceId() => _deviceId ?? '';
- double latitude() => _latitude;
- double longitude() => _longitude;
- int altitude() => _altitude;
- int heading() => _heading;
- double speed() => _speed;
- double temperature() => _temperature;
- double pressure() => _pressure;
- double relativeHumidity() => _relativeHumidity;
- double pm1() => _pm1;
- double pm2_5() => _pm2_5;
- double pm4() => _pm4;
- double pm10() => _pm10;
+ int get timestamp => this._timestamp;
+ String get deviceId => this._deviceId ?? '';
+ String get url => this._url ?? '';
+ double get latitude => this._latitude;
+ double get longitude => this._longitude;
+ int get altitude => this._altitude;
+ int get heading => this._heading;
+ double get speed => this._speed;
+ double get temperature => this._temperature;
+ double get pressure => this._pressure;
+ double get relativeHumidity => this._relativeHumidity;
+ double get pm1 => this._pm1;
+ double get pm2_5 => this._pm2_5;
+ double get pm4 => this._pm4;
+ double get pm10 => this._pm10;
+
+ set deviceId(String newId) => this._deviceId = newId;
+ set url(String newUrl) => this._url = newUrl;
DataPacket(this._data) {
_timestamp = DateTime.now().millisecondsSinceEpoch;
List acquiredData = String.fromCharCodes(this._data.sublist(1, this._data.length - 1)).split(',');
+
this._latitude = (acquiredData[0] != '') ? parseDoubleWrapper(acquiredData[0]) : null;
this._longitude = (acquiredData[1] != '') ? parseDoubleWrapper(acquiredData[1]) : null;
this._altitude = (acquiredData[2] != '') ? int.tryParse(acquiredData[2]) : null;
@@ -80,9 +87,15 @@ class DataPacket {
DataPacket.fromData(this._timestamp, this._latitude, this._longitude, this._altitude, this._speed, this._heading, this._temperature, this._pressure, this._relativeHumidity, this._pm1, this._pm2_5, this._pm4, this._pm10, this._extraData);
- // TODO Guard clause
DataPacket.fromMappedData(Map data) {
+ List guardSet = ['device_id', 'url', 'timestamp_nix', 'latitude', 'longitude', 'altitude', 'speed', 'heading', 'temperature', 'pressure', 'relative_humidity', 'pm_1', 'pm_2_5', 'pm_4', 'pm_10', 'extra'];
+
+ if(data.keys.toList().where((String key) => guardSet.contains(key)).length < guardSet.length) {
+ throw Exception('Mapped Data Error');
+ }
+
this._deviceId = data['device_id'];
+ this._url = data['url'];
this._timestamp = data['timestamp_nix'];
this._latitude = data['latitude'];
this._longitude = data['longitude'];
@@ -90,8 +103,8 @@ class DataPacket {
this._speed = data['speed'];
this._heading = data['heading'];
this._temperature = data['temperature'];
- this._relativeHumidity = data['relative_humidity'];
this._pressure = data['pressure'];
+ this._relativeHumidity = data['relative_humidity'];
this._pm1 = data['pm_1'];
this._pm2_5 = data['pm_2_5'];
this._pm4 = data['pm_4'];
@@ -117,6 +130,7 @@ class DataPacket {
this._pm10
];
+ /// Retrieves the DB insertable reference to this packet.
Map toMap() {
return {
'timestamp_nix': this._timestamp,
@@ -126,13 +140,16 @@ class DataPacket {
'speed': this._speed,
'heading': this._heading,
'temperature': this._temperature,
- 'relative_humidity': this._temperature,
+ 'relative_humidity': this.relativeHumidity,
'pressure': this._pressure,
'pm_1': this._pm1,
'pm_2_5': this._pm2_5,
'pm_4': this._pm4,
'pm_10': this._pm10,
- 'extra': ''
+ 'extra': '',
+ 'device_id': this._deviceId,
+ 'url': this._url,
+
};
}
diff --git a/lib/logic/handlers/bluetooth_le_handler.dart b/lib/logic/handlers/bluetooth_le_handler.dart
index 6a0b93213eb6af604e3b3fcd61d02a5ecd9f7757..cdbd29df7b482fd47f4d6c043999572b65c505a8 100644
--- a/lib/logic/handlers/bluetooth_le_handler.dart
+++ b/lib/logic/handlers/bluetooth_le_handler.dart
@@ -6,11 +6,12 @@ import 'package:flutter_blue/flutter_blue.dart';
import 'package:kotlin_flavor/scope_functions.dart';
import 'package:logair_application/logic/handlers/bluetooth_wake_handler.dart';
import 'package:logair_application/logic/handlers/preference_handler.dart';
-import 'package:logair_application/services/wake_service.dart';
import 'package:logair_application/utils/enums/bluetooth_connection_status.dart';
import 'package:logair_application/logic/handlers/data_handler.dart';
import 'package:logair_application/utils/enums/preference_keys.dart';
+// TODO Attempt reacquiring device after 5 seconds inactivity.
+
/// Serves as a wrapper class around [FlutterBlue], and helps integrate it into the application with extensions
class BTLEHandler {
/// [Singleton]() instantiation factory.
@@ -60,7 +61,7 @@ class BTLEHandler {
Stream getConnectionStatus() async* {
while (true) {
yield _bluetoothConnectionStatus;
- await Future.delayed(Duration(seconds: 2));
+ await Future.delayed(Duration(milliseconds: 250));
}
}
diff --git a/lib/logic/handlers/bluetooth_wake_handler.dart b/lib/logic/handlers/bluetooth_wake_handler.dart
index 7c63b61b438c28f323cdbac64a8c97ab24e16619..28633c381656f0e1c90245749a71e31838f14f45 100644
--- a/lib/logic/handlers/bluetooth_wake_handler.dart
+++ b/lib/logic/handlers/bluetooth_wake_handler.dart
@@ -1,9 +1,7 @@
-import 'dart:async';
-
import 'package:logair_application/services/wake_service.dart';
/// Handler that wraps the [WakeService]
-/// TODO flutter_blue seems to do so already, needs testing and iOS solution
+// TODO: Relative end / start -> Start and end with guard instead of switch.
class BTWakeHandler {
factory BTWakeHandler() => _singleton;
diff --git a/lib/logic/handlers/data_handler.dart b/lib/logic/handlers/data_handler.dart
index 7905fde6efcbf0a98f745df9064f602d5b029660..988bba3147186b5152c6771358508d2ed4940441 100644
--- a/lib/logic/handlers/data_handler.dart
+++ b/lib/logic/handlers/data_handler.dart
@@ -1,7 +1,7 @@
import 'package:logair_application/logic/handlers/bluetooth_le_handler.dart';
import 'package:logair_application/logic/data_header.dart';
import 'package:logair_application/logic/data_packet.dart';
-import 'package:logair_application/logic/handlers/database_handler.dart';
+import 'package:logair_application/logic/handlers/main_database_handler.dart';
import 'package:logair_application/logic/handlers/network_handler.dart';
class DataHandler {
@@ -57,53 +57,56 @@ class DataHandler {
bool wasSet = DataHeader().headerSet;
DataHeader().setHeader(packet);
/// Retroactively add all previous packets
- if (!wasSet && DataHeader().headerSet)
- _sortedData.forEach((packet) => DatabaseHandler().insertData(packet, DataHeader().deviceID, DataHeader().url));
+ if (!wasSet && DataHeader().headerSet) {
+ _sortedData.forEach((dataPacket) {
+ dataPacket.deviceId = DataHeader().deviceId;
+ dataPacket.url = DataHeader().url;
+ MainDatabaseHandler().insertData(dataPacket);
+ });
+ }
/// Or if it is a [DataPacket] instance.
} else if (packet[0] == 91) {
- _sortedData.add(DataPacket(packet));
print('PACKET ${String.fromCharCodes(packet)}');
- if (DataHeader().headerSet)
- DatabaseHandler().insertData(_sortedData.last, DataHeader().deviceID, DataHeader().url);
+ DataPacket dataPacket = DataPacket(packet);
+ if (DataHeader().headerSet) {
+ dataPacket.deviceId = DataHeader().deviceId;
+ dataPacket.url = DataHeader().url;
+ MainDatabaseHandler().insertData(dataPacket);
+ } else
+ _sortedData.add(dataPacket);
}
}
- /// TODO Used for debugging, later
- void printLatest() {
- print(_sortedData.last);
- }
/// Get the entirety of the [DataPacket]s.
+ @deprecated
List getData() => _sortedData;
/// Remove the entirety of the acquired data.
+ @deprecated
void clearData() {
_sortedData.removeWhere((element) => true);
}
/// Remove the first element of the [DataPacket]s. Used for surgical removal.
- void pop() {
- if (_sortedData.isNotEmpty)
- _sortedData.removeAt(0);
+ @deprecated
+ void pop(int timestamp) {
+ if (_sortedData.isNotEmpty)
+ _sortedData.removeWhere((DataPacket d) => d.timestamp == timestamp);
}
/// Get the latest [DataPacket]
+ @deprecated
DataPacket getLatestData() => (_sortedData.length > 0) ? _sortedData.last : null;
/// Stream the latest confirmed [DataPacket] received by the device.
+ @deprecated
Stream getDataStream() async* {
while(true) {
yield (_sortedData.length > 0) ? _sortedData.last : null;
await Future.delayed(Duration(seconds: 1));
}
}
-
- Stream getMockDataStream() async* {
- while(true) {
- yield new DataPacket.fromData(1597957282000, 5, 42, 420, 3.0, 32, 24, 10123, 32, null, 5, null, 9, "");
- await Future.delayed(Duration(seconds: 1));
- }
- }
/// This destroys the elements it depends on to avoid duplication or wrong information
void dispose() {
diff --git a/lib/logic/handlers/locations_interest_database_handler.dart b/lib/logic/handlers/locations_interest_database_handler.dart
new file mode 100644
index 0000000000000000000000000000000000000000..86bca84728e108a3ae8343428118ebf8c1fc5b06
--- /dev/null
+++ b/lib/logic/handlers/locations_interest_database_handler.dart
@@ -0,0 +1,88 @@
+
+import 'dart:async';
+
+import 'package:flutter/cupertino.dart';
+import 'package:logair_application/logic/data_packet.dart';
+import 'package:logair_application/utils/helpers/location_of_interest.dart';
+import 'package:path/path.dart';
+import 'package:rxdart/rxdart.dart';
+import 'package:sqflite/sqflite.dart';
+
+/// Handler that integrates a mysqli database into the application's workflow.
+class LocationsOfInterestDatabaseHandler {
+ factory LocationsOfInterestDatabaseHandler() => _singleton;
+
+ LocationsOfInterestDatabaseHandler._internal();
+
+ static final LocationsOfInterestDatabaseHandler _singleton = new LocationsOfInterestDatabaseHandler._internal();
+
+ /// Reference to the internalized [Database] within this instance.
+ Future _loidb;
+
+ /// [Database] initialization string, to reduce repetition.
+ final String _createLOIDBString = '''CREATE TABLE loi(
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ name TEXT, latitude REAL, longitude REAL
+ )''';
+
+ /// Retrieves the internal [Database] instance, and if not instantiated, instantiates it.
+ Future get _loiDatabase async {
+ if (_loidb == null)
+ this._loidb = openDatabase(
+ join((await getDatabasesPath()), 'logair_loi.db'),
+ version: 0,
+ onCreate: (db, version) => db.execute(this._createLOIDBString),
+ );
+ return this._loidb;
+ }
+
+ /// Purges the [Database] of all internal data.
+ Future recreateDB() async {
+ final Database database = await _loiDatabase;
+
+ await database.rawQuery('DROP TABLE IF EXISTS loi');
+ await database.rawQuery(this._createLOIDBString);
+ this.onUpdate.value = 1;
+ }
+
+ /// Inserts data into the [Database].
+ Future insertData({@required String name, @required double latitude, @required double longitude}) async {
+ final Database database = await this._loiDatabase;
+ Map insert = {
+ 'name': name,
+ 'latitude': latitude,
+ 'longitude': longitude
+ };
+ await database.insert(
+ 'loi',
+ insert,
+ conflictAlgorithm: ConflictAlgorithm.replace
+ );
+ this.onUpdate.value = 1;
+ }
+
+ /// Retrieves all of the [DataPacket]s inserted into the [Database].
+ Future> get data async {
+ final Database database = await this._loiDatabase;
+
+ final List