Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
Himanshu Goyel ee19s025
Published

IOT based Complete Home Automation System

Realtime lighting control, live temperature, lighting and electric cost monitoring, real time energy cost calculation and anomaly detection.

AdvancedFull instructions provided3 days5,290
IOT based Complete Home Automation System

Things used in this project

Hardware components

Bolt WiFi Module
Bolt IoT Bolt WiFi Module
×1
Arduino UNO
Arduino UNO
×1
RGB Backlight LCD - 16x2
Adafruit RGB Backlight LCD - 16x2
×1
Temperature Sensor
Temperature Sensor
×1
LDR, 5 Mohm
LDR, 5 Mohm
×1
Relay (generic)
×1
Bipolar (BJT) Single Transistor, Brt
Bipolar (BJT) Single Transistor, Brt
×1
Breadboard (generic)
Breadboard (generic)
×1
DC motor (generic)
×1
USB-A to Micro-USB Cable
USB-A to Micro-USB Cable
×1
Resistor 10k ohm
Resistor 10k ohm
×1
Resistor 1k ohm
Resistor 1k ohm
×1
Resistor 220 ohm
Resistor 220 ohm
×1
3.6V 0.5W Zener Diode
3.6V 0.5W Zener Diode
×1
Jumper wires (generic)
Jumper wires (generic)
×1
4x4 keypad
×1
Single Turn Potentiometer- 10k ohms
Single Turn Potentiometer- 10k ohms
×1
LED (generic)
LED (generic)
×1
Motor driver
×1

Software apps and online services

Sublime text editor
Bolt Cloud
Bolt IoT Bolt Cloud
Bolt IoT Android App
Bolt IoT Android App
Python Programming Language

Hand tools and fabrication machines

Hot glue gun (generic)
Hot glue gun (generic)
Soldering iron (generic)
Soldering iron (generic)
Solder Wire, Lead Free
Solder Wire, Lead Free

Story

Read more

Schematics

Complete Hardware

Up load the code on arduino board and Use the spdt switch as a sensor, as mentioned in the video.

Code

live_data_from_bolt

Python
Captures the live data from bolt module and saves in a text file in JSON script. Make sure you create a text file of the name "bolt_data" in the working directory
from boltiot import Bolt
import time 
import json

API_KEY="xxxxxxxxxxxxxxxxxxxxxx"
DEVICE_ID="xxxxxxxxxxx"

mybolt = Bolt(API_KEY,DEVICE_ID) #Create bolt object

mybolt.serialBegin('9600')

while True:
    try:
        response = mybolt.serialRead('10') #read serial data from arduino
        print(response)
        light=json.loads(response)
        print("Average Light= "+light['value']) #display the average light
        light_temp=light['value']
        end= len(light_temp)
        comma1=light_temp.find(',') #each reading is sperated by a comma so                                          #finding the first comma
        print(comma1)
        comma2=light_temp.find(',', comma1+1, end) #finding comma 2
        print(comma2)
        comma3=light_temp.find(',', comma2+1, end) #finding comma 3
        print(comma3)
        if comma1>=0: #if a value is been send from bolt comma1 will be 1 else -1
            lightin = light_temp[0:comma1] #seperating the values
            temp = light_temp[comma1+1:comma2]
            u = light_temp[comma2+1:end]
            if comma3>=0:
                u = light_temp[comma2+1:comma3]
            print(u, temp, lightin)
            t = time.localtime() #getting current time
            current_time = time.strftime("%d:%b:%Y::%H:%M:%S",t) # saving it to                                                    #current_time in redable format
            dic = {                     #saving all the values as a dictionary
                    'light' : lightin,
                    'temperature' : temp,
                    'u' : u,
                    'sensed_date_time':current_time,
                    }
            with open('bolt_data.txt', 'w') as outfile: #Opening the pre made
                json.dump(dic, outfile)       #text file and dumping the                                                       #dictionary in it as a jason text  
        time.sleep(30)
    except:
        time.sleep(30)

webscraping

Python
Captures the cost of electricity from caiso (calarfornia Iso real time 5 min markets) and saves in a text file in JSON script. Make sure you create a text file of the name "cost.txt" in the working directory
import pandas as pd
import time
import json

