Md. Khairul Alam
Published © CC BY

Toilet Management System

Using the system multiple persons can share a single toilet efficiently.

AdvancedWork in progress5 hours3,300
Toilet Management System

Things used in this project

Hardware components

Seeed Studio Grove - Ultrasonic Ranger
×1
Seeed Studio Grove - Air quality sensor
MQ135 Eqivalent
×1
Seeed Studio Grove - Temp&Humi Sensor
DHT11 Sensor
×1
Seeed Studio Grove - Buzzer
Optional, Code is not implemented here.
×1
Seeed Studio Grove Breakout for LinkIt Smart 7688 Duo
You can make your own breakout using Grove - Universal 4 pin connector. I made one.
×1
Water Level Detector
In the Internet, you can find lots of resource about how you can make a water level detector. Some using 555 timer, some using only BJTs and even using microcontroller. Choose one as you like. Just fed the digital output of the water level sensor to the LinkIt Smart Board according to the schematic. No need change anything in the program.
×1

Software apps and online services

Arduino IDE
Arduino IDE
Node.js
Language
Socket.IO
Node module
Serialport
Node module
Express
Framework
JavaScript
Language
HTML & CSS
Language

Story

Read more

Custom parts and enclosures

Enclosure

Side view

Enclosure

Top view

Schematics

Schematic

Schematic was designed using Fritzing.

Schematic 1

Basic schematic

MediaTek LinkIt Smart 7688 Duo pinout

Fritzing Source

Web Interface

Complete browser window

Web view

Web View 1

When Engaged

Code

Arduino Sketch

Arduino
Upload this program using Arduino environment to Linkit Smart Board.
/* Smart Toilet
 *  Toilet Management Syatem
 *  Author: MD. KHAIRUL ALAM TAIFUR
 *  Date: 15 March 2017
 */

#include"Arduino.h"
#include"AirQuality.h"
#include "dht.h"
#include "Ultrasonic.h"

AirQuality airqualitysensor;
int current_quality =-1;
int air_quality = 0;
int water = 0;
dht DHT;

#define DHT11_PIN 5 //thmp and humid sensor to pin D5
#define AIR_PIN A1 // Air quality sensor to pin A1
#define BUZZER_PIN 6 // Buzzer to pin D6
#define WATER_SENSOR 4 //for connecting water level detection sensor

Ultrasonic ultrasonic(7); //ultrasonic sensor to pin D7

float temperature = 0; 
int humidity = 0;
int distance = 0;

String measurement = " ";

void setup() 
{
    Serial.begin(9600); //serial connection for terminal
    Serial1.begin(57600); //serial port sending data to MPU unit
    pinMode(BUZZER_PIN, OUTPUT);
    pinMode(WATER_SENSOR, INPUT_PULLUP);
    Serial.println("DHT TEST PROGRAM ");
    Serial.print("LIBRARY VERSION: ");
    Serial.println(DHT_LIB_VERSION);
    Serial.println("Type,\tstatus,\tHumidity (%),\tTemperature (C)");
    airqualitysensor.init(14);
}

void loop(){
  air_quality_test();
  ultrasonic_cm();
  temperature_humidity();
  read_water_level();
  tone(BUZZER_PIN, 2000, 500);
  send_to_linkit(); //we are sending data every 2s from mcu to mpu
  delay(2000);
  }

//this function read temperature and humidity from the DHT11 sensor
void temperature_humidity(){
  // READ DATA
  Serial.print("DHT11, \t");
  int chk = DHT.read11(DHT11_PIN);
  if(chk) return; // to see the error comment this line and uncomment following block
  /*
  switch (chk)
  {
    case DHTLIB_OK:  
    Serial.print("OK,\t"); 
    break;
    case DHTLIB_ERROR_CHECKSUM: 
    Serial.print("Checksum error,\t"); 
    break;
    case DHTLIB_ERROR_TIMEOUT: 
    Serial.print("Time out error,\t"); 
    break;
    case DHTLIB_ERROR_CONNECT:
        Serial.print("Connect error,\t");
        break;
    case DHTLIB_ERROR_ACK_L:
        Serial.print("Ack Low error,\t");
        break;
    case DHTLIB_ERROR_ACK_H:
        Serial.print("Ack High error,\t");
        break;
    default: 
    Serial.print("Unknown error,\t"); 
    break;
  }
  */
  // DISPLAY DATA to the arduino serial terminal
  Serial.print(DHT.humidity, 1);
  humidity = DHT.humidity;
  Serial.print(",\t");
  Serial.println(DHT.temperature, 1);
  temperature = DHT.temperature;
}

