In this project I am going to discuss ,how to build a home automation system using Raspberry Pi
Home automation is the use of one or more computers to control basic home functions and features automatically and sometimes remotely. An automated home is sometimes called a smart home .Home automation or smart home (also known as domotics) is building automation for the home. It involves the control and automation of lighting, heating (such as smart thermostats), ventilation, air conditioning (HVAC), and security, as well as home appliances such as washer/dryers, ovens or refrigerators/freezers.
Things needed for this Project
- Raspberry Pi 3
The Raspberry Pi 3 is the third-generation Raspberry Pi. It replaced the Raspberry Pi 2 Model B in February 2016. Quad Core 1.2GHz Broadcom BCM2837 64bit CPU. 1GB RAM. BCM43438 wireless LAN and Bluetooth Low Energy (BLE) on board.
2.Relay Driver Module
Relay driver module can be choosed according to our need 2 channel,4 channel 8 or 16 .In this project i am using 4 channel relay because in my room there is only 2 lights one fan and one TV.
3.JUMPER WIRES
We require Male-Female and Female-Female Jumper wires for connection.
4.RTC Tiny (Real time clock Module)
Since Raspberry Pi has no in built clock we need to include an external clock to our Project.I am using RTC tiny in my project since it is small and costs less.You can also use RTC 3231.
RTC is used for sending the device ON/OFF time to the cloud.It has got Seven Registers to store Seconds,Minute,Hour,Day,Date,Month and Year.
5.A PubNub Cloud Account
PubNub is a global Data Stream Network (DSN) and real time infrastructure-as-a-service (IaaS) company based in San Francisco, California. The company makes products for software and hardware developers to build real time web, mobile, and Internet of Things(IoT) applications.
PubNub's primary product is a real time publish/subscribe messaging API built on their global data stream network which is made up of a replicated network of at least 14 data centers located in North America, South America, Europe, and Asia. The network currently serves over 300 million devices and streams more than 750 billion messages per month.
In our Project we are using this cloud service to send our message to Raspberry Pi and receive the message back from Raspberry Pi.
So Lets Create Our account in the PubNub Cloud...
Got to
- Click on GET STARTED or LOGIN if you already have one account.
- Enter Your Email and password and click Next.
- Enter Name,Company name etc...and click Next.
- You Will Get a Publish Key and a Subscribe Key.(Please Copy this key to some where so that we can use this in our Project)
- In the main Window click on keys and click on Debug Console in the bottom left corner tab.
- Now debug console window will open.This is where we need to provide the channels and enter the Channel name and click on Add client,I am giving Channel Names as HALL,KITCHEN and BEDROOM. And one LOG Channel for receiving the RTC Time to Pubnub.
That's it with PUBNUB.
Now we need to install PubNub libraries on our Raspberry Pi.For that run following commands in the Terminal.
sudo apt-get -y update
sudo apt-get -y install libevent-dev
sudo apt-get -y install libjson0-dev
sudo apt-get -y install libjcurl4-openssl-dev
sudo apt-get -y install libssl-dev
to install pubnub SDK in terminal type:
git clone https://github.com/pubnub/c
After installing connect the Raspberry Pi to Relay driver and RTC as shown in the figure below and Power up the Pi.
But before doing the connections we need to enable the I2C Device driver on the Pi by going to settings(raspi-config).This is for connecting the RTC to Pi.
After Installing the PubNub library you will get The following Directory:
/home/pi/pubnub/c/
got to this directory and in terminal type :
make
sudo make install
we cannot write pubnub program outside c directory because all library functions are in this directory only.
Download and Extract the Following tar file in the c/ directory.
Now navigate to :
/home/pi/PROJECTS/pubnub/c/PublishSubscribe/listen/
In that directory listenMakefile is available open that and change the last line to
-include /home/pi/pubnub/c/Makefile.lib
Save and close the File.
Now open listen.c file and delete all lines copy the PROJECT CODE SNIPPET below and paste it in to that file.Replace Publish and Subscribe Keys with your Publish and Subscribe Keys.
Enter the command
make listenMakefile
Now it will make the file
Execute By Running ./listen
Now if you type anything on the dialogue console of Pubnub and send it .Then it will be received and will show on Raspberry pi window.
NOTE:If your Channel name given in the Pubnub cloud is not matched with what channel you give in the program then this will not work!!!!
PROJECT CODE SNIPPET:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <wiringPi.h>
#include <json.h>
#include <time.h>
#include "pubnub.h"
#include "pubnub-sync.h"
#define PUBLISH_KEY "pub-c-46377636-b2b7-408e-b29c-xxxxxxxxxxxxxx"
#define SUBSCRIBE_KEY "sub-c-2ff36754-64ab-11e7-898a-xxxxxxxxxxxxxx"
#define AT24C08_SA 0x50
#define DS3231_SA 0x68
struct pubnub_sync *_sync;
struct pubnub *p;
json_object *msg;
char *buff,chanl[15];
static int c=0;
char * readPubnub ()
{
/* Subscribe */
/* 1 */ const char *channels[] = { "Hall","Kitchen","Bed"};
/* 2 */ pubnub_subscribe_multi(
/* struct pubnub */ p,
/* list of channels */ channels,
/* number of listed channels */ 3,
/* default timeout */ -1,
/* callback; sync needs NULL! */ NULL,
/* callback data */ NULL);
if (pubnub_sync_last_result(_sync) != PNR_OK)
return EXIT_FAILURE;
msg = pubnub_sync_last_response(_sync);
if (json_object_array_length(msg) == 0) {
printf("pubnub subscribe ok, no news\n");
} else {
char **msg_channels = pubnub_sync_last_channels(_sync);
for (int i = 0; i < json_object_array_length(msg); i++) {
json_object *msg1 = json_object_array_get_idx(msg, i);
if(strcmp(msg_channels[i],"Hall")==0)
{
c=1;printf("%s****\n",msg_channels[i]);
}
else if(strcmp(msg_channels[i],"Kitchen")==0)
{
c=2;printf("%s****\n",msg_channels[i]);
}
else if(strcmp(msg_channels[i],"Bed")==0)
{
c=3;
printf("%s****%d\n",msg_channels[i],c);
}
printf("pubnub subscribe [%s]: %s\n", msg_channels[i], buff = (char *)json_object_get_string(msg1));
}
}
return buff;
}
int writePubnub (char *mymsg)
{
/* Publish */
msg = json_object_new_object();
json_object_object_add(msg, "str", json_object_new_string(mymsg));
/* 1 */ pubnub_publish(
/* struct pubnub */ p,
/* channel name*/ "ACK",
/* message */ msg,
/* default timeout */ -1,
/* callback; sync needs NULL! */ NULL,
/* callback data */ NULL);
json_object_put(msg);
if (pubnub_sync_last_result(_sync) != PNR_OK)
return EXIT_FAILURE;
msg = pubnub_sync_last_response(_sync);
json_object_put(msg);
}
void PubNubInit ()
{
_sync = pubnub_sync_init();
p = pubnub_init(
/* publish_key */ PUBLISH_KEY,
/* subscribe_key */ SUBSCRIBE_KEY,
/* pubnub_callbacks */ &pubnub_sync_callbacks,
/* pubnub_callbacks data */ _sync);
}
int main(void)
{
char *readbuff,k[300];
int fd,hr,min,sec;
PubNubInit ();
wiringPiSetup();
pinMode(0,OUTPUT);
pinMode(2,OUTPUT);
pinMode(3,OUTPUT);
pinMode(5,OUTPUT);
pinMode(12,OUTPUT);
pinMode(13,OUTPUT);
FILE *fd;
fd=fopen("LOG","a");
while(1)
{
fd=wiringPiI2CSetup(DS3231_SA);
if(fd<0)
{
fprintf(stderr,"DEVICE NOT FOUND\n");
return fd;
}
/* wiringPiI2CWriteReg8(fd,0x2,0x6);
wiringPiI2CWriteReg8(fd,0x1,0x51);
wiringPiI2CWriteReg8(fd,0x0,0x00);
*/
hr=wiringPiI2CReadReg8(fd,0x2);
min=wiringPiI2CReadReg8(fd,0x1);
sec=wiringPiI2CReadReg8(fd,0x0);
readbuff = readPubnub();
switch(c)
{
case 1: if(strstr(readbuff,"BULB ON")) //hall
{
digitalWrite(0,LOW);
sprintf(k,"HALL BULB ON AT %x:%x:%x\n",hr,min,sec);
writePubnub(k);
}
else if(strstr(readbuff,"BULB OFF"))
{
digitalWrite(0,HIGH);
sprintf(k,"HALL BULB OFF AT %x:%x:%x\n",hr,min,sec);
writePubnub(k);
}
if(strstr(readbuff,"FAN ON"))
{
digitalWrite(2,LOW);
sprintf(k,"HALL FAN ON AT %x:%x:%x\n",hr,min,sec);
writePubnub(k);
}
else if(strstr(readbuff,"FAN OFF"))
{
digitalWrite(2,HIGH);
sprintf(k,"HALL FAN OFF AT %x:%x:%x\n",hr,min,sec);
writePubnub(k);
}
printf ("HALL = %s %d\n",readbuff,c);
break;
case 2: if(strstr(readbuff,"BULB ON")) //Kitchen
{
digitalWrite(3,LOW);
sprintf(k,"KITCHEN BULB ON AT %x:%x:%x\n",hr,min,sec);
writePubnub(k);
}
else if(strstr(readbuff,"BULB OFF"))
{
digitalWrite(3,HIGH);
sprintf(k,"KITCHEN BULB OFF AT %x:%x:%x\n",hr,min,sec);
writePubnub(k);
}
if(strstr(readbuff,"FAN ON"))
{
digitalWrite(5,LOW);
sprintf(k,"KITCHEN FAN ON AT %x:%x:%x\n",hr,min,sec);
writePubnub(k);
}
else if(strstr(readbuff,"FAN OFF"))
{
digitalWrite(5,HIGH);
sprintf(k,"KITCHEN FAN OFF AT %x:%x:%x\n",hr,min,sec);
writePubnub(k);
}
printf ("KITCHEN = %s,%d\n",readbuff,c);
break;
case 3: if(strstr(readbuff,"BULB ON"))
{
digitalWrite(12,LOW);
sprintf(k,"BEDROOM BULB ON AT %x:%x:%x\n",hr,min,sec);
writePubnub(k);
}
else if(strstr(readbuff,"BULB OFF"))
{
digitalWrite(12,HIGH);
sprintf(k,"BEDROOM BULB OFF AT %x:%x:%x\n",hr,min,sec);
writePubnub(k);
}
if(strstr(readbuff,"FAN ON"))
{
digitalWrite(13,LOW);
sprintf(k,"BEDROOM FAN ON AT %x:%x:%x\n",hr,min,sec);
writePubnub(k);
}
else if(strstr(readbuff,"FAN OFF"))
{
digitalWrite(13,HIGH);
sprintf(k,"BEDROOM FAN OFF AT %x:%x:%x\n",hr,min,sec);
writePubnub(k);
}
printf ("BEDROOM = %s,%d\n",readbuff,c);
break;
default: printf("UNKNOWN\n");
}
}
}
CODE EXPLANATION:
The code may be divided in to 5 sections
Declarations
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <wiringPi.h>
#include <json.h>
#include <time.h>
#include "pubnub.h"
#include "pubnub-sync.h"
#define PUBLISH_KEY "pub-c-46377636-b2b7-408e-b29c-xxxxxxxxxxxxxx"
#define SUBSCRIBE_KEY "sub-c-2ff36754-64ab-11e7-898a-xxxxxxxxxxxxxx"
#define AT24C08_SA 0x50
#define DS3231_SA 0x68
struct pubnub_sync *_sync;
struct pubnub *p;
json_object *msg;
char *buff,chanl[15];
static int c=0;
In this area we are including Header files,defining Publish and Subscribe Key ,Pub nub structure,Channel arrays and a Count C.
Read PUBNUB
char * readPubnub ()
{
/* Subscribe */
/* 1 */ const char *channels[] = { "Hall","Kitchen","Bed"};
/* 2 */ pubnub_subscribe_multi(
/* struct pubnub */ p,
/* list of channels */ channels,
/* number of listed channels */ 3,
/* default timeout */ -1,
/* callback; sync needs NULL! */ NULL,
/* callback data */ NULL);
if (pubnub_sync_last_result(_sync) != PNR_OK)
return EXIT_FAILURE;
msg = pubnub_sync_last_response(_sync);
if (json_object_array_length(msg) == 0) {
printf("pubnub subscribe ok, no news\n");
} else {
char **msg_channels = pubnub_sync_last_channels(_sync);
for (int i = 0; i < json_object_array_length(msg); i++) {
json_object *msg1 = json_object_array_get_idx(msg, i);
if(strcmp(msg_channels[i],"Hall")==0)
{
c=1;printf("%s****\n",msg_channels[i]);
}
else if(strcmp(msg_channels[i],"Kitchen")==0)
{
c=2;printf("%s****\n",msg_channels[i]);
}
else if(strcmp(msg_channels[i],"Bed")==0)
{
c=3;
printf("%s****%d\n",msg_channels[i],c);
}
printf("pubnub subscribe [%s]: %s\n", msg_channels[i], buff = (char *)json_object_get_string(msg1));
}
}
return buff;
}
In this section we are assigning *channel[] a 2D array to hold channel names,we need to provide number of channels and default timeout of the channels also.The message sent from pubnub will be available in the **msg buffer ,and **msg_channels holds the channel name ,We need to manipulate this buffer in order to know from which channel the message came,according to that a variable (c) is changed
ie.Take an example ,
we are comparing **msg_channels with "Hall" and if we send some message from Hall channel this returns true and C is set to 1.
in similar way,comparing **msg_channels with "Kitchen" and if we send some message from Kitchen channel this returns true and C is set to 2 and set to 3 when anything is send from "Bed" channel.This is why we are making C as static variable.
On Pi's terminal {"text":"YOUR MESSAGE"} along with channel name is printed.
Write PUBNUB
int writePubnub (char *mymsg)
{
/* Publish */
msg = json_object_new_object();
json_object_object_add(msg, "str", json_object_new_string(mymsg));
/* 1 */ pubnub_publish(
/* struct pubnub */ p,
/* channel name*/ "ACK",
/* message */ msg,
/* default timeout */ -1,
/* callback; sync needs NULL! */ NULL,
/* callback data */ NULL);
json_object_put(msg);
if (pubnub_sync_last_result(_sync) != PNR_OK)
return EXIT_FAILURE;
msg = pubnub_sync_last_response(_sync);
json_object_put(msg);
}
In this section we are writing to Pubnub ,In my Project i am writing the time and date of each ON/OFF to pubnub .a structure pubnub_publish will send acknowledgement to what we have sent.writePubnub (),will send our message to pubnub from the main().
PUBNUB init()
void PubNubInit ()
{
_sync = pubnub_sync_init();
p = pubnub_init(
/* publish_key */ PUBLISH_KEY,
/* subscribe_key */ SUBSCRIBE_KEY,
/* pubnub_callbacks */ &pubnub_sync_callbacks,
/* pubnub_callbacks data */ _sync);
}
This section will initialise the pubnub,by giving Publish and subscribe Keys to the Functions(no need to copy paste the keys here).
Main()
int main(void)
{
char *readbuff,k[300];
int fd,hr,min,sec;
PubNubInit ();
wiringPiSetup();
pinMode(0,OUTPUT);
pinMode(2,OUTPUT);
pinMode(3,OUTPUT);
pinMode(5,OUTPUT);
pinMode(12,OUTPUT);
pinMode(13,OUTPUT);
FILE *fd;
fd=fopen("LOG","a");
while(1)
{
fd=wiringPiI2CSetup(DS3231_SA);
if(fd<0)
{
fprintf(stderr,"DEVICE NOT FOUND\n");
return fd;
}
/* wiringPiI2CWriteReg8(fd,0x2,0x6);
wiringPiI2CWriteReg8(fd,0x1,0x51);
wiringPiI2CWriteReg8(fd,0x0,0x00);
*/
hr=wiringPiI2CReadReg8(fd,0x2);
min=wiringPiI2CReadReg8(fd,0x1);
sec=wiringPiI2CReadReg8(fd,0x0);
readbuff = readPubnub();
switch(c)
{
case 1: if(strstr(readbuff,"BULB ON")) //hall
{
digitalWrite(0,LOW);
sprintf(k,"HALL BULB ON AT %x:%x:%x\n",hr,min,sec);
writePubnub(k);
}
else if(strstr(readbuff,"BULB OFF"))
{
digitalWrite(0,HIGH);
sprintf(k,"HALL BULB OFF AT %x:%x:%x\n",hr,min,sec);
writePubnub(k);
}
if(strstr(readbuff,"FAN ON"))
{
digitalWrite(2,LOW);
sprintf(k,"HALL FAN ON AT %x:%x:%x\n",hr,min,sec);
writePubnub(k);
}
else if(strstr(readbuff,"FAN OFF"))
{
digitalWrite(2,HIGH);
sprintf(k,"HALL FAN OFF AT %x:%x:%x\n",hr,min,sec);
writePubnub(k);
}
printf ("HALL = %s %d\n",readbuff,c);
break;
case 2: if(strstr(readbuff,"BULB ON")) //Kitchen
{
digitalWrite(3,LOW);
sprintf(k,"KITCHEN BULB ON AT %x:%x:%x\n",hr,min,sec);
writePubnub(k);
}
else if(strstr(readbuff,"BULB OFF"))
{
digitalWrite(3,HIGH);
sprintf(k,"KITCHEN BULB OFF AT %x:%x:%x\n",hr,min,sec);
writePubnub(k);
}
if(strstr(readbuff,"FAN ON"))
{
digitalWrite(5,LOW);
sprintf(k,"KITCHEN FAN ON AT %x:%x:%x\n",hr,min,sec);
writePubnub(k);
}
else if(strstr(readbuff,"FAN OFF"))
{
digitalWrite(5,HIGH);
sprintf(k,"KITCHEN FAN OFF AT %x:%x:%x\n",hr,min,sec);
writePubnub(k);
}
printf ("KITCHEN = %s,%d\n",readbuff,c);
break;
case 3: if(strstr(readbuff,"BULB ON"))
{
digitalWrite(12,LOW);
sprintf(k,"BEDROOM BULB ON AT %x:%x:%x\n",hr,min,sec);
writePubnub(k);
}
else if(strstr(readbuff,"BULB OFF"))
{
digitalWrite(12,HIGH);
sprintf(k,"BEDROOM BULB OFF AT %x:%x:%x\n",hr,min,sec);
writePubnub(k);
}
if(strstr(readbuff,"FAN ON"))
{
digitalWrite(13,LOW);
sprintf(k,"BEDROOM FAN ON AT %x:%x:%x\n",hr,min,sec);
writePubnub(k);
}
else if(strstr(readbuff,"FAN OFF"))
{
digitalWrite(13,HIGH);
sprintf(k,"BEDROOM FAN OFF AT %x:%x:%x\n",hr,min,sec);
writePubnub(k);
}
printf ("BEDROOM = %s,%d\n",readbuff,c);
break;
default: printf("UNKNOWN\n");
}
}
}
In main we are assigning the pins of pi,and according to the status of c variable we are giving output to pins.I have taken wiringPi pins
0 - HALL BULB
2- HALL FAN
3 - KITCHEN BULB
5 - KITCHEN FAN
12 - BED BULB
13 - BED FAN
I am writing the RTC hr,min,sec to a buffer K and passing it to writepubnub function.
Thats all for this project,Hope you all liked it...Automate your own home and Enjoy....
ReplyDeleteI have got one myself because like 10 decades. I like it also, maybe not modded as yours nonetheless.
Currently it does not operate, it hastens if heating. Brought to a neigbour of mine and he will find a deeper look at it.
It seems like a few have had difficulty working with the automated decompression valve, which do yours have this?
Enjoy an excellent day!
How To Use A Chainsaw Sharpener