NodeMCU: Show Live Data from DHT11 Sensor Using WebSocket on Flutter Mobile App
In this example, we are going to show you how to show live data like temperature, humidity, and Heat Index from DHT11 Sensor on a mobile App using NodeMCU (ESP8266). We have used WebSocket to transfer data from NodeMCU to Mobile App. WebSocket is very fast for communication, therefore we use it to stream live data to a mobile app.
We are using PlatromIO on Visual Studio Code as an IDE. Download WebSocket.zip and DHT.zip CPP library for NodeMCU. Extract the zip folders to lib/ folder.
#include <Arduino.h>
#include <ESP8266WiFi.h> //import for wifi functionality
#include <WebSocketsServer.h> //import for websocket
#include <DHT.h> //library for DHT Sensor
#define dhttype DHT11 //defining DHT Type
const char *ssid = "HelloHPC - Wifi"; //Wifi SSID (Name)
const char *pass = "12345678"; //wifi password
String json; //variable for json
char tstr[10]; //Character array for temperature
char hstr[10]; //Character array for Humidity
char histr[10]; //Character array for Heat Index
DHT dht(D5, dhttype); //initialize DHT sensor, D5 is the pin where we connect data pin from sensor
WebSocketsServer webSocket = WebSocketsServer(81); //websocket init with port 81
void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {
//webscket event method
String cmd = "";
switch(type) {
case WStype_DISCONNECTED:
Serial.println("Websocket is disconnected");
//case when Websocket is disconnected
break;
case WStype_CONNECTED:{
//wcase when websocket is connected
Serial.println("Websocket is connected");
Serial.println(webSocket.remoteIP(num).toString());
webSocket.sendTXT(num, "connected");}
break;
case WStype_TEXT:
cmd = "";
for(int i = 0; i < length; i++) {
cmd = cmd + (char) payload[i];
} //merging payload to single string
Serial.println(cmd);
if(cmd == "readdata"){ //when command from app is "poweron"
//recieved command from mobile app
//we can do task according to command from mobile using if-else-else if
}
webSocket.sendTXT(num, cmd+":success");
//send response to mobile, if command is "poweron" then response will be "poweron:success"
//this response can be used to track down the success of command in mobile app.
break;
case WStype_FRAGMENT_TEXT_START:
break;
case WStype_FRAGMENT_BIN_START:
break;
case WStype_BIN:
hexdump(payload, length);
break;
default:
break;
}
}
String chr2str(char* chr){ //function to convert characters to String
String rval;
for(int x = 0; x < strlen(chr); x++){
rval = rval + chr[x];
}
return rval;
}
void setup() {
Serial.begin(9600); //serial start
Serial.println("Connecting to wifi");
IPAddress apIP(192, 168, 0, 1); //Static IP for wifi gateway
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); //set Static IP gateway on NodeMCU
WiFi.softAP(ssid, pass); //turn on WIFI
webSocket.begin(); //websocket Begin
webSocket.onEvent(webSocketEvent); //set Event for websocket
Serial.println("Websocket is started");
}
void loop() {
webSocket.loop(); //keep this line on loop method
delay(2000); //delay by 2 second, DHT sesor senses data slowly with delay around 2 seconds
float h = dht.readHumidity(); //Humidity float value from DHT sensor
float t = dht.readTemperature(); //Temperature float value from DHT sensor
float f = dht.readTemperature(true); //Temperature float value from DHT sensor
if (isnan(h) || isnan(t) || isnan(f)) {
//if data from DHT sensor is null
Serial.println(F("Failed to read from DHT sensor!"));
return;
}else{
float hic = dht.computeHeatIndex(t, h, false); //convert humidity and temperature to heat index
sprintf(tstr, "%.2f", t); //convert float to characters
sprintf(hstr, "%.2f", h); //convert float to characters
sprintf(histr, "%.2f", hic); //convert float to characters
json = "{'temp':'" + chr2str(tstr) + "','humidity':'" + chr2str(hstr) + "%','heat':'" + chr2str(histr) + "'}";
//formulate JSON string format from characters (Converted to string using chr2str())
Serial.println("DHT Data read Successful");
webSocket.broadcastTXT(json); //send JSON to mobile
}
}
Now on the Flutter part, add web_socket_channel plugin as a dependency on pubspec.yaml file.
dependencies:
flutter:
sdk: flutter
web_socket_channel: ^1.1.0
Add Internet Permission by adding this line in android/app/src/main/AndroidManifest.xml before <application>
<uses-permission android:name="android.permission.INTERNET"/>
Here we are using ws
, non-secure WebSocket protocol. Therefore, add the following lines to AndroidManifest.xml file as well.
<application
android:usesCleartextTraffic="true"
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:web_socket_channel/io.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: WebSocketDHT(),
);
}
}
//apply this class on home: attribute at MaterialApp()
class WebSocketDHT extends StatefulWidget{
@override
State<StatefulWidget> createState() {
return _WebSocketDHT();
}
}
class _WebSocketDHT extends State<WebSocketDHT>{
String temp; //variable for temperature
String humidity; //variable for humidity
String heatindex; //variable for heatindex
IOWebSocketChannel channel;
bool connected; //boolean value to track if WebSocket is connected
@override
void initState() {
connected = false; //initially connection status is "NO" so its FALSE
temp = "0"; //initial value of temperature
humidity = "0"; //initial value of humidity
heatindex = "0"; //initial value of heatindex
Future.delayed(Duration.zero,() async {
channelconnect(); //connect to WebSocket wth NodeMCU
});
super.initState();
}
channelconnect(){ //function to connect
try{
channel = IOWebSocketChannel.connect("ws://192.168.0.1:81"); //channel IP : Port
channel.stream.listen((message) {
print(message);
setState(() {
if(message == "connected"){
connected = true; //message is "connected" from NodeMCU
}else if(message.substring(0, 6) == "{'temp"){
//check if the resonse has {'temp on it
message = message.replaceAll(RegExp("'"), '"');
Map<String, dynamic> jsondata = json.decode(message); //decode json to array
setState(() {
temp = jsondata["temp"]; //temperature value
humidity = jsondata["humidity"]; //humidity value
heatindex = jsondata["heat"]; //heatindex value
});
}
//you can apply "if elese - else if for more message type from NodeMCU"
});
},
onDone: () {
//if WebSocket is disconnected
print("Web socket is closed");
setState(() {
connected = false;
});
},
onError: (error) {
print(error.toString());
},);
}catch (_){
print("error on connecting to websocket.");
}
}
Future<void> sendcmd(String cmd) async {
if(connected == true){
channel.sink.add(cmd); //sending Command to NodeMCU
//send command to NodeMCU
}else{
channelconnect();
print("Websocket is not connected.");
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title:Text("DHT 11 - TEMP/HUMIDITY/HEAT INDEX"),
backgroundColor: Colors.redAccent
),
body:Container(
alignment: Alignment.topCenter, //inner widget alignment to center
padding: EdgeInsets.all(20),
child:Column(
children:[
Container( //showing if websocket is connected or disconnected
child: connected?Text("WEBSOCKET: CONNECTED"):Text("DISCONNECTED")
),
Container(
child: Text("Current Weather in Kathmandu",
style:TextStyle(fontSize: 20, color: Colors.redAccent))
),
Container( //showing temperature and humidity
child: Text("Temperature $temp°C | Humidity: $humidity",
style: TextStyle(fontSize: 18),),
),
Container( //showing heat index
child: Text("Heat Index: $heatindex°C"),
),
],
)
),
);
}
}
This is the way you can read Temperature, Humidity, and Heat Index from DHT11 sensor and live display on Android/iOS Mobile app using Flutter.
Please Wait...
No any Comments on this Article