Sistema de monitoramento de saúde

Tempo de leitura: 8 minutes

ESP32 + LM35 + MAX30102 +Firebase-database + Flutter

Arduino path

Firebase

devices

 

Apps

 

Código Fonte (Arduino)

#define analogTem 35
#include <WiFi.h>
#include <Wire.h>
#include <FirebaseESP32.h>
#include "MAX30105.h"
#include "heartRate.h"

#define WIFI_SSID "godusevpn" // Change the name of your WIFI
#define WIFI_PASSWORD "dsa21413" // Change the password of your WIFI
#define FIREBASE_HOST "https://fyp-test-c34d8-default-rtdb.firebaseio.com/"
#define FIREBASE_Authorization_key "w5kidxuOqHNKtMB4EbhEJuF8lFAyXhLKJGfypMXV"

MAX30105 particleSensor;
const byte RATE_SIZE = 4; //Increase this for more averaging. 4 is good.
byte rates[RATE_SIZE]; //Array of heart rates
byte rateSpot = 0;
long lastBeat = 0; //Time at which the last beat occurred
float beatsPerMinute;
float BPM = 0;
int beatAvg;
int Avg =0;

FirebaseData firebaseData;
FirebaseJson json;

uint32_t tsLastReport = 0;
void onBeatDetected(){
    Serial.println("Beat Detected!");
}
void connectToNetwork(){
  Serial.println("Connected to network");
  Serial.println(WIFI_SSID);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  while (WiFi.status() != WL_CONNECTED){
    delay(500);
    Serial.println("Establishing connection to WiFi..");
  }
  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());
}

void MAX30102pox(){
    if (!particleSensor.begin(Wire, I2C_SPEED_FAST)){ //Use default I2C port, 400kHz speed
      Serial.println("MAX30105 was not found. Please check wiring/power. ");
      while (1);
    }
    Serial.println("Place your index finger on the sensor with steady pressure.");
    particleSensor.setup(); //Configure sensor with default settings
    particleSensor.setPulseAmplitudeRed(0x0A); //Turn Red LED to low to indicate sensor is running
    particleSensor.setPulseAmplitudeGreen(0); //Turn off Green LED
}
void setup(){
    Serial.begin(115200);
    //wifi connect____________________________________________
    connectToNetwork();
    //MAX30102 connect________________________________________
    MAX30102pox();
    //firebase connect________________________________________
    Firebase.begin(FIREBASE_HOST,FIREBASE_Authorization_key);
}
 
void loop(){
  long irValue = particleSensor.getIR();
  int TemRawValue = analogRead(analogTem);
  float Voltage = TemRawValue * (1330 / 1024.0);//3.3V and arm 1330
  float TempData = Voltage * 0.1;
  
  if (checkForBeat(irValue) == true){
    long delta = millis() - lastBeat;
    lastBeat = millis();
    //Serial.println(delta);//hand base 2000-3000
    beatsPerMinute =60/(delta / 3800.0);//org 1000 testing 3000
    //Firebase.setFloat(firebaseData,"/ESP32/BPM", beatsPerMinute);
    if (beatsPerMinute < 255 && beatsPerMinute > 20){
      rates[rateSpot++] = (byte)beatsPerMinute; //Store this reading in the array
      rateSpot %= RATE_SIZE; //Wrap variable
      beatAvg = 0;//Take average of reading
      for (byte x = 0 ; x < RATE_SIZE ; x++)
        beatAvg += rates[x];
      beatAvg /= RATE_SIZE;
      Firebase.setFloat(firebaseData,"/ESP32/Avg", beatAvg);
      Firebase.setFloat(firebaseData,"/ESP32/Temperature", TempData);  
    }
  }
  Serial.print(beatsPerMinute);
  Serial.println("bpm");
  Serial.print(beatAvg);
  Serial.println("avg bpm");
  Serial.print(TempData,1);
  Serial.println(" \xC2\xB0 C");
}

Código Fonte Flutter

main.dart

import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import './DataDisplay.dart';
import 'package:testingesp32/DataDisplay.dart';
import 'package:flutter/cupertino.dart';
import 'package:adaptive_theme/adaptive_theme.dart';