//this function test air quality
void air_quality_test(){
  current_quality=airqualitysensor.slope();
    if (current_quality >= 0)// if a valid data returned.
    {   air_quality = current_quality; //we are sending the value (1, 2 or 3) to MPU
        if (current_quality==0)
            Serial.println("High pollution! Force signal active");
        else if (current_quality==1)
            Serial.println("High pollution!");
        else if (current_quality==2)
            Serial.println("Low pollution!");
        else if (current_quality ==3)
            Serial.println("Fresh air");
    }
  }
//interrupt service routine to read air quality sensor
ISR(TIMER1_OVF_vect)
{
  if(airqualitysensor.counter==61)//set 2 seconds as a detected duty
  {

      airqualitysensor.last_vol=airqualitysensor.first_vol;
      airqualitysensor.first_vol=analogRead(AIR_PIN);
      airqualitysensor.counter=0;
      airqualitysensor.timer_index=1;
      PORTB=PORTB^0x20;
  }
  else
  {
    airqualitysensor.counter++;
  }
}

void ultrasonic_cm(){
  //long RangeInInches;
  long RangeInCentimeters;
  //to see the data in inch uncomment the following block.
  /*
  Serial.println("The distance to obstacles in front is: ");
  RangeInInches = ultrasonic.MeasureInInches();
  Serial.print(RangeInInches);//0~157 inches
  Serial.println(" inch");
  delay(250);
  */
  RangeInCentimeters = ultrasonic.MeasureInCentimeters(); // two measurements should keep an interval
  distance = RangeInCentimeters;
  Serial.print("Distance = ");//0~400cm
  Serial.print(RangeInCentimeters);//0~400cm
  Serial.println(" cm");
  delay(250);
  }

void read_water_level(){
  if(digitalRead(WATER_SENSOR))
    water = 50; // just two value I am using to identify the water level
  else water = 10;
}
//this function sends data from MCU to MPU using serial port.
//we are sending all the data in a single string and then seperated 
//in the MPU using node.js
void send_to_linkit(){
   //+= is used to add the value to measurement string
   measurement += temperature;
   measurement += " ";
   measurement += humidity;
   measurement += " ";
   measurement += air_quality;
   measurement += " ";
   measurement += distance;
   measurement += " ";
   measurement += water;
   measurement += " ";
   Serial1.println(measurement);
   measurement = " "; //measurement string is null here     
  }

Index HTML

