diff --git a/lib/addevent.dart b/lib/addevent.dart index 0f45a65bf73e7b21cf4b54def10e54ffdb46df9d..aa4086abc77b53f859558f30dfd033d472aefdcc 100644 --- a/lib/addevent.dart +++ b/lib/addevent.dart @@ -23,6 +23,7 @@ class _AddEventPageState extends State<AddEvent> { late double accuracy = 0.0; late StreamSubscription<Position> streamHandler; //For canceling GNSS stream on dispose final prefs = SharedPreferences.getInstance(); // Is async + var database = DatabaseInstance(); Future startGNSS() async { debugPrint("Check Location Permission"); @@ -162,25 +163,8 @@ class _AddEventPageState extends State<AddEvent> { final EventStoreInstance eventsStore = EventStoreInstance(); final ConfigurationStoreInstance configuration = ConfigurationStoreInstance(); eventsStore.currentEvent.typeId = configuration.getEventIdFromName(eventsStore.currentEvent.type); - eventsStore.currentEvent.status = "PENDING"; - eventsStore.events.add( - Event( - id: 0, - urnId: eventsStore.currentEvent.urnId, - urn: eventsStore.currentEvent.urn, - label: eventsStore.currentEvent.label, - type: eventsStore.currentEvent.type, - typeId: eventsStore.currentEvent.typeId, - description: eventsStore.currentEvent.description, - status: eventsStore.currentEvent.status, - startDate: eventsStore.currentEvent.startDate, - endDate: eventsStore.currentEvent.endDate, - latitude: eventsStore.currentEvent.latitude, - longitude: eventsStore.currentEvent.longitude, - elevation: eventsStore.currentEvent.elevation - )); - + database.addEvent(eventsStore.currentEvent); //TODO: display feedback after this async function } @override diff --git a/lib/databaseconnector.dart b/lib/databaseconnector.dart index da584897140c46038d9691a292a0412fe985cf53..f9b6b1a024cf2619bfea417000602056c224484d 100644 --- a/lib/databaseconnector.dart +++ b/lib/databaseconnector.dart @@ -1,12 +1,24 @@ -import 'package:flutter/material.dart'; import 'package:sqflite/sqflite.dart'; import 'package:path/path.dart'; import 'dart:async'; import 'datamodel.dart'; +class DatabaseInstance extends DatabaseConnector { + static final DatabaseInstance _instance = DatabaseInstance + ._internal(); -class DatabaseConnector{ + factory DatabaseInstance() { + return _instance; + } + + DatabaseInstance._internal() { + //connect(); + } +} + + +abstract class DatabaseConnector{ static const String eventDatabase = 'mobileEventLog.db'; static const String eventTable = 'events'; dynamic database; @@ -25,12 +37,11 @@ class DatabaseConnector{ }, // Set the version. This executes the onCreate function and provides a // path to perform database upgrades and downgrades. - version: 3, + version: 1, ); } - - Future<int> insertNewEvent(Event event) async { + Future<int> addEvent(Event event) async { int rowId = 0; rowId = await database.insert( eventTable, @@ -52,10 +63,7 @@ class DatabaseConnector{ } Future<List<Event>> getEvents() async { - // Get a reference to the database. - final db = await database; - - final List<Map<String, dynamic>> maps = await db.query(eventTable); + final List<Map<String, dynamic>> maps = await database.query(eventTable); // Convert the List<Map<String, dynamic> into a List<Event>. return List.generate(maps.length, (i) { @@ -77,13 +85,14 @@ class DatabaseConnector{ }); } + Future<int> getPendingEventCnt() async { + List<Event> events = await getPendingEvents(); + return events.length; + } // A method that retrieves all the dogs from the dogs table. Future<List<Event>> getPendingEvents() async { - // Get a reference to the database. - final db = await database; - - final List<Map<String, dynamic>> maps = await db.query(eventTable, where: '"status" = "PENDING"'); + final List<Map<String, dynamic>> maps = await database.query(eventTable, where: 'status = ?', whereArgs: ['PENDING']); // Convert the List<Map<String, dynamic> into a List<Event>. return List.generate(maps.length, (i) { @@ -98,33 +107,10 @@ class DatabaseConnector{ status: maps[i]['status'], startDate: maps[i]['startDate'], endDate: maps[i]['endDate'], - latitude: maps[i]['latitude'], - longitude: maps[i]['longitude'], - elevation: maps[i]['elevation'], + latitude: maps[i]['latitude'].toString(), //TODO: change datamodel to double + longitude: maps[i]['longitude'].toString(), + elevation: maps[i]['elevation'].toString(), ); }); } - } - - - - - - -/* -* int id; // Device URN id - String urn; - String label; - String type; // Event type name TODO: this should be an EventType variable - int typeId; - String description; - String status; - String startDate; - String endDate; - String latitude; - String longitude; - String elevation; -* -* -* */ \ No newline at end of file diff --git a/lib/datamodel.dart b/lib/datamodel.dart index 53b7d6283a85a74e73eca009848f08de5bdd35e5..ad65c305c528f6e88fa2e07f8cba202e2bd55345 100644 --- a/lib/datamodel.dart +++ b/lib/datamodel.dart @@ -311,7 +311,7 @@ class ConfigurationStoreInstance extends ConfigurationStoreBase { abstract class EventStoreBase{ - List<Event> events = []; + //List<Event> events = []; Event currentEvent = Event( id: 0, urnId:-1, @@ -328,7 +328,8 @@ abstract class EventStoreBase{ elevation: '' ); - int getPendingEventCount(){ + /* + int getPendingEventCount(List<Event> events){ int count = 0; for (var event in events) { if (event.status == 'PENDING') { @@ -337,25 +338,25 @@ abstract class EventStoreBase{ } return count; } - - String getEventDump(){ - String ev = '['; - - for (var event in events) { - ev += jsonEncode(event); - ev += ','; - } - ev += ']'; - return ev; - } - - fromEventDump(dump){ - events = []; - for (var entry in dump) { - debugPrint('Added Event from Storage: ' + entry.toString()); - events.add(Event.fromJson(entry)); - } - } + */ + //String getEventDump(List<Event> events){ + // String ev = '['; + + // for (var event in events) { + // ev += jsonEncode(event); + // ev += ','; + // } + // ev += ']'; + // return ev; + //} + + //fromEventDump(dump){ + // events = []; + // for (var entry in dump) { + // debugPrint('Added Event from Storage: ' + entry.toString()); + // events.add(Event.fromJson(entry)); + // } + //} } @@ -367,7 +368,7 @@ class EventStoreInstance extends EventStoreBase { } EventStoreInstance._internal() { - events = []; + //events = []; currentEvent = Event( id:0, urnId:-1, @@ -386,7 +387,7 @@ class EventStoreInstance extends EventStoreBase { } void reset(){ - events = []; + //events = []; currentEvent = Event( id:0, urnId:-1, diff --git a/lib/main.dart b/lib/main.dart index 7fa259d28e50d793c62dd3e53b3ae01e4e538453..68ab8a3ef63a3a882e854e2982087b388302f9ac 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -34,8 +34,8 @@ Future<void> pathStuff() async { //Map<String, String> allValues = await storage.readAll(); //print('Secure Storage: ' + allValues.toString()); - var database = DatabaseConnector(); - await database.connect(); + var database = DatabaseInstance(); + await database.connect(); //Do once at start of APP! Event event = Event.fromJson({"id":0,"urnId":102,"urn":"mooring:f9-12","label":"hggg","type":"Calibration", "typeId":15,"description":"ggggg","status":"PENDING", @@ -47,12 +47,12 @@ Future<void> pathStuff() async { //Update second event in sql database event.id = 2; - event.description = 'updated description'; - database.updateEvent(event); + event.description = 'updated description1'; + //database.updateEvent(event); //debugPrint("Add Event to database: " + event.toString()); - //int rowId = await database.insertEvent(event); + //int rowId = await database.addEvent(event); //debugPrint("Events row Id: " + rowId.toString()); tempEvents = await database.getEvents(); @@ -86,6 +86,7 @@ void main() { //configuration.currentCollection = Collection.fromJson({"id":1,"description":"","collectionName":"FRAM"}); //configuration.initialized = true; + /* events.fromEventDump( [ {"id":1,"urnId":102,"urn":"mooring:f9-12","label":"hggg","type":"Calibration", @@ -101,6 +102,7 @@ events.fromEventDump( ]); //events.fromEventDump([{"id":102,"urn":"mooring:f9-12","label":"cf","type":"Calibration","typeId":15,"description":"fd","status":"PENDING","startDate":"2022-03-25T12:47:30.659436Z","endDate":"2022-03-25T12:47:30.659436Z","latitude":"","longitude":"","elevation":""},{"id":102,"urn":"mooring:f9-12","label":"cf","type":"Calibration","typeId":15,"description":"fd","status":"PENDING","startDate":"2022-03-25T12:47:32.136009Z","endDate":"2022-03-25T12:47:32.136009Z","latitude":"","longitude":"","elevation":""}]); +*/ runApp(MaterialApp( title: 'Mobile Event Log', diff --git a/lib/viewevents.dart b/lib/viewevents.dart index c883ee781fd559423cd851dd975759a2725e68c8..fde41accab282608dd09f675dc02249659ef83fa 100644 --- a/lib/viewevents.dart +++ b/lib/viewevents.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'datamodel.dart'; import 'package:http/http.dart' as http; import 'sensorconnector.dart'; +import 'databaseconnector.dart'; class ViewEvents extends StatefulWidget { const ViewEvents({Key? key}) : super(key: key); @@ -16,20 +17,43 @@ class _ViewEvents extends State<ViewEvents> { // Get singleton to access locally stored events: final EventStoreInstance _events = EventStoreInstance(); String _syncStatus = ''; - //TODO: add exception handling and display exceptions to user. + + var database = DatabaseInstance(); + List<Event> localEvents = []; + + + Future<void> fetchEventsFromDb() async{ + localEvents = await database.getEvents(); + int pendingEventCnt = await database.getPendingEventCnt(); + + debugPrint("Database Events: "); + for (var event in localEvents){ + debugPrint(event.toString()); + } + + _syncStatus = pendingEventCnt.toString() + ' event(s) pending'; + setState(() {}); //Got events from database, so update UI + } @override void initState() { - _syncStatus = _events.getPendingEventCount().toString() + ' event(s) pending'; + _syncStatus = ''; super.initState(); - //TODO: Query all events from database everytime this widget is opened. Remove local event storage instance! + fetchEventsFromDb(); } Future<void> syncEvents() async { final ConfigurationStoreInstance configuration = ConfigurationStoreInstance(); SensorConnector connection = SensorConnector(); - int syncCounter = _events.getPendingEventCount();; //For displaying progress during event upload + + List<Event> events = await database.getPendingEvents(); + debugPrint('Pending Events'); + for (var event in events){ + debugPrint(event.toString()); + } + + int syncCounter = events.length; if(syncCounter > 0) { try { @@ -38,24 +62,24 @@ class _ViewEvents extends State<ViewEvents> { configuration.loginInformation.password); if (token != null) { - debugPrint('Number of Events: ' + _events.events.length.toString()); + debugPrint('Number of Events: ' + events.length.toString()); debugPrint('Number of Pending Events: ' + syncCounter.toString()); var index = 0; - for (var event in _events.events) { - if (event.status == 'PENDING') { //TODO: only query events which are 'PENDING' from database. - debugPrint('Idx: ' + index.toString() + ' ' + - event.toSensorJson().toString()); - index++; - if (await connection.putEvent(event, token) == true) { - //Event has been posted to Sensor. - syncCounter--; - debugPrint( - 'put success, remaining events: ' + syncCounter.toString()); - event.status = 'EXPORTED'; //Update event export only once //TODO: move to database and update event based in primary row id. - setState(() {}); - } else { - throw Exception('Sync for ' + event.urn + 'failed'); - } + for (var event in events) { + debugPrint('Idx: ' + index.toString() + ' ' + + event.toSensorJson().toString()); + index++; + if (await connection.putEvent(event, token) == true) { + //Event has been posted to Sensor. + syncCounter--; + debugPrint( + 'put success, remaining events: ' + syncCounter.toString()); + event.status = 'EXPORTED'; //Update event to export only once + database.updateEvent(event); //Update Event in SQL Database + fetchEventsFromDb(); //update view list //TODO: this is bad performance + setState(() {}); + } else { + throw Exception('Sync for ' + event.urn + 'failed'); } } _syncStatus = 'export success'; @@ -159,7 +183,7 @@ class _ViewEvents extends State<ViewEvents> { ), ], rows: <DataRow>[ - for (var event in _events.events) + for (var event in localEvents) DataRow( cells: <DataCell>[ DataCell(Text(event.urnId.toString())), @@ -245,7 +269,7 @@ class _ViewEvents extends State<ViewEvents> { icon: null, label: const Text('Sync'), onPressed: () { - debugPrint(_events.getEventDump()); + //debugPrint(_events.getEventDump()); syncEvents();