void manin() async{
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return AdaptiveTheme(

      light: ThemeData(
        brightness: Brightness.light,
        primarySwatch: Colors.grey,
        accentColor: Colors.black,
      ),
      dark: ThemeData(
        brightness: Brightness.dark,
        primarySwatch: Colors.grey,
        accentColor: Colors.black,
      ),
      initial: AdaptiveThemeMode.light,
      builder: (theme, darkTheme) => MaterialApp(
        title: 'Adaptive Theme Demo',
        theme: theme,
        darkTheme: darkTheme,
        debugShowCheckedModeBanner: false,
        home: DisplayPage(),
      ),
    );

  }
}

import 'package:flutter/material.dart';

String theLocate ="en";
double  textSizeValue =24;
String systemText(String text) {
  return Strings().getText(text);
}

TextStyle getTextSetting(double size) {
  return Strings().getTextStyle();
}

class Strings {
  String getText(String text) {
    switch (theLocate) {
    // eng ==================================================================================================================
      case 'en':
        switch (text) {
          case 'title':
            return 'Welcome to Health Monitor System';
            break;
          case 'Login':
            return 'Login in database';
            break;
          case 'apptitle':
            return 'Health Monitor App';
            break;
          case 'bpmtitle':
            return 'Heart Bit bpm';
            break;
          case 'temptitle':
            return 'Body Temperature';
            break;
          case 'nowtempis':
            return 'Now Temperature ';
            break;
          case 'nowbpm':
            return 'Now Heart bit ';
            break;
          case '°C':
            return '°C';
            break;
          case 'bpm':
            return 'bpm';
            break;
          case 'Language':
            return 'Language Setting';
            break;
          case 'english':
            return 'English';
            break;
          case 'chinese':
            return 'Chinese';
            break;
          case 'AppTitle':
            return 'Health Monitor System';
            break;
          case 'settingPage':
            return 'Main Setting';
            break;
          case 'Other Setting':
            return 'Other Setting';
            break;
          case 'close':
            return 'Close';
            break;
          case 'fontsize':
            return 'Text Size';
            break;
          case 'small':
            return 'S';
            break;
          case 'medium':
            return 'M';
            break;
          case 'large':
            return 'L';
            break;
          case 'mode':
            return 'Light Theme';
            break;
          case 'lightmode':
            return 'Light';
            break;
          case 'darkmode':
            return 'Dark';
            break;
          case 'call':
            return 'Ask for help';
            break;
          default:
            return 'error';
            break;
        }
        break;

    // zh locate ==================================================================================================================
      case 'zh':
        switch (text) {
          case 'AppTitle':
            return '健康監測系統';
            break;
          case 'bpm':
            return ' ';
            break;
          case 'bpmtitle':
            return '心跳率監測';
            break;
          case 'nowbpm':
            return '現在心跳率每分鐘';
            break;
          case 'temp':
            return '體溫';
            break;
          case '°C':
            return '度';
            break;
          case 'temptitle':
            return '體溫監測';
            break;
          case 'nowtempis':
            return '現在體溫';
            break;
          case 'Language':
            return '語言設定';
            break;
          case 'english':
            return '英文';
            break;
          case 'chinese':
            return '中文';
            break;
          case 'fontsize':
            return '字體大小';
            break;
          case 'small':
            return '小';
            break;
          case 'medium':
            return '中';
            break;
          case 'large':
            return '大';
            break;
          case 'textmode':
            return '文本模式';
            break;
          case 'Other Setting':
            return '其他設定';
            break;
          case 'settingPage':
            return '主要設定';
            break;
          case 'mode':
            return '顯示模式';
            break;
          case 'lightmode':
            return '亮模式';
            break;
          case 'darkmode':
            return '深色模式';
            break;
          case 'close':
            return '關閉';
            break;
          case 'call':
            return '尋求幫助';
            break;

          default:
            return '文字出現錯誤';
            break;
        }
        break;
    // default ==================================================================================================================
      default:
        switch (text) {
          case 'welcome':
            return 'welcome';
            break;
          default:
            return 'error';
            break;
        }
        break;
    }
  }

  TextStyle getTextStyle() {
    return TextStyle(fontSize: textSizeValue);
  }