HTML
For client side. HTML, CSS and JavaScript was used.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Toilet Management System</title>
	<style>
	.button {
		background-color: #4CAF50; /* Green */
		border: none;
		color: white;
		padding: 15px 32px;
		text-align: center;
		text-decoration: none;
		display: inline-block;
		font-size: 34px;
		margin: 4px 2px;
		cursor: pointer;
		width: 70%;
		margin-left:15%;
		margin-right:15%;
		
	}
	.button1 {background-color: #f44336;} /* Red */ 
	</style>
</head>

	<script src="/socket.io/socket.io.js"></script>
	<script>
		var socket = io();
		//socket.on('message', function(data){document.write(data)});		
		socket.on('update', function(data){
		//document.write(data.description)
		if(data.per==="-1 Persons") data.per = "0 Persons";
		document.getElementById("air").innerHTML = data.air;
		document.getElementById("temp").innerHTML = data.temp;
		document.getElementById("humid").innerHTML = data.humid;
		document.getElementById("status").innerHTML = data.stat;
		document.getElementById("person").innerHTML = data.per;
		document.getElementById("water").innerHTML = data.water;
		});
		
		socket.on('person', function(data){
		//document.write(data.description)
		if(data.per==="-1 Persons") data.per = "0 Persons";
		document.getElementById("person").innerHTML = data.per;
		});
		
		//send message to server when serial button click
		function sendRequest(){
			socket.emit('serialButton', 'Serial button was clicked');
			document.getElementById("b2").innerHTML = "Cancel Request";
			document.getElementById("b1").innerHTML = "You are in the Queue";
		}
		//send message to server on cancel button click
		function cancelRequest(){
			socket.emit('cancelButton', 'Cancel button was clicked');
			document.getElementById("b2").innerHTML = "Canceled";
			document.getElementById("b1").innerHTML = "Take a Serial";
		}
		//socket.on('broadcast', function(data){
			//document.body.ineerHTML = '';
			//document.write(data.description);
			//});
		socket.on('notice', function(data){
			alert("You already sent a request!");
		});
		
		socket.on('free', function(data){
			alert("Toilet is available! You may use it.");
			document.getElementById("b1").innerHTML = "Toilet is available";
		});
		
		socket.on('available', function(data){
			document.getElementById("status").innerHTML = "Available";
			document.getElementById("person").innerHTML = "0";
		});
		
		socket.on('info', function(data){
			document.getElementById("status").innerHTML = "Available";
			alert("It is your time! The toilet is available for you.");
			document.getElementById("b1").innerHTML = "Toilet is available";
		});
	</script>
	
<body style="margin:20px;">
    <table cellpadding="10px;" cellspacing="0" style="font:12px verdana, sans-serif; width:80%; margin:0 auto;">
        <tr>
            <td colspan="3" style="background-color:#679BB7;">
                <h1 style="font-size:38px; margin:10px 0; text-align: center; color: #212F3D">Toilet Management System</h1>
            </td>
        </tr>
        <tr style="height:450px;">
		    
            <td style="background-color:#bbd2df; width:20%; vertical-align:top;">
                <ul style="list-style:none; padding:0px; margin:0px;">
                    <li style="margin-bottom:15px;"><h2 style="font-size:16px; margin:0px;">Status</h2></li>
                    <li style="margin-bottom:15px;"><h2 id="status" style="font-size:24px; margin:0px; text-align: center; color: red">Engaged</h2></li>
					<li style="margin-bottom:15px;"><h2 style="font-size:16px; margin:0px;">Waiting</h2></li>
                    <li style="margin-bottom:15px;"><h2 id="person" style="font-size:24px; margin:0px; text-align: center; color: red">-- Persons</h2></li>
                    
                </ul>
            </td>
			
            <td style="background-color:#f0f0f0; width:60%; vertical-align:top;">
                <h2 style="font-size:36px; margin:0px; text-align: center; margin-bottom:25px; color:#5D6D7E">Welcome</h2>
				<button class="button" id="b1" onclick="sendRequest()">Take a Serial</button>
				<button class="button button1" id="b2" onclick="cancelRequest()">Cancel</button>
            </td>
            
            <td style="background-color:#bbd2df; width:20%; vertical-align:top;">
                <ul style="list-style:none; padding:0px; margin:0px;">
                    <li style="margin-bottom:15px;"><h2 style="font-size:16px; margin:0px;">Air Quality</h2></li>
					<li style="margin-bottom:15px;"><h2 id="air" style="font-size:24px; margin:0px; text-align:center">--</h2></li>
                    <li style="margin-bottom:15px;"><h2 style="font-size:16px; margin:0px;">Temperature</h2></li>
					<li style="margin-bottom:15px;"><h2 id="temp" style="font-size:24px; margin:0px; text-align:center">--</h2></li>
                    <li style="margin-bottom:15px;"><h2 style="font-size:16px; margin:0px;">Humidity</h2></li>
					<li style="margin-bottom:15px;"><h2 id="humid" style="font-size:24px; margin:0px; text-align:center">--</h2></li>
					<li style="margin-bottom:15px;"><h2 style="font-size:16px; margin:0px;">Water Supply</h2></li>
					<li style="margin-bottom:15px;"><h2 id="water" style="font-size:24px; margin:0px; text-align:center">--</h2></li>
                </ul>
            </td>
            
        </tr>
        <tr>
            <td colspan="3" style="background-color:#679BB7;">
                <p style="text-align:center; margin:5px;">copyright &copy; t@ifur</p>
            </td>
        </tr>
    </table>
</body>
</html> 

Node Application app.js (final with modified route and added comments)

JavaScript
With the relative path of index.html
//importing required modules
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http); //creates a new socket.io instance attached to the http server
var serialport = require("serialport");
var SerialPort = serialport.SerialPort;
var path = require('path');
path.join(__dirname, '/root/smart-toilet')
//routes the index.html file
app.get('/', function(req, res){
	//res.sendfile('./index.html');
	res.sendFile(__dirname + '/index.html');
});