while True:
	try:
		dfs=pd.read_html('http://oasis.caiso.com/oasisapi/prc_hub_lmp/PRC_HUB_LMP.html')     #reading the website for getting the electricity cost
		dfs1=dfs[1] #Shortlisting the actual value form other data
		val=dfs1.values.tolist()
		val0=val[0]
		val01=val0[1] #final value 
		electricity_cost=float(val01.replace('$','').replace(' ','')) #converting into redable format
		t = time.localtime() #getting current time
		current_date = time.strftime("%d:%b:%Y",t)
		current_time = time.strftime("%H:%M:%S",t)
		print(current_time, "==> ",electricity_cost,"$/MWh")

		dic = {                     #saving the values as a dictionary
		'cost' : electricity_cost,
		'cost_date':current_date,
		'cost_time':current_time,
		}
		with open('cost.txt', 'w') as outfile: # dumping the file in the already created text file in a JSON format
			json.dump(dic, outfile)
		
		time.sleep(60)
	except:          #in case some error in above script just wait for 60 seconds and the run the above script again
		time.sleep(60)	

live_monitoring

Python
Captures the cost, light and temperature from the text files and plots real-time graph for monitoring purpose.
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from datetime import datetime
import json

Temperature = []
Light_intensity = []
Sensed_time = []
Cost = []
def figure(i): # defining the figure

	with open ('cost.txt') as f:  #getting the values from text files
		cost_data = json.load(f)
	with open ('bolt_data.txt') as f:
		sensor_data = json.load(f)
	date_time = datetime.strptime(sensor_data['sensed_date_time'], '%d:%b:%Y::%H:%M:%S') #converting the date time from text file to machine redable format
	Cost.append(float(cost_data['cost'])) #creating list for plotting
	Temperature.append(float(sensor_data['temperature']))
	Light_intensity.append(float(sensor_data['light']))
	Sensed_time.append(date_time)
	print(sensor_data['temperature'])
	print(sensor_data['light'])
	print(cost_data['cost'])
	plt.cla() # clearing the plot
	plt.plot(Sensed_time,Temperature) # plotting the graphs
	plt.plot(Sensed_time,Light_intensity)
	plt.plot(Sensed_time,Cost)
ani = FuncAnimation(plt.gcf(), figure, interval=30000) #running the function after every 30 seconds

plt.show() #display the graph

controlling

Python
Used to control the battery charging and motor connected to the bolt module via driver circuit. Also captures the status of the batter sensor connected to the digital pin of bolt module. Calculates the energy cost and saves it to a text file in json format. It also plots real time energy cost curve i.e total energy cost added up till now. Text file named "energy cost" should be there in the working directory
from boltiot import Bolt
import time 
import json
import matplotlib.pyplot as plt
from drawnow import drawnow
from datetime import datetime


API_KEY="xxxxxxxxxxxxxxxxx"
DEVICE_ID="xxxxxxxxx"

mybolt = Bolt(API_KEY,DEVICE_ID) #Create bolt object

cost_margin = 38 
pump_wattage = 3000 #3KW load
EV_wattage = 10000  #10KW load
					#Indoor lighting system 250W maximum
port0 = 0
port1 = 1
total_cost = 0



plt.ion()  # enable interactivity
fig = plt.figure()  # make a figure


def make_fig():         #update fifure values to the graph
    plt.plot(time_axis, Tot_cost)  

Tot_cost = list()
time_axis = list()

while True:
	try:
		with open ('cost.txt') as f:  #getting cost data from text file
			cost_data = json.load(f)
		with open ('bolt_data.txt') as f:  #getting light, temperature, PWM(u) and date-time data from text file
			sensor_data = json.load(f)
		cost = float(cost_data['cost'])
		lighting = float(sensor_data['u'])


		if cost < cost_margin:   #checking if current electricity cost is less than marginal cost
			bat_status = 1
		else:
			bat_status = 0

		response = mybolt.digitalRead(port1) #Reading the sensor value to check if battery is chargable or not
		response = json.loads(response)
		battery_status = int(response['value'])
		print(battery_status)
		if battery_status==0:
			bat_status=0

		if bat_status==1: #battery charging along with motor turns on if sensor value = 1 and cost < cost marginal 
			print("Batery and Motor ON")
			response = mybolt.analogWrite(port0, '255')
		if bat_status==0:
			print("Batery and Motor OFF")
			response = mybolt.analogWrite(port0, '0')	

		print(response)

		cost = (cost/(1000000*60*60))	#convert to $/Wsec
		print(cost)

		total_cost = cost*30*(((pump_wattage+EV_wattage)*bat_status)+lighting) + total_cost       #Calculating the total energy consumed up till current iteration
		print(round(total_cost,5), "$")
		
		date_time = datetime.strptime(sensor_data['sensed_date_time'], '%d:%b:%Y::%H:%M:%S') #converting the date time taken from text file(JSON format) into computer understandable date time
		print(date_time)
		dic = {                           #saving values in a dictionary
				'energy_cost' : total_cost,
				'sensed_time': str(date_time),
				}
		with open('energy_cost.txt', 'w') as outfile:  #opening the pre made text file and dumping the values in it
			json.dump(dic, outfile)

		Tot_cost.append(total_cost) #appending the values in a list
		time_axis.append(date_time) 
		drawnow(make_fig) #making the real time graph

		plt.pause(30) #pausing the graph display for 30 seconds
	except:
		time.sleep(30)