  Color getThemeTextColor(String theme) {
    if (theme == 'light') {
      return Colors.black;
    } else if (theme == 'dark') {
      return Colors.white;
    }
    return Colors.white;
  }
}

class ThemeChanger with ChangeNotifier {
  Brightness _themeData;
  double _textFont;
  String _displayList;
  int _sortedNumber;
  ThemeChanger(this._themeData, this._textFont);

  getTheme() => _themeData;
  getTextFont() => _textFont;
  getDisplayList() => _displayList;
  getSortedNumber () => _sortedNumber;
  setSortedNumber (int sortedNumber) {
    _sortedNumber = sortedNumber;
    notifyListeners();
  }
  setTheme(Brightness theme) {
    _themeData = theme;
    notifyListeners();
  }
  setTextFont(double textFont) {
    _textFont = textFont;
    notifyListeners();
  }
  setDisplayList(String displayList) {
    _displayList = displayList;
    notifyListeners();
  }
}
class ESP{
  final double temp;
  final double avg;
  final double bpm;

  ESP({this.temp, this.avg,this.bpm});
  factory ESP.fromJson(Map<dynamic,dynamic> json){
    double dataValue(dynamic source){
      try{
        return double.parse(source.toString());
      } on FormatException{
        return -1;
      }
    }
    return ESP(
      temp: dataValue(json['Temperature']),
      bpm: dataValue(json['BPM']),
      avg: dataValue(json['Avg']));
  }
}
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_icons/flutter_icons.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter_animation_progress_bar/flutter_animation_progress_bar.dart';
import '/dataHandle.dart';
import 'package:oscilloscope/oscilloscope.dart';
import 'package:testingesp32/stringValue.dart';
import 'package:adaptive_theme/adaptive_theme.dart';

class DisplayPage extends StatefulWidget {
  final Widget Function(BuildContext context,Brightness brightness) builder;
  DisplayPage({this.builder});
  @override
  _DisplayPageState createState() => _DisplayPageState();
}


class _DisplayPageState extends State<DisplayPage> with SingleTickerProviderStateMixin{

  TabController _tabController;
  int tabSet = 0;
  int _radioModeValue;
  int _radioTextValue;
  int _radioLanguageValue;
  double textSizeChange = 1;
  final FirebaseAuth _auth =FirebaseAuth.instance;
  DatabaseReference  _espRef = FirebaseDatabase.instance.ref().child('ESP32');
  bool _login;
  // ignore: deprecated_member_use
  List<double> traceDustTemp =List();
  // ignore: deprecated_member_use
  List<double> traceDustBpm =List();

  @override

  void initState() {
    // TODO: implement initState
    setState(() {
      _radioModeValue = 0;
      _radioTextValue = 1;
      _radioLanguageValue = 1;
    });
    super.initState();
    _tabController= TabController(length: 3, vsync: this);
    _login =false;
  }

  @override
  Widget build(BuildContext context) {

    return _login ? firstScaffold() : logInScaffold();
  }
  Widget firstScaffold(){
    return Scaffold(
      appBar: AppBar(
        title: Text(systemText("AppTitle"),
          style: TextStyle(fontSize: 22*textSizeChange),
        ),
        bottom: TabBar(
          indicatorColor: Colors.cyanAccent,
          indicatorSize: TabBarIndicatorSize.label,
          controller: _tabController,
          onTap: (int index){setState(() {tabSet = index;});},
          tabs: [
            Tab(icon: Icon(MaterialCommunityIcons.temperature_celsius),),
            Tab(icon: Icon(Icons.favorite),),
            Tab(icon: Icon(Icons.settings),)
          ],
        ),
      ),
      body: StreamBuilder(
        stream: _espRef.onValue,
          builder: (context, snapshot) {
            if (snapshot.hasData &&
                !snapshot.hasError &&
                snapshot.data.snapshot.value != null){
              print("snapshot data:${snapshot.data.snapshot.value.toString()}");
              var _esp =ESP.fromJson(snapshot.data.snapshot.value);
              print("ESP json data :${_esp.temp}/${_esp.bpm}/${_esp.avg}");
              traceDustTemp.add(double.tryParse(_esp.temp.toStringAsFixed(1)) ?? 0);
              traceDustBpm.add(double.tryParse(_esp.avg.toStringAsFixed(0)) ?? 0);

              return IndexedStack(
                index: tabSet,
                children: [_tempUI(_esp),_bpmUI(_esp),_settingUI(_esp),],
              );
            }else{
              return Center(
                child: Text("NO DATA YET"),
              );
            }
          }
      ),
    );
  }