//setup serial port
var sp = new SerialPort("/dev/ttyS0", { //for serial communication with arduino chip 
    baudrate: 57600,  
    parser: serialport.parsers.readline("\n")
});

//required global variables
var total_clients = 0;
var connected_clients_id = [];
var flag = 0;
var engaged = false;
var button_flag = 0;

//triggers when connected to serial port 
sp.on("open", function () {
	//trigger on connection to any client
    io.on('connection', function(socket){
	console.log('A user connected (id=' +socket.id + ').');
	
	//In order to send an event to everyone, Socket.IO gives us the io.emit:

    //this function is triggered on any serial data received
	sp.on('data', function(data) {
            console.log("Serial port received data:" + data);
            //data gets split by " " to get the values and stored in result array
            var result=data.split(" ");
			var temperature = result[1];
			var humidity = result[2];
			var air_quality = result[3];
			var distance = result[4];
			var water = result[5];
			var air_status; var water_supply; var toilet_status;
			if(air_quality == 3)  air_status = 'Fresh Air';
			else if(air_quality == 2)  air_status = 'Low Pollution';
			else if(air_quality == 1)  air_status = 'High Pollution';
			//I am taking a random value set to arduino program to sense water sypply
			//30 means nothing, you can use your own value and should be set to arduino program
			if(water>30) water_supply = 'Available';
			else water_supply = 'Not Available';
			//flag variable is used to track either a person used the toilet or not
			if(distance<10) {toilet_status = 'Engaged'; flag = 1; engaged = true; if(button_flag){total_clients++; button_flag = 0;}}
			//if(distance<10 && flag==1) toilet_status = 'Engaged';
			else if(distance>20 && total_clients<1) toilet_status = 'Available';
			else if(distance>20 && total_clients>=1) {toilet_status = 'Engaged'; if(button_flag) total_clients++; }
			//socket.emit sends data to all client in JSON format
			socket.emit('update', { temp: temperature.toString()+'C', humid: humidity+'%', air: air_status, 
									stat: toilet_status, per: (total_clients-1).toString()+' Persons', water: water_supply});
			//the distance may be changed for your case
			//and depends on the sensor placement and room sizeToContent
			//adjust it according to your requirement
			if(distance>20 && flag==1) {
				//after sending a request a toilet will be engaged immediately and will be available againg
				//after user's entering and then outgoing, flag==1 when engaged and distance>20 when free again
				flag = 0; engaged = false; button_flag = 0;
				io.to(connected_clients_id[0]).emit('info', 'it is your time');
				connected_clients_id.splice(0, 1);
				if(total_clients>0)total_clients--;
				socket.emit('person', { per: (total_clients-1).toString()+' Persons'});
			}
    });
	
	//Receive a message from client side
	socket.on('serialButton', function(data){
		console.log(data);
		
		//Store the id of new client to an array
		var index = connected_clients_id.indexOf(socket.id);
		// if he is the first user and toilet is available
		if(total_clients==0 && engaged==false){ 
			io.to(socket.id).emit('free', {click: '0'});
			//status changed to engaged after clicking the serial button
			toilet_status = 'Engaged';
			total_clients++;
		}
		// when first user enter the system and found toilet engaged
		else if(total_clients==0 && engaged==true){
			//then his id is added to the queue
			connected_clients_id.push(socket.id);
			total_clients++;
			button_flag = 1; //keeps trac either user click to the button
			socket.emit('person', { per: (total_clients).toString()+' Persons'});
		}
		else if(index != -1){
			//if already any user click the serial button then check here either this click is from 
			//a different user or not. If same user click to the serial button multiple times his first
			//request will be considered only
			if(search(socket.id, connected_clients_id)){
				//request sent to specific client with client id 
				io.to(socket.id).emit('notice', 'You already sent a request');
			}
			else{
				connected_clients_id.push(socket.id);
				total_clients++;
				//number of client waiting = total client - 1
				//because one client will be in service 
				socket.emit('person', { per: (total_clients-1).toString()+' Persons'});
			}
		}
		else{
			connected_clients_id.push(socket.id);
			total_clients++;
			socket.emit('person', { per: (total_clients-1).toString()+' Persons'});
		}
	});
	//when a client click to cancel button his id will be removed from the list
	socket.on('cancelButton', function(data){
		console.log(data);
		var index = connected_clients_id.indexOf(socket.id);
		if(index != -1){
			console.log('A user disconnected (id =' +socket.id + ')');
			//remove the id of disconnected client from the array
			connected_clients_id.splice(index, 1);
			total_clients--;
		}
		socket.emit('person', { per: (total_clients-1).toString()+' Persons'});
	});
	
	//Whenever some disconnects this piece of code executed
	socket.on('disconnect', function(){
		console.log('A user disconnected (id =' +socket.id + ')');
		var index = connected_clients_id.indexOf(socket.id);
		if(index != -1){
			console.log('A user disconnected (id =' +socket.id + ')');
			//remove the id of disconnected client from the array
			connected_clients_id.splice(index, 1);
			total_clients--;
		}
	});
  //end of io.on() function	
  }); 
//end of sp.on() function  
});
//here I chacked an id is already available in the array or not
function search(nameKey, myArray){
    for (var i=0; i < myArray.length; i++) {
        if (myArray[i] === nameKey) {
            return true;
        }
    }
	return false;
}

