Real time temperature monitoring and device control from mobile App developed on Flutter through NodeMCU

A temperature monitoring system which will turn ON a device such as cooling fan, when the temperature is increased above an upper threshold. Similarly, device will be turned OFF when the temperature is decreased below lower threshold. In between lower threshold and upper threshold, device will continue its state. Circuit is done as shown in the following diagram.

Download the TemperatureMonitorAndDeviceControl library from the following link.

Unzip and copy the downloaded library to Arduino libraries folder. Restart Arduino software and open the example program from File -> Examples -> TemperatureMonitorAndDeviceControl -> TemperatureMonitorAndDeviceControl. Compile and upload the program to your NodeMCU.

How to get the mobile App ?

There are two methods to get the mobile App.

  1. Download and install HABEROCEAN App from Google Play Store.
  2. Design it yourself on Flutter

Method 1

Download and install HABEROCEAN App from Google Play Store through the following link.

HABEROCEAN - Changing Future
HABEROCEAN - Changing Future
Developer: HABEROCEAN
Price: Free
  • HABEROCEAN - Changing Future Screenshot
  • HABEROCEAN - Changing Future Screenshot
  • HABEROCEAN - Changing Future Screenshot
  • HABEROCEAN - Changing Future Screenshot
  • HABEROCEAN - Changing Future Screenshot
  • HABEROCEAN - Changing Future Screenshot
  • HABEROCEAN - Changing Future Screenshot
  • HABEROCEAN - Changing Future Screenshot

Connect mobile device to NodeMCU through WiFi. Launch HABEROCEAN App.

video

Method 2

Next is to create the mobile App using Flutter. Necessary program files for creating the mobile App using Flutter is given below.

pubspec.yaml

name: timerapp
description: A new Flutter application.

version: 1.0.0+1

environment:
  sdk: ">=2.1.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter
  http: ^0.12.0+4

  cupertino_icons: ^0.1.2
  flutter_timer: ^0.0.6

dev_dependencies:
  flutter_test:
    sdk: flutter

flutter:
  uses-material-design: true

  fonts:
    - family: Pacifico
      fonts:
        - asset: fonts/Pacifico-Regular.ttf

    - family: Bitter-Bold
      fonts:
        - asset: fonts/Bitter-Bold.ttf

    - family: Bitter-Regular
      fonts:
        - asset: fonts/Bitter-Regular.ttf

main.dart

import 'dart:async';
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';

class Post
{
  dynamic temperature;
  String deviceStatus;
  String message;

  Post({this.temperature, this.deviceStatus, this.message});

  factory Post.fromJson(Map <String, dynamic> json)
  {
    return Post(
      temperature: json['temperature'],
      deviceStatus: json['fanStatus'],
      message: json['message'],
    );
  }
}

Future <Post> createPost(String url, {Map body}) async
{
  return http.post(url, body: body).then((http.Response response)
  {
    final int statusCode = response.statusCode;

    if(statusCode < 200 || statusCode > 400 || json == null)
      {
        throw new Exception("Failed to fetch");
      }
    return Post.fromJson(json.decode(response.body));
  });
}

class getParam
{
  int upperThreshold;
  int lowerThreshold;
  int delayTime;

  getParam({this.upperThreshold, this.lowerThreshold, this.delayTime});

  factory getParam.fromJson(Map <String, dynamic> json)
  {
    return getParam(
        upperThreshold: json['upperThreshold'],
        lowerThreshold: json['lowerThreshold'],
        delayTime: json['delayTime']
    );
  }
}

Future <getParam> requestForParam(String url, {Map body}) async
{
  return http.post(url, body: body).then((http.Response response)
  {
    final int statusCode = response.statusCode;

    if(statusCode < 200 || statusCode > 400 || json == null)
    {
      throw new Exception("Failed to fetch");
    }
    return getParam.fromJson(json.decode(response.body));
  });
}

Future <http.Response> sendData(int upperThreshold, int lowerThreshold, int delay) async
{
  final response =
      await http.get('http://192.168.4.1/saveData?upperThreshold=${upperThreshold}&lowerThreshold=${lowerThreshold}&delay=${delay}');
}

void main() => runApp(MyApp());