  static const Radius _borderRadius = const Radius.circular(50);
  Widget _tempUI(ESP _esp){
      Oscilloscope vied = Oscilloscope(
      showYAxis: true,
      margin: EdgeInsets.all(20.10),
      strokeWidth: 5,
      backgroundColor: Colors.grey,
      traceColor: Colors.red,
      yAxisMax: 45.0,
      yAxisMin: 30.0,
      dataSet: traceDustTemp,
    );
    return Center(
      child:Column(
        children: [
          Container(
            padding: const EdgeInsets.only(top: 50),
            child: Text(systemText("temptitle"),
              style: TextStyle(fontWeight: FontWeight.bold,
                  fontSize: 30 *textSizeChange
              ),
            ),
          ),
          Expanded(
            flex: 1,
              child: Padding(
                padding: const EdgeInsets.symmetric(vertical: 20),
                child: Row(
                  children:<Widget>[
                    Container(
                      width: 200,
                      margin: EdgeInsets.all(40),
                      child: vied,
                    ),
                    FAProgressBar(
                      direction: Axis.vertical,
                      verticalDirection: VerticalDirection.up,
                      currentValue:_esp.temp,
                      progressColor: Colors.green,
                      backgroundColor: Colors.grey,
                      changeProgressColor: Colors.red,
                      size: 80,
                      maxValue: 50,
                      changeColorValue: 41,
                      displayText: " °C",
                      borderRadius: BorderRadius.all(_borderRadius),
                      animatedDuration: Duration(milliseconds: 1000),
                    ),
                  ]
                ),
            ),
          ),
          Container(
            padding: const EdgeInsets.only(bottom: 50),
            child: Text('${systemText('nowtempis')}'
                '${_esp.temp.toStringAsFixed(1)} ${systemText('°C')}',
              style: TextStyle(fontWeight: FontWeight.bold,fontSize: 30* textSizeChange),
            ),
          ),
        ],
      )
    );
  }

  Widget _bpmUI(ESP _esp){
    Oscilloscope ibp = Oscilloscope(
      showYAxis: true,
      margin: EdgeInsets.all(20.10),
      strokeWidth: 5,
      backgroundColor: Colors.grey,
      traceColor: Colors.red,
      yAxisMax: 200.0,
      yAxisMin: 20.0,
      dataSet: traceDustBpm,
    );
    return Center(
        child:Column(
          children: [
            Container(
              padding: const EdgeInsets.only(top:50),
              child: Text(systemText("bpmtitle"),
                style: TextStyle(fontWeight: FontWeight.bold,
                    fontSize: 30 *textSizeChange),
              ),
            ),
            Expanded(
              flex: 1,
              child: Padding(
                padding: const EdgeInsets.symmetric(vertical: 20),
                child: Row(
                  children:<Widget>[
                    Container(
                      width: 200,
                      margin: EdgeInsets.all(40),
                      child: ibp,
                    ),
                    FAProgressBar(
                      direction: Axis.vertical,
                      verticalDirection: VerticalDirection.up,
                      currentValue:_esp.avg,
                      progressColor: Colors.pink,
                      backgroundColor: Colors.grey,
                      changeProgressColor: Colors.red,
                      size: 80,
                      maxValue: 180,
                      changeColorValue: 105,//5 value change
                      displayText: "bpm",
                      borderRadius: BorderRadius.all(_borderRadius),
                      animatedDuration: Duration(milliseconds: 1000),
                    ),
                  ],
                )
              ),
            ),
            Container(
              padding: const EdgeInsets.only(bottom: 50),
              child: Text('${systemText('nowbpm')} '
                  '${_esp.avg.toStringAsFixed(0)} ${systemText('bpm')}',
                style: TextStyle(
                    fontWeight: FontWeight.bold,
                    fontSize: 30* textSizeChange
                ),
              ),
            ),
          ],
        )
    );
  }

