Nilton Schumacher F
Nilton Schumacher F

Reputation: 1180

Creating StreamBuilder to keep track whenever there is a change on Sensor value with Realtime Firebase

I'm working on a project to keep track of temperature and humidity sensor whenever they change. I will be working with a ESP32 to send the data to the Firebase, and my App to keep monitoring the values. So if the value goes from 23 to 24 I would like to immediately show the user on my app that change.

I will use a StreamBuilder to keep track of theses changes, But I'm having problems using the Stream.

This is how I the code I'm using to gather the specific user sensor info. This code is at a separate dart file, called auth.dart

class AuthService {

  final FirebaseAuth _auth = FirebaseAuth.instance;

  final databaseReference = FirebaseDatabase.instance.reference();

  //Cria um objeto baseado no Usuario da FirebaseUser
  User _userFromFirebaseUser (FirebaseUser user){
    return user != null ? User(uid: user.uid) : null;
  }

  // Devolve o UID da pessoa
  Future<String> personuid() async{
    final FirebaseUser user = await _auth.currentUser();
    return user.uid;
  }
   // Função para ler o valor da temperatura
  Future<int> getSensorTemperature() async {
    final FirebaseUser user = await _auth.currentUser();
    int result = (await databaseReference.child(user.uid+"/temperature").once()).value;
    print(result);
    return result;
  }

  // Função para ler o valor da humidade
  Future<int> getSensorHumidity() async {
    final FirebaseUser user = await _auth.currentUser();
    int result = (await databaseReference.child(user.uid+"/humidity").once()).value;
    print(result);
    return result;
  }

In my home page I attempted to use the StreamBuilder like this:

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {

  final AuthService _auth = AuthService();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Main page'),
        actions: <Widget>[
          FlatButton.icon(onPressed: () async {
            await _auth.signOut();
          }, 
          icon: Icon(Icons.logout), 
          label: Text('Logout'))
        ],
      ),
      body: StreamBuilder(
        stream: _auth.getSensorTemperature(), <-- I get an error here
        builder: (context, snapshot) {
          if (snapshot.hasError){
            return Container(color: Colors.red,);
          }
          if (!snapshot.hasData){
            return Center(child: CircularProgressIndicator(),);
          }
          if (snapshot.hasData){
            return Container(
              color: Colors.blue,
            );
          }
        },
      ),
    );
  }
}

The error I get from the StreamBuilder is: The argument type 'Futureint' can't be assigned to the parameter type 'Streamdynamic'

Upvotes: 0

Views: 245

Answers (1)

Christopher Moore
Christopher Moore

Reputation: 17141

You're not actually using streams. You were only taking a single event previously. Use the streams that the package make available and then use an await for to handle it.

Stream<int> getSensorTemperature() async* {
  final FirebaseUser user = await _auth.currentUser();

  await for(var event in databaseReference.child(user.uid+"/temperature").onValue) {
    yield event.snapshot.value;
  }
}

With error handling:

Stream<int> getSensorTemperature() async* {
  final FirebaseUser user = await _auth.currentUser();

  Stream stream = databaseReference.child(user.uid+"/temperature").onValue.handleError((error) {
    print("Error: $error");
  });
  await for(var event in stream) {
    yield event.snapshot.value;
  }
}

Upvotes: 1

Related Questions