//Run server to listen on port 3000.
http.listen('3000', function(){
	console.log('listening on *:3000');
});

// When the client connects, they are sent a message
// socket.emit('message', 'You are connected!');
// The other clients are told that someone new has arrived
// socket.broadcast.emit('message', 'Another client has just connected!');
// In order to send an event to everyone, Socket.IO gives us the io.emit:
// io.emit('some event', { for: 'everyone' });
// To broadcast an event to all the clients io.sockets.emit
// io.sockets.emit('broadcast',{ description: clients + ' clients connected!'});
	//arr.push(socket);
	//clients++;
	//arr[clients-1].emit('testerEvent', { temp: "23.45C", humid: '60%', air: 'Good', stat: 'Available', per: '3 Persons', water: 'Available'});

//arr.includes(searchElement)

Node.js Application

JavaScript
Server side program
//importing required modules
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http); //creates a new socket.io instance attached to the http server
var serialport = require("serialport");
var SerialPort = serialport.SerialPort;

//routes the index.html file
app.get('/', function(req, res){
	res.sendfile('index.html');
});

//setup serial port
var sp = new SerialPort("/dev/ttyS0", { //for serial communication with arduino chip 
    baudrate: 57600,  
    parser: serialport.parsers.readline("\n")
});

//required global variables
var total_clients = 0;
var connected_clients_id = [];
var flag = 0;
var engaged = false;
var button_flag = 0;

