Skip to content
Snippets Groups Projects
configuration.dart 10.4 KiB
Newer Older
Maximilian Betz's avatar
Maximilian Betz committed
import 'dart:convert';
import 'package:flutter/material.dart';
Maximilian Betz's avatar
Maximilian Betz committed
import 'package:flutter/services.dart';
import 'sensorconnector.dart';
import 'databaseconnector.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
class Configuration extends StatefulWidget {
Maximilian Betz's avatar
Maximilian Betz committed
  const Configuration({Key? key}) : super(key: key);

  @override
  State<Configuration> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<Configuration> {
  late Future<Collection> futureCollection;
  late Future<List<Collection>> futureCollections;
  late Future<List<EventType>> futureEventTypes;
  late Future<List<Device>> futureDevices;
  late Future<String> futureAuthToken;
  var database = DatabaseInstance();
  SensorConnector connector = SensorConnector();
  final ConfigurationStoreInstance configuration = ConfigurationStoreInstance();

  Future<void> dumpToFile() async{
    var date = DateTime.now().toUtc();
    var isoDate = date.toIso8601String();

    String filename =
        date.year.toString().padLeft(4, '0') +
            date.month.toString().padLeft(2, '0') +
            date.day.toString().padLeft(2, '0') +
            date.hour.toString().padLeft(2, '0') +
            date.minute.toString().padLeft(2, '0') +
            date.second.toString().padLeft(2, '0') +
            '_events.json';

    String eventsJson = await database.eventDump();

    final Directory? directory = await getExternalStorageDirectory();
    if(directory != null) {
      String filepath = join(directory.path, filename);

      final File file = File(filepath);
      await file.writeAsString(eventsJson);
      debugPrint('Stored file at: ' + filepath);
    }
  }


  Future<void> updateConfiguration() async {
    final EventStoreInstance event = EventStoreInstance();
    String token = '';

    try{
      token = await connector.getAuthToken(configuration.loginInformation.mail, configuration.loginInformation.password);
      configuration.devices = await futureDevices; //already fetched just use the data.
      configuration.eventTypes = await futureEventTypes; //already fetched just use the data.

      event.currentEvent.id = 0;
      event.currentEvent.urnId = configuration.devices[0].id; //TODO: fix if devices are an empty list.
      event.currentEvent.urn = configuration.devices[0].urn;
      event.currentEvent.description = '';
      event.currentEvent.label = '';
      event.currentEvent.type = configuration.eventTypes[0].name;

      var date = DateTime.now().toUtc();
      var isoDate = date.toIso8601String();
      event.currentEvent.startDate = isoDate;
      event.currentEvent.endDate = isoDate;
      configuration.initialized = true;

      HapticFeedback.vibrate();
      //TODO: display success user feedback
      //TODO: store complete "configuration"

      await event.storeToSharedPrefs();
      await configuration.storeToSharedPrefs();
      debugPrint('Configuration stored!');

Maximilian Betz's avatar
Maximilian Betz committed
      _status = 'Login success & configuration stored';
      setState(() {});

    } catch (e) {
      debugPrint('Exception: $e');
      _status = '$e';
      setState(() {});
    }
  Future<void> fetchInitData() async {
    try {
      //Start fetching all possible sensor data as soon as possible:
      futureCollections = connector.fetchCollections();
      futureEventTypes = connector.fetchEventTypes();
      if (configuration.currentCollection.id != -1) {
        futureDevices = connector.fetchCollectionDevices(configuration.currentCollection.id);
      }
      await futureCollections;
      await futureEventTypes;
      await futureDevices;
    }catch(e){
      debugPrint(e.toString());
  }

  @override
  void initState() {
    super.initState();
    fetchInitData();
  late Future<String> eventTypes;

  @override
  Widget build(BuildContext context) {
    final ConfigurationStoreInstance configuration = ConfigurationStoreInstance();
    final EventStoreInstance events = EventStoreInstance();
Maximilian Betz's avatar
Maximilian Betz committed
        appBar: AppBar(
          title: const Text('Configuration'),
        ),
Maximilian Betz's avatar
Maximilian Betz committed
        body: SingleChildScrollView(
          child: Container(
            margin: const EdgeInsets.symmetric(horizontal: 5.0),
            child:
            Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  const SizedBox(height: 50),
                  const Text(
                      'You must be online to do something here!',
                      style: TextStyle(fontSize: 14)
                  ),
                  const SizedBox(height: 50),
                  TextFormField(
                    keyboardType: TextInputType.emailAddress,
                    autofocus: false,
                    initialValue: configuration.loginInformation.mail,
                    decoration: const InputDecoration(
                      border: OutlineInputBorder(),
                      labelText: 'E-Mail',
                      hintText: '',
                    ),
                    onChanged: (value) {
                      configuration.loginInformation.mail = value;
                    },
                    onFieldSubmitted: (value) {
                      //futureAuthToken = connector.getAuthToken(configuration.loginInformation.mail, configuration.loginInformation.password);
                    },
Maximilian Betz's avatar
Maximilian Betz committed
                  ),
                  const SizedBox(height: 15.0),
                  TextFormField(
                    obscureText: true,
                    autofocus: false,
                    initialValue: configuration.loginInformation.password,
                    decoration: const InputDecoration(
                      border: OutlineInputBorder(),
                      labelText: 'Password',
                      hintText: '',
                    ),
                    onChanged: (value){
                      configuration.loginInformation.password = value;
                    },
                    onFieldSubmitted: (value) {
                      //futureAuthToken = connector.getAuthToken(configuration.loginInformation.mail, configuration.loginInformation.password);
                    },
Maximilian Betz's avatar
Maximilian Betz committed
                  ),
                  const SizedBox(height: 50),
                  FutureBuilder<List<Collection>>(
                      future: futureCollections,
                      builder: (context, snapshot){
                        if (snapshot.hasData)
                        {
                          configuration.collections = [];
                          snapshot.data?.forEach((element) {
                            configuration.collections.add(element);
                          });

                          /*Initialize active collection with first received
Maximilian Betz's avatar
Maximilian Betz committed
                    collection if not initialized yet*/
                          if(configuration.currentCollection.id == -1){
                            configuration.currentCollection = configuration.collections[0];
                            futureDevices = connector.fetchCollectionDevices(configuration.currentCollection.id);
                            //TODO: shall this be removed here and just done at confirmation.?
                          return DropdownButtonFormField(
                              value: configuration.currentCollection.collectionName,
                              decoration: const InputDecoration(
                                labelText: 'Chose Collection',
                                border: OutlineInputBorder(),
                              ),
                              items:
                              configuration.collections.map((Collection collection) {
                                return DropdownMenuItem(
                                  value: collection.collectionName,
                                  child: Text(collection.collectionName),
                                );
                              }).toList(),
                              onChanged: (value) {
                                configuration.currentCollection = configuration.getCollectionFromName(value.toString());
                                //Fetch new selected collection devices
                                futureDevices = connector.fetchCollectionDevices(configuration.currentCollection.id);
                              }
                          );
                        }
                        else{
                          return const CircularProgressIndicator();
                        }
                  ),
                  const SizedBox(height: 50.0),
                  TextFormField(
                    readOnly: true,
                    autofocus: false,
                    enabled: false,
                    controller: TextEditingController(
                        text: _status),
                  ),
                  const SizedBox(height: 15.0),

                ],
              ),
Maximilian Betz's avatar
Maximilian Betz committed
        ),
        bottomNavigationBar: Container(
          margin: const EdgeInsets.symmetric(vertical: 10.0),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.end,
            children: [
              //const SizedBox(width: 10.0),
Maximilian Betz's avatar
Maximilian Betz committed
              FloatingActionButton.extended(
                heroTag: null,
                tooltip: 'Export events to local .json file',
                icon: const Icon(Icons.download),
                label: const Text('Dump Events'),
Maximilian Betz's avatar
Maximilian Betz committed
                onPressed: () {
Maximilian Betz's avatar
Maximilian Betz committed
                  //TODO: remove before release this is not a real use case!
                  var db = DatabaseInstance();
                  db.delete();
                  //configuration.reset();
Maximilian Betz's avatar
Maximilian Betz committed
                },
              ),
              const SizedBox(width: 50),
              FloatingActionButton.extended(
                heroTag: null,
Maximilian Betz's avatar
Maximilian Betz committed
                tooltip: 'Download corresponding devices and store locally',
Maximilian Betz's avatar
Maximilian Betz committed
                icon: const Icon(Icons.save),
                label: const Text('Store'),
Maximilian Betz's avatar
Maximilian Betz committed
                onPressed: () {
                  updateConfiguration();
Maximilian Betz's avatar
Maximilian Betz committed
                  //TODO: display failed as user feedback somehow
                },
              ),
              const SizedBox(width: 5.0),
Maximilian Betz's avatar
Maximilian Betz committed
            ],
Maximilian Betz's avatar
Maximilian Betz committed

//TODO: write configuration on app dispose!
Maximilian Betz's avatar
Maximilian Betz committed
//TODO: display mission internet connection properly.
//TODO: add label prefix with appended upcounting number.
//TODO: grey out update button if nothing has changed. ?