Commit 438c8dc0 authored by Nicolas Richard Walter Boeckh's avatar Nicolas Richard Walter Boeckh 💬

Revamp architecture, document

parent 97437cdf
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"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":"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":"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":"shared_preferences_web","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences_web-0.1.2+5\\\\","dependencies":[]}]},"dependencyGraph":[{"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-05-14 22:04:13.189169","version":"1.19.0-2.0.pre.49"}
\ No newline at end of file
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"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":"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":"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":"shared_preferences_web","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences_web-0.1.2+5\\\\","dependencies":[]}]},"dependencyGraph":[{"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-05-15 09:53:45.937806","version":"1.19.0-2.0.pre.71"}
\ No newline at end of file
......@@ -11,6 +11,24 @@ The Application that handles the connection between LogAir devices and LogAir's
```bash
flutter pub get
flutter pub pub run intl_translation:extract_to_arb --output-dir=lib/l10n lib/localization/localization.dart
flutter pub pub run intl_translation:generate_from_arb --output-dir=lib/l10n --no-use-deferred-loading lib/localization/localization.dart lib/l10n/intl_en.arb lib/l10n/intl_fr.arb
flutter pub pub run intl_translation:extract_to_arb --output-dir=lib/localization/l10n lib/localization/localization.dart
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
```
## File Structure
The project is divided in multiple components:
- `localization` contains the code enabling the software to transition from one locale to another:
- `l10n`: Language files.
- `logic` represents logical elements (advanced data types specific to the software's function):
- `controllers`: Fine control over a Widget even from outside of its scope ;
- `handlers`: Fine control over a logic segment from any scope.
- `services` contains code enabling the access to platform side content ;
- `ui` contains code for the Widgets ie. the Graphical components of the software ;
- `animation`: Transitions between pages ;
- `components`: Various tree end Widgets ;
- `dialog`: Dialogs for user interaction ;
- `routes`: Widget Tree root elements.
- `utils` contains decluttering code :
- `enums`: type representation ;
{
"@@last_modified": "2020-02-05T17:25:56.614777",
"ok": "OK",
"@ok": {
"type": "text",
"placeholders": {}
},
"cancel": "Annuler",
"@cancel": {
"type": "text",
"placeholders": {}
},
"none": "Aucun",
"@none": {
"type": "text",
"placeholders": {}
},
"locationPromptTitle": "L'application requiert des permissions de localisation",
"@locationPromptTitle": {
"description": "Titre pour l'annonce the requête de permissions de localisations",
"type": "text",
"placeholders": {}
},
"locationPromptReason": "Afin d'augmenter la précision de la localisation et pour utiliser Bluetooth Low Energy, cette permission est nécessaire.",
"@locationPromptReason": {
"description": "Raison pour l'annonce de requête de permissions de localisation",
"type": "text",
"placeholders": {}
},
"bluetoothAvailable": "Appareils Disponibles",
"@bluetoothAvailable": {
"type": "text",
"placeholders": {}
},
"bluetoothFrequent": "Appareils Fréquemment Utilisés",
"@bluetoothFrequent": {
"type": "text",
"placeholders": {}
},
"bluetoothInactive": "Bluetooth n'est pas actif sur votre appareil.\nL'activer ?",
"@bluetoothInactive": {
"type": "text",
"placeholders": {}
},
"bluetoothScanMessage": "Recherche d'appareils Bluetooth",
"@bluetoothScanMessage": {
"type": "text",
"placeholders": {}
},
"bluetoothUnsupported": "Cette appareil n'est pas compatible avec Bluetooth Low Energy",
"@bluetoothUnsupported": {
"type": "text",
"placeholders": {}
}
{
"@@last_modified": "2020-02-05T17:25:56.614777",
"ok": "OK",
"@ok": {
"type": "text",
"placeholders": {}
},
"cancel": "Annuler",
"@cancel": {
"type": "text",
"placeholders": {}
},
"none": "Aucun",
"@none": {
"type": "text",
"placeholders": {}
},
"locationPromptTitle": "L'application requiert des permissions de localisation",
"@locationPromptTitle": {
"description": "Titre pour l'annonce the requête de permissions de localisations",
"type": "text",
"placeholders": {}
},
"locationPromptReason": "Afin d'augmenter la précision de la localisation et pour utiliser Bluetooth Low Energy, cette permission est nécessaire.",
"@locationPromptReason": {
"description": "Raison pour l'annonce de requête de permissions de localisation",
"type": "text",
"placeholders": {}
},
"bluetoothAvailable": "Appareils Disponibles",
"@bluetoothAvailable": {
"type": "text",
"placeholders": {}
},
"bluetoothFrequent": "Appareils Fréquemment Utilisés",
"@bluetoothFrequent": {
"type": "text",
"placeholders": {}
},
"bluetoothInactive": "Bluetooth n'est pas actif sur votre appareil.\nL'activer ?",
"@bluetoothInactive": {
"type": "text",
"placeholders": {}
},
"bluetoothScanMessage": "Recherche d'appareils Bluetooth",
"@bluetoothScanMessage": {
"type": "text",
"placeholders": {}
},
"bluetoothUnsupported": "Cette appareil n'est pas compatible avec Bluetooth Low Energy",
"@bluetoothUnsupported": {
"type": "text",
"placeholders": {}
}
}
\ No newline at end of file
{
"@@last_modified": "2020-02-20T07:40:18.875039",
"ok": "OK",
"@ok": {
"type": "text",
"placeholders": {}
},
"cancel": "Cancel",
"@cancel": {
"type": "text",
"placeholders": {}
},
"none": "None",
"@none": {
"type": "text",
"placeholders": {}
},
"locationPromptTitle": "This app needs to use location services",
"@locationPromptTitle": {
"description": "Title for the location permission request prompt",
"type": "text",
"placeholders": {}
},
"locationPromptReason": "To use Bluetooth Low Energy and to increase data collection accuracy, this permission is required.",
"@locationPromptReason": {
"description": "Reason for the location permission request prompt",
"type": "text",
"placeholders": {}
},
"bluetoothAvailable": "Available Devices",
"@bluetoothAvailable": {
"type": "text",
"placeholders": {}
},
"bluetoothFrequent": "Frequently Used Devices",
"@bluetoothFrequent": {
"type": "text",
"placeholders": {}
},
"bluetoothInactive": "Bluetooth is not active on this device.\nTurn it on ?",
"@bluetoothInactive": {
"type": "text",
"placeholders": {}
},
"bluetoothScanMessage": "Scan for Bluetooth Devices",
"@bluetoothScanMessage": {
"type": "text",
"placeholders": {}
},
"bluetoothUnsupported": "This device does not support Bluetooth Low Energy",
"@bluetoothUnsupported": {
"type": "text",
"placeholders": {}
}
{
"@@last_modified": "2020-02-20T07:40:18.875039",
"ok": "OK",
"@ok": {
"type": "text",
"placeholders": {}
},
"cancel": "Cancel",
"@cancel": {
"type": "text",
"placeholders": {}
},
"none": "None",
"@none": {
"type": "text",
"placeholders": {}
},
"locationPromptTitle": "This app needs to use location services",
"@locationPromptTitle": {
"description": "Title for the location permission request prompt",
"type": "text",
"placeholders": {}
},
"locationPromptReason": "To use Bluetooth Low Energy and to increase data collection accuracy, this permission is required.",
"@locationPromptReason": {
"description": "Reason for the location permission request prompt",
"type": "text",
"placeholders": {}
},
"bluetoothAvailable": "Available Devices",
"@bluetoothAvailable": {
"type": "text",
"placeholders": {}
},
"bluetoothFrequent": "Frequently Used Devices",
"@bluetoothFrequent": {
"type": "text",
"placeholders": {}
},
"bluetoothInactive": "Bluetooth is not active on this device.\nTurn it on ?",
"@bluetoothInactive": {
"type": "text",
"placeholders": {}
},
"bluetoothScanMessage": "Scan for Bluetooth Devices",
"@bluetoothScanMessage": {
"type": "text",
"placeholders": {}
},
"bluetoothUnsupported": "This device does not support Bluetooth Low Energy",
"@bluetoothUnsupported": {
"type": "text",
"placeholders": {}
}
}
\ No newline at end of file
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:logair_application/l10n/messages_all.dart' show initializeMessages;
import 'package:logair_application/localization/l10n/messages_all.dart' show initializeMessages;
/// Reference https://github.com/dart-lang/intl https://pub.dev/packages/intl
/// Adding a localization should follow the guidelines defined here : https://github.com/flutter/website/blob/master/examples/internationalization/add_language/lib/main.dart
/// The frequent locales have already been integrated (but who knows when you'll need Belarusian).
class AppLocalization {
/// The current [Locale]
final String locale;
/// Constructor
const AppLocalization(this.locale);
/// The deferred [Locale] language loader
static Future<AppLocalization> load(Locale locale) {
/// Checks whether the queried [Locale] is defined on the fly, or had been predefined.
final String name = locale.countryCode.isEmpty ? locale.languageCode : locale.toString();
final String localeName = Intl.canonicalizedLocale(name);
/// Load the internationalized values.
return initializeMessages(localeName).then((_) => AppLocalization(localeName));
}
static AppLocalization of(BuildContext context) => Localizations.of(context, AppLocalization);
/// The following definitions are the English base values for internationalizable dialog
/// TODO Add new because UI.
/* General Values */
String get ok => Intl.message(
'OK',
name: 'ok',
......
import 'package:flutter/cupertino.dart';
import 'package:logair_application/localization/localization.dart';
/// Enables the loading and reloading of app [Locale]s
class AppLocalizationDelegate extends LocalizationsDelegate<AppLocalization> {
const AppLocalizationDelegate();
/// Returns whether the demanded locale exists in the app's localization files
@override
bool isSupported(Locale locale) => ['en', 'fr'].contains(locale.languageCode);
bool isSupported(Locale locale) => [
'en',
'fr'
].contains(locale.languageCode);
/// Delegates the loading of [Locale] to an [async] task, which enables it to be done in the background.
@override
Future<AppLocalization> load(Locale locale) => AppLocalization.load(locale);
/// Returns whether the app should reload
@override
bool shouldReload(AppLocalizationDelegate old) => false;
}
\ No newline at end of file
import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter/cupertino.dart';
import 'package:logair_application/ui/routes/home.dart';
/// This controller class is integrated to the [HomeView] to enable out of scope control of select Widgets therein.
class HomeController {
factory HomeController() => _singleton;
......@@ -7,10 +10,13 @@ class HomeController {
static final HomeController _singleton = new HomeController._internal();
/// The controller for the [CarouselSlider].
PageController _pageController;
set carouselController(PageController carouselController) => this._pageController = carouselController;
get carouselController => this._pageController;
/// Force the [CarouselSlider] to navigate to another page.
void gotoPage(int page) => (this._pageController != null) ? this._pageController.jumpToPage(page) : {};
}
\ No newline at end of file
......@@ -4,12 +4,12 @@ import 'dart:collection';
import 'package:flutter/material.dart';
import 'package:flutter_map/plugin_api.dart';
import 'package:latlong/latlong.dart';
import 'package:logair_application/handlers/bluetooth_le_handler.dart';
import 'package:logair_application/handlers/data_handler.dart';
import 'package:logair_application/handlers/network_handler.dart';
import 'package:logair_application/logic/handlers/bluetooth_le_handler.dart';
import 'package:logair_application/logic/handlers/data_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/handlers/position_handler.dart';
import 'package:logair_application/logic/handlers/position_handler.dart';
/// The [MapDisplayController] is a [Singleton] that handles the mapping of information.
class MapDisplayController {
......@@ -56,6 +56,7 @@ class MapDisplayController {
/// Object used to calculate the real-life distance of two [Position]s
final Distance _distance = new Distance();
// TODO Faster to rebuild than to store ?
List<CircleMarker> pmMarkers() => this._pmMarkers[_pmKey[_pmKeyIndex]];
List<String> _pmKey = ["PM1", "PM2_5", "PM4", "PM10"];
......
......@@ -13,7 +13,7 @@ class DataHeader {
static final DataHeader _singleton = new DataHeader._internal();
/// Data contained within the Header packet
List<String> _headerData;
bool _headerSet;
......@@ -23,10 +23,11 @@ class DataHeader {
this._headerSet = true;
}
/// Retrieve the deviceID from the header
String get deviceID => (this._headerData != null && this._headerData.length > 0) ? this._headerData[0] : '';
/// @Getter for _headerSet;
bool isHeaderSet() => _headerSet;
bool get headerSet => this._headerSet;
bool isEqual(List<int> that) => ListEquality().equals(_headerData, that);
......
import 'package:geolocator/geolocator.dart';
import 'package:logair_application/handlers/position_handler.dart';
import 'package:logair_application/logic/handlers/position_handler.dart';
import 'package:logair_application/utils/utils.dart';
/// Represents 1 second of data streamed from LogAir's devices,
/// and contains methods for:
......@@ -40,18 +41,6 @@ class DataPacket {
double pm2_5() => _pm2_5;
double pm4() => _pm4;
double pm10() => _pm10;
double parseDoubleWrapper(String data) {
double result = double.tryParse(data);
if (result == null) {
int result2 = int.tryParse(data);
if (result2 == null)
return null;
else
result = result2.toDouble();
}
return result;
}
DataPacket(this._data) {
_timestamp = DateTime.now().millisecondsSinceEpoch;
......
......@@ -3,13 +3,14 @@ import 'dart:io';
import 'package:flutter_blue/flutter_blue.dart';
import 'package:kotlin_flavor/scope_functions.dart';
import 'package:logair_application/enums/bluetooth_connection_status.dart';
import 'package:logair_application/handlers/data_handler.dart';
import 'package:logair_application/logic/handlers/preference_handler.dart';
import 'package:logair_application/utils/enums/bluetooth_connection_status.dart';
import 'package:logair_application/logic/handlers/data_handler.dart';
/// Serves as a wrapper class around [FlutterBlue], and helps integrate it into the application with extensions
class BTLEHandler {
/// Static values used by the chip.
/// TODO Optionize ?
/// TODO Optionize (ongoing see [PreferencesHandler]) ?
static final String bluetoothLeCc254xServiceUUID = "0000ffe0-0000-1000-8000-00805f9b34fb";
static final String bluetoothLeCc254xReadUUID = "0000ffe1-0000-1000-8000-00805f9b34fb";
......
......@@ -2,6 +2,8 @@ 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
class BTWakeHandler {
factory BTWakeHandler() => _singleton;
......@@ -9,30 +11,32 @@ class BTWakeHandler {
static final BTWakeHandler _singleton = BTWakeHandler._internal();
/// TODO Used for debugging, remove
Timer _t;
static Duration duration = new Duration(seconds: 1);
/// TODO Used for debugging, remove
static Duration _duration = new Duration(seconds: 1);
static bool wakeServiceActive = false;
static bool _wakeServiceActive = false;
bool switchState() {
if (wakeServiceActive)
if (_wakeServiceActive)
_end();
else
_start();
return wakeServiceActive;
return _wakeServiceActive;
}
void _start() {
WakeService().modifyWakeService(true).then((value) => print('_device will stay awake $value'));
wakeServiceActive = true;
_t = new Timer.periodic(duration, (Timer t) => print("${new DateTime.now()}"));
_wakeServiceActive = true;
_t = new Timer.periodic(_duration, (Timer t) => print("${new DateTime.now()}"));
}
void _end() {
WakeService().modifyWakeService(false).then((value) => print('_device will stay awake $value'));
wakeServiceActive = false;
_wakeServiceActive = false;
_t.cancel();
}
}
\ No newline at end of file
import 'package:logair_application/handlers/bluetooth_le_handler.dart';
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';
......@@ -21,50 +21,64 @@ class DataHandler {
void addData(List<int> data) {
_data.addAll(data);
/// Get a start index for the data, either '{' (DataHeader) or '[' (DataPacket)
int index = _data.indexWhere((e) => e == 91 || e == 123);
if (index == -1)
return;
/// Remove noise if exists
_data.removeRange(0, index);
/// Get the termination index '$'
int termIndex = _data.indexWhere((e) => e == 36);
if (termIndex == -1)
return;
/// If both exist, then extract the packet.
List<int> packet = _data.sublist(index, termIndex + 1);
_data.removeRange(0, termIndex);
/// If a packet is ingrained within this packet (possibly because of BLE transmission issues),
/// this will attempt to fix it.
if (packet.sublist(1).contains((e) => e == 91 || e == 123)) {
print('True ${packet.sublist(1).indexWhere((e) => e == 91 || e == 123)}');
int startIndex = packet.sublist(1).indexWhere((e) => e == 91 || e == 123);
packet.removeRange(0, startIndex);
}
/// If it's a [DataHeader] instance.
if (packet[0] == 123) {
print('HEADER ${String.fromCharCodes(packet)}');
DataHeader().setHeader(packet);
/// Or if it is a [DataPacket] instance.
} else if (packet[0] == 91) {
_sortedData.add(DataPacket(packet));
print('PACKET ${String.fromCharCodes(packet)}');
}
}
/// TODO Used for debugging, later
void printLatest() {
print(_sortedData.last);
}
/// Get the entirety of the [DataPacket]s.
/// TODO Caching
List<DataPacket> getData() => _sortedData;
/// Get a subrange of [DataPacket]s.
List<DataPacket> getDataRange(int range) => (range > _sortedData.length) ? _sortedData : _sortedData.sublist(0, range);
/// Remove the entirety of the acquired data.
void clearData() {
_sortedData.removeWhere((element) => true);
}
/// Remove the first element of the [DataPacket]s. Used for surgical removal.
void pop() {
_sortedData.removeAt(0);
}
/// Get the latest [DataPacket]
DataPacket getLatestData() => (_sortedData.length > 0) ? _sortedData.last : null;
/// Stream the latest confirmed [DataPacket] received by the device.
......@@ -75,6 +89,7 @@ class DataHandler {
}
}
/// Used to monitor the amount of unsent [DataPacket]s.
Stream<int> getUnsentPacketsLength() async* {
while (true) {
yield (_sortedData.length);
......
......@@ -9,7 +9,7 @@ import 'package:latlong/latlong.dart';
import 'package:logair_application/logic/data_header.dart';
import 'package:logair_application/logic/data_packet.dart';
import 'package:logair_application/handlers/data_handler.dart';
import 'package:logair_application/logic/handlers/data_handler.dart';
/// Singleton data structure that contains services enabling the application to send data to a webserver.
/// TODO Make URL user configurable.
......@@ -32,7 +32,7 @@ class NetworkHandler {
String url = 'https://api.logair.unige.ch/v1/service';
/// Break conditions ([DataHeader] unset or no [DataPacket] available).
if (!DataHeader().isHeaderSet() || DataHandler().getData().length == 0)
if (!DataHeader().headerSet || DataHandler().getData().length == 0)
return;
/// Get the map representation of a [DataHeader].
......@@ -70,6 +70,7 @@ class NetworkHandler {
}
}
/// Get all of the points in proximity to the device.
void getProximityPoints(String deviceId, LatLngBounds bounds) async {
/// The default endpoint.
String url = 'https://api.logair.unige.ch/v1/service/map/bounds?localId=$deviceId&lat1=${bounds.northEast.latitude}&lng1=${bounds.northEast.longitude}&lat2=${bounds.southWest.latitude}&lng2=${bounds.southWest.longitude}&age=${5000}&limit=${200}&skip=0';
......@@ -82,10 +83,11 @@ class NetworkHandler {
.catchError((e) => print('COULDN\'T CONNECT'));
if (response != null && response.statusCode == 200) {
// TODO Complete
}
}
/// Get the time of the last server transmission.
Stream<DateTime> getLastServerConnection() async* {
while (true) {
yield _lastServerTransmission;
......
......@@ -2,7 +2,9 @@ import 'dart:async';
import 'package:geolocator/geolocator.dart';
import 'package:logair_application/services/permission_service.dart';
import 'package:permission_handler/permission_handler.dart';
/// Handler enabling the frequent polling of the devices [Position]
class PositionHandler {
/// [Singleton]() instantiation factory.
factory PositionHandler() => _singleton;
......@@ -12,16 +14,23 @@ class PositionHandler {
/// Internal static [Singleton]() reference.
static final PositionHandler _singleton = new PositionHandler._internal();
/// The last known [Position] of the device.
Position _lastPosition;
/// Whether the app has checked for the appropriate [PermissionGroup]
bool _permissionChecked = false;
/// The underlying service that enables this to get [Position] data.
Geolocator _geolocator = Geolocator();