anomaly_mail

Python
It calculates the z-score. It mails and sends an SMS in case the z score crosses the upper bound. It also sends an alert if the the cost of electricity is very high
import email_conf
from boltiot import Email, Bolt
from boltiot import Sms, Bolt
import json, time, math, statistics

mybolt = Bolt(email_conf.API_KEY, email_conf.DEVICE_ID)
mailer = Email(email_conf.MAILGUN_API_KEY, email_conf.SANDBOX_URL, email_conf.SENDER_EMAIL, email_conf.RECIPIENT_EMAIL)
sms = Sms(email_conf.SID, email_conf.AUTH_TOKEN, email_conf.TO_NUMBER, email_conf.FROM_NUMBER)

history_data=[]
conf=email_conf
def compute_bounds(history_data,frame_size,factor): #calculating Z-score using equations and setting high and low bounds
    if len(history_data)<frame_size :
        return None
    if len(history_data)>frame_size :
        del history_data[0:len(history_data)-frame_size]
        Mn=statistics.mean(history_data)
        Variance=0
        for data in history_data :
            Variance +=math.pow((data-Mn),2)
        Zn = factor*math.sqrt(Variance/frame_size)
        High_bound = history_data[frame_size-1]+Zn
        Low_bound = history_data[frame_size-1]-Zn
        return [High_bound,Low_bound]

while True:
    with open ('cost.txt') as f: #OPENING THE TEXT FILES AND READING THE DATA
        cost_data = json.load(f)
    with open ('bolt_data.txt') as f:
        sensor_data = json.load(f)
    with open ('energy_cost.txt') as f:
        energy_cost = json.load(f)    
    print ("Total cost is: " + str(energy_cost['energy_cost']))
    print ("Time of cost calculation: " + str(energy_cost['sensed_time']))
    
    bound = compute_bounds(history_data,conf.FRAME_SIZE,conf.MUL_FACTOR) #computing z-score
    if not bound: #if not enough data
        required_data_count = conf.FRAME_SIZE-len(history_data)
        print("Not enough data to compute z-score. Need",required_data_count,"more data ponts")
        history_data.append(float(energy_cost['energy_cost']))
        time.sleep(30)
        continue
    sensor_value = float(energy_cost['energy_cost'])
    try:
        if sensor_value > bound[0]: # enough data is present and the energy consumption increases suddenly
            print ("The energy consumption increased suddenly. Sending a mail")
            response = mailer.send_email("Alert","Sudden increase in energy consumption please monitor")  #sending a mail
            print("This is the response",response)

            print("Making request to Twilio to send a SMS")
            response = sms.send_sms("Sudden increase in energy consumption please monitor. ")  # sending an sms
            print("Response received from Twilio is: " + str(response))
            print("Status of SMS at Twilio is :" + str(response.status))


        if float(cost_data['cost']) > 50:  # if cost of electricity is more than 50$/MWh ten again send an alert
            print ("The energy cost is very high. Sending a mail")
            response = mailer.send_email("Alert","Cost is very high reduce consumption immediately")
            print("This is the response",response)

            print("Making request to Twilio to send a SMS")
            response = sms.send_sms("Cost is very high reduce consumption immediately ")
            print("Response received from Twilio is: " + str(response))
            print("Status of SMS at Twilio is :" + str(response.status))

        history_data.append(sensor_value)
    except Exception as e:
        print("Error",e)-
    time.sleep(30)

email_conf

Python
Contains Mailgun, Twillo, and bolt apis keys and ids. Also contains Frame size and multiplication factor for z score calculation
MAILGUN_API_KEY="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" 
SANDBOX_URL="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
SENDER_EMAIL="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
RECIPIENT_EMAIL="himanshugoyel05@gmail.com"
API_KEY="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
DEVICE_ID="XXXXXXXXXXXXX"
FRAME_SIZE = 10  #number of readings to calculate z score
MUL_FACTOR = 3   #multiplication factor