//triggers when connected to serial port 
sp.on("open", function () {
	//trigger on connection to any client
    io.on('connection', function(socket){
	console.log('A user connected (id=' +socket.id + ').');
	
	//In order to send an event to everyone, Socket.IO gives us the io.emit:

    //this function is triggered on any serial data received
	sp.on('data', function(data) {
            console.log("Serial port received data:" + data);
            //data gets split by " " to get the values and stored in result array
            var result=data.split(" ");
			var temperature = result[1];
			var humidity = result[2];
			var air_quality = result[3];
			var distance = result[4];
			var water = result[5];
			var air_status; var water_supply; var toilet_status;
			if(air_quality == 3)  air_status = 'Fresh Air';
			else if(air_quality == 2)  air_status = 'Low Pollution';
			else if(air_quality == 1)  air_status = 'High Pollution';
			if(water>30) water_supply = 'Available';
			else water_supply = 'Not Available';
			if(distance<10) {toilet_status = 'Engaged'; flag = 1; engaged = true; if(button_flag){total_clients++; button_flag = 0;}}
			//if(distance<10 && flag==1) toilet_status = 'Engaged';
			else if(distance>20 && total_clients<1) toilet_status = 'Available';
			else if(distance>20 && total_clients>=1) {toilet_status = 'Engaged'; if(button_flag) total_clients++; }
			//socket.emit sends data to all client
			//data is updated in every 2s
			socket.emit('update', { temp: temperature.toString()+'C', humid: humidity+'%', air: air_status, 
									stat: toilet_status, per: (total_clients-1).toString()+' Persons', water: water_supply});
			if(distance>20 && flag==1) {
				flag = 0; engaged = false; button_flag = 0;
				io.to(connected_clients_id[0]).emit('info', 'it is your time');
				connected_clients_id.splice(0, 1);
				if(total_clients>0)total_clients--;
				socket.emit('person', { per: (total_clients-1).toString()+' Persons'});
			}
    });
	
	//this function executes when serial button preass from client side
	socket.on('serialButton', function(data){
		console.log(data);
		
		//Store the id of new client to an array
		var index = connected_clients_id.indexOf(socket.id);
		if(total_clients==0 && engaged==false){
			io.to(socket.id).emit('free', {click: '0'});
			toilet_status = 'Engaged';
			total_clients++;
		}
		else if(total_clients==0 && engaged==true){
			connected_clients_id.push(socket.id);
			total_clients++;
			button_flag = 1;
			socket.emit('person', { per: (total_clients).toString()+' Persons'});
		}
		else if(index != -1){
			if(search(socket.id, connected_clients_id)){
				io.to(socket.id).emit('notice', 'You already sent a request');
			}
			else{
				connected_clients_id.push(socket.id);
				total_clients++;
				socket.emit('person', { per: (total_clients-1).toString()+' Persons'});
			}
		}
		else{
			connected_clients_id.push(socket.id);
			total_clients++;
			socket.emit('person', { per: (total_clients-1).toString()+' Persons'});
		}
	});
	//this function executes when cancel button press
	socket.on('cancelButton', function(data){
		console.log(data);
		var index = connected_clients_id.indexOf(socket.id);
		if(index != -1){
			console.log('A user disconnected (id =' +socket.id + ')');
			//remove the id of disconnected client from the array
			connected_clients_id.splice(index, 1);
			total_clients--;
		}
		socket.emit('person', { per: (total_clients-1).toString()+' Persons'});
	});
	
	//Whenever some disconnects this piece of code executed
	socket.on('disconnect', function(){
		console.log('A user disconnected (id =' +socket.id + ')');
		var index = connected_clients_id.indexOf(socket.id);
		if(index != -1){
			console.log('A user disconnected (id =' +socket.id + ')');
			//remove the id of disconnected client from the array
			connected_clients_id.splice(index, 1);
			total_clients--;
		}
	});
  //end of io.on() function	
  }); 
//end of sp.on() function  
});
//search a specific element on an array
function search(nameKey, myArray){
    for (var i=0; i < myArray.length; i++) {
        if (myArray[i] === nameKey) {
            return true;
        }
    }
	return false;
}

//Run server to listen on port 3000.
http.listen('3000', function(){
	console.log('listening on *:3000');
});

// When the client connects, they are sent a message
// socket.emit('message', 'You are connected!');
// The other clients are told that someone new has arrived
// socket.broadcast.emit('message', 'Another client has just connected!');
// In order to send an event to everyone, Socket.IO gives us the io.emit:
// io.emit('some event', { for: 'everyone' });
// To broadcast an event to all the clients io.sockets.emit
// io.sockets.emit('broadcast',{ description: clients + ' clients connected!'});

Complete Source Code

All the necessary source code are attached.

Credits

Md. Khairul Alam

Md. Khairul Alam

68 projects • 584 followers
Developer, Maker & Hardware Hacker. Currently working as a faculty at the University of Asia Pacific, Dhaka, Bangladesh.

Comments