  Widget _settingUI(ESP _esp){
     return Scaffold(
       body: Container(
         padding: const EdgeInsets.all(10),
         child: ListView(
           children: [
             SizedBox(height: 40),
             Row(
               children: [
                 Icon(Icons.settings, color: Colors.indigoAccent,),
                 SizedBox(width: 10),
                 Text(systemText("settingPage"),
                   style: TextStyle(
                       fontSize: 24 * textSizeChange,
                       fontWeight: FontWeight.bold,
                       letterSpacing: 1.2
                   ),
                 )
               ],
             ),
             Divider(height: 20, thickness: 1),
             SizedBox(height: 10),
             //buildSetting(context, "Content Settings"),
             buildSetting(context, systemText("Language")),
             SizedBox(height: 20),
             Row(
               children: [
                 Icon(Icons.settings, color: Colors.indigoAccent,),
                 SizedBox(width: 10),
                 Text(systemText("Other Setting"),
                   style: TextStyle(
                     fontSize: 24 *textSizeChange,
                     fontWeight: FontWeight.bold,
                     letterSpacing: 1.2
                   ),
                 )
               ],
             ),
             Divider(height: 20, thickness: 1),
             SizedBox(height: 10),
             Row(
               children: <Widget>[
                 Container(
                   height: 50,
                   margin: EdgeInsets.all(10),
                   //width: 110,
                   child: Text(
                     systemText('fontsize'),
                     textAlign: TextAlign.center,
                     style: TextStyle(
                       fontSize: 20 *textSizeChange
                     ),
                   ),
                   alignment: Alignment(0.0, 0.0),
                 ),
                 Container(
                   height: 30,
                   margin: EdgeInsets.all(20),
                   child: Row(
                     children: <Widget>[
                       Text(systemText('small'),
                         style: TextStyle(fontSize: 16 *textSizeChange),
                       ),
                       new Radio(
                         value: 0,
                         groupValue: _radioTextValue,
                         onChanged: _handleRadioTextValueChange,
                       ),
                       Text(systemText('medium'),
                           style: TextStyle(fontSize: 20 *textSizeChange),
                       ),
                       new Radio(
                         value: 1,
                         groupValue: _radioTextValue,
                         onChanged: _handleRadioTextValueChange,
                       ),
                       Text(systemText('large'),
                         style: TextStyle(fontSize: 22 *textSizeChange),
                       ),
                       new Radio(
                         value: 2,
                         groupValue: _radioTextValue,
                         onChanged: _handleRadioTextValueChange,

                       ),
                     ],
                   ),
                 ),
               ],
             ),
             SizedBox(height: 20),
             Row(
               children: <Widget>[
                 Container(
                   margin: EdgeInsets.all(10),
                   //height: 60,
                   //width: 80,
                   child: Text(
                     systemText('mode'),
                     textAlign: TextAlign.center,
                     style: TextStyle(fontSize: 20*textSizeChange),
                   ),
                   alignment: Alignment(0.0, 0.0),
                 ),
                 Container(
                   height: 30,
                   decoration: BoxDecoration(
                     //border: Border.all(width: 2.8, color: Colors.red),
                       borderRadius: BorderRadius.circular(12)),
                   child: Row(
                     children: <Widget>[
                       Text(systemText('lightmode'),
                         style: TextStyle(fontSize: 18*textSizeChange),),
                       new Radio(
                         value: 0,
                         groupValue: _radioModeValue,
                         onChanged: _handleRadioModeValueChange,
                       ),
                       Text(systemText('darkmode'),
                         style: TextStyle(fontSize: 18*textSizeChange),),
                       new Radio(
                         value: 1,
                         groupValue: _radioModeValue,
                         onChanged: _handleRadioModeValueChange,
                       ),
                     ],
                   ),
                 ),
               ],
             ),

             Center(
               child: OutlinedButton(
                 style:OutlinedButton.styleFrom(
                   padding: const EdgeInsets.symmetric(horizontal: 40),
                   shape: RoundedRectangleBorder(
                     borderRadius: BorderRadius.circular(20)
                   )
                 ),
                 onPressed: (){},
                 child: Text(systemText("call"),
                   style: TextStyle(
                       fontSize: 16* textSizeChange,
                       letterSpacing: 2.2,
                       //color: Colors.black
                 ),),
               ),
             )
           ],
         ),
       ),
     );
   }