SID = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
AUTH_TOKEN = "XXXXXXXXXXXXXXXXXXXXXX"
FROM_NUMBER = "XXXXXXXXXXXXX"
TO_NUMBER = "+919653203388"

Arduino

Arduino
Upload this code in your arduino board. What it does is controls the offline indoor lighting system, captures the temperature value and send it to the bolt module via UART communication. The LCD and Keypad are also interfaced in this program. The keypad is used to enter the reference light intensity value.
#include <LiquidCrystal.h>  //required libraries
#include <Keypad.h>

int rs=7, e=6, d4=5, d5=4, d6=3, d7=2;  // the arduino pins to which the LCD pins are conncected
LiquidCrystal lcd(rs, e, d4, d5, d6, d7); // initializing the LCD display

// initilizing the keypad
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
char hexaKeys[ROWS][COLS] = {  //keypad buttons
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
// the arduino pins to which the keypad pins are connected
byte rowPins[ROWS] = {A5, A4, A3, 8}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {10, 11, 12, 13}; //connect to the column pinouts of the keypad

Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); 

void setup() {
// initializing the arduino
pinMode(A0,INPUT);       //LDR
pinMode(A1,INPUT);       //Temperature sensor
                                                                                                                    
pinMode(11,OUTPUT);
pinMode(10,OUTPUT);

lcd.begin(16,2);


Serial.begin(9600); //communication baud rate of 9600
}
//initializing the variables
int temp=0;
int light=0;
int u=0;
int uavg=0;
int x;
int pin=9;
int i=0;
int lightavg=0;
int tempavg=0;
int xreq=70;
String temperory;
int xref;

void loop() {
i=i+1;
temp=analogRead(A1);  //Temperature sensor connected to PIN A1
light=analogRead(A0); //LDR voltage divider circuit connected to PIN A0

temp=(temp/2.05);


lcd.setCursor(0,1);
lcd.print("Light=");
lcd.print(light);
x=light;

char customKey = customKeypad.getKey(); //getting the keypad pressed value
if (customKey=='D'){      //initialized keypad "D" button as enter button
  xref=temperory.toInt();
  temperory="";
  }
if (customKey=='1' || customKey=='2' || customKey=='3'|| customKey=='4'|| customKey=='5'|| customKey=='6'|| customKey=='7'|| customKey=='8'|| customKey=='9'|| customKey=='0'){   //if keypad input is number then saving it to temperory and if "D" i.e enter is not pressed then merging new value with the old
    temperory += customKey;
     }

if (xref != 0 && xref <= 1000){   //if the reference value specified using keypad is not zero and less than 1000 then save the value in xreq
  xreq=xref;
}
//controlling the PWM output of the LED interfaced pin withing _-5 range of the required light intensity value xreq
if (x<=xreq-5) { //increasing the PWM output of LED control pin if the current light intensity is less than xreq-5
u=u+5;r
}
if (x>=xreq+5) {  //decreasing the PWM output of LED control pin if the current light intensity is less than xreq+5
u=u-5;
}
if (u>=250){
  u=250;
}
if (u<=0){
  u=0;
}
lcd.setCursor(9,1); //printing the values on the lcd display
lcd.print("Req=");
lcd.print(xreq);
lcd.setCursor(12,0);
lcd.print(u);
delay(150);
analogWrite(pin, u);  // controlling the pin to control the LEDs or indoor lighting system
uavg=(uavg+u)/2; // averaging the values for further sending to system
lightavg = (lightavg+light)/2;
tempavg = (tempavg+temp)/2;
if (i==200){   //sending the values to the bolt module through UART communication every 200th iteration ie every 30 seconds since 1 iteration is 0.15 seconds
  
  lcd.setCursor(0,0);
  lcd.print("              ");
  
  Serial.print(lightavg);
  Serial.print(",");
  Serial.print(tempavg);
  Serial.print(",");
  Serial.print(uavg);
  Serial.print(",;");
  
  lcd.setCursor(6,0);
  lcd.print(uavg);
  lcd.setCursor(3,0);
  lcd.print(tempavg);
  lcd.setCursor(0,0);
  lcd.print(lightavg);
  tempavg=0;
  i=0;
  lightavg=0;
    
  }
  
lcd.setCursor(12,0); //displaying the values in the LCD screen
lcd.print("   ");
lcd.setCursor(0,1);
lcd.print("                ");
}

Credits

Himanshu Goyel ee19s025

Himanshu Goyel ee19s025

1 project • 1 follower

Comments