class MyApp extends StatefulWidget
{
  MyApp({Key key}):super(key:key);

  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp>
{
  String temperature = "0";
  int upperThreshold ;
  int lowerThreshold;
  int delayTime;
  String deviceStatus = "OFF";
  String message = "No errors, Everything fine...";

  static final READ_TEMP_STATUS_MESSAGE_URL = 'http://192.168.4.1/convertTempStatusMessageToJson';
  static final READ_UPPER_LOWER_DELAY = 'http://192.168.4.1/convertUpperLowerDelayToJson';
  static final SAVE_DATA_URL = 'http://192.168.4.1/saveData';

  TextEditingController upperThresholdController, lowerThresholdController, delayTimeController;

  void fetchParams() async
  {
    getParam params = await requestForParam(READ_UPPER_LOWER_DELAY);
    upperThreshold = params.upperThreshold;
    lowerThreshold = params.lowerThreshold;
    delayTime = params.delayTime;

    upperThresholdController = new TextEditingController(text: upperThreshold.toString());
    lowerThresholdController = new TextEditingController(text: lowerThreshold.toString());
    delayTimeController = new TextEditingController(text: delayTime.toString());
  }

  void initState() {
    fetchParams();
    Timer.periodic(Duration(seconds: 2), (timer) {
      changeTemperature();
    });
  }

  void changeTemperature() async
  {
    Post p = await createPost(READ_TEMP_STATUS_MESSAGE_URL);
    setState(() {
      temperature = p.temperature.toString();
      deviceStatus = p.deviceStatus;
      message = p.message;
    });
  }

  Widget build(BuildContext context)
  {
    return MaterialApp(
      title: "Temperature monitoring system",
      theme: ThemeData(
        primaryColor: Colors.teal,
      ),
      home: Scaffold(
        //appBar: AppBar(
        //  title: Text(
        //    'Temperature monitoring system',
        //  ),
        //),
        body: new SafeArea(
          child: new ListView(
            padding: EdgeInsets.only(right: 10, left: 10),
            children: <Widget>[

              new SizedBox(
                height: 20,
              ),

              new Text(
                'Current temperature is',
                style: TextStyle(
                  fontSize: 22,
                  color: Colors.pink,
                  fontFamily: 'Pacifico',
                ),
                textAlign: TextAlign.center,
              ),

              new SizedBox(
                height: 10,
              ),

              new Row(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  new Text(
                    "${temperature}",
                    style: TextStyle(
                      fontSize: 45,
                      fontFamily: 'Bitter-Regular',
                    ),
                  ),

                  new Column(
                    children: <Widget>[
                      new Row(
                        children: <Widget>[
                          new Text("\u2103",
                            style: TextStyle(
                              fontSize: 20,
                              fontFamily: 'Bitter-Regular',
                            ),
                          ),
                        ],
                      )
                    ],
                  ),
                ],
              ),

              new SizedBox(
                height: 20,
              ),

              new Text(
                'Device status',
                style: TextStyle(
                  fontSize: 20,
                  color: Colors.teal,
                  fontFamily: 'Pacifico',

                ),
                textAlign: TextAlign.center,
              ),

              new SizedBox(
                height: 10,
              ),

              new Text(
                "$deviceStatus",
                textAlign: TextAlign.center,
                style: TextStyle(
                  fontSize: 23,
                  fontWeight: FontWeight.bold,
                  fontFamily: 'Bitter-Regular',
                ),
              ),

              new SizedBox(
                height: 10,
              ),

              new TextField(
                controller: upperThresholdController,
                decoration: InputDecoration(
                  hintText: "Celsius (0 - 255)",
                  hintStyle: TextStyle(
                    fontSize: 13,
                  ),
                  labelText: 'Set upper threshold',
                  labelStyle: TextStyle(
                    fontSize: 18,
                  ),
                ),
                keyboardType: TextInputType.number,
              ),

              new SizedBox(
                height: 20,
              ),

              new TextField(
                controller: lowerThresholdController,
                decoration: InputDecoration(
                  hintText: "Celsius (0 - 255)",
                  hintStyle: TextStyle(
                    fontSize: 13,
                  ),
                  labelText: 'Set lower Threshold',
                  labelStyle: TextStyle(
                    fontSize: 18,
                  )
                ),
                keyboardType: TextInputType.number,
              ),

              new SizedBox(
                height: 20,
              ),

              new TextField(
                controller: delayTimeController,
                decoration: InputDecoration(
                  hintText: "Seconds (0 - 255)",
                  hintStyle: TextStyle(
                    fontSize: 13,
                  ),
                  labelText: 'Set delay',
                  labelStyle: TextStyle(
                    fontSize: 18,
                  )
                ),
                keyboardType: TextInputType.number,
              ),

              new SizedBox(
                height: 20,
              ),

              new Text(
                "$message",
                style: TextStyle(
                  fontSize: 15,
                  color: Colors.grey.shade600,
                ),
              ),

              new SizedBox(
                height: 20,
              ),

              new RaisedButton(onPressed: () async
                {
                  //showAlertDialog(context);
                  sendData(int.parse(upperThresholdController.text), int.parse(lowerThresholdController.text), int.parse(delayTimeController.text));
                },

                color: Colors.pink,
                shape: RoundedRectangleBorder(
                  borderRadius: new BorderRadius.circular(10),
                ),
                padding: EdgeInsets.only(top: 15, bottom: 15),
                child: const Text(
                  "Save changes",
                  style: TextStyle(
                    color: Colors.white,
                  ),
                ),
              ),

              new SizedBox(
                height: 20,
              ),

            ],
          ),

        ),
      ),
    );
  }
}

After designing and uploading your new App to mobile device, connect your mobile device to NodeMCU through WiFi. Then, open your newly designed App on your mobile device. Current temperature, device status, upper threshold, lower threshold, delay and messages will be displayed on the App as shown in following images. In the App, you can set your upper threshold, lower threshold and delay as per your requirement.

Pages:  1 2

Published by

Leave a Reply

avatar
  Subscribe  
Notify of
X