   GestureDetector buildSetting(BuildContext context, String title){
    return GestureDetector(
      onTap: (){
        showDialog(context: context, builder: (BuildContext context){
          return AlertDialog(
            title: Text(title,style: TextStyle(fontSize: 22*textSizeChange),),
            content: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Row(
                  children: <Widget>[
                    Container(
                      margin: EdgeInsets.all(5),
                      decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(12)),
                      child: Row(
                        children: <Widget>[
                          Text(systemText('chinese')),
                          new Radio(
                            value: 0,
                            groupValue: _radioLanguageValue,
                            onChanged: _handleRadioLanguageValueChange,
                          ),
                          Text(systemText('english')),
                          new Radio(
                            value: 1,
                            groupValue: _radioLanguageValue,
                            onChanged: _handleRadioLanguageValueChange,
                          ),
                        ],
                      ),
                    )
                  ],
                )
              ],
            ),
            actions: [
              TextButton(
                  onPressed: (){
                    Navigator.of(context).pop();
                  },
                  child: Text(systemText("close")))
            ],
          );
        });
      },
      child: Padding(
        padding: const EdgeInsets.symmetric(vertical: 8,horizontal: 20),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            Text(title,style: TextStyle(
              fontSize: 20* textSizeChange,
              fontWeight: FontWeight.w500,
            )),
            Icon(Icons.arrow_forward,color: Colors.grey)
          ],
        ),
      ),
    );
   }


  Widget logInScaffold(){
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [Text(systemText("title"),
            style: TextStyle(fontWeight :FontWeight.bold, fontSize: 20),
          ),
            SizedBox(height: 50,),
            ElevatedButton(
              child: Text(systemText('Login'),
                style: TextStyle(fontSize: 20),
              ),
              style: ElevatedButton.styleFrom(
                  shape: new RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(20),
                      side: BorderSide(color: Colors.black)
              )),
              onPressed: ()async{
                _signIn();
              },
            )],
        ),
      ),
    );
  }

  void _signIn() async {
    final User user = (await _auth.signInAnonymously()).user;
    print("*** user isAnonymous: ${user.isAnonymous}");
    print("*** user uid: ${user.uid}");
    setState(() {
      if (user != null) {
        _login = true;
      } else {
        _login = false;
      }
    });
  }

  void _handleRadioModeValueChange(int value){
    setState(() {
      _radioModeValue =value;
      if(_radioModeValue == 0){
        AdaptiveTheme.of(context).setLight();
      }else if(_radioModeValue ==1){
        AdaptiveTheme.of(context).setDark();
      }
    });
  }

  void _handleRadioTextValueChange(int value) {
    setState(() {
      _radioTextValue = value;
      if (_radioTextValue == 0) {
        return textSizeChange =0.8;
      } else if (_radioTextValue == 1) {
        return textSizeChange =1;
      } else if (_radioTextValue == 2) {
        return textSizeChange =1.2;
      }
    });
  }

  void _handleRadioLanguageValueChange(int value) {
    setState(() {
      _radioLanguageValue = value;
      if (_radioLanguageValue == 0) {
        setState(() {
          theLocate = 'zh';
        });
      } else if (_radioLanguageValue == 1) {
        setState(() {
          theLocate = 'en';
        });
      }
    });
  }

}

 

pubspec.yaml

name: testingesp32
description: A new Flutter application.

publish_to: 'none' # Remove this line if you wish to publish to pub.dev

version: 1.0.0+1

environment:
  sdk: ">=2.7.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter


  cupertino_icons: ^1.0.2
  firebase_auth: ^3.0.0
  firebase_database: ^9.0.7
  google_sign_in: ^5.1.0
  flutter_animation_progress_bar: ^2.1.1
  flutter_icons: ^1.1.0
  oscilloscope: ^0.2.0+1
  adaptive_theme: ^2.3.1

dev_dependencies:
  flutter_test:
    sdk: flutter
  firebase_core : ^1.10.0

flutter:

  uses-material-design: true